def test_add_ephemerals_with_zfs(self, block_device_info_get_ephemerals, execute): ctx = context.get_admin_context() block_device_info_get_ephemerals.return_value = [{ 'virtual_name': 'ephemerals0' }] instance = fake_instance.fake_instance_obj(ctx, name='test', memory_mb=0) block_device_info = mock.Mock() lxd_config = { 'environment': { 'storage': 'zfs' }, 'config': { 'storage.zfs_pool_name': 'zfs' } } container = mock.Mock() container.config = { 'volatile.last_state.idmap': '[{"Isuid":true,"Isgid":false,' '"Hostid":165536,"Nsid":0,' '"Maprange":65536}]' } client = mock.Mock() client.containers.get.return_value = container storage.attach_ephemeral(client, 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=/i/instance-00000001/storage/ephemerals0', '-o', 'quota=0G', 'zfs/instance-00000001-ephemeral', run_as_root=True), mock.call('chown', '165536', '/i/instance-00000001/storage/ephemerals0', run_as_root=True) ] self.assertEqual(expected_calls, execute.call_args_list)
def test_ephemeral_with_lvm( self, block_device_info_get_ephemerals, execute): ctx = context.get_admin_context() block_device_info_get_ephemerals.return_value = [ {'virtual_name': 'ephemerals0'}] instance = fake_instance.fake_instance_obj( ctx, name='test', memory_mb=0) block_device_info = mock.Mock() lxd_config = {'environment': {'storage': 'lvm'}, 'config': {'storage.lvm_vg_name': 'lxd'}} storage.fileutils = mock.Mock() container = mock.Mock() container.config = { 'volatile.last_state.idmap': '[{"Isuid":true,"Isgid":false,' '"Hostid":165536,"Nsid":0,' '"Maprange":65536}]' } client = mock.Mock() client.containers.get.return_value = container storage.attach_ephemeral( client, block_device_info, lxd_config, instance) block_device_info_get_ephemerals.assert_called_once_with( block_device_info) expected_calls = [ mock.call( 'lvcreate', '-L', '0G', '-n', 'instance-00000001-ephemerals0', 'lxd', attempts=3, run_as_root=True), mock.call( 'mkfs', '-t', 'ext4', '/dev/lxd/instance-00000001-ephemerals0', run_as_root=True), mock.call( 'mount', '-t', 'ext4', '/dev/lxd/instance-00000001-ephemerals0', '/i/instance-00000001/storage/ephemerals0', run_as_root=True), mock.call( 'chown', '165536', '/i/instance-00000001/storage/ephemerals0', run_as_root=True)] self.assertEqual(expected_calls, execute.call_args_list)
def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info=None, block_device_info=None): """Create a new lxd container as a nova instance. Creating a new container requires a number of steps. First, the image is fetched from glance, if needed. Next, the network is connected. A profile is created in LXD, and then the container is created and started. See `nova.virt.driver.ComputeDriver.spawn` for more information. """ 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 # Re-raise the exception if it wasn't NotFound instance_dir = common.InstanceAttributes(instance).instance_dir if not os.path.exists(instance_dir): fileutils.ensure_tree(instance_dir) # Check to see if LXD already has a copy of the image. If not, # fetch it. try: self.client.images.get_by_alias(instance.image_ref) except lxd_exceptions.LXDAPIException as e: if e.response.status_code != 404: raise _sync_glance_image_to_lxd( self.client, context, instance.image_ref) # Plug in the network if network_info: timeout = CONF.vif_plugging_timeout if (utils.is_neutron() and timeout): events = [('network-vif-plugged', vif['id']) for vif in network_info if not vif.get( 'active', True)] else: events = [] try: with self.virtapi.wait_for_instance_event( instance, events, deadline=timeout, error_callback=_neutron_failed_callback): self.plug_vifs(instance, network_info) except eventlet.timeout.Timeout: LOG.warn('Timeout waiting for vif plugging callback for ' 'instance %(uuid)s', {'uuid': instance['name']}) if CONF.vif_plugging_is_fatal: self.destroy( context, instance, network_info, block_device_info) raise exception.InstanceDeployFailure( 'Timeout waiting for vif plugging', instance_id=instance['name']) # Create the profile try: profile = flavor.to_profile( self.client, instance, network_info, block_device_info) except lxd_exceptions.LXDAPIException as e: with excutils.save_and_reraise_exception(): self.cleanup( context, instance, network_info, block_device_info) # Create the container container_config = { 'name': instance.name, 'profiles': [profile.name], 'source': { 'type': 'image', 'alias': instance.image_ref, }, } try: container = self.client.containers.create( container_config, wait=True) except lxd_exceptions.LXDAPIException as e: with excutils.save_and_reraise_exception(): self.cleanup( context, instance, network_info, block_device_info) lxd_config = self.client.host_info storage.attach_ephemeral( self.client, block_device_info, lxd_config, instance) if configdrive.required_by(instance): configdrive_path = self._add_configdrive( context, instance, injected_files, admin_password, network_info) profile = self.client.profiles.get(instance.name) config_drive = { 'configdrive': { 'path': '/config-drive', 'source': configdrive_path, 'type': 'disk', 'readonly': 'True', } } profile.devices.update(config_drive) profile.save() try: self.firewall_driver.setup_basic_filtering( instance, network_info) self.firewall_driver.instance_filter( instance, network_info) container.start(wait=True) self.firewall_driver.apply_instance_filter( instance, network_info) except lxd_exceptions.LXDAPIException as e: with excutils.save_and_reraise_exception(): self.cleanup( context, instance, network_info, block_device_info)
def test_add_ephemerals_with_btrfs( self, block_device_info_get_ephemerals, execute): ctx = context.get_admin_context() block_device_info_get_ephemerals.return_value = [ {'virtual_name': 'ephemerals0'}] instance = fake_instance.fake_instance_obj( ctx, name='test', memory_mb=0) instance.ephemeral_gb = 1 block_device_info = mock.Mock() lxd_config = {'environment': {'storage': 'btrfs'}} profile = mock.Mock() profile.devices = { 'root': { 'path': '/', 'type': 'disk', 'size': '1G' }, 'ephemerals0': { 'optional': 'True', 'path': '/mnt', 'source': '/path/fake_path', 'type': 'disk' } } client = mock.Mock() client.profiles.get.return_value = profile container = mock.Mock() container.config = { 'volatile.last_state.idmap': '[{"Isuid":true,"Isgid":false,' '"Hostid":165536,"Nsid":0,' '"Maprange":65536}]' } client.containers.get.return_value = container storage.attach_ephemeral( client, block_device_info, lxd_config, instance) block_device_info_get_ephemerals.assert_called_once_with( block_device_info) profile.save.assert_called_once_with() expected_calls = [ mock.call( 'btrfs', 'subvolume', 'create', '/var/lib/lxd/containers/instance-00000001/ephemerals0', run_as_root=True), mock.call( 'btrfs', 'qgroup', 'limit', '1g', '/var/lib/lxd/containers/instance-00000001/ephemerals0', run_as_root=True), mock.call( 'chown', '165536', '/var/lib/lxd/containers/instance-00000001/ephemerals0', run_as_root=True) ] self.assertEqual(expected_calls, execute.call_args_list) self.assertEqual( profile.devices['ephemerals0']['source'], '/var/lib/lxd/containers/instance-00000001/ephemerals0')
def test_add_ephemerals_with_btrfs(self, block_device_info_get_ephemerals, execute): ctx = context.get_admin_context() block_device_info_get_ephemerals.return_value = [{ 'virtual_name': 'ephemerals0' }] instance = fake_instance.fake_instance_obj(ctx, name='test', memory_mb=0) instance.ephemeral_gb = 1 block_device_info = mock.Mock() lxd_config = {'environment': {'storage': 'btrfs'}} profile = mock.Mock() profile.devices = { 'root': { 'path': '/', 'type': 'disk', 'size': '1G' }, 'ephemerals0': { 'optional': 'True', 'path': '/mnt', 'source': '/path/fake_path', 'type': 'disk' } } client = mock.Mock() client.profiles.get.return_value = profile container = mock.Mock() container.config = { 'volatile.last_state.idmap': '[{"Isuid":true,"Isgid":false,' '"Hostid":165536,"Nsid":0,' '"Maprange":65536}]' } client.containers.get.return_value = container storage.attach_ephemeral(client, block_device_info, lxd_config, instance) block_device_info_get_ephemerals.assert_called_once_with( block_device_info) profile.save.assert_called_once_with() expected_calls = [ mock.call('btrfs', 'subvolume', 'create', '/var/lib/lxd/containers/instance-00000001/ephemerals0', run_as_root=True), mock.call('btrfs', 'qgroup', 'limit', '1g', '/var/lib/lxd/containers/instance-00000001/ephemerals0', run_as_root=True), mock.call('chown', '165536', '/var/lib/lxd/containers/instance-00000001/ephemerals0', run_as_root=True) ] self.assertEqual(expected_calls, execute.call_args_list) self.assertEqual( profile.devices['ephemerals0']['source'], '/var/lib/lxd/containers/instance-00000001/ephemerals0')