direct-io.hg

view tools/python/xen/xend/server/SrvDomainDir.py @ 12779:e98c84468b72

The new lifecycle patches in xen-unstable added 3 new operations which can
be performed on domains - new, start and delete. libvirt has had no-op
stub implementations of these APIs for a while & thus we'd enable their
use for Xen 3.0.4 builds. The new APIs are not currently exposed via the
existing SEXPR protocol, and since the new Xen-API protocol is unsupported
tech-preview for 3.0.4 we don't want to re-write against that just yet.

Thus the attached patch adds the 3 neccessary bindings for the SEXPR protocol
to allow the lifecycle functionality to be invoked. It also allows the 'state'
parameter to be specified when listing domains, so we can explicitly request
inactive domains if we know we're running against a 3.0.4 era XenD

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
author Ewan Mellor <ewan@xensource.com>
date Thu Dec 07 12:15:30 2006 +0000 (2006-12-07)
parents 5bf91da9797d
children 780ef7701772
line source
1 #============================================================================
2 # This library is free software; you can redistribute it and/or
3 # modify it under the terms of version 2.1 of the GNU Lesser General Public
4 # License as published by the Free Software Foundation.
5 #
6 # This library is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 # Lesser General Public License for more details.
10 #
11 # You should have received a copy of the GNU Lesser General Public
12 # License along with this library; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 #============================================================================
15 # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
16 #============================================================================
18 import traceback
19 from StringIO import StringIO
21 from xen.web import http
23 from xen.xend import sxp
24 from xen.xend import XendDomain
25 from xen.xend.XendDomainInfo import XendDomainInfo
26 from xen.xend.Args import FormFn
27 from xen.xend.XendError import XendError
28 from xen.xend.XendLogging import log
29 from xen.xend.XendConstants import DOM_STATE_RUNNING
31 from xen.web.SrvDir import SrvDir
32 from SrvDomain import SrvDomain
35 class SrvDomainDir(SrvDir):
36 """Service that manages the domain directory.
37 """
39 def __init__(self):
40 SrvDir.__init__(self)
41 self.xd = XendDomain.instance()
43 def domain(self, x):
44 dom = self.xd.domain_lookup(x)
45 if not dom:
46 raise XendError('No such domain ' + str(x))
47 return SrvDomain(dom)
49 def get(self, x):
50 v = SrvDir.get(self, x)
51 if v is not None:
52 return v
53 else:
54 return self.domain(x)
56 def op_create(self, _, req):
57 """Create a domain.
58 Expects the domain config in request parameter 'config' in SXP format.
59 """
60 ok = 0
61 errmsg = ''
62 try:
63 configstring = req.args.get('config')[0]
64 #print 'op_create>', 'config:', configstring
65 pin = sxp.Parser()
66 pin.input(configstring)
67 pin.input_eof()
68 config = pin.get_val()
69 ok = 1
70 except sxp.ParseError, ex:
71 errmsg = 'Invalid configuration ' + str(ex)
72 except Exception, ex:
73 print 'op_create> Exception in config', ex
74 traceback.print_exc()
75 errmsg = 'Configuration error ' + str(ex)
76 if not ok:
77 raise XendError(errmsg)
78 try:
79 dominfo = self.xd.domain_create(config)
80 return self._op_create_cb(dominfo, configstring, req)
81 except Exception, ex:
82 print 'op_create> Exception creating domain:'
83 traceback.print_exc()
84 raise XendError("Error creating domain: " + str(ex))
86 def _op_create_cb(self, dominfo, configstring, req):
87 """Callback to handle domain creation.
88 """
89 dom = dominfo.getName()
90 domurl = "%s/%s" % (req.prePathURL(), dom)
91 req.setResponseCode(http.CREATED, "created")
92 req.setHeader("Location", domurl)
93 if self.use_sxp(req):
94 return dominfo.sxpr()
95 else:
96 out = StringIO()
97 print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
98 % (domurl, dom))
99 print >> out, '<p><pre>'
100 print >> out, configstring
101 print >> out, '</pre></p>'
102 val = out.getvalue()
103 out.close()
104 return val
106 def op_new(self, _, req):
107 """Define a new domain.
108 Expects the domain config in request parameter 'config' in SXP format.
109 """
110 ok = 0
111 errmsg = ''
112 try:
113 configstring = req.args.get('config')[0]
114 #print 'op_create>', 'config:', configstring
115 pin = sxp.Parser()
116 pin.input(configstring)
117 pin.input_eof()
118 config = pin.get_val()
119 ok = 1
120 except sxp.ParseError, ex:
121 errmsg = 'Invalid configuration ' + str(ex)
122 except Exception, ex:
123 print 'op_create> Exception in config', ex
124 traceback.print_exc()
125 errmsg = 'Configuration error ' + str(ex)
126 if not ok:
127 raise XendError(errmsg)
128 try:
129 self.xd.domain_new(config)
130 except Exception, ex:
131 print 'op_create> Exception creating domain:'
132 traceback.print_exc()
133 raise XendError("Error creating domain: " + str(ex))
135 def op_restore(self, op, req):
136 """Restore a domain from file.
138 """
139 return req.threadRequest(self.do_restore, op, req)
141 def do_restore(self, _, req):
142 fn = FormFn(self.xd.domain_restore,
143 [['file', 'str']])
144 dominfo = fn(req.args)
145 dom = dominfo.getName()
146 domurl = "%s/%s" % (req.prePathURL(), dom)
147 req.setResponseCode(http.CREATED)
148 req.setHeader("Location", domurl)
149 if self.use_sxp(req):
150 return dominfo.sxpr()
151 else:
152 out = StringIO()
153 print >> out, ('<p> Created <a href="%s">Domain %s</a></p>'
154 % (domurl, dom))
155 val = out.getvalue()
156 out.close()
157 return val
160 def op_list(self, _, req):
161 """List the details for this domain."""
162 self._list(req, True)
165 def render_POST(self, req):
166 return self.perform(req)
168 def render_GET(self, req):
169 self._list(req, 'detail' in req.args and req.args['detail'] == ['1'])
172 def _list(self, req, detail):
173 if self.use_sxp(req):
174 req.setHeader("Content-Type", sxp.mime_type)
175 self.ls_domain(req, detail, True)
176 else:
177 req.write("<html><head></head><body>")
178 self.print_path(req)
179 self.ls(req)
180 self.ls_domain(req, detail, False)
181 self.form(req)
182 req.write("</body></html>")
185 def ls_domain(self, req, detail, use_sxp):
186 url = req.prePathURL()
187 if not url.endswith('/'):
188 url += '/'
189 if use_sxp:
190 if detail:
191 sxp.show(map(XendDomainInfo.sxpr, self.xd.list()), out=req)
192 else:
193 state = DOM_STATE_RUNNING
194 if 'state' in req.args and len(req.args['state']) > 0:
195 state = req.args['state'][0]
196 log.debug("Listing domains in state " + str(state))
197 sxp.show(self.xd.list_names(state), out=req)
198 else:
199 domains = self.xd.list_sorted()
200 req.write('<ul>')
201 for d in domains:
202 req.write(
203 '<li><a href="%s%s">Domain %s</a>: id = %s, memory = %d'
204 % (url, d.getName(), d.getName(), d.getDomid(),
205 d.getMemoryTarget()))
206 req.write('</li>')
207 req.write('</ul>')
210 def form(self, req):
211 """Generate the form(s) for domain dir operations.
212 """
213 req.write('<form method="post" action="%s" enctype="multipart/form-data">'
214 % req.prePathURL())
215 req.write('<button type="submit" name="op" value="create">Create Domain</button>')
216 req.write('Config <input type="file" name="config"><br>')
217 req.write('</form>')
219 req.write('<form method="post" action="%s" enctype="multipart/form-data">'
220 % req.prePathURL())
221 req.write('<button type="submit" name="op" value="restore">Restore Domain</button>')
222 req.write('State <input type="string" name="state"><br>')
223 req.write('</form>')