- :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))
-
- ssh = SSH()
- ssh.connect(node)
-
- # We're using this "| sudo tee" construct because redirecting
- # a sudo'd outut ("sudo echo xxx > /path/to/file") does not
- # work on most platforms...
- (ret, stdout, stderr) = \
- ssh.exec_command('echo "{0}" | sudo tee {1}'.
- format(vppconfig, 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))
-
- # 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))
- 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))
-
- # 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):
- 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) = \
- ssh.exec_command('echo show hardware-interfaces | '
- 'nc 0 5002')
- if ret == 0:
- vpp_is_running = True
- else:
- logger.debug('VPP not yet running, {} retries left'.
- format(retries_left))
- if retries_left == 0:
- raise RuntimeError('VPP failed to restart on node {}'.
- format(hostname))
- logger.debug('VPP interfaces found on node {}'.
- format(stdout))
+ :param filename: Startup configuration file name.
+ :type filename: str
+ """
+ self.dump_config(self._nodeconfig)
+
+ if filename is None:
+ filename = self._vpp_startup_conf
+
+ if self._vpp_startup_conf_backup is not None:
+ cmd = f"cp {self._vpp_startup_conf} {self._vpp_startup_conf_backup}"
+ exec_cmd_no_error(
+ self._node, cmd, sudo=True, message=u"Copy config file failed!"
+ )
+
+ cmd = f"echo \"{self._vpp_config}\" | sudo tee {filename}"
+ exec_cmd_no_error(
+ self._node, cmd, message=u"Writing config file failed!"
+ )
+
+ def apply_config(self, filename=None, verify_vpp=True):
+ """Generate and write VPP startup configuration to file and restart VPP.
+
+ Use data from calls to this class to form a startup.conf file and
+ replace /etc/vpp/startup.conf with it on topology node.
+
+ :param filename: Startup configuration file name.
+ :param verify_vpp: Verify VPP is running after restart.
+ :type filename: str
+ :type verify_vpp: bool
+ """
+ self.write_config(filename=filename)
+
+ VPPUtil.restart_vpp_service(self._node, self._node_key)
+ if verify_vpp:
+ VPPUtil.verify_vpp(self._node)
+
+ def restore_config(self):
+ """Restore VPP startup.conf from backup."""
+ cmd = f"cp {self._vpp_startup_conf_backup} {self._vpp_startup_conf}"
+ exec_cmd_no_error(
+ self._node, cmd, sudo=True, message=u"Copy config file failed!"
+ )