Statistics
| Branch: | Tag: | Revision:

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
            print
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
                print
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
                print
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
        print
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()