Refactor IPv4 utils
[csit.git] / resources / libraries / python / topology.py
index 522de37..8b6905d 100644 (file)
@@ -43,6 +43,14 @@ class NodeType(object):
     # Traffic Generator (this node has traffic generator on it)
     TG = 'TG'
 
+class NodeSubTypeTG(object):
+    #T-Rex traffic generator
+    TREX = 'TREX'
+    # Moongen
+    MOONGEN = 'MOONGEN'
+    #IxNetwork
+    IXNET = 'IXNET'
+
 DICT__nodes = load_topo_from_yaml()
 
 
@@ -315,7 +323,7 @@ class Topology(object):
         This method updates the topology dictionary by querying interface lists
         of all nodes mentioned in the topology dictionary.
         It does this by dumping interface list to json output from all devices
-        using vpe_api_test, and pairing known information from topology
+        using vpp_api_test, and pairing known information from topology
         (mac address/pci address of interface) to state from VPP.
         For TG/linux nodes add interface name only.
         """
@@ -345,6 +353,22 @@ class Topology(object):
 
         return None
 
+    @staticmethod
+    def get_interface_mac_by_port_key(node, port_key):
+        """Get MAC address for the interface based on port key.
+
+        :param node: Node to get interface mac on.
+        :param port_key: Dictionary key name of interface.
+        :type node: dict
+        :type port_key: str
+        :return: Return MAC or None if not found.
+        """
+        for port_name, port_data in node['interfaces'].iteritems():
+            if port_name == port_key:
+                return port_data['mac_address']
+
+        return None
+
     @staticmethod
     def get_interface_mac(node, interface):
         """Get MAC address for the interface.
@@ -365,19 +389,64 @@ class Topology(object):
         return None
 
     @staticmethod
-    def get_adjacent_interface(node, interface_name):
-        """Get interface adjacent to specified interface on local network.
-
-           :param node: Node that contains specified interface.
-           :param interface_name: Interface name.
-           :type node: dict
-           :type interface_name: str
-           :return: Return interface or None if not found.
-           :rtype: dict
+    def get_adjacent_node_and_interface_by_key(nodes_info, node, port_key):
+        """Get node and interface adjacent to specified interface
+        on local network.
+
+        :param nodes_info: Dictionary containing information on all nodes
+        in topology.
+        :param node: Node that contains specified interface.
+        :param port_key: Interface port key.
+        :type nodes_info: dict
+        :type node: dict
+        :type port_key: str
+        :return: Return (node, interface info) tuple or None if not found.
+        :rtype: (dict, dict)
+        """
+        link_name = None
+       # get link name where the interface belongs to
+        for port_name, port_data in node['interfaces'].iteritems():
+            if port_name == 'mgmt':
+                continue
+            if port_name == port_key:
+                link_name = port_data['link']
+                break
+
+        if link_name is None: 
+            return None
+
+        # find link
+        for node_data in nodes_info.values():
+            # skip self
+            if node_data['host'] == node['host']:
+                continue
+            for interface, interface_data \
+                    in node_data['interfaces'].iteritems():
+                if 'link' not in interface_data:
+                    continue
+                if interface_data['link'] == link_name:
+                    return node_data, node_data['interfaces'][interface]
+
+    @staticmethod
+    def get_adjacent_node_and_interface(nodes_info, node, interface_name):
+        """Get node and interface adjacent to specified interface
+        on local network.
+
+        :param nodes_info: Dictionary containing information on all nodes
+        in topology.
+        :param node: Node that contains specified interface.
+        :param interface_name: Interface name.
+        :type nodes_info: dict
+        :type node: dict
+        :type interface_name: str
+        :return: Return (node, interface info) tuple or None if not found.
+        :rtype: (dict, dict)
         """
         link_name = None
         # get link name where the interface belongs to
-        for _, port_data in node['interfaces'].iteritems():
+        for port_name, port_data in node['interfaces'].iteritems():
+            if port_name == 'mgmt':
+                continue
             if port_data['name'] == interface_name:
                 link_name = port_data['link']
                 break
@@ -386,7 +455,7 @@ class Topology(object):
             return None
 
         # find link
-        for _, node_data in DICT__nodes.iteritems():
+        for node_data in nodes_info.values():
             # skip self
             if node_data['host'] == node['host']:
                 continue
@@ -395,7 +464,7 @@ class Topology(object):
                 if 'link' not in interface_data:
                     continue
                 if interface_data['link'] == link_name:
-                    return node_data['interfaces'][interface]
+                    return node_data, node_data['interfaces'][interface]
 
     @staticmethod
     def get_interface_pci_addr(node, interface):
@@ -537,3 +606,61 @@ class Topology(object):
         if not interfaces:
             raise RuntimeError('No engress interface for nodes')
         return interfaces[0]
+
+    @keyword('Get link data useful in circular topology test from tg "${tgen}"'
+             ' dut1 "${dut1}" dut2 "${dut2}"')
+    def get_links_dict_from_nodes(self, tgen, dut1, dut2):
+        """Returns link combinations used in tests in circular topology.
+
+        For the time being it returns links from the Node path:
+        TG->DUT1->DUT2->TG
+        :param tg: traffic generator node data
+        :param dut1: DUT1 node data
+        :param dut2: DUT2 node data
+        :type tg: dict
+        :type dut1: dict
+        :type dut2: dict
+        :return: dictionary of possible link combinations
+        the naming convention until changed to something more general is
+        implemented is this:
+        DUT1_DUT2_LINK: link name between DUT! and DUT2
+        DUT1_TG_LINK: link name between DUT1 and TG
+        DUT2_TG_LINK: link name between DUT2 and TG
+        TG_TRAFFIC_LINKS: list of link names that generated traffic is sent
+        to and from
+        DUT1_BD_LINKS: list of link names that will be connected by the bridge
+        domain on DUT1
+        DUT2_BD_LINKS: list of link names that will be connected by the bridge
+        domain on DUT2
+        """
+        # TODO: replace with generic function.
+        dut1_dut2_link = self.get_first_active_connecting_link(dut1, dut2)
+        dut1_tg_link = self.get_first_active_connecting_link(dut1, tgen)
+        dut2_tg_link = self.get_first_active_connecting_link(dut2, tgen)
+        tg_traffic_links = [dut1_tg_link, dut2_tg_link]
+        dut1_bd_links = [dut1_dut2_link, dut1_tg_link]
+        dut2_bd_links = [dut1_dut2_link, dut2_tg_link]
+        topology_links = {'DUT1_DUT2_LINK': dut1_dut2_link,
+                          'DUT1_TG_LINK': dut1_tg_link,
+                          'DUT2_TG_LINK': dut2_tg_link,
+                          'TG_TRAFFIC_LINKS': tg_traffic_links,
+                          'DUT1_BD_LINKS': dut1_bd_links,
+                          'DUT2_BD_LINKS': dut2_bd_links}
+        return topology_links
+
+    @staticmethod
+    def is_tg_node(node):
+        """Find out whether the node is TG
+
+        :param node: node to examine
+        :return: True if node is type of TG; False otherwise
+        """
+        return node['type'] == NodeType.TG
+
+    @staticmethod
+    def get_node_hostname(node):
+        """
+        :param node: node dictionary
+        :return: host name as 'str' type
+        """
+        return node['host']
\ No newline at end of file