X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=resources%2Flibraries%2Fpython%2Ftopology.py;h=91578a5ccff7d5335f8c068f42d9c3c1cf5e2c02;hb=e7a8aec57027b1791178bccacd58facacc322f6a;hp=82516beb6b1274520a148a51e58c86cc84cf48f8;hpb=b4e5c717f5e2c39ded81f0c6f7b0f9f61945befd;p=csit.git diff --git a/resources/libraries/python/topology.py b/resources/libraries/python/topology.py index 82516beb6b..91578a5ccf 100644 --- a/resources/libraries/python/topology.py +++ b/resources/libraries/python/topology.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Cisco and/or its affiliates. +# Copyright (c) 2019 Cisco and/or its affiliates. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: @@ -13,6 +13,8 @@ """Defines nodes and topology structure.""" +import re + from collections import Counter from yaml import load @@ -21,7 +23,7 @@ from robot.api import logger from robot.libraries.BuiltIn import BuiltIn, RobotNotRunningError from robot.api.deco import keyword -__all__ = ["DICT__nodes", 'Topology', 'NodeType'] +__all__ = ["DICT__nodes", 'Topology', 'NodeType', 'SocketType'] def load_topo_from_yaml(): @@ -59,6 +61,13 @@ class NodeSubTypeTG(object): # IxNetwork IXNET = 'IXNET' +class SocketType(object): + """Defines socket types used in topology dictionaries.""" + # VPP Socket PAPI + PAPI = 'PAPI' + # VPP PAPI Stats (legacy option until stats are migrated to Socket PAPI) + STATS = 'STATS' + DICT__nodes = load_topo_from_yaml() @@ -80,6 +89,26 @@ class Topology(object): the methods without having filled active topology with internal nodes data. """ + def add_node_item(self, node, value, path): + """Add item to topology node. + + :param node: Topology node. + :param value: Value to insert. + :param path: Path where to insert item. + :type node: dict + :type value: str + :type path: list + """ + if len(path) == 1: + node[path[0]] = value + return + if path[0] not in node: + node[path[0]] = {} + elif isinstance(node[path[0]], str): + node[path[0]] = {} if node[path[0]] == '' \ + else {node[path[0]]: ''} + self.add_node_item(node[path[0]], value, path[1:]) + @staticmethod def add_new_port(node, ptype): """Add new port to the node to active topology. @@ -138,13 +167,40 @@ class Topology(object): :returns: Nothing """ port_types = ('subinterface', 'vlan_subif', 'memif', 'tap', 'vhost', - 'loopback', 'gre_tunnel', 'vxlan_tunnel', 'eth_bond') + 'loopback', 'gre_tunnel', 'vxlan_tunnel', 'eth_bond', + 'eth_avf') 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 remove_all_vif_ports(node): + """Remove all Virtual Interfaces on DUT node. + + :param node: Node to remove VIF ports on. + :type node: dict + :returns: Nothing + """ + reg_ex = re.compile(r'port\d+_vif\d+') + for if_key in list(node['interfaces']): + if re.match(reg_ex, if_key): + node['interfaces'].pop(if_key) + + @staticmethod + def remove_all_added_vif_ports_on_all_duts_from_topology(nodes): + """Remove all added Virtual Interfaces on all DUT nodes in + the topology. + + :param nodes: Nodes in the topology. + :type nodes: dict + :returns: Nothing + """ + for node_data in nodes.values(): + if node_data['type'] == NodeType.DUT: + Topology.remove_all_vif_ports(node_data) + @staticmethod def update_interface_sw_if_index(node, iface_key, sw_if_index): """Update sw_if_index on the interface from the node. @@ -184,6 +240,32 @@ class Topology(object): """ node['interfaces'][iface_key]['mac_address'] = str(mac_address) + @staticmethod + def update_interface_pci_address(node, iface_key, pci_address): + """Update pci_address on the interface from the node. + + :param node: Node to update PCI on. + :param iface_key: Topology key of the interface. + :param pci_address: PCI address. + :type node: dict + :type iface_key: str + :type pci_address: str + """ + node['interfaces'][iface_key]['pci_address'] = str(pci_address) + + @staticmethod + def update_interface_vlan(node, iface_key, vlan): + """Update VLAN on the interface from the node. + + :param node: Node to update VLAN on. + :param iface_key: Topology key of the interface. + :param vlan: VLAN ID. + :type node: dict + :type iface_key: str + :type vlan: str + """ + node['interfaces'][iface_key]['vlan'] = int(vlan) + @staticmethod def update_interface_vhost_socket(node, iface_key, vhost_socket): """Update vhost socket name on the interface from the node. @@ -369,28 +451,29 @@ class Topology(object): return retval @staticmethod - def get_interface_by_sw_index(node, sw_index): + def get_interface_by_sw_index(node, sw_if_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 node: The node topology dictionary. - :param sw_index: Sw_index of the link that a interface is connected to. + :param sw_if_index: sw_if_index of the link that a interface is + connected to. :type node: dict - :type sw_index: int + :type sw_if_index: int :returns: Interface name of the interface connected to the given link. :rtype: str """ return Topology._get_interface_by_key_value(node, "vpp_sw_index", - sw_index) + sw_if_index) @staticmethod 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 iface_key: Interface key from topology file, or sw_index. + :param iface_key: Interface key from topology file, or sw_if_index. :type node: dict :type iface_key: str/int :returns: Return sw_if_index or None if not found. @@ -682,6 +765,21 @@ class Topology(object): except KeyError: return None + @staticmethod + def get_interface_vlan(node, iface_key): + """Get interface vlan. + + :param node: Node to get interface driver on. + :param iface_key: Interface key from topology file. + :type node: dict + :type iface_key: str + :returns: Return interface vlan or None if not found. + """ + try: + return node['interfaces'][iface_key].get('vlan') + except KeyError: + return None + @staticmethod def get_node_interfaces(node): """Get all node interfaces. @@ -697,7 +795,7 @@ class Topology(object): def get_node_link_mac(node, link_name): """Return interface mac address by link name. - :param node: Node to get interface sw_index on. + :param node: Node to get interface sw_if_index on. :param link_name: Link name. :type node: dict :type link_name: str @@ -961,3 +1059,47 @@ class Topology(object): return iface_key except KeyError: return None + + def add_new_socket(self, node, socket_type, socket_id, socket_path): + """Add socket file of specific SocketType and ID to node. + + :param node: Node to add socket on. + :param socket_type: Socket type. + :param socket_id: Socket id. + :param socket_path: Socket absolute path. + :type node: dict + :type socket_type: SocketType + :type socket_id: str + :type socket path: str + """ + path = ['sockets', socket_type, socket_id] + self.add_node_item(node, socket_path, path) + + @staticmethod + def get_node_sockets(node, socket_type=None): + """Get node socket files. + + :param node: Node to get sockets from. + :param socket_type: Socket type or None for all sockets. + :type node: dict + :type socket_type: SocketType + :returns: Node sockets or None if not found. + :rtype: list + """ + try: + if socket_type: + return node['sockets'][socket_type] + return node['sockets'] + except KeyError: + return None + + @staticmethod + def clean_sockets_on_all_nodes(nodes): + """Remove temporary socket files from topology file. + + :param nodes: SUT nodes. + :type node: dict + """ + for node in nodes.values(): + if 'sockets' in node.keys(): + node.pop('sockets')