summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandy Walsh <sandy.walsh@rackspace.com>2011-05-25 08:22:51 -0700
committerSandy Walsh <sandy.walsh@rackspace.com>2011-05-25 08:22:51 -0700
commit30b6d5e2722d1c92115f668b405dc7eed9cc27b2 (patch)
tree9108fe915bbe4ee6049eee7592a6abb9f54a98ec
parent714fe839580d4858417592608e4bf95ac26cf5d1 (diff)
parent6f3f188e4ca9136f293ecf4b9813a7615c7a5929 (diff)
trunk merge
-rw-r--r--Authors2
-rwxr-xr-xbin/nova-dhcpbridge7
-rw-r--r--doc/source/devref/index.rst1
-rw-r--r--doc/source/devref/zone.rst6
-rw-r--r--doc/source/man/novamanage.rst4
-rw-r--r--doc/source/runnova/managing.users.rst6
-rw-r--r--nova/api/ec2/__init__.py4
-rw-r--r--nova/api/openstack/servers.py3
-rw-r--r--nova/compute/api.py4
-rw-r--r--nova/flags.py7
-rw-r--r--nova/tests/api/openstack/test_servers.py24
-rw-r--r--nova/tests/fake_flags.py28
-rw-r--r--nova/tests/real_flags.py26
-rw-r--r--nova/tests/test_api.py23
-rw-r--r--nova/tests/test_flags.py14
-rw-r--r--nova/virt/xenapi/vmops.py4
-rw-r--r--nova/virt/xenapi/volume_utils.py43
17 files changed, 119 insertions, 87 deletions
diff --git a/Authors b/Authors
index 6741c81ff..50f4680a9 100644
--- a/Authors
+++ b/Authors
@@ -17,6 +17,7 @@ Christian Berendt <berendt@b1-systems.de>
Chuck Short <zulcss@ubuntu.com>
Cory Wright <corywright@gmail.com>
Dan Prince <dan.prince@rackspace.com>
+Dave Walker <DaveWalker@ubuntu.com>
David Pravec <David.Pravec@danix.org>
Dean Troyer <dtroyer@gmail.com>
Devin Carlen <devin.carlen@gmail.com>
@@ -65,6 +66,7 @@ Nachi Ueno <ueno.nachi@lab.ntt.co.jp>
Naveed Massjouni <naveedm9@gmail.com>
Nirmal Ranganathan <nirmal.ranganathan@rackspace.com>
Paul Voccio <paul@openstack.org>
+Renuka Apte <renuka.apte@citrix.com>
Ricardo Carrillo Cruz <emaildericky@gmail.com>
Rick Clark <rick@openstack.org>
Rick Harris <rconradharris@gmail.com>
diff --git a/bin/nova-dhcpbridge b/bin/nova-dhcpbridge
index f42dfd6b5..5926b97de 100755
--- a/bin/nova-dhcpbridge
+++ b/bin/nova-dhcpbridge
@@ -108,6 +108,13 @@ def main():
interface = os.environ.get('DNSMASQ_INTERFACE', FLAGS.dnsmasq_interface)
if int(os.environ.get('TESTING', '0')):
from nova.tests import fake_flags
+
+ #if FLAGS.fake_rabbit:
+ # LOG.debug(_("leasing ip"))
+ # network_manager = utils.import_object(FLAGS.network_manager)
+ ## reload(fake_flags)
+ # from nova.tests import fake_flags
+
action = argv[1]
if action in ['add', 'del', 'old']:
mac = argv[2]
diff --git a/doc/source/devref/index.rst b/doc/source/devref/index.rst
index 9613ba990..0a5a7a4d6 100644
--- a/doc/source/devref/index.rst
+++ b/doc/source/devref/index.rst
@@ -35,6 +35,7 @@ Programming Concepts
.. toctree::
:maxdepth: 3
+ zone
rabbit
API Reference
diff --git a/doc/source/devref/zone.rst b/doc/source/devref/zone.rst
index 3dd9d37d3..263560ee2 100644
--- a/doc/source/devref/zone.rst
+++ b/doc/source/devref/zone.rst
@@ -17,7 +17,7 @@
Zones
=====
-A Nova deployment is called a Zone. At the very least a Zone requires an API node, a Scheduler node, a database and RabbitMQ. Pushed further a Zone may contain many API nodes, many Scheduler, Volume, Network and Compute nodes as well as a cluster of databases and RabbitMQ servers. A Zone allows you to partition your deployments into logical groups for load balancing and instance distribution.
+A Nova deployment is called a Zone. A Zone allows you to partition your deployments into logical groups for load balancing and instance distribution. At the very least a Zone requires an API node, a Scheduler node, a database and RabbitMQ. Pushed further a Zone may contain many API nodes, many Scheduler, Volume, Network and Compute nodes as well as a cluster of databases and RabbitMQ servers.
The idea behind Zones is, if a particular deployment is not capable of servicing a particular request, the request may be forwarded to (child) Zones for possible processing. Zones may be nested in a tree fashion.
@@ -34,7 +34,7 @@ Routing between Zones is based on the Capabilities of that Zone. Capabilities ar
key=value;value;value, key=value;value;value
-Zones have Capabilities which are general to the Zone and are set via `--zone-capabilities` flag. Zones also have dynamic per-service Capabilities. Services derived from `nova.manager.SchedulerDependentManager` (such as Compute, Volume and Network) can set these capabilities by calling the `update_service_capabilities()` method on their `Manager` base class. These capabilities will be periodically sent to the Scheduler service automatically. The rate at which these updates are sent is controlled by the `--periodic_interval` flag.
+Zones have Capabilities which are general to the Zone and are set via `--zone_capabilities` flag. Zones also have dynamic per-service Capabilities. Services derived from `nova.manager.SchedulerDependentManager` (such as Compute, Volume and Network) can set these capabilities by calling the `update_service_capabilities()` method on their `Manager` base class. These capabilities will be periodically sent to the Scheduler service automatically. The rate at which these updates are sent is controlled by the `--periodic_interval` flag.
Flow within a Zone
------------------
@@ -47,7 +47,7 @@ Inter-service communication within a Zone is done with RabbitMQ. Each class of S
These capability messages are received by the Scheduler services and stored in the `ZoneManager` object. The SchedulerManager object has a reference to the `ZoneManager` it can use for load balancing.
-The `ZoneManager` also polls the child Zones periodically to gather their capabilities to aid in decision making. This is done via the OpenStack API `/v1.0/zones/info` REST call. This also captures the name of each child Zone. The Zone name is set via the `--zone-name` flag (and defaults to "nova").
+The `ZoneManager` also polls the child Zones periodically to gather their capabilities to aid in decision making. This is done via the OpenStack API `/v1.0/zones/info` REST call. This also captures the name of each child Zone. The Zone name is set via the `--zone_name` flag (and defaults to "nova").
Zone administrative functions
-----------------------------
diff --git a/doc/source/man/novamanage.rst b/doc/source/man/novamanage.rst
index 9c54f3608..397cc8e80 100644
--- a/doc/source/man/novamanage.rst
+++ b/doc/source/man/novamanage.rst
@@ -6,7 +6,7 @@ nova-manage
control and manage cloud computer instances and images
------------------------------------------------------
-:Author: nova@lists.launchpad.net
+:Author: openstack@lists.launchpad.net
:Date: 2010-11-16
:Copyright: OpenStack LLC
:Version: 0.1
@@ -121,7 +121,7 @@ Nova Role
nova-manage role <action> [<argument>]
``nova-manage role add <username> <rolename> <(optional) projectname>``
- Add a user to either a global or project-based role with the indicated <rolename> assigned to the named user. Role names can be one of the following five roles: admin, itsec, projectmanager, netadmin, developer. If you add the project name as the last argument then the role is assigned just for that project, otherwise the user is assigned the named role for all projects.
+ Add a user to either a global or project-based role with the indicated <rolename> assigned to the named user. Role names can be one of the following five roles: cloudadmin, itsec, sysadmin, netadmin, developer. If you add the project name as the last argument then the role is assigned just for that project, otherwise the user is assigned the named role for all projects.
``nova-manage role has <username> <projectname>``
Checks the user or project and responds with True if the user has a global role with a particular project.
diff --git a/doc/source/runnova/managing.users.rst b/doc/source/runnova/managing.users.rst
index 392142e86..d3442bed9 100644
--- a/doc/source/runnova/managing.users.rst
+++ b/doc/source/runnova/managing.users.rst
@@ -38,11 +38,11 @@ Role-based access control (RBAC) is an approach to restricting system access to
Nova’s rights management system employs the RBAC model and currently supports the following five roles:
-* **Cloud Administrator.** (admin) Users of this class enjoy complete system access.
+* **Cloud Administrator.** (cloudadmin) Users of this class enjoy complete system access.
* **IT Security.** (itsec) This role is limited to IT security personnel. It permits role holders to quarantine instances.
-* **Project Manager.** (projectmanager)The default for project owners, this role affords users the ability to add other users to a project, interact with project images, and launch and terminate instances.
+* **System Administrator.** (sysadmin) The default for project owners, this role affords users the ability to add other users to a project, interact with project images, and launch and terminate instances.
* **Network Administrator.** (netadmin) Users with this role are permitted to allocate and assign publicly accessible IP addresses as well as create and modify firewall rules.
-* **Developer.** This is a general purpose role that is assigned to users by default.
+* **Developer.** (developer) This is a general purpose role that is assigned to users by default.
RBAC management is exposed through the dashboard for simplified user management.
diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py
index cd59340bd..c13993dd3 100644
--- a/nova/api/ec2/__init__.py
+++ b/nova/api/ec2/__init__.py
@@ -338,6 +338,10 @@ class Executor(wsgi.Application):
else:
return self._error(req, context, type(ex).__name__,
unicode(ex))
+ except exception.KeyPairExists as ex:
+ LOG.debug(_('KeyPairExists raised: %s'), unicode(ex),
+ context=context)
+ return self._error(req, context, type(ex).__name__, unicode(ex))
except Exception as ex:
extra = {'environment': req.environ}
LOG.exception(_('Unexpected error raised: %s'), unicode(ex),
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 8f2de2afe..fcb630fae 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -609,7 +609,8 @@ class ControllerV10(Controller):
def _parse_update(self, context, server_id, inst_dict, update_dict):
if 'adminPass' in inst_dict['server']:
update_dict['admin_pass'] = inst_dict['server']['adminPass']
- self.compute_api.set_admin_password(context, server_id)
+ self.compute_api.set_admin_password(context, server_id,
+ inst_dict['server']['adminPass'])
def _action_rebuild(self, info, request, instance_id):
context = request.environ['nova.context']
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 4ddbbd0e2..216550e40 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -670,8 +670,8 @@ class API(base.Base):
def set_admin_password(self, context, instance_id, password=None):
"""Set the root/admin password for the given instance."""
- eventlet.spawn_n(self._set_admin_password(context, instance_id,
- password))
+ eventlet.spawn_n(self._set_admin_password, context, instance_id,
+ password)
def inject_file(self, context, instance_id):
"""Write a file to the given instance."""
diff --git a/nova/flags.py b/nova/flags.py
index 32cb6efa8..9eaac5596 100644
--- a/nova/flags.py
+++ b/nova/flags.py
@@ -110,7 +110,7 @@ class FlagValues(gflags.FlagValues):
return name in self.__dict__['__dirty']
def ClearDirty(self):
- self.__dict__['__is_dirty'] = []
+ self.__dict__['__dirty'] = []
def WasAlreadyParsed(self):
return self.__dict__['__was_already_parsed']
@@ -119,11 +119,12 @@ class FlagValues(gflags.FlagValues):
if '__stored_argv' not in self.__dict__:
return
new_flags = FlagValues(self)
- for k in self.__dict__['__dirty']:
+ for k in self.FlagDict().iterkeys():
new_flags[k] = gflags.FlagValues.__getitem__(self, k)
+ new_flags.Reset()
new_flags(self.__dict__['__stored_argv'])
- for k in self.__dict__['__dirty']:
+ for k in new_flags.FlagDict().iterkeys():
setattr(self, k, getattr(new_flags, k))
self.ClearDirty()
diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py
index e8182b6a9..dc8815845 100644
--- a/nova/tests/api/openstack/test_servers.py
+++ b/nova/tests/api/openstack/test_servers.py
@@ -138,6 +138,16 @@ def find_host(self, context, instance_id):
return "nova"
+class MockSetAdminPassword(object):
+ def __init__(self):
+ self.instance_id = None
+ self.password = None
+
+ def __call__(self, context, instance_id, password):
+ self.instance_id = instance_id
+ self.password = password
+
+
class ServersTest(test.TestCase):
def setUp(self):
@@ -773,6 +783,8 @@ class ServersTest(test.TestCase):
self.stubs.Set(nova.db.api, 'instance_update',
server_update)
self.stubs.Set(nova.compute.api.API, "_find_host", find_host)
+ mock_method = MockSetAdminPassword()
+ self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
req = webob.Request.blank('/v1.0/servers/1')
req.method = 'PUT'
@@ -780,6 +792,8 @@ class ServersTest(test.TestCase):
req.body = self.body
res = req.get_response(fakes.wsgi_app())
self.assertEqual(res.status_int, 204)
+ self.assertEqual(mock_method.instance_id, '1')
+ self.assertEqual(mock_method.password, 'bacon')
def test_update_server_adminPass_ignored_v1_1(self):
inst_dict = dict(name='server_test', adminPass='bacon')
@@ -996,16 +1010,6 @@ class ServersTest(test.TestCase):
self.assertEqual(res.status_int, 501)
def test_server_change_password_v1_1(self):
-
- class MockSetAdminPassword(object):
- def __init__(self):
- self.instance_id = None
- self.password = None
-
- def __call__(self, context, instance_id, password):
- self.instance_id = instance_id
- self.password = password
-
mock_method = MockSetAdminPassword()
self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
body = {'changePassword': {'adminPass': '1234pass'}}
diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py
index 5d7ca98b5..ecefc464a 100644
--- a/nova/tests/fake_flags.py
+++ b/nova/tests/fake_flags.py
@@ -21,24 +21,24 @@ from nova import flags
FLAGS = flags.FLAGS
flags.DECLARE('volume_driver', 'nova.volume.manager')
-FLAGS.volume_driver = 'nova.volume.driver.FakeISCSIDriver'
-FLAGS.connection_type = 'fake'
-FLAGS.fake_rabbit = True
+FLAGS['volume_driver'].SetDefault('nova.volume.driver.FakeISCSIDriver')
+FLAGS['connection_type'].SetDefault('fake')
+FLAGS['fake_rabbit'].SetDefault(True)
flags.DECLARE('auth_driver', 'nova.auth.manager')
-FLAGS.auth_driver = 'nova.auth.dbdriver.DbDriver'
+FLAGS['auth_driver'].SetDefault('nova.auth.dbdriver.DbDriver')
flags.DECLARE('network_size', 'nova.network.manager')
flags.DECLARE('num_networks', 'nova.network.manager')
flags.DECLARE('fake_network', 'nova.network.manager')
-FLAGS.network_size = 8
-FLAGS.num_networks = 2
-FLAGS.fake_network = True
-FLAGS.image_service = 'nova.image.local.LocalImageService'
+FLAGS['network_size'].SetDefault(8)
+FLAGS['num_networks'].SetDefault(2)
+FLAGS['fake_network'].SetDefault(True)
+FLAGS['image_service'].SetDefault('nova.image.local.LocalImageService')
flags.DECLARE('num_shelves', 'nova.volume.driver')
flags.DECLARE('blades_per_shelf', 'nova.volume.driver')
flags.DECLARE('iscsi_num_targets', 'nova.volume.driver')
-FLAGS.num_shelves = 2
-FLAGS.blades_per_shelf = 4
-FLAGS.iscsi_num_targets = 8
-FLAGS.verbose = True
-FLAGS.sqlite_db = "tests.sqlite"
-FLAGS.use_ipv6 = True
+FLAGS['num_shelves'].SetDefault(2)
+FLAGS['blades_per_shelf'].SetDefault(4)
+FLAGS['iscsi_num_targets'].SetDefault(8)
+FLAGS['verbose'].SetDefault(True)
+FLAGS['sqlite_db'].SetDefault("tests.sqlite")
+FLAGS['use_ipv6'].SetDefault(True)
diff --git a/nova/tests/real_flags.py b/nova/tests/real_flags.py
deleted file mode 100644
index 71da04992..000000000
--- a/nova/tests/real_flags.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# vim: tabstop=4 shiftwidth=4 softtabstop=4
-
-# Copyright 2010 United States Government as represented by the
-# Administrator of the National Aeronautics and Space Administration.
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from nova import flags
-
-FLAGS = flags.FLAGS
-
-FLAGS.connection_type = 'libvirt'
-FLAGS.fake_rabbit = False
-FLAGS.fake_network = False
-FLAGS.verbose = False
diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py
index 97f401b87..7c0331eff 100644
--- a/nova/tests/test_api.py
+++ b/nova/tests/test_api.py
@@ -224,6 +224,29 @@ class ApiEc2TestCase(test.TestCase):
self.manager.delete_project(project)
self.manager.delete_user(user)
+ def test_create_duplicate_key_pair(self):
+ """Test that, after successfully generating a keypair,
+ requesting a second keypair with the same name fails sanely"""
+ self.expect_http()
+ self.mox.ReplayAll()
+ keyname = "".join(random.choice("sdiuisudfsdcnpaqwertasd") \
+ for x in range(random.randint(4, 8)))
+ user = self.manager.create_user('fake', 'fake', 'fake')
+ project = self.manager.create_project('fake', 'fake', 'fake')
+ # NOTE(vish): create depends on pool, so call helper directly
+ self.ec2.create_key_pair('test')
+
+ try:
+ self.ec2.create_key_pair('test')
+ except EC2ResponseError, e:
+ if e.code == 'KeyPairExists':
+ pass
+ else:
+ self.fail("Unexpected EC2ResponseError: %s "
+ "(expected KeyPairExists)" % e.code)
+ else:
+ self.fail('Exception not raised.')
+
def test_get_all_security_groups(self):
"""Test that we can retrieve security groups"""
self.expect_http()
diff --git a/nova/tests/test_flags.py b/nova/tests/test_flags.py
index 707300fcf..05319d91f 100644
--- a/nova/tests/test_flags.py
+++ b/nova/tests/test_flags.py
@@ -91,6 +91,20 @@ class FlagsTestCase(test.TestCase):
self.assert_('runtime_answer' in self.global_FLAGS)
self.assertEqual(self.global_FLAGS.runtime_answer, 60)
+ def test_long_vs_short_flags(self):
+ flags.DEFINE_string('duplicate_answer_long', 'val', 'desc',
+ flag_values=self.global_FLAGS)
+ argv = ['flags_test', '--duplicate_answer=60', 'extra_arg']
+ args = self.global_FLAGS(argv)
+
+ self.assert_('duplicate_answer' not in self.global_FLAGS)
+ self.assert_(self.global_FLAGS.duplicate_answer_long, 60)
+
+ flags.DEFINE_integer('duplicate_answer', 60, 'desc',
+ flag_values=self.global_FLAGS)
+ self.assertEqual(self.global_FLAGS.duplicate_answer, 60)
+ self.assertEqual(self.global_FLAGS.duplicate_answer_long, 'val')
+
def test_flag_leak_left(self):
self.assertEqual(FLAGS.flags_unittest, 'foo')
FLAGS.flags_unittest = 'bar'
diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py
index 0074444f8..45b04351d 100644
--- a/nova/virt/xenapi/vmops.py
+++ b/nova/virt/xenapi/vmops.py
@@ -1171,13 +1171,13 @@ class SimpleDH(object):
shared = self._shared
cmd = base_cmd % locals()
proc = _runproc(cmd)
- proc.stdin.write(text)
+ proc.stdin.write(text + '\n')
proc.stdin.close()
proc.wait()
err = proc.stderr.read()
if err:
raise RuntimeError(_('OpenSSL error: %s') % err)
- return proc.stdout.read()
+ return proc.stdout.read().strip('\n')
def encrypt(self, text):
return self._run_ssl(text, 'enc')
diff --git a/nova/virt/xenapi/volume_utils.py b/nova/virt/xenapi/volume_utils.py
index 72284ac02..7821a4f7e 100644
--- a/nova/virt/xenapi/volume_utils.py
+++ b/nova/virt/xenapi/volume_utils.py
@@ -204,14 +204,17 @@ def _get_volume_id(path_or_id):
if isinstance(path_or_id, int):
return path_or_id
# n must contain at least the volume_id
- # /vol- is for remote volumes
- # -vol- is for local volumes
+ # :volume- is for remote volumes
+ # -volume- is for local volumes
# see compute/manager->setup_compute_volume
- volume_id = path_or_id[path_or_id.find('/vol-') + 1:]
+ volume_id = path_or_id[path_or_id.find(':volume-') + 1:]
if volume_id == path_or_id:
- volume_id = path_or_id[path_or_id.find('-vol-') + 1:]
- volume_id = volume_id.replace('--', '-')
- return volume_id
+ volume_id = path_or_id[path_or_id.find('-volume--') + 1:]
+ volume_id = volume_id.replace('volume--', '')
+ else:
+ volume_id = volume_id.replace('volume-', '')
+ volume_id = volume_id[0:volume_id.find('-')]
+ return int(volume_id)
def _get_target_host(iscsi_string):
@@ -244,25 +247,23 @@ def _get_target(volume_id):
Gets iscsi name and portal from volume name and host.
For this method to work the following are needed:
1) volume_ref['host'] must resolve to something rather than loopback
- 2) ietd must bind only to the address as resolved above
- If any of the two conditions are not met, fall back on Flags.
"""
- volume_ref = db.volume_get_by_ec2_id(context.get_admin_context(),
- volume_id)
+ volume_ref = db.volume_get(context.get_admin_context(),
+ volume_id)
result = (None, None)
try:
- (r, _e) = utils.execute("sudo iscsiadm -m discovery -t "
- "sendtargets -p %s" %
- volume_ref['host'])
+ (r, _e) = utils.execute('sudo', 'iscsiadm',
+ '-m', 'discovery',
+ '-t', 'sendtargets',
+ '-p', volume_ref['host'])
except exception.ProcessExecutionError, exc:
LOG.exception(exc)
else:
- targets = r.splitlines()
- if len(_e) == 0 and len(targets) == 1:
- for target in targets:
- if volume_id in target:
- (location, _sep, iscsi_name) = target.partition(" ")
- break
- iscsi_portal = location.split(",")[0]
- result = (iscsi_name, iscsi_portal)
+ volume_name = "volume-%08x" % volume_id
+ for target in r.splitlines():
+ if FLAGS.iscsi_ip_prefix in target and volume_name in target:
+ (location, _sep, iscsi_name) = target.partition(" ")
+ break
+ iscsi_portal = location.split(",")[0]
+ result = (iscsi_name, iscsi_portal)
return result