Adding client commands for Backup feature

- Added create, list and delete backup commands
- Updated the create instance command to include optional param 'BackupRef'
- Added 'backups' subcommand to 'instance' used to list all backups for that instance.

Change-Id: Icc32e7097858708d0ed0f4c309d4c86f5cbd8aa6
BP: https://blueprints.launchpad.net/reddwarf/+spec/consistent-snapshots
This commit is contained in:
Steve Leon
2013-03-29 09:49:36 -07:00
parent 0921900be4
commit 50cefc7f90
5 changed files with 112 additions and 5 deletions

62
reddwarfclient/backups.py Normal file
View File

@@ -0,0 +1,62 @@
# Copyright (c) 2011 OpenStack, LLC.
# All Rights Reserved.
#
# 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 reddwarfclient import base
import exceptions
class Backup(base.Resource):
"""
Backup is a resource used to hold backup information.
"""
def __repr__(self):
return "<Backup: %s>" % self.name
class Backups(base.ManagerWithFind):
"""
Manage :class:`Backups` information.
"""
resource_class = Backup
def list(self, limit=None, marker=None):
"""
Get a list of all backups.
:rtype: list of :class:`Backups`.
"""
return self._list("/backups", "backups", limit, marker)
def create(self, name, instance, description=None):
"""
Create a new backup from the given instance.
"""
body = {"backup": {
"name": name,
"instance": instance,
"description": description,
}}
return self._create("/backups", body, "backup")
def delete(self, backup_id):
"""
Delete the specified backup.
:param backup_id: The backup id to delete
"""
resp, body = self.api.client.delete("/backups/%s" % backup_id)
if resp.status in (422, 500):
raise exceptions.from_response(resp, body)

View File

@@ -47,14 +47,18 @@ class InstanceCommands(common.AuthedCommandsBase):
'marker', 'marker',
'name', 'name',
'size', 'size',
] 'backupRef'
]
def create(self): def create(self):
"""Create a new instance""" """Create a new instance"""
self._require('name', 'size', 'flavor') self._require('name', 'size', 'flavor')
volume = {"size": self.size} volume = {"size": self.size}
restorePoint = None
if self.backupRef is not None:
restorePoint = {"backupRef": self.backupRef}
self._pretty_print(self.dbaas.instances.create, self.name, self._pretty_print(self.dbaas.instances.create, self.name,
self.flavor, volume) self.flavor, volume, restorePoint=restorePoint)
def delete(self): def delete(self):
"""Delete the specified instance""" """Delete the specified instance"""
@@ -66,6 +70,11 @@ class InstanceCommands(common.AuthedCommandsBase):
self._require('id') self._require('id')
self._pretty_print(self.dbaas.instances.get, self.id) self._pretty_print(self.dbaas.instances.get, self.id)
def backups(self):
"""Get a list of backups for the specified instance"""
self._require('id')
self._pretty_list(self.dbaas.instances.backups, self.id)
def list(self): def list(self):
"""List all instances for account""" """List all instances for account"""
# limit and marker are not required. # limit and marker are not required.
@@ -242,6 +251,26 @@ class LimitsCommands(common.AuthedCommandsBase):
self._pretty_list(self.dbaas.limits.list) self._pretty_list(self.dbaas.limits.list)
class BackupsCommands(common.AuthedCommandsBase):
"""Command to manage and show backups"""
params = ['name', 'instance', 'description']
def list(self):
"""List backups"""
self._pretty_list(self.dbaas.backups.list)
def create(self):
"""Create a new backup"""
self._require('name', 'instance')
self._pretty_print(self.dbaas.backups.create, self.name,
self.instance, self.description)
def delete(self):
"""Delete a backup"""
self._require('id')
self._pretty_print(self.dbaas.backups.delete, self.id)
class SecurityGroupCommands(common.AuthedCommandsBase): class SecurityGroupCommands(common.AuthedCommandsBase):
"""Commands to list and show Security Groups For an Instance and """ """Commands to list and show Security Groups For an Instance and """
"""create and delete security group rules for them. """ """create and delete security group rules for them. """
@@ -281,6 +310,7 @@ COMMANDS = {'auth': common.Auth,
'flavor': FlavorsCommands, 'flavor': FlavorsCommands,
'database': DatabaseCommands, 'database': DatabaseCommands,
'limit': LimitsCommands, 'limit': LimitsCommands,
'backup': BackupsCommands,
'user': UserCommands, 'user': UserCommands,
'root': RootCommands, 'root': RootCommands,
'version': VersionCommands, 'version': VersionCommands,

View File

@@ -306,6 +306,7 @@ class Dbaas(object):
from reddwarfclient.root import Root from reddwarfclient.root import Root
from reddwarfclient.hosts import Hosts from reddwarfclient.hosts import Hosts
from reddwarfclient.quota import Quotas from reddwarfclient.quota import Quotas
from reddwarfclient.backups import Backups
from reddwarfclient.security_groups import SecurityGroups from reddwarfclient.security_groups import SecurityGroups
from reddwarfclient.security_groups import SecurityGroupRules from reddwarfclient.security_groups import SecurityGroupRules
from reddwarfclient.storage import StorageInfo from reddwarfclient.storage import StorageInfo
@@ -330,6 +331,7 @@ class Dbaas(object):
self.root = Root(self) self.root = Root(self)
self.hosts = Hosts(self) self.hosts = Hosts(self)
self.quota = Quotas(self) self.quota = Quotas(self)
self.backups = Backups(self)
self.security_groups = SecurityGroups(self) self.security_groups = SecurityGroups(self)
self.security_group_rules = SecurityGroupRules(self) self.security_group_rules = SecurityGroupRules(self)
self.storage = StorageInfo(self) self.storage = StorageInfo(self)

View File

@@ -55,7 +55,8 @@ class Instances(base.ManagerWithFind):
""" """
resource_class = Instance resource_class = Instance
def create(self, name, flavor_id, volume, databases=None, users=None): def create(self, name, flavor_id, volume, databases=None, users=None,
restorePoint=None):
""" """
Create (boot) a new instance. Create (boot) a new instance.
""" """
@@ -68,6 +69,8 @@ class Instances(base.ManagerWithFind):
body["instance"]["databases"] = databases body["instance"]["databases"] = databases
if users: if users:
body["instance"]["users"] = users body["instance"]["users"] = users
if restorePoint:
body["instance"]["restorePoint"] = restorePoint
return self._create("/instances", body, "instance") return self._create("/instances", body, "instance")
@@ -102,7 +105,16 @@ class Instances(base.ManagerWithFind):
:rtype: :class:`Instance` :rtype: :class:`Instance`
""" """
return self._get("/instances/%s" % base.getid(instance), return self._get("/instances/%s" % base.getid(instance),
"instance") "instance")
def backups(self, instance):
"""
Get the list of backups for a specific instance.
:rtype: list of :class:`Backups`.
"""
return self._list("/instances/%s/backups" % base.getid(instance),
"backups")
def delete(self, instance): def delete(self, instance):
""" """

View File

@@ -20,7 +20,8 @@ LISTIFY = {
"versions": [[]], "versions": [[]],
"attachments": [[]], "attachments": [[]],
"limits": [[]], "limits": [[]],
"security_groups": [[]] "security_groups": [[]],
"backups": [[]]
} }
TYPE_MAP = { TYPE_MAP = {