summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRick Harris <rconradharris@gmail.com>2011-09-21 16:00:53 -0500
committerRick Harris <rconradharris@gmail.com>2011-09-21 16:00:53 -0500
commit4fb602fcbc2a7b0681e79454fe7c3f01110b1f0e (patch)
tree1c5c5f7ded02c886f48d5e2fa008881c7f0ebdc1
parent748b056209947032735c71212b8be21a16f2cadf (diff)
parent9cf7352fbd26fe8db4205c385b92778603af7797 (diff)
downloadnova-4fb602fcbc2a7b0681e79454fe7c3f01110b1f0e.tar.gz
nova-4fb602fcbc2a7b0681e79454fe7c3f01110b1f0e.tar.xz
nova-4fb602fcbc2a7b0681e79454fe7c3f01110b1f0e.zip
Renumbering instance progress migration
-rw-r--r--nova/api/openstack/servers.py41
-rw-r--r--nova/api/openstack/zones.py2
-rw-r--r--nova/compute/api.py6
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/048_add_zone_name.py35
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/049_add_instances_progress.py (renamed from nova/db/sqlalchemy/migrate_repo/versions/048_add_instances_progress.py)0
-rw-r--r--nova/db/sqlalchemy/models.py1
-rw-r--r--nova/rpc/impl_kombu.py1
-rw-r--r--nova/scheduler/abstract_scheduler.py3
-rw-r--r--nova/scheduler/api.py58
-rw-r--r--nova/scheduler/zone_manager.py17
-rw-r--r--nova/tests/scheduler/test_scheduler.py68
-rw-r--r--nova/tests/test_zones.py29
-rw-r--r--tools/pip-requires2
13 files changed, 192 insertions, 71 deletions
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 0e7c37486..1a4703069 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -17,6 +17,7 @@ import base64
import os
import traceback
+from novaclient import exceptions as novaclient_exceptions
from lxml import etree
from webob import exc
import webob
@@ -45,6 +46,27 @@ LOG = logging.getLogger('nova.api.openstack.servers')
FLAGS = flags.FLAGS
+class ConvertedException(exc.WSGIHTTPException):
+ def __init__(self, code, title, explanation):
+ self.code = code
+ self.title = title
+ self.explanation = explanation
+ super(ConvertedException, self).__init__()
+
+
+def novaclient_exception_converter(f):
+ """Convert novaclient ClientException HTTP codes to webob exceptions.
+ Has to be the outer-most decorator.
+ """
+ def new_f(*args, **kwargs):
+ try:
+ ret = f(*args, **kwargs)
+ return ret
+ except novaclient_exceptions.ClientException, e:
+ raise ConvertedException(e.code, e.message, e.details)
+ return new_f
+
+
class Controller(object):
""" The Server API base controller class for the OpenStack API """
@@ -135,6 +157,7 @@ class Controller(object):
return dict(servers=servers)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def show(self, req, id):
""" Returns server details by server id """
@@ -210,6 +233,7 @@ class Controller(object):
def _update(self, context, req, id, inst_dict):
return exc.HTTPNotImplemented()
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def action(self, req, id, body):
"""Multi-purpose method used to take actions on a server"""
@@ -348,6 +372,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def lock(self, req, id):
"""
@@ -364,6 +389,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def unlock(self, req, id):
"""
@@ -380,6 +406,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def get_lock(self, req, id):
"""
@@ -395,6 +422,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def reset_network(self, req, id):
"""
@@ -410,6 +438,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def inject_network_info(self, req, id):
"""
@@ -425,6 +454,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def pause(self, req, id):
""" Permit Admins to Pause the server. """
@@ -437,6 +467,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def unpause(self, req, id):
""" Permit Admins to Unpause the server. """
@@ -449,6 +480,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def suspend(self, req, id):
"""permit admins to suspend the server"""
@@ -461,6 +493,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def resume(self, req, id):
"""permit admins to resume the server from suspend"""
@@ -473,6 +506,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def migrate(self, req, id):
try:
@@ -482,6 +516,7 @@ class Controller(object):
raise exc.HTTPBadRequest()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def rescue(self, req, id, body={}):
"""Permit users to rescue the server."""
@@ -500,6 +535,7 @@ class Controller(object):
return {'adminPass': password}
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def unrescue(self, req, id):
"""Permit users to unrescue the server."""
@@ -512,6 +548,7 @@ class Controller(object):
raise exc.HTTPUnprocessableEntity()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def get_ajax_console(self, req, id):
"""Returns a url to an instance's ajaxterm console."""
@@ -522,6 +559,7 @@ class Controller(object):
raise exc.HTTPNotFound()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def get_vnc_console(self, req, id):
"""Returns a url to an instance's ajaxterm console."""
@@ -532,6 +570,7 @@ class Controller(object):
raise exc.HTTPNotFound()
return webob.Response(status_int=202)
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def diagnostics(self, req, id):
"""Permit Admins to retrieve server diagnostics."""
@@ -574,6 +613,7 @@ class Controller(object):
class ControllerV10(Controller):
"""v1.0 OpenStack API controller"""
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def delete(self, req, id):
""" Destroys a server """
@@ -652,6 +692,7 @@ class ControllerV10(Controller):
class ControllerV11(Controller):
"""v1.1 OpenStack API controller"""
+ @novaclient_exception_converter
@scheduler_api.redirect_handler
def delete(self, req, id):
""" Destroys a server """
diff --git a/nova/api/openstack/zones.py b/nova/api/openstack/zones.py
index a2bf267ed..998498e82 100644
--- a/nova/api/openstack/zones.py
+++ b/nova/api/openstack/zones.py
@@ -46,7 +46,7 @@ def _filter_keys(item, keys):
def _exclude_keys(item, keys):
- return dict((k, v) for k, v in item.iteritems() if k not in keys)
+ return dict((k, v) for k, v in item.iteritems() if k and (k not in keys))
def _scrub_zone(zone):
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 76b0596e7..cedbd747a 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -995,10 +995,8 @@ class API(base.Base):
if not recurse_zones:
return instances
- # Recurse zones. Need admin context for this. Send along
- # the un-modified search options we received..
- admin_context = context.elevated()
- children = scheduler_api.call_zone_method(admin_context,
+ # Recurse zones. Send along the un-modified search options we received.
+ children = scheduler_api.call_zone_method(context,
"list",
errors_to_ignore=[novaclient.exceptions.NotFound],
novaclient_collection_name="servers",
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/048_add_zone_name.py b/nova/db/sqlalchemy/migrate_repo/versions/048_add_zone_name.py
new file mode 100644
index 000000000..3198e48a9
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/048_add_zone_name.py
@@ -0,0 +1,35 @@
+# 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
+# under the License.
+
+from sqlalchemy import Column, Integer, MetaData, String, Table
+
+meta = MetaData()
+
+zones = Table('zones', meta,
+ Column('id', Integer(), primary_key=True, nullable=False),
+ )
+
+name = Column('name', String(255))
+
+
+def upgrade(migrate_engine):
+ meta.bind = migrate_engine
+
+ zones.create_column(name)
+
+
+def downgrade(migrate_engine):
+ meta.bind = migrate_engine
+
+ zones.drop_column(name)
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/048_add_instances_progress.py b/nova/db/sqlalchemy/migrate_repo/versions/049_add_instances_progress.py
index d23d52e80..d23d52e80 100644
--- a/nova/db/sqlalchemy/migrate_repo/versions/048_add_instances_progress.py
+++ b/nova/db/sqlalchemy/migrate_repo/versions/049_add_instances_progress.py
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index b7a35f881..2261a1d09 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -839,6 +839,7 @@ class Zone(BASE, NovaBase):
"""Represents a child zone of this zone."""
__tablename__ = 'zones'
id = Column(Integer, primary_key=True)
+ name = Column(String(255))
api_url = Column(String(255))
username = Column(String(255))
password = Column(String(255))
diff --git a/nova/rpc/impl_kombu.py b/nova/rpc/impl_kombu.py
index b994a6a10..e7fc491ea 100644
--- a/nova/rpc/impl_kombu.py
+++ b/nova/rpc/impl_kombu.py
@@ -728,7 +728,6 @@ def multicall(context, topic, msg):
wait_msg = MulticallWaiter(conn)
conn.declare_direct_consumer(msg_id, wait_msg)
conn.topic_send(topic, msg)
-
return wait_msg
diff --git a/nova/scheduler/abstract_scheduler.py b/nova/scheduler/abstract_scheduler.py
index 6e8c7d715..b121444f2 100644
--- a/nova/scheduler/abstract_scheduler.py
+++ b/nova/scheduler/abstract_scheduler.py
@@ -118,7 +118,8 @@ class AbstractScheduler(driver.Scheduler):
". ReservationID=%(reservation_id)s") % locals())
nova = None
try:
- nova = novaclient.Client(zone.username, zone.password, None, url)
+ nova = novaclient.Client(zone.username, zone.password, None, url,
+ token=context.auth_token)
nova.authenticate()
except novaclient_exceptions.BadRequest, e:
raise exception.NotAuthorized(_("Bad credentials attempting "
diff --git a/nova/scheduler/api.py b/nova/scheduler/api.py
index 719437b73..44e01aa0c 100644
--- a/nova/scheduler/api.py
+++ b/nova/scheduler/api.py
@@ -17,6 +17,8 @@
Handles all requests relating to schedulers.
"""
+import functools
+
from novaclient import v1_1 as novaclient
from novaclient import exceptions as novaclient_exceptions
@@ -117,13 +119,16 @@ def call_zone_method(context, method_name, errors_to_ignore=None,
zones = db.zone_get_all(context)
for zone in zones:
try:
+ # Do this on behalf of the user ...
nova = novaclient.Client(zone.username, zone.password, None,
- zone.api_url)
+ zone.api_url, region_name=zone.name,
+ token=context.auth_token)
nova.authenticate()
except novaclient_exceptions.BadRequest, e:
url = zone.api_url
- LOG.warn(_("Failed request to zone; URL=%(url)s: %(e)s")
- % locals())
+ name = zone.name
+ LOG.warn(_("Authentication failed to zone "
+ "'%(name)s' URL=%(url)s: %(e)s") % locals())
#TODO (dabo) - add logic for failure counts per zone,
# with escalation after a given number of failures.
continue
@@ -144,25 +149,20 @@ def call_zone_method(context, method_name, errors_to_ignore=None,
return [(zone.id, res.wait()) for zone, res in results]
-def child_zone_helper(zone_list, func):
+def child_zone_helper(context, zone_list, func):
"""Fire off a command to each zone in the list.
The return is [novaclient return objects] from each child zone.
For example, if you are calling server.pause(), the list will
be whatever the response from server.pause() is. One entry
per child zone called."""
- def _wrap_method(function, arg1):
- """Wrap method to supply an argument."""
- def _wrap(*args, **kwargs):
- return function(arg1, *args, **kwargs)
- return _wrap
-
- def _process(func, zone):
+ def _process(func, context, zone):
"""Worker stub for green thread pool. Give the worker
an authenticated nova client and zone info."""
try:
nova = novaclient.Client(zone.username, zone.password, None,
- zone.api_url)
+ zone.api_url, region_name=zone.name,
+ token=context.auth_token)
nova.authenticate()
except novaclient_exceptions.BadRequest, e:
url = zone.api_url
@@ -174,11 +174,15 @@ def child_zone_helper(zone_list, func):
# there if no other zones had a response.
return exception.ZoneRequestError()
else:
- return func(nova, zone)
+ try:
+ answer = func(nova, zone)
+ return answer
+ except Exception, e:
+ return e
green_pool = greenpool.GreenPool()
return [result for result in green_pool.imap(
- _wrap_method(_process, func), zone_list)]
+ functools.partial(_process, func, context), zone_list)]
def _issue_novaclient_command(nova, zone, collection,
@@ -211,11 +215,11 @@ def _issue_novaclient_command(nova, zone, collection,
item = args.pop(0)
try:
result = manager.get(item)
- except novaclient_exceptions.NotFound:
+ except novaclient_exceptions.NotFound, e:
url = zone.api_url
LOG.debug(_("%(collection)s '%(item)s' not found on '%(url)s'" %
locals()))
- return None
+ raise e
if method_name.lower() != 'get':
# if we're doing something other than 'get', call it passing args.
@@ -278,7 +282,7 @@ class reroute_compute(object):
# Ask the children to provide an answer ...
LOG.debug(_("Asking child zones ..."))
- result = self._call_child_zones(zones,
+ result = self._call_child_zones(context, zones,
wrap_novaclient_function(_issue_novaclient_command,
collection, self.method_name, item_uuid))
# Scrub the results and raise another exception
@@ -318,10 +322,10 @@ class reroute_compute(object):
return wrapped_f
- def _call_child_zones(self, zones, function):
+ def _call_child_zones(self, context, zones, function):
"""Ask the child zones to perform this operation.
Broken out for testing."""
- return child_zone_helper(zones, function)
+ return child_zone_helper(context, zones, function)
def get_collection_context_and_id(self, args, kwargs):
"""Returns a tuple of (novaclient collection name, security
@@ -369,11 +373,19 @@ class reroute_compute(object):
del server[k]
reduced_response.append(dict(server=server))
+
+ # Boil the responses down to a single response.
+ #
+ # If we get a happy response use that, ignore all the
+ # complaint repsonses ...
if reduced_response:
return reduced_response[0] # first for now.
elif found_exception:
- raise found_exception
- raise exception.InstanceNotFound(instance_id=self.item_uuid)
+ return found_exception
+
+ # Some operations, like delete(), don't send back any results
+ # on success. We'll do the same.
+ return None
def redirect_handler(f):
@@ -381,5 +393,9 @@ def redirect_handler(f):
try:
return f(*args, **kwargs)
except RedirectResult, e:
+ # Remember: exceptions are returned, not thrown, in the decorator.
+ # At this point it's safe to throw it.
+ if isinstance(e.results, BaseException):
+ raise e.results
return e.results
return new_f
diff --git a/nova/scheduler/zone_manager.py b/nova/scheduler/zone_manager.py
index 9d05ea42e..c61ff7b77 100644
--- a/nova/scheduler/zone_manager.py
+++ b/nova/scheduler/zone_manager.py
@@ -51,16 +51,18 @@ class ZoneState(object):
def update_credentials(self, zone):
"""Update zone credentials from db"""
self.zone_id = zone.id
+ self.name = zone.name
self.api_url = zone.api_url
self.username = zone.username
self.password = zone.password
+ self.weight_offset = zone.weight_offset
+ self.weight_scale = zone.weight_scale
def update_metadata(self, zone_metadata):
"""Update zone metadata after successful communications with
child zone."""
self.last_seen = utils.utcnow()
self.attempt = 0
- self.name = zone_metadata.get("name", "n/a")
self.capabilities = ", ".join(["%s=%s" % (k, v)
for k, v in zone_metadata.iteritems() if k != 'name'])
self.is_active = True
@@ -68,7 +70,8 @@ class ZoneState(object):
def to_dict(self):
return dict(name=self.name, capabilities=self.capabilities,
is_active=self.is_active, api_url=self.api_url,
- id=self.zone_id)
+ id=self.zone_id, weight_scale=self.weight_scale,
+ weight_offset=self.weight_offset)
def log_error(self, exception):
"""Something went wrong. Check to see if zone should be
@@ -89,15 +92,19 @@ class ZoneState(object):
def _call_novaclient(zone):
- """Call novaclient. Broken out for testing purposes."""
+ """Call novaclient. Broken out for testing purposes. Note that
+ we have to use the admin credentials for this since there is no
+ available context."""
client = novaclient.Client(zone.username, zone.password, None,
- zone.api_url)
+ zone.api_url, region_name=zone.name)
return client.zones.info()._info
def _poll_zone(zone):
"""Eventlet worker to poll a zone."""
- logging.debug(_("Polling zone: %s") % zone.api_url)
+ name = zone.name
+ url = zone.api_url
+ logging.debug(_("Polling zone: %(name)s @ %(url)s") % locals())
try:
zone.update_metadata(_call_novaclient(zone))
except Exception, e:
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py
index 890348192..0b51792a0 100644
--- a/nova/tests/scheduler/test_scheduler.py
+++ b/nova/tests/scheduler/test_scheduler.py
@@ -53,6 +53,10 @@ FAKE_UUID_NOT_FOUND = 'ffffffff-ffff-ffff-ffff-ffffffffffff'
FAKE_UUID = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
+class FakeContext(object):
+ auth_token = None
+
+
class TestDriver(driver.Scheduler):
"""Scheduler Driver for Tests"""
def schedule(context, topic, *args, **kwargs):
@@ -956,11 +960,12 @@ class MultiDriverTestCase(SimpleDriverTestCase):
class FakeZone(object):
- def __init__(self, id, api_url, username, password):
+ def __init__(self, id, api_url, username, password, name='child'):
self.id = id
self.api_url = api_url
self.username = username
self.password = password
+ self.name = name
ZONE_API_URL1 = "http://1.example.com"
@@ -986,7 +991,7 @@ class FakeRerouteCompute(api.reroute_compute):
super(FakeRerouteCompute, self).__init__(method_name)
self.id_to_return = id_to_return
- def _call_child_zones(self, zones, function):
+ def _call_child_zones(self, context, zones, function):
return []
def get_collection_context_and_id(self, args, kwargs):
@@ -1071,8 +1076,8 @@ class ZoneRedirectTest(test.TestCase):
def test_unmarshal_single_server(self):
decorator = api.reroute_compute("foo")
decorator.item_uuid = 'fake_uuid'
- self.assertRaises(exception.InstanceNotFound,
- decorator.unmarshall_result, [])
+ result = decorator.unmarshall_result([])
+ self.assertEquals(decorator.unmarshall_result([]), None)
self.assertEquals(decorator.unmarshall_result(
[FakeResource(dict(a=1, b=2)), ]),
dict(server=dict(a=1, b=2)))
@@ -1092,7 +1097,8 @@ class ZoneRedirectTest(test.TestCase):
return None
class FakeNovaClientWithFailure(object):
- def __init__(self, username, password, method, api_url):
+ def __init__(self, username, password, method, api_url,
+ token=None, region_name=None):
self.api_url = api_url
def authenticate(self):
@@ -1107,8 +1113,11 @@ class ZoneRedirectTest(test.TestCase):
def do_get(self, context, uuid):
pass
- self.assertRaises(exception.ZoneRequestError,
- do_get, None, {}, FAKE_UUID)
+ try:
+ do_get(None, FakeContext(), FAKE_UUID)
+ self.fail("Should have got redirect exception.")
+ except api.RedirectResult, e:
+ self.assertTrue(isinstance(e.results, exception.ZoneRequestError))
def test_one_zone_down_got_instance(self):
@@ -1120,7 +1129,8 @@ class ZoneRedirectTest(test.TestCase):
return FakeServer()
class FakeNovaClientWithFailure(object):
- def __init__(self, username, password, method, api_url):
+ def __init__(self, username, password, method, api_url,
+ token=None, region_name=None):
self.api_url = api_url
def authenticate(self):
@@ -1136,14 +1146,14 @@ class ZoneRedirectTest(test.TestCase):
pass
try:
- do_get(None, {}, FAKE_UUID)
+ do_get(None, FakeContext(), FAKE_UUID)
except api.RedirectResult, e:
results = e.results
self.assertIn('server', results)
self.assertEqual(results['server']['id'], FAKE_UUID)
self.assertEqual(results['server']['test'], '1234')
except Exception, e:
- self.fail(_("RedirectResult should have been raised"))
+ self.fail(_("RedirectResult should have been raised: %s" % e))
else:
self.fail(_("RedirectResult should have been raised"))
@@ -1153,7 +1163,8 @@ class ZoneRedirectTest(test.TestCase):
return None
class FakeNovaClientNoFailure(object):
- def __init__(self, username, password, method, api_url):
+ def __init__(self, username, password, method, api_url,
+ token=None, region_name=None):
pass
def authenticate(self):
@@ -1167,8 +1178,11 @@ class ZoneRedirectTest(test.TestCase):
def do_get(self, context, uuid):
pass
- self.assertRaises(exception.InstanceNotFound,
- do_get, None, {}, FAKE_UUID)
+ try:
+ do_get(None, FakeContext(), FAKE_UUID)
+ self.fail("Expected redirect exception")
+ except api.RedirectResult, e:
+ self.assertEquals(e.results, None)
class FakeServerCollection(object):
@@ -1209,17 +1223,19 @@ class DynamicNovaClientTest(test.TestCase):
def test_issue_novaclient_command_not_found(self):
zone = FakeZone(1, 'http://example.com', 'bob', 'xxx')
- self.assertEquals(api._issue_novaclient_command(
- FakeNovaClient(FakeEmptyServerCollection()),
- zone, "servers", "get", 100), None)
-
- self.assertEquals(api._issue_novaclient_command(
- FakeNovaClient(FakeEmptyServerCollection()),
- zone, "servers", "find", name="test"), None)
+ try:
+ api._issue_novaclient_command(FakeNovaClient(
+ FakeEmptyServerCollection()), zone, "servers", "get", 100)
+ self.fail("Expected NotFound exception")
+ except novaclient_exceptions.NotFound, e:
+ pass
- self.assertEquals(api._issue_novaclient_command(
- FakeNovaClient(FakeEmptyServerCollection()),
- zone, "servers", "any", "name"), None)
+ try:
+ api._issue_novaclient_command(FakeNovaClient(
+ FakeEmptyServerCollection()), zone, "servers", "any", "name")
+ self.fail("Expected NotFound exception")
+ except novaclient_exceptions.NotFound, e:
+ pass
class FakeZonesProxy(object):
@@ -1250,7 +1266,7 @@ class CallZoneMethodTest(test.TestCase):
super(CallZoneMethodTest, self).tearDown()
def test_call_zone_method(self):
- context = {}
+ context = FakeContext()
method = 'do_something'
results = api.call_zone_method(context, method)
self.assertEqual(len(results), 2)
@@ -1258,12 +1274,12 @@ class CallZoneMethodTest(test.TestCase):
self.assertIn((2, 42), results)
def test_call_zone_method_not_present(self):
- context = {}
+ context = FakeContext()
method = 'not_present'
self.assertRaises(AttributeError, api.call_zone_method,
context, method)
def test_call_zone_method_generates_exception(self):
- context = {}
+ context = FakeContext()
method = 'raises_exception'
self.assertRaises(Exception, api.call_zone_method, context, method)
diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py
index 9efa23015..9b5b9b24a 100644
--- a/nova/tests/test_zones.py
+++ b/nova/tests/test_zones.py
@@ -63,7 +63,8 @@ class ZoneManagerTestCase(test.TestCase):
self.mox.StubOutWithMock(db, 'zone_get_all')
db.zone_get_all(mox.IgnoreArg()).AndReturn([
FakeZone(id=1, api_url='http://foo.com', username='user1',
- password='pass1'),
+ password='pass1', name='child', weight_offset=0.0,
+ weight_scale=1.0),
])
self.assertEquals(len(zm.zone_states), 0)
@@ -107,13 +108,15 @@ class ZoneManagerTestCase(test.TestCase):
zm = zone_manager.ZoneManager()
zone_state = zone_manager.ZoneState()
zone_state.update_credentials(FakeZone(id=1, api_url='http://foo.com',
- username='user1', password='pass1'))
+ username='user1', password='pass1', name='child',
+ weight_offset=0.0, weight_scale=1.0))
zm.zone_states[1] = zone_state
self.mox.StubOutWithMock(db, 'zone_get_all')
db.zone_get_all(mox.IgnoreArg()).AndReturn([
FakeZone(id=1, api_url='http://foo.com', username='user2',
- password='pass2'),
+ password='pass2', name='child',
+ weight_offset=0.0, weight_scale=1.0),
])
self.assertEquals(len(zm.zone_states), 1)
@@ -129,7 +132,8 @@ class ZoneManagerTestCase(test.TestCase):
zm = zone_manager.ZoneManager()
zone_state = zone_manager.ZoneState()
zone_state.update_credentials(FakeZone(id=1, api_url='http://foo.com',
- username='user1', password='pass1'))
+ username='user1', password='pass1', name='child',
+ weight_offset=0.0, weight_scale=1.0))
zm.zone_states[1] = zone_state
self.mox.StubOutWithMock(db, 'zone_get_all')
@@ -147,14 +151,16 @@ class ZoneManagerTestCase(test.TestCase):
zm = zone_manager.ZoneManager()
zone_state = zone_manager.ZoneState()
zone_state.update_credentials(FakeZone(id=1, api_url='http://foo.com',
- username='user1', password='pass1'))
+ username='user1', password='pass1', name='child',
+ weight_offset=2.0, weight_scale=3.0))
zm.zone_states[1] = zone_state
self.mox.StubOutWithMock(db, 'zone_get_all')
db.zone_get_all(mox.IgnoreArg()).AndReturn([
FakeZone(id=2, api_url='http://foo.com', username='user2',
- password='pass2'),
+ password='pass2', name='child', weight_offset=2.0,
+ weight_scale=3.0),
])
self.assertEquals(len(zm.zone_states), 1)
@@ -168,19 +174,20 @@ class ZoneManagerTestCase(test.TestCase):
def test_poll_zone(self):
self.mox.StubOutWithMock(zone_manager, '_call_novaclient')
zone_manager._call_novaclient(mox.IgnoreArg()).AndReturn(
- dict(name='zohan', capabilities='hairdresser'))
+ dict(name='child', capabilities='hairdresser'))
zone_state = zone_manager.ZoneState()
zone_state.update_credentials(FakeZone(id=2,
api_url='http://foo.com', username='user2',
- password='pass2'))
+ password='pass2', name='child',
+ weight_offset=0.0, weight_scale=1.0))
zone_state.attempt = 1
self.mox.ReplayAll()
zone_manager._poll_zone(zone_state)
self.mox.VerifyAll()
self.assertEquals(zone_state.attempt, 0)
- self.assertEquals(zone_state.name, 'zohan')
+ self.assertEquals(zone_state.name, 'child')
def test_poll_zone_fails(self):
self.stubs.Set(zone_manager, "_call_novaclient", exploding_novaclient)
@@ -188,7 +195,8 @@ class ZoneManagerTestCase(test.TestCase):
zone_state = zone_manager.ZoneState()
zone_state.update_credentials(FakeZone(id=2,
api_url='http://foo.com', username='user2',
- password='pass2'))
+ password='pass2', name='child',
+ weight_offset=0.0, weight_scale=1.0))
zone_state.attempt = FLAGS.zone_failures_to_offline - 1
self.mox.ReplayAll()
@@ -196,7 +204,6 @@ class ZoneManagerTestCase(test.TestCase):
self.mox.VerifyAll()
self.assertEquals(zone_state.attempt, 3)
self.assertFalse(zone_state.is_active)
- self.assertEquals(zone_state.name, None)
def test_host_service_caps_stale_no_stale_service(self):
zm = zone_manager.ZoneManager()
diff --git a/tools/pip-requires b/tools/pip-requires
index a4af326dc..f47d6130c 100644
--- a/tools/pip-requires
+++ b/tools/pip-requires
@@ -11,7 +11,7 @@ eventlet
kombu
lockfile==0.8
lxml==2.3
-python-novaclient==2.6.0
+python-novaclient==2.6.5
python-daemon==1.5.5
python-gflags==1.3
redis==2.0.0