Add support for v2.37 and auto-allocated networking
This adds support for the v2.37 microversion. The networks part of the server create request is required in this microversion so if nothing is specified for --nic arguments on the command line we default to 'auto' for backward compatibility in the CLI. Part of blueprint get-me-a-network Change-Id: I6636ddcd3be7bf393d2d69cc6c1ba5c7d65ff674
This commit is contained in:
parent
84d86d3f3c
commit
030ce53d4e
@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
|
||||
# when client supported the max version, and bumped sequentially, otherwise
|
||||
# the client may break due to server side new version may include some
|
||||
# backward incompatible change.
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.36")
|
||||
API_MAX_VERSION = api_versions.APIVersion("2.37")
|
||||
|
@ -172,3 +172,59 @@ class TestServersTagsV226(base.ClientTestBase):
|
||||
uuid = self._boot_server_with_tags()
|
||||
self.nova("server-tag-delete-all %s" % uuid)
|
||||
self.assertEqual([], self.client.servers.tag_list(uuid))
|
||||
|
||||
|
||||
class TestServersAutoAllocateNetworkCLI(base.ClientTestBase):
|
||||
|
||||
COMPUTE_API_VERSION = '2.37'
|
||||
|
||||
def _find_network_in_table(self, table):
|
||||
# Example:
|
||||
# +-----------------+-----------------------------------+
|
||||
# | Property | Value |
|
||||
# +-----------------+-----------------------------------+
|
||||
# | private network | 192.168.154.128 |
|
||||
# +-----------------+-----------------------------------+
|
||||
for line in table.split('\n'):
|
||||
if '|' in line:
|
||||
l_property, l_value = line.split('|')[1:3]
|
||||
if ' network' in l_property.strip():
|
||||
return ' '.join(l_property.strip().split()[:-1])
|
||||
|
||||
def test_boot_server_with_auto_network(self):
|
||||
"""Tests that the CLI defaults to 'auto' when --nic isn't specified.
|
||||
"""
|
||||
server_info = self.nova('boot', params=(
|
||||
'%(name)s --flavor %(flavor)s --poll '
|
||||
'--image %(image)s ' % {'name': self.name_generate('server'),
|
||||
'flavor': self.flavor.id,
|
||||
'image': self.image.id}))
|
||||
server_id = self._get_value_from_the_table(server_info, 'id')
|
||||
self.addCleanup(self.wait_for_resource_delete,
|
||||
server_id, self.client.servers)
|
||||
self.addCleanup(self.client.servers.delete, server_id)
|
||||
# get the server details to verify there is a network, we don't care
|
||||
# what the network name is, we just want to see an entry show up
|
||||
server_info = self.nova('show', params=server_id)
|
||||
network = self._find_network_in_table(server_info)
|
||||
self.assertIsNotNone(
|
||||
network, 'Auto-allocated network not found: %s' % server_info)
|
||||
|
||||
def test_boot_server_with_no_network(self):
|
||||
"""Tests that '--nic none' is honored.
|
||||
"""
|
||||
server_info = self.nova('boot', params=(
|
||||
'%(name)s --flavor %(flavor)s --poll '
|
||||
'--image %(image)s --nic none' %
|
||||
{'name': self.name_generate('server'),
|
||||
'flavor': self.flavor.id,
|
||||
'image': self.image.id}))
|
||||
server_id = self._get_value_from_the_table(server_info, 'id')
|
||||
self.addCleanup(self.wait_for_resource_delete,
|
||||
server_id, self.client.servers)
|
||||
self.addCleanup(self.client.servers.delete, server_id)
|
||||
# get the server details to verify there is not a network
|
||||
server_info = self.nova('show', params=server_id)
|
||||
network = self._find_network_in_table(server_info)
|
||||
self.assertIsNone(
|
||||
network, 'Unexpected network allocation: %s' % server_info)
|
||||
|
@ -42,6 +42,11 @@ class ServersTest(utils.FixturedTestCase):
|
||||
if self.api_version:
|
||||
self.cs.api_version = api_versions.APIVersion(self.api_version)
|
||||
|
||||
def _get_server_create_default_nics(self):
|
||||
"""Callback for default nics kwarg when creating a server.
|
||||
"""
|
||||
return None
|
||||
|
||||
def test_list_servers(self):
|
||||
sl = self.cs.servers.list()
|
||||
self.assert_request_id(sl, fakes.FAKE_REQUEST_ID_LIST)
|
||||
@ -132,7 +137,8 @@ class ServersTest(utils.FixturedTestCase):
|
||||
files={
|
||||
'/etc/passwd': 'some data', # a file
|
||||
'/tmp/foo.txt': six.StringIO('data'), # a stream
|
||||
}
|
||||
},
|
||||
nics=self._get_server_create_default_nics()
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -191,7 +197,8 @@ class ServersTest(utils.FixturedTestCase):
|
||||
meta={'foo': 'bar'},
|
||||
userdata="hello moto",
|
||||
key_name="fakekey",
|
||||
block_device_mapping_v2=bdm
|
||||
block_device_mapping_v2=bdm,
|
||||
nics=self._get_server_create_default_nics()
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/os-volumes_boot')
|
||||
@ -239,7 +246,8 @@ class ServersTest(utils.FixturedTestCase):
|
||||
userdata="hello moto",
|
||||
key_name="fakekey",
|
||||
access_ip_v6=access_ip_v6,
|
||||
access_ip_v4=access_ip_v4
|
||||
access_ip_v4=access_ip_v4,
|
||||
nics=self._get_server_create_default_nics()
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -256,6 +264,7 @@ class ServersTest(utils.FixturedTestCase):
|
||||
'/etc/passwd': 'some data', # a file
|
||||
'/tmp/foo.txt': six.StringIO('data'), # a stream
|
||||
},
|
||||
nics=self._get_server_create_default_nics(),
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -273,6 +282,7 @@ class ServersTest(utils.FixturedTestCase):
|
||||
'/etc/passwd': 'some data', # a file
|
||||
'/tmp/foo.txt': six.StringIO('data'), # a stream
|
||||
},
|
||||
nics=self._get_server_create_default_nics(),
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -290,6 +300,7 @@ class ServersTest(utils.FixturedTestCase):
|
||||
'/etc/passwd': 'some data', # a file
|
||||
'/tmp/foo.txt': six.StringIO('data'), # a stream
|
||||
},
|
||||
nics=self._get_server_create_default_nics(),
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -303,7 +314,8 @@ class ServersTest(utils.FixturedTestCase):
|
||||
image=1,
|
||||
flavor=1,
|
||||
admin_pass=test_password,
|
||||
key_name=test_key
|
||||
key_name=test_key,
|
||||
nics=self._get_server_create_default_nics()
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -328,6 +340,7 @@ class ServersTest(utils.FixturedTestCase):
|
||||
'/etc/passwd': 'some data', # a file
|
||||
'/tmp/foo.txt': six.StringIO('data'), # a stream
|
||||
},
|
||||
nics=self._get_server_create_default_nics(),
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -343,7 +356,8 @@ class ServersTest(utils.FixturedTestCase):
|
||||
name="My server",
|
||||
image=1,
|
||||
flavor=1,
|
||||
disk_config=disk_config
|
||||
disk_config=disk_config,
|
||||
nics=self._get_server_create_default_nics(),
|
||||
)
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
@ -976,6 +990,16 @@ class ServersTest(utils.FixturedTestCase):
|
||||
key_name="fakekey"
|
||||
)
|
||||
|
||||
def test_create_server_with_nics_auto(self):
|
||||
"""Negative test for specifying nics='auto' before 2.37
|
||||
"""
|
||||
self.assertRaises(ValueError,
|
||||
self.cs.servers.create,
|
||||
name='test',
|
||||
image='d9d8d53c-4b4a-4144-a5e5-b30d9f1fe46a',
|
||||
flavor='1',
|
||||
nics='auto')
|
||||
|
||||
|
||||
class ServersV26Test(ServersTest):
|
||||
|
||||
@ -1074,7 +1098,8 @@ class ServersV219Test(ServersV217Test):
|
||||
flavor=1,
|
||||
meta={'foo': 'bar'},
|
||||
userdata="hello moto",
|
||||
key_name="fakekey"
|
||||
key_name="fakekey",
|
||||
nics=self._get_server_create_default_nics()
|
||||
)
|
||||
self.assert_called('POST', '/servers')
|
||||
|
||||
@ -1260,3 +1285,39 @@ class ServersV232Test(ServersV226Test):
|
||||
image=1, flavor=1, meta={'foo': 'bar'},
|
||||
userdata="hello moto", key_name="fakekey",
|
||||
block_device_mapping_v2=bdm)
|
||||
|
||||
|
||||
class ServersV2_37Test(ServersV226Test):
|
||||
|
||||
api_version = "2.37"
|
||||
|
||||
def _get_server_create_default_nics(self):
|
||||
return 'auto'
|
||||
|
||||
def test_create_server_no_nics(self):
|
||||
"""Tests that nics are required in microversion 2.37+
|
||||
"""
|
||||
self.assertRaises(ValueError, self.cs.servers.create,
|
||||
name='test',
|
||||
image='d9d8d53c-4b4a-4144-a5e5-b30d9f1fe46a',
|
||||
flavor='1')
|
||||
|
||||
def test_create_server_with_nics_auto(self):
|
||||
s = self.cs.servers.create(
|
||||
name='test', image='d9d8d53c-4b4a-4144-a5e5-b30d9f1fe46a',
|
||||
flavor='1', nics=self._get_server_create_default_nics())
|
||||
self.assert_request_id(s, fakes.FAKE_REQUEST_ID_LIST)
|
||||
self.assert_called('POST', '/servers')
|
||||
self.assertIsInstance(s, servers.Server)
|
||||
|
||||
def test_add_floating_ip(self):
|
||||
# self.cs.floating_ips.list() is not available after 2.35
|
||||
pass
|
||||
|
||||
def test_add_floating_ip_to_fixed(self):
|
||||
# self.cs.floating_ips.list() is not available after 2.35
|
||||
pass
|
||||
|
||||
def test_remove_floating_ip(self):
|
||||
# self.cs.floating_ips.list() is not available after 2.35
|
||||
pass
|
||||
|
@ -606,6 +606,64 @@ class ShellTest(utils.TestCase):
|
||||
cmd, api_version='2.32')
|
||||
self.assertIn('tag=tag', six.text_type(ex))
|
||||
|
||||
def test_boot_invalid_nics_v2_36_auto(self):
|
||||
"""This is a negative test to make sure we fail with the correct
|
||||
message. --nic auto isn't allowed before 2.37.
|
||||
"""
|
||||
cmd = ('boot --image %s --flavor 1 --nic auto test' % FAKE_UUID_1)
|
||||
ex = self.assertRaises(exceptions.CommandError, self.run_command,
|
||||
cmd, api_version='2.36')
|
||||
self.assertNotIn('auto,none', six.text_type(ex))
|
||||
|
||||
def test_boot_invalid_nics_v2_37(self):
|
||||
"""This is a negative test to make sure we fail with the correct
|
||||
message.
|
||||
"""
|
||||
cmd = ('boot --image %s --flavor 1 '
|
||||
'--nic net-id=1 --nic auto some-server' % FAKE_UUID_1)
|
||||
ex = self.assertRaises(exceptions.CommandError, self.run_command,
|
||||
cmd, api_version='2.37')
|
||||
self.assertIn('auto,none', six.text_type(ex))
|
||||
|
||||
def test_boot_nics_auto_allocate_default(self):
|
||||
"""Tests that if microversion>=2.37 is specified and no --nics are
|
||||
specified that a single --nic with net-id=auto is used.
|
||||
"""
|
||||
cmd = 'boot --image %s --flavor 1 some-server' % FAKE_UUID_1
|
||||
self.run_command(cmd, api_version='2.37')
|
||||
self.assert_called_anytime(
|
||||
'POST', '/servers',
|
||||
{
|
||||
'server': {
|
||||
'flavorRef': '1',
|
||||
'name': 'some-server',
|
||||
'imageRef': FAKE_UUID_1,
|
||||
'min_count': 1,
|
||||
'max_count': 1,
|
||||
'networks': 'auto',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def test_boot_nics_auto_allocate_none(self):
|
||||
"""Tests specifying '--nic none' with microversion 2.37
|
||||
"""
|
||||
cmd = 'boot --image %s --flavor 1 --nic none some-server' % FAKE_UUID_1
|
||||
self.run_command(cmd, api_version='2.37')
|
||||
self.assert_called_anytime(
|
||||
'POST', '/servers',
|
||||
{
|
||||
'server': {
|
||||
'flavorRef': '1',
|
||||
'name': 'some-server',
|
||||
'imageRef': FAKE_UUID_1,
|
||||
'min_count': 1,
|
||||
'max_count': 1,
|
||||
'networks': 'none',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
def test_boot_nics_ipv6(self):
|
||||
cmd = ('boot --image %s --flavor 1 '
|
||||
'--nic net-id=a=c,v6-fixed-ip=2001:db9:0:1::10 some-server' %
|
||||
@ -3062,6 +3120,7 @@ class ShellTest(utils.TestCase):
|
||||
32, # doesn't require separate version-wrapped methods in
|
||||
# novaclient
|
||||
34, # doesn't require any changes in novaclient
|
||||
37, # There are no versioned wrapped shell method changes for this
|
||||
])
|
||||
versions_supported = set(range(0,
|
||||
novaclient.API_MAX_VERSION.ver_minor + 1))
|
||||
|
@ -709,27 +709,32 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
body['server']['block_device_mapping_v2'] = block_device_mapping_v2
|
||||
|
||||
if nics is not None:
|
||||
# NOTE(tr3buchet): nics can be an empty list
|
||||
all_net_data = []
|
||||
for nic_info in nics:
|
||||
net_data = {}
|
||||
# if value is empty string, do not send value in body
|
||||
if nic_info.get('net-id'):
|
||||
net_data['uuid'] = nic_info['net-id']
|
||||
if (nic_info.get('v4-fixed-ip') and
|
||||
nic_info.get('v6-fixed-ip')):
|
||||
raise base.exceptions.CommandError(_(
|
||||
"Only one of 'v4-fixed-ip' and 'v6-fixed-ip' may be"
|
||||
" provided."))
|
||||
elif nic_info.get('v4-fixed-ip'):
|
||||
net_data['fixed_ip'] = nic_info['v4-fixed-ip']
|
||||
elif nic_info.get('v6-fixed-ip'):
|
||||
net_data['fixed_ip'] = nic_info['v6-fixed-ip']
|
||||
if nic_info.get('port-id'):
|
||||
net_data['port'] = nic_info['port-id']
|
||||
if nic_info.get('tag'):
|
||||
net_data['tag'] = nic_info['tag']
|
||||
all_net_data.append(net_data)
|
||||
# With microversion 2.37+ nics can be an enum of 'auto' or 'none'
|
||||
# or a list of dicts.
|
||||
if isinstance(nics, six.string_types):
|
||||
all_net_data = nics
|
||||
else:
|
||||
# NOTE(tr3buchet): nics can be an empty list
|
||||
all_net_data = []
|
||||
for nic_info in nics:
|
||||
net_data = {}
|
||||
# if value is empty string, do not send value in body
|
||||
if nic_info.get('net-id'):
|
||||
net_data['uuid'] = nic_info['net-id']
|
||||
if (nic_info.get('v4-fixed-ip') and
|
||||
nic_info.get('v6-fixed-ip')):
|
||||
raise base.exceptions.CommandError(_(
|
||||
"Only one of 'v4-fixed-ip' and 'v6-fixed-ip' "
|
||||
"may be provided."))
|
||||
elif nic_info.get('v4-fixed-ip'):
|
||||
net_data['fixed_ip'] = nic_info['v4-fixed-ip']
|
||||
elif nic_info.get('v6-fixed-ip'):
|
||||
net_data['fixed_ip'] = nic_info['v6-fixed-ip']
|
||||
if nic_info.get('port-id'):
|
||||
net_data['port'] = nic_info['port-id']
|
||||
if nic_info.get('tag'):
|
||||
net_data['tag'] = nic_info['tag']
|
||||
all_net_data.append(net_data)
|
||||
body['server']['networks'] = all_net_data
|
||||
|
||||
if disk_config is not None:
|
||||
@ -1219,6 +1224,14 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
base.getid(server))
|
||||
return base.TupleWithMeta((resp, body), resp)
|
||||
|
||||
def _validate_create_nics(self, nics):
|
||||
# nics are required with microversion 2.37+ and can be a string or list
|
||||
if self.api_version > api_versions.APIVersion('2.36'):
|
||||
if not nics:
|
||||
raise ValueError('nics are required after microversion 2.36')
|
||||
elif nics and not isinstance(nics, list):
|
||||
raise ValueError('nics must be a list')
|
||||
|
||||
def create(self, name, image, flavor, meta=None, files=None,
|
||||
reservation_id=None, min_count=None,
|
||||
max_count=None, security_groups=None, userdata=None,
|
||||
@ -1259,9 +1272,17 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
device mappings for this server.
|
||||
:param block_device_mapping_v2: (optional extension) A dict of block
|
||||
device mappings for this server.
|
||||
:param nics: (optional extension) an ordered list of nics to be
|
||||
added to this server, with information about
|
||||
connected networks, fixed IPs, port etc.
|
||||
:param nics: An ordered list of nics (dicts) to be added to this
|
||||
server, with information about connected networks,
|
||||
fixed IPs, port etc.
|
||||
Beginning in microversion 2.37 this field is required and
|
||||
also supports a single string value of 'auto' or 'none'.
|
||||
The 'auto' value means the Compute service will
|
||||
automatically allocate a network for the project if one
|
||||
is not available. This is the same behavior as not
|
||||
passing anything for nics before microversion 2.37. The
|
||||
'none' value tells the Compute service to not allocate
|
||||
any networking for the server.
|
||||
:param scheduler_hints: (optional extension) arbitrary key-value pairs
|
||||
specified by the client to help boot an instance
|
||||
:param config_drive: (optional extension) value for config drive
|
||||
@ -1289,6 +1310,8 @@ class ServerManager(base.BootingManagerWithFind):
|
||||
if "description" in kwargs and self.api_version < descr_microversion:
|
||||
raise exceptions.UnsupportedAttribute("description", "2.19")
|
||||
|
||||
self._validate_create_nics(nics)
|
||||
|
||||
tags_microversion = api_versions.APIVersion("2.32")
|
||||
if self.api_version < tags_microversion:
|
||||
if nics:
|
||||
|
@ -188,7 +188,16 @@ def _parse_block_device_mapping_v2(args, image):
|
||||
|
||||
|
||||
def _parse_nics(cs, args):
|
||||
if cs.api_version >= api_versions.APIVersion('2.32'):
|
||||
supports_auto_alloc = cs.api_version >= api_versions.APIVersion('2.37')
|
||||
if supports_auto_alloc:
|
||||
err_msg = (_("Invalid nic argument '%s'. Nic arguments must be of "
|
||||
"the form --nic <auto,none,net-id=net-uuid,"
|
||||
"net-name=network-name,v4-fixed-ip=ip-addr,"
|
||||
"v6-fixed-ip=ip-addr,port-id=port-uuid,tag=tag>, "
|
||||
"with only one of net-id, net-name or port-id "
|
||||
"specified. Specifying a --nic of auto or none cannot "
|
||||
"be used with any other --nic value."))
|
||||
elif cs.api_version >= api_versions.APIVersion('2.32'):
|
||||
err_msg = (_("Invalid nic argument '%s'. Nic arguments must be of "
|
||||
"the form --nic <net-id=net-uuid,"
|
||||
"net-name=network-name,v4-fixed-ip=ip-addr,"
|
||||
@ -202,6 +211,7 @@ def _parse_nics(cs, args):
|
||||
"v6-fixed-ip=ip-addr,port-id=port-uuid>, "
|
||||
"with only one of net-id, net-name or port-id "
|
||||
"specified."))
|
||||
auto_or_none = False
|
||||
nics = []
|
||||
for nic_str in args.nics:
|
||||
nic_info = {"net-id": "", "v4-fixed-ip": "", "v6-fixed-ip": "",
|
||||
@ -209,6 +219,13 @@ def _parse_nics(cs, args):
|
||||
|
||||
for kv_str in nic_str.split(","):
|
||||
try:
|
||||
# handle the special auto/none cases
|
||||
if kv_str in ('auto', 'none'):
|
||||
if not supports_auto_alloc:
|
||||
raise exceptions.CommandError(err_msg % nic_str)
|
||||
nics.append(kv_str)
|
||||
auto_or_none = True
|
||||
continue
|
||||
k, v = kv_str.split("=", 1)
|
||||
except ValueError:
|
||||
raise exceptions.CommandError(err_msg % nic_str)
|
||||
@ -225,6 +242,9 @@ def _parse_nics(cs, args):
|
||||
else:
|
||||
raise exceptions.CommandError(err_msg % nic_str)
|
||||
|
||||
if auto_or_none:
|
||||
continue
|
||||
|
||||
if nic_info['v4-fixed-ip'] and not netutils.is_valid_ipv4(
|
||||
nic_info['v4-fixed-ip']):
|
||||
raise exceptions.CommandError(_("Invalid ipv4 address."))
|
||||
@ -238,6 +258,17 @@ def _parse_nics(cs, args):
|
||||
|
||||
nics.append(nic_info)
|
||||
|
||||
if nics:
|
||||
if auto_or_none:
|
||||
if len(nics) > 1:
|
||||
raise exceptions.CommandError(err_msg % nic_str)
|
||||
# change the single list entry to a string
|
||||
nics = nics[0]
|
||||
else:
|
||||
# Default to 'auto' if API version >= 2.37 and nothing was specified
|
||||
if supports_auto_alloc:
|
||||
nics = 'auto'
|
||||
|
||||
return nics
|
||||
|
||||
|
||||
@ -577,6 +608,7 @@ def _boot(cs, args):
|
||||
dest='nics',
|
||||
default=[],
|
||||
start_version='2.32',
|
||||
end_version='2.36',
|
||||
help=_("Create a NIC on the server. "
|
||||
"Specify option multiple times to create multiple nics. "
|
||||
"net-id: attach NIC to network with this UUID "
|
||||
@ -587,6 +619,31 @@ def _boot(cs, args):
|
||||
"port-id: attach NIC to port with this UUID "
|
||||
"tag: interface metadata tag (optional) "
|
||||
"(either port-id or net-id must be provided)."))
|
||||
@utils.arg(
|
||||
'--nic',
|
||||
metavar="<auto,none,"
|
||||
"net-id=net-uuid,net-name=network-name,port-id=port-uuid,"
|
||||
"v4-fixed-ip=ip-addr,v6-fixed-ip=ip-addr,tag=tag>",
|
||||
action='append',
|
||||
dest='nics',
|
||||
default=[],
|
||||
start_version='2.37',
|
||||
help=_("Create a NIC on the server. "
|
||||
"Specify option multiple times to create multiple nics unless "
|
||||
"using the special 'auto' or 'none' values. "
|
||||
"auto: automatically allocate network resources if none are "
|
||||
"available. This cannot be specified with any other nic value and "
|
||||
"cannot be specified multiple times. "
|
||||
"none: do not attach a NIC at all. This cannot be specified "
|
||||
"with any other nic value and cannot be specified multiple times. "
|
||||
"net-id: attach NIC to network with a specific UUID. "
|
||||
"net-name: attach NIC to network with this name "
|
||||
"(either port-id or net-id or net-name must be provided), "
|
||||
"v4-fixed-ip: IPv4 fixed address for NIC (optional), "
|
||||
"v6-fixed-ip: IPv6 fixed address for NIC (optional), "
|
||||
"port-id: attach NIC to port with this UUID "
|
||||
"tag: interface metadata tag (optional) "
|
||||
"(either port-id or net-id must be provided)."))
|
||||
@utils.arg(
|
||||
'--config-drive',
|
||||
metavar="<value>",
|
||||
|
27
releasenotes/notes/microversion-2.37-d03da96406a45e67.yaml
Normal file
27
releasenotes/notes/microversion-2.37-d03da96406a45e67.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The 2.37 microversion is now supported. This introduces the following
|
||||
changes:
|
||||
|
||||
* CLI: The **--nic** value for the **nova boot** command now takes two
|
||||
special values, 'auto' and 'none'. If --nic is not specified, the
|
||||
CLI defaults to 'auto'.
|
||||
* Python API: The **nics** kwarg is required when creating a server using
|
||||
the *novaclient.v2.servers.ServerManager.create* API. The **nics**
|
||||
value can be a list of dicts or a string with value 'auto' or
|
||||
'none'.
|
||||
|
||||
upgrade:
|
||||
- |
|
||||
With the 2.37 microversion, the **nics** kwarg is required when creating
|
||||
a server using the *novaclient.v2.servers.ServerManager.create* API. The
|
||||
**nics** value can be a list of dicts or an enum string with one of the
|
||||
following values:
|
||||
|
||||
* **auto**: This tells the Compute service to automatically allocate a
|
||||
network for the project if one is not available and then associate
|
||||
an IP from that network with the server. This is the same behavior as
|
||||
passing nics=None before the 2.37 microversion.
|
||||
* **none**: This tells the Compute service to not allocate any networking
|
||||
for the server.
|
Loading…
Reference in New Issue
Block a user