X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2Ftopology.py;h=4ff68ec43df07be95a53c7ed0f90e5603e387b25;hp=7e9400757e42a8590553abc235b29e7ce3dfc388;hb=7bfb36dfd9284bbca10881e31e14108c7d468b7c;hpb=c8790d06d412b1daf303f6da9d8d11d97d053697 diff --git a/resources/libraries/python/topology.py b/resources/libraries/python/topology.py index 7e9400757e..4ff68ec43d 100644 --- a/resources/libraries/python/topology.py +++ b/resources/libraries/python/topology.py @@ -13,10 +13,12 @@ """Defines nodes and topology structure.""" +from collections import Counter + from yaml import load from robot.api import logger -from robot.libraries.BuiltIn import BuiltIn +from robot.libraries.BuiltIn import BuiltIn, RobotNotRunningError from robot.api.deco import keyword __all__ = ["DICT__nodes", 'Topology'] @@ -25,14 +27,19 @@ __all__ = ["DICT__nodes", 'Topology'] def load_topo_from_yaml(): """Load topology from file defined in "${TOPOLOGY_PATH}" variable. - :return: Nodes from loaded topology. + :returns: Nodes from loaded topology. """ - topo_path = BuiltIn().get_variable_value("${TOPOLOGY_PATH}") + try: + topo_path = BuiltIn().get_variable_value("${TOPOLOGY_PATH}") + except RobotNotRunningError: + return '' with open(topo_path) as work_file: return load(work_file.read())['nodes'] +# pylint: disable=invalid-name + class NodeType(object): """Defines node types used in topology dictionaries.""" # Device Under Test (this node has VPP running on it) @@ -44,6 +51,7 @@ class NodeType(object): class NodeSubTypeTG(object): + """Defines node sub-type TG - traffic generator.""" # T-Rex traffic generator TREX = 'TREX' # Moongen @@ -58,9 +66,189 @@ class Topology(object): """Topology data manipulation and extraction methods. Defines methods used for manipulation and extraction of data from - the used topology. + the active topology. + + "Active topology" contains initially data from the topology file and can be + extended with additional data from the DUTs like internal interface indexes + or names. Additional data which can be filled to the active topology are + - additional internal representation (index, name, ...) + - operational data (dynamic ports) + + To access the port data it is recommended to use a port key because the key + does not rely on the data retrieved from nodes, this allows to call most of + the methods without having filled active topology with internal nodes data. """ + @staticmethod + def add_new_port(node, ptype): + """Add new port to the node to active topology. + + :param node: Node to add new port on. + :param ptype: Port type, used as key prefix. + :type node: dict + :type ptype: str + :returns: Port key or None + :rtype: string or None + """ + max_ports = 1000000 + iface = None + for i in range(1, max_ports): + if node['interfaces'].get(str(ptype) + str(i)) is None: + iface = str(ptype) + str(i) + node['interfaces'][iface] = dict() + break + return iface + + @staticmethod + def remove_port(node, iface_key): + """Remove required port from active topology. + + :param node: Node to remove port on. + :param: iface_key: Topology key of the interface. + :type node: dict + :type iface_key: str + :returns: Nothing + """ + try: + node['interfaces'].pop(iface_key) + except KeyError: + pass + + @staticmethod + def remove_all_ports(node, ptype): + """Remove all ports with ptype as prefix. + + :param node: Node to remove ports on. + :param: ptype: Port type, used as key prefix. + :type node: dict + :type ptype: str + :returns: Nothing + """ + for if_key in list(node['interfaces']): + if if_key.startswith(str(ptype)): + node['interfaces'].pop(if_key) + + @staticmethod + def remove_all_added_ports_on_all_duts_from_topology(nodes): + """Remove all added ports on all DUT nodes in the topology. + + :param nodes: Nodes in the topology. + :type nodes: dict + :returns: Nothing + """ + port_types = ('subinterface', 'vlan_subif', 'memif', 'tap', 'vhost', + 'loopback', 'gre_tunnel', 'vxlan_tunnel') + + for node_data in nodes.values(): + if node_data['type'] == NodeType.DUT: + for ptype in port_types: + Topology.remove_all_ports(node_data, ptype) + + @staticmethod + def update_interface_sw_if_index(node, iface_key, sw_if_index): + """Update sw_if_index on the interface from the node. + + :param node: Node to update sw_if_index on. + :param iface_key: Topology key of the interface. + :param sw_if_index: Internal index to store. + :type node: dict + :type iface_key: str + :type sw_if_index: int + """ + node['interfaces'][iface_key]['vpp_sw_index'] = int(sw_if_index) + + @staticmethod + def update_interface_name(node, iface_key, name): + """Update name on the interface from the node. + + :param node: Node to update name on. + :param iface_key: Topology key of the interface. + :param name: Interface name to store. + :type node: dict + :type iface_key: str + :type name: str + """ + node['interfaces'][iface_key]['name'] = str(name) + + @staticmethod + def update_interface_mac_address(node, iface_key, mac_address): + """Update mac_address on the interface from the node. + + :param node: Node to update MAC on. + :param iface_key: Topology key of the interface. + :param mac_address: MAC address. + :type node: dict + :type iface_key: str + :type mac_address: str + """ + node['interfaces'][iface_key]['mac_address'] = str(mac_address) + + @staticmethod + def update_interface_vhost_socket(node, iface_key, vhost_socket): + """Update vhost socket name on the interface from the node. + + :param node: Node to update socket name on. + :param iface_key: Topology key of the interface. + :param vhost_socket: Path to named socket on node. + :type node: dict + :type iface_key: str + :type vhost_socket: str + """ + node['interfaces'][iface_key]['vhost_socket'] = str(vhost_socket) + + @staticmethod + def update_interface_memif_socket(node, iface_key, memif_socket): + """Update memif socket name on the interface from the node. + + :param node: Node to update socket name on. + :param iface_key: Topology key of the interface. + :param memif_socket: Path to named socket on node. + :type node: dict + :type iface_key: str + :type memif_socket: str + """ + node['interfaces'][iface_key]['memif_socket'] = str(memif_socket) + + @staticmethod + def update_interface_memif_id(node, iface_key, memif_id): + """Update memif ID on the interface from the node. + + :param node: Node to update memif ID on. + :param iface_key: Topology key of the interface. + :param memif_id: Memif interface ID. + :type node: dict + :type iface_key: str + :type memif_id: str + """ + node['interfaces'][iface_key]['memif_id'] = str(memif_id) + + @staticmethod + def update_interface_memif_role(node, iface_key, memif_role): + """Update memif role on the interface from the node. + + :param node: Node to update memif role on. + :param iface_key: Topology key of the interface. + :param memif_role: Memif role. + :type node: dict + :type iface_key: str + :type memif_role: str + """ + node['interfaces'][iface_key]['memif_role'] = str(memif_role) + + @staticmethod + def update_interface_tap_dev_name(node, iface_key, dev_name): + """Update device name on the tap interface from the node. + + :param node: Node to update tap device name on. + :param iface_key: Topology key of the interface. + :param dev_name: Device name of the tap interface. + :type node: dict + :type iface_key: str + :type dev_name: str + :returns: Nothing + """ + node['interfaces'][iface_key]['dev_name'] = str(dev_name) + @staticmethod def get_node_by_hostname(nodes, hostname): """Get node from nodes of the topology by hostname. @@ -69,7 +257,7 @@ class Topology(object): :param hostname: Host name. :type nodes: dict :type hostname: str - :return: Node dictionary or None if not found. + :returns: Node dictionary or None if not found. """ for node in nodes.values(): if node['host'] == hostname: @@ -83,7 +271,7 @@ class Topology(object): :param nodes: Nodes of the test topology. :type nodes: dict - :return: Links in the topology. + :returns: Links in the topology. :rtype: list """ links = [] @@ -99,35 +287,59 @@ class Topology(object): @staticmethod def _get_interface_by_key_value(node, key, value): - """Return node interface name according to key and value. + """Return node interface key from topology file + according to key and value. :param node: The node dictionary. :param key: Key by which to select the interface. :param value: Value that should be found using the key. - :return: + :type node: dict + :type key: string + :type value: string + :returns: Interface key from topology file + :rtype: string """ interfaces = node['interfaces'] retval = None - for interface in interfaces.values(): - k_val = interface.get(key) + for if_key, if_val in interfaces.iteritems(): + k_val = if_val.get(key) if k_val is not None: if k_val == value: - retval = interface['name'] + retval = if_key break return retval - def get_interface_by_link_name(self, node, link_name): - """Return interface name of link on node. + @staticmethod + def get_interface_by_name(node, iface_name): + """Return interface key based on name from DUT/TG. + + This method returns interface key based on interface name + retrieved from the DUT, or TG. + + :param node: The node topology dictionary. + :param iface_name: Interface name (string form). + :type node: dict + :type iface_name: string + :returns: Interface key. + :rtype: str + """ + return Topology._get_interface_by_key_value(node, "name", iface_name) + + @staticmethod + def get_interface_by_link_name(node, link_name): + """Return interface key of link on node. This method returns the interface name associated with a given link for a given node. - :param link_name: Name of the link that a interface is connected to. :param node: The node topology dictionary. - :return: Interface name of the interface connected to the given link. + :param link_name: Name of the link that a interface is connected to. + :type node: dict + :type link_name: string + :returns: Interface key of the interface connected to the given link. :rtype: str """ - return self._get_interface_by_key_value(node, "link", link_name) + return Topology._get_interface_by_key_value(node, "link", link_name) def get_interfaces_by_link_names(self, node, link_names): """Return dictionary of dictionaries {"interfaceN", interface name}. @@ -135,10 +347,12 @@ class Topology(object): This method returns the interface names associated with given links for a given node. + :param node: The node topology directory. :param link_names: List of names of the link that a interface is connected to. - :param node: The node topology directory. - :return: Dictionary of interface names that are connected to the given + :type node: dict + :type link_names: list + :returns: Dictionary of interface names that are connected to the given links. :rtype: dict """ @@ -146,155 +360,267 @@ class Topology(object): interface_key_tpl = "interface{}" interface_number = 1 for link_name in link_names: - interface_name = self.get_interface_by_link_name(node, link_name) + interface = self.get_interface_by_link_name(node, link_name) + interface_name = self.get_interface_name(node, interface) interface_key = interface_key_tpl.format(str(interface_number)) retval[interface_key] = interface_name interface_number += 1 return retval - def get_interface_by_sw_index(self, node, sw_index): + @staticmethod + def get_interface_by_sw_index(node, sw_index): """Return interface name of link on node. This method returns the interface name associated with a software interface index assigned to the interface by vpp for a given node. - :param sw_index: Sw_index of the link that a interface is connected to. :param node: The node topology dictionary. - :return: Interface name of the interface connected to the given link. + :param sw_index: Sw_index of the link that a interface is connected to. + :type node: dict + :type sw_index: int + :returns: Interface name of the interface connected to the given link. :rtype: str """ - return self._get_interface_by_key_value(node, "vpp_sw_index", sw_index) + return Topology._get_interface_by_key_value(node, "vpp_sw_index", + sw_index) @staticmethod - def get_interface_sw_index(node, interface): - """Get VPP sw_if_index for the interface. + def get_interface_sw_index(node, iface_key): + """Get VPP sw_if_index for the interface using interface key. :param node: Node to get interface sw_if_index on. - :param interface: Interface identifier. + :param iface_key: Interface key from topology file, or sw_index. :type node: dict - :type interface: str or int - :return: Return sw_if_index or None if not found. + :type iface_key: str/int + :returns: Return sw_if_index or None if not found. """ try: - return int(interface) - except ValueError: - for port in node['interfaces'].values(): - port_name = port.get('name') - if port_name == interface: - return port.get('vpp_sw_index') + if isinstance(iface_key, basestring): + return node['interfaces'][iface_key].get('vpp_sw_index') + # TODO: use only iface_key, do not use integer + else: + return int(iface_key) + except (KeyError, ValueError): return None @staticmethod - def get_interface_mtu(node, interface): + def get_interface_sw_index_by_name(node, iface_name): + """Get VPP sw_if_index for the interface using interface name. + + :param node: Node to get interface sw_if_index on. + :param iface_name: Interface name. + :type node: dict + :type iface_name: str + :returns: Return sw_if_index or None if not found. + :raises TypeError: If provided interface name is not a string. + """ + try: + if isinstance(iface_name, basestring): + iface_key = Topology.get_interface_by_name(node, iface_name) + return node['interfaces'][iface_key].get('vpp_sw_index') + else: + raise TypeError("Interface name must be a string.") + except (KeyError, ValueError): + return None + + @staticmethod + def get_interface_mtu(node, iface_key): """Get interface MTU. Returns physical layer MTU (max. size of Ethernet frame). :param node: Node to get interface MTU on. - :param interface: Interface name. + :param iface_key: Interface key from topology file. :type node: dict - :type interface: str - :return: MTU or None if not found. + :type iface_key: str + :returns: MTU or None if not found. :rtype: int """ - for port in node['interfaces'].values(): - port_name = port.get('name') - if port_name == interface: - return port.get('mtu') + try: + return node['interfaces'][iface_key].get('mtu') + except KeyError: + return None - return None + @staticmethod + def get_interface_name(node, iface_key): + """Get interface name (retrieved from DUT/TG). + + Returns name in string format, retrieved from the node. + :param node: Node to get interface name on. + :param iface_key: Interface key from topology file. + :type node: dict + :type iface_key: str + :returns: Interface name or None if not found. + :rtype: str + """ + try: + return node['interfaces'][iface_key].get('name') + except KeyError: + return None @staticmethod - def get_interface_mac_by_port_key(node, port_key): - """Get MAC address for the interface based on port key. + def convert_interface_reference_to_key(node, interface): + """Takes interface reference in any format + (name, link name, interface key or sw_if_index) + and converts to interface key using Topology methods. + + :param node: Node in topology. + :param interface: Name, sw_if_index, link name or key of an interface + on the node. + Valid formats are: sw_if_index, key, name. + :type node: dict + :type interface: str or int - :param node: Node to get interface mac on. - :param port_key: Dictionary key name of interface. + :returns: Interface key. + :rtype: str + + :raises TypeError: If provided with invalid interface argument. + :raises RuntimeError: If the interface does not exist in topology. + """ + + if isinstance(interface, int): + key = Topology.get_interface_by_sw_index(node, interface) + if key is None: + raise RuntimeError("Interface with sw_if_index={0} does not " + "exist in topology.".format(interface)) + elif interface in Topology.get_node_interfaces(node): + key = interface + elif interface in Topology.get_links({"dut": node}): + key = Topology.get_interface_by_link_name(node, interface) + elif isinstance(interface, basestring): + key = Topology.get_interface_by_name(node, interface) + if key is None: + raise RuntimeError("Interface with key, name or link name " + "\"{0}\" does not exist in topology." + .format(interface)) + else: + raise TypeError("Type of interface argument must be integer" + " or string.") + return key + + @staticmethod + def convert_interface_reference(node, interface, wanted_format): + """Takes interface reference in any format + (name, link name, topology key or sw_if_index) and returns + its equivalent in the desired format. + + :param node: Node in topology. + :param interface: Name, sw_if_index, link name or key of an interface + on the node. + :param wanted_format: Format of return value wanted. + Valid options are: sw_if_index, key, name. :type node: dict - :type port_key: str - :return: Return MAC or None if not found. + :type interface: str or int + :type wanted_format: str + + :returns: Interface name, interface key or sw_if_index. + :rtype: str or int + + :raises TypeError, ValueError: If provided with invalid arguments. + :raises RuntimeError: If the interface does not exist in topology. """ - for port_name, port_data in node['interfaces'].iteritems(): - if port_name == port_key: - return port_data['mac_address'] - return None + key = Topology.convert_interface_reference_to_key(node, interface) + + conversions = { + "key": lambda x, y: y, + "name": Topology.get_interface_name, + "sw_if_index": Topology.get_interface_sw_index + } + + try: + return conversions[wanted_format](node, key) + except KeyError: + raise ValueError("Unrecognized return value wanted: {0}." + "Valid options are key, name, sw_if_index" + .format(wanted_format)) @staticmethod - def get_interface_mac(node, interface): - """Get MAC address for the interface. + def get_interface_numa_node(node, iface_key): + """Get interface numa node. - :param node: Node to get interface sw_index on. - :param interface: Interface name. + Returns physical relation to numa node, numa_id. + + :param node: Node to get numa id on. + :param iface_key: Interface key from topology file. :type node: dict - :type interface: str - :return: Return MAC or None if not found. + :type iface_key: str + :returns: numa node id, None if not available. + :rtype: int """ - for port in node['interfaces'].values(): - port_name = port.get('name') - if port_name == interface: - return port.get('mac_address') + try: + return node['interfaces'][iface_key].get('numa_node') + except KeyError: + return None - return None + @staticmethod + def get_interfaces_numa_node(node, *iface_keys): + """Get numa node on which are located most of the interfaces. + + Return numa node with highest count of interfaces provided as arguments. + Return 0 if the interface does not have numa_node information available. + If all interfaces have unknown location (-1), then return 0. + If most of interfaces have unknown location (-1), but there are + some interfaces with known location, then return the second most + location of the provided interfaces. + + :param node: Node from DICT__nodes. + :param iface_keys: Interface keys for lookup. + :type node: dict + :type iface_keys: strings + """ + numa_list = [] + for if_key in iface_keys: + try: + numa_list.append(node['interfaces'][if_key].get('numa_node')) + except KeyError: + pass + + numa_cnt_mc = Counter(numa_list).most_common() + + if len(numa_cnt_mc) > 0 and numa_cnt_mc[0][0] != -1: + return numa_cnt_mc[0][0] + elif len(numa_cnt_mc) > 1 and numa_cnt_mc[0][0] == -1: + return numa_cnt_mc[1][0] + else: + return 0 @staticmethod - def get_adjacent_node_and_interface_by_key(nodes_info, node, port_key): - """Get node and interface adjacent to specified interface - on local network. + def get_interface_mac(node, iface_key): + """Get MAC address for the interface. - :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 + :param node: Node to get interface mac on. + :param iface_key: Interface key from topology file. :type node: dict - :type port_key: str - :return: Return (node, interface info) tuple or None if not found. - :rtype: (dict, dict) + :type iface_key: str + :returns: Return MAC or None if not found. """ - 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: + try: + return node['interfaces'][iface_key].get('mac_address') + except KeyError: 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): + def get_adjacent_node_and_interface(nodes_info, node, iface_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 interface_name: Interface name. + :param iface_key: Interface key from topology file. :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) + :type iface_key: str + :returns: Return (node, interface_key) tuple or None if not found. + :rtype: (dict, str) """ link_name = None # get link name where the interface belongs to - for port_name, port_data in node['interfaces'].iteritems(): - if port_data['name'] == interface_name: - link_name = port_data['link'] + for if_key, if_val in node['interfaces'].iteritems(): + if if_key == 'mgmt': + continue + if if_key == iface_key: + link_name = if_val['link'] break if link_name is None: @@ -305,42 +631,53 @@ class Topology(object): # skip self if node_data['host'] == node['host']: continue - for interface, interface_data \ + for if_key, if_val \ in node_data['interfaces'].iteritems(): - if 'link' not in interface_data: + if 'link' not in if_val: continue - if interface_data['link'] == link_name: - return node_data, node_data['interfaces'][interface] + if if_val['link'] == link_name: + return node_data, if_key @staticmethod - def get_interface_pci_addr(node, interface): + def get_interface_pci_addr(node, iface_key): """Get interface PCI address. :param node: Node to get interface PCI address on. - :param interface: Interface name. + :param iface_key: Interface key from topology file. :type node: dict - :type interface: str - :return: Return PCI address or None if not found. + :type iface_key: str + :returns: Return PCI address or None if not found. """ - for port in node['interfaces'].values(): - if interface == port.get('name'): - return port.get('pci_address') - return None + try: + return node['interfaces'][iface_key].get('pci_address') + except KeyError: + return None @staticmethod - def get_interface_driver(node, interface): + def get_interface_driver(node, iface_key): """Get interface driver. :param node: Node to get interface driver on. - :param interface: Interface name. + :param iface_key: Interface key from topology file. :type node: dict - :type interface: str - :return: Return interface driver or None if not found. + :type iface_key: str + :returns: Return interface driver or None if not found. """ - for port in node['interfaces'].values(): - if interface == port.get('name'): - return port.get('driver') - return None + try: + return node['interfaces'][iface_key].get('driver') + except KeyError: + return None + + @staticmethod + def get_node_interfaces(node): + """Get all node interfaces. + + :param node: Node to get list of interfaces from. + :type node: dict + :returns: Return list of keys of all interfaces. + :rtype: list + """ + return node['interfaces'].keys() @staticmethod def get_node_link_mac(node, link_name): @@ -350,7 +687,7 @@ class Topology(object): :param link_name: Link name. :type node: dict :type link_name: str - :return: MAC address string. + :returns: MAC address string. :rtype: str """ for port in node['interfaces'].values(): @@ -366,7 +703,7 @@ class Topology(object): :param filter_list: Link filter criteria. :type node: dict :type filter_list: list of strings - :return: List of strings that represent link names occupied by the node. + :returns: List of strings representing link names occupied by the node. :rtype: list """ interfaces = node['interfaces'] @@ -378,7 +715,7 @@ class Topology(object): if filt == interface['model']: link_names.append(interface['link']) elif (filter_list is not None) and ('model' not in interface): - logger.trace("Cannot apply filter on interface: {}" \ + logger.trace('Cannot apply filter on interface: {}' .format(str(interface))) else: link_names.append(interface['link']) @@ -398,9 +735,9 @@ class Topology(object): :param filter_list_node2: Link filter criteria for node2. :type node1: dict :type node2: dict - :type filter_list1: list of strings - :type filter_list2: list of strings - :return: List of strings that represent connecting link names. + :type filter_list_node1: list of strings + :type filter_list_node2: list of strings + :returns: List of strings that represent connecting link names. :rtype: list """ @@ -432,7 +769,7 @@ class Topology(object): :param node2: Connected node. :type node1: dict :type node2: dict - :return: Name of link connecting the two nodes together. + :returns: Name of link connecting the two nodes together. :rtype: str :raises: RuntimeError """ @@ -442,15 +779,16 @@ class Topology(object): else: return connecting_links[0] - @keyword('Get egress interfaces on "${node1}" for link with "${node2}"') - def get_egress_interfaces_for_nodes(self, node1, node2): + @keyword('Get egress interfaces name on "${node1}" for link with ' + '"${node2}"') + def get_egress_interfaces_name_for_nodes(self, node1, node2): """Get egress interfaces on node1 for link with node2. :param node1: First node, node to get egress interface on. :param node2: Second node. :type node1: dict :type node2: dict - :return: Egress interfaces. + :returns: Egress interfaces. :rtype: list """ interfaces = [] @@ -469,19 +807,19 @@ class Topology(object): interfaces.append(name) return interfaces - @keyword('Get first egress interface on "${node1}" for link with ' + @keyword('Get first egress interface name on "${node1}" for link with ' '"${node2}"') def get_first_egress_interface_for_nodes(self, node1, node2): """Get first egress interface on node1 for link with node2. - :param node1: First node, node to get egress interface on. + :param node1: First node, node to get egress interface name on. :param node2: Second node. :type node1: dict :type node2: dict - :return: Egress interface. + :returns: Egress interface name. :rtype: str """ - interfaces = self.get_egress_interfaces_for_nodes(node1, node2) + interfaces = self.get_egress_interfaces_name_for_nodes(node1, node2) if not interfaces: raise RuntimeError('No egress interface for nodes') return interfaces[0] @@ -511,7 +849,7 @@ class Topology(object): :type tgen: dict :type dut1: dict :type dut2: dict - :return: Dictionary of possible link combinations. + :returns: Dictionary of possible link combinations. :rtype: dict """ # TODO: replace with generic function. @@ -535,7 +873,7 @@ class Topology(object): :param node: Node to examine. :type node: dict - :return: True if node is type of TG, otherwise False. + :returns: True if node is type of TG, otherwise False. :rtype: bool """ return node['type'] == NodeType.TG @@ -546,7 +884,51 @@ class Topology(object): :param node: Node created from topology. :type node: dict - :return: Hostname or IP address. + :returns: Hostname or IP address. :rtype: str """ return node['host'] + + @staticmethod + def get_cryptodev(node): + """Return Crytodev configuration of the node. + + :param node: Node created from topology. + :type node: dict + :returns: Cryptodev configuration string. + :rtype: str + """ + try: + return node['cryptodev'] + except KeyError: + return None + + @staticmethod + def get_uio_driver(node): + """Return uio-driver configuration of the node. + + :param node: Node created from topology. + :type node: dict + :returns: uio-driver configuration string. + :rtype: str + """ + try: + return node['uio_driver'] + except KeyError: + return None + + @staticmethod + def set_interface_numa_node(node, iface_key, numa_node_id): + """Set interface numa_node location. + + :param node: Node to set numa_node on. + :param iface_key: Interface key from topology file. + :type node: dict + :type iface_key: str + :returns: Return iface_key or None if not found. + """ + try: + node['interfaces'][iface_key]['numa_node'] = numa_node_id + return iface_key + except KeyError: + return None