summaryrefslogtreecommitdiffstats
path: root/nova/compute
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-12-05 00:44:13 +0000
committerGerrit Code Review <review@openstack.org>2012-12-05 00:44:13 +0000
commit255692feea3eee12bfc763f75fc8f3dabdbe9ba5 (patch)
treed690cc690f581e40ca7e49c246a4e0b1cc07cb51 /nova/compute
parentf35427693091bfca336207f2135f12b91348febb (diff)
parent1d00dfcfbb9bdeff358503fefefc7e6e7b4903eb (diff)
downloadnova-255692feea3eee12bfc763f75fc8f3dabdbe9ba5.tar.gz
nova-255692feea3eee12bfc763f75fc8f3dabdbe9ba5.tar.xz
nova-255692feea3eee12bfc763f75fc8f3dabdbe9ba5.zip
Merge "Boot from volume without image supplied"
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/api.py82
-rw-r--r--nova/compute/manager.py26
2 files changed, 69 insertions, 39 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 42db85a66..07a3a3afe 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -317,8 +317,7 @@ class API(base.Base):
self.network_api.validate_networks(context, requested_networks)
@staticmethod
- def _handle_kernel_and_ramdisk(context, kernel_id, ramdisk_id, image,
- image_service):
+ def _handle_kernel_and_ramdisk(context, kernel_id, ramdisk_id, image):
"""Choose kernel and ramdisk appropriate for the instance.
The kernel and ramdisk can be chosen in one of three ways:
@@ -330,11 +329,13 @@ class API(base.Base):
3. Forced to None by using `null_kernel` FLAG.
"""
# Inherit from image if not specified
+ image_properties = image.get('properties', {})
+
if kernel_id is None:
- kernel_id = image['properties'].get('kernel_id')
+ kernel_id = image_properties.get('kernel_id')
if ramdisk_id is None:
- ramdisk_id = image['properties'].get('ramdisk_id')
+ ramdisk_id = image_properties.get('ramdisk_id')
# Force to None if using null_kernel
if kernel_id == str(CONF.null_kernel):
@@ -343,9 +344,13 @@ class API(base.Base):
# Verify kernel and ramdisk exist (fail-fast)
if kernel_id is not None:
+ image_service, kernel_id = glance.get_remote_image_service(
+ context, kernel_id)
image_service.show(context, kernel_id)
if ramdisk_id is not None:
+ image_service, ramdisk_id = glance.get_remote_image_service(
+ context, ramdisk_id)
image_service.show(context, ramdisk_id)
return kernel_id, ramdisk_id
@@ -367,9 +372,11 @@ class API(base.Base):
@staticmethod
def _inherit_properties_from_image(image, auto_disk_config):
+ image_properties = image.get('properties', {})
+
def prop(prop_, prop_type=None):
"""Return the value of an image property."""
- value = image['properties'].get(prop_)
+ value = image_properties.get(prop_)
if value is not None:
if prop_type == 'bool':
@@ -435,17 +442,23 @@ class API(base.Base):
self._check_injected_file_quota(context, injected_files)
self._check_requested_networks(context, requested_networks)
- (image_service, image_id) = glance.get_remote_image_service(
- context, image_href)
- image = image_service.show(context, image_id)
- if image['status'] != 'active':
- raise exception.ImageNotActive(image_id=image_id)
+ if image_href:
+ (image_service, image_id) = glance.get_remote_image_service(
+ context, image_href)
+ image = image_service.show(context, image_id)
+ if image['status'] != 'active':
+ raise exception.ImageNotActive(image_id=image_id)
+ else:
+ image = {}
if instance_type['memory_mb'] < int(image.get('min_ram') or 0):
raise exception.InstanceTypeMemoryTooSmall()
if instance_type['root_gb'] < int(image.get('min_disk') or 0):
raise exception.InstanceTypeDiskTooSmall()
+ kernel_id, ramdisk_id = self._handle_kernel_and_ramdisk(
+ context, kernel_id, ramdisk_id, image)
+
# Handle config_drive
config_drive_id = None
if config_drive and config_drive is not True:
@@ -454,10 +467,9 @@ class API(base.Base):
config_drive = None
# Ensure config_drive image exists
- image_service.show(context, config_drive_id)
-
- kernel_id, ramdisk_id = self._handle_kernel_and_ramdisk(
- context, kernel_id, ramdisk_id, image, image_service)
+ cd_image_service, config_drive_id = \
+ glance.get_remote_image_service(context, config_drive_id)
+ cd_image_service.show(context, config_drive_id)
if key_data is None and key_name:
key_pair = self.db.key_pair_get(context, context.user_id,
@@ -467,11 +479,8 @@ class API(base.Base):
if reservation_id is None:
reservation_id = utils.generate_uid('r')
- # grab the architecture from glance
- architecture = image['properties'].get('architecture', 'Unknown')
-
root_device_name = block_device.properties_root_device_name(
- image['properties'])
+ image.get('properties', {}))
availability_zone, forced_host = self._handle_availability_zone(
availability_zone)
@@ -505,7 +514,6 @@ class API(base.Base):
'access_ip_v6': access_ip_v6,
'availability_zone': availability_zone,
'root_device_name': root_device_name,
- 'architecture': architecture,
'progress': 0}
if user_data:
@@ -663,12 +671,13 @@ class API(base.Base):
# require elevated context?
elevated = context.elevated()
instance_uuid = instance['uuid']
- mappings = image['properties'].get('mappings', [])
+ image_properties = image.get('properties', {})
+ mappings = image_properties.get('mappings', [])
if mappings:
self._update_image_block_device_mapping(elevated,
instance_type, instance_uuid, mappings)
- image_bdm = image['properties'].get('block_device_mapping', [])
+ image_bdm = image_properties.get('block_device_mapping', [])
for mapping in (image_bdm, block_device_mapping):
if not mapping:
continue
@@ -678,9 +687,10 @@ class API(base.Base):
def _populate_instance_shutdown_terminate(self, instance, image,
block_device_mapping):
"""Populate instance shutdown_terminate information."""
+ image_properties = image.get('properties', {})
if (block_device_mapping or
- image['properties'].get('mappings') or
- image['properties'].get('block_device_mapping')):
+ image_properties.get('mappings') or
+ image_properties.get('block_device_mapping')):
instance['shutdown_terminate'] = False
def _populate_instance_names(self, instance):
@@ -701,6 +711,7 @@ class API(base.Base):
def _populate_instance_for_create(self, base_options, image,
security_groups):
"""Build the beginning of a new instance."""
+ image_properties = image.get('properties', {})
instance = base_options
if not instance.get('uuid'):
@@ -716,13 +727,13 @@ class API(base.Base):
# Store image properties so we can use them later
# (for notifications, etc). Only store what we can.
instance.setdefault('system_metadata', {})
- for key, value in image['properties'].iteritems():
+ for key, value in image_properties.iteritems():
new_value = str(value)[:255]
instance['system_metadata']['image_%s' % key] = new_value
# Keep a record of the original base image that this
# image's instance is derived from:
- base_image_ref = image['properties'].get('base_image_ref')
+ base_image_ref = image_properties.get('base_image_ref')
if not base_image_ref:
# base image ref property not previously set through a snapshot.
# default to using the image ref as the base:
@@ -1509,8 +1520,12 @@ class API(base.Base):
def rebuild(self, context, instance, image_href, admin_password, **kwargs):
"""Rebuild the given instance with the provided attributes."""
- orig_image_ref = instance['image_ref']
- image = self._get_image(context, image_href)
+ if instance['image_ref']:
+ orig_image_ref = instance['image_ref']
+ image = self._get_image(context, image_href)
+ else:
+ orig_image_ref = ''
+ image = {}
files_to_inject = kwargs.pop('files_to_inject', [])
self._check_injected_file_quota(context, files_to_inject)
@@ -1524,11 +1539,14 @@ class API(base.Base):
if instance_type['root_gb'] < int(image.get('min_disk') or 0):
raise exception.InstanceTypeDiskTooSmall()
- (image_service, image_id) = glance.get_remote_image_service(context,
- image_href)
- image = image_service.show(context, image_id)
+ if image_href:
+ (image_service, image_id) = glance.get_remote_image_service(
+ context, image_href)
+ image = image_service.show(context, image_id)
+ else:
+ image = {}
kernel_id, ramdisk_id = self._handle_kernel_and_ramdisk(
- context, None, None, image, image_service)
+ context, None, None, image)
def _reset_image_metadata():
"""
@@ -1551,7 +1569,7 @@ class API(base.Base):
if key.startswith('image_'):
del sys_metadata[key]
# Add the new ones
- for key, value in image['properties'].iteritems():
+ for key, value in image.get('properties', {}).iteritems():
new_value = str(value)[:255]
sys_metadata['image_%s' % key] = new_value
self.db.instance_system_metadata_update(context,
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 16b7b19dc..fd8dc7d17 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -589,7 +589,11 @@ class ComputeManager(manager.SchedulerDependentManager):
LOG.debug(_("No node specified, defaulting to %(node)s") %
locals())
- extra_usage_info = {"image_name": image_meta['name']}
+ if image_meta:
+ extra_usage_info = {"image_name": image_meta['name']}
+ else:
+ extra_usage_info = {}
+
self._start_building(context, instance)
self._notify_about_instance_usage(
context, instance, "create.start",
@@ -770,7 +774,10 @@ class ComputeManager(manager.SchedulerDependentManager):
image, but is accurate because it reflects the image's
actual size.
"""
- image_meta = _get_image_meta(context, instance['image_ref'])
+ if instance['image_ref']:
+ image_meta = _get_image_meta(context, instance['image_ref'])
+ else: # Instance was started from volume - so no image ref
+ return {}
try:
size_bytes = image_meta['size']
@@ -1205,7 +1212,10 @@ class ComputeManager(manager.SchedulerDependentManager):
LOG.audit(_("Rebuilding instance"), context=context,
instance=instance)
- image_meta = _get_image_meta(context, image_ref)
+ if image_ref:
+ image_meta = _get_image_meta(context, image_ref)
+ else:
+ image_meta = {}
# This instance.exists message should contain the original
# image_ref, not the new one. Since the DB has been updated
@@ -1217,7 +1227,7 @@ class ComputeManager(manager.SchedulerDependentManager):
extra_usage_info=extra_usage_info)
# This message should contain the new image_ref
- extra_usage_info = {'image_name': image_meta['name']}
+ extra_usage_info = {'image_name': image_meta.get('name', '')}
self._notify_about_instance_usage(context, instance,
"rebuild.start", extra_usage_info=extra_usage_info)
@@ -1558,10 +1568,12 @@ class ComputeManager(manager.SchedulerDependentManager):
network_info = self._get_instance_nw_info(context, instance)
- # Boot the instance using the 'base' image instead of the user's
- # current (possibly broken) image
rescue_image_ref = self._get_rescue_image_ref(context, instance)
- rescue_image_meta = _get_image_meta(context, rescue_image_ref)
+
+ if rescue_image_ref:
+ rescue_image_meta = _get_image_meta(context, rescue_image_ref)
+ else:
+ rescue_image_meta = {}
with self._error_out_instance_on_exception(context, instance['uuid']):
self.driver.rescue(context, instance,