root / tools / cloud @ 40777cc8
History | View | Annotate | Download (14.8 kB)
1 | ab756200 | Giorgos Verigakis | #!/usr/bin/env python |
---|---|---|---|
2 | ab756200 | Giorgos Verigakis | |
3 | ab756200 | Giorgos Verigakis | from functools import wraps |
4 | ab756200 | Giorgos Verigakis | from httplib import HTTPConnection |
5 | ab756200 | Giorgos Verigakis | from optparse import OptionParser |
6 | ab756200 | Giorgos Verigakis | from os.path import basename |
7 | ab756200 | Giorgos Verigakis | from sys import argv, exit |
8 | ab756200 | Giorgos Verigakis | |
9 | ab756200 | Giorgos Verigakis | import json |
10 | ab756200 | Giorgos Verigakis | |
11 | ab756200 | Giorgos Verigakis | DEFAULT_HOST = '127.0.0.1:8000' |
12 | d8e50a39 | Giorgos Verigakis | DEFAULT_API = 'v1.1' |
13 | ab756200 | Giorgos Verigakis | |
14 | 40777cc8 | Giorgos Verigakis | TOKEN = '46e427d657b20defe352804f0eb6f8a2' |
15 | 40777cc8 | Giorgos Verigakis | |
16 | ab756200 | Giorgos Verigakis | |
17 | ab756200 | Giorgos Verigakis | commands = {} |
18 | ab756200 | Giorgos Verigakis | |
19 | ab756200 | Giorgos Verigakis | def command_name(name): |
20 | ab756200 | Giorgos Verigakis | def decorator(cls): |
21 | ab756200 | Giorgos Verigakis | commands[name] = cls |
22 | ab756200 | Giorgos Verigakis | return cls |
23 | ab756200 | Giorgos Verigakis | return decorator |
24 | ab756200 | Giorgos Verigakis | |
25 | ab756200 | Giorgos Verigakis | |
26 | ab756200 | Giorgos Verigakis | def address_to_string(address): |
27 | ab756200 | Giorgos Verigakis | key = address['id'] |
28 | ab756200 | Giorgos Verigakis | val = ' '.join(ip['addr'] for ip in address['values']) |
29 | ab756200 | Giorgos Verigakis | return '%s: %s' % (key, val) |
30 | ab756200 | Giorgos Verigakis | |
31 | ab756200 | Giorgos Verigakis | def print_dict(d, show_empty=True): |
32 | ab756200 | Giorgos Verigakis | for key, val in sorted(d.items()): |
33 | ab756200 | Giorgos Verigakis | if key == 'metadata': |
34 | ab756200 | Giorgos Verigakis | val = ', '.join('%s="%s"' % x for x in val['values'].items()) |
35 | ab756200 | Giorgos Verigakis | if key == 'addresses': |
36 | ab756200 | Giorgos Verigakis | val = ', '.join(address_to_string(address) for address in val['values']) |
37 | ab756200 | Giorgos Verigakis | if val or show_empty: |
38 | ab756200 | Giorgos Verigakis | print '%s: %s' % (key.rjust(12), val) |
39 | ab756200 | Giorgos Verigakis | |
40 | ab756200 | Giorgos Verigakis | |
41 | ab756200 | Giorgos Verigakis | class Command(object): |
42 | ab756200 | Giorgos Verigakis | def __init__(self, argv): |
43 | ab756200 | Giorgos Verigakis | parser = OptionParser() |
44 | ab756200 | Giorgos Verigakis | parser.add_option('--host', dest='host', metavar='HOST', default=DEFAULT_HOST, |
45 | ab756200 | Giorgos Verigakis | help='use server HOST') |
46 | ab756200 | Giorgos Verigakis | parser.add_option('--api', dest='api', metavar='API', default=DEFAULT_API, |
47 | ab756200 | Giorgos Verigakis | help='use api API') |
48 | ab756200 | Giorgos Verigakis | parser.add_option('-v', action='store_true', dest='verbose', default=False, |
49 | ab756200 | Giorgos Verigakis | help='use verbose output') |
50 | ab756200 | Giorgos Verigakis | self.add_options(parser) |
51 | ab756200 | Giorgos Verigakis | options, args = parser.parse_args(argv) |
52 | ab756200 | Giorgos Verigakis | |
53 | ab756200 | Giorgos Verigakis | # Add options to self |
54 | ab756200 | Giorgos Verigakis | for opt in parser.option_list: |
55 | ab756200 | Giorgos Verigakis | key = opt.dest |
56 | ab756200 | Giorgos Verigakis | if key: |
57 | ab756200 | Giorgos Verigakis | val = getattr(options, key) |
58 | ab756200 | Giorgos Verigakis | setattr(self, key, val) |
59 | ab756200 | Giorgos Verigakis | |
60 | ab756200 | Giorgos Verigakis | self.execute(*args) |
61 | ab756200 | Giorgos Verigakis | |
62 | ab756200 | Giorgos Verigakis | def add_options(self, parser): |
63 | ab756200 | Giorgos Verigakis | pass |
64 | ab756200 | Giorgos Verigakis | |
65 | ab756200 | Giorgos Verigakis | def execute(self, *args): |
66 | ab756200 | Giorgos Verigakis | pass |
67 | ab756200 | Giorgos Verigakis | |
68 | ab756200 | Giorgos Verigakis | def http_cmd(self, method, path, body=None, expected_status=200): |
69 | ab756200 | Giorgos Verigakis | conn = HTTPConnection(self.host) |
70 | ab756200 | Giorgos Verigakis | |
71 | ab756200 | Giorgos Verigakis | kwargs = {} |
72 | 40777cc8 | Giorgos Verigakis | kwargs['headers'] = {'X-Auth-Token': TOKEN} |
73 | ab756200 | Giorgos Verigakis | if body: |
74 | 40777cc8 | Giorgos Verigakis | kwargs['headers']['Content-Type'] = 'application/json' |
75 | ab756200 | Giorgos Verigakis | kwargs['body'] = body |
76 | ab756200 | Giorgos Verigakis | conn.request(method, path, **kwargs) |
77 | ab756200 | Giorgos Verigakis | |
78 | ab756200 | Giorgos Verigakis | resp = conn.getresponse() |
79 | ab756200 | Giorgos Verigakis | if self.verbose: |
80 | ab756200 | Giorgos Verigakis | print '%d %s' % (resp.status, resp.reason) |
81 | ab756200 | Giorgos Verigakis | for key, val in resp.getheaders(): |
82 | ab756200 | Giorgos Verigakis | print '%s: %s' % (key.capitalize(), val) |
83 | ab756200 | Giorgos Verigakis | |
84 | ab756200 | Giorgos Verigakis | |
85 | ab756200 | Giorgos Verigakis | buf = resp.read() or '{}' |
86 | ab756200 | Giorgos Verigakis | reply = json.loads(buf) |
87 | ab756200 | Giorgos Verigakis | |
88 | 4cf8adf8 | Vangelis Koukis | # If the response status is not the expected one, |
89 | 4cf8adf8 | Vangelis Koukis | # assume an error has occured and treat the body |
90 | 4cf8adf8 | Vangelis Koukis | # as a cloudfault. |
91 | ab756200 | Giorgos Verigakis | if resp.status != expected_status: |
92 | ab756200 | Giorgos Verigakis | if len(reply) == 1: |
93 | ab756200 | Giorgos Verigakis | key = reply.keys()[0] |
94 | ab756200 | Giorgos Verigakis | val = reply[key] |
95 | d8e50a39 | Giorgos Verigakis | print '%s: %s' % (key, val.get('message', '')) |
96 | ab756200 | Giorgos Verigakis | if self.verbose: |
97 | ab756200 | Giorgos Verigakis | print val.get('details', '') |
98 | ab756200 | Giorgos Verigakis | exit(1) |
99 | ab756200 | Giorgos Verigakis | |
100 | ab756200 | Giorgos Verigakis | return reply |
101 | ab756200 | Giorgos Verigakis | |
102 | ab756200 | Giorgos Verigakis | def http_get(self, path, expected_status=200): |
103 | ab756200 | Giorgos Verigakis | return self.http_cmd('GET', path, None, expected_status) |
104 | ab756200 | Giorgos Verigakis | |
105 | ab756200 | Giorgos Verigakis | def http_post(self, path, body, expected_status=202): |
106 | ab756200 | Giorgos Verigakis | return self.http_cmd('POST', path, body, expected_status) |
107 | ab756200 | Giorgos Verigakis | |
108 | ab756200 | Giorgos Verigakis | def http_put(self, path, body, expected_status=204): |
109 | ab756200 | Giorgos Verigakis | return self.http_cmd('PUT', path, body, expected_status) |
110 | ab756200 | Giorgos Verigakis | |
111 | ab756200 | Giorgos Verigakis | def http_delete(self, path, expected_status=204): |
112 | ab756200 | Giorgos Verigakis | return self.http_cmd('DELETE', path, None, expected_status) |
113 | ab756200 | Giorgos Verigakis | |
114 | ab756200 | Giorgos Verigakis | |
115 | ab756200 | Giorgos Verigakis | @command_name('ls') |
116 | ab756200 | Giorgos Verigakis | class ListServers(Command): |
117 | ab756200 | Giorgos Verigakis | description = 'list servers' |
118 | ab756200 | Giorgos Verigakis | |
119 | ab756200 | Giorgos Verigakis | def add_options(self, parser): |
120 | ab756200 | Giorgos Verigakis | parser.add_option('-l', action='store_true', dest='detail', default=False, |
121 | ab756200 | Giorgos Verigakis | help='show detailed output') |
122 | ab756200 | Giorgos Verigakis | parser.add_option('-a', action='store_true', dest='show_empty', default=False, |
123 | ab756200 | Giorgos Verigakis | help='include empty values') |
124 | ab756200 | Giorgos Verigakis | |
125 | ab756200 | Giorgos Verigakis | def execute(self): |
126 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers' % self.api |
127 | ab756200 | Giorgos Verigakis | if self.detail: |
128 | ab756200 | Giorgos Verigakis | path += '/detail' |
129 | ab756200 | Giorgos Verigakis | |
130 | ab756200 | Giorgos Verigakis | reply = self.http_get(path) |
131 | ab756200 | Giorgos Verigakis | |
132 | ab756200 | Giorgos Verigakis | for server in reply['servers']['values']: |
133 | ab756200 | Giorgos Verigakis | id = server.pop('id') |
134 | ab756200 | Giorgos Verigakis | name = server.pop('name') |
135 | ab756200 | Giorgos Verigakis | if self.detail: |
136 | ab756200 | Giorgos Verigakis | print '%d %s' % (id, name) |
137 | ab756200 | Giorgos Verigakis | print_dict(server, self.show_empty) |
138 | ab756200 | Giorgos Verigakis | |
139 | ab756200 | Giorgos Verigakis | else: |
140 | ab756200 | Giorgos Verigakis | print '%3d %s' % (id, name) |
141 | ab756200 | Giorgos Verigakis | |
142 | ab756200 | Giorgos Verigakis | |
143 | ab756200 | Giorgos Verigakis | @command_name('info') |
144 | ab756200 | Giorgos Verigakis | class GetServerDetails(Command): |
145 | ab756200 | Giorgos Verigakis | description = 'get server details' |
146 | ab756200 | Giorgos Verigakis | syntax = '<server id>' |
147 | ab756200 | Giorgos Verigakis | |
148 | ab756200 | Giorgos Verigakis | def add_options(self, parser): |
149 | ab756200 | Giorgos Verigakis | parser.add_option('-a', action='store_true', dest='show_empty', default=False, |
150 | ab756200 | Giorgos Verigakis | help='include empty values') |
151 | ab756200 | Giorgos Verigakis | |
152 | ab756200 | Giorgos Verigakis | def execute(self, server_id): |
153 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers/%d' % (self.api, int(server_id)) |
154 | ab756200 | Giorgos Verigakis | reply = self.http_get(path) |
155 | ab756200 | Giorgos Verigakis | server = reply['server'] |
156 | ab756200 | Giorgos Verigakis | server.pop('id') |
157 | ab756200 | Giorgos Verigakis | print_dict(server, self.show_empty) |
158 | ab756200 | Giorgos Verigakis | |
159 | ab756200 | Giorgos Verigakis | |
160 | ab756200 | Giorgos Verigakis | @command_name('create') |
161 | ab756200 | Giorgos Verigakis | class CreateServer(Command): |
162 | ab756200 | Giorgos Verigakis | description = 'create server' |
163 | ab756200 | Giorgos Verigakis | syntax = '<server name>' |
164 | ab756200 | Giorgos Verigakis | |
165 | ab756200 | Giorgos Verigakis | def add_options(self, parser): |
166 | ab756200 | Giorgos Verigakis | parser.add_option('-f', dest='flavor', metavar='FLAVOR_ID', default=1, |
167 | ab756200 | Giorgos Verigakis | help='use flavor FLAVOR_ID') |
168 | ab756200 | Giorgos Verigakis | parser.add_option('-i', dest='image', metavar='IMAGE_ID', default=1, |
169 | ab756200 | Giorgos Verigakis | help='use image IMAGE_ID') |
170 | ab756200 | Giorgos Verigakis | |
171 | ab756200 | Giorgos Verigakis | def execute(self, name): |
172 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers' % self.api |
173 | ab756200 | Giorgos Verigakis | server = {'name': name, 'flavorRef': self.flavor, 'imageRef': self.image} |
174 | ab756200 | Giorgos Verigakis | body = json.dumps({'server': server}) |
175 | ab756200 | Giorgos Verigakis | reply = self.http_post(path, body) |
176 | ab756200 | Giorgos Verigakis | server = reply['server'] |
177 | ab756200 | Giorgos Verigakis | print_dict(server) |
178 | ab756200 | Giorgos Verigakis | |
179 | ab756200 | Giorgos Verigakis | |
180 | ab756200 | Giorgos Verigakis | @command_name('rename') |
181 | ab756200 | Giorgos Verigakis | class UpdateServerName(Command): |
182 | ab756200 | Giorgos Verigakis | description = 'update server name' |
183 | ab756200 | Giorgos Verigakis | syntax = '<server id> <new name>' |
184 | ab756200 | Giorgos Verigakis | |
185 | ab756200 | Giorgos Verigakis | def execute(self, server_id, name): |
186 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers/%d' % (self.api, int(server_id)) |
187 | ab756200 | Giorgos Verigakis | body = json.dumps({'server': {'name': name}}) |
188 | ab756200 | Giorgos Verigakis | self.http_put(path, body) |
189 | ab756200 | Giorgos Verigakis | |
190 | ab756200 | Giorgos Verigakis | |
191 | ab756200 | Giorgos Verigakis | @command_name('delete') |
192 | ab756200 | Giorgos Verigakis | class DeleteServer(Command): |
193 | ab756200 | Giorgos Verigakis | description = 'delete server' |
194 | ab756200 | Giorgos Verigakis | syntax = '<server id>' |
195 | ab756200 | Giorgos Verigakis | |
196 | ab756200 | Giorgos Verigakis | def execute(self, server_id): |
197 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers/%d' % (self.api, int(server_id)) |
198 | ab756200 | Giorgos Verigakis | self.http_delete(path) |
199 | ab756200 | Giorgos Verigakis | |
200 | ab756200 | Giorgos Verigakis | |
201 | ab756200 | Giorgos Verigakis | @command_name('reboot') |
202 | ab756200 | Giorgos Verigakis | class RebootServer(Command): |
203 | ab756200 | Giorgos Verigakis | description = 'reboot server' |
204 | ab756200 | Giorgos Verigakis | syntax = '<server id>' |
205 | ab756200 | Giorgos Verigakis | |
206 | ab756200 | Giorgos Verigakis | def add_options(self, parser): |
207 | ab756200 | Giorgos Verigakis | parser.add_option('-f', action='store_true', dest='hard', default=False, |
208 | ab756200 | Giorgos Verigakis | help='perform a hard reboot') |
209 | ab756200 | Giorgos Verigakis | |
210 | ab756200 | Giorgos Verigakis | def execute(self, server_id): |
211 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers/%d/action' % (self.api, int(server_id)) |
212 | ab756200 | Giorgos Verigakis | type = 'HARD' if self.hard else 'SOFT' |
213 | ab756200 | Giorgos Verigakis | body = json.dumps({'reboot': {'type': type}}) |
214 | ab756200 | Giorgos Verigakis | self.http_post(path, body) |
215 | ab756200 | Giorgos Verigakis | |
216 | ab756200 | Giorgos Verigakis | |
217 | ab756200 | Giorgos Verigakis | @command_name('start') |
218 | ab756200 | Giorgos Verigakis | class StartServer(Command): |
219 | ab756200 | Giorgos Verigakis | description = 'start server' |
220 | ab756200 | Giorgos Verigakis | syntax = '<server id>' |
221 | ab756200 | Giorgos Verigakis | |
222 | ab756200 | Giorgos Verigakis | def execute(self, server_id): |
223 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers/%d/action' % (self.api, int(server_id)) |
224 | ab756200 | Giorgos Verigakis | body = json.dumps({'start': {}}) |
225 | ab756200 | Giorgos Verigakis | self.http_post(path, body) |
226 | ab756200 | Giorgos Verigakis | |
227 | ab756200 | Giorgos Verigakis | |
228 | ab756200 | Giorgos Verigakis | @command_name('shutdown') |
229 | ab756200 | Giorgos Verigakis | class StartServer(Command): |
230 | ab756200 | Giorgos Verigakis | description = 'shutdown server' |
231 | ab756200 | Giorgos Verigakis | syntax = '<server id>' |
232 | ab756200 | Giorgos Verigakis | |
233 | ab756200 | Giorgos Verigakis | def execute(self, server_id): |
234 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers/%d/action' % (self.api, int(server_id)) |
235 | ab756200 | Giorgos Verigakis | body = json.dumps({'shutdown': {}}) |
236 | ab756200 | Giorgos Verigakis | self.http_post(path, body) |
237 | ab756200 | Giorgos Verigakis | |
238 | ab756200 | Giorgos Verigakis | |
239 | 09471611 | Vangelis Koukis | @command_name('console') |
240 | 09471611 | Vangelis Koukis | class ServerConsole(Command): |
241 | 09471611 | Vangelis Koukis | description = 'get VNC console' |
242 | 09471611 | Vangelis Koukis | syntax = '<server id>' |
243 | 09471611 | Vangelis Koukis | |
244 | 09471611 | Vangelis Koukis | def add_options(self, parser): |
245 | 09471611 | Vangelis Koukis | pass |
246 | 09471611 | Vangelis Koukis | |
247 | 09471611 | Vangelis Koukis | def execute(self, server_id): |
248 | 09471611 | Vangelis Koukis | path = '/api/%s/servers/%d/action' % (self.api, int(server_id)) |
249 | 529178b1 | Giorgos Verigakis | body = json.dumps({'console': {'type': 'vnc'}}) |
250 | 4cf8adf8 | Vangelis Koukis | reply = self.http_cmd('POST', path, body, 200) |
251 | 529178b1 | Giorgos Verigakis | print_dict(reply['console']) |
252 | 09471611 | Vangelis Koukis | |
253 | 09471611 | Vangelis Koukis | |
254 | ab756200 | Giorgos Verigakis | @command_name('lsaddr') |
255 | ab756200 | Giorgos Verigakis | class ListAddresses(Command): |
256 | ab756200 | Giorgos Verigakis | description = 'list server addresses' |
257 | ab756200 | Giorgos Verigakis | syntax = '<server id> [network]' |
258 | ab756200 | Giorgos Verigakis | |
259 | ab756200 | Giorgos Verigakis | def execute(self, server_id, network=None): |
260 | ab756200 | Giorgos Verigakis | path = '/api/%s/servers/%d/ips' % (self.api, int(server_id)) |
261 | ab756200 | Giorgos Verigakis | if network: |
262 | ab756200 | Giorgos Verigakis | path += '/%s' % network |
263 | ab756200 | Giorgos Verigakis | reply = self.http_get(path) |
264 | ab756200 | Giorgos Verigakis | |
265 | ab756200 | Giorgos Verigakis | addresses = [reply['network']] if network else reply['addresses']['values'] |
266 | ab756200 | Giorgos Verigakis | for address in addresses: |
267 | ab756200 | Giorgos Verigakis | print address_to_string(address) |
268 | ab756200 | Giorgos Verigakis | |
269 | ab756200 | Giorgos Verigakis | |
270 | ab756200 | Giorgos Verigakis | @command_name('lsflv') |
271 | ab756200 | Giorgos Verigakis | class ListFlavors(Command): |
272 | ab756200 | Giorgos Verigakis | description = 'list flavors' |
273 | ab756200 | Giorgos Verigakis | |
274 | ab756200 | Giorgos Verigakis | def add_options(self, parser): |
275 | ab756200 | Giorgos Verigakis | parser.add_option('-l', action='store_true', dest='detail', default=False, |
276 | ab756200 | Giorgos Verigakis | help='show detailed output') |
277 | ab756200 | Giorgos Verigakis | |
278 | ab756200 | Giorgos Verigakis | def execute(self): |
279 | ab756200 | Giorgos Verigakis | path = '/api/%s/flavors' % self.api |
280 | ab756200 | Giorgos Verigakis | if self.detail: |
281 | ab756200 | Giorgos Verigakis | path += '/detail' |
282 | ab756200 | Giorgos Verigakis | reply = self.http_get(path) |
283 | ab756200 | Giorgos Verigakis | |
284 | ab756200 | Giorgos Verigakis | for flavor in reply['flavors']['values']: |
285 | ab756200 | Giorgos Verigakis | id = flavor.pop('id') |
286 | ab756200 | Giorgos Verigakis | name = flavor.pop('name') |
287 | ab756200 | Giorgos Verigakis | details = ' '.join('%s=%s' % item for item in sorted(flavor.items())) |
288 | ab756200 | Giorgos Verigakis | print '%3d %s %s' % (id, name, details) |
289 | ab756200 | Giorgos Verigakis | |
290 | ab756200 | Giorgos Verigakis | |
291 | d8e50a39 | Giorgos Verigakis | @command_name('flvinfo') |
292 | ab756200 | Giorgos Verigakis | class GetFlavorDetails(Command): |
293 | ab756200 | Giorgos Verigakis | description = 'get flavor details' |
294 | ab756200 | Giorgos Verigakis | syntax = '<flavor id>' |
295 | ab756200 | Giorgos Verigakis | |
296 | ab756200 | Giorgos Verigakis | def execute(self, flavor_id): |
297 | ab756200 | Giorgos Verigakis | path = '/api/%s/flavors/%d' % (self.api, int(flavor_id)) |
298 | ab756200 | Giorgos Verigakis | reply = self.http_get(path) |
299 | ab756200 | Giorgos Verigakis | |
300 | ab756200 | Giorgos Verigakis | flavor = reply['flavor'] |
301 | ab756200 | Giorgos Verigakis | id = flavor.pop('id') |
302 | ab756200 | Giorgos Verigakis | name = flavor.pop('name') |
303 | ab756200 | Giorgos Verigakis | details = ' '.join('%s=%s' % item for item in sorted(flavor.items())) |
304 | ab756200 | Giorgos Verigakis | print '%3d %s %s' % (id, name, details) |
305 | ab756200 | Giorgos Verigakis | |
306 | ab756200 | Giorgos Verigakis | |
307 | ab756200 | Giorgos Verigakis | @command_name('lsimg') |
308 | ab756200 | Giorgos Verigakis | class ListImages(Command): |
309 | ab756200 | Giorgos Verigakis | description = 'list images' |
310 | ab756200 | Giorgos Verigakis | |
311 | ab756200 | Giorgos Verigakis | def add_options(self, parser): |
312 | ab756200 | Giorgos Verigakis | parser.add_option('-l', action='store_true', dest='detail', default=False, |
313 | ab756200 | Giorgos Verigakis | help='show detailed output') |
314 | ab756200 | Giorgos Verigakis | |
315 | ab756200 | Giorgos Verigakis | def execute(self): |
316 | ab756200 | Giorgos Verigakis | path = '/api/%s/images' % self.api |
317 | ab756200 | Giorgos Verigakis | if self.detail: |
318 | ab756200 | Giorgos Verigakis | path += '/detail' |
319 | ab756200 | Giorgos Verigakis | reply = self.http_get(path) |
320 | ab756200 | Giorgos Verigakis | |
321 | ab756200 | Giorgos Verigakis | for image in reply['images']['values']: |
322 | ab756200 | Giorgos Verigakis | id = image.pop('id') |
323 | ab756200 | Giorgos Verigakis | name = image.pop('name') |
324 | ab756200 | Giorgos Verigakis | if self.detail: |
325 | ab756200 | Giorgos Verigakis | print '%d %s' % (id, name) |
326 | ab756200 | Giorgos Verigakis | print_dict(image) |
327 | ab756200 | Giorgos Verigakis | |
328 | ab756200 | Giorgos Verigakis | else: |
329 | ab756200 | Giorgos Verigakis | print '%3d %s' % (id, name) |
330 | ab756200 | Giorgos Verigakis | |
331 | ab756200 | Giorgos Verigakis | |
332 | ab756200 | Giorgos Verigakis | @command_name('imginfo') |
333 | ab756200 | Giorgos Verigakis | class GetImageDetails(Command): |
334 | ab756200 | Giorgos Verigakis | description = 'get image details' |
335 | ab756200 | Giorgos Verigakis | syntax = '<image id>' |
336 | ab756200 | Giorgos Verigakis | |
337 | ab756200 | Giorgos Verigakis | def execute(self, image_id): |
338 | ab756200 | Giorgos Verigakis | path = '/api/%s/images/%d' % (self.api, int(image_id)) |
339 | ab756200 | Giorgos Verigakis | reply = self.http_get(path) |
340 | ab756200 | Giorgos Verigakis | image = reply['image'] |
341 | ab756200 | Giorgos Verigakis | image.pop('id') |
342 | ab756200 | Giorgos Verigakis | print_dict(image) |
343 | ab756200 | Giorgos Verigakis | |
344 | ab756200 | Giorgos Verigakis | |
345 | ab756200 | Giorgos Verigakis | @command_name('createimg') |
346 | ab756200 | Giorgos Verigakis | class CreateImage(Command): |
347 | ab756200 | Giorgos Verigakis | description = 'create image' |
348 | ab756200 | Giorgos Verigakis | syntax = '<server id> <image name>' |
349 | ab756200 | Giorgos Verigakis | |
350 | ab756200 | Giorgos Verigakis | def execute(self, server_id, name): |
351 | ab756200 | Giorgos Verigakis | path = '/api/%s/images' % self.api |
352 | ab756200 | Giorgos Verigakis | image = {'name': name, 'serverRef': int(server_id)} |
353 | ab756200 | Giorgos Verigakis | body = json.dumps({'image': image}) |
354 | ab756200 | Giorgos Verigakis | reply = self.http_post(path, body) |
355 | ab756200 | Giorgos Verigakis | print_dict(reply['image']) |
356 | ab756200 | Giorgos Verigakis | |
357 | ab756200 | Giorgos Verigakis | @command_name('deleteimg') |
358 | ab756200 | Giorgos Verigakis | class DeleteImage(Command): |
359 | ab756200 | Giorgos Verigakis | description = 'delete image' |
360 | ab756200 | Giorgos Verigakis | syntax = '<image id>' |
361 | ab756200 | Giorgos Verigakis | |
362 | ab756200 | Giorgos Verigakis | def execute(self, image_id): |
363 | ab756200 | Giorgos Verigakis | path = '/api/%s/images/%d' % (self.api, int(image_id)) |
364 | ab756200 | Giorgos Verigakis | self.http_delete(path) |
365 | ab756200 | Giorgos Verigakis | |
366 | d8e50a39 | Giorgos Verigakis | @command_name('lsmeta') |
367 | d8e50a39 | Giorgos Verigakis | class ListServerMeta(Command): |
368 | d8e50a39 | Giorgos Verigakis | description = 'list server meta' |
369 | d8e50a39 | Giorgos Verigakis | syntax = '<server id> [key]' |
370 | d8e50a39 | Giorgos Verigakis | |
371 | d8e50a39 | Giorgos Verigakis | def execute(self, server_id, key=None): |
372 | d8e50a39 | Giorgos Verigakis | path = '/api/%s/servers/%d/meta' % (self.api, int(server_id)) |
373 | d8e50a39 | Giorgos Verigakis | if key: |
374 | d8e50a39 | Giorgos Verigakis | path += '/' + key |
375 | d8e50a39 | Giorgos Verigakis | reply = self.http_get(path) |
376 | d8e50a39 | Giorgos Verigakis | if key: |
377 | d8e50a39 | Giorgos Verigakis | print_dict(reply['meta']) |
378 | d8e50a39 | Giorgos Verigakis | else: |
379 | d8e50a39 | Giorgos Verigakis | print_dict(reply['metadata']['values']) |
380 | d8e50a39 | Giorgos Verigakis | |
381 | d8e50a39 | Giorgos Verigakis | @command_name('setmeta') |
382 | d8e50a39 | Giorgos Verigakis | class UpdateServerMeta(Command): |
383 | d8e50a39 | Giorgos Verigakis | description = 'update server meta' |
384 | d8e50a39 | Giorgos Verigakis | syntax = '<server id> <key> <val>' |
385 | d8e50a39 | Giorgos Verigakis | |
386 | d8e50a39 | Giorgos Verigakis | def execute(self, server_id, key, val): |
387 | d8e50a39 | Giorgos Verigakis | path = '/api/%s/servers/%d/meta' % (self.api, int(server_id)) |
388 | d8e50a39 | Giorgos Verigakis | metadata = {key: val} |
389 | d8e50a39 | Giorgos Verigakis | body = json.dumps({'metadata': metadata}) |
390 | d8e50a39 | Giorgos Verigakis | reply = self.http_post(path, body, expected_status=201) |
391 | d8e50a39 | Giorgos Verigakis | print_dict(reply['metadata']) |
392 | d8e50a39 | Giorgos Verigakis | |
393 | d8e50a39 | Giorgos Verigakis | @command_name('addmeta') |
394 | d8e50a39 | Giorgos Verigakis | class CreateServerMeta(Command): |
395 | d8e50a39 | Giorgos Verigakis | description = 'add server meta' |
396 | d8e50a39 | Giorgos Verigakis | syntax = '<server id> <key> <val>' |
397 | d8e50a39 | Giorgos Verigakis | |
398 | d8e50a39 | Giorgos Verigakis | def execute(self, server_id, key, val): |
399 | d8e50a39 | Giorgos Verigakis | path = '/api/%s/servers/%d/meta/%s' % (self.api, int(server_id), key) |
400 | d8e50a39 | Giorgos Verigakis | meta = {key: val} |
401 | d8e50a39 | Giorgos Verigakis | body = json.dumps({'meta': meta}) |
402 | d8e50a39 | Giorgos Verigakis | reply = self.http_put(path, body, expected_status=201) |
403 | d8e50a39 | Giorgos Verigakis | print_dict(reply['meta']) |
404 | d8e50a39 | Giorgos Verigakis | |
405 | d8e50a39 | Giorgos Verigakis | @command_name('delmeta') |
406 | d8e50a39 | Giorgos Verigakis | class DeleteServerMeta(Command): |
407 | d8e50a39 | Giorgos Verigakis | description = 'delete server meta' |
408 | d8e50a39 | Giorgos Verigakis | syntax = '<server id> <key>' |
409 | d8e50a39 | Giorgos Verigakis | |
410 | d8e50a39 | Giorgos Verigakis | def execute(self, server_id, key): |
411 | d8e50a39 | Giorgos Verigakis | path = '/api/%s/servers/%d/meta/%s' % (self.api, int(server_id), key) |
412 | d8e50a39 | Giorgos Verigakis | reply = self.http_delete(path) |
413 | d8e50a39 | Giorgos Verigakis | |
414 | 432fc8c3 | Giorgos Verigakis | @command_name('lsimgmeta') |
415 | 432fc8c3 | Giorgos Verigakis | class ListImageMeta(Command): |
416 | 432fc8c3 | Giorgos Verigakis | description = 'list image meta' |
417 | 432fc8c3 | Giorgos Verigakis | syntax = '<image id> [key]' |
418 | 432fc8c3 | Giorgos Verigakis | |
419 | 432fc8c3 | Giorgos Verigakis | def execute(self, image_id, key=None): |
420 | 432fc8c3 | Giorgos Verigakis | path = '/api/%s/images/%d/meta' % (self.api, int(image_id)) |
421 | 432fc8c3 | Giorgos Verigakis | if key: |
422 | 432fc8c3 | Giorgos Verigakis | path += '/' + key |
423 | 432fc8c3 | Giorgos Verigakis | reply = self.http_get(path) |
424 | 432fc8c3 | Giorgos Verigakis | if key: |
425 | 432fc8c3 | Giorgos Verigakis | print_dict(reply['meta']) |
426 | 432fc8c3 | Giorgos Verigakis | else: |
427 | 432fc8c3 | Giorgos Verigakis | print_dict(reply['metadata']['values']) |
428 | 432fc8c3 | Giorgos Verigakis | |
429 | 432fc8c3 | Giorgos Verigakis | @command_name('setimgmeta') |
430 | 432fc8c3 | Giorgos Verigakis | class UpdateImageMeta(Command): |
431 | 432fc8c3 | Giorgos Verigakis | description = 'update image meta' |
432 | 432fc8c3 | Giorgos Verigakis | syntax = '<image id> <key> <val>' |
433 | 432fc8c3 | Giorgos Verigakis | |
434 | 432fc8c3 | Giorgos Verigakis | def execute(self, image_id, key, val): |
435 | 432fc8c3 | Giorgos Verigakis | path = '/api/%s/images/%d/meta' % (self.api, int(image_id)) |
436 | 432fc8c3 | Giorgos Verigakis | metadata = {key: val} |
437 | 432fc8c3 | Giorgos Verigakis | body = json.dumps({'metadata': metadata}) |
438 | 432fc8c3 | Giorgos Verigakis | reply = self.http_post(path, body, expected_status=201) |
439 | 432fc8c3 | Giorgos Verigakis | print_dict(reply['metadata']) |
440 | 432fc8c3 | Giorgos Verigakis | |
441 | 432fc8c3 | Giorgos Verigakis | @command_name('addimgmeta') |
442 | 432fc8c3 | Giorgos Verigakis | class CreateImageMeta(Command): |
443 | 432fc8c3 | Giorgos Verigakis | description = 'add image meta' |
444 | 432fc8c3 | Giorgos Verigakis | syntax = '<image id> <key> <val>' |
445 | 432fc8c3 | Giorgos Verigakis | |
446 | 432fc8c3 | Giorgos Verigakis | def execute(self, image_id, key, val): |
447 | 432fc8c3 | Giorgos Verigakis | path = '/api/%s/images/%d/meta/%s' % (self.api, int(image_id), key) |
448 | 432fc8c3 | Giorgos Verigakis | meta = {key: val} |
449 | 432fc8c3 | Giorgos Verigakis | body = json.dumps({'meta': meta}) |
450 | 432fc8c3 | Giorgos Verigakis | reply = self.http_put(path, body, expected_status=201) |
451 | 432fc8c3 | Giorgos Verigakis | print_dict(reply['meta']) |
452 | 432fc8c3 | Giorgos Verigakis | |
453 | 432fc8c3 | Giorgos Verigakis | @command_name('delimgmeta') |
454 | 432fc8c3 | Giorgos Verigakis | class DeleteImageMeta(Command): |
455 | 432fc8c3 | Giorgos Verigakis | description = 'delete image meta' |
456 | 432fc8c3 | Giorgos Verigakis | syntax = '<image id> <key>' |
457 | 432fc8c3 | Giorgos Verigakis | |
458 | 432fc8c3 | Giorgos Verigakis | def execute(self, image_id, key): |
459 | 432fc8c3 | Giorgos Verigakis | path = '/api/%s/images/%d/meta/%s' % (self.api, int(image_id), key) |
460 | 432fc8c3 | Giorgos Verigakis | reply = self.http_delete(path) |
461 | 432fc8c3 | Giorgos Verigakis | |
462 | ab756200 | Giorgos Verigakis | |
463 | ab756200 | Giorgos Verigakis | def main(): |
464 | ab756200 | Giorgos Verigakis | try: |
465 | ab756200 | Giorgos Verigakis | name = argv[1] |
466 | ab756200 | Giorgos Verigakis | cls = commands[name] |
467 | ab756200 | Giorgos Verigakis | except (IndexError, KeyError): |
468 | ab756200 | Giorgos Verigakis | print 'Usage: %s <command>' % basename(argv[0]) |
469 | ab756200 | Giorgos Verigakis | |
470 | ab756200 | Giorgos Verigakis | print 'Commands:' |
471 | ab756200 | Giorgos Verigakis | for name, cls in sorted(commands.items()): |
472 | ab756200 | Giorgos Verigakis | description = getattr(cls, 'description', '') |
473 | ab756200 | Giorgos Verigakis | print ' %s %s' % (name.ljust(12), description) |
474 | ab756200 | Giorgos Verigakis | exit(1) |
475 | ab756200 | Giorgos Verigakis | |
476 | ab756200 | Giorgos Verigakis | try: |
477 | ab756200 | Giorgos Verigakis | commands[name](argv[2:]) |
478 | ab756200 | Giorgos Verigakis | except TypeError: |
479 | ab756200 | Giorgos Verigakis | syntax = getattr(cls, 'syntax', '') |
480 | ab756200 | Giorgos Verigakis | if syntax: |
481 | ab756200 | Giorgos Verigakis | print 'Syntax: %s %s' % (name, syntax) |
482 | ab756200 | Giorgos Verigakis | else: |
483 | ab756200 | Giorgos Verigakis | print 'Invalid syntax' |
484 | ab756200 | Giorgos Verigakis | exit(1) |
485 | ab756200 | Giorgos Verigakis | |
486 | ab756200 | Giorgos Verigakis | |
487 | ab756200 | Giorgos Verigakis | if __name__ == '__main__': |
488 | ab756200 | Giorgos Verigakis | main() |