root / kamaki / cli / commands / volume.py @ 05f1452c
History | View | Annotate | Download (5.2 kB)
1 |
# Copyright 2011-2013 GRNET S.A. All rights reserved.
|
---|---|
2 |
#
|
3 |
# Redistribution and use in source and binary forms, with or
|
4 |
# without modification, are permitted provided that the following
|
5 |
# conditions are met:
|
6 |
#
|
7 |
# 1. Redistributions of source code must retain the above
|
8 |
# copyright notice, this list of conditions and the following
|
9 |
# disclaimer.
|
10 |
#
|
11 |
# 2. Redistributions in binary form must reproduce the above
|
12 |
# copyright notice, this list of conditions and the following
|
13 |
# disclaimer in the documentation and/or other materials
|
14 |
# provided with the distribution.
|
15 |
#
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 |
# POSSIBILITY OF SUCH DAMAGE.
|
28 |
#
|
29 |
# The views and conclusions contained in the software and
|
30 |
# documentation are those of the authors and should not be
|
31 |
# interpreted as representing official policies, either expressed
|
32 |
# or implied, of GRNET S.A.
|
33 |
|
34 |
from kamaki.cli import command |
35 |
from kamaki.cli.command_tree import CommandTree |
36 |
from kamaki.cli.commands.cyclades import _init_cyclades |
37 |
from kamaki.cli.errors import CLIBaseUrlError |
38 |
from kamaki.cli.argument import ( |
39 |
FlagArgument, ValueArgument, KeyValueArgument, IntArgument) |
40 |
from kamaki.cli.commands import _command_init, errors, addLogSettings |
41 |
from kamaki.cli.commands import _optional_json |
42 |
from kamaki.clients.volume import VolumeClient |
43 |
|
44 |
|
45 |
snapshot_cmds = CommandTree('snapshot', 'Server image snapshot operations') |
46 |
volume_cmds = CommandTree('volume', 'Server volume operations') |
47 |
_commands = [snapshot_cmds, volume_cmds] |
48 |
|
49 |
|
50 |
class _init_volume(_command_init): |
51 |
@errors.generic.all
|
52 |
@addLogSettings
|
53 |
def _run(self, service='volume'): |
54 |
if getattr(self, 'cloud', None): |
55 |
base_url = self._custom_url(service) or self._custom_url( |
56 |
'volume')
|
57 |
if base_url:
|
58 |
token = self._custom_token(service) or self._custom_token( |
59 |
'volume') or self.config.get_cloud('token') |
60 |
self.client = VolumeClient(base_url=base_url, token=token)
|
61 |
return
|
62 |
else:
|
63 |
self.cloud = 'default' |
64 |
if getattr(self, 'auth_base', False): |
65 |
cyclades_endpoints = self.auth_base.get_service_endpoints(
|
66 |
self._custom_type('volume') or 'volume', |
67 |
self._custom_version('volume') or '') |
68 |
base_url = cyclades_endpoints['publicURL']
|
69 |
token = self.auth_base.token
|
70 |
self.client = VolumeClient(base_url=base_url, token=token)
|
71 |
else:
|
72 |
raise CLIBaseUrlError(service='volume') |
73 |
|
74 |
def main(self): |
75 |
self._run()
|
76 |
|
77 |
|
78 |
@command(volume_cmds)
|
79 |
class volume_list(_init_cyclades, _optional_json): |
80 |
"""List a server volume or the volumes for all servers"""
|
81 |
|
82 |
arguments = dict(
|
83 |
server_id=IntArgument('list volumes of this server', '--server-id') |
84 |
) |
85 |
|
86 |
@errors.generic.all
|
87 |
@errors.cyclades.connection
|
88 |
def _run(self): |
89 |
servers = [self.client.get_server_details(self['server_id'])] if ( |
90 |
self['server_id']) else self.client.list_servers(detail=True) |
91 |
volumes = [dict(
|
92 |
server_id=s['id'],
|
93 |
volumes=' '.join('%s' % v for v in s['volumes'])) for s in servers] |
94 |
self._print(volumes)
|
95 |
|
96 |
def main(self): |
97 |
super(self.__class__, self)._run() |
98 |
self._run()
|
99 |
|
100 |
|
101 |
@command(snapshot_cmds)
|
102 |
class snapshot_create(_init_volume, _optional_json): |
103 |
"""Create a snapshot of a volume"""
|
104 |
|
105 |
arguments = dict(
|
106 |
name=ValueArgument( |
107 |
'The snapshot name (otherwise it is created automatically)',
|
108 |
'--name'),
|
109 |
description=ValueArgument('Snapshot description', '--description'), |
110 |
metadata=KeyValueArgument( |
111 |
'Snapshot custom metadata (can be repeated)', '--metadata') |
112 |
) |
113 |
|
114 |
@errors.generic.all
|
115 |
@errors.cyclades.connection
|
116 |
def _run(self, volume_id): |
117 |
self._print(self.client.create_snapshot( |
118 |
volume_id, self['name'], self['description'], self['metadata'])) |
119 |
|
120 |
def main(self, volume_id): |
121 |
super(self.__class__, self)._run() |
122 |
self._run(volume_id)
|
123 |
|
124 |
|
125 |
@command(snapshot_cmds)
|
126 |
class snapshot_list(_init_cyclades, _optional_json): |
127 |
"""List all snapshots"""
|
128 |
|
129 |
arguments = dict(
|
130 |
detail=FlagArgument('show detailed output', ('-l', '--details')) |
131 |
) |
132 |
|
133 |
@errors.generic.all
|
134 |
@errors.cyclades.connection
|
135 |
def _run(self): |
136 |
r = [img for img in self.client.list_images(detail=True) if ( |
137 |
img.get('is_snapshot', False))] |
138 |
if not self['detail']: |
139 |
r = [dict(name=img['name'], id=img['id']) for img in r] |
140 |
self._print(r)
|
141 |
|
142 |
def main(self): |
143 |
super(self.__class__, self)._run() |
144 |
self._run()
|