diff options
author | Huan Xie <huan.xie@citrix.com> | 2017-04-05 00:06:06 -0700 |
---|---|---|
committer | Huan Xie <huan.xie@citrix.com> | 2017-06-06 22:01:24 -0700 |
commit | a2f6aac01de30c5b3031b9ef9d0130c77ebc685d (patch) | |
tree | 9120171e5faf15e01de4fe6f6174cf760c257350 /nova/tests | |
parent | 72119868b27b293d5fa60c19392c0ba08e3df9b3 (diff) | |
download | nova-a2f6aac01de30c5b3031b9ef9d0130c77ebc685d.tar.gz |
XenAPI: use os-xenapi 0.2.0 in nova
This patch is to change nova project to use os-xenapi 0.2.0 which
has added python interfaces for calling dom0 plugins
1. use os_xenapi.client.host_network
2. use os_xenapi.client.disk_management
3. use os_xenapi.client.vm_management
4. use os_xenapi.client.host_xenstore
5. use os_xenapi.client.host_agent
6. use os_xenapi.client.host_management
7. use os_xenapi.client.host_glance
Change-Id: Id87b83ef3ca496525f63b9c7b731e8a22c693e02
Diffstat (limited to 'nova/tests')
-rw-r--r-- | nova/tests/unit/virt/xenapi/image/test_glance.py | 143 | ||||
-rw-r--r-- | nova/tests/unit/virt/xenapi/test_agent.py | 119 | ||||
-rw-r--r-- | nova/tests/unit/virt/xenapi/test_vif.py | 18 | ||||
-rw-r--r-- | nova/tests/unit/virt/xenapi/test_vm_utils.py | 78 | ||||
-rw-r--r-- | nova/tests/unit/virt/xenapi/test_vmops.py | 43 | ||||
-rw-r--r-- | nova/tests/unit/virt/xenapi/test_xenapi.py | 91 |
6 files changed, 305 insertions, 187 deletions
diff --git a/nova/tests/unit/virt/xenapi/image/test_glance.py b/nova/tests/unit/virt/xenapi/image/test_glance.py index 5d43317186..0e4c3da7c1 100644 --- a/nova/tests/unit/virt/xenapi/image/test_glance.py +++ b/nova/tests/unit/virt/xenapi/image/test_glance.py @@ -17,12 +17,15 @@ import random import time import mock +from os_xenapi.client import host_glance from os_xenapi.client import XenAPI from nova.compute import utils as compute_utils from nova import context from nova import exception +from nova.image import glance as common_glance from nova.tests.unit.virt.xenapi import stubs +from nova import utils from nova.virt.xenapi import driver as xenapi_conn from nova.virt.xenapi import fake from nova.virt.xenapi.image import glance @@ -121,50 +124,114 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB): def _get_upload_params(self, auto_disk_config=True, expected_os_type='default'): - params = self._get_params() + params = {} params['vdi_uuids'] = ['fake_vdi_uuid'] params['properties'] = {'auto_disk_config': auto_disk_config, 'os_type': expected_os_type} return params - def _test_upload_image(self, auto_disk_config, expected_os_type='default'): - params = self._get_upload_params(auto_disk_config, expected_os_type) - with mock.patch.object(self.session, 'call_plugin_serialized' - ) as mock_call_plugin: - self.store.upload_image(self.context, self.session, self.instance, - 'fake_image_uuid', ['fake_vdi_uuid']) - - mock_call_plugin.assert_called_once_with('glance.py', - 'upload_vhd2', - **params) - - def test_upload_image(self): - self._test_upload_image(True) - - def test_upload_image_None_os_type(self): + @mock.patch.object(utils, 'get_auto_disk_config_from_instance') + @mock.patch.object(common_glance, 'generate_identity_headers') + @mock.patch.object(vm_utils, 'get_sr_path') + @mock.patch.object(host_glance, 'upload_vhd') + def test_upload_image(self, mock_upload, mock_sr_path, mock_extra_header, + mock_disk_config): + params = self._get_upload_params() + mock_upload.return_value = 'fake_upload' + mock_sr_path.return_value = 'fake_sr_path' + mock_extra_header.return_value = 'fake_extra_header' + mock_disk_config.return_value = 'true' + self.store.upload_image(self.context, self.session, self.instance, + 'fake_image_uuid', ['fake_vdi_uuid']) + + mock_sr_path.assert_called_once_with(self.session) + mock_extra_header.assert_called_once_with(self.context) + mock_upload.assert_called_once_with( + self.session, 0, mock.ANY, mock.ANY, 'fake_image_uuid', + 'fake_sr_path', 'fake_extra_header', **params) + + @mock.patch.object(utils, 'get_auto_disk_config_from_instance') + @mock.patch.object(common_glance, 'generate_identity_headers') + @mock.patch.object(vm_utils, 'get_sr_path') + @mock.patch.object(host_glance, 'upload_vhd') + def test_upload_image_None_os_type(self, mock_upload, mock_sr_path, + mock_extra_header, mock_disk_config): self.instance['os_type'] = None - self._test_upload_image(True, 'linux') - - def test_upload_image_no_os_type(self): + mock_sr_path.return_value = 'fake_sr_path' + mock_extra_header.return_value = 'fake_extra_header' + mock_upload.return_value = 'fake_upload' + mock_disk_config.return_value = 'true' + params = self._get_upload_params(True, 'linux') + self.store.upload_image(self.context, self.session, self.instance, + 'fake_image_uuid', ['fake_vdi_uuid']) + + mock_sr_path.assert_called_once_with(self.session) + mock_extra_header.assert_called_once_with(self.context) + mock_upload.assert_called_once_with( + self.session, 0, mock.ANY, mock.ANY, 'fake_image_uuid', + 'fake_sr_path', 'fake_extra_header', **params) + mock_disk_config.assert_called_once_with(self.instance) + + @mock.patch.object(utils, 'get_auto_disk_config_from_instance') + @mock.patch.object(common_glance, 'generate_identity_headers') + @mock.patch.object(vm_utils, 'get_sr_path') + @mock.patch.object(host_glance, 'upload_vhd') + def test_upload_image_no_os_type(self, mock_upload, mock_sr_path, + mock_extra_header, mock_disk_config): + mock_sr_path.return_value = 'fake_sr_path' + mock_extra_header.return_value = 'fake_extra_header' + mock_upload.return_value = 'fake_upload' del self.instance['os_type'] - self._test_upload_image(True, 'linux') - - def test_upload_image_auto_config_disk_disabled(self): + params = self._get_upload_params(True, 'linux') + self.store.upload_image(self.context, self.session, self.instance, + 'fake_image_uuid', ['fake_vdi_uuid']) + + mock_sr_path.assert_called_once_with(self.session) + mock_extra_header.assert_called_once_with(self.context) + mock_upload.assert_called_once_with( + self.session, 0, mock.ANY, mock.ANY, 'fake_image_uuid', + 'fake_sr_path', 'fake_extra_header', **params) + mock_disk_config.assert_called_once_with(self.instance) + + @mock.patch.object(common_glance, 'generate_identity_headers') + @mock.patch.object(vm_utils, 'get_sr_path') + @mock.patch.object(host_glance, 'upload_vhd') + def test_upload_image_auto_config_disk_disabled( + self, mock_upload, mock_sr_path, mock_extra_header): + mock_sr_path.return_value = 'fake_sr_path' + mock_extra_header.return_value = 'fake_extra_header' + mock_upload.return_value = 'fake_upload' sys_meta = [{"key": "image_auto_disk_config", "value": "Disabled"}] self.instance["system_metadata"] = sys_meta - self._test_upload_image("disabled") - - def test_upload_image_raises_exception(self): + params = self._get_upload_params("disabled") + self.store.upload_image(self.context, self.session, self.instance, + 'fake_image_uuid', ['fake_vdi_uuid']) + + mock_sr_path.assert_called_once_with(self.session) + mock_extra_header.assert_called_once_with(self.context) + mock_upload.assert_called_once_with( + self.session, 0, mock.ANY, mock.ANY, 'fake_image_uuid', + 'fake_sr_path', 'fake_extra_header', **params) + + @mock.patch.object(common_glance, 'generate_identity_headers') + @mock.patch.object(vm_utils, 'get_sr_path') + @mock.patch.object(host_glance, 'upload_vhd') + def test_upload_image_raises_exception(self, mock_upload, mock_sr_path, + mock_extra_header): + + mock_sr_path.return_value = 'fake_sr_path' + mock_extra_header.return_value = 'fake_extra_header' + mock_upload.side_effect = RuntimeError params = self._get_upload_params() - with mock.patch.object(self.session, 'call_plugin_serialized', - side_effect=RuntimeError) as mock_call_plugin: - self.assertRaises(RuntimeError, self.store.upload_image, - self.context, self.session, self.instance, - 'fake_image_uuid', ['fake_vdi_uuid']) + self.assertRaises(RuntimeError, self.store.upload_image, + self.context, self.session, self.instance, + 'fake_image_uuid', ['fake_vdi_uuid']) - mock_call_plugin.assert_called_once_with('glance.py', - 'upload_vhd2', - **params) + mock_sr_path.assert_called_once_with(self.session) + mock_extra_header.assert_called_once_with(self.context) + mock_upload.assert_called_once_with( + self.session, 0, mock.ANY, mock.ANY, 'fake_image_uuid', + 'fake_sr_path', 'fake_extra_header', **params) @mock.patch.object(time, 'sleep') @mock.patch.object(compute_utils, 'add_instance_fault_from_exc') @@ -172,10 +239,11 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB): mock_add_inst, mock_time_sleep): self.flags(num_retries=2, group='glance') - params = self._get_upload_params() + params = self._get_params() + params.update(self._get_upload_params()) error_details = ["", "", "RetryableError", ""] - error = self.session.XenAPI.Failure(details=error_details) + error = XenAPI.Failure(details=error_details) with mock.patch.object(self.session, 'call_plugin_serialized', side_effect=error) as mock_call_plugin: @@ -206,10 +274,11 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB): mock_add_inst, mock_time_sleep): self.flags(num_retries=2, group='glance') - params = self._get_upload_params() + params = self._get_params() + params.update(self._get_upload_params()) error_details = ["", "task signaled", "", ""] - error = self.session.XenAPI.Failure(details=error_details) + error = XenAPI.Failure(details=error_details) # Note(johngarbutt) XenServer 6.1 and later has this error error_details_v61 = ["", "signal: SIGTERM", "", ""] diff --git a/nova/tests/unit/virt/xenapi/test_agent.py b/nova/tests/unit/virt/xenapi/test_agent.py index 2069f5155a..8c77445c22 100644 --- a/nova/tests/unit/virt/xenapi/test_agent.py +++ b/nova/tests/unit/virt/xenapi/test_agent.py @@ -15,10 +15,11 @@ import base64 import time -import uuid import mock +from os_xenapi.client import host_agent from os_xenapi.client import XenAPI +from oslo_utils import uuidutils from nova import exception from nova import test @@ -169,7 +170,7 @@ class FileInjectionTestCase(AgentTestCaseBase): b64_contents = base64.b64encode(b'contents') agent.inject_file("path", "contents") - mock_call_agent.assert_called_once_with('inject_file', + mock_call_agent.assert_called_once_with(host_agent.inject_file, {'b64_contents': b64_contents, 'b64_path': b64_path}) @@ -197,35 +198,21 @@ class FileInjectionTestCase(AgentTestCaseBase): mock_inject_file.assert_not_called() -class FakeRebootException(Exception): - details = ["", "", "", "asdf REBOOT: asdf"] - - class RebootRetryTestCase(AgentTestCaseBase): @mock.patch.object(agent, '_wait_for_new_dom_id') def test_retry_on_reboot(self, mock_wait): mock_session = mock.Mock() - - def fake_call_plugin(*args, **kwargs): - if fake_call_plugin.called: - return {"returncode": '0', "message": "done"} - else: - fake_call_plugin.called = True - raise FakeRebootException() - - fake_call_plugin.called = False - mock_session.XenAPI.Failure = FakeRebootException mock_session.VM.get_domid.return_value = "fake_dom_id" - mock_session.call_plugin.side_effect = fake_call_plugin - agent = self._create_agent(None, mock_session) - - result = agent._call_agent("asdf") + mock_method = mock.Mock().method() + mock_method.side_effect = [XenAPI.Failure(["REBOOT: fake"]), + {"returncode": '0', "message": "done"}] + result = agent._call_agent(mock_method) self.assertEqual("done", result) self.assertTrue(mock_session.VM.get_domid.called) - self.assertEqual(2, mock_session.call_plugin.call_count) + self.assertEqual(2, mock_method.call_count) mock_wait.assert_called_once_with(mock_session, self.vm_ref, - "fake_dom_id", "asdf") + "fake_dom_id", mock_method) @mock.patch.object(time, 'sleep') @mock.patch.object(time, 'time') @@ -267,10 +254,12 @@ class RebootRetryTestCase(AgentTestCaseBase): mock_time.side_effect = fake_time mock_session = mock.Mock() mock_session.VM.get_domid.return_value = "old" + mock_method = mock.Mock().method() + mock_method.__name__ = "mock_method" self.assertRaises(exception.AgentTimeout, agent._wait_for_new_dom_id, - mock_session, "vm_ref", "old", "method") + mock_session, "vm_ref", "old", mock_method) self.assertEqual(4, mock_session.VM.get_domid.call_count) @@ -286,7 +275,8 @@ class SetAdminPasswordTestCase(AgentTestCaseBase): result = agent._exchange_key_with_agent() - mock_call_agent.assert_called_once_with('key_init', {"pub": "4321"}, + mock_call_agent.assert_called_once_with(host_agent.key_init, + {"pub": "4321"}, success_codes=['D0'], ignore_errors=False) result.compute_shared.assert_called_once_with(1234) @@ -305,7 +295,7 @@ class SetAdminPasswordTestCase(AgentTestCaseBase): agent_inst.set_admin_password("new_pass") mock_dh.encrypt.assert_called_once_with("new_pass\n") - mock_call_agent.assert_called_once_with('password', + mock_call_agent.assert_called_once_with(host_agent.password, {'enc_pass': 'enc_pass'}) mock_save.assert_called_once_with("new_pass") @@ -339,7 +329,7 @@ class UpgradeRequiredTestCase(test.NoDBTestCase): self.assertTrue(agent.is_upgrade_required('1.2.3', '1.2.3.4')) -@mock.patch.object(uuid, "uuid4") +@mock.patch.object(uuidutils, 'generate_uuid') class CallAgentTestCase(AgentTestCaseBase): def test_call_agent_success(self, mock_uuid): session = mock.Mock() @@ -348,83 +338,88 @@ class CallAgentTestCase(AgentTestCaseBase): session.VM.get_domid.return_value = '42' mock_uuid.return_value = 1 - session.call_plugin.return_value = {'returncode': '4', - 'message': "asdf\\r\\n"} + mock_method = mock.Mock().method() + mock_method.return_value = {'returncode': '4', 'message': "asdf\\r\\n"} + mock_method.__name__ = "mock_method" self.assertEqual("asdf", agent._call_agent(session, instance, "vm_ref", - "method", addl_args, timeout=300, + mock_method, addl_args, timeout=300, success_codes=['0', '4'])) - expected_args = { - 'id': '1', - 'dom_id': '42', - 'timeout': '300', - } + expected_args = {} expected_args.update(addl_args) - session.call_plugin.assert_called_once_with("agent.py", "method", - expected_args) + mock_method.assert_called_once_with(session, 1, '42', 300, + **expected_args) session.VM.get_domid.assert_called_once_with("vm_ref") - def _call_agent_setup(self, session, mock_uuid, + def _call_agent_setup(self, session, mock_uuid, mock_method, returncode='0', success_codes=None, exception=None): session.XenAPI.Failure = XenAPI.Failure instance = {"uuid": "fake"} + addl_args = {"foo": "bar"} session.VM.get_domid.return_value = "42" mock_uuid.return_value = 1 if exception: - session.call_plugin.side_effect = exception + mock_method.side_effect = exception else: - session.call_plugin.return_value = {'returncode': returncode, - 'message': "asdf\\r\\n"} - - return agent._call_agent(session, instance, "vm_ref", "method", - success_codes=success_codes) - - def _assert_agent_called(self, session, mock_uuid): - expected_args = { - 'id': '1', - 'dom_id': '42', - 'timeout': '30', - } - session.call_plugin.assert_called_once_with("agent.py", "method", - expected_args) + mock_method.return_value = {'returncode': returncode, + 'message': "asdf\\r\\n"} + + return agent._call_agent(session, instance, "vm_ref", mock_method, + addl_args, success_codes=success_codes) + + def _assert_agent_called(self, session, mock_uuid, mock_method): + expected_args = {"foo": "bar"} + mock_uuid.assert_called_once_with() + mock_method.assert_called_once_with(session, 1, '42', 30, + **expected_args) session.VM.get_domid.assert_called_once_with("vm_ref") def test_call_agent_works_with_defaults(self, mock_uuid): session = mock.Mock() - self._call_agent_setup(session, mock_uuid) - self._assert_agent_called(session, mock_uuid) + mock_method = mock.Mock().method() + mock_method.__name__ = "mock_method" + self._call_agent_setup(session, mock_uuid, mock_method) + self._assert_agent_called(session, mock_uuid, mock_method) def test_call_agent_fails_with_timeout(self, mock_uuid): session = mock.Mock() + mock_method = mock.Mock().method() + mock_method.__name__ = "mock_method" self.assertRaises(exception.AgentTimeout, self._call_agent_setup, - session, mock_uuid, + session, mock_uuid, mock_method, exception=XenAPI.Failure(["TIMEOUT:fake"])) - self._assert_agent_called(session, mock_uuid) + self._assert_agent_called(session, mock_uuid, mock_method) def test_call_agent_fails_with_not_implemented(self, mock_uuid): session = mock.Mock() + mock_method = mock.Mock().method() + mock_method.__name__ = "mock_method" self.assertRaises(exception.AgentNotImplemented, self._call_agent_setup, - session, mock_uuid, + session, mock_uuid, mock_method, exception=XenAPI.Failure(["NOT IMPLEMENTED:"])) - self._assert_agent_called(session, mock_uuid) + self._assert_agent_called(session, mock_uuid, mock_method) def test_call_agent_fails_with_other_error(self, mock_uuid): session = mock.Mock() + mock_method = mock.Mock().method() + mock_method.__name__ = "mock_method" self.assertRaises(exception.AgentError, self._call_agent_setup, - session, mock_uuid, + session, mock_uuid, mock_method, exception=XenAPI.Failure(["asdf"])) - self._assert_agent_called(session, mock_uuid) + self._assert_agent_called(session, mock_uuid, mock_method) def test_call_agent_fails_with_returned_error(self, mock_uuid): session = mock.Mock() + mock_method = mock.Mock().method() + mock_method.__name__ = "mock_method" self.assertRaises(exception.AgentError, self._call_agent_setup, - session, mock_uuid, returncode='42') - self._assert_agent_called(session, mock_uuid) + session, mock_uuid, mock_method, returncode='42') + self._assert_agent_called(session, mock_uuid, mock_method) class XenAPIBasedAgent(AgentTestCaseBase): diff --git a/nova/tests/unit/virt/xenapi/test_vif.py b/nova/tests/unit/virt/xenapi/test_vif.py index 57a25043ab..e5f419ca96 100644 --- a/nova/tests/unit/virt/xenapi/test_vif.py +++ b/nova/tests/unit/virt/xenapi/test_vif.py @@ -23,6 +23,7 @@ from nova.tests.unit.virt.xenapi import stubs from nova.virt.xenapi import network_utils from nova.virt.xenapi import vif from nova.virt.xenapi import vm_utils +import os_xenapi fake_vif = { @@ -237,17 +238,14 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase): @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_delete_linux_bridge') @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_delete_linux_port') - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_device_exists') - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_br') - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_port') + @mock.patch.object(os_xenapi.client.host_network, 'ovs_del_br') + @mock.patch.object(os_xenapi.client.host_network, 'ovs_del_port') @mock.patch.object(network_utils, 'find_network_with_name_label') def test_delete_network_and_bridge(self, mock_find_network, mock_ovs_del_port, mock_ovs_del_br, - mock_device_exists, mock_delete_linux_port, mock_delete_linux_bridge): mock_find_network.return_value = 'fake_network' - mock_device_exists.return_value = True instance = {'name': 'fake_instance'} vif = {'id': 'fake_vif'} self._session.network = mock.Mock() @@ -261,7 +259,7 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase): self.assertTrue(mock_delete_linux_bridge.called) self.assertTrue(mock_ovs_del_br.called) - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_del_port') + @mock.patch.object(os_xenapi.client.host_network, 'ovs_del_port') @mock.patch.object(network_utils, 'find_network_with_name_label', return_value='fake_network') def test_delete_network_and_bridge_destroy_exception(self, @@ -283,9 +281,9 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase): self.assertTrue(mock_ovs_del_port.called) @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_device_exists') - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_brctl_add_if') + @mock.patch.object(os_xenapi.client.host_network, 'brctl_add_if') @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_create_linux_bridge') - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_add_port') + @mock.patch.object(os_xenapi.client.host_network, 'ovs_add_port') def test_post_start_actions(self, mock_ovs_add_port, mock_create_linux_bridge, mock_brctl_add_if, mock_device_exists): @@ -317,9 +315,9 @@ class XenAPIOpenVswitchDriverTestCase(XenVIFDriverTestBase): self.assertTrue(mock_brctl_add_if.called) @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_device_exists') - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_brctl_add_if') + @mock.patch.object(os_xenapi.client.host_network, 'brctl_add_if') @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_create_linux_bridge') - @mock.patch.object(vif.XenAPIOpenVswitchDriver, '_ovs_add_port') + @mock.patch.object(os_xenapi.client.host_network, 'ovs_add_port') def test_post_start_actions_tap_exist(self, mock_ovs_add_port, mock_create_linux_bridge, mock_brctl_add_if, mock_device_exists): diff --git a/nova/tests/unit/virt/xenapi/test_vm_utils.py b/nova/tests/unit/virt/xenapi/test_vm_utils.py index a42dfe9932..707931cdcb 100644 --- a/nova/tests/unit/virt/xenapi/test_vm_utils.py +++ b/nova/tests/unit/virt/xenapi/test_vm_utils.py @@ -18,6 +18,7 @@ import contextlib from eventlet import greenthread import mock from mox3 import mox +import os_xenapi from oslo_concurrency import lockutils from oslo_concurrency import processutils from oslo_config import fixture as config_fixture @@ -1003,24 +1004,23 @@ class VDIOtherConfigTestCase(VMUtilsTestBase): self.assertEqual(expected, other_config) - def test_import_migrated_vhds(self): + @mock.patch.object(os_xenapi.client.vm_management, 'receive_vhd') + @mock.patch.object(vm_utils, 'scan_default_sr') + @mock.patch.object(vm_utils, 'get_sr_path') + def test_import_migrated_vhds(self, mock_sr_path, mock_scan_sr, + mock_recv_vhd): # Migrated images should preserve the `other_config` other_config = {} def VDI_add_to_other_config(ref, key, value): other_config[key] = value - def call_plugin_serialized(*args, **kwargs): - return {'root': {'uuid': 'aaaa-bbbb-cccc-dddd'}} - # Stubbing on the session object and not class so we don't pollute # other tests self.session.VDI_add_to_other_config = VDI_add_to_other_config self.session.VDI_get_other_config = lambda vdi: {} - self.session.call_plugin_serialized = call_plugin_serialized - self.stubs.Set(vm_utils, 'get_sr_path', lambda *a, **k: None) - self.stubs.Set(vm_utils, 'scan_default_sr', lambda *a, **k: None) + mock_sr_path.return_value = {'root': {'uuid': 'aaaa-bbbb-cccc-dddd'}} vm_utils._import_migrated_vhds(self.session, self.fake_instance, "disk_label", "root", "vdi_label") @@ -1029,6 +1029,11 @@ class VDIOtherConfigTestCase(VMUtilsTestBase): 'nova_instance_uuid': 'aaaa-bbbb-cccc-dddd'} self.assertEqual(expected, other_config) + mock_scan_sr.assert_called_once_with(self.session) + mock_recv_vhd.assert_called_with( + self.session, "disk_label", + {'root': {'uuid': 'aaaa-bbbb-cccc-dddd'}}, mock.ANY) + mock_sr_path.assert_called_once_with(self.session) class GenerateDiskTestCase(VMUtilsTestBase): @@ -1367,7 +1372,9 @@ class CreateKernelRamdiskTestCase(VMUtilsTestBase): self.session, self.instance, self.name_label) self.assertEqual((None, None), result) - def test_create_kernel_and_ramdisk_create_both_cached(self): + @mock.patch.object(os_xenapi.client.disk_management, + 'create_kernel_ramdisk') + def test_create_kernel_and_ramdisk_create_both_cached(self, mock_ramdisk): kernel_id = "kernel" ramdisk_id = "ramdisk" self.instance["kernel_id"] = kernel_id @@ -1377,22 +1384,22 @@ class CreateKernelRamdiskTestCase(VMUtilsTestBase): args_kernel['cached-image'] = kernel_id args_kernel['new-image-uuid'] = "fake_uuid1" uuidutils.generate_uuid().AndReturn("fake_uuid1") - self.session.call_plugin('kernel.py', 'create_kernel_ramdisk', - args_kernel).AndReturn("k") + mock_ramdisk.side_effect = ["k", "r"] args_ramdisk = {} args_ramdisk['cached-image'] = ramdisk_id args_ramdisk['new-image-uuid'] = "fake_uuid2" uuidutils.generate_uuid().AndReturn("fake_uuid2") - self.session.call_plugin('kernel.py', 'create_kernel_ramdisk', - args_ramdisk).AndReturn("r") self.mox.ReplayAll() result = vm_utils.create_kernel_and_ramdisk(self.context, self.session, self.instance, self.name_label) self.assertEqual(("k", "r"), result) - def test_create_kernel_and_ramdisk_create_kernel_not_cached(self): + @mock.patch.object(os_xenapi.client.disk_management, + 'create_kernel_ramdisk') + def test_create_kernel_and_ramdisk_create_kernel_not_cached(self, + mock_ramdisk): kernel_id = "kernel" self.instance["kernel_id"] = kernel_id @@ -1400,8 +1407,7 @@ class CreateKernelRamdiskTestCase(VMUtilsTestBase): args_kernel['cached-image'] = kernel_id args_kernel['new-image-uuid'] = "fake_uuid1" uuidutils.generate_uuid().AndReturn("fake_uuid1") - self.session.call_plugin('kernel.py', 'create_kernel_ramdisk', - args_kernel).AndReturn("") + mock_ramdisk.return_value = "" kernel = {"kernel": {"file": "k"}} vm_utils._fetch_disk_image(self.context, self.session, self.instance, @@ -1423,8 +1429,6 @@ class CreateKernelRamdiskTestCase(VMUtilsTestBase): if cache_images == 'all': uuidutils.generate_uuid().AndReturn("fake_uuid1") - self.session.call_plugin('kernel.py', 'create_kernel_ramdisk', - args_kernel).AndReturn("cached_image") else: kernel = {"kernel": {"file": "new_image", "uuid": None}} vm_utils._fetch_disk_image(self.context, self.session, @@ -1446,8 +1450,13 @@ class CreateKernelRamdiskTestCase(VMUtilsTestBase): self.assertEqual(result, {"kernel": {"file": "new_image", "uuid": None}}) - def test_create_kernel_image_cached_config(self): + @mock.patch.object(os_xenapi.client.disk_management, + 'create_kernel_ramdisk') + def test_create_kernel_image_cached_config(self, mock_ramdisk): + mock_ramdisk.return_value = "cached_image" self._test_create_kernel_image('all') + mock_ramdisk.assert_called_once_with(self.session, "kernel", + "fake_uuid1") def test_create_kernel_image_uncached_config(self): self._test_create_kernel_image('none') @@ -2020,14 +2029,15 @@ class ImportMigratedDisksTestCase(VMUtilsTestBase): vm_utils._import_migrate_ephemeral_disks("s", instance) mock_get_sizes.assert_called_once_with(4000) + @mock.patch.object(os_xenapi.client.vm_management, 'receive_vhd') @mock.patch.object(vm_utils, '_set_vdi_info') @mock.patch.object(vm_utils, 'scan_default_sr') @mock.patch.object(vm_utils, 'get_sr_path') def test_import_migrated_vhds(self, mock_get_sr_path, mock_scan_sr, - mock_set_info): + mock_set_info, mock_recv_vhd): session = mock.Mock() instance = {"uuid": "uuid"} - session.call_plugin_serialized.return_value = {"root": {"uuid": "a"}} + mock_recv_vhd.return_value = {"root": {"uuid": "a"}} session.call_xenapi.return_value = "vdi_ref" mock_get_sr_path.return_value = "sr_path" @@ -2037,9 +2047,8 @@ class ImportMigratedDisksTestCase(VMUtilsTestBase): expected = {'uuid': "a", 'ref': "vdi_ref"} self.assertEqual(expected, result) mock_get_sr_path.assert_called_once_with(session) - session.call_plugin_serialized.assert_called_once_with('migration.py', - 'move_vhds_into_sr', instance_uuid='chain_label', - sr_path='sr_path', uuid_stack=mock.ANY) + mock_recv_vhd.assert_called_once_with(session, 'chain_label', + 'sr_path', mock.ANY) mock_scan_sr.assert_called_once_with(session) session.call_xenapi.assert_called_once_with('VDI.get_by_uuid', 'a') mock_set_info.assert_called_once_with(session, 'vdi_ref', 'disk_type', @@ -2061,33 +2070,42 @@ class MigrateVHDTestCase(VMUtilsTestBase): 'migration.py', 'transfer_vhd', instance_uuid=label, host="dest", vdi_uuid="vdi_uuid", sr_path="sr_path", seq_num=2) - def test_migrate_vhd_root(self): + @mock.patch.object(os_xenapi.client.vm_management, 'transfer_vhd') + def test_migrate_vhd_root(self, mock_trans_vhd): session = mock.Mock() instance = {"uuid": "a"} vm_utils.migrate_vhd(session, instance, "vdi_uuid", "dest", "sr_path", 2) - self._assert_transfer_called(session, "a") + mock_trans_vhd.assert_called_once_with(session, "a", + "dest", "vdi_uuid", "sr_path", + 2) - def test_migrate_vhd_ephemeral(self): + @mock.patch.object(os_xenapi.client.vm_management, 'transfer_vhd') + def test_migrate_vhd_ephemeral(self, mock_trans_vhd): session = mock.Mock() instance = {"uuid": "a"} vm_utils.migrate_vhd(session, instance, "vdi_uuid", "dest", "sr_path", 2, 2) - self._assert_transfer_called(session, "a_ephemeral_2") + mock_trans_vhd.assert_called_once_with(session, "a_ephemeral_2", + "dest", "vdi_uuid", "sr_path", + 2) - def test_migrate_vhd_converts_exceptions(self): + @mock.patch.object(os_xenapi.client.vm_management, 'transfer_vhd') + def test_migrate_vhd_converts_exceptions(self, mock_trans_vhd): session = mock.Mock() session.XenAPI.Failure = test.TestingException - session.call_plugin_serialized.side_effect = test.TestingException() + mock_trans_vhd.side_effect = test.TestingException() instance = {"uuid": "a"} self.assertRaises(exception.MigrationError, vm_utils.migrate_vhd, session, instance, "vdi_uuid", "dest", "sr_path", 2) - self._assert_transfer_called(session, "a") + mock_trans_vhd.assert_called_once_with(session, "a", + "dest", "vdi_uuid", "sr_path", + 2) class StripBaseMirrorTestCase(VMUtilsTestBase): diff --git a/nova/tests/unit/virt/xenapi/test_vmops.py b/nova/tests/unit/virt/xenapi/test_vmops.py index 0ff4d434b9..83cc845674 100644 --- a/nova/tests/unit/virt/xenapi/test_vmops.py +++ b/nova/tests/unit/virt/xenapi/test_vmops.py @@ -22,6 +22,7 @@ except ImportError: from eventlet import greenthread import mock +from os_xenapi.client import host_xenstore from os_xenapi.client import session as xenapi_session import six @@ -1307,35 +1308,43 @@ class XenstoreCallsTestCase(VMOpsTestBase): from vmops. """ - @mock.patch.object(vmops.VMOps, '_make_plugin_call') - def test_read_from_xenstore(self, fake_xapi_call): - fake_xapi_call.return_value = "fake_xapi_return" + @mock.patch.object(vmops.VMOps, '_get_dom_id') + @mock.patch.object(host_xenstore, 'read_record') + def test_read_from_xenstore(self, mock_read_record, mock_dom_id): + mock_read_record.return_value = "fake_xapi_return" + mock_dom_id.return_value = "fake_dom_id" fake_instance = {"name": "fake_instance"} path = "attr/PVAddons/MajorVersion" self.assertEqual("fake_xapi_return", self.vmops._read_from_xenstore(fake_instance, path, vm_ref="vm_ref")) - - @mock.patch.object(vmops.VMOps, '_make_plugin_call') - def test_read_from_xenstore_ignore_missing_path(self, fake_xapi_call): + mock_dom_id.assert_called_once_with(fake_instance, "vm_ref") + + @mock.patch.object(vmops.VMOps, '_get_dom_id') + @mock.patch.object(host_xenstore, 'read_record') + def test_read_from_xenstore_ignore_missing_path(self, mock_read_record, + mock_dom_id): + mock_read_record.return_value = "fake_xapi_return" + mock_dom_id.return_value = "fake_dom_id" fake_instance = {"name": "fake_instance"} path = "attr/PVAddons/MajorVersion" self.vmops._read_from_xenstore(fake_instance, path, vm_ref="vm_ref") - fake_xapi_call.assert_called_once_with('xenstore.py', 'read_record', - fake_instance, vm_ref="vm_ref", - path=path, - ignore_missing_path='True') - - @mock.patch.object(vmops.VMOps, '_make_plugin_call') - def test_read_from_xenstore_missing_path(self, fake_xapi_call): + mock_read_record.assert_called_once_with( + self._session, "fake_dom_id", path, ignore_missing_path=True) + + @mock.patch.object(vmops.VMOps, '_get_dom_id') + @mock.patch.object(host_xenstore, 'read_record') + def test_read_from_xenstore_missing_path(self, mock_read_record, + mock_dom_id): + mock_read_record.return_value = "fake_xapi_return" + mock_dom_id.return_value = "fake_dom_id" fake_instance = {"name": "fake_instance"} path = "attr/PVAddons/MajorVersion" self.vmops._read_from_xenstore(fake_instance, path, vm_ref="vm_ref", ignore_missing_path=False) - fake_xapi_call.assert_called_once_with('xenstore.py', 'read_record', - fake_instance, vm_ref="vm_ref", - path=path, - ignore_missing_path='False') + mock_read_record.assert_called_once_with(self._session, "fake_dom_id", + path, + ignore_missing_path=False) class LiveMigrateTestCase(VMOpsTestBase): diff --git a/nova/tests/unit/virt/xenapi/test_xenapi.py b/nova/tests/unit/virt/xenapi/test_xenapi.py index 59642369ed..a980edc02c 100644 --- a/nova/tests/unit/virt/xenapi/test_xenapi.py +++ b/nova/tests/unit/virt/xenapi/test_xenapi.py @@ -24,6 +24,7 @@ import re import mock from mox3 import mox +from os_xenapi.client import host_management from os_xenapi.client import session as xenapi_session from os_xenapi.client import XenAPI from oslo_concurrency import lockutils @@ -1694,18 +1695,29 @@ class XenAPIMigrateInstance(stubs.XenAPITestBase): instance.create() return instance + @mock.patch.object(vmops.VMOps, '_migrate_disk_resizing_up') + @mock.patch.object(vm_utils, 'get_sr_path') + @mock.patch.object(vm_utils, 'lookup') @mock.patch.object(volume_utils, 'is_booted_from_volume') - def test_migrate_disk_and_power_off(self, mock_boot): + def test_migrate_disk_and_power_off(self, mock_boot_from_volume, + mock_lookup, mock_sr_path, + mock_migrate): instance = self._create_instance() xenapi_fake.create_vm(instance['name'], 'Running') flavor = fake_flavor.fake_flavor_obj(self.context, root_gb=80, ephemeral_gb=0) conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False) - vm_ref = vm_utils.lookup(conn._session, instance['name']) - volume_utils.is_booted_from_volume(conn._session, vm_ref) + mock_boot_from_volume.return_value = True + mock_lookup.return_value = 'fake_vm_ref' + mock_sr_path.return_value = 'fake_sr_path' conn.migrate_disk_and_power_off(self.context, instance, '127.0.0.1', flavor, None) - mock_boot.assert_any_call(conn._session, vm_ref) + mock_lookup.assert_called_once_with(conn._session, instance['name'], + False) + mock_sr_path.assert_called_once_with(conn._session) + mock_migrate.assert_called_once_with(self.context, instance, + '127.0.0.1', 'fake_vm_ref', + 'fake_sr_path') def test_migrate_disk_and_power_off_passes_exceptions(self): instance = self._create_instance() @@ -1735,20 +1747,31 @@ class XenAPIMigrateInstance(stubs.XenAPITestBase): self.context, instance, 'fake_dest', flavor, None) + @mock.patch.object(vmops.VMOps, '_migrate_disk_resizing_up') + @mock.patch.object(vm_utils, 'get_sr_path') + @mock.patch.object(vm_utils, 'lookup') @mock.patch.object(volume_utils, 'is_booted_from_volume') - def test_migrate_disk_and_power_off_with_zero_gb_old_and_new_works(self, - mock_boot): + def test_migrate_disk_and_power_off_with_zero_gb_old_and_new_works( + self, mock_boot_from_volume, mock_lookup, mock_sr_path, + mock_migrate): flavor = fake_flavor.fake_flavor_obj(self.context, root_gb=0, ephemeral_gb=0) instance = self._create_instance(root_gb=0, ephemeral_gb=0) instance.flavor.root_gb = 0 instance.flavor.ephemeral_gb = 0 xenapi_fake.create_vm(instance['name'], 'Running') + mock_boot_from_volume.return_value = True + mock_lookup.return_value = 'fake_vm_ref' + mock_sr_path.return_value = 'fake_sr_path' conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False) - vm_ref = vm_utils.lookup(conn._session, instance['name']) conn.migrate_disk_and_power_off(self.context, instance, '127.0.0.1', flavor, None) - mock_boot.assert_any_call(conn._session, vm_ref) + mock_lookup.assert_called_once_with(conn._session, instance['name'], + False) + mock_sr_path.assert_called_once_with(conn._session) + mock_migrate.assert_called_once_with(self.context, instance, + '127.0.0.1', 'fake_vm_ref', + 'fake_sr_path') def _test_revert_migrate(self, power_on): instance = create_instance_with_system_metadata(self.context, @@ -2234,12 +2257,15 @@ class XenAPIHostTestCase(stubs.XenAPITestBase): stats = self.conn.host_state.get_host_stats(False) self.assertEqual("SOMERETURNVALUE", stats['supported_instances']) - def test_update_stats_caches_hostname(self): - self.mox.StubOutWithMock(host, 'call_xenhost') - self.mox.StubOutWithMock(vm_utils, 'scan_default_sr') - self.mox.StubOutWithMock(vm_utils, 'list_vms') - self.mox.StubOutWithMock(self.conn._session, 'call_xenapi') - self.mox.StubOutWithMock(host.HostState, 'get_disk_used') + @mock.patch.object(host.HostState, 'get_disk_used') + @mock.patch.object(host.HostState, '_get_passthrough_devices') + @mock.patch.object(jsonutils, 'loads') + @mock.patch.object(vm_utils, 'list_vms') + @mock.patch.object(vm_utils, 'scan_default_sr') + @mock.patch.object(host_management, 'get_host_data') + def test_update_stats_caches_hostname(self, mock_host_data, mock_scan_sr, + mock_list_vms, mock_loads, + mock_devices, mock_dis_used): data = {'disk_total': 0, 'disk_used': 0, 'disk_available': 0, @@ -2253,23 +2279,26 @@ class XenAPIHostTestCase(stubs.XenAPITestBase): 'physical_utilisation': 0, 'virtual_allocation': 0, } - - for i in range(3): - host.call_xenhost(mox.IgnoreArg(), 'host_data', {}).AndReturn(data) - vm_utils.scan_default_sr(self.conn._session).AndReturn("ref") - vm_utils.list_vms(self.conn._session).AndReturn([]) - self.conn._session.call_xenapi('SR.get_record', "ref").AndReturn( - sr_rec) - host.HostState.get_disk_used("ref").AndReturn((0, 0)) - if i == 2: - # On the third call (the second below) change the hostname - data = dict(data, host_hostname='bar') - - self.mox.ReplayAll() - stats = self.conn.host_state.get_host_stats(refresh=True) - self.assertEqual('foo', stats['hypervisor_hostname']) - stats = self.conn.host_state.get_host_stats(refresh=True) - self.assertEqual('foo', stats['hypervisor_hostname']) + mock_loads.return_value = data + mock_host_data.return_value = data + mock_scan_sr.return_value = 'ref' + mock_list_vms.return_value = [] + mock_devices.return_value = "dev1" + mock_dis_used.return_value = (0, 0) + self.conn._session = mock.Mock() + with mock.patch.object(self.conn._session.SR, 'get_record') \ + as mock_record: + mock_record.return_value = sr_rec + stats = self.conn.host_state.get_host_stats(refresh=True) + self.assertEqual('foo', stats['hypervisor_hostname']) + self.assertEqual(2, mock_loads.call_count) + self.assertEqual(2, mock_host_data.call_count) + self.assertEqual(2, mock_scan_sr.call_count) + self.assertEqual(2, mock_devices.call_count) + mock_loads.assert_called_with(data) + mock_host_data.assert_called_with(self.conn._session) + mock_scan_sr.assert_called_with(self.conn._session) + mock_devices.assert_called_with() @mock.patch.object(host.HostState, 'update_status') |