libvirt: making set_host_enabled to be a private methods

Currently _set_host_enabled() is being used only for internal libvirt
driver purposes, which doesn't correlate to set_host_enabled in the
compute API.

_set_host_enabled in the driver is disabling and re-enabling
the compute service automatically and shouldn't be exposed to the users.

Also, adding disable_reason as an optional variable and enabled variable
to be boolean only.

Change-Id: I5fd13ef352fcbb4a1c96764a9e473cdaf7b128da
Closes-Bug: #1251803
This commit is contained in:
Vladik Romanovsky 2013-12-09 15:54:50 -05:00
parent 52dc40e9df
commit e1fdd8f9b1
3 changed files with 116 additions and 175 deletions

View File

@ -44,6 +44,7 @@ from nova import db
from nova import exception
from nova.objects import instance as instance_obj
from nova.objects import pci_device as pci_device_obj
from nova.objects import service as service_obj
from nova.openstack.common import fileutils
from nova.openstack.common import importutils
from nova.openstack.common import jsonutils
@ -509,25 +510,25 @@ class LibvirtConnTestCase(test.TestCase):
# Tests disabling an enabled host.
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
self._create_service(host='fake-mini')
self.assertEqual('disabled', conn.set_host_enabled('fake-mini', False))
self.assertEqual('disabled', conn._set_host_enabled(False))
def test_set_host_enabled_with_enable(self):
# Tests enabling a disabled host.
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
self._create_service(disabled=True, host='fake-mini')
self.assertEqual('enabled', conn.set_host_enabled('fake-mini', True))
self.assertEqual('enabled', conn._set_host_enabled(True))
def test_set_host_enabled_with_enable_state_enabled(self):
# Tests enabling an enabled host.
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
self._create_service(disabled=False, host='fake-mini')
self.assertEqual('enabled', conn.set_host_enabled('fake-mini', True))
self.assertEqual('enabled', conn._set_host_enabled(True))
def test_set_host_enabled_with_disable_state_disabled(self):
# Tests disabling a disabled host.
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
self._create_service(disabled=True, host='fake-mini')
self.assertEqual('disabled', conn.set_host_enabled('fake-mini', False))
self.assertEqual('disabled', conn._set_host_enabled(False))
def test_set_host_enabled_swallows_exceptions(self):
# Tests that set_host_enabled will swallow exceptions coming from the
@ -538,7 +539,7 @@ class LibvirtConnTestCase(test.TestCase):
# Make db.service_get_by_compute_host raise NovaException; this
# is more robust than just raising ComputeHostNotFound.
db_mock.side_effect = exception.NovaException
self.assertIsNone(conn.set_host_enabled('fake-mini', False))
self.assertIsNone(conn._set_host_enabled(False))
def create_instance_obj(self, context, **params):
default_params = self.test_instance
@ -718,95 +719,66 @@ class LibvirtConnTestCase(test.TestCase):
self.assertThat(expected, matchers.DictMatches(result))
def test_close_callback(self):
class FakeConn(object):
def getLibVersion(self):
return (1 * 1000 * 1000) + (0 * 1000) + 1
def domainEventRegisterAny(self, *args, **kwargs):
pass
def registerCloseCallback(self, cb, opaque):
pass
self.close_callback = None
def set_close_callback(cb, opaque):
self.close_callback = cb
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
conn._wrapped_conn = FakeConn()
service_mock = mock.MagicMock()
service_mock.disabled.return_value = False
with contextlib.nested(
mock.patch.object(conn, "_connect", return_value=self.conn),
mock.patch.object(self.conn, "registerCloseCallback",
side_effect=set_close_callback),
mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock)):
self.mox.StubOutWithMock(conn, '_connect')
self.mox.StubOutWithMock(conn._conn, 'registerCloseCallback')
self.mox.StubOutWithMock(conn, 'set_host_enabled')
# verify that the driver registers for the close callback
# and re-connects after receiving the callback
conn._get_connection()
self.assertFalse(service_mock.disabled)
self.assertTrue(self.close_callback)
self.close_callback(self.conn, 1, None)
conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
conn._conn.registerCloseCallback(
mox.IgnoreArg(), mox.IgnoreArg()
).WithSideEffects(set_close_callback)
conn.set_host_enabled('fake-mini', True)
conn.set_host_enabled('fake-mini', 'Connection to libvirt lost: 1')
conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
conn.set_host_enabled('fake-mini', True)
conn._conn.registerCloseCallback(mox.IgnoreArg(), mox.IgnoreArg())
self.mox.ReplayAll()
# verify that the driver registers for the close callback
# and re-connects after receiving the callback
conn._get_new_connection()
self.assertTrue(self.close_callback)
self.close_callback(conn._conn, 1, None)
conn._get_connection()
self.mox.UnsetStubs()
self.assertTrue(service_mock.disabled)
conn._get_connection()
def test_close_callback_bad_signature(self):
class FakeConn(object):
def getLibVersion(self):
return (1 * 1000 * 1000) + (0 * 1000) + 0
def domainEventRegisterAny(self, *args, **kwargs):
pass
def registerCloseCallback(self, cb, opaque, *args, **kwargs):
pass
'''Validates that a connection to libvirt exist,
even when registerCloseCallback method has a different
number of arguments in the libvirt python library.
'''
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
conn._wrapped_conn = FakeConn()
service_mock = mock.MagicMock()
service_mock.disabled.return_value = False
with contextlib.nested(
mock.patch.object(conn, "_connect", return_value=self.conn),
mock.patch.object(self.conn, "registerCloseCallback",
side_effect=TypeError('dd')),
mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock)):
self.mox.StubOutWithMock(conn, '_connect')
self.mox.StubOutWithMock(conn._conn, 'registerCloseCallback')
self.mox.StubOutWithMock(conn, 'set_host_enabled')
conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(conn._conn)
conn.set_host_enabled('fake-mini', True)
conn._conn.registerCloseCallback(
mox.IgnoreArg(), mox.IgnoreArg()).AndRaise(TypeError)
self.mox.ReplayAll()
conn._get_new_connection()
connection = conn._get_connection()
self.assertTrue(connection)
def test_close_callback_not_defined(self):
class FakeConn():
def getLibVersion(self):
return (0 * 1000 * 1000) + (9 * 1000) + 0
def domainEventRegisterAny(self, *args, **kwargs):
pass
'''Validates that a connection to libvirt exist,
even when registerCloseCallback method missing from
the libvirt python library.
'''
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
conn._wrapped_conn = FakeConn()
service_mock = mock.MagicMock()
service_mock.disabled.return_value = False
with contextlib.nested(
mock.patch.object(conn, "_connect", return_value=self.conn),
mock.patch.object(self.conn, "registerCloseCallback",
side_effect=AttributeError('dd')),
mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock)):
self.mox.StubOutWithMock(conn, '_connect')
self.mox.StubOutWithMock(conn, 'set_host_enabled')
conn._connect(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
conn._wrapped_conn)
conn.set_host_enabled('fake-mini', True)
self.mox.ReplayAll()
conn._get_new_connection()
connection = conn._get_connection()
self.assertTrue(connection)
def test_cpu_features_bug_1217630(self):
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
@ -4303,69 +4275,53 @@ class LibvirtConnTestCase(test.TestCase):
def test_command_with_broken_connection(self):
self.mox.UnsetStubs()
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.mox.StubOutWithMock(libvirt, "openAuth")
self.mox.StubOutWithMock(libvirt.libvirtError, "get_error_code")
self.mox.StubOutWithMock(libvirt.libvirtError, "get_error_domain")
self.mox.StubOutWithMock(conn, 'set_host_enabled')
libvirt.openAuth(mox.IgnoreArg(), mox.IgnoreArg(),
mox.IgnoreArg()).AndRaise(
libvirt.libvirtError("fake failure"))
conn.set_host_enabled('fake-mini', 'Connection to libvirt lost: ERROR')
conn.set_host_enabled('fake-mini', False)
self.mox.ReplayAll()
conn._close_callback(conn._wrapped_conn, 'ERROR', '')
self.assertRaises(exception.HypervisorUnavailable,
conn.get_num_instances)
with contextlib.nested(
mock.patch.object(libvirt, 'openAuth',
side_effect=libvirt.libvirtError("fake")),
mock.patch.object(libvirt.libvirtError, "get_error_code"),
mock.patch.object(libvirt.libvirtError, "get_error_domain"),
mock.patch.object(conn, '_set_host_enabled')):
conn._close_callback(conn._wrapped_conn, 'ERROR', '')
self.assertRaises(exception.HypervisorUnavailable,
conn.get_num_instances)
def test_broken_connection_disable_service(self):
disabled_reason = 'Connection to libvirt lost: ERROR!'
reason = 'Connection to libvirt lost: ERROR!'
self.mox.UnsetStubs()
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.mox.StubOutWithMock(libvirt, "openAuth")
self.mox.StubOutWithMock(libvirt.libvirtError, "get_error_code")
self.mox.StubOutWithMock(libvirt.libvirtError, "get_error_domain")
libvirt.openAuth(mox.IgnoreArg(), mox.IgnoreArg(),
mox.IgnoreArg()).AndRaise(
libvirt.libvirtError("fake failure"))
from nova.objects import service as service_obj
service_mock = mock.MagicMock()
service_mock.__getitem__.return_value = False
service_mock.disabled.return_value = False
service_mock_failed_conn = mock.MagicMock()
service_mock_failed_conn.__getitem__.return_value = True
self.mox.StubOutWithMock(service_obj.Service,
'get_by_compute_host')
service_obj.Service.get_by_compute_host(mox.IgnoreArg(),
'fake-mini').AndReturn(service_mock)
service_obj.Service.get_by_compute_host(mox.IgnoreArg(),
'fake-mini').AndReturn(service_mock_failed_conn)
self.mox.ReplayAll()
service_mock_failed_conn.disabled.return_value = True
mocks_list = [service_mock, service_mock_failed_conn]
with contextlib.nested(
mock.patch.object(libvirt, 'openAuth',
side_effect=libvirt.libvirtError("fake")),
mock.patch.object(libvirt.libvirtError, "get_error_code"),
mock.patch.object(libvirt.libvirtError, "get_error_domain"),
mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=mocks_list.pop())):
conn._close_callback(conn._wrapped_conn, 'ERROR!', '')
self.assertTrue(service_mock.disabled and
service_mock.disabled_reason.endswith(disabled_reason))
self.assertRaises(exception.HypervisorUnavailable,
conn.get_num_instances)
conn._close_callback(conn._wrapped_conn, 'ERROR!', '')
self.assertTrue(service_mock.disabled and
service_mock.disabled_reason.endswith(reason))
self.assertRaises(exception.HypervisorUnavailable,
conn.get_num_instances)
def test_service_resume_after_broken_connection(self):
self.mox.UnsetStubs()
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
self.mox.StubOutWithMock(libvirt, "openAuth")
libvirt.openAuth(mox.IgnoreArg(), mox.IgnoreArg(),
mox.IgnoreArg()).AndReturn(mock.MagicMock())
from nova.objects import service as service_obj
service_mock = mock.MagicMock()
service_mock.__getitem__.return_value = True
self.mox.StubOutWithMock(service_obj.Service,
'get_by_compute_host')
service_obj.Service.get_by_compute_host(mox.IgnoreArg(),
'fake-mini').AndReturn(service_mock)
self.mox.ReplayAll()
conn.get_num_instances()
self.assertTrue(not service_mock.disabled and
service_mock.disabled_reason is 'None')
service_mock.disabled.return_value = True
with contextlib.nested(
mock.patch.object(libvirt, 'openAuth',
return_value=mock.MagicMock()),
mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock)):
conn.get_num_instances()
self.assertTrue(not service_mock.disabled and
service_mock.disabled_reason is 'None')
def test_broken_connection_no_wrapped_conn(self):
# Tests that calling _close_callback when _wrapped_conn is None

View File

@ -729,7 +729,7 @@ class LibvirtConnTestCase(_VirtDriverTestCase, test.TestCase):
self.driver_module = 'nova.virt.libvirt.LibvirtDriver'
super(LibvirtConnTestCase, self).setUp()
self.stubs.Set(self.connection,
'set_host_enabled', mock.MagicMock())
'_set_host_enabled', mock.MagicMock())
self.useFixture(fixtures.MonkeyPatch(
'nova.context.get_admin_context',
self._fake_admin_context))
@ -746,23 +746,19 @@ class LibvirtConnTestCase(_VirtDriverTestCase, test.TestCase):
self.skipTest("Test nothing, but this method"
" needed to override superclass.")
def test_set_host_enabled(self):
def test_internal_set_host_enabled(self):
self.mox.UnsetStubs()
service_mock = mock.MagicMock()
# Previous status of the service: disabled: False
# service_mock.__getitem__.return_value = False
service_mock.configure_mock(disabled_reason='None',
disabled=False)
from nova.objects import service as service_obj
self.mox.StubOutWithMock(service_obj.Service,
'get_by_compute_host')
service_obj.Service.get_by_compute_host(self.ctxt,
'fake-mini').AndReturn(service_mock)
self.mox.ReplayAll()
self.connection.set_host_enabled('my_test_host', 'ERROR!')
self.assertTrue(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'AUTO: ERROR!')
with mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock):
self.connection._set_host_enabled(False, 'ERROR!')
self.assertTrue(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'AUTO: ERROR!')
def test_set_host_enabled_when_auto_disabled(self):
self.mox.UnsetStubs()
@ -772,14 +768,11 @@ class LibvirtConnTestCase(_VirtDriverTestCase, test.TestCase):
service_mock.configure_mock(disabled_reason='AUTO: ERROR',
disabled=True)
from nova.objects import service as service_obj
self.mox.StubOutWithMock(service_obj.Service,
'get_by_compute_host')
service_obj.Service.get_by_compute_host(self.ctxt,
'fake-mini').AndReturn(service_mock)
self.mox.ReplayAll()
self.connection.set_host_enabled('my_test_host', True)
self.assertFalse(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'None')
with mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock):
self.connection._set_host_enabled(True)
self.assertFalse(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'None')
def test_set_host_enabled_when_manually_disabled(self):
self.mox.UnsetStubs()
@ -789,14 +782,11 @@ class LibvirtConnTestCase(_VirtDriverTestCase, test.TestCase):
service_mock.configure_mock(disabled_reason='Manually disabled',
disabled=True)
from nova.objects import service as service_obj
self.mox.StubOutWithMock(service_obj.Service,
'get_by_compute_host')
service_obj.Service.get_by_compute_host(self.ctxt,
'fake-mini').AndReturn(service_mock)
self.mox.ReplayAll()
self.connection.set_host_enabled('my_test_host', True)
self.assertTrue(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'Manually disabled')
with mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock):
self.connection._set_host_enabled(True)
self.assertTrue(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'Manually disabled')
def test_set_host_enabled_dont_override_manually_disabled(self):
self.mox.UnsetStubs()
@ -806,11 +796,8 @@ class LibvirtConnTestCase(_VirtDriverTestCase, test.TestCase):
service_mock.configure_mock(disabled_reason='Manually disabled',
disabled=True)
from nova.objects import service as service_obj
self.mox.StubOutWithMock(service_obj.Service,
'get_by_compute_host')
service_obj.Service.get_by_compute_host(self.ctxt,
'fake-mini').AndReturn(service_mock)
self.mox.ReplayAll()
self.connection.set_host_enabled('my_test_host', 'ERROR!')
self.assertTrue(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'Manually disabled')
with mock.patch.object(service_obj.Service, "get_by_compute_host",
return_value=service_mock):
self.connection._set_host_enabled(False, 'ERROR!')
self.assertTrue(service_mock.disabled)
self.assertEqual(service_mock.disabled_reason, 'Manually disabled')

View File

@ -647,8 +647,10 @@ class LibvirtDriver(driver.ComputeDriver):
finally:
# Enabling the compute service, in case it was disabled
# since the connection was successful.
is_connected = bool(wrapped_conn)
self.set_host_enabled(CONF.host, is_connected)
disable_reason = DISABLE_REASON_UNDEFINED
if not wrapped_conn:
disable_reason = 'Failed to connect to libvirt'
self._set_host_enabled(bool(wrapped_conn), disable_reason)
self._wrapped_conn = wrapped_conn
@ -702,7 +704,7 @@ class LibvirtDriver(driver.ComputeDriver):
self._wrapped_conn = None
# Disable compute service to avoid
# new instances of being scheduled on this host.
self.set_host_enabled(CONF.host, _error)
self._set_host_enabled(False, disable_reason=_error)
@staticmethod
def _test_connection(conn):
@ -2723,8 +2725,9 @@ class LibvirtDriver(driver.ComputeDriver):
% {'dev': pci_devs, 'dom': dom.ID()})
raise
def set_host_enabled(self, host, enabled):
"""Sets the specified host's ability to accept new instances.
def _set_host_enabled(self, enabled,
disable_reason=DISABLE_REASON_UNDEFINED):
"""Enables / Disables the compute service on this host.
This doesn't override non-automatic disablement with an automatic
setting; thereby permitting operators to keep otherwise
@ -2734,12 +2737,7 @@ class LibvirtDriver(driver.ComputeDriver):
status_name = {True: 'disabled',
False: 'enabled'}
if isinstance(enabled, bool):
disable_service = not enabled
disable_reason = DISABLE_REASON_UNDEFINED
else:
disable_service = bool(enabled)
disable_reason = enabled
disable_service = not enabled
ctx = nova_context.get_admin_context()
try: