def add(self, csit_papi_command, history=True, **kwargs): """Add next command to internal command list; return self. Unless disabled, new entry to papi history is also added at this point. The argument name 'csit_papi_command' must be unique enough as it cannot be repeated in kwargs. The kwargs dict is deep-copied, so it is safe to use the original with partial modifications for subsequent commands. Any pending conflicts from .api.json processing are raised. Then the command name is checked for known CRCs. Unsupported commands raise an exception, as CSIT change should not start using messages without making sure which CRCs are supported. Each CRC issue is raised only once, so subsequent tests can raise other issues. :param csit_papi_command: VPP API command. :param history: Enable/disable adding command to PAPI command history. :param kwargs: Optional key-value arguments. :type csit_papi_command: str :type history: bool :type kwargs: dict :returns: self, so that method chaining is possible. :rtype: PapiSocketExecutor :raises RuntimeError: If unverified or conflicting CRC is encountered. """ self.crc_checker.report_initial_conflicts() if history: PapiHistory.add_to_papi_history(self._node, csit_papi_command, **kwargs) self.crc_checker.check_api_name(csit_papi_command) self._api_command_list.append( dict(api_name=csit_papi_command, api_args=copy.deepcopy(kwargs))) return self
def add(self, csit_papi_command=u"vpp-stats", history=True, **kwargs): """Add next command to internal command list; return self. The argument name 'csit_papi_command' must be unique enough as it cannot be repeated in kwargs. The kwargs dict is deep-copied, so it is safe to use the original with partial modifications for subsequent commands. :param csit_papi_command: VPP API command. :param history: Enable/disable adding command to PAPI command history. :param kwargs: Optional key-value arguments. :type csit_papi_command: str :type history: bool :type kwargs: dict :returns: self, so that method chaining is possible. :rtype: PapiExecutor """ if history: PapiHistory.add_to_papi_history( self._node, csit_papi_command, **kwargs ) self._api_command_list.append( dict( api_name=csit_papi_command, api_args=copy.deepcopy(kwargs) ) ) return self
def vat_terminal_exec_cmd(self, cmd): """Execute command on the opened VAT terminal. :param cmd: Command to be executed. :returns: Command output in python representation of JSON format or None if not in JSON mode. """ PapiHistory.add_to_papi_history(self._node, cmd, papi=False) logger.debug(f"Executing command in VAT terminal: {cmd}") try: out = self._ssh.interactive_terminal_exec_command( self._tty, cmd, self.__VAT_PROMPT ) self.vat_stdout = out except Exception: self._exec_failure = True vpp_pid = get_vpp_pid(self._node) if vpp_pid: if isinstance(vpp_pid, int): msg = f"VPP running on node {self._node[u'host']} " \ f"but VAT command {cmd} execution failed." else: msg = f"More instances of VPP running on node " \ f"{self._node[u'host']}. VAT command {cmd} " \ f"execution failed." else: msg = f"VPP not running on node {self._node[u'host']}. " \ f"VAT command {cmd} execution failed." raise RuntimeError(msg) logger.debug(f"VAT output: {out}") if self.json: obj_start = out.find(u"{") obj_end = out.rfind(u"}") array_start = out.find(u"[") array_end = out.rfind(u"]") if obj_start == -1 and array_start == -1: raise RuntimeError(f"VAT command {cmd}: no JSON data.") if obj_start < array_start or array_start == -1: start = obj_start end = obj_end + 1 else: start = array_start end = array_end + 1 out = out[start:end] json_out = json.loads(out) return json_out return None
def vat_terminal_exec_cmd(self, cmd): """Execute command on the opened VAT terminal. :param cmd: Command to be executed. :returns: Command output in python representation of JSON format or None if not in JSON mode. """ PapiHistory.add_to_papi_history(self._node, cmd, papi=False) logger.debug("Executing command in VAT terminal: {0}".format(cmd)) try: out = self._ssh.interactive_terminal_exec_command(self._tty, cmd, self.__VAT_PROMPT) self.vat_stdout = out except Exception: self._exec_failure = True vpp_pid = get_vpp_pid(self._node) if vpp_pid: if isinstance(vpp_pid, int): raise RuntimeError("VPP running on node {0} but VAT command" " {1} execution failed.". format(self._node['host'], cmd)) else: raise RuntimeError("More instances of VPP running on node " "{0}. VAT command {1} execution failed.". format(self._node['host'], cmd)) else: raise RuntimeError("VPP not running on node {0}. VAT command " "{1} execution failed.". format(self._node['host'], cmd)) logger.debug("VAT output: {0}".format(out)) if self.json: obj_start = out.find('{') obj_end = out.rfind('}') array_start = out.find('[') array_end = out.rfind(']') if obj_start == -1 and array_start == -1: raise RuntimeError("VAT command {0}: no JSON data.".format(cmd)) if obj_start < array_start or array_start == -1: start = obj_start end = obj_end + 1 else: start = array_start end = array_end + 1 out = out[start:end] json_out = json.loads(out) return json_out else: return None
def add(self, csit_papi_command="vpp-stats", history=True, **kwargs): """Add next command to internal command list; return self. The argument name 'csit_papi_command' must be unique enough as it cannot be repeated in kwargs. :param csit_papi_command: VPP API command. :param history: Enable/disable adding command to PAPI command history. :param kwargs: Optional key-value arguments. :type csit_papi_command: str :type history: bool :type kwargs: dict :returns: self, so that method chaining is possible. :rtype: PapiExecutor """ if history: PapiHistory.add_to_papi_history(self._node, csit_papi_command, **kwargs) self._api_command_list.append( dict(api_name=csit_papi_command, api_args=kwargs)) return self
def execute_script(self, vat_name, node, timeout=120, json_out=True, copy_on_execute=False, history=True): """Execute VAT script on remote node, and store the result. There is an option to copy script from local host to remote host before execution. Path is defined automatically. :param vat_name: Name of the vat script file. Only the file name of the script is required, the resources path is prepended automatically. :param node: Node to execute the VAT script on. :param timeout: Seconds to allow the script to run. :param json_out: Require JSON output. :param copy_on_execute: If true, copy the file from local host to remote before executing. :param history: If true, add command to history. :type vat_name: str :type node: dict :type timeout: int :type json_out: bool :type copy_on_execute: bool :type history: bool :raises SSHException: If cannot open connection for VAT. :raises SSHTimeout: If VAT execution is timed out. :raises RuntimeError: If VAT script execution fails. """ ssh = SSH() try: ssh.connect(node) except: raise SSHException( f"Cannot open SSH connection to execute VAT command(s) " f"from vat script {vat_name}") if copy_on_execute: ssh.scp(vat_name, vat_name) remote_file_path = vat_name if history: with open(vat_name, u"rt") as vat_file: for line in vat_file: PapiHistory.add_to_papi_history(node, line.replace( u"\n", u""), papi=False) else: remote_file_path = f"{Constants.REMOTE_FW_DIR}/" \ f"{Constants.RESOURCES_TPL_VAT}/{vat_name}" cmd = f"{Constants.VAT_BIN_NAME}" \ f"{u' json' if json_out is True else u''} " \ f"in {remote_file_path} script" try: ret_code, stdout, stderr = ssh.exec_command_sudo(cmd=cmd, timeout=timeout) except SSHTimeout: logger.error(f"VAT script execution timeout: {cmd}") raise except Exception: raise RuntimeError(f"VAT script execution failed: {cmd}") self._ret_code = ret_code self._stdout = stdout self._stderr = stderr self._script_name = vat_name
def execute_script(self, vat_name, node, timeout=120, json_out=True, copy_on_execute=False): """Execute VAT script on remote node, and store the result. There is an option to copy script from local host to remote host before execution. Path is defined automatically. :param vat_name: Name of the vat script file. Only the file name of the script is required, the resources path is prepended automatically. :param node: Node to execute the VAT script on. :param timeout: Seconds to allow the script to run. :param json_out: Require JSON output. :param copy_on_execute: If true, copy the file from local host to remote before executing. :type vat_name: str :type node: dict :type timeout: int :type json_out: bool :type copy_on_execute: bool :raises SSHException: If cannot open connection for VAT. :raises SSHTimeout: If VAT execution is timed out. :raises RuntimeError: If VAT script execution fails. """ ssh = SSH() try: ssh.connect(node) except: raise SSHException("Cannot open SSH connection to execute VAT " "command(s) from vat script {name}" .format(name=vat_name)) if copy_on_execute: ssh.scp(vat_name, vat_name) remote_file_path = vat_name with open(vat_name, 'r') as vat_file: for line in vat_file: PapiHistory.add_to_papi_history(node, line.replace('\n', ''), papi=False) else: remote_file_path = '{0}/{1}/{2}'.format(Constants.REMOTE_FW_DIR, Constants.RESOURCES_TPL_VAT, vat_name) cmd = "{vat_bin} {json} in {vat_path} script".format( vat_bin=Constants.VAT_BIN_NAME, json="json" if json_out is True else "", vat_path=remote_file_path) try: ret_code, stdout, stderr = ssh.exec_command_sudo(cmd=cmd, timeout=timeout) except SSHTimeout: logger.error("VAT script execution timeout: {0}".format(cmd)) raise except: raise RuntimeError("VAT script execution failed: {0}".format(cmd)) self._ret_code = ret_code self._stdout = stdout self._stderr = stderr self._script_name = vat_name