compute: Add support for 'server boot --nic ...,tag=<tag>'

This has been around for a long time but was not exposed via OSC. Close
this gap.

Change-Id: I71aabf10f791f68ee7405ffb5e8317cc96cb3b38
Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
Stephen Finucane 2021-01-19 16:55:14 +00:00
parent c7d582379a
commit 9ed34aac0a
3 changed files with 133 additions and 4 deletions

View File

@ -646,6 +646,8 @@ class NICAction(argparse.Action):
values = '='.join([self.key, values])
# We don't include 'tag' here by default since that requires a
# particular microversion
info = {
'net-id': '',
'port-id': '',
@ -656,11 +658,11 @@ class NICAction(argparse.Action):
for kv_str in values.split(','):
k, sep, v = kv_str.partition("=")
if k not in info or not v:
if k not in list(info) + ['tag'] or not v:
msg = _(
"Invalid argument %s; argument must be of form "
"'net-id=net-uuid,v4-fixed-ip=ip-addr,v6-fixed-ip=ip-addr,"
"port-id=port-uuid'"
"'net-id=net-uuid,port-id=port-uuid,v4-fixed-ip=ip-addr,"
"v6-fixed-ip=ip-addr,tag=tag'"
)
raise argparse.ArgumentTypeError(msg % values)
@ -801,7 +803,7 @@ class CreateServer(command.ShowOne):
parser.add_argument(
'--nic',
metavar="<net-id=net-uuid,port-id=port-uuid,v4-fixed-ip=ip-addr,"
"v6-fixed-ip=ip-addr,auto,none>",
"v6-fixed-ip=ip-addr,tag=tag,auto,none>",
action=NICAction,
dest='nics',
default=[],
@ -814,6 +816,8 @@ class CreateServer(command.ShowOne):
"\n"
"v6-fixed-ip=<ip-addr>: IPv6 fixed address for NIC (optional),"
"\n"
"tag: interface metadata tag (optional) "
"(supported by --os-compute-api-version 2.43 or above),\n"
"none: (v2.37+) no network is attached,\n"
"auto: (v2.37+) the compute service will automatically "
"allocate a network.\n"
@ -1191,6 +1195,17 @@ class CreateServer(command.ShowOne):
nics = nics[0]
else:
for nic in nics:
if 'tag' in nic:
if (
compute_client.api_version <
api_versions.APIVersion('2.43')
):
msg = _(
'--os-compute-api-version 2.43 or greater is '
'required to support the --nic tag field'
)
raise exceptions.CommandError(msg)
if self.app.client_manager.is_network_endpoint_enabled():
network_client = self.app.client_manager.network

View File

@ -1423,6 +1423,113 @@ class TestServerCreate(TestServer):
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist(), data)
def test_server_create_with_network_tag(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion(
'2.43')
arglist = [
'--image', 'image1',
'--flavor', 'flavor1',
'--nic', 'net-id=net1,tag=foo',
self.new_server.name,
]
verifylist = [
('image', 'image1'),
('flavor', 'flavor1'),
('nics', [
{
'net-id': 'net1', 'port-id': '',
'v4-fixed-ip': '', 'v6-fixed-ip': '',
'tag': 'foo',
},
]),
('server_name', self.new_server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
find_network = mock.Mock()
network_client = self.app.client_manager.network
network_client.find_network = find_network
network_resource = mock.Mock(id='net1_uuid')
find_network.return_value = network_resource
# Mock sdk APIs.
_network = mock.Mock(id='net1_uuid')
find_network = mock.Mock()
find_network.return_value = _network
self.app.client_manager.network.find_network = find_network
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
kwargs = dict(
meta=None,
files={},
reservation_id=None,
min_count=1,
max_count=1,
security_groups=[],
userdata=None,
key_name=None,
availability_zone=None,
admin_pass=None,
block_device_mapping_v2=[],
nics=[
{
'net-id': 'net1_uuid',
'v4-fixed-ip': '',
'v6-fixed-ip': '',
'port-id': '',
'tag': 'foo',
},
],
scheduler_hints={},
config_drive=None,
)
# ServerManager.create(name, image, flavor, **kwargs)
self.servers_mock.create.assert_called_with(
self.new_server.name,
self.image,
self.flavor,
**kwargs
)
self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist(), data)
network_client.find_network.assert_called_once()
self.app.client_manager.network.find_network.assert_called_once()
def test_server_create_with_network_tag_pre_v243(self):
self.app.client_manager.compute.api_version = api_versions.APIVersion(
'2.42')
arglist = [
'--image', 'image1',
'--flavor', 'flavor1',
'--nic', 'net-id=net1,tag=foo',
self.new_server.name,
]
verifylist = [
('image', 'image1'),
('flavor', 'flavor1'),
('nics', [
{
'net-id': 'net1', 'port-id': '',
'v4-fixed-ip': '', 'v6-fixed-ip': '',
'tag': 'foo',
},
]),
('server_name', self.new_server.name),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
self.assertRaises(
exceptions.CommandError, self.cmd.take_action, parsed_args)
def test_server_create_with_auto_network(self):
arglist = [
'--image', 'image1',

View File

@ -0,0 +1,7 @@
---
features:
- |
The ``--nic`` option of the ``server create`` command now supports an
optional ``tag=<tag>`` key-value pair. This can be used to set a tag for
the interface in server metadata, which can be useful to maintain
persistent references to interfaces during various operations.