summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Waldon <bcwaldon@gmail.com>2012-01-20 15:12:01 -0800
committerBrian Waldon <bcwaldon@gmail.com>2012-01-20 19:47:46 -0800
commitc7646aa88d564694b99a569c3cdd2c7ffbbb745d (patch)
tree2fab0252183edb69fd9e99afa79dce2f41a050d2
parent16ea348a1623f055809d0d9b7fe9f046515b5dd1 (diff)
downloadnova-c7646aa88d564694b99a569c3cdd2c7ffbbb745d.tar.gz
nova-c7646aa88d564694b99a569c3cdd2c7ffbbb745d.tar.xz
nova-c7646aa88d564694b99a569c3cdd2c7ffbbb745d.zip
Add SchedulerHints compute extension
This allows arbitrary key/values to be passed in on a compute create request or rebuild/resize action. That data will be made available to the compute api as a filter_properties dictionary. Change-Id: Ie2ec57dcbc0d1d178e06606cb41027f9e46719a2
-rw-r--r--nova/api/openstack/compute/contrib/scheduler_hints.py65
-rw-r--r--nova/api/openstack/compute/servers.py4
-rw-r--r--nova/compute/api.py9
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py103
-rw-r--r--nova/tests/api/openstack/compute/test_extensions.py1
5 files changed, 178 insertions, 4 deletions
diff --git a/nova/api/openstack/compute/contrib/scheduler_hints.py b/nova/api/openstack/compute/contrib/scheduler_hints.py
new file mode 100644
index 000000000..ef665da27
--- /dev/null
+++ b/nova/api/openstack/compute/contrib/scheduler_hints.py
@@ -0,0 +1,65 @@
+# 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
+# under the License
+
+import webob.exc
+
+from nova.api.openstack import extensions
+from nova.api.openstack import wsgi
+import nova.log as logging
+
+LOG = logging.getLogger('nova.api.openstack.compute.contrib.scheduler_hints')
+
+
+class SchedulerHintsController(wsgi.Controller):
+
+ @staticmethod
+ def _extract_scheduler_hints(body):
+ hints = {}
+
+ try:
+ hints.update(body['os:scheduler_hints'])
+
+ # Ignore if data is not present
+ except KeyError:
+ pass
+
+ # Fail if non-dict provided
+ except ValueError:
+ msg = _("Malformed scheduler_hints attribute")
+ raise webob.exc.HTTPBadRequest(reason=msg)
+
+ return hints
+
+ @wsgi.extends
+ def create(self, req, body):
+ hints = self._extract_scheduler_hints(body)
+ body['server']['scheduler_hints'] = hints
+ yield
+
+
+class Scheduler_hints(extensions.ExtensionDescriptor):
+ """Pass arbitrary key/value pairs to the scheduler"""
+
+ name = "SchedulerHints"
+ alias = "os-scheduler-hints"
+ namespace = "http://docs.openstack.org/compute/ext/" \
+ "scheduler-hints/api/v2"
+ updated = "2011-07-19T00:00:00+00:00"
+
+ def get_controller_extensions(self):
+ controller = SchedulerHintsController()
+ ext = extensions.ControllerExtension(self, 'servers', controller)
+ return [ext]
diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py
index 988b403b1..ee7038c6e 100644
--- a/nova/api/openstack/compute/servers.py
+++ b/nova/api/openstack/compute/servers.py
@@ -709,6 +709,7 @@ class Controller(wsgi.Controller):
min_count = max_count
auto_disk_config = server_dict.get('auto_disk_config')
+ scheduler_hints = server_dict.get('scheduler_hints', {})
try:
inst_type = \
@@ -735,7 +736,8 @@ class Controller(wsgi.Controller):
availability_zone=availability_zone,
config_drive=config_drive,
block_device_mapping=block_device_mapping,
- auto_disk_config=auto_disk_config)
+ auto_disk_config=auto_disk_config,
+ scheduler_hints=scheduler_hints)
except exception.QuotaError as error:
self._handle_quota_error(error)
except exception.InstanceTypeMemoryTooSmall as error:
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 138d70b66..2f3749ca0 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -179,7 +179,7 @@ class API(base.Base):
reservation_id, access_ip_v4, access_ip_v6,
requested_networks, config_drive,
block_device_mapping, auto_disk_config,
- create_instance_here=False):
+ create_instance_here=False, scheduler_hints=None):
"""Verify all the input parameters regardless of the provisioning
strategy being performed and schedule the instance(s) for
creation."""
@@ -298,6 +298,8 @@ class API(base.Base):
else:
filter_properties = {}
+ filter_properties['scheduler_hints'] = scheduler_hints
+
base_options = {
'reservation_id': reservation_id,
'image_ref': image_href,
@@ -571,7 +573,7 @@ class API(base.Base):
reservation_id=None, block_device_mapping=None,
access_ip_v4=None, access_ip_v6=None,
requested_networks=None, config_drive=None,
- auto_disk_config=None):
+ auto_disk_config=None, scheduler_hints=None):
"""
Provision instances, sending instance information to the
scheduler. The scheduler will determine where the instance(s)
@@ -610,7 +612,8 @@ class API(base.Base):
reservation_id, access_ip_v4, access_ip_v6,
requested_networks, config_drive,
block_device_mapping, auto_disk_config,
- create_instance_here=create_instance_here)
+ create_instance_here=create_instance_here,
+ scheduler_hints=scheduler_hints)
if create_instance_here or instances is None:
return (instances, reservation_id)
diff --git a/nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py b/nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py
new file mode 100644
index 000000000..7185873a7
--- /dev/null
+++ b/nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py
@@ -0,0 +1,103 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from nova.api.openstack import compute
+from nova.api.openstack.compute import extensions
+from nova.api.openstack import wsgi
+import nova.db.api
+import nova.rpc
+from nova import test
+from nova.tests.api.openstack import fakes
+from nova import utils
+
+
+UUID = fakes.FAKE_UUID
+
+
+class SchedulerHintsTestCase(test.TestCase):
+
+ def setUp(self):
+ super(SchedulerHintsTestCase, self).setUp()
+
+ self.fake_instance = fakes.stub_instance(1, uuid=UUID)
+
+ app = compute.APIRouter()
+ app = extensions.ExtensionMiddleware(app)
+ app = wsgi.LazySerializationMiddleware(app)
+ self.app = app
+
+ def test_create_server_without_hints(self):
+
+ def fake_create(*args, **kwargs):
+ self.assertEqual(kwargs['scheduler_hints'], {})
+ return ([self.fake_instance], '')
+
+ self.stubs.Set(nova.compute.api.API, 'create', fake_create)
+
+ req = fakes.HTTPRequest.blank('/fake/servers')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ body = {'server': {
+ 'name': 'server_test',
+ 'imageRef': 'cedef40a-ed67-4d10-800e-17455edce175',
+ 'flavorRef': '1',
+ }}
+
+ req.body = utils.dumps(body)
+ res = req.get_response(self.app)
+ self.assertEqual(202, res.status_int)
+
+ def test_create_server_with_hints(self):
+
+ def fake_create(*args, **kwargs):
+ self.assertEqual(kwargs['scheduler_hints'], {'a': 'b'})
+ return ([self.fake_instance], '')
+
+ self.stubs.Set(nova.compute.api.API, 'create', fake_create)
+
+ req = fakes.HTTPRequest.blank('/fake/servers')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ body = {
+ 'server': {
+ 'name': 'server_test',
+ 'imageRef': 'cedef40a-ed67-4d10-800e-17455edce175',
+ 'flavorRef': '1',
+ },
+ 'os:scheduler_hints': {'a': 'b'},
+ }
+
+ req.body = utils.dumps(body)
+ res = req.get_response(self.app)
+ self.assertEqual(202, res.status_int)
+
+ def test_create_server_bad_hints(self):
+ req = fakes.HTTPRequest.blank('/fake/servers')
+ req.method = 'POST'
+ req.content_type = 'application/json'
+ body = {
+ 'server': {
+ 'name': 'server_test',
+ 'imageRef': 'cedef40a-ed67-4d10-800e-17455edce175',
+ 'flavorRef': '1',
+ },
+ 'os:scheduler_hints': 'here',
+ }
+
+ req.body = utils.dumps(body)
+ res = req.get_response(self.app)
+ self.assertEqual(400, res.status_int)
diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py
index 02356bc44..6bc56532f 100644
--- a/nova/tests/api/openstack/compute/test_extensions.py
+++ b/nova/tests/api/openstack/compute/test_extensions.py
@@ -173,6 +173,7 @@ class ExtensionControllerTest(ExtensionTestCase):
"Multinic",
"Quotas",
"Rescue",
+ "SchedulerHints",
"SecurityGroups",
"ServerActionList",
"ServerDiagnostics",