Adding new SRIOV Standalone Context 55/29555/12
authorNeha Vadnere <neha.r.vadnere@intel.com>
Mon, 24 Apr 2017 18:47:44 +0000 (00:17 +0530)
committerBindya N <bindya.narayan@intel.com>
Mon, 24 Jul 2017 11:50:03 +0000 (17:20 +0530)
This patch adds new SRIOV context to run VNFs with
 - random uuid generation,
 - mac address generation,
 - getting dpdk_nic_bind path,
 - ssh key based authentication,
 - printing log messages,
 - added apache2 licence

JIRA: YARDSTICK-480

Change-Id: Ic8317eb9e7e4ecf270091c18be4782d1299ff087
Signed-off-by: Neha Vadnere <neha.r.vadnere@intel.com>
Signed-off-by: Bindya N <bindya.narayan@intel.com>
tests/unit/benchmark/contexts/nodes_duplicate_sample_new.yaml [new file with mode: 0644]
tests/unit/benchmark/contexts/nodes_sample_new.yaml [new file with mode: 0644]
tests/unit/benchmark/contexts/sriov_sample_password.yaml [new file with mode: 0644]
tests/unit/benchmark/contexts/sriov_sample_ssh_key.yaml [new file with mode: 0644]
tests/unit/benchmark/contexts/sriov_sample_write_to_file.txt [new file with mode: 0644]
tests/unit/benchmark/contexts/test_sriov.py [new file with mode: 0644]
tests/unit/benchmark/contexts/test_standalone.py
yardstick/benchmark/contexts/sriov.py [new file with mode: 0644]
yardstick/benchmark/contexts/standalone.py

diff --git a/tests/unit/benchmark/contexts/nodes_duplicate_sample_new.yaml b/tests/unit/benchmark/contexts/nodes_duplicate_sample_new.yaml
new file mode 100644 (file)
index 0000000..48f4065
--- /dev/null
@@ -0,0 +1,112 @@
+# Copyright (c) 2016-2017 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.
+
+nodes:
+-
+    name: trafficgen_1
+    role: TrafficGen
+    ip: 10.123.123.123
+    user: root
+    auth_type: password
+    password: password
+    interfaces:
+        xe0:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.0"
+            driver:    ixgbe
+            dpdk_port_num: 0
+            local_ip: "152.16.100.20"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+        xe1:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.1"
+            driver:    ixgbe
+            dpdk_port_num: 1
+            local_ip: "152.16.100.21"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+-
+    name: sriov
+    role: Sriov
+    ip: 10.123.123.122
+    user: root
+    auth_type: password
+    password: password
+    vf_macs:
+     - "00:00:00:00:00:00"
+     - "00:00:00:00:00:00"
+    phy_ports: # Physical ports to configure sriov
+     - "0000:06:00.0"
+     - "0000:06:00.1"
+    phy_driver:    i40e # kernel driver
+    images: "/var/lib/libvirt/images/ubuntu1.img"
+
+-
+    name: sriov
+    role: Sriov
+    ip: 10.123.123.111
+    user: root
+    auth_type: password
+    password: password
+    vf_macs:
+     - "00:00:00:00:00:00"
+     - "00:00:00:00:00:00"
+    phy_ports: # Physical ports to configure sriov
+     - "0000:06:00.0"
+     - "0000:06:00.1"
+    phy_driver:    i40e # kernel driver
+    images: "/var/lib/libvirt/images/ubuntu1.img"
+
+-
+    name: vnf
+    role: vnf
+    ip: 10.123.123.121
+    user: root
+    auth_type: password
+    password: password
+    host: 10.123.123.121 #BM host == ip, SRIOV & ovs-dpdk host == compute node.
+    interfaces:
+        xe0:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:06:00.0"
+            driver:    i40e
+            dpdk_port_num: 0
+            local_ip: "152.16.100.19"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+
+        xe1:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:06:00.1"
+            driver:    i40e
+            dpdk_port_num: 1
+            local_ip: "152.16.40.19"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+    routing_table:
+    - network: "152.16.100.20"
+      netmask: "255.255.255.0"
+      gateway: "152.16.100.20"
+      if: "xe0"
+    - network: "152.16.40.20"
+      netmask: "255.255.255.0"
+      gateway: "152.16.40.20"
+      if: "xe1"
+    nd_route_tbl:
+    - network: "0064:ff9b:0:0:0:0:9810:6414"
+      netmask: "112"
+      gateway: "0064:ff9b:0:0:0:0:9810:6414"
+      if: "xe0"
+    - network: "0064:ff9b:0:0:0:0:9810:2814"
+      netmask: "112"
+      gateway: "0064:ff9b:0:0:0:0:9810:2814"
+      if: "xe1"
+                                      
diff --git a/tests/unit/benchmark/contexts/nodes_sample_new.yaml b/tests/unit/benchmark/contexts/nodes_sample_new.yaml
new file mode 100644 (file)
index 0000000..a400bec
--- /dev/null
@@ -0,0 +1,96 @@
+# Copyright (c) 2016-2017 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.
+
+nodes:
+-
+    name: trafficgen_1
+    role: TrafficGen
+    ip: 10.123.123.123
+    user: root
+    auth_type: password
+    password: password
+    interfaces:
+        xe0:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.0"
+            driver:    ixgbe
+            dpdk_port_num: 0
+            local_ip: "152.16.100.20"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+        xe1:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.1"
+            driver:    ixgbe
+            dpdk_port_num: 1
+            local_ip: "152.16.100.21"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+-
+    name: sriov
+    role: Sriov
+    ip: 10.123.123.122
+    user: root
+    auth_type: password
+    password: password
+    vf_macs:
+     - "00:00:00:00:00:00"
+     - "00:00:00:00:00:00"
+    phy_ports: # Physical ports to configure sriov
+     - "0000:06:00.0"
+     - "0000:06:00.1"
+    phy_driver:    i40e # kernel driver
+    images: "/var/lib/libvirt/images/ubuntu1.img"
+
+-
+    name: vnf
+    role: vnf
+    ip: 10.123.123.121
+    user: root
+    auth_type: password
+    password: password
+    host: 10.123.123.121 #BM host == ip, SRIOV & ovs-dpdk host == compute node.
+    interfaces:
+        xe0:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:06:00.0"
+            driver:    i40e
+            dpdk_port_num: 0
+            local_ip: "152.16.100.19"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+
+        xe1:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:06:00.1"
+            driver:    i40e
+            dpdk_port_num: 1
+            local_ip: "152.16.40.19"
+            netmask:   "255.255.255.0"
+            local_mac:   "00:00:00:00:00:00"
+    routing_table:
+    - network: "152.16.100.20"
+      netmask: "255.255.255.0"
+      gateway: "152.16.100.20"
+      if: "xe0"
+    - network: "152.16.40.20"
+      netmask: "255.255.255.0"
+      gateway: "152.16.40.20"
+      if: "xe1"
+    nd_route_tbl:
+    - network: "0064:ff9b:0:0:0:0:9810:6414"
+      netmask: "112"
+      gateway: "0064:ff9b:0:0:0:0:9810:6414"
+      if: "xe0"
+    - network: "0064:ff9b:0:0:0:0:9810:2814"
+      netmask: "112"
+      gateway: "0064:ff9b:0:0:0:0:9810:2814"
+      if: "xe1"
+                                      
diff --git a/tests/unit/benchmark/contexts/sriov_sample_password.yaml b/tests/unit/benchmark/contexts/sriov_sample_password.yaml
new file mode 100644 (file)
index 0000000..4f60e46
--- /dev/null
@@ -0,0 +1,52 @@
+# Copyright (c) 2016-2017 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.
+
+nodes:
+-
+    name: trafficgen_1
+    role: TrafficGen
+    ip: 10.10.10.10
+    auth_type: password
+    user: root
+    password: password
+    interfaces:
+        xe0:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.0"
+            driver:    ixgbe
+            dpdk_port_num: 0
+            local_ip: "152.16.100.20"
+            netmask:   "255.255.255.0"
+            local_mac:   "90:e2:ba:77:ce:68"
+        xe1:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.1"
+            driver:    ixgbe
+            dpdk_port_num: 1
+            local_ip: "152.16.100.21"
+            netmask:   "255.255.255.0"
+            local_mac:   "90:e2:ba:77:ce:69"
+-
+    name: sriov
+    role: Sriov
+    ip: 10.10.10.11
+    auth_type: password
+    user: root
+    password: password
+    vf_macs:
+     - "00:00:00:71:7d:25"
+     - "00:00:00:71:7d:26"
+    phy_ports: # Physical ports to configure sriov
+     - "0000:06:00.0"
+     - "0000:06:00.1"
+    phy_driver:    i40e # kernel driver
+    images: "/var/lib/libvirt/images/ubuntu1.img"
diff --git a/tests/unit/benchmark/contexts/sriov_sample_ssh_key.yaml b/tests/unit/benchmark/contexts/sriov_sample_ssh_key.yaml
new file mode 100644 (file)
index 0000000..faa4967
--- /dev/null
@@ -0,0 +1,54 @@
+# Copyright (c) 2016-2017 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.
+
+nodes:
+-
+    name: trafficgen_1
+    role: TrafficGen
+    ip: 10.10.10.10
+    auth_type: ssh_key
+    user: root
+    ssh_port: 22
+    key_filename: /root/.ssh/id_rsa
+    interfaces:
+        xe0:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.0"
+            driver:    ixgbe
+            dpdk_port_num: 0
+            local_ip: "152.16.100.20"
+            netmask:   "255.255.255.0"
+            local_mac:   "90:e2:ba:77:ce:68"
+        xe1:  # logical name from topology.yaml and vnfd.yaml
+            vpci:      "0000:03:00.1"
+            driver:    ixgbe
+            dpdk_port_num: 1
+            local_ip: "152.16.100.21"
+            netmask:   "255.255.255.0"
+            local_mac:   "90:e2:ba:77:ce:69"
+-
+    name: sriov
+    role: Sriov
+    ip: 10.10.10.11
+    auth_type: ssh_key
+    user: root
+    ssh_port: 22
+    key_filename: /root/.ssh/id_rsa
+    vf_macs:
+     - "00:00:00:71:7d:25"
+     - "00:00:00:71:7d:26"
+    phy_ports: # Physical ports to configure sriov
+     - "0000:06:00.0"
+     - "0000:06:00.1"
+    phy_driver:    i40e # kernel driver
+    images: "/var/lib/libvirt/images/ubuntu1.img"
diff --git a/tests/unit/benchmark/contexts/sriov_sample_write_to_file.txt b/tests/unit/benchmark/contexts/sriov_sample_write_to_file.txt
new file mode 100644 (file)
index 0000000..f0eec86
--- /dev/null
@@ -0,0 +1 @@
+some content
\ No newline at end of file
diff --git a/tests/unit/benchmark/contexts/test_sriov.py b/tests/unit/benchmark/contexts/test_sriov.py
new file mode 100644 (file)
index 0000000..e4d8f5e
--- /dev/null
@@ -0,0 +1,423 @@
+# Copyright (c) 2016-2017 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.
+
+from __future__ import absolute_import
+import os
+import mock
+import unittest
+
+from yardstick.benchmark.contexts import sriov
+
+NIC_INPUT = {
+    'interface': {},
+    'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+    'pci': ['0000:06:00.0', '0000:06:00.1'],
+    'phy_driver': 'i40e'}
+DRIVER = "i40e"
+NIC_DETAILS = {
+    'interface': {0: 'enp6s0f0', 1: 'enp6s0f1'},
+    'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+    'pci': ['0000:06:00.0', '0000:06:00.1'],
+    'phy_driver': 'i40e'}
+
+CORRECT_FILE_PATH = "/etc/yardstick/nodes/pod_sriov.yaml"
+WRONG_FILE_PATH = "/etc/yardstick/wrong.yaml"
+SAMPLE_FILE = "sriov_sample_write_to_file.txt"
+
+SRIOV = [{
+    'auth_type': 'ssh_key',
+    'name': 'sriov',
+    'ssh_port': 22,
+    'ip': '10.10.10.11',
+    'key_filename': '/root/.ssh/id_rsa',
+    'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+    'role': 'Sriov',
+    'user': 'root',
+    'images': '/var/lib/libvirt/images/ubuntu1.img',
+    'phy_driver': 'i40e',
+    'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
+
+SRIOV_PASSWORD = [{
+    'auth_type': 'password',
+    'name': 'sriov',
+    'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+    'ip': '10.10.10.11',
+    'role': 'Sriov',
+    'user': 'root',
+    'images': '/var/lib/libvirt/images/ubuntu1.img',
+    'phy_driver': 'i40e',
+    'password': 'password',
+    'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
+
+vfnic = "i40evf"
+PCIS = ['0000:06:00.0', '0000:06:00.1']
+
+
+class SriovTestCase(unittest.TestCase):
+
+    NODES_SAMPLE_SSH = "sriov_sample_ssh_key.yaml"
+    NODES_SAMPLE_PASSWORD = "sriov_sample_password.yaml"
+
+    def setUp(self):
+        self.test_context = sriov.Sriov()
+
+    def test_construct(self):
+        self.assertIsNone(self.test_context.name)
+        self.assertIsNone(self.test_context.file_path)
+        self.assertEqual(self.test_context.nodes, [])
+        self.assertEqual(self.test_context.sriov, [])
+        self.assertFalse(self.test_context.vm_deploy)
+        self.assertTrue(self.test_context.first_run)
+        self.assertEqual(self.test_context.user, "")
+        self.assertEqual(self.test_context.ssh_ip, "")
+        self.assertEqual(self.test_context.passwd, "")
+        self.assertEqual(self.test_context.ssh_port, "")
+        self.assertEqual(self.test_context.auth_type, "")
+
+    def test_init(self):
+        self.test_context.parse_pod_and_get_data = mock.Mock()
+        self.test_context.file_path = CORRECT_FILE_PATH
+        self.test_context.init()
+        self.assertIsNone(self.test_context.init())
+
+    def test_successful_init_with_ssh(self):
+        CORRECT_FILE_PATH = self._get_file_abspath(self.NODES_SAMPLE_SSH)
+        self.test_context.parse_pod_and_get_data(CORRECT_FILE_PATH)
+
+    def test_successful_init_with_password(self):
+        CORRECT_FILE_PATH = self._get_file_abspath(self.NODES_SAMPLE_PASSWORD)
+        self.test_context.parse_pod_and_get_data(CORRECT_FILE_PATH)
+
+    def test_unsuccessful_init(self):
+        self.assertRaises(
+            IOError,
+            lambda: self.test_context.parse_pod_and_get_data(WRONG_FILE_PATH))
+
+    @mock.patch('yardstick.network_services.utils.provision_tool', return_value="a")
+    def test_ssh_connection(self, mock_prov):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(1, "a", ""))
+            ssh.return_value = ssh_mock
+            mock_prov.provision_tool = mock.Mock()
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            sriov_obj.sriov = SRIOV_PASSWORD
+            self.assertIsNone(sriov_obj.ssh_remote_machine())
+
+    @mock.patch('yardstick.network_services.utils.provision_tool', return_value="a")
+    def test_ssh_connection_ssh_key(self, mock_prov):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(1, "a", ""))
+            ssh.return_value = ssh_mock
+            mock_prov.provision_tool = mock.Mock()
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            sriov_obj.sriov = SRIOV
+            sriov_obj.key_filename = '/root/.ssh/id_rsa'
+            self.assertIsNone(sriov_obj.ssh_remote_machine())
+
+    def test_get_nic_details(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, "eth0 eth1", ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.sriov = SRIOV
+            sriov_obj.connection = ssh_mock
+            self.assertIsNotNone(sriov_obj.get_nic_details())
+
+    def test_install_req_libs(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.first_run = True
+            sriov_obj.connection = ssh_mock
+            self.assertIsNone(sriov_obj.install_req_libs())
+
+    def test_configure_nics_for_sriov(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            nic_details = {
+                'interface': {0: 'enp6s0f0', 1: 'enp6s0f1'},
+                'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+                'pci': ['0000:06:00.0', '0000:06:00.1'],
+                'phy_driver': 'i40e',
+                'vf_pci': [{}, {}]}
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock((DRIVER), return_value=(0, "0 driver", ""))
+            ssh.return_value = ssh_mock
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            for i in range(len(NIC_DETAILS['pci'])):
+                ssh_mock.execute = \
+                    mock.Mock(return_value=(0, {}, ""))
+                ssh_mock.execute = \
+                    mock.Mock(return_value=(0, {}, ""))
+                sriov_obj = sriov.Sriov()
+                sriov_obj.connection = ssh_mock
+                ssh_mock.execute = \
+                    mock.Mock(return_value=(
+                        0,
+                        "{'0':'06:02:00','1':'06:06:00'}",
+                        ""))
+                sriov_obj.get_vf_datas = mock.Mock(return_value={
+                    '0000:06:00.0': '0000:06:02.0'})
+                nic_details['vf_pci'][i] = sriov_obj.get_vf_datas.return_value
+                vf_pci = [[], []]
+                vf_pci[i] = sriov_obj.get_vf_datas.return_value
+            self.assertIsNotNone(
+                sriov_obj.configure_nics_for_sriov(DRIVER, NIC_DETAILS))
+
+    def test_setup_sriov_context(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            nic_details = {
+                'interface': {0: 'enp6s0f0', 1: 'enp6s0f1'},
+                'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+                'pci': ['0000:06:00.0', '0000:06:00.1'],
+                'phy_driver': 'i40e',
+                'vf_pci': [{'vf_pci': '06:02.00'}, {'vf_pci': '06:06.00'}]}
+            vf = [{'vf_pci': '06:02.00'}, {'vf_pci': '06:06.00'}]
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            sriov_obj.sriov = SRIOV
+            blacklist = "/etc/modprobe.d/blacklist.conf"
+            self.assertEqual(vfnic, "i40evf")
+            mock_sriov = mock.Mock()
+            mock_sriov.sriov_obj.read_from_file(blacklist)
+            sriov_obj.read_from_file = mock.Mock(
+                return_value="some random text")
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            sriov_obj.configure_nics_for_sriov = mock.Mock(
+                return_value=nic_details)
+            nic_details = sriov_obj.configure_nics_for_sriov.return_value
+            self.assertEqual(vf, nic_details['vf_pci'])
+            vf = [
+                {'vf_pci': '06:02.00', 'mac': '00:00:00:00:00:0a'},
+                {'vf_pci': '06:06.00', 'mac': '00:00:00:00:00:0b'}]
+            sriov_obj.add_sriov_interface = mock.Mock()
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh_mock.put = mock.Mock()
+            sriov_obj.check_output = mock.Mock(return_value=(1, {}))
+            self.assertIsNone(
+                sriov_obj.setup_sriov_context(PCIS, nic_details, DRIVER))
+
+    def test_setup_sriov_context_vm_already_present(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            nic_details = {
+                'interface': {0: 'enp6s0f0', 1: 'enp6s0f1'},
+                'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+                'pci': ['0000:06:00.0', '0000:06:00.1'],
+                'phy_driver': 'i40e',
+                'vf_pci': [{'vf_pci': '06:02.00'}, {'vf_pci': '06:06.00'}]}
+            vf = [{'vf_pci': '06:02.00'}, {'vf_pci': '06:06.00'}]
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            sriov_obj.sriov = SRIOV
+            blacklist = "/etc/modprobe.d/blacklist.conf"
+            self.assertEqual(vfnic, "i40evf")
+            mock_sriov = mock.Mock()
+            mock_sriov.sriov_obj.read_from_file(blacklist)
+            sriov_obj.read_from_file = mock.Mock(
+                return_value="some random text")
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            sriov_obj.configure_nics_for_sriov = mock.Mock(
+                return_value=nic_details)
+            nic_details = sriov_obj.configure_nics_for_sriov.return_value
+            self.assertEqual(vf, nic_details['vf_pci'])
+            vf = [
+                {'vf_pci': '06:02.00', 'mac': '00:00:00:00:00:0a'},
+                {'vf_pci': '06:06.00', 'mac': '00:00:00:00:00:0b'}]
+            sriov_obj.add_sriov_interface = mock.Mock()
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh_mock.put = mock.Mock()
+            sriov_obj.check_output = mock.Mock(return_value=(0, "vm1"))
+            self.assertIsNone(sriov_obj.setup_sriov_context(
+                PCIS,
+                nic_details,
+                DRIVER))
+
+    @mock.patch(
+        'yardstick.benchmark.contexts.sriov',
+        return_value="Domain vm1 created from /tmp/vm_sriov.xml")
+    def test_is_vm_created(self, NIC_INPUT):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            mock_sriov = mock.Mock()
+            pcis = NIC_DETAILS['pci']
+            driver = NIC_DETAILS['phy_driver']
+            self.assertIsNotNone(
+                mock_sriov.sriov_obj.setup_sriov_context(
+                    pcis,
+                    NIC_DETAILS,
+                    driver))
+
+    def test_add_sriov_interface(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            with mock.patch("xml.etree.ElementTree.parse") as parse:
+                with mock.patch("re.search") as re:
+                    with mock.patch("xml.etree.ElementTree.SubElement") \
+                        as elem:
+                            parse = mock.Mock(return_value="root")
+                            re = mock.Mock()
+                            elem = mock.Mock()
+                            print("{0} {1} {2}".format(parse, re, elem))
+                            self.assertIsNone(sriov_obj.add_sriov_interface(
+                                0,
+                                "0000:06:02.0",
+                                "00:00:00:00:00:0a",
+                                "/tmp/vm_sriov.xml"))
+
+    def test_get_virtual_devices(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            pci_out = " \
+            PCI_CLASS=20000 \
+            PCI_ID=8086:154C \
+            PCI_SUBSYS_ID=8086:0000 \
+            PCI_SLOT_NAME=0000:06:02.0 \
+            MODALIAS= \
+            pci:v00008086d0000154Csv00008086sd00000000bc02sc00i00"
+            pci = "0000:06:00.0"
+            sriov_obj.check_output = mock.Mock(return_value=(0, pci_out))
+            with mock.patch("re.search") as re:
+                re = mock.Mock(return_value="a")
+                print("{0}".format(re))
+                self.assertIsNotNone(sriov_obj.get_virtual_devices(pci))
+
+    def test_get_vf_datas(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            sriov_obj.get_virtual_devices = mock.Mock(
+                return_value={'0000:06:00.0': '0000:06:02.0'})
+            with mock.patch("re.search") as re:
+                re = mock.Mock()
+                print("{0}".format(re))
+                self.assertIsNotNone(sriov_obj.get_vf_datas(
+                    'vf_pci',
+                    {'0000:06:00.0': '0000:06:02.0'},
+                    "00:00:00:00:00:0a"))
+
+    def test_check_output(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            cmd = "command"
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            self.assertIsNotNone(sriov_obj.check_output(cmd, None))
+
+    def test_split_cpu_list_available(self):
+        with mock.patch("itertools.chain") as iter1:
+            iter1 = mock.Mock()
+            print("{0}".format(iter1))
+            sriov_obj = sriov.Sriov()
+            self.assertIsNotNone(sriov_obj.split_cpu_list('0,5'))
+
+    def test_split_cpu_list_null(self):
+        with mock.patch("itertools.chain") as iter1:
+            iter1 = mock.Mock()
+            print("{0}".format(iter1))
+            sriov_obj = sriov.Sriov()
+            self.assertEqual(sriov_obj.split_cpu_list([]), [])
+
+    def test_destroy_vm_successful(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            sriov_obj.sriov = SRIOV
+            sriov_obj.check_output = mock.Mock(return_value=(0, "vm1"))
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, "0 i40e"))
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, "0 i40e"))
+            self.assertIsNone(sriov_obj.destroy_vm())
+
+    def test_destroy_vm_unsuccessful(self):
+        with mock.patch("yardstick.ssh.SSH") as ssh:
+            ssh_mock = mock.Mock(autospec=ssh.SSH)
+            ssh_mock.execute = \
+                mock.Mock(return_value=(0, {}, ""))
+            ssh.return_value = ssh_mock
+            sriov_obj = sriov.Sriov()
+            sriov_obj.connection = ssh_mock
+            sriov_obj.sriov = SRIOV
+            sriov_obj.check_output = mock.Mock(return_value=(1, {}))
+            self.assertIsNone(sriov_obj.destroy_vm())
+
+    def test_read_from_file(self):
+        CORRECT_FILE_PATH = self._get_file_abspath(self.NODES_SAMPLE_PASSWORD)
+        sriov_obj = sriov.Sriov()
+        self.assertIsNotNone(sriov_obj.read_from_file(CORRECT_FILE_PATH))
+
+    def test_write_to_file(self):
+        sriov_obj = sriov.Sriov()
+        self.assertIsNone(sriov_obj.write_to_file(SAMPLE_FILE, "some content"))
+
+    def _get_file_abspath(self, filename):
+        curr_path = os.path.dirname(os.path.abspath(__file__))
+        file_path = os.path.join(curr_path, filename)
+        return file_path
+
+if __name__ == '__main__':
+    unittest.main()
index a6fd776..ee25bb3 100644 (file)
 from __future__ import absolute_import
 import os
 import unittest
-
+import mock
 from yardstick.benchmark.contexts import standalone
+from yardstick.benchmark.contexts import sriov
+
+MOCKS = {
+    'yardstick.benchmark.contexts': mock.MagicMock(),
+    'yardstick.benchmark.contexts.sriov': mock.MagicMock(),
+    'yardstick.benchmark.contexts.standalone': mock.MagicMock(),
+}
 
 
 class StandaloneContextTestCase(unittest.TestCase):
 
-    NODES_SAMPLE = "standalone_sample.yaml"
-    NODES_DUPLICATE_SAMPLE = "standalone_duplicate_sample.yaml"
+    NODES_SAMPLE = "nodes_sample_new.yaml"
+    NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample_new.yaml"
 
     def setUp(self):
         self.test_context = standalone.StandaloneContext()
 
     def test_construct(self):
-
         self.assertIsNone(self.test_context.name)
         self.assertIsNone(self.test_context.file_path)
         self.assertEqual(self.test_context.nodes, [])
         self.assertEqual(self.test_context.nfvi_node, [])
 
     def test_unsuccessful_init(self):
-
         attrs = {
             'name': 'foo',
             'file': self._get_file_abspath("error_file")
         }
-
         self.assertRaises(IOError, self.test_context.init, attrs)
 
     def test_successful_init(self):
-
         attrs = {
-            'name': 'foo',
+            'name': 'sriov',
             'file': self._get_file_abspath(self.NODES_SAMPLE)
         }
 
+        self.test_context.nfvi_node = [{
+            'name': 'sriov',
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'ip': '10.123.123.122',
+            'role': 'Sriov',
+            'user': 'root',
+            'images': '/var/lib/libvirt/images/ubuntu1.img',
+            'phy_driver': 'i40e',
+            'password': 'password',
+            'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
+        self.test_context.get_nfvi_obj = mock.Mock()
         self.test_context.init(attrs)
-
-        self.assertEqual(self.test_context.name, "foo")
+        self.assertEqual(self.test_context.name, "sriov")
         self.assertEqual(len(self.test_context.nodes), 3)
-        self.assertEqual(len(self.test_context.nfvi_node), 1)
-        self.assertEqual(self.test_context.nfvi_node[0]["name"], "node2")
+        self.assertEqual(len(self.test_context.nfvi_node), 2)
+        self.assertEqual(self.test_context.nfvi_node[0]["name"], "sriov")
 
     def test__get_server_with_dic_attr_name(self):
-
         attrs = {
             'name': 'foo',
             'file': self._get_file_abspath(self.NODES_SAMPLE)
         }
-
+        self.test_context.nfvi_node = [{
+            'name': 'sriov',
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'ip': '10.123.123.122',
+            'role': 'Sriov',
+            'user': 'root',
+            'images': '/var/lib/libvirt/images/ubuntu1.img',
+            'phy_driver': 'i40e',
+            'password': 'password',
+            'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
         self.test_context.init(attrs)
-
         attr_name = {'name': 'foo.bar'}
         result = self.test_context._get_server(attr_name)
-
         self.assertEqual(result, None)
 
     def test__get_server_not_found(self):
-
         attrs = {
             'name': 'foo',
             'file': self._get_file_abspath(self.NODES_SAMPLE)
         }
-
+        self.test_context.nfvi_node = [{
+            'name': 'sriov',
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'ip': '10.123.123.122',
+            'role': 'Sriov',
+            'user': 'root',
+            'images': '/var/lib/libvirt/images/ubuntu1.img',
+            'phy_driver': 'i40e',
+            'password': 'password',
+            'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
         self.test_context.init(attrs)
-
         attr_name = 'bar.foo'
         result = self.test_context._get_server(attr_name)
-
         self.assertEqual(result, None)
 
     def test__get_server_duplicate(self):
-
         attrs = {
             'name': 'foo',
             'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
         }
-
+        self.test_context.nfvi_node = [{
+            'name': 'sriov',
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'ip': '10.123.123.122',
+            'role': 'Sriov',
+            'user': 'root',
+            'images': '/var/lib/libvirt/images/ubuntu1.img',
+            'phy_driver': 'i40e',
+            'password': 'password',
+            'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
         self.test_context.init(attrs)
-
-        attr_name = 'node2.foo'
-
-        self.assertRaises(ValueError, self.test_context._get_server, attr_name)
+        attr_name = 'sriov.foo'
+        self.assertRaises(
+            ValueError,
+            self.test_context._get_server,
+            attr_name)
 
     def test__get_server_found(self):
-
         attrs = {
-            'name': 'foo',
+            'name': 'sriov',
             'file': self._get_file_abspath(self.NODES_SAMPLE)
         }
-
+        self.test_context.nfvi_node = [{
+            'name': 'sriov',
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'ip': '10.123.123.122',
+            'role': 'Sriov',
+            'user': 'root',
+            'images': '/var/lib/libvirt/images/ubuntu1.img',
+            'phy_driver': 'i40e',
+            'password': 'password',
+            'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
         self.test_context.init(attrs)
-
-        attr_name = 'node1.foo'
+        attr_name = 'sriov.sriov'
         result = self.test_context._get_server(attr_name)
-
-        self.assertEqual(result['ip'], '1.1.1.1')
-        self.assertEqual(result['name'], 'node1.foo')
+        self.assertEqual(result['ip'], '10.123.123.122')
+        self.assertEqual(result['name'], 'sriov.sriov')
         self.assertEqual(result['user'], 'root')
 
     def test_deploy(self):
+        attrs = {
+            'name': 'foo',
+            'file': self._get_file_abspath(self.NODES_SAMPLE)
+        }
+
+        self.test_context.nfvi_node = [{
+            'name': 'sriov',
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'ip': '10.123.123.122',
+            'role': 'Sriov',
+            'user': 'root',
+            'images': '/var/lib/libvirt/images/ubuntu1.img',
+            'phy_driver': 'i40e',
+            'password': 'password',
+            'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
+        self.test_context.get_nfvi_obj = mock.MagicMock()
+        self.test_context.init(attrs)
+        self.test_context.nfvi_obj.ssh_remote_machine = mock.Mock()
+        self.test_context.nfvi_obj.first_run = True
+        self.test_context.nfvi_obj.get_nic_details = mock.Mock()
+        PORTS = ['0000:06:00.0', '0000:06:00.1']
+        NIC_DETAILS = {
+            'interface': {0: 'enp6s0f0', 1: 'enp6s0f1'},
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'pci': ['0000:06:00.0', '0000:06:00.1'],
+            'phy_driver': 'i40e'}
+        DRIVER = 'i40e'
+        result = self.test_context.nfvi_obj.setup_sriov_context(
+            PORTS,
+            NIC_DETAILS,
+            DRIVER)
+        print("{0}".format(result))
         self.assertIsNone(self.test_context.deploy())
 
     def test_undeploy(self):
+        attrs = {
+            'name': 'foo',
+            'file': self._get_file_abspath(self.NODES_SAMPLE)
+        }
+        self.test_context.nfvi_node = [{
+            'name': 'sriov',
+            'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+            'ip': '10.123.123.122',
+            'role': 'Sriov',
+            'user': 'root',
+            'images': '/var/lib/libvirt/images/ubuntu1.img',
+            'phy_driver': 'i40e',
+            'password': 'password',
+            'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
+        self.test_context.get_nfvi_obj = mock.MagicMock()
+        self.test_context.init(attrs)
+        self.test_context.nfvi_obj.destroy_vm = mock.Mock()
         self.assertIsNone(self.test_context.undeploy())
 
+    def test_get_nfvi_obj(self):
+        with mock.patch('yardstick.benchmark.contexts.sriov'):
+            attrs = {
+                'name': 'sriov',
+                'file': self._get_file_abspath(self.NODES_SAMPLE)
+            }
+            self.test_context.init(attrs)
+            self.test_context.nfvi_obj.file_path = self._get_file_abspath(
+                self.NODES_SAMPLE)
+            self.test_context.nfvi_node = [{
+                'name': 'sriov',
+                'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'],
+                'ip': '10.123.123.122',
+                'role': 'Sriov',
+                'user': 'root',
+                'images': '/var/lib/libvirt/images/ubuntu1.img',
+                'phy_driver': 'i40e',
+                'password': 'password',
+                'phy_ports': ['0000:06:00.0', '0000:06:00.1']}]
+            self.test_context.get_nfvi_obj = mock.MagicMock()
+            self.test_context.init(attrs)
+            self.test_context.get_context_impl = mock.Mock(
+                return_value=sriov.Sriov)
+            self.assertIsNotNone(self.test_context.get_nfvi_obj())
+
+    def test_get_context_impl_correct_obj(self):
+        with mock.patch.dict("sys.modules", MOCKS):
+            self.assertIsNotNone(self.test_context.get_context_impl('Sriov'))
+
+    def test_get_context_impl_wrong_obj(self):
+        with mock.patch.dict("sys.modules", MOCKS):
+            self.assertRaises(
+                ValueError,
+                lambda: self.test_context.get_context_impl('wrong_object'))
+
     def _get_file_abspath(self, filename):
         curr_path = os.path.dirname(os.path.abspath(__file__))
         file_path = os.path.join(curr_path, filename)
@@ -174,3 +298,5 @@ class StandaloneContextTestCase(unittest.TestCase):
         expected = network1
         result = self.test_context._get_network(attr_name)
         self.assertDictEqual(result, expected)
+if __name__ == '__main__':
+    unittest.main()
diff --git a/yardstick/benchmark/contexts/sriov.py b/yardstick/benchmark/contexts/sriov.py
new file mode 100644 (file)
index 0000000..5dc27bf
--- /dev/null
@@ -0,0 +1,432 @@
+# Copyright (c) 2016-2017 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.
+
+from __future__ import absolute_import
+import os
+import yaml
+import re
+import time
+import glob
+import uuid
+import random
+import logging
+import itertools
+import xml.etree.ElementTree as ET
+from yardstick import ssh
+from yardstick.network_services.utils import get_nsb_option
+from yardstick.network_services.utils import provision_tool
+from yardstick.benchmark.contexts.standalone import StandaloneContext
+
+log = logging.getLogger(__name__)
+
+VM_TEMPLATE = """
+<domain type="kvm">
+ <name>vm1</name>
+  <uuid>{random_uuid}</uuid>
+  <memory unit="KiB">102400</memory>
+  <currentMemory unit="KiB">102400</currentMemory>
+  <memoryBacking>
+    <hugepages />
+  </memoryBacking>
+  <vcpu placement="static">20</vcpu>
+  <os>
+    <type arch="x86_64" machine="pc-i440fx-utopic">hvm</type>
+    <boot dev="hd" />
+  </os>
+  <features>
+    <acpi />
+    <apic />
+    <pae />
+  </features>
+  <cpu match="exact" mode="custom">
+    <model fallback="allow">SandyBridge</model>
+    <topology cores="10" sockets="1" threads="2" />
+  </cpu>
+  <clock offset="utc">
+    <timer name="rtc" tickpolicy="catchup" />
+    <timer name="pit" tickpolicy="delay" />
+    <timer name="hpet" present="no" />
+  </clock>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/bin/kvm-spice</emulator>
+    <disk device="disk" type="file">
+      <driver name="qemu" type="qcow2" />
+      <source file="{vm_image}"/>
+      <target bus="virtio" dev="vda" />
+      <address bus="0x00" domain="0x0000"
+function="0x0" slot="0x04" type="pci" />
+    </disk>
+    <controller index="0" model="ich9-ehci1" type="usb">
+      <address bus="0x00" domain="0x0000"
+function="0x7" slot="0x05" type="pci" />
+    </controller>
+    <controller index="0" model="ich9-uhci1" type="usb">
+      <master startport="0" />
+      <address bus="0x00" domain="0x0000" function="0x0"
+multifunction="on" slot="0x05" type="pci" />
+    </controller>
+    <controller index="0" model="ich9-uhci2" type="usb">
+      <master startport="2" />
+      <address bus="0x00" domain="0x0000"
+function="0x1" slot="0x05" type="pci" />
+    </controller>
+    <controller index="0" model="ich9-uhci3" type="usb">
+      <master startport="4" />
+      <address bus="0x00" domain="0x0000"
+function="0x2" slot="0x05" type="pci" />
+    </controller>
+    <controller index="0" model="pci-root" type="pci" />
+      <serial type="pty">
+      <target port="0" />
+    </serial>
+    <console type="pty">
+      <target port="0" type="serial" />
+    </console>
+    <input bus="usb" type="tablet" />
+    <input bus="ps2" type="mouse" />
+    <input bus="ps2" type="keyboard" />
+    <graphics autoport="yes" listen="0.0.0.0" port="-1" type="vnc" />
+    <video>
+      <model heads="1" type="cirrus" vram="16384" />
+      <address bus="0x00" domain="0x0000"
+function="0x0" slot="0x02" type="pci" />
+    </video>
+    <memballoon model="virtio">
+      <address bus="0x00" domain="0x0000"
+function="0x0" slot="0x06" type="pci" />
+    </memballoon>
+    <interface type="bridge">
+      <mac address="{mac_addr}" />
+      <source bridge="virbr0" />
+    </interface>
+   </devices>
+</domain>
+"""
+
+
+class Sriov(StandaloneContext):
+    def __init__(self):
+        self.name = None
+        self.file_path = None
+        self.nodes = []
+        self.vm_deploy = False
+        self.sriov = []
+        self.first_run = True
+        self.dpdk_nic_bind = ""
+        self.user = ""
+        self.ssh_ip = ""
+        self.passwd = ""
+        self.ssh_port = ""
+        self.auth_type = ""
+
+    def init(self):
+        self.parse_pod_and_get_data(self.file_path)
+
+    def parse_pod_and_get_data(self, file_path):
+        self.file_path = file_path
+        log.debug("parsing pod file: {0}".format(self.file_path))
+        try:
+            with open(self.file_path) as stream:
+                cfg = yaml.load(stream)
+        except IOError:
+            log.error("File {0} does not exist".format(self.file_path))
+            raise
+
+        self.nodes.extend([node for node in cfg["nodes"]
+                           if node["role"] != "Sriov"])
+        self.sriov.extend([node for node in cfg["nodes"]
+                           if node["role"] == "Sriov"])
+        self.user = self.sriov[0]['user']
+        self.ssh_ip = self.sriov[0]['ip']
+        if self.sriov[0]['auth_type'] == "password":
+            self.passwd = self.sriov[0]['password']
+        else:
+            self.ssh_port = self.sriov[0]['ssh_port']
+            self.key_filename = self.sriov[0]['key_filename']
+
+    def ssh_remote_machine(self):
+        if self.sriov[0]['auth_type'] == "password":
+            self.connection = ssh.SSH(
+                self.user,
+                self.ssh_ip,
+                password=self.passwd)
+            self.connection.wait()
+        else:
+            if self.ssh_port is not None:
+                ssh_port = self.ssh_port
+            else:
+                ssh_port = ssh.DEFAULT_PORT
+            self.connection = ssh.SSH(
+                self.user,
+                self.ssh_ip,
+                port=ssh_port,
+                key_filename=self.key_filename)
+            self.connection.wait()
+        self.dpdk_nic_bind = provision_tool(
+            self.connection,
+            os.path.join(get_nsb_option("bin_path"), "dpdk_nic_bind.py"))
+
+    def get_nic_details(self):
+        nic_details = {}
+        nic_details = {
+            'interface': {},
+            'pci': self.sriov[0]['phy_ports'],
+            'phy_driver': self.sriov[0]['phy_driver'],
+            'vf_macs': self.sriov[0]['vf_macs']
+        }
+        #   Make sure that ports are bound to kernel drivers e.g. i40e/ixgbe
+        for i, _ in enumerate(nic_details['pci']):
+            err, out, _ = self.connection.execute(
+                "{dpdk_nic_bind} --force -b {driver} {port}".format(
+                    dpdk_nic_bind=self.dpdk_nic_bind,
+                    driver=self.sriov[0]['phy_driver'],
+                    port=self.sriov[0]['phy_ports'][i]))
+            err, out, _ = self.connection.execute(
+                "lshw -c network -businfo | grep '{port}'".format(
+                    port=self.sriov[0]['phy_ports'][i]))
+            a = out.split()[1]
+            err, out, _ = self.connection.execute(
+                "ip -s link show {interface}".format(
+                    interface=out.split()[1]))
+            nic_details['interface'][i] = str(a)
+        log.info("{0}".format(nic_details))
+        return nic_details
+
+    def install_req_libs(self):
+        if self.first_run:
+            log.info("Installing required libraries...")
+            err, out, _ = self.connection.execute("apt-get update")
+            log.debug("{0}".format(out))
+            err, out, _ = self.connection.execute(
+                "apt-get -y install qemu-kvm libvirt-bin")
+            log.debug("{0}".format(out))
+            err, out, _ = self.connection.execute(
+                "apt-get -y install libvirt-dev  bridge-utils numactl")
+            log.debug("{0}".format(out))
+            self.first_run = False
+
+    def configure_nics_for_sriov(self, host_driver, nic_details):
+        vf_pci = [[], []]
+        self.connection.execute(
+            "rmmod {0}".format(host_driver))[1].splitlines()
+        self.connection.execute(
+            "modprobe {0} num_vfs=1".format(host_driver))[1].splitlines()
+        nic_details['vf_pci'] = {}
+        for i in range(len(nic_details['pci'])):
+            self.connection.execute(
+                "echo 1 > /sys/bus/pci/devices/{0}/sriov_numvfs".format(
+                    nic_details['pci'][i]))
+            err, out, _ = self.connection.execute(
+                "ip link set {interface} vf 0 mac {mac}".format(
+                    interface=nic_details['interface'][i],
+                    mac=nic_details['vf_macs'][i]))
+            time.sleep(3)
+            vf_pci[i] = self.get_vf_datas(
+                'vf_pci',
+                nic_details['pci'][i],
+                nic_details['vf_macs'][i])
+            nic_details['vf_pci'][i] = vf_pci[i]
+        log.debug("NIC DETAILS : {0}".format(nic_details))
+        return nic_details
+
+    def setup_sriov_context(self, pcis, nic_details, host_driver):
+        blacklist = "/etc/modprobe.d/blacklist.conf"
+
+        #   1 : Blacklist the vf driver in /etc/modprobe.d/blacklist.conf
+        vfnic = "{0}vf".format(host_driver)
+        lines = self.read_from_file(blacklist)
+        if vfnic not in lines:
+            vfblacklist = "blacklist {vfnic}".format(vfnic=vfnic)
+            self.connection.execute(
+                "echo {vfblacklist} >> {blacklist}".format(
+                    vfblacklist=vfblacklist,
+                    blacklist=blacklist))
+
+        #   2 : modprobe host_driver with num_vfs
+        nic_details = self.configure_nics_for_sriov(host_driver, nic_details)
+
+        #   3: Setup vm_sriov.xml to launch VM
+        cfg_sriov = '/tmp/vm_sriov.xml'
+        mac = [0x00, 0x24, 0x81,
+               random.randint(0x00, 0x7f),
+               random.randint(0x00, 0xff),
+               random.randint(0x00, 0xff)]
+        mac_address = ':'.join(map(lambda x: "%02x" % x, mac))
+        vm_sriov_xml = VM_TEMPLATE.format(
+            random_uuid=uuid.uuid4(),
+            mac_addr=mac_address,
+            vm_image=self.sriov[0]["images"])
+        with open(cfg_sriov, 'w') as f:
+            f.write(vm_sriov_xml)
+
+        vf = nic_details['vf_pci']
+        for index in range(len(nic_details['vf_pci'])):
+            self.add_sriov_interface(
+                index,
+                vf[index]['vf_pci'],
+                mac_address,
+                "/tmp/vm_sriov.xml")
+            self.connection.execute(
+                "ifconfig {interface} up".format(
+                    interface=nic_details['interface'][index]))
+
+        #   4: Create and start the VM
+        self.connection.put(cfg_sriov, cfg_sriov)
+        time.sleep(10)
+        err, out = self.check_output("virsh list --name | grep -i vm1")
+        try:
+            if out == "vm1":
+                log.info("VM is already present")
+            else:
+                #    FIXME: launch through libvirt
+                log.info("virsh create ...")
+                err, out, _ = self.connection.execute(
+                    "virsh create /tmp/vm_sriov.xml")
+                time.sleep(10)
+                log.error("err : {0}".format(err))
+                log.error("{0}".format(_))
+                log.debug("out : {0}".format(out))
+        except ValueError:
+                raise
+
+        #    5: Tunning for better performace
+        self.pin_vcpu(pcis)
+        self.connection.execute(
+            "echo 1 > /sys/module/kvm/parameters/"
+            "allow_unsafe_assigned_interrupts")
+        self.connection.execute(
+            "echo never > /sys/kernel/mm/transparent_hugepage/enabled")
+
+    def add_sriov_interface(self, index, vf_pci, vfmac, xml):
+        root = ET.parse(xml)
+        pattern = "0000:(\d+):(\d+).(\d+)"
+        m = re.search(pattern, vf_pci, re.MULTILINE)
+        device = root.find('devices')
+
+        interface = ET.SubElement(device, 'interface')
+        interface.set('managed', 'yes')
+        interface.set('type', 'hostdev')
+
+        mac = ET.SubElement(interface, 'mac')
+        mac.set('address', vfmac)
+        source = ET.SubElement(interface, 'source')
+
+        addr = ET.SubElement(source, "address")
+        addr.set('domain', "0x0")
+        addr.set('bus', "{0}".format(m.group(1)))
+        addr.set('function', "{0}".format(m.group(3)))
+        addr.set('slot', "{0}".format(m.group(2)))
+        addr.set('type', "pci")
+
+        vf_pci = ET.SubElement(interface, 'address')
+        vf_pci.set('type', 'pci')
+        vf_pci.set('domain', '0x0000')
+        vf_pci.set('bus', '0x00')
+        vf_pci.set('slot', '0x0{0}'.format(index + 7))
+        vf_pci.set('function', '0x00')
+
+        root.write(xml)
+
+    #   This is roughly compatible with check_output function in subprocess
+    #   module which is only available in python 2.7
+    def check_output(self, cmd, stderr=None):
+        #   Run a command and capture its output
+        err, out, _ = self.connection.execute(cmd)
+        return err, out
+
+    def get_virtual_devices(self, pci):
+        pf_vfs = {}
+        err, extra_info = self.check_output(
+            "cat /sys/bus/pci/devices/{0}/virtfn0/uevent".format(pci))
+        pattern = "PCI_SLOT_NAME=(?P<name>[0-9:.\s.]+)"
+        m = re.search(pattern, extra_info, re.MULTILINE)
+
+        if m:
+            pf_vfs.update({pci: str(m.group(1).rstrip())})
+        log.info("pf_vfs : {0}".format(pf_vfs))
+        return pf_vfs
+
+    def get_vf_datas(self, key, value, vfmac):
+        vfret = {}
+        pattern = "0000:(\d+):(\d+).(\d+)"
+
+        vfret["mac"] = vfmac
+        vfs = self.get_virtual_devices(value)
+        log.info("vfs: {0}".format(vfs))
+        for k, v in vfs.items():
+            m = re.search(pattern, k, re.MULTILINE)
+            m1 = re.search(pattern, value, re.MULTILINE)
+            if m.group(1) == m1.group(1):
+                vfret["vf_pci"] = str(v)
+                break
+
+        return vfret
+
+    def read_from_file(self, filename):
+        data = ""
+        with open(filename, 'r') as the_file:
+            data = the_file.read()
+        return data
+
+    def write_to_file(self, filename, content):
+        with open(filename, 'w') as the_file:
+            the_file.write(content)
+
+    def pin_vcpu(self, pcis):
+        nodes = self.get_numa_nodes()
+        log.info("{0}".format(nodes))
+        num_nodes = len(nodes)
+        for i in range(0, 10):
+            self.connection.execute(
+                "virsh vcpupin vm1 {0} {1}".format(
+                    i, nodes[str(num_nodes - 1)][i]))
+
+    def get_numa_nodes(self):
+        nodes_sysfs = glob.iglob("/sys/devices/system/node/node*")
+        nodes = {}
+        for node_sysfs in nodes_sysfs:
+            num = os.path.basename(node_sysfs).replace("node", "")
+            with open(os.path.join(node_sysfs, "cpulist")) as cpulist_file:
+                cpulist = cpulist_file.read().strip()
+            nodes[num] = self.split_cpu_list(cpulist)
+        log.info("nodes: {0}".format(nodes))
+        return nodes
+
+    def split_cpu_list(self, cpu_list):
+        if cpu_list:
+            ranges = cpu_list.split(',')
+            bounds = ([int(b) for b in r.split('-')] for r in ranges)
+            range_objects =\
+                (range(bound[0], bound[1] + 1 if len(bound) == 2
+                 else bound[0] + 1) for bound in bounds)
+
+            return sorted(itertools.chain.from_iterable(range_objects))
+        else:
+            return []
+
+    def destroy_vm(self):
+        host_driver = self.sriov[0]["phy_driver"]
+        err, out = self.check_output("virsh list --name | grep -i vm1")
+        log.info("{0}".format(out))
+        if err == 0:
+            self.connection.execute("virsh shutdown vm1")
+            self.connection.execute("virsh destroy vm1")
+            self.check_output("rmmod {0}".format(host_driver))[1].splitlines()
+            self.check_output("modprobe {0}".format(host_driver))[
+                1].splitlines()
+        else:
+            log.error("error : {0}".format(err))
index 8614f0c..e921437 100644 (file)
@@ -21,6 +21,7 @@ import yaml
 
 from yardstick.benchmark.contexts.base import Context
 from yardstick.common.constants import YARDSTICK_ROOT_PATH
+from yardstick.common.utils import import_modules_from_package, itersubclasses
 
 LOG = logging.getLogger(__name__)
 
@@ -38,7 +39,8 @@ class StandaloneContext(Context):
         self.nodes = []
         self.networks = {}
         self.nfvi_node = []
-        super(StandaloneContext, self).__init__()
+        self.nfvi_obj = None
+        super(self.__class__, self).__init__()
 
     def read_config_file(self):
         """Read from config file"""
@@ -48,6 +50,14 @@ class StandaloneContext(Context):
             cfg = yaml.load(stream)
         return cfg
 
+    def get_nfvi_obj(self):
+        print("{0}".format(self.nfvi_node[0]['role']))
+        context_type = self.get_context_impl(self.nfvi_node[0]['role'])
+        nfvi_obj = context_type()
+        nfvi_obj.__init__()
+        nfvi_obj.parse_pod_and_get_data(self.file_path)
+        return nfvi_obj
+
     def init(self, attrs):
         """initializes itself from the supplied arguments"""
 
@@ -69,6 +79,15 @@ class StandaloneContext(Context):
                                if node["role"] == "nfvi_node"])
         # add optional static network definition
         self.networks.update(cfg.get("networks", {}))
+        for node in cfg["nodes"]:
+            if str(node["role"]) == "Sriov":
+                self.nfvi_node.extend([node for node in cfg["nodes"]
+                                       if str(node["role"]) == "Sriov"])
+            if str(node["role"]) == "ovs-dpdk":
+                LOG.info("{0}".format(node["role"]))
+            else:
+                LOG.debug("Node role is other than SRIOV and OVS")
+        self.nfvi_obj = self.get_nfvi_obj()
         LOG.debug("Nodes: %r", self.nodes)
         LOG.debug("NFVi Node: %r", self.nfvi_node)
         LOG.debug("Networks: %r", self.networks)
@@ -77,13 +96,26 @@ class StandaloneContext(Context):
         """don't need to deploy"""
 
         # Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config.
+        self.nfvi_obj.ssh_remote_machine()
+        if self.nfvi_obj.first_run is True:
+            self.nfvi_obj.install_req_libs()
+
+        nic_details = self.nfvi_obj.get_nic_details()
+        print("{0}".format(nic_details))
+        self.nfvi_obj.setup_sriov_context(
+            self.nfvi_obj.sriov[0]['phy_ports'],
+            nic_details,
+            self.nfvi_obj.sriov[0]['phy_driver'])
         pass
 
     def undeploy(self):
         """don't need to undeploy"""
 
         # Todo: NFVi undeploy (sriov, vswitch, ovs etc) based on the config.
-        super(StandaloneContext, self).undeploy()
+        # self.nfvi_obj = self.get_nfvi_obj()
+        self.nfvi_obj.ssh_remote_machine()
+        self.nfvi_obj.destroy_vm()
+        pass
 
     def _get_server(self, attr_name):
         """lookup server info by name from context
@@ -95,7 +127,7 @@ class StandaloneContext(Context):
         if isinstance(attr_name, collections.Mapping):
             return None
 
-        if self.name.split("-")[0] != attr_name.split(".")[1]:
+        if self.name != attr_name.split(".")[1]:
             return None
 
         node_name = attr_name.split(".")[0]
@@ -146,3 +178,19 @@ class StandaloneContext(Context):
             "physical_network": network.get("physical_network"),
         }
         return result
+
+    def get_context_impl(self, nfvi_type):
+        """ Find the implementing class from vnf_model["vnf"]["name"] field
+
+        :param vnf_model: dictionary containing a parsed vnfd
+        :return: subclass of GenericVNF
+        """
+        import_modules_from_package(
+            "yardstick.benchmark.contexts")
+        expected_name = nfvi_type
+        impl = [c for c in itersubclasses(StandaloneContext)
+                if c.__name__ == expected_name]
+        try:
+            return next(iter(impl))
+        except StopIteration:
+            raise ValueError("No implementation for %s", expected_name)