From 818c2424a0547882fe6bdfe6613ee66a248d91db Mon Sep 17 00:00:00 2001 From: Mike Scherbakov Date: Sun, 15 May 2011 15:11:54 +0400 Subject: Define image state during snapshotting. Name snapshot to the name provided, not generate. --- nova/compute/api.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 63884be97..971c0732f 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -500,9 +500,10 @@ class API(base.Base): """ properties = {'instance_id': str(instance_id), - 'user_id': str(context.user_id)} + 'user_id': str(context.user_id), + 'image_state': 'creating'} sent_meta = {'name': name, 'is_public': False, - 'properties': properties} + 'status': 'creating', 'properties': properties} recv_meta = self.image_service.create(context, sent_meta) params = {'image_id': recv_meta['id']} self._cast_compute_message('snapshot_instance', context, instance_id, -- cgit From dacb4899ea631840fd95ee0bd25d999fbb16b8b4 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 17 May 2011 19:10:11 -0400 Subject: use utils.get_image_service in compute_api --- nova/compute/api.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index a12f8d515..930e4efaa 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -156,7 +156,8 @@ class API(base.Base): self._check_metadata_properties_quota(context, metadata) self._check_injected_file_quota(context, injected_files) - image = self.image_service.show(context, image_id) + (image_service, service_image_id) = utils.get_image_service(image_id) + image = image_service.show(context, service_image_id) os_type = None if 'properties' in image and 'os_type' in image['properties']: @@ -176,9 +177,9 @@ class API(base.Base): logging.debug("Using Kernel=%s, Ramdisk=%s" % (kernel_id, ramdisk_id)) if kernel_id: - self.image_service.show(context, kernel_id) + image_service.show(context, kernel_id) if ramdisk_id: - self.image_service.show(context, ramdisk_id) + image_service.show(context, ramdisk_id) if security_group is None: security_group = ['default'] @@ -515,6 +516,8 @@ class API(base.Base): 'user_id': str(context.user_id)} sent_meta = {'name': name, 'is_public': False, 'properties': properties} + # TODO(wwolf): not sure if we need to use + # utils.get_image_service() here ? recv_meta = self.image_service.create(context, sent_meta) params = {'image_id': recv_meta['id']} self._cast_compute_message('snapshot_instance', context, instance_id, -- cgit From 6c151bfbfeb728d6e38f777640d483c1e344113d Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Wed, 18 May 2011 03:51:25 -0400 Subject: Removed all utils.import_object(FLAGS.image_service) and replaced with utils.get_default_image_service(). --- nova/compute/api.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 930e4efaa..4e7af7421 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -58,9 +58,7 @@ class API(base.Base): def __init__(self, image_service=None, network_api=None, volume_api=None, hostname_factory=generate_default_hostname, **kwargs): - if not image_service: - image_service = utils.import_object(FLAGS.image_service) - self.image_service = image_service + self.image_service = image_service or utils.get_default_image_service() if not network_api: network_api = network.API() self.network_api = network_api -- cgit From 048dda438c9670998e9c91f6a906373a12ea294d Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 18 May 2011 13:03:05 -0400 Subject: fixed bug with compute_api not having actual image_ref to use proper image service --- nova/compute/api.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 4e7af7421..40d011132 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -132,7 +132,7 @@ class API(base.Base): display_name='', display_description='', key_name=None, key_data=None, security_group='default', availability_zone=None, user_data=None, metadata={}, - injected_files=None): + injected_files=None, image_ref=None): """Create the number and type of instances requested. Verifies that quota and other arguments are valid. @@ -154,7 +154,8 @@ class API(base.Base): self._check_metadata_properties_quota(context, metadata) self._check_injected_file_quota(context, injected_files) - (image_service, service_image_id) = utils.get_image_service(image_id) + (image_service, service_image_id) = utils.get_image_service( + image_ref or image_id) image = image_service.show(context, service_image_id) os_type = None @@ -198,7 +199,7 @@ class API(base.Base): base_options = { 'reservation_id': utils.generate_uid('r'), - 'image_id': image_id, + 'image_id': image_ref or image_id, 'kernel_id': kernel_id or '', 'ramdisk_id': ramdisk_id or '', 'state': 0, -- cgit From 1c315d233128f1013d1ec02c78acb36821f6c63d Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 23 May 2011 10:28:04 -0400 Subject: moved utils functions into nova/image/ --- 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 61adda13a..a9075ff8a 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -26,6 +26,7 @@ import time from nova import db from nova import exception from nova import flags +import nova.image from nova import log as logging from nova import network from nova import quota @@ -58,7 +59,9 @@ class API(base.Base): def __init__(self, image_service=None, network_api=None, volume_api=None, hostname_factory=generate_default_hostname, **kwargs): - self.image_service = image_service or utils.get_default_image_service() + self.image_service = image_service or \ + nova.image.get_default_image_service() + if not network_api: network_api = network.API() self.network_api = network_api @@ -154,7 +157,7 @@ class API(base.Base): self._check_metadata_properties_quota(context, metadata) self._check_injected_file_quota(context, injected_files) - (image_service, service_image_id) = utils.get_image_service( + (image_service, service_image_id) = nova.image.get_image_service( image_ref or image_id) image = image_service.show(context, service_image_id) -- cgit From b6a4f6aa5b2a97a6a7d79c40c1a3160abc1def39 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Mon, 23 May 2011 16:47:25 -0400 Subject: Renaming service_image_id vars to image_id to reduce confusion. Also some minor cleanup. --- nova/compute/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index a9075ff8a..47f7a594f 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -157,9 +157,9 @@ class API(base.Base): self._check_metadata_properties_quota(context, metadata) self._check_injected_file_quota(context, injected_files) - (image_service, service_image_id) = nova.image.get_image_service( + (image_service, image_id) = nova.image.get_image_service( image_ref or image_id) - image = image_service.show(context, service_image_id) + image = image_service.show(context, image_id) os_type = None if 'properties' in image and 'os_type' in image['properties']: -- cgit From 0ed410621b3c2d621aa3fa52ca7ac46c6a5f0b70 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 23 May 2011 16:19:12 -0700 Subject: getting closer to working select call --- nova/compute/api.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 785aff397..301c777bb 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -257,19 +257,21 @@ class API(base.Base): # we'll be ripping this whole for-loop out and deferring the # creation of the Instance record. At that point all this will # change. + filter_driver = 'nova.scheduler.host_filter.InstanceTypeFilter' + request_spec = { + 'instance_properties': base_options, + 'instance_type': instance_type, + 'filter_driver': filter_driver, + 'blob': zone_blob + } + LOG.debug(_("**** REQUEST SPEC: %(request_spec)s") % locals()) + rpc.cast(context, FLAGS.scheduler_topic, {"method": "run_instance", "args": {"topic": FLAGS.compute_topic, "instance_id": instance_id, - "request_spec": { - 'instance_properties': instance, - 'instance_type': instance_type, - 'filter_driver': - 'nova.scheduler.host_filter.' - 'InstanceTypeFilter', - 'blob': zone_blob - }, + "request_spec": request_spec, "availability_zone": availability_zone, "injected_files": injected_files}}) -- cgit From a5efbca08a6b057290622ba5938f87d2e44be3eb Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 23 May 2011 21:55:15 -0400 Subject: take out irrelevant TODO --- nova/compute/api.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 47f7a594f..7ffe9c90c 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -525,8 +525,7 @@ class API(base.Base): 'user_id': str(context.user_id)} sent_meta = {'name': name, 'is_public': False, 'properties': properties} - # TODO(wwolf): not sure if we need to use - # utils.get_image_service() here ? + recv_meta = self.image_service.create(context, sent_meta) params = {'image_id': recv_meta['id']} self._cast_compute_message('snapshot_instance', context, instance_id, -- cgit From f49024c437f2680a18eb702f2975de2955b98889 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Mon, 23 May 2011 22:47:44 -0400 Subject: make image_ref and image_id usage more consistant, eliminate redundancy in compute_api.create() call --- nova/compute/api.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 7ffe9c90c..4c4bc592b 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -130,12 +130,12 @@ class API(base.Base): raise quota.QuotaError(msg, "MetadataLimitExceeded") def create(self, context, instance_type, - image_id, kernel_id=None, ramdisk_id=None, + image_ref, 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, image_ref=None): + injected_files=None): """Create the number and type of instances requested. Verifies that quota and other arguments are valid. @@ -157,8 +157,7 @@ class API(base.Base): self._check_metadata_properties_quota(context, metadata) self._check_injected_file_quota(context, injected_files) - (image_service, image_id) = nova.image.get_image_service( - image_ref or image_id) + (image_service, image_id) = nova.image.get_image_service(image_ref) image = image_service.show(context, image_id) os_type = None @@ -202,7 +201,7 @@ class API(base.Base): base_options = { 'reservation_id': utils.generate_uid('r'), - 'image_id': image_ref or image_id, + 'image_id': image_ref, 'kernel_id': kernel_id or '', 'ramdisk_id': ramdisk_id or '', 'state': 0, -- cgit From 48a3ec6e55f029578d5dc8ef7fe2e9fbe0de1b81 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 24 May 2011 12:05:46 -0700 Subject: more fix up --- nova/compute/api.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 301c777bb..d66ee7920 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -264,7 +264,6 @@ class API(base.Base): 'filter_driver': filter_driver, 'blob': zone_blob } - LOG.debug(_("**** REQUEST SPEC: %(request_spec)s") % locals()) rpc.cast(context, FLAGS.scheduler_topic, -- cgit From 660d1802a6c202465af585a059930113de5ae646 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 25 May 2011 13:20:34 -0700 Subject: starting breakdown of nova.compute.api.create() --- nova/compute/api.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 7 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 57f8c421a..1d75dbc80 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -54,6 +54,7 @@ def generate_default_hostname(instance_id): class API(base.Base): """API for interacting with the compute manager.""" + scheduler_rules = None def __init__(self, image_service=None, network_api=None, volume_api=None, hostname_factory=generate_default_hostname, @@ -128,18 +129,15 @@ class API(base.Base): LOG.warn(msg) raise quota.QuotaError(msg, "MetadataLimitExceeded") - def create(self, context, instance_type, + def _check_create_parameters(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, zone_blob=None): - """Create the number and type of instances requested. - - Verifies that quota and other arguments are valid. - - """ + """Verify all the input parameters regardless of the provisioning + strategy being performed.""" if not instance_type: instance_type = instance_types.get_default_instance_type() @@ -220,7 +218,46 @@ class API(base.Base): 'metadata': metadata, 'availability_zone': availability_zone, 'os_type': os_type} - elevated = context.elevated() + + return (num_instances, base_options) + + def create_all_at_once(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, zone_blob=None): + """Provision the instances by passing the whole request to + the Scheduler for execution.""" + self._check_create_parameters(self, context, instance_type, + image_id, kernel_id, ramdisk_id, min_count=1, max_count=1, + display_name, display_description, + key_name, key_data, security_group, + availability_zone, user_data, metadata, + injected_files, zone_blob) + + 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, zone_blob=None): + """Provision the instances by sending off a series of single + instance requests to the Schedulers. This is fine for trival + Scheduler drivers, but may remove the effectiveness of the + more complicated drivers.""" + + num_instances, base_options = self._check_create_parameters( + context, instance_type, + image_id, kernel_id, ramdisk_id, + min_count=1, max_count=1, + display_name, display_description, + key_name, key_data, security_group, + availability_zone, user_data, metadata, + injected_files, zone_blob) + instances = [] LOG.debug(_("Going to run %s instances..."), num_instances) for num in range(num_instances): @@ -279,6 +316,22 @@ class API(base.Base): return [dict(x.iteritems()) for x in instances] + def smart_create(self, *args, **kwargs): + """Ask the scheduler if we should: 1. do single shot instance + requests or all-at-once, and 2. defer the DB work until + a suitable host has been selected (if at all). Cache this + information and act accordingly.""" + + if API.scheduler_rules == None: + API.scheduler_rules = scheduler_api.get_scheduler_rules(context) + + should_create_all_at_once, should_defer_database_create = \ + API.scheduler_rules + + if should_create_all_at_once: + return self.create_all_at_once(*args, **kwargs) + return self.create(*args, **kwargs) + def has_finished_migration(self, context, instance_id): """Returns true if an instance has a finished migration.""" try: -- cgit From 781672793c5fb774c5d9d291798775db471233b2 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Wed, 25 May 2011 19:57:04 -0400 Subject: Renamed image_ref variables to image_href. Since the convention is that x_ref vars may imply that they are db objects. --- nova/compute/api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 4c4bc592b..bb419520d 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -130,7 +130,7 @@ class API(base.Base): raise quota.QuotaError(msg, "MetadataLimitExceeded") def create(self, context, instance_type, - image_ref, kernel_id=None, ramdisk_id=None, + image_href, 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', @@ -157,7 +157,7 @@ class API(base.Base): self._check_metadata_properties_quota(context, metadata) self._check_injected_file_quota(context, injected_files) - (image_service, image_id) = nova.image.get_image_service(image_ref) + (image_service, image_id) = nova.image.get_image_service(image_href) image = image_service.show(context, image_id) os_type = None @@ -201,7 +201,7 @@ class API(base.Base): base_options = { 'reservation_id': utils.generate_uid('r'), - 'image_id': image_ref, + 'image_id': image_href, 'kernel_id': kernel_id or '', 'ramdisk_id': ramdisk_id or '', 'state': 0, -- cgit From bc176751de7f55d22d1bb04552bbff9c496979ed Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 26 May 2011 08:28:57 -0700 Subject: refactoring compute.api.create() --- nova/compute/api.py | 193 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 118 insertions(+), 75 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 1d75dbc80..cd4d7ca47 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -54,7 +54,11 @@ def generate_default_hostname(instance_id): class API(base.Base): """API for interacting with the compute manager.""" - scheduler_rules = None + + # Should we create instances all-at-once or as single-shot requests. + # Different schedulers use different approaches. + # This is cached across all API instances. + should_create_all_at_once = None # None implies uninitialized. def __init__(self, image_service=None, network_api=None, volume_api=None, hostname_factory=generate_default_hostname, @@ -219,8 +223,74 @@ class API(base.Base): 'availability_zone': availability_zone, 'os_type': os_type} - return (num_instances, base_options) + return (num_instances, base_options, security_groups) + + def create_db_entry_for_new_instance(self, context, base_options, + security_groups, num=1): + """Create an entry in the DB for this new instance, + including any related table updates (such as security + groups, MAC address, etc). This will called by create() + in the majority of situations, but all-at-once style + Schedulers may initiate the call.""" + instance = dict(mac_address=utils.generate_mac(), + launch_index=num, + **base_options) + instance = self.db.instance_create(context, instance) + instance_id = instance['id'] + + elevated = context.elevated() + if not security_groups: + security_groups = [] + for security_group_id in security_groups: + self.db.instance_add_security_group(elevated, + instance_id, + security_group_id) + + # Set sane defaults if not specified + updates = dict(hostname=self.hostname_factory(instance_id)) + if (not hasattr(instance, 'display_name') or + instance.display_name is None): + updates['display_name'] = "Server %s" % instance_id + + instance = self.update(context, instance_id, **updates) + + for group_id in security_groups: + self.trigger_security_group_members_refresh(elevated, group_id) + + return instance + def _ask_scheduler_to_create_instance(self, context, base_options, + instance_type, zone_blob, + availability_zone, injected_files, + instance_id=None, num_instances=1): + """Send the run_instance request to the schedulers for processing.""" + pid = context.project_id + uid = context.user_id + if instance_id: + LOG.debug(_("Casting to scheduler for %(pid)s/%(uid)s's" + " instance %(instance_id)s (single-shot)") % locals()) + else: + LOG.debug(_("Casting to scheduler for %(pid)s/%(uid)s's" + " (all-at-once)") % locals()) + + filter_class = 'nova.scheduler.host_filter.InstanceTypeFilter' + request_spec = { + 'instance_properties': base_options, + 'instance_type': instance_type, + 'filter': filter_class, + 'blob': zone_blob, + 'num_instances': num_instances + } + + rpc.cast(context, + FLAGS.scheduler_topic, + {"method": "run_instance", + "args": {"topic": FLAGS.compute_topic, + "instance_id": instance_id, + "request_spec": request_spec, + "availability_zone": availability_zone, + "injected_files": injected_files}}) + def create_all_at_once(self, context, instance_type, image_id, kernel_id=None, ramdisk_id=None, min_count=1, max_count=1, @@ -229,13 +299,24 @@ class API(base.Base): availability_zone=None, user_data=None, metadata={}, injected_files=None, zone_blob=None): """Provision the instances by passing the whole request to - the Scheduler for execution.""" - self._check_create_parameters(self, context, instance_type, - image_id, kernel_id, ramdisk_id, min_count=1, max_count=1, - display_name, display_description, - key_name, key_data, security_group, - availability_zone, user_data, metadata, - injected_files, zone_blob) + the Scheduler for execution. Returns a Reservation ID + related to the creation of all of these instances.""" + num_instances, base_options, security_groups = \ + self._check_create_parameters( + context, instance_type, + image_id, kernel_id, ramdisk_id, + min_count, max_count, + display_name, display_description, + key_name, key_data, security_group, + availability_zone, user_data, metadata, + injected_files, zone_blob) + + self._ask_scheduler_to_create_instance(context, base_options, + instance_type, zone_blob, + availability_zone, injected_files, + num_instances=num_instances) + + return base_options['reservation_id'] def create(self, context, instance_type, image_id, kernel_id=None, ramdisk_id=None, @@ -244,15 +325,20 @@ class API(base.Base): key_name=None, key_data=None, security_group='default', availability_zone=None, user_data=None, metadata={}, injected_files=None, zone_blob=None): - """Provision the instances by sending off a series of single + """ + Provision the instances by sending off a series of single instance requests to the Schedulers. This is fine for trival Scheduler drivers, but may remove the effectiveness of the - more complicated drivers.""" + more complicated drivers. + + Returns a list of instance dicts. + """ - num_instances, base_options = self._check_create_parameters( + num_instances, base_options, security_groups = \ + self._check_create_parameters( context, instance_type, image_id, kernel_id, ramdisk_id, - min_count=1, max_count=1, + min_count, max_count, display_name, display_description, key_name, key_data, security_group, availability_zone, user_data, metadata, @@ -261,74 +347,31 @@ class API(base.Base): instances = [] LOG.debug(_("Going to run %s instances..."), num_instances) for num in range(num_instances): - instance = dict(mac_address=utils.generate_mac(), - launch_index=num, - **base_options) - instance = self.db.instance_create(context, instance) - instance_id = instance['id'] - - elevated = context.elevated() - if not security_groups: - security_groups = [] - for security_group_id in security_groups: - self.db.instance_add_security_group(elevated, - instance_id, - security_group_id) - - # Set sane defaults if not specified - updates = dict(hostname=self.hostname_factory(instance_id)) - if (not hasattr(instance, 'display_name') or - instance.display_name is None): - updates['display_name'] = "Server %s" % instance_id - - instance = self.update(context, instance_id, **updates) + instance = self.create_db_entry_for_new_instance(context, + base_options, security_groups, num=num) instances.append(instance) - - pid = context.project_id - uid = context.user_id - LOG.debug(_("Casting to scheduler for %(pid)s/%(uid)s's" - " instance %(instance_id)s") % locals()) - - # NOTE(sandy): For now we're just going to pass in the - # instance_type record to the scheduler. In a later phase - # we'll be ripping this whole for-loop out and deferring the - # creation of the Instance record. At that point all this will - # change. - filter_driver = 'nova.scheduler.host_filter.InstanceTypeFilter' - request_spec = { - 'instance_properties': base_options, - 'instance_type': instance_type, - 'filter_driver': filter_driver, - 'blob': zone_blob - } - - rpc.cast(context, - FLAGS.scheduler_topic, - {"method": "run_instance", - "args": {"topic": FLAGS.compute_topic, - "instance_id": instance_id, - "request_spec": request_spec, - "availability_zone": availability_zone, - "injected_files": injected_files}}) - - for group_id in security_groups: - self.trigger_security_group_members_refresh(elevated, group_id) - - return [dict(x.iteritems()) for x in instances] + instance_id = instance['id'] + + self._ask_scheduler_to_create_instance(context, base_options, + instance_type, zone_blob, + availability_zone, injected_files, + instance_id=instance_id) + + return [x.items() for x in instances] def smart_create(self, *args, **kwargs): - """Ask the scheduler if we should: 1. do single shot instance - requests or all-at-once, and 2. defer the DB work until - a suitable host has been selected (if at all). Cache this - information and act accordingly.""" + """ + Ask the scheduler if we should do single shot instance requests + or all-at-once. - if API.scheduler_rules == None: - API.scheduler_rules = scheduler_api.get_scheduler_rules(context) + Cache this information on first request and act accordingly. + """ - should_create_all_at_once, should_defer_database_create = \ - API.scheduler_rules + if API.should_create_all_at_once == None: + API.should_create_all_at_once = \ + scheduler_api.should_create_all_at_once(context) - if should_create_all_at_once: + if API.should_create_all_at_once: return self.create_all_at_once(*args, **kwargs) return self.create(*args, **kwargs) -- cgit From 9a9dc80bcb47db5864b0c35fe1dd1a636b0a933e Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 26 May 2011 11:34:53 -0700 Subject: tests pass and pep8'ed --- nova/compute/api.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index cd4d7ca47..032ef7469 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -225,9 +225,9 @@ class API(base.Base): return (num_instances, base_options, security_groups) - def create_db_entry_for_new_instance(self, context, base_options, + def create_db_entry_for_new_instance(self, context, base_options, security_groups, num=1): - """Create an entry in the DB for this new instance, + """Create an entry in the DB for this new instance, including any related table updates (such as security groups, MAC address, etc). This will called by create() in the majority of situations, but all-at-once style @@ -272,7 +272,7 @@ class API(base.Base): else: LOG.debug(_("Casting to scheduler for %(pid)s/%(uid)s's" " (all-at-once)") % locals()) - + filter_class = 'nova.scheduler.host_filter.InstanceTypeFilter' request_spec = { 'instance_properties': base_options, @@ -290,7 +290,7 @@ class API(base.Base): "request_spec": request_spec, "availability_zone": availability_zone, "injected_files": injected_files}}) - + def create_all_at_once(self, context, instance_type, image_id, kernel_id=None, ramdisk_id=None, min_count=1, max_count=1, @@ -298,10 +298,10 @@ class API(base.Base): key_name=None, key_data=None, security_group='default', availability_zone=None, user_data=None, metadata={}, injected_files=None, zone_blob=None): - """Provision the instances by passing the whole request to - the Scheduler for execution. Returns a Reservation ID - related to the creation of all of these instances.""" - num_instances, base_options, security_groups = \ + """Provision the instances by passing the whole request to + the Scheduler for execution. Returns a Reservation ID + related to the creation of all of these instances.""" + num_instances, base_options, security_groups = \ self._check_create_parameters( context, instance_type, image_id, kernel_id, ramdisk_id, @@ -311,12 +311,12 @@ class API(base.Base): availability_zone, user_data, metadata, injected_files, zone_blob) - self._ask_scheduler_to_create_instance(context, base_options, + self._ask_scheduler_to_create_instance(context, base_options, instance_type, zone_blob, availability_zone, injected_files, num_instances=num_instances) - return base_options['reservation_id'] + return base_options['reservation_id'] def create(self, context, instance_type, image_id, kernel_id=None, ramdisk_id=None, @@ -330,7 +330,7 @@ class API(base.Base): instance requests to the Schedulers. This is fine for trival Scheduler drivers, but may remove the effectiveness of the more complicated drivers. - + Returns a list of instance dicts. """ @@ -343,7 +343,7 @@ class API(base.Base): key_name, key_data, security_group, availability_zone, user_data, metadata, injected_files, zone_blob) - + instances = [] LOG.debug(_("Going to run %s instances..."), num_instances) for num in range(num_instances): @@ -351,13 +351,13 @@ class API(base.Base): base_options, security_groups, num=num) instances.append(instance) instance_id = instance['id'] - + self._ask_scheduler_to_create_instance(context, base_options, instance_type, zone_blob, availability_zone, injected_files, instance_id=instance_id) - - return [x.items() for x in instances] + + return [dict(x.iteritems()) for x in instances] def smart_create(self, *args, **kwargs): """ -- cgit From 2819681b762fe8a23f3af68f1c1cbed0a113c08e Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 26 May 2011 18:14:38 -0400 Subject: Rename instances.image_id to instances.image_ref. --- nova/compute/api.py | 2 +- nova/compute/manager.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 432ea1fad..61b45843d 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -207,7 +207,7 @@ class API(base.Base): base_options = { 'reservation_id': utils.generate_uid('r'), - 'image_id': image_href, + 'image_ref': image_href, 'kernel_id': kernel_id or '', 'ramdisk_id': ramdisk_id or '', 'state': 0, diff --git a/nova/compute/manager.py b/nova/compute/manager.py index d1e01f275..7c88236ba 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -235,7 +235,7 @@ class ComputeManager(manager.SchedulerDependentManager): power_state.NOSTATE, 'networking') - is_vpn = instance_ref['image_id'] == str(FLAGS.vpn_image_id) + is_vpn = instance_ref['image_ref'] == str(FLAGS.vpn_image_id) # NOTE(vish): This could be a cast because we don't do anything # with the address currently, but I'm leaving it as # a call to ensure that network setup completes. We -- cgit From 4f8c995bbeca903319bcc1f314b25be0150eea2f Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 30 May 2011 22:47:10 -0400 Subject: Updated compute api and manager to support image_refs in rebuild. --- nova/compute/api.py | 4 ++-- nova/compute/manager.py | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 61b45843d..e0f9ec8f3 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -533,7 +533,7 @@ 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_ref, metadata=None, files_to_inject=None): """Rebuild the given instance with the provided metadata.""" instance = db.api.instance_get(context, instance_id) @@ -551,7 +551,7 @@ class API(base.Base): self.db.instance_update(context, instance_id, {"metadata": metadata}) rebuild_params = { - "image_id": image_id, + "image_ref": image_ref, "injected_files": files_to_inject, } diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 7c88236ba..055d15c43 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -162,9 +162,9 @@ class ComputeManager(manager.SchedulerDependentManager): 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): + def _update_image_ref(self, context, instance_id, image_ref): """Update the image_id for the given instance.""" - data = {'image_id': image_id} + data = {'image_ref': image_ref} self.db.instance_update(context, instance_id, data) def get_console_topic(self, context, **kwargs): @@ -331,7 +331,7 @@ class ComputeManager(manager.SchedulerDependentManager): @exception.wrap_exception @checks_instance_lock - def rebuild_instance(self, context, instance_id, image_id): + def rebuild_instance(self, context, instance_id, image_ref): """Destroy and re-make this instance. A 'rebuild' effectively purges all existing data from the system and @@ -339,7 +339,7 @@ class ComputeManager(manager.SchedulerDependentManager): :param context: `nova.RequestContext` object :param instance_id: Instance identifier (integer) - :param image_id: Image identifier (integer) + :param image_ref: Image identifier (href or integer) """ context = context.elevated() @@ -349,10 +349,10 @@ class ComputeManager(manager.SchedulerDependentManager): self._update_state(context, instance_id, power_state.BUILDING) self.driver.destroy(instance_ref) - instance_ref.image_id = image_id + instance_ref.image_ref = image_ref self.driver.spawn(instance_ref) - self._update_image_id(context, instance_id, image_id) + self._update_image_ref(context, instance_id, image_ref) self._update_launched_at(context, instance_id) self._update_state(context, instance_id) -- cgit From 0e419c00ef9a463acc704f034e4c37929f0ef2eb Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Wed, 1 Jun 2011 23:37:51 -0400 Subject: image href should be passed through the rebuild pipeline, not the image id. --- nova/compute/api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 2b353cebb..6a1c68561 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -529,8 +529,8 @@ 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, name=None, metadata=None, - files_to_inject=None): + def rebuild(self, context, instance_id, image_href, name=None, + metadata=None, files_to_inject=None): """Rebuild the given instance with the provided metadata.""" instance = db.api.instance_get(context, instance_id) @@ -550,7 +550,7 @@ class API(base.Base): self.db.instance_update(context, instance_id, values) rebuild_params = { - "image_ref": image_ref, + "image_ref": image_href, "injected_files": files_to_inject, } -- cgit From b2fb1738db489206557abccb631b13991c31fd4e Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 2 Jun 2011 14:23:05 -0700 Subject: make all uses of utcnow use our testable utils.utcnow --- nova/compute/api.py | 3 +-- nova/compute/manager.py | 3 +-- nova/compute/monitor.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 7122ebe67..de87ddd88 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -18,7 +18,6 @@ """Handles all requests relating to instances (guest vms).""" -import datetime import eventlet import re import time @@ -405,7 +404,7 @@ class API(base.Base): instance['id'], state_description='terminating', state=0, - terminated_at=datetime.datetime.utcnow()) + terminated_at=utils.utcnow()) host = instance['host'] if host: diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 3897b3a9e..a57d6e246 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -35,7 +35,6 @@ terminating it. """ -import datetime import os import socket import sys @@ -159,7 +158,7 @@ class ComputeManager(manager.SchedulerDependentManager): def _update_launched_at(self, context, instance_id, launched_at=None): """Update the launched_at parameter of the given instance.""" - data = {'launched_at': launched_at or datetime.datetime.utcnow()} + data = {'launched_at': launched_at or utils.utcnow()} self.db.instance_update(context, instance_id, data) def _update_image_id(self, context, instance_id, image_id): diff --git a/nova/compute/monitor.py b/nova/compute/monitor.py index 3bb54a382..613734bef 100644 --- a/nova/compute/monitor.py +++ b/nova/compute/monitor.py @@ -86,7 +86,7 @@ RRD_VALUES = { ]} -utcnow = datetime.datetime.utcnow +utcnow = utils.utcnow LOG = logging.getLogger('nova.compute.monitor') -- cgit From 727317333978ac5cf0fb1cd3f86e49e9868f1e19 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 6 Jun 2011 17:58:40 -0700 Subject: fixed up tests after trunk merge --- nova/compute/api.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 24f04f226..e09127d5c 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -134,7 +134,7 @@ class API(base.Base): raise quota.QuotaError(msg, "MetadataLimitExceeded") def _check_create_parameters(self, context, instance_type, - image_id, kernel_id=None, ramdisk_id=None, + image_href, 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', @@ -300,7 +300,7 @@ class API(base.Base): "injected_files": injected_files}}) def create_all_at_once(self, context, instance_type, - image_id, kernel_id=None, ramdisk_id=None, + image_href, 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', @@ -312,7 +312,7 @@ class API(base.Base): num_instances, base_options, security_groups = \ self._check_create_parameters( context, instance_type, - image_id, kernel_id, ramdisk_id, + image_href, kernel_id, ramdisk_id, min_count, max_count, display_name, display_description, key_name, key_data, security_group, @@ -328,7 +328,7 @@ class API(base.Base): return base_options['reservation_id'] def create(self, context, instance_type, - image_id, kernel_id=None, ramdisk_id=None, + image_href, 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', @@ -346,7 +346,7 @@ class API(base.Base): num_instances, base_options, security_groups = \ self._check_create_parameters( context, instance_type, - image_id, kernel_id, ramdisk_id, + image_href, kernel_id, ramdisk_id, min_count, max_count, display_name, display_description, key_name, key_data, security_group, -- cgit From c680176d11edb46a28ba065f0548e18cbf1297d5 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Tue, 7 Jun 2011 13:32:53 -0400 Subject: Fixed incorrect error message Added missing import Fixed Typo (pylint "undefined variable NoneV") --- nova/compute/instance_types.py | 2 +- nova/compute/monitor.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index 1275a6fdd..1d246e445 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -114,7 +114,7 @@ def get_instance_type(id): ctxt = context.get_admin_context() return db.instance_type_get_by_id(ctxt, id) except exception.DBError: - raise exception.ApiError(_("Unknown instance type: %s") % name) + raise exception.ApiError(_("Unknown instance type: %s") % id) def get_instance_type_by_name(name): diff --git a/nova/compute/monitor.py b/nova/compute/monitor.py index 613734bef..9d8e2a25d 100644 --- a/nova/compute/monitor.py +++ b/nova/compute/monitor.py @@ -36,6 +36,7 @@ from twisted.application import service from nova import flags from nova import log as logging +from nova import utils from nova.virt import connection as virt_connection -- cgit From dcb0d38aa829e1e2492defffaf6ad393b809289b Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 8 Jun 2011 08:13:23 -0700 Subject: removed straggler code --- nova/compute/api.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index e09127d5c..b0949a729 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -55,11 +55,6 @@ def generate_default_hostname(instance_id): class API(base.Base): """API for interacting with the compute manager.""" - # Should we create instances all-at-once or as single-shot requests. - # Different schedulers use different approaches. - # This is cached across all API instances. - should_create_all_at_once = None # None implies uninitialized. - def __init__(self, image_service=None, network_api=None, volume_api=None, hostname_factory=generate_default_hostname, **kwargs): -- cgit