diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-12-05 00:44:13 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-12-05 00:44:13 +0000 |
| commit | 255692feea3eee12bfc763f75fc8f3dabdbe9ba5 (patch) | |
| tree | d690cc690f581e40ca7e49c246a4e0b1cc07cb51 /nova/compute | |
| parent | f35427693091bfca336207f2135f12b91348febb (diff) | |
| parent | 1d00dfcfbb9bdeff358503fefefc7e6e7b4903eb (diff) | |
| download | nova-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.py | 82 | ||||
| -rw-r--r-- | nova/compute/manager.py | 26 |
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, |
