From 3e3dc6a8a1076adeb464c6d7ed0a158aafc0c884 Mon Sep 17 00:00:00 2001 From: liusheng Date: Tue, 25 Jul 2017 12:49:53 +0800 Subject: [PATCH] Improve flavor set command to support updating flavor For now, "flavor set" command only support to add flavor accesses, this change add support to updating flavor other attributes for this command. Change-Id: If32a46decebee62695f4e4f7f51c2fafbb64b5bf --- moganclient/osc/v1/flavor.py | 114 +++++++++++-------- moganclient/tests/unit/fakes.py | 2 +- moganclient/tests/unit/osc/v1/test_flavor.py | 38 +++++++ moganclient/v1/flavor.py | 4 + 4 files changed, 112 insertions(+), 46 deletions(-) diff --git a/moganclient/osc/v1/flavor.py b/moganclient/osc/v1/flavor.py index daf2e98..b6bc1b5 100644 --- a/moganclient/osc/v1/flavor.py +++ b/moganclient/osc/v1/flavor.py @@ -22,6 +22,7 @@ from osc_lib.cli import parseractions from osc_lib.command import command from osc_lib import exceptions from osc_lib import utils +from oslo_utils import strutils from moganclient.common.i18n import _ @@ -164,50 +165,6 @@ class ListFlavor(command.Lister): ) for s in data)) -class SetFlavor(command.Command): - """Set baremetal flavor properties""" - - def get_parser(self, prog_name): - parser = super(SetFlavor, self).get_parser(prog_name) - parser.add_argument( - 'flavor', - metavar='', - help=_("Flavor to modify (name or UUID)") - ) - parser.add_argument( - '--project', - metavar='', - help=_('Set flavor access to project (name or ID) ' - '(admin only)'), - ) - return parser - - def take_action(self, parsed_args): - - bc_client = self.app.client_manager.baremetal_compute - data = utils.find_resource( - bc_client.flavor, - parsed_args.flavor, - ) - - result = 0 - if parsed_args.project: - try: - if data.is_public: - msg = _("Cannot set access for a public flavor") - raise exceptions.CommandError(msg) - else: - bc_client.flavor.add_tenant_access( - data, parsed_args.project) - except Exception as e: - LOG.error("Failed to set flavor access to project: %s", e) - result += 1 - - if result > 0: - raise exceptions.CommandError(_("Command Failed: One or more of" - " the operations failed")) - - class ShowFlavor(command.ShowOne): """Display baremetal flavor details""" @@ -226,12 +183,79 @@ class ShowFlavor(command.ShowOne): bc_client.flavor, parsed_args.flavor, ) - info = {} info.update(data._info) return zip(*sorted(info.items())) +class SetFlavor(command.Command): + """Set baremetal flavor properties""" + + def get_parser(self, prog_name): + parser = super(SetFlavor, self).get_parser(prog_name) + parser.add_argument( + 'flavor', + metavar='', + help=_("Flavor to modify (name or UUID)") + ) + parser.add_argument( + '--project', + metavar='', + help=_('Set flavor access to project (name or ID) ' + '(admin only)'), + ) + parser.add_argument( + '--name', + metavar='', + help=_('Set a new name to a flavor (admin only)') + ) + parser.add_argument( + '--is-public', + metavar='', + type=strutils.bool_from_string, + help=_('Set a flavor to be public or private ' + '(admin only)'), + ) + parser.add_argument( + '--disabled', + metavar='', + type=strutils.bool_from_string, + help=_('Set a flavor to be disabled or enabled ' + '(admin only)'), + ) + return parser + + def take_action(self, parsed_args): + + bc_client = self.app.client_manager.baremetal_compute + data = utils.find_resource( + bc_client.flavor, + parsed_args.flavor, + ) + updates = [] + if parsed_args.name: + updates.append({"op": "replace", + "path": "/name", + "value": parsed_args.name}) + if parsed_args.is_public is not None: + updates.append({"op": "replace", + "path": "/is_public", + "value": parsed_args.is_public}) + if parsed_args.disabled is not None: + updates.append({"op": "replace", + "path": "/disabled", + "value": parsed_args.disabled}) + if updates: + bc_client.flavor.update(data, updates) + if parsed_args.project: + if data.is_public: + msg = _("Cannot set access for a public flavor") + raise exceptions.CommandError(msg) + else: + bc_client.flavor.add_tenant_access( + data, parsed_args.project) + + class UnsetFlavor(command.Command): """Unset baremetal flavor properties""" diff --git a/moganclient/tests/unit/fakes.py b/moganclient/tests/unit/fakes.py index 6fa0080..35ac4e6 100644 --- a/moganclient/tests/unit/fakes.py +++ b/moganclient/tests/unit/fakes.py @@ -171,7 +171,7 @@ class FakeFlavor(object): "description": "fake_description", "resources": {"BAREMETAL_GOLD": 1}, "resource_traits": {"BAREMETAL_GOLD": "FPGA"}, - "is_public": True, + "is_public": False, "disabled": False, "name": "flavor-name-" + uuidutils.generate_uuid(dashed=False), "updated_at": None, diff --git a/moganclient/tests/unit/osc/v1/test_flavor.py b/moganclient/tests/unit/osc/v1/test_flavor.py index 8bd739c..48c7df4 100644 --- a/moganclient/tests/unit/osc/v1/test_flavor.py +++ b/moganclient/tests/unit/osc/v1/test_flavor.py @@ -273,3 +273,41 @@ class TestFlavorShow(TestFlavor): mock_get.assert_called_once_with(expected_url) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + + +@mock.patch.object(utils, 'find_resource') +@mock.patch.object(flavor_mgr.FlavorManager, '_update') +class TestFlavorSet(TestFlavor): + def setUp(self): + super(TestFlavorSet, self).setUp() + self.cmd = flavor.SetFlavor(self.app, None) + + @mock.patch.object(flavor_mgr.FlavorManager, '_create') + def test_flavor_set(self, mock_create, mock_update, mock_find): + mock_find.return_value = self.fake_flavor + arglist = [ + '--project', 'fake_project', + '--name', 'new_name', + '--disabled', 'false', + '--is-public', 'false', + self.fake_flavor.uuid, + ] + verifylist = [ + ('flavor', self.fake_flavor.uuid), + ('disabled', False), + ('is_public', False), + ('name', 'new_name'), + ('project', 'fake_project'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + self.cmd.take_action(parsed_args) + expected_url = '/flavors/%s' % parsed_args.flavor + expected_args = [ + {'path': '/name', 'value': 'new_name', 'op': 'replace'}, + {'path': '/is_public', 'value': False, 'op': 'replace'}, + {'path': '/disabled', 'value': False, 'op': 'replace'}, + ] + mock_update.assert_called_once_with(expected_url, expected_args) + expected_url += '/access' + mock_create.assert_called_once_with( + expected_url, data={'tenant_id': 'fake_project'}) diff --git a/moganclient/v1/flavor.py b/moganclient/v1/flavor.py index 1750dbb..3331d49 100644 --- a/moganclient/v1/flavor.py +++ b/moganclient/v1/flavor.py @@ -50,6 +50,10 @@ class FlavorManager(base.ManagerWithFind): url = '/flavors' return self._list(url, response_key='flavors') + def update(self, flavor, data): + url = '/flavors/%s' % base.getid(flavor) + return self._update(url, data) + def add_tenant_access(self, flavor, project): url = '/flavors/%s/access' % base.getid(flavor) return self._create(url, data={'tenant_id': project})