Merge "Improve "get_server" function in Kubernetes context"
[yardstick.git] / yardstick / tests / unit / benchmark / contexts / standalone / test_ovs_dpdk.py
index 0223fd3..69779d3 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import io
 import os
 
 import mock
+import six
 import unittest
 
+from yardstick.benchmark import contexts
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts.standalone import model
 from yardstick.benchmark.contexts.standalone import ovs_dpdk
+from yardstick.common import exceptions
+from yardstick.network_services import utils
 
 
 class OvsDpdkContextTestCase(unittest.TestCase):
@@ -27,7 +34,6 @@ class OvsDpdkContextTestCase(unittest.TestCase):
     NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
 
     NETWORKS = {
-        'mgmt': {'cidr': '152.16.100.10/24'},
         'private_0': {
             'phy_port': "0000:05:00.0",
             'vpci': "0000:00:07.0",
@@ -53,11 +59,19 @@ class OvsDpdkContextTestCase(unittest.TestCase):
             'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
         }
         self.ovs_dpdk = ovs_dpdk.OvsDpdkContext()
+        self._mock_log = mock.patch.object(ovs_dpdk, 'LOG')
+        self.mock_log = self._mock_log.start()
         self.addCleanup(self._remove_contexts)
+        self.addCleanup(self._stop_mocks)
 
-    def _remove_contexts(self):
-        if self.ovs_dpdk in self.ovs_dpdk.list:
-            self.ovs_dpdk._delete_context()
+    @staticmethod
+    def _remove_contexts():
+        for context in base.Context.list:
+            context._delete_context()
+        base.Context.list = []
+
+    def _stop_mocks(self):
+        self._mock_log.stop()
 
     @mock.patch('yardstick.benchmark.contexts.standalone.model.Server')
     @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper')
@@ -69,7 +83,7 @@ class OvsDpdkContextTestCase(unittest.TestCase):
 
     def test_init(self):
         ATTRS = {
-            'name': 'StandaloneOvsDpdk',
+            'name': contexts.CONTEXT_STANDALONEOVSDPDK,
             'task_id': '1234567890',
             'file': 'pod',
             'flavor': {},
@@ -82,15 +96,43 @@ class OvsDpdkContextTestCase(unittest.TestCase):
         self.assertIsNone(self.ovs_dpdk.init(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())
+        fake_path = '/fake_path'
+        fake_dpdk_nic_bind = 'dpdk_tool.py'
+        self.ovs_dpdk.ovs_properties = {'vpath': fake_path}
+        self.ovs_dpdk.dpdk_devbind = fake_dpdk_nic_bind
+        self.ovs_dpdk.networks = self.NETWORKS
+        self.ovs_dpdk.connection = mock.Mock()
+        self.ovs_dpdk.connection.execute = mock.Mock(return_value=(0, 0, 0))
+        create_from = fake_path + '/etc/openvswitch/conf.db'
+        create_to = fake_path + '/share/openvswitch/vswitch.ovsschema'
+        cmd_list = [
+            'killall -r "ovs.*" -q | true',
+            'mkdir -p {0}/etc/openvswitch'.format(fake_path),
+            'mkdir -p {0}/var/run/openvswitch'.format(fake_path),
+            'rm {0}/etc/openvswitch/conf.db | true'.format(fake_path),
+            'ovsdb-tool create {0} {1}'.format(create_from, create_to),
+            'modprobe vfio-pci',
+            'chmod a+x /dev/vfio',
+            'chmod 0666 /dev/vfio/*',
+            '{0} --force -b vfio-pci {1}'.format(fake_dpdk_nic_bind,
+                self.ovs_dpdk.networks['private_0']['phy_port']),
+            '{0} --force -b vfio-pci {1}'.format(fake_dpdk_nic_bind,
+                self.ovs_dpdk.networks['public_0']['phy_port'])
+        ]
+        calls = [mock.call(cmd, timeout=self.ovs_dpdk.CMD_TIMEOUT)
+                 for cmd in cmd_list]
+
+        self.ovs_dpdk.setup_ovs()
+        self.ovs_dpdk.connection.execute.assert_has_calls(calls,
+                                                          any_order=True)
+
+    def test_setup_ovs_exception(self):
+        self.ovs_dpdk.networks = self.NETWORKS
+        self.ovs_dpdk.connection = mock.Mock()
+        self.ovs_dpdk.connection.execute = mock.Mock(return_value=(1, 0, 0))
+
+        with self.assertRaises(exceptions.OVSSetupError):
+            self.ovs_dpdk.setup_ovs()
 
     def test_start_ovs_serverswitch(self):
         with mock.patch("yardstick.ssh.SSH") as ssh:
@@ -129,34 +171,45 @@ class OvsDpdkContextTestCase(unittest.TestCase):
        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()
-            # NOTE(elfoley): Check for a specific Exception
-            self.assertRaises(Exception, self.ovs_dpdk.check_ovs_dpdk_env)
+    @mock.patch.object(ovs_dpdk.OvsDpdkContext, '_check_hugepages')
+    @mock.patch.object(utils, 'get_nsb_option')
+    @mock.patch.object(model.OvsDeploy, 'ovs_deploy')
+    def test_check_ovs_dpdk_env(self, mock_ovs_deploy, mock_get_nsb_option,
+                                mock_check_hugepages):
+        self.ovs_dpdk.connection = mock.Mock()
+        self.ovs_dpdk.connection.execute = mock.Mock(
+            return_value=(1, 0, 0))
+        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()
+        mock_get_nsb_option.return_value = 'fake_path'
+
+        self.ovs_dpdk.check_ovs_dpdk_env()
+        mock_ovs_deploy.assert_called_once()
+        mock_check_hugepages.assert_called_once()
+        mock_get_nsb_option.assert_called_once_with('bin_path')
+
+    @mock.patch.object(ovs_dpdk.OvsDpdkContext, '_check_hugepages')
+    def test_check_ovs_dpdk_env_wrong_version(self, mock_check_hugepages):
+        self.ovs_dpdk.connection = mock.Mock()
+        self.ovs_dpdk.connection.execute = mock.Mock(
+            return_value=(1, 0, 0))
+        self.ovs_dpdk.networks = self.NETWORKS
+        self.ovs_dpdk.ovs_properties = {
+            'version': {'ovs': '0.0.1', 'dpdk': '9.8.7'}
+        }
+        self.ovs_dpdk.wait_for_vswitchd = 0
+        self.ovs_dpdk.cleanup_ovs_dpdk_env = mock.Mock()
 
-    @mock.patch('yardstick.ssh.SSH')
-    def test_deploy(self, mock_ssh):
-        mock_ssh.execute.return_value = 0, "a", ""
+        with self.assertRaises(exceptions.OVSUnsupportedVersion):
+            self.ovs_dpdk.check_ovs_dpdk_env()
+        mock_check_hugepages.assert_called_once()
 
+    @mock.patch('yardstick.ssh.SSH')
+    def test_deploy(self, *args):
         self.ovs_dpdk.vm_deploy = False
         self.assertIsNone(self.ovs_dpdk.deploy())
 
@@ -174,21 +227,19 @@ class OvsDpdkContextTestCase(unittest.TestCase):
         # output.
         self.assertIsNone(self.ovs_dpdk.deploy())
 
-    @mock.patch('yardstick.benchmark.contexts.standalone.model.Libvirt')
-    @mock.patch('yardstick.ssh.SSH')
-    def test_undeploy(self, mock_ssh, *args):
-        mock_ssh.execute.return_value = 0, "a", ""
-
-        self.ovs_dpdk.vm_deploy = False
-        self.assertIsNone(self.ovs_dpdk.undeploy())
-
+    @mock.patch.object(model.Libvirt, 'check_if_vm_exists_and_delete')
+    def test_undeploy(self, mock_libvirt):
         self.ovs_dpdk.vm_deploy = True
-        self.ovs_dpdk.connection = mock_ssh
+        self.ovs_dpdk.connection = mock.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())
+        self.ovs_dpdk.undeploy()
+        mock_libvirt.assert_has_calls([
+            mock.call(self.ovs_dpdk.vm_names[0], self.ovs_dpdk.connection),
+            mock.call(self.ovs_dpdk.vm_names[1], self.ovs_dpdk.connection)
+        ])
 
     def _get_file_abspath(self, filename):
         curr_path = os.path.dirname(os.path.abspath(__file__))
@@ -246,6 +297,22 @@ class OvsDpdkContextTestCase(unittest.TestCase):
         self.assertEqual(result['user'], 'root')
         self.assertEqual(result['key_filename'], '/root/.yardstick_key')
 
+    def test__get_physical_node_for_server(self):
+        attrs = self.attrs
+        attrs.update({'servers': {'server1': {}}})
+        self.ovs_dpdk.init(attrs)
+
+        # When server is not from this context
+        result = self.ovs_dpdk._get_physical_node_for_server('server1.another-context')
+        self.assertIsNone(result)
+
+        # When node_name is not from this context
+        result = self.ovs_dpdk._get_physical_node_for_server('fake.foo-12345678')
+        self.assertIsNone(result)
+
+        result = self.ovs_dpdk._get_physical_node_for_server('server1.foo-12345678')
+        self.assertEqual(result, 'node5.foo')
+
     # TODO(elfoley): Split this test for networks that exist and networks that
     #                don't
     def test__get_network(self):
@@ -310,34 +377,28 @@ class OvsDpdkContextTestCase(unittest.TestCase):
         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, *args):
-        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.patch.object(model.Libvirt, 'add_ovs_interface')
+    def test__enable_interfaces(self, mock_add_ovs_interface):
         self.ovs_dpdk.vm_deploy = True
-        self.ovs_dpdk.connection = ssh_mock
+        self.ovs_dpdk.connection = mock.Mock()
         self.ovs_dpdk.vm_names = ['vm_0', 'vm_1']
         self.ovs_dpdk.drivers = []
         self.ovs_dpdk.networks = self.NETWORKS
+        self.ovs_dpdk.ovs_properties = {'vpath': 'fake_path'}
         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.model.Server')
-    @mock.patch('yardstick.benchmark.contexts.standalone.ovs_dpdk.Libvirt')
-    def test_setup_ovs_dpdk_context(self, mock_libvirt, *args):
-        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._enable_interfaces(0, ["private_0"], 'test')
+        mock_add_ovs_interface.assert_called_once_with(
+            'fake_path', 0, self.NETWORKS['private_0']['vpci'],
+            self.NETWORKS['private_0']['mac'], 'test')
+
+    @mock.patch.object(model.Libvirt, 'write_file')
+    @mock.patch.object(model.Libvirt, 'build_vm_xml')
+    @mock.patch.object(model.Libvirt, 'check_if_vm_exists_and_delete')
+    @mock.patch.object(model.Libvirt, 'virsh_create_vm')
+    def test_setup_ovs_dpdk_context(self, mock_create_vm, mock_check_if_exists,
+                                    mock_build_xml, mock_write_file):
         self.ovs_dpdk.vm_deploy = True
-        self.ovs_dpdk.connection = ssh_mock
+        self.ovs_dpdk.connection = mock.Mock()
         self.ovs_dpdk.vm_names = ['vm_0', 'vm_1']
         self.ovs_dpdk.drivers = []
         self.ovs_dpdk.servers = {
@@ -353,11 +414,64 @@ class OvsDpdkContextTestCase(unittest.TestCase):
         self.ovs_dpdk.host_mgmt = {}
         self.ovs_dpdk.flavor = {}
         self.ovs_dpdk.configure_nics_for_ovs_dpdk = mock.Mock(return_value="")
-        mock_libvirt.build_vm_xml.return_value = [6, "00:00:00:00:00:01"]
-        self.ovs_dpdk._enable_interfaces = mock.Mock(return_value="")
-        mock_libvirt.virsh_create_vm.return_value = ""
-        mock_libvirt.pin_vcpu_for_perf.return_value = ""
+        xml_str = mock.Mock()
+        mock_build_xml.return_value = (xml_str, '00:00:00:00:00:01')
+        self.ovs_dpdk._enable_interfaces = mock.Mock(return_value=xml_str)
+        vnf_instance = mock.Mock()
         self.ovs_dpdk.vnf_node.generate_vnf_instance = mock.Mock(
-            return_value={})
-
-        self.assertIsNotNone(self.ovs_dpdk.setup_ovs_dpdk_context())
+            return_value=vnf_instance)
+
+        self.assertEqual([vnf_instance],
+                         self.ovs_dpdk.setup_ovs_dpdk_context())
+        mock_create_vm.assert_called_once_with(
+            self.ovs_dpdk.connection, '/tmp/vm_ovs_0.xml')
+        mock_check_if_exists.assert_called_once_with(
+            'vm_0', self.ovs_dpdk.connection)
+        mock_build_xml.assert_called_once_with(
+            self.ovs_dpdk.connection, self.ovs_dpdk.vm_flavor, 'vm_0', 0)
+        mock_write_file.assert_called_once_with('/tmp/vm_ovs_0.xml', xml_str)
+
+    @mock.patch.object(io, 'BytesIO')
+    def test__check_hugepages(self, mock_bytesio):
+        data = six.BytesIO('HugePages_Total:      20\n'
+                           'HugePages_Free:       20\n'
+                           'HugePages_Rsvd:        0\n'
+                           'HugePages_Surp:        0\n'
+                           'Hugepagesize:    1048576 kB'.encode())
+        mock_bytesio.return_value = data
+        self.ovs_dpdk.connection = mock.Mock()
+        self.ovs_dpdk._check_hugepages()
+
+    @mock.patch.object(io, 'BytesIO')
+    def test__check_hugepages_no_info(self, mock_bytesio):
+        data = six.BytesIO(''.encode())
+        mock_bytesio.return_value = data
+        self.ovs_dpdk.connection = mock.Mock()
+        with self.assertRaises(exceptions.OVSHugepagesInfoError):
+            self.ovs_dpdk._check_hugepages()
+
+    @mock.patch.object(io, 'BytesIO')
+    def test__check_hugepages_no_total_hp(self, mock_bytesio):
+        data = six.BytesIO('HugePages_Total:       0\n'
+                           'HugePages_Free:        0\n'
+                           'HugePages_Rsvd:        0\n'
+                           'HugePages_Surp:        0\n'
+                           'Hugepagesize:    1048576 kB'.encode())
+        mock_bytesio.return_value = data
+        self.ovs_dpdk.connection = mock.Mock()
+        with self.assertRaises(exceptions.OVSHugepagesNotConfigured):
+            self.ovs_dpdk._check_hugepages()
+
+    @mock.patch.object(io, 'BytesIO')
+    def test__check_hugepages_no_free_hp(self, mock_bytesio):
+        data = six.BytesIO('HugePages_Total:      20\n'
+                           'HugePages_Free:        0\n'
+                           'HugePages_Rsvd:        0\n'
+                           'HugePages_Surp:        0\n'
+                           'Hugepagesize:    1048576 kB'.encode())
+        mock_bytesio.return_value = data
+        self.ovs_dpdk.connection = mock.Mock()
+        with self.assertRaises(exceptions.OVSHugepagesZeroFree) as exc:
+            self.ovs_dpdk._check_hugepages()
+        self.assertEqual('There are no HugePages free in this system. Total '
+                         'HugePages configured: 20', exc.exception.msg)