Merge "Unify Firewall testcases TG and VNF names"
authorVolodymyr Mytnyk <volodymyrx.mytnyk@intel.com>
Wed, 6 Feb 2019 16:05:55 +0000 (16:05 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Wed, 6 Feb 2019 16:05:55 +0000 (16:05 +0000)
samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_ixia_multi_framesize.yaml [new file with mode: 0644]
yardstick/benchmark/runners/sequence.py
yardstick/ssh.py
yardstick/tests/unit/test_ssh.py

diff --git a/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_ixia_multi_framesize.yaml b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_ixia_multi_framesize.yaml
new file mode 100644 (file)
index 0000000..dfbff28
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright (c) 2019 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf-RFC2544
+  traffic_profile: ../../traffic_profiles/ixia_ipv4_latency.yaml
+  topology: agnostic_vnf_topology_ixia_2ports.yaml
+  nodes:
+    tg__0: tg_0.yardstick
+    vnf__0: vnf_0.yardstick
+  options:
+    framesize:
+    flow:
+      src_ip: [{'tg__0': 'xe0'}]
+      dst_ip: [{'tg__0': 'xe1'}]
+      count: 1
+    traffic_type: 4
+    rfc2544:
+      allowed_drop_rate: 0.0001 - 0.0001
+    vnf__0:
+        []
+  runner:
+    type: Sequence
+    scenario_option_name: framesize
+    sequence:
+    - uplink: {64B: 100}
+      downlink: {64B: 100}
+    - uplink: {512B: 100}
+      downlink: {512B: 100}
+context:
+  type: Node
+  name: yardstick
+  nfvi_type: baremetal
+  file: /etc/yardstick/nodes/pod_ixia.yaml
index 0148a45..58ffddd 100644 (file)
@@ -38,8 +38,6 @@ LOG = logging.getLogger(__name__)
 def _worker_process(queue, cls, method_name, scenario_cfg,
                     context_cfg, aborted, output_queue):
 
-    sequence = 1
-
     runner_cfg = scenario_cfg['runner']
 
     interval = runner_cfg.get("interval", 1)
@@ -56,6 +54,7 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
     LOG.info("worker START, sequence_values(%s, %s), class %s",
              arg_name, sequence_values, cls)
 
+    scenario_output = base.ScenarioOutput(queue, sequence=1, errors="")
     benchmark = cls(scenario_cfg, context_cfg)
     benchmark.setup()
     method = getattr(benchmark, method_name)
@@ -68,22 +67,23 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
         options[arg_name] = value
 
         LOG.debug("runner=%(runner)s seq=%(sequence)s START",
-                  {"runner": runner_cfg["runner_id"], "sequence": sequence})
+                  {"runner": runner_cfg["runner_id"],
+                   "sequence": scenario_output.sequence})
 
-        data = {}
-        errors = ""
+        scenario_output.clear()
+        scenario_output.errors = ""
 
         try:
-            result = method(data)
+            result = method(scenario_output)
         except y_exc.SLAValidationError as error:
             # SLA validation failed in scenario, determine what to do now
             if sla_action == "assert":
                 raise
             elif sla_action == "monitor":
                 LOG.warning("SLA validation failed: %s", error.args)
-                errors = error.args
+                scenario_output.errors = error.args
         except Exception as e:  # pylint: disable=broad-except
-            errors = traceback.format_exc()
+            scenario_output.errors = traceback.format_exc()
             LOG.exception(e)
         else:
             if result:
@@ -91,21 +91,16 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
 
         time.sleep(interval)
 
-        benchmark_output = {
-            'timestamp': time.time(),
-            'sequence': sequence,
-            'data': data,
-            'errors': errors
-        }
-
-        queue.put(benchmark_output)
+        if scenario_output:
+            scenario_output.push()
 
         LOG.debug("runner=%(runner)s seq=%(sequence)s END",
-                  {"runner": runner_cfg["runner_id"], "sequence": sequence})
+                  {"runner": runner_cfg["runner_id"],
+                   "sequence": scenario_output.sequence})
 
-        sequence += 1
+        scenario_output.sequence += 1
 
-        if (errors and sla_action is None) or aborted.is_set():
+        if (scenario_output.errors and sla_action is None) or aborted.is_set():
             break
 
     try:
index 2ebf40e..438e815 100644 (file)
@@ -448,6 +448,86 @@ class SSH(object):
         with client.open_sftp() as sftp:
             sftp.getfo(remotepath, file_obj)
 
+    def interactive_terminal_open(self, time_out=45):
+        """Open interactive terminal on a SSH channel.
+
+        :param time_out: Timeout in seconds.
+        :returns: SSH channel with opened terminal.
+
+        .. warning:: Interruptingcow is used here, and it uses
+           signal(SIGALRM) to let the operating system interrupt program
+           execution. This has the following limitations: Python signal
+           handlers only apply to the main thread, so you cannot use this
+           from other threads. You must not use this in a program that
+           uses SIGALRM itself (this includes certain profilers)
+        """
+        chan = self._get_client().get_transport().open_session()
+        chan.get_pty()
+        chan.invoke_shell()
+        chan.settimeout(int(time_out))
+        chan.set_combine_stderr(True)
+
+        buf = ''
+        while not buf.endswith((":~# ", ":~$ ", "~]$ ", "~]# ")):
+            try:
+                chunk = chan.recv(10 * 1024 * 1024)
+                if not chunk:
+                    break
+                buf += chunk
+                if chan.exit_status_ready():
+                    self.log.error('Channel exit status ready')
+                    break
+            except socket.timeout:
+                raise exceptions.SSHTimeout(error_msg='Socket timeout: %s' % buf)
+        return chan
+
+    def interactive_terminal_exec_command(self, chan, cmd, prompt):
+        """Execute command on interactive terminal.
+
+        interactive_terminal_open() method has to be called first!
+
+        :param chan: SSH channel with opened terminal.
+        :param cmd: Command to be executed.
+        :param prompt: Command prompt, sequence of characters used to
+        indicate readiness to accept commands.
+        :returns: Command output.
+
+        .. warning:: Interruptingcow is used here, and it uses
+           signal(SIGALRM) to let the operating system interrupt program
+           execution. This has the following limitations: Python signal
+           handlers only apply to the main thread, so you cannot use this
+           from other threads. You must not use this in a program that
+           uses SIGALRM itself (this includes certain profilers)
+        """
+        chan.sendall('{c}\n'.format(c=cmd))
+        buf = ''
+        while not buf.endswith(prompt):
+            try:
+                chunk = chan.recv(10 * 1024 * 1024)
+                if not chunk:
+                    break
+                buf += chunk
+                if chan.exit_status_ready():
+                    self.log.error('Channel exit status ready')
+                    break
+            except socket.timeout:
+                message = ("Socket timeout during execution of command: "
+                           "%(cmd)s\nBuffer content:\n%(buf)s" % {"cmd": cmd,
+                                                                  "buf": buf})
+                raise exceptions.SSHTimeout(error_msg=message)
+        tmp = buf.replace(cmd.replace('\n', ''), '')
+        for item in prompt:
+            tmp.replace(item, '')
+        return tmp
+
+    @staticmethod
+    def interactive_terminal_close(chan):
+        """Close interactive terminal SSH channel.
+
+        :param: chan: SSH channel to be closed.
+        """
+        chan.close()
+
 
 class AutoConnectSSH(SSH):
 
index 71929f1..374fb66 100644 (file)
@@ -286,6 +286,48 @@ class SSHTestCase(unittest.TestCase):
         mock_paramiko_exec_command.assert_called_once_with('cmd',
                                                            get_pty=True)
 
+    @mock.patch("yardstick.ssh.paramiko")
+    def test_interactive_terminal_open(self, mock_paramiko):
+        fake_client = mock.Mock()
+        fake_session = mock.Mock()
+        fake_session.recv.return_value = ":~# "
+        fake_transport = mock.Mock()
+        fake_transport.open_session.return_value = fake_session
+        fake_client.get_transport.return_value = fake_transport
+        mock_paramiko.SSHClient.return_value = fake_client
+
+        test_ssh = ssh.SSH("admin", "example.net", pkey="key")
+        result = test_ssh.interactive_terminal_open()
+        self.assertEqual(fake_session, result)
+
+    @mock.patch("yardstick.ssh.paramiko")
+    def test_interactive_terminal_exec_command(self, mock_paramiko):
+        fake_client = mock.Mock()
+        fake_session = mock.Mock()
+        fake_session.recv.return_value = "stdout fake data"
+        fake_transport = mock.Mock()
+        fake_transport.open_session.return_value = fake_session
+        fake_client.get_transport.return_value = fake_transport
+        mock_paramiko.SSHClient.return_value = fake_client
+
+        test_ssh = ssh.SSH("admin", "example.net", pkey="key")
+        with mock.patch.object(fake_session, "sendall") \
+                as mock_paramiko_send_command:
+            result = test_ssh.interactive_terminal_exec_command(fake_session,
+                                                                'cmd', "vat# ")
+        self.assertEqual("stdout fake data", result)
+        mock_paramiko_send_command.assert_called_once_with('cmd\n')
+
+    @mock.patch("yardstick.ssh.paramiko")
+    def test_interactive_terminal_close(self, _):
+        fake_session = mock.Mock()
+        paramiko_sshclient = self.test_client._get_client()
+        paramiko_sshclient.get_transport.open_session.return_value = fake_session
+        with mock.patch.object(fake_session, "close") \
+                as mock_paramiko_terminal_close:
+            self.test_client.interactive_terminal_close(fake_session)
+        mock_paramiko_terminal_close.assert_called_once_with()
+
 
 class SSHRunTestCase(unittest.TestCase):
     """Test SSH.run method in different aspects.