XenAPI Use os-xenapi lib for nova

XenServer has released os-xenapi lib on pypi, this patch is to
use os-xenapi in nova project. In this patch, we only change
the usage of XenAPI to os-xenapi and fix unit tests. In the next
patch, we will delete those unused files.

Partially-Implements: blueprint add-os-xenapi-library

Depends-On: Ic327135b893a77672fd42af919f47f181e932773

Change-Id: I424dfcd507c4b7fbeea5245cc1c234dec01d5781
This commit is contained in:
Huan Xie
2016-12-01 22:33:30 -08:00
parent 8e3e9f6d2d
commit 062065ca9e
12 changed files with 67 additions and 246 deletions

View File

@@ -14,12 +14,12 @@
# under the License. # under the License.
import mock import mock
from os_xenapi import client
import six import six
from nova import context from nova import context
from nova import test from nova import test
from nova.tests.unit.virt.xenapi import stubs from nova.tests.unit.virt.xenapi import stubs
from nova.virt.xenapi import client
from nova.virt.xenapi import driver as xenapi_conn from nova.virt.xenapi import driver as xenapi_conn
from nova.virt.xenapi import fake from nova.virt.xenapi import fake
from nova.virt.xenapi.image import bittorrent from nova.virt.xenapi.image import bittorrent

View File

@@ -18,7 +18,7 @@ import time
import mock import mock
from mox3 import mox from mox3 import mox
from oslo_log import log as logging from os_xenapi.client import XenAPI
from nova.compute import utils as compute_utils from nova.compute import utils as compute_utils
from nova import context from nova import context
@@ -93,9 +93,7 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
@mock.patch.object(random, 'shuffle') @mock.patch.object(random, 'shuffle')
@mock.patch.object(time, 'sleep') @mock.patch.object(time, 'sleep')
@mock.patch.object(compute_utils, 'add_instance_fault_from_exc') @mock.patch.object(compute_utils, 'add_instance_fault_from_exc')
@mock.patch.object(logging.getLogger('nova.virt.xenapi.client.session'), def test_download_image_retry(self, mock_fault, mock_sleep,
'debug')
def test_download_image_retry(self, mock_log_debug, mock_fault, mock_sleep,
mock_shuffle, mock_make_uuid_stack): mock_shuffle, mock_make_uuid_stack):
params = self._get_download_params() params = self._get_download_params()
self.flags(num_retries=2, group='glance') self.flags(num_retries=2, group='glance')
@@ -107,16 +105,6 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
mock.call('glance.py', 'download_vhd2', mock.call('glance.py', 'download_vhd2',
endpoint='http://10.0.0.1:9293', endpoint='http://10.0.0.1:9293',
**params)] **params)]
log_calls = [mock.call(mock.ANY,
{'callback_result': 'http://10.0.1.1:9292',
'attempts': 3, 'attempt': 1,
'fn': 'download_vhd2',
'plugin': 'glance.py'}),
mock.call(mock.ANY,
{'callback_result': 'http://10.0.0.1:9293',
'attempts': 3, 'attempt': 2,
'fn': 'download_vhd2',
'plugin': 'glance.py'})]
glance_api_servers = ['10.0.1.1:9292', glance_api_servers = ['10.0.1.1:9292',
'http://10.0.0.1:9293'] 'http://10.0.0.1:9293']
@@ -132,7 +120,6 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
self.instance, 'fake_image_uuid') self.instance, 'fake_image_uuid')
mock_call_plugin_serialized.assert_has_calls(calls) mock_call_plugin_serialized.assert_has_calls(calls)
mock_log_debug.assert_has_calls(log_calls, any_order=True)
self.assertEqual(1, mock_fault.call_count) self.assertEqual(1, mock_fault.call_count)
@@ -197,21 +184,21 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
self.session.call_plugin_serialized('glance.py', 'upload_vhd2', self.session.call_plugin_serialized('glance.py', 'upload_vhd2',
**params).AndRaise(error) **params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance, compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure, error, (XenAPI.Failure,
error, error,
mox.IgnoreArg())) mox.IgnoreArg()))
time.sleep(0.5) time.sleep(0.5)
self.session.call_plugin_serialized('glance.py', 'upload_vhd2', self.session.call_plugin_serialized('glance.py', 'upload_vhd2',
**params).AndRaise(error) **params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance, compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure, error, (XenAPI.Failure,
error, error,
mox.IgnoreArg())) mox.IgnoreArg()))
time.sleep(1) time.sleep(1)
self.session.call_plugin_serialized('glance.py', 'upload_vhd2', self.session.call_plugin_serialized('glance.py', 'upload_vhd2',
**params).AndRaise(error) **params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance, compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure, error, (XenAPI.Failure,
error, error,
mox.IgnoreArg())) mox.IgnoreArg()))
self.mox.ReplayAll() self.mox.ReplayAll()
@@ -234,7 +221,7 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
self.session.call_plugin_serialized('glance.py', 'upload_vhd2', self.session.call_plugin_serialized('glance.py', 'upload_vhd2',
**params).AndRaise(error) **params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance, compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure, error, (XenAPI.Failure,
error, error,
mox.IgnoreArg())) mox.IgnoreArg()))
time.sleep(0.5) time.sleep(0.5)
@@ -244,7 +231,7 @@ class TestGlanceStore(stubs.XenAPITestBaseNoDB):
self.session.call_plugin_serialized('glance.py', 'upload_vhd2', self.session.call_plugin_serialized('glance.py', 'upload_vhd2',
**params).AndRaise(error) **params).AndRaise(error)
compute_utils.add_instance_fault_from_exc(self.context, self.instance, compute_utils.add_instance_fault_from_exc(self.context, self.instance,
error, (fake.Failure, error, (XenAPI.Failure,
error, error,
mox.IgnoreArg())) mox.IgnoreArg()))
time.sleep(1) time.sleep(1)

View File

@@ -17,11 +17,11 @@ import contextlib
import tarfile import tarfile
import eventlet import eventlet
from os_xenapi.client import session as xenapi_session
import six import six
from nova.image import glance from nova.image import glance
from nova import test from nova import test
from nova.virt.xenapi.client import session as xenapi_session
from nova.virt.xenapi.image import vdi_through_dev from nova.virt.xenapi.image import vdi_through_dev

View File

@@ -19,12 +19,13 @@ import sys
import fixtures import fixtures
import mock import mock
from os_xenapi.client import session
from os_xenapi.client import XenAPI
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
import six import six
from nova import test from nova import test
import nova.tests.unit.image.fake import nova.tests.unit.image.fake
from nova.virt.xenapi.client import session
from nova.virt.xenapi import fake from nova.virt.xenapi import fake
from nova.virt.xenapi import vm_utils from nova.virt.xenapi import vm_utils
from nova.virt.xenapi import vmops from nova.virt.xenapi import vmops
@@ -121,7 +122,7 @@ def stubout_fetch_disk_image(stubs, raise_failure=False):
def _fake_fetch_disk_image(context, session, instance, name_label, image, def _fake_fetch_disk_image(context, session, instance, name_label, image,
image_type): image_type):
if raise_failure: if raise_failure:
raise fake.Failure("Test Exception raised by " raise XenAPI.Failure("Test Exception raised by "
"fake fetch_image_glance_disk") "fake fetch_image_glance_disk")
elif image_type == vm_utils.ImageType.KERNEL: elif image_type == vm_utils.ImageType.KERNEL:
filename = "kernel" filename = "kernel"
@@ -140,7 +141,7 @@ def stubout_create_vm(stubs):
"""Simulates a failure in create_vm.""" """Simulates a failure in create_vm."""
def f(*args): def f(*args):
raise fake.Failure("Test Exception raised by fake create_vm") raise XenAPI.Failure("Test Exception raised by fake create_vm")
stubs.Set(vm_utils, 'create_vm', f) stubs.Set(vm_utils, 'create_vm', f)
@@ -148,7 +149,7 @@ def stubout_attach_disks(stubs):
"""Simulates a failure in _attach_disks.""" """Simulates a failure in _attach_disks."""
def f(*args): def f(*args):
raise fake.Failure("Test Exception raised by fake _attach_disks") raise XenAPI.Failure("Test Exception raised by fake _attach_disks")
stubs.Set(vmops.VMOps, '_attach_disks', f) stubs.Set(vmops.VMOps, '_attach_disks', f)
@@ -187,7 +188,7 @@ class FakeSessionForVMTests(fake.SessionBase):
def VM_start(self, _1, ref, _2, _3): def VM_start(self, _1, ref, _2, _3):
vm = fake.get_record('VM', ref) vm = fake.get_record('VM', ref)
if vm['power_state'] != 'Halted': if vm['power_state'] != 'Halted':
raise fake.Failure(['VM_BAD_POWER_STATE', ref, 'Halted', raise XenAPI.Failure(['VM_BAD_POWER_STATE', ref, 'Halted',
vm['power_state']]) vm['power_state']])
vm['power_state'] = 'Running' vm['power_state'] = 'Running'
vm['is_a_template'] = False vm['is_a_template'] = False
@@ -302,7 +303,7 @@ class FakeSessionForVolumeTests(fake.SessionBase):
if rec['uuid'] == uuid: if rec['uuid'] == uuid:
valid_vdi = True valid_vdi = True
if not valid_vdi: if not valid_vdi:
raise fake.Failure([['INVALID_VDI', 'session', self._session]]) raise XenAPI.Failure([['INVALID_VDI', 'session', self._session]])
class FakeSessionForVolumeFailedTests(FakeSessionForVolumeTests): class FakeSessionForVolumeFailedTests(FakeSessionForVolumeTests):
@@ -310,7 +311,7 @@ class FakeSessionForVolumeFailedTests(FakeSessionForVolumeTests):
def VDI_introduce(self, _1, uuid, _2, _3, _4, _5, def VDI_introduce(self, _1, uuid, _2, _3, _4, _5,
_6, _7, _8, _9, _10, _11): _6, _7, _8, _9, _10, _11):
# This is for testing failure # This is for testing failure
raise fake.Failure([['INVALID_VDI', 'session', self._session]]) raise XenAPI.Failure([['INVALID_VDI', 'session', self._session]])
def PBD_unplug(self, _1, ref): def PBD_unplug(self, _1, ref):
rec = fake.get_record('PBD', ref) rec = fake.get_record('PBD', ref)
@@ -367,14 +368,14 @@ def stub_out_migration_methods(stubs):
class FakeSessionForFailedMigrateTests(FakeSessionForVMTests): class FakeSessionForFailedMigrateTests(FakeSessionForVMTests):
def VM_assert_can_migrate(self, session, vmref, migrate_data, def VM_assert_can_migrate(self, session, vmref, migrate_data,
live, vdi_map, vif_map, options): live, vdi_map, vif_map, options):
raise fake.Failure("XenAPI VM.assert_can_migrate failed") raise XenAPI.Failure("XenAPI VM.assert_can_migrate failed")
def host_migrate_receive(self, session, hostref, networkref, options): def host_migrate_receive(self, session, hostref, networkref, options):
raise fake.Failure("XenAPI host.migrate_receive failed") raise XenAPI.Failure("XenAPI host.migrate_receive failed")
def VM_migrate_send(self, session, vmref, migrate_data, islive, vdi_map, def VM_migrate_send(self, session, vmref, migrate_data, islive, vdi_map,
vif_map, options): vif_map, options):
raise fake.Failure("XenAPI VM.migrate_send failed") raise XenAPI.Failure("XenAPI VM.migrate_send failed")
def get_fake_session(error=None): def get_fake_session(error=None):

View File

@@ -18,11 +18,11 @@ import time
import uuid import uuid
import mock import mock
from os_xenapi.client import XenAPI
from nova import exception from nova import exception
from nova import test from nova import test
from nova.virt.xenapi import agent from nova.virt.xenapi import agent
from nova.virt.xenapi import fake as xenapi_fake
def _get_fake_instance(**kwargs): def _get_fake_instance(**kwargs):
@@ -369,7 +369,7 @@ class CallAgentTestCase(AgentTestCaseBase):
def _call_agent_setup(self, session, mock_uuid, def _call_agent_setup(self, session, mock_uuid,
returncode='0', success_codes=None, returncode='0', success_codes=None,
exception=None): exception=None):
session.XenAPI.Failure = xenapi_fake.Failure session.XenAPI.Failure = XenAPI.Failure
instance = {"uuid": "fake"} instance = {"uuid": "fake"}
session.VM.get_domid.return_value = "42" session.VM.get_domid.return_value = "42"
@@ -402,7 +402,7 @@ class CallAgentTestCase(AgentTestCaseBase):
session = mock.Mock() session = mock.Mock()
self.assertRaises(exception.AgentTimeout, self._call_agent_setup, self.assertRaises(exception.AgentTimeout, self._call_agent_setup,
session, mock_uuid, session, mock_uuid,
exception=xenapi_fake.Failure(["TIMEOUT:fake"])) exception=XenAPI.Failure(["TIMEOUT:fake"]))
self._assert_agent_called(session, mock_uuid) self._assert_agent_called(session, mock_uuid)
def test_call_agent_fails_with_not_implemented(self, mock_uuid): def test_call_agent_fails_with_not_implemented(self, mock_uuid):
@@ -410,14 +410,14 @@ class CallAgentTestCase(AgentTestCaseBase):
self.assertRaises(exception.AgentNotImplemented, self.assertRaises(exception.AgentNotImplemented,
self._call_agent_setup, self._call_agent_setup,
session, mock_uuid, session, mock_uuid,
exception=xenapi_fake.Failure(["NOT IMPLEMENTED:"])) exception=XenAPI.Failure(["NOT IMPLEMENTED:"]))
self._assert_agent_called(session, mock_uuid) self._assert_agent_called(session, mock_uuid)
def test_call_agent_fails_with_other_error(self, mock_uuid): def test_call_agent_fails_with_other_error(self, mock_uuid):
session = mock.Mock() session = mock.Mock()
self.assertRaises(exception.AgentError, self._call_agent_setup, self.assertRaises(exception.AgentError, self._call_agent_setup,
session, mock_uuid, session, mock_uuid,
exception=xenapi_fake.Failure(["asdf"])) exception=XenAPI.Failure(["asdf"]))
self._assert_agent_called(session, mock_uuid) self._assert_agent_called(session, mock_uuid)
def test_call_agent_fails_with_returned_error(self, mock_uuid): def test_call_agent_fails_with_returned_error(self, mock_uuid):

View File

@@ -22,6 +22,7 @@ except ImportError:
from eventlet import greenthread from eventlet import greenthread
import mock import mock
from os_xenapi.client import session as xenapi_session
from nova.compute import power_state from nova.compute import power_state
from nova.compute import task_states from nova.compute import task_states
@@ -38,7 +39,6 @@ from nova.tests import uuidsentinel as uuids
from nova import utils from nova import utils
from nova.virt import fake from nova.virt import fake
from nova.virt.xenapi import agent as xenapi_agent from nova.virt.xenapi import agent as xenapi_agent
from nova.virt.xenapi.client import session as xenapi_session
from nova.virt.xenapi import fake as xenapi_fake from nova.virt.xenapi import fake as xenapi_fake
from nova.virt.xenapi import vm_utils from nova.virt.xenapi import vm_utils
from nova.virt.xenapi import vmops from nova.virt.xenapi import vmops

View File

@@ -24,6 +24,8 @@ import re
import mock import mock
from mox3 import mox from mox3 import mox
from os_xenapi.client import session as xenapi_session
from os_xenapi.client import XenAPI
from oslo_concurrency import lockutils from oslo_concurrency import lockutils
from oslo_config import fixture as config_fixture from oslo_config import fixture as config_fixture
from oslo_log import log as logging from oslo_log import log as logging
@@ -62,7 +64,6 @@ from nova.tests.unit.virt.xenapi import stubs
from nova.tests import uuidsentinel as uuids from nova.tests import uuidsentinel as uuids
from nova.virt import fake from nova.virt import fake
from nova.virt.xenapi import agent from nova.virt.xenapi import agent
from nova.virt.xenapi.client import session as xenapi_session
from nova.virt.xenapi import driver as xenapi_conn from nova.virt.xenapi import driver as xenapi_conn
from nova.virt.xenapi import fake as xenapi_fake from nova.virt.xenapi import fake as xenapi_fake
from nova.virt.xenapi import host from nova.virt.xenapi import host
@@ -841,7 +842,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
vdi_recs_start = self._list_vdis() vdi_recs_start = self._list_vdis()
start_vms = self._list_vms() start_vms = self._list_vms()
stubs.stubout_fetch_disk_image(self.stubs, raise_failure=True) stubs.stubout_fetch_disk_image(self.stubs, raise_failure=True)
self.assertRaises(xenapi_fake.Failure, self._test_spawn, self.assertRaises(XenAPI.Failure, self._test_spawn,
IMAGE_MACHINE, IMAGE_KERNEL, IMAGE_RAMDISK) IMAGE_MACHINE, IMAGE_KERNEL, IMAGE_RAMDISK)
# No additional VDI should be found. # No additional VDI should be found.
vdi_recs_end = self._list_vdis() vdi_recs_end = self._list_vdis()
@@ -858,7 +859,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
vdi_recs_start = self._list_vdis() vdi_recs_start = self._list_vdis()
start_vms = self._list_vms() start_vms = self._list_vms()
stubs.stubout_create_vm(self.stubs) stubs.stubout_create_vm(self.stubs)
self.assertRaises(xenapi_fake.Failure, self._test_spawn, self.assertRaises(XenAPI.Failure, self._test_spawn,
IMAGE_MACHINE, IMAGE_KERNEL, IMAGE_RAMDISK) IMAGE_MACHINE, IMAGE_KERNEL, IMAGE_RAMDISK)
# No additional VDI should be found. # No additional VDI should be found.
vdi_recs_end = self._list_vdis() vdi_recs_end = self._list_vdis()
@@ -875,7 +876,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase):
stubs.stubout_attach_disks(self.stubs) stubs.stubout_attach_disks(self.stubs)
vdi_recs_start = self._list_vdis() vdi_recs_start = self._list_vdis()
start_vms = self._list_vms() start_vms = self._list_vms()
self.assertRaises(xenapi_fake.Failure, self._test_spawn, self.assertRaises(XenAPI.Failure, self._test_spawn,
IMAGE_MACHINE, IMAGE_KERNEL, IMAGE_RAMDISK) IMAGE_MACHINE, IMAGE_KERNEL, IMAGE_RAMDISK)
# No additional VDI should be found. # No additional VDI should be found.
vdi_recs_end = self._list_vdis() vdi_recs_end = self._list_vdis()
@@ -1219,7 +1220,7 @@ iface eth0 inet6 static
def fake_agent_call(self, method, args): def fake_agent_call(self, method, args):
if failure: if failure:
raise xenapi_fake.Failure([failure]) raise XenAPI.Failure([failure])
else: else:
return value return value
@@ -1398,7 +1399,7 @@ iface eth0 inet6 static
instance = self._create_instance(spawn=False) instance = self._create_instance(spawn=False)
conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False) conn = xenapi_conn.XenAPIDriver(fake.FakeVirtAPI(), False)
xenapi_fake.create_vm(instance['name'], 'Unknown') xenapi_fake.create_vm(instance['name'], 'Unknown')
self.assertRaises(xenapi_fake.Failure, conn.reboot, self.context, self.assertRaises(XenAPI.Failure, conn.reboot, self.context,
instance, None, "SOFT") instance, None, "SOFT")
def test_reboot_rescued(self): def test_reboot_rescued(self):
@@ -1492,34 +1493,6 @@ iface eth0 inet6 static
expected_name) expected_name)
self.assertEqual(inst_uuid, fake_inst['uuid']) self.assertEqual(inst_uuid, fake_inst['uuid'])
def test_session_virtapi(self):
was = {'called': False}
def fake_aggregate_get_by_host(self, *args, **kwargs):
was['called'] = True
raise test.TestingException()
self.stub_out("nova.db.aggregate_get_by_host",
fake_aggregate_get_by_host)
self.stubs.Set(self.conn._session, "is_slave", True)
self.assertRaises(test.TestingException,
self.conn._session._get_host_uuid)
self.assertTrue(was['called'])
def test_session_handles_aggregate_metadata(self):
def fake_aggregate_get(context, host, key):
agg = copy.copy(test_aggregate.fake_aggregate)
agg['metadetails'][CONF.host] = 'this_should_be_metadata'
return [agg]
self.stub_out('nova.db.aggregate_get_by_host',
fake_aggregate_get)
self.stubs.Set(self.conn._session, "is_slave", True)
self.assertEqual('this_should_be_metadata',
self.conn._session._get_host_uuid())
def test_per_instance_usage_running(self): def test_per_instance_usage_running(self):
instance = self._create_instance(spawn=True) instance = self._create_instance(spawn=True)
flavor = objects.Flavor.get_by_id(self.context, 3) flavor = objects.Flavor.get_by_id(self.context, 3)
@@ -4018,151 +3991,6 @@ class XenAPIInjectMetadataTestCase(stubs.XenAPITestBaseNoDB):
self.assertTrue(self.called_fake_get_vm_opaque_ref) self.assertTrue(self.called_fake_get_vm_opaque_ref)
class XenAPISessionTestCase(test.NoDBTestCase):
def _get_mock_xapisession(self, software_version):
class MockXapiSession(xenapi_session.XenAPISession):
def __init__(_ignore):
"Skip the superclass's dirty init"
def _get_software_version(_ignore):
return software_version
return MockXapiSession()
def test_local_session(self):
session = self._get_mock_xapisession({})
session.is_local_connection = True
session.XenAPI = self.mox.CreateMockAnything()
session.XenAPI.xapi_local().AndReturn("local_connection")
self.mox.ReplayAll()
self.assertEqual("local_connection",
session._create_session("unix://local"))
def test_remote_session(self):
session = self._get_mock_xapisession({})
session.is_local_connection = False
session.XenAPI = self.mox.CreateMockAnything()
session.XenAPI.Session("url").AndReturn("remote_connection")
self.mox.ReplayAll()
self.assertEqual("remote_connection", session._create_session("url"))
def test_get_product_version_product_brand_does_not_fail(self):
session = self._get_mock_xapisession({
'build_number': '0',
'date': '2012-08-03',
'hostname': 'komainu',
'linux': '3.2.0-27-generic',
'network_backend': 'bridge',
'platform_name': 'XCP_Kronos',
'platform_version': '1.6.0',
'xapi': '1.3',
'xen': '4.1.2',
'xencenter_max': '1.10',
'xencenter_min': '1.10'
})
self.assertEqual(
((1, 6, 0), None),
session._get_product_version_and_brand()
)
def test_get_product_version_product_brand_xs_6(self):
session = self._get_mock_xapisession({
'product_brand': 'XenServer',
'product_version': '6.0.50',
'platform_version': '0.0.1'
})
self.assertEqual(
((6, 0, 50), 'XenServer'),
session._get_product_version_and_brand()
)
def test_verify_plugin_version_same(self):
session = self._get_mock_xapisession({})
session.PLUGIN_REQUIRED_VERSION = '2.4'
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
session.call_plugin_serialized('nova_plugin_version.py', 'get_version',
).AndReturn("2.4")
self.mox.ReplayAll()
session._verify_plugin_version()
def test_verify_plugin_version_compatible(self):
session = self._get_mock_xapisession({})
session.XenAPI = xenapi_fake.FakeXenAPI()
session.PLUGIN_REQUIRED_VERSION = '2.4'
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
session.call_plugin_serialized('nova_plugin_version.py', 'get_version',
).AndReturn("2.5")
self.mox.ReplayAll()
session._verify_plugin_version()
def test_verify_plugin_version_python_extensions(self):
"""Validate that 2.0 is equivalent to 1.8."""
session = self._get_mock_xapisession({})
session.XenAPI = xenapi_fake.FakeXenAPI()
session.PLUGIN_REQUIRED_VERSION = '2.0'
with mock.patch.object(session, 'call_plugin_serialized',
return_value='1.8'):
session._verify_plugin_version()
def test_verify_plugin_version_bad_maj(self):
session = self._get_mock_xapisession({})
session.XenAPI = xenapi_fake.FakeXenAPI()
session.PLUGIN_REQUIRED_VERSION = '2.4'
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
session.call_plugin_serialized('nova_plugin_version.py', 'get_version',
).AndReturn("3.0")
self.mox.ReplayAll()
self.assertRaises(xenapi_fake.Failure, session._verify_plugin_version)
def test_verify_plugin_version_bad_min(self):
session = self._get_mock_xapisession({})
session.XenAPI = xenapi_fake.FakeXenAPI()
session.PLUGIN_REQUIRED_VERSION = '2.4'
self.mox.StubOutWithMock(session, 'call_plugin_serialized')
session.call_plugin_serialized('nova_plugin_version.py', 'get_version',
).AndReturn("2.3")
self.mox.ReplayAll()
self.assertRaises(xenapi_fake.Failure, session._verify_plugin_version)
def test_verify_current_version_matches(self):
session = self._get_mock_xapisession({})
# Import the plugin to extract its version
path = os.path.dirname(__file__)
rel_path_elem = "../../../../../plugins/xenserver/xenapi/etc/xapi.d/" \
"plugins/nova_plugin_version.py"
for elem in rel_path_elem.split('/'):
path = os.path.join(path, elem)
path = os.path.realpath(path)
plugin_version = None
with open(path) as plugin_file:
for line in plugin_file:
if "PLUGIN_VERSION = " in line:
plugin_version = line.strip()[17:].strip('"')
self.assertEqual(session.PLUGIN_REQUIRED_VERSION,
plugin_version)
class XenAPIFakeTestCase(test.NoDBTestCase): class XenAPIFakeTestCase(test.NoDBTestCase):
def test_query_matches(self): def test_query_matches(self):
record = {'a': '1', 'b': '2', 'c_d': '3'} record = {'a': '1', 'b': '2', 'c_d': '3'}

View File

@@ -25,6 +25,7 @@ A driver for XenServer or Xen Cloud Platform.
import math import math
from os_xenapi.client import session
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import units from oslo_utils import units
@@ -36,7 +37,6 @@ import nova.conf
from nova.i18n import _, _LE, _LW from nova.i18n import _, _LE, _LW
from nova import exception from nova import exception
from nova.virt import driver from nova.virt import driver
from nova.virt.xenapi.client import session
from nova.virt.xenapi import host from nova.virt.xenapi import host
from nova.virt.xenapi import pool from nova.virt.xenapi import pool
from nova.virt.xenapi import vm_utils from nova.virt.xenapi import vm_utils
@@ -79,7 +79,8 @@ class XenAPIDriver(driver.ComputeDriver):
'connection_password to use ' 'connection_password to use '
'compute_driver=xenapi.XenAPIDriver')) 'compute_driver=xenapi.XenAPIDriver'))
self._session = session.XenAPISession(url, username, password) self._session = session.XenAPISession(url, username, password,
originator="nova")
self._volumeops = volumeops.VolumeOps(self._session) self._volumeops = volumeops.VolumeOps(self._session)
self._host_state = None self._host_state = None
self._host = host.Host(self._session, self.virtapi) self._host = host.Host(self._session, self.virtapi)

View File

@@ -54,6 +54,8 @@ import random
from xml.sax import saxutils from xml.sax import saxutils
import zlib import zlib
from os_xenapi.client import session as xenapi_session
from os_xenapi.client import XenAPI
from oslo_log import log as logging from oslo_log import log as logging
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
from oslo_utils import timeutils from oslo_utils import timeutils
@@ -63,7 +65,6 @@ import six
from nova import exception from nova import exception
from nova.i18n import _ from nova.i18n import _
from nova.virt.xenapi.client import session as xenapi_session
_CLASSES = ['host', 'network', 'session', 'pool', 'SR', 'VBD', _CLASSES = ['host', 'network', 'session', 'pool', 'SR', 'VBD',
@@ -360,7 +361,7 @@ def _create_sr(table, obj):
sr_type = obj[6] sr_type = obj[6]
# Forces fake to support iscsi only # Forces fake to support iscsi only
if sr_type != 'iscsi' and sr_type != 'nfs': if sr_type != 'iscsi' and sr_type != 'nfs':
raise Failure(['SR_UNKNOWN_DRIVER', sr_type]) raise XenAPI.Failure(['SR_UNKNOWN_DRIVER', sr_type])
host_ref = list(_db_content['host'])[0] host_ref = list(_db_content['host'])[0]
sr_ref = _create_object(table, obj[2]) sr_ref = _create_object(table, obj[2])
if sr_type == 'iscsi': if sr_type == 'iscsi':
@@ -452,7 +453,7 @@ def get_record(table, ref):
if ref in _db_content[table]: if ref in _db_content[table]:
return _db_content[table].get(ref) return _db_content[table].get(ref)
else: else:
raise Failure(['HANDLE_INVALID', table, ref]) raise XenAPI.Failure(['HANDLE_INVALID', table, ref])
def check_for_session_leaks(): def check_for_session_leaks():
@@ -511,14 +512,14 @@ class SessionBase(object):
def VBD_plug(self, _1, ref): def VBD_plug(self, _1, ref):
rec = get_record('VBD', ref) rec = get_record('VBD', ref)
if rec['currently_attached']: if rec['currently_attached']:
raise Failure(['DEVICE_ALREADY_ATTACHED', ref]) raise XenAPI.Failure(['DEVICE_ALREADY_ATTACHED', ref])
rec['currently_attached'] = True rec['currently_attached'] = True
rec['device'] = 'fakedev' rec['device'] = 'fakedev'
def VBD_unplug(self, _1, ref): def VBD_unplug(self, _1, ref):
rec = get_record('VBD', ref) rec = get_record('VBD', ref)
if not rec['currently_attached']: if not rec['currently_attached']:
raise Failure(['DEVICE_ALREADY_DETACHED', ref]) raise XenAPI.Failure(['DEVICE_ALREADY_DETACHED', ref])
rec['currently_attached'] = False rec['currently_attached'] = False
rec['device'] = '' rec['device'] = ''
@@ -527,8 +528,8 @@ class SessionBase(object):
if 'other_config' not in db_ref: if 'other_config' not in db_ref:
db_ref['other_config'] = {} db_ref['other_config'] = {}
if key in db_ref['other_config']: if key in db_ref['other_config']:
raise Failure(['MAP_DUPLICATE_KEY', 'VBD', 'other_config', raise XenAPI.Failure(
vbd_ref, key]) ['MAP_DUPLICATE_KEY', 'VBD', 'other_config', vbd_ref, key])
db_ref['other_config'][key] = value db_ref['other_config'][key] = value
def VBD_get_other_config(self, _1, vbd_ref): def VBD_get_other_config(self, _1, vbd_ref):
@@ -545,7 +546,7 @@ class SessionBase(object):
def PBD_plug(self, _1, pbd_ref): def PBD_plug(self, _1, pbd_ref):
rec = get_record('PBD', pbd_ref) rec = get_record('PBD', pbd_ref)
if rec['currently_attached']: if rec['currently_attached']:
raise Failure(['DEVICE_ALREADY_ATTACHED', rec]) raise XenAPI.Failure(['DEVICE_ALREADY_ATTACHED', rec])
rec['currently_attached'] = True rec['currently_attached'] = True
sr_ref = rec['SR'] sr_ref = rec['SR']
_db_content['SR'][sr_ref]['PBDs'] = [pbd_ref] _db_content['SR'][sr_ref]['PBDs'] = [pbd_ref]
@@ -553,7 +554,7 @@ class SessionBase(object):
def PBD_unplug(self, _1, pbd_ref): def PBD_unplug(self, _1, pbd_ref):
rec = get_record('PBD', pbd_ref) rec = get_record('PBD', pbd_ref)
if not rec['currently_attached']: if not rec['currently_attached']:
raise Failure(['DEVICE_ALREADY_DETACHED', rec]) raise XenAPI.Failure(['DEVICE_ALREADY_DETACHED', rec])
rec['currently_attached'] = False rec['currently_attached'] = False
sr_ref = rec['SR'] sr_ref = rec['SR']
_db_content['SR'][sr_ref]['PBDs'].remove(pbd_ref) _db_content['SR'][sr_ref]['PBDs'].remove(pbd_ref)
@@ -625,8 +626,8 @@ class SessionBase(object):
if 'other_config' not in db_ref: if 'other_config' not in db_ref:
db_ref['other_config'] = {} db_ref['other_config'] = {}
if key in db_ref['other_config']: if key in db_ref['other_config']:
raise Failure(['MAP_DUPLICATE_KEY', 'VDI', 'other_config', raise XenAPI.Failure(
vdi_ref, key]) ['MAP_DUPLICATE_KEY', 'VDI', 'other_config', vdi_ref, key])
db_ref['other_config'][key] = value db_ref['other_config'][key] = value
def VDI_copy(self, _1, vdi_to_copy_ref, sr_ref): def VDI_copy(self, _1, vdi_to_copy_ref, sr_ref):
@@ -775,12 +776,12 @@ class SessionBase(object):
def _plugin_console_get_console_log(self, method, args): def _plugin_console_get_console_log(self, method, args):
dom_id = args["dom_id"] dom_id = args["dom_id"]
if dom_id == 0: if dom_id == 0:
raise Failure('Guest does not have a console') raise XenAPI.Failure('Guest does not have a console')
return base64.b64encode( return base64.b64encode(
zlib.compress(("dom_id: %s" % dom_id).encode('utf-8'))) zlib.compress(("dom_id: %s" % dom_id).encode('utf-8')))
def _plugin_nova_plugin_version_get_version(self, method, args): def _plugin_dom0_plugin_version_get_version(self, method, args):
return pickle.dumps("1.8") return pickle.dumps("2.0")
def _plugin_xenhost_query_gc(self, method, args): def _plugin_xenhost_query_gc(self, method, args):
return pickle.dumps("False") return pickle.dumps("False")
@@ -809,8 +810,8 @@ class SessionBase(object):
def _VM_reboot(self, session, vm_ref): def _VM_reboot(self, session, vm_ref):
db_ref = _db_content['VM'][vm_ref] db_ref = _db_content['VM'][vm_ref]
if db_ref['power_state'] != 'Running': if db_ref['power_state'] != 'Running':
raise Failure(['VM_BAD_POWER_STATE', raise XenAPI.Failure(['VM_BAD_POWER_STATE', 'fake-opaque-ref',
'fake-opaque-ref', db_ref['power_state'].lower(), 'halted']) db_ref['power_state'].lower(), 'halted'])
db_ref['power_state'] = 'Running' db_ref['power_state'] = 'Running'
db_ref['domid'] = '%d' % (random.randrange(1, 1 << 16)) db_ref['domid'] = '%d' % (random.randrange(1, 1 << 16))
@@ -975,7 +976,7 @@ class SessionBase(object):
if (field in _db_content[cls][ref]): if (field in _db_content[cls][ref]):
return _db_content[cls][ref][field] return _db_content[cls][ref][field]
else: else:
raise Failure(['HANDLE_INVALID', cls, ref]) raise XenAPI.Failure(['HANDLE_INVALID', cls, ref])
LOG.debug('Raising NotImplemented') LOG.debug('Raising NotImplemented')
raise NotImplementedError( raise NotImplementedError(
@@ -1038,7 +1039,7 @@ class SessionBase(object):
table = name.split('.')[0] table = name.split('.')[0]
ref = params[1] ref = params[1]
if ref not in _db_content[table]: if ref not in _db_content[table]:
raise Failure(['HANDLE_INVALID', table, ref]) raise XenAPI.Failure(['HANDLE_INVALID', table, ref])
# Call destroy function (if exists) # Call destroy function (if exists)
destroy_func = _destroy_functions.get('destroy_%s' % table.lower()) destroy_func = _destroy_functions.get('destroy_%s' % table.lower())
@@ -1057,7 +1058,7 @@ class SessionBase(object):
result = as_value(result) result = as_value(result)
task['result'] = result task['result'] = result
task['status'] = 'success' task['status'] = 'success'
except Failure as exc: except XenAPI.Failure as exc:
task['error_info'] = exc.details task['error_info'] = exc.details
task['status'] = 'failed' task['status'] = 'failed'
task['finished'] = timeutils.utcnow() task['finished'] = timeutils.utcnow()
@@ -1066,7 +1067,8 @@ class SessionBase(object):
def _check_session(self, params): def _check_session(self, params):
if (self._session is None or if (self._session is None or
self._session not in _db_content['session']): self._session not in _db_content['session']):
raise Failure(['HANDLE_INVALID', 'session', self._session]) raise XenAPI.Failure(
['HANDLE_INVALID', 'session', self._session])
if len(params) == 0 or params[0] != self._session: if len(params) == 0 or params[0] != self._session:
LOG.debug('Raising NotImplemented') LOG.debug('Raising NotImplemented')
raise NotImplementedError('Call to XenAPI without using .xenapi') raise NotImplementedError('Call to XenAPI without using .xenapi')
@@ -1074,8 +1076,8 @@ class SessionBase(object):
def _check_arg_count(self, params, expected): def _check_arg_count(self, params, expected):
actual = len(params) actual = len(params)
if actual != expected: if actual != expected:
raise Failure(['MESSAGE_PARAMETER_COUNT_MISMATCH', raise XenAPI.Failure(
expected, actual]) ['MESSAGE_PARAMETER_COUNT_MISMATCH', expected, actual])
def _get_by_field(self, recs, k, v, return_singleton): def _get_by_field(self, recs, k, v, return_singleton):
result = [] result = []
@@ -1087,14 +1089,14 @@ class SessionBase(object):
try: try:
return result[0] return result[0]
except IndexError: except IndexError:
raise Failure(['UUID_INVALID', v, result, recs, k]) raise XenAPI.Failure(['UUID_INVALID', v, result, recs, k])
return result return result
class FakeXenAPI(object): class FakeXenAPI(object):
def __init__(self): def __init__(self):
self.Failure = Failure self.Failure = XenAPI.Failure
# Based upon _Method from xmlrpclib. # Based upon _Method from xmlrpclib.

View File

@@ -16,6 +16,7 @@
import functools import functools
import sys import sys
from os_xenapi.client import exception as xenapi_exception
from oslo_log import log as logging from oslo_log import log as logging
import six import six
@@ -66,7 +67,7 @@ class GlanceStore(object):
try: try:
vdis = self._call_glance_plugin(context, instance, session, vdis = self._call_glance_plugin(context, instance, session,
'download_vhd2', params) 'download_vhd2', params)
except exception.PluginRetriesExceeded: except xenapi_exception.PluginRetriesExceeded:
raise exception.CouldNotFetchImage(image_id=image_id) raise exception.CouldNotFetchImage(image_id=image_id)
return vdis return vdis
@@ -91,5 +92,5 @@ class GlanceStore(object):
try: try:
self._call_glance_plugin(context, instance, session, self._call_glance_plugin(context, instance, session,
'upload_vhd2', params) 'upload_vhd2', params)
except exception.PluginRetriesExceeded: except xenapi_exception.PluginRetriesExceeded:
raise exception.CouldNotUploadImage(image_id=image_id) raise exception.CouldNotUploadImage(image_id=image_id)

View File

@@ -58,3 +58,4 @@ os-vif>=1.3.0 # Apache-2.0
os-win>=1.1.0 # Apache-2.0 os-win>=1.1.0 # Apache-2.0
castellan>=0.4.0 # Apache-2.0 castellan>=0.4.0 # Apache-2.0
microversion-parse>=0.1.2 # Apache-2.0 microversion-parse>=0.1.2 # Apache-2.0
os-xenapi>=0.1.1 # Apache-2.0

View File

@@ -28,6 +28,7 @@ eventlet.monkey_patch()
import os import os
import sys import sys
from os_xenapi.client import session
from oslo_config import cfg from oslo_config import cfg
# If ../nova/__init__.py exists, add ../ to Python search path, so that # If ../nova/__init__.py exists, add ../ to Python search path, so that
@@ -42,7 +43,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')):
import nova.conf import nova.conf
from nova import config from nova import config
from nova import utils from nova import utils
from nova.virt.xenapi.client import session
from nova.virt.xenapi import vm_utils from nova.virt.xenapi import vm_utils
destroy_opts = [ destroy_opts = [