Merge "Add network_data
ironic node attribute support"
This commit is contained in:
commit
aa3c66584c
@ -37,7 +37,7 @@ from ironicclient import exc
|
|||||||
# http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa
|
# http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa
|
||||||
# for full details.
|
# for full details.
|
||||||
DEFAULT_VER = '1.9'
|
DEFAULT_VER = '1.9'
|
||||||
LAST_KNOWN_API_VERSION = 65
|
LAST_KNOWN_API_VERSION = 66
|
||||||
LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION)
|
LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION)
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -39,6 +39,14 @@ CONFIG_DRIVE_ARG_HELP = _(
|
|||||||
"more details).")
|
"more details).")
|
||||||
|
|
||||||
|
|
||||||
|
NETWORK_DATA_ARG_HELP = _(
|
||||||
|
"JSON string or a file or '-' for stdin to read static network "
|
||||||
|
"configuration for the baremetal node associated with this ironic node. "
|
||||||
|
"Format of this file should comply with Nova network data metadata "
|
||||||
|
"(network_data.json). Depending on ironic boot interface capabilities "
|
||||||
|
"being used, network configuration may or may not been served to the "
|
||||||
|
"node for offline network configuration.")
|
||||||
|
|
||||||
SUPPORTED_INTERFACES = ['bios', 'boot', 'console', 'deploy', 'inspect',
|
SUPPORTED_INTERFACES = ['bios', 'boot', 'console', 'deploy', 'inspect',
|
||||||
'management', 'network', 'power', 'raid', 'rescue',
|
'management', 'network', 'power', 'raid', 'rescue',
|
||||||
'storage', 'vendor']
|
'storage', 'vendor']
|
||||||
@ -402,6 +410,11 @@ class CreateBaremetalNode(command.ShowOne):
|
|||||||
help=_('Management interface used by the node\'s driver. This is '
|
help=_('Management interface used by the node\'s driver. This is '
|
||||||
'only applicable when the specified --driver is a '
|
'only applicable when the specified --driver is a '
|
||||||
'hardware type.'))
|
'hardware type.'))
|
||||||
|
parser.add_argument(
|
||||||
|
'--network-data',
|
||||||
|
metavar="<network data>",
|
||||||
|
dest='network_data',
|
||||||
|
help=NETWORK_DATA_ARG_HELP)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--network-interface',
|
'--network-interface',
|
||||||
metavar='<network_interface>',
|
metavar='<network_interface>',
|
||||||
@ -477,6 +490,9 @@ class CreateBaremetalNode(command.ShowOne):
|
|||||||
if k in field_list and not (v is None))
|
if k in field_list and not (v is None))
|
||||||
fields = utils.args_array_to_dict(fields, 'driver_info')
|
fields = utils.args_array_to_dict(fields, 'driver_info')
|
||||||
fields = utils.args_array_to_dict(fields, 'extra')
|
fields = utils.args_array_to_dict(fields, 'extra')
|
||||||
|
if parsed_args.network_data:
|
||||||
|
fields['network_data'] = utils.handle_json_arg(
|
||||||
|
parsed_args.network_data, 'static network configuration')
|
||||||
fields = utils.args_array_to_dict(fields, 'properties')
|
fields = utils.args_array_to_dict(fields, 'properties')
|
||||||
node = baremetal_client.node.create(**fields)._info
|
node = baremetal_client.node.create(**fields)._info
|
||||||
|
|
||||||
@ -1123,6 +1139,12 @@ class SetBaremetalNode(command.Command):
|
|||||||
reset_help=_('Reset the network interface to its hardware type '
|
reset_help=_('Reset the network interface to its hardware type '
|
||||||
'default'),
|
'default'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--network-data',
|
||||||
|
metavar="<network data>",
|
||||||
|
dest='network_data',
|
||||||
|
help=NETWORK_DATA_ARG_HELP
|
||||||
|
)
|
||||||
self._add_interface_args(
|
self._add_interface_args(
|
||||||
parser, 'power',
|
parser, 'power',
|
||||||
set_help=_('Set the power interface for the node'),
|
set_help=_('Set the power interface for the node'),
|
||||||
@ -1300,6 +1322,12 @@ class SetBaremetalNode(command.Command):
|
|||||||
properties.extend(utils.args_array_to_patch(
|
properties.extend(utils.args_array_to_patch(
|
||||||
'add', ['instance_info/' + x for x
|
'add', ['instance_info/' + x for x
|
||||||
in parsed_args.instance_info]))
|
in parsed_args.instance_info]))
|
||||||
|
if parsed_args.network_data:
|
||||||
|
network_data = utils.handle_json_arg(
|
||||||
|
parsed_args.network_data, 'static network configuration')
|
||||||
|
network_data = ["network_data=%s" % json.dumps(network_data)]
|
||||||
|
properties.extend(utils.args_array_to_patch('add', network_data))
|
||||||
|
|
||||||
if properties:
|
if properties:
|
||||||
baremetal_client.node.update(
|
baremetal_client.node.update(
|
||||||
parsed_args.node, properties,
|
parsed_args.node, properties,
|
||||||
@ -1474,6 +1502,11 @@ class UnsetBaremetalNode(command.Command):
|
|||||||
action='store_true',
|
action='store_true',
|
||||||
help=_('Unset inspect interface on this baremetal node'),
|
help=_('Unset inspect interface on this baremetal node'),
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--network-data',
|
||||||
|
action='store_true',
|
||||||
|
help=_("Unset network data on this baremetal port.")
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--management-interface",
|
"--management-interface",
|
||||||
dest='management_interface',
|
dest='management_interface',
|
||||||
@ -1607,6 +1640,9 @@ class UnsetBaremetalNode(command.Command):
|
|||||||
properties.extend(utils.args_array_to_patch('remove',
|
properties.extend(utils.args_array_to_patch('remove',
|
||||||
['instance_info/' + x for x
|
['instance_info/' + x for x
|
||||||
in parsed_args.instance_info]))
|
in parsed_args.instance_info]))
|
||||||
|
if parsed_args.network_data:
|
||||||
|
properties.extend(utils.args_array_to_patch(
|
||||||
|
'remove', ["network_data"]))
|
||||||
if properties:
|
if properties:
|
||||||
baremetal_client.node.update(parsed_args.node, properties)
|
baremetal_client.node.update(parsed_args.node, properties)
|
||||||
elif not parsed_args.target_raid_config:
|
elif not parsed_args.target_raid_config:
|
||||||
|
@ -415,6 +415,11 @@ class TestBaremetalCreate(TestBaremetal):
|
|||||||
[('management_interface', 'management')],
|
[('management_interface', 'management')],
|
||||||
{'management_interface': 'management'})
|
{'management_interface': 'management'})
|
||||||
|
|
||||||
|
def test_baremetal_create_with_network_data(self):
|
||||||
|
self.check_with_options(['--network-data', '{"a": ["b"]}'],
|
||||||
|
[('network_data', '{"a": ["b"]}')],
|
||||||
|
{'network_data': {"a": ["b"]}})
|
||||||
|
|
||||||
def test_baremetal_create_with_network_interface(self):
|
def test_baremetal_create_with_network_interface(self):
|
||||||
self.check_with_options(['--network-interface', 'neutron'],
|
self.check_with_options(['--network-interface', 'neutron'],
|
||||||
[('network_interface', 'neutron')],
|
[('network_interface', 'neutron')],
|
||||||
@ -2779,10 +2784,33 @@ class TestBaremetalSet(TestBaremetal):
|
|||||||
|
|
||||||
self.cmd.take_action(parsed_args)
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.assert_called_once_with(
|
||||||
|
'node_uuid', [{'op': 'add',
|
||||||
|
'path': '/lessee',
|
||||||
|
'value': 'lessee 1'}],
|
||||||
|
reset_interfaces=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch.object(commonutils, 'get_from_stdin', autospec=True)
|
||||||
|
@mock.patch.object(commonutils, 'handle_json_or_file_arg', autospec=True)
|
||||||
|
def test_baremetal_set_network_data(self, mock_handle, mock_stdin):
|
||||||
|
self.cmd.log = mock.Mock(autospec=True)
|
||||||
|
network_data_string = '{"a": ["b"]}'
|
||||||
|
expected_network_data = {'a': ['b']}
|
||||||
|
mock_handle.return_value = expected_network_data.copy()
|
||||||
|
|
||||||
|
arglist = ['node_uuid',
|
||||||
|
'--network-data', network_data_string]
|
||||||
|
verifylist = [('node', 'node_uuid'),
|
||||||
|
('network_data', network_data_string)]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
self.baremetal_mock.node.update.assert_called_once_with(
|
self.baremetal_mock.node.update.assert_called_once_with(
|
||||||
'node_uuid',
|
'node_uuid',
|
||||||
[{'path': '/lessee',
|
[{'path': '/network_data', 'value': expected_network_data,
|
||||||
'value': 'lessee 1',
|
|
||||||
'op': 'add'}],
|
'op': 'add'}],
|
||||||
reset_interfaces=None,
|
reset_interfaces=None,
|
||||||
)
|
)
|
||||||
@ -3405,6 +3433,25 @@ class TestBaremetalUnset(TestBaremetal):
|
|||||||
[{'path': '/lessee', 'op': 'remove'}]
|
[{'path': '/lessee', 'op': 'remove'}]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_baremetal_unset_network_data(self):
|
||||||
|
arglist = [
|
||||||
|
'node_uuid',
|
||||||
|
'--network-data',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('node', 'node_uuid'),
|
||||||
|
('network_data', True)
|
||||||
|
]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
self.cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
self.baremetal_mock.node.update.assert_called_once_with(
|
||||||
|
'node_uuid',
|
||||||
|
[{'path': '/network_data', 'op': 'remove'}]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestValidate(TestBaremetal):
|
class TestValidate(TestBaremetal):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -36,6 +36,7 @@ NODE1 = {'uuid': '66666666-7777-8888-9999-000000000000',
|
|||||||
'driver_info': {'user': 'foo', 'password': 'bar'},
|
'driver_info': {'user': 'foo', 'password': 'bar'},
|
||||||
'properties': {'num_cpu': 4},
|
'properties': {'num_cpu': 4},
|
||||||
'name': 'fake-node-1',
|
'name': 'fake-node-1',
|
||||||
|
'network_data': {},
|
||||||
'resource_class': 'foo',
|
'resource_class': 'foo',
|
||||||
'extra': {},
|
'extra': {},
|
||||||
'conductor_group': 'in-the-closet-to-the-left'}
|
'conductor_group': 'in-the-closet-to-the-left'}
|
||||||
@ -46,6 +47,7 @@ NODE2 = {'uuid': '66666666-7777-8888-9999-111111111111',
|
|||||||
'driver': 'fake too',
|
'driver': 'fake too',
|
||||||
'driver_info': {'user': 'foo', 'password': 'bar'},
|
'driver_info': {'user': 'foo', 'password': 'bar'},
|
||||||
'properties': {'num_cpu': 4},
|
'properties': {'num_cpu': 4},
|
||||||
|
'network_data': {},
|
||||||
'resource_class': 'bar',
|
'resource_class': 'bar',
|
||||||
'extra': {},
|
'extra': {},
|
||||||
'owner': '33333333-2222-1111-0000-111111111111',
|
'owner': '33333333-2222-1111-0000-111111111111',
|
||||||
|
@ -53,7 +53,7 @@ class NodeManager(base.CreateManager):
|
|||||||
'raid_interface', 'rescue_interface',
|
'raid_interface', 'rescue_interface',
|
||||||
'storage_interface', 'vendor_interface',
|
'storage_interface', 'vendor_interface',
|
||||||
'resource_class', 'conductor_group',
|
'resource_class', 'conductor_group',
|
||||||
'automated_clean']
|
'automated_clean', 'network_data']
|
||||||
_resource_name = 'nodes'
|
_resource_name = 'nodes'
|
||||||
|
|
||||||
def list(self, associated=None, maintenance=None, marker=None,
|
def list(self, associated=None, maintenance=None, marker=None,
|
||||||
|
@ -93,6 +93,7 @@ class Resource(object):
|
|||||||
'fault': 'Fault',
|
'fault': 'Fault',
|
||||||
'mode': 'Mode',
|
'mode': 'Mode',
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
|
'network_data': 'Network Configuration',
|
||||||
'node_uuid': 'Node UUID',
|
'node_uuid': 'Node UUID',
|
||||||
'owner': 'Owner',
|
'owner': 'Owner',
|
||||||
'power_state': 'Power State',
|
'power_state': 'Power State',
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds support for adding static network configuration to ports and
|
||||||
|
portgroups by adding ``network-data`` attribute to port/portgroup
|
||||||
|
commands.
|
Loading…
Reference in New Issue
Block a user