From d224b0509273ca8a92c5c2b9abca69038835935c Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 30 Mar 2011 15:10:40 -0400 Subject: adding v1.0 support for rebuild; adding compute api rebuild support --- nova/compute/api.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 1dbd73f8f..93a5e7855 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -480,6 +480,15 @@ class API(base.Base): """Reboot the given instance.""" self._cast_compute_message('reboot_instance', context, instance_id) + def rebuild(self, context, instance_id, image_id, metadata=None): + """Rebuild the given instance with the provided metadata.""" + return + # default to an empty list + metadata = metadata or [] + #TODO: validate metadata + self._cast_compute_message('rebuild_instance', context, + instance_id, metadata) + def revert_resize(self, context, instance_id): """Reverts a resize, deleting the 'new' instance in the process""" context = context.elevated() -- cgit From e52cdaa75ac4b5c9ea37a8a8c9b1f02e8d0f638f Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 30 Mar 2011 15:33:52 -0400 Subject: Rough implementation of rebuild_instance in compute manager. --- nova/compute/manager.py | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 08b772517..7366785dd 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -152,6 +152,11 @@ class ComputeManager(manager.SchedulerDependentManager): state = power_state.FAILED self.db.instance_set_state(context, instance_id, state) + def _update_launched_at(self, context, instance_id): + """Update the launched_at parameter of the given instance.""" + data = {'launched_at': datetime.datetime.utcnow()} + self.db.instance_update(context, instance_id, data) + def get_console_topic(self, context, **kwargs): """Retrieves the console host for a project on this host Currently this is just set in the flags for each compute @@ -232,10 +237,7 @@ class ComputeManager(manager.SchedulerDependentManager): try: self.driver.spawn(instance_ref) - now = datetime.datetime.utcnow() - self.db.instance_update(context, - instance_id, - {'launched_at': now}) + self._update_launched_at(context, instance_id) except Exception: # pylint: disable=W0702 LOG.exception(_("Instance '%s' failed to spawn. Is virtualization" " enabled in the BIOS?"), instance_id, @@ -294,6 +296,32 @@ class ComputeManager(manager.SchedulerDependentManager): # TODO(ja): should we keep it in a terminated state for a bit? self.db.instance_destroy(context, instance_id) + @exception.wrap_exception + @checks_instance_lock + def rebuild_instance(self, context, instance_id): + """Destroy and re-make this instance. + + A 'rebuild' effectively purges all existing data from the system and + remakes the VM with given 'metadata' and 'personalities'. + + :param context: `nova.RequestContext` object + :param instance_id: Instance identifier (integer) + """ + context = context.elevated() + + instance_ref = self.db.instance_get(context, instance_id) + LOG.audit(_("Rebuilding instance %s"), instance_id, context=context) + + # TODO(blamar): Detach volumes prior to rebuild. + + # NOTE(blamar): The driver interface seems to indicate `destroy` is an + # async call, but the implementations look sync... + self.driver.destroy(instance_ref) + self.driver.spawn(instance_ref) + + self._update_launched_at(context, instance_id) + self._update_state(context, instance_id) + @exception.wrap_exception @checks_instance_lock def reboot_instance(self, context, instance_id): -- cgit From cee0e90c058c3e50a3388eb4960afeb21b441f6a Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 30 Mar 2011 16:17:07 -0400 Subject: adding initial v1.1 rebuild action support --- nova/compute/api.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 93a5e7855..fdfb8103b 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -482,12 +482,15 @@ class API(base.Base): def rebuild(self, context, instance_id, image_id, metadata=None): """Rebuild the given instance with the provided metadata.""" - return # default to an empty list metadata = metadata or [] #TODO: validate metadata + params = { + "image_id": image_id, + "metadata": metadata, + } self._cast_compute_message('rebuild_instance', context, - instance_id, metadata) + instance_id, params=params) def revert_resize(self, context, instance_id): """Reverts a resize, deleting the 'new' instance in the process""" -- cgit From 158d434b9ec3018909f2f90a1808e27e28e4f704 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 31 Mar 2011 09:49:03 -0400 Subject: Rebuild improvements. --- nova/compute/manager.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 7366785dd..0e2a6deb9 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -152,9 +152,14 @@ class ComputeManager(manager.SchedulerDependentManager): state = power_state.FAILED self.db.instance_set_state(context, instance_id, state) - def _update_launched_at(self, context, instance_id): + def _update_launched_at(self, context, instance_id, launched_at=None): """Update the launched_at parameter of the given instance.""" - data = {'launched_at': datetime.datetime.utcnow()} + data = {'launched_at': launched_at or datetime.datetime.utcnow()} + self.db.instance_update(context, instance_id, data) + + def _update_image_id(self, context, instance_id, image_id): + """Update the image_id for the given instance.""" + data = {'image_id': image_id} self.db.instance_update(context, instance_id, data) def get_console_topic(self, context, **kwargs): @@ -298,7 +303,7 @@ class ComputeManager(manager.SchedulerDependentManager): @exception.wrap_exception @checks_instance_lock - def rebuild_instance(self, context, instance_id): + def rebuild_instance(self, context, instance_id, image_id, metadata): """Destroy and re-make this instance. A 'rebuild' effectively purges all existing data from the system and @@ -306,6 +311,8 @@ class ComputeManager(manager.SchedulerDependentManager): :param context: `nova.RequestContext` object :param instance_id: Instance identifier (integer) + :param image_id: Image identifier (integer) + :param metadata: Metadata dictionary """ context = context.elevated() @@ -314,11 +321,14 @@ class ComputeManager(manager.SchedulerDependentManager): # TODO(blamar): Detach volumes prior to rebuild. - # NOTE(blamar): The driver interface seems to indicate `destroy` is an - # async call, but the implementations look sync... self.driver.destroy(instance_ref) + + #self._update_state(context, instance_id) + instance_ref.image_id = image_id + self.driver.spawn(instance_ref) + self._update_image_id(context, instance_id, image_id) self._update_launched_at(context, instance_id) self._update_state(context, instance_id) -- cgit From 2d800666df9cb16e90a47c10dc7d5d7a800088d4 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 31 Mar 2011 10:18:44 -0400 Subject: adding metadata support for v1.1 --- nova/compute/api.py | 59 +++++++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 27 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index fdfb8103b..43f972882 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -100,26 +100,7 @@ class API(base.Base): if len(content) > content_limit: raise quota.QuotaError(code="OnsetFileContentLimitExceeded") - def create(self, context, instance_type, - image_id, kernel_id=None, ramdisk_id=None, - min_count=1, max_count=1, - display_name='', display_description='', - key_name=None, key_data=None, security_group='default', - availability_zone=None, user_data=None, metadata=[], - injected_files=None): - """Create the number of instances requested if quota and - other arguments check out ok.""" - - type_data = instance_types.get_instance_type(instance_type) - num_instances = quota.allowed_instances(context, max_count, type_data) - if num_instances < min_count: - pid = context.project_id - LOG.warn(_("Quota exceeeded for %(pid)s," - " tried to run %(min_count)s instances") % locals()) - raise quota.QuotaError(_("Instance quota exceeded. You can only " - "run %s more instances of this type.") % - num_instances, "InstanceLimitExceeded") - + def _check_metadata_quota(self, context, metadata): num_metadata = len(metadata) quota_metadata = quota.allowed_metadata_items(context, num_metadata) if quota_metadata < num_metadata: @@ -130,6 +111,7 @@ class API(base.Base): LOG.warn(msg) raise quota.QuotaError(msg, "MetadataLimitExceeded") + def _check_metadata_item_length(self, context, metadata): # Because metadata is stored in the DB, we hard-code the size limits # In future, we may support more variable length strings, so we act # as if this is quota-controlled for forwards compatibility @@ -144,6 +126,29 @@ class API(base.Base): LOG.warn(msg) raise quota.QuotaError(msg, "MetadataLimitExceeded") + def create(self, context, instance_type, + image_id, kernel_id=None, ramdisk_id=None, + min_count=1, max_count=1, + display_name='', display_description='', + key_name=None, key_data=None, security_group='default', + availability_zone=None, user_data=None, metadata=[], + injected_files=None): + """Create the number of instances requested if quota and + other arguments check out ok.""" + + type_data = instance_types.get_instance_type(instance_type) + num_instances = quota.allowed_instances(context, max_count, type_data) + if num_instances < min_count: + pid = context.project_id + LOG.warn(_("Quota exceeeded for %(pid)s," + " tried to run %(min_count)s instances") % locals()) + raise quota.QuotaError(_("Instance quota exceeded. You can only " + "run %s more instances of this type.") % + num_instances, "InstanceLimitExceeded") + + self._check_metadata_quota(context, metadata) + self._check_metadata_item_length(context, metadata) + self._check_injected_file_quota(context, injected_files) image = self.image_service.show(context, image_id) @@ -482,15 +487,15 @@ class API(base.Base): def rebuild(self, context, instance_id, image_id, metadata=None): """Rebuild the given instance with the provided metadata.""" - # default to an empty list + metadata = metadata or [] - #TODO: validate metadata - params = { - "image_id": image_id, - "metadata": metadata, - } + self._check_metadata_quota(context, metadata) + self._check_metadata_item_length(context, metadata) + self._cast_compute_message('rebuild_instance', context, - instance_id, params=params) + instance_id, params={"image_id": image_id}) + + self.db.instance_update(context, instance_id, {"metadata": metadata}) def revert_resize(self, context, instance_id): """Reverts a resize, deleting the 'new' instance in the process""" -- cgit From 8e079f75e6391a3fc181fce7b6d03919b9625737 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 31 Mar 2011 10:45:53 -0400 Subject: Update state between delete and spawn. --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 0e2a6deb9..943a455a6 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -323,7 +323,7 @@ class ComputeManager(manager.SchedulerDependentManager): self.driver.destroy(instance_ref) - #self._update_state(context, instance_id) + self._update_state(context, instance_id) instance_ref.image_id = image_id self.driver.spawn(instance_ref) -- cgit From 1ecd9b3d00f002799a9eab92f0179dcbea8b8c37 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 31 Mar 2011 14:15:42 -0400 Subject: adding 'building' power state; testing for 409 from OSAPI when rebuild requested on server being rebuild --- nova/compute/api.py | 6 ++++++ nova/compute/power_state.py | 21 ++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 43f972882..32b283d31 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -34,6 +34,7 @@ from nova import rpc from nova import utils from nova import volume from nova.compute import instance_types +from nova.compute import power_state from nova.scheduler import api as scheduler_api from nova.db import base @@ -488,6 +489,11 @@ class API(base.Base): def rebuild(self, context, instance_id, image_id, metadata=None): """Rebuild the given instance with the provided metadata.""" + instance = db.api.instance_get(context, instance_id) + if instance["state"] == power_state.BUILDING: + msg = _("Instance already building") + raise exception.BuildInProgress(msg) + metadata = metadata or [] self._check_metadata_quota(context, metadata) self._check_metadata_item_length(context, metadata) diff --git a/nova/compute/power_state.py b/nova/compute/power_state.py index ef013b2ef..c468fe6b3 100644 --- a/nova/compute/power_state.py +++ b/nova/compute/power_state.py @@ -30,20 +30,23 @@ SHUTOFF = 0x05 CRASHED = 0x06 SUSPENDED = 0x07 FAILED = 0x08 +BUILDING = 0x09 # TODO(justinsb): Power state really needs to be a proper class, # so that we're not locked into the libvirt status codes and can put mapping # logic here rather than spread throughout the code _STATE_MAP = { - NOSTATE: 'pending', - RUNNING: 'running', - BLOCKED: 'blocked', - PAUSED: 'paused', - SHUTDOWN: 'shutdown', - SHUTOFF: 'shutdown', - CRASHED: 'crashed', - SUSPENDED: 'suspended', - FAILED: 'failed to spawn'} + NOSTATE: 'pending', + RUNNING: 'running', + BLOCKED: 'blocked', + PAUSED: 'paused', + SHUTDOWN: 'shutdown', + SHUTOFF: 'shutdown', + CRASHED: 'crashed', + SUSPENDED: 'suspended', + FAILED: 'failed to spawn', + BUILDING: 'building', +} def name(code): -- cgit From 59e8112994e293fa1155b703abcc3e33d7cfc6c7 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 31 Mar 2011 14:35:25 -0400 Subject: pep8 --- nova/compute/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 32b283d31..17bec2545 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -34,7 +34,7 @@ from nova import rpc from nova import utils from nova import volume from nova.compute import instance_types -from nova.compute import power_state +from nova.compute import power_state from nova.scheduler import api as scheduler_api from nova.db import base -- cgit From 6e6288d6d42bc17508b5df9781c7f04104f34fb2 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 31 Mar 2011 15:37:38 -0400 Subject: Now using the new power state instead of string. --- nova/compute/manager.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 2c5285dff..94d4f1991 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -141,15 +141,21 @@ class ComputeManager(manager.SchedulerDependentManager): """ self.driver.init_host(host=self.host) - def _update_state(self, context, instance_id, desc=None): + def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" instance_ref = self.db.instance_get(context, instance_id) - try: - info = self.driver.get_info(instance_ref['name']) - state = info['state'] - except exception.NotFound: - state = power_state.FAILED - self.db.instance_set_state(context, instance_id, state, desc) + + if state is None: + try: + info = self.driver.get_info(instance_ref['name']) + except exception.NotFound: + info = None + state = power_state.FAILED + + if info is not None: + state = info['state'] + + self.db.instance_set_state(context, instance_id, state) def _update_launched_at(self, context, instance_id, launched_at=None): """Update the launched_at parameter of the given instance.""" @@ -318,7 +324,7 @@ class ComputeManager(manager.SchedulerDependentManager): LOG.audit(_("Rebuilding instance %s"), instance_id, context=context) # TODO(blamar): Detach volumes prior to rebuild. - self._update_state(context, instance_id, "rebuilding") + self._update_state(context, instance_id, power_state.BUILDING) self.driver.destroy(instance_ref) instance_ref.image_id = image_id -- cgit From 7688cbb07ffcfd6446dc9ede60fb9eb610809c1d Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 31 Mar 2011 16:46:08 -0400 Subject: Removal of instance_set_state from driver code, it shouldnt be there, but instead should be in the compute manager. --- nova/compute/manager.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 94d4f1991..db1d6950e 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -240,21 +240,16 @@ class ComputeManager(manager.SchedulerDependentManager): instance_id) # TODO(vish) check to make sure the availability zone matches - self.db.instance_set_state(context, - instance_id, - power_state.NOSTATE, - 'spawning') + self._update_state(context, instance_id, power_state.BUILDING) try: self.driver.spawn(instance_ref) self._update_launched_at(context, instance_id) - except Exception: # pylint: disable=W0702 + except Exception as ex: # pylint: disable=W0702 + LOG.debug(ex) LOG.exception(_("Instance '%s' failed to spawn. Is virtualization" " enabled in the BIOS?"), instance_id, context=context) - self.db.instance_set_state(context, - instance_id, - power_state.SHUTDOWN) self._update_state(context, instance_id) @@ -1133,9 +1128,7 @@ class ComputeManager(manager.SchedulerDependentManager): if vm_state != db_state: LOG.info(_("DB/VM state mismatch. Changing state from " "'%(db_state)s' to '%(vm_state)s'") % locals()) - self.db.instance_set_state(context, - db_instance['id'], - vm_state) + self._update_state(context, db_instance['id'], vm_state) if vm_state == power_state.SHUTOFF: # TODO(soren): This is what the compute manager does when you -- cgit From dcb94be18b1f8b3591d7304208b64a296cdd71f6 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 1 Apr 2011 14:16:17 -0400 Subject: Poller needs to check for BUILDING not NOSTATE now, since we're being more explict about what is going on. --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index db1d6950e..1e0997a97 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1104,7 +1104,7 @@ class ComputeManager(manager.SchedulerDependentManager): if vm_instance is None: # NOTE(justinsb): We have to be very careful here, because a # concurrent operation could be in progress (e.g. a spawn) - if db_state == power_state.NOSTATE: + if db_state == power_state.BUILDING: # Assume that NOSTATE => spawning # TODO(justinsb): This does mean that if we crash during a # spawn, the machine will never leave the spawning state, -- cgit From b2f693f63d73e3e51cb3be40b5deae720c773340 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 12 Apr 2011 09:23:52 -0400 Subject: Reverted some superfluous changes to make MP more concise. --- nova/compute/api.py | 52 ++++++++++++++++++++++++------------------------- nova/compute/manager.py | 11 ++++++----- 2 files changed, 32 insertions(+), 31 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 020d3b06d..5ec88adbd 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -105,32 +105,6 @@ class API(base.Base): if len(content) > content_limit: raise quota.QuotaError(code="OnsetFileContentLimitExceeded") - def _check_metadata_quota(self, context, metadata): - num_metadata = len(metadata) - quota_metadata = quota.allowed_metadata_items(context, num_metadata) - if quota_metadata < num_metadata: - pid = context.project_id - msg = (_("Quota exceeeded for %(pid)s," - " tried to set %(num_metadata)s metadata properties") - % locals()) - LOG.warn(msg) - raise quota.QuotaError(msg, "MetadataLimitExceeded") - - def _check_metadata_item_length(self, context, metadata): - # Because metadata is stored in the DB, we hard-code the size limits - # In future, we may support more variable length strings, so we act - # as if this is quota-controlled for forwards compatibility - for metadata_item in metadata: - k = metadata_item['key'] - v = metadata_item['value'] - if len(k) > 255 or len(v) > 255: - pid = context.project_id - msg = (_("Quota exceeeded for %(pid)s," - " metadata property key or value too long") - % locals()) - LOG.warn(msg) - raise quota.QuotaError(msg, "MetadataLimitExceeded") - def create(self, context, instance_type, image_id, kernel_id=None, ramdisk_id=None, min_count=1, max_count=1, @@ -267,6 +241,32 @@ class API(base.Base): return [dict(x.iteritems()) for x in instances] + def _check_metadata_quota(self, context, metadata): + num_metadata = len(metadata) + quota_metadata = quota.allowed_metadata_items(context, num_metadata) + if quota_metadata < num_metadata: + pid = context.project_id + msg = (_("Quota exceeeded for %(pid)s," + " tried to set %(num_metadata)s metadata properties") + % locals()) + LOG.warn(msg) + raise quota.QuotaError(msg, "MetadataLimitExceeded") + + def _check_metadata_item_length(self, context, metadata): + # Because metadata is stored in the DB, we hard-code the size limits + # In future, we may support more variable length strings, so we act + # as if this is quota-controlled for forwards compatibility + for metadata_item in metadata: + k = metadata_item['key'] + v = metadata_item['value'] + if len(k) > 255 or len(v) > 255: + pid = context.project_id + msg = (_("Quota exceeeded for %(pid)s," + " metadata property key or value too long") + % locals()) + LOG.warn(msg) + raise quota.QuotaError(msg, "MetadataLimitExceeded") + def has_finished_migration(self, context, instance_id): """Retrieves whether or not a finished migration exists for an instance""" diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 51f5322cd..04f2abc49 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -150,10 +150,11 @@ class ComputeManager(manager.SchedulerDependentManager): info = self.driver.get_info(instance_ref['name']) except exception.NotFound: info = None - state = power_state.FAILED if info is not None: state = info['state'] + else: + state = power_state.FAILED self.db.instance_set_state(context, instance_id, state) @@ -246,10 +247,10 @@ class ComputeManager(manager.SchedulerDependentManager): self.driver.spawn(instance_ref) self._update_launched_at(context, instance_id) except Exception as ex: # pylint: disable=W0702 - LOG.debug(ex) - LOG.exception(_("Instance '%s' failed to spawn. Is virtualization" - " enabled in the BIOS?"), instance_id, - context=context) + msg = _("Instance '%(instance_id)s' failed to spawn. Is " + "virtualization enabled in the BIOS? Details: " + "%(ex)s") % locals() + LOG.exception(msg) self._update_state(context, instance_id) -- cgit From ae30b0a83469b15d1986fdbbef4f1dee52d68c17 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 12 Apr 2011 09:37:06 -0400 Subject: Removed extra call from try/except. --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 04f2abc49..a8bb091ec 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -245,13 +245,13 @@ class ComputeManager(manager.SchedulerDependentManager): try: self.driver.spawn(instance_ref) - self._update_launched_at(context, instance_id) except Exception as ex: # pylint: disable=W0702 msg = _("Instance '%(instance_id)s' failed to spawn. Is " "virtualization enabled in the BIOS? Details: " "%(ex)s") % locals() LOG.exception(msg) + self._update_launched_at(context, instance_id) self._update_state(context, instance_id) @exception.wrap_exception -- cgit From cebc98176926f57016a508d5c59b11f55dfcf2b3 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 12 Apr 2011 10:19:37 -0400 Subject: Commit for merge of metadata_quotas preq. --- nova/compute/api.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 5ec88adbd..e5065c3a5 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -497,10 +497,11 @@ class API(base.Base): """Reboot the given instance.""" self._cast_compute_message('reboot_instance', context, instance_id) - def rebuild(self, context, instance_id, image_id, metadata=None): + def rebuild(self, context, instance_id, image_id, metadata=None, + files_to_inject=None): """Rebuild the given instance with the provided metadata.""" - instance = db.api.instance_get(context, instance_id) + if instance["state"] == power_state.BUILDING: msg = _("Instance already building") raise exception.BuildInProgress(msg) @@ -509,11 +510,22 @@ class API(base.Base): self._check_metadata_quota(context, metadata) self._check_metadata_item_length(context, metadata) - self._cast_compute_message('rebuild_instance', context, - instance_id, params={"image_id": image_id}) + files_to_inject = files_to_inject or [] + self._check_injected_file_quota(context, files_to_inject) + self._check_injected_file_format(context, files_to_inject) self.db.instance_update(context, instance_id, {"metadata": metadata}) + rebuild_params = { + "image_id": image_id, + "injected_files": files_to_inject, + } + + self._cast_compute_message('rebuild_instance', + context, + instance_id, + params=rebuild_params) + def revert_resize(self, context, instance_id): """Reverts a resize, deleting the 'new' instance in the process""" context = context.elevated() -- cgit From 5de1825e2c1d1cdc63790f61e05b1f8b05ded1b3 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 12 Apr 2011 11:09:31 -0400 Subject: Cleanup after prereq merge. --- nova/compute/api.py | 42 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 30 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index effe68d6d..c99d7f828 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -105,6 +105,15 @@ class API(base.Base): if len(content) > content_limit: raise quota.QuotaError(code="OnsetFileContentLimitExceeded") + def _check_injected_file_format(self, injected_files): + """Ensure given injected files are in the correct format.""" + for _, content in injected_files: + try: + base64.b64decode(content) + except TypeError: + msg = _("File contents must be base64 encoded.") + raise exception.Error(msg) + def _check_metadata_properties_quota(self, context, metadata={}): """Enforce quota limits on metadata properties""" num_metadata = len(metadata) @@ -263,32 +272,6 @@ class API(base.Base): return [dict(x.iteritems()) for x in instances] - def _check_metadata_quota(self, context, metadata): - num_metadata = len(metadata) - quota_metadata = quota.allowed_metadata_items(context, num_metadata) - if quota_metadata < num_metadata: - pid = context.project_id - msg = (_("Quota exceeeded for %(pid)s," - " tried to set %(num_metadata)s metadata properties") - % locals()) - LOG.warn(msg) - raise quota.QuotaError(msg, "MetadataLimitExceeded") - - def _check_metadata_item_length(self, context, metadata): - # Because metadata is stored in the DB, we hard-code the size limits - # In future, we may support more variable length strings, so we act - # as if this is quota-controlled for forwards compatibility - for metadata_item in metadata: - k = metadata_item['key'] - v = metadata_item['value'] - if len(k) > 255 or len(v) > 255: - pid = context.project_id - msg = (_("Quota exceeeded for %(pid)s," - " metadata property key or value too long") - % locals()) - LOG.warn(msg) - raise quota.QuotaError(msg, "MetadataLimitExceeded") - def has_finished_migration(self, context, instance_id): """Retrieves whether or not a finished migration exists for an instance""" @@ -528,13 +511,12 @@ class API(base.Base): msg = _("Instance already building") raise exception.BuildInProgress(msg) - metadata = metadata or [] - self._check_metadata_quota(context, metadata) - self._check_metadata_item_length(context, metadata) + metadata = metadata or {} + self._check_metadata_properties_quota(context, metadata) files_to_inject = files_to_inject or [] self._check_injected_file_quota(context, files_to_inject) - self._check_injected_file_format(context, files_to_inject) + self._check_injected_file_format(files_to_inject) self.db.instance_update(context, instance_id, {"metadata": metadata}) -- cgit From e5e1863349a1842d3f6ca452a59e574c03102ebf Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 12 Apr 2011 11:47:08 -0400 Subject: Added some tests. --- nova/compute/api.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index c99d7f828..3bf18c667 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -20,6 +20,7 @@ Handles all requests relating to instances (guest vms). """ +import base64 import datetime import re import time -- cgit From bee606e08f5ba96a25d02a9358265db4a59ce5cd Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 20 Apr 2011 11:06:03 -0400 Subject: Removed _ and replaced with real variable name. --- nova/compute/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index a0f0ff27e..703533f55 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -106,7 +106,7 @@ class API(base.Base): def _check_injected_file_format(self, injected_files): """Ensure given injected files are in the correct format.""" - for _, content in injected_files: + for file_path, content in injected_files: try: base64.b64decode(content) except TypeError: -- cgit From e628007bec0e313f252d8dd15d19297f99dc93f8 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 20 Apr 2011 11:09:14 -0400 Subject: Removed TODO we don't need. --- nova/compute/manager.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 0e5d6c4ff..5a7b4fb11 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -319,7 +319,6 @@ class ComputeManager(manager.SchedulerDependentManager): instance_ref = self.db.instance_get(context, instance_id) LOG.audit(_("Rebuilding instance %s"), instance_id, context=context) - # TODO(blamar): Detach volumes prior to rebuild. self._update_state(context, instance_id, power_state.BUILDING) self.driver.destroy(instance_ref) -- cgit From 6c538b870005464b2bab0510b4e98a71d0d24770 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 20 Apr 2011 11:11:45 -0400 Subject: Removed no longer relevant comment. --- nova/compute/manager.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 5a7b4fb11..46f910b27 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -1103,7 +1103,6 @@ class ComputeManager(manager.SchedulerDependentManager): # NOTE(justinsb): We have to be very careful here, because a # concurrent operation could be in progress (e.g. a spawn) if db_state == power_state.BUILDING: - # Assume that NOSTATE => spawning # TODO(justinsb): This does mean that if we crash during a # spawn, the machine will never leave the spawning state, # but this is just the way nova is; this function isn't -- cgit From 6c037c5c639249556fcadd871d8af91760b50e90 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 21 Apr 2011 16:17:16 -0400 Subject: Fixes and reworkings based on review. --- nova/compute/api.py | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 703533f55..4ec840b07 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -18,7 +18,6 @@ """Handles all requests relating to instances (guest vms).""" -import base64 import datetime import re import time @@ -104,15 +103,6 @@ class API(base.Base): if len(content) > content_limit: raise quota.QuotaError(code="OnsetFileContentLimitExceeded") - def _check_injected_file_format(self, injected_files): - """Ensure given injected files are in the correct format.""" - for file_path, content in injected_files: - try: - base64.b64decode(content) - except TypeError: - msg = _("File contents must be base64 encoded.") - raise exception.Error(msg) - def _check_metadata_properties_quota(self, context, metadata={}): """Enforce quota limits on metadata properties.""" num_metadata = len(metadata) @@ -526,7 +516,6 @@ class API(base.Base): files_to_inject = files_to_inject or [] self._check_injected_file_quota(context, files_to_inject) - self._check_injected_file_format(files_to_inject) self.db.instance_update(context, instance_id, {"metadata": metadata}) -- cgit From 8e6875e8c9b45a03396d5e4312c4f9136b1dc552 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 27 Apr 2011 14:03:05 -0700 Subject: further cleanup of nova/exceptions.py --- nova/compute/instance_types.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index 7e7198b96..8cfa2f8da 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -37,11 +37,11 @@ def create(name, memory, vcpus, local_gb, flavorid, swap=0, try: int(option) except ValueError: - raise exception.InvalidInputException( - _("create arguments must be positive integers")) + raise exception.InvalidInput(reason=_("create arguments must " + "be positive integers")) if (int(memory) <= 0) or (int(vcpus) <= 0) or (int(local_gb) < 0): - raise exception.InvalidInputException( - _("create arguments must be positive integers")) + raise exception.InvalidInput(reason=_("create arguments must " + "be positive integers")) try: db.instance_type_create( @@ -64,7 +64,7 @@ def create(name, memory, vcpus, local_gb, flavorid, swap=0, def destroy(name): """Marks instance types as deleted.""" if name is None: - raise exception.InvalidInputException(_("No instance type specified")) + raise exception.InstanceNotFound(instance_id=instance_name) else: try: db.instance_type_destroy(context.get_admin_context(), name) @@ -76,7 +76,7 @@ def destroy(name): def purge(name): """Removes instance types from database.""" if name is None: - raise exception.InvalidInputException(_("No instance type specified")) + raise exception.InnstanceNotFound(instance_id=name) else: try: db.instance_type_purge(context.get_admin_context(), name) -- cgit From 0fe36c8ba3e524e490c66011c0787ea8a26dcfee Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 27 Apr 2011 14:23:21 -0700 Subject: Correcting exception case --- nova/compute/instance_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index 8cfa2f8da..1275a6fdd 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -64,7 +64,7 @@ def create(name, memory, vcpus, local_gb, flavorid, swap=0, def destroy(name): """Marks instance types as deleted.""" if name is None: - raise exception.InstanceNotFound(instance_id=instance_name) + raise exception.InvalidInstanceType(instance_type=name) else: try: db.instance_type_destroy(context.get_admin_context(), name) @@ -76,7 +76,7 @@ def destroy(name): def purge(name): """Removes instance types from database.""" if name is None: - raise exception.InnstanceNotFound(instance_id=name) + raise exception.InvalidInstanceType(instance_type=name) else: try: db.instance_type_purge(context.get_admin_context(), name) -- cgit