bitkeeper revision 1.1080 (40f50d9aaH0Dd_smhBdPvYcIQFbsoA)

Improved error handling in xend and XendClient.
This commit is contained in:
mjw@wray-m-3.hpl.hp.com committed 2004-07-14 10:40:26 +00:00
1 parent 838c51889a
commit bcb3aec834
16 files changed
+224 -140

No files matched your search

+1
View File
@@ -240,6 +240,7 @@
40c9c468fSl3H3IypyT0ppkbb0ZT9A tools/python/xen/xend/XendDomain.py
40c9c468bbKq3uC7_fuNUkiMMjArdw tools/python/xen/xend/XendDomainConfig.py
40c9c4685ykq87_n1kVUbMr9flx9fg tools/python/xen/xend/XendDomainInfo.py
40f50d99YiiaMI1fZBh1VCDFLD57qg tools/python/xen/xend/XendError.py
40c9c46854nsHmuxHQHncKk5rAs5NA tools/python/xen/xend/XendMigrate.py
40c9c468M96gA1EYDvNa5w5kQNYLFA tools/python/xen/xend/XendNode.py
40c9c4686jruMyZIqiaZRMiMoqMJtg tools/python/xen/xend/XendRoot.py
+5 -3
View File
@@ -13,6 +13,8 @@ import types
from StringIO import StringIO
import urlparse
from twisted.protocols import http
from encode import *
import sxp
import PrettyPrint
@@ -121,9 +123,9 @@ def xend_request(url, method, data=None):
resp = conn.getresponse()
if DEBUG: print resp.status, resp.reason
if DEBUG: print resp.msg.headers
if resp.status in [204, 404]:
if resp.status in [ http.NO_CONTENT ]:
return None
if resp.status not in [200, 201, 202, 203]:
if resp.status not in [ http.OK, http.CREATED, http.ACCEPTED ]:
raise XendError(resp.reason)
pin = sxp.Parser()
data = resp.read()
@@ -135,7 +137,7 @@ def xend_request(url, method, data=None):
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':
if isinstance(val, types.ListType) and sxp.name(val) == 'xend.err':
raise XendError(val[1])
if DEBUG: print '**val='; sxp.show(val); print
return val
+5 -4
View File
@@ -21,6 +21,7 @@ import XendDomainInfo
import XendConsole
import XendMigrate
import EventServer
from XendError import XendError
from xen.xend.server import SrvDaemon
xend = SrvDaemon.instance()
@@ -324,9 +325,9 @@ class XendDomain:
dom = int(id)
dominfo = self.domain_get(dom)
if not dominfo:
raise ValueError("Invalid domain: " + str(id))
raise XendError("Invalid domain: " + str(id))
if dominfo.config:
raise ValueError("Domain already configured: " + str(id))
raise XendError("Domain already configured: " + str(id))
def fn(dominfo):
self._add_domain(dominfo.id, dominfo)
return dominfo
@@ -575,7 +576,7 @@ class XendDomain:
dom = int(dom)
dominfo = self.domain_get(dom)
if not dominfo:
raise ValueError("invalid domain:" + str(dom))
raise XendError("invalid domain:" + str(dom))
self.refresh_schedule()
return dominfo.device_create(devconfig)
@@ -589,7 +590,7 @@ class XendDomain:
dom = int(dom)
dominfo = self.domain_get(dom)
if not dominfo:
raise ValueError("invalid domain:" + str(dom))
raise XendError("invalid domain:" + str(dom))
self.refresh_schedule()
return dominfo.device_destroy(type, idx)
+6 -10
View File
@@ -29,6 +29,8 @@ xendConsole = XendConsole.instance()
import server.SrvDaemon
xend = server.SrvDaemon.instance()
from XendError import VmError
"""Flag for a block device backend domain."""
SIF_BLK_BE_DOMAIN = (1<<4)
@@ -58,16 +60,6 @@ def shutdown_reason(code):
"""
return shutdown_reasons.get(code, "?")
class VmError(ValueError):
"""Vm construction error."""
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
def blkdev_name_to_number(name):
"""Take the given textual block-device name (e.g., '/dev/sda1',
'hda') and return the device number used by the OS. """
@@ -410,7 +402,11 @@ class XendDomainInfo:
self.autorestart = 1
self.configure_backends()
image = sxp.child_value(config, 'image')
if image is None:
raise VmError('missing image')
image_name = sxp.name(image)
if image_name is None:
raise VmError('missing image name')
image_handler = get_image_handler(image_name)
if image_handler is None:
raise VmError('unknown image type: ' + image_name)
+14
View File
@@ -0,0 +1,14 @@
class XendError(ValueError):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
class VmError(XendError):
"""Vm construction error."""
pass
+55 -12
View File
@@ -10,12 +10,15 @@ import StringIO
from twisted.internet import defer
#defer.Deferred.debug = 1
from twisted.internet import reactor
from twisted.protocols import http
from twisted.web import error
from twisted.web import resource
from twisted.web import server
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend.Args import ArgError
from xen.xend.XendError import XendError
def uri_pathlist(p):
"""Split a path into a list.
@@ -86,33 +89,45 @@ class SrvBase(resource.Resource):
"""
op = req.args.get('op')
if op is None or len(op) != 1:
req.setResponseCode(404, "Invalid")
req.setResponseCode(http.NOT_ACCEPTABLE, "Invalid request")
return ''
op = op[0]
op_method = self.get_op_method(op)
if op_method is None:
req.setResponseCode(501, "Not implemented")
req.setResponseCode(http.NOT_IMPLEMENTED, "Operation not implemented: " + op)
req.setHeader("Content-Type", "text/plain")
req.write("Not implemented: " + op)
req.write("Operation not implemented: " + op)
return ''
else:
val = op_method(op, req)
if isinstance(val, defer.Deferred):
val.addCallback(self._cb_perform, req, 1)
return server.NOT_DONE_YET
else:
self._cb_perform(val, req, 0)
return ''
return self._perform(op, op_method, req)
def _cb_perform(self, val, req, dfr):
def _perform(self, op, op_method, req):
try:
val = op_method(op, req)
except Exception, err:
return self._perform_err(err, req)
if isinstance(val, defer.Deferred):
val.addCallback(self._perform_cb, req, dfr=1)
val.addErrback(self._perform_err, req, dfr=1)
return server.NOT_DONE_YET
else:
self._perform_cb(val, req, 0)
return ''
def _perform_cb(self, val, req, dfr):
"""Callback to complete the request.
May be called from a Deferred.
@param err: the error
@param req: request causing the error
@param dfr: deferred flag
"""
if isinstance(val, error.ErrorPage):
req.write(val.render(req))
elif self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(val, req)
sxp.show(val, out=req)
else:
req.write('<html><head></head><body>')
self.print_path(req)
@@ -126,6 +141,34 @@ class SrvBase(resource.Resource):
if dfr:
req.finish()
def _perform_err(self, err, req, dfr=0):
"""Error callback to complete a request.
May be called from a Deferred.
@param err: the error
@param req: request causing the error
@param dfr: deferred flag
"""
if not (isinstance(err, ArgError) or
isinstance(err, sxp.ParseError) or
isinstance(err, XendError)):
if dfr:
return err
else:
raise
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(['xend.err', str(err)], out=req)
else:
req.setHeader("Content-Type", "text/plain")
req.write('Error in ')
req.write(op)
req.write(': ')
req.write(str(err))
if dfr:
req.finish()
def print_path(self, req):
"""Print the path with hyperlinks.
"""
+16 -13
View File
@@ -21,19 +21,22 @@ class SrvConsole(SrvDir):
return self.perform(req)
def render_GET(self, req):
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(self.info.sxpr(), out=req)
else:
req.write('<html><head></head><body>')
self.print_path(req)
#self.ls()
req.write('<p>%s</p>' % self.info)
req.write('<p><a href="%s">Connect to domain %d</a></p>'
% (self.info.uri(), self.info.dom2))
self.form(req)
req.write('</body></html>')
return ''
try:
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(self.info.sxpr(), out=req)
else:
req.write('<html><head></head><body>')
self.print_path(req)
#self.ls()
req.write('<p>%s</p>' % self.info)
req.write('<p><a href="%s">Connect to domain %d</a></p>'
% (self.info.uri(), self.info.dom2))
self.form(req)
req.write('</body></html>')
return ''
except Exception, ex:
self._perform_err(ex, req)
def form(self, req):
req.write('<form method="post" action="%s">' % req.prePathURL())
+14 -11
View File
@@ -31,17 +31,20 @@ class SrvConsoleDir(SrvDir):
return v
def render_GET(self, req):
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
self.ls_console(req, 1)
else:
req.write("<html><head></head><body>")
self.print_path(req)
self.ls(req)
self.ls_console(req)
#self.form(req.wfile)
req.write("</body></html>")
return ''
try:
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
self.ls_console(req, 1)
else:
req.write("<html><head></head><body>")
self.print_path(req)
self.ls(req)
self.ls_console(req)
#self.form(req.wfile)
req.write("</body></html>")
return ''
except Exception, ex:
self._perform_err(ex, req)
def ls_console(self, req, use_sxp=0):
url = req.prePathURL()
+10 -9
View File
@@ -31,6 +31,7 @@ from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend import EventServer
eserver = EventServer.instance()
from xen.xend.XendError import XendError
from xen.xend.server import SrvServer
@@ -114,7 +115,7 @@ class MgmtProtocol(protocol.DatagramProtocol):
"""
print name, req
dom = sxp.child_value(req, 'domain')
if not dom: raise ValueError('Missing domain')
if not dom: raise XendError('Missing domain')
dom = int(dom)
console_port = sxp.child_value(req, 'console_port')
if console_port:
@@ -131,11 +132,11 @@ class MgmtProtocol(protocol.DatagramProtocol):
def op_console_disconnect(self, name, req):
id = sxp.child_value(req, 'id')
if not id:
raise ValueError('Missing console id')
raise XendError('Missing console id')
id = int(id)
console = self.daemon.get_console(id)
if not console:
raise ValueError('Invalid console id')
raise XendError('Invalid console id')
if console.conn:
console.conn.loseConnection()
return ['ok']
@@ -340,7 +341,7 @@ class EventProtocol(protocol.Protocol):
return 'op_' + name.replace('.', '_')
def operror(self, name, req):
raise NotImplementedError('Invalid operation: ' +name)
raise XendError('Invalid operation: ' +name)
def dispatch(self, req):
op_name = sxp.name(req)
@@ -371,7 +372,7 @@ class EventProtocol(protocol.Protocol):
def op_console_disconnect(self, name, req):
id = sxp.child_value(req, 'id')
if not id:
raise ValueError('Missing console id')
raise XendError('Missing console id')
self.daemon.console_disconnect(id)
return ['ok']
@@ -707,7 +708,7 @@ class Daemon:
"""
ctrl = self.blkifCF.getInstanceByDom(dom)
if not ctrl:
raise ValueError('No blkif controller: %d' % dom)
raise XendError('No blkif controller: %d' % dom)
print 'blkif_dev_create>', dom, vdev, mode, segment
d = ctrl.attachDevice(vdev, mode, segment, recreate=recreate)
return d
@@ -740,7 +741,7 @@ class Daemon:
"""
ctrl = self.netifCF.getInstanceByDom(dom)
if not ctrl:
raise ValueError('No netif controller: %d' % dom)
raise XendError('No netif controller: %d' % dom)
d = ctrl.attachDevice(vif, config, recreate=recreate)
return d
@@ -769,7 +770,7 @@ class Daemon:
"""
console = self.get_console(id)
if not console:
raise ValueError('Invalid console id')
raise XendError('Invalid console id')
console.disconnect()
def domain_shutdown(self, dom, reason):
@@ -777,7 +778,7 @@ class Daemon:
"""
ctrl = self.domainCF.getInstanceByDom(dom)
if not ctrl:
raise ValueError('No domain controller: %d' % dom)
raise XendError('No domain controller: %d' % dom)
ctrl.shutdown(reason)
return 0
+32 -12
View File
@@ -1,9 +1,20 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
from twisted.protocols import http
from twisted.web import error
from xen.xend import sxp
from xen.xend.XendError import XendError
from SrvBase import SrvBase
class SrvError(error.ErrorPage):
def render(self, request):
val = error.ErrorPage.render(self, request)
request.setResponseCode(self.code, self.brief)
return val
class SrvConstructor:
"""Delayed constructor for sub-servers.
Does not import the sub-server class or create the object until needed.
@@ -38,11 +49,17 @@ class SrvDir(SrvBase):
self.table = {}
self.order = []
def noChild(self, msg):
return SrvError(http.NOT_FOUND, msg, msg)
def getChild(self, x, req):
if x == '': return self
val = self.get(x)
try:
val = self.get(x)
except XendError, ex:
return self.noChild(str(ex))
if val is None:
return error.NoResource('Not found')
return self.noChild('Not found ' + str(x))
else:
return val
@@ -59,16 +76,19 @@ class SrvDir(SrvBase):
self.order.append(x)
def render_GET(self, req):
if self.use_sxp(req):
req.setHeader("Content-type", sxp.mime_type)
self.ls(req, 1)
else:
req.write('<html><head></head><body>')
self.print_path(req)
self.ls(req)
self.form(req)
req.write('</body></html>')
return ''
try:
if self.use_sxp(req):
req.setHeader("Content-type", sxp.mime_type)
self.ls(req, 1)
else:
req.write('<html><head></head><body>')
self.print_path(req)
self.ls(req)
self.form(req)
req.write('</body></html>')
return ''
except Exception, ex:
self._perform_err(ex, req)
def ls(self, req, use_sxp=0):
url = req.prePathURL()
+13 -10
View File
@@ -14,16 +14,19 @@ class SrvDmesg(SrvDir):
self.xd = XendDmesg.instance()
def render_GET(self, req):
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(['dmesg'] + self.info(), out=req)
else:
req.write('<html><head></head><body>')
req.write('<pre>')
self.print_path(req)
req.write(self.info()[0])
req.write('</pre></body></html>')
return ''
try:
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(['dmesg'] + self.info(), out=req)
else:
req.write('<html><head></head><body>')
req.write('<pre>')
self.print_path(req)
req.write(self.info()[0])
req.write('</pre></body></html>')
return ''
except Exception, ex:
self._perform_err(ex, req)
def info(self):
return self.xd.info()
+2 -9
View File
@@ -100,15 +100,8 @@ class SrvDomain(SrvDir):
fn = FormFn(self.xd.domain_device_create,
[['dom', 'int'],
['config', 'sxpr']])
try:
d = fn(req.args, {'dom': self.dom.id})
d.addErrback(self._op_device_create_err, req)
return d
except ValueError, ex:
return ['err', str(ex)]
def _op_device_create_err(self, err, req):
return ['err', str(err)]
d = fn(req.args, {'dom': self.dom.id})
return d
def op_device_destroy(self, op, req):
fn = FormFn(self.xd.domain_device_destroy,
+26 -28
View File
@@ -9,6 +9,7 @@ from twisted.web import error
from xen.xend import sxp
from xen.xend import XendDomain
from xen.xend.Args import FormFn
from xen.xend.XendError import XendError
from SrvDir import SrvDir
from SrvDomain import SrvDomain
@@ -23,13 +24,10 @@ class SrvDomainDir(SrvDir):
def domain(self, x):
val = None
try:
dom = self.xd.domain_get(x)
if not dom: raise KeyError('No such domain')
val = SrvDomain(dom)
except KeyError, ex:
print 'SrvDomainDir>', ex
pass
dom = self.xd.domain_get(x)
if not dom:
raise XendError('No such domain ' + str(x))
val = SrvDomain(dom)
return val
def get(self, x):
@@ -44,6 +42,7 @@ class SrvDomainDir(SrvDir):
Expects the domain config in request parameter 'config' in SXP format.
"""
ok = 0
errmsg = ''
try:
configstring = req.args.get('config')[0]
print 'config:', configstring
@@ -55,12 +54,12 @@ class SrvDomainDir(SrvDir):
except Exception, ex:
print 'op_create> Exception in config', ex
traceback.print_exc()
errmsg = 'Configuration error ' + str(ex)
except sxp.ParseError, ex:
errmsg = 'Invalid configuration ' + str(ex)
if not ok:
req.setResponseCode(http.BAD_REQUEST, "Invalid configuration")
return "Invalid configuration"
return error.ErrorPage(http.BAD_REQUEST,
"Invalid",
"Invalid configuration")
req.setResponseCode(http.BAD_REQUEST, errmsg)
return errmsg
try:
deferred = self.xd.domain_create(config)
deferred.addCallback(self._op_create_cb, configstring, req)
@@ -71,10 +70,6 @@ class SrvDomainDir(SrvDir):
traceback.print_exc()
req.setResponseCode(http.BAD_REQUEST, "Error creating domain: " + str(ex))
return str(ex)
#return error.ErrorPage(http.BAD_REQUEST,
# "Error creating domain",
# str(ex))
def _op_create_cb(self, dominfo, configstring, req):
"""Callback to handle deferred domain creation.
@@ -113,7 +108,7 @@ class SrvDomainDir(SrvDir):
[['file', 'str']])
deferred = fn(req.args)
deferred.addCallback(self._op_restore_cb, req)
deferred.addErrback(self._op_restore_err, req)
#deferred.addErrback(self._op_restore_err, req)
return deferred
def _op_restore_cb(self, dominfo, req):
@@ -140,17 +135,20 @@ class SrvDomainDir(SrvDir):
return self.perform(req)
def render_GET(self, req):
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
self.ls_domain(req, 1)
else:
req.write("<html><head></head><body>")
self.print_path(req)
self.ls(req)
self.ls_domain(req)
self.form(req)
req.write("</body></html>")
return ''
try:
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
self.ls_domain(req, 1)
else:
req.write("<html><head></head><body>")
self.print_path(req)
self.ls(req)
self.ls_domain(req)
self.form(req)
req.write("</body></html>")
return ''
except Exception, ex:
self._perform_err(ex, req)
def ls_domain(self, req, use_sxp=0):
url = req.prePathURL()
+19 -16
View File
@@ -45,22 +45,25 @@ class SrvNode(SrvDir):
return self.perform(req)
def render_GET(self, req):
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(['node'] + self.info(), out=req)
else:
url = req.prePathURL()
if not url.endswith('/'):
url += '/'
req.write('<html><head></head><body>')
self.print_path(req)
req.write('<ul>')
for d in self.info():
req.write('<li> %10s: %s' % (d[0], str(d[1])))
req.write('<li><a href="' +url + 'dmesg">Xen dmesg output</a>')
req.write('</ul>')
req.write('</body></html>')
return ''
try:
if self.use_sxp(req):
req.setHeader("Content-Type", sxp.mime_type)
sxp.show(['node'] + self.info(), out=req)
else:
url = req.prePathURL()
if not url.endswith('/'):
url += '/'
req.write('<html><head></head><body>')
self.print_path(req)
req.write('<ul>')
for d in self.info():
req.write('<li> %10s: %s' % (d[0], str(d[1])))
req.write('<li><a href="' + url + 'dmesg">Xen dmesg output</a>')
req.write('</ul>')
req.write('</body></html>')
return ''
except Exception, ex:
self._perform_err(ex, req)
def info(self):
return self.xn.info()
+3 -1
View File
@@ -1,5 +1,7 @@
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
from xen.xend.XendError import XendError
import channel
import controller
from messages import *
@@ -57,6 +59,6 @@ class DomainController(controller.Controller):
"""
msgtype = self.reasons.get(reason)
if not msgtype:
raise ValueError('invalid reason:' + reason)
raise XendError('invalid reason:' + reason)
msg = packMsg(msgtype, {})
self.writeRequest(msg)
+3 -2
View File
@@ -8,6 +8,7 @@ from twisted.internet import defer
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend import Vifctl
from xen.xend.XendError import XendError
import channel
import controller
@@ -123,9 +124,9 @@ class NetDev(controller.Dev):
self.ipaddr = None
vmac = sxp.child_value(config, 'mac')
if not vmac: raise ValueError("invalid mac")
if not vmac: raise XendError("invalid mac")
mac = [ int(x, 16) for x in vmac.split(':') ]
if len(mac) != 6: raise ValueError("invalid mac")
if len(mac) != 6: raise XendError("invalid mac")
self.mac = mac
self.bridge = sxp.child_value(config, 'bridge')
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.