summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingxian Kong <anlin.kong@gmail.com>2020-07-12 21:48:29 +1200
committerLingxian Kong <anlin.kong@gmail.com>2020-07-16 23:03:53 +1200
commit40af5562643856efad8717698511e613b4b142d4 (patch)
tree9cf69c00f4dc5fbea365d18571c1ed5afb12d082
parenta05020128dda73f912f37f97fd609242fd76e448 (diff)
downloadpython-troveclient-40af5562643856efad8717698511e613b4b142d4.tar.gz
Support backup strategy
Change-Id: Ic8c20109b287f2f9220379cb249669d18b52893d
-rw-r--r--releasenotes/notes/victoria-backup-strategy.yaml3
-rw-r--r--setup.cfg3
-rw-r--r--troveclient/base.py1
-rw-r--r--troveclient/osc/v1/database_backup_strategy.py105
-rw-r--r--troveclient/osc/v1/database_backups.py22
-rw-r--r--troveclient/tests/osc/v1/test_database_backup_strategy.py89
-rw-r--r--troveclient/tests/osc/v1/test_database_backups.py6
-rw-r--r--troveclient/v1/backup_strategy.py60
-rw-r--r--troveclient/v1/backups.py5
-rw-r--r--troveclient/v1/client.py2
10 files changed, 288 insertions, 8 deletions
diff --git a/releasenotes/notes/victoria-backup-strategy.yaml b/releasenotes/notes/victoria-backup-strategy.yaml
new file mode 100644
index 0000000..e40a842
--- /dev/null
+++ b/releasenotes/notes/victoria-backup-strategy.yaml
@@ -0,0 +1,3 @@
+---
+features:
+ - Support backup strategy CLI.
diff --git a/setup.cfg b/setup.cfg
index 36e5bbf..b87e50d 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -104,3 +104,6 @@ openstack.database.v1 =
datastore_version_list = troveclient.osc.v1.datastores:ListDatastoreVersions
datastore_version_show = troveclient.osc.v1.datastores:ShowDatastoreVersion
datastore_version_delete = troveclient.osc.v1.datastores:DeleteDatastoreVersion
+ database_backup_strategy_list = troveclient.osc.v1.database_backup_strategy:ListDatabaseBackupStrategies
+ database_backup_strategy_create = troveclient.osc.v1.database_backup_strategy:CreateDatabaseBackupStrategy
+ database_backup_strategy_delete = troveclient.osc.v1.database_backup_strategy:DeleteDatabaseBackupStrategy
diff --git a/troveclient/base.py b/troveclient/base.py
index 7af8668..950ab2e 100644
--- a/troveclient/base.py
+++ b/troveclient/base.py
@@ -187,6 +187,7 @@ class Manager(utils.HookableMixin):
def _delete(self, url):
resp, body = self.api.client.delete(url)
+ return resp, body
def _update(self, url, body, **kwargs):
self.run_hooks('modify_body_for_update', body, **kwargs)
diff --git a/troveclient/osc/v1/database_backup_strategy.py b/troveclient/osc/v1/database_backup_strategy.py
new file mode 100644
index 0000000..db36709
--- /dev/null
+++ b/troveclient/osc/v1/database_backup_strategy.py
@@ -0,0 +1,105 @@
+# Copyright 2020 Catalyst Cloud
+#
+# 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 osc_lib.command import command
+from osc_lib import utils as osc_utils
+
+from troveclient.i18n import _
+
+
+class ListDatabaseBackupStrategies(command.Lister):
+ _description = _("List backup strategies")
+ columns = ['Project ID', 'Instance ID', 'Swift Container']
+
+ def get_parser(self, prog_name):
+ parser = super(ListDatabaseBackupStrategies, self).get_parser(
+ prog_name)
+
+ parser.add_argument(
+ '--instance-id',
+ help=_('Filter results by database instance ID.')
+ )
+ parser.add_argument(
+ '--project-id',
+ help=_('Project ID in Keystone. Only admin user is allowed to '
+ 'list backup strategy for other projects.')
+ )
+
+ return parser
+
+ def take_action(self, parsed_args):
+ manager = self.app.client_manager.database.backup_strategies
+ result = manager.list(instance_id=parsed_args.instance_id,
+ project_id=parsed_args.project_id)
+ backup_strategies = [osc_utils.get_item_properties(item, self.columns)
+ for item in result]
+
+ return self.columns, backup_strategies
+
+
+class CreateDatabaseBackupStrategy(command.ShowOne):
+ _description = _("Creates backup strategy for the project or a particular "
+ "instance.")
+
+ def get_parser(self, prog_name):
+ parser = super(CreateDatabaseBackupStrategy, self).get_parser(
+ prog_name)
+
+ parser.add_argument(
+ '--project-id',
+ help=_('Project ID in Keystone. Only admin user is allowed to '
+ 'create backup strategy for other projects.')
+ )
+ parser.add_argument(
+ '--instance-id',
+ help=_('Database instance ID.')
+ )
+ parser.add_argument(
+ '--swift-container',
+ help=_('The container name for storing the backup data when Swift '
+ 'is used as backup storage backend.')
+ )
+
+ return parser
+
+ def take_action(self, parsed_args):
+ manager = self.app.client_manager.database.backup_strategies
+ result = manager.create(
+ instance_id=parsed_args.instance_id,
+ swift_container=parsed_args.swift_container
+ )
+ return zip(*sorted(result.to_dict().items()))
+
+
+class DeleteDatabaseBackupStrategy(command.Command):
+ _description = _("Deletes backup strategy.")
+
+ def get_parser(self, prog_name):
+ parser = super(DeleteDatabaseBackupStrategy, self).get_parser(
+ prog_name)
+ parser.add_argument(
+ '--project-id',
+ help=_('Project ID in Keystone. Only admin user is allowed to '
+ 'delete backup strategy for other projects.')
+ )
+ parser.add_argument(
+ '--instance-id',
+ help=_('Database instance ID.')
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ manager = self.app.client_manager.database.backup_strategies
+ manager.delete(instance_id=parsed_args.instance_id,
+ project_id=parsed_args.project_id)
diff --git a/troveclient/osc/v1/database_backups.py b/troveclient/osc/v1/database_backups.py
index 53e19fc..f6e5e31 100644
--- a/troveclient/osc/v1/database_backups.py
+++ b/troveclient/osc/v1/database_backups.py
@@ -225,6 +225,15 @@ class CreateDatabaseBackup(command.ShowOne):
' full or incremental backup. It will create a'
' full backup if no existing backup found.')
)
+ parser.add_argument(
+ '--swift-container',
+ help=_('The container name for storing the backup data when Swift '
+ 'is used as backup storage backend. If not specified, will '
+ 'use the container name configured in the backup strategy, '
+ 'otherwise, the default value configured by the cloud '
+ 'operator. Non-existent container is created '
+ 'automatically.')
+ )
return parser
def take_action(self, parsed_args):
@@ -232,11 +241,14 @@ class CreateDatabaseBackup(command.ShowOne):
database_backups = manager.backups
instance = osc_utils.find_resource(manager.instances,
parsed_args.instance)
- backup = database_backups.create(parsed_args.name,
- instance,
- description=parsed_args.description,
- parent_id=parsed_args.parent,
- incremental=parsed_args.incremental)
+ backup = database_backups.create(
+ parsed_args.name,
+ instance,
+ description=parsed_args.description,
+ parent_id=parsed_args.parent,
+ incremental=parsed_args.incremental,
+ swift_container=parsed_args.swift_container
+ )
backup = set_attributes_for_print_detail(backup)
return zip(*sorted(six.iteritems(backup)))
diff --git a/troveclient/tests/osc/v1/test_database_backup_strategy.py b/troveclient/tests/osc/v1/test_database_backup_strategy.py
new file mode 100644
index 0000000..fe5c951
--- /dev/null
+++ b/troveclient/tests/osc/v1/test_database_backup_strategy.py
@@ -0,0 +1,89 @@
+# Copyright 2020 Catalyst Cloud
+#
+# 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 troveclient.osc.v1 import database_backup_strategy
+from troveclient.tests.osc.v1 import fakes
+from troveclient.v1 import backup_strategy
+
+
+class TestBackupStrategy(fakes.TestDatabasev1):
+ def setUp(self):
+ super(TestBackupStrategy, self).setUp()
+ self.manager = self.app.client_manager.database.backup_strategies
+
+
+class TestBackupStrategyList(TestBackupStrategy):
+ def setUp(self):
+ super(TestBackupStrategyList, self).setUp()
+ self.cmd = database_backup_strategy.ListDatabaseBackupStrategies(
+ self.app, None)
+
+ def test_list(self):
+ item = backup_strategy.BackupStrategy(
+ None,
+ {
+ 'project_id': 'fake_project_id',
+ 'instance_id': 'fake_instance_id',
+ 'swift_container': 'fake_container'
+ }
+ )
+ self.manager.list.return_value = [item]
+
+ parsed_args = self.check_parser(self.cmd, [], [])
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.manager.list.assert_called_once_with(instance_id=None,
+ project_id=None)
+ self.assertEqual(
+ database_backup_strategy.ListDatabaseBackupStrategies.columns,
+ columns)
+ self.assertEqual(
+ [('fake_project_id', 'fake_instance_id', 'fake_container')],
+ data)
+
+
+class TestBackupStrategyCreate(TestBackupStrategy):
+ def setUp(self):
+ super(TestBackupStrategyCreate, self).setUp()
+ self.cmd = database_backup_strategy.CreateDatabaseBackupStrategy(
+ self.app, None)
+
+ def test_create(self):
+ args = ['--instance-id', 'fake_instance_id', '--swift-container',
+ 'fake_container']
+ parsed_args = self.check_parser(self.cmd, args, [])
+ self.cmd.take_action(parsed_args)
+
+ self.manager.create.assert_called_once_with(
+ instance_id='fake_instance_id',
+ swift_container='fake_container'
+ )
+
+
+class TestBackupStrategyDelete(TestBackupStrategy):
+ def setUp(self):
+ super(TestBackupStrategyDelete, self).setUp()
+ self.cmd = database_backup_strategy.DeleteDatabaseBackupStrategy(
+ self.app, None)
+
+ def test_delete(self):
+ args = ['--instance-id', 'fake_instance_id', '--project-id',
+ 'fake_project']
+ parsed_args = self.check_parser(self.cmd, args, [])
+ self.cmd.take_action(parsed_args)
+
+ self.manager.delete.assert_called_once_with(
+ project_id='fake_project',
+ instance_id='fake_instance_id',
+ )
diff --git a/troveclient/tests/osc/v1/test_database_backups.py b/troveclient/tests/osc/v1/test_database_backups.py
index a8c1966..0010a46 100644
--- a/troveclient/tests/osc/v1/test_database_backups.py
+++ b/troveclient/tests/osc/v1/test_database_backups.py
@@ -224,7 +224,8 @@ class TestBackupCreate(TestBackups):
'1234',
description=None,
parent_id=None,
- incremental=False)
+ incremental=False,
+ swift_container=None)
@mock.patch.object(utils, 'find_resource')
def test_incremental_backup_create(self, mock_find):
@@ -237,7 +238,8 @@ class TestBackupCreate(TestBackups):
'1234',
description='backup 1234',
parent_id='1234-1',
- incremental=True)
+ incremental=True,
+ swift_container=None)
class TestDatabaseBackupExecutionDelete(TestBackups):
diff --git a/troveclient/v1/backup_strategy.py b/troveclient/v1/backup_strategy.py
new file mode 100644
index 0000000..61c124f
--- /dev/null
+++ b/troveclient/v1/backup_strategy.py
@@ -0,0 +1,60 @@
+# Copyright 2020 Catalyst Cloud
+#
+# 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 troveclient import base
+from troveclient import common
+
+
+class BackupStrategy(base.Resource):
+ def __repr__(self):
+ return "<BackupStrategy: %s[%s]>" % (self.project_id, self.instance_id)
+
+
+class BackupStrategiesManager(base.ManagerWithFind):
+ resource_class = BackupStrategy
+
+ def list(self, instance_id=None, project_id=None):
+ query_strings = {}
+ if instance_id:
+ query_strings["instance_id"] = instance_id
+ if project_id:
+ query_strings["project_id"] = project_id
+
+ url = common.append_query_strings('/backup_strategies',
+ **query_strings)
+
+ return self._list(url, "backup_strategies")
+
+ def create(self, instance_id=None, swift_container=None):
+ backup_strategy = {}
+ if instance_id:
+ backup_strategy['instance_id'] = instance_id
+ if swift_container:
+ backup_strategy['swift_container'] = swift_container
+ body = {"backup_strategy": backup_strategy}
+
+ return self._create("/backup_strategies", body, "backup_strategy")
+
+ def delete(self, instance_id=None, project_id=None):
+ url = "/backup_strategies"
+ query_strings = {}
+ if instance_id:
+ query_strings["instance_id"] = instance_id
+ if project_id:
+ query_strings["project_id"] = project_id
+
+ url = common.append_query_strings('/backup_strategies',
+ **query_strings)
+
+ resp, body = self._delete(url)
+ common.check_for_exceptions(resp, body, url)
diff --git a/troveclient/v1/backups.py b/troveclient/v1/backups.py
index 3e93ddc..cce6560 100644
--- a/troveclient/v1/backups.py
+++ b/troveclient/v1/backups.py
@@ -74,7 +74,7 @@ class Backups(base.ManagerWithFind):
query_strings)
def create(self, name, instance, description=None,
- parent_id=None, incremental=False):
+ parent_id=None, incremental=False, swift_container=None):
"""Create a new backup from the given instance.
:param name: name for backup.
@@ -83,6 +83,7 @@ class Backups(base.ManagerWithFind):
:param parent_id: base for incremental backup (optional).
:param incremental: flag to indicate incremental backup based on
last backup
+ :param swift_container: Swift container name.
:returns: :class:`Backups`
"""
body = {
@@ -98,6 +99,8 @@ class Backups(base.ManagerWithFind):
body['backup']['description'] = description
if parent_id:
body['backup']['parent_id'] = parent_id
+ if swift_container:
+ body['backup']['swift_container'] = swift_container
return self._create("/backups", body, "backup")
def delete(self, backup):
diff --git a/troveclient/v1/client.py b/troveclient/v1/client.py
index 97af857..88a7257 100644
--- a/troveclient/v1/client.py
+++ b/troveclient/v1/client.py
@@ -15,6 +15,7 @@
# under the License.
from troveclient import client as trove_client
+from troveclient.v1 import backup_strategy
from troveclient.v1 import backups
from troveclient.v1 import clusters
from troveclient.v1 import configurations
@@ -67,6 +68,7 @@ class Client(object):
self.users = users.Users(self)
self.databases = databases.Databases(self)
self.backups = backups.Backups(self)
+ self.backup_strategies = backup_strategy.BackupStrategiesManager(self)
self.clusters = clusters.Clusters(self)
self.instances = instances.Instances(self)
self.limits = limits.Limits(self)