From 8bea4a1c56e67a826f66c642678ef3a429ee9c8a Mon Sep 17 00:00:00 2001 From: Alexander Saprykin Date: Thu, 24 Mar 2016 10:50:31 +0200 Subject: [PATCH] Add support of bulk operations for openstack-config * Add multiple node filter for openstack-config list * Allow upload config for multiple nodes * Allow execute config for multiple nodes Related-Bug: #1557462 Change-Id: I3d964be1dcf1745ab1634b946850c3294fa799d5 (cherry-picked from 54439bbaa346a84e097986b28bed8e076ce292a5) --- fuelclient/cli/actions/openstack_config.py | 19 ++++---- fuelclient/objects/openstack_config.py | 5 +++ .../tests/unit/v1/test_openstack_config.py | 44 ++++++++++++++++++- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/fuelclient/cli/actions/openstack_config.py b/fuelclient/cli/actions/openstack_config.py index 65e77b4..7ed1c11 100644 --- a/fuelclient/cli/actions/openstack_config.py +++ b/fuelclient/cli/actions/openstack_config.py @@ -32,7 +32,7 @@ class OpenstackConfigAction(Action): self.args = ( Args.get_env_arg(), Args.get_file_arg("Openstack configuration file"), - Args.get_single_node_arg("Node ID"), + Args.get_node_arg("Node IDs list"), Args.get_single_role_arg("Node role"), Args.get_config_id_arg("Openstack config ID"), Args.get_deleted_arg("Get deleted configurations"), @@ -60,7 +60,7 @@ class OpenstackConfigAction(Action): def list(self, params): """List all available configurations: fuel openstack-config --list --env 1 - fuel openstack-config --list --env 1 --node 1 + fuel openstack-config --list --env 1 --node 1[,2,3,...] fuel openstack-config --list --env 1 --deleted """ filters = {'cluster_id': params.env} @@ -69,7 +69,7 @@ class OpenstackConfigAction(Action): filters['is_active'] = int(not params.deleted) if 'node' in params: - filters['node_id'] = params.node + filters['node_ids'] = params.node if 'role' in params: filters['node_role'] = params.role @@ -99,18 +99,19 @@ class OpenstackConfigAction(Action): def upload(self, params): """Upload new configuration from file: fuel openstack-config --upload --env 1 --file config.yaml - fuel openstack-config --upload --env 1 --node 1 --file config.yaml + fuel openstack-config --upload --env 1 --node 1[,2,3,...] + --file config.yaml fuel openstack-config --upload --env 1 --role controller --file config.yaml """ - node_id = getattr(params, 'node', None) + node_ids = getattr(params, 'node', None) node_role = getattr(params, 'role', None) data = OpenstackConfig.read_file(params.file) config = OpenstackConfig.create( cluster_id=params.env, configuration=data['configuration'], - node_id=node_id, node_role=node_role) + node_ids=node_ids, node_role=node_role) print("Openstack configuration with id {0} " "has been uploaded from file '{1}'" "".format(config.id, params.file)) @@ -130,15 +131,15 @@ class OpenstackConfigAction(Action): def execute(self, params): """Deploy configuration: fuel openstack-config --execute --env 1 - fuel openstack-config --execute --env 1 --node 1 + fuel openstack-config --execute --env 1 --node 1[,2,3,...] fuel openstack-config --execute --env 1 --role controller fuel openstack-config --execute --env 1 --force """ - node_id = getattr(params, 'node', None) + node_ids = getattr(params, 'node', None) node_role = getattr(params, 'role', None) force = getattr(params, 'force', False) task_result = OpenstackConfig.execute( - cluster_id=params.env, node_id=node_id, + cluster_id=params.env, node_ids=node_ids, node_role=node_role, force=force) if task_result['status'] == 'error': print( diff --git a/fuelclient/objects/openstack_config.py b/fuelclient/objects/openstack_config.py index e1ac3b2..c568354 100644 --- a/fuelclient/objects/openstack_config.py +++ b/fuelclient/objects/openstack_config.py @@ -50,6 +50,11 @@ class OpenstackConfig(BaseObject): def get_filtered_data(cls, **kwargs): url = cls.class_api_path params = cls._prepare_params(kwargs) + + node_ids = params.get('node_ids') + if node_ids is not None: + params['node_ids'] = ','.join([str(n) for n in node_ids]) + return cls.connection.get_request(url, params=params) @classmethod diff --git a/fuelclient/tests/unit/v1/test_openstack_config.py b/fuelclient/tests/unit/v1/test_openstack_config.py index 0365661..f4c500e 100644 --- a/fuelclient/tests/unit/v1/test_openstack_config.py +++ b/fuelclient/tests/unit/v1/test_openstack_config.py @@ -72,6 +72,27 @@ class TestOpenstackConfigActions(base.UnitTestCase): '--upload', '--file', 'config.yaml']) self.assertTrue(m_post.called) + req = json.loads(m_post.last_request.text) + self.assertEqual(req['cluster_id'], 1) + + def test_config_upload_multinode(self): + m_post = self.m_request.post( + '/api/v1/openstack-config/', json=self.config) + + m_open = mock.mock_open(read_data=yaml.safe_dump( + {'configuration': self.config['configuration']})) + with mock.patch('fuelclient.cli.serializers.open', + m_open, create=True): + with mock.patch('fuelclient.objects.openstack_config.os'): + self.execute(['fuel', 'openstack-config', '--env', '1', + '--node', '1,2,3', + '--upload', '--file', 'config.yaml']) + self.assertTrue(m_post.called) + + req = json.loads(m_post.last_request.text) + self.assertEqual(req['node_ids'], [1, 2, 3]) + self.assertEqual(req['cluster_id'], 1) + @mock.patch('sys.stderr') def test_config_upload_fail(self, mocked_stderr): self.assertRaises( @@ -107,13 +128,23 @@ class TestOpenstackConfigActions(base.UnitTestCase): self.assertTrue(m_get.called) m_get = self.m_request.get( - '/api/v1/openstack-config/?cluster_id=84&node_id=42', json=[ + '/api/v1/openstack-config/?cluster_id=84&node_ids=42', json=[ utils.get_fake_openstack_config(id=1, cluster_id=32), ]) self.execute(['fuel', 'openstack-config', '--env', '84', '--node', '42', '--list']) self.assertTrue(m_get.called) + def test_config_list_multinode(self): + m_get = self.m_request.get( + '/api/v1/openstack-config/?cluster_id=84&node_ids=1,2,3', + json=[utils.get_fake_openstack_config( + id=1, cluster_id=32, node_id=1)]) + + self.execute(['fuel', 'openstack-config', '--env', '84', + '--node', '1,2,3', '--list']) + self.assertTrue(m_get.called) + @mock.patch('sys.stderr') def test_config_list_fail(self, m_stderr): self.assertRaises( @@ -137,6 +168,17 @@ class TestOpenstackConfigActions(base.UnitTestCase): self.assertEqual({"cluster_id": 42, "force": False}, json.loads(m_put.last_request.text)) + def test_config_execute_multinode(self): + m_put = self.m_request.put('/api/v1/openstack-config/execute/', + json={'status': 'ready'}) + + self.execute(['fuel', 'openstack-config', '--env', '42', + '--node', '1,2,3', '--execute']) + self.assertTrue(m_put.called) + self.assertEqual( + {"cluster_id": 42, "force": False, "node_ids": [1, 2, 3]}, + json.loads(m_put.last_request.text)) + def test_config_force_execute(self): m_put = self.m_request.put('/api/v1/openstack-config/execute/', json={'status': 'ready'})