Skip to content

Commit b90c780

Browse files
committed
Add volume backup import/export commands
This adds commands to import and export volume backup records so they can be imported and restored on other Cinder instances or to the original instance if the service or database has been lost and had to be rebuilt. I know this is a commonly used process by some users, so it would be good to have this functionality in osc so they do not have to switch clients. More details about the export and import process can be found here: https://docs.openstack.org/cinder/latest/admin/blockstorage-volume-backups-export-import.html Change-Id: Ic95f87b36a416a2b50cb2193fd5759ab59336975 Signed-off-by: Sean McGinnis <sean.mcginnis@gmail.com>
1 parent 097b456 commit b90c780

8 files changed

Lines changed: 250 additions & 197 deletions

File tree

doc/source/cli/command-objects/volume-backup.rst

Lines changed: 3 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -2,200 +2,8 @@
22
volume backup
33
=============
44

5-
Block Storage v1, v2
5+
Volume v1, v2
66

7-
volume backup create
8-
--------------------
7+
.. autoprogram-cliff:: openstack.volume.v2
8+
:command: volume backup *
99

10-
Create new volume backup
11-
12-
.. program:: volume backup create
13-
.. code:: bash
14-
15-
openstack volume backup create
16-
[--container <container>]
17-
[--name <name>]
18-
[--description <description>]
19-
[--snapshot <snapshot>]
20-
[--force]
21-
[--incremental]
22-
<volume>
23-
24-
.. option:: --container <container>
25-
26-
Optional backup container name
27-
28-
.. option:: --name <name>
29-
30-
Name of the backup
31-
32-
.. option:: --description <description>
33-
34-
Description of the backup
35-
36-
.. option:: --snapshot <snapshot>
37-
38-
Snapshot to backup (name or ID)
39-
40-
*Volume version 2 only*
41-
42-
.. option:: --force
43-
44-
Allow to back up an in-use volume
45-
46-
*Volume version 2 only*
47-
48-
.. option:: --incremental
49-
50-
Perform an incremental backup
51-
52-
*Volume version 2 only*
53-
54-
.. _volume_backup_create-backup:
55-
.. describe:: <volume>
56-
57-
Volume to backup (name or ID)
58-
59-
volume backup delete
60-
--------------------
61-
62-
Delete volume backup(s)
63-
64-
.. program:: volume backup delete
65-
.. code:: bash
66-
67-
openstack volume backup delete
68-
[--force]
69-
<backup> [<backup> ...]
70-
71-
.. option:: --force
72-
73-
Allow delete in state other than error or available
74-
75-
*Volume version 2 only*
76-
77-
.. _volume_backup_delete-backup:
78-
.. describe:: <backup>
79-
80-
Backup(s) to delete (name or ID)
81-
82-
volume backup list
83-
------------------
84-
85-
List volume backups
86-
87-
.. program:: volume backup list
88-
.. code:: bash
89-
90-
openstack volume backup list
91-
[--long]
92-
[--name <name>]
93-
[--status <status>]
94-
[--volume <volume>]
95-
[--marker <volume-backup>]
96-
[--limit <num-backups>]
97-
[--all-projects]
98-
99-
.. _volume_backup_list-backup:
100-
.. option:: --long
101-
102-
List additional fields in output
103-
104-
.. option:: --name <name>
105-
106-
Filters results by the backup name
107-
108-
.. option:: --status <status>
109-
110-
Filters results by the backup status
111-
('creating', 'available', 'deleting', 'error', 'restoring' or 'error_restoring')
112-
113-
.. option:: --volume <volume>
114-
115-
Filters results by the volume which they backup (name or ID)"
116-
117-
.. option:: --marker <volume-backup>
118-
119-
The last backup of the previous page (name or ID)
120-
121-
*Volume version 2 only*
122-
123-
.. option:: --limit <num-backups>
124-
125-
Maximum number of backups to display
126-
127-
*Volume version 2 only*
128-
129-
.. option:: --all-projects
130-
131-
Include all projects (admin only)
132-
133-
volume backup restore
134-
---------------------
135-
136-
Restore volume backup
137-
138-
.. program:: volume backup restore
139-
.. code:: bash
140-
141-
openstack volume backup restore
142-
<backup>
143-
<volume>
144-
145-
.. _volume_backup_restore-backup:
146-
.. describe:: <backup>
147-
148-
Backup to restore (name or ID)
149-
150-
.. describe:: <volume>
151-
152-
Volume to restore to (name or ID)
153-
154-
volume backup set
155-
-----------------
156-
157-
Set volume backup properties
158-
159-
.. program:: volume backup set
160-
.. code:: bash
161-
162-
openstack volume backup set
163-
[--name <name>]
164-
[--description <description>]
165-
[--state <state>]
166-
<backup>
167-
168-
.. option:: --name <name>
169-
170-
New backup name
171-
172-
.. option:: --description <description>
173-
174-
New backup description
175-
176-
.. option:: --state <state>
177-
178-
New backup state ("available" or "error") (admin only)
179-
(This option simply changes the state of the backup in the database with
180-
no regard to actual status, exercise caution when using)
181-
182-
.. _backup_set-volume-backup:
183-
.. describe:: <backup>
184-
185-
Backup to modify (name or ID)
186-
187-
volume backup show
188-
------------------
189-
190-
Display volume backup details
191-
192-
.. program:: volume backup show
193-
.. code:: bash
194-
195-
openstack volume backup show
196-
<backup>
197-
198-
.. _volume_backup_show-backup:
199-
.. describe:: <backup>
200-
201-
Backup to display (name or ID)

doc/source/cli/commands.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ referring to both Compute and Volume quotas.
158158
* ``volume backup``: (**Volume**) backup for volumes
159159
* ``volume backend capability``: (**volume**) volume backend storage capabilities
160160
* ``volume backend pool``: (**volume**) volume backend storage pools
161+
* ``volume backup record``: (**Volume**) volume record that can be imported or exported
162+
* ``volume backend``: (**volume**) volume backend storage
161163
* ``volume host``: (**Volume**) the physical computer for volumes
162164
* ``volume qos``: (**Volume**) quality-of-service (QoS) specification for volumes
163165
* ``volume snapshot``: (**Volume**) a point-in-time copy of a volume

doc/source/cli/data/cinder.csv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ absolute-limits,limits show --absolute,Lists absolute limits for a user.
22
availability-zone-list,availability zone list --volume,Lists all availability zones.
33
backup-create,volume backup create,Creates a volume backup.
44
backup-delete,volume backup delete,Removes a backup.
5-
backup-export,volume backup export,Export backup metadata record.
6-
backup-import,volume backup import,Import backup metadata record.
5+
backup-export,volume backup record export,Export backup metadata record.
6+
backup-import,volume backup record import,Import backup metadata record.
77
backup-list,volume backup list,Lists all backups.
88
backup-reset-state,volume backup set --state,Explicitly updates the backup state.
99
backup-restore,volume backup restore,Restores a backup.

openstackclient/tests/unit/volume/v2/fakes.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,35 @@ def get_backups(backups=None, count=2):
596596

597597
return mock.Mock(side_effect=backups)
598598

599+
@staticmethod
600+
def create_backup_record():
601+
"""Gets a fake backup record for a given backup.
602+
603+
:return: An "exported" backup record.
604+
"""
605+
606+
return {
607+
'backup_service': 'cinder.backup.drivers.swift.SwiftBackupDriver',
608+
'backup_url': 'eyJzdGF0dXMiOiAiYXZh',
609+
}
610+
611+
@staticmethod
612+
def import_backup_record():
613+
"""Creates a fake backup record import response from a backup.
614+
615+
:return: The fake backup object that was encoded.
616+
"""
617+
return {
618+
'backup': {
619+
'id': 'backup.id',
620+
'name': 'backup.name',
621+
'links': [
622+
{'href': 'link1', 'rel': 'self'},
623+
{'href': 'link2', 'rel': 'bookmark'},
624+
],
625+
},
626+
}
627+
599628

600629
class FakeConsistencyGroup(object):
601630
"""Fake one or more consistency group."""
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#
2+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3+
# not use this file except in compliance with the License. You may obtain
4+
# a copy of the License at
5+
#
6+
# http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11+
# License for the specific language governing permissions and limitations
12+
# under the License.
13+
#
14+
15+
from openstackclient.tests.unit.volume.v2 import fakes as volume_fakes
16+
from openstackclient.volume.v2 import backup_record
17+
18+
19+
class TestBackupRecord(volume_fakes.TestVolume):
20+
21+
def setUp(self):
22+
super(TestBackupRecord, self).setUp()
23+
24+
self.backups_mock = self.app.client_manager.volume.backups
25+
self.backups_mock.reset_mock()
26+
27+
28+
class TestBackupRecordExport(TestBackupRecord):
29+
30+
new_backup = volume_fakes.FakeBackup.create_one_backup(
31+
attrs={'volume_id': 'a54708a2-0388-4476-a909-09579f885c25'})
32+
new_record = volume_fakes.FakeBackup.create_backup_record()
33+
34+
def setUp(self):
35+
super(TestBackupRecordExport, self).setUp()
36+
37+
self.backups_mock.export_record.return_value = self.new_record
38+
self.backups_mock.get.return_value = self.new_backup
39+
40+
# Get the command object to mock
41+
self.cmd = backup_record.ExportBackupRecord(self.app, None)
42+
43+
def test_backup_export_table(self):
44+
arglist = [
45+
self.new_backup.name,
46+
]
47+
verifylist = [
48+
("backup", self.new_backup.name),
49+
]
50+
51+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
52+
parsed_args.formatter = 'table'
53+
columns, __ = self.cmd.take_action(parsed_args)
54+
55+
self.backups_mock.export_record.assert_called_with(
56+
self.new_backup.id,
57+
)
58+
59+
expected_columns = ('Backup Service', 'Metadata')
60+
self.assertEqual(columns, expected_columns)
61+
62+
def test_backup_export_json(self):
63+
arglist = [
64+
self.new_backup.name,
65+
]
66+
verifylist = [
67+
("backup", self.new_backup.name),
68+
]
69+
70+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
71+
parsed_args.formatter = 'json'
72+
columns, __ = self.cmd.take_action(parsed_args)
73+
74+
self.backups_mock.export_record.assert_called_with(
75+
self.new_backup.id,
76+
)
77+
78+
expected_columns = ('backup_service', 'backup_url')
79+
self.assertEqual(columns, expected_columns)
80+
81+
82+
class TestBackupRecordImport(TestBackupRecord):
83+
84+
new_backup = volume_fakes.FakeBackup.create_one_backup(
85+
attrs={'volume_id': 'a54708a2-0388-4476-a909-09579f885c25'})
86+
new_import = volume_fakes.FakeBackup.import_backup_record()
87+
88+
def setUp(self):
89+
super(TestBackupRecordImport, self).setUp()
90+
91+
self.backups_mock.import_record.return_value = self.new_import
92+
93+
# Get the command object to mock
94+
self.cmd = backup_record.ImportBackupRecord(self.app, None)
95+
96+
def test_backup_import(self):
97+
arglist = [
98+
"cinder.backup.drivers.swift.SwiftBackupDriver",
99+
"fake_backup_record_data",
100+
]
101+
verifylist = [
102+
("backup_service",
103+
"cinder.backup.drivers.swift.SwiftBackupDriver"),
104+
("backup_metadata", "fake_backup_record_data"),
105+
]
106+
107+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
108+
columns, __ = self.cmd.take_action(parsed_args)
109+
110+
self.backups_mock.import_record.assert_called_with(
111+
"cinder.backup.drivers.swift.SwiftBackupDriver",
112+
"fake_backup_record_data",
113+
)
114+
self.assertEqual(columns, ('backup',))

0 commit comments

Comments
 (0)