Add support for scheduler_hints

Partially Implements: bp support-schedule-hints
Change-Id: I7c482ca0ac1031f0017c6bc832892111ecfb20dc
This commit is contained in:
liusheng 2017-05-09 19:24:31 +08:00
parent d577c88d4a
commit 6302f74832
10 changed files with 140 additions and 72 deletions

View File

@ -586,6 +586,19 @@ provision_state:
in: body
required: true
type: string
scheduler_hints:
description: |
The dictionary of data send to the scheduler, it represents scheduling
options will be passed to scheduler.
in: body
required: false
type: object
server:
description: |
The dictionary of data represent a server creation request.
in: body
required: true
type: object
server_description:
description: |
A free form description of the server. Limited to 255 characters

View File

@ -1,26 +1,29 @@
{
"name": "test_server",
"description": "this is a test server",
"flavor_uuid": "0607b5f3-6111-424d-ba46-f5de39a6fa69",
"image_uuid": "efe0a06f-ca95-4808-b41e-9f55b9c5eb98",
"availability_zone": "mogan",
"networks": [
{
"net_id": "c1940655-8b8e-4370-b8f9-03ba1daeca31"
"server": {
"name": "test_server",
"description": "this is a test server",
"flavor_uuid": "0607b5f3-6111-424d-ba46-f5de39a6fa69",
"image_uuid": "efe0a06f-ca95-4808-b41e-9f55b9c5eb98",
"availability_zone": "mogan",
"networks": [
{
"net_id": "c1940655-8b8e-4370-b8f9-03ba1daeca31"
},
{
"net_id": "8e8ceb07-4641-4188-9b22-840755e92ee2"
}
],
"metadata" : {
"My Server Name" : "Apache1"
},
{
"net_id": "8e8ceb07-4641-4188-9b22-840755e92ee2"
}
],
"metadata" : {
"My Server Name" : "Apache1"
"personality": [
{
"path": "/etc/banner.txt",
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
}
],
"user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
"key_name": "test_key"
},
"personality": [
{
"path": "/etc/banner.txt",
"contents": "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 b25zLiINCg0KLVJpY2hhcmQgQmFjaA=="
}
],
"user_data": "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
"key_name": "test_key"
"scheduler_hints": {"group": "group1"}
}

View File

@ -30,6 +30,7 @@ Request
.. rest_parameters:: parameters.yaml
- server: server
- name: server_name
- description: server_description
- flavor_uuid: flavorRef
@ -42,6 +43,7 @@ Request
- user_data: user_data
- personality: personality
- key_name: key_name
- scheduler_hints: scheduler_hints
**Example Create Server: JSON request**

View File

@ -16,37 +16,50 @@
from mogan.api.validation import parameter_types
create_server = {
"type": "object",
"properties": {
'name': parameter_types.name,
'description': parameter_types.description,
'availability_zone': parameter_types.availability_zone,
'image_uuid': parameter_types.image_id,
'flavor_uuid': parameter_types.flavor_id,
'networks': {
'type': 'array', 'minItems': 1,
'items': {
'type': 'object',
'properties': {
'net_id': parameter_types.network_id,
'port_id': parameter_types.network_port_id,
"server": {
"type": "object",
"properties": {
'name': parameter_types.name,
'description': parameter_types.description,
'availability_zone': parameter_types.availability_zone,
'image_uuid': parameter_types.image_id,
'flavor_uuid': parameter_types.flavor_id,
'networks': {
'type': 'array', 'minItems': 1,
'items': {
'type': 'object',
'properties': {
'net_id': parameter_types.network_id,
'port_id': parameter_types.network_port_id,
},
'oneOf': [
{'required': ['net_id']},
{'required': ['port_id']}
],
},
'additionalProperties': False,
},
'oneOf': [
{'required': ['net_id']},
{'required': ['port_id']}
],
'additionalProperties': False,
'user_data': {'type': 'string', 'format': 'base64'},
'personality': parameter_types.personality,
'key_name': parameter_types.name,
'min_count': {'type': 'integer', 'minimum': 1},
'max_count': {'type': 'integer', 'minimum': 1},
'metadata': parameter_types.metadata,
},
'required': ['name', 'image_uuid', 'flavor_uuid', 'networks'],
'additionalProperties': False,
},
"scheduler_hints": {
'type': 'object',
'properties': {
'group': parameter_types.server_group_id
},
'additionalProperties': False,
},
'user_data': {'type': 'string', 'format': 'base64'},
'personality': parameter_types.personality,
'key_name': parameter_types.name,
'min_count': {'type': 'integer', 'minimum': 1},
'max_count': {'type': 'integer', 'minimum': 1},
'metadata': parameter_types.metadata,
},
'required': ['name', 'image_uuid', 'flavor_uuid', 'networks'],
'required': ['server'],
'additionalProperties': False,
}

View File

@ -678,6 +678,9 @@ class ServerController(ServerControllerBase):
:param server: a server within the request body.
"""
validation.check_schema(server, server_schemas.create_server)
scheduler_hints = server.get('scheduler_hints', {})
server = server.get('server')
min_count = server.get('min_count', 1)
max_count = server.get('max_count', min_count)
@ -715,8 +718,8 @@ class ServerController(ServerControllerBase):
injected_files=injected_files,
key_name=key_name,
min_count=min_count,
max_count=max_count)
max_count=max_count,
scheduler_hints=scheduler_hints)
# Set the HTTP Location Header for the first server.
pecan.response.location = link.build_url('server', servers[0].uuid)
return Server.convert_with_links(servers[0])

View File

@ -58,6 +58,9 @@ flavor_id = {
'type': 'string', 'format': 'uuid'
}
server_group_id = {
'type': 'string', 'format': 'uuid'
}
metadata = {
'type': 'object',

View File

@ -265,7 +265,7 @@ class API(object):
def _create_server(self, context, flavor, image_uuid,
name, description, availability_zone, metadata,
requested_networks, user_data, injected_files,
key_name, min_count, max_count):
key_name, min_count, max_count, scheduler_hints):
"""Verify all the input parameters"""
# Verify the specified image exists
@ -306,6 +306,7 @@ class API(object):
},
'flavor': dict(flavor),
'availability_zone': availability_zone,
'scheduler_hints': scheduler_hints
}
self.engine_rpcapi.schedule_and_create_servers(context, servers,
@ -321,7 +322,7 @@ class API(object):
name=None, description=None, availability_zone=None,
metadata=None, requested_networks=None, user_data=None,
injected_files=None, key_name=None, min_count=None,
max_count=None):
max_count=None, scheduler_hints=None):
"""Provision servers
Sending server information to the engine and will handle
@ -340,7 +341,7 @@ class API(object):
availability_zone, metadata,
requested_networks, user_data,
injected_files, key_name,
min_count, max_count)
min_count, max_count, scheduler_hints)
def _delete_server(self, context, server):

View File

@ -102,14 +102,16 @@ class TestServers(v1_test.APITestV1):
headers = self.gen_headers(self.context)
for i in six.moves.xrange(amount):
test_body = {
"name": "test_server_" + str(i),
"description": "just test server " + str(i),
'flavor_uuid': self.FLAVOR_UUID,
'image_uuid': 'b8f82429-3a13-4ffe-9398-4d1abdc256a8',
'networks': [
{'net_id': 'c1940655-8b8e-4370-b8f9-03ba1daeca31'}
],
'metadata': {'fake_key': 'fake_value'}
"server": {
"name": "test_server_" + str(i),
"description": "just test server " + str(i),
'flavor_uuid': self.FLAVOR_UUID,
'image_uuid': 'b8f82429-3a13-4ffe-9398-4d1abdc256a8',
'networks': [
{'net_id': 'c1940655-8b8e-4370-b8f9-03ba1daeca31'}
],
'metadata': {'fake_key': 'fake_value'}
}
}
responses.append(
self.post_json('/servers', test_body, headers=headers,
@ -141,6 +143,31 @@ class TestServers(v1_test.APITestV1):
self.delete('/flavors/' + self.FLAVOR_UUID,
headers=headers, status=409)
@mock.patch('mogan.engine.rpcapi.EngineAPI.schedule_and_create_servers')
@mock.patch('oslo_utils.uuidutils.generate_uuid')
def test_server_post_with_scheduler_hints(self, mocked_uuid,
mock_create):
mocked_uuid.return_value = self.SERVER_UUIDS[0]
mock_create.return_value = mock.MagicMock()
body = {
"server": {
"name": "test_server_with_hints",
"description": "just test server with hints",
'flavor_uuid': 'ff28b5a2-73e5-431c-b4b7-1b96b74bca7b',
'image_uuid': 'b8f82429-3a13-4ffe-9398-4d1abdc256a8',
'networks': [
{'net_id': 'c1940655-8b8e-4370-b8f9-03ba1daeca31',
'port_type': 'Ethernet'}],
'metadata': {'fake_key': 'fake_value'}
},
"scheduler_hints": {"group": 'group1'}
}
headers = self.gen_headers(self.context)
response = self.post_json('/servers', body, headers=headers,
status=201)
server = response.json
self.assertEqual('test_server_with_hints', server['name'])
def test_server_show(self):
self._prepare_server(1)
headers = self.gen_headers(self.context)

View File

@ -81,11 +81,12 @@ class BaseBaremetalComputeTest(tempest.test.BaseTestCase):
@classmethod
def create_server(cls, wait_until_active=True):
body = {'name': data_utils.rand_name('mogan_server'),
'description': "mogan tempest server",
'flavor_uuid': cls.flavor,
'image_uuid': cls.image_id,
"networks": [{"net_id": cls.net_id}]
body = {"server": {'name': data_utils.rand_name('mogan_server'),
'description': "mogan tempest server",
'flavor_uuid': cls.flavor,
'image_uuid': cls.image_id,
"networks": [{"net_id": cls.net_id}]
}
}
resp = cls.baremetal_compute_client.create_server(**body)
cls.server_ids.append(resp['uuid'])

View File

@ -34,13 +34,15 @@ def gen_post_body(**kw):
}
]
return {
"name": kw.get("name", "test_server"),
"description": kw.get("description", "this is a test server"),
"flavor_uuid": kw.get(
"flavor_uuid", "0607b5f3-6111-424d-ba46-f5de39a6fa69"),
"image_uuid": kw.get(
"image_uuid", "efe0a06f-ca95-4808-b41e-9f55b9c5eb98"),
"networks": kw.get("networks", fake_networks)
"server": {
"name": kw.get("name", "test_server"),
"description": kw.get("description", "this is a test server"),
"flavor_uuid": kw.get(
"flavor_uuid", "0607b5f3-6111-424d-ba46-f5de39a6fa69"),
"image_uuid": kw.get(
"image_uuid", "efe0a06f-ca95-4808-b41e-9f55b9c5eb98"),
"networks": kw.get("networks", fake_networks)
}
}