Add datastore flavor association support
Trove currently supports associating flavors with datastore versions through trove-manage, which requires direct access to the Trove control plane. This is unsuitable for deployments where datastore version maintenance is automated through API workflows or control plane access is restricted. Add --flavors and --remove-flavors options to the openstack datastore version set command. These options allow operators to manage datastore version flavor associations through the Trove management API. Depends-On: https://review.opendev.org/c/openstack/trove/+/997965 Change-Id: I0507623b4fa5ce045c9808e790428590565be17a Signed-off-by: Olessya Khussainova <freckled.cellofun@gmail.com>
This commit is contained in:
1 parent
44ca384d8a
commit
2e1e050276
5 files changed
+105
-2
No files matched your search
@@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds ``--flavors`` and ``--remove-flavors`` options to the
|
||||
``openstack datastore version set`` command for adding and removing
|
||||
datastore version flavor associations.
|
||||
@@ -317,6 +317,17 @@ class UpdateDatastoreVersion(command.Command):
|
||||
default=None,
|
||||
action='store_const',
|
||||
const='false')
|
||||
flavor_group = parser.add_mutually_exclusive_group()
|
||||
flavor_group.add_argument('--flavors', dest='flavor_ids',
|
||||
metavar='<flavor_ids>',
|
||||
nargs='+',
|
||||
default=None,
|
||||
help=_('Flavor IDs to associate.'))
|
||||
flavor_group.add_argument('--remove-flavors',
|
||||
metavar='<flavor_ids>',
|
||||
nargs='+',
|
||||
default=None,
|
||||
help=_('Flavor IDs to disassociate.'))
|
||||
volume_type_group = parser.add_mutually_exclusive_group()
|
||||
volume_type_group.add_argument('--volume-types',
|
||||
dest='volume_type_ids',
|
||||
@@ -353,6 +364,15 @@ class UpdateDatastoreVersion(command.Command):
|
||||
name=parsed_args.version_name
|
||||
)
|
||||
|
||||
if parsed_args.flavor_ids is not None:
|
||||
client.add_flavors(
|
||||
parsed_args.datastore_version_id,
|
||||
parsed_args.flavor_ids)
|
||||
elif parsed_args.remove_flavors is not None:
|
||||
for flavor_id in parsed_args.remove_flavors:
|
||||
client.delete_flavor(
|
||||
parsed_args.datastore_version_id, flavor_id)
|
||||
|
||||
if parsed_args.volume_type_ids is not None:
|
||||
client.add_volume_types(
|
||||
parsed_args.datastore_version_id,
|
||||
@@ -360,8 +380,8 @@ class UpdateDatastoreVersion(command.Command):
|
||||
elif parsed_args.remove_volume_types is not None:
|
||||
for volume_type_id in parsed_args.remove_volume_types:
|
||||
client.delete_volume_type(
|
||||
parsed_args.datastore_version_id,
|
||||
volume_type_id)
|
||||
parsed_args.datastore_version_id, volume_type_id)
|
||||
|
||||
except Exception as e:
|
||||
msg = (_("Failed to update datastore version %(version)s: %(e)s")
|
||||
% {'version': parsed_args.datastore_version_id, 'e': e})
|
||||
|
||||
@@ -202,6 +202,29 @@ class TestUpdateDatastoreVersion(TestDatastores):
|
||||
registry_ext="registry-ext",
|
||||
repl_strategy="repl_strategy", name=None)
|
||||
|
||||
def test_update_datastore_version_flavors(self):
|
||||
version_id = uuidutils.generate_uuid()
|
||||
args = [version_id, '--flavors', 'flavor-1', 'flavor-2']
|
||||
parsed_args = self.check_parser(self.cmd, args, [])
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
self.dsversion_mgmt_client.add_flavors.assert_called_once_with(
|
||||
version_id, ['flavor-1', 'flavor-2'])
|
||||
|
||||
def test_update_datastore_version_remove_flavors(self):
|
||||
version_id = uuidutils.generate_uuid()
|
||||
args = [version_id, '--remove-flavors', 'flavor-1', 'flavor-2']
|
||||
parsed_args = self.check_parser(self.cmd, args, [])
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
self.dsversion_mgmt_client.delete_flavor.assert_has_calls([
|
||||
mock.call(version_id, 'flavor-1'),
|
||||
mock.call(version_id, 'flavor-2')])
|
||||
self.assertEqual(
|
||||
2, self.dsversion_mgmt_client.delete_flavor.call_count)
|
||||
|
||||
def test_update_datastore_version_volume_types(self):
|
||||
version_id = uuidutils.generate_uuid()
|
||||
args = [version_id, '--volume-types', 'type-1', 'type-2']
|
||||
|
||||
@@ -294,6 +294,37 @@ class MgmtDatastoreVersionsTest(testtools.TestCase):
|
||||
self.assertRaises(Exception, self.ds_version.edit, 'ds-version-1',
|
||||
"new-mgr", "non-existent-image")
|
||||
|
||||
def test_list_flavors(self):
|
||||
resp = mock.Mock(status_code=200)
|
||||
self.ds_version.api.client.get.return_value = (
|
||||
resp, {'flavor_ids': ['flavor-1', 'flavor-2']})
|
||||
|
||||
result = self.ds_version.list_flavors('ds-version-1')
|
||||
|
||||
self.assertEqual(['flavor-1', 'flavor-2'], result)
|
||||
self.ds_version.api.client.get.assert_called_once_with(
|
||||
'/mgmt/datastore-versions/ds-version-1/flavors')
|
||||
|
||||
def test_add_flavors(self):
|
||||
self.ds_version.api.client.post = self._get_mock_method()
|
||||
self._resp.status_code = 202
|
||||
self.ds_version.add_flavors(
|
||||
'ds-version-1', flavor_ids=['flavor-1', 'flavor-2'])
|
||||
self.assertEqual(
|
||||
'/mgmt/datastore-versions/ds-version-1/flavors',
|
||||
self._url)
|
||||
self.assertEqual({'flavor_ids': ['flavor-1', 'flavor-2']}, self._body)
|
||||
|
||||
def test_delete_flavor(self):
|
||||
self.ds_version.api.client.delete = self._get_mock_method()
|
||||
self._resp.status_code = 204
|
||||
|
||||
self.ds_version.delete_flavor('ds-version-1', 'flavor-1')
|
||||
|
||||
self.assertEqual(
|
||||
'/mgmt/datastore-versions/ds-version-1/flavors/flavor-1',
|
||||
self._url)
|
||||
|
||||
def test_list_volume_types(self):
|
||||
resp = mock.Mock(status_code=200)
|
||||
self.ds_version.api.client.get.return_value = (
|
||||
|
||||
@@ -347,6 +347,29 @@ class MgmtDatastoreVersions(base.ManagerWithFind):
|
||||
resp, body = self.api.client.delete(url)
|
||||
common.check_for_exceptions(resp, body, url)
|
||||
|
||||
def list_flavors(self, datastore_version_id):
|
||||
"""List flavor associations for a datastore version."""
|
||||
url = "/mgmt/datastore-versions/%s/flavors" % datastore_version_id
|
||||
resp, body = self.api.client.get(url)
|
||||
common.check_for_exceptions(resp, body, url)
|
||||
return body['flavor_ids']
|
||||
|
||||
def add_flavors(self, datastore_version_id, flavor_ids):
|
||||
"""Add flavor associations to a datastore version."""
|
||||
body = {
|
||||
'flavor_ids': flavor_ids
|
||||
}
|
||||
url = "/mgmt/datastore-versions/%s/flavors" % datastore_version_id
|
||||
resp, body = self.api.client.post(url, body=body)
|
||||
common.check_for_exceptions(resp, body, url)
|
||||
|
||||
def delete_flavor(self, datastore_version_id, flavor_id):
|
||||
"""Delete a flavor association from a datastore version."""
|
||||
url = "/mgmt/datastore-versions/%s/flavors/%s" % (
|
||||
datastore_version_id, flavor_id)
|
||||
resp, body = self.api.client.delete(url)
|
||||
common.check_for_exceptions(resp, body, url)
|
||||
|
||||
def list_volume_types(self, datastore_version_id):
|
||||
"""List volume type associations for a datastore version."""
|
||||
url = "/mgmt/datastore-versions/%s/volume-types" % (
|
||||
|
||||
Reference in new issue
Block a user