From 234205bf538489dfc9c42858b104224170259278 Mon Sep 17 00:00:00 2001 From: Gaurav Gupta <gaurav@denali-systems.com> Date: Thu, 29 Sep 2011 08:09:50 -0700 Subject: [PATCH 1/2] Added the following CLI commands to access nova volumes: volume-attach Attach a volume to a server. volume-create Add a new volume. volume-delete Remove a volume. volume-detach Detach a volume from a server. volume-list List all the volumes. volume-show Show details about a volume. --- README.rst | 6 +++ novaclient/v1_1/client.py | 2 + novaclient/v1_1/shell.py | 88 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) diff --git a/README.rst b/README.rst index 1916a79b8..7955d326a 100644 --- a/README.rst +++ b/README.rst @@ -106,6 +106,12 @@ You'll find complete documentation on the shell by running root-password Change the root password for a server. show Show details about the given server. unrescue Unrescue a server. + volume-attach Attach a volume to a server. + volume-create Add a new volume. + volume-delete Remove a volume. + volume-detach Detach a volume from a server. + volume-list List all the volumes. + volume-show Show details about a volume. zone Show or edit a Child Zone zone-add Add a Child Zone. zone-boot Boot a server, considering Zones. diff --git a/novaclient/v1_1/client.py b/novaclient/v1_1/client.py index 81118c6c6..a46d6bbb8 100644 --- a/novaclient/v1_1/client.py +++ b/novaclient/v1_1/client.py @@ -7,6 +7,7 @@ from novaclient.v1_1 import security_group_rules from novaclient.v1_1 import security_groups from novaclient.v1_1 import servers from novaclient.v1_1 import quotas +from novaclient.v1_1 import volumes from novaclient.v1_1 import zones @@ -36,6 +37,7 @@ class Client(object): self.servers = servers.ServerManager(self) # extensions + self.volumes = volumes.VolumeManager(self) self.keypairs = keypairs.KeypairManager(self) self.zones = zones.ZoneManager(self) self.quotas = quotas.QuotaSetManager(self) diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py index 6b83292e5..7575ac6fb 100644 --- a/novaclient/v1_1/shell.py +++ b/novaclient/v1_1/shell.py @@ -703,3 +703,91 @@ def do_remove_fixed_ip(cs, args): """Remove an IP address from a server.""" server = _find_server(cs, args.server) server.remove_fixed_ip(args.address) + + +def _find_volume(cs, volume): + """Get a volume by ID.""" + return utils.find_resource(cs.volumes, volume) + + +def _print_volume(cs, volume): + utils.print_dict(volume._info) + + +def _translate_volume_keys(collection): + convert = [('displayName', 'display_name')] + for item in collection: + keys = item.__dict__.keys() + for from_key, to_key in convert: + if from_key in keys and to_key not in keys: + setattr(item, to_key, item._info[from_key]) + + +def do_volume_list(cs, args): + """List all the volumes.""" + volumes = cs.volumes.list() + _translate_volume_keys(volumes) + + # Create a list of servers to which the volume is attached + for vol in volumes: + servers = [server.get('serverId') for server in vol.attachments] + setattr(vol, 'attached_to', ','.join(map(str, servers))) + utils.print_list(volumes, ['ID', 'Status', 'Display Name', + 'Size', 'Attached to']) + + +@utils.arg('volume', metavar='<volume>', help='ID of the volume.') +def do_volume_show(cs, args): + """Show details about a volume.""" + volume = _find_volume(cs, args.volume) + _print_volume(cs, volume) + + +@utils.arg('size', + metavar='<size>', + type=int, + help='Size of volume in GB') +@utils.arg('--display_name', metavar='<display_name>', + help='Optional volume name. (Default=None)', + default=None) +@utils.arg('--display_description', metavar='<display_description>', + help='Optional volume description. (Default=None)', + default=None) +def do_volume_create(cs, args): + """Add a new volume.""" + cs.volumes.create(args.size, args.display_name, args.display_description) + + +@utils.arg('volume', metavar='<volume>', help='ID of the volume to delete.') +def do_volume_delete(cs, args): + """Remove a volume.""" + volume = _find_volume(cs, args.volume) + volume.delete() + + +@utils.arg('server', + metavar='<server>', + type=int, + help='Name or ID of server.') +@utils.arg('volume', + metavar='<volume>', + type=int, + help='ID of the volume to attach.') +@utils.arg('device', metavar='<device>', + help='Name of the device e.g. /dev/vdb.') +def do_volume_attach(cs, args): + """Attach a volume to a server.""" + cs.volumes.create_server_volume(args.server, args.volume, args.device) + + +@utils.arg('server', + metavar='<server>', + type=int, + help='Name or ID of server.') +@utils.arg('attachment_id', + metavar='<volume>', + type=int, + help='Attachment ID of the volume.') +def do_volume_detach(cs, args): + """Detach a volume from a server.""" + cs.volumes.delete_server_volume(args.server, args.attachment_id) From cd9f3cb47e7fc02e843867cac7bd8c309ebb24f5 Mon Sep 17 00:00:00 2001 From: Gaurav Gupta <gaurav@denali-systems.com> Date: Sun, 16 Oct 2011 15:21:53 -0700 Subject: [PATCH 2/2] Updated volume attach/detach commands to accept server name (in addition to server id). Code review comments: https://github.com/rackspace/python-novaclient/pull/125/files#r169829 --- novaclient/v1_1/shell.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py index 7575ac6fb..075a56ee6 100644 --- a/novaclient/v1_1/shell.py +++ b/novaclient/v1_1/shell.py @@ -767,7 +767,6 @@ def do_volume_delete(cs, args): @utils.arg('server', metavar='<server>', - type=int, help='Name or ID of server.') @utils.arg('volume', metavar='<volume>', @@ -777,12 +776,13 @@ def do_volume_delete(cs, args): help='Name of the device e.g. /dev/vdb.') def do_volume_attach(cs, args): """Attach a volume to a server.""" - cs.volumes.create_server_volume(args.server, args.volume, args.device) + cs.volumes.create_server_volume(_find_server(cs, args.server).id, + args.volume, + args.device) @utils.arg('server', metavar='<server>', - type=int, help='Name or ID of server.') @utils.arg('attachment_id', metavar='<volume>', @@ -790,4 +790,5 @@ def do_volume_attach(cs, args): help='Attachment ID of the volume.') def do_volume_detach(cs, args): """Detach a volume from a server.""" - cs.volumes.delete_server_volume(args.server, args.attachment_id) + cs.volumes.delete_server_volume(_find_server(cs, args.server).id, + args.attachment_id)