Add Ironic CLI commands for volume connector
This patch adds the following commands for volume connector. - ironic volume-connector-list - ironic volume-connector-show - ironic volume-connector-create - ironic volume-connector-update - ironic volume-connector-delete Co-Authored-By: Tomoki Sekiyama <tomoki.sekiyama@hds.com> Co-Authored-By: Satoru Moriya <satoru.moriya.br@hitachi.com> Co-Authored-By: Stephane Miller <stephane@alum.mit.edu> Change-Id: I9ebbb4bc82afa001d2cf53c834e8efd320b7ba16 Partial-Bug: 1526231
This commit is contained in:
		
							
								
								
									
										284
									
								
								ironicclient/tests/unit/v1/test_volume_connector_shell.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								ironicclient/tests/unit/v1/test_volume_connector_shell.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,284 @@
 | 
				
			|||||||
 | 
					# Copyright 2017 Hitachi Data Systems
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
				
			||||||
 | 
					#    not use this file except in compliance with the License. You may obtain
 | 
				
			||||||
 | 
					#    a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#         http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#    Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
				
			||||||
 | 
					#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
				
			||||||
 | 
					#    License for the specific language governing permissions and limitations
 | 
				
			||||||
 | 
					#    under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import mock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from oslo_utils import uuidutils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ironicclient.common.apiclient import exceptions
 | 
				
			||||||
 | 
					from ironicclient.common import cliutils
 | 
				
			||||||
 | 
					from ironicclient.common import utils as commonutils
 | 
				
			||||||
 | 
					from ironicclient.tests.unit import utils
 | 
				
			||||||
 | 
					import ironicclient.v1.volume_connector_shell as vc_shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Volume_ConnectorShellTest(utils.BaseTestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_volume_connector_show(self):
 | 
				
			||||||
 | 
					        actual = {}
 | 
				
			||||||
 | 
					        fake_print_dict = lambda data, *args, **kwargs: actual.update(data)
 | 
				
			||||||
 | 
					        with mock.patch.object(cliutils, 'print_dict', fake_print_dict):
 | 
				
			||||||
 | 
					            volume_connector = object()
 | 
				
			||||||
 | 
					            vc_shell._print_volume_connector_show(volume_connector)
 | 
				
			||||||
 | 
					        exp = ['created_at', 'extra', 'node_uuid', 'type', 'updated_at',
 | 
				
			||||||
 | 
					               'uuid', 'connector_id']
 | 
				
			||||||
 | 
					        act = actual.keys()
 | 
				
			||||||
 | 
					        self.assertEqual(sorted(exp), sorted(act))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_show(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = 'volume_connector_uuid'
 | 
				
			||||||
 | 
					        args.fields = None
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_show(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.get.assert_called_once_with(
 | 
				
			||||||
 | 
					            'volume_connector_uuid', fields=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_show_space_uuid(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = '   '
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_show,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_show_empty_uuid(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = ''
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_show,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_show_fields(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = 'volume_connector_uuid'
 | 
				
			||||||
 | 
					        args.fields = [['uuid', 'connector_id']]
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_show(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.get.assert_called_once_with(
 | 
				
			||||||
 | 
					            'volume_connector_uuid', fields=['uuid', 'connector_id'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_show_invalid_fields(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = 'volume_connector_uuid'
 | 
				
			||||||
 | 
					        args.fields = [['foo', 'bar']]
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_show,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_update(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = 'volume_connector_uuid'
 | 
				
			||||||
 | 
					        args.op = 'add'
 | 
				
			||||||
 | 
					        args.attributes = [['arg1=val1', 'arg2=val2']]
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_update(client_mock, args)
 | 
				
			||||||
 | 
					        patch = commonutils.args_array_to_patch(args.op, args.attributes[0])
 | 
				
			||||||
 | 
					        client_mock.volume_connector.update.assert_called_once_with(
 | 
				
			||||||
 | 
					            'volume_connector_uuid', patch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_update_wrong_op(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = 'volume_connector_uuid'
 | 
				
			||||||
 | 
					        args.op = 'foo'
 | 
				
			||||||
 | 
					        args.attributes = [['arg1=val1', 'arg2=val2']]
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_update,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					        self.assertFalse(client_mock.volume_connector.update.called)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _get_client_mock_args(self, node=None, marker=None, limit=None,
 | 
				
			||||||
 | 
					                              sort_dir=None, sort_key=None, detail=False,
 | 
				
			||||||
 | 
					                              fields=None, json=False):
 | 
				
			||||||
 | 
					        args = mock.MagicMock(spec=True)
 | 
				
			||||||
 | 
					        args.node = node
 | 
				
			||||||
 | 
					        args.marker = marker
 | 
				
			||||||
 | 
					        args.limit = limit
 | 
				
			||||||
 | 
					        args.sort_dir = sort_dir
 | 
				
			||||||
 | 
					        args.sort_key = sort_key
 | 
				
			||||||
 | 
					        args.detail = detail
 | 
				
			||||||
 | 
					        args.fields = fields
 | 
				
			||||||
 | 
					        args.json = json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return args
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_list(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.list.assert_called_once_with(detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_detail(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(detail=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_list(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.list.assert_called_once_with(detail=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_sort_key(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(sort_key='uuid',
 | 
				
			||||||
 | 
					                                          detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_list(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.list.assert_called_once_with(
 | 
				
			||||||
 | 
					            sort_key='uuid', detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_wrong_sort_key(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(sort_key='node_uuid', detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_list,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					        self.assertFalse(client_mock.volume_connector.list.called)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_detail_sort_key(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(sort_key='uuid',
 | 
				
			||||||
 | 
					                                          detail=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_list(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.list.assert_called_once_with(
 | 
				
			||||||
 | 
					            sort_key='uuid', detail=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_detail_wrong_sort_key(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(sort_key='node_uuid',
 | 
				
			||||||
 | 
					                                          detail=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_list,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					        self.assertFalse(client_mock.volume_connector.list.called)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_fields(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(fields=[['uuid', 'connector_id']])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_list(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.list.assert_called_once_with(
 | 
				
			||||||
 | 
					            fields=['uuid', 'connector_id'], detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_invalid_fields(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(fields=[['foo', 'bar']])
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_list,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_sort_dir(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(sort_dir='desc', detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_list(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.list.assert_called_once_with(
 | 
				
			||||||
 | 
					            sort_dir='desc', detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_list_detail_sort_dir(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(sort_dir='asc', detail=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_list(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.list.assert_called_once_with(
 | 
				
			||||||
 | 
					            sort_dir='asc', detail=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_wrong_sort_dir(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = self._get_client_mock_args(sort_dir='abc', detail=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_list,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					        self.assertFalse(client_mock.volume_connector.list.called)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_create(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_create(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.create.assert_called_once_with()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_create_with_uuid(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.uuid = uuidutils.generate_uuid()
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_create(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.create.assert_called_once_with(
 | 
				
			||||||
 | 
					            uuid=args.uuid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_create_valid_fields_values(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.type = 'type'
 | 
				
			||||||
 | 
					        args.connector_id = 'connector_id'
 | 
				
			||||||
 | 
					        args.node_uuid = 'uuid'
 | 
				
			||||||
 | 
					        args.extra = ["key1=val1", "key2=val2"]
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_create(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.create.assert_called_once_with(
 | 
				
			||||||
 | 
					            type='type', connector_id='connector_id', node_uuid='uuid',
 | 
				
			||||||
 | 
					            extra={'key1': 'val1', 'key2': 'val2'})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_create_invalid_extra_fields(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.type = 'type'
 | 
				
			||||||
 | 
					        args.connector_id = 'connector_id'
 | 
				
			||||||
 | 
					        args.node_uuid = 'uuid'
 | 
				
			||||||
 | 
					        args.extra = ["foo"]
 | 
				
			||||||
 | 
					        args.json = False
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.CommandError,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_create,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_delete(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = ['volume_connector_uuid']
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_delete(client_mock, args)
 | 
				
			||||||
 | 
					        client_mock.volume_connector.delete.assert_called_once_with(
 | 
				
			||||||
 | 
					            'volume_connector_uuid')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_delete_multi(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = ['uuid1', 'uuid2']
 | 
				
			||||||
 | 
					        vc_shell.do_volume_connector_delete(client_mock, args)
 | 
				
			||||||
 | 
					        self.assertEqual([mock.call('uuid1'), mock.call('uuid2')],
 | 
				
			||||||
 | 
					                         client_mock.volume_connector.delete.call_args_list)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_do_volume_connector_delete_multi_error(self):
 | 
				
			||||||
 | 
					        client_mock = mock.MagicMock()
 | 
				
			||||||
 | 
					        args = mock.MagicMock()
 | 
				
			||||||
 | 
					        args.volume_connector = ['uuid1', 'uuid2']
 | 
				
			||||||
 | 
					        client_mock.volume_connector.delete.side_effect = [
 | 
				
			||||||
 | 
					            exceptions.ClientException('error'), None]
 | 
				
			||||||
 | 
					        self.assertRaises(exceptions.ClientException,
 | 
				
			||||||
 | 
					                          vc_shell.do_volume_connector_delete,
 | 
				
			||||||
 | 
					                          client_mock, args)
 | 
				
			||||||
 | 
					        self.assertEqual([mock.call('uuid1'), mock.call('uuid2')],
 | 
				
			||||||
 | 
					                         client_mock.volume_connector.delete.call_args_list)
 | 
				
			||||||
@@ -18,6 +18,7 @@ from ironicclient.v1 import driver_shell
 | 
				
			|||||||
from ironicclient.v1 import node_shell
 | 
					from ironicclient.v1 import node_shell
 | 
				
			||||||
from ironicclient.v1 import port_shell
 | 
					from ironicclient.v1 import port_shell
 | 
				
			||||||
from ironicclient.v1 import portgroup_shell
 | 
					from ironicclient.v1 import portgroup_shell
 | 
				
			||||||
 | 
					from ironicclient.v1 import volume_connector_shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMMAND_MODULES = [
 | 
					COMMAND_MODULES = [
 | 
				
			||||||
    chassis_shell,
 | 
					    chassis_shell,
 | 
				
			||||||
@@ -26,6 +27,7 @@ COMMAND_MODULES = [
 | 
				
			|||||||
    portgroup_shell,
 | 
					    portgroup_shell,
 | 
				
			||||||
    driver_shell,
 | 
					    driver_shell,
 | 
				
			||||||
    create_resources_shell,
 | 
					    create_resources_shell,
 | 
				
			||||||
 | 
					    volume_connector_shell,
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										209
									
								
								ironicclient/v1/volume_connector_shell.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								ironicclient/v1/volume_connector_shell.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
				
			|||||||
 | 
					# Copyright 2017 Hitachi Data Systems
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 | 
				
			||||||
 | 
					#    not use this file except in compliance with the License. You may obtain
 | 
				
			||||||
 | 
					#    a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#         http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#    Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
				
			||||||
 | 
					#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
				
			||||||
 | 
					#    License for the specific language governing permissions and limitations
 | 
				
			||||||
 | 
					#    under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from ironicclient.common.apiclient import exceptions
 | 
				
			||||||
 | 
					from ironicclient.common import cliutils
 | 
				
			||||||
 | 
					from ironicclient.common.i18n import _
 | 
				
			||||||
 | 
					from ironicclient.common import utils
 | 
				
			||||||
 | 
					from ironicclient.v1 import resource_fields as res_fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _print_volume_connector_show(volume_connector, fields=None, json=False):
 | 
				
			||||||
 | 
					    if fields is None:
 | 
				
			||||||
 | 
					        fields = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data = dict([(f, getattr(volume_connector, f, '')) for f in fields])
 | 
				
			||||||
 | 
					    cliutils.print_dict(data, wrap=72, json_flag=json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'volume_connector',
 | 
				
			||||||
 | 
					    metavar='<id>',
 | 
				
			||||||
 | 
					    help=_("UUID of the volume connector."))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--fields',
 | 
				
			||||||
 | 
					    nargs='+',
 | 
				
			||||||
 | 
					    dest='fields',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    default=[],
 | 
				
			||||||
 | 
					    help=_("One or more volume connector fields. Only these fields will be "
 | 
				
			||||||
 | 
					           "fetched from the server."))
 | 
				
			||||||
 | 
					def do_volume_connector_show(cc, args):
 | 
				
			||||||
 | 
					    """Show detailed information about a volume connector."""
 | 
				
			||||||
 | 
					    fields = args.fields[0] if args.fields else None
 | 
				
			||||||
 | 
					    utils.check_for_invalid_fields(
 | 
				
			||||||
 | 
					        fields, res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields)
 | 
				
			||||||
 | 
					    utils.check_empty_arg(args.volume_connector, '<id>')
 | 
				
			||||||
 | 
					    volume_connector = cc.volume_connector.get(args.volume_connector,
 | 
				
			||||||
 | 
					                                               fields=fields)
 | 
				
			||||||
 | 
					    _print_volume_connector_show(volume_connector, fields=fields,
 | 
				
			||||||
 | 
					                                 json=args.json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--detail',
 | 
				
			||||||
 | 
					    dest='detail',
 | 
				
			||||||
 | 
					    action='store_true',
 | 
				
			||||||
 | 
					    default=False,
 | 
				
			||||||
 | 
					    help=_("Show detailed information about volume connectors."))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '-n', '--node',
 | 
				
			||||||
 | 
					    metavar='<node>',
 | 
				
			||||||
 | 
					    help=_('Only list volume connectors of this node (name or UUID)'))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--limit',
 | 
				
			||||||
 | 
					    metavar='<limit>',
 | 
				
			||||||
 | 
					    type=int,
 | 
				
			||||||
 | 
					    help=_('Maximum number of volume connectors to return per request, '
 | 
				
			||||||
 | 
					           '0 for no limit. Default is the maximum number used '
 | 
				
			||||||
 | 
					           'by the Baremetal API Service.'))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--marker',
 | 
				
			||||||
 | 
					    metavar='<volume connector>',
 | 
				
			||||||
 | 
					    help=_('Volume connector UUID (for example, of the last volume connector '
 | 
				
			||||||
 | 
					           'in the list from a previous request). Returns the list of volume '
 | 
				
			||||||
 | 
					           'connectors after this UUID.'))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--sort-key',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    help=_('Volume connector field that will be used for sorting.'))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--sort-dir',
 | 
				
			||||||
 | 
					    metavar='<direction>',
 | 
				
			||||||
 | 
					    choices=['asc', 'desc'],
 | 
				
			||||||
 | 
					    help=_('Sort direction: "asc" (the default) or "desc".'))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '--fields',
 | 
				
			||||||
 | 
					    nargs='+',
 | 
				
			||||||
 | 
					    dest='fields',
 | 
				
			||||||
 | 
					    metavar='<field>',
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    default=[],
 | 
				
			||||||
 | 
					    help=_("One or more volume connector fields. Only these fields will be "
 | 
				
			||||||
 | 
					           "fetched from the server. Can not be used when '--detail' is "
 | 
				
			||||||
 | 
					           "specified."))
 | 
				
			||||||
 | 
					def do_volume_connector_list(cc, args):
 | 
				
			||||||
 | 
					    """List the volume connectors."""
 | 
				
			||||||
 | 
					    params = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.node is not None:
 | 
				
			||||||
 | 
					        params['node'] = args.node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.detail:
 | 
				
			||||||
 | 
					        fields = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields
 | 
				
			||||||
 | 
					        field_labels = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.labels
 | 
				
			||||||
 | 
					    elif args.fields:
 | 
				
			||||||
 | 
					        utils.check_for_invalid_fields(
 | 
				
			||||||
 | 
					            args.fields[0],
 | 
				
			||||||
 | 
					            res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.fields)
 | 
				
			||||||
 | 
					        resource = res_fields.Resource(args.fields[0])
 | 
				
			||||||
 | 
					        fields = resource.fields
 | 
				
			||||||
 | 
					        field_labels = resource.labels
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        fields = res_fields.VOLUME_CONNECTOR_RESOURCE.fields
 | 
				
			||||||
 | 
					        field_labels = res_fields.VOLUME_CONNECTOR_RESOURCE.labels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sort_fields = res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.sort_fields
 | 
				
			||||||
 | 
					    sort_field_labels = (
 | 
				
			||||||
 | 
					        res_fields.VOLUME_CONNECTOR_DETAILED_RESOURCE.sort_labels)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    params.update(utils.common_params_for_list(args,
 | 
				
			||||||
 | 
					                                               sort_fields,
 | 
				
			||||||
 | 
					                                               sort_field_labels))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    volume_connector = cc.volume_connector.list(**params)
 | 
				
			||||||
 | 
					    cliutils.print_list(volume_connector, fields,
 | 
				
			||||||
 | 
					                        field_labels=field_labels,
 | 
				
			||||||
 | 
					                        sortby_index=None,
 | 
				
			||||||
 | 
					                        json_flag=args.json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '-e', '--extra',
 | 
				
			||||||
 | 
					    metavar="<key=value>",
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    help=_("Record arbitrary key/value metadata. "
 | 
				
			||||||
 | 
					           "Can be specified multiple times."))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '-n', '--node',
 | 
				
			||||||
 | 
					    dest='node_uuid',
 | 
				
			||||||
 | 
					    metavar='<node>',
 | 
				
			||||||
 | 
					    required=True,
 | 
				
			||||||
 | 
					    help=_('UUID of the node that this volume connector belongs to.'))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '-t', '--type',
 | 
				
			||||||
 | 
					    metavar="<type>",
 | 
				
			||||||
 | 
					    required=True,
 | 
				
			||||||
 | 
					    choices=['iqn', 'ip', 'mac', 'wwnn', 'wwpn'],
 | 
				
			||||||
 | 
					    help=_("Type of the volume connector. Can be 'iqn', 'ip', 'mac', 'wwnn', "
 | 
				
			||||||
 | 
					           "'wwpn'."))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '-i', '--connector_id',
 | 
				
			||||||
 | 
					    metavar="<connector id>",
 | 
				
			||||||
 | 
					    required=True,
 | 
				
			||||||
 | 
					    help=_("ID of the Volume connector in the specified type."))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    '-u', '--uuid',
 | 
				
			||||||
 | 
					    metavar='<uuid>',
 | 
				
			||||||
 | 
					    help=_("UUID of the volume connector."))
 | 
				
			||||||
 | 
					def do_volume_connector_create(cc, args):
 | 
				
			||||||
 | 
					    """Create a new volume connector."""
 | 
				
			||||||
 | 
					    field_list = ['extra', 'type', 'connector_id', 'node_uuid', 'uuid']
 | 
				
			||||||
 | 
					    fields = dict((k, v) for (k, v) in vars(args).items()
 | 
				
			||||||
 | 
					                  if k in field_list and not (v is None))
 | 
				
			||||||
 | 
					    fields = utils.args_array_to_dict(fields, 'extra')
 | 
				
			||||||
 | 
					    volume_connector = cc.volume_connector.create(**fields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data = dict([(f, getattr(volume_connector, f, '')) for f in field_list])
 | 
				
			||||||
 | 
					    cliutils.print_dict(data, wrap=72, json_flag=args.json)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('volume_connector', metavar='<volume connector>', nargs='+',
 | 
				
			||||||
 | 
					              help=_("UUID of the volume connector."))
 | 
				
			||||||
 | 
					def do_volume_connector_delete(cc, args):
 | 
				
			||||||
 | 
					    """Delete a volume connector."""
 | 
				
			||||||
 | 
					    failures = []
 | 
				
			||||||
 | 
					    for vc in args.volume_connector:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            cc.volume_connector.delete(vc)
 | 
				
			||||||
 | 
					            print(_('Deleted volume connector %s') % vc)
 | 
				
			||||||
 | 
					        except exceptions.ClientException as e:
 | 
				
			||||||
 | 
					            failures.append(_("Failed to delete volume connector %(vc)s: "
 | 
				
			||||||
 | 
					                              "%(error)s")
 | 
				
			||||||
 | 
					                            % {'vc': vc, 'error': e})
 | 
				
			||||||
 | 
					    if failures:
 | 
				
			||||||
 | 
					        raise exceptions.ClientException("\n".join(failures))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@cliutils.arg('volume_connector', metavar='<volume connector>',
 | 
				
			||||||
 | 
					              help=_("UUID of the volume connector."))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'op',
 | 
				
			||||||
 | 
					    metavar='<op>',
 | 
				
			||||||
 | 
					    choices=['add', 'replace', 'remove'],
 | 
				
			||||||
 | 
					    help=_("Operation: 'add', 'replace', or 'remove'."))
 | 
				
			||||||
 | 
					@cliutils.arg(
 | 
				
			||||||
 | 
					    'attributes',
 | 
				
			||||||
 | 
					    metavar='<path=value>',
 | 
				
			||||||
 | 
					    nargs='+',
 | 
				
			||||||
 | 
					    action='append',
 | 
				
			||||||
 | 
					    default=[],
 | 
				
			||||||
 | 
					    help=_("Attribute to add, replace, or remove. Can be specified multiple "
 | 
				
			||||||
 | 
					           "times. For 'remove', only <path> is necessary."))
 | 
				
			||||||
 | 
					def do_volume_connector_update(cc, args):
 | 
				
			||||||
 | 
					    """Update information about a volume connector."""
 | 
				
			||||||
 | 
					    patch = utils.args_array_to_patch(args.op, args.attributes[0])
 | 
				
			||||||
 | 
					    volume_connector = cc.volume_connector.update(args.volume_connector, patch)
 | 
				
			||||||
 | 
					    _print_volume_connector_show(volume_connector, json=args.json)
 | 
				
			||||||
@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					features:
 | 
				
			||||||
 | 
					  - |
 | 
				
			||||||
 | 
					    Adds these Ironic CLI commands for volume connector resources:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    * ``ironic volume-connector-create``
 | 
				
			||||||
 | 
					    * ``ironic volume-connector-list``
 | 
				
			||||||
 | 
					    * ``ironic volume-connector-show``
 | 
				
			||||||
 | 
					    * ``ironic volume-connector-update``
 | 
				
			||||||
 | 
					    * ``ironic volume-connector-delete``
 | 
				
			||||||
		Reference in New Issue
	
	Block a user