Add host and hypervisor_hostname to create servers
Adds the --host and --hypervisor-hostname options to the nova boot command and related python API bindings. Depends-On: https://review.opendev.org/#/c/645520/ Change-Id: If16d00b75f4d5f2b96aa6e3f32a973108049d928 Blueprint: add-host-and-hypervisor-hostname-flag-to-create-server
This commit is contained in:
parent
4bfcc1a9fa
commit
41c25881e6
@ -952,6 +952,8 @@ nova boot
|
|||||||
[--description <description>] [--tags <tags>]
|
[--description <description>] [--tags <tags>]
|
||||||
[--return-reservation-id]
|
[--return-reservation-id]
|
||||||
[--trusted-image-certificate-id <trusted-image-certificate-id>]
|
[--trusted-image-certificate-id <trusted-image-certificate-id>]
|
||||||
|
[--host <host>]
|
||||||
|
[--hypervisor-hostname <hypervisor-hostname>]
|
||||||
<name>
|
<name>
|
||||||
|
|
||||||
Boot a new server.
|
Boot a new server.
|
||||||
@ -1117,6 +1119,14 @@ quality of service support, microversion ``2.72`` is required.
|
|||||||
May be specified multiple times to pass multiple trusted image
|
May be specified multiple times to pass multiple trusted image
|
||||||
certificate IDs. (Supported by API versions '2.63' - '2.latest')
|
certificate IDs. (Supported by API versions '2.63' - '2.latest')
|
||||||
|
|
||||||
|
``--host <host>``
|
||||||
|
Requested host to create servers. Admin only by default.
|
||||||
|
(Supported by API versions '2.74' - '2.latest')
|
||||||
|
|
||||||
|
``--hypervisor-hostname <hypervisor-hostname>``
|
||||||
|
Requested hypervisor hostname to create servers. Admin only by default.
|
||||||
|
(Supported by API versions '2.74' - '2.latest')
|
||||||
|
|
||||||
.. _nova_cell-capacities:
|
.. _nova_cell-capacities:
|
||||||
|
|
||||||
nova cell-capacities
|
nova cell-capacities
|
||||||
|
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
|||||||
# when client supported the max version, and bumped sequentially, otherwise
|
# when client supported the max version, and bumped sequentially, otherwise
|
||||||
# the client may break due to server side new version may include some
|
# the client may break due to server side new version may include some
|
||||||
# backward incompatible change.
|
# backward incompatible change.
|
||||||
API_MAX_VERSION = api_versions.APIVersion("2.73")
|
API_MAX_VERSION = api_versions.APIVersion("2.74")
|
||||||
|
@ -1743,3 +1743,99 @@ class ServersV273Test(ServersV268Test):
|
|||||||
self.assert_called('GET', '/servers/detail?locked=False')
|
self.assert_called('GET', '/servers/detail?locked=False')
|
||||||
for s in sl:
|
for s in sl:
|
||||||
self.assertIsInstance(s, servers.Server)
|
self.assertIsInstance(s, servers.Server)
|
||||||
|
|
||||||
|
|
||||||
|
class ServersV274Test(ServersV273Test):
|
||||||
|
|
||||||
|
api_version = "2.74"
|
||||||
|
|
||||||
|
def test_create_server_with_host(self):
|
||||||
|
self.cs.servers.create(
|
||||||
|
name="My server",
|
||||||
|
image=1,
|
||||||
|
flavor=1,
|
||||||
|
nics="auto",
|
||||||
|
host="new-host"
|
||||||
|
)
|
||||||
|
self.assert_called('POST', '/servers',
|
||||||
|
{'server': {
|
||||||
|
'flavorRef': '1',
|
||||||
|
'imageRef': '1',
|
||||||
|
'max_count': 1,
|
||||||
|
'min_count': 1,
|
||||||
|
'name': 'My server',
|
||||||
|
'networks': 'auto',
|
||||||
|
'host': 'new-host'
|
||||||
|
}}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_server_with_hypervisor_hostname(self):
|
||||||
|
self.cs.servers.create(
|
||||||
|
name="My server",
|
||||||
|
image=1,
|
||||||
|
flavor=1,
|
||||||
|
nics="auto",
|
||||||
|
hypervisor_hostname="new-host"
|
||||||
|
)
|
||||||
|
self.assert_called('POST', '/servers',
|
||||||
|
{'server': {
|
||||||
|
'flavorRef': '1',
|
||||||
|
'imageRef': '1',
|
||||||
|
'max_count': 1,
|
||||||
|
'min_count': 1,
|
||||||
|
'name': 'My server',
|
||||||
|
'networks': 'auto',
|
||||||
|
'hypervisor_hostname': 'new-host'
|
||||||
|
}}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_server_with_host_and_hypervisor_hostname(self):
|
||||||
|
self.cs.servers.create(
|
||||||
|
name="My server",
|
||||||
|
image=1,
|
||||||
|
flavor=1,
|
||||||
|
nics="auto",
|
||||||
|
host="new-host",
|
||||||
|
hypervisor_hostname="new-host"
|
||||||
|
)
|
||||||
|
self.assert_called('POST', '/servers',
|
||||||
|
{'server': {
|
||||||
|
'flavorRef': '1',
|
||||||
|
'imageRef': '1',
|
||||||
|
'max_count': 1,
|
||||||
|
'min_count': 1,
|
||||||
|
'name': 'My server',
|
||||||
|
'networks': 'auto',
|
||||||
|
'host': 'new-host',
|
||||||
|
'hypervisor_hostname': 'new-host'
|
||||||
|
}}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_create_server_with_host_pre_274_fails(self):
|
||||||
|
self.cs.api_version = api_versions.APIVersion('2.73')
|
||||||
|
ex = self.assertRaises(exceptions.UnsupportedAttribute,
|
||||||
|
self.cs.servers.create,
|
||||||
|
name="My server", image=1, flavor=1,
|
||||||
|
nics='auto', host="new-host")
|
||||||
|
self.assertIn("'host' argument is only allowed since microversion "
|
||||||
|
"2.74", six.text_type(ex))
|
||||||
|
|
||||||
|
def test_create_server_with_hypervisor_hostname_pre_274_fails(self):
|
||||||
|
self.cs.api_version = api_versions.APIVersion('2.73')
|
||||||
|
ex = self.assertRaises(exceptions.UnsupportedAttribute,
|
||||||
|
self.cs.servers.create,
|
||||||
|
name="My server", image=1, flavor=1,
|
||||||
|
nics='auto', hypervisor_hostname="new-host")
|
||||||
|
self.assertIn("'hypervisor_hostname' argument is only allowed since "
|
||||||
|
"microversion 2.74", six.text_type(ex))
|
||||||
|
|
||||||
|
def test_create_server_with_host_and_hypervisor_hostname_pre_274_fails(
|
||||||
|
self):
|
||||||
|
self.cs.api_version = api_versions.APIVersion('2.73')
|
||||||
|
ex = self.assertRaises(exceptions.UnsupportedAttribute,
|
||||||
|
self.cs.servers.create,
|
||||||
|
name="My server", image=1, flavor=1,
|
||||||
|
nics='auto', host="new-host",
|
||||||
|
hypervisor_hostname="new-host")
|
||||||
|
self.assertIn("'host' argument is only allowed since microversion "
|
||||||
|
"2.74", six.text_type(ex))
|
||||||
|
@ -1374,6 +1374,83 @@ class ShellTest(utils.TestCase):
|
|||||||
self.assertIn('Instance %s could not be found.' % FAKE_UUID_1,
|
self.assertIn('Instance %s could not be found.' % FAKE_UUID_1,
|
||||||
six.text_type(ex))
|
six.text_type(ex))
|
||||||
|
|
||||||
|
def test_boot_with_host_v274(self):
|
||||||
|
self.run_command('boot --flavor 1 --image %s '
|
||||||
|
'--host new-host --nic auto '
|
||||||
|
'some-server' % FAKE_UUID_1,
|
||||||
|
api_version='2.74')
|
||||||
|
self.assert_called_anytime(
|
||||||
|
'POST', '/servers',
|
||||||
|
{'server': {
|
||||||
|
'flavorRef': '1',
|
||||||
|
'name': 'some-server',
|
||||||
|
'imageRef': FAKE_UUID_1,
|
||||||
|
'min_count': 1,
|
||||||
|
'max_count': 1,
|
||||||
|
'networks': 'auto',
|
||||||
|
'host': 'new-host',
|
||||||
|
}},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_boot_with_hypervisor_hostname_v274(self):
|
||||||
|
self.run_command('boot --flavor 1 --image %s --nic auto '
|
||||||
|
'--hypervisor-hostname new-host '
|
||||||
|
'some-server' % FAKE_UUID_1,
|
||||||
|
api_version='2.74')
|
||||||
|
self.assert_called_anytime(
|
||||||
|
'POST', '/servers',
|
||||||
|
{'server': {
|
||||||
|
'flavorRef': '1',
|
||||||
|
'name': 'some-server',
|
||||||
|
'imageRef': FAKE_UUID_1,
|
||||||
|
'min_count': 1,
|
||||||
|
'max_count': 1,
|
||||||
|
'networks': 'auto',
|
||||||
|
'hypervisor_hostname': 'new-host',
|
||||||
|
}},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_boot_with_host_and_hypervisor_hostname_v274(self):
|
||||||
|
self.run_command('boot --flavor 1 --image %s '
|
||||||
|
'--host new-host --nic auto '
|
||||||
|
'--hypervisor-hostname new-host '
|
||||||
|
'some-server' % FAKE_UUID_1,
|
||||||
|
api_version='2.74')
|
||||||
|
self.assert_called_anytime(
|
||||||
|
'POST', '/servers',
|
||||||
|
{'server': {
|
||||||
|
'flavorRef': '1',
|
||||||
|
'name': 'some-server',
|
||||||
|
'imageRef': FAKE_UUID_1,
|
||||||
|
'min_count': 1,
|
||||||
|
'max_count': 1,
|
||||||
|
'networks': 'auto',
|
||||||
|
'host': 'new-host',
|
||||||
|
'hypervisor_hostname': 'new-host',
|
||||||
|
}},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_boot_with_host_pre_v274(self):
|
||||||
|
cmd = ('boot --flavor 1 --image %s --nic auto '
|
||||||
|
'--host new-host some-server'
|
||||||
|
% FAKE_UUID_1)
|
||||||
|
self.assertRaises(SystemExit, self.run_command,
|
||||||
|
cmd, api_version='2.73')
|
||||||
|
|
||||||
|
def test_boot_with_hypervisor_hostname_pre_v274(self):
|
||||||
|
cmd = ('boot --flavor 1 --image %s --nic auto '
|
||||||
|
'--hypervisor-hostname new-host some-server'
|
||||||
|
% FAKE_UUID_1)
|
||||||
|
self.assertRaises(SystemExit, self.run_command,
|
||||||
|
cmd, api_version='2.73')
|
||||||
|
|
||||||
|
def test_boot_with_host_and_hypervisor_hostname_pre_v274(self):
|
||||||
|
cmd = ('boot --flavor 1 --image %s --nic auto '
|
||||||
|
'--host new-host --hypervisor-hostname new-host some-server'
|
||||||
|
% FAKE_UUID_1)
|
||||||
|
self.assertRaises(SystemExit, self.run_command,
|
||||||
|
cmd, api_version='2.73')
|
||||||
|
|
||||||
def test_flavor_list(self):
|
def test_flavor_list(self):
|
||||||
out, _ = self.run_command('flavor-list')
|
out, _ = self.run_command('flavor-list')
|
||||||
self.assert_called_anytime('GET', '/flavors/detail')
|
self.assert_called_anytime('GET', '/flavors/detail')
|
||||||
@ -4185,6 +4262,7 @@ class ShellTest(utils.TestCase):
|
|||||||
70, # There are no version-wrapped shell method changes for this.
|
70, # There are no version-wrapped shell method changes for this.
|
||||||
71, # There are no version-wrapped shell method changes for this.
|
71, # There are no version-wrapped shell method changes for this.
|
||||||
72, # There are no version-wrapped shell method changes for this.
|
72, # There are no version-wrapped shell method changes for this.
|
||||||
|
74, # There are no version-wrapped shell method changes for this.
|
||||||
])
|
])
|
||||||
versions_supported = set(range(0,
|
versions_supported = set(range(0,
|
||||||
novaclient.API_MAX_VERSION.ver_minor + 1))
|
novaclient.API_MAX_VERSION.ver_minor + 1))
|
||||||
|
@ -694,7 +694,8 @@ class ServerManager(base.BootingManagerWithFind):
|
|||||||
block_device_mapping_v2=None, nics=None, scheduler_hints=None,
|
block_device_mapping_v2=None, nics=None, scheduler_hints=None,
|
||||||
config_drive=None, admin_pass=None, disk_config=None,
|
config_drive=None, admin_pass=None, disk_config=None,
|
||||||
access_ip_v4=None, access_ip_v6=None, description=None,
|
access_ip_v4=None, access_ip_v6=None, description=None,
|
||||||
tags=None, trusted_image_certificates=None, **kwargs):
|
tags=None, trusted_image_certificates=None,
|
||||||
|
host=None, hypervisor_hostname=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Create (boot) a new server.
|
Create (boot) a new server.
|
||||||
"""
|
"""
|
||||||
@ -817,6 +818,12 @@ class ServerManager(base.BootingManagerWithFind):
|
|||||||
body['server']['trusted_image_certificates'] = (
|
body['server']['trusted_image_certificates'] = (
|
||||||
trusted_image_certificates)
|
trusted_image_certificates)
|
||||||
|
|
||||||
|
if host:
|
||||||
|
body['server']['host'] = host
|
||||||
|
|
||||||
|
if hypervisor_hostname:
|
||||||
|
body['server']['hypervisor_hostname'] = hypervisor_hostname
|
||||||
|
|
||||||
return self._create('/servers', body, response_key,
|
return self._create('/servers', body, response_key,
|
||||||
return_raw=return_raw, **kwargs)
|
return_raw=return_raw, **kwargs)
|
||||||
|
|
||||||
@ -1267,7 +1274,9 @@ class ServerManager(base.BootingManagerWithFind):
|
|||||||
nics=None, scheduler_hints=None,
|
nics=None, scheduler_hints=None,
|
||||||
config_drive=None, disk_config=None, admin_pass=None,
|
config_drive=None, disk_config=None, admin_pass=None,
|
||||||
access_ip_v4=None, access_ip_v6=None,
|
access_ip_v4=None, access_ip_v6=None,
|
||||||
trusted_image_certificates=None, **kwargs):
|
trusted_image_certificates=None,
|
||||||
|
host=None, hypervisor_hostname=None,
|
||||||
|
**kwargs):
|
||||||
# TODO(anthony): indicate in doc string if param is an extension
|
# TODO(anthony): indicate in doc string if param is an extension
|
||||||
# and/or optional
|
# and/or optional
|
||||||
"""
|
"""
|
||||||
@ -1334,6 +1343,10 @@ class ServerManager(base.BootingManagerWithFind):
|
|||||||
server as tags (allowed since microversion 2.52)
|
server as tags (allowed since microversion 2.52)
|
||||||
:param trusted_image_certificates: A list of trusted certificate IDs
|
:param trusted_image_certificates: A list of trusted certificate IDs
|
||||||
(allowed since microversion 2.63)
|
(allowed since microversion 2.63)
|
||||||
|
:param host: requested host to create servers
|
||||||
|
(allowed since microversion 2.74)
|
||||||
|
:param hypervisor_hostname: requested hypervisor hostname to create
|
||||||
|
servers (allowed since microversion 2.74)
|
||||||
"""
|
"""
|
||||||
if not min_count:
|
if not min_count:
|
||||||
min_count = 1
|
min_count = 1
|
||||||
@ -1388,6 +1401,15 @@ class ServerManager(base.BootingManagerWithFind):
|
|||||||
"Block device volume_type is not supported before "
|
"Block device volume_type is not supported before "
|
||||||
"microversion 2.67")
|
"microversion 2.67")
|
||||||
|
|
||||||
|
host_microversion = api_versions.APIVersion("2.74")
|
||||||
|
if host and self.api_version < host_microversion:
|
||||||
|
raise exceptions.UnsupportedAttribute("host", "2.74")
|
||||||
|
hypervisor_hostname_microversion = api_versions.APIVersion("2.74")
|
||||||
|
if (hypervisor_hostname and
|
||||||
|
self.api_version < hypervisor_hostname_microversion):
|
||||||
|
raise exceptions.UnsupportedAttribute(
|
||||||
|
"hypervisor_hostname", "2.74")
|
||||||
|
|
||||||
boot_kwargs = dict(
|
boot_kwargs = dict(
|
||||||
meta=meta, files=files, userdata=userdata,
|
meta=meta, files=files, userdata=userdata,
|
||||||
reservation_id=reservation_id, min_count=min_count,
|
reservation_id=reservation_id, min_count=min_count,
|
||||||
@ -1396,7 +1418,9 @@ class ServerManager(base.BootingManagerWithFind):
|
|||||||
scheduler_hints=scheduler_hints, config_drive=config_drive,
|
scheduler_hints=scheduler_hints, config_drive=config_drive,
|
||||||
disk_config=disk_config, admin_pass=admin_pass,
|
disk_config=disk_config, admin_pass=admin_pass,
|
||||||
access_ip_v4=access_ip_v4, access_ip_v6=access_ip_v6,
|
access_ip_v4=access_ip_v4, access_ip_v6=access_ip_v6,
|
||||||
trusted_image_certificates=trusted_image_certificates, **kwargs)
|
trusted_image_certificates=trusted_image_certificates,
|
||||||
|
host=host, hypervisor_hostname=hypervisor_hostname,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
if block_device_mapping:
|
if block_device_mapping:
|
||||||
boot_kwargs['block_device_mapping'] = block_device_mapping
|
boot_kwargs['block_device_mapping'] = block_device_mapping
|
||||||
|
@ -517,6 +517,12 @@ def _boot(cs, args):
|
|||||||
if 'tags' in args and args.tags:
|
if 'tags' in args and args.tags:
|
||||||
boot_kwargs["tags"] = args.tags.split(',')
|
boot_kwargs["tags"] = args.tags.split(',')
|
||||||
|
|
||||||
|
if 'host' in args and args.host:
|
||||||
|
boot_kwargs["host"] = args.host
|
||||||
|
|
||||||
|
if 'hypervisor_hostname' in args and args.hypervisor_hostname:
|
||||||
|
boot_kwargs["hypervisor_hostname"] = args.hypervisor_hostname
|
||||||
|
|
||||||
if include_files:
|
if include_files:
|
||||||
boot_kwargs['files'] = files
|
boot_kwargs['files'] = files
|
||||||
|
|
||||||
@ -942,6 +948,21 @@ def _boot(cs, args):
|
|||||||
'May be specified multiple times to pass multiple trusted image '
|
'May be specified multiple times to pass multiple trusted image '
|
||||||
'certificate IDs.'),
|
'certificate IDs.'),
|
||||||
start_version="2.63")
|
start_version="2.63")
|
||||||
|
@utils.arg(
|
||||||
|
'--host',
|
||||||
|
metavar='<host>',
|
||||||
|
dest='host',
|
||||||
|
default=None,
|
||||||
|
help=_('Requested host to create servers. Admin only by default.'),
|
||||||
|
start_version="2.74")
|
||||||
|
@utils.arg(
|
||||||
|
'--hypervisor-hostname',
|
||||||
|
metavar='<hypervisor-hostname>',
|
||||||
|
dest='hypervisor_hostname',
|
||||||
|
default=None,
|
||||||
|
help=_('Requested hypervisor hostname to create servers. Admin only by '
|
||||||
|
'default.'),
|
||||||
|
start_version="2.74")
|
||||||
def do_boot(cs, args):
|
def do_boot(cs, args):
|
||||||
"""Boot a new server."""
|
"""Boot a new server."""
|
||||||
boot_args, boot_kwargs = _boot(cs, args)
|
boot_args, boot_kwargs = _boot(cs, args)
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Support is added for the `2.74 microversion`_ which allows specifying the
|
||||||
|
``--host`` and ``--hypervisor-hostname`` options on the ``nova boot``
|
||||||
|
command. The ``novaclient.v2.servers.ServerManager.create()`` method now
|
||||||
|
also supports ``host`` and ``hypervisor_hostname`` parameters.
|
||||||
|
|
||||||
|
.. _2.74 microversion: https://docs.openstack.org/nova/latest/reference/api-microversion-history.html#id66
|
Loading…
Reference in New Issue
Block a user