Statistics
| Branch: | Tag: | Revision:

root / tools / cloud @ f533f224

History | View | Annotate | Download (18 kB)

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