From 9ad17dec99608b3738d662d91c49964b3f207d02 Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Wed, 17 Aug 2011 09:57:15 -0700 Subject: Add NetworkCommandsTestCase into unit test of nova-manage --- nova/tests/test_nova_manage.py | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 9c6563f14..69e73367f 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import gettext import os import sys @@ -24,16 +25,20 @@ TOPDIR = os.path.normpath(os.path.join( os.pardir)) NOVA_MANAGE_PATH = os.path.join(TOPDIR, 'bin', 'nova-manage') +gettext.install('nova', unicode=1) + sys.dont_write_bytecode = True import imp nova_manage = imp.load_source('nova_manage.py', NOVA_MANAGE_PATH) sys.dont_write_bytecode = False import netaddr +import StringIO from nova import context from nova import db from nova import flags from nova import test +from nova import exception FLAGS = flags.FLAGS @@ -80,3 +85,71 @@ class FixedIpCommandsTestCase(test.TestCase): address = db.fixed_ip_get_by_address(context.get_admin_context(), '10.0.0.100') self.assertEqual(address['reserved'], False) + +class NetworkCommandsTestCase(test.TestCase): + def setUp(self): +# print 'piyo' + super(NetworkCommandsTestCase, self).setUp() + self.commands = nova_manage.NetworkCommands() + self.context = context.get_admin_context() + nets = db.network_get_all(self.context) + for net in nets: + db.network_delete_safe(self.context, net['id']) + + def tearDown(self): + super(NetworkCommandsTestCase, self).tearDown() + + def test_create(self): + self.commands.create( + label = 'Test', + fixed_range_v4 = '10.2.0.0/24', + fixed_range_v6 = 'fd00:2::/64', + num_networks = 1, + network_size = 256, + vlan_start = 200, + bridge_interface = 'eth0', + ) + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + self.assertEqual(net['label'], 'Test') + self.assertEqual(net['cidr'], '10.2.0.0/24') + self.assertEqual(net['netmask'], '255.255.255.0') + self.assertEqual(net['cidr_v6'], 'fd00:2::/64') + self.assertEqual(net['bridge_interface'], 'eth0') + self.assertEqual(net['vlan'], 200) + + def test_list(self): + format = "%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s" + head = format % ( + _('IPv4'), + _('IPv6'), + _('start address'), + _('DNS1'), + _('DNS2'), + _('VlanID'), + _('project')) + body = format % ( + '10.2.0.0/24', + 'fd00:2::/64', + '10.2.0.3', + 'None', + 'None', + '200', + 'None',) + self.test_create() + output = StringIO.StringIO() + sys.stdout = output + self.commands.list() + sys.stdout = sys.__stdout__ + result = output.getvalue() + answer = '%s\n%s\n' % (head, body) + self.assertEqual(result, answer) + + def test_delete(self): + self.test_create() + self.commands.delete(fixed_range = '10.2.0.0/24') + net_exist = True + try: + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + except exception.NetworkNotFoundForCidr, e: + net_exist = False + self.assertEqual(net_exist, False) -- cgit From b3d3f735a7402c49b8db0e19c9b1f8521187378b Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Fri, 19 Aug 2011 09:32:39 -0700 Subject: Fix unit test for the change of 'nova-manage network list' format --- nova/tests/test_nova_manage.py | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 69e73367f..e4914e0b1 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -103,7 +103,7 @@ class NetworkCommandsTestCase(test.TestCase): self.commands.create( label = 'Test', fixed_range_v4 = '10.2.0.0/24', - fixed_range_v6 = 'fd00:2::/64', + fixed_range_v6 = 'fd00:2::/120', num_networks = 1, network_size = 256, vlan_start = 200, @@ -113,34 +113,38 @@ class NetworkCommandsTestCase(test.TestCase): self.assertEqual(net['label'], 'Test') self.assertEqual(net['cidr'], '10.2.0.0/24') self.assertEqual(net['netmask'], '255.255.255.0') - self.assertEqual(net['cidr_v6'], 'fd00:2::/64') + self.assertEqual(net['cidr_v6'], 'fd00:2::/120') self.assertEqual(net['bridge_interface'], 'eth0') self.assertEqual(net['vlan'], 200) def test_list(self): - format = "%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s" - head = format % ( - _('IPv4'), - _('IPv6'), - _('start address'), - _('DNS1'), - _('DNS2'), - _('VlanID'), - _('project')) - body = format % ( - '10.2.0.0/24', - 'fd00:2::/64', - '10.2.0.3', - 'None', - 'None', - '200', - 'None',) self.test_create() + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') output = StringIO.StringIO() sys.stdout = output self.commands.list() sys.stdout = sys.__stdout__ result = output.getvalue() + _fmt = "%-5s\t%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s" + head = _fmt % (_('id'), + _('IPv4'), + _('IPv6'), + _('start address'), + _('DNS1'), + _('DNS2'), + _('VlanID'), + _('project'), + _("uuid")) + body = _fmt % ( + net['id'], + '10.2.0.0/24', + 'fd00:2::/120', + '10.2.0.3', + 'None', + 'None', + '200', + 'None', + net['uuid'],) answer = '%s\n%s\n' % (head, body) self.assertEqual(result, answer) -- cgit From 37508da788c5b2c2eadb36ef61d58836d93a3365 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sat, 20 Aug 2011 12:41:38 -0700 Subject: improve test coverage for instance types / flavors --- nova/tests/test_instance_types.py | 66 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index ef271518c..989c6f32f 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -47,6 +47,29 @@ class InstanceTypeTestCase(test.TestCase): self.id = max_id["id"] + 1 self.name = str(int(time.time())) + def _nonexistant_flavor_name(self): + """return an instance type name not in the DB""" + nonexistant_flavor = "sdfsfsdf" + flavors = instance_types.get_all_types() + while flavors.has_key(nonexistant_flavor): + nonexistant_flavor = nonexistant_flavor.join("z") + else: + return nonexistant_flavor + + def _nonexistant_flavor_id(self): + """return an instance type ID not in the DB""" + nonexistant_flavor = 2700 + flavor_ids = [ value["id"] for key, value in\ + instance_types.get_all_types().iteritems() ] + while nonexistant_flavor in flavor_ids: + nonexistant_flavor += 1 + else: + return nonexistant_flavor + + def _existing_flavor(self): + """return first instance type name""" + return instance_types.get_all_types().keys()[0] + def test_instance_type_create_then_delete(self): """Ensure instance types can be created""" starting_inst_list = instance_types.get_all_types() @@ -87,7 +110,8 @@ class InstanceTypeTestCase(test.TestCase): def test_non_existant_inst_type_shouldnt_delete(self): """Ensures that instance type creation fails with invalid args""" self.assertRaises(exception.ApiError, - instance_types.destroy, "sfsfsdfdfs") + instance_types.destroy, + self._nonexistant_flavor_name()) def test_repeated_inst_types_should_raise_api_error(self): """Ensures that instance duplicates raises ApiError""" @@ -97,3 +121,43 @@ class InstanceTypeTestCase(test.TestCase): self.assertRaises( exception.ApiError, instance_types.create, new_name, 256, 1, 120, self.flavorid) + + def test_will_not_destroy_with_no_name(self): + """Ensure destroy sad path of no name raises error""" + self.assertRaises(exception.ApiError, + instance_types.destroy, + self._nonexistant_flavor_name()) + + def test_will_not_purge_without_name(self): + """Ensure purge without a name raises error""" + self.assertRaises(exception.InvalidInstanceType, + instance_types.purge, None) + + def test_will_not_purge_with_wrong_name(self): + """Ensure purge without correct name raises error""" + self.assertRaises(exception.ApiError, + instance_types.purge, + self._nonexistant_flavor_name()) + + def test_will_not_get_bad_default_instance_type(self): + """ensures error raised on bad default instance type""" + FLAGS.default_instance_type = self._nonexistant_flavor_name() + self.assertRaises(exception.InstanceTypeNotFoundByName, + instance_types.get_default_instance_type) + + def test_will_not_get_instance_type_by_name_with_no_name(self): + """Ensure get by name returns default flavor with no name""" + self.assertEqual(instance_types.get_default_instance_type(), + instance_types.get_instance_type_by_name(None)) + + def test_will_not_get_instance_type_with_bad_name(self): + """Ensure get by name returns default flavor with bad name""" + self.assertRaises(exception.InstanceTypeNotFound, + instance_types.get_instance_type, + self._nonexistant_flavor_name()) + + def test_will_not_get_flavor_by_bad_flavor_id(self): + """Ensure get by flavor raises error with wrong flavorid""" + self.assertRaises(exception.InstanceTypeNotFound, + instance_types.get_instance_type_by_name, + self._nonexistant_flavor_id()) -- cgit From 65b30ad73338fa481d1ab9155153b8265fbe8f90 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sat, 20 Aug 2011 12:43:50 -0700 Subject: pep8 --- nova/tests/test_instance_types.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 989c6f32f..556ba91a9 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -51,20 +51,20 @@ class InstanceTypeTestCase(test.TestCase): """return an instance type name not in the DB""" nonexistant_flavor = "sdfsfsdf" flavors = instance_types.get_all_types() - while flavors.has_key(nonexistant_flavor): - nonexistant_flavor = nonexistant_flavor.join("z") + while nonexistant_flavor in flavors: + nonexistant_flavor = nonexistant_flavor.join("z") else: - return nonexistant_flavor + return nonexistant_flavor def _nonexistant_flavor_id(self): """return an instance type ID not in the DB""" nonexistant_flavor = 2700 - flavor_ids = [ value["id"] for key, value in\ - instance_types.get_all_types().iteritems() ] + flavor_ids = [value["id"] for key, value in\ + instance_types.get_all_types().iteritems()] while nonexistant_flavor in flavor_ids: - nonexistant_flavor += 1 + nonexistant_flavor += 1 else: - return nonexistant_flavor + return nonexistant_flavor def _existing_flavor(self): """return first instance type name""" @@ -127,12 +127,12 @@ class InstanceTypeTestCase(test.TestCase): self.assertRaises(exception.ApiError, instance_types.destroy, self._nonexistant_flavor_name()) - + def test_will_not_purge_without_name(self): """Ensure purge without a name raises error""" self.assertRaises(exception.InvalidInstanceType, instance_types.purge, None) - + def test_will_not_purge_with_wrong_name(self): """Ensure purge without correct name raises error""" self.assertRaises(exception.ApiError, @@ -149,7 +149,7 @@ class InstanceTypeTestCase(test.TestCase): """Ensure get by name returns default flavor with no name""" self.assertEqual(instance_types.get_default_instance_type(), instance_types.get_instance_type_by_name(None)) - + def test_will_not_get_instance_type_with_bad_name(self): """Ensure get by name returns default flavor with bad name""" self.assertRaises(exception.InstanceTypeNotFound, -- cgit From 9508bb599c15035f7afbdc80fe70d539e8598edf Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Mon, 22 Aug 2011 08:59:35 -0700 Subject: Add 'nova-manage network modify' command. --- bin/nova-manage | 30 +++++++++++++++++++++++++ nova/db/api.py | 5 +++++ nova/db/sqlalchemy/api.py | 32 +++++++++++++++++++++++++++ nova/tests/test_nova_manage.py | 50 ++++++++++++++++++++++++++++++++---------- 4 files changed, 106 insertions(+), 11 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 62504f827..0a8edb9f3 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -795,6 +795,36 @@ class NetworkCommands(object): ' before delete' % network.project_id)) db.network_delete_safe(context.get_admin_context(), network.id) + @args('--network', dest="fixed_range", metavar='', + help='Network to modify') + @args('--project', dest="project", metavar='', + help='Project name to associate/disasscociate') + @args('--host', dest="host", metavar='', + help='Host to associate/disasscociate') + def modify(self, fixed_range, project=None, host=None): + """Associate/Disasscociate Network with Project and/or Host + arguments: network project host + specify 'None' to disassociate it + leave any field blank to ignore it + """ + admin_context = context.get_admin_context() + network = db.network_get_by_cidr(admin_context, fixed_range) + if project != "None": + if project: + project_id = manager.Project.safe_id(project) + db.network_associate_by_id(admin_context, network_id=network['id'], project_id=project, force=True) + else: + db.network_disassociate(admin_context, network_id=network['id']) + if host != "None": + if host: + db.network_set_host(admin_context, + network['id'], + host) + else: + db.network_set_host(admin_context, + network['id'], + None) + class VmCommands(object): """Class for mangaging VM instances.""" diff --git a/nova/db/api.py b/nova/db/api.py index 6833e6312..ec701ebdc 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -623,6 +623,11 @@ def network_associate(context, project_id, force=False): return IMPL.network_associate(context, project_id, force) +def network_associate_by_id(context, network_id, project_id, force=False): + """Associate a project with a network specified by id.""" + return IMPL.network_associate_by_id(context, network_id, project_id, force=False) + + def network_count(context): """Return the number of networks.""" return IMPL.network_count(context) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 2f9cab1ab..37dac1444 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1669,6 +1669,38 @@ def network_associate(context, project_id, force=False): return network_ref +@require_admin_context +def network_associate_by_id(context, network_id, project_id, force=False): + """Associate a project with a network specified by id. + + only associate if the network isn't already associated + with a project or if force is True + """ + session = get_session() + with session.begin(): + + def network_query(network_filter): + if force: + return session.query(models.Network).\ + filter_by(deleted=False).\ + filter_by(id=network_filter).\ + with_lockmode('update').\ + first() + else: + return session.query(models.Network).\ + filter_by(deleted=False).\ + filter_by(project_id=None).\ + filter_by(id=network_filter).\ + with_lockmode('update').\ + first() + network_ref = network_query(network_id) + if network_ref: + network_ref['project_id'] = project_id + session.add(network_ref) + LOG.debug("piyo: network_ref['project_id']=%s" % network_ref['project_id']) + return network_ref + + @require_admin_context def network_count(context): session = get_session() diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index e4914e0b1..4c828da16 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -39,8 +39,10 @@ from nova import db from nova import flags from nova import test from nova import exception +from nova import log as logging FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.nova_manage') class FixedIpCommandsTestCase(test.TestCase): @@ -88,7 +90,6 @@ class FixedIpCommandsTestCase(test.TestCase): class NetworkCommandsTestCase(test.TestCase): def setUp(self): -# print 'piyo' super(NetworkCommandsTestCase, self).setUp() self.commands = nova_manage.NetworkCommands() self.context = context.get_admin_context() @@ -100,22 +101,29 @@ class NetworkCommandsTestCase(test.TestCase): super(NetworkCommandsTestCase, self).tearDown() def test_create(self): + FLAGS.network_manager='nova.network.manager.VlanManager' self.commands.create( - label = 'Test', - fixed_range_v4 = '10.2.0.0/24', - fixed_range_v6 = 'fd00:2::/120', - num_networks = 1, - network_size = 256, - vlan_start = 200, - bridge_interface = 'eth0', - ) + label='Test', + fixed_range_v4='10.2.0.0/24', + num_networks=1, + network_size=256, + multi_host='F', + vlan_start=200, + vpn_start=2000, + fixed_range_v6='fd00:2::/120', + gateway_v6='fd00:2::22', + bridge_interface='eth0') net = db.network_get_by_cidr(self.context, '10.2.0.0/24') self.assertEqual(net['label'], 'Test') self.assertEqual(net['cidr'], '10.2.0.0/24') self.assertEqual(net['netmask'], '255.255.255.0') + self.assertEqual(net['multi_host'], False) + self.assertEqual(net['vlan'], 200) + self.assertEqual(net['bridge'], 'br200') + self.assertEqual(net['vpn_public_port'], 2000) self.assertEqual(net['cidr_v6'], 'fd00:2::/120') + self.assertEqual(net['gateway_v6'], 'fd00:2::22') self.assertEqual(net['bridge_interface'], 'eth0') - self.assertEqual(net['vlan'], 200) def test_list(self): self.test_create() @@ -150,10 +158,30 @@ class NetworkCommandsTestCase(test.TestCase): def test_delete(self): self.test_create() - self.commands.delete(fixed_range = '10.2.0.0/24') + self.commands.delete(fixed_range='10.2.0.0/24') net_exist = True try: net = db.network_get_by_cidr(self.context, '10.2.0.0/24') except exception.NetworkNotFoundForCidr, e: net_exist = False self.assertEqual(net_exist, False) + + def test_modify(self): + self.test_create() + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + db.network_disassociate(self.context, net['id']) + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + self.assertEqual(net['project_id'], None) + self.assertEqual(net['host'], None) + self.commands.modify('10.2.0.0/24', project='test_project', host='test_host') + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + self.assertEqual(net['project_id'], 'test_project') + self.assertEqual(net['host'], 'test_host') + self.commands.modify('10.2.0.0/24') + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + self.assertEqual(net['project_id'], 'test_project') + self.assertEqual(net['host'], 'test_host') + self.commands.modify('10.2.0.0/24', project='None', host='None') + net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + self.assertEqual(net['project_id'], None) + self.assertEqual(net['host'], None) -- cgit From 9bcd9fc5b339af97d161a65f3da84ed1bd99da2f Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Mon, 22 Aug 2011 10:27:54 -0700 Subject: delete debug code. --- nova/db/sqlalchemy/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 37dac1444..f87d32b63 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1697,7 +1697,6 @@ def network_associate_by_id(context, network_id, project_id, force=False): if network_ref: network_ref['project_id'] = project_id session.add(network_ref) - LOG.debug("piyo: network_ref['project_id']=%s" % network_ref['project_id']) return network_ref -- cgit From f05da72e28fac1bfc7f208ce57d4462a53f290f2 Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Mon, 22 Aug 2011 11:50:44 -0700 Subject: Fix pep8 --- bin/nova-manage | 5 ++++- nova/db/api.py | 3 ++- nova/tests/test_nova_manage.py | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 0a8edb9f3..736e55653 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -812,7 +812,10 @@ class NetworkCommands(object): if project != "None": if project: project_id = manager.Project.safe_id(project) - db.network_associate_by_id(admin_context, network_id=network['id'], project_id=project, force=True) + db.network_associate_by_id(admin_context, + network_id=network['id'], + project_id=project, + force=True) else: db.network_disassociate(admin_context, network_id=network['id']) if host != "None": diff --git a/nova/db/api.py b/nova/db/api.py index ec701ebdc..928c695fd 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -625,7 +625,8 @@ def network_associate(context, project_id, force=False): def network_associate_by_id(context, network_id, project_id, force=False): """Associate a project with a network specified by id.""" - return IMPL.network_associate_by_id(context, network_id, project_id, force=False) + return IMPL.network_associate_by_id(context, network_id, project_id, + force=False) def network_count(context): diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 4c828da16..d6edc8ba9 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -88,6 +88,7 @@ class FixedIpCommandsTestCase(test.TestCase): '10.0.0.100') self.assertEqual(address['reserved'], False) + class NetworkCommandsTestCase(test.TestCase): def setUp(self): super(NetworkCommandsTestCase, self).setUp() @@ -101,7 +102,7 @@ class NetworkCommandsTestCase(test.TestCase): super(NetworkCommandsTestCase, self).tearDown() def test_create(self): - FLAGS.network_manager='nova.network.manager.VlanManager' + FLAGS.network_manager = 'nova.network.manager.VlanManager' self.commands.create( label='Test', fixed_range_v4='10.2.0.0/24', @@ -173,7 +174,8 @@ class NetworkCommandsTestCase(test.TestCase): net = db.network_get_by_cidr(self.context, '10.2.0.0/24') self.assertEqual(net['project_id'], None) self.assertEqual(net['host'], None) - self.commands.modify('10.2.0.0/24', project='test_project', host='test_host') + self.commands.modify('10.2.0.0/24', project='test_project', + host='test_host') net = db.network_get_by_cidr(self.context, '10.2.0.0/24') self.assertEqual(net['project_id'], 'test_project') self.assertEqual(net['host'], 'test_host') -- cgit From 25ee794d803fa522d31177dc16d8c535d9b8daab Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 22 Aug 2011 21:52:49 +0200 Subject: Add a generic set of tests for hypervisor drivers. --- nova/tests/test_virt_drivers.py | 483 ++++++++++++++++++++++++++++++++++++++++ nova/virt/fake.py | 8 + 2 files changed, 491 insertions(+) create mode 100644 nova/tests/test_virt_drivers.py diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py new file mode 100644 index 000000000..2c91c0664 --- /dev/null +++ b/nova/tests/test_virt_drivers.py @@ -0,0 +1,483 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright 2010 OpenStack LLC +# +# 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. + +import base64 +import netaddr +import sys +import traceback + +from nova import exception +from nova import flags +from nova import image +from nova import log as logging +from nova import test +from nova.tests import utils as test_utils + +libvirt = None +FLAGS = flags.FLAGS + +LOG = logging.getLogger('nova.tests.test_virt_drivers') + +def catch_notimplementederror(f): + """Decorator to simplify catching drivers raising NotImplementedError + + If a particular call makes a driver raise NotImplementedError, we + log it so that we can extract this information afterwards to + automatically generate a hypervisor/feature support matrix.""" + def wrapped_func(self, *args, **kwargs): + try: + return f(self, *args, **kwargs) + except NotImplementedError: + frame = traceback.extract_tb(sys.exc_info()[2])[-1] + LOG.error('%(driver)s does not implement %(method)s' % { + 'driver': type(self.connection), + 'method': frame[2]}) + + wrapped_func.__name__ = f.__name__ + wrapped_func.__doc__ = f.__doc__ + return wrapped_func + +class _VirtDriverTestCase(test.TestCase): + def setUp(self): + super(_VirtDriverTestCase, self).setUp() + self.connection = self.driver_module.get_connection('') + self.ctxt = test_utils.get_test_admin_context() + self.image_service = image.get_default_image_service() + + @catch_notimplementederror + def test_init_host(self): + self.connection.init_host('myhostname') + + @catch_notimplementederror + def test_list_instances(self): + self.connection.list_instances() + + @catch_notimplementederror + def test_list_instances_detail(self): + self.connection.list_instances_detail() + + @catch_notimplementederror + def test_spawn(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + + domains = self.connection.list_instances() + self.assertIn(instance_ref['name'], domains) + + domains_details = self.connection.list_instances_detail() + self.assertIn(instance_ref['name'], [i.name for i in domains_details]) + + @catch_notimplementederror + def test_snapshot_not_running(self): + instance_ref = test_utils.get_test_instance() + img_ref = self.image_service.create(self.ctxt, {'name': 'snap-1'}) + self.assertRaises(exception.InstanceNotRunning, + self.connection.snapshot, + self.ctxt, instance_ref, img_ref['id']) + + @catch_notimplementederror + def test_snapshot_running(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + img_ref = self.image_service.create(self.ctxt, {'name': 'snap-1'}) + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.snapshot(self.ctxt, instance_ref, img_ref['id']) + + @catch_notimplementederror + def test_reboot(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.reboot(instance_ref, network_info) + + @catch_notimplementederror + def test_get_host_ip_addr(self): + host_ip = self.connection.get_host_ip_addr() + + # Will raise an exception if it's not a valid IP at all + ip = netaddr.IPAddress(host_ip) + + # For now, assume IPv4. + self.assertEquals(ip.version, 4) + + @catch_notimplementederror + def test_resize_running(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.resize(instance_ref, 7) + + @catch_notimplementederror + def test_set_admin_password(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.set_admin_password(instance_ref, 'p4ssw0rd') + + @catch_notimplementederror + def test_inject_file(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.inject_file(instance_ref, + base64.b64encode('/testfile'), + base64.b64encode('testcontents')) + + @catch_notimplementederror + def test_agent_update(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.agent_update(instance_ref, 'http://www.openstack.org/', + 'd41d8cd98f00b204e9800998ecf8427e') + + @catch_notimplementederror + def test_rescue(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.rescue(self.ctxt, instance_ref, + lambda x:None, network_info) + + @catch_notimplementederror + def test_unrescue_unrescued_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.unrescue(instance_ref, lambda x:None, network_info) + + @catch_notimplementederror + def test_unrescue_rescued_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.rescue(self.ctxt, instance_ref, + lambda x:None, network_info) + self.connection.unrescue(instance_ref, lambda x:None, network_info) + + @catch_notimplementederror + def test_poll_rescued_instances(self): + self.connection.poll_rescued_instances(10) + + @catch_notimplementederror + def test_migrate_disk_and_power_off(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.migrate_disk_and_power_off(instance_ref, 'dest_host') + + @catch_notimplementederror + def test_pause(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.pause(instance_ref, None) + + @catch_notimplementederror + def test_unpause_unpaused_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.unpause(instance_ref, None) + + @catch_notimplementederror + def test_unpause_paused_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.pause(instance_ref, None) + self.connection.unpause(instance_ref, None) + + @catch_notimplementederror + def test_suspend(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.suspend(instance_ref, None) + + @catch_notimplementederror + def test_resume_unsuspended_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.resume(instance_ref, None) + + @catch_notimplementederror + def test_resume_suspended_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.suspend(instance_ref, None) + self.connection.resume(instance_ref, None) + + @catch_notimplementederror + def test_destroy_instance_nonexistant(self): + fake_instance = { 'id': 42, 'name': 'I just made this up!' } + network_info = test_utils.get_test_network_info() + self.connection.destroy(fake_instance, network_info) + + @catch_notimplementederror + def test_destroy_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.assertIn(instance_ref['name'], + self.connection.list_instances()) + self.connection.destroy(instance_ref, network_info) + self.assertNotIn(instance_ref['name'], + self.connection.list_instances()) + + @catch_notimplementederror + def test_attach_detach_volume(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.attach_volume(instance_ref['name'], + '/dev/null', '/mnt/nova/something') + self.connection.detach_volume(instance_ref['name'], + '/mnt/nova/something') + + @catch_notimplementederror + def test_get_info(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + info = self.connection.get_info(instance_ref['name']) + self.assertIn('state', info) + self.assertIn('max_mem', info) + self.assertIn('mem', info) + self.assertIn('num_cpu', info) + self.assertIn('cpu_time', info) + + @catch_notimplementederror + def test_get_info_for_unknown_instance(self): + self.assertRaises(exception.NotFound, + self.connection.get_info, 'I just made this name up') + + @catch_notimplementederror + def test_get_diagnostics(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.get_diagnostics(instance_ref['name']) + + @catch_notimplementederror + def test_list_disks(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.list_disks(instance_ref['name']) + + @catch_notimplementederror + def test_list_interfaces(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.list_interfaces(instance_ref['name']) + + @catch_notimplementederror + def test_block_stats(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + stats = self.connection.block_stats(instance_ref['name'], 'someid') + self.assertEquals(len(stats), 5) + + @catch_notimplementederror + def test_interface_stats(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + stats = self.connection.interface_stats(instance_ref['name'], 'someid') + self.assertEquals(len(stats), 8) + + @catch_notimplementederror + def test_get_console_output(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + console_output = self.connection.get_console_output(instance_ref) + self.assertTrue(isinstance(console_output, basestring)) + + @catch_notimplementederror + def test_get_ajax_console(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + ajax_console = self.connection.get_ajax_console(instance_ref) + self.assertIn('token', ajax_console) + self.assertIn('host', ajax_console) + self.assertIn('port', ajax_console) + + @catch_notimplementederror + def test_get_vnc_console(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + vnc_console = self.connection.get_vnc_console(instance_ref) + self.assertIn('token', vnc_console) + self.assertIn('host', vnc_console) + self.assertIn('port', vnc_console) + + @catch_notimplementederror + def test_get_console_pool_info(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + console_pool = self.connection.get_console_pool_info(instance_ref) + self.assertIn('address', console_pool) + self.assertIn('username', console_pool) + self.assertIn('password', console_pool) + + @catch_notimplementederror + def test_refresh_security_group_rules(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + # FIXME: Create security group and add the instance to it + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.refresh_security_group_rules(1) + + @catch_notimplementederror + def test_refresh_security_group_members(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + # FIXME: Create security group and add the instance to it + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.refresh_security_group_members(1) + + @catch_notimplementederror + def test_refresh_provider_fw_rules(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.refresh_provider_fw_rules() + + @catch_notimplementederror + def test_update_available_resource(self): + self.compute = self.start_service('compute', host='dummy') + self.connection.update_available_resource(self.ctxt, 'dummy') + + @catch_notimplementederror + def test_compare_cpu(self): + cpu_info = '''{ "topology": { + "sockets": 1, + "cores": 2, + "threads": 1 }, + "features": [ + "xtpr", + "tm2", + "est", + "vmx", + "ds_cpl", + "monitor", + "pbe", + "tm", + "ht", + "ss", + "acpi", + "ds", + "vme"], + "arch": "x86_64", + "model": "Penryn", + "vendor": "Intel" }''' + + self.connection.compare_cpu(cpu_info) + + @catch_notimplementederror + def test_ensure_filtering_for_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.ensure_filtering_rules_for_instance(instance_ref, + network_info) + + @catch_notimplementederror + def test_unfilter_instance(self): + instance_ref = test_utils.get_test_instance() + network_info = test_utils.get_test_network_info() + self.connection.unfilter_instance(instance_ref, network_info) + + + @catch_notimplementederror + def test_live_migration(self): + network_info = test_utils.get_test_network_info() + instance_ref = test_utils.get_test_instance() + self.connection.spawn(self.ctxt, instance_ref, network_info) + self.connection.live_migration(self.ctxt, instance_ref, 'otherhost', + None, None) + + @catch_notimplementederror + def _check_host_status_fields(self, host_status): + self.assertIn('host_name-description', host_status) + self.assertIn('host_hostname', host_status) + self.assertIn('host_memory_total', host_status) + self.assertIn('host_memory_overhead', host_status) + self.assertIn('host_memory_free', host_status) + self.assertIn('host_memory_free_computed', host_status) + self.assertIn('host_other_config', host_status) + self.assertIn('host_ip_address', host_status) + self.assertIn('host_cpu_info', host_status) + self.assertIn('disk_available', host_status) + self.assertIn('disk_total', host_status) + self.assertIn('disk_used', host_status) + self.assertIn('host_uuid', host_status) + self.assertIn('host_name_label', host_status) + + @catch_notimplementederror + def test_update_host_status(self): + host_status = self.connection.update_host_status() + self._check_host_status_fields(host_status) + + @catch_notimplementederror + def test_get_host_stats(self): + host_status = self.connection.get_host_stats() + self._check_host_status_fields(host_status) + + @catch_notimplementederror + def test_set_host_enabled(self): + self.connection.set_host_enabled('Am I a useless argument?', True) + + @catch_notimplementederror + def test_host_power_action_reboot(self): + self.connection.host_power_action('Am I a useless argument?', 'reboot') + + @catch_notimplementederror + def test_host_power_action_shutdown(self): + self.connection.host_power_action('Am I a useless argument?', 'shutdown') + + @catch_notimplementederror + def test_host_power_action_startup(self): + self.connection.host_power_action('Am I a useless argument?', 'startup') + +class AbstractDriverTestCase(_VirtDriverTestCase): + def setUp(self): + import nova.virt.driver + self.driver_module = nova.virt.driver + def get_driver_connection(_): + return nova.virt.driver.ComputeDriver() + self.driver_module.get_connection = get_driver_connection + super(AbstractDriverTestCase, self).setUp() + +class FakeConnectionTestCase(_VirtDriverTestCase): + def setUp(self): + import nova.virt.fake + self.driver_module = nova.virt.fake + super(FakeConnectionTestCase, self).setUp() + +# Before long, we'll add the real hypervisor drivers here as well +# with whatever instrumentation they need to work independently of +# their hypervisor. This way, we can verify that they all act the +# same. diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 13b7aeab5..e1e909c42 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -67,6 +67,7 @@ class FakeConnection(driver.ComputeDriver): 'disk_used': 100000000000, 'host_uuid': 'cedb9b39-9388-41df-8891-c5c9a0c0fe5f', 'host_name_label': 'fake-mini'} + self._mounts = {} @classmethod def instance(cls): @@ -152,9 +153,16 @@ class FakeConnection(driver.ComputeDriver): (key, self.instances)) def attach_volume(self, instance_name, device_path, mountpoint): + if not instance_name in self._mounts: + self._mounts[instance_name] = {} + self._mounts[instance_name][mountpoint] = device_path return True def detach_volume(self, instance_name, mountpoint): + try: + del self._mounts[instance_name][mountpoint] + except KeyError: + pass return True def get_info(self, instance_name): -- cgit From b24a05dbc19eaf67661eac98aa778d789ffa7b4e Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 22 Aug 2011 23:25:08 +0200 Subject: Make snapshot raise InstanceNotRunning when the instance isn't running. --- nova/virt/fake.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nova/virt/fake.py b/nova/virt/fake.py index e1e909c42..d5e2bf31b 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -100,7 +100,8 @@ class FakeConnection(driver.ComputeDriver): self.instances[name] = fake_instance def snapshot(self, context, instance, name): - pass + if not instance['name'] in self.instances: + raise exception.InstanceNotRunning() def reboot(self, instance, network_info): pass @@ -145,7 +146,7 @@ class FakeConnection(driver.ComputeDriver): pass def destroy(self, instance, network_info, cleanup=True): - key = instance.name + key = instance['name'] if key in self.instances: del self.instances[key] else: -- cgit From 150098011db8ca6c534c4a281df388bd42301eea Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 22 Aug 2011 23:26:12 +0200 Subject: Update a few doc strings. Address a few pep8 issues. Add nova.tests.utils which provides a couple of handy methods for testing stuff. --- nova/tests/test_test_utils.py | 41 +++++++++++++++++++++++++ nova/tests/test_virt_drivers.py | 26 ++++++++++------ nova/tests/utils.py | 68 +++++++++++++++++++++++++++++++++++++++++ nova/virt/driver.py | 18 +++++------ 4 files changed, 132 insertions(+), 21 deletions(-) create mode 100644 nova/tests/test_test_utils.py create mode 100644 nova/tests/utils.py diff --git a/nova/tests/test_test_utils.py b/nova/tests/test_test_utils.py new file mode 100644 index 000000000..237339758 --- /dev/null +++ b/nova/tests/test_test_utils.py @@ -0,0 +1,41 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright 2010 OpenStack LLC +# +# 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 nova import db +from nova import test +from nova.tests import utils as test_utils + + +class TestUtilsTestCase(test.TestCase): + def test_get_test_admin_context(self): + """get_test_admin_context's return value behaves like admin context""" + ctxt = test_utils.get_test_admin_context() + + # TODO(soren): This should verify the full interface context + # objects expose. + self.assertTrue(ctxt.is_admin) + + def test_get_test_instance(self): + """get_test_instance's return value looks like an instance_ref""" + instance_ref = test_utils.get_test_instance() + ctxt = test_utils.get_test_admin_context() + db.instance_get(ctxt, instance_ref['id']) + + def _test_get_test_network_info(self): + """Does the return value match a real network_info structure""" + # The challenge here is to define what exactly such a structure + # must look like. + pass diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py index 2c91c0664..480247c91 100644 --- a/nova/tests/test_virt_drivers.py +++ b/nova/tests/test_virt_drivers.py @@ -31,6 +31,7 @@ FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.test_virt_drivers') + def catch_notimplementederror(f): """Decorator to simplify catching drivers raising NotImplementedError @@ -50,6 +51,7 @@ def catch_notimplementederror(f): wrapped_func.__doc__ = f.__doc__ return wrapped_func + class _VirtDriverTestCase(test.TestCase): def setUp(self): super(_VirtDriverTestCase, self).setUp() @@ -151,14 +153,14 @@ class _VirtDriverTestCase(test.TestCase): network_info = test_utils.get_test_network_info() self.connection.spawn(self.ctxt, instance_ref, network_info) self.connection.rescue(self.ctxt, instance_ref, - lambda x:None, network_info) + lambda x: None, network_info) @catch_notimplementederror def test_unrescue_unrescued_instance(self): instance_ref = test_utils.get_test_instance() network_info = test_utils.get_test_network_info() self.connection.spawn(self.ctxt, instance_ref, network_info) - self.connection.unrescue(instance_ref, lambda x:None, network_info) + self.connection.unrescue(instance_ref, lambda x: None, network_info) @catch_notimplementederror def test_unrescue_rescued_instance(self): @@ -166,8 +168,8 @@ class _VirtDriverTestCase(test.TestCase): network_info = test_utils.get_test_network_info() self.connection.spawn(self.ctxt, instance_ref, network_info) self.connection.rescue(self.ctxt, instance_ref, - lambda x:None, network_info) - self.connection.unrescue(instance_ref, lambda x:None, network_info) + lambda x: None, network_info) + self.connection.unrescue(instance_ref, lambda x: None, network_info) @catch_notimplementederror def test_poll_rescued_instances(self): @@ -226,7 +228,7 @@ class _VirtDriverTestCase(test.TestCase): @catch_notimplementederror def test_destroy_instance_nonexistant(self): - fake_instance = { 'id': 42, 'name': 'I just made this up!' } + fake_instance = {'id': 42, 'name': 'I just made this up!'} network_info = test_utils.get_test_network_info() self.connection.destroy(fake_instance, network_info) @@ -410,7 +412,6 @@ class _VirtDriverTestCase(test.TestCase): network_info = test_utils.get_test_network_info() self.connection.unfilter_instance(instance_ref, network_info) - @catch_notimplementederror def test_live_migration(self): network_info = test_utils.get_test_network_info() @@ -448,29 +449,34 @@ class _VirtDriverTestCase(test.TestCase): @catch_notimplementederror def test_set_host_enabled(self): - self.connection.set_host_enabled('Am I a useless argument?', True) + self.connection.set_host_enabled('a useless argument?', True) @catch_notimplementederror def test_host_power_action_reboot(self): - self.connection.host_power_action('Am I a useless argument?', 'reboot') + self.connection.host_power_action('a useless argument?', 'reboot') @catch_notimplementederror def test_host_power_action_shutdown(self): - self.connection.host_power_action('Am I a useless argument?', 'shutdown') + self.connection.host_power_action('a useless argument?', 'shutdown') @catch_notimplementederror def test_host_power_action_startup(self): - self.connection.host_power_action('Am I a useless argument?', 'startup') + self.connection.host_power_action('a useless argument?', 'startup') + class AbstractDriverTestCase(_VirtDriverTestCase): def setUp(self): import nova.virt.driver + self.driver_module = nova.virt.driver + def get_driver_connection(_): return nova.virt.driver.ComputeDriver() + self.driver_module.get_connection = get_driver_connection super(AbstractDriverTestCase, self).setUp() + class FakeConnectionTestCase(_VirtDriverTestCase): def setUp(self): import nova.virt.fake diff --git a/nova/tests/utils.py b/nova/tests/utils.py new file mode 100644 index 000000000..e0cacadb4 --- /dev/null +++ b/nova/tests/utils.py @@ -0,0 +1,68 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright 2011 OpenStack LLC +# +# 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 +# + +import nova.context +import nova.db +import nova.flags + +FLAGS = nova.flags.FLAGS + + +def get_test_admin_context(): + return nova.context.get_admin_context() + + +def get_test_instance(context=None): + if not context: + context = get_test_admin_context() + + test_instance = {'memory_kb': '1024000', + 'basepath': '/some/path', + 'bridge_name': 'br100', + 'vcpus': 2, + 'project_id': 'fake', + 'bridge': 'br101', + 'image_ref': '1', + 'instance_type_id': '5'} # m1.small + + instance_ref = nova.db.instance_create(context, test_instance) + return instance_ref + + +def get_test_network_info(count=1): + ipv6 = FLAGS.use_ipv6 + fake = 'fake' + fake_ip = '0.0.0.0/0' + fake_ip_2 = '0.0.0.1/0' + fake_ip_3 = '0.0.0.1/0' + fake_vlan = 100 + fake_bridge_interface = 'eth0' + network = {'bridge': fake, + 'cidr': fake_ip, + 'cidr_v6': fake_ip, + 'vlan': fake_vlan, + 'bridge_interface': fake_bridge_interface, + 'injected': False} + mapping = {'mac': fake, + 'dhcp_server': fake, + 'gateway': fake, + 'gateway6': fake, + 'ips': [{'ip': fake_ip}, {'ip': fake_ip}]} + if ipv6: + mapping['ip6s'] = [{'ip': fake_ip}, + {'ip': fake_ip_2}, + {'ip': fake_ip_3}] + return [(network, mapping) for x in xrange(0, count)] diff --git a/nova/virt/driver.py b/nova/virt/driver.py index 93290aba7..d05b51bd9 100644 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -140,7 +140,7 @@ class ComputeDriver(object): that it was before this call began. :param context: security context - :param instance: Instance of {nova.compute.service.Instance}. + :param instance: Instance object as returned by DB layer. This function should use the data there to guide the creation of the new instance. :param network_info: @@ -152,14 +152,11 @@ class ComputeDriver(object): def destroy(self, instance, network_info, cleanup=True): """Destroy (shutdown and delete) the specified instance. - The given parameter is an instance of nova.compute.service.Instance, - If the instance is not found (for example if networking failed), this function should still succeed. It's probably a good idea to log a warning in that case. - :param instance: Instance of {nova.compute.service.Instance} and so - the instance is being specified as instance.name. + :param instance: Instance object as returned by DB layer. :param network_info: :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` :param cleanup: @@ -171,8 +168,7 @@ class ComputeDriver(object): def reboot(self, instance, network_info): """Reboot the specified instance. - :param instance: Instance of {nova.compute.service.Instance} and so - the instance is being specified as instance.name. + :param instance: Instance object as returned by DB layer. :param network_info: :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` """ @@ -240,10 +236,10 @@ class ComputeDriver(object): """ Snapshots the specified instance. - The given parameter is an instance of nova.compute.service.Instance, - and so the instance is being specified as instance.name. - - The second parameter is the name of the snapshot. + :param context: security context + :param instance: Instance object as returned by DB layer. + :param image_id: Reference to a pre-created image that will + hold the snapshot. """ raise NotImplementedError() -- cgit From 0d0c8dfbf29b47aa13e18dd8861bad6ccb10cf12 Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Mon, 22 Aug 2011 16:46:29 -0700 Subject: Change parameters of 'nova-manage network modify'. Move common test codes into private method. --- bin/nova-manage | 40 +++++++++++++++++++++------------------- nova/tests/test_nova_manage.py | 21 +++++++++++---------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 736e55653..349a53a5c 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -798,32 +798,34 @@ class NetworkCommands(object): @args('--network', dest="fixed_range", metavar='', help='Network to modify') @args('--project', dest="project", metavar='', - help='Project name to associate/disasscociate') + help='Project name to associate') @args('--host', dest="host", metavar='', - help='Host to associate/disasscociate') - def modify(self, fixed_range, project=None, host=None): - """Associate/Disasscociate Network with Project and/or Host + help='Host to associate') + @args('--disassociate-project', action="store_true", dest='dis_project', + default=False, help='Disassociate Network from Project') + @args('--disassociate-host', action="store_true", dest='dis_host', + default=False, help='Disassociate Host from Project') + def modify(self, fixed_range, project=None, host=None, + dis_project=None, dis_host=None): + """Associate/Disassociate Network with Project and/or Host arguments: network project host - specify 'None' to disassociate it leave any field blank to ignore it """ admin_context = context.get_admin_context() network = db.network_get_by_cidr(admin_context, fixed_range) - if project != "None": - if project: - project_id = manager.Project.safe_id(project) - db.network_associate_by_id(admin_context, - network_id=network['id'], - project_id=project, - force=True) - else: + if project: + project_id = manager.Project.safe_id(project) + db.network_associate_by_id(admin_context, + network_id=network['id'], + project_id=project, + force=True) + elif dis_project: db.network_disassociate(admin_context, network_id=network['id']) - if host != "None": - if host: - db.network_set_host(admin_context, - network['id'], - host) - else: + if host: + db.network_set_host(admin_context, + network['id'], + host) + elif dis_host: db.network_set_host(admin_context, network['id'], None) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index d6edc8ba9..91130de67 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -36,10 +36,10 @@ import netaddr import StringIO from nova import context from nova import db -from nova import flags -from nova import test from nova import exception +from nova import flags from nova import log as logging +from nova import test FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.nova_manage') @@ -101,7 +101,7 @@ class NetworkCommandsTestCase(test.TestCase): def tearDown(self): super(NetworkCommandsTestCase, self).tearDown() - def test_create(self): + def _create_network(self): FLAGS.network_manager = 'nova.network.manager.VlanManager' self.commands.create( label='Test', @@ -114,7 +114,10 @@ class NetworkCommandsTestCase(test.TestCase): fixed_range_v6='fd00:2::/120', gateway_v6='fd00:2::22', bridge_interface='eth0') - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + return db.network_get_by_cidr(self.context, '10.2.0.0/24') + + def test_create(self): + net = self._create_network() self.assertEqual(net['label'], 'Test') self.assertEqual(net['cidr'], '10.2.0.0/24') self.assertEqual(net['netmask'], '255.255.255.0') @@ -127,8 +130,7 @@ class NetworkCommandsTestCase(test.TestCase): self.assertEqual(net['bridge_interface'], 'eth0') def test_list(self): - self.test_create() - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + net = self._create_network() output = StringIO.StringIO() sys.stdout = output self.commands.list() @@ -158,7 +160,7 @@ class NetworkCommandsTestCase(test.TestCase): self.assertEqual(result, answer) def test_delete(self): - self.test_create() + net = self._create_network() self.commands.delete(fixed_range='10.2.0.0/24') net_exist = True try: @@ -168,8 +170,7 @@ class NetworkCommandsTestCase(test.TestCase): self.assertEqual(net_exist, False) def test_modify(self): - self.test_create() - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') + net = self._create_network() db.network_disassociate(self.context, net['id']) net = db.network_get_by_cidr(self.context, '10.2.0.0/24') self.assertEqual(net['project_id'], None) @@ -183,7 +184,7 @@ class NetworkCommandsTestCase(test.TestCase): net = db.network_get_by_cidr(self.context, '10.2.0.0/24') self.assertEqual(net['project_id'], 'test_project') self.assertEqual(net['host'], 'test_host') - self.commands.modify('10.2.0.0/24', project='None', host='None') + self.commands.modify('10.2.0.0/24', dis_project=True, dis_host=True) net = db.network_get_by_cidr(self.context, '10.2.0.0/24') self.assertEqual(net['project_id'], None) self.assertEqual(net['host'], None) -- cgit From 8cd7dcca1ccac0347289d633ebd10567d6cba4c7 Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Tue, 23 Aug 2011 15:06:24 -0700 Subject: Stub out the DB in unit test. Fix 'nova-manage network modify' to use db.network_update() --- bin/nova-manage | 18 ++--- nova/db/api.py | 6 -- nova/db/sqlalchemy/api.py | 31 -------- nova/tests/test_nova_manage.py | 162 +++++++++++++++++++++++++++-------------- 4 files changed, 113 insertions(+), 104 deletions(-) diff --git a/bin/nova-manage b/bin/nova-manage index 349a53a5c..b0322eb11 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -813,22 +813,16 @@ class NetworkCommands(object): """ admin_context = context.get_admin_context() network = db.network_get_by_cidr(admin_context, fixed_range) + net = {} if project: - project_id = manager.Project.safe_id(project) - db.network_associate_by_id(admin_context, - network_id=network['id'], - project_id=project, - force=True) + net['project_id'] = project elif dis_project: - db.network_disassociate(admin_context, network_id=network['id']) + net['project_id'] = None if host: - db.network_set_host(admin_context, - network['id'], - host) + net['host'] = host elif dis_host: - db.network_set_host(admin_context, - network['id'], - None) + net['host'] = None + db.network_update(admin_context, network['id'], net) class VmCommands(object): diff --git a/nova/db/api.py b/nova/db/api.py index 7268cde7f..2d854f24c 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -621,12 +621,6 @@ def network_associate(context, project_id, force=False): return IMPL.network_associate(context, project_id, force) -def network_associate_by_id(context, network_id, project_id, force=False): - """Associate a project with a network specified by id.""" - return IMPL.network_associate_by_id(context, network_id, project_id, - force=False) - - def network_count(context): """Return the number of networks.""" return IMPL.network_count(context) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index e5fffa784..04b5405f6 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -1662,37 +1662,6 @@ def network_associate(context, project_id, force=False): return network_ref -@require_admin_context -def network_associate_by_id(context, network_id, project_id, force=False): - """Associate a project with a network specified by id. - - only associate if the network isn't already associated - with a project or if force is True - """ - session = get_session() - with session.begin(): - - def network_query(network_filter): - if force: - return session.query(models.Network).\ - filter_by(deleted=False).\ - filter_by(id=network_filter).\ - with_lockmode('update').\ - first() - else: - return session.query(models.Network).\ - filter_by(deleted=False).\ - filter_by(project_id=None).\ - filter_by(id=network_filter).\ - with_lockmode('update').\ - first() - network_ref = network_query(network_id) - if network_ref: - network_ref['project_id'] = project_id - session.add(network_ref) - return network_ref - - @require_admin_context def network_count(context): session = get_session() diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 6b34a90f9..03ee1140d 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -75,17 +75,59 @@ class FixedIpCommandsTestCase(test.TestCase): class NetworkCommandsTestCase(test.TestCase): def setUp(self): super(NetworkCommandsTestCase, self).setUp() + self.stubs = stubout.StubOutForTesting() self.commands = nova_manage.NetworkCommands() self.context = context.get_admin_context() - nets = db.network_get_all(self.context) - for net in nets: - db.network_delete_safe(self.context, net['id']) + self.net = {'id': 0, + 'label': 'fake', + 'injected': False, + 'cidr': '192.168.0.0/24', + 'cidr_v6': 'dead:beef::/64', + 'multi_host': False, + 'gateway_v6': 'dead:beef::1', + 'netmask_v6': '64', + 'netmask': '255.255.255.0', + 'bridge': 'fa0', + 'bridge_interface': 'fake_fa0', + 'gateway': '192.168.0.1', + 'broadcast': '192.168.0.255', + 'dns1': '8.8.8.8', + 'dns2': '8.8.4.4', + 'vlan': 200, + 'vpn_public_address': '10.0.0.2', + 'vpn_public_port': '2222', + 'vpn_private_address': '192.168.0.2', + 'dhcp_start': '192.168.0.3', + 'project_id': 'fake_project', + 'host': 'fake_host', + 'uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'} + def tearDown(self): super(NetworkCommandsTestCase, self).tearDown() + self.stubs.UnsetAll() + + def test_create(self): - def _create_network(self): + def fake_create_networks(obj, context, **kwargs): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(kwargs['label'], 'Test') + self.assertEqual(kwargs['cidr'], '10.2.0.0/24') + self.assertEqual(kwargs['multi_host'], False) + self.assertEqual(kwargs['num_networks'], 1) + self.assertEqual(kwargs['network_size'], 256) + self.assertEqual(kwargs['vlan_start'], 200) + self.assertEqual(kwargs['vpn_start'], 2000) + self.assertEqual(kwargs['cidr_v6'], 'fd00:2::/120') + self.assertEqual(kwargs['gateway_v6'], 'fd00:2::22') + self.assertEqual(kwargs['bridge'], 'br200') + self.assertEqual(kwargs['bridge_interface'], 'eth0') + self.assertEqual(kwargs['dns1'], '8.8.8.8') + self.assertEqual(kwargs['dns2'], '8.8.4.4') FLAGS.network_manager = 'nova.network.manager.VlanManager' + from nova.network import manager as net_manager + self.stubs.Set(net_manager.VlanManager, 'create_networks', + fake_create_networks) self.commands.create( label='Test', fixed_range_v4='10.2.0.0/24', @@ -96,24 +138,16 @@ class NetworkCommandsTestCase(test.TestCase): vpn_start=2000, fixed_range_v6='fd00:2::/120', gateway_v6='fd00:2::22', - bridge_interface='eth0') - return db.network_get_by_cidr(self.context, '10.2.0.0/24') - - def test_create(self): - net = self._create_network() - self.assertEqual(net['label'], 'Test') - self.assertEqual(net['cidr'], '10.2.0.0/24') - self.assertEqual(net['netmask'], '255.255.255.0') - self.assertEqual(net['multi_host'], False) - self.assertEqual(net['vlan'], 200) - self.assertEqual(net['bridge'], 'br200') - self.assertEqual(net['vpn_public_port'], 2000) - self.assertEqual(net['cidr_v6'], 'fd00:2::/120') - self.assertEqual(net['gateway_v6'], 'fd00:2::22') - self.assertEqual(net['bridge_interface'], 'eth0') + bridge='br200', + bridge_interface='eth0', + dns1='8.8.8.8', + dns2='8.8.4.4') def test_list(self): - net = self._create_network() + + def fake_network_get_all(context): + return [db_fakes.FakeModel(self.net)] + self.stubs.Set(db, 'network_get_all', fake_network_get_all) output = StringIO.StringIO() sys.stdout = output self.commands.list() @@ -129,45 +163,63 @@ class NetworkCommandsTestCase(test.TestCase): _('VlanID'), _('project'), _("uuid")) - body = _fmt % ( - net['id'], - '10.2.0.0/24', - 'fd00:2::/120', - '10.2.0.3', - 'None', - 'None', - '200', - 'None', - net['uuid'],) + body = _fmt % (self.net['id'], + self.net['cidr'], + self.net['cidr_v6'], + self.net['dhcp_start'], + self.net['dns1'], + self.net['dns2'], + self.net['vlan'], + self.net['project_id'], + self.net['uuid']) answer = '%s\n%s\n' % (head, body) self.assertEqual(result, answer) def test_delete(self): - net = self._create_network() - self.commands.delete(fixed_range='10.2.0.0/24') - net_exist = True - try: - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') - except exception.NetworkNotFoundForCidr, e: - net_exist = False - self.assertEqual(net_exist, False) + net_dis = self.net + net_dis['project_id'] = None + net_dis['host'] = None + + def fake_network_get_by_cidr(context, cidr): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(cidr, net_dis['cidr']) + return db_fakes.FakeModel(net_dis) + self.stubs.Set(db, 'network_get_by_cidr', fake_network_get_by_cidr) + + def fake_network_delete_safe(context, network_id): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(network_id, net_dis['id']) + self.stubs.Set(db, 'network_delete_safe', fake_network_delete_safe) + self.commands.delete(fixed_range=net_dis['cidr']) def test_modify(self): - net = self._create_network() - db.network_disassociate(self.context, net['id']) - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') - self.assertEqual(net['project_id'], None) - self.assertEqual(net['host'], None) - self.commands.modify('10.2.0.0/24', project='test_project', + + def fake_network_get_by_cidr(context, cidr): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(cidr, self.net['cidr']) + return db_fakes.FakeModel(self.net) + self.stubs.Set(db, 'network_get_by_cidr', fake_network_get_by_cidr) + + def fake_network_update(context, network_id, values): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(network_id, self.net['id']) + self.assertEqual(values, {'project_id': 'test_project', + 'host': 'test_host'}) + self.stubs.Set(db, 'network_update', fake_network_update) + self.commands.modify(self.net['cidr'], project='test_project', host='test_host') - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') - self.assertEqual(net['project_id'], 'test_project') - self.assertEqual(net['host'], 'test_host') - self.commands.modify('10.2.0.0/24') - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') - self.assertEqual(net['project_id'], 'test_project') - self.assertEqual(net['host'], 'test_host') - self.commands.modify('10.2.0.0/24', dis_project=True, dis_host=True) - net = db.network_get_by_cidr(self.context, '10.2.0.0/24') - self.assertEqual(net['project_id'], None) - self.assertEqual(net['host'], None) + + def fake_network_update(context, network_id, values): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(network_id, self.net['id']) + self.assertEqual(values, {}) + self.stubs.Set(db, 'network_update', fake_network_update) + self.commands.modify(self.net['cidr']) + + def fake_network_update(context, network_id, values): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(network_id, self.net['id']) + self.assertEqual(values, {'project_id': None, + 'host': None}) + self.stubs.Set(db, 'network_update', fake_network_update) + self.commands.modify(self.net['cidr'], dis_project=True, dis_host=True) -- cgit From 9fbdfa5061dc17e43fc8a5200415e0dffc55b911 Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Tue, 23 Aug 2011 15:40:28 -0700 Subject: Fix pep8 --- nova/tests/test_nova_manage.py | 1 - 1 file changed, 1 deletion(-) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 097d2dbf5..ca4f4c894 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -112,7 +112,6 @@ class NetworkCommandsTestCase(test.TestCase): 'host': 'fake_host', 'uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'} - def tearDown(self): super(NetworkCommandsTestCase, self).tearDown() self.stubs.UnsetAll() -- cgit From 1ba752768a8834a855bd968a5772588f23b81c80 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Tue, 23 Aug 2011 22:43:10 -0400 Subject: Update paste config so that EC2 admin API defaults to noauth. --- etc/nova/api-paste.ini | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/etc/nova/api-paste.ini b/etc/nova/api-paste.ini index dafdef877..cd24efb13 100644 --- a/etc/nova/api-paste.ini +++ b/etc/nova/api-paste.ini @@ -26,7 +26,11 @@ pipeline = logrequest ec2noauth cloudrequest authorizer ec2executor # pipeline = logrequest totoken authtoken keystonecontext cloudrequest authorizer ec2executor [pipeline:ec2admin] -pipeline = logrequest authenticate adminrequest authorizer ec2executor +pipeline = logrequest ec2noauth adminrequest authorizer ec2executor +# NOTE(vish): use the following pipeline for deprecated auth +#pipeline = logrequest authenticate adminrequest authorizer ec2executor +# NOTE(vish): use the following pipeline for keystone +#pipeline = logrequest totoken authtoken keystonecontext adminrequest authorizer ec2executor [pipeline:ec2metadata] pipeline = logrequest ec2md -- cgit From 0873a3c7b9a1a75c6e04bd1b66f8fbe4935585b2 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 24 Aug 2011 15:49:53 +0100 Subject: Fix flavorid migration failure With sqlalchemy 0.7.2 and migrate 0.7.1, I was seeing: Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/nova/db/migration.py", line 37, in db_sync ret = IMPL.db_sync(version=version) [...] File "/usr/lib/python2.7/site-packages/nova/db/sqlalchemy/migrate_repo/versions/036_change_flavor_id_in_migrations.py", line 46, in upgrade .values(old_instance_type_id=instance_type.id)) [...] File "/usr/lib64/python2.7/site-packages/sqlalchemy/engine/default.py", line 301, in do_commit connection.commit() OperationalError: (OperationalError) database is locked None None It looks like the database is being held open as we iterate over the rows in the instance_types table. --- .../versions/036_change_flavor_id_in_migrations.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) 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 f3244033b..dfbd4ba32 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 @@ -40,13 +40,17 @@ def upgrade(migrate_engine): migrations.create_column(new_instance_type_id) # Convert flavor_id to instance_type_id + itypes = {} for instance_type in migrate_engine.execute(instance_types.select()): + itypes[instance_type.id] = instance_type.flavorid + + for instance_type_id in itypes.keys(): migrate_engine.execute(migrations.update()\ - .where(migrations.c.old_flavor_id == instance_type.flavorid)\ - .values(old_instance_type_id=instance_type.id)) + .where(migrations.c.old_flavor_id == itypes[instance_type_id])\ + .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)) + .where(migrations.c.new_flavor_id == itypes[instance_type_id])\ + .values(new_instance_type_id=instance_type_id)) migrations.c.old_flavor_id.drop() migrations.c.new_flavor_id.drop() -- cgit From b428ac4c20e44f537b0dedeefcc2637efbc998ea Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 24 Aug 2011 15:50:46 +0100 Subject: Fix quotas migration failure With sqlalchemy 0.7.2 and migrate 0.7.1, I was seeing: Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/nova/db/migration.py", line 37, in db_sync ret = IMPL.db_sync(version=version) [..] File "/usr/lib/python2.7/site-packages/nova/db/sqlalchemy/migrate_repo/versions/016_make_quotas_key_and_value.py", line 189, in upgrade new_quotas.rename('quotas') [..] File "/usr/lib/python2.7/site-packages/migrate/changeset/schema.py", line 479, in deregister del meta.tables[key] File "/usr/lib64/python2.7/site-packages/sqlalchemy/util/_collections.py", line 38, in _immutable raise TypeError("%s object is immutable" % self.__class__.__name__) TypeError: immutabledict object is immutable This is actually a bug in sqlalchemy-migrate: http://code.google.com/p/sqlalchemy-migrate/issues/detail?id=128 But it can be worked around by ensuring there isn't a 'quotas' table in the metadata's table hash before renaming. --- .../versions/016_make_quotas_key_and_value.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/016_make_quotas_key_and_value.py b/nova/db/sqlalchemy/migrate_repo/versions/016_make_quotas_key_and_value.py index a4fe3e482..56b287171 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/016_make_quotas_key_and_value.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/016_make_quotas_key_and_value.py @@ -75,8 +75,8 @@ def new_style_quotas_table(name): ) -def existing_quotas_table(migrate_engine): - return Table('quotas', meta, autoload=True, autoload_with=migrate_engine) +def quotas_table(migrate_engine, name='quotas'): + return Table(name, meta, autoload=True, autoload_with=migrate_engine) def _assert_no_duplicate_project_ids(quotas): @@ -179,13 +179,18 @@ def upgrade(migrate_engine): # bind migrate_engine to your metadata meta.bind = migrate_engine - old_quotas = existing_quotas_table(migrate_engine) + old_quotas = quotas_table(migrate_engine) assert_old_quotas_have_no_active_duplicates(migrate_engine, old_quotas) new_quotas = new_style_quotas_table('quotas_new') new_quotas.create() convert_forward(migrate_engine, old_quotas, new_quotas) old_quotas.drop() + + # clear metadata to work around this: + # http://code.google.com/p/sqlalchemy-migrate/issues/detail?id=128 + meta.clear() + new_quotas = quotas_table(migrate_engine, 'quotas_new') new_quotas.rename('quotas') @@ -193,11 +198,16 @@ def downgrade(migrate_engine): # Operations to reverse the above upgrade go here. meta.bind = migrate_engine - new_quotas = existing_quotas_table(migrate_engine) + new_quotas = quotas_table(migrate_engine) assert_new_quotas_have_no_active_duplicates(migrate_engine, new_quotas) old_quotas = old_style_quotas_table('quotas_old') old_quotas.create() convert_backward(migrate_engine, old_quotas, new_quotas) new_quotas.drop() + + # clear metadata to work around this: + # http://code.google.com/p/sqlalchemy-migrate/issues/detail?id=128 + meta.clear() + old_quotas = quotas_table(migrate_engine, 'quotas_old') old_quotas.rename('quotas') -- cgit From df0f06a8f0d66f07f402aa54cb1aa7ce1b7416c9 Mon Sep 17 00:00:00 2001 From: "vladimir.p" Date: Wed, 24 Aug 2011 08:51:14 -0700 Subject: check log file mode prior to chmod --- nova/log.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nova/log.py b/nova/log.py index 222b8c5fb..3b86d78e8 100644 --- a/nova/log.py +++ b/nova/log.py @@ -257,7 +257,11 @@ class NovaRootLogger(NovaLogger): self.filelog = WatchedFileHandler(logpath) self.addHandler(self.filelog) self.logpath = logpath - os.chmod(self.logpath, FLAGS.logfile_mode) + + import stat + st = os.stat(self.logpath) + if st.st_mode != (stat.S_IFREG | FLAGS.logfile_mode): + os.chmod(self.logpath, FLAGS.logfile_mode) else: self.removeHandler(self.filelog) self.addHandler(self.streamlog) -- cgit From 390f35f8e7736bfbd650c9e3f522274e92adb005 Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Wed, 24 Aug 2011 09:11:57 -0700 Subject: Fix flag override in unit test --- nova/tests/test_nova_manage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index ca4f4c894..ce731222c 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -133,7 +133,7 @@ class NetworkCommandsTestCase(test.TestCase): self.assertEqual(kwargs['bridge_interface'], 'eth0') self.assertEqual(kwargs['dns1'], '8.8.8.8') self.assertEqual(kwargs['dns2'], '8.8.4.4') - FLAGS.network_manager = 'nova.network.manager.VlanManager' + self.flags(network_manager='nova.network.manager.VlanManager') from nova.network import manager as net_manager self.stubs.Set(net_manager.VlanManager, 'create_networks', fake_create_networks) -- cgit From 5ab769daf354033f5044c88d4f899d56effd998e Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Wed, 24 Aug 2011 10:47:11 -0700 Subject: split test_modify() into specific unit tests --- nova/tests/test_nova_manage.py | 88 ++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index ce731222c..c83d773f2 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -34,18 +34,15 @@ sys.dont_write_bytecode = False import mox import stubout -import netaddr import StringIO from nova import context from nova import db from nova import exception from nova import flags -from nova import log as logging from nova import test from nova.tests.db import fakes as db_fakes FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.tests.nova_manage') class FixedIpCommandsTestCase(test.TestCase): @@ -112,6 +109,18 @@ class NetworkCommandsTestCase(test.TestCase): 'host': 'fake_host', 'uuid': 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'} + def fake_network_get_by_cidr(context, cidr): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(cidr, self.fake_net['cidr']) + return db_fakes.FakeModel(self.fake_net) + + def fake_network_update(context, network_id, values): + self.assertTrue(context.to_dict()['is_admin']) + self.assertEqual(network_id, self.fake_net['id']) + self.assertEqual(values, self.fake_update_value) + self.fake_network_get_by_cidr = fake_network_get_by_cidr + self.fake_network_update = fake_network_update + def tearDown(self): super(NetworkCommandsTestCase, self).tearDown() self.stubs.UnsetAll() @@ -185,50 +194,37 @@ class NetworkCommandsTestCase(test.TestCase): self.assertEqual(result, answer) def test_delete(self): - net_dis = self.net - net_dis['project_id'] = None - net_dis['host'] = None - - def fake_network_get_by_cidr(context, cidr): - self.assertTrue(context.to_dict()['is_admin']) - self.assertEqual(cidr, net_dis['cidr']) - return db_fakes.FakeModel(net_dis) - self.stubs.Set(db, 'network_get_by_cidr', fake_network_get_by_cidr) + self.fake_net = self.net + self.fake_net['project_id'] = None + self.fake_net['host'] = None + self.stubs.Set(db, 'network_get_by_cidr', + self.fake_network_get_by_cidr) def fake_network_delete_safe(context, network_id): self.assertTrue(context.to_dict()['is_admin']) - self.assertEqual(network_id, net_dis['id']) + self.assertEqual(network_id, self.fake_net['id']) self.stubs.Set(db, 'network_delete_safe', fake_network_delete_safe) - self.commands.delete(fixed_range=net_dis['cidr']) - - def test_modify(self): - - def fake_network_get_by_cidr(context, cidr): - self.assertTrue(context.to_dict()['is_admin']) - self.assertEqual(cidr, self.net['cidr']) - return db_fakes.FakeModel(self.net) - self.stubs.Set(db, 'network_get_by_cidr', fake_network_get_by_cidr) - - def fake_network_update(context, network_id, values): - self.assertTrue(context.to_dict()['is_admin']) - self.assertEqual(network_id, self.net['id']) - self.assertEqual(values, {'project_id': 'test_project', - 'host': 'test_host'}) - self.stubs.Set(db, 'network_update', fake_network_update) - self.commands.modify(self.net['cidr'], project='test_project', - host='test_host') - - def fake_network_update(context, network_id, values): - self.assertTrue(context.to_dict()['is_admin']) - self.assertEqual(network_id, self.net['id']) - self.assertEqual(values, {}) - self.stubs.Set(db, 'network_update', fake_network_update) - self.commands.modify(self.net['cidr']) - - def fake_network_update(context, network_id, values): - self.assertTrue(context.to_dict()['is_admin']) - self.assertEqual(network_id, self.net['id']) - self.assertEqual(values, {'project_id': None, - 'host': None}) - self.stubs.Set(db, 'network_update', fake_network_update) - self.commands.modify(self.net['cidr'], dis_project=True, dis_host=True) + self.commands.delete(fixed_range=self.fake_net['cidr']) + + def _test_modify_base(self, update_value, project, host, dis_project=None, + dis_host=None): + self.fake_net = self.net + self.fake_update_value = update_value + self.stubs.Set(db, 'network_get_by_cidr', + self.fake_network_get_by_cidr) + self.stubs.Set(db, 'network_update', self.fake_network_update) + self.commands.modify(self.fake_net['cidr'], project=project, host=host, + dis_project=dis_project, dis_host=dis_host) + + def test_modify_associate(self): + self._test_modify_base(update_value={'project_id': 'test_project', + 'host': 'test_host'}, + project='test_project', host='test_host') + + def test_modify_unchanged(self): + self._test_modify_base(update_value={}, project=None, host=None) + + def test_modify_disassociate(self): + self._test_modify_base(update_value={'project_id': None, 'host': None}, + project=None, host=None, dis_project=True, + dis_host=True) -- cgit From e51c73a2d953103d4245cb8d456cad590be73ff5 Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Wed, 24 Aug 2011 11:10:05 -0700 Subject: Removed unused imports --- nova/tests/test_nova_manage.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index c83d773f2..70efbf651 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -15,7 +15,6 @@ # License for the specific language governing permissions and limitations # under the License. -import gettext import os import sys @@ -25,8 +24,6 @@ TOPDIR = os.path.normpath(os.path.join( os.pardir)) NOVA_MANAGE_PATH = os.path.join(TOPDIR, 'bin', 'nova-manage') -gettext.install('nova', unicode=1) - sys.dont_write_bytecode = True import imp nova_manage = imp.load_source('nova_manage.py', NOVA_MANAGE_PATH) @@ -38,12 +35,9 @@ import StringIO from nova import context from nova import db from nova import exception -from nova import flags from nova import test from nova.tests.db import fakes as db_fakes -FLAGS = flags.FLAGS - class FixedIpCommandsTestCase(test.TestCase): def setUp(self): -- cgit From 156f2fb68981bde1a24233e2648d11890a98e34a Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Wed, 24 Aug 2011 13:10:56 -0700 Subject: Add names to placeholders of formatting --- nova/tests/test_nova_manage.py | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 70efbf651..520bfbea1 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -165,25 +165,27 @@ class NetworkCommandsTestCase(test.TestCase): self.commands.list() sys.stdout = sys.__stdout__ result = output.getvalue() - _fmt = "%-5s\t%-18s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s\t%-15s" - head = _fmt % (_('id'), - _('IPv4'), - _('IPv6'), - _('start address'), - _('DNS1'), - _('DNS2'), - _('VlanID'), - _('project'), - _("uuid")) - body = _fmt % (self.net['id'], - self.net['cidr'], - self.net['cidr_v6'], - self.net['dhcp_start'], - self.net['dns1'], - self.net['dns2'], - self.net['vlan'], - self.net['project_id'], - self.net['uuid']) + _fmt = "%(id)-5s\t%(cidr)-18s\t%(cidr_v6)-15s\t%(dhcp_start)-15s\t" +\ + "%(dns1)-15s\t%(dns2)-15s\t%(vlan)-15s\t%(project_id)-15s\t" +\ + "%(uuid)-15s" + head = _fmt % {'id': _('id'), + 'cidr': _('IPv4'), + 'cidr_v6': _('IPv6'), + 'dhcp_start': _('start address'), + 'dns1': _('DNS1'), + 'dns2': _('DNS2'), + 'vlan': _('VlanID'), + 'project_id': _('project'), + 'uuid': _("uuid")} + body = _fmt % {'id': self.net['id'], + 'cidr': self.net['cidr'], + 'cidr_v6': self.net['cidr_v6'], + 'dhcp_start': self.net['dhcp_start'], + 'dns1': self.net['dns1'], + 'dns2': self.net['dns2'], + 'vlan': self.net['vlan'], + 'project_id': self.net['project_id'], + 'uuid': self.net['uuid']} answer = '%s\n%s\n' % (head, body) self.assertEqual(result, answer) -- cgit From 88a2dfb582eec7b4c7547c2aa51f3b661a3b9c5d Mon Sep 17 00:00:00 2001 From: Hisaharu Ishii Date: Wed, 24 Aug 2011 14:01:33 -0700 Subject: Add comments for associate/dissociate logic --- bin/nova-manage | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/nova-manage b/bin/nova-manage index eae9e905c..890cde0b8 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -817,6 +817,10 @@ class NetworkCommands(object): admin_context = context.get_admin_context() network = db.network_get_by_cidr(admin_context, fixed_range) net = {} + #User can choose the following actions each for project and host. + #1) Associate (set not None value given by project/host parameter) + #2) Disassociate (set None by disassociate parameter) + #3) Keep unchanged (project/host key is not added to 'net') if project: net['project_id'] = project elif dis_project: -- cgit From b77d1462eb40fc9473aed5df84903e80fd6a1525 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Wed, 24 Aug 2011 22:16:02 +0100 Subject: Add me to Authors --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index 310c0c8b9..68e922ff7 100644 --- a/Authors +++ b/Authors @@ -69,6 +69,7 @@ Koji Iida Lorin Hochstein Lvov Maxim Mandell Degerness +Mark McLoughlin Mark Washenberger Masanori Itoh Matt Dietz -- cgit From e30d2c372cc36d7e9a6cf3af5016834b499a7b42 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Wed, 24 Aug 2011 15:18:17 -0700 Subject: fixing inappropriate rubyism in test code --- nova/tests/test_instance_types.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 556ba91a9..409a22fb6 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -47,24 +47,24 @@ class InstanceTypeTestCase(test.TestCase): self.id = max_id["id"] + 1 self.name = str(int(time.time())) - def _nonexistant_flavor_name(self): + def _nonexistent_flavor_name(self): """return an instance type name not in the DB""" - nonexistant_flavor = "sdfsfsdf" + nonexistent_flavor = "sdfsfsdf" flavors = instance_types.get_all_types() - while nonexistant_flavor in flavors: - nonexistant_flavor = nonexistant_flavor.join("z") + while nonexistent_flavor in flavors: + nonexistent_flavor += "z" else: - return nonexistant_flavor + return nonexistent_flavor - def _nonexistant_flavor_id(self): + def _nonexistent_flavor_id(self): """return an instance type ID not in the DB""" - nonexistant_flavor = 2700 + nonexistent_flavor = 2700 flavor_ids = [value["id"] for key, value in\ instance_types.get_all_types().iteritems()] - while nonexistant_flavor in flavor_ids: - nonexistant_flavor += 1 + while nonexistent_flavor in flavor_ids: + nonexistent_flavor += 1 else: - return nonexistant_flavor + return nonexistent_flavor def _existing_flavor(self): """return first instance type name""" @@ -111,7 +111,7 @@ class InstanceTypeTestCase(test.TestCase): """Ensures that instance type creation fails with invalid args""" self.assertRaises(exception.ApiError, instance_types.destroy, - self._nonexistant_flavor_name()) + self._nonexistent_flavor_name()) def test_repeated_inst_types_should_raise_api_error(self): """Ensures that instance duplicates raises ApiError""" @@ -126,7 +126,7 @@ class InstanceTypeTestCase(test.TestCase): """Ensure destroy sad path of no name raises error""" self.assertRaises(exception.ApiError, instance_types.destroy, - self._nonexistant_flavor_name()) + self._nonexistent_flavor_name()) def test_will_not_purge_without_name(self): """Ensure purge without a name raises error""" @@ -137,11 +137,11 @@ class InstanceTypeTestCase(test.TestCase): """Ensure purge without correct name raises error""" self.assertRaises(exception.ApiError, instance_types.purge, - self._nonexistant_flavor_name()) + self._nonexistent_flavor_name()) def test_will_not_get_bad_default_instance_type(self): """ensures error raised on bad default instance type""" - FLAGS.default_instance_type = self._nonexistant_flavor_name() + FLAGS.default_instance_type = self._nonexistent_flavor_name() self.assertRaises(exception.InstanceTypeNotFoundByName, instance_types.get_default_instance_type) @@ -154,10 +154,10 @@ class InstanceTypeTestCase(test.TestCase): """Ensure get by name returns default flavor with bad name""" self.assertRaises(exception.InstanceTypeNotFound, instance_types.get_instance_type, - self._nonexistant_flavor_name()) + self._nonexistent_flavor_name()) def test_will_not_get_flavor_by_bad_flavor_id(self): """Ensure get by flavor raises error with wrong flavorid""" self.assertRaises(exception.InstanceTypeNotFound, instance_types.get_instance_type_by_name, - self._nonexistant_flavor_id()) + self._nonexistent_flavor_id()) -- cgit From e356009b3ab374f073c2ff2cdb30d78bf432670d Mon Sep 17 00:00:00 2001 From: "vladimir.p" Date: Wed, 24 Aug 2011 15:20:37 -0700 Subject: moved import to the top --- nova/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/log.py b/nova/log.py index 3b86d78e8..b1dfd9ed2 100644 --- a/nova/log.py +++ b/nova/log.py @@ -34,6 +34,7 @@ import logging.handlers import os import sys import traceback +import stat import nova from nova import flags @@ -258,7 +259,6 @@ class NovaRootLogger(NovaLogger): self.addHandler(self.filelog) self.logpath = logpath - import stat st = os.stat(self.logpath) if st.st_mode != (stat.S_IFREG | FLAGS.logfile_mode): os.chmod(self.logpath, FLAGS.logfile_mode) -- cgit From dde9fdc6665e2562ec490fe43f46dcf945c59220 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Wed, 24 Aug 2011 16:03:32 -0700 Subject: removes french spellings to satisfy american developers --- nova/tests/test_instance_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 409a22fb6..09f532239 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -107,7 +107,7 @@ class InstanceTypeTestCase(test.TestCase): exception.InvalidInput, instance_types.create, self.name, 256, 1, "aa", self.flavorid) - def test_non_existant_inst_type_shouldnt_delete(self): + def test_non_existent_inst_type_shouldnt_delete(self): """Ensures that instance type creation fails with invalid args""" self.assertRaises(exception.ApiError, instance_types.destroy, -- cgit From d8da62dd6b30505bc700bafcd73f4f990cdab807 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 25 Aug 2011 11:37:17 -0400 Subject: fixing bug --- nova/virt/xenapi/vmops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 64c106f47..e90022de3 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -241,7 +241,7 @@ class VMOps(object): # Alter the image before VM start for, e.g. network injection also # alter the image if there's metadata. - if FLAGS.flat_injected or instance['metadata']: + if FLAGS.flat_injected: VMHelper.preconfigure_instance(self._session, instance, first_vdi_ref, network_info) -- cgit From 42f9739a608b5b6219aa9f51bc90c2d072edc33a Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 25 Aug 2011 11:44:21 -0400 Subject: changing comment --- nova/virt/xenapi/vmops.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index e90022de3..c5f105f40 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -239,8 +239,7 @@ class VMOps(object): self._attach_disks(instance, disk_image_type, vm_ref, first_vdi_ref, vdis) - # Alter the image before VM start for, e.g. network injection also - # alter the image if there's metadata. + # Alter the image before VM start for network injection. if FLAGS.flat_injected: VMHelper.preconfigure_instance(self._session, instance, first_vdi_ref, network_info) -- cgit From 4859cce97b328cf6f76b3b5bd7a0e7d3227428f7 Mon Sep 17 00:00:00 2001 From: "vladimir.p" Date: Thu, 25 Aug 2011 08:59:21 -0700 Subject: moved import up --- nova/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/log.py b/nova/log.py index b1dfd9ed2..eb0b6020f 100644 --- a/nova/log.py +++ b/nova/log.py @@ -32,9 +32,9 @@ import json import logging import logging.handlers import os +import stat import sys import traceback -import stat import nova from nova import flags -- cgit -- cgit From fafaf040ed4518006efd3e5909ac31bae47af33d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 25 Aug 2011 15:08:28 -0700 Subject: pass all commands to run_iscsiadm as a tuple --- nova/volume/driver.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nova/volume/driver.py b/nova/volume/driver.py index c99534c07..473470788 100644 --- a/nova/volume/driver.py +++ b/nova/volume/driver.py @@ -523,7 +523,7 @@ class ISCSIDriver(VolumeDriver): "node.session.auth.password", iscsi_properties['auth_password']) - self._run_iscsiadm(iscsi_properties, "--login") + self._run_iscsiadm(iscsi_properties, ("--login", )) self._iscsiadm_update(iscsi_properties, "node.startup", "automatic") @@ -544,7 +544,7 @@ class ISCSIDriver(VolumeDriver): locals()) # The rescan isn't documented as being necessary(?), but it helps - self._run_iscsiadm(iscsi_properties, "--rescan") + self._run_iscsiadm(iscsi_properties, ("--rescan", )) tries = tries + 1 if not os.path.exists(mount_device): @@ -561,7 +561,7 @@ class ISCSIDriver(VolumeDriver): """Undiscover volume on a remote host.""" iscsi_properties = self._get_iscsi_properties(volume) self._iscsiadm_update(iscsi_properties, "node.startup", "manual") - self._run_iscsiadm(iscsi_properties, "--logout") + self._run_iscsiadm(iscsi_properties, ("--logout", )) self._run_iscsiadm(iscsi_properties, ('--op', 'delete')) def check_for_export(self, context, volume_id): -- cgit