Merge "Move vbd plug/unplug into session object"

This commit is contained in:
Jenkins 2014-03-05 08:45:03 +00:00 committed by Gerrit Code Review
commit cb380e8172
9 changed files with 63 additions and 58 deletions

View File

@ -16,6 +16,7 @@
import mock import mock
from nova.tests.virt.xenapi import stubs from nova.tests.virt.xenapi import stubs
from nova import utils
from nova.virt.xenapi.client import objects from nova.virt.xenapi.client import objects
@ -89,3 +90,31 @@ class ObjectsTestCase(stubs.XenAPITestBaseNoDB):
pool = objects.Pool(self.session) pool = objects.Pool(self.session)
pool.get_X("ref") pool.get_X("ref")
self.session.call_xenapi.assert_called_once_with("pool.get_X", "ref") self.session.call_xenapi.assert_called_once_with("pool.get_X", "ref")
class VBDTestCase(stubs.XenAPITestBaseNoDB):
def setUp(self):
super(VBDTestCase, self).setUp()
self.session = mock.Mock()
self.session.VBD = objects.VBD(self.session)
def test_plug(self):
self.session.VBD.plug("vbd_ref", "vm_ref")
self.session.call_xenapi.assert_called_once_with("VBD.plug", "vbd_ref")
@mock.patch.object(utils, 'synchronized')
def test_vbd_plug_check_synchronized(self, mock_synchronized):
session = mock.Mock()
self.session.VBD.plug("vbd_ref", "vm_ref")
mock_synchronized.assert_called_once_with("xenapi-vbd-vm_ref")
def test_unplug(self):
self.session.VBD.unplug("vbd_ref", "vm_ref")
self.session.call_xenapi.assert_called_once_with("VBD.unplug",
"vbd_ref")
@mock.patch.object(utils, 'synchronized')
def test_vbd_plug_check_synchronized(self, mock_synchronized):
session = mock.Mock()
self.session.VBD.unplug("vbd_ref", "vm_ref")
mock_synchronized.assert_called_once_with("xenapi-vbd-vm_ref")

View File

@ -887,7 +887,7 @@ class CreateVBDTestCase(VMUtilsTestBase):
class UnplugVbdTestCase(VMUtilsTestBase): class UnplugVbdTestCase(VMUtilsTestBase):
@mock.patch.object(greenthread, 'sleep') @mock.patch.object(greenthread, 'sleep')
def test_unplug_vbd_works(self, mock_sleep): def test_unplug_vbd_works(self, mock_sleep):
session = mock.Mock() session = _get_fake_session()
vbd_ref = "vbd_ref" vbd_ref = "vbd_ref"
vm_ref = 'vm_ref' vm_ref = 'vm_ref'
@ -897,7 +897,7 @@ class UnplugVbdTestCase(VMUtilsTestBase):
self.assertEqual(0, mock_sleep.call_count) self.assertEqual(0, mock_sleep.call_count)
def test_unplug_vbd_raises_unexpected_error(self): def test_unplug_vbd_raises_unexpected_error(self):
session = mock.Mock() session = _get_fake_session()
vbd_ref = "vbd_ref" vbd_ref = "vbd_ref"
vm_ref = 'vm_ref' vm_ref = 'vm_ref'
session.call_xenapi.side_effect = test.TestingException() session.call_xenapi.side_effect = test.TestingException()
@ -1742,16 +1742,13 @@ class VDIAttachedHere(VMUtilsTestBase):
@mock.patch.object(vm_utils, 'destroy_vbd') @mock.patch.object(vm_utils, 'destroy_vbd')
@mock.patch.object(vm_utils, '_get_this_vm_ref') @mock.patch.object(vm_utils, '_get_this_vm_ref')
@mock.patch.object(vm_utils, 'create_vbd') @mock.patch.object(vm_utils, 'create_vbd')
@mock.patch.object(volume_utils, 'vbd_plug')
@mock.patch.object(vm_utils, '_remap_vbd_dev') @mock.patch.object(vm_utils, '_remap_vbd_dev')
@mock.patch.object(vm_utils, '_wait_for_device') @mock.patch.object(vm_utils, '_wait_for_device')
@mock.patch.object(utils, 'execute') @mock.patch.object(utils, 'execute')
@mock.patch.object(vm_utils, 'unplug_vbd') def test_sync_called(self, mock_execute, mock_wait_for_device,
def test_sync_called(self, mock_unplug_vbd, mock_execute, mock_remap_vbd_dev, mock_create_vbd,
mock_wait_for_device, mock_remap_vbd_dev,
mock_vbd_plug, mock_create_vbd,
mock_get_this_vm_ref, mock_destroy_vbd): mock_get_this_vm_ref, mock_destroy_vbd):
session = mock.Mock() session = _get_fake_session()
with vm_utils.vdi_attached_here(session, 'vdi_ref'): with vm_utils.vdi_attached_here(session, 'vdi_ref'):
pass pass
mock_execute.assert_called_with('sync', run_as_root=True) mock_execute.assert_called_with('sync', run_as_root=True)

View File

@ -18,34 +18,9 @@ import mock
from eventlet import greenthread from eventlet import greenthread
from nova.tests.virt.xenapi import stubs from nova.tests.virt.xenapi import stubs
from nova import utils
from nova.virt.xenapi import volume_utils from nova.virt.xenapi import volume_utils
class CallXenAPIHelpersTestCase(stubs.XenAPITestBaseNoDB):
def test_vbd_plug(self):
session = mock.Mock()
volume_utils.vbd_plug(session, "vbd_ref", "vm_ref:123")
session.call_xenapi.assert_called_once_with("VBD.plug", "vbd_ref")
@mock.patch.object(utils, 'synchronized')
def test_vbd_plug_check_synchronized(self, mock_synchronized):
session = mock.Mock()
volume_utils.vbd_plug(session, "vbd_ref", "vm_ref:123")
mock_synchronized.assert_called_once_with("xenapi-events-vm_ref:123")
def test_vbd_unplug(self):
session = mock.Mock()
volume_utils.vbd_unplug(session, "vbd_ref", "vm_ref:123")
session.call_xenapi.assert_called_once_with("VBD.unplug", "vbd_ref")
@mock.patch.object(utils, 'synchronized')
def test_vbd_unplug_check_synchronized(self, mock_synchronized):
session = mock.Mock()
volume_utils.vbd_unplug(session, "vbd_ref", "vm_ref:123")
mock_synchronized.assert_called_once_with("xenapi-events-vm_ref:123")
class SROps(stubs.XenAPITestBaseNoDB): class SROps(stubs.XenAPITestBaseNoDB):
def test_find_sr_valid_uuid(self): def test_find_sr_valid_uuid(self):
self.session = mock.Mock() self.session = mock.Mock()

View File

@ -128,6 +128,7 @@ class VolumeAttachTestCase(test.NoDBTestCase):
self.mox.StubOutWithMock(volumeops.volume_utils, 'introduce_vdi') self.mox.StubOutWithMock(volumeops.volume_utils, 'introduce_vdi')
self.mox.StubOutWithMock(volumeops.vm_utils, 'create_vbd') self.mox.StubOutWithMock(volumeops.vm_utils, 'create_vbd')
self.mox.StubOutWithMock(volumeops.vm_utils, 'is_vm_shutdown') self.mox.StubOutWithMock(volumeops.vm_utils, 'is_vm_shutdown')
self.mox.StubOutWithMock(ops._session.VBD, 'plug')
self.mox.StubOutWithMock(ops._session, 'call_xenapi') self.mox.StubOutWithMock(ops._session, 'call_xenapi')
instance_name = 'instance_1' instance_name = 'instance_1'
@ -159,7 +160,7 @@ class VolumeAttachTestCase(test.NoDBTestCase):
volumeops.vm_utils.is_vm_shutdown(session, volumeops.vm_utils.is_vm_shutdown(session,
vm_ref).AndReturn(not vm_running) vm_ref).AndReturn(not vm_running)
if plugged: if plugged:
ops._session.call_xenapi("VBD.plug", vbd_ref) ops._session.VBD.plug(vbd_ref, vm_ref)
ops._session.call_xenapi("VDI.get_uuid", ops._session.call_xenapi("VDI.get_uuid",
vdi_ref).AndReturn(vdi_uuid) vdi_ref).AndReturn(vdi_uuid)

View File

@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from nova import utils
class XenAPISessionObject(object): class XenAPISessionObject(object):
"""Wrapper to make calling and mocking the session easier """Wrapper to make calling and mocking the session easier
@ -71,6 +73,26 @@ class VBD(XenAPISessionObject):
def __init__(self, session): def __init__(self, session):
super(VBD, self).__init__(session, "VBD") super(VBD, self).__init__(session, "VBD")
def plug(self, vbd_ref, vm_ref):
@utils.synchronized('xenapi-vbd-' + vm_ref)
def synchronized_plug():
self._call_method("plug", vbd_ref)
# NOTE(johngarbutt) we need to ensure there is only ever one
# VBD.unplug or VBD.plug happening at once per VM
# due to a bug in XenServer 6.1 and 6.2
synchronized_plug()
def unplug(self, vbd_ref, vm_ref):
@utils.synchronized('xenapi-vbd-' + vm_ref)
def synchronized_unplug():
self._call_method("unplug", vbd_ref)
# NOTE(johngarbutt) we need to ensure there is only ever one
# VBD.unplug or VBD.plug happening at once per VM
# due to a bug in XenServer 6.1 and 6.2
synchronized_unplug()
class VDI(XenAPISessionObject): class VDI(XenAPISessionObject):
"""Virtual disk image.""" """Virtual disk image."""

View File

@ -63,6 +63,7 @@ from nova.openstack.common import jsonutils
from nova.openstack.common import log as logging from nova.openstack.common import log as logging
from nova.openstack.common import timeutils from nova.openstack.common import timeutils
from nova.openstack.common import units from nova.openstack.common import units
from nova.virt.xenapi.client import session as xenapi_session
_CLASSES = ['host', 'network', 'session', 'pool', 'SR', 'VBD', _CLASSES = ['host', 'network', 'session', 'pool', 'SR', 'VBD',
@ -472,6 +473,7 @@ class SessionBase(object):
def __init__(self, uri): def __init__(self, uri):
self._session = None self._session = None
xenapi_session.apply_session_helpers(self)
def pool_get_default_SR(self, _1, pool_ref): def pool_get_default_SR(self, _1, pool_ref):
return _db_content['pool'].values()[0]['default-SR'] return _db_content['pool'].values()[0]['default-SR']

View File

@ -426,7 +426,7 @@ def unplug_vbd(session, vbd_ref, this_vm_ref):
if num_attempt > 1: if num_attempt > 1:
greenthread.sleep(1) greenthread.sleep(1)
volume_utils.vbd_unplug(session, vbd_ref, this_vm_ref) session.VBD.unplug(vbd_ref, this_vm_ref)
return return
except session.XenAPI.Failure as exc: except session.XenAPI.Failure as exc:
err = len(exc.details) > 0 and exc.details[0] err = len(exc.details) > 0 and exc.details[0]
@ -2186,7 +2186,7 @@ def vdi_attached_here(session, vdi_ref, read_only=False):
read_only=read_only, bootable=False) read_only=read_only, bootable=False)
try: try:
LOG.debug(_('Plugging VBD %s ... '), vbd_ref) LOG.debug(_('Plugging VBD %s ... '), vbd_ref)
volume_utils.vbd_plug(session, vbd_ref, this_vm_ref) session.VBD.plug(vbd_ref, this_vm_ref)
try: try:
LOG.debug(_('Plugging VBD %s done.'), vbd_ref) LOG.debug(_('Plugging VBD %s done.'), vbd_ref)
orig_dev = session.call_xenapi("VBD.get_device", vbd_ref) orig_dev = session.call_xenapi("VBD.get_device", vbd_ref)

View File

@ -26,7 +26,6 @@ from oslo.config import cfg
from nova.openstack.common.gettextutils import _ from nova.openstack.common.gettextutils import _
from nova.openstack.common import log as logging from nova.openstack.common import log as logging
from nova import utils
xenapi_volume_utils_opts = [ xenapi_volume_utils_opts = [
cfg.IntOpt('introduce_vdi_retry_wait', cfg.IntOpt('introduce_vdi_retry_wait',
@ -312,23 +311,3 @@ def _get_target_port(iscsi_string):
return iscsi_string.split(':')[1] return iscsi_string.split(':')[1]
return CONF.xenserver.target_port return CONF.xenserver.target_port
def vbd_plug(session, vbd_ref, vm_ref):
@utils.synchronized('xenapi-events-' + vm_ref)
def synchronized_plug():
session.call_xenapi("VBD.plug", vbd_ref)
# NOTE(johngarbutt) we need to ensure there is only ever one VBD.plug
# happening at once per VM due to a bug in XenServer 6.1 and 6.2
synchronized_plug()
def vbd_unplug(session, vbd_ref, vm_ref):
@utils.synchronized('xenapi-events-' + vm_ref)
def synchronized_unplug():
session.call_xenapi("VBD.unplug", vbd_ref)
# NOTE(johngarbutt) we need to ensure there is only ever one VBD.unplug
# happening at once per VM due to a bug in XenServer 6.1 and 6.2
synchronized_unplug()

View File

@ -111,7 +111,7 @@ class VolumeOps(object):
running = not vm_utils.is_vm_shutdown(self._session, vm_ref) running = not vm_utils.is_vm_shutdown(self._session, vm_ref)
if hotplug and running: if hotplug and running:
volume_utils.vbd_plug(self._session, vbd_ref, vm_ref) self._session.VBD.plug(vbd_ref, vm_ref)
vdi_uuid = self._session.call_xenapi("VDI.get_uuid", vdi_ref) vdi_uuid = self._session.call_xenapi("VDI.get_uuid", vdi_ref)
return (sr_uuid, vdi_uuid) return (sr_uuid, vdi_uuid)