summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorRussell Bryant <rbryant@redhat.com>2012-08-01 16:48:03 -0400
committerRussell Bryant <rbryant@redhat.com>2012-08-03 22:13:28 -0400
commit6e134c9df2ec05ebce9f62c6d85988ece18620ad (patch)
tree4aa467c5fe04990c3c51d7cfa5efd26b6f862117 /nova
parent5fb51ea04b2ccff55f45af9e99cecd5d22f27a42 (diff)
downloadnova-6e134c9df2ec05ebce9f62c6d85988ece18620ad.tar.gz
nova-6e134c9df2ec05ebce9f62c6d85988ece18620ad.tar.xz
nova-6e134c9df2ec05ebce9f62c6d85988ece18620ad.zip
Updates to the prep_resize scheduler rpc call.
I started looking at this because of the prep_resize rpc call in the compute manager. An API server calls prep_resize on the scheduler which then calls it on a compute node. I will need to make the same changes on the compute side, but this is the first step. The prep_resize call was taking two object IDs, an instance UUID and an instance_type ID. Both of these have been converted. It now takes an instance dict and an instance_type dict, instead. It can also handle receiving the old IDs for backwards compatibility. prep_resize also took a topic argument that was unused, so it has just been removed. There are a number of changes in the scheduler code tied up in this to make it more explicit about exactly what arguments are expected instead of just using *args, **kwargs. Part of blueprint no-db-messaging. Change-Id: I4af18e5575e2bb60a410fc8edabf3d607c72aabc
Diffstat (limited to 'nova')
-rw-r--r--nova/compute/api.py5
-rw-r--r--nova/scheduler/chance.py24
-rw-r--r--nova/scheduler/driver.py3
-rw-r--r--nova/scheduler/filter_scheduler.py17
-rw-r--r--nova/scheduler/manager.py30
-rw-r--r--nova/scheduler/rpcapi.py15
-rw-r--r--nova/tests/scheduler/test_chance_scheduler.py6
-rw-r--r--nova/tests/scheduler/test_filter_scheduler.py2
-rw-r--r--nova/tests/scheduler/test_rpcapi.py9
-rw-r--r--nova/tests/scheduler/test_scheduler.py39
10 files changed, 96 insertions, 54 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 4f7e67105..834f7bd38 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -1441,9 +1441,8 @@ class API(base.Base):
filter_properties['ignore_hosts'].append(instance['host'])
args = {
- "topic": FLAGS.compute_topic,
- "instance_uuid": instance['uuid'],
- "instance_type_id": new_instance_type['id'],
+ "instance": instance,
+ "instance_type": new_instance_type,
"image": image,
"update_db": False,
"request_spec": jsonutils.to_primitive(request_spec),
diff --git a/nova/scheduler/chance.py b/nova/scheduler/chance.py
index b9fab9540..1be86dda6 100644
--- a/nova/scheduler/chance.py
+++ b/nova/scheduler/chance.py
@@ -30,15 +30,14 @@ from nova.scheduler import driver
class ChanceScheduler(driver.Scheduler):
"""Implements Scheduler as a random node selector."""
- def _filter_hosts(self, request_spec, hosts, **kwargs):
+ def _filter_hosts(self, request_spec, hosts, filter_properties):
"""Filter a list of hosts based on request_spec."""
- filter_properties = kwargs.get('filter_properties', {})
ignore_hosts = filter_properties.get('ignore_hosts', [])
hosts = [host for host in hosts if host not in ignore_hosts]
return hosts
- def _schedule(self, context, topic, request_spec, **kwargs):
+ def _schedule(self, context, topic, request_spec, filter_properties):
"""Picks a host that is up at random."""
elevated = context.elevated()
@@ -47,7 +46,7 @@ class ChanceScheduler(driver.Scheduler):
msg = _("Is the appropriate service running?")
raise exception.NoValidHost(reason=msg)
- hosts = self._filter_hosts(request_spec, hosts, **kwargs)
+ hosts = self._filter_hosts(request_spec, hosts, filter_properties)
if not hosts:
msg = _("Could not find another compute")
raise exception.NoValidHost(reason=msg)
@@ -57,16 +56,19 @@ class ChanceScheduler(driver.Scheduler):
def schedule(self, context, topic, method, *_args, **kwargs):
"""Picks a host that is up at random."""
- host = self._schedule(context, topic, None, **kwargs)
+ filter_properties = kwargs.get('filter_properties', {})
+ host = self._schedule(context, topic, None, filter_properties)
driver.cast_to_host(context, topic, host, method, **kwargs)
def schedule_run_instance(self, context, request_spec, reservations,
*_args, **kwargs):
"""Create and run an instance or instances"""
num_instances = request_spec.get('num_instances', 1)
+ filter_properties = kwargs.get('filter_properties', {})
instances = []
for num in xrange(num_instances):
- host = self._schedule(context, 'compute', request_spec, **kwargs)
+ host = self._schedule(context, 'compute', request_spec,
+ filter_properties)
request_spec['instance_properties']['launch_index'] = num
instance = self.create_instance_db_entry(context, request_spec,
reservations)
@@ -79,7 +81,11 @@ class ChanceScheduler(driver.Scheduler):
del request_spec['instance_properties']['uuid']
return instances
- def schedule_prep_resize(self, context, request_spec, *args, **kwargs):
+ def schedule_prep_resize(self, context, image, update_db, request_spec,
+ filter_properties, instance, instance_type):
"""Select a target for resize."""
- host = self._schedule(context, 'compute', request_spec, **kwargs)
- driver.cast_to_compute_host(context, host, 'prep_resize', **kwargs)
+ host = self._schedule(context, 'compute', request_spec,
+ filter_properties)
+ driver.cast_to_compute_host(context, host, 'prep_resize',
+ instance_uuid=instance['uuid'],
+ instance_type_id=instance_type['id'], image=image)
diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py
index 94fc6f5fe..39d3446c6 100644
--- a/nova/scheduler/driver.py
+++ b/nova/scheduler/driver.py
@@ -179,7 +179,8 @@ class Scheduler(object):
"""Must override schedule method for scheduler to work."""
raise NotImplementedError(_("Must implement a fallback schedule"))
- def schedule_prep_resize(self, context, request_spec, *_args, **_kwargs):
+ def schedule_prep_resize(self, context, image, update_db, request_spec,
+ filter_properties, instance, instance_type):
"""Must override schedule_prep_resize method for scheduler to work."""
msg = _("Driver must implement schedule_prep_resize")
raise NotImplementedError(msg)
diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py
index 5b0bcd4f1..63405541b 100644
--- a/nova/scheduler/filter_scheduler.py
+++ b/nova/scheduler/filter_scheduler.py
@@ -70,7 +70,7 @@ class FilterScheduler(driver.Scheduler):
filter_properties = kwargs.pop('filter_properties', {})
weighted_hosts = self._schedule(context, "compute", request_spec,
- filter_properties, *args, **kwargs)
+ filter_properties)
if not weighted_hosts:
raise exception.NoValidHost(reason="")
@@ -103,7 +103,8 @@ class FilterScheduler(driver.Scheduler):
return instances
- def schedule_prep_resize(self, context, request_spec, *args, **kwargs):
+ def schedule_prep_resize(self, context, image, update_db, request_spec,
+ filter_properties, instance, instance_type):
"""Select a target for resize.
Selects a target host for the instance, post-resize, and casts
@@ -111,18 +112,15 @@ class FilterScheduler(driver.Scheduler):
"""
hosts = self._schedule(context, 'compute', request_spec,
- *args, **kwargs)
+ filter_properties)
if not hosts:
raise exception.NoValidHost(reason="")
host = hosts.pop(0)
- # NOTE(comstud): Make sure we do not pass this through. It
- # contains an instance of RpcContext that cannot be serialized.
- kwargs.pop('filter_properties', None)
-
# Forward off to the host
driver.cast_to_compute_host(context, host.host_state.host,
- 'prep_resize', **kwargs)
+ 'prep_resize', instance_uuid=instance['uuid'],
+ instance_type_id=instance_type['id'], image=image)
def _provision_resource(self, context, weighted_host, request_spec,
reservations, filter_properties, kwargs):
@@ -207,8 +205,7 @@ class FilterScheduler(driver.Scheduler):
msg = _("Exceeded max scheduling attempts %d ") % max_attempts
raise exception.NoValidHost(msg, instance_uuid=uuid)
- def _schedule(self, context, topic, request_spec, filter_properties, *args,
- **kwargs):
+ def _schedule(self, context, topic, request_spec, filter_properties):
"""Returns a list of hosts that meet the required specs,
ordered by their fitness.
"""
diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py
index e243e4518..b63de6c4d 100644
--- a/nova/scheduler/manager.py
+++ b/nova/scheduler/manager.py
@@ -53,7 +53,7 @@ QUOTAS = quota.QUOTAS
class SchedulerManager(manager.Manager):
"""Chooses a host to run instances on."""
- RPC_API_VERSION = '1.0'
+ RPC_API_VERSION = '1.1'
def __init__(self, scheduler_driver=None, *args, **kwargs):
if not scheduler_driver:
@@ -138,24 +138,42 @@ class SchedulerManager(manager.Manager):
if reservations:
QUOTAS.rollback(context, reservations)
- def prep_resize(self, context, topic, *args, **kwargs):
+ def prep_resize(self, context, image, update_db, request_spec,
+ filter_properties, instance=None, instance_uuid=None,
+ instance_type=None, instance_type_id=None, topic=None):
"""Tries to call schedule_prep_resize on the driver.
Sets instance vm_state to ACTIVE on NoHostFound
Sets vm_state to ERROR on other exceptions
"""
- args = (context,) + args
+ if not instance:
+ instance = db.instance_get_by_uuid(context, instance_uuid)
+
+ if not instance_type:
+ instance_type = db.instance_type_get(context, instance_type_id)
+
try:
- return self.driver.schedule_prep_resize(*args, **kwargs)
+ kwargs = {
+ 'context': context,
+ 'image': image,
+ 'update_db': update_db,
+ 'request_spec': request_spec,
+ 'filter_properties': filter_properties,
+ 'instance': instance,
+ 'instance_type': instance_type,
+ }
+ return self.driver.schedule_prep_resize(**kwargs)
except exception.NoValidHost as ex:
self._set_vm_state_and_notify('prep_resize',
{'vm_state': vm_states.ACTIVE,
'task_state': None},
- context, ex, *args, **kwargs)
+ context, ex,
+ request_spec=request_spec)
except Exception as ex:
with excutils.save_and_reraise_exception():
self._set_vm_state_and_notify('prep_resize',
{'vm_state': vm_states.ERROR},
- context, ex, *args, **kwargs)
+ context, ex,
+ request_spec=request_spec)
def _set_vm_state_and_notify(self, method, updates, context, ex,
*args, **kwargs):
diff --git a/nova/scheduler/rpcapi.py b/nova/scheduler/rpcapi.py
index b2522ab53..60de98c91 100644
--- a/nova/scheduler/rpcapi.py
+++ b/nova/scheduler/rpcapi.py
@@ -19,6 +19,7 @@ Client side of the scheduler manager RPC API.
"""
from nova import flags
+from nova.openstack.common import jsonutils
import nova.openstack.common.rpc.proxy
@@ -31,6 +32,10 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
API version history:
1.0 - Initial version.
+ 1.1 - Changes to prep_resize():
+ - remove instance_uuid, add instance
+ - remove instance_type_id, add instance_type
+ - remove topic, it was unused
'''
BASE_RPC_API_VERSION = '1.0'
@@ -51,12 +56,14 @@ class SchedulerAPI(nova.openstack.common.rpc.proxy.RpcProxy):
filter_properties=filter_properties,
reservations=reservations))
- def prep_resize(self, ctxt, topic, instance_uuid, instance_type_id, image,
+ def prep_resize(self, ctxt, instance, instance_type, image,
update_db, request_spec, filter_properties):
- self.cast(ctxt, self.make_msg('prep_resize', topic=topic,
- instance_uuid=instance_uuid, instance_type_id=instance_type_id,
+ instance_p = jsonutils.to_primitive(instance)
+ instance_type_p = jsonutils.to_primitive(instance_type)
+ self.cast(ctxt, self.make_msg('prep_resize',
+ instance=instance_p, instance_type=instance_type_p,
image=image, update_db=update_db, request_spec=request_spec,
- filter_properties=filter_properties))
+ filter_properties=filter_properties), version='1.1')
def show_host_resources(self, ctxt, host):
return self.call(ctxt, self.make_msg('show_host_resources', host=host))
diff --git a/nova/tests/scheduler/test_chance_scheduler.py b/nova/tests/scheduler/test_chance_scheduler.py
index ec853594b..eabfa93dc 100644
--- a/nova/tests/scheduler/test_chance_scheduler.py
+++ b/nova/tests/scheduler/test_chance_scheduler.py
@@ -149,7 +149,8 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
self.mox.StubOutWithMock(driver, 'cast_to_compute_host')
self.mox.StubOutWithMock(driver, 'encode_instance')
# instance 1
- self.driver._schedule(ctxt, 'compute', request_spec).AndReturn('host')
+ self.driver._schedule(ctxt, 'compute', request_spec,
+ {}).AndReturn('host')
self.driver.create_instance_db_entry(
ctxt, mox.Func(_has_launch_index(0)), None
).WithSideEffects(_add_uuid(1)).AndReturn(instance1)
@@ -157,7 +158,8 @@ class ChanceSchedulerTestCase(test_scheduler.SchedulerTestCase):
instance_uuid=instance1['uuid'])
driver.encode_instance(instance1).AndReturn(instance1)
# instance 2
- self.driver._schedule(ctxt, 'compute', request_spec).AndReturn('host')
+ self.driver._schedule(ctxt, 'compute', request_spec,
+ {}).AndReturn('host')
self.driver.create_instance_db_entry(
ctxt, mox.Func(_has_launch_index(1)), None
).WithSideEffects(_add_uuid(2)).AndReturn(instance2)
diff --git a/nova/tests/scheduler/test_filter_scheduler.py b/nova/tests/scheduler/test_filter_scheduler.py
index 158fc0d83..648373945 100644
--- a/nova/tests/scheduler/test_filter_scheduler.py
+++ b/nova/tests/scheduler/test_filter_scheduler.py
@@ -111,7 +111,7 @@ class FilterSchedulerTestCase(test_scheduler.SchedulerTestCase):
self.mox.StubOutWithMock(self.driver, '_provision_resource')
self.driver._schedule(context_fake, 'compute',
- request_spec, {}, **fake_kwargs
+ request_spec, {}
).AndReturn(['host1', 'host2'])
# instance 1
self.driver._provision_resource(
diff --git a/nova/tests/scheduler/test_rpcapi.py b/nova/tests/scheduler/test_rpcapi.py
index 000138bc9..c881bc306 100644
--- a/nova/tests/scheduler/test_rpcapi.py
+++ b/nova/tests/scheduler/test_rpcapi.py
@@ -40,8 +40,9 @@ class SchedulerRpcAPITestCase(test.TestCase):
ctxt = context.RequestContext('fake_user', 'fake_project')
rpcapi = scheduler_rpcapi.SchedulerAPI()
expected_retval = 'foo' if method == 'call' else None
+ expected_version = kwargs.pop('version', rpcapi.BASE_RPC_API_VERSION)
expected_msg = rpcapi.make_msg(method, **kwargs)
- expected_msg['version'] = rpcapi.BASE_RPC_API_VERSION
+ expected_msg['version'] = expected_version
if rpc_method == 'cast' and method == 'run_instance':
kwargs['call'] = False
@@ -81,10 +82,10 @@ class SchedulerRpcAPITestCase(test.TestCase):
def test_prep_resize(self):
self._test_scheduler_api('prep_resize', rpc_method='cast',
- topic='fake_topic', instance_uuid='fake_uuid',
- instance_type_id='fake_type_id', image='fake_image',
+ instance='fake_instance',
+ instance_type='fake_type', image='fake_image',
update_db='fake_update_db', request_spec='fake_request_spec',
- filter_properties='fake_props')
+ filter_properties='fake_props', version='1.1')
def test_show_host_resources(self):
self._test_scheduler_api('show_host_resources', rpc_method='call',
diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py
index ec30321d0..b9cb4de59 100644
--- a/nova/tests/scheduler/test_scheduler.py
+++ b/nova/tests/scheduler/test_scheduler.py
@@ -245,18 +245,23 @@ class SchedulerManagerTestCase(test.TestCase):
request_spec = {'instance_properties':
{'uuid': fake_instance_uuid}}
- self.fake_kwargs['request_spec'] = request_spec
-
- self.manager.driver.schedule_prep_resize(self.context,
- *self.fake_args, **self.fake_kwargs).AndRaise(
- exception.NoValidHost(reason=""))
+ kwargs = {
+ 'context': self.context,
+ 'image': 'fake_image',
+ 'update_db': True,
+ 'request_spec': request_spec,
+ 'filter_properties': 'fake_props',
+ 'instance': 'fake_instance',
+ 'instance_type': 'fake_type',
+ }
+ self.manager.driver.schedule_prep_resize(**kwargs).AndRaise(
+ exception.NoValidHost(reason=""))
db.instance_update_and_get_original(self.context, fake_instance_uuid,
{"vm_state": vm_states.ACTIVE, "task_state": None}).AndReturn(
(inst, inst))
self.mox.ReplayAll()
- self.manager.prep_resize(self.context, self.topic,
- *self.fake_args, **self.fake_kwargs)
+ self.manager.prep_resize(**kwargs)
def test_prep_resize_exception_host_in_error_state_and_raise(self):
"""Test that a NoValidHost exception for prep_resize puts
@@ -270,10 +275,17 @@ class SchedulerManagerTestCase(test.TestCase):
request_spec = {'instance_properties':
{'uuid': fake_instance_uuid}}
- self.fake_kwargs['request_spec'] = request_spec
+ kwargs = {
+ 'context': self.context,
+ 'image': 'fake_image',
+ 'update_db': True,
+ 'request_spec': request_spec,
+ 'filter_properties': 'fake_props',
+ 'instance': 'fake_instance',
+ 'instance_type': 'fake_type',
+ }
- self.manager.driver.schedule_prep_resize(self.context,
- *self.fake_args, **self.fake_kwargs).AndRaise(
+ self.manager.driver.schedule_prep_resize(**kwargs).AndRaise(
self.AnException('something happened'))
inst = {
@@ -286,8 +298,7 @@ class SchedulerManagerTestCase(test.TestCase):
self.mox.ReplayAll()
self.assertRaises(self.AnException, self.manager.prep_resize,
- self.context, self.topic,
- *self.fake_args, **self.fake_kwargs)
+ **kwargs)
class SchedulerTestCase(test.TestCase):
@@ -772,8 +783,8 @@ class SchedulerDriverBaseTestCase(SchedulerTestCase):
self.assertRaises(NotImplementedError,
self.driver.schedule_prep_resize,
- self.context, fake_request_spec,
- *fake_args, **fake_kwargs)
+ self.context, {}, False,
+ fake_request_spec, {}, {}, {})
class SchedulerDriverModuleTestCase(test.TestCase):