From dcc58be823aec7725d0b85c443c463124fcdae38 Mon Sep 17 00:00:00 2001 From: Ilya Alekseyev Date: Wed, 22 Dec 2010 22:38:50 +0300 Subject: [PATCH 1/8] Zone scheduler added --- nova/db/sqlalchemy/models.py | 1 + nova/scheduler/zone.py | 58 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 nova/scheduler/zone.py diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 693db8d23d97..843675fe620a 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -149,6 +149,7 @@ class Service(BASE, NovaBase): topic = Column(String(255)) report_count = Column(Integer, nullable=False, default=0) disabled = Column(Boolean, default=False) + availability_zone = Column(String(255)) class Certificate(BASE, NovaBase): diff --git a/nova/scheduler/zone.py b/nova/scheduler/zone.py new file mode 100644 index 000000000000..ec2166adff49 --- /dev/null +++ b/nova/scheduler/zone.py @@ -0,0 +1,58 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2010 Openstack, LLC. +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Availability Zone Scheduler implementation +""" + +import random + +from nova.scheduler import driver +from nova import db + + +class ZoneScheduler(driver.Scheduler): + """Implements Scheduler as a random node selector.""" + + def hosts_up_with_zone(self, context, topic, zone): + """Return the list of hosts that have a running service + for topic and availability zone (if defined). + """ + + if zone is None: + return self.hosts_up(context, topic) + + services = db.service_get_all_by_topic(context, topic) + return [service.host + for service in services + if self.service_is_up(service) + and service.availability_zone == zone] + + + def schedule(self, context, topic, *_args, **_kwargs): + """Picks a host that is up at random in selected + availability zone (if defined). + """ + + zone = _kwargs.get('availability_zone') + hosts = self.hosts_up_with_zone(context, topic, zone) + if not hosts: + raise driver.NoValidHost(_("No hosts found")) + return hosts[int(random.random() * len(hosts))] + From d88817a360676173ac31566e13201d56f1e2b0b0 Mon Sep 17 00:00:00 2001 From: Ilya Alekseyev Date: Thu, 23 Dec 2010 22:46:58 +0300 Subject: [PATCH 2/8] unit test - should be reworked --- nova/tests/scheduler_unittest.py | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/nova/tests/scheduler_unittest.py b/nova/tests/scheduler_unittest.py index d1756b8fb5a4..dbc195a6e53b 100644 --- a/nova/tests/scheduler_unittest.py +++ b/nova/tests/scheduler_unittest.py @@ -19,6 +19,9 @@ Tests For Scheduler """ +import datetime + +from mox import IgnoreArg from nova import context from nova import db from nova import flags @@ -72,6 +75,46 @@ class SchedulerTestCase(test.TestCase): self.mox.ReplayAll() scheduler.named_method(ctxt, 'topic', num=7) +class ZoneSchedulerTestCase(test.TestCase): + """Test case for zone scheduler""" + def setUp(self): + super(ZoneSchedulerTestCase, self).setUp() + self.flags(scheduler_driver='nova.scheduler.zone.ZoneScheduler') + + def _create_service_model(self, **kwargs): + service = db.sqlalchemy.models.Service() + service.host = kwargs['host'] + service.disabled = False + service.deleted = False + service.report_count = 0 + service.binary = 'nova-compute' + service.topic = 'compute' + service.id = kwargs['id'] + service.availability_zone = kwargs['zone'] + service.created_at = datetime.datetime.utcnow() + return service + + + def test_with_two_zones(self): + scheduler = manager.SchedulerManager() + ctxt = context.get_admin_context() + service_list = [ + self._create_service_model(id=1, host='host1', zone='zone1'), + self._create_service_model(id=2, host='host2', zone='zone2'), + self._create_service_model(id=3, host='host3', zone='zone2'), + self._create_service_model(id=4, host='host4', zone='zone2'), + self._create_service_model(id=5, host='host5', zone='zone2') + ] + self.mox.StubOutWithMock(db, 'service_get_all_by_topic') + db.service_get_all_by_topic(IgnoreArg(), IgnoreArg()).AndReturn(service_list) + self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) + rpc.cast(ctxt, + 'compute.host1', + {'method': 'create_instance', #TODO: check it + 'args': {'availability_zone': 'zone1'}}) + self.mox.ReplayAll() + scheduler.create_instance(ctxt, 'compute', availability_zone='zone1') + class SimpleDriverTestCase(test.TestCase): """Test case for simple driver""" From 43f59fc025b4decd02a78acbfd0cf654bc9cf0db Mon Sep 17 00:00:00 2001 From: Ilya Alekseyev Date: Fri, 24 Dec 2010 21:05:45 +0300 Subject: [PATCH 3/8] adding zones to api --- nova/api/ec2/cloud.py | 7 ++++++- nova/compute/api.py | 6 ++++-- nova/db/sqlalchemy/models.py | 2 +- nova/service.py | 3 ++- nova/tests/test_scheduler.py | 7 ++++--- nova/tests/test_service.py | 24 ++++++++++++++++-------- 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index e09261f00c3f..66060bbfc53f 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -753,6 +753,10 @@ class CloudController(object): def run_instances(self, context, **kwargs): max_count = int(kwargs.get('max_count', 1)) + placement = kwargs.get('placement') + avzone = None + if placement is not None: + avzone = placement['availability_zone'] instances = self.compute_api.create_instances(context, instance_types.get_by_type(kwargs.get('instance_type', None)), kwargs['image_id'], @@ -765,7 +769,8 @@ class CloudController(object): key_name=kwargs.get('key_name'), user_data=kwargs.get('user_data'), security_group=kwargs.get('security_group'), - generate_hostname=internal_id_to_ec2_id) + generate_hostname=internal_id_to_ec2_id, + availability_zone=avzone) return self._format_run_instances(context, instances[0]['reservation_id']) diff --git a/nova/compute/api.py b/nova/compute/api.py index 4953fe559fdb..cc377a1e45dd 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -75,7 +75,8 @@ class ComputeAPI(base.Base): display_name='', description='', key_name=None, key_data=None, security_group='default', user_data=None, - generate_hostname=generate_default_hostname): + generate_hostname=generate_default_hostname, + availability_zone=None): """Create the number of instances requested if quote and other arguments check out ok.""" @@ -175,7 +176,8 @@ class ComputeAPI(base.Base): FLAGS.scheduler_topic, {"method": "run_instance", "args": {"topic": FLAGS.compute_topic, - "instance_id": instance_id}}) + "instance_id": instance_id, + "availability_zone": availability_zone}}) return instances diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 843675fe620a..5a020a469b48 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -149,7 +149,7 @@ class Service(BASE, NovaBase): topic = Column(String(255)) report_count = Column(Integer, nullable=False, default=0) disabled = Column(Boolean, default=False) - availability_zone = Column(String(255)) + availability_zone = Column(String(255), default='nova') class Certificate(BASE, NovaBase): diff --git a/nova/service.py b/nova/service.py index f1f90742f845..a612ac592c57 100644 --- a/nova/service.py +++ b/nova/service.py @@ -114,7 +114,8 @@ class Service(object): {'host': self.host, 'binary': self.binary, 'topic': self.topic, - 'report_count': 0}) + 'report_count': 0, + 'availability_zone': FLAGS.node_availability_zone}) self.service_id = service_ref['id'] def __getattr__(self, key): diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 487e7b9e64ff..188e50aac232 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -110,10 +110,11 @@ class ZoneSchedulerTestCase(test.TestCase): self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) rpc.cast(ctxt, 'compute.host1', - {'method': 'create_instance', #TODO: check it - 'args': {'availability_zone': 'zone1'}}) + {'method': 'run_instance', + 'args':{'instance_id': 'i-ffffffff', + 'availability_zone': 'zone1'}}) self.mox.ReplayAll() - scheduler.create_instance(ctxt, 'compute', availability_zone='zone1') + scheduler.run_instance(ctxt, 'compute', instance_id='i-ffffffff', availability_zone='zone1') class SimpleDriverTestCase(test.TestCase): diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index b30838ad738c..1400b88e5816 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -107,11 +107,13 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'report_count': 0, - 'id': 1} + 'id': 1, + 'availability_zone': 'nova'} service.db.service_get_by_args(mox.IgnoreArg(), host, @@ -135,12 +137,14 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'topic': topic, 'report_count': 0, - 'id': 1} + 'id': 1, + 'availability_zone': 'nova'} service.db.service_get_by_args(mox.IgnoreArg(), host, @@ -167,12 +171,14 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'topic': topic, 'report_count': 0, - 'id': 1} + 'id': 1, + 'availability_zone': 'nova'} service.db.service_get_by_args(mox.IgnoreArg(), host, @@ -198,12 +204,14 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'topic': topic, 'report_count': 0, - 'id': 1} + 'id': 1, + 'availability_zone': 'nova'} service.db.service_get_by_args(mox.IgnoreArg(), host, From d30ec2b5814480010d1b42ce2e9bed9fbc441fd1 Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Wed, 29 Dec 2010 19:51:25 +0300 Subject: [PATCH 4/8] Added implementation availability_zones to EC2 API --- nova/api/ec2/cloud.py | 25 +++++++++++++++++++++---- nova/db/api.py | 7 +++++-- nova/db/sqlalchemy/api.py | 14 ++++++++++++-- nova/flags.py | 1 - nova/tests/test_cloud.py | 17 +++++++++++++++++ 5 files changed, 55 insertions(+), 9 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 66060bbfc53f..0c20ef3290df 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -138,6 +138,9 @@ class CloudController(object): {"method": "refresh_security_group", "args": {"security_group_id": security_group.id}}) + def _get_availability_zone_by_host(self, context, hostname): + return db.service_get_all_compute_by_host(context, hostname)[0]['availability_zone'] + def get_metadata(self, address): ctxt = context.get_admin_context() instance_ref = db.fixed_ip_get_instance(ctxt, address) @@ -150,6 +153,7 @@ class CloudController(object): else: keys = '' hostname = instance_ref['hostname'] + availability_zone = self._get_availability_zone_by_host(ctxt, hostname) floating_ip = db.instance_get_floating_address(ctxt, instance_ref['id']) ec2_id = internal_id_to_ec2_id(instance_ref['internal_id']) @@ -172,8 +176,7 @@ class CloudController(object): 'local-hostname': hostname, 'local-ipv4': address, 'kernel-id': instance_ref['kernel_id'], - # TODO(vish): real zone - 'placement': {'availability-zone': 'nova'}, + 'placement': {'availability-zone': availability_zone}, 'public-hostname': hostname, 'public-ipv4': floating_ip or '', 'public-keys': keys, @@ -188,8 +191,20 @@ class CloudController(object): return data def describe_availability_zones(self, context, **kwargs): - return {'availabilityZoneInfo': [{'zoneName': 'nova', - 'zoneState': 'available'}]} + enabled_services = db.service_get_all_by_topic(context, 'compute') + disabled_services = db.service_get_all_by_topic(context, 'compute', True) + available_zones = [service.availability_zone for service in enabled_services] + not_available_zones = [service.availability_zone for service in disabled_services + and not service['availability_zone'] in available_zones] + + result = [] + for zone in available_zones: + result.append({'zoneName': zone, + 'zoneState': "available"}) + for zone in not_available_zones: + result.append({'zoneName': zone, + 'zoneState': "not available"}) + return {'availabilityZoneInfo': result} def describe_regions(self, context, region_name=None, **kwargs): if FLAGS.region_list: @@ -660,6 +675,8 @@ class CloudController(object): r['groupSet'] = self._convert_to_set([], 'groups') r['instancesSet'] = [] reservations[instance['reservation_id']] = r + availability_zone = self._get_availability_zone_by_host(ctxt, instance['hostname']) + i['placement'] = {'availabilityZone': availability_zone} reservations[instance['reservation_id']]['instancesSet'].append(i) return list(reservations.values()) diff --git a/nova/db/api.py b/nova/db/api.py index fde3f0852a87..c0cab1068d75 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -76,10 +76,13 @@ def service_get(context, service_id): return IMPL.service_get(context, service_id) -def service_get_all_by_topic(context, topic): +def service_get_all_by_topic(context, topic, disabled=False): """Get all compute services for a given topic.""" - return IMPL.service_get_all_by_topic(context, topic) + return IMPL.service_get_all_by_topic(context, topic, disabled) +def service_get_all_compute_by_host(context, host): + """Get all compute service for a given host""" + return IMPL.service_get_all_compute_by_host(context, host) def service_get_all_compute_sorted(context): """Get all compute services sorted by instance count. diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 7e945e4cb3d8..55c3c5594692 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -136,11 +136,11 @@ def service_get(context, service_id, session=None): @require_admin_context -def service_get_all_by_topic(context, topic): +def service_get_all_by_topic(context, topic, disabled=False): session = get_session() return session.query(models.Service).\ filter_by(deleted=False).\ - filter_by(disabled=False).\ + filter_by(disabled=disabled).\ filter_by(topic=topic).\ all() @@ -156,6 +156,16 @@ def _service_get_all_topic_subquery(context, session, topic, subq, label): order_by(sort_value).\ all() +@require_admin_context +def service_get_all_compute_by_host(context, host): + session = get_session() + topic = 'compute' + return session.query(models.Service).\ + filter_by(host=host).\ + filter_by(deleted=False).\ + filter_by(topic=topic).\ + all() + @require_admin_context def service_get_all_compute_sorted(context): diff --git a/nova/flags.py b/nova/flags.py index 76a98d35a859..b157c9e5d69d 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -277,6 +277,5 @@ DEFINE_string('image_service', 'nova.image.s3.S3ImageService', DEFINE_string('host', socket.gethostname(), 'name of this node') -# UNUSED DEFINE_string('node_availability_zone', 'nova', 'availability zone of this node') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 70d2c44daaec..d7e99b3c857a 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -133,6 +133,23 @@ class CloudTestCase(test.TestCase): db.volume_destroy(self.context, vol1['id']) db.volume_destroy(self.context, vol2['id']) + def test_describe_availability_zones(self): + """Makes sure describe_availability_zones works and filters results.""" + service1 = db.service_create(self.context, {'host': 'host1_describe_zones', + 'binary': "nova-compute", + 'topic': 'compute', + 'report_count': 0, + 'availability_zone': "zone1"}) + service2 = db.service_create(self.context, {'host': 'host2_describe_zones', + 'binary': "nova-compute", + 'topic': 'compute', + 'report_count': 0, + 'availability_zone': "zone2"}) + result = self.cloud.describe_availability_zones(self.context) + self.assertEqual(len(result['availabilityZoneInfo']), 3) + db.service_destroy(self.context, service1['id']) + db.service_destroy(self.context, service2['id']) + def test_console_output(self): image_id = FLAGS.default_image instance_type = FLAGS.default_instance_type From 579d0e1437efb32ef1a1c50ddbfca9093cfa3d18 Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Wed, 29 Dec 2010 23:30:08 +0300 Subject: [PATCH 5/8] added tests for EC2 describe_instances --- nova/api/ec2/cloud.py | 7 +++++-- nova/tests/test_cloud.py | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 0c20ef3290df..9fa4223013e6 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -139,7 +139,10 @@ class CloudController(object): "args": {"security_group_id": security_group.id}}) def _get_availability_zone_by_host(self, context, hostname): - return db.service_get_all_compute_by_host(context, hostname)[0]['availability_zone'] + services = db.service_get_all_compute_by_host(context, hostname) + if len(services) > 0: + return services[0]['availability_zone'] + raise Exception(_('No service with hostname: %s' % hostname)) def get_metadata(self, address): ctxt = context.get_admin_context() @@ -675,7 +678,7 @@ class CloudController(object): r['groupSet'] = self._convert_to_set([], 'groups') r['instancesSet'] = [] reservations[instance['reservation_id']] = r - availability_zone = self._get_availability_zone_by_host(ctxt, instance['hostname']) + availability_zone = self._get_availability_zone_by_host(context, instance['hostname']) i['placement'] = {'availabilityZone': availability_zone} reservations[instance['reservation_id']]['instancesSet'].append(i) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index d7e99b3c857a..3adecb72952d 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -62,7 +62,7 @@ class CloudTestCase(test.TestCase): self.cloud = cloud.CloudController() # set up services - self.compute = service.Service.create(binary='nova-compute') + self.compute = service.Service.create(binary='nova-compute', host='host1') self.compute.start() self.network = service.Service.create(binary='nova-network') self.network.start() @@ -228,6 +228,20 @@ class CloudTestCase(test.TestCase): logging.debug("Terminating instance %s" % instance_id) rv = yield self.compute.terminate_instance(instance_id) + def test_describe_instances(self): + """Makes sure describe_instances works.""" + instance1 = db.instance_create(self.context, {'hostname': 'host2'}) + service1 = db.service_create(self.context, {'host': 'host1', + 'availability_zone': 'zone1', + 'topic': "compute"}) + result = self.cloud.describe_instances(self.context) + self.assertEqual(result['reservationSet'][0]\ + ['instancesSet'][0]\ + ['placement']['availabilityZone'], 'zone1') + db.instance_destroy(self.context, instance1['id']) + db.service_destroy(self.context, service1['id']) + + def test_instance_update_state(self): def instance(num): return { From 3478e90442ad7a22497b53153ae893df96e55b4e Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Fri, 7 Jan 2011 05:59:30 +0300 Subject: [PATCH 6/8] merge --- Authors | 1 + nova/api/ec2/cloud.py | 34 ++++++++++++++++++++++++---- nova/compute/api.py | 3 ++- nova/db/api.py | 13 ++++++++++- nova/db/sqlalchemy/api.py | 17 ++++++++++++++ nova/db/sqlalchemy/models.py | 2 +- nova/flags.py | 1 - nova/service.py | 3 ++- nova/tests/test_cloud.py | 35 +++++++++++++++++++++++++++++ nova/tests/test_scheduler.py | 43 ++++++++++++++++++++++++++++++++++++ nova/tests/test_service.py | 15 +++++++++---- 11 files changed, 154 insertions(+), 13 deletions(-) diff --git a/Authors b/Authors index 8dfaf955740a..e67363308100 100644 --- a/Authors +++ b/Authors @@ -15,6 +15,7 @@ Eldar Nugaev Eric Day Ewan Mellor Hisaki Ohara +Ilya Alekseyev Jay Pipes Jesse Andrews Joe Heck diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 6619b545292c..b6966e605b7d 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -140,6 +140,12 @@ class CloudController(object): {"method": "refresh_security_group", "args": {"security_group_id": security_group.id}}) + def _get_availability_zone_by_host(self, context, host): + services = db.service_get_all_by_host(context, host) + if len(services) > 0: + return services[0]['availability_zone'] + return 'unknown zone' + def get_metadata(self, address): ctxt = context.get_admin_context() instance_ref = self.compute_api.get_all(ctxt, fixed_ip=address) @@ -152,6 +158,8 @@ class CloudController(object): else: keys = '' hostname = instance_ref['hostname'] + availability_zone = self._get_availability_zone_by_host(ctxt, + instance_ref['host']) floating_ip = db.instance_get_floating_address(ctxt, instance_ref['id']) ec2_id = id_to_ec2_id(instance_ref['id']) @@ -174,8 +182,7 @@ class CloudController(object): 'local-hostname': hostname, 'local-ipv4': address, 'kernel-id': instance_ref['kernel_id'], - # TODO(vish): real zone - 'placement': {'availability-zone': 'nova'}, + 'placement': {'availability-zone': availability_zone}, 'public-hostname': hostname, 'public-ipv4': floating_ip or '', 'public-keys': keys, @@ -199,8 +206,25 @@ class CloudController(object): return self._describe_availability_zones(context, **kwargs) def _describe_availability_zones(self, context, **kwargs): - return {'availabilityZoneInfo': [{'zoneName': 'nova', - 'zoneState': 'available'}]} + enabled_services = db.service_get_all(context) + disabled_services = db.service_get_all(context, True) + available_zones = [] + for zone in [service.availability_zone for service in enabled_services]: + if not zone in available_zones: + available_zones.append(zone) + not_available_zones = [] + for zone in [service.availability_zone for service in disabled_services + and not service['availability_zone'] in available_zones]: + if not zone in not_available_zones: + not_available_zones.append(zone) + result = [] + for zone in available_zones: + result.append({'zoneName': zone, + 'zoneState': "available"}) + for zone in not_available_zones: + result.append({'zoneName': zone, + 'zoneState': "not available"}) + return {'availabilityZoneInfo': result} def _describe_availability_zones_verbose(self, context, **kwargs): rv = {'availabilityZoneInfo': [{'zoneName': 'nova', @@ -632,6 +656,8 @@ class CloudController(object): i['amiLaunchIndex'] = instance['launch_index'] i['displayName'] = instance['display_name'] i['displayDescription'] = instance['display_description'] + availability_zone = self._get_availability_zone_by_host(context, instance['host']) + i['placement'] = {'availabilityZone': availability_zone} if instance['reservation_id'] not in reservations: r = {} r['reservationId'] = instance['reservation_id'] diff --git a/nova/compute/api.py b/nova/compute/api.py index 64d47b1ce093..3ba91fe05132 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -181,7 +181,8 @@ class API(base.Base): FLAGS.scheduler_topic, {"method": "run_instance", "args": {"topic": FLAGS.compute_topic, - "instance_id": instance_id}}) + "instance_id": instance_id, + "availability_zone": availability_zone}}) return instances diff --git a/nova/db/api.py b/nova/db/api.py index 0fa5eb1e8e42..ee4c521a03e3 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -81,11 +81,22 @@ def service_get(context, service_id): return IMPL.service_get(context, service_id) +def service_get_all(context, disabled=False): + """Get all service.""" + return IMPL.service_get_all(context, disabled) + + def service_get_all_by_topic(context, topic): - """Get all compute services for a given topic.""" + """Get all services for a given topic.""" return IMPL.service_get_all_by_topic(context, topic) +def service_get_all_by_host(context, host): + """Get all services for a given host.""" + return IMPL.service_get_all_by_host(context, host) + + + def service_get_all_compute_sorted(context): """Get all compute services sorted by instance count. diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index aaa07e3c9291..aa0306eb49e9 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -134,6 +134,14 @@ def service_get(context, service_id, session=None): return result +@require_admin_context +def service_get_all(context, disabled=False): + session = get_session() + return session.query(models.Service).\ + filter_by(deleted=False).\ + filter_by(disabled=disabled).\ + all() + @require_admin_context def service_get_all_by_topic(context, topic): session = get_session() @@ -144,6 +152,15 @@ def service_get_all_by_topic(context, topic): all() +@require_admin_context +def service_get_all_by_host(context, host): + session = get_session() + return session.query(models.Service).\ + filter_by(deleted=False).\ + filter_by(host=host).\ + all() + + @require_admin_context def _service_get_all_topic_subquery(context, session, topic, subq, label): sort_value = getattr(subq.c, label) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 62bb1780d218..1ffb9298f4cb 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -149,7 +149,7 @@ class Service(BASE, NovaBase): topic = Column(String(255)) report_count = Column(Integer, nullable=False, default=0) disabled = Column(Boolean, default=False) - + availability_zone = Column(String(255), default='nova') class Certificate(BASE, NovaBase): """Represents a an x509 certificate""" diff --git a/nova/flags.py b/nova/flags.py index 4b73349270a3..4e71d215252e 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -285,6 +285,5 @@ DEFINE_string('image_service', 'nova.image.s3.S3ImageService', DEFINE_string('host', socket.gethostname(), 'name of this node') -# UNUSED DEFINE_string('node_availability_zone', 'nova', 'availability zone of this node') diff --git a/nova/service.py b/nova/service.py index 7203430c6f82..d4a6f3839066 100644 --- a/nova/service.py +++ b/nova/service.py @@ -118,7 +118,8 @@ class Service(object): {'host': self.host, 'binary': self.binary, 'topic': self.topic, - 'report_count': 0}) + 'report_count': 0, + 'availability_zone': FLAGS.node_availability_zone}) self.service_id = service_ref['id'] def __getattr__(self, key): diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index ba58fab59532..21d212df7116 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -133,6 +133,25 @@ class CloudTestCase(test.TestCase): db.volume_destroy(self.context, vol1['id']) db.volume_destroy(self.context, vol2['id']) + + def test_describe_availability_zones(self): + """Makes sure describe_availability_zones works and filters results.""" + service1 = db.service_create(self.context, {'host': 'host1_describe_zones', + 'binary': "nova-compute", + 'topic': 'compute', + 'report_count': 0, + 'availability_zone': "zone1"}) + service2 = db.service_create(self.context, {'host': 'host2_describe_zones', + 'binary': "nova-compute", + 'topic': 'compute', + 'report_count': 0, + 'availability_zone': "zone2"}) + result = self.cloud.describe_availability_zones(self.context) + self.assertEqual(len(result['availabilityZoneInfo']), 3) + db.service_destroy(self.context, service1['id']) + db.service_destroy(self.context, service2['id']) + + def test_console_output(self): image_id = FLAGS.default_image instance_type = FLAGS.default_instance_type @@ -212,6 +231,21 @@ class CloudTestCase(test.TestCase): logging.debug("Terminating instance %s" % instance_id) rv = self.compute.terminate_instance(instance_id) + + def test_describe_instances(self): + """Makes sure describe_instances works.""" + instance1 = db.instance_create(self.context, {'host': 'host2'}) + service1 = db.service_create(self.context, {'host': 'host2', + 'availability_zone': 'zone1', + 'topic': "compute"}) + result = self.cloud.describe_instances(self.context) + self.assertEqual(result['reservationSet'][0]\ + ['instancesSet'][0]\ + ['placement']['availabilityZone'], 'zone1') + db.instance_destroy(self.context, instance1['id']) + db.service_destroy(self.context, service1['id']) + + def test_instance_update_state(self): def instance(num): return { @@ -261,6 +295,7 @@ class CloudTestCase(test.TestCase): # data = self.cloud.get_metadata(instance(i)['private_dns_name']) # self.assert_(data['meta-data']['ami-id'] == 'ami-%s' % i) + @staticmethod def _fake_set_image_description(ctxt, image_id, description): from nova.objectstore import handler diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index a9937d79743c..99f62f136c76 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -21,6 +21,7 @@ Tests For Scheduler import datetime +from mox import IgnoreArg from nova import context from nova import db from nova import flags @@ -76,6 +77,48 @@ class SchedulerTestCase(test.TestCase): scheduler.named_method(ctxt, 'topic', num=7) +class ZoneSchedulerTestCase(test.TestCase): + """Test case for zone scheduler""" + def setUp(self): + super(ZoneSchedulerTestCase, self).setUp() + self.flags(scheduler_driver='nova.scheduler.zone.ZoneScheduler') + + def _create_service_model(self, **kwargs): + service = db.sqlalchemy.models.Service() + service.host = kwargs['host'] + service.disabled = False + service.deleted = False + service.report_count = 0 + service.binary = 'nova-compute' + service.topic = 'compute' + service.id = kwargs['id'] + service.availability_zone = kwargs['zone'] + service.created_at = datetime.datetime.utcnow() + return service + + + def test_with_two_zones(self): + scheduler = manager.SchedulerManager() + ctxt = context.get_admin_context() + service_list = [ + self._create_service_model(id=1, host='host1', zone='zone1'), + self._create_service_model(id=2, host='host2', zone='zone2'), + self._create_service_model(id=3, host='host3', zone='zone2'), + self._create_service_model(id=4, host='host4', zone='zone2'), + self._create_service_model(id=5, host='host5', zone='zone2') + ] + self.mox.StubOutWithMock(db, 'service_get_all_by_topic') + db.service_get_all_by_topic(IgnoreArg(), IgnoreArg()).AndReturn(service_list) + self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) + rpc.cast(ctxt, + 'compute.host1', + {'method': 'run_instance', + 'args':{'instance_id': 'i-ffffffff', + 'availability_zone': 'zone1'}}) + self.mox.ReplayAll() + scheduler.run_instance(ctxt, 'compute', instance_id='i-ffffffff', availability_zone='zone1') + + class SimpleDriverTestCase(test.TestCase): """Test case for simple driver""" def setUp(self): diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index 9f1a181a0a12..a67c8d1e8c24 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -133,7 +133,8 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'report_count': 0, @@ -161,11 +162,13 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'topic': topic, 'report_count': 0, + 'availability_zone': 'nova', 'id': 1} service.db.service_get_by_args(mox.IgnoreArg(), @@ -193,11 +196,13 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'topic': topic, 'report_count': 0, + 'availability_zone': 'nova', 'id': 1} service.db.service_get_by_args(mox.IgnoreArg(), @@ -224,11 +229,13 @@ class ServiceTestCase(test.TestCase): service_create = {'host': host, 'binary': binary, 'topic': topic, - 'report_count': 0} + 'report_count': 0, + 'availability_zone': 'nova'} service_ref = {'host': host, 'binary': binary, 'topic': topic, 'report_count': 0, + 'availability_zone': 'nova', 'id': 1} service.db.service_get_by_args(mox.IgnoreArg(), From d01b546ae574f74b9c4c07a039c2c52cf0ed3bfb Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Wed, 12 Jan 2011 01:27:36 +0300 Subject: [PATCH 7/8] resolve pylint warnings --- nova/api/ec2/cloud.py | 14 ++-- nova/db/api.py | 1 - nova/db/sqlalchemy/models.py | 1 + nova/scheduler/zone.py | 8 +-- nova/service.py | 3 +- nova/tests/test_cloud.py | 45 ++++++------ nova/tests/test_scheduler.py | 134 ++++++++++++++--------------------- 7 files changed, 87 insertions(+), 119 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index b6748e6084fc..42245fa54461 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -159,8 +159,8 @@ class CloudController(object): else: keys = '' hostname = instance_ref['hostname'] - availability_zone = self._get_availability_zone_by_host(ctxt, - instance_ref['host']) + host = instance_ref['host'] + availability_zone = self._get_availability_zone_by_host(ctxt, host) floating_ip = db.instance_get_floating_address(ctxt, instance_ref['id']) ec2_id = id_to_ec2_id(instance_ref['id']) @@ -210,12 +210,13 @@ class CloudController(object): enabled_services = db.service_get_all(context) disabled_services = db.service_get_all(context, True) available_zones = [] - for zone in [service.availability_zone for service in enabled_services]: + for zone in [service.availability_zone for service + in enabled_services]: if not zone in available_zones: available_zones.append(zone) not_available_zones = [] for zone in [service.availability_zone for service in disabled_services - and not service['availability_zone'] in available_zones]: + if not service['availability_zone'] in available_zones]: if not zone in not_available_zones: not_available_zones.append(zone) result = [] @@ -679,8 +680,9 @@ class CloudController(object): i['amiLaunchIndex'] = instance['launch_index'] i['displayName'] = instance['display_name'] i['displayDescription'] = instance['display_description'] - availability_zone = self._get_availability_zone_by_host(context, instance['host']) - i['placement'] = {'availabilityZone': availability_zone} + host = instance['host'] + zone = self._get_availability_zone_by_host(context, host) + i['placement'] = {'availabilityZone': zone} if instance['reservation_id'] not in reservations: r = {} r['reservationId'] = instance['reservation_id'] diff --git a/nova/db/api.py b/nova/db/api.py index 64fee590b213..4577d97d2a0c 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -96,7 +96,6 @@ def service_get_all_by_host(context, host): return IMPL.service_get_all_by_host(context, host) - def service_get_all_compute_sorted(context): """Get all compute services sorted by instance count. diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 05ddbeb72edb..8e5b6b3acb94 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -151,6 +151,7 @@ class Service(BASE, NovaBase): disabled = Column(Boolean, default=False) availability_zone = Column(String(255), default='nova') + class Certificate(BASE, NovaBase): """Represents a an x509 certificate""" __tablename__ = 'certificates' diff --git a/nova/scheduler/zone.py b/nova/scheduler/zone.py index ec2166adff49..49786cd3236c 100644 --- a/nova/scheduler/zone.py +++ b/nova/scheduler/zone.py @@ -31,8 +31,8 @@ class ZoneScheduler(driver.Scheduler): """Implements Scheduler as a random node selector.""" def hosts_up_with_zone(self, context, topic, zone): - """Return the list of hosts that have a running service - for topic and availability zone (if defined). + """Return the list of hosts that have a running service + for topic and availability zone (if defined). """ if zone is None: @@ -44,9 +44,8 @@ class ZoneScheduler(driver.Scheduler): if self.service_is_up(service) and service.availability_zone == zone] - def schedule(self, context, topic, *_args, **_kwargs): - """Picks a host that is up at random in selected + """Picks a host that is up at random in selected availability zone (if defined). """ @@ -55,4 +54,3 @@ class ZoneScheduler(driver.Scheduler): if not hosts: raise driver.NoValidHost(_("No hosts found")) return hosts[int(random.random() * len(hosts))] - diff --git a/nova/service.py b/nova/service.py index 2998ed3e5b63..8b2a22ce0fa5 100644 --- a/nova/service.py +++ b/nova/service.py @@ -113,12 +113,13 @@ class Service(object): self.timers.append(periodic) def _create_service_ref(self, context): + zone = FLAGS.node_availability_zone service_ref = db.service_create(context, {'host': self.host, 'binary': self.binary, 'topic': self.topic, 'report_count': 0, - 'availability_zone': FLAGS.node_availability_zone}) + 'availability_zone': zone}) self.service_id = service_ref['id'] def __getattr__(self, key): diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index afb6a8f1b10c..afa6e91404c2 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -135,12 +135,12 @@ class CloudTestCase(test.TestCase): def test_describe_availability_zones(self): """Makes sure describe_availability_zones works and filters results.""" - service1 = db.service_create(self.context, {'host': 'host1_describe_zones', + service1 = db.service_create(self.context, {'host': 'host1_zones', 'binary': "nova-compute", 'topic': 'compute', 'report_count': 0, 'availability_zone': "zone1"}) - service2 = db.service_create(self.context, {'host': 'host2_describe_zones', + service2 = db.service_create(self.context, {'host': 'host2_zones', 'binary': "nova-compute", 'topic': 'compute', 'report_count': 0, @@ -150,17 +150,18 @@ class CloudTestCase(test.TestCase): db.service_destroy(self.context, service1['id']) db.service_destroy(self.context, service2['id']) - def test_describe_instances(self): """Makes sure describe_instances works and filters results.""" - inst1 = db.instance_create(self.context, {'reservation_id': 'a', 'host': 'host1'}) - inst2 = db.instance_create(self.context, {'reservation_id': 'a', 'host': 'host2'}) - compute1 = db.service_create(self.context, {'host': 'host1', - 'availability_zone': 'zone1', - 'topic': "compute"}) - compute2 = db.service_create(self.context, {'host': 'host2', - 'availability_zone': 'zone2', - 'topic': "compute"}) + inst1 = db.instance_create(self.context, {'reservation_id': 'a', + 'host': 'host1'}) + inst2 = db.instance_create(self.context, {'reservation_id': 'a', + 'host': 'host2'}) + comp1 = db.service_create(self.context, {'host': 'host1', + 'availability_zone': 'zone1', + 'topic': "compute"}) + comp2 = db.service_create(self.context, {'host': 'host2', + 'availability_zone': 'zone2', + 'topic': "compute"}) result = self.cloud.describe_instances(self.context) result = result['reservationSet'][0] self.assertEqual(len(result['instancesSet']), 2) @@ -171,13 +172,12 @@ class CloudTestCase(test.TestCase): self.assertEqual(len(result['instancesSet']), 1) self.assertEqual(result['instancesSet'][0]['instanceId'], instance_id) - self.assertEqual(result['instancesSet'][0]\ + self.assertEqual(result['instancesSet'][0] ['placement']['availabilityZone'], 'zone2') db.instance_destroy(self.context, inst1['id']) db.instance_destroy(self.context, inst2['id']) - db.service_destroy(self.context, compute1['id']) - db.service_destroy(self.context, compute2['id']) - + db.service_destroy(self.context, comp1['id']) + db.service_destroy(self.context, comp2['id']) def test_console_output(self): image_id = FLAGS.default_image @@ -257,21 +257,19 @@ class CloudTestCase(test.TestCase): LOG.debug(_("Terminating instance %s"), instance_id) rv = self.compute.terminate_instance(instance_id) - def test_describe_instances(self): """Makes sure describe_instances works.""" instance1 = db.instance_create(self.context, {'host': 'host2'}) - service1 = db.service_create(self.context, {'host': 'host2', - 'availability_zone': 'zone1', - 'topic': "compute"}) + comp1 = db.service_create(self.context, {'host': 'host2', + 'availability_zone': 'zone1', + 'topic': "compute"}) result = self.cloud.describe_instances(self.context) - self.assertEqual(result['reservationSet'][0]\ - ['instancesSet'][0]\ + self.assertEqual(result['reservationSet'][0] + ['instancesSet'][0] ['placement']['availabilityZone'], 'zone1') db.instance_destroy(self.context, instance1['id']) - db.service_destroy(self.context, service1['id']) + db.service_destroy(self.context, comp1['id']) - def test_instance_update_state(self): def instance(num): return { @@ -321,7 +319,6 @@ class CloudTestCase(test.TestCase): # data = self.cloud.get_metadata(instance(i)['private_dns_name']) # self.assert_(data['meta-data']['ami-id'] == 'ami-%s' % i) - @staticmethod def _fake_set_image_description(ctxt, image_id, description): from nova.objectstore import handler diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 127d666e47bf..ce4262ccfbdc 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -76,89 +76,59 @@ class SchedulerTestCase(test.TestCase): self.mox.ReplayAll() scheduler.named_method(ctxt, 'topic', num=7) -class ZoneSchedulerTestCase(test.TestCase): - """Test case for zone scheduler""" - def setUp(self): - super(ZoneSchedulerTestCase, self).setUp() - self.flags(scheduler_driver='nova.scheduler.zone.ZoneScheduler') - - def _create_service_model(self, **kwargs): - service = db.sqlalchemy.models.Service() - service.host = kwargs['host'] - service.disabled = False - service.deleted = False - service.report_count = 0 - service.binary = 'nova-compute' - service.topic = 'compute' - service.id = kwargs['id'] - service.availability_zone = kwargs['zone'] - service.created_at = datetime.datetime.utcnow() - return service - - - def test_with_two_zones(self): - scheduler = manager.SchedulerManager() - ctxt = context.get_admin_context() - service_list = [ - self._create_service_model(id=1, host='host1', zone='zone1'), - self._create_service_model(id=2, host='host2', zone='zone2'), - self._create_service_model(id=3, host='host3', zone='zone2'), - self._create_service_model(id=4, host='host4', zone='zone2'), - self._create_service_model(id=5, host='host5', zone='zone2') - ] - self.mox.StubOutWithMock(db, 'service_get_all_by_topic') - db.service_get_all_by_topic(IgnoreArg(), IgnoreArg()).AndReturn(service_list) - self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) - rpc.cast(ctxt, - 'compute.host1', - {'method': 'run_instance', - 'args':{'instance_id': 'i-ffffffff', - 'availability_zone': 'zone1'}}) - self.mox.ReplayAll() - scheduler.run_instance(ctxt, 'compute', instance_id='i-ffffffff', availability_zone='zone1') - - -class ZoneSchedulerTestCase(test.TestCase): - """Test case for zone scheduler""" - def setUp(self): - super(ZoneSchedulerTestCase, self).setUp() - self.flags(scheduler_driver='nova.scheduler.zone.ZoneScheduler') - - def _create_service_model(self, **kwargs): - service = db.sqlalchemy.models.Service() - service.host = kwargs['host'] - service.disabled = False - service.deleted = False - service.report_count = 0 - service.binary = 'nova-compute' - service.topic = 'compute' - service.id = kwargs['id'] - service.availability_zone = kwargs['zone'] - service.created_at = datetime.datetime.utcnow() - return service - - - def test_with_two_zones(self): - scheduler = manager.SchedulerManager() - ctxt = context.get_admin_context() - service_list = [ - self._create_service_model(id=1, host='host1', zone='zone1'), - self._create_service_model(id=2, host='host2', zone='zone2'), - self._create_service_model(id=3, host='host3', zone='zone2'), - self._create_service_model(id=4, host='host4', zone='zone2'), - self._create_service_model(id=5, host='host5', zone='zone2') - ] - self.mox.StubOutWithMock(db, 'service_get_all_by_topic') - db.service_get_all_by_topic(IgnoreArg(), IgnoreArg()).AndReturn(service_list) - self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) - rpc.cast(ctxt, - 'compute.host1', - {'method': 'run_instance', - 'args':{'instance_id': 'i-ffffffff', - 'availability_zone': 'zone1'}}) - self.mox.ReplayAll() - scheduler.run_instance(ctxt, 'compute', instance_id='i-ffffffff', availability_zone='zone1') +class ZoneSchedulerTestCase(test.TestCase): + """Test case for zone scheduler""" + def setUp(self): + super(ZoneSchedulerTestCase, self).setUp() + self.flags(scheduler_driver='nova.scheduler.zone.ZoneScheduler') + + def _create_service_model(self, **kwargs): + service = db.sqlalchemy.models.Service() + service.host = kwargs['host'] + service.disabled = False + service.deleted = False + service.report_count = 0 + service.binary = 'nova-compute' + service.topic = 'compute' + service.id = kwargs['id'] + service.availability_zone = kwargs['zone'] + service.created_at = datetime.datetime.utcnow() + return service + + def test_with_two_zones(self): + scheduler = manager.SchedulerManager() + ctxt = context.get_admin_context() + service_list = [self._create_service_model(id=1, + host='host1', + zone='zone1'), + self._create_service_model(id=2, + host='host2', + zone='zone2'), + self._create_service_model(id=3, + host='host3', + zone='zone2'), + self._create_service_model(id=4, + host='host4', + zone='zone2'), + self._create_service_model(id=5, + host='host5', + zone='zone2')] + self.mox.StubOutWithMock(db, 'service_get_all_by_topic') + arg = IgnoreArg() + db.service_get_all_by_topic(arg, arg).AndReturn(service_list) + self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) + rpc.cast(ctxt, + 'compute.host1', + {'method': 'run_instance', + 'args': {'instance_id': 'i-ffffffff', + 'availability_zone': 'zone1'}}) + self.mox.ReplayAll() + scheduler.run_instance(ctxt, + 'compute', + instance_id='i-ffffffff', + availability_zone='zone1') + class SimpleDriverTestCase(test.TestCase): """Test case for simple driver""" From b94f3a6cce3a49853c2426b87740fc467a4a787b Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Wed, 12 Jan 2011 02:19:05 +0300 Subject: [PATCH 8/8] remove extra whitspaces --- nova/db/sqlalchemy/models.py | 2 +- nova/tests/test_scheduler.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 8e5b6b3acb94..e7e984c18061 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -151,7 +151,7 @@ class Service(BASE, NovaBase): disabled = Column(Boolean, default=False) availability_zone = Column(String(255), default='nova') - + class Certificate(BASE, NovaBase): """Represents a an x509 certificate""" __tablename__ = 'certificates' diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index ce4262ccfbdc..9d458244b042 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -76,7 +76,7 @@ class SchedulerTestCase(test.TestCase): self.mox.ReplayAll() scheduler.named_method(ctxt, 'topic', num=7) - + class ZoneSchedulerTestCase(test.TestCase): """Test case for zone scheduler""" def setUp(self):