From 4887331a0d972b4d9e1fbd365c36edf1d7b076ec Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 2 Aug 2011 15:10:09 -0400 Subject: [PATCH 01/23] fix pylint errors --- nova/tests/scheduler/test_scheduler.py | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index 6a56a57dbf..a515636a39 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -51,10 +51,10 @@ FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' class TestDriver(driver.Scheduler): """Scheduler Driver for Tests""" - def schedule(context, topic, *args, **kwargs): + def schedule(self, context, topic, *args, **kwargs): return 'fallback_host' - def schedule_named_method(context, topic, num): + def schedule_named_method(self, context, topic, num): return 'named_host' @@ -301,7 +301,7 @@ class SimpleDriverTestCase(test.TestCase): db.compute_node_create(self.context, dic) return db.service_get(self.context, s_ref['id']) - def test_doesnt_report_disabled_hosts_as_up(self): + def test_doesnt_report_disabled_hosts_as_up_no_queue(self): """Ensures driver doesn't find hosts before they are enabled""" # NOTE(vish): constructing service without create method # because we are going to use it without queue @@ -324,7 +324,7 @@ class SimpleDriverTestCase(test.TestCase): compute1.kill() compute2.kill() - def test_reports_enabled_hosts_as_up(self): + def test_reports_enabled_hosts_as_up_no_queue(self): """Ensures driver can find the hosts that are up""" # NOTE(vish): constructing service without create method # because we are going to use it without queue @@ -343,7 +343,7 @@ class SimpleDriverTestCase(test.TestCase): compute1.kill() compute2.kill() - def test_least_busy_host_gets_instance(self): + def test_least_busy_host_gets_instance_no_queue(self): """Ensures the host with less cores gets the next one""" compute1 = service.Service('host1', 'nova-compute', @@ -366,7 +366,7 @@ class SimpleDriverTestCase(test.TestCase): compute1.kill() compute2.kill() - def test_specific_host_gets_instance(self): + def test_specific_host_gets_instance_no_queue(self): """Ensures if you set availability_zone it launches on that zone""" compute1 = service.Service('host1', 'nova-compute', @@ -389,7 +389,7 @@ class SimpleDriverTestCase(test.TestCase): compute1.kill() compute2.kill() - def test_wont_sechedule_if_specified_host_is_down(self): + def test_wont_sechedule_if_specified_host_is_down_no_queue(self): compute1 = service.Service('host1', 'nova-compute', 'compute', @@ -408,7 +408,7 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id2) compute1.kill() - def test_will_schedule_on_disabled_host_if_specified(self): + def test_will_schedule_on_disabled_host_if_specified_no_queue(self): compute1 = service.Service('host1', 'nova-compute', 'compute', @@ -423,7 +423,7 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id2) compute1.kill() - def test_too_many_cores(self): + def test_too_many_cores_no_queue(self): """Ensures we don't go over max cores""" compute1 = service.Service('host1', 'nova-compute', @@ -456,7 +456,7 @@ class SimpleDriverTestCase(test.TestCase): compute1.kill() compute2.kill() - def test_least_busy_host_gets_volume(self): + def test_least_busy_host_gets_volume_no_queue(self): """Ensures the host with less gigabytes gets the next one""" volume1 = service.Service('host1', 'nova-volume', @@ -477,7 +477,7 @@ class SimpleDriverTestCase(test.TestCase): volume1.delete_volume(self.context, volume_id1) db.volume_destroy(self.context, volume_id2) - def test_doesnt_report_disabled_hosts_as_up(self): + def test_doesnt_report_disabled_hosts_as_up2(self): """Ensures driver doesn't find hosts before they are enabled""" compute1 = self.start_service('compute', host='host1') compute2 = self.start_service('compute', host='host2') @@ -993,7 +993,7 @@ class ZoneRedirectTest(test.TestCase): decorator = FakeRerouteCompute("foo", id_to_return=FAKE_UUID_NOT_FOUND) try: result = decorator(go_boom)(None, None, 1) - self.assertFail(_("Should have rerouted.")) + self.fail(_("Should have rerouted.")) except api.RedirectResult, e: self.assertEquals(e.results['magic'], 'found me') @@ -1081,10 +1081,10 @@ class DynamicNovaClientTest(test.TestCase): class FakeZonesProxy(object): - def do_something(*args, **kwargs): + def do_something(self, *args, **kwargs): return 42 - def raises_exception(*args, **kwargs): + def raises_exception(self, *args, **kwargs): raise Exception('testing') From 378571665538fb5c4667a9d068678378ddf8526f Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 2 Aug 2011 15:19:00 -0400 Subject: [PATCH 02/23] fix pylint errors --- nova/db/sqlalchemy/api.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 36614df1f2..ad935fa449 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3202,9 +3202,8 @@ def instance_metadata_update_or_create(context, instance_id, metadata): meta_ref = None for key, value in metadata.iteritems(): try: - meta_ref = instance_metadata_get_item(context, instance_id, key, - session) - except: + meta_ref = instance_metadata_get_item(context, instance_id, key) + except exception.InstanceMetadataNotFound, e: meta_ref = models.InstanceMetadata() meta_ref.update({"key": key, "value": value, "instance_id": instance_id, @@ -3322,11 +3321,9 @@ def instance_type_extra_specs_update_or_create(context, instance_type_id, spec_ref = None for key, value in specs.iteritems(): try: - spec_ref = instance_type_extra_specs_get_item(context, - instance_type_id, - key, - session) - except: + spec_ref = instance_type_extra_specs_get_item( + context, instance_type_id, key) + except exception.InstanceTypeExtraSpecsNotFound, e: spec_ref = models.InstanceTypeExtraSpecs() spec_ref.update({"key": key, "value": value, "instance_type_id": instance_type_id, From d1891d2dd18a14535ec22a0363fd8234a01dbb8c Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 2 Aug 2011 15:30:27 -0400 Subject: [PATCH 03/23] remove unused parameter --- nova/virt/hyperv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index c26fe108bd..315f635c77 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -373,7 +373,7 @@ class HyperVConnection(driver.ComputeDriver): raise exception.InstanceNotFound(instance_id=instance.id) self._set_vm_state(instance.name, 'Reboot') - def destroy(self, instance, network_info): + def destroy(self, instance): """Destroy the VM. Also destroy the associated VHD disk files""" LOG.debug(_("Got request to destroy vm %s"), instance.name) vm = self._lookup(instance.name) From 614895b6c93904888aab99d1507d94271d763c04 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 2 Aug 2011 16:08:17 -0400 Subject: [PATCH 04/23] fix missing method call and add failing test --- nova/tests/test_xenapi.py | 9 +++++++++ nova/tests/xenapi/stubs.py | 4 ++++ nova/virt/xenapi_conn.py | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 6b7d5df761..9032c82ab4 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -669,6 +669,14 @@ class XenAPIVMTestCase(test.TestCase): self.conn.spawn(instance, network_info) return instance + def test_revert_migration(self): + instance = self._create_instance() + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) + stubs.stubout_loopingcall_start(self.stubs) + conn = xenapi_conn.get_connection(False) + conn.revert_migration(instance) + + class XenAPIDiffieHellmanTestCase(test.TestCase): """Unit tests for Diffie-Hellman code.""" @@ -842,6 +850,7 @@ class XenAPIMigrateInstance(test.TestCase): network_info, resize_instance=False) + class XenAPIImageTypeTestCase(test.TestCase): """Test ImageType class.""" diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 66c79d4659..195e4d038d 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -230,10 +230,14 @@ def stub_out_vm_methods(stubs): def fake_spawn_rescue(self, inst): inst._rescue = False + def fake_revert_migration(self, inst): + pass + stubs.Set(vmops.VMOps, "_shutdown", fake_shutdown) stubs.Set(vmops.VMOps, "_acquire_bootlock", fake_acquire_bootlock) stubs.Set(vmops.VMOps, "_release_bootlock", fake_release_bootlock) stubs.Set(vmops.VMOps, "spawn_rescue", fake_spawn_rescue) + stubs.Set(vmops.VMOps, "revert_migration", fake_revert_migration) class FakeSessionForVolumeTests(fake.SessionBase): diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index a3d0abf9fb..042bf2b02a 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -190,7 +190,7 @@ class XenAPIConnection(driver.ComputeDriver): def revert_migration(self, instance): """Reverts a resize, powering back on the instance""" - self._vmops.revert_resize(instance) + self._vmops.revert_migration(instance) def finish_migration(self, instance, disk_info, network_info, resize_instance=False): From b5a4a8d6cc68fec2dab205c5da494bce69241c33 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 2 Aug 2011 17:05:10 -0400 Subject: [PATCH 05/23] fix pep8 complaints --- nova/tests/test_xenapi.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 9032c82ab4..8e3c88f8e5 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -677,7 +677,6 @@ class XenAPIVMTestCase(test.TestCase): conn.revert_migration(instance) - class XenAPIDiffieHellmanTestCase(test.TestCase): """Unit tests for Diffie-Hellman code.""" def setUp(self): @@ -850,7 +849,6 @@ class XenAPIMigrateInstance(test.TestCase): network_info, resize_instance=False) - class XenAPIImageTypeTestCase(test.TestCase): """Test ImageType class.""" From 9bac11d9ff9933460f7ddf1bd1dd77d4d3397e47 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 2 Aug 2011 17:05:21 -0400 Subject: [PATCH 06/23] fix failing tests --- nova/db/sqlalchemy/api.py | 17 +++++++++++------ nova/tests/scheduler/test_scheduler.py | 4 ++-- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index ad935fa449..60220cd688 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3177,8 +3177,9 @@ def instance_metadata_delete_all(context, instance_id): @require_context @require_instance_exists -def instance_metadata_get_item(context, instance_id, key): - session = get_session() +def instance_metadata_get_item(context, instance_id, key, session=None): + if not session: + session = get_session() meta_result = session.query(models.InstanceMetadata).\ filter_by(instance_id=instance_id).\ @@ -3202,7 +3203,8 @@ def instance_metadata_update_or_create(context, instance_id, metadata): meta_ref = None for key, value in metadata.iteritems(): try: - meta_ref = instance_metadata_get_item(context, instance_id, key) + meta_ref = instance_metadata_get_item( + context, instance_id, key, session) except exception.InstanceMetadataNotFound, e: meta_ref = models.InstanceMetadata() meta_ref.update({"key": key, "value": value, @@ -3298,8 +3300,11 @@ def instance_type_extra_specs_delete(context, instance_type_id, key): @require_context -def instance_type_extra_specs_get_item(context, instance_type_id, key): - session = get_session() +def instance_type_extra_specs_get_item(context, instance_type_id, key, + session=None): + + if not session: + session = get_session() spec_result = session.query(models.InstanceTypeExtraSpecs).\ filter_by(instance_type_id=instance_type_id).\ @@ -3322,7 +3327,7 @@ def instance_type_extra_specs_update_or_create(context, instance_type_id, for key, value in specs.iteritems(): try: spec_ref = instance_type_extra_specs_get_item( - context, instance_type_id, key) + context, instance_type_id, key, session) except exception.InstanceTypeExtraSpecsNotFound, e: spec_ref = models.InstanceTypeExtraSpecs() spec_ref.update({"key": key, "value": value, diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index a515636a39..0d7634d0d4 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -51,10 +51,10 @@ FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' class TestDriver(driver.Scheduler): """Scheduler Driver for Tests""" - def schedule(self, context, topic, *args, **kwargs): + def schedule(context, topic, *args, **kwargs): return 'fallback_host' - def schedule_named_method(self, context, topic, num): + def schedule_named_method(context, topic, num): return 'named_host' From 8774c69c4a8d97ab2dac32c0f52e6963543a46f1 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 2 Aug 2011 17:11:53 -0400 Subject: [PATCH 07/23] raise correct error --- nova/scheduler/zone_aware_scheduler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/scheduler/zone_aware_scheduler.py b/nova/scheduler/zone_aware_scheduler.py index d99d7214c9..8440421e14 100644 --- a/nova/scheduler/zone_aware_scheduler.py +++ b/nova/scheduler/zone_aware_scheduler.py @@ -264,7 +264,7 @@ class ZoneAwareScheduler(driver.Scheduler): """ if topic != "compute": - raise NotImplemented(_("Zone Aware Scheduler only understands " + raise NotImplementedError(_("Zone Aware Scheduler only understands " "Compute nodes (for now)")) num_instances = request_spec.get('num_instances', 1) From e34a4c2feb7b2abef806ed720e1533e2e0fb94ef Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 14:05:58 -0400 Subject: [PATCH 08/23] remove bit-rotted code. fixes #820062 --- bin/nova-import-canonical-imagestore | 110 --------------------------- 1 file changed, 110 deletions(-) delete mode 100755 bin/nova-import-canonical-imagestore diff --git a/bin/nova-import-canonical-imagestore b/bin/nova-import-canonical-imagestore deleted file mode 100755 index 404ae37f49..0000000000 --- a/bin/nova-import-canonical-imagestore +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# 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. - -""" - Download images from Canonical Image Store -""" - -import gettext -import json -import os -import tempfile -import shutil -import subprocess -import sys -import urllib2 - -# If ../nova/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): - sys.path.insert(0, possible_topdir) - -gettext.install('nova', unicode=1) - -from nova import flags -from nova import log as logging -from nova import utils -from nova.objectstore import image - -FLAGS = flags.FLAGS - -API_URL = 'https://imagestore.canonical.com/api/dashboard' - - -def get_images(): - """Get a list of the images from the imagestore URL.""" - images = json.load(urllib2.urlopen(API_URL))['images'] - images = [img for img in images if img['title'].find('amd64') > -1] - return images - - -def download(img): - """Download an image to the local filesystem.""" - # FIXME(ja): add checksum/signature checks - tempdir = tempfile.mkdtemp(prefix='cis-') - - kernel_id = None - ramdisk_id = None - - for f in img['files']: - if f['kind'] == 'kernel': - dest = os.path.join(tempdir, 'kernel') - subprocess.call(['curl', '--fail', f['url'], '-o', dest]) - kernel_id = image.Image.add(dest, - description='kernel/' + img['title'], kernel=True) - - for f in img['files']: - if f['kind'] == 'ramdisk': - dest = os.path.join(tempdir, 'ramdisk') - subprocess.call(['curl', '--fail', f['url'], '-o', dest]) - ramdisk_id = image.Image.add(dest, - description='ramdisk/' + img['title'], ramdisk=True) - - for f in img['files']: - if f['kind'] == 'image': - dest = os.path.join(tempdir, 'image') - subprocess.call(['curl', '--fail', f['url'], '-o', dest]) - ramdisk_id = image.Image.add(dest, - description=img['title'], kernel=kernel_id, ramdisk=ramdisk_id) - - shutil.rmtree(tempdir) - - -def main(): - """Main entry point.""" - utils.default_flagfile() - argv = FLAGS(sys.argv) - logging.setup() - images = get_images() - - if len(argv) == 2: - for img in images: - if argv[1] == 'all' or argv[1] == img['title']: - download(img) - else: - print 'usage: %s (title|all)' - print 'available images:' - for img in images: - print img['title'] - -if __name__ == '__main__': - main() From 916e0ce0997bdf3135684865eff6fadcda95752b Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 14:13:53 -0400 Subject: [PATCH 09/23] remove unused imports --- nova/api/openstack/create_instance_helper.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 53e814cd5d..e4b897cd68 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -14,8 +14,6 @@ # under the License. import base64 -import re -import webob from webob import exc from xml.dom import minidom From 91e16e057f083d1a0b8dffaa00b5979c12c23edc Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 14:30:45 -0400 Subject: [PATCH 10/23] fix potential runtime exception The exception could occur if a client were to create an APIRouter object. The fix relies on more established OOP patterns. --- nova/api/openstack/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 868b98a31c..8d7f7a4057 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -81,7 +81,10 @@ class APIRouter(base_wsgi.Router): self._setup_routes(mapper) super(APIRouter, self).__init__(mapper) - def _setup_routes(self, mapper, version): + def _setup_routes(self, mapper): + raise NotImplementedError("you must implement _setup_routes") + + def _setup_base_routes(self, mapper, version): """Routes common to all versions.""" server_members = self.server_members @@ -147,7 +150,7 @@ class APIRouterV10(APIRouter): """Define routes specific to OpenStack API V1.0.""" def _setup_routes(self, mapper): - super(APIRouterV10, self)._setup_routes(mapper, '1.0') + self._setup_base_routes(mapper, '1.0') mapper.resource("shared_ip_group", "shared_ip_groups", collection={'detail': 'GET'}, @@ -163,7 +166,7 @@ class APIRouterV11(APIRouter): """Define routes specific to OpenStack API V1.1.""" def _setup_routes(self, mapper): - super(APIRouterV11, self)._setup_routes(mapper, '1.1') + self._setup_base_routes(mapper, '1.1') image_metadata_controller = image_metadata.create_resource() mapper.resource("image_meta", "metadata", controller=image_metadata_controller, From a049e682b54525d2814f20b08ca64320040675b8 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 14:46:02 -0400 Subject: [PATCH 11/23] fix undefined variable error --- nova/scheduler/least_cost.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nova/scheduler/least_cost.py b/nova/scheduler/least_cost.py index 8c400d4767..329107efe9 100644 --- a/nova/scheduler/least_cost.py +++ b/nova/scheduler/least_cost.py @@ -96,7 +96,8 @@ class LeastCostScheduler(zone_aware_scheduler.ZoneAwareScheduler): cost_fn_str=cost_fn_str) try: - weight = getattr(FLAGS, "%s_weight" % cost_fn.__name__) + flag_name = "%s_weight" % cost_fn.__name__ + weight = getattr(FLAGS, flag_name) except AttributeError: raise exception.SchedulerWeightFlagNotFound( flag_name=flag_name) From 933587d821797037bb765e9d0bd5ea063c07785b Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 14:47:35 -0400 Subject: [PATCH 12/23] fix duplicate function name --- nova/tests/test_instance_types_extra_specs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_instance_types_extra_specs.py b/nova/tests/test_instance_types_extra_specs.py index 393ed1e368..205601277a 100644 --- a/nova/tests/test_instance_types_extra_specs.py +++ b/nova/tests/test_instance_types_extra_specs.py @@ -136,7 +136,7 @@ class InstanceTypeExtraSpecsTestCase(test.TestCase): "m1.small") self.assertEquals(instance_type['extra_specs'], {}) - def test_instance_type_get_with_extra_specs(self): + def test_instance_type_get_by_flavor_id_with_extra_specs(self): instance_type = db.api.instance_type_get_by_flavor_id( context.get_admin_context(), 105) From 98307324d7b1cce2f7312d1195c9674f0e0323b6 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 14:49:14 -0400 Subject: [PATCH 13/23] use correct exception name --- nova/virt/vmwareapi/vif.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/vmwareapi/vif.py b/nova/virt/vmwareapi/vif.py index b3e43b2093..fb6548b34e 100644 --- a/nova/virt/vmwareapi/vif.py +++ b/nova/virt/vmwareapi/vif.py @@ -63,7 +63,7 @@ class VMWareVlanBridgeDriver(VIFDriver): vswitch_associated = network_utils.get_vswitch_for_vlan_interface( session, vlan_interface) if vswitch_associated is None: - raise exception.SwicthNotFoundForNetworkAdapter( + raise exception.SwitchNotFoundForNetworkAdapter( adapter=vlan_interface) # Check whether bridge already exists and retrieve the the ref of the # network whose name_label is "bridge" From 4aada43cc0d1a3cb32094d6d6be1eb662f01d063 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 14:51:47 -0400 Subject: [PATCH 14/23] use an existing exception --- nova/virt/xenapi/vm_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 60ef0df435..8a715af356 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -794,7 +794,7 @@ def get_vdi_for_vm_safely(session, vm_ref): else: num_vdis = len(vdi_refs) if num_vdis != 1: - raise exception.Exception(_("Unexpected number of VDIs" + raise exception.Error(_("Unexpected number of VDIs" "(%(num_vdis)s) found" " for VM %(vm_ref)s") % locals()) From 6203ae5d5b285d62bd2c1bf1f2f11d3b64b53511 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 15:05:57 -0400 Subject: [PATCH 15/23] pep8 fixes --- nova/scheduler/zone_aware_scheduler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/scheduler/zone_aware_scheduler.py b/nova/scheduler/zone_aware_scheduler.py index 8440421e14..2979225709 100644 --- a/nova/scheduler/zone_aware_scheduler.py +++ b/nova/scheduler/zone_aware_scheduler.py @@ -264,8 +264,8 @@ class ZoneAwareScheduler(driver.Scheduler): """ if topic != "compute": - raise NotImplementedError(_("Zone Aware Scheduler only understands " - "Compute nodes (for now)")) + raise NotImplementedError(_("Zone Aware Scheduler only understands" + " Compute nodes (for now)")) num_instances = request_spec.get('num_instances', 1) instance_type = request_spec['instance_type'] From a5add8b30c96ad1d83eebcd9756b0f358c9cb725 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 15:16:38 -0400 Subject: [PATCH 16/23] follow convention when raising exceptions --- nova/api/openstack/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 8d7f7a4057..0af39c2dff 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -82,7 +82,7 @@ class APIRouter(base_wsgi.Router): super(APIRouter, self).__init__(mapper) def _setup_routes(self, mapper): - raise NotImplementedError("you must implement _setup_routes") + raise NotImplementedError(_("You must implement _setup_routes.")) def _setup_base_routes(self, mapper, version): """Routes common to all versions.""" From e7cb0c70384fc247a7f330ed7c4db5a3b0de814c Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 16:45:46 -0400 Subject: [PATCH 17/23] align multi-line string --- nova/scheduler/zone_aware_scheduler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/scheduler/zone_aware_scheduler.py b/nova/scheduler/zone_aware_scheduler.py index 2979225709..9ac0f94edc 100644 --- a/nova/scheduler/zone_aware_scheduler.py +++ b/nova/scheduler/zone_aware_scheduler.py @@ -265,7 +265,7 @@ class ZoneAwareScheduler(driver.Scheduler): if topic != "compute": raise NotImplementedError(_("Zone Aware Scheduler only understands" - " Compute nodes (for now)")) + " Compute nodes (for now)")) num_instances = request_spec.get('num_instances', 1) instance_type = request_spec['instance_type'] From 8b0ebd90edb47be344b355334ae16d6b7715087d Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 17:02:45 -0400 Subject: [PATCH 18/23] all subclasses of ComputeDriver should fully implement the interface of the destroy method. --- nova/virt/fake.py | 2 +- nova/virt/hyperv.py | 2 +- nova/virt/vmwareapi_conn.py | 2 +- nova/virt/xenapi_conn.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 2898f23a4f..b7396d61c6 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -293,7 +293,7 @@ class FakeConnection(driver.ComputeDriver): """ pass - def destroy(self, instance, network_info): + def destroy(self, instance, network_info, cleanup=True): key = instance.name if key in self.instances: del self.instances[key] diff --git a/nova/virt/hyperv.py b/nova/virt/hyperv.py index 315f635c77..1e4cce10ca 100644 --- a/nova/virt/hyperv.py +++ b/nova/virt/hyperv.py @@ -373,7 +373,7 @@ class HyperVConnection(driver.ComputeDriver): raise exception.InstanceNotFound(instance_id=instance.id) self._set_vm_state(instance.name, 'Reboot') - def destroy(self, instance): + def destroy(self, instance, network_info, cleanup=True): """Destroy the VM. Also destroy the associated VHD disk files""" LOG.debug(_("Got request to destroy vm %s"), instance.name) vm = self._lookup(instance.name) diff --git a/nova/virt/vmwareapi_conn.py b/nova/virt/vmwareapi_conn.py index ce57847b20..10d80c0a02 100644 --- a/nova/virt/vmwareapi_conn.py +++ b/nova/virt/vmwareapi_conn.py @@ -136,7 +136,7 @@ class VMWareESXConnection(driver.ComputeDriver): """Reboot VM instance.""" self._vmops.reboot(instance, network_info) - def destroy(self, instance, network_info): + def destroy(self, instance, network_info, cleanup=True): """Destroy VM instance.""" self._vmops.destroy(instance, network_info) diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 042bf2b02a..571638496c 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -216,7 +216,7 @@ class XenAPIConnection(driver.ComputeDriver): """ self._vmops.inject_file(instance, b64_path, b64_contents) - def destroy(self, instance, network_info): + def destroy(self, instance, network_info, cleanup=True): """Destroy VM instance""" self._vmops.destroy(instance, network_info) From 23f6ec84a93638e880f60bec00db8587b9e3e8d8 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 20:26:37 -0400 Subject: [PATCH 19/23] fix pylint W0102 errors. --- nova/api/openstack/extensions.py | 6 +++++- nova/compute/api.py | 19 +++++++++++++++---- nova/objectstore/s3server.py | 5 ++++- nova/scheduler/manager.py | 4 +++- nova/tests/api/openstack/test_limits.py | 5 ++++- nova/tests/test_auth.py | 7 ++++++- nova/tests/test_compute.py | 10 ++++++++-- nova/tests/test_libvirt.py | 5 ++++- nova/virt/vmwareapi/io_util.py | 5 ++++- nova/virt/vmwareapi/vim_util.py | 10 ++++++++-- nova/virt/vmwareapi/vmware_images.py | 6 +++++- 11 files changed, 66 insertions(+), 16 deletions(-) diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py index cc889703e3..b070dd61ac 100644 --- a/nova/api/openstack/extensions.py +++ b/nova/api/openstack/extensions.py @@ -460,7 +460,11 @@ class ResourceExtension(object): """Add top level resources to the OpenStack API in nova.""" def __init__(self, collection, controller, parent=None, - collection_actions={}, member_actions={}): + collection_actions=None, member_actions=None): + if not collection_actions: + collection_actions = {} + if not member_actions: + member_actions = {} self.collection = collection self.controller = controller self.parent = parent diff --git a/nova/compute/api.py b/nova/compute/api.py index aae16d1da2..fe62b50cea 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -121,8 +121,10 @@ class API(base.Base): if len(content) > content_limit: raise quota.QuotaError(code="OnsetFileContentLimitExceeded") - def _check_metadata_properties_quota(self, context, metadata={}): + def _check_metadata_properties_quota(self, context, metadata=None): """Enforce quota limits on metadata properties.""" + if not metadata: + metadata = {} num_metadata = len(metadata) quota_metadata = quota.allowed_metadata_items(context, num_metadata) if quota_metadata < num_metadata: @@ -148,7 +150,7 @@ class API(base.Base): min_count=None, max_count=None, display_name='', display_description='', key_name=None, key_data=None, security_group='default', - availability_zone=None, user_data=None, metadata={}, + availability_zone=None, user_data=None, metadata=None, injected_files=None, admin_password=None, zone_blob=None, reservation_id=None): """Verify all the input parameters regardless of the provisioning @@ -160,6 +162,8 @@ class API(base.Base): min_count = 1 if not max_count: max_count = min_count + if not metadata: + metadata = {} num_instances = quota.allowed_instances(context, max_count, instance_type) @@ -395,12 +399,16 @@ class API(base.Base): min_count=None, max_count=None, display_name='', display_description='', key_name=None, key_data=None, security_group='default', - availability_zone=None, user_data=None, metadata={}, + availability_zone=None, user_data=None, metadata=None, injected_files=None, admin_password=None, zone_blob=None, reservation_id=None, block_device_mapping=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.""" + + if not metadata: + metadata = {} + num_instances, base_options, image = self._check_create_parameters( context, instance_type, image_href, kernel_id, ramdisk_id, @@ -424,7 +432,7 @@ class API(base.Base): min_count=None, max_count=None, display_name='', display_description='', key_name=None, key_data=None, security_group='default', - availability_zone=None, user_data=None, metadata={}, + availability_zone=None, user_data=None, metadata=None, injected_files=None, admin_password=None, zone_blob=None, reservation_id=None, block_device_mapping=None): """ @@ -439,6 +447,9 @@ class API(base.Base): Returns a list of instance dicts. """ + if not metadata: + metadata = {} + num_instances, base_options, image = self._check_create_parameters( context, instance_type, image_href, kernel_id, ramdisk_id, diff --git a/nova/objectstore/s3server.py b/nova/objectstore/s3server.py index 76025a1e3f..1ab47b0349 100644 --- a/nova/objectstore/s3server.py +++ b/nova/objectstore/s3server.py @@ -155,7 +155,10 @@ class BaseRequestHandler(object): self.finish('\n' + ''.join(parts)) - def _render_parts(self, value, parts=[]): + def _render_parts(self, value, parts=None): + if not parts: + parts = [] + if isinstance(value, basestring): parts.append(utils.xhtml_escape(value)) elif isinstance(value, int) or isinstance(value, long): diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 749d66cadb..c8b16b6222 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -69,8 +69,10 @@ class SchedulerManager(manager.Manager): return self.zone_manager.get_zone_capabilities(context) def update_service_capabilities(self, context=None, service_name=None, - host=None, capabilities={}): + host=None, capabilities=None): """Process a capability update from a service node.""" + if not capability: + capability = {} self.zone_manager.update_service_capabilities(service_name, host, capabilities) diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py index 6c3d531e33..1dc3c3a17c 100644 --- a/nova/tests/api/openstack/test_limits.py +++ b/nova/tests/api/openstack/test_limits.py @@ -819,12 +819,15 @@ class FakeHttplibConnection(object): self.app = app self.host = host - def request(self, method, path, body="", headers={}): + def request(self, method, path, body="", headers=None): """ Requests made via this connection actually get translated and routed into our WSGI app, we then wait for the response and turn it back into an `httplib.HTTPResponse`. """ + if not headers: + headers = {} + req = webob.Request.blank(path) req.method = method req.headers = headers diff --git a/nova/tests/test_auth.py b/nova/tests/test_auth.py index 7c0f783bbd..0fb2fdcc6c 100644 --- a/nova/tests/test_auth.py +++ b/nova/tests/test_auth.py @@ -62,7 +62,12 @@ class project_generator(object): class user_and_project_generator(object): - def __init__(self, manager, user_state={}, project_state={}): + def __init__(self, manager, user_state=None, project_state=None): + if not user_state: + user_state = {} + if not project_state: + project_state = {} + self.manager = manager if 'name' not in user_state: user_state['name'] = 'test1' diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 879e4b9cbf..9be349d146 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -73,8 +73,11 @@ class ComputeTestCase(test.TestCase): self.stubs.Set(nova.image.fake._FakeImageService, 'show', fake_show) - def _create_instance(self, params={}): + def _create_instance(self, params=None): """Create a test instance""" + if not params: + params = {} + inst = {} inst['image_ref'] = 1 inst['reservation_id'] = 'r-fakeres' @@ -87,8 +90,11 @@ class ComputeTestCase(test.TestCase): inst.update(params) return db.instance_create(self.context, inst)['id'] - def _create_instance_type(self, params={}): + def _create_instance_type(self, params=None): """Create a test instance""" + if not params: + params = {} + context = self.context.elevated() inst = {} inst['name'] = 'm1.small' diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index c5c3151dc7..aa77258cbc 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -1162,8 +1162,11 @@ class NWFilterTestCase(test.TestCase): 'project_id': 'fake', 'instance_type_id': 1}) - def _create_instance_type(self, params={}): + def _create_instance_type(self, params=None): """Create a test instance""" + if not params: + params = {} + context = self.context.elevated() inst = {} inst['name'] = 'm1.small' diff --git a/nova/virt/vmwareapi/io_util.py b/nova/virt/vmwareapi/io_util.py index 2ec773b7b4..4092428005 100644 --- a/nova/virt/vmwareapi/io_util.py +++ b/nova/virt/vmwareapi/io_util.py @@ -68,7 +68,10 @@ class GlanceWriteThread(object): """Ensures that image data is written to in the glance client and that it is in correct ('active')state.""" - def __init__(self, input, glance_client, image_id, image_meta={}): + def __init__(self, input, glance_client, image_id, image_meta=None): + if not image_meta: + image_meta = {} + self.input = input self.glance_client = glance_client self.image_id = image_id diff --git a/nova/virt/vmwareapi/vim_util.py b/nova/virt/vmwareapi/vim_util.py index 11214231cd..e03daddacb 100644 --- a/nova/virt/vmwareapi/vim_util.py +++ b/nova/virt/vmwareapi/vim_util.py @@ -95,9 +95,12 @@ def build_recursive_traversal_spec(client_factory): def build_property_spec(client_factory, type="VirtualMachine", - properties_to_collect=["name"], + properties_to_collect=None, all_properties=False): """Builds the Property Spec.""" + if not properties_to_collect: + properties_to_collect = ["name"] + property_spec = client_factory.create('ns0:PropertySpec') property_spec.all = all_properties property_spec.pathSet = properties_to_collect @@ -155,8 +158,11 @@ def get_dynamic_property(vim, mobj, type, property_name): return property_value -def get_objects(vim, type, properties_to_collect=["name"], all=False): +def get_objects(vim, type, properties_to_collect=None, all=False): """Gets the list of objects of the type specified.""" + if not properties_to_collect: + properties_to_collect = ["name"] + client_factory = vim.client.factory object_spec = build_object_spec(client_factory, vim.get_service_content().rootFolder, diff --git a/nova/virt/vmwareapi/vmware_images.py b/nova/virt/vmwareapi/vmware_images.py index 70adba74f0..f5f75dae26 100644 --- a/nova/virt/vmwareapi/vmware_images.py +++ b/nova/virt/vmwareapi/vmware_images.py @@ -33,11 +33,15 @@ QUEUE_BUFFER_SIZE = 10 def start_transfer(read_file_handle, data_size, write_file_handle=None, - glance_client=None, image_id=None, image_meta={}): + glance_client=None, image_id=None, image_meta=None): """Start the data transfer from the reader to the writer. Reader writes to the pipe and the writer reads from the pipe. This means that the total transfer time boils down to the slower of the read/write and not the addition of the two times.""" + + if not image_meta: + image_meta = {} + # The pipe that acts as an intermediate store of data for reader to write # to and writer to grab from. thread_safe_pipe = io_util.ThreadSafePipe(QUEUE_BUFFER_SIZE, data_size) From 4c7a33ee907ae7abcff020c75dde8ed320fe7aeb Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Mon, 8 Aug 2011 15:30:44 -0400 Subject: [PATCH 20/23] assert that vmops.revert_migration is called --- nova/tests/test_xenapi.py | 25 ++++++++++++++++++------- nova/tests/xenapi/stubs.py | 4 ---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 8e3c88f8e5..34aba140ba 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -637,6 +637,24 @@ class XenAPIVMTestCase(test.TestCase): # Ensure that it will not unrescue a non-rescued instance. self.assertRaises(Exception, conn.unrescue, instance, None) + def test_revert_migration(self): + instance = self._create_instance() + + class VMOpsMock(): + + def __init__(self): + self.revert_migration_called = False + + def revert_migration(self, instance): + self.revert_migration_called = True + + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) + + conn = xenapi_conn.get_connection(False) + conn._vmops = VMOpsMock() + conn.revert_migration(instance) + self.assertTrue(conn._vmops.revert_migration_called) + def _create_instance(self, instance_id=1, spawn=True): """Creates and spawns a test instance.""" stubs.stubout_loopingcall_start(self.stubs) @@ -669,13 +687,6 @@ class XenAPIVMTestCase(test.TestCase): self.conn.spawn(instance, network_info) return instance - def test_revert_migration(self): - instance = self._create_instance() - stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) - stubs.stubout_loopingcall_start(self.stubs) - conn = xenapi_conn.get_connection(False) - conn.revert_migration(instance) - class XenAPIDiffieHellmanTestCase(test.TestCase): """Unit tests for Diffie-Hellman code.""" diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 195e4d038d..66c79d4659 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -230,14 +230,10 @@ def stub_out_vm_methods(stubs): def fake_spawn_rescue(self, inst): inst._rescue = False - def fake_revert_migration(self, inst): - pass - stubs.Set(vmops.VMOps, "_shutdown", fake_shutdown) stubs.Set(vmops.VMOps, "_acquire_bootlock", fake_acquire_bootlock) stubs.Set(vmops.VMOps, "_release_bootlock", fake_release_bootlock) stubs.Set(vmops.VMOps, "spawn_rescue", fake_spawn_rescue) - stubs.Set(vmops.VMOps, "revert_migration", fake_revert_migration) class FakeSessionForVolumeTests(fake.SessionBase): From 1fc7164ecaa42c33ff510ec8ef3ca92f183c96e3 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Mon, 8 Aug 2011 15:37:23 -0400 Subject: [PATCH 21/23] remove obsolete script from setup.py --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 8121e250ba..118ac1abd1 100644 --- a/setup.py +++ b/setup.py @@ -123,7 +123,6 @@ setup(name='nova', 'bin/nova-console', 'bin/nova-dhcpbridge', 'bin/nova-direct-api', - 'bin/nova-import-canonical-imagestore', 'bin/nova-logspool', 'bin/nova-manage', 'bin/nova-network', From 8c6ebaf9861e3b652663c0ff60ad545864f72677 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 9 Aug 2011 19:34:51 -0400 Subject: [PATCH 22/23] use correct variable name --- nova/db/sqlalchemy/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 1da54b3dac..8119cdfb8b 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3346,8 +3346,8 @@ def instance_metadata_update(context, instance_id, metadata, delete): item = {"value": meta_value} try: - meta_ref = instance_metadata_get_item( - context, instance_id, key, session) + meta_ref = instance_metadata_get_item(context, instance_id, + meta_key, session) except exception.InstanceMetadataNotFound, e: meta_ref = models.InstanceMetadata() item.update({"key": meta_key, "instance_id": instance_id}) From 83ed9faa488b3ec0f1cb16e7147293c912e2fc2b Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Tue, 9 Aug 2011 19:35:40 -0400 Subject: [PATCH 23/23] pep8 fix --- nova/api/openstack/contrib/floating_ips.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/api/openstack/contrib/floating_ips.py b/nova/api/openstack/contrib/floating_ips.py index 52c9c6cf93..2aba1068ad 100644 --- a/nova/api/openstack/contrib/floating_ips.py +++ b/nova/api/openstack/contrib/floating_ips.py @@ -102,7 +102,7 @@ class FloatingIPController(object): def delete(self, req, id): context = req.environ['nova.context'] ip = self.network_api.get_floating_ip(context, id) - + if 'fixed_ip' in ip: try: self.disassociate(req, id, '')