diff --git a/ironicclient/common/http.py b/ironicclient/common/http.py index 0558f53ff..735cebce9 100644 --- a/ironicclient/common/http.py +++ b/ironicclient/common/http.py @@ -43,7 +43,7 @@ from ironicclient import exc # http://specs.openstack.org/openstack/ironic-specs/specs/kilo/api-microversions.html # noqa # for full details. DEFAULT_VER = '1.9' -LAST_KNOWN_API_VERSION = 49 +LAST_KNOWN_API_VERSION = 50 LATEST_VERSION = '1.{}'.format(LAST_KNOWN_API_VERSION) LOG = logging.getLogger(__name__) diff --git a/ironicclient/osc/v1/baremetal_node.py b/ironicclient/osc/v1/baremetal_node.py index f1d6cec0f..463e0b1b7 100755 --- a/ironicclient/osc/v1/baremetal_node.py +++ b/ironicclient/osc/v1/baremetal_node.py @@ -437,6 +437,10 @@ class CreateBaremetalNode(command.ShowOne): action='store_true', default=None, help=_('Enable automated cleaning for the node')) + parser.add_argument( + '--owner', + metavar='', + help=_('Owner of the node.')) return parser @@ -447,7 +451,7 @@ class CreateBaremetalNode(command.ShowOne): field_list = ['automated_clean', 'chassis_uuid', 'driver', 'driver_info', 'properties', 'extra', 'uuid', 'name', - 'conductor_group', + 'conductor_group', 'owner', 'resource_class'] + ['%s_interface' % iface for iface in SUPPORTED_INTERFACES] fields = dict((k, v) for (k, v) in vars(parsed_args).items() @@ -617,6 +621,11 @@ class ListBaremetalNode(command.Lister): dest='chassis', metavar='', help=_("Limit list to nodes of this chassis")) + parser.add_argument( + '--owner', + metavar='', + help=_("Limit list to nodes with owner " + "")) display_group = parser.add_mutually_exclusive_group(required=False) display_group.add_argument( '--long', @@ -658,7 +667,7 @@ class ListBaremetalNode(command.Lister): if getattr(parsed_args, field) is not None: params[field] = getattr(parsed_args, field) for field in ['provision_state', 'driver', 'resource_class', - 'chassis', 'conductor']: + 'chassis', 'conductor', 'owner']: if getattr(parsed_args, field): params[field] = getattr(parsed_args, field) if parsed_args.long: @@ -1166,6 +1175,10 @@ class SetBaremetalNode(command.Command): help=_('Instance information to set on this baremetal node ' '(repeat option to set multiple instance infos)'), ) + parser.add_argument( + "--owner", + metavar='', + help=_('Set the owner for the node')), return parser @@ -1188,7 +1201,8 @@ class SetBaremetalNode(command.Command): properties = [] for field in ['automated_clean', 'instance_uuid', 'name', 'chassis_uuid', 'driver', 'resource_class', - 'conductor_group', 'protected', 'protected_reason']: + 'conductor_group', 'protected', 'protected_reason', + 'owner']: value = getattr(parsed_args, field) if value: properties.extend(utils.args_array_to_patch( @@ -1461,6 +1475,11 @@ class UnsetBaremetalNode(command.Command): help=_('Unset the protected reason (gets unset automatically when ' 'protected is unset)'), ) + parser.add_argument( + "--owner", + action="store_true", + help=_('Unset the owner field of the node'), + ) return parser @@ -1483,7 +1502,7 @@ class UnsetBaremetalNode(command.Command): 'management_interface', 'network_interface', 'power_interface', 'raid_interface', 'rescue_interface', 'storage_interface', 'vendor_interface', - 'protected', 'protected_reason']: + 'protected', 'protected_reason', 'owner']: if getattr(parsed_args, field): properties.extend(utils.args_array_to_patch('remove', [field])) diff --git a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py index e6d9ed7be..c11854d91 100644 --- a/ironicclient/tests/unit/osc/v1/test_baremetal_node.py +++ b/ironicclient/tests/unit/osc/v1/test_baremetal_node.py @@ -460,6 +460,11 @@ class TestBaremetalCreate(TestBaremetal): [('automated_clean', True)], {'automated_clean': True}) + def test_baremetal_create_with_owner(self): + self.check_with_options(['--owner', 'owner 1'], + [('owner', 'owner 1')], + {'owner': 'owner 1'}) + class TestBaremetalDelete(TestBaremetal): def setUp(self): @@ -634,6 +639,7 @@ class TestBaremetalList(TestBaremetal): 'Management Interface', 'Name', 'Network Interface', + 'Owner', 'Power Interface', 'Power State', 'Properties', @@ -987,6 +993,30 @@ class TestBaremetalList(TestBaremetal): **kwargs ) + def test_baremetal_list_by_owner(self): + owner = 'owner 1' + arglist = [ + '--owner', owner, + ] + verifylist = [ + ('owner', owner), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # DisplayCommandBase.take_action() returns two tuples + self.cmd.take_action(parsed_args) + + # Set excepted values + kwargs = { + 'marker': None, + 'limit': None, + 'owner': owner + } + + self.baremetal_mock.node.list.assert_called_with( + **kwargs + ) + def test_baremetal_list_fields(self): arglist = [ '--fields', 'uuid', 'name', @@ -2536,6 +2566,27 @@ class TestBaremetalSet(TestBaremetal): self.baremetal_mock.node.set_target_raid_config.called) self.assertFalse(self.baremetal_mock.node.update.called) + def test_baremetal_set_owner(self): + arglist = [ + 'node_uuid', + '--owner', 'owner 1', + ] + verifylist = [ + ('node', 'node_uuid'), + ('owner', 'owner 1') + ] + 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': '/owner', + 'value': 'owner 1', + 'op': 'add'}], + reset_interfaces=None, + ) + class TestBaremetalShow(TestBaremetal): def setUp(self): @@ -3059,6 +3110,25 @@ class TestBaremetalUnset(TestBaremetal): def test_baremetal_unset_vendor_interface(self): self._test_baremetal_unset_hw_interface('vendor') + def test_baremetal_unset_owner(self): + arglist = [ + 'node_uuid', + '--owner', + ] + verifylist = [ + ('node', 'node_uuid'), + ('owner', 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': '/owner', 'op': 'remove'}] + ) + class TestValidate(TestBaremetal): def setUp(self): diff --git a/ironicclient/tests/unit/v1/test_node_shell.py b/ironicclient/tests/unit/v1/test_node_shell.py index 6608afb86..4c05f8a74 100644 --- a/ironicclient/tests/unit/v1/test_node_shell.py +++ b/ironicclient/tests/unit/v1/test_node_shell.py @@ -59,6 +59,7 @@ class NodeShellTest(utils.BaseTestCase): 'inspect_interface', 'management_interface', 'network_interface', + 'owner', 'power_interface', 'raid_interface', 'rescue_interface', diff --git a/ironicclient/v1/resource_fields.py b/ironicclient/v1/resource_fields.py index d8ab2857b..a0d6f3e7b 100644 --- a/ironicclient/v1/resource_fields.py +++ b/ironicclient/v1/resource_fields.py @@ -91,6 +91,7 @@ class Resource(object): 'mode': 'Mode', 'name': 'Name', 'node_uuid': 'Node UUID', + 'owner': 'Owner', 'power_state': 'Power State', 'properties': 'Properties', 'protected': 'Protected', @@ -238,6 +239,7 @@ NODE_DETAILED_RESOURCE = Resource( 'management_interface', 'name', 'network_interface', + 'owner', 'power_interface', 'power_state', 'properties', diff --git a/releasenotes/notes/add-node-owner-c2dce5a6075ce2b7.yaml b/releasenotes/notes/add-node-owner-c2dce5a6075ce2b7.yaml new file mode 100644 index 000000000..f99fe7189 --- /dev/null +++ b/releasenotes/notes/add-node-owner-c2dce5a6075ce2b7.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Adds support to display and update the ``owner`` field of nodes, + which is introduced in API 1.50.