aboutsummaryrefslogtreecommitdiffstats
path: root/tools/python/xen/xend/XendClient.py
blob: 13dc3dbb1eeac682b1931a51ef9379359782b1ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""Client API for the HTTP interface on xend.
Callable as a script - see main().
"""
import sys
import httplib
import types
from StringIO import StringIO
import urlparse

from encode import *
import sxp
import PrettyPrint

DEBUG = 0

class Foo(httplib.HTTPResponse):

    def begin(self):
        fin = self.fp
        while(1):
            buf = fin.readline()
            print "***", buf
            if buf == '':
                print
                sys.exit()


def sxprio(sxpr):
    io = StringIO()
    sxp.show(sxpr, out=io)
    print >> io
    io.seek(0)
    return io

def fileof(val):
    """Converter for passing configs.
    Handles lists, files directly.
    Assumes a string is a file name and passes its contents.
    """
    if isinstance(val, types.ListType):
        return sxprio(val)
    if isinstance(val, types.StringType):
        return file(val)
    if hasattr(val, 'readlines'):
        return val

# todo: need to sort of what urls/paths are using for objects.
# e.g. for domains at the moment return '0'.
# should probably return abs path w.r.t. server, e.g. /xend/domain/0.
# As an arg, assume abs path is obj uri, otherwise just id.

# Function to convert to full url: Xend.uri(path), e.g.
# maps /xend/domain/0 to http://wray-m-3.hpl.hp.com:8000/xend/domain/0
# And should accept urls for ids?

def urljoin(location, root, prefix='', rest=''):
    prefix = str(prefix)
    rest = str(rest)
    base = 'http://' + location + root + prefix
    url = urlparse.urljoin(base, rest)
    return url

def nodeurl(location, root, id=''):
    return urljoin(location, root, 'node/', id)

def domainurl(location, root, id=''):
    return urljoin(location, root, 'domain/', id)

def consoleurl(location, root, id=''):
    return urljoin(location, root, 'console/', id)

def deviceurl(location, root, id=''):
    return urljoin(location, root, 'device/', id)

def vneturl(location, root, id=''):
    return urljoin(location, root, 'vnet/', id)

def eventurl(location, root, id=''):
    return urljoin(location, root, 'event/', id)

def xend_request(url, method, data=None):
    urlinfo = urlparse.urlparse(url)
    (uproto, ulocation, upath, uparam, uquery, ufrag) = urlinfo
    if DEBUG: print url, urlinfo
    if uproto != 'http':
        raise StandardError('Invalid protocol: ' + uproto)
    if DEBUG: print '>xend_request', ulocation, upath, method, data
    (hdr, args) = encode_data(data)
    if data and method == 'GET':
        upath += '?' + args
        args = None
    if method == "POST" and upath.endswith('/'):
        upath = upath[:-1]
    if DEBUG: print "ulocation=", ulocation, "upath=", upath, "args=", args
    #hdr['User-Agent'] = 'Mozilla'
    #hdr['Accept'] = 'text/html,text/plain'
    conn = httplib.HTTPConnection(ulocation)
    #conn.response_class = Foo
    if DEBUG: conn.set_debuglevel(1)
    conn.request(method, upath, args, hdr)
    resp = conn.getresponse()
    if DEBUG: print resp.status, resp.reason
    if DEBUG: print resp.msg.headers
    if resp.status in [204, 404]:
        return None
    if resp.status not in [200, 201, 202, 203]:
        raise RuntimeError(resp.reason)
    pin = sxp.Parser()
    data = resp.read()
    if DEBUG: print "***data" , data
    if DEBUG: print "***"
    pin.input(data);
    pin.input_eof()
    conn.close()
    val = pin.get_val()
    #if isinstance(val, types.ListType) and sxp.name(val) == 'val':
    #    val = val[1]
    if isinstance(val, types.ListType) and sxp.name(val) == 'err':
        raise RuntimeError(val[1])
    if DEBUG: print '**val='; sxp.show(val); print
    return val

def xend_get(url, args=None):
    return xend_request(url, "GET", args)

def xend_call(url, data):
    return xend_request(url, "POST", data)

class Xend:

    SRV_DEFAULT = "localhost:8000"
    ROOT_DEFAULT = "/xend/"

    def __init__(self, srv=None, root=None):
        self.bind(srv, root)

    def bind(self, srv=None, root=None):
        if srv is None: srv = self.SRV_DEFAULT
        if root is None: root = self.ROOT_DEFAULT
        if not root.endswith('/'): root += '/'
        self.location = srv
        self.root = root

    def nodeurl(self, id=''):
        return nodeurl(self.location, self.root, id)

    def domainurl(self, id=''):
        return domainurl(self.location, self.root, id)

    def consoleurl(self, id=''):
        return consoleurl(self.location, self.root, id)

    def deviceurl(self, id=''):
        return deviceurl(self.location, self.root, id)

    def vneturl(self, id=''):
        return vneturl(self.location, self.root, id)

    def eventurl(self, id=''):
        return eventurl(self.location, self.root, id)

    def xend(self):
        return xend_get(urljoin(self.location, self.root))

    def xend_node(self):
        return xend_get(self.nodeurl())

    def xend_node_cpu_rrobin_slice_set(self, slice):
        return xend_call(self.nodeurl(),
                         {'op'      : 'cpu_rrobin_slice_set',
                          'slice'   : slice })
    
    def xend_node_cpu_bvt_slice_set(self, slice):
        return xend_call(self.nodeurl(),
                         {'op'      : 'cpu_bvt_slice_set',
                          'slice'   : slice })

    def xend_domains(self):
        return xend_get(self.domainurl())

    def xend_domain_create(self, conf):
        return xend_call(self.domainurl(),
                         {'op'      : 'create',
                          'config'  : fileof(conf) })

    def xend_domain(self, id):
        return xend_get(self.domainurl(id))

    def xend_domain_unpause(self, id):
        return xend_call(self.domainurl(id),
                         {'op'      : 'unpause'})

    def xend_domain_pause(self, id):
        return xend_call(self.domainurl(id),
                         {'op'      : 'pause'})

    def xend_domain_shutdown(self, id):
        return xend_call(self.domainurl(id),
                         {'op'      : 'shutdown'})

    def xend_domain_destroy(self, id):
        return xend_call(self.domainurl(id),
                         {'op'      : 'destroy'})

    def xend_domain_save(self, id, filename):
        return xend_call(self.domainurl(id),
                         {'op'      : 'save',
                          'file'    : filename})

    def xend_domain_restore(self, id, filename):
        return xend_call(self.domainurl(id),
                         {'op'      : 'restore',
                          'file'    : filename })

    def xend_domain_migrate(self, id, dst):
        return xend_call(self.domainurl(id),
                         {'op'      : 'migrate',
                          'destination': dst})

    def xend_domain_pincpu(self, id, cpu):
        return xend_call(self.domainurl(id),
                         {'op'      : 'pincpu',
                          'cpu'     : cpu})

    def xend_domain_cpu_bvt_set(self, id, mcuadv, warp, warpl, warpu):
        return xend_call(self.domainurl(id),
                         {'op'      : 'cpu_bvt_set',
                          'mcuadv'  : mvuadv,
                          'warp'    : warp,
                          'warpl'   : warpl,
                          'warpu'   : warpu })

    def xend_domain_cpu_atropos_set(self, id, period, slice, latency, xtratime):
        return xend_call(self.domainurl(id),
                         {'op'      : 'cpu_atropos_set',
                          'period'  : period,
                          'slice'   : slice,
                          'latency' : latency,
                          'xtratime': xtratime })

    def xend_domain_vifs(self, id):
        return xend_get(self.domainurl(id),
                        { 'op'      : 'vifs' })
    
    def xend_domain_vif_ip_add(self, id, vif, ipaddr):
        return xend_call(self.domainurl(id),
                         {'op'      : 'vif_ip_add',
                          'vif'     : vif,
                          'ip'      : ipaddr })
        
    def xend_domain_vbds(self, id):
        return xend_get(self.domainurl(id),
                        {'op'       : 'vbds'})

    def xend_domain_vbd(self, id, vbd):
        return xend_get(self.domainurl(id),
                        {'op'       : 'vbd',
                         'vbd'      : vbd})

    def xend_consoles(self):
        return xend_get(self.consoleurl())

    def xend_console(self, id):
        return xend_get(self.consoleurl(id))

    def xend_vnets(self):
        return xend_get(self.vneturl())

    def xend_vnet_create(self, conf):
        return xend_call(self.vneturl(),
                         {'op': 'create', 'config': fileof(conf) })

    def xend_vnet(self, id):
        return xend_get(self.vneturl(id))

    def xend_vnet_delete(self, id):
        return xend_call(self.vneturl(id),
                         {'op': 'delete'})

    def xend_event_inject(self, sxpr):
        val = xend_call(self.eventurl(),
                        {'op': 'inject', 'event': fileof(sxpr) })
    

def main(argv):
    """Call an API function:
    
    python XendClient.py fn args...

    The leading 'xend_' on the function can be omitted.
    Example:

    > python XendClient.py domains
    (domain 0 8)
    > python XendClient.py domain 0
    (domain (id 0) (name Domain-0) (memory 128))
    """
    server = Xend()
    fn = argv[1]
    if not fn.startswith('xend'):
        fn = 'xend_' + fn
    args = argv[2:]
    val = getattr(server, fn)(*args)
    PrettyPrint.prettyprint(val)
    print

if __name__ == "__main__":
    main(sys.argv)
else:    
    server = Xend()