Remove the remainder of the small container methods from session.

In the ongoing effort to remove nova.virt.lxd.session, I've removed
more of the smaller container related methods from it, and replaced
them with the modern api. `container_init` will require a little more
effort to remove, and will need some full migration testing before
we remove it.

Change-Id: Ieafe916d1da1b0c1a8976d437b94ddd8dfd6bf63
This commit is contained in:
Paul Hummer 2016-11-09 17:38:03 -07:00
parent cb0ab27c18
commit 8277d81d03
5 changed files with 78 additions and 272 deletions

View File

@ -1388,6 +1388,70 @@ class LXDDriverTest(test.NoDBTestCase):
'container_format': 'bare'},
data)
def test_finish_revert_migration(self):
ctx = context.get_admin_context()
instance = fake_instance.fake_instance_obj(ctx, name='test')
network_info = []
container = mock.Mock()
self.client.containers.get.return_value = container
lxd_driver = driver.LXDDriver(None)
lxd_driver.init_host(None)
lxd_driver.finish_revert_migration(ctx, instance, network_info)
container.start.assert_called_once_with(wait=True)
def test_check_can_live_migrate_destination(self):
ctx = context.get_admin_context()
instance = fake_instance.fake_instance_obj(ctx, name='test')
src_compute_info = mock.Mock()
dst_compute_info = mock.Mock()
def container_get(*args, **kwargs):
raise lxdcore_exceptions.LXDAPIException(MockResponse(404))
self.client.containers.get.side_effect = container_get
lxd_driver = driver.LXDDriver(None)
lxd_driver.init_host(None)
retval = lxd_driver.check_can_live_migrate_destination(
ctx, instance, src_compute_info, dst_compute_info)
self.assertIsInstance(retval, driver.LXDLiveMigrateData)
def test_confirm_migration(self):
migration = mock.Mock()
instance = fake_instance.fake_instance_obj(
context.get_admin_context, name='test')
network_info = []
profile = mock.Mock()
container = mock.Mock()
self.client.profiles.get.return_value = profile
self.client.containers.get.return_value = container
lxd_driver = driver.LXDDriver(None)
lxd_driver.init_host(None)
lxd_driver.confirm_migration(migration, instance, network_info)
profile.delete.assert_called_once_with()
container.delete.assert_called_once_with(wait=True)
def test_post_live_migration(self):
ctx = context.get_admin_context()
instance = fake_instance.fake_instance_obj(ctx, name='test')
container = mock.Mock()
self.client.containers.get.return_value = container
lxd_driver = driver.LXDDriver(None)
lxd_driver.init_host(None)
lxd_driver.post_live_migration(context, instance, None)
container.delete.assert_called_once_with(wait=True)
class InstanceAttributesTest(test.NoDBTestCase):
"""Tests for InstanceAttributes."""

View File

@ -19,47 +19,14 @@ import nova.conf
from nova import exception
from nova import test
from nova.tests.unit import fake_instance
from nova.tests.unit import fake_network
import pylxd
from pylxd.deprecated import exceptions as lxd_exceptions
from nova.virt.lxd import driver
from nova.virt.lxd import session
CONF = nova.conf.CONF
class LXDTestContainerMigrate(test.NoDBTestCase):
def setUp(self):
super(LXDTestContainerMigrate, self).setUp()
self.driver = driver.LXDDriver(None)
self.context = 'fake_context'
self.driver.session = mock.MagicMock()
self.driver.config = mock.MagicMock()
self.driver.unplug_vifs = mock.MagicMock()
@mock.patch.object(session.LXDAPISession, 'container_defined')
def test_confirm_migration(self, mock_contaienr_defined):
"""Verify that the correct migration container calls
are made.
"""
mock_instance = fake_instance.fake_instance_obj(self.context)
fake_network_info = fake_network.fake_get_instance_nw_info
self.driver.confirm_migration(
mock.sentinel.migration, mock_instance, fake_network_info)
self.driver.session.profile_delete.assert_called_once_with(
mock_instance
)
self.driver.session.container_destroy.assert_called_once_with(
mock_instance.name, mock_instance
)
self.driver.unplug_vifs.assert_called_once_with(
mock_instance, fake_network_info
)
class LXDTestLiveMigrate(test.NoDBTestCase):
def setUp(self):
@ -128,17 +95,6 @@ class LXDTestLiveMigrate(test.NoDBTestCase):
mock.sentinel.recover_method, mock.sentinel.block_migration,
mock.sentinel.migrate_data)
def test_post_live_migration(self):
"""Verify that the correct post_live_migration calls
are made.
"""
mock_instance = fake_instance.fake_instance_obj(self.context)
self.driver.post_live_migration(
mock.sentinel.context, mock_instance,
mock.sentinel.block_device_info, mock.sentinel.migrate_data)
self.driver.session.container_destroy.assert_called_once_with(
mock_instance.name, mock_instance)
def test_live_migration_not_allowed(self):
"""Verify an exception is raised when live migration is not allowed."""
self.flags(allow_live_migration=False,

View File

@ -47,93 +47,6 @@ class SessionContainerTest(test.NoDBTestCase):
self.session = session.LXDAPISession()
@stubs.annotated_data(
('exists', True),
('missing', False),
)
def test_container_defined(self, tag, side_effect):
"""
container_defined returns True if the container
exists on an LXD host, False otherwise, verify
the apporiate return value is returned.
"""
instance = stubs._fake_instance()
self.ml.container_defined.return_value = side_effect
if side_effect:
self.assertTrue(self.session.container_defined(
instance.name, instance))
if not side_effect:
self.assertFalse(self.session.container_defined(
instance.name, instance))
@stubs.annotated_data(
('1', True, (200, fake_api.fake_operation_info_ok()))
)
def test_container_start(self, tag, defined, side_effect=None):
"""
containser_start starts a container on a given LXD host.
Verify that the correct pyLXD calls are made.
"""
instance = stubs._fake_instance()
self.ml.container_start.return_value = side_effect
self.assertEqual(None,
self.session.container_start(instance.name,
instance))
calls = [mock.call.container_start(instance.name, -1),
mock.call.wait_container_operation(
'/1.0/operation/1234', 200, -1)]
self.assertEqual(calls, self.ml.method_calls)
@stubs.annotated_data(
('exists', (200, fake_api.fake_operation_info_ok())),
)
def test_container_destroy(self, tag, side_effect):
"""
container_destroy delete a container from the LXD Host. Check
that the approiate pylxd calls are made.
"""
instance = stubs._fake_instance()
self.ml.container_stop.return_value = side_effect
self.ml.container_destroy.return_value = side_effect
self.assertEqual(None,
self.session.container_destroy(instance.name,
instance))
calls = [mock.call.container_stop(instance.name, -1),
mock.call.wait_container_operation(
'/1.0/operation/1234', 200, -1),
mock.call.container_destroy(instance.name),
mock.call.wait_container_operation(
'/1.0/operation/1234', 200, -1)]
self.assertEqual(calls, self.ml.method_calls)
@stubs.annotated_data(
('fail_to_stop', True, 'fail_stop',
lxd_exceptions.APIError('Fake', '500'), exception.NovaException),
('fail_to_destroy', True, 'fail_destroy',
lxd_exceptions.APIError('Fake', '500'), exception.NovaException)
)
def test_container_destroy_fail(self, tag, container_defined,
test_type, side_effect, expected):
"""
container_destroy deletes a container on the LXD host.
Check whether an exeption.NovaException is raised when
there is an APIError or when the container fails to stop.
"""
instance = stubs._fake_instance()
self.ml.cotnainer_defined.return_value = container_defined
if test_type == 'fail_stop':
self.ml.container_stop.side_effect = side_effect
self.assertRaises(expected,
self.session.container_destroy, instance.name,
instance)
if test_type == 'fail_destroy':
self.ml.container_stop.return_value = \
(200, fake_api.fake_operation_info_ok())
self.ml.container_destroy.side_effect = side_effect
self.assertRaises(expected,
self.session.container_destroy, instance.name,
instance)
@stubs.annotated_data(
('1', (200, fake_api.fake_operation_info_ok()))
)

View File

@ -980,9 +980,6 @@ class LXDDriver(driver.ComputeDriver):
def finish_migration(self, context, migration, instance, disk_info,
network_info, image_meta, resize_instance,
block_device_info=None, power_on=True):
if self.session.container_defined(instance.name, instance):
return
# Ensure that the instance directory exists
instance_dir = InstanceAttributes(instance).instance_dir
if not os.path.exists(instance_dir):
@ -997,18 +994,17 @@ class LXDDriver(driver.ComputeDriver):
# Step 3 - Start the network and container
self.plug_vifs(instance, network_info)
self.session.container_start(instance.name, instance)
self.client.container.get(instance.name).start(wait=True)
def confirm_migration(self, migration, instance, network_info):
self.session.profile_delete(instance)
self.session.container_destroy(instance.name,
instance)
self.unplug_vifs(instance, network_info)
self.client.profiles.get(instance.name).delete()
self.client.containers.get(instance.name).delete(wait=True)
def finish_revert_migration(self, context, instance, network_info,
block_device_info=None, power_on=True):
if self.session.container_defined(instance.name, instance):
self.session.container_start(instance.name, instance)
self.client.containers.get(instance.name).start(wait=True)
def pre_live_migration(self, context, instance, block_device_info,
network_info, disk_info, migrate_data=None):
@ -1038,7 +1034,7 @@ class LXDDriver(driver.ComputeDriver):
def post_live_migration(self, context, instance, block_device_info,
migrate_data=None):
self.session.container_destroy(instance.name, instance)
self.client.containers.get(instance.name).delete(wait=True)
def post_live_migration_at_source(self, context, instance, network_info):
self.session.profile_delete(instance)
@ -1051,12 +1047,15 @@ class LXDDriver(driver.ComputeDriver):
# XXX: rockstar (20 Jul 2016) - nova-lxd does not support
# `check_instance_shared_storage_cleanup`
def check_can_live_migrate_destination(self, context, instance,
src_compute_info, dst_compute_info,
block_migration=False,
disk_over_commit=False):
if self.session.container_defined(instance.name, instance):
def check_can_live_migrate_destination(
self, context, instance, src_compute_info, dst_compute_info,
block_migration=False, disk_over_commit=False):
try:
self.client.containers.get(instance.name)
raise exception.InstanceExists(name=instance.name)
except lxd_exceptions.LXDAPIException as e:
if e.response.status_code != 404:
raise
return LXDLiveMigrateData()
def cleanup_live_migration_destination_check(

View File

@ -66,132 +66,6 @@ class LXDAPISession(object):
#
# Container related API methods
#
def container_defined(self, instance_name, instance):
"""Determine if the container exists
:param instance_name: container anme
:param instance: nova instance opbject
:return: True if exists otherwise False
"""
LOG.debug('container_defined for instance', instance=instance)
try:
client = self.get_session()
return client.container_defined(instance_name)
except lxd_exceptions.APIError as ex:
if ex.status_code == 404:
return False
else:
msg = _('Failed to get container status: %s') % ex
raise exception.NovaException(msg)
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.error(_LE('Error from LXD during container_defined'
'%(instance)s: %(reason)s'),
{'instance': instance.name, 'reason': e},
instance=instance)
def container_start(self, instance_name, instance):
"""Start an LXD container
:param instance_name: name of container
:param instance: nova instance object
"""
LOG.debug('container_start called for instance', instance=instance)
try:
LOG.info(_LI('Starting instance %(instance)s with '
'%(image)s'), {'instance': instance.name,
'image': instance.image_ref})
# Start the container
client = self.get_session()
(state, data) = client.container_start(instance_name,
CONF.lxd.timeout)
self.operation_wait(data.get('operation'), instance)
LOG.info(_LI('Successfully started instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref})
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
'reason': ex}
raise exception.NovaException(msg)
except Exception as ex:
with excutils.save_and_reraise_exception():
LOG.error(
_LE('Failed to start container %(instance)s: %(reason)s'),
{'instance': instance_name, 'reason': ex},
instance=instance)
def container_stop(self, instance_name, instance):
"""Stops an LXD container
:param instance_name: instance name
:param instance: nova instance object
"""
LOG.debug('container_stop called for instance', instance=instance)
try:
LOG.info(_LI('Stopping instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref})
# Stop the container
client = self.get_session()
(state, data) = client.container_stop(instance_name,
CONF.lxd.timeout)
self.operation_wait(data.get('operation'), instance)
LOG.info(_LI('Successfully stopped instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref})
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
'reason': ex}
raise exception.NovaException(msg)
except Exception as ex:
with excutils.save_and_reraise_exception():
LOG.error(
_LE('Failed to stop container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
'reason': ex})
def container_destroy(self, instance_name, instance):
"""Destroy a LXD container
:param instance_name: container name
:param instance: nova instance object
"""
LOG.debug('container_destroy for instance', instance=instance)
try:
LOG.info(_LI('Destroying instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref})
# Destroying container
self.container_stop(instance_name, instance)
client = self.get_session()
(state, data) = client.container_destroy(instance_name)
self.operation_wait(data.get('operation'), instance)
LOG.info(_LI('Successfully destroyed instance %(instance)s with'
' %(image)s'), {'instance': instance.name,
'image': instance.image_ref})
except lxd_exceptions.APIError as ex:
msg = _('Failed to communicate with LXD API %(instance)s:'
' %(reason)s') % {'instance': instance.name,
'reason': ex}
raise exception.NovaException(msg)
except Exception as ex:
with excutils.save_and_reraise_exception():
LOG.error(_LE('Failed to destroy container %(instance)s: '
'%(reason)s'), {'instance': instance_name,
'reason': ex})
def container_init(self, config, instance, host=None):
"""Create a LXD container