Add support for zfs backend
Add support for zfs ephemeral storage backends. Also use nova.virt.driver.block_device_info_get_ephemerals method for determining ephemeral information. Change-Id: Ie85e12ca22118e6439e9ebfd88af1ed53bfaebd7 Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
parent
bb20ba8c6d
commit
3f9f39e32b
|
@ -2,4 +2,4 @@
|
|||
# This file should be owned by (and only-writable by) the root user
|
||||
|
||||
[Filters]
|
||||
tar: CommandFilter, tar, root
|
||||
zfs: CommandFilter, zfs, root
|
||||
|
|
|
@ -126,6 +126,7 @@ class LXDDriverTest(test.NoDBTestCase):
|
|||
lxd_driver.setup_image = mock.Mock()
|
||||
lxd_driver.vif_driver = mock.Mock()
|
||||
lxd_driver.firewall_driver = mock.Mock()
|
||||
lxd_driver._add_ephemeral = mock.Mock()
|
||||
lxd_driver.create_profile = mock.Mock(return_value={
|
||||
'name': instance.name, 'config': {}, 'devices': {}})
|
||||
|
||||
|
@ -146,6 +147,8 @@ class LXDDriverTest(test.NoDBTestCase):
|
|||
instance, network_info)
|
||||
fd.apply_instance_filter.assert_called_once_with(
|
||||
instance, network_info)
|
||||
lxd_driver._add_ephemeral.assert_called_once_with(
|
||||
block_device_info, lxd_driver.client.host_info, instance)
|
||||
|
||||
def test_spawn_already_exists(self):
|
||||
"""InstanceExists is raised if the container already exists."""
|
||||
|
@ -165,6 +168,39 @@ class LXDDriverTest(test.NoDBTestCase):
|
|||
ctx, instance, image_meta, injected_files, admin_password,
|
||||
None, None)
|
||||
|
||||
@mock.patch('os.stat')
|
||||
@mock.patch('nova.virt.lxd.driver.container_utils.get_container_storage')
|
||||
@mock.patch.object(driver.utils, 'execute')
|
||||
@mock.patch('nova.virt.driver.block_device_info_get_ephemerals')
|
||||
def test_add_ephemerals_with_zfs(
|
||||
self, block_device_info_get_ephemerals, execute,
|
||||
get_container_storage, stat):
|
||||
ctx = context.get_admin_context()
|
||||
block_device_info_get_ephemerals.return_value = [
|
||||
{'virtual_name': 'ephemerals0'}]
|
||||
instance = fake_instance.fake_instance_obj(ctx, name='test')
|
||||
block_device_info = mock.Mock()
|
||||
lxd_config = {'environment': {'storage': 'zfs'},
|
||||
'config': {'storage.zfs_pool_name': 'zfs'}}
|
||||
get_container_storage.return_value = '/path'
|
||||
stat.return_value.st_uid = 1234
|
||||
|
||||
lxd_driver = driver.LXDDriver(None)
|
||||
lxd_driver.init_host(None)
|
||||
lxd_driver._add_ephemeral(block_device_info, lxd_config, instance)
|
||||
|
||||
block_device_info_get_ephemerals.assert_called_once_with(
|
||||
block_device_info)
|
||||
|
||||
expected_calls = [
|
||||
mock.call(
|
||||
'zfs', 'create', '-o', 'mountpoint=/path', '-o', 'quota=0G',
|
||||
'zfs/instance-00000001-ephemeral', run_as_root=True),
|
||||
mock.call('chown', 1234, '/path', run_as_root=True)
|
||||
]
|
||||
|
||||
self.assertEqual(expected_calls, execute.call_args_list)
|
||||
|
||||
def test_destroy(self):
|
||||
mock_profile = mock.Mock()
|
||||
mock_container = mock.Mock()
|
||||
|
@ -202,22 +238,52 @@ class LXDDriverTest(test.NoDBTestCase):
|
|||
instance = fake_instance.fake_instance_obj(ctx, name='test')
|
||||
network_info = [mock.Mock()]
|
||||
instance_dir = utils.get_instance_dir(instance.name)
|
||||
block_device_info = mock.Mock()
|
||||
|
||||
lxd_driver = driver.LXDDriver(None)
|
||||
lxd_driver.init_host(None)
|
||||
lxd_driver.vif_driver = mock.Mock()
|
||||
lxd_driver.firewall_driver = mock.Mock()
|
||||
lxd_driver._remove_ephemeral = mock.Mock()
|
||||
|
||||
lxd_driver.cleanup(ctx, instance, network_info)
|
||||
lxd_driver.cleanup(ctx, instance, network_info, block_device_info)
|
||||
|
||||
lxd_driver.vif_driver.unplug.assert_called_once_with(
|
||||
instance, network_info[0])
|
||||
lxd_driver.firewall_driver.unfilter_instance.assert_called_once_with(
|
||||
instance, network_info)
|
||||
lxd_driver._remove_ephemeral.assert_called_once_with(
|
||||
block_device_info, lxd_driver.client.host_info, instance)
|
||||
execute.assert_called_once_with(
|
||||
'chown', '-R', 'user:user', instance_dir, run_as_root=True)
|
||||
rmtree.assert_called_once_with(instance_dir)
|
||||
|
||||
@mock.patch.object(driver.utils, 'execute')
|
||||
@mock.patch('nova.virt.driver.block_device_info_get_ephemerals')
|
||||
def test_remove_emepheral_with_zfs(
|
||||
self, block_device_info_get_ephemerals, execute):
|
||||
block_device_info_get_ephemerals.return_value = [
|
||||
{'virtual_name': 'ephemerals0'}]
|
||||
|
||||
ctx = context.get_admin_context()
|
||||
instance = fake_instance.fake_instance_obj(ctx, name='test')
|
||||
block_device_info = mock.Mock()
|
||||
lxd_config = {'environment': {'storage': 'zfs'},
|
||||
'config': {'storage.zfs_pool_name': 'zfs'}}
|
||||
|
||||
lxd_driver = driver.LXDDriver(None)
|
||||
lxd_driver.init_host(None)
|
||||
lxd_driver._remove_ephemeral(block_device_info, lxd_config, instance)
|
||||
|
||||
block_device_info_get_ephemerals.assert_called_once_with(
|
||||
block_device_info)
|
||||
|
||||
expected_calls = [
|
||||
mock.call('zfs', 'destroy', 'zfs/instance-00000001-ephemeral',
|
||||
run_as_root=True)
|
||||
]
|
||||
self.assertEqual(expected_calls, execute.call_args_list)
|
||||
|
||||
def test_reboot(self):
|
||||
ctx = context.get_admin_context()
|
||||
instance = fake_instance.fake_instance_obj(ctx, name='test')
|
||||
|
|
|
@ -218,11 +218,13 @@ class LXDDriver(driver.ComputeDriver):
|
|||
}
|
||||
LOG.debug(container_config)
|
||||
container = self.client.containers.create(container_config, wait=True)
|
||||
container.start()
|
||||
|
||||
# XXX: rockstar (6 Jul 2016) - _add_ephemeral is only used here,
|
||||
# and hasn't really been audited. It may need a cleanup.
|
||||
self._add_ephemeral(block_device_info, instance)
|
||||
# and hasn't really been audited. It may need a cleanup
|
||||
lxd_config = self.client.host_info
|
||||
self._add_ephemeral(block_device_info, lxd_config, instance)
|
||||
|
||||
container.start()
|
||||
|
||||
def destroy(self, context, instance, network_info, block_device_info=None,
|
||||
destroy_disks=True, migrate_data=None):
|
||||
|
@ -257,6 +259,11 @@ class LXDDriver(driver.ComputeDriver):
|
|||
pass
|
||||
self.firewall_driver.unfilter_instance(instance, network_info)
|
||||
|
||||
# XXX: zulcss (14 Jul 2016) - _remove_ephemeral is only used here,
|
||||
# and hasn't really been audited. It may need a cleanup
|
||||
lxd_config = self.client.host_info
|
||||
self._remove_ephemeral(block_device_info, lxd_config, instance)
|
||||
|
||||
name = pwd.getpwuid(os.getuid()).pw_name
|
||||
|
||||
container_dir = container_utils.get_instance_dir(instance.name)
|
||||
|
@ -384,26 +391,51 @@ class LXDDriver(driver.ComputeDriver):
|
|||
# have not been through the cleanup process. We know the cleanup process
|
||||
# is complete when there is no more code below this comment, and the
|
||||
# comment can be removed.
|
||||
def _add_ephemeral(self, block_device_info, instance):
|
||||
if instance.get('ephemeral_gb', 0) != 0:
|
||||
ephemerals = block_device_info.get('ephemerals', [])
|
||||
def _add_ephemeral(self, block_device_info, lxd_config, instance):
|
||||
ephemeral_storage = driver.block_device_info_get_ephemerals(
|
||||
block_device_info)
|
||||
if ephemeral_storage:
|
||||
storage_driver = lxd_config['environment']['storage']
|
||||
container_root = container_utils.get_container_rootfs(
|
||||
instance.name)
|
||||
|
||||
root_dir = container_utils.get_container_rootfs(instance.name)
|
||||
if ephemerals == []:
|
||||
ephemeral_src = container_utils.get_container_storage(
|
||||
ephemerals['virtual_name'], instance.name)
|
||||
fileutils.ensure_tree(ephemeral_src)
|
||||
utils.execute('chown',
|
||||
os.stat(root_dir).st_uid,
|
||||
ephemeral_src, run_as_root=True)
|
||||
else:
|
||||
for id, ephx in enumerate(ephemerals):
|
||||
ephemeral_src = container_utils.get_container_storage(
|
||||
ephx['virtual_name'], instance.name)
|
||||
fileutils.ensure_tree(ephemeral_src)
|
||||
utils.execute('chown',
|
||||
os.stat(root_dir).st_uid,
|
||||
ephemeral_src, run_as_root=True)
|
||||
for ephemeral in ephemeral_storage:
|
||||
storage_dir = container_utils.get_container_storage(
|
||||
ephemeral['virtual_name'], instance.name)
|
||||
if storage_driver == 'zfs':
|
||||
zfs_pool = lxd_config['config']['storage.zfs_pool_name']
|
||||
|
||||
utils.execute(
|
||||
'zfs', 'create',
|
||||
'-o', 'mountpoint=%s' % storage_dir,
|
||||
'-o', 'quota=%sG' % instance.ephemeral_gb,
|
||||
'%s/%s-ephemeral' % (zfs_pool, instance.name),
|
||||
run_as_root=True)
|
||||
else:
|
||||
reason = _('Unsupport LXD storage detected. Supported'
|
||||
' storage drivers is zfs.')
|
||||
raise exception.NovaException(reason)
|
||||
|
||||
utils.execute(
|
||||
'chown', os.stat(container_root).st_uid,
|
||||
storage_dir, run_as_root=True)
|
||||
|
||||
def _remove_ephemeral(self, block_device_info, lxd_config, instance):
|
||||
"""Remove empeheral device from the instance."""
|
||||
ephemeral_storage = driver.block_device_info_get_ephemerals(
|
||||
block_device_info)
|
||||
if ephemeral_storage:
|
||||
storage_driver = lxd_config['environment']['storage']
|
||||
|
||||
for ephemeral in ephemeral_storage:
|
||||
if storage_driver == 'zfs':
|
||||
zfs_pool = \
|
||||
lxd_config['config']['storage.zfs_pool_name']
|
||||
|
||||
utils.execute(
|
||||
'zfs', 'destroy',
|
||||
'%s/%s-ephemeral' % (zfs_pool, instance.name),
|
||||
run_as_root=True)
|
||||
|
||||
def snapshot(self, context, instance, image_id, update_task_state):
|
||||
lock_path = str(os.path.join(CONF.instances_path, 'locks'))
|
||||
|
|
Loading…
Reference in New Issue