diff --git a/doc/source/command-objects/flavor.rst b/doc/source/command-objects/flavor.rst index a30bedecb6..11efaa6f02 100644 --- a/doc/source/command-objects/flavor.rst +++ b/doc/source/command-objects/flavor.rst @@ -21,6 +21,8 @@ Create new flavor [--vcpus ] [--rxtx-factor ] [--public | --private] + [--project ] + [--project-domain ] .. option:: --id @@ -59,6 +61,16 @@ Create new flavor Flavor is not available to other projects +.. option:: --project + + Allow to access private flavor (name or ID) + (Must be used with :option:`--private` option) + +.. option:: --project-domain + + Domain the project belongs to (name or ID). + This can be used in case collisions between project names exist. + .. _flavor_create-flavor-name: .. describe:: diff --git a/openstackclient/compute/v2/flavor.py b/openstackclient/compute/v2/flavor.py index 0a0d25c2de..49cc4e367b 100644 --- a/openstackclient/compute/v2/flavor.py +++ b/openstackclient/compute/v2/flavor.py @@ -121,10 +121,22 @@ class CreateFlavor(command.ShowOne): action="store_false", help=_("Flavor is not available to other projects") ) + parser.add_argument( + '--project', + metavar='', + help=_("Allow to access private flavor (name or ID) " + "(Must be used with --private option)"), + ) + identity_common.add_project_domain_option_to_parser(parser) return parser def take_action(self, parsed_args): compute_client = self.app.client_manager.compute + identity_client = self.app.client_manager.identity + + if parsed_args.project and parsed_args.public: + msg = _("--project is only allowed with --private") + raise exceptions.CommandError(msg) args = ( parsed_args.name, @@ -141,6 +153,20 @@ class CreateFlavor(command.ShowOne): flavor = compute_client.flavors.create(*args)._info.copy() flavor.pop("links") + if parsed_args.project: + try: + project_id = identity_common.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, + ).id + compute_client.flavor_access.add_tenant_access( + parsed_args.id, project_id) + except Exception as e: + msg = _("Failed to add project %(project)s access to " + "flavor: %(e)s") + LOG.error(msg % {'project': parsed_args.project, 'e': e}) + return zip(*sorted(six.iteritems(flavor))) diff --git a/openstackclient/tests/compute/v2/test_flavor.py b/openstackclient/tests/compute/v2/test_flavor.py index 4365a540bc..c25d243133 100644 --- a/openstackclient/tests/compute/v2/test_flavor.py +++ b/openstackclient/tests/compute/v2/test_flavor.py @@ -75,6 +75,12 @@ class TestFlavorCreate(TestFlavor): def setUp(self): super(TestFlavorCreate, self).setUp() + # Return a project + self.projects_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.PROJECT), + loaded=True, + ) self.flavors_mock.create.return_value = self.flavor self.cmd = flavor.CreateFlavor(self.app, None) @@ -161,6 +167,7 @@ class TestFlavorCreate(TestFlavor): '--vcpus', str(self.flavor.vcpus), '--rxtx-factor', str(self.flavor.rxtx_factor), '--private', + '--project', identity_fakes.project_id, ] verifylist = [ ('name', self.flavor.name), @@ -172,6 +179,7 @@ class TestFlavorCreate(TestFlavor): ('vcpus', self.flavor.vcpus), ('rxtx_factor', self.flavor.rxtx_factor), ('public', False), + ('project', identity_fakes.project_id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -188,10 +196,28 @@ class TestFlavorCreate(TestFlavor): ) columns, data = self.cmd.take_action(parsed_args) self.flavors_mock.create.assert_called_once_with(*args) - + self.flavor_access_mock.add_tenant_access.assert_called_with( + self.flavor.id, + identity_fakes.project_id, + ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_public_flavor_create_with_project(self): + arglist = [ + '--project', identity_fakes.project_id, + self.flavor.name, + ] + verifylist = [ + ('project', identity_fakes.project_id), + ('name', self.flavor.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises(exceptions.CommandError, + self.cmd.take_action, + parsed_args) + def test_flavor_create_no_options(self): arglist = [] verifylist = None diff --git a/releasenotes/notes/flavor-create-with-project-19d41bfa93e3c6d0.yaml b/releasenotes/notes/flavor-create-with-project-19d41bfa93e3c6d0.yaml new file mode 100644 index 0000000000..312dece847 --- /dev/null +++ b/releasenotes/notes/flavor-create-with-project-19d41bfa93e3c6d0.yaml @@ -0,0 +1,5 @@ +--- +features: + - Add ``--project`` and ``--project-domain`` options to the ``flavor create`` + command. We can use these options to add the flavor access to a given project + when we create the flavor.