From 8d97118be776fcaad3053d1f93f61d339685a4ae Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Fri, 22 Jul 2011 17:26:11 +0400 Subject: Moved restaring instances from livbirt driver to ComputeManager. --- nova/compute/manager.py | 19 +++++++++++++++++++ nova/flags.py | 3 +++ nova/virt/libvirt/connection.py | 25 ++----------------------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 5819a520a..c7d3004a5 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -146,7 +146,26 @@ class ComputeManager(manager.SchedulerDependentManager): def init_host(self): """Initialization for a standalone compute service.""" + # NOTE(nsokolov): based on itoumsn's implementation from libvirt driver + from nova import context self.driver.init_host(host=self.host) + admin_context = context.get_admin_context() + for instance in self.db.instance_get_all_by_host(admin_context, self.host): + try: + LOG.debug(_('Checking state of %s'), instance['name']) + state = self.driver.get_info(instance['name'])['state'] + except exception.NotFound: + state = power_state.SHUTOFF + + LOG.debug(_('Current state of %(name)s is %(state)s, state in DB is %(db_state)s.'), + {'name': instance['name'], 'state': state, 'db_state': instance['state']}) + + if instance['state'] == power_state.RUNNING and state != power_state.RUNNING \ + and FLAGS.start_guests_on_host_boot: + LOG.debug(_('Rebooting instance %(name)s after nova-compute restart.')) + self.reboot_instance(admin_context, instance[id]) + else: + self.db.instance_set_state(ctxt, instance['id'], state) def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" diff --git a/nova/flags.py b/nova/flags.py index 49355b436..23ca38b17 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -387,3 +387,6 @@ DEFINE_list('zone_capabilities', 'Key/Multi-value list representng capabilities of this zone') DEFINE_string('build_plan_encryption_key', None, '128bit (hex) encryption key for scheduler build plans.') + +DEFINE_bool('start_guests_on_host_boot', False, + 'Whether to restart guests when the host reboots') diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 342dea98f..d85b91ee2 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -121,8 +121,6 @@ flags.DEFINE_integer('live_migration_bandwidth', 0, 'Define live migration behavior') flags.DEFINE_string('qemu_img', 'qemu-img', 'binary to use for qemu-img commands') -flags.DEFINE_bool('start_guests_on_host_boot', False, - 'Whether to restart guests when the host reboots') def get_connection(read_only): @@ -167,27 +165,8 @@ class LibvirtConnection(driver.ComputeDriver): self.firewall_driver = fw_class(get_connection=self._get_connection) def init_host(self, host): - # Adopt existing VM's running here - ctxt = context.get_admin_context() - for instance in db.instance_get_all_by_host(ctxt, host): - try: - LOG.debug(_('Checking state of %s'), instance['name']) - state = self.get_info(instance['name'])['state'] - except exception.NotFound: - state = power_state.SHUTOFF - - LOG.debug(_('Current state of %(name)s was %(state)s.'), - {'name': instance['name'], 'state': state}) - db.instance_set_state(ctxt, instance['id'], state) - - # NOTE(justinsb): We no longer delete SHUTOFF instances, - # the user may want to power them back on - - if state != power_state.RUNNING: - continue - self.firewall_driver.setup_basic_filtering(instance) - self.firewall_driver.prepare_instance_filter(instance) - self.firewall_driver.apply_instance_filter(instance) + # NOTE(nsokolov): moved instance restarting to ComputeManager + pass def _get_connection(self): if not self._wrapped_conn or not self._test_connection(): -- cgit From 4937c2f2c757776eacba20a6446c059c4938d6b8 Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Mon, 25 Jul 2011 11:06:06 +0400 Subject: Removed driver-specific autostart code. --- nova/virt/libvirt/connection.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index d85b91ee2..65a6b6393 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -571,11 +571,6 @@ class LibvirtConnection(driver.ComputeDriver): LOG.debug(_("instance %s: is running"), instance['name']) self.firewall_driver.apply_instance_filter(instance) - if FLAGS.start_guests_on_host_boot: - LOG.debug(_("instance %s: setting autostart ON") % - instance['name']) - domain.setAutostart(1) - def _wait_for_boot(): """Called at an interval until the VM is running.""" instance_name = instance['name'] -- cgit From 708b0cb65a672e9f6b8bab4817061be4fa2a8928 Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Mon, 25 Jul 2011 14:22:38 +0400 Subject: Fixed init_host context name. --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index c7d3004a5..b876e87d0 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -165,7 +165,7 @@ class ComputeManager(manager.SchedulerDependentManager): LOG.debug(_('Rebooting instance %(name)s after nova-compute restart.')) self.reboot_instance(admin_context, instance[id]) else: - self.db.instance_set_state(ctxt, instance['id'], state) + self.db.instance_set_state(admin_context, instance['id'], state) def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" -- cgit From d8f4d773b08a94b171ff2643d48daa5b2709118a Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Mon, 25 Jul 2011 14:33:45 +0400 Subject: Fixed id. --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index b876e87d0..b7e54d903 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -163,7 +163,7 @@ class ComputeManager(manager.SchedulerDependentManager): if instance['state'] == power_state.RUNNING and state != power_state.RUNNING \ and FLAGS.start_guests_on_host_boot: LOG.debug(_('Rebooting instance %(name)s after nova-compute restart.')) - self.reboot_instance(admin_context, instance[id]) + self.reboot_instance(admin_context, instance['id']) else: self.db.instance_set_state(admin_context, instance['id'], state) -- cgit From 19379c78e6efd4637d876c91b022e6e7dbd38836 Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Mon, 25 Jul 2011 14:37:21 +0400 Subject: Fixed logging. --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index b7e54d903..071eabcfe 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -162,7 +162,7 @@ class ComputeManager(manager.SchedulerDependentManager): if instance['state'] == power_state.RUNNING and state != power_state.RUNNING \ and FLAGS.start_guests_on_host_boot: - LOG.debug(_('Rebooting instance %(name)s after nova-compute restart.')) + LOG.debug(_('Rebooting instance %(name)s after nova-compute restart.'), {'name': instance['name']}) self.reboot_instance(admin_context, instance['id']) else: self.db.instance_set_state(admin_context, instance['id'], state) -- cgit From cf4aea379eb337b16a9816d45c50c0553c500d0d Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Mon, 25 Jul 2011 15:03:02 +0400 Subject: pep8 --- nova/compute/manager.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 071eabcfe..ebd91177f 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -150,22 +150,29 @@ class ComputeManager(manager.SchedulerDependentManager): from nova import context self.driver.init_host(host=self.host) admin_context = context.get_admin_context() - for instance in self.db.instance_get_all_by_host(admin_context, self.host): + for instance in self.db.instance_get_all_by_host(admin_context, + self.host): try: LOG.debug(_('Checking state of %s'), instance['name']) state = self.driver.get_info(instance['name'])['state'] except exception.NotFound: state = power_state.SHUTOFF - LOG.debug(_('Current state of %(name)s is %(state)s, state in DB is %(db_state)s.'), - {'name': instance['name'], 'state': state, 'db_state': instance['state']}) - - if instance['state'] == power_state.RUNNING and state != power_state.RUNNING \ - and FLAGS.start_guests_on_host_boot: - LOG.debug(_('Rebooting instance %(name)s after nova-compute restart.'), {'name': instance['name']}) + LOG.debug(_('Current state of %(name)s is %(state)s, state in ' + 'DB is %(db_state)s.'), {'name': instance['name'], + 'state': state, + 'db_state': + instance['state']}) + + if instance['state'] == power_state.RUNNING \ + and state != power_state.RUNNING \ + and FLAGS.start_guests_on_host_boot: + LOG.debug(_('Rebooting instance %(name)s after nova-compute ' + ' restart.'), {'name': instance['name']}) self.reboot_instance(admin_context, instance['id']) else: - self.db.instance_set_state(admin_context, instance['id'], state) + self.db.instance_set_state(admin_context, instance['id'], + state) def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" -- cgit From d85a43c4cdb1bfd28355ded486af2ded8f43d6b0 Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Mon, 25 Jul 2011 19:54:23 +0400 Subject: Some estetic refactoring. --- nova/compute/manager.py | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index ebd91177f..950fe0d53 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -44,6 +44,7 @@ import functools from eventlet import greenthread +import nova.context from nova import exception from nova import flags import nova.image @@ -145,34 +146,26 @@ class ComputeManager(manager.SchedulerDependentManager): *args, **kwargs) def init_host(self): - """Initialization for a standalone compute service.""" - # NOTE(nsokolov): based on itoumsn's implementation from libvirt driver - from nova import context + """Initialization for a standalone compute service. + + Reboots instances marked as running in DB if they is not running.""" self.driver.init_host(host=self.host) - admin_context = context.get_admin_context() - for instance in self.db.instance_get_all_by_host(admin_context, - self.host): - try: - LOG.debug(_('Checking state of %s'), instance['name']) - state = self.driver.get_info(instance['name'])['state'] - except exception.NotFound: - state = power_state.SHUTOFF - - LOG.debug(_('Current state of %(name)s is %(state)s, state in ' - 'DB is %(db_state)s.'), {'name': instance['name'], - 'state': state, - 'db_state': - instance['state']}) - - if instance['state'] == power_state.RUNNING \ - and state != power_state.RUNNING \ - and FLAGS.start_guests_on_host_boot: - LOG.debug(_('Rebooting instance %(name)s after nova-compute ' - ' restart.'), {'name': instance['name']}) - self.reboot_instance(admin_context, instance['id']) - else: - self.db.instance_set_state(admin_context, instance['id'], - state) + context = nova.context.get_admin_context() + instances = self.db.instance_get_all_by_host(context, self.host) + for instance in instances: + inst_name = instance['name'] + db_state = instance['state'] + drv_state = self._update_state(context, instance['id']) + + expect_running = db_state == power_state.RUNNING != drv_state + + LOG.debug(_('Current state of %(inst_name)s is %(drv_state)s, ' + 'state in DB is %(db_state)s.'), locals()) + + if expect_running and FLAGS.start_guests_on_host_boot: + LOG.info(_('Rebooting instance %(inst_name)s after ' + 'nova-compute restart.'), locals()) + self.reboot_instance(context, instance['id']) def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" @@ -180,6 +173,7 @@ class ComputeManager(manager.SchedulerDependentManager): if state is None: try: + LOG.debug(_('Checking state of %s'), instance_ref['name']) info = self.driver.get_info(instance_ref['name']) except exception.NotFound: info = None -- cgit From 9c88bbee56dd05703af8f7c0df839a4da73f491a Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Mon, 25 Jul 2011 19:59:00 +0400 Subject: Hotfix. --- nova/compute/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 950fe0d53..79e9b16d3 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -184,6 +184,7 @@ class ComputeManager(manager.SchedulerDependentManager): state = power_state.FAILED self.db.instance_set_state(context, instance_id, state) + return state def _update_launched_at(self, context, instance_id, launched_at=None): """Update the launched_at parameter of the given instance.""" -- cgit From ba4946d0d3c73e5d9f67f42203d103bf98563458 Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Tue, 26 Jul 2011 00:31:42 +0400 Subject: Fixed old libvirt semantics, added resume_guests_state_on_host_boot flag. --- nova/compute/manager.py | 9 ++++----- nova/flags.py | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 79e9b16d3..bfac3df28 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -146,9 +146,7 @@ class ComputeManager(manager.SchedulerDependentManager): *args, **kwargs) def init_host(self): - """Initialization for a standalone compute service. - - Reboots instances marked as running in DB if they is not running.""" + """Initialization for a standalone compute service.""" self.driver.init_host(host=self.host) context = nova.context.get_admin_context() instances = self.db.instance_get_all_by_host(context, self.host) @@ -157,12 +155,13 @@ class ComputeManager(manager.SchedulerDependentManager): db_state = instance['state'] drv_state = self._update_state(context, instance['id']) - expect_running = db_state == power_state.RUNNING != drv_state + expect_running = (db_state == power_state.RUNNING != drv_state) LOG.debug(_('Current state of %(inst_name)s is %(drv_state)s, ' 'state in DB is %(db_state)s.'), locals()) - if expect_running and FLAGS.start_guests_on_host_boot: + if (expect_running and FLAGS.resume_guests_state_on_host_boot)\ + or FLAGS.start_guests_on_host_boot: LOG.info(_('Rebooting instance %(inst_name)s after ' 'nova-compute restart.'), locals()) self.reboot_instance(context, instance['id']) diff --git a/nova/flags.py b/nova/flags.py index 23ca38b17..6c7e448ad 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -390,3 +390,5 @@ DEFINE_string('build_plan_encryption_key', None, DEFINE_bool('start_guests_on_host_boot', False, 'Whether to restart guests when the host reboots') +DEFINE_bool('resume_guests_state_on_host_boot', False, + 'Whether to start guests, that was running before the host reboot') -- cgit From 879e49c67b78d3336a24cf1af12f21258c2225fa Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Tue, 26 Jul 2011 01:46:40 +0400 Subject: Estetic fix. --- nova/compute/manager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index bfac3df28..a6eb1efb2 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -155,7 +155,8 @@ class ComputeManager(manager.SchedulerDependentManager): db_state = instance['state'] drv_state = self._update_state(context, instance['id']) - expect_running = (db_state == power_state.RUNNING != drv_state) + expect_running = db_state == power_state.RUNNING \ + and drv_state != db_state LOG.debug(_('Current state of %(inst_name)s is %(drv_state)s, ' 'state in DB is %(db_state)s.'), locals()) -- cgit From d4842ac958bda3b446d14c7348692acc231e0041 Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Tue, 26 Jul 2011 02:30:20 +0400 Subject: Added ensuring filter rules for all VMs. --- nova/compute/manager.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index a6eb1efb2..53390098a 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -166,6 +166,11 @@ class ComputeManager(manager.SchedulerDependentManager): LOG.info(_('Rebooting instance %(inst_name)s after ' 'nova-compute restart.'), locals()) self.reboot_instance(context, instance['id']) + elif drv_state == power_state.RUNNING: + try: # Hyper-V and VMWareAPI drivers will raise and exception + self.driver.ensure_filtering_rules_for_instance(instance) + except NotImplementedError: + pass def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" -- cgit From 8f5a6d15e671c95c6e38147ca15fb49fd672e788 Mon Sep 17 00:00:00 2001 From: Nikolay Sokolov Date: Tue, 26 Jul 2011 02:33:39 +0400 Subject: Warn user instead of ignoring --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 53390098a..1f207e6f0 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -170,7 +170,7 @@ class ComputeManager(manager.SchedulerDependentManager): try: # Hyper-V and VMWareAPI drivers will raise and exception self.driver.ensure_filtering_rules_for_instance(instance) except NotImplementedError: - pass + LOG.warning(_('Hypervisor driver does not support firewall rules')) def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" -- cgit From 6fb2fe901bc4f4479e6a2bb087870927be7318a2 Mon Sep 17 00:00:00 2001 From: John Tran Date: Tue, 26 Jul 2011 10:03:16 -0700 Subject: added warning when size of subnet(s) being created are larger than FLAG.network_size in attempt to alleviate confusion. For example, currently when 'nova-manage network create foo 192.168.0.0/16', the result is that it creates a 192.168.0.0/24 instead without any indication to why. --- bin/nova-manage | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bin/nova-manage b/bin/nova-manage index b63bd326f..da9538e39 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -56,6 +56,7 @@ import gettext import glob import json +import math import netaddr import os import sys @@ -669,6 +670,14 @@ class NetworkCommands(object): num_networks = FLAGS.num_networks if not network_size: network_size = FLAGS.network_size + fixnet = netaddr.IPNetwork(fixed_range) + each_subnet_size = fixnet.size / int(num_networks) + if each_subnet_size > network_size: + subnet = 32 - int(math.log(network_size, 2)) + oversize_msg = _('Subnet(s) too large, defaulting to /%s.' + ' To override, specify network_size flag.' + % subnet) + print oversize_msg if not multi_host: multi_host = FLAGS.multi_host else: -- cgit From e239dc589982a0d90eb8a50967af05a10d5e4d5b Mon Sep 17 00:00:00 2001 From: John Tran Date: Tue, 26 Jul 2011 13:12:34 -0700 Subject: fixed per peer review --- bin/nova-manage | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/nova-manage b/bin/nova-manage index da9538e39..ca60d28d6 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -676,7 +676,7 @@ class NetworkCommands(object): subnet = 32 - int(math.log(network_size, 2)) oversize_msg = _('Subnet(s) too large, defaulting to /%s.' ' To override, specify network_size flag.' - % subnet) + ) % subnet print oversize_msg if not multi_host: multi_host = FLAGS.multi_host -- cgit From d5b76d89d7cfc2581e2de618d33331f9267126d4 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 27 Jul 2011 09:33:20 -0400 Subject: updating tests --- nova/tests/api/openstack/test_server_metadata.py | 55 ++++++++---------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py index 0431e68d2..12fc7665b 100644 --- a/nova/tests/api/openstack/test_server_metadata.py +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -94,8 +94,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_index(self): self.stubs.Set(nova.db.api, 'instance_metadata_get', return_server_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) @@ -104,16 +103,14 @@ class ServerMetaDataTest(unittest.TestCase): def test_index_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) - req = webob.Request.blank('/v1.1/servers/1/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata') res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) def test_index_no_data(self): self.stubs.Set(nova.db.api, 'instance_metadata_get', return_empty_server_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) @@ -123,8 +120,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_show(self): self.stubs.Set(nova.db.api, 'instance_metadata_get', return_server_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta/key5') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key5') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) @@ -133,32 +129,28 @@ class ServerMetaDataTest(unittest.TestCase): def test_show_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) - req = webob.Request.blank('/v1.1/servers/1/meta/key5') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key5') res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) def test_show_meta_not_found(self): self.stubs.Set(nova.db.api, 'instance_metadata_get', return_empty_server_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta/key6') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key6') res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) def test_delete(self): self.stubs.Set(nova.db.api, 'instance_metadata_delete', delete_server_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta/key5') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key5') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertEqual(200, res.status_int) def test_delete_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) - req = webob.Request.blank('/v1.1/servers/1/meta/key5') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key5') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) @@ -166,8 +158,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_create(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata') req.method = 'POST' req.body = '{"metadata": {"key1": "value1"}}' req.headers["content-type"] = "application/json" @@ -180,8 +171,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_create_empty_body(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata') req.method = 'POST' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) @@ -189,8 +179,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_create_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) - req = webob.Request.blank('/v1.1/servers/100/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/100/metadata') req.method = 'POST' req.body = '{"metadata": {"key1": "value1"}}' req.headers["content-type"] = "application/json" @@ -200,8 +189,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_update_item(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key1') req.method = 'PUT' req.body = '{"key1": "value1"}' req.headers["content-type"] = "application/json" @@ -213,8 +201,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_update_item_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) - req = webob.Request.blank('/v1.1/servers/asdf/100/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/asdf/metadata/key1') req.method = 'PUT' req.body = '{"key1": "value1"}' req.headers["content-type"] = "application/json" @@ -224,9 +211,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_update_item_empty_body(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta/key1') - req.environ['api.version'] = '1.1' - req.method = 'PUT' + req = webob.Request.blank('/v1.1/servers/1/metadata/key1') req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) @@ -234,8 +219,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_update_item_too_many_keys(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key1') req.method = 'PUT' req.body = '{"key1": "value1", "key2": "value2"}' req.headers["content-type"] = "application/json" @@ -245,8 +229,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_update_item_body_uri_mismatch(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) - req = webob.Request.blank('/v1.1/servers/1/meta/bad') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/bad') req.method = 'PUT' req.body = '{"key1": "value1"}' req.headers["content-type"] = "application/json" @@ -260,8 +243,7 @@ class ServerMetaDataTest(unittest.TestCase): for num in range(FLAGS.quota_metadata_items + 1): data['metadata']['key%i' % num] = "blah" json_string = str(data).replace("\'", "\"") - req = webob.Request.blank('/v1.1/servers/1/meta') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata') req.method = 'POST' req.body = json_string req.headers["content-type"] = "application/json" @@ -271,8 +253,7 @@ class ServerMetaDataTest(unittest.TestCase): def test_to_many_metadata_items_on_update_item(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata_max) - req = webob.Request.blank('/v1.1/servers/1/meta/key1') - req.environ['api.version'] = '1.1' + req = webob.Request.blank('/v1.1/servers/1/metadata/key1') req.method = 'PUT' req.body = '{"a new key": "a new value"}' req.headers["content-type"] = "application/json" -- cgit From 0760948609ac89a43a590b36e79d691a6c79b4c3 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 27 Jul 2011 11:32:18 -0400 Subject: updating servers metadata resource --- nova/api/openstack/__init__.py | 11 +- nova/api/openstack/common.py | 4 +- nova/api/openstack/server_metadata.py | 113 ++++++++---- nova/tests/api/openstack/test_server_metadata.py | 220 ++++++++++++++++++++--- 4 files changed, 279 insertions(+), 69 deletions(-) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 1d14474a8..6585f1751 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -164,7 +164,9 @@ class APIRouterV11(APIRouter): def _setup_routes(self, mapper): super(APIRouterV11, self)._setup_routes(mapper, '1.1') + image_metadata_controller = image_metadata.create_resource() + mapper.resource("image_meta", "metadata", controller=image_metadata_controller, parent_resource=dict(member_name='image', @@ -175,7 +177,14 @@ class APIRouterV11(APIRouter): action='update_all', conditions={"method": ['PUT']}) + server_metadata_controller = server_metadata.create_resource() + mapper.resource("server_meta", "metadata", - controller=server_metadata.create_resource(), + controller=server_metadata_controller, parent_resource=dict(member_name='server', collection_name='servers')) + + mapper.connect("metadata", "/servers/{server_id}/metadata", + controller=server_metadata_controller, + action='update_all', + conditions={"method": ['PUT']}) diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index efa4ab385..24c82035a 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -247,7 +247,7 @@ class MetadataXMLSerializer(wsgi.XMLDictSerializer): container_node = self.meta_list_to_xml(xml_doc, items) xml_doc.appendChild(container_node) self._add_xmlns(container_node) - return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') + return xml_doc.toxml('UTF-8') def index(self, metadata_dict): return self._meta_list_to_xml_string(metadata_dict) @@ -264,7 +264,7 @@ class MetadataXMLSerializer(wsgi.XMLDictSerializer): item_node = self._meta_item_to_xml(xml_doc, item_key, item_value) xml_doc.appendChild(item_node) self._add_xmlns(item_node) - return xml_doc.toprettyxml(indent=' ', encoding='UTF-8') + return xml_doc.toxml('UTF-8') def show(self, meta_item_dict): return self._meta_item_to_xml_string(meta_item_dict['meta']) diff --git a/nova/api/openstack/server_metadata.py b/nova/api/openstack/server_metadata.py index d4f42bbf5..d8f9cdbac 100644 --- a/nova/api/openstack/server_metadata.py +++ b/nova/api/openstack/server_metadata.py @@ -18,6 +18,7 @@ from webob import exc from nova import compute +from nova.api.openstack import common from nova.api.openstack import wsgi from nova import exception from nova import quota @@ -31,36 +32,37 @@ class Controller(object): super(Controller, self).__init__() def _get_metadata(self, context, server_id): - metadata = self.compute_api.get_instance_metadata(context, server_id) + try: + meta = self.compute_api.get_instance_metadata(context, server_id) + except exception.InstanceNotFound: + msg = _('Server does not exist') + raise exc.HTTPNotFound(explanation=msg) + meta_dict = {} - for key, value in metadata.iteritems(): + for key, value in meta.iteritems(): meta_dict[key] = value - return dict(metadata=meta_dict) - - def _check_body(self, body): - if body == None or body == "": - expl = _('No Request Body') - raise exc.HTTPBadRequest(explanation=expl) + return meta_dict def index(self, req, server_id): """ Returns the list of metadata for a given instance """ context = req.environ['nova.context'] - try: - return self._get_metadata(context, server_id) - except exception.InstanceNotFound: - msg = _('Server %(server_id)s does not exist') % locals() - raise exc.HTTPNotFound(explanation=msg) + return {'metadata': self._get_metadata(context, server_id)} def create(self, req, server_id, body): - self._check_body(body) + try: + metadata = body['metadata'] + except (KeyError, TypeError): + msg = _("Malformed request body") + raise exc.HTTPBadRequest(esplanation=msg) + context = req.environ['nova.context'] - metadata = body.get('metadata') + try: self.compute_api.update_or_create_instance_metadata(context, server_id, metadata) except exception.InstanceNotFound: - msg = _('Server %(server_id)s does not exist') % locals() + msg = _('Server does not exist') raise exc.HTTPNotFound(explanation=msg) except quota.QuotaError as error: @@ -69,51 +71,80 @@ class Controller(object): return body def update(self, req, server_id, id, body): - self._check_body(body) - context = req.environ['nova.context'] - if not id in body: + try: + meta_item = body['meta'] + except (TypeError, KeyError): + expl = _('Malformed request body') + raise exc.HTTPBadRequest(explanation=expl) + + try: + meta_value = meta_item.pop(id) + except (AttributeError, KeyError): expl = _('Request body and URI mismatch') raise exc.HTTPBadRequest(explanation=expl) - if len(body) > 1: + + if len(meta_item) > 0: expl = _('Request body contains too many items') raise exc.HTTPBadRequest(explanation=expl) + + context = req.environ['nova.context'] + self._set_instance_metadata(context, server_id, meta_item) + + return {'meta': {id: meta_value}} + + def update_all(self, req, server_id, body): + try: + metadata = body['metadata'] + except (TypeError, KeyError): + expl = _('Malformed request body') + raise exc.HTTPBadRequest(explanation=expl) + + context = req.environ['nova.context'] + self._set_instance_metadata(context, server_id, metadata) + + return {'metadata': metadata} + + def _set_instance_metadata(self, context, server_id, metadata): try: self.compute_api.update_or_create_instance_metadata(context, server_id, - body) + metadata) except exception.InstanceNotFound: - msg = _('Server %(server_id)s does not exist') % locals() + msg = _('Server does not exist') raise exc.HTTPNotFound(explanation=msg) + except ValueError: + msg = _("Malformed request body") + raise exc.HTTPBadRequest(explanation=msg) + except quota.QuotaError as error: self._handle_quota_error(error) - return body - def show(self, req, server_id, id): """ Return a single metadata item """ context = req.environ['nova.context'] - try: - data = self._get_metadata(context, server_id) - except exception.InstanceNotFound: - msg = _('Server %(server_id)s does not exist') % locals() - raise exc.HTTPNotFound(explanation=msg) + data = self._get_metadata(context, server_id) try: - return {id: data['metadata'][id]} + return {'meta': {id: data[id]}} except KeyError: - msg = _("metadata item %s was not found" % (id)) + msg = _("Metadata item was not found") raise exc.HTTPNotFound(explanation=msg) def delete(self, req, server_id, id): """ Deletes an existing metadata """ context = req.environ['nova.context'] + + metadata = self._get_metadata(context, server_id) + try: - self.compute_api.delete_instance_metadata(context, server_id, id) - except exception.InstanceNotFound: - msg = _('Server %(server_id)s does not exist') % locals() + meta_key = metadata[id] + except KeyError: + msg = _("Metadata item was not found") raise exc.HTTPNotFound(explanation=msg) + self.compute_api.delete_instance_metadata(context, server_id, meta_key) + def _handle_quota_error(self, error): """Reraise quota errors as api-specific http exceptions.""" if error.code == "MetadataLimitExceeded": @@ -122,10 +153,16 @@ class Controller(object): def create_resource(): - body_serializers = { - 'application/xml': wsgi.XMLDictSerializer(xmlns=wsgi.XMLNS_V11), + headers_serializer = common.MetadataHeadersSerializer() + + body_deserializers = { + 'application/xml': common.MetadataXMLDeserializer(), } - serializer = wsgi.ResponseSerializer(body_serializers) + body_serializers = { + 'application/xml': common.MetadataXMLSerializer(), + } + serializer = wsgi.ResponseSerializer(body_serializers, headers_serializer) + deserializer = wsgi.RequestDeserializer(body_deserializers) - return wsgi.Resource(Controller(), serializer=serializer) + return wsgi.Resource(Controller(), deserializer, serializer) diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py index 12fc7665b..ded30a950 100644 --- a/nova/tests/api/openstack/test_server_metadata.py +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -19,7 +19,7 @@ import json import stubout import unittest import webob - +from xml.dom import minidom from nova import exception from nova import flags @@ -53,11 +53,10 @@ def delete_server_metadata(context, server_id, key): def stub_server_metadata(): metadata = { - "key1": "value1", - "key2": "value2", - "key3": "value3", - "key4": "value4", - "key5": "value5"} + "key1": "value1", + "key2": "value2", + "key3": "value3", + } return metadata @@ -96,10 +95,38 @@ class ServerMetaDataTest(unittest.TestCase): return_server_metadata) req = webob.Request.blank('/v1.1/servers/1/metadata') res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) + res_dict = json.loads(res.body) self.assertEqual('application/json', res.headers['Content-Type']) - self.assertEqual('value1', res_dict['metadata']['key1']) + expected = { + 'metadata': { + 'key1':'value1', + 'key2':'value2', + 'key3':'value3', + }, + } + self.assertEqual(expected, res_dict) + + def test_index_xml(self): + self.stubs.Set(nova.db.api, 'instance_metadata_get', + return_server_metadata) + request = webob.Request.blank("/v1.1/servers/1/metadata") + request.accept = "application/xml" + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(200, response.status_int) + self.assertEqual("application/xml", response.content_type) + + actual_metadata = minidom.parseString(response.body.replace(" ", "")) + + expected_metadata = minidom.parseString(""" + + value3 + value2 + value1 + + """.replace(" ", "").replace("\n","")) + + self.assertEqual(expected_metadata.toxml(), actual_metadata.toxml()) def test_index_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) @@ -112,24 +139,42 @@ class ServerMetaDataTest(unittest.TestCase): return_empty_server_metadata) req = webob.Request.blank('/v1.1/servers/1/metadata') res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) - self.assertEqual('application/json', res.headers['Content-Type']) - self.assertEqual(0, len(res_dict['metadata'])) + res_dict = json.loads(res.body) + expected = {'metadata': {}} + self.assertEqual(expected, res_dict) def test_show(self): self.stubs.Set(nova.db.api, 'instance_metadata_get', return_server_metadata) - req = webob.Request.blank('/v1.1/servers/1/metadata/key5') + req = webob.Request.blank('/v1.1/servers/1/metadata/key2') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(200, res.status_int) - self.assertEqual('application/json', res.headers['Content-Type']) - self.assertEqual('value5', res_dict['key5']) + expected = {'meta': {'key2': 'value2'}} + self.assertEqual(expected, res_dict) + + def test_show_xml(self): + self.stubs.Set(nova.db.api, 'instance_metadata_get', + return_server_metadata) + request = webob.Request.blank("/v1.1/servers/1/metadata/key2") + request.accept = "application/xml" + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(200, response.status_int) + self.assertEqual("application/xml", response.content_type) + + actual_metadata = minidom.parseString(response.body.replace(" ", "")) + + expected_metadata = minidom.parseString(""" + value2 + """.replace(" ", "").replace("\n","")) + + self.assertEqual(expected_metadata.toxml(), actual_metadata.toxml()) def test_show_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) - req = webob.Request.blank('/v1.1/servers/1/metadata/key5') + req = webob.Request.blank('/v1.1/servers/1/metadata/key2') res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) @@ -141,16 +186,27 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual(404, res.status_int) def test_delete(self): + self.stubs.Set(nova.db.api, 'instance_metadata_get', + return_server_metadata) self.stubs.Set(nova.db.api, 'instance_metadata_delete', delete_server_metadata) - req = webob.Request.blank('/v1.1/servers/1/metadata/key5') + req = webob.Request.blank('/v1.1/servers/1/metadata/key2') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) - self.assertEqual(200, res.status_int) + self.assertEqual(204, res.status_int) + self.assertEqual('', res.body) def test_delete_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) - req = webob.Request.blank('/v1.1/servers/1/metadata/key5') + req = webob.Request.blank('/v1.1/servers/1/metadata/key1') + req.method = 'DELETE' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(404, res.status_int) + + def test_delete_meta_not_found(self): + self.stubs.Set(nova.db.api, 'instance_metadata_get', + return_empty_server_metadata) + req = webob.Request.blank('/v1.1/servers/1/metadata/key6') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) @@ -160,13 +216,38 @@ class ServerMetaDataTest(unittest.TestCase): return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/metadata') req.method = 'POST' - req.body = '{"metadata": {"key1": "value1"}}' - req.headers["content-type"] = "application/json" + req.content_type = "application/json" + expected = {"metadata": {"key1": "value1"}} + req.body = json.dumps(expected) res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) res_dict = json.loads(res.body) - self.assertEqual('application/json', res.headers['Content-Type']) - self.assertEqual('value1', res_dict['metadata']['key1']) + self.assertEqual(expected, res_dict) + + def test_create_xml(self): + self.stubs.Set(nova.db.api, "instance_metadata_update_or_create", + return_create_instance_metadata) + req = webob.Request.blank("/v1.1/servers/1/metadata") + req.method = "POST" + req.content_type = "application/xml" + req.accept = "application/xml" + + request_metadata = minidom.parseString(""" + + value3 + value2 + value1 + + """.replace(" ","").replace("\n","")) + + req.body = str(request_metadata.toxml()) + response = req.get_response(fakes.wsgi_app()) + + self.assertEqual(200, response.status_int) + actual_metadata = minidom.parseString(response.body) + + self.assertEqual(request_metadata.toxml(), actual_metadata.toxml()) def test_create_empty_body(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', @@ -186,24 +267,105 @@ class ServerMetaDataTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) + def test_update_all(self): + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/metadata') + req.method = 'PUT' + req.content_type = "application/json" + expected = { + 'metadata': { + 'key10': 'value10', + 'key99': 'value99', + }, + } + req.body = json.dumps(expected) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) + res_dict = json.loads(res.body) + self.assertEqual(expected, res_dict) + + def test_update_all_empty_container(self): + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/metadata') + req.method = 'PUT' + req.content_type = "application/json" + expected = {'metadata': {}} + req.body = json.dumps(expected) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) + res_dict = json.loads(res.body) + self.assertEqual(expected, res_dict) + + def test_update_all_malformed_container(self): + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/metadata') + req.method = 'PUT' + req.content_type = "application/json" + expected = {'meta': {}} + req.body = json.dumps(expected) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, res.status_int) + + def test_update_all_malformed_data(self): + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/metadata') + req.method = 'PUT' + req.content_type = "application/json" + expected = {'metadata': ['asdf']} + req.body = json.dumps(expected) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, res.status_int) + + def test_update_all_nonexistant_server(self): + self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) + req = webob.Request.blank('/v1.1/servers/100/metadata') + req.method = 'PUT' + req.content_type = "application/json" + req.body = json.dumps({'metadata': {'key10': 'value10'}}) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(404, res.status_int) + def test_update_item(self): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/metadata/key1') req.method = 'PUT' - req.body = '{"key1": "value1"}' + req.body = '{"meta": {"key1": "value1"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(200, res.status_int) self.assertEqual('application/json', res.headers['Content-Type']) res_dict = json.loads(res.body) - self.assertEqual('value1', res_dict['key1']) + expected = {'meta': {'key1': 'value1'}} + self.assertEqual(expected, res_dict) + + def test_update_item_xml(self): + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/metadata/key9') + req.method = 'PUT' + req.accept = "application/json" + req.content_type = "application/xml" + req.body = """ + value9 + """ + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) + self.assertEqual('application/json', res.headers['Content-Type']) + res_dict = json.loads(res.body) + expected = {'meta': {'key9': 'value9'}} + self.assertEqual(expected, res_dict) def test_update_item_nonexistant_server(self): self.stubs.Set(nova.db.api, 'instance_get', return_server_nonexistant) req = webob.Request.blank('/v1.1/servers/asdf/metadata/key1') req.method = 'PUT' - req.body = '{"key1": "value1"}' + req.body = '{"meta":{"key1": "value1"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(404, res.status_int) @@ -212,6 +374,7 @@ class ServerMetaDataTest(unittest.TestCase): self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/metadata/key1') + req.method = 'PUT' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) @@ -221,7 +384,7 @@ class ServerMetaDataTest(unittest.TestCase): return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/metadata/key1') req.method = 'PUT' - req.body = '{"key1": "value1", "key2": "value2"}' + req.body = '{"meta": {"key1": "value1", "key2": "value2"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) @@ -231,7 +394,7 @@ class ServerMetaDataTest(unittest.TestCase): return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/metadata/bad') req.method = 'PUT' - req.body = '{"key1": "value1"}' + req.body = '{"meta": {"key1": "value1"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) @@ -255,7 +418,8 @@ class ServerMetaDataTest(unittest.TestCase): return_create_instance_metadata_max) req = webob.Request.blank('/v1.1/servers/1/metadata/key1') req.method = 'PUT' - req.body = '{"a new key": "a new value"}' + req.body = '{"meta": {"a new key": "a new value"}}' req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) + -- cgit From 4add644dbd1650a3e83e715c6d6a38c4114e4d06 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Wed, 27 Jul 2011 11:39:34 -0400 Subject: Moved server/actions tests to test_server_actions.py --- nova/tests/api/openstack/test_server_actions.py | 628 ++++++++++++++++++++++++ nova/tests/api/openstack/test_servers.py | 492 ------------------- 2 files changed, 628 insertions(+), 492 deletions(-) create mode 100644 nova/tests/api/openstack/test_server_actions.py diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py new file mode 100644 index 000000000..97c108068 --- /dev/null +++ b/nova/tests/api/openstack/test_server_actions.py @@ -0,0 +1,628 @@ +import base64 +import json +import unittest +from xml.dom import minidom + +import stubout +import webob + +from nova import context +from nova import db +from nova import utils +from nova.api.openstack import create_instance_helper +from nova.compute import instance_types +from nova.compute import power_state +import nova.db.api +from nova import test +from nova.tests.api.openstack import common +from nova.tests.api.openstack import fakes + + +def return_server_by_id(context, id): + return _get_instance() + + +def instance_update(context, instance_id, kwargs): + return _get_instance() + + +def return_server_with_power_state(power_state): + def _return_server(context, id): + instance = _get_instance() + instance['state'] = power_state + return instance + return _return_server + + +def return_server_with_uuid_and_power_state(power_state): + def _return_server(context, id): + return return_server_with_power_state(power_state) + return _return_server + + +class MockSetAdminPassword(object): + def __init__(self): + self.instance_id = None + self.password = None + + def __call__(self, context, instance_id, password): + self.instance_id = instance_id + self.password = password + + +def _get_instance(): + instance = { + "id": 1, + "created_at": "2010-10-10T12:00:00Z", + "updated_at": "2010-11-11T11:00:00Z", + "admin_pass": "", + "user_id": "", + "project_id": "", + "image_ref": "5", + "kernel_id": "", + "ramdisk_id": "", + "launch_index": 0, + "key_name": "", + "key_data": "", + "state": 0, + "state_description": "", + "memory_mb": 0, + "vcpus": 0, + "local_gb": 0, + "hostname": "", + "host": "", + "instance_type": { + "flavorid": 1, + }, + "user_data": "", + "reservation_id": "", + "mac_address": "", + "scheduled_at": utils.utcnow(), + "launched_at": utils.utcnow(), + "terminated_at": utils.utcnow(), + "availability_zone": "", + "display_name": "test_server", + "display_description": "", + "locked": False, + "metadata": [], + #"address": , + #"floating_ips": [{"address":ip} for ip in public_addresses]} + "uuid": "deadbeef-feed-edee-beef-d0ea7beefedd"} + + return instance + + +class ServerActionsTest(test.TestCase): + + def setUp(self): + self.maxDiff = None + super(ServerActionsTest, self).setUp() + self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.reset_fake_data() + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_auth(self.stubs) + self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id) + self.stubs.Set(nova.db.api, 'instance_update', instance_update) + + self.webreq = common.webob_factory('/v1.0/servers') + + def tearDown(self): + self.stubs.UnsetAll() + + def test_server_actions(self): + req = webob.Request.blank("/v1.0/servers/1/actions") + req.method = "GET" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 404) + + def test_server_change_password(self): + body = {'changePassword': {'adminPass': '1234pass'}} + req = webob.Request.blank('/v1.0/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 501) + + def test_server_change_password_xml(self): + req = webob.Request.blank('/v1.0/servers/1/action') + req.method = 'POST' + req.content_type = 'application/xml' + req.body = '' +# res = req.get_response(fakes.wsgi_app()) +# self.assertEqual(res.status_int, 501) + + def test_server_change_password_not_a_string_v1_1(self): + body = {'changePassword': {'adminPass': 1234}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_reboot(self): + body = dict(server=dict( + name='server_test', imageId=2, flavorId=2, metadata={}, + personality={})) + req = webob.Request.blank('/v1.0/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + + def test_server_rebuild_accepted(self): + body = { + "rebuild": { + "imageId": 2, + }, + } + + req = webob.Request.blank('/v1.0/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertEqual(res.body, "") + + def test_server_rebuild_rejected_when_building(self): + body = { + "rebuild": { + "imageId": 2, + }, + } + + state = power_state.BUILDING + new_return_server = return_server_with_power_state(state) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + self.stubs.Set(nova.db, 'instance_get_by_uuid', + return_server_with_uuid_and_power_state(state)) + + req = webob.Request.blank('/v1.0/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 409) + + def test_server_rebuild_bad_entity(self): + body = { + "rebuild": { + }, + } + + req = webob.Request.blank('/v1.0/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_resize_server(self): + req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) + + self.resize_called = False + + def resize_mock(*args): + self.resize_called = True + + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + + def test_resize_bad_flavor_fails(self): + req = self.webreq('/1/action', 'POST', dict(resize=dict(derp=3))) + + self.resize_called = False + + def resize_mock(*args): + self.resize_called = True + + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 422) + self.assertEqual(self.resize_called, False) + + def test_resize_raises_fails(self): + req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) + + def resize_mock(*args): + raise Exception('hurr durr') + + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 500) + + def test_resized_server_has_correct_status(self): + req = self.webreq('/1', 'GET') + + def fake_migration_get(*args): + return {} + + self.stubs.Set(nova.db, 'migration_get_by_instance_and_status', + fake_migration_get) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + body = json.loads(res.body) + self.assertEqual(body['server']['status'], 'RESIZE-CONFIRM') + + def test_confirm_resize_server(self): + req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) + + self.resize_called = False + + def confirm_resize_mock(*args): + self.resize_called = True + + self.stubs.Set(nova.compute.api.API, 'confirm_resize', + confirm_resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 204) + self.assertEqual(self.resize_called, True) + + def test_confirm_resize_server_fails(self): + req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) + + def confirm_resize_mock(*args): + raise Exception('hurr durr') + + self.stubs.Set(nova.compute.api.API, 'confirm_resize', + confirm_resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_revert_resize_server(self): + req = self.webreq('/1/action', 'POST', dict(revertResize=None)) + + self.resize_called = False + + def revert_resize_mock(*args): + self.resize_called = True + + self.stubs.Set(nova.compute.api.API, 'revert_resize', + revert_resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + + def test_revert_resize_server_fails(self): + req = self.webreq('/1/action', 'POST', dict(revertResize=None)) + + def revert_resize_mock(*args): + raise Exception('hurr durr') + + self.stubs.Set(nova.compute.api.API, 'revert_resize', + revert_resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_migrate_server(self): + """This is basically the same as resize, only we provide the `migrate` + attribute in the body's dict. + """ + req = self.webreq('/1/action', 'POST', dict(migrate=None)) + + self.resize_called = False + + def resize_mock(*args): + self.resize_called = True + + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + + +class ServerActionsTestV11(test.TestCase): + + def setUp(self): + self.maxDiff = None + super(ServerActionsTestV11, self).setUp() + self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.reset_fake_data() + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_auth(self.stubs) + self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id) + self.stubs.Set(nova.db.api, 'instance_update', instance_update) + + fakes.stub_out_glance(self.stubs) + fakes.stub_out_compute_api_snapshot(self.stubs) + service_class = 'nova.image.glance.GlanceImageService' + self.service = utils.import_object(service_class) + self.context = context.RequestContext(1, None) + self.service.delete_all() + self.sent_to_glance = {} + fakes.stub_out_glance_add_image(self.stubs, self.sent_to_glance) + + def tearDown(self): + self.stubs.UnsetAll() + + def test_server_change_password_v1_1(self): + mock_method = MockSetAdminPassword() + self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method) + body = {'changePassword': {'adminPass': '1234pass'}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertEqual(mock_method.instance_id, '1') + self.assertEqual(mock_method.password, '1234pass') + + def test_server_change_password_bad_request_v1_1(self): + body = {'changePassword': {'pass': '12345'}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_change_password_empty_string_v1_1(self): + body = {'changePassword': {'adminPass': ''}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_change_password_none_v1_1(self): + body = {'changePassword': {'adminPass': None}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_rebuild_accepted_minimum_v1_1(self): + body = { + "rebuild": { + "imageRef": "http://localhost/images/2", + }, + } + + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + + def test_server_rebuild_rejected_when_building_v1_1(self): + body = { + "rebuild": { + "imageRef": "http://localhost/images/2", + }, + } + + state = power_state.BUILDING + new_return_server = return_server_with_power_state(state) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + self.stubs.Set(nova.db, 'instance_get_by_uuid', + return_server_with_uuid_and_power_state(state)) + + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 409) + + def test_server_rebuild_accepted_with_metadata_v1_1(self): + body = { + "rebuild": { + "imageRef": "http://localhost/images/2", + "metadata": { + "new": "metadata", + }, + }, + } + + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + + def test_server_rebuild_accepted_with_bad_metadata_v1_1(self): + body = { + "rebuild": { + "imageRef": "http://localhost/images/2", + "metadata": "stack", + }, + } + + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_rebuild_bad_entity_v1_1(self): + body = { + "rebuild": { + "imageId": 2, + }, + } + + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_rebuild_bad_personality_v1_1(self): + body = { + "rebuild": { + "imageRef": "http://localhost/images/2", + "personality": [{ + "path": "/path/to/file", + "contents": "INVALID b64", + }] + }, + } + + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_rebuild_personality_v1_1(self): + body = { + "rebuild": { + "imageRef": "http://localhost/images/2", + "personality": [{ + "path": "/path/to/file", + "contents": base64.b64encode("Test String"), + }] + }, + } + + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + + def test_resize_server_v11(self): + + req = webob.Request.blank('/v1.1/servers/1/action') + req.content_type = 'application/json' + req.method = 'POST' + body_dict = dict(resize=dict(flavorRef="http://localhost/3")) + req.body = json.dumps(body_dict) + + self.resize_called = False + + def resize_mock(*args): + self.resize_called = True + + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + + def test_create_image_v1_1(self): + body = { + 'createImage': { + 'name': 'Snapshot 1', + }, + } + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + response = req.get_response(fakes.wsgi_app()) + self.assertEqual(202, response.status_int) + location = response.headers['Location'] + self.assertEqual('http://localhost/v1.1/images/123', location) + + def test_create_image_v1_1_with_metadata(self): + body = { + 'createImage': { + 'name': 'Snapshot 1', + 'metadata': {'key': 'asdf'}, + }, + } + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + response = req.get_response(fakes.wsgi_app()) + self.assertEqual(202, response.status_int) + location = response.headers['Location'] + self.assertEqual('http://localhost/v1.1/images/123', location) + + def test_create_image_v1_1_no_name(self): + body = { + 'createImage': {}, + } + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + response = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, response.status_int) + + def test_create_image_v1_1_bad_metadata(self): + body = { + 'createImage': { + 'name': 'geoff', + 'metadata': 'henry', + }, + } + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + response = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, response.status_int) + + +class TestServerActionXMLDeserializer(test.TestCase): + + def setUp(self): + self.deserializer = create_instance_helper.ServerXMLDeserializer() + + def tearDown(self): + pass + + def test_create_image(self): + serial_request = """ +""" + request = self.deserializer.deserialize(serial_request, 'action') + expected = { + "createImage": { + "name": "new-server-test", + "metadata": {}, + }, + } + self.assertEquals(request['body'], expected) + + def test_create_image_with_metadata(self): + serial_request = """ + + + value1 + +""" + request = self.deserializer.deserialize(serial_request, 'action') + expected = { + "createImage": { + "name": "new-server-test", + "metadata": {"key1": "value1"}, + }, + } + self.assertEquals(request['body'], expected) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 9d2c7b73f..b68183429 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -1766,262 +1766,6 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 404) - def test_server_actions(self): - req = webob.Request.blank("/v1.0/servers/1/actions") - req.method = "GET" - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 404) - - def test_server_change_password(self): - body = {'changePassword': {'adminPass': '1234pass'}} - req = webob.Request.blank('/v1.0/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 501) - - def test_server_change_password_xml(self): - req = webob.Request.blank('/v1.0/servers/1/action') - req.method = 'POST' - req.content_type = 'application/xml' - req.body = '' -# res = req.get_response(fakes.wsgi_app()) -# self.assertEqual(res.status_int, 501) - - def test_server_change_password_v1_1(self): - mock_method = MockSetAdminPassword() - self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method) - body = {'changePassword': {'adminPass': '1234pass'}} - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - self.assertEqual(mock_method.instance_id, '1') - self.assertEqual(mock_method.password, '1234pass') - - def test_server_change_password_bad_request_v1_1(self): - body = {'changePassword': {'pass': '12345'}} - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_change_password_empty_string_v1_1(self): - body = {'changePassword': {'adminPass': ''}} - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_change_password_none_v1_1(self): - body = {'changePassword': {'adminPass': None}} - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_change_password_not_a_string_v1_1(self): - body = {'changePassword': {'adminPass': 1234}} - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_reboot(self): - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) - req = webob.Request.blank('/v1.0/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - - def test_server_rebuild_accepted(self): - body = { - "rebuild": { - "imageId": 2, - }, - } - - req = webob.Request.blank('/v1.0/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - self.assertEqual(res.body, "") - - def test_server_rebuild_rejected_when_building(self): - body = { - "rebuild": { - "imageId": 2, - }, - } - - state = power_state.BUILDING - new_return_server = return_server_with_power_state(state) - self.stubs.Set(nova.db.api, 'instance_get', new_return_server) - self.stubs.Set(nova.db, 'instance_get_by_uuid', - return_server_with_uuid_and_power_state(state)) - - req = webob.Request.blank('/v1.0/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 409) - - def test_server_rebuild_bad_entity(self): - body = { - "rebuild": { - }, - } - - req = webob.Request.blank('/v1.0/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_rebuild_accepted_minimum_v1_1(self): - body = { - "rebuild": { - "imageRef": "http://localhost/images/2", - }, - } - - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - - def test_server_rebuild_rejected_when_building_v1_1(self): - body = { - "rebuild": { - "imageRef": "http://localhost/images/2", - }, - } - - state = power_state.BUILDING - new_return_server = return_server_with_power_state(state) - self.stubs.Set(nova.db.api, 'instance_get', new_return_server) - self.stubs.Set(nova.db, 'instance_get_by_uuid', - return_server_with_uuid_and_power_state(state)) - - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 409) - - def test_server_rebuild_accepted_with_metadata_v1_1(self): - body = { - "rebuild": { - "imageRef": "http://localhost/images/2", - "metadata": { - "new": "metadata", - }, - }, - } - - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - - def test_server_rebuild_accepted_with_bad_metadata_v1_1(self): - body = { - "rebuild": { - "imageRef": "http://localhost/images/2", - "metadata": "stack", - }, - } - - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_rebuild_bad_entity_v1_1(self): - body = { - "rebuild": { - "imageId": 2, - }, - } - - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_rebuild_bad_personality_v1_1(self): - body = { - "rebuild": { - "imageRef": "http://localhost/images/2", - "personality": [{ - "path": "/path/to/file", - "contents": "INVALID b64", - }] - }, - } - - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_server_rebuild_personality_v1_1(self): - body = { - "rebuild": { - "imageRef": "http://localhost/images/2", - "personality": [{ - "path": "/path/to/file", - "contents": base64.b64encode("Test String"), - }] - }, - } - - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - def test_delete_server_instance(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'DELETE' @@ -2089,147 +1833,6 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 204) self.assertEqual(self.server_delete_called, True) - def test_resize_server(self): - req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) - - self.resize_called = False - - def resize_mock(*args): - self.resize_called = True - - self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - self.assertEqual(self.resize_called, True) - - def test_resize_server_v11(self): - - req = webob.Request.blank('/v1.1/servers/1/action') - req.content_type = 'application/json' - req.method = 'POST' - body_dict = dict(resize=dict(flavorRef="http://localhost/3")) - req.body = json.dumps(body_dict) - - self.resize_called = False - - def resize_mock(*args): - self.resize_called = True - - self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - self.assertEqual(self.resize_called, True) - - def test_resize_bad_flavor_fails(self): - req = self.webreq('/1/action', 'POST', dict(resize=dict(derp=3))) - - self.resize_called = False - - def resize_mock(*args): - self.resize_called = True - - self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 422) - self.assertEqual(self.resize_called, False) - - def test_resize_raises_fails(self): - req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) - - def resize_mock(*args): - raise Exception('hurr durr') - - self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 500) - - def test_resized_server_has_correct_status(self): - req = self.webreq('/1', 'GET') - - def fake_migration_get(*args): - return {} - - self.stubs.Set(nova.db, 'migration_get_by_instance_and_status', - fake_migration_get) - res = req.get_response(fakes.wsgi_app()) - body = json.loads(res.body) - self.assertEqual(body['server']['status'], 'RESIZE-CONFIRM') - - def test_confirm_resize_server(self): - req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) - - self.resize_called = False - - def confirm_resize_mock(*args): - self.resize_called = True - - self.stubs.Set(nova.compute.api.API, 'confirm_resize', - confirm_resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 204) - self.assertEqual(self.resize_called, True) - - def test_confirm_resize_server_fails(self): - req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) - - def confirm_resize_mock(*args): - raise Exception('hurr durr') - - self.stubs.Set(nova.compute.api.API, 'confirm_resize', - confirm_resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_revert_resize_server(self): - req = self.webreq('/1/action', 'POST', dict(revertResize=None)) - - self.resize_called = False - - def revert_resize_mock(*args): - self.resize_called = True - - self.stubs.Set(nova.compute.api.API, 'revert_resize', - revert_resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - self.assertEqual(self.resize_called, True) - - def test_revert_resize_server_fails(self): - req = self.webreq('/1/action', 'POST', dict(revertResize=None)) - - def revert_resize_mock(*args): - raise Exception('hurr durr') - - self.stubs.Set(nova.compute.api.API, 'revert_resize', - revert_resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - - def test_migrate_server(self): - """This is basically the same as resize, only we provide the `migrate` - attribute in the body's dict. - """ - req = self.webreq('/1/action', 'POST', dict(migrate=None)) - - self.resize_called = False - - def resize_mock(*args): - self.resize_called = True - - self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) - - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 202) - self.assertEqual(self.resize_called, True) - def test_shutdown_status(self): new_server = return_server_with_power_state(power_state.SHUTDOWN) self.stubs.Set(nova.db.api, 'instance_get', new_server) @@ -2248,101 +1851,6 @@ class ServersTest(test.TestCase): res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['status'], 'SHUTOFF') - def test_create_image_v1_1(self): - body = { - 'createImage': { - 'name': 'Snapshot 1', - }, - } - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.body = json.dumps(body) - req.headers["content-type"] = "application/json" - response = req.get_response(fakes.wsgi_app()) - self.assertEqual(202, response.status_int) - location = response.headers['Location'] - self.assertEqual('http://localhost/v1.1/images/123', location) - - def test_create_image_v1_1_with_metadata(self): - body = { - 'createImage': { - 'name': 'Snapshot 1', - 'metadata': {'key': 'asdf'}, - }, - } - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.body = json.dumps(body) - req.headers["content-type"] = "application/json" - response = req.get_response(fakes.wsgi_app()) - self.assertEqual(202, response.status_int) - location = response.headers['Location'] - self.assertEqual('http://localhost/v1.1/images/123', location) - - def test_create_image_v1_1_no_name(self): - body = { - 'createImage': {}, - } - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.body = json.dumps(body) - req.headers["content-type"] = "application/json" - response = req.get_response(fakes.wsgi_app()) - self.assertEqual(400, response.status_int) - - def test_create_image_v1_1_bad_metadata(self): - body = { - 'createImage': { - 'name': 'geoff', - 'metadata': 'henry', - }, - } - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.body = json.dumps(body) - req.headers["content-type"] = "application/json" - response = req.get_response(fakes.wsgi_app()) - self.assertEqual(400, response.status_int) - - -class TestServerActionXMLDeserializer(test.TestCase): - - def setUp(self): - self.deserializer = create_instance_helper.ServerXMLDeserializer() - - def tearDown(self): - pass - - def test_create_image(self): - serial_request = """ -""" - request = self.deserializer.deserialize(serial_request, 'action') - expected = { - "createImage": { - "name": "new-server-test", - "metadata": {}, - }, - } - self.assertEquals(request['body'], expected) - - def test_create_image_with_metadata(self): - serial_request = """ - - - value1 - -""" - request = self.deserializer.deserialize(serial_request, 'action') - expected = { - "createImage": { - "name": "new-server-test", - "metadata": {"key1": "value1"}, - }, - } - self.assertEquals(request['body'], expected) - class TestServerCreateRequestXMLDeserializerV10(unittest.TestCase): -- cgit From 154129acf1ecbdd97e5bb8558598a9b24eb8559f Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Wed, 27 Jul 2011 11:43:20 -0400 Subject: Cleaned up test_servers --- nova/tests/api/openstack/test_servers.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index b68183429..c33d6b367 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -97,12 +97,6 @@ def return_server_with_power_state(power_state): return _return_server -def return_server_with_uuid_and_power_state(power_state): - def _return_server(context, id): - return stub_instance(id, uuid=FAKE_UUID, power_state=power_state) - return _return_server - - def return_servers(context, user_id=1): return [stub_instance(i, user_id) for i in xrange(5)] @@ -264,19 +258,8 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.compute.API, "get_diagnostics", fake_compute_api) self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api) - fakes.stub_out_glance(self.stubs) - fakes.stub_out_compute_api_snapshot(self.stubs) - service_class = 'nova.image.glance.GlanceImageService' - self.service = utils.import_object(service_class) - self.context = context.RequestContext(1, None) - self.service.delete_all() - self.sent_to_glance = {} - fakes.stub_out_glance_add_image(self.stubs, self.sent_to_glance) - self.allow_admin = FLAGS.allow_admin_api - self.webreq = common.webob_factory('/v1.0/servers') - def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin -- cgit From b6ee05e9575769039aca2c65c2a761c14562e7e0 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 27 Jul 2011 11:45:22 -0400 Subject: updating common metadata xml serializer tests --- nova/tests/api/openstack/test_common.py | 60 +++++++++++---------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 0b76841f0..ee96fea7e 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -323,14 +323,10 @@ class MetadataXMLSerializationTest(test.TestCase): expected = minidom.parseString(""" - - four - - - two - + four + two - """.replace(" ", "")) + """.replace(" ", "").replace("\n","")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -346,11 +342,9 @@ class MetadataXMLSerializationTest(test.TestCase): expected = minidom.parseString(""" - - None - + None - """.replace(" ", "")) + """.replace(" ", "").replace("\n","")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -366,11 +360,9 @@ class MetadataXMLSerializationTest(test.TestCase): expected = minidom.parseString(u""" - - Jos\xe9 - + Jos\xe9 - """.encode("UTF-8").replace(" ", "")) + """.encode("UTF-8").replace(" ", "").replace("\n","")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -385,10 +377,9 @@ class MetadataXMLSerializationTest(test.TestCase): actual = minidom.parseString(output.replace(" ", "")) expected = minidom.parseString(""" - - two - - """.replace(" ", "")) + two + """.replace(" ", "").replace("\n","")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -405,14 +396,10 @@ class MetadataXMLSerializationTest(test.TestCase): expected = minidom.parseString(""" - - value6 - - - value4 - + value6 + value4 - """.replace(" ", "")) + """.replace(" ", "").replace("\n","")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -427,10 +414,9 @@ class MetadataXMLSerializationTest(test.TestCase): actual = minidom.parseString(output.replace(" ", "")) expected = minidom.parseString(""" - - two - - """.replace(" ", "")) + two + """.replace(" ", "").replace("\n","")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -448,17 +434,11 @@ class MetadataXMLSerializationTest(test.TestCase): expected = minidom.parseString(""" - - value2 - - - value9 - - - value1 - + value2 + value9 + value1 - """.replace(" ", "")) + """.replace(" ", "").replace("\n","")) self.assertEqual(expected.toxml(), actual.toxml()) -- cgit From 572847f9eb43ce23190566439118547ae6d6a992 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 27 Jul 2011 11:53:09 -0400 Subject: pep8 --- nova/api/openstack/server_metadata.py | 6 +++--- nova/tests/api/openstack/test_common.py | 14 +++++++------- nova/tests/api/openstack/test_server_metadata.py | 13 ++++++------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/nova/api/openstack/server_metadata.py b/nova/api/openstack/server_metadata.py index d8f9cdbac..f25d36535 100644 --- a/nova/api/openstack/server_metadata.py +++ b/nova/api/openstack/server_metadata.py @@ -72,13 +72,13 @@ class Controller(object): def update(self, req, server_id, id, body): try: - meta_item = body['meta'] + meta_item = body['meta'] except (TypeError, KeyError): expl = _('Malformed request body') raise exc.HTTPBadRequest(explanation=expl) try: - meta_value = meta_item.pop(id) + meta_value = meta_item.pop(id) except (AttributeError, KeyError): expl = _('Request body and URI mismatch') raise exc.HTTPBadRequest(explanation=expl) @@ -94,7 +94,7 @@ class Controller(object): def update_all(self, req, server_id, body): try: - metadata = body['metadata'] + metadata = body['metadata'] except (TypeError, KeyError): expl = _('Malformed request body') raise exc.HTTPBadRequest(explanation=expl) diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index ee96fea7e..5a6e43579 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -326,7 +326,7 @@ class MetadataXMLSerializationTest(test.TestCase): four two - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -344,7 +344,7 @@ class MetadataXMLSerializationTest(test.TestCase): None - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -362,7 +362,7 @@ class MetadataXMLSerializationTest(test.TestCase): Jos\xe9 - """.encode("UTF-8").replace(" ", "").replace("\n","")) + """.encode("UTF-8").replace(" ", "").replace("\n", "")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -379,7 +379,7 @@ class MetadataXMLSerializationTest(test.TestCase): expected = minidom.parseString(""" two - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -399,7 +399,7 @@ class MetadataXMLSerializationTest(test.TestCase): value6 value4 - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -416,7 +416,7 @@ class MetadataXMLSerializationTest(test.TestCase): expected = minidom.parseString(""" two - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -438,7 +438,7 @@ class MetadataXMLSerializationTest(test.TestCase): value9 value1 - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected.toxml(), actual.toxml()) diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py index ded30a950..2f432433d 100644 --- a/nova/tests/api/openstack/test_server_metadata.py +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -100,9 +100,9 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual('application/json', res.headers['Content-Type']) expected = { 'metadata': { - 'key1':'value1', - 'key2':'value2', - 'key3':'value3', + 'key1': 'value1', + 'key2': 'value2', + 'key3': 'value3', }, } self.assertEqual(expected, res_dict) @@ -124,7 +124,7 @@ class ServerMetaDataTest(unittest.TestCase): value2 value1 - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected_metadata.toxml(), actual_metadata.toxml()) @@ -168,7 +168,7 @@ class ServerMetaDataTest(unittest.TestCase): expected_metadata = minidom.parseString(""" value2 - """.replace(" ", "").replace("\n","")) + """.replace(" ", "").replace("\n", "")) self.assertEqual(expected_metadata.toxml(), actual_metadata.toxml()) @@ -239,7 +239,7 @@ class ServerMetaDataTest(unittest.TestCase): value2 value1 - """.replace(" ","").replace("\n","")) + """.replace(" ", "").replace("\n", "")) req.body = str(request_metadata.toxml()) response = req.get_response(fakes.wsgi_app()) @@ -422,4 +422,3 @@ class ServerMetaDataTest(unittest.TestCase): req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(400, res.status_int) - -- cgit From f9ff78a5ac5f83d789334c36bebfce62af0ea406 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 27 Jul 2011 17:20:42 -0400 Subject: refactoring MetadataXMLDeserializer in wsgi/common --- nova/api/openstack/common.py | 12 +++++++++++- nova/api/openstack/create_instance_helper.py | 7 +++++-- nova/api/openstack/wsgi.py | 13 ------------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index 24c82035a..a99951764 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -196,7 +196,17 @@ def get_version_from_href(href): return version -class MetadataXMLDeserializer(wsgi.MetadataXMLDeserializer): +class MetadataXMLDeserializer(wsgi.XMLDeserializer): + + def extract_metadata(self, metadata_node): + """Marshal the metadata attribute of a parsed request""" + if metadata_node is None: + return None + metadata = {} + for meta_node in self.find_children_named(metadata_node, "meta"): + key = meta_node.getAttribute("key") + metadata[key] = self.extract_text(meta_node) + return metadata def _extract_metadata_container(self, datastring): dom = minidom.parseString(datastring) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index f8317565e..70532cf79 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -28,6 +28,7 @@ from nova import quota from nova import utils from nova.compute import instance_types +from nova.api.openstack import common from nova.api.openstack import wsgi from nova.auth import manager as auth_manager @@ -285,7 +286,7 @@ class CreateInstanceHelper(object): return password -class ServerXMLDeserializer(wsgi.MetadataXMLDeserializer): +class ServerXMLDeserializer(wsgi.XMLDeserializer): """ Deserializer to handle xml-formatted server create requests. @@ -293,6 +294,8 @@ class ServerXMLDeserializer(wsgi.MetadataXMLDeserializer): and personality attributes """ + metadata_deserializer = common.MetadataXMLDeserializer() + def create(self, string): """Deserialize an xml-formatted server create request""" dom = minidom.parseString(string) @@ -307,7 +310,7 @@ class ServerXMLDeserializer(wsgi.MetadataXMLDeserializer): if server_node.getAttribute(attr): server[attr] = server_node.getAttribute(attr) metadata_node = self.find_first_child_named(server_node, "metadata") - metadata = self.extract_metadata(metadata_node) + metadata = self.metadata_deserializer.extract_metadata(metadata_node) if metadata is not None: server["metadata"] = metadata personality = self._extract_personality(server_node) diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index a28443d12..d10424d79 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -161,19 +161,6 @@ class XMLDeserializer(TextDeserializer): return {'body': self._from_xml(datastring)} -class MetadataXMLDeserializer(XMLDeserializer): - - def extract_metadata(self, metadata_node): - """Marshal the metadata attribute of a parsed request""" - if metadata_node is None: - return None - metadata = {} - for meta_node in self.find_children_named(metadata_node, "meta"): - key = meta_node.getAttribute("key") - metadata[key] = self.extract_text(meta_node) - return metadata - - class RequestHeadersDeserializer(ActionDispatcher): """Default request headers deserializer""" -- cgit From 92c8d269a13917de397c1d0ce9fecfaa36195ce9 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Thu, 28 Jul 2011 10:23:44 -0400 Subject: Removed v1_1 from individual tests --- nova/tests/api/openstack/test_server_actions.py | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py index 97c108068..5c23d6d9d 100644 --- a/nova/tests/api/openstack/test_server_actions.py +++ b/nova/tests/api/openstack/test_server_actions.py @@ -350,7 +350,7 @@ class ServerActionsTestV11(test.TestCase): def tearDown(self): self.stubs.UnsetAll() - def test_server_change_password_v1_1(self): + def test_server_change_password(self): mock_method = MockSetAdminPassword() self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method) body = {'changePassword': {'adminPass': '1234pass'}} @@ -363,7 +363,7 @@ class ServerActionsTestV11(test.TestCase): self.assertEqual(mock_method.instance_id, '1') self.assertEqual(mock_method.password, '1234pass') - def test_server_change_password_bad_request_v1_1(self): + def test_server_change_password_bad_request(self): body = {'changePassword': {'pass': '12345'}} req = webob.Request.blank('/v1.1/servers/1/action') req.method = 'POST' @@ -372,7 +372,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) - def test_server_change_password_empty_string_v1_1(self): + def test_server_change_password_empty_string(self): body = {'changePassword': {'adminPass': ''}} req = webob.Request.blank('/v1.1/servers/1/action') req.method = 'POST' @@ -381,7 +381,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) - def test_server_change_password_none_v1_1(self): + def test_server_change_password_none(self): body = {'changePassword': {'adminPass': None}} req = webob.Request.blank('/v1.1/servers/1/action') req.method = 'POST' @@ -390,7 +390,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) - def test_server_rebuild_accepted_minimum_v1_1(self): + def test_server_rebuild_accepted_minimum(self): body = { "rebuild": { "imageRef": "http://localhost/images/2", @@ -405,7 +405,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) - def test_server_rebuild_rejected_when_building_v1_1(self): + def test_server_rebuild_rejected_when_building(self): body = { "rebuild": { "imageRef": "http://localhost/images/2", @@ -426,7 +426,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 409) - def test_server_rebuild_accepted_with_metadata_v1_1(self): + def test_server_rebuild_accepted_with_metadata(self): body = { "rebuild": { "imageRef": "http://localhost/images/2", @@ -444,7 +444,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) - def test_server_rebuild_accepted_with_bad_metadata_v1_1(self): + def test_server_rebuild_accepted_with_bad_metadata(self): body = { "rebuild": { "imageRef": "http://localhost/images/2", @@ -460,7 +460,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) - def test_server_rebuild_bad_entity_v1_1(self): + def test_server_rebuild_bad_entity(self): body = { "rebuild": { "imageId": 2, @@ -475,7 +475,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) - def test_server_rebuild_bad_personality_v1_1(self): + def test_server_rebuild_bad_personality(self): body = { "rebuild": { "imageRef": "http://localhost/images/2", @@ -494,7 +494,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) - def test_server_rebuild_personality_v1_1(self): + def test_server_rebuild_personality(self): body = { "rebuild": { "imageRef": "http://localhost/images/2", @@ -513,7 +513,7 @@ class ServerActionsTestV11(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) - def test_resize_server_v11(self): + def test_resize_server(self): req = webob.Request.blank('/v1.1/servers/1/action') req.content_type = 'application/json' @@ -532,7 +532,7 @@ class ServerActionsTestV11(test.TestCase): self.assertEqual(res.status_int, 202) self.assertEqual(self.resize_called, True) - def test_create_image_v1_1(self): + def test_create_image(self): body = { 'createImage': { 'name': 'Snapshot 1', @@ -547,7 +547,7 @@ class ServerActionsTestV11(test.TestCase): location = response.headers['Location'] self.assertEqual('http://localhost/v1.1/images/123', location) - def test_create_image_v1_1_with_metadata(self): + def test_create_image_with_metadata(self): body = { 'createImage': { 'name': 'Snapshot 1', @@ -563,7 +563,7 @@ class ServerActionsTestV11(test.TestCase): location = response.headers['Location'] self.assertEqual('http://localhost/v1.1/images/123', location) - def test_create_image_v1_1_no_name(self): + def test_create_image_no_name(self): body = { 'createImage': {}, } @@ -574,7 +574,7 @@ class ServerActionsTestV11(test.TestCase): response = req.get_response(fakes.wsgi_app()) self.assertEqual(400, response.status_int) - def test_create_image_v1_1_bad_metadata(self): + def test_create_image_bad_metadata(self): body = { 'createImage': { 'name': 'geoff', -- cgit From cd065f6669a666387c8f9efb5c0fff7eaf94521c Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Thu, 28 Jul 2011 10:31:06 -0400 Subject: moved test --- nova/tests/api/openstack/test_server_actions.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py index 5c23d6d9d..1651b1645 100644 --- a/nova/tests/api/openstack/test_server_actions.py +++ b/nova/tests/api/openstack/test_server_actions.py @@ -132,15 +132,6 @@ class ServerActionsTest(test.TestCase): # res = req.get_response(fakes.wsgi_app()) # self.assertEqual(res.status_int, 501) - def test_server_change_password_not_a_string_v1_1(self): - body = {'changePassword': {'adminPass': 1234}} - req = webob.Request.blank('/v1.1/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 400) - def test_server_reboot(self): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, @@ -363,6 +354,15 @@ class ServerActionsTestV11(test.TestCase): self.assertEqual(mock_method.instance_id, '1') self.assertEqual(mock_method.password, '1234pass') + def test_server_change_password_not_a_string(self): + body = {'changePassword': {'adminPass': 1234}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + def test_server_change_password_bad_request(self): body = {'changePassword': {'pass': '12345'}} req = webob.Request.blank('/v1.1/servers/1/action') -- cgit From f91413bec1e6698935e00c323befa0655dea1ab1 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Fri, 29 Jul 2011 10:22:50 -0400 Subject: Fixed changes missed in merge --- nova/tests/api/openstack/test_server_actions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py index 1651b1645..0bc7e4cf3 100644 --- a/nova/tests/api/openstack/test_server_actions.py +++ b/nova/tests/api/openstack/test_server_actions.py @@ -53,8 +53,8 @@ class MockSetAdminPassword(object): def _get_instance(): instance = { "id": 1, - "created_at": "2010-10-10T12:00:00Z", - "updated_at": "2010-11-11T11:00:00Z", + "created_at": "2010-10-10 12:00:00", + "updated_at": "2010-11-11 11:00:00", "admin_pass": "", "user_id": "", "project_id": "", -- cgit From 7a1b622ed6088aaaa711b44c50a26e1a33695f63 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 12:21:46 -0400 Subject: updating HACKING --- HACKING | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/HACKING b/HACKING index 2f364c894..2dcb76591 100644 --- a/HACKING +++ b/HACKING @@ -10,13 +10,14 @@ Imports - thou shalt not import objects, only modules - thou shalt not import more than one module per line - thou shalt not make relative imports +- thou shalt order your imports by the full module path - thou shalt organize your imports according to the following template :: # vim: tabstop=4 shiftwidth=4 softtabstop=4 - {{stdlib imports in human alphabetical order}} + {{stdlib imports in human alphabetical order by module name}} \n - {{nova imports in human alphabetical order}} + {{nova imports in human alphabetical order by module name}} \n \n {{begin your code}} @@ -42,11 +43,12 @@ Human Alphabetical Order Examples import time import unittest - from nova import flags - from nova import test + import nova.api.ec2 + from nova.api import openstack from nova.auth import users - from nova.endpoint import api + import nova.flags from nova.endpoint import cloud + from nova import test Docstrings ---------- @@ -70,6 +72,61 @@ Docstrings :param foo: the foo parameter :param bar: the bar parameter - :returns: description of the return value + :returns: return_type -- description of the return value + :raises: AttributeError, KeyError """ + +Dictionaries/Lists +------------------ + If a dictionary (dict) or list object is longer than 80 characters, its + items should be split with newlines. Embedded iterables should have their + items indented. Additionally, the last item in the dictionary should have + a trailing comma. This increases readability and simplifies future diffs. + + Example: + + my_dictionary = { + "image": { + "name": "Just a Snapshot", + "size": 2749573, + "properties": { + "user_id": 12, + "arch": "x86_64", + }, + "things": [ + "thing_one", + "thing_two", + ], + "status": "ACTIVE", + }, + } + +Method Signatures +----------------- + Calls to methods 80 characters or longer should format each argument with + newlines. This is mainly for readability. + + unnecessarily_long_function_name('string one', + 'string two', + kwarg1=constants.ACTIVE, + kwarg2=['a', 'b', 'c']) + + + Rather than constructing parameters inline, it is better to break things up: + + list_of_strings = [ + 'what_a_long_string', + 'not as long', + ] + + dict_of_numbers = { + 'one': 1, + 'two': 2, + 'twenty four': 24, + } + + object_one.call_a_method('string three', + 'string four', + kwarg1=list_of_strings, + kwarg2=dict_of_numbers) -- cgit From 4438850e323e85673d504ae16bb09f6d05dc65bb Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 12:44:11 -0400 Subject: expanding --- HACKING | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/HACKING b/HACKING index 2dcb76591..ee919e205 100644 --- a/HACKING +++ b/HACKING @@ -50,6 +50,7 @@ Human Alphabetical Order Examples from nova.endpoint import cloud from nova import test + Docstrings ---------- """A one line docstring looks like this and ends in a period.""" @@ -77,6 +78,7 @@ Docstrings """ + Dictionaries/Lists ------------------ If a dictionary (dict) or list object is longer than 80 characters, its @@ -101,9 +103,38 @@ Dictionaries/Lists "status": "ACTIVE", }, } + + Only use the dict constructor for casting. Do not use it to create a new + dictionary. + + Example (BAD): + + my_dictionary = dict(key1='param1', key2='param2', key3=['a', 'b']) + + +Defining Methods +---------------- + Method signatures longer than 80 characters are very unreadable. If you + encounter this problem, first you should determine if your method is + too big. Otherwise, you should compress your keyword arguments with a + '**kwargs' parameter. You should use the 'kwargs' in your method as a + dictionary to retrieve the necessary keyword arguments. + + Example (BAD): + + def my_method(argument_one, argument_two, kwarg_one='default_one', + kwarg_two='default_two', kwarg_three='default_three'): + + Example (GOOD): + + def my_method(argumet_one, argument_two, **kwargs): + kwarg_one = kwargs.get('kwarg_one', 'default_one') + kwarg_two = kwargs.get('kwarg_one', 'default_one') + kwarg_three = kwargs.get('kwarg_three', 'default_three') -Method Signatures ------------------ + +Calling Methods +--------------- Calls to methods 80 characters or longer should format each argument with newlines. This is mainly for readability. @@ -130,3 +161,26 @@ Method Signatures 'string four', kwarg1=list_of_strings, kwarg2=dict_of_numbers) + +Internationalization (i18n) Strings +---------------------------- + In order to support multiple languages, we have a mechanism to support + automatic translations of exception and log strings. + + Example: + msg = _("An error occurred") + raise HTTPBadRequest(explanation=msg) + + If you have a variable to place within the string, first internationalize + the template string then do the replacement. + + Example: + msg = _("Missing parameter: %s") % ("flavor",) + LOG.error(msg) + + If you have multiple variables to place in the string, use keyword + parameters. This helps our translators reorder parameters when needed. + + Example: + msg = _("The server with id %(s_id)s has no key %(m_key)s") + LOG.error(msg % (s_id="1234, m_key="imageId")) -- cgit From 05ca64bd1fbf70c7066e84426dd08b5beb9cbb6d Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 12:49:48 -0400 Subject: upgrades --- HACKING | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/HACKING b/HACKING index ee919e205..82ccdb962 100644 --- a/HACKING +++ b/HACKING @@ -5,13 +5,23 @@ Step 1: Read http://www.python.org/dev/peps/pep-0008/ Step 2: Read http://www.python.org/dev/peps/pep-0008/ again Step 3: Read on + +General +------- +- Put two newlines twixt toplevel code (funcs, classes, etc) +- Put one newline twixt methods in classes and anywhere else +- Do not write "except:", use "except Exception:" at the very least +- Include your name with TODOs as in "TODO(termie)" +- Do not name anything the same name as a builtin or reserved word + + Imports ------- -- thou shalt not import objects, only modules -- thou shalt not import more than one module per line -- thou shalt not make relative imports -- thou shalt order your imports by the full module path -- thou shalt organize your imports according to the following template +- Do not import objects, only modules +- Do not import more than one module per line +- Do not make relative imports +- Order your imports by the full module path +- Organize your imports according to the following template :: # vim: tabstop=4 shiftwidth=4 softtabstop=4 @@ -23,16 +33,6 @@ Imports {{begin your code}} -General -------- -- thou shalt put two newlines twixt toplevel code (funcs, classes, etc) -- thou shalt put one newline twixt methods in classes and anywhere else -- thou shalt not write "except:", use "except Exception:" at the very least -- thou shalt include your name with TODOs as in "TODO(termie)" -- thou shalt not name anything the same name as a builtin or reserved word -- thou shalt not violate causality in our time cone, or else - - Human Alphabetical Order Examples --------------------------------- :: -- cgit From acf7b94a899b2901f102ad2fd176c895abf456a3 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 12:54:55 -0400 Subject: one last change --- HACKING | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/HACKING b/HACKING index 82ccdb962..9d6b43b98 100644 --- a/HACKING +++ b/HACKING @@ -8,11 +8,11 @@ Step 3: Read on General ------- -- Put two newlines twixt toplevel code (funcs, classes, etc) -- Put one newline twixt methods in classes and anywhere else +- Put two newlines between top-level code (funcs, classes, etc) +- Put one newline between methods in classes and anywhere else - Do not write "except:", use "except Exception:" at the very least -- Include your name with TODOs as in "TODO(termie)" -- Do not name anything the same name as a builtin or reserved word +- Include your name with TODOs as in "#TODO(termie)" +- Do not name anything the same name as a built-in or reserved word Imports -- cgit From 5c7b70cef1abe91861dd4f82a365143256e9f2cf Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 13:00:09 -0400 Subject: rewording --- HACKING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HACKING b/HACKING index 9d6b43b98..cb5f696d1 100644 --- a/HACKING +++ b/HACKING @@ -136,7 +136,7 @@ Defining Methods Calling Methods --------------- Calls to methods 80 characters or longer should format each argument with - newlines. This is mainly for readability. + newlines. This is not a requirement, but a guideline. unnecessarily_long_function_name('string one', 'string two', -- cgit From 58e2d9f46fef753857f559c8f5953e025d022d3c Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 13:46:24 -0400 Subject: rewording --- HACKING | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/HACKING b/HACKING index cb5f696d1..4c5193779 100644 --- a/HACKING +++ b/HACKING @@ -116,16 +116,12 @@ Defining Methods ---------------- Method signatures longer than 80 characters are very unreadable. If you encounter this problem, first you should determine if your method is - too big. Otherwise, you should compress your keyword arguments with a - '**kwargs' parameter. You should use the 'kwargs' in your method as a - dictionary to retrieve the necessary keyword arguments. + too big. If not, you can compress your keyword arguments with a + '**kwargs' parameter. You can then use 'kwargs' in your method as a + dictionary to retrieve the necessary keyword arguments. This is just a + guideline, not a requirement. - Example (BAD): - - def my_method(argument_one, argument_two, kwarg_one='default_one', - kwarg_two='default_two', kwarg_three='default_three'): - - Example (GOOD): + Example: def my_method(argumet_one, argument_two, **kwargs): kwarg_one = kwargs.get('kwarg_one', 'default_one') -- cgit From e664443e2f2565150b35d813f6cd95c941033524 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 13:51:49 -0400 Subject: removing 'Defining Methods' paragraph --- HACKING | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/HACKING b/HACKING index 4c5193779..ea0188141 100644 --- a/HACKING +++ b/HACKING @@ -112,23 +112,6 @@ Dictionaries/Lists my_dictionary = dict(key1='param1', key2='param2', key3=['a', 'b']) -Defining Methods ----------------- - Method signatures longer than 80 characters are very unreadable. If you - encounter this problem, first you should determine if your method is - too big. If not, you can compress your keyword arguments with a - '**kwargs' parameter. You can then use 'kwargs' in your method as a - dictionary to retrieve the necessary keyword arguments. This is just a - guideline, not a requirement. - - Example: - - def my_method(argumet_one, argument_two, **kwargs): - kwarg_one = kwargs.get('kwarg_one', 'default_one') - kwarg_two = kwargs.get('kwarg_one', 'default_one') - kwarg_three = kwargs.get('kwarg_three', 'default_three') - - Calling Methods --------------- Calls to methods 80 characters or longer should format each argument with @@ -158,6 +141,7 @@ Calling Methods kwarg1=list_of_strings, kwarg2=dict_of_numbers) + Internationalization (i18n) Strings ---------------------------- In order to support multiple languages, we have a mechanism to support -- cgit From 9fb6c29c10d3693c84e34c05092cac4117fa6eb5 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 15:26:14 -0400 Subject: adding more on return_type in docstrings --- HACKING | 1 + 1 file changed, 1 insertion(+) diff --git a/HACKING b/HACKING index ea0188141..2f33fd19f 100644 --- a/HACKING +++ b/HACKING @@ -74,6 +74,7 @@ Docstrings :param foo: the foo parameter :param bar: the bar parameter :returns: return_type -- description of the return value + :returns: description of the return value :raises: AttributeError, KeyError """ -- cgit From c8a6bd03aa7a74a1adbf3df3c879811ef0cc9944 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 15:32:27 -0400 Subject: removing dict() comment --- HACKING | 7 ------- 1 file changed, 7 deletions(-) diff --git a/HACKING b/HACKING index 2f33fd19f..9e1b29668 100644 --- a/HACKING +++ b/HACKING @@ -105,13 +105,6 @@ Dictionaries/Lists }, } - Only use the dict constructor for casting. Do not use it to create a new - dictionary. - - Example (BAD): - - my_dictionary = dict(key1='param1', key2='param2', key3=['a', 'b']) - Calling Methods --------------- -- cgit From 70574077c469a69547d7702592f07ecd0d551daf Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 15:42:10 -0400 Subject: removing extra verbage --- HACKING | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/HACKING b/HACKING index 9e1b29668..70b2b09e7 100644 --- a/HACKING +++ b/HACKING @@ -25,9 +25,9 @@ Imports :: # vim: tabstop=4 shiftwidth=4 softtabstop=4 - {{stdlib imports in human alphabetical order by module name}} + {{stdlib imports in human alphabetical order}} \n - {{nova imports in human alphabetical order by module name}} + {{nova imports in human alphabetical order}} \n \n {{begin your code}} -- cgit From 57cda5b254d34af0a63b3cbcb895b04ec7bf5407 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 15:43:23 -0400 Subject: fixing underline --- HACKING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HACKING b/HACKING index 70b2b09e7..3d79e9e82 100644 --- a/HACKING +++ b/HACKING @@ -137,7 +137,7 @@ Calling Methods Internationalization (i18n) Strings ----------------------------- +----------------------------------- In order to support multiple languages, we have a mechanism to support automatic translations of exception and log strings. -- cgit From 3d9f5b561063f714338c023d3b9ad6a786766279 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Fri, 29 Jul 2011 15:58:41 -0400 Subject: typo --- HACKING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HACKING b/HACKING index 3d79e9e82..232a353fd 100644 --- a/HACKING +++ b/HACKING @@ -157,4 +157,4 @@ Internationalization (i18n) Strings Example: msg = _("The server with id %(s_id)s has no key %(m_key)s") - LOG.error(msg % (s_id="1234, m_key="imageId")) + LOG.error(msg % {"s_id": "1234", "m_key": "imageId"}) -- cgit From 695afaffaa4de359b306280c252f8f40a3bab5a7 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Tue, 2 Aug 2011 11:48:01 -0400 Subject: cleanup --- nova/api/openstack/server_metadata.py | 2 +- nova/api/openstack/servers.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/nova/api/openstack/server_metadata.py b/nova/api/openstack/server_metadata.py index f25d36535..b0b014f86 100644 --- a/nova/api/openstack/server_metadata.py +++ b/nova/api/openstack/server_metadata.py @@ -53,7 +53,7 @@ class Controller(object): metadata = body['metadata'] except (KeyError, TypeError): msg = _("Malformed request body") - raise exc.HTTPBadRequest(esplanation=msg) + raise exc.HTTPBadRequest(explanation=msg) context = req.environ['nova.context'] diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 1453424ce..30169d450 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -19,7 +19,6 @@ import traceback from webob import exc from xml.dom import minidom import webob -from xml.dom import minidom from nova import compute from nova import exception -- cgit From 113fe431d61899b8402181d1016ab29479330636 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Tue, 2 Aug 2011 13:34:29 -0500 Subject: Get instance by UUID instead of id. --- nova/compute/manager.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index a2d84cd76..c7c88a1fb 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -648,37 +648,38 @@ class ComputeManager(manager.SchedulerDependentManager): @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @checks_instance_lock - def rescue_instance(self, context, instance_id): + def rescue_instance(self, context, instance_uuid): """Rescue an instance on this host.""" context = context.elevated() - instance_ref = self.db.instance_get(context, instance_id) - LOG.audit(_('instance %s: rescuing'), instance_id, context=context) + instance_ref = self.db.instance_get_by_uuid(context, instance_uuid) + LOG.audit(_('instance %s: rescuing'), instance_uuid, context=context) self.db.instance_set_state(context, - instance_id, + instance_uuid, power_state.NOSTATE, 'rescuing') _update_state = lambda result: self._update_state_callback( - self, context, instance_id, result) + self, context, instance_uuid, result) network_info = self._get_instance_nw_info(context, instance_ref) self.driver.rescue(instance_ref, _update_state, network_info) - self._update_state(context, instance_id) + self._update_state(context, instance_uuid) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @checks_instance_lock - def unrescue_instance(self, context, instance_id): + def unrescue_instance(self, context, instance_uuid): """Rescue an instance on this host.""" context = context.elevated() - instance_ref = self.db.instance_get(context, instance_id) - LOG.audit(_('instance %s: unrescuing'), instance_id, context=context) + instance_ref = self.db.instance_get_by_uuid(context, instance_uuid) + LOG.audit(_('instance %s: unrescuing'), instance_uuid, + context=context) self.db.instance_set_state(context, - instance_id, + instance_uuid, power_state.NOSTATE, 'unrescuing') _update_state = lambda result: self._update_state_callback( - self, context, instance_id, result) + self, context, instance_uuid, result) network_info = self._get_instance_nw_info(context, instance_ref) self.driver.unrescue(instance_ref, _update_state, network_info) - self._update_state(context, instance_id) + self._update_state(context, instance_uuid) @staticmethod def _update_state_callback(self, context, instance_id, result): -- cgit From ded9447aca01d593b0efa91b5ec23ecf8aa97264 Mon Sep 17 00:00:00 2001 From: Alex Meade Date: Tue, 2 Aug 2011 15:43:36 -0400 Subject: Fixed merge issues --- nova/api/openstack/images.py | 3 --- nova/api/openstack/servers.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index 43d976b8f..0834adfa5 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -197,9 +197,6 @@ class ControllerV11(Controller): def create(self, *args, **kwargs): raise webob.exc.HTTPMethodNotAllowed() - def create(self, *args, **kwargs): - raise webob.exc.HTTPMethodNotAllowed() - class ImageXMLSerializer(wsgi.XMLDictSerializer): diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index dfa150320..7b757143d 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -20,7 +20,6 @@ import traceback from webob import exc from xml.dom import minidom import webob -from xml.dom import minidom from nova import compute from nova import exception @@ -178,6 +177,7 @@ class Controller(object): for key in self.actions.keys(): if key in body: return self.actions[key](body, req, id) + raise exc.HTTPNotImplemented() def _action_create_backup(self, input_dict, req, instance_id): -- cgit From bfb5a5e1204bf868b5db8d8d038b63d0899665ce Mon Sep 17 00:00:00 2001 From: John Tran Date: Wed, 3 Aug 2011 00:11:52 -0700 Subject: updated to work w/ changes after merged trunk fixing var renaming. the logic which forces default to FLAGS.network_size if requested cidr was larger, was also applying to requested cidrs smaller than FLAGS.network_size. Requested cidrs smaller than FLAGS.network_size should be ignored and not overriden. --- bin/nova-manage | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 78cc96818..f53021581 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -695,15 +695,18 @@ class NetworkCommands(object): if not num_networks: num_networks = FLAGS.num_networks if not network_size: - network_size = FLAGS.network_size - fixnet = netaddr.IPNetwork(fixed_range) + #network_size = FLAGS.network_size + fixnet = netaddr.IPNetwork(fixed_range_v4) each_subnet_size = fixnet.size / int(num_networks) - if each_subnet_size > network_size: + if each_subnet_size > FLAGS.network_size: + network_size = FLAGS.network_size subnet = 32 - int(math.log(network_size, 2)) oversize_msg = _('Subnet(s) too large, defaulting to /%s.' ' To override, specify network_size flag.' ) % subnet print oversize_msg + else: + network_size = fixnet.size if not multi_host: multi_host = FLAGS.multi_host else: -- cgit From f942a7f22acb6a6719a3de778ba55ca25ea0ee68 Mon Sep 17 00:00:00 2001 From: John Tran Date: Wed, 3 Aug 2011 00:16:52 -0700 Subject: forgot to remove comment --- bin/nova-manage | 1 - 1 file changed, 1 deletion(-) diff --git a/bin/nova-manage b/bin/nova-manage index f53021581..f272351c2 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -695,7 +695,6 @@ class NetworkCommands(object): if not num_networks: num_networks = FLAGS.num_networks if not network_size: - #network_size = FLAGS.network_size fixnet = netaddr.IPNetwork(fixed_range_v4) each_subnet_size = fixnet.size / int(num_networks) if each_subnet_size > FLAGS.network_size: -- cgit From 2d2405e35d34c928c87d575bcfc7c74db9de6b1d Mon Sep 17 00:00:00 2001 From: Johannes Erdfelt Date: Wed, 3 Aug 2011 11:31:10 +0000 Subject: Use flavorid only at the API level and use instance_type_id internally --- nova/compute/api.py | 2 +- nova/compute/manager.py | 21 ++++--- .../versions/036_change_flavor_id_in_migrations.py | 71 ++++++++++++++++++++++ nova/db/sqlalchemy/models.py | 6 +- nova/tests/test_compute.py | 4 +- 5 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py diff --git a/nova/compute/api.py b/nova/compute/api.py index aae16d1da..f42df015a 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -955,7 +955,7 @@ class API(base.Base): {"method": "prep_resize", "args": {"topic": FLAGS.compute_topic, "instance_id": instance_ref['uuid'], - "flavor_id": new_instance_type['id']}}) + "instance_type_id": new_instance_type['id']}}) @scheduler_api.reroute_compute("add_fixed_ip") def add_fixed_ip(self, context, instance_id, network_id): diff --git a/nova/compute/manager.py b/nova/compute/manager.py index a2d84cd76..9b5fac58b 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -736,8 +736,8 @@ class ComputeManager(manager.SchedulerDependentManager): instance_ref = self.db.instance_get_by_uuid(context, migration_ref.instance_uuid) - instance_type = self.db.instance_type_get_by_flavor_id(context, - migration_ref['old_flavor_id']) + instance_type = self.db.instance_type_get(context, + migration_ref['old_instance_type_id']) # Just roll back the record. There's no need to resize down since # the 'old' VM already has the preferred attributes @@ -758,7 +758,7 @@ class ComputeManager(manager.SchedulerDependentManager): @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @checks_instance_lock - def prep_resize(self, context, instance_id, flavor_id): + def prep_resize(self, context, instance_id, instance_type_id): """Initiates the process of moving a running instance to another host. Possibly changes the RAM and disk size in the process. @@ -777,16 +777,16 @@ class ComputeManager(manager.SchedulerDependentManager): old_instance_type = self.db.instance_type_get(context, instance_ref['instance_type_id']) - new_instance_type = self.db.instance_type_get_by_flavor_id(context, - flavor_id) + new_instance_type = self.db.instance_type_get(context, + instance_type_id) migration_ref = self.db.migration_create(context, {'instance_uuid': instance_ref['uuid'], 'source_compute': instance_ref['host'], 'dest_compute': FLAGS.host, 'dest_host': self.driver.get_host_ip_addr(), - 'old_flavor_id': old_instance_type['flavorid'], - 'new_flavor_id': flavor_id, + 'old_instance_type_id': old_instance_type['id'], + 'new_instance_type_id': instance_type_id, 'status': 'pre-migrating'}) LOG.audit(_('instance %s: migrating'), instance_ref['uuid'], @@ -849,9 +849,10 @@ class ComputeManager(manager.SchedulerDependentManager): resize_instance = False instance_ref = self.db.instance_get_by_uuid(context, migration_ref.instance_uuid) - if migration_ref['old_flavor_id'] != migration_ref['new_flavor_id']: - instance_type = self.db.instance_type_get_by_flavor_id(context, - migration_ref['new_flavor_id']) + if migration_ref['old_instance_type_id'] != \ + migration_ref['new_instance_type_id']: + instance_type = self.db.instance_type_get(context, + migration_ref['new_instance_type_id']) self.db.instance_update(context, instance_ref.uuid, dict(instance_type_id=instance_type['id'], memory_mb=instance_type['memory_mb'], diff --git a/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py new file mode 100644 index 000000000..7ff709c17 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py @@ -0,0 +1,71 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# 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.from sqlalchemy import * + +from sqlalchemy import Column, Integer, MetaData, Table + + +meta = MetaData() + + +# +# Tables to alter +# +# + +old_flavor_id = Column('old_flavor_id', Integer()) +new_flavor_id = Column('new_flavor_id', Integer()) +old_instance_type_id = Column('old_instance_type_id', Integer()) +new_instance_type_id = Column('new_instance_type_id', Integer()) + + +def upgrade(migrate_engine): + meta.bind = migrate_engine + instance_types = Table('instance_types', meta, autoload=True) + migrations = Table('migrations', meta, autoload=True) + migrations.create_column(old_instance_type_id) + migrations.create_column(new_instance_type_id) + + # Convert flavor_id to instance_type_id + for instance_type in migrate_engine.execute(instance_types.select()): + migrate_engine.execute(migrations.update()\ + .where(migrations.c.old_flavor_id == instance_type.flavorid)\ + .values(old_instance_type_id=instance_type.id)) + migrate_engine.execute(migrations.update()\ + .where(migrations.c.new_flavor_id == instance_type.flavorid)\ + .values(new_instance_type_id=instance_type.id)) + + migrations.c.old_flavor_id.drop() + migrations.c.new_flavor_id.drop() + + +def downgrade(migrate_engine): + meta.bind = migrate_engine + migrations = Table('migrations', meta, autoload=True) + migrations.create_column(old_flavor_id) + migrations.create_column(new_flavor_id) + + # Convert instance_type_id to flavor_id + for instance_type in migrate_engine.execute(instance_types.select()): + migrate_engine.execute(migrations.update()\ + .where(migrations.c.old_instance_type_id == instance_type.id)\ + .values(old_flavor_id=instance_type.flavorid)) + migrate_engine.execute(migrations.update()\ + .where(migrations.c.new_instance_type_id == instance_type.id)\ + .values(new_flavor_id=instance_type.flavorid)) + + migrations.c.old_instance_type_id.drop() + migrations.c.new_instance_type_id.drop() diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 056259539..9f4c7a0aa 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -202,7 +202,7 @@ class Instance(BASE, NovaBase): hostname = Column(String(255)) host = Column(String(255)) # , ForeignKey('hosts.id')) - # aka flavor_id + # *not* flavor_id instance_type_id = Column(Integer) user_data = Column(Text) @@ -511,8 +511,8 @@ class Migration(BASE, NovaBase): source_compute = Column(String(255)) dest_compute = Column(String(255)) dest_host = Column(String(255)) - old_flavor_id = Column(Integer()) - new_flavor_id = Column(Integer()) + old_instance_type_id = Column(Integer()) + new_instance_type_id = Column(Integer()) instance_uuid = Column(String(255), ForeignKey('instances.uuid'), nullable=True) #TODO(_cerberus_): enum diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 879e4b9cb..bbf9ddcc6 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -535,7 +535,9 @@ class ComputeTestCase(test.TestCase): db.instance_update(self.context, instance_id, {'host': 'foo'}) - self.compute.prep_resize(context, inst_ref['uuid'], 3) + new_instance_type_ref = db.instance_type_get_by_flavor_id(context, 3) + self.compute.prep_resize(context, inst_ref['uuid'], + new_instance_type_ref['id']) migration_ref = db.migration_get_by_instance_and_status(context, inst_ref['uuid'], 'pre-migrating') -- cgit From 8c77b6afa20c443916dd71572f22b52a5ecc88e9 Mon Sep 17 00:00:00 2001 From: Jason Koelker Date: Wed, 3 Aug 2011 08:54:00 -0500 Subject: fumigate non-pep8 code --- nova/api/openstack/create_instance_helper.py | 2 +- nova/api/openstack/versions.py | 16 +++--- nova/api/openstack/views/versions.py | 6 +-- nova/tests/api/openstack/test_versions.py | 80 ++++++++++++++-------------- 4 files changed, 52 insertions(+), 52 deletions(-) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index a2d18d37e..333994fcc 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -92,7 +92,7 @@ class CreateInstanceHelper(object): image_href = self.controller._image_ref_from_req_data(body) # If the image href was generated by nova api, strip image_href # down to an id and use the default glance connection params - + if str(image_href).startswith(req.application_url): image_href = image_href.split('/').pop() try: diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/versions.py index 3ef72b7f6..e2f892fb6 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/versions.py @@ -34,23 +34,23 @@ VERSIONS = { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" + "servers/api/v1.0/application.wadl", }, ], "media-types": [ { "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.0+xml" + "type": "application/vnd.openstack.compute-v1.0+xml", }, { "base": "application/json", - "type": "application/vnd.openstack.compute-v1.0+json" + "type": "application/vnd.openstack.compute-v1.0+json", } ], }, @@ -63,23 +63,23 @@ VERSIONS = { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" + "servers/api/v1.1/application.wadl", }, ], "media-types": [ { "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.1+xml" + "type": "application/vnd.openstack.compute-v1.1+xml", }, { "base": "application/json", - "type": "application/vnd.openstack.compute-v1.1+json" + "type": "application/vnd.openstack.compute-v1.1+json", } ], }, diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/views/versions.py index 547289034..03da80818 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/views/versions.py @@ -42,10 +42,10 @@ class ViewBuilder(object): "links": [ { "rel": "self", - "href": self.generate_href(version['id'], req.path) - } + "href": self.generate_href(version['id'], req.path), + }, ], - "media-types": version['media-types'] + "media-types": version['media-types'], }) return dict(choices=version_objs) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index e68455778..7482368f9 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -38,24 +38,24 @@ VERSIONS = { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" + "servers/api/v1.0/application.wadl", }, ], "media-types": [ { "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.0+xml" + "type": "application/vnd.openstack.compute-v1.0+xml", }, { "base": "application/json", - "type": "application/vnd.openstack.compute-v1.0+json" - } + "type": "application/vnd.openstack.compute-v1.0+json", + }, ], }, "v1.1": { @@ -67,24 +67,24 @@ VERSIONS = { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" + "servers/api/v1.1/application.wadl", }, ], "media-types": [ { "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.1+xml" + "type": "application/vnd.openstack.compute-v1.1+xml", }, { "base": "application/json", - "type": "application/vnd.openstack.compute-v1.1+json" - } + "type": "application/vnd.openstack.compute-v1.1+json", + }, ], }, } @@ -150,34 +150,34 @@ class VersionsTest(test.TestCase): "links": [ { "rel": "self", - "href": "http://localhost/v1.0/" + "href": "http://localhost/v1.0/", }, { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" - } + "servers/api/v1.0/application.wadl", + }, ], "media-types": [ { "base": "application/xml", "type": "application/" - "vnd.openstack.compute-v1.0+xml" + "vnd.openstack.compute-v1.0+xml", }, { "base": "application/json", "type": "application/" - "vnd.openstack.compute-v1.0+json" - } - ] - } + "vnd.openstack.compute-v1.0+json", + }, + ], + }, } self.assertEqual(expected, version) @@ -196,34 +196,34 @@ class VersionsTest(test.TestCase): "links": [ { "rel": "self", - "href": "http://localhost/v1.1/" + "href": "http://localhost/v1.1/", }, { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" - } + "servers/api/v1.1/application.wadl", + }, ], "media-types": [ { "base": "application/xml", - "type": "application/" - "vnd.openstack.compute-v1.1+xml" + "type": "application/", + "vnd.openstack.compute-v1.1+xml", }, { "base": "application/json", "type": "application/" - "vnd.openstack.compute-v1.1+json" - } - ] - } + "vnd.openstack.compute-v1.1+json", + }, + ], + }, } self.assertEqual(expected, version) @@ -739,30 +739,30 @@ class VersionsSerializerTests(test.TestCase): "links": [ { "rel": "self", - "href": "http://localhost/v1.0/" + "href": "http://localhost/v1.0/", }, { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/cs-devguide-20110125.pdf" + "servers/api/v1.0/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.0/application.wadl" + "servers/api/v1.0/application.wadl", }, ], "media-types": [ { "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.0+xml" + "type": "application/vnd.openstack.compute-v1.0+xml", }, { "base": "application/json", - "type": "application/vnd.openstack.compute-v1.0+json" - } + "type": "application/vnd.openstack.compute-v1.0+json", + }, ], }, } @@ -874,29 +874,29 @@ class VersionsSerializerTests(test.TestCase): "links": [ { "rel": "self", - "href": "http://localhost/v1.1/" + "href": "http://localhost/v1.1/", }, { "rel": "describedby", "type": "application/pdf", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/cs-devguide-20110125.pdf" + "servers/api/v1.1/cs-devguide-20110125.pdf", }, { "rel": "describedby", "type": "application/vnd.sun.wadl+xml", "href": "http://docs.rackspacecloud.com/" - "servers/api/v1.1/application.wadl" + "servers/api/v1.1/application.wadl", }, ], "media-types": [ { "base": "application/xml", - "type": "application/vnd.openstack.compute-v1.1+xml" + "type": "application/vnd.openstack.compute-v1.1+xml", }, { "base": "application/json", - "type": "application/vnd.openstack.compute-v1.1+json" + "type": "application/vnd.openstack.compute-v1.1+json", } ], }, -- cgit From 736a18ad49b535ce9d935bbe8c3d8e67f73a4d15 Mon Sep 17 00:00:00 2001 From: Jason Koelker Date: Wed, 3 Aug 2011 08:57:27 -0500 Subject: whoops, got a little comma crazy --- nova/tests/api/openstack/test_versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 7482368f9..1269f13c9 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -214,7 +214,7 @@ class VersionsTest(test.TestCase): "media-types": [ { "base": "application/xml", - "type": "application/", + "type": "application/" "vnd.openstack.compute-v1.1+xml", }, { -- cgit From cb3bc75b316281866eaf32040dccc3fc3be257c2 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 3 Aug 2011 10:03:15 -0400 Subject: PEP8 issue --- nova/api/openstack/create_instance_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index a2d18d37e..333994fcc 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -92,7 +92,7 @@ class CreateInstanceHelper(object): image_href = self.controller._image_ref_from_req_data(body) # If the image href was generated by nova api, strip image_href # down to an id and use the default glance connection params - + if str(image_href).startswith(req.application_url): image_href = image_href.split('/').pop() try: -- cgit From 6166415d03db8f7af93778bdf7a735fb81e63fc5 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 3 Aug 2011 15:50:29 +0000 Subject: Default dns to '' if not present --- nova/virt/xenapi/vm_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 60ef0df43..e08acbedc 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -1092,6 +1092,8 @@ def _prepare_injectables(inst, networks_info): ip_v6 = info['ip6s'][0] if len(info['dns']) > 0: dns = info['dns'][0] + else: + dns = '' interface_info = {'name': 'eth%d' % ifc_num, 'address': ip_v4 and ip_v4['ip'] or '', 'netmask': ip_v4 and ip_v4['netmask'] or '', -- cgit From 5027838724a5adfd0e15c4a10be723f03b6bbbae Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Wed, 3 Aug 2011 11:48:50 -0500 Subject: Removes extraneous body argument from server controller methods --- nova/api/openstack/create_instance_helper.py | 2 +- nova/api/openstack/servers.py | 12 ++++++------ nova/tests/api/openstack/test_servers.py | 24 ------------------------ 3 files changed, 7 insertions(+), 31 deletions(-) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index a2d18d37e..333994fcc 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -92,7 +92,7 @@ class CreateInstanceHelper(object): image_href = self.controller._image_ref_from_req_data(body) # If the image href was generated by nova api, strip image_href # down to an id and use the default glance connection params - + if str(image_href).startswith(req.application_url): image_href = image_href.split('/').pop() try: diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 002b47edb..d17714371 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -328,7 +328,7 @@ class Controller(object): return webob.Response(status_int=202) @scheduler_api.redirect_handler - def reset_network(self, req, id, body): + def reset_network(self, req, id): """ Reset networking on an instance (admin only). @@ -343,7 +343,7 @@ class Controller(object): return webob.Response(status_int=202) @scheduler_api.redirect_handler - def inject_network_info(self, req, id, body): + def inject_network_info(self, req, id): """ Inject network info for an instance (admin only). @@ -358,7 +358,7 @@ class Controller(object): return webob.Response(status_int=202) @scheduler_api.redirect_handler - def pause(self, req, id, body): + def pause(self, req, id): """ Permit Admins to Pause the server. """ ctxt = req.environ['nova.context'] try: @@ -370,7 +370,7 @@ class Controller(object): return webob.Response(status_int=202) @scheduler_api.redirect_handler - def unpause(self, req, id, body): + def unpause(self, req, id): """ Permit Admins to Unpause the server. """ ctxt = req.environ['nova.context'] try: @@ -382,7 +382,7 @@ class Controller(object): return webob.Response(status_int=202) @scheduler_api.redirect_handler - def suspend(self, req, id, body): + def suspend(self, req, id): """permit admins to suspend the server""" context = req.environ['nova.context'] try: @@ -394,7 +394,7 @@ class Controller(object): return webob.Response(status_int=202) @scheduler_api.redirect_handler - def resume(self, req, id, body): + def resume(self, req, id): """permit admins to resume the server from suspend""" context = req.environ['nova.context'] try: diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 4d42972c1..7062b0982 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -1756,74 +1756,50 @@ class ServersTest(test.TestCase): def test_server_pause(self): self.flags(allow_admin_api=True) - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) req = webob.Request.blank('/v1.0/servers/1/pause') req.method = 'POST' req.content_type = 'application/json' - req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) def test_server_unpause(self): self.flags(allow_admin_api=True) - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) req = webob.Request.blank('/v1.0/servers/1/unpause') req.method = 'POST' req.content_type = 'application/json' - req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) def test_server_suspend(self): self.flags(allow_admin_api=True) - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) req = webob.Request.blank('/v1.0/servers/1/suspend') req.method = 'POST' req.content_type = 'application/json' - req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) def test_server_resume(self): self.flags(allow_admin_api=True) - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) req = webob.Request.blank('/v1.0/servers/1/resume') req.method = 'POST' req.content_type = 'application/json' - req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) def test_server_reset_network(self): self.flags(allow_admin_api=True) - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) req = webob.Request.blank('/v1.0/servers/1/reset_network') req.method = 'POST' req.content_type = 'application/json' - req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) def test_server_inject_network_info(self): self.flags(allow_admin_api=True) - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) req = webob.Request.blank( '/v1.0/servers/1/inject_network_info') req.method = 'POST' req.content_type = 'application/json' - req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) -- cgit From 4d500af8bdb4eda2d6040b54c217905cd7ed8bff Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 09:56:37 -0700 Subject: fix use of FLAGS in openstack API servers tests to use the new way --- nova/tests/api/openstack/test_servers.py | 35 +++++++++++++------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 4d42972c1..e927e6612 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -26,7 +26,6 @@ import webob from nova import context from nova import db from nova import exception -from nova import flags from nova import test from nova import utils import nova.api.openstack @@ -46,10 +45,6 @@ from nova.tests.api.openstack import common from nova.tests.api.openstack import fakes -FLAGS = flags.FLAGS -FLAGS.verbose = True - - FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' @@ -269,8 +264,6 @@ class ServersTest(test.TestCase): self.sent_to_glance = {} fakes.stub_out_glance_add_image(self.stubs, self.sent_to_glance) - self.allow_admin = FLAGS.allow_admin_api - self.webreq = common.webob_factory('/v1.0/servers') def test_get_server_by_id(self): @@ -767,7 +760,7 @@ class ServersTest(test.TestCase): self.assertEquals(ip.getAttribute('addr'), private) def test_get_server_by_id_with_addresses_v1_1(self): - FLAGS.use_ipv6 = True + self.flags(use_ipv6=True) interfaces = [ { 'network': {'label': 'network_1'}, @@ -811,7 +804,7 @@ class ServersTest(test.TestCase): self.assertEqual(addresses, expected) def test_get_server_by_id_with_addresses_v1_1_ipv6_disabled(self): - FLAGS.use_ipv6 = False + self.flags(use_ipv6=False) interfaces = [ { 'network': {'label': 'network_1'}, @@ -854,7 +847,7 @@ class ServersTest(test.TestCase): self.assertEqual(addresses, expected) def test_get_server_addresses_v1_1(self): - FLAGS.use_ipv6 = True + self.flags(use_ipv6=True) interfaces = [ { 'network': {'label': 'network_1'}, @@ -905,7 +898,7 @@ class ServersTest(test.TestCase): self.assertEqual(res_dict, expected) def test_get_server_addresses_single_network_v1_1(self): - FLAGS.use_ipv6 = True + self.flags(use_ipv6=True) interfaces = [ { 'network': {'label': 'network_1'}, @@ -2329,7 +2322,7 @@ class ServersTest(test.TestCase): """ req = self.webreq('/1/migrate', 'POST') - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) self.resize_called = False def resize_mock(*args): @@ -2344,7 +2337,7 @@ class ServersTest(test.TestCase): def test_migrate_server_no_admin_api_fails(self): req = self.webreq('/1/migrate', 'POST') - FLAGS.allow_admin_api = False + self.flags(allow_admin_api=False) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 404) @@ -2425,7 +2418,7 @@ class ServersTest(test.TestCase): def test_create_backup(self): """The happy path for creating backups""" - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = { 'createBackup': { @@ -2445,7 +2438,7 @@ class ServersTest(test.TestCase): def test_create_backup_v1_1(self): """The happy path for creating backups through v1.1 api""" - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = { 'createBackup': { @@ -2465,7 +2458,7 @@ class ServersTest(test.TestCase): def test_create_backup_admin_api_off(self): """The happy path for creating backups""" - FLAGS.allow_admin_api = False + self.flags(allow_admin_api=False) body = { 'createBackup': { @@ -2483,7 +2476,7 @@ class ServersTest(test.TestCase): self.assertEqual(501, response.status_int) def test_create_backup_with_metadata(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = { 'createBackup': { @@ -2504,7 +2497,7 @@ class ServersTest(test.TestCase): def test_create_backup_no_name(self): """Name is required for backups""" - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = { 'createBackup': { @@ -2522,7 +2515,7 @@ class ServersTest(test.TestCase): def test_create_backup_no_rotation(self): """Rotation is required for backup requests""" - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = { 'createBackup': { @@ -2541,7 +2534,7 @@ class ServersTest(test.TestCase): def test_create_backup_no_backup_type(self): """Backup Type (daily or weekly) is required for backup requests""" - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = { 'createBackup': { @@ -2558,7 +2551,7 @@ class ServersTest(test.TestCase): self.assertEqual(400, response.status_int) def test_create_backup_bad_entity(self): - FLAGS.allow_admin_api = True + self.flags(allow_admin_api=True) body = {'createBackup': 'go'} req = webob.Request.blank('/v1.0/images') -- cgit From d7f704876f5cfab165c855170468274e57935d15 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 10:11:20 -0700 Subject: more cleanup of API tests regarding FLAGS --- nova/test.py | 6 ++++++ nova/tests/api/openstack/test_accounts.py | 6 +----- nova/tests/api/openstack/test_adminapi.py | 5 +---- nova/tests/api/openstack/test_extensions.py | 2 -- nova/tests/api/openstack/test_flavors_extra_specs.py | 3 --- nova/tests/api/openstack/test_images.py | 8 +------- nova/tests/api/openstack/test_servers.py | 1 + nova/tests/api/openstack/test_users.py | 7 +------ nova/tests/api/openstack/test_zones.py | 2 +- 9 files changed, 12 insertions(+), 28 deletions(-) diff --git a/nova/test.py b/nova/test.py index 549aa6fcf..804dc8c37 100644 --- a/nova/test.py +++ b/nova/test.py @@ -100,6 +100,7 @@ class TestCase(unittest.TestCase): self.injected = [] self._services = [] self._original_flags = FLAGS.FlagValuesDict() + self._original_flags_verbosity = FLAGS.verbose def tearDown(self): """Runs after each test method to tear down test environment.""" @@ -157,6 +158,11 @@ class TestCase(unittest.TestCase): FLAGS.Reset() for k, v in self._original_flags.iteritems(): setattr(FLAGS, k, v) + FLAGS.verbose = self._original_flags_verbosity + + def set_flags_verbosity(self, verbose=True): + """Set the FLAGS verbosity for a test""" + FLAGS.verbose = verbose def start_service(self, name, host=None, **kwargs): host = host and host or uuid.uuid4().hex diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index 89dbf5213..b1ca546d2 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -18,17 +18,12 @@ import json import webob -from nova import flags from nova import test from nova.api.openstack import accounts from nova.auth.manager import User from nova.tests.api.openstack import fakes -FLAGS = flags.FLAGS -FLAGS.verbose = True - - def fake_init(self): self.manager = fakes.FakeAuthManager() @@ -41,6 +36,7 @@ class AccountsTest(test.TestCase): def setUp(self): super(AccountsTest, self).setUp() self.flags(allow_admin_api=True) + self.set_flags_verbosity(True) self.stubs.Set(accounts.Controller, '__init__', fake_init) self.stubs.Set(accounts.Controller, '_check_admin', diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index b83de40cf..9d03a7f9d 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -18,12 +18,9 @@ import webob -from nova import flags from nova import test from nova.tests.api.openstack import fakes -FLAGS = flags.FLAGS - class AdminAPITest(test.TestCase): @@ -31,7 +28,7 @@ class AdminAPITest(test.TestCase): super(AdminAPITest, self).setUp() fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - self.allow_admin = FLAGS.allow_admin_api + self.set_flags_verbosity(True) def test_admin_enabled(self): self.flags(allow_admin_api=True) diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 47c37225c..409fa0e71 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -21,7 +21,6 @@ import webob from xml.etree import ElementTree from nova import context -from nova import flags from nova import test from nova.api import openstack from nova.api.openstack import extensions @@ -29,7 +28,6 @@ from nova.api.openstack import flavors from nova.api.openstack import wsgi from nova.tests.api.openstack import fakes -FLAGS = flags.FLAGS NS = "{http://docs.openstack.org/compute/api/v1.1}" ATOMNS = "{http://www.w3.org/2005/Atom}" response_body = "Try to say this Mr. Knox, sir..." diff --git a/nova/tests/api/openstack/test_flavors_extra_specs.py b/nova/tests/api/openstack/test_flavors_extra_specs.py index d386958db..ccd1b0d9f 100644 --- a/nova/tests/api/openstack/test_flavors_extra_specs.py +++ b/nova/tests/api/openstack/test_flavors_extra_specs.py @@ -21,15 +21,12 @@ import webob import os.path -from nova import flags from nova import test from nova.api import openstack from nova.api.openstack import extensions from nova.tests.api.openstack import fakes import nova.wsgi -FLAGS = flags.FLAGS - def return_create_flavor_extra_specs(context, flavor_id, extra_specs): return stub_flavor_extra_specs() diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 942c0b333..38cfc287c 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -34,7 +34,6 @@ import webob from glance import client as glance_client from nova import context from nova import exception -from nova import flags from nova import test from nova import utils import nova.api.openstack @@ -42,9 +41,6 @@ from nova.api.openstack import images from nova.tests.api.openstack import fakes -FLAGS = flags.FLAGS - - class _BaseImageServiceTests(test.TestCase): """Tasks to test for all image services""" @@ -328,8 +324,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): def setUp(self): """Run before each test.""" super(ImageControllerWithGlanceServiceTest, self).setUp() - self.orig_image_service = FLAGS.image_service - FLAGS.image_service = 'nova.image.glance.GlanceImageService' + self.flags(image_service='nova.image.glance.GlanceImageService') self.stubs = stubout.StubOutForTesting() fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) @@ -342,7 +337,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): def tearDown(self): """Run after each test.""" self.stubs.UnsetAll() - FLAGS.image_service = self.orig_image_service super(ImageControllerWithGlanceServiceTest, self).tearDown() def _applicable_fixture(self, fixture, user_id): diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index e927e6612..796c494d4 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -230,6 +230,7 @@ class ServersTest(test.TestCase): def setUp(self): self.maxDiff = None super(ServersTest, self).setUp() + self.set_flags_verbosity(True) fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index 705c02f6b..649538f11 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -17,7 +17,6 @@ import json import webob -from nova import flags from nova import test from nova import utils from nova.api.openstack import users @@ -25,10 +24,6 @@ from nova.auth.manager import User, Project from nova.tests.api.openstack import fakes -FLAGS = flags.FLAGS -FLAGS.verbose = True - - def fake_init(self): self.manager = fakes.FakeAuthManager() @@ -41,6 +36,7 @@ class UsersTest(test.TestCase): def setUp(self): super(UsersTest, self).setUp() self.flags(allow_admin_api=True) + self.set_flags_verbosity(True) self.stubs.Set(users.Controller, '__init__', fake_init) self.stubs.Set(users.Controller, '_check_admin', @@ -56,7 +52,6 @@ class UsersTest(test.TestCase): fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) - self.allow_admin = FLAGS.allow_admin_api fakemgr = fakes.FakeAuthManager() fakemgr.add_user(User('id1', 'guy1', 'acc1', 'secret1', False)) fakemgr.add_user(User('id2', 'guy2', 'acc2', 'secret2', True)) diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 3deb844aa..442ee4313 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -29,7 +29,6 @@ from nova.scheduler import api FLAGS = flags.FLAGS -FLAGS.verbose = True def zone_get(context, zone_id): @@ -96,6 +95,7 @@ class ZonesTest(test.TestCase): def setUp(self): super(ZonesTest, self).setUp() self.flags(allow_admin_api=True) + self.set_flags_verbosity(True) fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) -- cgit From 8efe41aaa4993d0aa9ad381d202ba7b7d025939e Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 12:22:58 -0700 Subject: switch FLAGS.* = in tests to self.flags(...) remove unused cases of FLAGS from tests modified test.TestCase's flags() to allow multiple overrides added missing license to test_rpc_amqp.py --- nova/test.py | 8 +++----- nova/tests/hyperv_unittest.py | 5 +---- nova/tests/test_auth.py | 4 ++-- nova/tests/test_host_filter.py | 12 +++--------- nova/tests/test_ipv6.py | 3 --- nova/tests/test_libvirt.py | 23 +++++++++-------------- nova/tests/test_network.py | 2 -- nova/tests/test_quota.py | 42 +++++++++++++++++------------------------- nova/tests/test_rpc.py | 2 -- nova/tests/test_rpc_amqp.py | 24 ++++++++++++++++++++++-- nova/tests/test_service.py | 1 - nova/tests/test_xenapi.py | 12 ++++++------ 12 files changed, 63 insertions(+), 75 deletions(-) diff --git a/nova/test.py b/nova/test.py index 804dc8c37..fa5a662fd 100644 --- a/nova/test.py +++ b/nova/test.py @@ -142,11 +142,9 @@ class TestCase(unittest.TestCase): def flags(self, **kw): """Override flag variables for a test.""" for k, v in kw.iteritems(): - if k in self.flag_overrides: - self.reset_flags() - raise Exception( - 'trying to override already overriden flag: %s' % k) - self.flag_overrides[k] = getattr(FLAGS, k) + # Store original flag value if it's not been overriden yet + if k not in self.flag_overrides: + self.flag_overrides[k] = getattr(FLAGS, k) setattr(FLAGS, k, v) def reset_flags(self): diff --git a/nova/tests/hyperv_unittest.py b/nova/tests/hyperv_unittest.py index 0ea196950..d346d0a70 100644 --- a/nova/tests/hyperv_unittest.py +++ b/nova/tests/hyperv_unittest.py @@ -21,13 +21,9 @@ import random from nova import context from nova import db -from nova import flags from nova import test from nova.virt import hyperv -FLAGS = flags.FLAGS -FLAGS.connection_type = 'hyperv' - class HyperVTestCase(test.TestCase): """Test cases for the Hyper-V driver""" @@ -36,6 +32,7 @@ class HyperVTestCase(test.TestCase): self.user_id = 'fake' self.project_id = 'fake' self.context = context.RequestContext(self.user_id, self.project_id) + self.flags(connection_type='hyperv') def test_create_destroy(self): """Create a VM and destroy it""" diff --git a/nova/tests/test_auth.py b/nova/tests/test_auth.py index 7c0f783bb..2e24b7d6e 100644 --- a/nova/tests/test_auth.py +++ b/nova/tests/test_auth.py @@ -83,9 +83,9 @@ class user_and_project_generator(object): class _AuthManagerBaseTestCase(test.TestCase): def setUp(self): - FLAGS.auth_driver = self.auth_driver super(_AuthManagerBaseTestCase, self).setUp() - self.flags(connection_type='fake') + self.flags(auth_driver=self.auth_driver, + connection_type='fake') self.manager = manager.AuthManager(new=True) self.manager.mc.cache = {} diff --git a/nova/tests/test_host_filter.py b/nova/tests/test_host_filter.py index 438f3e522..3a1389a49 100644 --- a/nova/tests/test_host_filter.py +++ b/nova/tests/test_host_filter.py @@ -19,12 +19,9 @@ Tests For Scheduler Host Filters. import json from nova import exception -from nova import flags from nova import test from nova.scheduler import host_filter -FLAGS = flags.FLAGS - class FakeZoneManager: pass @@ -57,9 +54,9 @@ class HostFilterTestCase(test.TestCase): 'host_name-label': 'xs-%s' % multiplier} def setUp(self): - self.old_flag = FLAGS.default_host_filter - FLAGS.default_host_filter = \ - 'nova.scheduler.host_filter.AllHostsFilter' + super(HostFilterTestCase, self).setUp() + default_host_filter = 'nova.scheduler.host_filter.AllHostsFilter' + self.flags(default_host_filter=default_host_filter) self.instance_type = dict(name='tiny', memory_mb=50, vcpus=10, @@ -76,9 +73,6 @@ class HostFilterTestCase(test.TestCase): states['host%02d' % (x + 1)] = {'compute': self._host_caps(x)} self.zone_manager.service_states = states - def tearDown(self): - FLAGS.default_host_filter = self.old_flag - def test_choose_filter(self): # Test default filter ... hf = host_filter.choose_host_filter() diff --git a/nova/tests/test_ipv6.py b/nova/tests/test_ipv6.py index 11dc2ec98..d123df6f1 100644 --- a/nova/tests/test_ipv6.py +++ b/nova/tests/test_ipv6.py @@ -16,15 +16,12 @@ """Test suite for IPv6.""" -from nova import flags from nova import ipv6 from nova import log as logging from nova import test LOG = logging.getLogger('nova.tests.test_ipv6') -FLAGS = flags.FLAGS - import sys diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index cf25ce215..f8b866985 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -38,7 +38,6 @@ from nova.virt.libvirt import firewall libvirt = None FLAGS = flags.FLAGS -flags.DECLARE('instances_path', 'nova.compute.manager') def _concurrency(wait, done, target): @@ -93,6 +92,7 @@ def _setup_networking(instance_id, ip='1.2.3.4'): class CacheConcurrencyTestCase(test.TestCase): def setUp(self): super(CacheConcurrencyTestCase, self).setUp() + self.flags(instances_path='nova.compute.manager') def fake_exists(fname): basedir = os.path.join(FLAGS.instances_path, '_base') @@ -158,7 +158,7 @@ class LibvirtConnTestCase(test.TestCase): self.context = context.RequestContext(self.user_id, self.project_id) self.network = utils.import_object(FLAGS.network_manager) self.context = context.get_admin_context() - FLAGS.instances_path = '' + self.flags(instances_path='') self.call_libvirt_dependant_setup = False self.test_ip = '10.11.12.13' @@ -322,7 +322,7 @@ class LibvirtConnTestCase(test.TestCase): if not self.lazy_load_library_exists(): return - FLAGS.image_service = 'nova.image.fake.FakeImageService' + self.flags(image_service='nova.image.fake.FakeImageService') # Start test image_service = utils.import_object(FLAGS.image_service) @@ -357,7 +357,7 @@ class LibvirtConnTestCase(test.TestCase): if not self.lazy_load_library_exists(): return - FLAGS.image_service = 'nova.image.fake.FakeImageService' + self.flags(image_service='nova.image.fake.FakeImageService') # Start test image_service = utils.import_object(FLAGS.image_service) @@ -521,7 +521,7 @@ class LibvirtConnTestCase(test.TestCase): 'disk.local')] for (libvirt_type, (expected_uri, checks)) in type_uri_map.iteritems(): - FLAGS.libvirt_type = libvirt_type + self.flags(libvirt_type=libvirt_type) conn = connection.LibvirtConnection(True) uri = conn.get_uri() @@ -546,9 +546,9 @@ class LibvirtConnTestCase(test.TestCase): # checking against that later on. This way we make sure the # implementation doesn't fiddle around with the FLAGS. testuri = 'something completely different' - FLAGS.libvirt_uri = testuri + self.flags(libvirt_uri=testuri) for (libvirt_type, (expected_uri, checks)) in type_uri_map.iteritems(): - FLAGS.libvirt_type = libvirt_type + self.flags(libvirt_type=libvirt_type) conn = connection.LibvirtConnection(True) uri = conn.get_uri() self.assertEquals(uri, testuri) @@ -556,8 +556,7 @@ class LibvirtConnTestCase(test.TestCase): def test_update_available_resource_works_correctly(self): """Confirm compute_node table is updated successfully.""" - org_path = FLAGS.instances_path = '' - FLAGS.instances_path = '.' + self.flags(instances_path='.') # Prepare mocks def getVersion(): @@ -604,12 +603,10 @@ class LibvirtConnTestCase(test.TestCase): self.assertTrue(compute_node['hypervisor_version'] > 0) db.service_destroy(self.context, service_ref['id']) - FLAGS.instances_path = org_path def test_update_resource_info_no_compute_record_found(self): """Raise exception if no recorde found on services table.""" - org_path = FLAGS.instances_path = '' - FLAGS.instances_path = '.' + self.flags(instances_path='.') self.create_fake_libvirt_mock() self.mox.ReplayAll() @@ -618,8 +615,6 @@ class LibvirtConnTestCase(test.TestCase): conn.update_available_resource, self.context, 'dummy') - FLAGS.instances_path = org_path - def test_ensure_filtering_rules_for_instance_timeout(self): """ensure_filtering_fules_for_instance() finishes with timeout.""" # Skip if non-libvirt environment diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 28f50d328..2ca8b64f4 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -17,7 +17,6 @@ from nova import db from nova import exception -from nova import flags from nova import log as logging from nova import test from nova.network import manager as network_manager @@ -26,7 +25,6 @@ from nova.network import manager as network_manager import mox -FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.network') diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 92393b536..f4b481ebe 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -114,9 +114,7 @@ class QuotaTestCase(test.TestCase): db.quota_destroy_all_by_project(self.context, self.project_id) def test_unlimited_instances(self): - FLAGS.quota_instances = 2 - FLAGS.quota_ram = -1 - FLAGS.quota_cores = -1 + self.flags(quota_instances=2, quota_ram=-1, quota_cores=-1) instance_type = self._get_instance_type('m1.small') num_instances = quota.allowed_instances(self.context, 100, instance_type) @@ -130,9 +128,7 @@ class QuotaTestCase(test.TestCase): self.assertEqual(num_instances, 101) def test_unlimited_ram(self): - FLAGS.quota_instances = -1 - FLAGS.quota_ram = 2 * 2048 - FLAGS.quota_cores = -1 + self.flags(quota_instances=-1, quota_ram=2 * 2048, quota_cores=-1) instance_type = self._get_instance_type('m1.small') num_instances = quota.allowed_instances(self.context, 100, instance_type) @@ -146,9 +142,7 @@ class QuotaTestCase(test.TestCase): self.assertEqual(num_instances, 101) def test_unlimited_cores(self): - FLAGS.quota_instances = -1 - FLAGS.quota_ram = -1 - FLAGS.quota_cores = 2 + self.flags(quota_instances=-1, quota_ram=-1, quota_cores=2) instance_type = self._get_instance_type('m1.small') num_instances = quota.allowed_instances(self.context, 100, instance_type) @@ -162,8 +156,7 @@ class QuotaTestCase(test.TestCase): self.assertEqual(num_instances, 101) def test_unlimited_volumes(self): - FLAGS.quota_volumes = 10 - FLAGS.quota_gigabytes = -1 + self.flags(quota_volumes=10, quota_gigabytes=-1) volumes = quota.allowed_volumes(self.context, 100, 1) self.assertEqual(volumes, 10) db.quota_create(self.context, self.project_id, 'volumes', None) @@ -173,8 +166,7 @@ class QuotaTestCase(test.TestCase): self.assertEqual(volumes, 101) def test_unlimited_gigabytes(self): - FLAGS.quota_volumes = -1 - FLAGS.quota_gigabytes = 10 + self.flags(quota_volumes=-1, quota_gigabytes=10) volumes = quota.allowed_volumes(self.context, 100, 1) self.assertEqual(volumes, 10) db.quota_create(self.context, self.project_id, 'gigabytes', None) @@ -184,7 +176,7 @@ class QuotaTestCase(test.TestCase): self.assertEqual(volumes, 101) def test_unlimited_floating_ips(self): - FLAGS.quota_floating_ips = 10 + self.flags(quota_floating_ips=10) floating_ips = quota.allowed_floating_ips(self.context, 100) self.assertEqual(floating_ips, 10) db.quota_create(self.context, self.project_id, 'floating_ips', None) @@ -194,7 +186,7 @@ class QuotaTestCase(test.TestCase): self.assertEqual(floating_ips, 101) def test_unlimited_metadata_items(self): - FLAGS.quota_metadata_items = 10 + self.flags(quota_metadata_items=10) items = quota.allowed_metadata_items(self.context, 100) self.assertEqual(items, 10) db.quota_create(self.context, self.project_id, 'metadata_items', None) @@ -286,49 +278,49 @@ class QuotaTestCase(test.TestCase): metadata=metadata) def test_default_allowed_injected_files(self): - FLAGS.quota_max_injected_files = 55 + self.flags(quota_max_injected_files=55) self.assertEqual(quota.allowed_injected_files(self.context, 100), 55) def test_overridden_allowed_injected_files(self): - FLAGS.quota_max_injected_files = 5 + self.flags(quota_max_injected_files=5) db.quota_create(self.context, self.project_id, 'injected_files', 77) self.assertEqual(quota.allowed_injected_files(self.context, 100), 77) def test_unlimited_default_allowed_injected_files(self): - FLAGS.quota_max_injected_files = -1 + self.flags(quota_max_injected_files=-1) self.assertEqual(quota.allowed_injected_files(self.context, 100), 100) def test_unlimited_db_allowed_injected_files(self): - FLAGS.quota_max_injected_files = 5 + self.flags(quota_max_injected_files=5) db.quota_create(self.context, self.project_id, 'injected_files', None) self.assertEqual(quota.allowed_injected_files(self.context, 100), 100) def test_default_allowed_injected_file_content_bytes(self): - FLAGS.quota_max_injected_file_content_bytes = 12345 + self.flags(quota_max_injected_file_content_bytes=12345) limit = quota.allowed_injected_file_content_bytes(self.context, 23456) self.assertEqual(limit, 12345) def test_overridden_allowed_injected_file_content_bytes(self): - FLAGS.quota_max_injected_file_content_bytes = 12345 + self.flags(quota_max_injected_file_content_bytes=12345) db.quota_create(self.context, self.project_id, 'injected_file_content_bytes', 5678) limit = quota.allowed_injected_file_content_bytes(self.context, 23456) self.assertEqual(limit, 5678) def test_unlimited_default_allowed_injected_file_content_bytes(self): - FLAGS.quota_max_injected_file_content_bytes = -1 + self.flags(quota_max_injected_file_content_bytes=-1) limit = quota.allowed_injected_file_content_bytes(self.context, 23456) self.assertEqual(limit, 23456) def test_unlimited_db_allowed_injected_file_content_bytes(self): - FLAGS.quota_max_injected_file_content_bytes = 12345 + self.flags(quota_max_injected_file_content_bytes=12345) db.quota_create(self.context, self.project_id, 'injected_file_content_bytes', None) limit = quota.allowed_injected_file_content_bytes(self.context, 23456) self.assertEqual(limit, 23456) def _create_with_injected_files(self, files): - FLAGS.image_service = 'nova.image.fake.FakeImageService' + self.flags(image_service='nova.image.fake.FakeImageService') api = compute.API(image_service=self.StubImageService()) inst_type = instance_types.get_instance_type_by_name('m1.small') api.create(self.context, min_count=1, max_count=1, @@ -336,7 +328,7 @@ class QuotaTestCase(test.TestCase): injected_files=files) def test_no_injected_files(self): - FLAGS.image_service = 'nova.image.fake.FakeImageService' + self.flags(image_service='nova.image.fake.FakeImageService') api = compute.API(image_service=self.StubImageService()) inst_type = instance_types.get_instance_type_by_name('m1.small') api.create(self.context, instance_type=inst_type, image_href='3') diff --git a/nova/tests/test_rpc.py b/nova/tests/test_rpc.py index 2d2436175..ba9c0a859 100644 --- a/nova/tests/test_rpc.py +++ b/nova/tests/test_rpc.py @@ -20,13 +20,11 @@ Unit Tests for remote procedure calls using queue """ from nova import context -from nova import flags from nova import log as logging from nova import rpc from nova import test -FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.rpc') diff --git a/nova/tests/test_rpc_amqp.py b/nova/tests/test_rpc_amqp.py index d29f7ae32..2215a908b 100644 --- a/nova/tests/test_rpc_amqp.py +++ b/nova/tests/test_rpc_amqp.py @@ -1,12 +1,32 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2010 Openstack, LLC. +# 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. + +""" +Tests For RPC AMQP. +""" + from nova import context -from nova import flags from nova import log as logging from nova import rpc from nova.rpc import amqp from nova import test -FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.rpc') diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index bbf47b50f..8f92406ff 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -33,7 +33,6 @@ from nova import manager from nova import wsgi from nova.compute import manager as compute_manager -FLAGS = flags.FLAGS flags.DEFINE_string("fake_manager", "nova.tests.test_service.FakeManager", "Manager for testing") diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index a795b3c74..1ba2bf356 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -71,9 +71,9 @@ class XenAPIVolumeTestCase(test.TestCase): self.user_id = 'fake' self.project_id = 'fake' self.context = context.RequestContext(self.user_id, self.project_id) - FLAGS.target_host = '127.0.0.1' - FLAGS.xenapi_connection_url = 'test_url' - FLAGS.xenapi_connection_password = 'test_pass' + self.flags(target_host='127.0.0.1', + xenapi_connection_url='test_url', + xenapi_connection_password='test_pass') db_fakes.stub_out_db_instance_api(self.stubs) stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() @@ -719,9 +719,9 @@ class XenAPIMigrateInstance(test.TestCase): def setUp(self): super(XenAPIMigrateInstance, self).setUp() self.stubs = stubout.StubOutForTesting() - FLAGS.target_host = '127.0.0.1' - FLAGS.xenapi_connection_url = 'test_url' - FLAGS.xenapi_connection_password = 'test_pass' + self.flags(target_host='127.0.0.1', + xenapi_connection_url='test_url', + xenapi_connection_password='test_pass') db_fakes.stub_out_db_instance_api(self.stubs) stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() -- cgit From 25655e0bcea99ea27108d954104138a09f922f30 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 12:26:51 -0700 Subject: fix test_s3 FLAGS uses --- nova/tests/api/openstack/__init__.py | 3 --- nova/tests/image/test_s3.py | 10 +--------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/nova/tests/api/openstack/__init__.py b/nova/tests/api/openstack/__init__.py index bfb424afe..458434a81 100644 --- a/nova/tests/api/openstack/__init__.py +++ b/nova/tests/api/openstack/__init__.py @@ -22,14 +22,11 @@ import webob.dec from nova import test from nova import context -from nova import flags from nova.api.openstack.limits import RateLimitingMiddleware from nova.api.openstack.common import limited from nova.tests.api.openstack import fakes from webob import Request -FLAGS = flags.FLAGS - @webob.dec.wsgify def simple_wsgi(req): diff --git a/nova/tests/image/test_s3.py b/nova/tests/image/test_s3.py index 231e109f8..f1ceeb7fe 100644 --- a/nova/tests/image/test_s3.py +++ b/nova/tests/image/test_s3.py @@ -16,12 +16,9 @@ # under the License. from nova import context -from nova import flags from nova import test from nova.image import s3 -FLAGS = flags.FLAGS - ami_manifest_xml = """ @@ -59,15 +56,10 @@ ami_manifest_xml = """ class TestS3ImageService(test.TestCase): def setUp(self): super(TestS3ImageService, self).setUp() - self.orig_image_service = FLAGS.image_service - FLAGS.image_service = 'nova.image.fake.FakeImageService' + self.flags(image_service='nova.image.fake.FakeImageService') self.image_service = s3.S3ImageService() self.context = context.RequestContext(None, None) - def tearDown(self): - super(TestS3ImageService, self).tearDown() - FLAGS.image_service = self.orig_image_service - def _assertEqualList(self, list0, list1, keys): self.assertEqual(len(list0), len(list1)) key = keys[0] -- cgit From ff5dbc6d985d11ef937baa930ee96c93cbd8ccf9 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 14:06:56 -0700 Subject: fix more tests that use FLAGS setting --- nova/tests/integrated/integrated_helpers.py | 4 +--- nova/tests/integrated/test_extensions.py | 5 ----- nova/tests/integrated/test_login.py | 4 ---- nova/tests/integrated/test_servers.py | 5 ----- nova/tests/integrated/test_volumes.py | 5 ----- nova/tests/integrated/test_xml.py | 5 ----- 6 files changed, 1 insertion(+), 27 deletions(-) diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 47bd8c1e4..049ddbc60 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -23,7 +23,6 @@ import random import string from nova import exception -from nova import flags from nova import service from nova import test # For the flags from nova.auth import manager @@ -32,8 +31,6 @@ from nova.log import logging from nova.tests.integrated.api import client -FLAGS = flags.FLAGS - LOG = logging.getLogger('nova.tests.integrated') @@ -151,6 +148,7 @@ class _IntegratedTestBase(test.TestCase): f = self._get_flags() self.flags(**f) + self.set_flags_verbosity(True) def fake_get_image_service(image_href): image_id = int(str(image_href).split('/')[-1]) diff --git a/nova/tests/integrated/test_extensions.py b/nova/tests/integrated/test_extensions.py index 0d4ee8cab..c22cf0be0 100644 --- a/nova/tests/integrated/test_extensions.py +++ b/nova/tests/integrated/test_extensions.py @@ -17,7 +17,6 @@ import os -from nova import flags from nova.log import logging from nova.tests.integrated import integrated_helpers @@ -25,10 +24,6 @@ from nova.tests.integrated import integrated_helpers LOG = logging.getLogger('nova.tests.integrated') -FLAGS = flags.FLAGS -FLAGS.verbose = True - - class ExtensionsTest(integrated_helpers._IntegratedTestBase): def _get_flags(self): f = super(ExtensionsTest, self)._get_flags() diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index a5180b6bc..06359a52f 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -17,7 +17,6 @@ import unittest -from nova import flags from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client @@ -25,9 +24,6 @@ from nova.tests.integrated.api import client LOG = logging.getLogger('nova.tests.integrated') -FLAGS = flags.FLAGS -FLAGS.verbose = True - class LoginTest(integrated_helpers._IntegratedTestBase): def test_login(self): diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index 67b3c485a..150279a95 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -18,7 +18,6 @@ import time import unittest -from nova import flags from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client @@ -27,10 +26,6 @@ from nova.tests.integrated.api import client LOG = logging.getLogger('nova.tests.integrated') -FLAGS = flags.FLAGS -FLAGS.verbose = True - - class ServersTest(integrated_helpers._IntegratedTestBase): def test_get_servers(self): """Simple check that listing servers works.""" diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index e9fb3c4d1..d3e936462 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -18,7 +18,6 @@ import unittest import time -from nova import flags from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client @@ -28,10 +27,6 @@ from nova.volume import driver LOG = logging.getLogger('nova.tests.integrated') -FLAGS = flags.FLAGS -FLAGS.verbose = True - - class VolumesTest(integrated_helpers._IntegratedTestBase): def setUp(self): super(VolumesTest, self).setUp() diff --git a/nova/tests/integrated/test_xml.py b/nova/tests/integrated/test_xml.py index fde32f797..74baaacc2 100644 --- a/nova/tests/integrated/test_xml.py +++ b/nova/tests/integrated/test_xml.py @@ -15,7 +15,6 @@ # License for the specific language governing permissions and limitations # under the License. -from nova import flags from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.api.openstack import common @@ -24,10 +23,6 @@ from nova.api.openstack import common LOG = logging.getLogger('nova.tests.integrated') -FLAGS = flags.FLAGS -FLAGS.verbose = True - - class XmlTests(integrated_helpers._IntegratedTestBase): """"Some basic XML sanity checks.""" -- cgit From 4f9f56d8e9917f5db0c5f76653d7ee3a2db52a5f Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 14:08:22 -0700 Subject: fix scheduler tests that set FLAGS --- nova/tests/scheduler/test_scheduler.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index 6a56a57db..f60eb6433 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -962,13 +962,10 @@ class ZoneRedirectTest(test.TestCase): self.stubs.Set(db, 'zone_get_all', zone_get_all) self.stubs.Set(db, 'instance_get_by_uuid', fake_instance_get_by_uuid) - - self.enable_zone_routing = FLAGS.enable_zone_routing - FLAGS.enable_zone_routing = True + self.flags(enable_zone_routing=True) def tearDown(self): self.stubs.UnsetAll() - FLAGS.enable_zone_routing = self.enable_zone_routing super(ZoneRedirectTest, self).tearDown() def test_trap_found_locally(self): @@ -998,7 +995,7 @@ class ZoneRedirectTest(test.TestCase): self.assertEquals(e.results['magic'], 'found me') def test_routing_flags(self): - FLAGS.enable_zone_routing = False + self.flags(enable_zone_routing=False) decorator = FakeRerouteCompute("foo") self.assertRaises(exception.InstanceNotFound, decorator(go_boom), None, None, 1) -- cgit From 3765fca2cfd323c047141a27df248d9617d71ad0 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 14:11:37 -0700 Subject: dist scheduler flag setting fixes --- nova/tests/scheduler/test_host_filter.py | 11 ++--------- nova/tests/scheduler/test_least_cost_scheduler.py | 23 +++++++++-------------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/nova/tests/scheduler/test_host_filter.py b/nova/tests/scheduler/test_host_filter.py index b1892dab4..b016923c4 100644 --- a/nova/tests/scheduler/test_host_filter.py +++ b/nova/tests/scheduler/test_host_filter.py @@ -19,12 +19,9 @@ Tests For Scheduler Host Filters. import json from nova import exception -from nova import flags from nova import test from nova.scheduler import host_filter -FLAGS = flags.FLAGS - class FakeZoneManager: pass @@ -57,9 +54,8 @@ class HostFilterTestCase(test.TestCase): 'host_name-label': 'xs-%s' % multiplier} def setUp(self): - self.old_flag = FLAGS.default_host_filter - FLAGS.default_host_filter = \ - 'nova.scheduler.host_filter.AllHostsFilter' + default_host_filter = 'nova.scheduler.host_filter.AllHostsFilter' + self.flags(default_host_filter=default_host_filter) self.instance_type = dict(name='tiny', memory_mb=50, vcpus=10, @@ -98,9 +94,6 @@ class HostFilterTestCase(test.TestCase): host09['xpu_arch'] = 'fermi' host09['xpu_info'] = 'Tesla 2150' - def tearDown(self): - FLAGS.default_host_filter = self.old_flag - def test_choose_filter(self): # Test default filter ... hf = host_filter.choose_host_filter() diff --git a/nova/tests/scheduler/test_least_cost_scheduler.py b/nova/tests/scheduler/test_least_cost_scheduler.py index 49791053e..fbe6b2f77 100644 --- a/nova/tests/scheduler/test_least_cost_scheduler.py +++ b/nova/tests/scheduler/test_least_cost_scheduler.py @@ -16,13 +16,11 @@ Tests For Least Cost Scheduler """ -from nova import flags from nova import test from nova.scheduler import least_cost from nova.tests.scheduler import test_zone_aware_scheduler MB = 1024 * 1024 -FLAGS = flags.FLAGS class FakeHost(object): @@ -95,10 +93,9 @@ class LeastCostSchedulerTestCase(test.TestCase): self.assertWeights(expected, num, request_spec, hosts) def test_noop_cost_fn(self): - FLAGS.least_cost_scheduler_cost_functions = [ - 'nova.scheduler.least_cost.noop_cost_fn', - ] - FLAGS.noop_cost_fn_weight = 1 + self.flags(least_cost_scheduler_cost_functions=[ + 'nova.scheduler.least_cost.noop_cost_fn'], + noop_cost_fn_weight=1) num = 1 request_spec = {} @@ -109,10 +106,9 @@ class LeastCostSchedulerTestCase(test.TestCase): self.assertWeights(expected, num, request_spec, hosts) def test_cost_fn_weights(self): - FLAGS.least_cost_scheduler_cost_functions = [ - 'nova.scheduler.least_cost.noop_cost_fn', - ] - FLAGS.noop_cost_fn_weight = 2 + self.flags(least_cost_scheduler_cost_functions=[ + 'nova.scheduler.least_cost.noop_cost_fn'], + noop_cost_fn_weight=2) num = 1 request_spec = {} @@ -123,10 +119,9 @@ class LeastCostSchedulerTestCase(test.TestCase): self.assertWeights(expected, num, request_spec, hosts) def test_compute_fill_first_cost_fn(self): - FLAGS.least_cost_scheduler_cost_functions = [ - 'nova.scheduler.least_cost.compute_fill_first_cost_fn', - ] - FLAGS.compute_fill_first_cost_fn_weight = 1 + self.flags(least_cost_scheduler_cost_functions=[ + 'nova.scheduler.least_cost.compute_fill_first_cost_fn'], + compute_fill_first_cost_fn_weight=1) num = 1 instance_type = {'memory_mb': 1024} -- cgit From 544eecd0adc2c774e512f5c364f6952fb3fd1155 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Wed, 3 Aug 2011 14:13:37 -0700 Subject: fix test_cloud FLAGS setting --- nova/tests/test_cloud.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 8c1a74c70..e891fa197 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -99,11 +99,9 @@ class CloudTestCase(test.TestCase): """Makes sure describe regions runs without raising an exception""" result = self.cloud.describe_regions(self.context) self.assertEqual(len(result['regionInfo']), 1) - regions = FLAGS.region_list - FLAGS.region_list = ["one=test_host1", "two=test_host2"] + self.flags(region_list=["one=test_host1", "two=test_host2"]) result = self.cloud.describe_regions(self.context) self.assertEqual(len(result['regionInfo']), 2) - FLAGS.region_list = regions def test_describe_addresses(self): """Makes sure describe addresses runs without raising an exception""" -- cgit From 4fe63486dd44b036b87d0357563afe4396ecaeb3 Mon Sep 17 00:00:00 2001 From: Johannes Erdfelt Date: Wed, 3 Aug 2011 21:43:48 +0000 Subject: Fix trailing whitespace (PEP8) --- nova/api/openstack/create_instance_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index a2d18d37e..333994fcc 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -92,7 +92,7 @@ class CreateInstanceHelper(object): image_href = self.controller._image_ref_from_req_data(body) # If the image href was generated by nova api, strip image_href # down to an id and use the default glance connection params - + if str(image_href).startswith(req.application_url): image_href = image_href.split('/').pop() try: -- cgit From b87a999725c90e1c80ff7c2b8102b1c5921f8bc0 Mon Sep 17 00:00:00 2001 From: Johannes Erdfelt Date: Wed, 3 Aug 2011 21:44:03 +0000 Subject: Load instance_types in downgrade method too --- .../migrate_repo/versions/036_change_flavor_id_in_migrations.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py index 7ff709c17..f3244033b 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py @@ -54,6 +54,7 @@ def upgrade(migrate_engine): def downgrade(migrate_engine): meta.bind = migrate_engine + instance_types = Table('instance_types', meta, autoload=True) migrations = Table('migrations', meta, autoload=True) migrations.create_column(old_flavor_id) migrations.create_column(new_flavor_id) -- cgit From bd0a2ed74764de262a828fd086fa0e08493b2cec Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Wed, 3 Aug 2011 17:39:51 -0500 Subject: Fixes lp819397 --- nova/tests/test_xenapi.py | 7 +++++++ nova/virt/xenapi/vmops.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index a795b3c74..26a36b231 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -754,12 +754,18 @@ class XenAPIMigrateInstance(test.TestCase): def test_finish_migrate(self): instance = db.instance_create(self.context, self.values) self.called = False + self.fake_vm_start_called = False + + def fake_vm_start(*args, **kwargs): + self.fake_vm_start_called = True def fake_vdi_resize(*args, **kwargs): self.called = True self.stubs.Set(stubs.FakeSessionForMigrationTests, "VDI_resize_online", fake_vdi_resize) + self.stubs.Set(vmops.VMOps, '_start', fake_vm_start) + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) stubs.stubout_loopingcall_start(self.stubs) conn = xenapi_conn.get_connection(False) @@ -781,6 +787,7 @@ class XenAPIMigrateInstance(test.TestCase): dict(base_copy='hurr', cow='durr'), network_info, resize_instance=True) self.assertEqual(self.called, True) + self.assertEqual(self.fake_vm_start_called, True) def test_finish_migrate_no_local_storage(self): tiny_type_id = \ diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index b3b812a48..3b9f35034 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -122,7 +122,7 @@ class VMOps(object): network_info) if resize_instance: self.resize_instance(instance, vdi_uuid) - self._spawn(instance, vm_ref) + self._start(instance, vm_ref=vm_ref) def _start(self, instance, vm_ref=None): """Power on a VM instance""" -- cgit From f34a6fb9efd8d950555431f5e7268dbde8ae78c8 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 3 Aug 2011 19:17:08 -0400 Subject: Remove instances of the "diaper pattern" Anywhere "except:" occurs, I tried to replace it with an explicit except on known error types. If none were known, Except was used. In the process I've been able to unearth a few evasive bugs and clean up some adjacent code. --- nova/api/direct.py | 5 ++--- nova/api/ec2/__init__.py | 4 ++-- nova/api/ec2/apirequest.py | 2 +- nova/api/openstack/common.py | 27 +++++++++++---------------- nova/api/openstack/servers.py | 22 +++++++++++----------- nova/cloudpipe/pipelib.py | 17 +++++++---------- nova/db/sqlalchemy/api.py | 14 ++++++++------ nova/image/__init__.py | 3 ++- nova/utils.py | 18 +++++++++++++++++- nova/virt/libvirt/connection.py | 6 +++--- nova/virt/libvirt/vif.py | 5 +++-- nova/virt/xenapi_conn.py | 2 +- nova/vnc/proxy.py | 4 ++-- 13 files changed, 70 insertions(+), 59 deletions(-) diff --git a/nova/api/direct.py b/nova/api/direct.py index 993815fc7..139c46d63 100644 --- a/nova/api/direct.py +++ b/nova/api/direct.py @@ -48,7 +48,6 @@ import nova.api.openstack.wsgi # Global storage for registering modules. ROUTES = {} - def register_service(path, handle): """Register a service handle at a given path. @@ -296,8 +295,8 @@ class ServiceWrapper(object): 'application/json': nova.api.openstack.wsgi.JSONDictSerializer(), }[content_type] return serializer.serialize(result) - except: - raise exception.Error("returned non-serializable type: %s" + except Exception, e: + raise exception.Error(_("Returned non-serializable type: %s") % result) diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index af232edda..804e54ef9 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -147,7 +147,7 @@ class Authenticate(wsgi.Middleware): try: signature = req.params['Signature'] access = req.params['AWSAccessKeyId'] - except: + except KeyError, e: raise webob.exc.HTTPBadRequest() # Make a copy of args for authentication and signature verification. @@ -211,7 +211,7 @@ class Requestify(wsgi.Middleware): for non_arg in non_args: # Remove, but raise KeyError if omitted args.pop(non_arg) - except: + except KeyError, e: raise webob.exc.HTTPBadRequest() LOG.debug(_('action: %s'), action) diff --git a/nova/api/ec2/apirequest.py b/nova/api/ec2/apirequest.py index 7d78c5cfa..9a3e55925 100644 --- a/nova/api/ec2/apirequest.py +++ b/nova/api/ec2/apirequest.py @@ -104,7 +104,7 @@ class APIRequest(object): for key in data.keys(): val = data[key] el.appendChild(self._render_data(xml, key, val)) - except: + except Exception: LOG.debug(data) raise diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index efa4ab385..1304379a8 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -16,7 +16,7 @@ # under the License. import re -from urlparse import urlparse +import urlparse from xml.dom import minidom import webob @@ -137,8 +137,8 @@ def get_id_from_href(href): if re.match(r'\d+$', str(href)): return int(href) try: - return int(urlparse(href).path.split('/')[-1]) - except: + return int(urlparse.urlsplit(href).path.split('/')[-1]) + except ValueError, e: LOG.debug(_("Error extracting id from href: %s") % href) raise ValueError(_('could not parse id from href')) @@ -153,22 +153,17 @@ def remove_version_from_href(href): Returns: 'http://www.nova.com' """ - try: - #removes the first instance that matches /v#.#/ - new_href = re.sub(r'[/][v][0-9]+\.[0-9]+[/]', '/', href, count=1) + parsed_url = urlparse.urlsplit(href) + new_path = re.sub(r'^/v[0-9]+\.[0-9]+(/|$)', r'\1', parsed_url.path, count=1) - #if no version was found, try finding /v#.# at the end of the string - if new_href == href: - new_href = re.sub(r'[/][v][0-9]+\.[0-9]+$', '', href, count=1) - except: - LOG.debug(_("Error removing version from href: %s") % href) - msg = _('could not parse version from href') + if new_path == parsed_url.path: + msg = _('href %s does not contain version') % href + LOG.debug(msg) raise ValueError(msg) - if new_href == href: - msg = _('href does not contain version') - raise ValueError(msg) - return new_href + parsed_url = list(parsed_url) + parsed_url[2] = new_path + return urlparse.urlunsplit(parsed_url) def get_version_from_href(href): diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py index 002b47edb..493845e8c 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/servers.py @@ -290,7 +290,7 @@ class Controller(object): context = req.environ['nova.context'] try: self.compute_api.lock(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("Compute.api::lock %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -306,7 +306,7 @@ class Controller(object): context = req.environ['nova.context'] try: self.compute_api.unlock(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("Compute.api::unlock %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -321,7 +321,7 @@ class Controller(object): context = req.environ['nova.context'] try: self.compute_api.get_lock(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("Compute.api::get_lock %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -336,7 +336,7 @@ class Controller(object): context = req.environ['nova.context'] try: self.compute_api.reset_network(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("Compute.api::reset_network %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -351,7 +351,7 @@ class Controller(object): context = req.environ['nova.context'] try: self.compute_api.inject_network_info(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("Compute.api::inject_network_info %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -363,7 +363,7 @@ class Controller(object): ctxt = req.environ['nova.context'] try: self.compute_api.pause(ctxt, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("Compute.api::pause %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -375,7 +375,7 @@ class Controller(object): ctxt = req.environ['nova.context'] try: self.compute_api.unpause(ctxt, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("Compute.api::unpause %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -387,7 +387,7 @@ class Controller(object): context = req.environ['nova.context'] try: self.compute_api.suspend(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("compute.api::suspend %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -399,7 +399,7 @@ class Controller(object): context = req.environ['nova.context'] try: self.compute_api.resume(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("compute.api::resume %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -420,7 +420,7 @@ class Controller(object): context = req.environ["nova.context"] try: self.compute_api.rescue(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("compute.api::rescue %s"), readable) raise exc.HTTPUnprocessableEntity() @@ -432,7 +432,7 @@ class Controller(object): context = req.environ["nova.context"] try: self.compute_api.unrescue(context, id) - except: + except Exception: readable = traceback.format_exc() LOG.exception(_("compute.api::unrescue %s"), readable) raise exc.HTTPUnprocessableEntity() diff --git a/nova/cloudpipe/pipelib.py b/nova/cloudpipe/pipelib.py index 521525205..46549c9d7 100644 --- a/nova/cloudpipe/pipelib.py +++ b/nova/cloudpipe/pipelib.py @@ -141,15 +141,12 @@ class CloudPipe(object): try: result = cloud._gen_key(context, context.user_id, key_name) private_key = result['private_key'] - try: - key_dir = os.path.join(FLAGS.keys_path, context.user_id) - if not os.path.exists(key_dir): - os.makedirs(key_dir) - key_path = os.path.join(key_dir, '%s.pem' % key_name) - with open(key_path, 'w') as f: - f.write(private_key) - except: - pass - except exception.Duplicate: + key_dir = os.path.join(FLAGS.keys_path, context.user_id) + if not os.path.exists(key_dir): + os.makedirs(key_dir) + key_path = os.path.join(key_dir, '%s.pem' % key_name) + with open(key_path, 'w') as f: + f.write(private_key) + except exception.Duplicate, os.error, IOError: pass return key_name diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 4f1445217..ce12ba4e0 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3178,8 +3178,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).\ @@ -3205,7 +3206,7 @@ def instance_metadata_update_or_create(context, instance_id, metadata): try: meta_ref = instance_metadata_get_item(context, instance_id, key, session) - except: + except exception.InstanceMetadataNotFound, e: meta_ref = models.InstanceMetadata() meta_ref.update({"key": key, "value": value, "instance_id": instance_id, @@ -3300,8 +3301,9 @@ 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).\ @@ -3327,7 +3329,7 @@ def instance_type_extra_specs_update_or_create(context, instance_type_id, instance_type_id, key, session) - except: + except exception.InstanceTypeExtraSpecsNotFound, e: spec_ref = models.InstanceTypeExtraSpecs() spec_ref.update({"key": key, "value": value, "instance_type_id": instance_type_id, diff --git a/nova/image/__init__.py b/nova/image/__init__.py index a27d649d4..5447c8a3a 100644 --- a/nova/image/__init__.py +++ b/nova/image/__init__.py @@ -35,6 +35,7 @@ def _parse_image_ref(image_href): :param image_href: href of an image :returns: a tuple of the form (image_id, host, port) + :raises ValueError """ o = urlparse(image_href) @@ -72,7 +73,7 @@ def get_glance_client(image_href): try: (image_id, host, port) = _parse_image_ref(image_href) - except: + except ValueError: raise exception.InvalidImageRef(image_href=image_href) glance_client = GlanceClient(host, port) return (glance_client, image_id) diff --git a/nova/utils.py b/nova/utils.py index 4ea623cc1..1e2dbebb1 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -126,6 +126,22 @@ def fetchfile(url, target): def execute(*cmd, **kwargs): + """ + Helper method to execute command with optional retry. + + :cmd Passed to subprocess.Popen. + :process_input Send to opened process. + :addl_env Added to the processes env. + :check_exit_code Defaults to 0. Raise exception.ProcessExecutionError + unless program exits with this code. + :delay_on_retry True | False. Defaults to True. If set to True, wait a + short amount of time before retrying. + :attempts How many times to retry cmd. + + :raises exception.Error on receiving unknown arguments + :raises exception.ProcessExecutionError + """ + process_input = kwargs.pop('process_input', None) addl_env = kwargs.pop('addl_env', None) check_exit_code = kwargs.pop('check_exit_code', 0) @@ -790,7 +806,7 @@ def parse_server_string(server_str): (address, port) = server_str.split(':') return (address, port) - except: + except Exception: LOG.debug(_('Invalid server_string: %s' % server_str)) return ('', '') diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py index 0acf25d28..4dd8f02e5 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -370,7 +370,7 @@ class LibvirtConnection(driver.ComputeDriver): """Returns the xml for the disk mounted at device""" try: doc = libxml2.parseDoc(xml) - except: + except Exception: return None ctx = doc.xpathNewContext() try: @@ -1103,7 +1103,7 @@ class LibvirtConnection(driver.ComputeDriver): try: doc = libxml2.parseDoc(xml) - except: + except Exception: return [] ctx = doc.xpathNewContext() @@ -1144,7 +1144,7 @@ class LibvirtConnection(driver.ComputeDriver): try: doc = libxml2.parseDoc(xml) - except: + except Exception: return [] ctx = doc.xpathNewContext() diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index eef582fac..4be60ce8a 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -25,6 +25,7 @@ from nova.network import linux_net from nova.virt.libvirt import netutils from nova import utils from nova.virt.vif import VIFDriver +from nova import exception LOG = logging.getLogger('nova.virt.libvirt.vif') @@ -128,7 +129,7 @@ class LibvirtOpenVswitchDriver(VIFDriver): utils.execute('sudo', 'ovs-vsctl', 'del-port', network['bridge'], dev) utils.execute('sudo', 'ip', 'link', 'delete', dev) - except: + except exception.ProcessExecutionError, e: LOG.warning(_("Failed while unplugging vif of instance '%s'"), instance['name']) - raise + raise e diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 39afbd650..f75d4493c 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -441,7 +441,7 @@ class XenAPISession(object): params = None try: params = eval(exc.details[3]) - except: + except Exception: raise exc raise self.XenAPI.Failure(params) else: diff --git a/nova/vnc/proxy.py b/nova/vnc/proxy.py index c4603803b..2e3e38ca9 100644 --- a/nova/vnc/proxy.py +++ b/nova/vnc/proxy.py @@ -60,7 +60,7 @@ class WebsocketVNCProxy(object): break d = base64.b64encode(d) dest.send(d) - except: + except Exception: source.close() dest.close() @@ -72,7 +72,7 @@ class WebsocketVNCProxy(object): break d = base64.b64decode(d) dest.sendall(d) - except: + except Exception: source.close() dest.close() -- cgit From 6f3b63cd51549843b269cc6c138575a5af2337b2 Mon Sep 17 00:00:00 2001 From: Johannes Erdfelt Date: Thu, 4 Aug 2011 08:43:13 +0000 Subject: Revert should be sent to destination node and confirm should be sent to source node --- nova/compute/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/compute/api.py b/nova/compute/api.py index aae16d1da..1d09c69f6 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -888,7 +888,7 @@ class API(base.Base): params = {'migration_id': migration_ref['id']} self._cast_compute_message('revert_resize', context, instance_ref['uuid'], - migration_ref['source_compute'], + migration_ref['dest_compute'], params=params) self.db.migration_update(context, migration_ref['id'], @@ -908,7 +908,7 @@ class API(base.Base): params = {'migration_id': migration_ref['id']} self._cast_compute_message('confirm_resize', context, instance_ref['uuid'], - migration_ref['dest_compute'], + migration_ref['source_compute'], params=params) self.db.migration_update(context, migration_ref['id'], -- cgit From dbbc07750c2624b61af4f824d29c99bffe5f722f Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 4 Aug 2011 09:40:51 -0500 Subject: Fixed rescue and unrescue. --- nova/compute/manager.py | 25 ++++++++++++------------- nova/exception.py | 3 ++- nova/virt/xenapi/vmops.py | 3 ++- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 8780ad921..cf4ee229d 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -648,38 +648,37 @@ class ComputeManager(manager.SchedulerDependentManager): @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @checks_instance_lock - def rescue_instance(self, context, instance_uuid): + def rescue_instance(self, context, instance_id): """Rescue an instance on this host.""" context = context.elevated() - instance_ref = self.db.instance_get_by_uuid(context, instance_uuid) - LOG.audit(_('instance %s: rescuing'), instance_uuid, context=context) + instance_ref = self.db.instance_get(context, instance_id) + LOG.audit(_('instance %s: rescuing'), instance_id, context=context) self.db.instance_set_state(context, - instance_uuid, + instance_id, power_state.NOSTATE, 'rescuing') _update_state = lambda result: self._update_state_callback( - self, context, instance_uuid, result) + self, context, instance_id, result) network_info = self._get_instance_nw_info(context, instance_ref) self.driver.rescue(context, instance_ref, _update_state, network_info) - self._update_state(context, instance_uuid) + self._update_state(context, instance_id) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @checks_instance_lock - def unrescue_instance(self, context, instance_uuid): + def unrescue_instance(self, context, instance_id): """Rescue an instance on this host.""" context = context.elevated() - instance_ref = self.db.instance_get_by_uuid(context, instance_uuid) - LOG.audit(_('instance %s: unrescuing'), instance_uuid, - context=context) + instance_ref = self.db.instance_get(context, instance_id) + LOG.audit(_('instance %s: unrescuing'), instance_id, context=context) self.db.instance_set_state(context, - instance_uuid, + instance_id, power_state.NOSTATE, 'unrescuing') _update_state = lambda result: self._update_state_callback( - self, context, instance_uuid, result) + self, context, instance_id, result) network_info = self._get_instance_nw_info(context, instance_ref) self.driver.unrescue(instance_ref, _update_state, network_info) - self._update_state(context, instance_uuid) + self._update_state(context, instance_id) @staticmethod def _update_state_callback(self, context, instance_id, result): diff --git a/nova/exception.py b/nova/exception.py index 68e6ac937..8503f8e3e 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -122,7 +122,8 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None, LOG.exception(_('Uncaught exception')) #logging.error(traceback.extract_stack(exc_traceback)) raise Error(str(e)) - raise + # Don't mask the real exception. + raise Exception(e) return wraps(f)(wrapped) return inner diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index b3b812a48..9979a0165 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -935,7 +935,8 @@ class VMOps(object): self.spawn_rescue(context, instance, network_info) rescue_vm_ref = VMHelper.lookup(self._session, instance.name) - vbd_ref = self._session.get_xenapi().VM.get_VBDs(vm_ref)[0] + #NOTE(jk0): Find the root partition, not swap. + vbd_ref = self._session.get_xenapi().VM.get_VBDs(vm_ref)[1] vdi_ref = self._session.get_xenapi().VBD.get_record(vbd_ref)["VDI"] rescue_vbd_ref = VMHelper.create_vbd(self._session, rescue_vm_ref, vdi_ref, 1, False) -- cgit From 5e1d63cf3b16f78f02e9c2642f60a43402a933a9 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 4 Aug 2011 10:41:42 -0400 Subject: Updates to the XenServer glance plugin so that it obtains the set of existing headers and sends them along with the request to PUT a snapshotted image into glance. --- plugins/xenserver/xenapi/etc/xapi.d/plugins/glance | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance index 86e837849..17a5dbbfb 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance @@ -248,6 +248,19 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type, using chunked-transfer-encoded HTTP. """ conn = httplib.HTTPConnection(glance_host, glance_port) + + # NOTE(dprince): We need to resend any existing Glance meta/property + # headers so they are preserved in Glance. We obtain them here with a + # HEAD request. + conn.request('HEAD', '/v1/images/%s' % image_id) + resp = conn.getresponse() + if resp.status != httplib.OK: + raise Exception("Unexpected response from Glance %i" % resp.status) + headers = {} + for header, value in resp.getheaders(): + if header.lower().startswith("x-image-meta-property-"): + headers[header.lower()] = value + # NOTE(sirp): httplib under python2.4 won't accept a file-like object # to request conn.putrequest('PUT', '/v1/images/%s' % image_id) @@ -260,7 +273,7 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type, # 2. We're currently uploading a vanilla tarball. In order to be OVF/OVA # compliant, we'll need to embed a minimal OVF manifest as the first # file. - headers = { + ovf_headers = { 'content-type': 'application/octet-stream', 'transfer-encoding': 'chunked', 'x-image-meta-is-public': 'True', @@ -271,7 +284,9 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type, # If we have an auth_token, set an x-auth-token header if auth_token: - headers['x-auth-token'] = auth_token + ovf_headers['x-auth-token'] = auth_token + + headers.update(ovf_headers) for header, value in headers.iteritems(): conn.putheader(header, value) -- cgit From a3abff9c6243ecfddac72167320c74dce7398941 Mon Sep 17 00:00:00 2001 From: Ed Leafe Date: Thu, 4 Aug 2011 15:02:28 +0000 Subject: Changed the definition of the 'action' dict to always occur. --- nova/virt/xenapi_conn.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 39afbd650..8ddbbd33a 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -394,11 +394,10 @@ class XenAPISession(object): try: name = self._session.xenapi.task.get_name_label(task) status = self._session.xenapi.task.get_status(task) + # Ensure action is never > 255 + action = dict(action=name[:255], error=None) if id: - action = dict( - instance_id=int(id), - action=name[0:255], # Ensure action is never > 255 - error=None) + action["instance_id"] = int(id) if status == "pending": return elif status == "success": -- cgit -- cgit From 4eed25b0f01b510d0d90e864eef7f285964ab293 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 4 Aug 2011 11:11:12 -0400 Subject: The OSAPI v1.0 image create POST request should store the instance_id as a Glance property. --- nova/api/openstack/images.py | 8 ++++++-- nova/tests/api/openstack/test_images.py | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/nova/api/openstack/images.py b/nova/api/openstack/images.py index 0834adfa5..c76738d30 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/images.py @@ -116,13 +116,17 @@ class ControllerV10(Controller): try: image_name = image["name"] - server_id = image["serverId"] + instance_id = image["serverId"] except KeyError as missing_key: msg = _("Image entity requires %s") % missing_key raise webob.exc.HTTPBadRequest(explanation=msg) context = req.environ["nova.context"] - image = self._compute_service.snapshot(context, server_id, image_name) + props = {'instance_id': instance_id} + image = self._compute_service.snapshot(context, + instance_id, + image_name, + extra_properties=props) return dict(image=self.get_builder(req).build(image, detail=True)) diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 942c0b333..6486a069c 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -1031,6 +1031,9 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): req.headers["content-type"] = "application/json" response = req.get_response(fakes.wsgi_app()) self.assertEqual(200, response.status_int) + image_meta = json.loads(response.body)['image'] + self.assertEqual(123, image_meta['serverId']) + self.assertEqual('Snapshot 1', image_meta['name']) def test_create_snapshot_no_name(self): """Name is required for snapshots""" -- cgit From ae6b54cc1748d7b9c7bfa55374e9355665343b82 Mon Sep 17 00:00:00 2001 From: William Wolf Date: Thu, 4 Aug 2011 11:45:24 -0400 Subject: add test for spawning a xenapi instance with an empty dns list --- nova/tests/test_xenapi.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index a795b3c74..5f3aec700 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -397,7 +397,7 @@ class XenAPIVMTestCase(test.TestCase): instance_type_id="3", os_type="linux", architecture="x86-64", instance_id=1, check_injection=False, - create_record=True): + create_record=True, empty_dns=False): stubs.stubout_loopingcall_start(self.stubs) if create_record: values = {'id': instance_id, @@ -426,12 +426,22 @@ class XenAPIVMTestCase(test.TestCase): 'label': 'fake', 'mac': 'DE:AD:BE:EF:00:00', 'rxtx_cap': 3})] + if empty_dns: + network_info[0][1]['dns'] = [] + self.conn.spawn(self.context, instance, network_info) self.create_vm_record(self.conn, os_type, instance_id) self.check_vm_record(self.conn, check_injection) self.assertTrue(instance.os_type) self.assertTrue(instance.architecture) + def test_spawn_empty_dns(self): + """"Test spawning with an empty dns list""" + self._test_spawn(glance_stubs.FakeGlance.IMAGE_VHD, None, None, + os_type="linux", architecture="x86-64", + empty_dns=True) + self.check_vm_params_for_linux() + def test_spawn_not_enough_memory(self): self.assertRaises(Exception, self._test_spawn, -- cgit From 5826a793e7e05db8ccc14d15326245246fb652d4 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 4 Aug 2011 12:48:13 -0400 Subject: fixing typo --- nova/api/openstack/create_instance_helper.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nova/api/openstack/create_instance_helper.py b/nova/api/openstack/create_instance_helper.py index 178685889..2a8e7fd7e 100644 --- a/nova/api/openstack/create_instance_helper.py +++ b/nova/api/openstack/create_instance_helper.py @@ -332,7 +332,8 @@ class ServerXMLDeserializer(wsgi.XMLDeserializer): if value: data[attribute] = value metadata_node = self.find_first_child_named(node, 'metadata') - data['metadata'] = self.extract_metadata(metadata_node) + metadata = self.metadata_deserializer.extract_metadata(metadata_node) + data['metadata'] = metadata return data def create(self, string): -- cgit From 8fd335e309ea48d1460ee4d04105e429575f47f6 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Thu, 4 Aug 2011 10:03:15 -0700 Subject: fix up new test_server_actions.py file for flags verbosity change --- nova/tests/api/openstack/test_server_actions.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py index fc08a2d53..baec5f3d1 100644 --- a/nova/tests/api/openstack/test_server_actions.py +++ b/nova/tests/api/openstack/test_server_actions.py @@ -8,7 +8,6 @@ import webob from nova import context from nova import db -from nova import flags from nova import utils from nova.api.openstack import create_instance_helper from nova.compute import instance_types @@ -19,10 +18,6 @@ from nova.tests.api.openstack import common from nova.tests.api.openstack import fakes -FLAGS = flags.FLAGS -FLAGS.verbose = True - - def return_server_by_id(context, id): return _get_instance() @@ -102,6 +97,7 @@ class ServerActionsTest(test.TestCase): def setUp(self): self.maxDiff = None super(ServerActionsTest, self).setUp() + self.set_flags_verbosity(True) self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} -- cgit From 24b308ebb4f7fff5520383248170bfb7d51c6755 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Thu, 4 Aug 2011 10:17:55 -0700 Subject: test_host_filter setUp needs to call its super --- nova/tests/scheduler/test_host_filter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/nova/tests/scheduler/test_host_filter.py b/nova/tests/scheduler/test_host_filter.py index b016923c4..7e664d3f9 100644 --- a/nova/tests/scheduler/test_host_filter.py +++ b/nova/tests/scheduler/test_host_filter.py @@ -54,6 +54,7 @@ class HostFilterTestCase(test.TestCase): 'host_name-label': 'xs-%s' % multiplier} def setUp(self): + super(HostFilterTestCase, self).setUp() default_host_filter = 'nova.scheduler.host_filter.AllHostsFilter' self.flags(default_host_filter=default_host_filter) self.instance_type = dict(name='tiny', -- cgit From 7f35619377593b5bb30425984999e8bb9ed2bdb2 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Thu, 4 Aug 2011 10:34:36 -0700 Subject: fix pep8 issues that are in trunk --- nova/compute/manager.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 94bac9be4..9f566dea7 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -167,10 +167,12 @@ class ComputeManager(manager.SchedulerDependentManager): 'nova-compute restart.'), locals()) self.reboot_instance(context, instance['id']) elif drv_state == power_state.RUNNING: - try: # Hyper-V and VMWareAPI drivers will raise and exception + # Hyper-V and VMWareAPI drivers will raise and exception + try: self.driver.ensure_filtering_rules_for_instance(instance) except NotImplementedError: - LOG.warning(_('Hypervisor driver does not support firewall rules')) + LOG.warning(_('Hypervisor driver does not ' + 'support firewall rules')) def _update_state(self, context, instance_id, state=None): """Update the state of an instance from the driver info.""" -- cgit From ca79470843ff351623d07378ab553b2548cb8dc0 Mon Sep 17 00:00:00 2001 From: Mandell Degerness Date: Thu, 4 Aug 2011 10:43:16 -0700 Subject: Fix to nova-ajax-console-proxy to use the new syntax. create_consumer and create_connection abstractions were added recently. --- Authors | 1 + bin/nova-ajax-console-proxy | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Authors b/Authors index 0e5931462..b216873df 100644 --- a/Authors +++ b/Authors @@ -64,6 +64,7 @@ Kirill Shileev Koji Iida Lorin Hochstein Lvov Maxim +Mandell Degerness Mark Washenberger Masanori Itoh Matt Dietz diff --git a/bin/nova-ajax-console-proxy b/bin/nova-ajax-console-proxy index 21cf68007..2329581a2 100755 --- a/bin/nova-ajax-console-proxy +++ b/bin/nova-ajax-console-proxy @@ -114,11 +114,11 @@ class AjaxConsoleProxy(object): AjaxConsoleProxy.tokens[kwargs['token']] = \ {'args': kwargs, 'last_activity': time.time()} - conn = rpc.Connection.instance(new=True) - consumer = rpc.TopicAdapterConsumer( - connection=conn, - proxy=TopicProxy, - topic=FLAGS.ajax_console_proxy_topic) + conn = rpc.create_connection(new=True) + consumer = rpc.create_consumer( + conn, + FLAGS.ajax_console_proxy_topic, + TopicProxy) def delete_expired_tokens(): now = time.time() -- cgit From 7e70e5ff7c39862a328b304f13778936e422a212 Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Thu, 4 Aug 2011 14:37:24 -0400 Subject: remove unused reference to exception object --- nova/virt/libvirt/vif.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 4be60ce8a..711b05bae 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -129,7 +129,7 @@ class LibvirtOpenVswitchDriver(VIFDriver): utils.execute('sudo', 'ovs-vsctl', 'del-port', network['bridge'], dev) utils.execute('sudo', 'ip', 'link', 'delete', dev) - except exception.ProcessExecutionError, e: + except exception.ProcessExecutionError: LOG.warning(_("Failed while unplugging vif of instance '%s'"), instance['name']) - raise e + raise -- cgit From 7f35b6ee93ea2192a8c81a7c17e2e74694a397a1 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Thu, 4 Aug 2011 12:07:07 -0700 Subject: remove set_flags_verbosity.. it's not needed --- nova/test.py | 5 ----- nova/tests/api/openstack/test_accounts.py | 3 +-- nova/tests/api/openstack/test_adminapi.py | 2 +- nova/tests/api/openstack/test_server_actions.py | 2 +- nova/tests/api/openstack/test_servers.py | 2 +- nova/tests/api/openstack/test_users.py | 3 +-- nova/tests/api/openstack/test_zones.py | 3 +-- nova/tests/integrated/integrated_helpers.py | 2 +- 8 files changed, 7 insertions(+), 15 deletions(-) diff --git a/nova/test.py b/nova/test.py index fa5a662fd..ff85deeda 100644 --- a/nova/test.py +++ b/nova/test.py @@ -156,11 +156,6 @@ class TestCase(unittest.TestCase): FLAGS.Reset() for k, v in self._original_flags.iteritems(): setattr(FLAGS, k, v) - FLAGS.verbose = self._original_flags_verbosity - - def set_flags_verbosity(self, verbose=True): - """Set the FLAGS verbosity for a test""" - FLAGS.verbose = verbose def start_service(self, name, host=None, **kwargs): host = host and host or uuid.uuid4().hex diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index b1ca546d2..707a2599f 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -35,8 +35,7 @@ def fake_admin_check(self, req): class AccountsTest(test.TestCase): def setUp(self): super(AccountsTest, self).setUp() - self.flags(allow_admin_api=True) - self.set_flags_verbosity(True) + self.flags(verbose=True, allow_admin_api=True) self.stubs.Set(accounts.Controller, '__init__', fake_init) self.stubs.Set(accounts.Controller, '_check_admin', diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index 9d03a7f9d..c9e66dc4c 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -28,7 +28,7 @@ class AdminAPITest(test.TestCase): super(AdminAPITest, self).setUp() fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) - self.set_flags_verbosity(True) + self.flags(verbose=True) def test_admin_enabled(self): self.flags(allow_admin_api=True) diff --git a/nova/tests/api/openstack/test_server_actions.py b/nova/tests/api/openstack/test_server_actions.py index baec5f3d1..562cefe90 100644 --- a/nova/tests/api/openstack/test_server_actions.py +++ b/nova/tests/api/openstack/test_server_actions.py @@ -97,7 +97,7 @@ class ServerActionsTest(test.TestCase): def setUp(self): self.maxDiff = None super(ServerActionsTest, self).setUp() - self.set_flags_verbosity(True) + self.flags(verbose=True) self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index bb411af10..0477f6d92 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -230,7 +230,7 @@ class ServersTest(test.TestCase): def setUp(self): self.maxDiff = None super(ServersTest, self).setUp() - self.set_flags_verbosity(True) + self.flags(verbose=True) fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index 649538f11..1d133f9ab 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -35,8 +35,7 @@ def fake_admin_check(self, req): class UsersTest(test.TestCase): def setUp(self): super(UsersTest, self).setUp() - self.flags(allow_admin_api=True) - self.set_flags_verbosity(True) + self.flags(verbose=True, allow_admin_api=True) self.stubs.Set(users.Controller, '__init__', fake_init) self.stubs.Set(users.Controller, '_check_admin', diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 442ee4313..4a46a5764 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -94,8 +94,7 @@ def zone_select(context, specs): class ZonesTest(test.TestCase): def setUp(self): super(ZonesTest, self).setUp() - self.flags(allow_admin_api=True) - self.set_flags_verbosity(True) + self.flags(verbose=True, allow_admin_api=True) fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 049ddbc60..fb2f88502 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -148,7 +148,7 @@ class _IntegratedTestBase(test.TestCase): f = self._get_flags() self.flags(**f) - self.set_flags_verbosity(True) + self.flags(verbose=True) def fake_get_image_service(image_href): image_id = int(str(image_href).split('/')[-1]) -- cgit From b02fb7f6a3c35673122d7f409d8c999cc9fbae46 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Thu, 4 Aug 2011 12:21:09 -0700 Subject: remove storing original flags verbosity --- nova/test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nova/test.py b/nova/test.py index ff85deeda..5760d7a82 100644 --- a/nova/test.py +++ b/nova/test.py @@ -100,7 +100,6 @@ class TestCase(unittest.TestCase): self.injected = [] self._services = [] self._original_flags = FLAGS.FlagValuesDict() - self._original_flags_verbosity = FLAGS.verbose def tearDown(self): """Runs after each test method to tear down test environment.""" -- cgit From cae90fb1d5a798673416e51c5cf1f7db6cbd6c23 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 4 Aug 2011 14:30:12 -0500 Subject: Fixed rescue and unrescue. --- nova/compute/manager.py | 10 ++++------ nova/virt/xenapi/vmops.py | 4 ++-- nova/virt/xenapi_conn.py | 8 ++++---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index cf4ee229d..c6af0dfbe 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -651,16 +651,15 @@ class ComputeManager(manager.SchedulerDependentManager): def rescue_instance(self, context, instance_id): """Rescue an instance on this host.""" context = context.elevated() + self._update_state(context, instance_id) instance_ref = self.db.instance_get(context, instance_id) LOG.audit(_('instance %s: rescuing'), instance_id, context=context) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, 'rescuing') - _update_state = lambda result: self._update_state_callback( - self, context, instance_id, result) network_info = self._get_instance_nw_info(context, instance_ref) - self.driver.rescue(context, instance_ref, _update_state, network_info) + self.driver.rescue(context, instance_ref, None, network_info) self._update_state(context, instance_id) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @@ -668,16 +667,15 @@ class ComputeManager(manager.SchedulerDependentManager): def unrescue_instance(self, context, instance_id): """Rescue an instance on this host.""" context = context.elevated() + self._update_state(context, instance_id) instance_ref = self.db.instance_get(context, instance_id) LOG.audit(_('instance %s: unrescuing'), instance_id, context=context) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, 'unrescuing') - _update_state = lambda result: self._update_state_callback( - self, context, instance_id, result) network_info = self._get_instance_nw_info(context, instance_ref) - self.driver.unrescue(instance_ref, _update_state, network_info) + self.driver.unrescue(instance_ref, None, network_info) self._update_state(context, instance_id) @staticmethod diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 9979a0165..5badbac31 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -914,7 +914,7 @@ class VMOps(object): True) self._wait_with_callback(instance.id, task, callback) - def rescue(self, context, instance, callback, network_info): + def rescue(self, context, instance, _callback, network_info): """Rescue the specified instance. - shutdown the instance VM. @@ -943,7 +943,7 @@ class VMOps(object): self._session.call_xenapi("Async.VBD.plug", rescue_vbd_ref) - def unrescue(self, instance, callback): + def unrescue(self, instance, _callback): """Unrescue the specified instance. - unplug the instance VM's disk from the rescue VM. diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 39afbd650..9dcbb3cf9 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -242,13 +242,13 @@ class XenAPIConnection(driver.ComputeDriver): """resume the specified instance""" self._vmops.resume(instance, callback) - def rescue(self, context, instance, callback, network_info): + def rescue(self, context, instance, _callback, network_info): """Rescue the specified instance""" - self._vmops.rescue(context, instance, callback, network_info) + self._vmops.rescue(context, instance, _callback, network_info) - def unrescue(self, instance, callback, network_info): + def unrescue(self, instance, _callback, network_info): """Unrescue the specified instance""" - self._vmops.unrescue(instance, callback) + self._vmops.unrescue(instance, _callback) def poll_rescued_instances(self, timeout): """Poll for rescued instances""" -- cgit From c56d20383a432aa2c83e7e3c2beebdb49cbe9efc Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Thu, 4 Aug 2011 15:30:39 -0400 Subject: fix syntax error --- nova/cloudpipe/pipelib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/cloudpipe/pipelib.py b/nova/cloudpipe/pipelib.py index 46549c9d7..2c4673f9e 100644 --- a/nova/cloudpipe/pipelib.py +++ b/nova/cloudpipe/pipelib.py @@ -147,6 +147,6 @@ class CloudPipe(object): key_path = os.path.join(key_dir, '%s.pem' % key_name) with open(key_path, 'w') as f: f.write(private_key) - except exception.Duplicate, os.error, IOError: + except (exception.Duplicate, os.error, IOError): pass return key_name -- cgit From 12404f486a825dc8afdc45db0b10347a3a782e6d Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 4 Aug 2011 14:41:54 -0500 Subject: Removed temporary debugging raise. --- nova/exception.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nova/exception.py b/nova/exception.py index 8503f8e3e..68e6ac937 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -122,8 +122,7 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None, LOG.exception(_('Uncaught exception')) #logging.error(traceback.extract_stack(exc_traceback)) raise Error(str(e)) - # Don't mask the real exception. - raise Exception(e) + raise return wraps(f)(wrapped) return inner -- cgit From b8d4004e9de28dae47c6a1772a0caac965f7a69f Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 4 Aug 2011 15:16:42 -0500 Subject: Fixed rescue unit tests. --- nova/tests/test_xenapi.py | 6 ++++++ nova/virt/xenapi/vmops.py | 15 +++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index a795b3c74..1bc55027a 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -170,6 +170,10 @@ def reset_network(*args): pass +def _find_rescue_vbd_ref(*args): + pass + + class XenAPIVMTestCase(test.TestCase): """Unit tests for VM operations.""" def setUp(self): @@ -189,6 +193,8 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_stream_disk(self.stubs) stubs.stubout_is_vdi_pv(self.stubs) self.stubs.Set(vmops.VMOps, 'reset_network', reset_network) + self.stubs.Set(vmops.VMOps, '_find_rescue_vbd_ref', + _find_rescue_vbd_ref) stubs.stub_out_vm_methods(self.stubs) glance_stubs.stubout_glance_client(self.stubs) fake_utils.stub_out_utils_execute(self.stubs) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 5badbac31..81c6c6967 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -743,6 +743,14 @@ class VMOps(object): except self.XenAPI.Failure, exc: LOG.exception(exc) + def _find_rescue_vbd_ref(self, vm_ref, rescue_vm_ref): + """Find and return the rescue VM's vbd_ref.""" + vbd_ref = self._session.get_xenapi().VM.get_VBDs(vm_ref)[1] + vdi_ref = self._session.get_xenapi().VBD.get_record(vbd_ref)["VDI"] + + return VMHelper.create_vbd(self._session, rescue_vm_ref, vdi_ref, 1, + False) + def _shutdown_rescue(self, rescue_vm_ref): """Shutdown a rescue instance.""" self._session.call_xenapi("Async.VM.hard_shutdown", rescue_vm_ref) @@ -934,12 +942,7 @@ class VMOps(object): instance._rescue = True self.spawn_rescue(context, instance, network_info) rescue_vm_ref = VMHelper.lookup(self._session, instance.name) - - #NOTE(jk0): Find the root partition, not swap. - vbd_ref = self._session.get_xenapi().VM.get_VBDs(vm_ref)[1] - vdi_ref = self._session.get_xenapi().VBD.get_record(vbd_ref)["VDI"] - rescue_vbd_ref = VMHelper.create_vbd(self._session, rescue_vm_ref, - vdi_ref, 1, False) + rescue_vbd_ref = self._find_rescue_vbd_ref(vm_ref, rescue_vm_ref) self._session.call_xenapi("Async.VBD.plug", rescue_vbd_ref) -- cgit From eca23b1ad18a8626dd68cded4d488ca1aa779f69 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 4 Aug 2011 15:22:36 -0500 Subject: Removed debugging code. --- nova/compute/manager.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index c6af0dfbe..cf4ee229d 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -651,15 +651,16 @@ class ComputeManager(manager.SchedulerDependentManager): def rescue_instance(self, context, instance_id): """Rescue an instance on this host.""" context = context.elevated() - self._update_state(context, instance_id) instance_ref = self.db.instance_get(context, instance_id) LOG.audit(_('instance %s: rescuing'), instance_id, context=context) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, 'rescuing') + _update_state = lambda result: self._update_state_callback( + self, context, instance_id, result) network_info = self._get_instance_nw_info(context, instance_ref) - self.driver.rescue(context, instance_ref, None, network_info) + self.driver.rescue(context, instance_ref, _update_state, network_info) self._update_state(context, instance_id) @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) @@ -667,15 +668,16 @@ class ComputeManager(manager.SchedulerDependentManager): def unrescue_instance(self, context, instance_id): """Rescue an instance on this host.""" context = context.elevated() - self._update_state(context, instance_id) instance_ref = self.db.instance_get(context, instance_id) LOG.audit(_('instance %s: unrescuing'), instance_id, context=context) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, 'unrescuing') + _update_state = lambda result: self._update_state_callback( + self, context, instance_id, result) network_info = self._get_instance_nw_info(context, instance_ref) - self.driver.unrescue(instance_ref, None, network_info) + self.driver.unrescue(instance_ref, _update_state, network_info) self._update_state(context, instance_id) @staticmethod -- cgit From 475963efeae1b12ae7474508559fb904bc9c1675 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 4 Aug 2011 15:31:18 -0500 Subject: Added more informative docstring. --- nova/virt/xenapi/vmops.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 81c6c6967..69f1af75a 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -744,7 +744,10 @@ class VMOps(object): LOG.exception(exc) def _find_rescue_vbd_ref(self, vm_ref, rescue_vm_ref): - """Find and return the rescue VM's vbd_ref.""" + """Find and return the rescue VM's vbd_ref. + + We use the second VBD here because swap is first with the root file + system coming in second.""" vbd_ref = self._session.get_xenapi().VM.get_VBDs(vm_ref)[1] vdi_ref = self._session.get_xenapi().VBD.get_record(vbd_ref)["VDI"] -- cgit From 66916be1ad5bbc0cdc19928ee35e5e8f4e4a3915 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Fri, 5 Aug 2011 00:12:19 +0000 Subject: Read response to reset HTTPConnection state machine --- plugins/xenserver/xenapi/etc/xapi.d/plugins/glance | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance index 17a5dbbfb..a06312890 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance @@ -261,6 +261,9 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, os_type, if header.lower().startswith("x-image-meta-property-"): headers[header.lower()] = value + # Toss body so connection state-machine is ready for next request/response + resp.read() + # NOTE(sirp): httplib under python2.4 won't accept a file-like object # to request conn.putrequest('PUT', '/v1/images/%s' % image_id) -- cgit