Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions nova/virt/lxd/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

from nova import conf

from oslo_log import log as logging
LOG = logging.getLogger(__name__)

_InstanceAttributes = collections.namedtuple('InstanceAttributes', [
'instance_dir', 'console_path', 'storage_path', 'container_path'])
Expand All @@ -31,3 +33,55 @@ def InstanceAttributes(instance):
conf.CONF.lxd.root_dir, 'containers', instance.name)
return _InstanceAttributes(
instance_dir, console_path, storage_path, container_path)

"""
Pureport - The following functions facilitate finding LXD containers by name
in the event that the instance name template changes in OpenStack.
"""

def get_instance_criteria(instance):
"""Returns the list of possible instance name criteria used to find a container"""

return [
instance.name,
"instance-%08x" % instance.id
]

def get_container(client, instance, suffix = ''):
"""Returns the container associated to the specified instance.

Queries based on multiple possible sets of criteria to support scenarios
where OpenStack instance name template changes.
"""

instance_criteria = map(lambda x : x + suffix, get_instance_criteria(instance))

LOG.info("Instance = {}".format(instance))
for criteria in instance_criteria:
try:
instance = client.containers.get(criteria)
if instance != None:
LOG.info("Instance {} found by criteria {}", instance, criteria)
return instance
except:
LOG.warn("Unable to find instance {}".format(criteria), instance=instance)

return None

def get_rescue_container(client, instance):
"""Returns the rescue container for the specified instance if it exists."""
return get_container(client, instance, '-rescue')

def get_profile(client, instance):
"""Returns the profile for the specified instance """
instance_criteria = get_instance_criteria(instance)
for criteria in instance_criteria:
try:
instance = client.profiles.get(criteria)
if instance != None:
LOG.info("Instance {} found by criteria {}", instance, criteria)
return instance
except:
LOG.warn("Unable to find instance {}".format(criteria), instance=instance)

return None
65 changes: 31 additions & 34 deletions nova/virt/lxd/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ def cleanup_host(self, host):
def get_info(self, instance):
"""Return an InstanceInfo object for the instance."""
try:
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
except lxd_exceptions.NotFound:
raise exception.InstanceNotFound(instance_id=instance.uuid)

Expand All @@ -488,7 +488,7 @@ def spawn(self, context, instance, image_meta, injected_files,
information.
"""
try:
self.client.containers.get(instance.name)
common.get_container(self.client, instance)
raise exception.InstanceExists(name=instance.name)
except lxd_exceptions.LXDAPIException as e:
if e.response.status_code != 404:
Expand Down Expand Up @@ -568,7 +568,7 @@ def spawn(self, context, instance, image_meta, injected_files,
injected_files, admin_password,
network_info)

profile = self.client.profiles.get(instance.name)
profile = common.get_profile(self.client, instance)
config_drive = {
'configdrive': {
'path': '/config-drive',
Expand Down Expand Up @@ -606,13 +606,12 @@ def destroy(self, context, instance, network_info, block_device_info=None,
information.
"""
try:
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
if container.status != 'Stopped':
container.stop(wait=True)
container.delete(wait=True)
if (instance.vm_state == vm_states.RESCUED):
rescued_container = self.client.containers.get(
'%s-rescue' % instance.name)
rescued_container = get_rescue_container(self.client, instance)
if rescued_container.status != 'Stopped':
rescued_container.stop(wait=True)
rescued_container.delete(wait=True)
Expand Down Expand Up @@ -654,7 +653,7 @@ def cleanup(self, context, instance, network_info, block_device_info=None,
shutil.rmtree(container_dir)

try:
self.client.profiles.get(instance.name).delete()
common.get_profile(self.client, instance).delete()
except lxd_exceptions.LXDAPIException as e:
if e.response.status_code == 404:
LOG.warning('Failed to delete instance. '
Expand All @@ -674,7 +673,7 @@ def reboot(self, context, instance, network_info, reboot_type,
See `nova.virt.driver.ComputeDriver.cleanup` for more
information.
"""
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
container.restart(force=True, wait=True)

def get_console_output(self, context, instance):
Expand Down Expand Up @@ -715,7 +714,7 @@ def attach_volume(self, context, connection_info, instance, mountpoint,
See `nova.virt.driver.ComputeDriver.attach_volume' for
more information/
"""
profile = self.client.profiles.get(instance.name)
profile = common.get_profile(self.client, instance)
protocol = connection_info['driver_volume_type']
storage_driver = brick_get_connector(protocol)
device_info = storage_driver.connect_volume(
Expand Down Expand Up @@ -748,7 +747,7 @@ def detach_volume(self, connection_info, instance, mountpoint,
See `nova.virt.driver.Computedriver.detach_volume` for
more information.
"""
profile = self.client.profiles.get(instance.name)
profile = common.get_profile(self.client, instance)
vol_id = connection_info['data']['volume_id']
if vol_id in profile.devices:
del profile.devices[vol_id]
Expand All @@ -762,7 +761,7 @@ def attach_interface(self, context, instance, image_meta, vif):
self.vif_driver.plug(instance, vif)
self.firewall_driver.setup_basic_filtering(instance, vif)

profile = self.client.profiles.get(instance.name)
profile = common.get_profile(self.client, instance)

net_device = lxd_vif.get_vif_devname(vif)
config_update = {
Expand All @@ -778,7 +777,7 @@ def attach_interface(self, context, instance, image_meta, vif):
profile.save(wait=True)

def detach_interface(self, context, instance, vif):
profile = self.client.profiles.get(instance.name)
profile = common.get_profile(self.client, instance)
devname = lxd_vif.get_vif_devname(vif)

# NOTE(jamespage): Attempt to remove device using
Expand Down Expand Up @@ -810,7 +809,7 @@ def migrate_disk_and_power_off(
flavor.to_profile(
self.client, instance, network_info, block_device_info,
update=True)
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
container.stop(wait=True)
return ''

Expand All @@ -823,7 +822,7 @@ def snapshot(self, context, instance, image_id, update_task_state):

update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD)

container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
if container.status != 'Stopped':
container.stop(wait=True)
image = container.publish(wait=True)
Expand All @@ -846,7 +845,7 @@ def pause(self, instance):
See `nova.virt.driver.ComputeDriver.pause` for more
information.
"""
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
container.freeze(wait=True)

def unpause(self, instance):
Expand All @@ -855,7 +854,7 @@ def unpause(self, instance):
See `nova.virt.driver.ComputeDriver.unpause` for more
information.
"""
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
container.unfreeze(wait=True)

def suspend(self, context, instance):
Expand Down Expand Up @@ -910,12 +909,12 @@ def rescue(self, context, instance, network_info, image_meta,
"""
rescue = '%s-rescue' % instance.name

container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
container_rootfs = os.path.join(
nova.conf.CONF.lxd.root_dir, 'containers', instance.name, 'rootfs')
container.rename(rescue, wait=True)

profile = self.client.profiles.get(instance.name)
profile = common.get_profile(self.client, instance)

rescue_dir = {
'rescue': {
Expand Down Expand Up @@ -950,18 +949,16 @@ def unrescue(self, instance, network_info):
See 'nova.virt.drvier.ComputeDriver.unrescue` for more
information.
"""
rescue = '%s-rescue' % instance.name

container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
if container.status != 'Stopped':
container.stop(wait=True)
container.delete(wait=True)

profile = self.client.profiles.get(instance.name)
profile = common.get_profile(self.client, instance)
del profile.devices['rescue']
profile.save()

container = self.client.containers.get(rescue)
container = get_rescue_container(self.client, instance)
container.rename(instance.name, wait=True)
container.start(wait=True)

Expand All @@ -971,7 +968,7 @@ def power_off(self, instance, timeout=0, retry_interval=0):
See 'nova.virt.drvier.ComputeDriver.power_off` for more
information.
"""
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
if container.status != 'Stopped':
container.stop(wait=True)

Expand All @@ -982,7 +979,7 @@ def power_on(self, context, instance, network_info,
See 'nova.virt.drvier.ComputeDriver.power_on` for more
information.
"""
container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
if container.status != 'Running':
container.start(wait=True)

Expand Down Expand Up @@ -1132,17 +1129,17 @@ def finish_migration(self, context, migration, instance, disk_info,

# Step 3 - Start the network and container
self.plug_vifs(instance, network_info)
self.client.containers.get(instance.name).start(wait=True)
common.get_container(self.client, instance).start(wait=True)

def confirm_migration(self, context, migration, instance, network_info):
self.unplug_vifs(instance, network_info)

self.client.containers.get(instance.name).delete(wait=True)
self.client.profiles.get(instance.name).delete()
common.get_container(self.client, instance).delete(wait=True)
common.get_profile(self.client, instance).delete()

def finish_revert_migration(self, context, instance, network_info,
block_device_info=None, power_on=True):
self.client.containers.get(instance.name).start(wait=True)
common.get_container(self.client, instance).start(wait=True)

def pre_live_migration(self, context, instance, block_device_info,
network_info, disk_info, migrate_data=None):
Expand All @@ -1166,17 +1163,17 @@ def live_migration(self, context, instance, dest,

def post_live_migration(self, context, instance, block_device_info,
migrate_data=None):
self.client.containers.get(instance.name).delete(wait=True)
common.get_container(self.client, instance).delete(wait=True)

def post_live_migration_at_source(self, context, instance, network_info):
self.client.profiles.get(instance.name).delete()
common.get_profile(self.client, instance).delete()
self.cleanup(context, instance, network_info)

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)
common.get_container(self.client, instance)
raise exception.InstanceExists(name=instance.name)
except lxd_exceptions.LXDAPIException as e:
if e.response.status_code != 404:
Expand Down Expand Up @@ -1209,7 +1206,7 @@ def _add_configdrive(self, context, instance,
raise exception.ConfigDriveUnsupportedFormat(
format=CONF.config_drive_format)

container = self.client.containers.get(instance.name)
container = common.get_container(self.client, instance)
storage_id = 0
"""
Determine UID shift used for container uid mapping
Expand Down Expand Up @@ -1326,7 +1323,7 @@ def _migrate(self, source_host, instance):
"""Migrate an instance from source."""
source_client = pylxd.Client(
endpoint='https://{}:8443'.format(source_host), verify=False)
container = source_client.containers.get(instance.name)
container = common.get_container(source_client, instance)
data = container.generate_migration_data()

self.client.containers.create(data, wait=True)
2 changes: 1 addition & 1 deletion nova/virt/lxd/flavor.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def to_profile(client, instance, network_info, block_info, update=False):
devices.update(new)

if update is True:
profile = client.profiles.get(name)
profile = get_profile(client, instance)
profile.devices = devices
profile.config = config
profile.save()
Expand Down
4 changes: 2 additions & 2 deletions nova/virt/lxd/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def attach_ephemeral(client, block_device_info, lxd_config, instance):
if ephemeral_storage:
storage_driver = lxd_config['environment']['storage']

container = client.containers.get(instance.name)
container = common.get_container(client, instance)
container_id_map = container.config[
'volatile.last_state.idmap'].split(',')
storage_id = container_id_map[2].split(':')[1]
Expand Down Expand Up @@ -64,7 +64,7 @@ def attach_ephemeral(client, block_device_info, lxd_config, instance):
# before the container starts.
storage_dir = os.path.join(
instance_attrs.container_path, ephemeral['virtual_name'])
profile = client.profiles.get(instance.name)
profile = common.get_profile(client, instance)
storage_name = ephemeral['virtual_name']
profile.devices[storage_name]['source'] = storage_dir
profile.save()
Expand Down