+ self._ssh.disconnect(self._node)
+
+ def clear(self):
+ """Empty the internal command list; return self.
+
+ Use when not sure whether previous usage has left something in the list.
+
+ :returns: self, so that method chaining is possible.
+ :rtype: PapiExecutor
+ """
+ self._api_command_list = list()
+ return self
+
+ def add(self, command, **kwargs):
+ """Add next command to internal command list; return self.
+
+ :param command: VPP API command.
+ :param kwargs: Optional key-value arguments.
+ :type command: str
+ :type kwargs: dict
+ :returns: self, so that method chaining is possible.
+ :rtype: PapiExecutor
+ """
+ self._api_command_list.append(dict(api_name=command, api_args=kwargs))
+ return self
+
+ def execute(self, process_reply=True, ignore_errors=False, timeout=120):
+ """Turn internal command list into proper data and execute; return
+ PAPI response.
+
+ This method also clears the internal command list.
+
+ :param process_reply: Process PAPI reply if True.
+ :param ignore_errors: If true, the errors in the reply are ignored.
+ :param timeout: Timeout in seconds.
+ :type process_reply: bool
+ :type ignore_errors: bool
+ :type timeout: int
+ :returns: Papi response including: papi reply, stdout, stderr and
+ return code.
+ :rtype: PapiResponse
+ :raises KeyError: If the reply is not correct.
+ """
+
+ local_list = self._api_command_list
+
+ # Clear first as execution may fail.
+ self.clear()
+
+ ret_code, stdout, stderr = self._execute_papi(local_list, timeout)
+
+ papi_reply = list()
+ if process_reply:
+ json_data = json.loads(stdout)
+ for data in json_data:
+ try:
+ api_reply_processed = dict(
+ api_name=data["api_name"],
+ api_reply=self._process_reply(data["api_reply"]))
+ except KeyError:
+ if ignore_errors:
+ continue
+ else:
+ raise
+ papi_reply.append(api_reply_processed)
+
+ return PapiResponse(papi_reply=papi_reply,
+ stdout=stdout,
+ stderr=stderr,
+ ret_code=ret_code)
+
+ def execute_should_pass(self, err_msg="Failed to execute PAPI command.",
+ process_reply=True, ignore_errors=False,
+ timeout=120):
+ """Execute the PAPI commands and check the return code.
+ Raise exception if the PAPI command(s) failed.
+
+ Note: There are two exceptions raised to distinguish two situations. If
+ not needed, re-implement using only RuntimeError.
+
+ :param err_msg: The message used if the PAPI command(s) execution fails.
+ :param process_reply: Indicate whether or not to process PAPI reply.
+ :param ignore_errors: If true, the errors in the reply are ignored.
+ :param timeout: Timeout in seconds.
+ :type err_msg: str
+ :type process_reply: bool
+ :type ignore_errors: bool
+ :type timeout: int
+ :returns: Papi response including: papi reply, stdout, stderr and
+ return code.
+ :rtype: PapiResponse
+ :raises RuntimeError: If no PAPI command(s) executed.
+ :raises AssertionError: If PAPI command(s) execution passed.
+ """
+
+ response = self.execute(process_reply=process_reply,
+ ignore_errors=ignore_errors,
+ timeout=timeout)
+
+ if response.ret_code != 0:
+ raise AssertionError(err_msg)
+ return response
+
+ def execute_should_fail(self,
+ err_msg="Execution of PAPI command did not fail.",
+ process_reply=False, ignore_errors=False,
+ timeout=120):
+ """Execute the PAPI commands and check the return code.
+ Raise exception if the PAPI command(s) did not fail.
+
+ It does not return anything as we expect it fails.
+
+ Note: There are two exceptions raised to distinguish two situations. If
+ not needed, re-implement using only RuntimeError.
+
+ :param err_msg: The message used if the PAPI command(s) execution fails.
+ :param process_reply: Indicate whether or not to process PAPI reply.
+ :param ignore_errors: If true, the errors in the reply are ignored.
+ :param timeout: Timeout in seconds.
+ :type err_msg: str
+ :type process_reply: bool
+ :type ignore_errors: bool
+ :type timeout: int
+ :raises RuntimeError: If no PAPI command(s) executed.
+ :raises AssertionError: If PAPI command(s) execution passed.
+ """
+
+ response = self.execute(process_reply=process_reply,
+ ignore_errors=ignore_errors,
+ timeout=timeout)
+
+ if response.ret_code == 0:
+ raise AssertionError(err_msg)