d53e57c309d2fcecf35f7fb6618a0d3d607e702b
[csit.git] / resources / libraries / python / VatExecutor.py
1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13 from ssh import SSH
14 from robot.api import logger
15 from constants import Constants
16 import json
17
18 __all__ = ['VatExecutor']
19
20
21 def cleanup_vat_json_output(json_output):
22     """Return VAT json output cleaned from VAT clutter.
23
24     Clean up VAT json output from clutter like vat# prompts and such
25     :param json_output: cluttered json output.
26     :return: cleaned up output json string
27     """
28
29     retval = json_output
30     clutter = ['vat#', 'dump_interface_table error: Misc']
31     for garbage in clutter:
32         retval = retval.replace(garbage, '')
33     return retval
34
35
36 class VatExecutor(object):
37
38     def __init__(self):
39         self._stdout = None
40         self._stderr = None
41         self._ret_code = None
42
43     def execute_script(self, vat_name, node, timeout=10, json_out=True):
44         """Copy local_path script to node, execute it and return result.
45
46         :param vat_name: name of the vat script file. Only the file name of
47             the script is required, the resources path is prepended
48             automatically.
49         :param node: node to execute the VAT script on.
50         :param timeout: seconds to allow the script to run.
51         :param json_out: require json output.
52         :return: (rc, stdout, stderr) tuple.
53         """
54
55         ssh = SSH()
56         ssh.connect(node)
57
58         remote_file_path = '{0}/{1}/{2}'.format(Constants.REMOTE_FW_DIR,
59                                                 Constants.RESOURCES_TPL_VAT,
60                                                 vat_name)
61         # TODO this overwrites the output if the vat script has been used twice
62         remote_file_out = remote_file_path + ".out"
63
64         cmd = "sudo -S {vat} {json} < {input}".format(
65             vat=Constants.VAT_BIN_NAME,
66             json="json" if json_out is True else "",
67             input=remote_file_path)
68         (ret_code, stdout, stderr) = ssh.exec_command(cmd, timeout)
69         self._ret_code = ret_code
70         self._stdout = stdout
71         self._stderr = stderr
72
73         logger.trace("Command '{0}' returned {1}'".format(cmd, self._ret_code))
74         logger.trace("stdout: '{0}'".format(self._stdout))
75         logger.trace("stderr: '{0}'".format(self._stderr))
76
77         # TODO: download vpp_api_test output file
78         # self._delete_files(node, remote_file_path, remote_file_out)
79
80     def execute_script_json_out(self, vat_name, node, timeout=10,):
81         self.execute_script(vat_name, node, timeout, json_out=True)
82         self._stdout = cleanup_vat_json_output(self._stdout)
83
84     def _delete_files(self, node, *files):
85         ssh = SSH()
86         ssh.connect(node)
87         files = " ".join([str(x) for x in files])
88         ssh.exec_command("rm {0}".format(files))
89
90     def script_should_have_failed(self):
91         if self._ret_code is None:
92             raise Exception("First execute the script!")
93         if self._ret_code == 0:
94             raise AssertionError(
95                 "Script execution passed, but failure was expected")
96
97     def script_should_have_passed(self):
98         if self._ret_code is None:
99             raise Exception("First execute the script!")
100         if self._ret_code != 0:
101             raise AssertionError(
102                 "Script execution failed, but success was expected")
103
104     def get_script_stdout(self):
105         return self._stdout
106
107     def get_script_stderr(self):
108         return self._stderr
109
110     @staticmethod
111     def cmd_from_template(node, vat_template_file, **vat_args):
112         """Execute VAT script on specified node. This method supports
113          script templates with parameters
114         :param node: node in topology on witch the scrtipt is executed
115         :param vat_template_file: template file of VAT script
116         :param vat_args: arguments to the template file
117         :return: list of json objects returned by VAT
118         """
119         vat = VatTerminal(node)
120         ret = vat.vat_terminal_exec_cmd_from_template(vat_template_file,
121                                                       **vat_args)
122         vat.vat_terminal_close()
123         return ret
124
125     @staticmethod
126     def copy_config_to_remote(node, local_path, remote_path):
127         # TODO: will be removed once v4 is merged to master.
128         """Copies vat configuration file to node
129
130         :param node: Remote node on which to copy the VAT configuration file
131         :param local_path: path of the VAT script on local device that launches
132         test cases.
133         :param remote_path: path on remote node where to copy the VAT
134         configuration script file
135         """
136         ssh = SSH()
137         ssh.connect(node)
138         logger.trace("Removing old file {}".format(remote_path))
139         ssh.exec_command_sudo("rm -f {}".format(remote_path))
140         ssh.scp(local_path, remote_path)
141
142
143 class VatTerminal(object):
144     """VAT interactive terminal
145
146        :param node: Node to open VAT terminal on.
147     """
148
149     __VAT_PROMPT = "vat# "
150     __LINUX_PROMPT = ":~$ "
151
152     def __init__(self, node):
153         self._ssh = SSH()
154         self._ssh.connect(node)
155         self._tty = self._ssh.interactive_terminal_open()
156         self._ssh.interactive_terminal_exec_command(
157             self._tty,
158             'sudo -S {vat} json'.format(vat=Constants.VAT_BIN_NAME),
159             self.__VAT_PROMPT)
160
161     def vat_terminal_exec_cmd(self, cmd):
162         """Execute command on the opened VAT terminal.
163
164            :param cmd: Command to be executed.
165
166            :return: Command output in python representation of JSON format.
167         """
168         logger.debug("Executing command in VAT terminal: {}".format(cmd));
169         out = self._ssh.interactive_terminal_exec_command(self._tty,
170                                                           cmd,
171                                                           self.__VAT_PROMPT)
172         logger.debug("VAT output: {}".format(out));
173         json_out = json.loads(out)
174         return json_out
175
176     def vat_terminal_close(self):
177         """Close VAT terminal."""
178         self._ssh.interactive_terminal_exec_command(self._tty,
179                                                     'quit',
180                                                     self.__LINUX_PROMPT)
181         self._ssh.interactive_terminal_close(self._tty)
182
183     def vat_terminal_exec_cmd_from_template(self, vat_template_file, **args):
184         """Execute VAT script from a file.
185         :param vat_template_file: template file name of a VAT script
186         :param args: dictionary of parameters for VAT script
187         :return: list of json objects returned by VAT
188         """
189         file_path = '{}/{}'.format(Constants.RESOURCES_TPL_VAT,
190                                    vat_template_file)
191         with open(file_path, 'r') as template_file:
192             cmd_template = template_file.readlines()
193         ret = []
194         for line_tmpl in cmd_template:
195             vat_cmd = line_tmpl.format(**args)
196             ret.append(self.vat_terminal_exec_cmd(vat_cmd.replace('\n', '')))
197         return ret