diff options
author | Deepak S <deepak.s@linux.intel.com> | 2017-09-19 01:37:02 -0700 |
---|---|---|
committer | Ross Brattain <ross.b.brattain@intel.com> | 2017-10-02 15:16:04 -0700 |
commit | 8ae63e17a4f6934895d69f4c8b4dbc7628d48526 (patch) | |
tree | 14eb9e3df1c7d50ec1996105c41c9c8208eb8c7b | |
parent | 134e77b91771487e9a85b92d727829d43403ce38 (diff) |
Enabling multi_VM & multi port launch in standalone context
new context names:
- SRIOV - StandaloneSriov
- OvsDpdk - StandaloneOvsDpdk
- Seperate helper, libvirt, server info class
- Allow multi-port and multi-VM support.
Change-Id: I3c65e4535082fa0e2f4c6ee11c3bca9ccfdc01b8
Signed-off-by: Deepak S <deepak.s@linux.intel.com>
Signed-off-by: Martin Banszel <martinx.banszel@intel.com>
21 files changed, 2289 insertions, 2639 deletions
diff --git a/tests/unit/benchmark/contexts/standalone/nodes_duplicate_sample.yaml b/tests/unit/benchmark/contexts/standalone/nodes_duplicate_sample.yaml new file mode 100644 index 000000000..2e501a6af --- /dev/null +++ b/tests/unit/benchmark/contexts/standalone/nodes_duplicate_sample.yaml @@ -0,0 +1,37 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +nodes: +- + name: node1 + role: Controller + ip: 10.229.47.137 + user: root + key_filename: /root/.yardstick_key +- + name: node1 + role: Controller + ip: 10.229.47.138 + user: root + key_filename: /root/.yardstick_key + +- + name: node5 + role: Sriov + ip: 10.229.47.140 + user: root + password: password + key_filename: /root/.yardstick_key + +- + name: node5 + role: OvsDpdk + ip: 10.229.47.140 + user: root + password: password + key_filename: /root/.yardstick_key diff --git a/tests/unit/benchmark/contexts/standalone/nodes_ovs_dpdk_sample.yaml b/tests/unit/benchmark/contexts/standalone/nodes_ovs_dpdk_sample.yaml new file mode 100644 index 000000000..0f51dbe63 --- /dev/null +++ b/tests/unit/benchmark/contexts/standalone/nodes_ovs_dpdk_sample.yaml @@ -0,0 +1,40 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +nodes: +- + name: node1 + role: Controller + ip: 10.229.47.137 + user: root + key_filename: /root/.yardstick_key +- + name: node2 + role: Controller + ip: 10.229.47.138 + user: root + key_filename: /root/.yardstick_key +- + name: node3 + role: Compute + ip: 10.229.47.139 + user: root + key_filename: /root/.yardstick_key +- + name: node4 + role: Baremetal + ip: 10.229.47.140 + user: root + key_filename: /root/.yardstick_key +- + name: node5 + role: OvsDpdk + ip: 10.229.47.140 + user: root + password: password + key_filename: /root/.yardstick_key diff --git a/tests/unit/benchmark/contexts/standalone/nodes_sample.yaml b/tests/unit/benchmark/contexts/standalone/nodes_sample.yaml new file mode 100644 index 000000000..8d50c3aea --- /dev/null +++ b/tests/unit/benchmark/contexts/standalone/nodes_sample.yaml @@ -0,0 +1,33 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +nodes: +- + name: node1 + role: Controller + ip: 10.229.47.137 + user: root + key_filename: /root/.yardstick_key +- + name: node2 + role: Controller + ip: 10.229.47.138 + user: root + key_filename: /root/.yardstick_key +- + name: node3 + role: Compute + ip: 10.229.47.139 + user: root + key_filename: /root/.yardstick_key +- + name: node4 + role: Baremetal + ip: 10.229.47.140 + user: root + key_filename: /root/.yardstick_key diff --git a/tests/unit/benchmark/contexts/standalone/nodes_sriov_sample.yaml b/tests/unit/benchmark/contexts/standalone/nodes_sriov_sample.yaml new file mode 100644 index 000000000..1c43b8725 --- /dev/null +++ b/tests/unit/benchmark/contexts/standalone/nodes_sriov_sample.yaml @@ -0,0 +1,40 @@ +############################################################################## +# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +nodes: +- + name: node1 + role: Controller + ip: 10.229.47.137 + user: root + key_filename: /root/.yardstick_key +- + name: node2 + role: Controller + ip: 10.229.47.138 + user: root + key_filename: /root/.yardstick_key +- + name: node3 + role: Compute + ip: 10.229.47.139 + user: root + key_filename: /root/.yardstick_key +- + name: node4 + role: Baremetal + ip: 10.229.47.140 + user: root + key_filename: /root/.yardstick_key +- + name: node5 + role: Sriov + ip: 10.229.47.140 + user: root + password: password + key_filename: /root/.yardstick_key diff --git a/tests/unit/benchmark/contexts/standalone/ovs_sample_password.yaml b/tests/unit/benchmark/contexts/standalone/ovs_sample_password.yaml deleted file mode 100644 index b1da1ea9f..000000000 --- a/tests/unit/benchmark/contexts/standalone/ovs_sample_password.yaml +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright (c) 2016 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.223.197.182 - user: root - auth_type: password - password: intel123 - 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: ovs - role: Ovsdpdk - ip: 10.223.197.222 - user: root - auth_type: password - password: intel123 - vpath: "/usr/local/" - vports: - - dpdkvhostuser0 - - dpdkvhostuser1 - vports_mac: - - "00:00:00:00:00:03" - - "00:00:00:00:00:04" - phy_ports: # Physical ports to configure ovs - - "0000:06:00.0" - - "0000:06:00.1" - flow: - - ovs-ofctl add-flow br0 in_port=1,action=output:3 - - ovs-ofctl add-flow br0 in_port=3,action=output:1 - - ovs-ofctl add-flow br0 in_port=4,action=output:2 - - ovs-ofctl add-flow br0 in_port=2,action=output:4 - phy_driver: i40e # kernel driver - images: "/var/lib/libvirt/images/ubuntu1.img" - -- - name: vnf - role: vnf - ip: 10.223.197.155 - user: root - auth_type: password - password: intel123 - host: 10.223.197.140 - interfaces: - xe0: # logical name from topology.yaml and vnfd.yaml - vpci: "0000:00:04.0" - driver: virtio-pci - dpdk_port_num: 0 - local_ip: "152.16.100.19" - netmask: "255.255.255.0" - local_mac: "00:00:00:00:00:03" - - xe1: # logical name from topology.yaml and vnfd.yaml - vpci: "0000:00:05.0" - driver: virtio-pci - dpdk_port_num: 1 - local_ip: "152.16.40.19" - netmask: "255.255.255.0" - local_mac: "00:00:00:00:00:04" - 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/standalone/ovs_sample_ssh_key.yaml b/tests/unit/benchmark/contexts/standalone/ovs_sample_ssh_key.yaml deleted file mode 100644 index 896ec33bb..000000000 --- a/tests/unit/benchmark/contexts/standalone/ovs_sample_ssh_key.yaml +++ /dev/null @@ -1,69 +0,0 @@ -############################################################################## -# Copyright (c) 2015 Huawei Technologies Co.,Ltd and others. -# -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Apache License, Version 2.0 -# which accompanies this distribution, and is available at -# http://www.apache.org/licenses/LICENSE-2.0 -############################################################################## ---- -# Sample config file about the POD information, including the -# name/IP/user/ssh key of Bare Metal and Controllers/Computes -# -# The options of this config file include: -# name: the name of this node -# role: node's role, support role: Master/Controller/Comupte/BareMetal -# ip: the node's IP address -# user: the username for login -# key_filename:the path of the private key file for login - -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: ovs - role: Ovsdpdk - ip: 10.223.197.222 - auth_type: ssh_key - user: root - ssh_port: 22 - key_filename: /root/.ssh/id_rsa - vpath: "/usr/local/" - vports: - - dpdkvhostuser0 - - dpdkvhostuser1 - vports_mac: - - "00:00:00:00:00:03" - - "00:00:00:00:00:04" - phy_ports: # Physical ports to configure ovs - - "0000:06:00.0" - - "0000:06:00.1" - flow: - - ovs-ofctl add-flow br0 in_port=1,action=output:3 - - ovs-ofctl add-flow br0 in_port=3,action=output:1 - - ovs-ofctl add-flow br0 in_port=4,action=output:2 - - ovs-ofctl add-flow br0 in_port=2,action=output:4 - phy_driver: i40e # kernel driver - images: "/var/lib/libvirt/images/ubuntu1.img" - diff --git a/tests/unit/benchmark/contexts/standalone/ovs_sample_write_to_file.txt b/tests/unit/benchmark/contexts/standalone/ovs_sample_write_to_file.txt deleted file mode 100644 index f0eec86f6..000000000 --- a/tests/unit/benchmark/contexts/standalone/ovs_sample_write_to_file.txt +++ /dev/null @@ -1 +0,0 @@ -some content
\ No newline at end of file diff --git a/tests/unit/benchmark/contexts/standalone/sriov_sample_password.yaml b/tests/unit/benchmark/contexts/standalone/sriov_sample_password.yaml deleted file mode 100644 index 4f60e46d5..000000000 --- a/tests/unit/benchmark/contexts/standalone/sriov_sample_password.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# 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/standalone/sriov_sample_ssh_key.yaml b/tests/unit/benchmark/contexts/standalone/sriov_sample_ssh_key.yaml deleted file mode 100644 index faa496771..000000000 --- a/tests/unit/benchmark/contexts/standalone/sriov_sample_ssh_key.yaml +++ /dev/null @@ -1,54 +0,0 @@ -# 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/standalone/sriov_sample_write_to_file.txt b/tests/unit/benchmark/contexts/standalone/sriov_sample_write_to_file.txt deleted file mode 100644 index f0eec86f6..000000000 --- a/tests/unit/benchmark/contexts/standalone/sriov_sample_write_to_file.txt +++ /dev/null @@ -1 +0,0 @@ -some content
\ No newline at end of file diff --git a/tests/unit/benchmark/contexts/standalone/test_model.py b/tests/unit/benchmark/contexts/standalone/test_model.py new file mode 100644 index 000000000..ddbc1a4bb --- /dev/null +++ b/tests/unit/benchmark/contexts/standalone/test_model.py @@ -0,0 +1,331 @@ +#!/usr/bin/env python + +# 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. + +# Unittest for yardstick.benchmark.contexts.standalone.model + + +from __future__ import absolute_import +import os +import unittest +import errno +import mock + +from yardstick.common import constants as consts +from yardstick.benchmark.contexts.standalone.model import Libvirt +from yardstick.benchmark.contexts.standalone.model import StandaloneContextHelper +from yardstick.benchmark.contexts.standalone import model +from yardstick.network_services.utils import PciAddress + + +class ModelLibvirtTestCase(unittest.TestCase): + + def test_check_if_vm_exists_and_delete(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + result = Libvirt.check_if_vm_exists_and_delete("vm_0", ssh_mock) + self.assertIsNone(result) + + def test_virsh_create_vm(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + result = Libvirt.virsh_create_vm(ssh_mock, "vm_0") + self.assertIsNone(result) + + def test_virsh_destroy_vm(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + result = Libvirt.virsh_destroy_vm("vm_0", ssh_mock) + self.assertIsNone(result) + + @mock.patch('yardstick.benchmark.contexts.standalone.model.ET') + def test_add_interface_address(self, mock_et): + pci_address = PciAddress.parse_address("0000:00:04.0", multi_line=True) + result = Libvirt.add_interface_address("<interface/>", pci_address) + self.assertIsNotNone(result) + + @mock.patch('yardstick.benchmark.contexts.standalone.model.Libvirt.add_interface_address') + @mock.patch('yardstick.benchmark.contexts.standalone.model.ET') + def test_add_ovs_interfaces(self, mock_et, mock_add_interface_address): + pci_address = PciAddress.parse_address("0000:00:04.0", multi_line=True) + result = Libvirt.add_ovs_interface("/usr/local", 0, "0000:00:04.0", + "00:00:00:00:00:01", "xml") + self.assertIsNone(result) + + @mock.patch('yardstick.benchmark.contexts.standalone.model.Libvirt.add_interface_address') + @mock.patch('yardstick.benchmark.contexts.standalone.model.ET') + def test_add_sriov_interfaces(self, mock_et, mock_add_interface_address): + pci_address = PciAddress.parse_address("0000:00:04.0", multi_line=True) + result = Libvirt.add_sriov_interfaces("0000:00:05.0", "0000:00:04.0", + "00:00:00:00:00:01", "xml") + self.assertIsNone(result) + + def test_create_snapshot_qemu(self): + result = "/var/lib/libvirt/images/0.qcow2" + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + image = Libvirt.create_snapshot_qemu(ssh_mock, "0", "ubuntu.img") + self.assertEqual(image, result) + + @mock.patch("yardstick.benchmark.contexts.standalone.model.Libvirt.create_snapshot_qemu") + @mock.patch('yardstick.benchmark.contexts.standalone.model.open') + @mock.patch('yardstick.benchmark.contexts.standalone.model.write_file') + def test_build_vm_xml(self, mock_open, mock_write_file, mock_create_snapshot_qemu): + result = [4] + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + mock_create_snapshot_qemu.return_value = "0.img" + status = Libvirt.build_vm_xml(ssh_mock, {}, "test", "vm_0", 0) + self.assertEqual(status[0], result[0]) + + def test_split_cpu_list(self): + result = Libvirt.split_cpu_list("1,2,3") + self.assertEqual(result, [1, 2, 3]) + + def test_get_numa_nodes(self): + result = Libvirt.get_numa_nodes() + self.assertIsNotNone(result) + + def test_update_interrupts_hugepages_perf(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + status = Libvirt.update_interrupts_hugepages_perf(ssh_mock) + self.assertIsNone(status) + + @mock.patch("yardstick.benchmark.contexts.standalone.model.Libvirt.get_numa_nodes") + @mock.patch("yardstick.benchmark.contexts.standalone.model.Libvirt.update_interrupts_hugepages_perf") + def test_pin_vcpu_for_perf(self, mock_update_interrupts_hugepages_perf, mock_get_numa_nodes): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + mock_get_numa_nodes.return_value = {'1': [18, 19, 20, 21], '0': [0, 1, 2, 3]} + status = Libvirt.pin_vcpu_for_perf(ssh_mock, "vm_0", 4) + self.assertIsNone(status) + +class StandaloneContextHelperTestCase(unittest.TestCase): + + NODE_SAMPLE = "nodes_sample.yaml" + NODE_SRIOV_SAMPLE = "nodes_sriov_sample.yaml" + + NETWORKS = { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'private_0': { + 'phy_port': "0000:05:00.0", + 'vpci': "0000:00:07.0", + 'cidr': '152.16.100.10/24', + 'gateway_ip': '152.16.100.20'}, + 'public_0': { + 'phy_port': "0000:05:00.1", + 'vpci': "0000:00:08.0", + 'cidr': '152.16.40.10/24', + 'gateway_ip': '152.16.100.20'} + } + + def setUp(self): + self.helper = StandaloneContextHelper() + + def test___init__(self): + self.assertIsNone(self.helper.file_path) + + 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=(1, "a", "")) + ssh.return_value = ssh_mock + status = StandaloneContextHelper.install_req_libs(ssh_mock) + self.assertIsNone(status) + + def test_get_kernel_module(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(1, "i40e", "")) + ssh.return_value = ssh_mock + status = StandaloneContextHelper.get_kernel_module(ssh_mock, "05:00.0", None) + self.assertEqual(status, "i40e") + + @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper.get_kernel_module') + def test_get_nic_details(self, mock_get_kernel_module): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(1, "i40e ixgbe", "")) + ssh.return_value = ssh_mock + mock_get_kernel_module.return_value = "i40e" + status = StandaloneContextHelper.get_nic_details(ssh_mock, self.NETWORKS, "dpdk-devbind.py") + self.assertIsNotNone(status) + + def test_get_virtual_devices(self): + pattern = "PCI_SLOT_NAME=0000:05:00.0" + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(1, pattern, "")) + ssh.return_value = ssh_mock + status = StandaloneContextHelper.get_virtual_devices(ssh_mock, "0000:00:05.0") + self.assertIsNotNone(status) + + 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 + + def test_read_config_file(self): + self.helper.file_path = self._get_file_abspath(self.NODE_SAMPLE) + status = self.helper.read_config_file() + self.assertIsNotNone(status) + + def test_parse_pod_file(self): + self.helper.file_path = self._get_file_abspath("dummy") + self.assertRaises(IOError, self.helper.parse_pod_file, self.helper.file_path) + + self.helper.file_path = self._get_file_abspath(self.NODE_SAMPLE) + self.assertRaises(TypeError, self.helper.parse_pod_file, self.helper.file_path) + + self.helper.file_path = self._get_file_abspath(self.NODE_SRIOV_SAMPLE) + self.assertIsNotNone(self.helper.parse_pod_file(self.helper.file_path)) + + def test_get_mac_address(self): + status = StandaloneContextHelper.get_mac_address() + self.assertIsNotNone(status) + + @mock.patch('yardstick.ssh.SSH') + def test_get_mgmt_ip(self, mock_ssh): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(1, "1.2.3.4 00:00:00:00:00:01", "")) + ssh.return_value = ssh_mock + status = StandaloneContextHelper.get_mgmt_ip(ssh_mock, "00:00:00:00:00:01", "1.1.1.1/24", {}) + self.assertIsNotNone(status) + + @mock.patch('yardstick.ssh.SSH') + def test_get_mgmt_ip_no(self, mock_ssh): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(1, "", "")) + ssh.return_value = ssh_mock + + model.WAIT_FOR_BOOT = 0 + status = StandaloneContextHelper.get_mgmt_ip(ssh_mock, "99", "1.1.1.1/24", {}) + self.assertIsNone(status) + +class ServerTestCase(unittest.TestCase): + + NETWORKS = { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'private_0': { + 'phy_port': "0000:05:00.0", + 'vpci': "0000:00:07.0", + 'driver': 'i40e', + 'mac': '', + 'cidr': '152.16.100.10/24', + 'gateway_ip': '152.16.100.20'}, + 'public_0': { + 'phy_port': "0000:05:00.1", + 'vpci': "0000:00:08.0", + 'driver': 'i40e', + 'mac': '', + 'cidr': '152.16.40.10/24', + 'gateway_ip': '152.16.100.20'} + } + def setUp(self): + self.server = model.Server() + + def test___init__(self): + self.assertIsNotNone(self.server) + + def test_build_vnf_interfaces(self): + vnf = { + "network_ports": { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'xe0': ['private_0'], + 'xe1': ['public_0'], + } + } + status = model.Server.build_vnf_interfaces(vnf, self.NETWORKS) + self.assertIsNotNone(status) + + def test_generate_vnf_instance(self): + vnf = { + "network_ports": { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'xe0': ['private_0'], + 'xe1': ['public_0'], + } + } + status = self.server.generate_vnf_instance({}, self.NETWORKS, "1.1.1.1/24", 'vm_0', vnf, '00:00:00:00:00:01') + self.assertIsNotNone(status) + +class OvsDeployTestCase(unittest.TestCase): + + NETWORKS = { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'private_0': { + 'phy_port': "0000:05:00.0", + 'vpci': "0000:00:07.0", + 'driver': 'i40e', + 'mac': '', + 'cidr': '152.16.100.10/24', + 'gateway_ip': '152.16.100.20'}, + 'public_0': { + 'phy_port': "0000:05:00.1", + 'vpci': "0000:00:08.0", + 'driver': 'i40e', + 'mac': '', + 'cidr': '152.16.40.10/24', + 'gateway_ip': '152.16.100.20'} + } + @mock.patch('yardstick.ssh.SSH') + def setUp(self, mock_ssh): + self.ovs_deploy = model.OvsDeploy(mock_ssh, '/tmp/dpdk-devbind.py', {}) + + def test___init__(self): + self.assertIsNotNone(self.ovs_deploy.connection) + + @mock.patch('yardstick.benchmark.contexts.standalone.model.os') + def test_prerequisite(self, mock_ssh): + self.ovs_deploy.helper = mock.Mock() + self.assertIsNone(self.ovs_deploy.prerequisite()) + + @mock.patch('yardstick.benchmark.contexts.standalone.model.os') + def test_prerequisite(self, mock_ssh): + self.ovs_deploy.helper = mock.Mock() + self.ovs_deploy.connection.execute = \ + mock.Mock(return_value=(1, "1.2.3.4 00:00:00:00:00:01", "")) + self.ovs_deploy.prerequisite = mock.Mock() + self.assertIsNone(self.ovs_deploy.ovs_deploy()) diff --git a/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py b/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py new file mode 100644 index 000000000..5d1b0421c --- /dev/null +++ b/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py @@ -0,0 +1,377 @@ +# 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. + +# Unittest for yardstick.benchmark.contexts.standalone.standaloneovs + +from __future__ import absolute_import +import os +import unittest +import errno +import mock + +from yardstick.common import constants as consts +from yardstick.benchmark.contexts.standalone import ovs_dpdk +from yardstick.network_services.utils import PciAddress + + +class OvsDpdkContextTestCase(unittest.TestCase): + + NODES_SAMPLE = "nodes_sample.yaml" + NODES_ovs_dpdk_SAMPLE = "nodes_ovs_dpdk_sample.yaml" + NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml" + + ATTRS = { + 'name': 'StandaloneOvsDpdk', + 'file': 'pod', + 'flavor': {}, + 'servers': {}, + 'networks': {}, + } + + NETWORKS = { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'private_0': { + 'phy_port': "0000:05:00.0", + 'vpci': "0000:00:07.0", + 'cidr': '152.16.100.10/24', + 'interface': 'if0', + 'mac': "00:00:00:00:00:01", + 'vf_pci': {'vf_pci': 0}, + 'gateway_ip': '152.16.100.20'}, + 'public_0': { + 'phy_port': "0000:05:00.1", + 'vpci': "0000:00:08.0", + 'cidr': '152.16.40.10/24', + 'interface': 'if0', + 'vf_pci': {'vf_pci': 0}, + 'mac': "00:00:00:00:00:01", + 'gateway_ip': '152.16.100.20'}, + } + + def setUp(self): + self.ovs_dpdk = ovs_dpdk.OvsDpdkContext() + + @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper') + @mock.patch('yardstick.benchmark.contexts.standalone.model.Server') + def test___init__(self, mock_helper, mock_server): + self.ovs_dpdk.helper = mock_helper + self.ovs_dpdk.vnf_node = mock_server + self.assertIsNone(self.ovs_dpdk.file_path) + self.assertEqual(self.ovs_dpdk.first_run, True) + + def test_init(self): + self.ovs_dpdk.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}]) + self.assertIsNone(self.ovs_dpdk.init(self.ATTRS)) + + def test_setup_ovs(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.ovs_properties = {} + self.assertIsNone(self.ovs_dpdk.setup_ovs()) + + def test_start_ovs_serverswitch(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.ovs_properties = {} + self.ovs_dpdk.wait_for_vswitchd = 0 + self.assertIsNone(self.ovs_dpdk.start_ovs_serverswitch()) + + def test_setup_ovs_bridge_add_flows(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.ovs_properties = { + 'version': {'ovs': '2.7.0'} + } + self.ovs_dpdk.wait_for_vswitchd = 0 + self.assertIsNone(self.ovs_dpdk.setup_ovs_bridge_add_flows()) + + def test_cleanup_ovs_dpdk_env(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.ovs_properties = { + 'version': {'ovs': '2.7.0'} + } + self.ovs_dpdk.wait_for_vswitchd = 0 + self.assertIsNone(self.ovs_dpdk.cleanup_ovs_dpdk_env()) + + @mock.patch('yardstick.benchmark.contexts.standalone.model.OvsDeploy') + def test_check_ovs_dpdk_env(self, mock_ovs): + 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 + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.ovs_properties = { + 'version': {'ovs': '2.7.0', 'dpdk': '16.11.1'} + } + self.ovs_dpdk.wait_for_vswitchd = 0 + self.ovs_dpdk.cleanup_ovs_dpdk_env = mock.Mock() + self.assertIsNone(self.ovs_dpdk.check_ovs_dpdk_env()) + self.ovs_dpdk.ovs_properties = { + 'version': {'ovs': '2.0.0'} + } + self.ovs_dpdk.wait_for_vswitchd = 0 + self.cleanup_ovs_dpdk_env = mock.Mock() + mock_ovs.deploy = mock.Mock() + self.assertRaises(Exception, self.ovs_dpdk.check_ovs_dpdk_env) + + @mock.patch('yardstick.ssh.SSH') + def test_deploy(self, mock_ssh): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.vm_deploy = False + self.assertIsNone(self.ovs_dpdk.deploy()) + + self.ovs_dpdk.vm_deploy = True + self.ovs_dpdk.host_mgmt = {} + self.ovs_dpdk.install_req_libs = mock.Mock() + self.ovs_dpdk.helper.get_nic_details = mock.Mock(return_value={}) + self.ovs_dpdk.check_ovs_dpdk_env = mock.Mock(return_value={}) + self.ovs_dpdk.setup_ovs = mock.Mock(return_value={}) + self.ovs_dpdk.start_ovs_serverswitch = mock.Mock(return_value={}) + self.ovs_dpdk.setup_ovs_bridge_add_flows = mock.Mock(return_value={}) + self.ovs_dpdk.setup_ovs_dpdk_context = mock.Mock(return_value={}) + self.ovs_dpdk.wait_for_vnfs_to_start = mock.Mock(return_value={}) + self.assertIsNone(self.ovs_dpdk.deploy()) + + @mock.patch('yardstick.benchmark.contexts.standalone.ovs_dpdk.Libvirt') + @mock.patch('yardstick.ssh.SSH') + def test_undeploy(self, mock_ssh, mock_libvirt): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.vm_deploy = False + self.assertIsNone(self.ovs_dpdk.undeploy()) + + self.ovs_dpdk.vm_deploy = True + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.vm_names = ['vm_0', 'vm_1'] + self.ovs_dpdk.drivers = ['vm_0', 'vm_1'] + self.ovs_dpdk.cleanup_ovs_dpdk_env = mock.Mock() + self.ovs_dpdk.networks = self.NETWORKS + self.assertIsNone(self.ovs_dpdk.undeploy()) + + 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 + + def test__get_server_with_dic_attr_name(self): + + attrs = { + 'name': 'foo', + 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE) + } + + self.ovs_dpdk.init(attrs) + + attr_name = {'name': 'foo.bar'} + result = self.ovs_dpdk._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_ovs_dpdk_SAMPLE) + } + + self.ovs_dpdk.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}]) + self.ovs_dpdk.init(attrs) + + attr_name = 'bar.foo' + result = self.ovs_dpdk._get_server(attr_name) + + self.assertEqual(result, None) + + def test__get_server_mismatch(self): + + attrs = { + 'name': 'foo', + 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE) + } + + self.ovs_dpdk.init(attrs) + + attr_name = 'bar.foo1' + result = self.ovs_dpdk._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.ovs_dpdk.init(attrs) + + attr_name = 'node1.foo' + with self.assertRaises(ValueError): + self.ovs_dpdk._get_server(attr_name) + + def test__get_server_found(self): + + attrs = { + 'name': 'foo', + 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE) + } + + self.ovs_dpdk.init(attrs) + + attr_name = 'node1.foo' + result = self.ovs_dpdk._get_server(attr_name) + + self.assertEqual(result['ip'], '10.229.47.137') + self.assertEqual(result['name'], 'node1.foo') + self.assertEqual(result['user'], 'root') + self.assertEqual(result['key_filename'], '/root/.yardstick_key') + + def test__get_network(self): + network1 = { + 'name': 'net_1', + 'vld_id': 'vld111', + 'segmentation_id': 'seg54', + 'network_type': 'type_a', + 'physical_network': 'phys', + } + network2 = { + 'name': 'net_2', + 'vld_id': 'vld999', + } + self.ovs_dpdk.networks = { + 'a': network1, + 'b': network2, + } + + attr_name = {} + self.assertIsNone(self.ovs_dpdk._get_network(attr_name)) + + attr_name = {'vld_id': 'vld777'} + self.assertIsNone(self.ovs_dpdk._get_network(attr_name)) + + self.assertIsNone(self.ovs_dpdk._get_network(None)) + + attr_name = 'vld777' + self.assertIsNone(self.ovs_dpdk._get_network(attr_name)) + + attr_name = {'vld_id': 'vld999'} + expected = { + "name": 'net_2', + "vld_id": 'vld999', + "segmentation_id": None, + "network_type": None, + "physical_network": None, + } + result = self.ovs_dpdk._get_network(attr_name) + self.assertDictEqual(result, expected) + + attr_name = 'a' + expected = network1 + result = self.ovs_dpdk._get_network(attr_name) + self.assertDictEqual(result, expected) + + def test_configure_nics_for_ovs_dpdk(self): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.vm_deploy = True + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.vm_names = ['vm_0', 'vm_1'] + self.ovs_dpdk.drivers = [] + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.helper.get_mac_address = mock.Mock(return_value="") + self.ovs_dpdk.get_vf_datas = mock.Mock(return_value="") + self.assertIsNone(self.ovs_dpdk.configure_nics_for_ovs_dpdk()) + + @mock.patch('yardstick.benchmark.contexts.standalone.ovs_dpdk.Libvirt') + def test__enable_interfaces(self, mock_add_ovs_interface): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.vm_deploy = True + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.vm_names = ['vm_0', 'vm_1'] + self.ovs_dpdk.drivers = [] + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.get_vf_datas = mock.Mock(return_value="") + self.assertIsNone(self.ovs_dpdk._enable_interfaces(0, ["private_0"], 'test')) + + @mock.patch('yardstick.benchmark.contexts.standalone.ovs_dpdk.Libvirt') + @mock.patch('yardstick.benchmark.contexts.standalone.model.Server') + def test_setup_ovs_dpdk_context(self, mock_server, mock_libvirt): + with mock.patch("yardstick.ssh.SSH") as ssh: + ssh_mock = mock.Mock(autospec=ssh.SSH) + ssh_mock.execute = \ + mock.Mock(return_value=(0, "a", "")) + ssh_mock.put = \ + mock.Mock(return_value=(0, "a", "")) + ssh.return_value = ssh_mock + self.ovs_dpdk.vm_deploy = True + self.ovs_dpdk.connection = ssh_mock + self.ovs_dpdk.vm_names = ['vm_0', 'vm_1'] + self.ovs_dpdk.drivers = [] + self.ovs_dpdk.servers = { + 'vnf_0': { + 'network_ports': { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'xe0': ['private_0'], + 'xe1': ['public_0'] + } + } + } + self.ovs_dpdk.networks = self.NETWORKS + self.ovs_dpdk.host_mgmt = {} + self.ovs_dpdk.flavor = {} + self.ovs_dpdk.configure_nics_for_ovs_dpdk = mock.Mock(return_value="") + mock_libvirt.check_if_vm_exists_and_delete = mock.Mock(return_value="") + mock_libvirt.build_vm_xml = mock.Mock(return_value=[6, "00:00:00:00:00:01"]) + self.ovs_dpdk._enable_interfaces = mock.Mock(return_value="") + mock_libvirt.virsh_create_vm = mock.Mock(return_value="") + mock_libvirt.pin_vcpu_for_perf= mock.Mock(return_value="") + self.ovs_dpdk.vnf_node.generate_vnf_instance = mock.Mock(return_value={}) + self.assertIsNotNone(self.ovs_dpdk.setup_ovs_dpdk_context()) diff --git a/tests/unit/benchmark/contexts/standalone/test_ovsdpdk.py b/tests/unit/benchmark/contexts/standalone/test_ovsdpdk.py deleted file mode 100644 index 1d68384c9..000000000 --- a/tests/unit/benchmark/contexts/standalone/test_ovsdpdk.py +++ /dev/null @@ -1,327 +0,0 @@ -# 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 unittest - -import mock - -from yardstick.benchmark.contexts.standalone import ovsdpdk - -NIC_INPUT = { - 'interface': {}, - 'vports_mac': ['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'}, - 'vports_mac': ['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_ovs.yaml" -WRONG_FILE_PATH = "/etc/yardstick/wrong.yaml" -SAMPLE_FILE = "ovs_sample_write_to_file.txt" - -OVS = [{ - 'auth_type': 'ssh_key', - 'name': 'ovs', - 'ssh_port': 22, - 'ip': '10.10.10.11', - 'key_filename': '/root/.ssh/id_rsa', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'vpath': '/usr/local/', - 'role': 'Ovsdpdk', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'flow': ['ovs-ofctl add-flow br0 in_port=1,action=output:3', - 'ovs-ofctl add-flow br0 in_port=3,action=output:1', - 'ovs-ofctl add-flow br0 in_port=4,action=output:2', - 'ovs-ofctl add-flow br0 in_port=2,action=output:4'], - 'phy_driver': 'i40e', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - -OVS_PASSWORD = [{ - 'auth_type': 'password', - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.10.10.11', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'flow': ['ovs-ofctl add-flow br0 in_port=1,action=output:3', - 'ovs-ofctl add-flow br0 in_port=3,action=output:1', - 'ovs-ofctl add-flow br0 in_port=4,action=output:2', - 'ovs-ofctl add-flow br0 in_port=2,action=output:4'], - '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 OvsdpdkTestCase(unittest.TestCase): - - NODES_SAMPLE_SSH = "ovs_sample_ssh_key.yaml" - NODES_SAMPLE_PASSWORD = "ovs_sample_password.yaml" - - def setUp(self): - self.test_context = ovsdpdk.Ovsdpdk() - - 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.ovs, []) - 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)) - - def test_ssh_connection(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 - - @mock.patch('yardstick.network_services.utils.provision_tool', return_value="b") - 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, "b", "")) - ssh.return_value = ssh_mock - mock_prov.provision_tool = mock.Mock() - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS_PASSWORD - self.assertIsNone(ovs_obj.ssh_remote_machine()) - - @mock.patch('yardstick.network_services.utils.provision_tool', return_value="b") - 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, "b", "")) - ssh.return_value = ssh_mock - mock_prov.provision_tool = mock.Mock() - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - ovs_obj.key_filename = '/root/.ssh/id_rsa' - self.assertIsNone(ovs_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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.ovs = OVS - ovs_obj.connection = ssh_mock - self.assertIsNotNone(ovs_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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.first_run = True - ovs_obj.connection = ssh_mock - self.assertIsNone(ovs_obj.install_req_libs()) - - def test_setup_ovs(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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - self.assertIsNone(ovs_obj.setup_ovs({"eth0 eth1"})) - - def test_start_ovs_serverswitch(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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - self.assertIsNone(ovs_obj.start_ovs_serverswitch()) - - def test_setup_ovs_bridge(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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - self.assertIsNone(ovs_obj.setup_ovs_bridge()) - - def test_add_oflows(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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - self.assertIsNone(ovs_obj.add_oflows()) - - def test_setup_ovs_context_vm_already_present(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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - mock_ovs = mock.Mock() - ssh_mock.put = mock.Mock() - ovs_obj.check_output = mock.Mock(return_value=(0, "vm1")) - with mock.patch("yardstick.benchmark.contexts.standalone.ovsdpdk.time"): - self.assertIsNone(ovs_obj.setup_ovs_context(PCIS, NIC_DETAILS, DRIVER)) - - @mock.patch( - 'yardstick.benchmark.contexts.standalone.ovsdpdk', - return_value="Domain vm1 created from /tmp/vm_ovs.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_mock.put = \ - mock.Mock(return_value=(0, {}, "")) - ssh.return_value = ssh_mock - mock_ovs = mock.Mock() - ret_create = mock.Mock() - pcis = NIC_DETAILS['pci'] - driver = NIC_DETAILS['phy_driver'] - self.assertIsNotNone( - mock_ovs.ovs_obj.setup_ovs_context( - pcis, - NIC_DETAILS, - driver)) - - 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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - self.assertIsNotNone(ovs_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)) - ovs_obj = ovsdpdk.Ovsdpdk() - self.assertIsNotNone(ovs_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)) - ovs_obj = ovsdpdk.Ovsdpdk() - self.assertEqual(ovs_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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - ovs_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(ovs_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 - ovs_obj = ovsdpdk.Ovsdpdk() - ovs_obj.connection = ssh_mock - ovs_obj.ovs = OVS - ovs_obj.check_output = mock.Mock(return_value=(1, {})) - self.assertIsNone(ovs_obj.destroy_vm()) - - def test_read_from_file(self): - CORRECT_FILE_PATH = self._get_file_abspath(self.NODES_SAMPLE_PASSWORD) - ovs_obj = ovsdpdk.Ovsdpdk() - self.assertIsNotNone(ovs_obj.read_from_file(CORRECT_FILE_PATH)) - - def test_write_to_file(self): - ovs_obj = ovsdpdk.Ovsdpdk() - self.assertIsNone(ovs_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() diff --git a/tests/unit/benchmark/contexts/standalone/test_sriov.py b/tests/unit/benchmark/contexts/standalone/test_sriov.py index ea72e1bab..50ae5fe13 100644 --- a/tests/unit/benchmark/contexts/standalone/test_sriov.py +++ b/tests/unit/benchmark/contexts/standalone/test_sriov.py @@ -12,412 +12,311 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import +# Unittest for yardstick.benchmark.contexts.standalone.standalonesriov +from __future__ import absolute_import import os import unittest - +import errno import mock +from yardstick.common import constants as consts from yardstick.benchmark.contexts.standalone 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" +from yardstick.network_services.utils import PciAddress + + +class SriovContextTestCase(unittest.TestCase): + + NODES_SAMPLE = "nodes_sample.yaml" + NODES_SRIOV_SAMPLE = "nodes_sriov_sample.yaml" + NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml" + + ATTRS = { + 'name': 'StandaloneSriov', + 'file': 'pod', + 'flavor': {}, + 'servers': {}, + 'networks': {}, + } + + NETWORKS = { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'private_0': { + 'phy_port': "0000:05:00.0", + 'vpci': "0000:00:07.0", + 'cidr': '152.16.100.10/24', + 'interface': 'if0', + 'mac': "00:00:00:00:00:01", + 'vf_pci': {'vf_pci': 0}, + 'gateway_ip': '152.16.100.20'}, + 'public_0': { + 'phy_port': "0000:05:00.1", + 'vpci': "0000:00:08.0", + 'cidr': '152.16.40.10/24', + 'interface': 'if0', + 'vf_pci': {'vf_pci': 0}, + 'mac': "00:00:00:00:00:01", + 'gateway_ip': '152.16.100.20'}, + } 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, "") + self.sriov = sriov.SriovContext() + + @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper') + @mock.patch('yardstick.benchmark.contexts.standalone.sriov.Libvirt') + @mock.patch('yardstick.benchmark.contexts.standalone.model.Server') + def test___init__(self, mock_helper, mock_libvirt, mock_server): + self.sriov.helper = mock_helper + self.sriov.vnf_node = mock_server + self.assertIsNone(self.sriov.file_path) + self.assertEqual(self.sriov.first_run, True) 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()) + self.sriov.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}]) + self.assertIsNone(self.sriov.init(self.ATTRS)) - def test_install_req_libs(self): + @mock.patch('yardstick.ssh.SSH') + def test_deploy(self, mock_ssh): with mock.patch("yardstick.ssh.SSH") as ssh: ssh_mock = mock.Mock(autospec=ssh.SSH) ssh_mock.execute = \ - mock.Mock(return_value=(0, {}, "")) + mock.Mock(return_value=(0, "a", "")) 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 - with mock.patch("yardstick.benchmark.contexts.standalone.sriov.time"): - 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, {})) - with mock.patch("yardstick.benchmark.contexts.standalone.sriov.time"): - self.assertIsNone(sriov_obj.setup_sriov_context(PCIS, nic_details, DRIVER)) + self.sriov.vm_deploy = False + self.assertIsNone(self.sriov.deploy()) - 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")) - with mock.patch("yardstick.benchmark.contexts.standalone.sriov.time"): - self.assertIsNone(sriov_obj.setup_sriov_context(PCIS, nic_details, DRIVER)) - - @mock.patch( - 'yardstick.benchmark.contexts.standalone.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): + self.sriov.vm_deploy = True + self.sriov.host_mgmt = {} + self.sriov.install_req_libs = mock.Mock() + self.sriov.get_nic_details = mock.Mock(return_value={}) + self.sriov.setup_sriov_context = mock.Mock(return_value={}) + self.sriov.wait_for_vnfs_to_start = mock.Mock(return_value={}) + self.assertIsNone(self.sriov.deploy()) + + @mock.patch('yardstick.ssh.SSH') + @mock.patch('yardstick.benchmark.contexts.standalone.sriov.Libvirt') + def test_undeploy(self, mock_libvirt, mock_ssh): with mock.patch("yardstick.ssh.SSH") as ssh: ssh_mock = mock.Mock(autospec=ssh.SSH) ssh_mock.execute = \ - mock.Mock(return_value=(0, {}, "")) + mock.Mock(return_value=(0, "a", "")) 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): + + self.sriov.vm_deploy = False + self.assertIsNone(self.sriov.undeploy()) + + self.sriov.vm_deploy = True + self.sriov.connection = ssh_mock + self.sriov.vm_names = ['vm_0', 'vm_1'] + self.sriov.drivers = ['vm_0', 'vm_1'] + self.assertIsNone(self.sriov.undeploy()) + + 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 + + def test__get_server_with_dic_attr_name(self): + + attrs = { + 'name': 'foo', + 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE) + } + + self.sriov.init(attrs) + + attr_name = {'name': 'foo.bar'} + result = self.sriov._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_SRIOV_SAMPLE) + } + + self.sriov.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}]) + self.sriov.init(attrs) + + attr_name = 'bar.foo' + result = self.sriov._get_server(attr_name) + + self.assertEqual(result, None) + + def test__get_server_mismatch(self): + + attrs = { + 'name': 'foo', + 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE) + } + + self.sriov.init(attrs) + + attr_name = 'bar.foo1' + result = self.sriov._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.sriov.init(attrs) + + attr_name = 'node1.foo' + with self.assertRaises(ValueError): + self.sriov._get_server(attr_name) + + def test__get_server_found(self): + + attrs = { + 'name': 'foo', + 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE) + } + + self.sriov.init(attrs) + + attr_name = 'node1.foo' + result = self.sriov._get_server(attr_name) + + self.assertEqual(result['ip'], '10.229.47.137') + self.assertEqual(result['name'], 'node1.foo') + self.assertEqual(result['user'], 'root') + self.assertEqual(result['key_filename'], '/root/.yardstick_key') + + def test__get_network(self): + network1 = { + 'name': 'net_1', + 'vld_id': 'vld111', + 'segmentation_id': 'seg54', + 'network_type': 'type_a', + 'physical_network': 'phys', + } + network2 = { + 'name': 'net_2', + 'vld_id': 'vld999', + } + self.sriov.networks = { + 'a': network1, + 'b': network2, + } + + attr_name = {} + self.assertIsNone(self.sriov._get_network(attr_name)) + + attr_name = {'vld_id': 'vld777'} + self.assertIsNone(self.sriov._get_network(attr_name)) + + self.assertIsNone(self.sriov._get_network(None)) + + attr_name = 'vld777' + self.assertIsNone(self.sriov._get_network(attr_name)) + + attr_name = {'vld_id': 'vld999'} + expected = { + "name": 'net_2', + "vld_id": 'vld999', + "segmentation_id": None, + "network_type": None, + "physical_network": None, + } + result = self.sriov._get_network(attr_name) + self.assertDictEqual(result, expected) + + attr_name = 'a' + expected = network1 + result = self.sriov._get_network(attr_name) + self.assertDictEqual(result, expected) + + def test_configure_nics_for_sriov(self): with mock.patch("yardstick.ssh.SSH") as ssh: ssh_mock = mock.Mock(autospec=ssh.SSH) ssh_mock.execute = \ - mock.Mock(return_value=(0, {}, "")) + mock.Mock(return_value=(0, "a", "")) 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): + self.sriov.vm_deploy = True + self.sriov.connection = ssh_mock + self.sriov.vm_names = ['vm_0', 'vm_1'] + self.sriov.drivers = [] + self.sriov.networks = self.NETWORKS + self.sriov.helper.get_mac_address = mock.Mock(return_value="") + self.sriov.get_vf_data = mock.Mock(return_value="") + self.assertIsNone(self.sriov.configure_nics_for_sriov()) + + @mock.patch('yardstick.benchmark.contexts.standalone.sriov.Libvirt') + def test__enable_interfaces(self, mock_libvirt): 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, {}, "")) + mock.Mock(return_value=(0, "a", "")) 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): + self.sriov.vm_deploy = True + self.sriov.connection = ssh_mock + self.sriov.vm_names = ['vm_0', 'vm_1'] + self.sriov.drivers = [] + self.sriov.networks = self.NETWORKS + self.sriov.get_vf_data = mock.Mock(return_value="") + self.assertIsNone(self.sriov._enable_interfaces(0, 0, ["private_0"], 'test')) + + @mock.patch('yardstick.benchmark.contexts.standalone.model.Server') + @mock.patch('yardstick.benchmark.contexts.standalone.sriov.Libvirt') + def test_setup_sriov_context(self, mock_libvirt, mock_server): with mock.patch("yardstick.ssh.SSH") as ssh: ssh_mock = mock.Mock(autospec=ssh.SSH) ssh_mock.execute = \ - mock.Mock(return_value=(0, {}, "")) + mock.Mock(return_value=(0, "a", "")) + ssh_mock.put = \ + mock.Mock(return_value=(0, "a", "")) 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): + self.sriov.vm_deploy = True + self.sriov.connection = ssh_mock + self.sriov.vm_names = ['vm_0', 'vm_1'] + self.sriov.drivers = [] + self.sriov.servers = { + 'vnf_0': { + 'network_ports': { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'xe0': ['private_0'], + 'xe1': ['public_0'] + } + } + } + self.sriov.networks = self.NETWORKS + self.sriov.host_mgmt = {} + self.sriov.flavor = {} + self.sriov.configure_nics_for_sriov = mock.Mock(return_value="") + mock_libvirt.build_vm_xml = mock.Mock(return_value=[6, "00:00:00:00:00:01"]) + self.sriov._enable_interfaces = mock.Mock(return_value="") + self.sriov.vnf_node.generate_vnf_instance = mock.Mock(return_value={}) + self.assertIsNotNone(self.sriov.setup_sriov_context()) + + def test_get_vf_data(self): with mock.patch("yardstick.ssh.SSH") as ssh: ssh_mock = mock.Mock(autospec=ssh.SSH) ssh_mock.execute = \ - mock.Mock(return_value=(0, {}, "")) + mock.Mock(return_value=(0, "a", "")) + ssh_mock.put = \ + mock.Mock(return_value=(0, "a", "")) 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() + self.sriov.vm_deploy = True + self.sriov.connection = ssh_mock + self.sriov.vm_names = ['vm_0', 'vm_1'] + self.sriov.drivers = [] + self.sriov.servers = { + 'vnf_0': { + 'network_ports': { + 'mgmt': {'cidr': '152.16.100.10/24'}, + 'xe0': ['private_0'], + 'xe1': ['public_0'] + } + } + } + self.sriov.networks = self.NETWORKS + self.sriov.helper.get_virtual_devices = mock.Mock(return_value={"0000:00:01.0": ""}) + self.assertIsNotNone(self.sriov.get_vf_data("", "0000:00:01.0", "00:00:00:00:00:01", "if0")) diff --git a/tests/unit/benchmark/contexts/test_standalone.py b/tests/unit/benchmark/contexts/test_standalone.py deleted file mode 100644 index b1402a1c9..000000000 --- a/tests/unit/benchmark/contexts/test_standalone.py +++ /dev/null @@ -1,682 +0,0 @@ -#!/usr/bin/env python - -# 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. -# - -# Unittest for yardstick.benchmark.contexts.standalone - -from __future__ import absolute_import - -import os -import unittest - -import mock - -from yardstick.benchmark.contexts import standalone -from yardstick.benchmark.contexts.standalone import ovsdpdk, sriov - -MOCKS = { - 'yardstick.benchmark.contexts': mock.MagicMock(), - 'yardstick.benchmark.contexts.standalone.sriov': mock.MagicMock(), - 'yardstick.benchmark.contexts.standalone.ovsdpdk': mock.MagicMock(), - 'yardstick.benchmark.contexts.standalone': mock.MagicMock(), -} - - -@mock.patch('yardstick.benchmark.contexts.standalone.ovsdpdk.time') -@mock.patch('yardstick.benchmark.contexts.standalone.time') -@mock.patch('yardstick.benchmark.contexts.standalone.sriov.time') -class StandaloneContextTestCase(unittest.TestCase): - NODES_SAMPLE = "nodes_sample_new.yaml" - NODES_SAMPLE_SRIOV = "nodes_sample_new_sriov.yaml" - NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample_new.yaml" - - NODES_SAMPLE_OVSDPDK = "nodes_sample_ovs.yaml" - NODES_SAMPLE_OVSDPDK_ROLE = "nodes_sample_ovsdpdk.yaml" - NODES_DUPLICATE_OVSDPDK = "nodes_duplicate_sample_ovs.yaml" - - def setUp(self): - self.test_context = standalone.StandaloneContext() - - def test_construct(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - 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, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath("error_file") - } - self.assertRaises(IOError, self.test_context.init, attrs) - - def test_successful_init_sriov(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs_sriov = { - '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.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - self.test_context.get_nfvi_obj = mock.Mock() - self.test_context.init(attrs_sriov) - self.assertEqual(self.test_context.name, "sriov") - self.assertEqual(len(self.test_context.nodes), 2) - self.assertEqual(len(self.test_context.nfvi_node), 2) - self.assertEqual(self.test_context.nfvi_node[0]["name"], "sriov") - - def test_successful_init_ovs(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - attrs_ovs = { - 'name': 'ovs', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK) - } - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - '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_ovs) - self.assertEqual(self.test_context.name, "ovs") - self.assertEqual(len(self.test_context.nodes), 2) - self.assertEqual(len(self.test_context.nfvi_node), 2) - self.assertEqual(self.test_context.nfvi_node[0]["name"], "ovs") - - def test__get_server_with_dic_attr_name_sriov(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs_sriov = { - '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.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - self.test_context.init(attrs_sriov) - attr_name = {'name': 'foo.bar'} - result = self.test_context._get_server(attr_name) - self.assertEqual(result, None) - - def test__get_server_with_dic_attr_name_ovs(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs_ovs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK) - } - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - self.test_context.init(attrs_ovs) - attr_name = {'name': 'foo.bar'} - result = self.test_context._get_server(attr_name) - self.assertEqual(result, None) - - def test__get_server_not_found_sriov(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - 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.223.197.140', - '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_not_found_ovs(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK) - } - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - '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_sriov(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - 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.223.197.140', - '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(return_value="sriov") - self.test_context.init(attrs) - attr_name = 'sriov.foo' - # self.test_context.name = "sriov" - self.assertRaises(ValueError, self.test_context._get_server, attr_name) - - def test__get_server_duplicate_ovs(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_DUPLICATE_OVSDPDK) - } - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - self.test_context.get_nfvi_obj = mock.Mock(return_value="OvsDpdk") - self.test_context.init(attrs) - - attr_name = 'ovs.foo' - self.assertRaises( - ValueError, - self.test_context._get_server, - attr_name) - - def test__get_server_found_sriov(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_SAMPLE_SRIOV) - } - self.test_context.nfvi_node = [{ - 'name': 'sriov', - 'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'], - 'ip': '10.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - self.test_context.get_nfvi_obj = mock.Mock(return_value="OvsDpdk") - self.test_context.init(attrs) - attr_name = 'sriov.foo' - result = self.test_context._get_server(attr_name) - self.assertEqual(result['ip'], '10.123.123.122') - self.assertEqual(result['name'], 'sriov.foo') - self.assertEqual(result['user'], 'root') - - def test__get_server_found_ovs(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK_ROLE) - } - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - '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(return_value="OvsDpdk") - self.test_context.init(attrs) - attr_name = 'ovs.foo' - result = self.test_context._get_server(attr_name) - self.assertEqual(result['ip'], '10.223.197.222') - self.assertEqual(result['name'], 'ovs.foo') - self.assertEqual(result['user'], 'root') - - def test__deploy_unsuccessful(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - self.test_context.vm_deploy = False - - def test__deploy_sriov_firsttime(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - 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.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - MYSRIOV = [{ - 'name': 'sriov', - 'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'], - 'ip': '10.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - self.test_context.vm_deploy = True - - self.test_context.get_nfvi_obj = mock.MagicMock() - self.test_context.init(attrs) - self.test_context.nfvi_obj.sriov = MYSRIOV - self.test_context.nfvi_obj.ssh_remote_machine = mock.Mock() - self.test_context.nfvi_obj.first_run = True - self.test_context.nfvi_obj.install_req_libs() - 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__deploy_sriov_notfirsttime(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - 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.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - MYSRIOV = [{ - 'name': 'sriov', - 'vf_macs': ['00:00:00:71:7d:25', '00:00:00:71:7d:26'], - 'ip': '10.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - self.test_context.vm_deploy = True - self.test_context.get_nfvi_obj = mock.MagicMock() - self.test_context.init(attrs) - self.test_context.nfvi_obj.sriov = MYSRIOV - self.test_context.nfvi_obj.ssh_remote_machine = mock.Mock() - self.test_context.nfvi_obj.first_run = False - 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__deploy_ovs_firsttime(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK) - } - - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'password', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - MYOVS = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'password', - 'flow': ['ovs-ofctl add-flow br0 in_port=1,action=output:3', - 'ovs-ofctl add-flow br0 in_port=3,action=output:1' - 'ovs-ofctl add-flow br0 in_port=4,action=output:2' - 'ovs-ofctl add-flow br0 in_port=2,action=output:4'], - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - self.test_context.vm_deploy = True - self.test_context.get_nfvi_obj = mock.MagicMock() - self.test_context.init(attrs) - self.test_context.ovs = MYOVS - self.test_context.nfvi_obj.ssh_remote_machine = mock.Mock() - self.test_context.nfvi_obj.first_run = True - self.test_context.nfvi_obj.install_req_libs() - 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'}, - 'vports_mac': ['00:00:00:00:00:05', '00:00:00:00:00:06'], - 'pci': ['0000:06:00.0', '0000:06:00.1'], - 'phy_driver': 'i40e'} - DRIVER = 'i40e' - - self.test_context.nfvi_obj.setup_ovs = mock.Mock() - self.test_context.nfvi_obj.start_ovs_serverswitch = mock.Mock() - self.test_context.nfvi_obj.setup_ovs_bridge = mock.Mock() - self.test_context.nfvi_obj.add_oflows = mock.Mock() - - result = self.test_context.nfvi_obj.setup_ovs_context( - PORTS, - NIC_DETAILS, - DRIVER) - print("{0}".format(result)) - self.assertIsNone(self.test_context.deploy()) - - def test__deploy_ovs_notfirsttime(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK) - } - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'password', - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - MYOVS = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'password', - 'flow': ['ovs-ofctl add-flow br0 in_port=1,action=output:3', - 'ovs-ofctl add-flow br0 in_port=3,action=output:1' - 'ovs-ofctl add-flow br0 in_port=4,action=output:2' - 'ovs-ofctl add-flow br0 in_port=2,action=output:4'], - 'phy_ports': ['0000:06:00.0', '0000:06:00.1']}] - - self.test_context.vm_deploy = True - self.test_context.get_nfvi_obj = mock.MagicMock() - self.test_context.init(attrs) - self.test_context.ovs = MYOVS - self.test_context.nfvi_obj.ssh_remote_machine = mock.Mock() - self.test_context.nfvi_obj.first_run = False - 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'}, - 'vports_mac': ['00:00:00:00:00:05', '00:00:00:00:00:06'], - 'pci': ['0000:06:00.0', '0000:06:00.1'], - 'phy_driver': 'i40e'} - DRIVER = 'i40e' - - self.test_context.nfvi_obj.setup_ovs(PORTS) - self.test_context.nfvi_obj.start_ovs_serverswitch() - self.test_context.nfvi_obj.setup_ovs_bridge() - self.test_context.nfvi_obj.add_oflows() - - result = self.test_context.nfvi_obj.setup_ovs_context( - PORTS, - NIC_DETAILS, - DRIVER) - print("{0}".format(result)) - self.assertIsNone(self.test_context.deploy()) - - def test_undeploy_sriov(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - 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.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - '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_undeploy_ovs(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - attrs = { - 'name': 'foo', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK) - } - - self.test_context.nfvi_node = [{ - 'name': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - '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_sriov(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - with mock.patch('yardstick.benchmark.contexts.standalone.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.223.197.140', - 'role': 'Sriov', - 'user': 'root', - 'images': '/var/lib/libvirt/images/ubuntu1.img', - 'phy_driver': 'i40e', - 'password': 'intel123', - '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_nfvi_obj_ovs(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - with mock.patch('yardstick.benchmark.contexts.standalone.ovsdpdk'): - attrs = { - 'name': 'ovs', - 'file': self._get_file_abspath(self.NODES_SAMPLE_OVSDPDK) - } - 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': 'ovs', - 'vports_mac': ['00:00:00:00:00:03', '00:00:00:00:00:04'], - 'ip': '10.223.197.140', - 'role': 'Ovsdpdk', - 'user': 'root', - 'vpath': '/usr/local/', - '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=ovsdpdk.Ovsdpdk) - self.assertIsNotNone(self.test_context.get_nfvi_obj()) - - def test_get_context_impl_correct_obj(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - with mock.patch.dict("sys.modules", MOCKS): - self.assertIsNotNone(self.test_context.get_context_impl('Sriov')) - - def test_get_context_impl_wrong_obj(self, mock_sriov_time, mock_standlalone_time, - mock_ovsdpdk_time): - 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) - return file_path - - def test__get_network(self, mock_sriov_time, mock_standlalone_time, mock_ovsdpdk_time): - network1 = { - 'name': 'net_1', - 'vld_id': 'vld111', - 'segmentation_id': 'seg54', - 'network_type': 'type_a', - 'physical_network': 'phys', - } - network2 = { - 'name': 'net_2', - 'vld_id': 'vld999', - } - self.test_context.networks = { - 'a': network1, - 'b': network2, - } - - attr_name = None - self.assertIsNone(self.test_context._get_network(attr_name)) - - attr_name = {} - self.assertIsNone(self.test_context._get_network(attr_name)) - - attr_name = {'vld_id': 'vld777'} - self.assertIsNone(self.test_context._get_network(attr_name)) - - attr_name = 'vld777' - self.assertIsNone(self.test_context._get_network(attr_name)) - - attr_name = {'vld_id': 'vld999'} - expected = { - "name": 'net_2', - "vld_id": 'vld999', - "segmentation_id": None, - "network_type": None, - "physical_network": None, - } - result = self.test_context._get_network(attr_name) - self.assertDictEqual(result, expected) - - attr_name = 'a' - 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/standalone/__init__.py b/yardstick/benchmark/contexts/standalone/__init__.py index f0ef1d560..e69de29bb 100644 --- a/yardstick/benchmark/contexts/standalone/__init__.py +++ b/yardstick/benchmark/contexts/standalone/__init__.py @@ -1,211 +0,0 @@ -# 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. -"""This module handle non managed standalone virtualization node.""" - -from __future__ import absolute_import -import logging -import os -import errno -import collections -import time - -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 -from yardstick.common.yaml_loader import yaml_load - -LOG = logging.getLogger(__name__) - - -class StandaloneContext(Context): - """ This class handles standalone nodes - VM running on Non-Managed NFVi - Configuration: vswitch, ovs, ovs-dpdk, sr-iov, linuxbridge - """ - - __context_type__ = "Standalone" - - def __init__(self): - self.name = None - self.file_path = None - self.nodes = [] - self.networks = {} - self.nfvi_node = [] - self.nfvi_obj = None - self.attrs = {} - super(StandaloneContext, self).__init__() - - def read_config_file(self): - """Read from config file""" - - with open(self.file_path) as stream: - LOG.info("Parsing pod file: %s", self.file_path) - 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""" - - self.name = attrs["name"] - self.file_path = file_path = attrs.get("file", "pod.yaml") - - try: - cfg = self.read_config_file() - except IOError as io_error: - if io_error.errno != errno.ENOENT: - raise - self.file_path = os.path.join(YARDSTICK_ROOT_PATH, file_path) - cfg = self.read_config_file() - - self.vm_deploy = attrs.get("vm_deploy", True) - self.nodes.extend([node for node in cfg["nodes"] - if str(node["role"]) != "Sriov" and - str(node["role"]) != "Ovsdpdk"]) - 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"]) == "Ovsdpdk": - self.nfvi_node.extend([node for node in cfg["nodes"] - if str(node["role"]) == "Ovsdpdk"]) - LOG.info("{0}".format(node["role"])) - else: - LOG.debug("Node role is other than SRIOV and OVS") - self.nfvi_obj = self.get_nfvi_obj() - self.attrs = attrs - # add optional static network definition - self.networks.update(cfg.get("networks", {})) - 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) - - def deploy(self): - """don't need to deploy""" - - # Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config. - if not self.vm_deploy: - return - - # 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)) - - if self.nfvi_node[0]["role"] == "Sriov": - self.nfvi_obj.setup_sriov_context( - self.nfvi_obj.sriov[0]['phy_ports'], - nic_details, - self.nfvi_obj.sriov[0]['phy_driver']) - if self.nfvi_node[0]["role"] == "Ovsdpdk": - self.nfvi_obj.setup_ovs(self.nfvi_obj.ovs[0]["phy_ports"]) - self.nfvi_obj.start_ovs_serverswitch() - time.sleep(5) - self.nfvi_obj.setup_ovs_bridge() - self.nfvi_obj.add_oflows() - self.nfvi_obj.setup_ovs_context( - self.nfvi_obj.ovs[0]['phy_ports'], - nic_details, - self.nfvi_obj.ovs[0]['phy_driver']) - pass - - def undeploy(self): - """don't need to undeploy""" - - if not self.vm_deploy: - return - # Todo: NFVi undeploy (sriov, vswitch, ovs etc) based on the config. - # 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 - - Keyword arguments: - attr_name -- A name for a server listed in nodes config file - """ - node_name, name = self.split_name(attr_name) - if name is None or self.name != name: - return None - - matching_nodes = (n for n in self.nodes if n["name"] == node_name) - try: - # A clone is created in order to avoid affecting the - # original one. - node = dict(next(matching_nodes)) - except StopIteration: - return None - - try: - duplicate = next(matching_nodes) - except StopIteration: - pass - else: - raise ValueError("Duplicate nodes!!! Nodes: %s %s", - (node, duplicate)) - - node["name"] = attr_name - return node - - def _get_network(self, attr_name): - if not isinstance(attr_name, collections.Mapping): - network = self.networks.get(attr_name) - - else: - # Don't generalize too much Just support vld_id - vld_id = attr_name.get('vld_id', {}) - # for standalone context networks are dicts - iter1 = (n for n in self.networks.values() if n.get('vld_id') == vld_id) - network = next(iter1, None) - - if network is None: - return None - - result = { - # name is required - "name": network["name"], - "vld_id": network.get("vld_id"), - "segmentation_id": network.get("segmentation_id"), - "network_type": network.get("network_type"), - "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) diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py new file mode 100644 index 000000000..4491660e0 --- /dev/null +++ b/yardstick/benchmark/contexts/standalone/model.py @@ -0,0 +1,493 @@ +# 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 re +import time +import glob +import uuid +import random +import logging +import itertools +import errno + +from netaddr import IPNetwork +import xml.etree.ElementTree as ET + +from yardstick import ssh +from yardstick.common.constants import YARDSTICK_ROOT_PATH +from yardstick.common.yaml_loader import yaml_load +from yardstick.network_services.utils import PciAddress +from yardstick.common.utils import write_file + +LOG = logging.getLogger(__name__) + +VM_TEMPLATE = """ +<domain type="kvm"> + <name>{vm_name}</name> + <uuid>{random_uuid}</uuid> + <memory unit="MB">{memory}</memory> + <currentMemory unit="MB">{memory}</currentMemory> + <memoryBacking> + <hugepages /> + </memoryBacking> + <vcpu placement="static">{vcpu}</vcpu> + <os> + <type arch="x86_64" machine="pc-i440fx-utopic">hvm</type> + <boot dev="hd" /> + </os> + <features> + <acpi /> + <apic /> + <pae /> + </features> + <cpu mode='host-passthrough'> + <topology cores="{cpu}" sockets="{socket}" threads="{threads}" /> + <numa> + <cell id='0' cpus='{numa_cpus}' memory='{memory}' unit='MB' memAccess='shared'/> + </numa> + </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" /> + </disk> + <graphics autoport="yes" listen="0.0.0.0" port="-1" type="vnc" /> + <interface type="bridge"> + <mac address='{mac_addr}'/> + <source bridge="br-int" /> + <model type='virtio'/> + </interface> + </devices> +</domain> +""" +WAIT_FOR_BOOT = 30 + + +class Libvirt(object): + """ This class handles all the libvirt updates to lauch VM + """ + + @staticmethod + def check_if_vm_exists_and_delete(vm_name, connection): + cmd_template = "virsh list --name | grep -i %s" + status = connection.execute(cmd_template % vm_name)[0] + if status == 0: + LOG.info("VM '%s' is already present.. destroying" % vm_name) + connection.execute("virsh destroy %s" % vm_name) + + @staticmethod + def virsh_create_vm(connection, cfg): + err = connection.execute("virsh create %s" % cfg)[0] + LOG.info("VM create status: %s" % (err)) + + @staticmethod + def virsh_destroy_vm(vm_name, connection): + connection.execute("virsh destroy %s" % vm_name) + + @staticmethod + def add_interface_address(interface, pci_address): + vm_pci = ET.SubElement(interface, 'address') + vm_pci.set('type', 'pci') + vm_pci.set('domain', '0x%s' % pci_address.domain) + vm_pci.set('bus', '0x%s' % pci_address.bus) + vm_pci.set('slot', '0x%s' % pci_address.slot) + vm_pci.set('function', '0x%s' % pci_address.function) + return vm_pci + + @classmethod + def add_ovs_interface(cls, vpath, port_num, vpci, vports_mac, xml): + vhost_path = '{0}/var/run/openvswitch/dpdkvhostuser{1}' + root = ET.parse(xml) + pci_address = PciAddress.parse_address(vpci.strip(), multi_line=True) + device = root.find('devices') + + interface = ET.SubElement(device, 'interface') + interface.set('type', 'vhostuser') + mac = ET.SubElement(interface, 'mac') + mac.set('address', vports_mac) + + source = ET.SubElement(interface, 'source') + source.set('type', 'unix') + source.set('path', vhost_path.format(vpath, port_num)) + source.set('mode', 'client') + + model = ET.SubElement(interface, 'model') + model.set('type', 'virtio') + + driver = ET.SubElement(interface, 'driver') + driver.set('queues', '4') + + host = ET.SubElement(driver, 'host') + host.set('mrg_rxbuf', 'off') + + cls.add_interface_address(interface, pci_address) + + root.write(xml) + + @classmethod + def add_sriov_interfaces(cls, vm_pci, vf_pci, vfmac, xml): + root = ET.parse(xml) + pci_address = PciAddress.parse_address(vf_pci.strip(), multi_line=True) + 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(pci_address.bus)) + addr.set('function', "{0}".format(pci_address.function)) + addr.set('slot', "0x{0}".format(pci_address.slot)) + addr.set('type', "pci") + + pci_vm_address = PciAddress.parse_address(vm_pci.strip(), multi_line=True) + cls.add_interface_address(interface, pci_vm_address) + + root.write(xml) + + @staticmethod + def create_snapshot_qemu(connection, index, vm_image): + # build snapshot image + image = "/var/lib/libvirt/images/%s.qcow2" % index + connection.execute("rm %s" % image) + qemu_template = "qemu-img create -f qcow2 -o backing_file=%s %s" + connection.execute(qemu_template % (vm_image, image)) + + return image + + @classmethod + def build_vm_xml(cls, connection, flavor, cfg, vm_name, index): + memory = flavor.get('ram', '4096') + extra_spec = flavor.get('extra_specs', {}) + cpu = extra_spec.get('hw:cpu_cores', '2') + socket = extra_spec.get('hw:cpu_sockets', '1') + threads = extra_spec.get('hw:cpu_threads', '2') + vcpu = int(cpu) * int(threads) + numa_cpus = '0-%s' % (vcpu - 1) + + mac = StandaloneContextHelper.get_mac_address(0x00) + image = cls.create_snapshot_qemu(connection, index, + flavor.get("images", None)) + vm_xml = VM_TEMPLATE.format( + vm_name=vm_name, + random_uuid=uuid.uuid4(), + mac_addr=mac, + memory=memory, vcpu=vcpu, cpu=cpu, + numa_cpus=numa_cpus, + socket=socket, threads=threads, + vm_image=image) + + write_file(cfg, vm_xml) + + return [vcpu, mac] + + @staticmethod + def split_cpu_list(cpu_list): + if not cpu_list: + return [] + + 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)) + + @classmethod + def get_numa_nodes(cls): + 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] = cls.split_cpu_list(cpulist) + LOG.info("nodes: {0}".format(nodes)) + return nodes + + @staticmethod + def update_interrupts_hugepages_perf(connection): + connection.execute("echo 1 > /sys/module/kvm/parameters/allow_unsafe_assigned_interrupts") + connection.execute("echo never > /sys/kernel/mm/transparent_hugepage/enabled") + + @classmethod + def pin_vcpu_for_perf(cls, connection, vm_name, cpu): + nodes = cls.get_numa_nodes() + num_nodes = len(nodes) + vcpi_pin_template = "virsh vcpupin {0} {1} {2}" + for i in range(0, int(cpu)): + core = nodes[str(num_nodes - 1)][i % len(nodes[str(num_nodes - 1)])] + connection.execute(vcpi_pin_template.format(vm_name, i, core)) + cls.update_interrupts_hugepages_perf(connection) + + +class StandaloneContextHelper(object): + """ This class handles all the common code for standalone + """ + def __init__(self): + self.file_path = None + super(StandaloneContextHelper, self).__init__() + + @staticmethod + def install_req_libs(connection, extra_pkgs=[]): + pkgs = ["qemu-kvm", "libvirt-bin", "bridge-utils", "numactl", "fping"] + pkgs.extend(extra_pkgs) + cmd_template = "dpkg-query -W --showformat='${Status}\\n' \"%s\"|grep 'ok installed'" + for pkg in pkgs: + if connection.execute(cmd_template % pkg)[0]: + connection.execute("apt-get update") + connection.execute("apt-get -y install %s" % pkg) + else: + # all installed + return + + @staticmethod + def get_kernel_module(connection, pci, driver): + if not driver: + out = connection.execute("lspci -k -s %s" % pci)[1] + driver = out.split("Kernel modules:").pop().strip() + return driver + + @classmethod + def get_nic_details(cls, connection, networks, dpdk_nic_bind): + for key, ports in networks.items(): + if key == "mgmt": + continue + + phy_ports = ports['phy_port'] + phy_driver = ports.get('phy_driver', None) + driver = cls.get_kernel_module(connection, phy_ports, phy_driver) + + # Make sure that ports are bound to kernel drivers e.g. i40e/ixgbe + bind_cmd = "{dpdk_nic_bind} --force -b {driver} {port}" + lshw_cmd = "lshw -c network -businfo | grep '{port}'" + link_show_cmd = "ip -s link show {interface}" + + cmd = bind_cmd.format(dpdk_nic_bind=dpdk_nic_bind, + driver=driver, port=ports['phy_port']) + connection.execute(cmd) + + out = connection.execute(lshw_cmd.format(port=phy_ports))[1] + interface = out.split()[1] + + connection.execute(link_show_cmd.format(interface=interface)) + + ports.update({ + 'interface': str(interface), + 'driver': driver + }) + LOG.info("{0}".format(networks)) + + return networks + + @staticmethod + def get_virtual_devices(connection, pci): + cmd = "cat /sys/bus/pci/devices/{0}/virtfn0/uevent" + output = connection.execute(cmd.format(pci))[1] + + pattern = "PCI_SLOT_NAME=({})".format(PciAddress.PCI_PATTERN_STR) + m = re.search(pattern, output, re.MULTILINE) + + pf_vfs = {} + if m: + pf_vfs = {pci: m.group(1).rstrip()} + + LOG.info("pf_vfs:\n%s", pf_vfs) + + return pf_vfs + + def read_config_file(self): + """Read from config file""" + + with open(self.file_path) as stream: + LOG.info("Parsing pod file: %s", self.file_path) + cfg = yaml_load(stream) + return cfg + + def parse_pod_file(self, file_path, nfvi_role='Sriov'): + self.file_path = file_path + nodes = [] + nfvi_host = [] + try: + cfg = self.read_config_file() + except IOError as io_error: + if io_error.errno != errno.ENOENT: + raise + self.file_path = os.path.join(YARDSTICK_ROOT_PATH, file_path) + cfg = self.read_config_file() + + nodes.extend([node for node in cfg["nodes"] if str(node["role"]) != nfvi_role]) + nfvi_host.extend([node for node in cfg["nodes"] if str(node["role"]) == nfvi_role]) + if not nfvi_host: + raise("Node role is other than SRIOV") + + host_mgmt = {'user': nfvi_host[0]['user'], + 'ip': str(IPNetwork(nfvi_host[0]['ip']).ip), + 'password': nfvi_host[0]['password'], + 'ssh_port': nfvi_host[0].get('ssh_port', 22), + 'key_filename': nfvi_host[0].get('key_filename')} + + return [nodes, nfvi_host, host_mgmt] + + @staticmethod + def get_mac_address(end=0x7f): + mac = [0x52, 0x54, 0x00, + random.randint(0x00, end), + random.randint(0x00, 0xff), + random.randint(0x00, 0xff)] + mac_address = ':'.join('%02x' % x for x in mac) + return mac_address + + @staticmethod + def get_mgmt_ip(connection, mac, cidr, node): + mgmtip = None + times = 10 + while not mgmtip and times: + connection.execute("fping -c 1 -g %s > /dev/null 2>&1" % cidr) + out = connection.execute("ip neighbor | grep '%s'" % mac)[1] + LOG.info("fping -c 1 -g %s > /dev/null 2>&1" % cidr) + if out.strip(): + mgmtip = str(out.split(" ")[0]).strip() + client = ssh.SSH.from_node(node, overrides={"ip": mgmtip}) + client.wait() + break + + time.sleep(WAIT_FOR_BOOT) # FixMe: How to find if VM is booted? + times = times - 1 + return mgmtip + + @classmethod + def wait_for_vnfs_to_start(cls, connection, servers, nodes): + for node in nodes: + vnf = servers[node["name"]] + mgmtip = vnf["network_ports"]["mgmt"]["cidr"] + ip = cls.get_mgmt_ip(connection, node["mac"], mgmtip, node) + if ip: + node["ip"] = ip + return nodes + + +class Server(object): + """ This class handles geting vnf nodes + """ + + @staticmethod + def build_vnf_interfaces(vnf, ports): + interfaces = {} + index = 0 + + for key, vfs in vnf["network_ports"].items(): + if key == "mgmt": + mgmtip = str(IPNetwork(vfs['cidr']).ip) + continue + + vf = ports[vfs[0]] + ip = IPNetwork(vf['cidr']) + interfaces.update({ + key: { + 'vpci': vf['vpci'], + 'driver': "%svf" % vf['driver'], + 'local_mac': vf['mac'], + 'dpdk_port_num': index, + 'local_ip': str(ip.ip), + 'netmask': str(ip.netmask) + }, + }) + index = index + 1 + + return mgmtip, interfaces + + @classmethod + def generate_vnf_instance(cls, flavor, ports, ip, key, vnf, mac): + mgmtip, interfaces = cls.build_vnf_interfaces(vnf, ports) + + result = { + "ip": mgmtip, + "mac": mac, + "host": ip, + "user": flavor.get('user', 'root'), + "interfaces": interfaces, + "routing_table": [], + # empty IPv6 routing table + "nd_route_tbl": [], + "name": key, "role": key + } + + try: + result['key_filename'] = flavor['key_filename'] + except KeyError: + pass + + try: + result['password'] = flavor['password'] + except KeyError: + pass + LOG.info(result) + return result + + +class OvsDeploy(object): + """ This class handles deploy of ovs dpdk + Configuration: ovs_dpdk + """ + + OVS_DEPLOY_SCRIPT = "ovs_deploy.bash" + + def __init__(self, connection, bin_path, ovs_properties): + self.connection = connection + self.bin_path = bin_path + self.ovs_properties = ovs_properties + + def prerequisite(self): + pkgs = ["git", "build-essential", "pkg-config", "automake", + "autotools-dev", "libltdl-dev", "cmake", "libnuma-dev", + "libpcap-dev"] + StandaloneContextHelper.install_req_libs(self.connection, pkgs) + + def ovs_deploy(self): + ovs_deploy = os.path.join(YARDSTICK_ROOT_PATH, + "yardstick/resources/scripts/install/", + self.OVS_DEPLOY_SCRIPT) + if os.path.isfile(ovs_deploy): + self.prerequisite() + remote_ovs_deploy = os.path.join(self.bin_path, self.OVS_DEPLOY_SCRIPT) + LOG.info(remote_ovs_deploy) + self.connection.put(ovs_deploy, remote_ovs_deploy) + + http_proxy = os.environ.get('http_proxy', '') + ovs_details = self.ovs_properties.get("version", {}) + ovs = ovs_details.get("ovs", "2.6.0") + dpdk = ovs_details.get("dpdk", "16.11.1") + + cmd = "sudo -E %s --ovs='%s' --dpdk='%s' -p='%s'" % (remote_ovs_deploy, + ovs, dpdk, http_proxy) + self.connection.execute(cmd) diff --git a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py new file mode 100644 index 000000000..833c3fb80 --- /dev/null +++ b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py @@ -0,0 +1,383 @@ +# 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 logging +import collections +import time + +from collections import OrderedDict + +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.base import Context +from yardstick.benchmark.contexts.standalone.model import Libvirt +from yardstick.benchmark.contexts.standalone.model import StandaloneContextHelper +from yardstick.benchmark.contexts.standalone.model import Server +from yardstick.benchmark.contexts.standalone.model import OvsDeploy +from yardstick.network_services.utils import PciAddress + +LOG = logging.getLogger(__name__) + + +class OvsDpdkContext(Context): + """ This class handles OVS standalone nodes - VM running on Non-Managed NFVi + Configuration: ovs_dpdk + """ + + __context_type__ = "StandaloneOvsDpdk" + + SUPPORTED_OVS_TO_DPDK_MAP = { + '2.6.0': '16.07.1', + '2.6.1': '16.07.2', + '2.7.0': '16.11.1', + '2.7.1': '16.11.2', + '2.7.2': '16.11.3', + '2.8.0': '17.05.2' + } + + DEFAULT_OVS = '2.6.0' + + PKILL_TEMPLATE = "pkill %s %s" + + def __init__(self): + self.file_path = None + self.sriov = [] + self.first_run = True + self.dpdk_nic_bind = "" + self.vm_names = [] + self.name = None + self.nfvi_host = [] + self.nodes = [] + self.networks = {} + self.attrs = {} + self.vm_flavor = None + self.servers = None + self.helper = StandaloneContextHelper() + self.vnf_node = Server() + self.ovs_properties = {} + self.wait_for_vswitchd = 10 + super(OvsDpdkContext, self).__init__() + + def init(self, attrs): + """initializes itself from the supplied arguments""" + + self.name = attrs["name"] + self.file_path = attrs.get("file", "pod.yaml") + + self.nodes, self.nfvi_host, self.host_mgmt = \ + self.helper.parse_pod_file(self.file_path, 'OvsDpdk') + + self.attrs = attrs + self.vm_flavor = attrs.get('flavor', {}) + self.servers = attrs.get('servers', {}) + self.vm_deploy = attrs.get("vm_deploy", True) + self.ovs_properties = attrs.get('ovs_properties', {}) + # add optional static network definition + self.networks = attrs.get("networks", {}) + + LOG.debug("Nodes: %r", self.nodes) + LOG.debug("NFVi Node: %r", self.nfvi_host) + LOG.debug("Networks: %r", self.networks) + + def setup_ovs(self): + vpath = self.ovs_properties.get("vpath", "/usr/local") + xargs_kill_cmd = self.PKILL_TEMPLATE % ('-9', 'ovs') + + create_from = os.path.join(vpath, 'etc/openvswitch/conf.db') + create_to = os.path.join(vpath, 'share/openvswitch/vswitch.ovsschema') + + cmd_list = [ + "chmod 0666 /dev/vfio/*", + "chmod a+x /dev/vfio", + "pkill -9 ovs", + xargs_kill_cmd, + "killall -r 'ovs*'", + "mkdir -p {0}/etc/openvswitch".format(vpath), + "mkdir -p {0}/var/run/openvswitch".format(vpath), + "rm {0}/etc/openvswitch/conf.db".format(vpath), + "ovsdb-tool create {0} {1}".format(create_from, create_to), + "modprobe vfio-pci", + "chmod a+x /dev/vfio", + "chmod 0666 /dev/vfio/*", + ] + for cmd in cmd_list: + self.connection.execute(cmd) + bind_cmd = "{dpdk_nic_bind} --force -b {driver} {port}" + phy_driver = "vfio-pci" + for key, port in self.networks.items(): + vpci = port.get("phy_port") + self.connection.execute(bind_cmd.format(dpdk_nic_bind=self.dpdk_nic_bind, + driver=phy_driver, port=vpci)) + + def start_ovs_serverswitch(self): + vpath = self.ovs_properties.get("vpath") + pmd_nums = int(self.ovs_properties.get("pmd_threads", 2)) + ovs_sock_path = '/var/run/openvswitch/db.sock' + log_path = '/var/log/openvswitch/ovs-vswitchd.log' + + pmd_mask = hex(sum(2 ** num for num in range(pmd_nums)) << 1) + socket0 = self.ovs_properties.get("ram", {}).get("socket_0", "2048") + socket1 = self.ovs_properties.get("ram", {}).get("socket_1", "2048") + + ovs_other_config = "ovs-vsctl {0}set Open_vSwitch . other_config:{1}" + detach_cmd = "ovs-vswitchd unix:{0}{1} --pidfile --detach --log-file={2}" + + cmd_list = [ + "mkdir -p /usr/local/var/run/openvswitch", + "ovsdb-server --remote=punix:/{0}/{1} --pidfile --detach".format(vpath, + ovs_sock_path), + ovs_other_config.format("--no-wait ", "dpdk-init=true"), + ovs_other_config.format("--no-wait ", "dpdk-socket-mem='%s,%s'" % (socket0, socket1)), + detach_cmd.format(vpath, ovs_sock_path, log_path), + ovs_other_config.format("", "pmd-cpu-mask=%s" % pmd_mask), + ] + + for cmd in cmd_list: + LOG.info(cmd) + self.connection.execute(cmd) + time.sleep(self.wait_for_vswitchd) + + def setup_ovs_bridge_add_flows(self): + dpdk_args = "" + dpdk_list = [] + vpath = self.ovs_properties.get("vpath", "/usr/local") + version = self.ovs_properties.get('version', {}) + ovs_ver = [int(x) for x in version.get('ovs', self.DEFAULT_OVS).split('.')] + ovs_add_port = \ + "ovs-vsctl add-port {br} {port} -- set Interface {port} type={type_}{dpdk_args}" + ovs_add_queue = "ovs-vsctl set Interface {port} options:n_rxq={queue}" + chmod_vpath = "chmod 0777 {0}/var/run/openvswitch/dpdkvhostuser*" + + cmd_dpdk_list = [ + "ovs-vsctl del-br br0", + "rm -rf /usr/local/var/run/openvswitch/dpdkvhostuser*", + "ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev", + ] + + ordered_network = OrderedDict(self.networks) + for index, (key, vnf) in enumerate(ordered_network.items()): + if ovs_ver >= [2, 7, 0]: + dpdk_args = " options:dpdk-devargs=%s" % vnf.get("phy_port") + dpdk_list.append(ovs_add_port.format(br='br0', port='dpdk%s' % vnf.get("port_num", 0), + type_='dpdk', dpdk_args=dpdk_args)) + dpdk_list.append(ovs_add_queue.format(port='dpdk%s' % vnf.get("port_num", 0), + queue=self.ovs_properties.get("queues", 4))) + + # Sorting the array to make sure we execute dpdk0... in the order + list.sort(dpdk_list) + cmd_dpdk_list.extend(dpdk_list) + + # Need to do two for loop to maintain the dpdk/vhost ports. + for index, _ in enumerate(ordered_network): + cmd_dpdk_list.append(ovs_add_port.format(br='br0', port='dpdkvhostuser%s' % index, + type_='dpdkvhostuser', dpdk_args="")) + + for cmd in cmd_dpdk_list: + LOG.info(cmd) + self.connection.execute(cmd) + + # Fixme: add flows code + ovs_flow = "ovs-ofctl add-flow br0 in_port=%s,action=output:%s" + + network_count = len(ordered_network) + 1 + for in_port, out_port in zip(range(1, network_count), + range(network_count, network_count * 2)): + self.connection.execute(ovs_flow % (in_port, out_port)) + self.connection.execute(ovs_flow % (out_port, in_port)) + + self.connection.execute(chmod_vpath.format(vpath)) + + def cleanup_ovs_dpdk_env(self): + self.connection.execute("ovs-vsctl del-br br0") + self.connection.execute("pkill -9 ovs") + + def check_ovs_dpdk_env(self): + self.cleanup_ovs_dpdk_env() + + version = self.ovs_properties.get("version", {}) + ovs_ver = version.get("ovs", self.DEFAULT_OVS) + dpdk_ver = version.get("dpdk", "16.07.2").split('.') + + supported_version = self.SUPPORTED_OVS_TO_DPDK_MAP.get(ovs_ver, None) + if supported_version is None or supported_version.split('.')[:2] != dpdk_ver[:2]: + raise Exception("Unsupported ovs '{}'. Please check the config...".format(ovs_ver)) + + status = self.connection.execute("ovs-vsctl -V | grep -i '%s'" % ovs_ver)[0] + if status: + deploy = OvsDeploy(self.connection, + get_nsb_option("bin_path"), + self.ovs_properties) + deploy.ovs_deploy() + + def deploy(self): + """don't need to deploy""" + + # Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config. + if not self.vm_deploy: + return + + self.connection = ssh.SSH.from_node(self.host_mgmt) + self.dpdk_nic_bind = provision_tool( + self.connection, + os.path.join(get_nsb_option("bin_path"), "dpdk-devbind.py")) + + # Check dpdk/ovs version, if not present install + self.check_ovs_dpdk_env() + # Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config. + StandaloneContextHelper.install_req_libs(self.connection) + self.networks = StandaloneContextHelper.get_nic_details(self.connection, + self.networks, + self.dpdk_nic_bind) + + self.setup_ovs() + self.start_ovs_serverswitch() + self.setup_ovs_bridge_add_flows() + self.nodes = self.setup_ovs_dpdk_context() + LOG.debug("Waiting for VM to come up...") + self.nodes = StandaloneContextHelper.wait_for_vnfs_to_start(self.connection, + self.servers, + self.nodes) + + def undeploy(self): + + if not self.vm_deploy: + return + + # Cleanup the ovs installation... + self.cleanup_ovs_dpdk_env() + + # Bind nics back to kernel + bind_cmd = "{dpdk_nic_bind} --force -b {driver} {port}" + for key, port in self.networks.items(): + vpci = port.get("phy_port") + phy_driver = port.get("driver") + self.connection.execute(bind_cmd.format(dpdk_nic_bind=self.dpdk_nic_bind, + driver=phy_driver, port=vpci)) + + # Todo: NFVi undeploy (sriov, vswitch, ovs etc) based on the config. + for vm in self.vm_names: + Libvirt.check_if_vm_exists_and_delete(vm, self.connection) + + def _get_server(self, attr_name): + """lookup server info by name from context + + Keyword arguments: + attr_name -- A name for a server listed in nodes config file + """ + node_name, name = self.split_name(attr_name) + if name is None or self.name != name: + return None + + matching_nodes = (n for n in self.nodes if n["name"] == node_name) + try: + # A clone is created in order to avoid affecting the + # original one. + node = dict(next(matching_nodes)) + except StopIteration: + return None + + try: + duplicate = next(matching_nodes) + except StopIteration: + pass + else: + raise ValueError("Duplicate nodes!!! Nodes: %s %s", + (node, duplicate)) + + node["name"] = attr_name + return node + + def _get_network(self, attr_name): + if not isinstance(attr_name, collections.Mapping): + network = self.networks.get(attr_name) + + else: + # Don't generalize too much Just support vld_id + vld_id = attr_name.get('vld_id', {}) + # for standalone context networks are dicts + iter1 = (n for n in self.networks.values() if n.get('vld_id') == vld_id) + network = next(iter1, None) + + if network is None: + return None + + result = { + # name is required + "name": network["name"], + "vld_id": network.get("vld_id"), + "segmentation_id": network.get("segmentation_id"), + "network_type": network.get("network_type"), + "physical_network": network.get("physical_network"), + } + return result + + def configure_nics_for_ovs_dpdk(self): + portlist = OrderedDict(self.networks) + for key, ports in portlist.items(): + mac = StandaloneContextHelper.get_mac_address() + portlist[key].update({'mac': mac}) + self.networks = portlist + LOG.info("Ports %s" % self.networks) + + def _enable_interfaces(self, index, vfs, cfg): + vpath = self.ovs_properties.get("vpath", "/usr/local") + vf = self.networks[vfs[0]] + port_num = vf.get('port_num', 0) + vpci = PciAddress.parse_address(vf['vpci'].strip(), multi_line=True) + # Generate the vpci for the interfaces + slot = index + port_num + 10 + vf['vpci'] = \ + "{}:{}:{:02x}.{}".format(vpci.domain, vpci.bus, slot, vpci.function) + Libvirt.add_ovs_interface(vpath, port_num, vf['vpci'], vf['mac'], str(cfg)) + + def setup_ovs_dpdk_context(self): + nodes = [] + + self.configure_nics_for_ovs_dpdk() + + for index, (key, vnf) in enumerate(OrderedDict(self.servers).items()): + cfg = '/tmp/vm_ovs_%d.xml' % index + vm_name = "vm_%d" % index + + # 1. Check and delete VM if already exists + Libvirt.check_if_vm_exists_and_delete(vm_name, self.connection) + + vcpu, mac = Libvirt.build_vm_xml(self.connection, self.vm_flavor, cfg, vm_name, index) + # 2: Cleanup already available VMs + for idx, (vkey, vfs) in enumerate(OrderedDict(vnf["network_ports"]).items()): + if vkey == "mgmt": + continue + self._enable_interfaces(index, vfs, cfg) + + # copy xml to target... + self.connection.put(cfg, cfg) + + # FIXME: launch through libvirt + LOG.info("virsh create ...") + Libvirt.virsh_create_vm(self.connection, cfg) + + # 5: Tunning for better performace + Libvirt.pin_vcpu_for_perf(self.connection, vm_name, vcpu) + self.vm_names.append(vm_name) + + # build vnf node details + nodes.append(self.vnf_node.generate_vnf_instance(self.vm_flavor, + self.networks, + self.host_mgmt.get('ip'), + key, vnf, mac)) + + return nodes diff --git a/yardstick/benchmark/contexts/standalone/ovsdpdk.py b/yardstick/benchmark/contexts/standalone/ovsdpdk.py deleted file mode 100644 index cf5529d89..000000000 --- a/yardstick/benchmark/contexts/standalone/ovsdpdk.py +++ /dev/null @@ -1,369 +0,0 @@ -# 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 time -import glob -import itertools -import logging -from yardstick import ssh -from yardstick.benchmark.contexts.standalone import StandaloneContext - -BIN_PATH = "/opt/isb_bin/" -DPDK_NIC_BIND = "dpdk_nic_bind.py" - -log = logging.getLogger(__name__) - -VM_TEMPLATE = """ -<domain type='kvm'> - <name>vm1</name> - <uuid>18230c0c-635d-4c50-b2dc-a213d30acb34</uuid> - <memory unit='KiB'>20971520</memory> - <currentMemory unit="KiB">20971520</currentMemory> - <memoryBacking> - <hugepages/> - </memoryBacking> - <vcpu placement='static'>20</vcpu> - <os> - <type arch='x86_64' machine='pc'>hvm</type> - <boot dev='hd'/> - </os> - <features> - <acpi/> - <apic/> - </features> - <cpu match="exact" mode='host-model'> - <model fallback='allow'/> - <topology sockets='1' cores='10' threads='2'/> - </cpu> - <on_poweroff>destroy</on_poweroff> - <on_reboot>restart</on_reboot> - <on_crash>destroy</on_crash> - <devices> - <emulator>/usr/bin/qemu-system-x86_64</emulator> - <disk type='file' device='disk'> - <driver name='qemu' type='qcow2' cache='none'/> - <source file="{vm_image}"/> - <target dev='vda' bus='virtio'/> - <address bus="0x00" domain="0x0000" - function="0x0" slot="0x04" type="pci" /> - </disk> - <!--disk type='dir' device='disk'> - <driver name='qemu' type='fat'/> - <source dir='/opt/isb_bin/dpdk'/> - <target dev='vdb' bus='virtio'/> - <readonly/> - </disk--> - <interface type="bridge"> - <mac address="00:00:00:ab:cd:ef" /> - <source bridge="br-int" /> - </interface> - <interface type='vhostuser'> - <mac address='00:00:00:00:00:01'/> - <source type='unix' path='/usr/local/var/run/openvswitch/dpdkvhostuser0' mode='client'/> - <model type='virtio'/> - <driver queues='4'> - <host mrg_rxbuf='off'/> - </driver> - </interface> - <interface type='vhostuser'> - <mac address='00:00:00:00:00:02'/> - <source type='unix' path='/usr/local/var/run/openvswitch/dpdkvhostuser1' mode='client'/> - <model type='virtio'/> - <driver queues='4'> - <host mrg_rxbuf='off'/> - </driver> - </interface> - <serial type='pty'> - <target port='0'/> - </serial> - <console type='pty'> - <target type='serial' port='0'/> - </console> - <graphics autoport="yes" listen="0.0.0.0" port="1" type="vnc" /> - </devices> -</domain> -""" - - -class Ovsdpdk(StandaloneContext): - def __init__(self): - self.name = None - self.file_path = None - self.nodes = [] - self.vm_deploy = False - self.ovs = [] - self.first_run = True - self.dpdk_nic_bind = BIN_PATH + DPDK_NIC_BIND - self.user = "" - self.ssh_ip = "" - self.passwd = "" - self.ssh_port = "" - self.auth_type = "" - - def init(self): - '''initializes itself''' - log.debug("In init") - self.parse_pod_and_get_data() - - def parse_pod_and_get_data(self, file_path): - self.file_path = file_path - print("parsing pod file: {0}".format(self.file_path)) - try: - with open(self.file_path) as stream: - cfg = yaml.load(stream) - except IOError: - print("File {0} does not exist".format(self.file_path)) - raise - - self.ovs.extend([node for node in cfg["nodes"] - if node["role"] == "Ovsdpdk"]) - self.user = self.ovs[0]['user'] - self.ssh_ip = self.ovs[0]['ip'] - if self.ovs[0]['auth_type'] == "password": - self.passwd = self.ovs[0]['password'] - else: - self.ssh_port = self.ovs[0]['ssh_port'] - self.key_filename = self.ovs[0]['key_filename'] - - def ssh_remote_machine(self): - if self.ovs[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() - - def get_nic_details(self): - nic_details = {} - nic_details['interface'] = {} - nic_details['pci'] = self.ovs[0]['phy_ports'] - nic_details['phy_driver'] = self.ovs[0]['phy_driver'] - nic_details['vports_mac'] = self.ovs[0]['vports_mac'] - # 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.ovs[0]['phy_driver'], - port=self.ovs[0]['phy_ports'][i])) - err, out, _ = self.connection.execute( - "lshw -c network -businfo | grep '{port}'".format( - port=self.ovs[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) - print("{0}".format(nic_details)) - return nic_details - - def install_req_libs(self): - if self.first_run: - err, out, _ = self.connection.execute("apt-get update") - print("{0}".format(out)) - err, out, _ = self.connection.execute( - "apt-get -y install qemu-kvm libvirt-bin") - print("{0}".format(out)) - err, out, _ = self.connection.execute( - "apt-get -y install libvirt-dev bridge-utils numactl") - print("{0}".format(out)) - self.first_run = False - - def setup_ovs(self, vpcis): - self.connection.execute("/usr/bin/chmod 0666 /dev/vfio/*") - self.connection.execute("/usr/bin/chmod a+x /dev/vfio") - self.connection.execute("pkill -9 ovs") - self.connection.execute("ps -ef | grep ovs | grep -v grep | " - "awk '{print $2}' | xargs -r kill -9") - self.connection.execute("killall -r 'ovs*'") - self.connection.execute( - "mkdir -p {0}/etc/openvswitch".format(self.ovs[0]["vpath"])) - self.connection.execute( - "mkdir -p {0}/var/run/openvswitch".format(self.ovs[0]["vpath"])) - self.connection.execute( - "rm {0}/etc/openvswitch/conf.db".format(self.ovs[0]["vpath"])) - self.connection.execute( - "ovsdb-tool create {0}/etc/openvswitch/conf.db " - "{0}/share/openvswitch/" - "vswitch.ovsschema".format(self.ovs[0]["vpath"])) - self.connection.execute("modprobe vfio-pci") - self.connection.execute("chmod a+x /dev/vfio") - self.connection.execute("chmod 0666 /dev/vfio/*") - for vpci in vpcis: - self.connection.execute( - "/opt/isb_bin/dpdk_nic_bind.py " - "--bind=vfio-pci {0}".format(vpci)) - - def start_ovs_serverswitch(self): - self.connection.execute("mkdir -p /usr/local/var/run/openvswitch") - self.connection.execute( - "ovsdb-server --remote=punix:" - "/usr/local/var/run/openvswitch/db.sock --pidfile --detach") - self.connection.execute( - "ovs-vsctl --no-wait set " - "Open_vSwitch . other_config:dpdk-init=true") - self.connection.execute( - "ovs-vsctl --no-wait set " - "Open_vSwitch . other_config:dpdk-lcore-mask=0x3") - self.connection.execute( - "ovs-vsctl --no-wait set " - "Open_vSwitch . other_config:dpdk-socket-mem='2048,0'") - self.connection.execute( - "ovs-vswitchd unix:{0}/" - "var/run/openvswitch/db.sock --pidfile --detach " - "--log-file=/var/log/openvswitch/" - "ovs-vswitchd.log".format( - self.ovs[0]["vpath"])) - self.connection.execute( - "ovs-vsctl set Open_vSwitch . other_config:pmd-cpu-mask=2C") - - def setup_ovs_bridge(self): - self.connection.execute("ovs-vsctl del-br br0") - self.connection.execute( - "rm -rf /usr/local/var/run/openvswitch/dpdkvhostuser*") - self.connection.execute( - "ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev") - self.connection.execute( - "ovs-vsctl add-port br0 dpdk0 -- set Interface dpdk0 type=dpdk") - self.connection.execute( - "ovs-vsctl add-port br0 dpdk1 -- set Interface dpdk1 type=dpdk") - self.connection.execute( - "ovs-vsctl add-port br0 dpdkvhostuser0 -- set Interface " - "dpdkvhostuser0 type=dpdkvhostuser") - self.connection.execute("ovs-vsctl add-port br0 dpdkvhostuser1 " - "-- set Interface dpdkvhostuser1 " - "type=dpdkvhostuser") - self.connection.execute( - "chmod 0777 {0}/var/run/" - "openvswitch/dpdkvhostuser*".format(self.ovs[0]["vpath"])) - - def add_oflows(self): - self.connection.execute("ovs-ofctl del-flows br0") - for flow in self.ovs[0]["flow"]: - self.connection.execute(flow) - self.connection.execute("ovs-ofctl dump-flows br0") - self.connection.execute( - "ovs-vsctl set Interface dpdk0 options:n_rxq=4") - self.connection.execute( - "ovs-vsctl set Interface dpdk1 options:n_rxq=4") - - def setup_ovs_context(self, pcis, nic_details, host_driver): - - ''' 1: Setup vm_ovs.xml to launch VM.''' - cfg_ovs = '/tmp/vm_ovs.xml' - vm_ovs_xml = VM_TEMPLATE.format(vm_image=self.ovs[0]["images"]) - with open(cfg_ovs, 'w') as f: - f.write(vm_ovs_xml) - - ''' 2: Create and start the VM''' - self.connection.put(cfg_ovs, cfg_ovs) - time.sleep(10) - err, out = self.check_output("virsh list --name | grep -i vm1") - if out == "vm1": - print("VM is already present") - else: - ''' FIXME: launch through libvirt''' - print("virsh create ...") - err, out, _ = self.connection.execute( - "virsh create /tmp/vm_ovs.xml") - time.sleep(10) - print("err : {0}".format(err)) - print("{0}".format(_)) - print("out : {0}".format(out)) - - ''' 3: Tuning 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") - print("After tuning performance ...") - - ''' 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 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() - print("{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 % len(nodes[str(num_nodes - 1)])])) - - 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() - print("cpulist: {0}".format(cpulist)) - nodes[num] = self.split_cpu_list(cpulist) - print("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.ovs[0]['phy_driver'] - err, out = self.check_output("virsh list --name | grep -i vm1") - print("{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: - print("error : ", err) diff --git a/yardstick/benchmark/contexts/standalone/sriov.py b/yardstick/benchmark/contexts/standalone/sriov.py index fe27d2579..55d7057a9 100644 --- a/yardstick/benchmark/contexts/standalone/sriov.py +++ b/yardstick/benchmark/contexts/standalone/sriov.py @@ -14,418 +14,248 @@ 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 +import collections +from collections import OrderedDict + 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): +from yardstick.benchmark.contexts.base import Context +from yardstick.benchmark.contexts.standalone.model import Libvirt +from yardstick.benchmark.contexts.standalone.model import StandaloneContextHelper +from yardstick.benchmark.contexts.standalone.model import Server +from yardstick.network_services.utils import PciAddress + +LOG = logging.getLogger(__name__) + + +class SriovContext(Context): + """ This class handles SRIOV standalone nodes - VM running on Non-Managed NFVi + Configuration: sr-iov + """ + + __context_type__ = "StandaloneSriov" + 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): - log.debug("In init") - 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.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.vm_names = [] + self.name = None + self.nfvi_host = [] + self.nodes = [] + self.networks = {} + self.attrs = {} + self.vm_flavor = None + self.servers = None + self.helper = StandaloneContextHelper() + self.vnf_node = Server() + self.drivers = [] + super(SriovContext, self).__init__() + + def init(self, attrs): + """initializes itself from the supplied arguments""" + + self.name = attrs["name"] + self.file_path = attrs.get("file", "pod.yaml") + + self.nodes, self.nfvi_host, self.host_mgmt = \ + self.helper.parse_pod_file(self.file_path, 'Sriov') + + self.attrs = attrs + self.vm_flavor = attrs.get('flavor', {}) + self.servers = attrs.get('servers', {}) + self.vm_deploy = attrs.get("vm_deploy", True) + # add optional static network definition + self.networks = attrs.get("networks", {}) + + LOG.debug("Nodes: %r", self.nodes) + LOG.debug("NFVi Node: %r", self.nfvi_host) + LOG.debug("Networks: %r", self.networks) + + def deploy(self): + """don't need to deploy""" + + # Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config. + if not self.vm_deploy: + return + + self.connection = ssh.SSH.from_node(self.host_mgmt) 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") + # Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config. + StandaloneContextHelper.install_req_libs(self.connection) + self.networks = StandaloneContextHelper.get_nic_details(self.connection, + self.networks, + self.dpdk_nic_bind) + self.nodes = self.setup_sriov_context() + + LOG.debug("Waiting for VM to come up...") + self.nodes = StandaloneContextHelper.wait_for_vnfs_to_start(self.connection, + self.servers, + self.nodes) + + def undeploy(self): + """don't need to undeploy""" + + if not self.vm_deploy: + return + + # Todo: NFVi undeploy (sriov, vswitch, ovs etc) based on the config. + for vm in self.vm_names: + Libvirt.check_if_vm_exists_and_delete(vm, self.connection) + + # Bind nics back to kernel + for key, ports in self.networks.items(): + # enable VFs for given... + build_vfs = "echo 0 > /sys/bus/pci/devices/{0}/sriov_numvfs" + self.connection.execute(build_vfs.format(ports.get('phy_port'))) + + def _get_server(self, attr_name): + """lookup server info by name from context + + Keyword arguments: + attr_name -- A name for a server listed in nodes config file + """ + node_name, name = self.split_name(attr_name) + if name is None or self.name != name: + return None + + matching_nodes = (n for n in self.nodes if n["name"] == node_name) 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 + # A clone is created in order to avoid affecting the + # original one. + node = dict(next(matching_nodes)) + except StopIteration: + return None - 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 % len(nodes[str(num_nodes - 1)])])) - - 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 + try: + duplicate = next(matching_nodes) + except StopIteration: + pass + else: + raise ValueError("Duplicate nodes!!! Nodes: %s %s", + (node, duplicate)) - 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) + node["name"] = attr_name + return node + + def _get_network(self, attr_name): + if not isinstance(attr_name, collections.Mapping): + network = self.networks.get(attr_name) - 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)) + # Don't generalize too much Just support vld_id + vld_id = attr_name.get('vld_id', {}) + # for standalone context networks are dicts + iter1 = (n for n in self.networks.values() if n.get('vld_id') == vld_id) + network = next(iter1, None) + + if network is None: + return None + + result = { + # name is required + "name": network["name"], + "vld_id": network.get("vld_id"), + "segmentation_id": network.get("segmentation_id"), + "network_type": network.get("network_type"), + "physical_network": network.get("physical_network"), + } + return result + + def configure_nics_for_sriov(self): + vf_cmd = "ip link set {0} vf 0 mac {1}" + for key, ports in self.networks.items(): + vf_pci = [] + host_driver = ports.get('driver') + if host_driver not in self.drivers: + self.connection.execute("rmmod %svf" % host_driver) + self.drivers.append(host_driver) + + # enable VFs for given... + build_vfs = "echo 1 > /sys/bus/pci/devices/{0}/sriov_numvfs" + self.connection.execute(build_vfs.format(ports.get('phy_port'))) + + # configure VFs... + mac = StandaloneContextHelper.get_mac_address() + interface = ports.get('interface') + if interface is not None: + self.connection.execute(vf_cmd.format(interface, mac)) + + vf_pci = self.get_vf_data('vf_pci', ports.get('phy_port'), mac, interface) + ports.update({ + 'vf_pci': vf_pci, + 'mac': mac + }) + + LOG.info("Ports %s" % self.networks) + + def _enable_interfaces(self, index, idx, vfs, cfg): + vf = self.networks[vfs[0]] + vpci = PciAddress.parse_address(vf['vpci'].strip(), multi_line=True) + # Generate the vpci for the interfaces + slot = index + idx + 10 + vf['vpci'] = \ + "{}:{}:{:02x}.{}".format(vpci.domain, vpci.bus, slot, vpci.function) + Libvirt.add_sriov_interfaces( + vf['vpci'], vf['vf_pci']['vf_pci'], vf['mac'], str(cfg)) + self.connection.execute("ifconfig %s up" % vf['interface']) + + def setup_sriov_context(self): + nodes = [] + + # 1 : modprobe host_driver with num_vfs + self.configure_nics_for_sriov() + + for index, (key, vnf) in enumerate(OrderedDict(self.servers).items()): + cfg = '/tmp/vm_sriov_%s.xml' % str(index) + vm_name = "vm_%s" % str(index) + + # 1. Check and delete VM if already exists + Libvirt.check_if_vm_exists_and_delete(vm_name, self.connection) + + vcpu, mac = Libvirt.build_vm_xml(self.connection, self.vm_flavor, cfg, vm_name, index) + # 2: Cleanup already available VMs + for idx, (vkey, vfs) in enumerate(OrderedDict(vnf["network_ports"]).items()): + if vkey == "mgmt": + continue + self._enable_interfaces(index, idx, vfs, cfg) + + # copy xml to target... + self.connection.put(cfg, cfg) + + # FIXME: launch through libvirt + LOG.info("virsh create ...") + Libvirt.virsh_create_vm(self.connection, cfg) + + # 5: Tunning for better performace + Libvirt.pin_vcpu_for_perf(self.connection, vm_name, vcpu) + self.vm_names.append(vm_name) + + # build vnf node details + nodes.append(self.vnf_node.generate_vnf_instance(self.vm_flavor, + self.networks, + self.host_mgmt.get('ip'), + key, vnf, mac)) + + return nodes + + def get_vf_data(self, key, value, vfmac, pfif): + vf_data = { + "mac": vfmac, + "pf_if": pfif + } + vfs = StandaloneContextHelper.get_virtual_devices(self.connection, value) + for k, v in vfs.items(): + m = PciAddress.parse_address(k.strip(), multi_line=True) + m1 = PciAddress.parse_address(value.strip(), multi_line=True) + if m.bus == m1.bus: + vf_data.update({"vf_pci": str(v)}) + break + + return vf_data diff --git a/yardstick/network_services/utils.py b/yardstick/network_services/utils.py index d52e27c15..eac3c814f 100644 --- a/yardstick/network_services/utils.py +++ b/yardstick/network_services/utils.py @@ -16,6 +16,7 @@ from __future__ import absolute_import import logging import os +import re from oslo_config import cfg from oslo_config.cfg import NoSuchOptError @@ -38,6 +39,59 @@ OPTS = [ CONF.register_opts(OPTS, group="nsb") +HEXADECIMAL = "[0-9a-zA-Z]" + + +class PciAddress(object): + + PCI_PATTERN_STR = HEXADECIMAL.join([ + "(", + "{4}):(", # domain (4 bytes) + "{2}):(", # bus (2 bytes) + "{2}).(", # function (2 bytes) + ")", # slot (1 byte) + ]) + + PCI_PATTERN = re.compile(PCI_PATTERN_STR) + + @classmethod + def parse_address(cls, text, multi_line=False): + if multi_line: + text = text.replace(os.linesep, '') + match = cls.PCI_PATTERN.search(text) + return cls(match.group(0)) + + def __init__(self, address): + super(PciAddress, self).__init__() + match = self.PCI_PATTERN.match(address) + if not match: + raise ValueError('Invalid PCI address: {}'.format(address)) + self.address = address + self.match = match + + def __repr__(self): + return self.address + + @property + def domain(self): + return self.match.group(1) + + @property + def bus(self): + return self.match.group(2) + + @property + def slot(self): + return self.match.group(3) + + @property + def function(self): + return self.match.group(4) + + def values(self): + return [self.match.group(n) for n in range(1, 5)] + + def get_nsb_option(option, default=None): """return requested option for yardstick.conf""" @@ -55,6 +109,8 @@ def provision_tool(connection, tool_path, tool_file=None): :return - Tool path """ + if not tool_path: + tool_path = get_nsb_option('tool_path') if tool_file: tool_path = os.path.join(tool_path, tool_file) bin_path = get_nsb_option("bin_path") @@ -64,6 +120,7 @@ def provision_tool(connection, tool_path, tool_file=None): logging.warning("%s not found on %s, will try to copy from localhost", tool_path, connection.host) + bin_path = get_nsb_option("bin_path") connection.execute('mkdir -p "%s"' % bin_path) connection.put(tool_path, tool_path) return tool_path |