X-Git-Url: https://gerrit.fd.io/r/gitweb?p=csit.git;a=blobdiff_plain;f=resources%2Ftools%2Ftopology%2Fupdate_topology.py;h=37d64b1a05b818b0f7dc37eb6b84788c65b58963;hp=d7a3929643fe4b0070296fb4fa2dc889080e0fb0;hb=HEAD;hpb=8f77a1ac982b07802f0fb209f589708c27f3e9c5 diff --git a/resources/tools/topology/update_topology.py b/resources/tools/topology/update_topology.py index d7a3929643..37d64b1a05 100755 --- a/resources/tools/topology/update_topology.py +++ b/resources/tools/topology/update_topology.py @@ -20,51 +20,55 @@ extracts MAC address from it.""" import sys import os import re + from argparse import ArgumentParser import yaml from resources.libraries.python.ssh import SSH + def load_topology(args): """Load topology file referenced to by parameter passed to this script. - :param args: arguments parsed from commandline + :param args: Arguments parsed from commandline. :type args: ArgumentParser().parse_args() - :return: Python representation of topology yaml + :return: Python representation of topology YAML. :rtype: dict """ data = None - with open(args.topology, 'r') as stream: + with open(args.topology, u"rt") as stream: try: - data = yaml.load(stream) + data = yaml.safe_load(stream) except yaml.YAMLError as exc: - print 'Failed to load topology file: {0}'.format(args.topology) - print exc + print(f"Failed to load topology file: {args.topology}") + print(exc) raise return data + def ssh_no_error(ssh, cmd): """Execute a command over ssh channel, and log and exit if the command - fials. + fails. - :param ssh: SSH() object connected to a node - :param cmd: Command line to execute on remote node + :param ssh: SSH() object connected to a node. + :param cmd: Command line to execute on remote node. :type ssh: SSH() object :type cmd: str - :return: stdout from the SSH command + :return: stdout from the SSH command. :rtype: str """ ret, stdo, stde = ssh.exec_command(cmd) - if 0 != ret: - print 'Command execution failed: "{}"'.format(cmd) - print 'stdout: {0}'.format(stdo) - print 'stderr: {0}'.format(stde) - raise RuntimeError('Unexpected ssh command failure') + if ret != 0: + print(f"Command execution failed: '{cmd}'") + print(f"stdout: {stdo}") + print(f"stderr: {stde}") + raise RuntimeError(u"Unexpected ssh command failure") return stdo + def update_mac_addresses_for_node(node): """For given node loop over all ports with PCI address and look for its MAC address. @@ -73,15 +77,16 @@ def update_mac_addresses_for_node(node): and binds it to linux kernel driver. After the device is bound to specific linux kernel driver the MAC address is extracted from /sys/bus/pci location and stored within the node dictionary that was passed to this function. - :param node: Node from topology + + :param node: Node from topology. :type node: dict - :return: None """ - for port_name, port in node['interfaces'].items(): - if not port.has_key('driver'): - err_msg = '{0} port {1} has no driver element, exiting'.format( - node['host'], port_name) - raise RuntimeError(err_msg) + for port_name, port in node[u"interfaces"].items(): + if u"driver" not in port: + raise RuntimeError( + f"{node[u'host']} port {port_name} has no driver element, " + f"exiting" + ) ssh = SSH() ssh.connect(node) @@ -89,78 +94,82 @@ def update_mac_addresses_for_node(node): # TODO: make following SSH commands into one-liner to save on SSH opers # First unbind from current driver - drvr_dir_path = '/sys/bus/pci/devices/{0}/driver'.format( - port['pci_address']) - cmd = '''\ - if [ -d {0} ]; then - echo {1} | sudo tee {0}/unbind ; + drvr_dir_path = f"/sys/bus/pci/devices/{port[u'pci_address']}/driver" + cmd = f'''\ + if [ -d {drvr_dir_path} ]; then + echo {port[u'pci_address']} | sudo tee {drvr_dir_path}/unbind ; else true Do not have to do anything, port already unbound ; - fi'''.format(drvr_dir_path, port['pci_address']) + fi''' ssh_no_error(ssh, cmd) # Then bind to the 'driver' from topology for given port - cmd = 'echo {0} | sudo tee /sys/bus/pci/drivers/{1}/bind'.\ - format(port['pci_address'], port['driver']) + cmd = f"echo {port[u'pci_address']} | " \ + f"sudo tee /sys/bus/pci/drivers/{port[u'driver']}/bind" ssh_no_error(ssh, cmd) # Then extract the mac address and store it in the topology - cmd = 'cat /sys/bus/pci/devices/{0}/net/*/address'.format( - port['pci_address']) + cmd = f"cat /sys/bus/pci/devices/{port['pci_address']}/net/*/address" mac = ssh_no_error(ssh, cmd).strip() - pattern = re.compile("^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$") + pattern = re.compile(u"^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$") if not pattern.match(mac): - raise RuntimeError('MAC address read from host {0} {1} is in ' - 'bad format "{2}"'.format(node['host'], - port['pci_address'], mac)) - print '{0}: Found MAC address of PCI device {1}: {2}'.format( - node['host'], port['pci_address'], mac) - port['mac_address'] = mac + raise RuntimeError( + f"MAC address read from host {node[u'host']} " + f"{port[u'pci_address']} is in bad format '{mac}'" + ) + print( + f"{node[u'host']}: Found MAC address of PCI device " + f"{port[u'pci_address']}: {mac}" + ) + port[u"mac_address"] = mac + def update_nodes_mac_addresses(topology): """Loop over nodes in topology and get mac addresses for all listed ports based on PCI addresses. - :param topology: Topology information with nodes + :param topology: Topology information with nodes. :type topology: dict - :return: None """ - - for node in topology['nodes'].values(): + for node in topology[u"nodes"].values(): update_mac_addresses_for_node(node) + def dump_updated_topology(topology, args): """Writes or prints out updated topology file. - :param topology: Topology information with nodes - :param args: arguments parsed from command line + :param topology: Topology information with nodes. + :param args: Arguments parsed from command line. :type topology: dict :type args: ArgumentParser().parse_args() - :return: 1 if error occured, 0 if successful + :return: 1 if error occurred, 0 if successful. :rtype: int """ - if args.output_file: if not args.force: if os.path.isfile(args.output_file): - print ('File {0} already exists. If you want to overwrite this ' - 'file, add -f as a parameter to this script'.format( - args.output_file)) + print ( + f"File {args.output_file} already exists. If you want to " + f"overwrite this file, add -f as a parameter to this script" + ) return 1 - with open(args.output_file, 'w') as stream: + with open(args.output_file, u"wt") as stream: yaml.dump(topology, stream, default_flow_style=False) else: - print yaml.dump(topology, default_flow_style=False) + print(yaml.dump(topology, default_flow_style=False)) return 0 + def main(): """Main function""" parser = ArgumentParser() - parser.add_argument('topology', help="Topology yaml file to read") - parser.add_argument('--output-file', '-o', help='Output file') - parser.add_argument('-f', '--force', help='Overwrite existing file', - action='store_const', const=True) - parser.add_argument('--verbose', '-v', action='store_true') + parser.add_argument(u"topology", help=u"Topology yaml file to read") + parser.add_argument(u"--output-file", u"-o", help=u"Output file") + parser.add_argument( + u"-f", u"--force", help=u"Overwrite existing file", + action=u"store_const", const=True + ) + parser.add_argument(u"--verbose", u"-v", action=u"store_true") args = parser.parse_args() topology = load_topology(args) @@ -170,7 +179,5 @@ def main(): return ret -if __name__ == "__main__": +if __name__ == u"__main__": sys.exit(main()) - -