diff options
author | Peter Mikus <pmikus@cisco.com> | 2017-06-09 09:28:10 +0200 |
---|---|---|
committer | Peter Mikus <pmikus@cisco.com> | 2017-06-12 13:21:14 +0000 |
commit | 5f6802ba1d16005e7562f0eace81512dddab6762 (patch) | |
tree | 6eeeb048eea420d78c62149c9d7600c29912f93c /resources/libraries/python/VppConfigGenerator.py | |
parent | dae0c43759ddbdac0b707ea1ba55b249913fb187 (diff) |
CSIT-646 Refactor VPPConfigGenerator script
Currently the VPPConfigGenerator script is not modular enough for creating
all combinations of VPP startup configuration. This patch is supposed to
implement unified structured way to create all configuration options.
Change-Id: If3f9cf5dc838fe0a698ea1c601abff6c4c0468b5
Signed-off-by: Peter Mikus <pmikus@cisco.com>
Diffstat (limited to 'resources/libraries/python/VppConfigGenerator.py')
-rw-r--r-- | resources/libraries/python/VppConfigGenerator.py | 660 |
1 files changed, 205 insertions, 455 deletions
diff --git a/resources/libraries/python/VppConfigGenerator.py b/resources/libraries/python/VppConfigGenerator.py index 2a8f202721..039f629309 100644 --- a/resources/libraries/python/VppConfigGenerator.py +++ b/resources/libraries/python/VppConfigGenerator.py @@ -11,558 +11,308 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""VPP Configuration File Generator library""" +"""VPP Configuration File Generator library.""" import re import time -from robot.api import logger - from resources.libraries.python.ssh import SSH from resources.libraries.python.topology import NodeType from resources.libraries.python.topology import Topology __all__ = ['VppConfigGenerator'] -# -# VPP configuration template. -# TODO: Do we need a better place for this? Somewhere in an external -# (template) file? -# Note: We're going to pass this through Python string Formatter, so -# any literal curly braces need to be escaped. -# -VPP_SERVICE_NAME = "vpp" -VPP_CONFIG_FILENAME = "/etc/vpp/startup.conf" -DEFAULT_SOCKETMEM_CONFIG = "1024,1024" -VPP_CONFIG_TEMPLATE = """ -unix {{ - nodaemon - log /tmp/vpe.log - cli-listen localhost:5002 - full-coredump -}} - -api-trace {{ - on -}} -{heapsizeconfig} -cpu {{ -{cpuconfig} -}} - -dpdk {{ - socket-mem {socketmemconfig} - dev default {{ - {rxqueuesconfig} - {txqueuesconfig} - }} -{pciconfig} - {cryptodevconfig} - {uiodriverconfig} -{nomultiseg} -{enablevhostuser} -}} - -ip6 {{ - hash-buckets 2000000 - heap-size 3G -}} -{snatconfig} -""" -# End VPP configuration template. - - class VppConfigGenerator(object): - """VPP Configuration File Generator""" + """VPP Configuration File Generator.""" def __init__(self): + # VPP Node to apply configuration on + self._node = '' + # VPP Hostname + self._hostname = '' + # VPP Configuration self._nodeconfig = {} + # Serialized VPP Configuration + self._vpp_config = '' + # VPP Service name + self._vpp_service_name = 'vpp' + # VPP Configuration file path + self._vpp_config_filename = '/etc/vpp/startup.conf' - def add_pci_all_devices(self, node): - """Add all PCI devices from topology file to startup config + def set_node(self, node): + """Set DUT node. - :param node: DUT node + :param node: Node to store configuration on. :type node: dict - :returns: nothing + :raises RuntimeError: If Node type is not DUT. """ - for port in node['interfaces'].keys(): - pci_addr = Topology.get_interface_pci_addr(node, port) - if pci_addr: - self.add_pci_device(node, pci_addr) - def add_pci_device(self, node, *pci_devices): - """Add PCI device configuration for node. + if node['type'] != NodeType.DUT: + raise RuntimeError('Startup config can only be applied to DUT' + 'node.') + self._node = node + self._hostname = Topology.get_node_hostname(node) - :param node: DUT node. - :param pci_devices: PCI devices (format 0000:00:00.0 or 00:00.0) - :type node: dict - :type pci_devices: tuple - :returns: nothing + def set_config_filename(self, filename): + """Set startup configuration filename. + + :param filename: Startup configuration filename. + :type filename: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') + self._vpp_config_filename = filename - # Specific device was given. - hostname = Topology.get_node_hostname(node) + def add_config_item(self, config, value, path): + """Add startup configuration item. - pattern = re.compile("^[0-9A-Fa-f]{4}:[0-9A-Fa-f]{2}:" - "[0-9A-Fa-f]{2}\\.[0-9A-Fa-f]$") - for pci_device in pci_devices: - if not pattern.match(pci_device): - raise ValueError('PCI address {} to be added to host {} ' - 'is not in valid format xxxx:xx:xx.x'. - format(pci_device, hostname)) + :param config: Startup configuration of node. + :param value: Value to insert. + :param path: Path where to insert item. + :type config: dict + :type value: str + :type path: list + """ - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - if 'pci_addrs' not in self._nodeconfig[hostname]: - self._nodeconfig[hostname]['pci_addrs'] = [] - self._nodeconfig[hostname]['pci_addrs'].append(pci_device) - logger.debug('Adding PCI device {1} to {0}'.format(hostname, - pci_device)) + if len(path) == 1: + config[path[0]] = value + return + if not config.has_key(path[0]): + config[path[0]] = {} + self.add_config_item(config[path[0]], value, path[1:]) - def add_cpu_config(self, node, cpu_config): - """Add CPU configuration for node. + def dump_config(self, obj, level=-1): + """Dump the startup configuration in VPP config format. - :param node: DUT node. - :param cpu_config: CPU configuration option, as a string. - :type node: dict - :type cpu_config: str + :param obj: Python Object to print. + :param nested_level: Nested level for indentation. + :type obj: Obj + :type nested_level: int :returns: nothing """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - if 'cpu_config' not in self._nodeconfig[hostname]: - self._nodeconfig[hostname]['cpu_config'] = [] - self._nodeconfig[hostname]['cpu_config'].append(cpu_config) - logger.debug('Adding {} to hostname {} CPU config'.format(hostname, - cpu_config)) - - def add_socketmem_config(self, node, socketmem_config): - """Add Socket Memory configuration for node. - - :param node: DUT node. - :param socketmem_config: Socket Memory configuration option, - as a string. - :type node: dict - :type socketmem_config: str - :returns: nothing + indent = ' ' + if level >= 0: + self._vpp_config += '{}{{\n'.format((level) * indent) + if isinstance(obj, dict): + for key, val in obj.items(): + if hasattr(val, '__iter__'): + self._vpp_config += '{}{}\n'.format((level + 1) * indent, + key) + self.dump_config(val, level + 1) + else: + self._vpp_config += '{}{} {}\n'.format((level + 1) * indent, + key, val) + else: + for val in obj: + self._vpp_config += '{}{}\n'.format((level + 1) * indent, val) + if level >= 0: + self._vpp_config += '{}}}\n'.format(level * indent) + + def add_unix_log(self, value='/tmp/vpe.log'): + """Add UNIX log configuration. + + :param value: Log file. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - self._nodeconfig[hostname]['socketmem_config'] = socketmem_config - logger.debug('Setting hostname {} Socket Memory config to {}'. - format(hostname, socketmem_config)) - - def add_heapsize_config(self, node, heapsize_config): - """Add Heap Size configuration for node. - - :param node: DUT node. - :param heapsize_config: Heap Size configuration, as a string. - :type node: dict - :type heapsize_config: str - :returns: nothing - """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - self._nodeconfig[hostname]['heapsize_config'] = heapsize_config - logger.debug('Setting hostname {} Heap Size config to {}'. - format(hostname, heapsize_config)) - - def add_rxqueues_config(self, node, rxqueues_config): - """Add Rx Queues configuration for node. - - :param node: DUT node. - :param rxqueues_config: Rxqueues configuration, as a string. - :type node: dict - :type rxqueues_config: str - :returns: nothing - """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - if 'rxqueues_config' not in self._nodeconfig[hostname]: - self._nodeconfig[hostname]['rxqueues_config'] = [] - self._nodeconfig[hostname]['rxqueues_config'].append(rxqueues_config) - logger.debug('Setting hostname {} rxqueues config to {}'. - format(hostname, rxqueues_config)) - - def add_no_multi_seg_config(self, node): - """Add No Multi Seg configuration for node. - - :param node: DUT node. - :type node: dict - :returns: nothing - """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - if 'no_multi_seg_config' not in self._nodeconfig[hostname]: - self._nodeconfig[hostname]['no_multi_seg_config'] = [] - self._nodeconfig[hostname]['no_multi_seg_config'].append("no-multi-seg") - logger.debug('Setting hostname {} config with {}'. - format(hostname, "no-multi-seg")) - - def add_enable_vhost_user_config(self, node): - """Add enable-vhost-user configuration for node. - - :param node: DUT node. - :type node: dict - :returns: nothing + path = ['unix', 'log'] + self.add_config_item(self._nodeconfig, value, path) + + def add_unix_cli_listen(self, value='localhost:5002'): + """Add UNIX cli-listen configuration. + + :param value: CLI listen address and port. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - if 'enable_vhost_user' not in self._nodeconfig[hostname]: - self._nodeconfig[hostname]['enable_vhost_user'] = [] - self._nodeconfig[hostname]['enable_vhost_user'].\ - append("enable-vhost-user") - logger.debug('Setting hostname {} config with {}'. - format(hostname, "enable-vhost-user")) - - def add_snat_config(self, node): - """Add SNAT configuration for the node. - - :param node: DUT node. - :type node: dict - :returns: nothing + path = ['unix', 'cli-listen'] + self.add_config_item(self._nodeconfig, value, path) + self._nodeconfig = {'unix': {'nodaemon': ''}} + + def add_unix_nodaemon(self): + """Add UNIX nodaemon configuration.""" + path = ['unix', 'nodaemon'] + self.add_config_item(self._nodeconfig, '', path) + + def add_dpdk_dev(self, *devices): + """Add DPDK PCI device configuration. + + :param devices: PCI device(s) (format xxxx:xx:xx.x) + :type devices: tuple + :raises ValueError: If PCI address format is not valid. """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - if 'snat_config' not in self._nodeconfig[hostname]: - self._nodeconfig[hostname]['snat_config'] = [] - self._nodeconfig[hostname]['snat_config'].append("deterministic") - logger.debug('Setting hostname {} config with {}'. - format(hostname, "SNAT")) - - def add_cryptodev_config(self, node, count): - """Add cryptodev configuration for node. - - :param node: DUT node. + + pattern = re.compile("^[0-9A-Fa-f]{4}:[0-9A-Fa-f]{2}:" + "[0-9A-Fa-f]{2}\\.[0-9A-Fa-f]$") + for device in devices: + if not pattern.match(device): + raise ValueError('PCI address {} to be added to host {} ' + 'is not in valid format xxxx:xx:xx.x'. + format(device, self._hostname)) + path = ['dpdk', 'dev {0}'.format(device)] + self.add_config_item(self._nodeconfig, '', path) + + def add_dpdk_cryptodev(self, count): + """Add DPDK Crypto PCI device configuration. + :param count: Number of crypto devices to add. - :type node: dict :type count: int - :returns: nothing - :raises ValueError: If node type is not a DUT """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname not in self._nodeconfig: - self._nodeconfig[hostname] = {} - - cryptodev = Topology.get_cryptodev(node) - cryptodev_config = '' - + cryptodev = Topology.get_cryptodev(self._node) for i in range(count): - cryptodev_config += 'dev {}\n'.format( + cryptodev_config = 'dev {0}'.format( re.sub(r'\d.\d$', '1.'+str(i), cryptodev)) + path = ['dpdk', cryptodev_config] + self.add_config_item(self._nodeconfig, '', path) + self.add_dpdk_uio_driver('igb_uio') - self._nodeconfig[hostname]['cryptodev_config'] = cryptodev_config - logger.debug('Setting hostname {} Cryptodev config to {}'. - format(hostname, cryptodev_config)) - - uio_driver_config = 'uio-driver {}'.\ - format(Topology.get_uio_driver(node)) + def add_dpdk_dev_default_rxq(self, value): + """Add DPDK dev default rxq configuration. - self._nodeconfig[hostname]['uio_driver_config'] = uio_driver_config - logger.debug('Setting hostname {} uio_driver config to {}'. - format(hostname, uio_driver_config)) + :param value: Default number of rxqs. + :type value: str + """ + path = ['dpdk', 'dev default', 'num-rx-queues'] + self.add_config_item(self._nodeconfig, value, path) - def remove_all_pci_devices(self, node): - """Remove PCI device configuration from node. + def add_dpdk_dev_default_txq(self, value): + """Add DPDK dev default txq configuration. - :param node: DUT node. - :type node: dict - :returns: nothing + :param value: Default number of txqs. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname]['pci_addrs'] = [] - logger.debug('Clearing all PCI devices for hostname {}.'. - format(hostname)) + path = ['dpdk', 'dev default', 'num-tx-queues'] + self.add_config_item(self._nodeconfig, value, path) - def remove_all_cpu_config(self, node): - """Remove CPU configuration from node. + def add_dpdk_socketmem(self, value): + """Add DPDK socket memory configuration. - :param node: DUT node. - :type node: dict - :returns: nothing + :param value: Socket memory size. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname]['cpu_config'] = [] - logger.debug('Clearing all CPU config for hostname {}.'. - format(hostname)) + path = ['dpdk', 'socket-mem'] + self.add_config_item(self._nodeconfig, value, path) - def remove_socketmem_config(self, node): - """Remove Socket Memory configuration from node. + def add_dpdk_uio_driver(self, value): + """Add DPDK uio-driver configuration. - :param node: DUT node. - :type node: dict - :returns: nothing + :param value: DPDK uio-driver configuration. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname].pop('socketmem_config', None) - logger.debug('Clearing Socket Memory config for hostname {}.'. - format(hostname)) + path = ['dpdk', 'uio-driver'] + self.add_config_item(self._nodeconfig, value, path) - def remove_cryptodev_config(self, node): - """Remove Cryptodev configuration from node. + def add_cpu_main_core(self, value): + """Add CPU main core configuration. - :param node: DUT node. - :type node: dict - :returns: nothing - :raises ValueError: If node type is not a DUT + :param value: Main core option. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname].pop('cryptodev_config', None) - logger.debug('Clearing Cryptodev config for hostname {}.'. - format(hostname)) + path = ['cpu', 'main-core'] + self.add_config_item(self._nodeconfig, value, path) - def remove_heapsize_config(self, node): - """Remove Heap Size configuration from node. + def add_cpu_corelist_workers(self, value): + """Add CPU corelist-workers configuration. - :param node: DUT node. - :type node: dict - :returns: nothing + :param value: Corelist-workers option. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname].pop('heapsize_config', None) - logger.debug('Clearing Heap Size config for hostname {}.'. - format(hostname)) + path = ['cpu', 'corelist-workers'] + self.add_config_item(self._nodeconfig, value, path) - def remove_rxqueues_config(self, node): - """Remove Rxqueues configuration from node. + def add_heapsize(self, value): + """Add Heapsize configuration. - :param node: DUT node. - :type node: dict - :returns: nothing + :param value: Amount of heapsize. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname]['rxqueues_config'] = [] - logger.debug('Clearing rxqueues config for hostname {}.'. - format(hostname)) + path = ['heapsize'] + self.add_config_item(self._nodeconfig, value, path) - def remove_no_multi_seg_config(self, node): - """Remove No Multi Seg configuration from node. + def add_api_trace(self): + """Add API trace configuration.""" + path = ['api-trace', 'on'] + self.add_config_item(self._nodeconfig, path, '') - :param node: DUT node. - :type node: dict - :returns: nothing + def add_ip6_hash_buckets(self, value): + """Add IP6 hash buckets configuration. + + :param value: Number of IP6 hash buckets. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname]['no_multi_seg_config'] = [] - logger.debug('Clearing No Multi Seg config for hostname {}.'. - format(hostname)) + path = ['ip6', 'hash-buckets'] + self.add_config_item(self._nodeconfig, value, path) - def remove_enable_vhost_user_config(self, node): - """Remove enable-vhost-user configuration from node. + def add_ip6_heap_size(self, value): + """Add IP6 heap-size configuration. - :param node: DUT node. - :type node: dict - :returns: nothing + :param value: IP6 Heapsize amount. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname]['enable_vhost_user'] = [] - logger.debug('Clearing enable-vhost-user config for hostname {}.'. - format(hostname)) + path = ['ip6', 'heap-size'] + self.add_config_item(self._nodeconfig, value, path) - def remove_snat_config(self, node): - """Remove SNAT configuration for the node. + def add_dpdk_no_multi_seg(self): + """Add DPDK no-multi-seg configuration.""" + path = ['dpdk', 'no-multi-seg'] + self.add_config_item(self._nodeconfig, '', path) - :param node: DUT node. - :type node: dict - :returns: nothing + def add_snat(self, value='deterministic'): + """Add SNAT configuration. + + :param value: SNAT mode. + :type value: str """ - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - if hostname in self._nodeconfig: - self._nodeconfig[hostname]['snat_config'] = [] - logger.debug('Clearing SNAT config for hostname {}.'.format(hostname)) + path = ['snat'] + self.add_config_item(self._nodeconfig, value, path) - def apply_config(self, node, waittime=5, retries=12): + def apply_config(self, waittime=5, retries=12): """Generate and apply VPP configuration for node. Use data from calls to this class to form a startup.conf file and replace /etc/vpp/startup.conf with it on node. - :param node: DUT node. :param waittime: Time to wait for VPP to restart (default 5 seconds). :param retries: Number of times (default 12) to re-try waiting. - :type node: dict :type waittime: int :type retries: int :raises RuntimeError: If writing config file failed, or restarting of VPP failed. """ - - if node['type'] != NodeType.DUT: - raise ValueError('Node type is not a DUT') - hostname = Topology.get_node_hostname(node) - - cpuconfig = "" - pciconfig = "" - socketmemconfig = DEFAULT_SOCKETMEM_CONFIG - heapsizeconfig = "" - rxqueuesconfig = "" - txqueuesconfig = "" - nomultiseg = "" - enablevhostuser = "" - cryptodevconfig = "" - uiodriverconfig = "" - snatconfig = "" - - if hostname in self._nodeconfig: - cfg = self._nodeconfig[hostname] - if 'cpu_config' in cfg: - cpuconfig = " " + "\n ".join(cfg['cpu_config']) - - if 'pci_addrs' in cfg: - pciconfig = " dev " + "\n dev ".join(cfg['pci_addrs']) - - if 'socketmem_config' in cfg: - socketmemconfig = cfg['socketmem_config'] - - if 'cryptodev_config' in cfg: - cryptodevconfig = cfg['cryptodev_config'] - - if 'uio_driver_config' in cfg: - uiodriverconfig = cfg['uio_driver_config'] - - if 'heapsize_config' in cfg: - heapsizeconfig = "\nheapsize {}\n".\ - format(cfg['heapsize_config']) - - if 'rxqueues_config' in cfg: - rxqueuesconfig = " " + "\n ".join(cfg['rxqueues_config']) - - if 'no_multi_seg_config' in cfg: - nomultiseg = " " + "\n ".join(cfg['no_multi_seg_config']) - - if 'enable_vhost_user' in cfg: - enablevhostuser = " " + "\n ".join(cfg['enable_vhost_user']) - - if 'snat_config' in cfg: - snatconfig = "snat {\n" - snatconfig += " " + "\n ".join(cfg['snat_config']) - snatconfig += "\n}" - - vppconfig = VPP_CONFIG_TEMPLATE.format(cpuconfig=cpuconfig, - pciconfig=pciconfig, - cryptodevconfig=cryptodevconfig, - uiodriverconfig=uiodriverconfig, - socketmemconfig=socketmemconfig, - heapsizeconfig=heapsizeconfig, - rxqueuesconfig=rxqueuesconfig, - txqueuesconfig=txqueuesconfig, - nomultiseg=nomultiseg, - enablevhostuser=enablevhostuser, - snatconfig=snatconfig) - - logger.debug('Writing VPP config to host {}: "{}"'.format(hostname, - vppconfig)) + self.dump_config(self._nodeconfig) ssh = SSH() - ssh.connect(node) + ssh.connect(self._node) # We're using this "| sudo tee" construct because redirecting - # a sudo'd outut ("sudo echo xxx > /path/to/file") does not + # a sudo's output ("sudo echo xxx > /path/to/file") does not # work on most platforms... - (ret, stdout, stderr) = \ + (ret, _, _) = \ ssh.exec_command('echo "{0}" | sudo tee {1}'. - format(vppconfig, VPP_CONFIG_FILENAME)) + format(self._vpp_config, + self._vpp_config_filename)) if ret != 0: - logger.debug('Writing config file failed to node {}'. - format(hostname)) - logger.debug('stdout: {}'.format(stdout)) - logger.debug('stderr: {}'.format(stderr)) raise RuntimeError('Writing config file failed to node {}'. - format(hostname)) + format(self._hostname)) # Instead of restarting, we'll do separate start and stop # actions. This way we don't care whether VPP was running # to begin with. - ssh.exec_command('sudo service {} stop'.format(VPP_SERVICE_NAME)) - (ret, stdout, stderr) = \ - ssh.exec_command('sudo service {} start'.format(VPP_SERVICE_NAME)) + ssh.exec_command('sudo service {} stop' + .format(self._vpp_service_name)) + (ret, _, _) = \ + ssh.exec_command('sudo service {} start' + .format(self._vpp_service_name)) if ret != 0: - logger.debug('Restarting VPP failed on node {}'. - format(hostname)) - logger.debug('stdout: {}'.format(stdout)) - logger.debug('stderr: {}'.format(stderr)) raise RuntimeError('Restarting VPP failed on node {}'. - format(hostname)) + format(self._hostname)) # Sleep <waittime> seconds, up to <retry> times, # and verify if VPP is running. - vpp_is_running = False - retries_left = retries - while (not vpp_is_running) and (retries_left > 0): + for _ in range(retries): time.sleep(waittime) - retries_left -= 1 - - # FIXME: Need to find a good way to check if VPP is operational. - # - # If VatTerminal/VatExecutor is anything like vppctl or - # vpp_api_test, then in case VPP is NOT running it will block for - # 30 seconds or so and not even return if VPP becomes alive during - # that time. This makes it unsuitable in this case. We either need - # a call that returns immediately, indicating whether VPP is - # healthy or not, or a call that waits (up to a defined length - # of time) and returns immediately if VPP is or becomes healthy. - (ret, stdout, stderr) = \ + (ret, _, _) = \ ssh.exec_command('echo show hardware-interfaces | ' - 'nc 0 5002') + 'nc 0 5002 || echo "VPP not yet running"') if ret == 0: - vpp_is_running = True - else: - logger.debug('VPP not yet running, {} retries left'. - format(retries_left)) - if retries_left == 0: + break + else: raise RuntimeError('VPP failed to restart on node {}'. - format(hostname)) - logger.debug('VPP interfaces found on node {}'. - format(stdout)) + format(self._hostname)) |