Skip to content

Commit ff0feed

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Add host and hypervisor_hostname flag to create server"
2 parents bea9058 + 564290a commit ff0feed

25 files changed

+660
-17
lines changed

api-ref/source/parameters.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5955,6 +5955,16 @@ server_groups_quota_optional:
59555955
in: body
59565956
required: false
59575957
type: integer
5958+
# This is the host in a POST (create instance) request body.
5959+
server_host_create:
5960+
description: |
5961+
The name of the compute service host on which the server is to be created.
5962+
The API will return 400 if no compute services are found with the given
5963+
host name. By default, it can be specified by administrators only.
5964+
in: body
5965+
required: false
5966+
type: string
5967+
min_version: 2.74
59585968
server_hostname:
59595969
in: body
59605970
required: false
@@ -5963,6 +5973,16 @@ server_hostname:
59635973
The hostname set on the instance when it is booted.
59645974
By default, it appears in the response for administrative users only.
59655975
min_version: 2.3
5976+
# This is the hypervisor_hostname in a POST (create instance) request body.
5977+
server_hypervisor_hostname_create:
5978+
description: |
5979+
The hostname of the hypervisor on which the server is to be created.
5980+
The API will return 400 if no hypervisors are found with the given
5981+
hostname. By default, it can be specified by administrators only.
5982+
in: body
5983+
required: false
5984+
type: string
5985+
min_version: 2.74
59665986
server_id:
59675987
description: |
59685988
The UUID of the server.

api-ref/source/servers.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ Request
397397
- description: server_description
398398
- tags: server_tags_create
399399
- trusted_image_certificates: server_trusted_image_certificates_create_req
400+
- host: server_host_create
401+
- hypervisor_hostname: server_hypervisor_hostname_create
400402
- os:scheduler_hints: os:scheduler_hints
401403
- os:scheduler_hints.build_near_host_ip: os:scheduler_hints_build_near_host_ip
402404
- os:scheduler_hints.cidr: os:scheduler_hints_cidr
@@ -427,6 +429,11 @@ Request
427429
.. literalinclude:: ../../doc/api_samples/servers/v2.63/server-create-req.json
428430
:language: javascript
429431

432+
**Example Create Server With Host and Hypervisor Hostname (v2.74)**
433+
434+
.. literalinclude:: ../../doc/api_samples/servers/v2.74/server-create-req-with-host-and-node.json
435+
:language: javascript
436+
430437
Response
431438
--------
432439

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"server" : {
3+
"adminPass": "MySecretPass",
4+
"accessIPv4": "1.2.3.4",
5+
"accessIPv6": "80fe::",
6+
"name" : "new-server-test",
7+
"imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b",
8+
"flavorRef" : "6",
9+
"OS-DCF:diskConfig": "AUTO",
10+
"metadata" : {
11+
"My Server Name" : "Apache1"
12+
},
13+
"security_groups": [
14+
{
15+
"name": "default"
16+
}
17+
],
18+
"user_data" : "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
19+
"networks": "auto",
20+
"host": "openstack-node-01",
21+
"hypervisor_hostname": "openstack-node-01"
22+
}
23+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"server" : {
3+
"adminPass": "MySecretPass",
4+
"accessIPv4": "1.2.3.4",
5+
"accessIPv6": "80fe::",
6+
"name" : "new-server-test",
7+
"imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b",
8+
"flavorRef" : "6",
9+
"OS-DCF:diskConfig": "AUTO",
10+
"metadata" : {
11+
"My Server Name" : "Apache1"
12+
},
13+
"security_groups": [
14+
{
15+
"name": "default"
16+
}
17+
],
18+
"user_data" : "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
19+
"networks": "auto",
20+
"host": "openstack-node-01"
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"server" : {
3+
"adminPass": "MySecretPass",
4+
"accessIPv4": "1.2.3.4",
5+
"accessIPv6": "80fe::",
6+
"name" : "new-server-test",
7+
"imageRef" : "70a599e0-31e7-49b7-b260-868f441e862b",
8+
"flavorRef" : "6",
9+
"OS-DCF:diskConfig": "AUTO",
10+
"metadata" : {
11+
"My Server Name" : "Apache1"
12+
},
13+
"security_groups": [
14+
{
15+
"name": "default"
16+
}
17+
],
18+
"user_data" : "IyEvYmluL2Jhc2gKL2Jpbi9zdQplY2hvICJJIGFtIGluIHlvdSEiCg==",
19+
"networks": "auto",
20+
"hypervisor_hostname": "openstack-node-01"
21+
}
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"server": {
3+
"OS-DCF:diskConfig": "AUTO",
4+
"adminPass": "DB2bQBhxvq8a",
5+
"id": "84e2b49d-39a9-4d32-9100-e62161c236db",
6+
"links": [
7+
{
8+
"href": "http://openstack.example.com/v2.1/6f70656e737461636b20342065766572/servers/84e2b49d-39a9-4d32-9100-e62161c236db",
9+
"rel": "self"
10+
},
11+
{
12+
"href": "http://openstack.example.com/6f70656e737461636b20342065766572/servers/84e2b49d-39a9-4d32-9100-e62161c236db",
13+
"rel": "bookmark"
14+
}
15+
],
16+
"security_groups": [
17+
{
18+
"name": "default"
19+
}
20+
]
21+
}
22+
}

doc/api_samples/versions/v21-version-get-resp.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
}
2020
],
2121
"status": "CURRENT",
22-
"version": "2.73",
22+
"version": "2.74",
2323
"min_version": "2.1",
2424
"updated": "2013-07-23T11:33:21Z"
2525
}

doc/api_samples/versions/versions-get-resp.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
}
2323
],
2424
"status": "CURRENT",
25-
"version": "2.73",
25+
"version": "2.74",
2626
"min_version": "2.1",
2727
"updated": "2013-07-23T11:33:21Z"
2828
}

nova/api/openstack/api_version_request.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@
184184
``POST /servers/{server_id}/action`` where the action is rebuild.
185185
It also supports ``locked`` as a filter/sort parameter for
186186
``GET /servers/detail`` and ``GET /servers``.
187+
* 2.74 - Add support for specifying ``host`` and/or ``hypervisor_hostname``
188+
in request body to ``POST /servers``. Allow users to specify which
189+
host/node they want their servers to land on and still be
190+
validated by the scheduler.
187191
"""
188192

189193
# The minimum and maximum versions of the API supported
@@ -192,7 +196,7 @@
192196
# Note(cyeoh): This only applies for the v2.1 API once microversions
193197
# support is fully merged. It does not affect the V2 API.
194198
_MIN_API_VERSION = "2.1"
195-
_MAX_API_VERSION = "2.73"
199+
_MAX_API_VERSION = "2.74"
196200
DEFAULT_API_VERSION = _MIN_API_VERSION
197201

198202
# Almost all proxy APIs which are related to network, images and baremetal

nova/api/openstack/compute/rest_api_version_history.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,3 +940,19 @@ server and exposes this information via ``GET /servers/detail``,
940940
``POST /servers/{server_id}/action`` where the action is rebuild. It also
941941
supports ``locked`` as a filter/sort parameter for ``GET /servers/detail``
942942
and ``GET /servers``.
943+
944+
2.74
945+
----
946+
947+
API microversion 2.74 adds support for specifying optional ``host``
948+
and/or ``hypervisor_hostname`` parameters in the request body of
949+
``POST /servers``. These request a specific destination host/node
950+
to boot the requested server. These parameters are mutually exclusive
951+
with the special ``availability_zone`` format of ``zone:host:node``.
952+
Unlike ``zone:host:node``, the ``host`` and/or ``hypervisor_hostname``
953+
parameters still allow scheduler filters to be run. If the requested
954+
host/node is unavailable or otherwise unsuitable, earlier failure will
955+
be raised.
956+
There will be also a new policy named
957+
``compute:servers:create:requested_destination``. By default,
958+
it can be specified by administrators only.

nova/api/openstack/compute/schemas/servers.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,14 @@
356356
'properties']['volume_type'] = parameter_types.volume_type
357357

358358

359+
# Add host and hypervisor_hostname in server
360+
base_create_v274 = copy.deepcopy(base_create_v267)
361+
base_create_v274['properties']['server'][
362+
'properties']['host'] = parameter_types.hostname
363+
base_create_v274['properties']['server'][
364+
'properties']['hypervisor_hostname'] = parameter_types.hostname
365+
366+
359367
base_update = {
360368
'type': 'object',
361369
'properties': {

nova/api/openstack/compute/servers.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,35 @@ def _process_networks_for_create(
561561

562562
create_kwargs['requested_networks'] = requested_networks
563563

564+
@staticmethod
565+
def _process_hosts_for_create(
566+
context, target, server_dict, create_kwargs, host, node):
567+
"""Processes hosts request parameter for server create
568+
569+
:param context: The nova auth request context
570+
:param target: The target dict for ``context.can`` policy checks
571+
:param server_dict: The POST /servers request body "server" entry
572+
:param create_kwargs: dict that gets populated by this method and
573+
passed to nova.comptue.api.API.create()
574+
:param host: Forced host of availability_zone
575+
:param node: Forced node of availability_zone
576+
:raise: webob.exc.HTTPBadRequest if the request parameters are invalid
577+
:raise: nova.exception.Forbidden if a policy check fails
578+
"""
579+
requested_host = server_dict.get('host')
580+
requested_hypervisor_hostname = server_dict.get('hypervisor_hostname')
581+
if requested_host or requested_hypervisor_hostname:
582+
# If the policy check fails, this will raise Forbidden exception.
583+
context.can(server_policies.REQUESTED_DESTINATION, target=target)
584+
if host or node:
585+
msg = _("One mechanism with host and/or "
586+
"hypervisor_hostname and another mechanism "
587+
"with zone:host:node are mutually exclusive.")
588+
raise exc.HTTPBadRequest(explanation=msg)
589+
create_kwargs['requested_host'] = requested_host
590+
create_kwargs['requested_hypervisor_hostname'] = (
591+
requested_hypervisor_hostname)
592+
564593
@wsgi.response(202)
565594
@wsgi.expected_errors((400, 403, 409))
566595
@validation.schema(schema_servers.base_create_v20, '2.0', '2.0')
@@ -573,7 +602,8 @@ def _process_networks_for_create(
573602
@validation.schema(schema_servers.base_create_v252, '2.52', '2.56')
574603
@validation.schema(schema_servers.base_create_v257, '2.57', '2.62')
575604
@validation.schema(schema_servers.base_create_v263, '2.63', '2.66')
576-
@validation.schema(schema_servers.base_create_v267, '2.67')
605+
@validation.schema(schema_servers.base_create_v267, '2.67', '2.73')
606+
@validation.schema(schema_servers.base_create_v274, '2.74')
577607
def create(self, req, body):
578608
"""Creates a new server for a given user."""
579609
context = req.environ['nova.context']
@@ -653,6 +683,10 @@ def create(self, req, body):
653683
if host or node:
654684
context.can(server_policies.SERVERS % 'create:forced_host', {})
655685

686+
if api_version_request.is_supported(req, min_version='2.74'):
687+
self._process_hosts_for_create(context, target, server_dict,
688+
create_kwargs, host, node)
689+
656690
# NOTE(danms): Don't require an answer from all cells here, as
657691
# we assume that if a cell isn't reporting we won't schedule into
658692
# it anyway. A bit of a gamble, but a reasonable one.
@@ -750,7 +784,8 @@ def create(self, req, body):
750784
exception.UnableToAutoAllocateNetwork,
751785
exception.MultiattachNotSupportedOldMicroversion,
752786
exception.CertificateValidationFailed,
753-
exception.CreateWithPortResourceRequestOldVersion) as error:
787+
exception.CreateWithPortResourceRequestOldVersion,
788+
exception.ComputeHostNotFound) as error:
754789
raise exc.HTTPBadRequest(explanation=error.format_message())
755790
except INVALID_FLAVOR_IMAGE_EXCEPTIONS as error:
756791
raise exc.HTTPBadRequest(explanation=error.format_message())

nova/compute/api.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,19 @@ def _provision_instances(self, context, instance_type, min_count,
999999
block_device_mapping, shutdown_terminate,
10001000
instance_group, check_server_group_quota, filter_properties,
10011001
key_pair, tags, trusted_certs, supports_multiattach,
1002-
network_metadata=None):
1002+
network_metadata=None, requested_host=None,
1003+
requested_hypervisor_hostname=None):
1004+
# NOTE(boxiang): Check whether compute nodes exist by validating
1005+
# the host and/or the hypervisor_hostname. Pass the destination
1006+
# to the scheduler with host and/or hypervisor_hostname(node).
1007+
destination = None
1008+
if requested_host or requested_hypervisor_hostname:
1009+
self._validate_host_or_node(context, requested_host,
1010+
requested_hypervisor_hostname)
1011+
destination = objects.Destination()
1012+
if requested_host:
1013+
destination.host = requested_host
1014+
destination.node = requested_hypervisor_hostname
10031015
# Check quotas
10041016
num_instances = compute_utils.check_num_instances_quota(
10051017
context, instance_type, min_count, max_count)
@@ -1041,6 +1053,9 @@ def _provision_instances(self, context, instance_type, min_count,
10411053
if network_metadata:
10421054
req_spec.network_metadata = network_metadata
10431055

1056+
if destination:
1057+
req_spec.requested_destination = destination
1058+
10441059
# Create an instance object, but do not store in db yet.
10451060
instance = objects.Instance(context=context)
10461061
instance.uuid = instance_uuid
@@ -1263,7 +1278,8 @@ def _create_instance(self, context, instance_type,
12631278
reservation_id=None, legacy_bdm=True, shutdown_terminate=False,
12641279
check_server_group_quota=False, tags=None,
12651280
supports_multiattach=False, trusted_certs=None,
1266-
supports_port_resource_request=False):
1281+
supports_port_resource_request=False,
1282+
requested_host=None, requested_hypervisor_hostname=None):
12671283
"""Verify all the input parameters regardless of the provisioning
12681284
strategy being performed and schedule the instance(s) for
12691285
creation.
@@ -1339,7 +1355,8 @@ def _create_instance(self, context, instance_type,
13391355
boot_meta, security_groups, block_device_mapping,
13401356
shutdown_terminate, instance_group, check_server_group_quota,
13411357
filter_properties, key_pair, tags, trusted_certs,
1342-
supports_multiattach, network_metadata)
1358+
supports_multiattach, network_metadata,
1359+
requested_host, requested_hypervisor_hostname)
13431360

13441361
instances = []
13451362
request_specs = []
@@ -1806,7 +1823,8 @@ def create(self, context, instance_type,
18061823
legacy_bdm=True, shutdown_terminate=False,
18071824
check_server_group_quota=False, tags=None,
18081825
supports_multiattach=False, trusted_certs=None,
1809-
supports_port_resource_request=False):
1826+
supports_port_resource_request=False,
1827+
requested_host=None, requested_hypervisor_hostname=None):
18101828
"""Provision instances, sending instance information to the
18111829
scheduler. The scheduler will determine where the instance(s)
18121830
go and will handle creating the DB entries.
@@ -1849,7 +1867,9 @@ def create(self, context, instance_type,
18491867
check_server_group_quota=check_server_group_quota,
18501868
tags=tags, supports_multiattach=supports_multiattach,
18511869
trusted_certs=trusted_certs,
1852-
supports_port_resource_request=supports_port_resource_request)
1870+
supports_port_resource_request=supports_port_resource_request,
1871+
requested_host=requested_host,
1872+
requested_hypervisor_hostname=requested_hypervisor_hostname)
18531873

18541874
def _check_auto_disk_config(self, instance=None, image=None,
18551875
**extra_instance_updates):

0 commit comments

Comments
 (0)