[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] merge?
# HG changeset patch # User cl349@xxxxxxxxxxxxxxxxxxxx # Node ID 308260e5868ce792f1a1276c4b0a04305a128216 # Parent cedb89d6b707071ba66fefe64b19925da9d68334 # Parent 8f9dfc5fb51c6110c3b59d53ee9f40dec90a58ba merge? diff -r cedb89d6b707 -r 308260e5868c docs/Makefile --- a/docs/Makefile Mon Sep 19 09:14:41 2005 +++ b/docs/Makefile Mon Sep 19 10:51:05 2005 @@ -36,11 +36,12 @@ $(MAKE) $(DOC_HTML); fi python-dev-docs: - mkdir -p api/tools/python + @mkdir -v -p api/tools/python @if which $(DOXYGEN) 1>/dev/null 2>/dev/null; then \ echo "Running doxygen to generate Python tools APIs ... "; \ $(DOXYGEN) Doxyfile; \ - $(MAKE) -C api/tools/python/latex ; fi + $(MAKE) -C api/tools/python/latex ; else \ + echo "Doxygen not installed; skipping python-dev-docs."; fi clean: rm -rf .word_count *.aux *.dvi *.bbl *.blg *.glo *.idx *~ diff -r cedb89d6b707 -r 308260e5868c tools/python/pylintrc --- a/tools/python/pylintrc Mon Sep 19 09:14:41 2005 +++ b/tools/python/pylintrc Mon Sep 19 10:51:05 2005 @@ -74,7 +74,7 @@ init-import=no # List of variable names used for dummy variables (i.e. not used). -dummy-variables=_,dummy +dummy-variables=_,_1,_2,_3,_4,_5,dummy @@ -131,7 +131,7 @@ bad-names=foo,bar,baz,toto,tutu,tata # List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input +bad-functions=apply,input diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/sv/Main.py --- a/tools/python/xen/sv/Main.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/sv/Main.py Mon Sep 19 10:51:05 2005 @@ -1,5 +1,4 @@ -from xen.sv.HTMLBase import HTMLBase from xen.sv.NodeInfo import NodeInfo from xen.sv.DomInfo import DomInfo from xen.sv.CreateDomain import CreateDomain @@ -33,15 +32,8 @@ result.append( (key, self.fieldStorage.getlist( key ) ) ) return result -class TwistedAdapter: - def __init__( self, req ): - self.args = Args( req ) - self.uri = req.unparsed_uri - self.url = req.uri - self.write = req.write - # This is the Main class -# It peices together all the modules +# It pieces together all the modules class Main: def __init__( self ): @@ -61,7 +53,7 @@ self.init_modules( request ) self.init_done = True - for moduleName, module in self.modules.iteritems(): + for _, module in self.modules.iteritems(): module.write_MENU( request ) request.write( "\n" ) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/sv/Wizard.py --- a/tools/python/xen/sv/Wizard.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/sv/Wizard.py Mon Sep 19 10:51:05 2005 @@ -47,7 +47,7 @@ def __init__( self, urlWriter, title, location ): HTMLBase.__init__( self ) self.urlWriter = urlWriter - self.feilds = [] + self.fields = [] self.title = title self.location = location self.passback = None @@ -86,9 +86,9 @@ request.write( "<table width='100%' cellpadding='0' cellspacing='1' border='0'>" ) - for (feild, control) in self.feilds: - control.write_Control( request, previous_values.get( feild ) ) - if previous_values.get( feild ) is not None and not control.validate( previous_values.get( feild ) ): + for (field, control) in self.fields: + control.write_Control( request, previous_values.get( field ) ) + if previous_values.get( field ) is not None and not control.validate( previous_values.get( field ) ): control.write_Help( request ) request.write( "</table>" ) @@ -97,7 +97,7 @@ #request.write( "<input type='hidden' name='visited-sheet%s' value='True'></p>" % self.location ) def addControl( self, control ): - self.feilds.append( [ control.getName(), control ] ) + self.fields.append( [ control.getName(), control ] ) def validate( self, request ): @@ -108,10 +108,10 @@ previous_values = ssxp2hash( string2sxp( self.passback ) ) #get the map for quick reference if DEBUG: print previous_values - for (feild, control) in self.feilds: - if not control.validate( previous_values.get( feild ) ): + for (field, control) in self.fields: + if not control.validate( previous_values.get( field ) ): check = False - if DEBUG: print "> %s = %s" % (feild, previous_values.get( feild )) + if DEBUG: print "> %s = %s" % (field, previous_values.get( field )) return check @@ -143,7 +143,7 @@ class InputControl( SheetControl ): - def __init__( self, name, defaultValue, humanText, reg_exp = ".*", help_text = "You must enter the appropriate details in this feild." ): + def __init__( self, name, defaultValue, humanText, reg_exp = ".*", help_text = "You must enter the appropriate details in this field." ): SheetControl.__init__( self, reg_exp ) self.setName( name ) @@ -206,7 +206,7 @@ class FileControl( InputControl ): - def __init__( self, name, defaultValue, humanText, reg_exp = ".*", help_text = "You must enter the appropriate details in this feild." ): + def __init__( self, name, defaultValue, humanText, reg_exp = ".*", help_text = "You must enter the appropriate details in this field." ): InputControl.__init__( self, name, defaultValue, humanText ) def validate( self, persistedValue ): diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/Args.py --- a/tools/python/xen/xend/Args.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/Args.py Mon Sep 19 10:51:05 2005 @@ -32,12 +32,12 @@ self.arg_dict = {} self.key_ord = [] self.key_dict = {} - for (name, type) in paramspec: + for (name, typ) in paramspec: self.arg_ord.append(name) - self.arg_dict[name] = type - for (name, type) in keyspec: + self.arg_dict[name] = typ + for (name, typ) in keyspec: self.key_ord.append(name) - self.key_dict[name] = type + self.key_dict[name] = typ def get_args(self, d, xargs=None): args = {} @@ -56,12 +56,12 @@ def split_args(self, d, args, keys): for (k, v) in d.items(): if k in self.arg_dict: - type = self.arg_dict[k] - val = self.coerce(type, v) + typ = self.arg_dict[k] + val = self.coerce(typ, v) args[k] = val elif k in self.key_dict: - type = self.key_dict[k] - val = self.coerce(type, v) + typ = self.key_dict[k] + val = self.coerce(typ, v) keys[k] = val else: raise ArgError('Invalid parameter: %s' % k) @@ -85,20 +85,20 @@ d[k] = val return self.get_args(d, xargs=xargs) - def coerce(self, type, v): + def coerce(self, typ, v): try: - if type == 'int': + if typ == 'int': val = int(v) - elif type == 'long': + elif typ == 'long': val = long(v) - elif type == 'str': + elif typ == 'str': val = str(v) - elif type == 'sxpr': + elif typ == 'sxpr': val = self.sxpr(v) - elif type == 'bool': + elif typ == 'bool': val = self.bool(v) else: - raise ArgError('invalid type:' + str(type)) + raise ArgError('invalid type:' + str(typ)) return val except ArgError: raise @@ -142,7 +142,9 @@ Used on the client. """ - def __init__(self, fn, paramspec, keyspec={}): + def __init__(self, fn, paramspec, keyspec = None): + if keyspec == None: + keyspec = {} Args.__init__(self, paramspec, keyspec) self.fn = fn @@ -154,7 +156,9 @@ Used in the HTTP server. """ - def __init__(self, fn, paramspec, keyspec={}): + def __init__(self, fn, paramspec, keyspec = None): + if keyspec == None: + keyspec = {} Args.__init__(self, paramspec, keyspec) self.fn = fn diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/EventServer.py --- a/tools/python/xen/xend/EventServer.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/EventServer.py Mon Sep 19 10:51:05 2005 @@ -145,7 +145,7 @@ self.lock.release() if async: - scheduler.now(self.call_handlers, [event, val]) + scheduler.now(self.call_handlers, event, val) else: self.call_handlers(event, val) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/Vifctl.py --- a/tools/python/xen/xend/Vifctl.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/Vifctl.py Mon Sep 19 10:51:05 2005 @@ -13,13 +13,13 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ """Xend interface to networking control scripts. """ import os import os.path -import sys import xen.util.process from xen.xend import XendRoot @@ -71,7 +71,7 @@ vif = vif_old return vif -def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, ipaddr=[]): +def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, ipaddr=None): """Call a vif control script. Xend calls this when bringing vifs up or down. diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/XendCheckpoint.py Mon Sep 19 10:51:05 2005 @@ -83,7 +83,7 @@ if child.wait() != 0: raise XendError("xc_save failed: %s" % lasterr) - dominfo.setStoreChannel(None) + dominfo.closeStoreChannel() xd.domain_destroy(dominfo.domid) return None diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/XendDomain.py Mon Sep 19 10:51:05 2005 @@ -55,7 +55,7 @@ class XendDomainDict(dict): def get_by_name(self, name): try: - return filter(lambda d: d.name == name, self.values())[0] + return filter(lambda d: d.getName() == name, self.values())[0] except IndexError, err: return None @@ -94,7 +94,7 @@ @return: domain objects """ doms = self.list() - doms.sort(lambda x, y: cmp(x.name, y.name)) + doms.sort(lambda x, y: cmp(x.getName(), y.getName())) return doms def list_names(self): @@ -103,7 +103,7 @@ @return: domain names """ doms = self.list_sorted() - return map(lambda x: x.name, doms) + return map(lambda x: x.getName(), doms) def onReleaseDomain(self): self.reap() @@ -183,12 +183,13 @@ @param info: domain info object @param notify: send a domain created event if true """ - if info.domid in self.domains: + if info.getDomain() in self.domains: notify = False - self.domains[info.domid] = info + self.domains[info.getDomain()] = info info.exportToDB(save=True) if notify: - eserver.inject('xend.domain.create', [info.name, info.domid]) + eserver.inject('xend.domain.create', [info.getName(), + info.getDomain()]) def _delete_domain(self, id, notify=True): """Remove a domain from the tables. @@ -202,7 +203,8 @@ info.cleanup() info.delete() if notify: - eserver.inject('xend.domain.died', [info.name, info.domid]) + eserver.inject('xend.domain.died', [info.getName(), + info.getDomain()]) # XXX this should not be needed for domdb in self.dbmap.values(): if not domdb.has_key("xend"): @@ -227,13 +229,13 @@ dominfo = self.domains.get(domid) if not dominfo or dominfo.is_terminated(): continue - log.debug('domain died name=%s domid=%d', dominfo.name, domid) + log.debug('domain died name=%s domid=%d', dominfo.getName(), domid) if d['crashed'] and xroot.get_enable_dump(): self.domain_dumpcore(domid) if d['shutdown']: reason = shutdown_reason(d['shutdown_reason']) - log.debug('shutdown name=%s id=%d reason=%s', dominfo.name, - domid, reason) + log.debug('shutdown name=%s id=%d reason=%s', + dominfo.getName(), domid, reason) if reason == 'suspend': dominfo.state_set("suspended") continue @@ -248,11 +250,11 @@ # Remove entries for domains that no longer exist. # Update entries for existing domains. for d in self.domains.values(): - info = doms.get(d.domid) + info = doms.get(d.getDomain()) if info: d.update(info) elif not d.restart_pending(): - self._delete_domain(d.domid) + self._delete_domain(d.getDomain()) def update_domain(self, id): """Update information for a single domain. @@ -281,20 +283,23 @@ @param dominfo: domain object """ - log.info("Restarting domain: name=%s id=%s", dominfo.name, dominfo.domid) + log.info("Restarting domain: name=%s id=%s", dominfo.getName(), + dominfo.getDomain()) eserver.inject("xend.domain.restart", - [dominfo.name, dominfo.domid, "begin"]) + [dominfo.getName(), dominfo.getDomain(), "begin"]) try: dominfo.restart() - log.info('Restarted domain name=%s id=%s', dominfo.name, dominfo.domid) + log.info('Restarted domain name=%s id=%s', dominfo.getName(), + dominfo.getDomain()) eserver.inject("xend.domain.restart", - [dominfo.name, dominfo.domid, "success"]) - self.domain_unpause(dominfo.domid) + [dominfo.getName(), dominfo.getDomain(), + "success"]) + self.domain_unpause(dominfo.getDomain()) except Exception, ex: log.exception("Exception restarting domain: name=%s id=%s", - dominfo.name, dominfo.domid) + dominfo.getName(), dominfo.getDomain()) eserver.inject("xend.domain.restart", - [dominfo.name, dominfo.domid, "fail"]) + [dominfo.getName(), dominfo.getDomain(), "fail"]) return dominfo def domain_configure(self, vmconfig): @@ -376,9 +381,10 @@ @param id: domain id """ dominfo = self.domain_lookup(id) - eserver.inject('xend.domain.unpause', [dominfo.name, dominfo.domid]) - try: - return xc.domain_unpause(dom=dominfo.domid) + eserver.inject('xend.domain.unpause', [dominfo.getName(), + dominfo.getDomain()]) + try: + return xc.domain_unpause(dom=dominfo.getDomain()) except Exception, ex: raise XendError(str(ex)) @@ -388,9 +394,10 @@ @param id: domain id """ dominfo = self.domain_lookup(id) - eserver.inject('xend.domain.pause', [dominfo.name, dominfo.domid]) - try: - return xc.domain_pause(dom=dominfo.domid) + eserver.inject('xend.domain.pause', [dominfo.getName(), + dominfo.getDomain()]) + try: + return xc.domain_pause(dom=dominfo.getDomain()) except Exception, ex: raise XendError(str(ex)) @@ -406,8 +413,9 @@ @param reason: shutdown type: poweroff, reboot, suspend, halt """ dominfo = self.domain_lookup(id) - self.domain_restart_schedule(dominfo.domid, reason, force=True) - eserver.inject('xend.domain.shutdown', [dominfo.name, dominfo.domid, reason]) + self.domain_restart_schedule(dominfo.getDomain(), reason, force=True) + eserver.inject('xend.domain.shutdown', [dominfo.getName(), + dominfo.getDomain(), reason]) if reason == 'halt': reason = 'poweroff' val = dominfo.shutdown(reason) @@ -431,13 +439,13 @@ if not dominfo.shutdown_pending: # domain doesn't need shutdown continue - id = dominfo.domid + id = dominfo.getDomain() left = dominfo.shutdown_time_left(SHUTDOWN_TIMEOUT) if left <= 0: # Shutdown expired - destroy domain. try: log.info("Domain shutdown timeout expired: name=%s id=%s", - dominfo.name, id) + dominfo.getName(), id) self.domain_destroy(id, reason= dominfo.shutdown_pending['reason']) except Exception: @@ -462,15 +470,16 @@ restart = (force and reason == 'reboot') or dominfo.restart_needed(reason) if restart: log.info('Scheduling restart for domain: name=%s id=%s', - dominfo.name, dominfo.domid) + dominfo.getName(), dominfo.getDomain()) eserver.inject("xend.domain.restart", - [dominfo.name, dominfo.domid, "schedule"]) + [dominfo.getName(), dominfo.getDomain(), + "schedule"]) dominfo.restarting() else: log.info('Cancelling restart for domain: name=%s id=%s', - dominfo.name, dominfo.domid) + dominfo.getName(), dominfo.getDomain()) eserver.inject("xend.domain.restart", - [dominfo.name, dominfo.domid, "cancel"]) + [dominfo.getName(), dominfo.getDomain(), "cancel"]) dominfo.restart_cancel() def domain_restarts(self): @@ -480,12 +489,12 @@ for dominfo in self.domains.values(): if not dominfo.restart_pending(): continue - info = doms.get(dominfo.domid) + info = doms.get(dominfo.getDomain()) if info: # Don't execute restart for domains still running. continue # Remove it from the restarts. - log.info('restarting: %s' % dominfo.name) + log.info('restarting: %s' % dominfo.getName()) self.domain_restart(dominfo) def domain_destroy(self, domid, reason='halt'): @@ -520,13 +529,14 @@ # temporarily rename domain for localhost migration if dst == "localhost": - dominfo.name = "tmp-" + dominfo.name + dominfo.setName("tmp-" + dominfo.getName()) try: XendCheckpoint.save(self, sock.fileno(), dominfo, live) except: if dst == "localhost": - dominfo.name = string.replace(dominfo.name, "tmp-", "", 1) + dominfo.setName( + string.replace(dominfo.getName(), "tmp-", "", 1)) raise return None @@ -560,7 +570,7 @@ """ dominfo = self.domain_lookup(id) try: - return xc.domain_pincpu(dominfo.domid, vcpu, cpumap) + return xc.domain_pincpu(dominfo.getDomain(), vcpu, cpumap) except Exception, ex: raise XendError(str(ex)) @@ -569,8 +579,10 @@ """ dominfo = self.domain_lookup(id) try: - return xc.bvtsched_domain_set(dom=dominfo.domid, mcuadv=mcuadv, - warpback=warpback, warpvalue=warpvalue, + return xc.bvtsched_domain_set(dom=dominfo.getDomain(), + mcuadv=mcuadv, + warpback=warpback, + warpvalue=warpvalue, warpl=warpl, warpu=warpu) except Exception, ex: raise XendError(str(ex)) @@ -580,7 +592,7 @@ """ dominfo = self.domain_lookup(id) try: - return xc.bvtsched_domain_get(dominfo.domid) + return xc.bvtsched_domain_get(dominfo.getDomain()) except Exception, ex: raise XendError(str(ex)) @@ -590,7 +602,8 @@ """ dominfo = self.domain_lookup(id) try: - return xc.sedf_domain_set(dominfo.domid, period, slice, latency, extratime, weight) + return xc.sedf_domain_set(dominfo.getDomain(), period, slice, + latency, extratime, weight) except Exception, ex: raise XendError(str(ex)) @@ -599,7 +612,7 @@ """ dominfo = self.domain_lookup(id) try: - return xc.sedf_domain_get(dominfo.domid) + return xc.sedf_domain_get(dominfo.getDomain()) except Exception, ex: raise XendError(str(ex)) @@ -647,9 +660,8 @@ @param type: device type """ dominfo = self.domain_lookup(id) - val = dominfo.device_delete(type, devid) - dominfo.exportToDB() - return val + return dominfo.destroyDevice(type, devid) + def domain_devtype_ls(self, id, type): """Get list of device sxprs for a domain. @@ -689,7 +701,7 @@ """ dominfo = self.domain_lookup(id) try: - return xc.shadow_control(dominfo.domid, op) + return xc.shadow_control(dominfo.getDomain(), op) except Exception, ex: raise XendError(str(ex)) @@ -703,7 +715,8 @@ dominfo = self.domain_lookup(id) maxmem = int(mem) * 1024 try: - return xc.domain_setmaxmem(dominfo.domid, maxmem_kb = maxmem) + return xc.domain_setmaxmem(dominfo.getDomain(), + maxmem_kb = maxmem) except Exception, ex: raise XendError(str(ex)) @@ -735,12 +748,13 @@ @param id: domain """ dominfo = self.domain_lookup(id) - corefile = "/var/xen/dump/%s.%s.core"% (dominfo.name, dominfo.domid) - try: - xc.domain_dumpcore(dom=dominfo.domid, corefile=corefile) + corefile = "/var/xen/dump/%s.%s.core" % (dominfo.getName(), + dominfo.getDomain()) + try: + xc.domain_dumpcore(dom=dominfo.getDomain(), corefile=corefile) except Exception, ex: log.warning("Dumpcore failed, id=%s name=%s: %s", - dominfo.domid, dominfo.name, ex) + dominfo.getDomain(), dominfo.getName(), ex) def instance(): """Singleton constructor. Use this instead of the class constructor. diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Mon Sep 19 10:51:05 2005 @@ -1,4 +1,4 @@ -#============================================================================ +#=========================================================================== # This library is free software; you can redistribute it and/or # modify it under the terms of version 2.1 of the GNU Lesser General Public # License as published by the Free Software Foundation. @@ -23,23 +23,18 @@ """ -import string, re -import os +import string import time import threading import errno -import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() -from xen.util.ip import check_subnet, get_current_ipgw +import xen.lowlevel.xc from xen.util.blkif import blkdev_uname_to_file -from xen.xend.server import controller -from xen.xend.server import SrvDaemon; xend = SrvDaemon.instance() +from xen.xend.server import SrvDaemon from xen.xend.server.channel import EventChannel -from xen.util.blkif import blkdev_name_to_number, expand_dev_name from xen.xend import sxp -from xen.xend import Blkctl from xen.xend.PrettyPrint import prettyprintstring from xen.xend.XendBootloader import bootloader from xen.xend.XendLogging import log @@ -47,7 +42,7 @@ from xen.xend.XendRoot import get_component from xen.xend.uuid import getUuid -from xen.xend.xenstore import DBVar, XenNode, DBMap +from xen.xend.xenstore import DBVar from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xsutil import IntroduceDomain @@ -96,6 +91,12 @@ """Flag for a TPM device backend domain.""" SIF_TPM_BE_DOMAIN = (1<<7) + + +xc = xen.lowlevel.xc.new() + + +xend = SrvDaemon.instance() def domain_exists(name): @@ -248,11 +249,9 @@ self.store_mfn = None self.console_channel = None self.console_mfn = None - self.controllers = {} self.info = None self.backend_flags = 0 - self.netif_idx = 0 #todo: state: running, suspended self.state = STATE_VM_OK @@ -334,26 +333,50 @@ def getName(self): return self.name + def getPath(self): + return self.path + + def getUuid(self): + return self.uuid + + def getVCpuCount(self): + return self.vcpus + + def getSsidref(self): + return self.ssidref + + def getMemoryTarget(self): + """Get this domain's target memory size, in MiB.""" + return self.memory + def setStoreRef(self, ref): self.store_mfn = ref self.storeDom("store/ring-ref", ref) - def setStoreChannel(self, channel): - if self.store_channel and self.store_channel != channel: - self.store_channel.close() - self.store_channel = channel - if channel: - port = channel.port1 - else: - port = None - self.storeDom("store/port", None) + + def getBackendFlags(self): + return self.backend_flags + + + def closeStoreChannel(self): + """Close the store channel, if any. Nothrow guarantee.""" + + try: + if self.store_channel: + try: + self.store_channel.close() + self.removeDom("store/port") + finally: + self.store_channel = None + except Exception, exn: + log.exception(exn) + def setConsoleRef(self, ref): self.console_mfn = ref self.storeDom("console/ring-ref", ref) def setMemoryTarget(self, target): - self.memory_target = target self.storeDom("memory/target", target) def update(self, info=None): @@ -394,150 +417,26 @@ __repr__ = __str__ - def getDeviceController(self, type, error=True): - ctrl = self.controllers.get(type) - if not ctrl and error: - raise XendError("invalid device type:" + type) - return ctrl - - def findDeviceController(self, type): - return (self.getDeviceController(type, error=False) - or self.createDeviceController(type)) - - def createDeviceController(self, type): - ctrl = controller.createDevController(type, self, recreate=self.recreate) - self.controllers[type] = ctrl - return ctrl - - def createDevice(self, type, devconfig, change=False): - if self.recreate: - return - if type == 'vbd': - typedev = sxp.child_value(devconfig, 'dev') - if re.match('^ioemu:', typedev): - return; - - backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) - - devnum = blkdev_name_to_number(sxp.child_value(devconfig, 'dev')) - - backpath = "%s/backend/%s/%s/%d" % (backdom.path, type, - self.uuid, devnum) - frontpath = "%s/device/%s/%d" % (self.path, type, devnum) - - front = { 'backend' : backpath, - 'backend-id' : "%i" % backdom.domid, - 'virtual-device' : "%i" % devnum } - xstransact.Write(frontpath, front) - - (type, params) = string.split(sxp.child_value(devconfig, - 'uname'), ':', 1) - readonly = sxp.child_value(devconfig, 'mode', 'r') - back = { 'type' : type, - 'params' : params, - 'frontend' : frontpath, - 'frontend-id' : "%i" % self.domid } - if readonly == 'r': - back['read-only'] = "" # existence indicates read-only - xstransact.Write(backpath, back) - - return - - if type == 'vif': - from xen.xend import XendRoot - xroot = XendRoot.instance() - - def _get_config_ipaddr(config): - val = [] - for ipaddr in sxp.children(config, elt='ip'): - val.append(sxp.child0(ipaddr)) - return val - - backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) - - devnum = self.netif_idx - self.netif_idx += 1 - - script = sxp.child_value(devconfig, 'script', - xroot.get_vif_script()) - script = os.path.join(xroot.network_script_dir, script) - bridge = sxp.child_value(devconfig, 'bridge', - xroot.get_vif_bridge()) - mac = sxp.child_value(devconfig, 'mac') - ipaddr = _get_config_ipaddr(devconfig) - - backpath = "%s/backend/%s/%s/%d" % (backdom.path, type, - self.uuid, devnum) - frontpath = "%s/device/%s/%d" % (self.path, type, devnum) - - front = { 'backend' : backpath, - 'backend-id' : "%i" % backdom.domid, - 'handle' : "%i" % devnum, - 'mac' : mac } - xstransact.Write(frontpath, front) - - back = { 'script' : script, - 'domain' : self.name, - 'mac' : mac, - 'bridge' : bridge, - 'frontend' : frontpath, - 'frontend-id' : "%i" % self.domid, - 'handle' : "%i" % devnum } - if ipaddr: - back['ip'] = ' '.join(ipaddr) - xstransact.Write(backpath, back) - - return - - if type == 'vtpm': - backdom = domain_exists(sxp.child_value(devconfig, 'backend', '0')) - - devnum = int(sxp.child_value(devconfig, 'instance', '0')) - log.error("The domain has a TPM with instance %d." % devnum) - - backpath = "%s/backend/%s/%s/%d" % (backdom.path, type, - self.uuid, devnum) - frontpath = "%s/device/%s/%d" % (self.path, type, devnum) - - front = { 'backend' : backpath, - 'backend-id' : "%i" % backdom.domid, - 'handle' : "%i" % devnum } - xstransact.Write(frontpath, front) - - back = { 'instance' : "%i" % devnum, - 'frontend' : frontpath, - 'frontend-id' : "%i" % self.domid } - xstransact.Write(backpath, back) - - return - - ctrl = self.findDeviceController(type) - return ctrl.createDevice(devconfig, recreate=self.recreate, - change=change) - - def configureDevice(self, type, id, devconfig): - ctrl = self.getDeviceController(type) - return ctrl.configureDevice(id, devconfig) - - def destroyDevice(self, type, id, change=False, reboot=False): - ctrl = self.getDeviceController(type) - return ctrl.destroyDevice(id, change=change, reboot=reboot) - - def deleteDevice(self, type, id): - ctrl = self.getDeviceController(type) - return ctrl.deleteDevice(id) - - def getDevice(self, type, id, error=True): - ctrl = self.getDeviceController(type) - return ctrl.getDevice(id, error=error) - - def getDeviceIds(self, type): - ctrl = self.getDeviceController(type) - return ctrl.getDeviceIds() - - def getDeviceSxprs(self, type): - ctrl = self.getDeviceController(type) - return ctrl.getDeviceSxprs() + + def getDeviceController(self, name): + if name not in controllerClasses: + raise XendError("unknown device type: " + str(name)) + + return controllerClasses[name](self) + + + def createDevice(self, deviceClass, devconfig): + return self.getDeviceController(deviceClass).createDevice(devconfig) + + + def configureDevice(self, deviceClass, devid, devconfig): + return self.getDeviceController(deviceClass).configureDevice( + devid, devconfig) + + + def destroyDevice(self, deviceClass, devid): + return self.getDeviceController(deviceClass).destroyDevice(devid) + def sxpr(self): sxpr = ['domain', @@ -593,23 +492,8 @@ sxpr.append(['restart_state', self.restart_state]) if self.restart_time: sxpr.append(['restart_time', str(self.restart_time)]) - - devs = self.sxpr_devices() - if devs: - sxpr.append(devs) if self.config: sxpr.append(['config', self.config]) - return sxpr - - def sxpr_devices(self): - sxpr = [] - for ty in self.controllers.keys(): - devs = self.getDeviceSxprs(ty) - sxpr += devs - if sxpr: - sxpr.insert(0, 'devices') - else: - sxpr = None return sxpr def check_name(self, name): @@ -753,8 +637,7 @@ """ self.state = STATE_VM_TERMINATED self.release_devices() - if self.store_channel: - self.setStoreChannel(None) + self.closeStoreChannel() if self.console_channel: # notify processes using this console? try: @@ -785,18 +668,20 @@ def release_devices(self): """Release all vm devices. """ - reboot = self.restart_pending() - for ctrl in self.controllers.values(): - if ctrl.isDestroyed(): continue - ctrl.destroyController(reboot=reboot) + t = xstransact("%s/device" % self.path) - for d in t.list("vbd"): - t.remove(d) - for d in t.list("vif"): - t.remove(d) - for d in t.list("vtpm"): - t.remove(d) + for n in controllerClasses.keys(): + for d in t.list(n): + try: + t.remove(d) + except ex: + # Log and swallow any exceptions in removal -- there's + # nothing more we can do. + log.exception( + "Device release failed: %s; %s; %s; %s" % + (self.info['name'], n, d, str(ex))) t.commit() + def show(self): """Print virtual machine info. @@ -853,9 +738,6 @@ raise VmError('invalid device') dev_type = sxp.name(dev_config) - if not controller.isDevControllerClass(dev_type): - raise VmError('unknown device type: ' + dev_type) - self.createDevice(dev_type, dev_config) @@ -864,10 +746,7 @@ @raise: VmError for invalid devices """ - if self.rebooting(): - for ctrl in self.controllers.values(): - ctrl.initController(reboot=True) - else: + if not self.rebooting(): self.create_configured_devices() self.image.createDeviceModel() @@ -877,47 +756,19 @@ @param dev_config: device configuration """ dev_type = sxp.name(dev_config) - dev = self.createDevice(dev_type, dev_config, change=True) - self.config.append(['device', dev.getConfig()]) - return dev.sxpr() - - def device_configure(self, dev_config, id): + devid = self.createDevice(dev_type, dev_config) +# self.config.append(['device', dev.getConfig()]) + return self.getDeviceController(dev_type).sxpr(devid) + + + def device_configure(self, dev_config, devid): """Configure an existing device. - @param dev_config: device configuration - @param id: device id - """ - type = sxp.name(dev_config) - dev = self.getDevice(type, id) - old_config = dev.getConfig() - new_config = dev.configure(dev_config, change=True) - # Patch new config into vm config. - new_full_config = ['device', new_config] - old_full_config = ['device', old_config] - old_index = self.config.index(old_full_config) - self.config[old_index] = new_full_config - return new_config - - def device_refresh(self, type, id): - """Refresh a device. - - @param type: device type - @param id: device id - """ - dev = self.getDevice(type, id) - dev.refresh() - - def device_delete(self, type, id): - """Destroy and remove a device. - - @param type: device type - @param id: device id - """ - dev = self.getDevice(type, id) - dev_config = dev.getConfig() - if dev_config: - self.config.remove(['device', dev_config]) - self.deleteDevice(type, dev.getId()) + @param devid: device id + """ + deviceClass = sxp.name(dev_config) + self.configureDevice(deviceClass, devid, dev_config) + def configure_restart(self): """Configure the vm restart mode. @@ -1036,7 +887,7 @@ """Configure a vm. """ - self.configure_fields() + self.configure_maxmem() self.create_devices() self.create_blkif() @@ -1047,26 +898,15 @@ """ return - blkif = self.getDeviceController("vbd", error=False) - if not blkif: - blkif = self.createDeviceController("vbd") - backend = blkif.getBackend(0) - backend.connect(recreate=self.recreate) - - def configure_fields(self): - """Process the vm configuration fields using the registered handlers. - """ - index = {} - for field in sxp.children(self.config): - field_name = sxp.name(field) - field_index = index.get(field_name, 0) - field_handler = config_handlers.get(field_name) - # Ignore unknown fields. Warn? - if field_handler: - v = field_handler(self, self.config, field, field_index) - else: - log.warning("Unknown config field %s", field_name) - index[field_name] = field_index + 1 + + def configure_maxmem(self): + try: + maxmem = int(sxp.child_value(self.config, 'maxmem', self.memory)) + xc.domain_setmaxmem(self.domid, maxmem_kb = maxmem * 1024) + except: + raise VmError("invalid maxmem: " + + sxp.child_value(self.config, 'maxmem')) + def vcpu_hotplug(self, vcpu, state): """Disable or enable VCPU in domain. @@ -1138,26 +978,6 @@ self.vcpu_hotplug(vcpu, 0) -def vm_field_ignore(_, _1, _2, _3): - """Dummy config field handler used for fields with built-in handling. - Matches the signature required by config_handlers. - """ - pass - - -def vm_field_maxmem(vm, _1, val, _2): - """Config field handler to configure vm memory limit. Matches the - signature required by config_handlers. - """ - maxmem = sxp.child0(val) - if maxmem is None: - maxmem = vm.memory - try: - maxmem = int(maxmem) - except: - raise VmError("invalid maxmem: " + str(maxmem)) - xc.domain_setmaxmem(vm.domid, maxmem_kb = maxmem * 1024) - #============================================================================ # Register image handlers. @@ -1172,37 +992,24 @@ addImageHandlerClass(VmxImageHandler) -"""Table of handlers for field configuration. - -field_name[String]: fn(vm, config, field, index) -> value(ignored) -""" -config_handlers = { - - # Ignore the fields we already handle. - - 'name': vm_field_ignore, - 'memory': vm_field_ignore, - 'ssidref': vm_field_ignore, - 'cpu': vm_field_ignore, - 'cpu_weight': vm_field_ignore, - 'restart': vm_field_ignore, - 'image': vm_field_ignore, - 'device': vm_field_ignore, - 'backend': vm_field_ignore, - 'vcpus': vm_field_ignore, - 'bootloader': vm_field_ignore, - - # Register other config handlers. - 'maxmem': vm_field_maxmem - } - - #============================================================================ # Register device controllers and their device config types. +"""A map from device-class names to the subclass of DevController that +implements the device control specific to that device-class.""" +controllerClasses = {} + + +def addControllerClass(device_class, cls): + """Register a subclass of DevController to handle the named device-class. + """ + cls.deviceClass = device_class + controllerClasses[device_class] = cls + + from xen.xend.server import blkif, netif, tpmif, pciif, usbif -controller.addDevControllerClass("vbd", blkif.BlkifController) -controller.addDevControllerClass("vif", netif.NetifController) -controller.addDevControllerClass("vtpm", tpmif.TPMifController) -controller.addDevControllerClass("pci", pciif.PciController) -controller.addDevControllerClass("usb", usbif.UsbifController) +addControllerClass('vbd', blkif.BlkifController) +addControllerClass('vif', netif.NetifController) +addControllerClass('vtpm', tpmif.TPMifController) +addControllerClass('pci', pciif.PciController) +addControllerClass('usb', usbif.UsbifController) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/image.py Mon Sep 19 10:51:05 2005 @@ -18,7 +18,7 @@ import os, string import re -import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() +import xen.lowlevel.xc from xen.xend import sxp from xen.xend.XendError import VmError from xen.xend.XendLogging import log @@ -26,6 +26,10 @@ from xen.xend.xenstore.xstransact import xstransact from xen.xend.server import channel + + +xc = xen.lowlevel.xc.new() + MAX_GUEST_CMDLINE = 1024 @@ -155,7 +159,8 @@ self.unlink(self.kernel) self.unlink(self.ramdisk) if dom <= 0: - raise VmError('Creating domain failed: name=%s' % self.vm.name) + raise VmError('Creating domain failed: name=%s' % + self.vm.getName()) log.debug("initDomain: cpu=%d mem_kb=%d ssidref=%d dom=%d", cpu, mem_kb, ssidref, dom) xc.domain_setcpuweight(dom, cpu_weight) xc.domain_setmaxmem(dom, mem_kb) @@ -183,21 +188,22 @@ return # Set params and call buildDomain(). - self.flags = self.vm.backend_flags + self.flags = self.vm.getBackendFlags() if not os.path.isfile(self.kernel): raise VmError('Kernel image does not exist: %s' % self.kernel) if self.ramdisk and not os.path.isfile(self.ramdisk): raise VmError('Kernel ramdisk does not exist: %s' % self.ramdisk) if len(self.cmdline) >= MAX_GUEST_CMDLINE: - log.warning('kernel cmdline too long, domain %d', self.vm.domid) + log.warning('kernel cmdline too long, domain %d', + self.vm.getDomain()) log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype, - self.vm.domid, self.vm.vcpus) + self.vm.getDomain(), self.vm.getVCpuCount()) err = self.buildDomain() if err != 0: raise VmError('Building domain failed: ostype=%s dom=%d err=%d' - % (self.ostype, self.vm.domid, err)) + % (self.ostype, self.vm.getDomain(), err)) def getDomainMemory(self, mem_mb): """Memory (in KB) the domain will need for mem_mb (in MB).""" @@ -237,23 +243,23 @@ else: console_evtchn = 0 - log.debug("dom = %d", self.vm.domid) + log.debug("dom = %d", self.vm.getDomain()) log.debug("image = %s", self.kernel) log.debug("store_evtchn = %d", store_evtchn) log.debug("console_evtchn = %d", console_evtchn) log.debug("cmdline = %s", self.cmdline) log.debug("ramdisk = %s", self.ramdisk) log.debug("flags = %d", self.flags) - log.debug("vcpus = %d", self.vm.vcpus) - - ret = xc.linux_build(dom = self.vm.domid, + log.debug("vcpus = %d", self.vm.getVCpuCount()) + + ret = xc.linux_build(dom = self.vm.getDomain(), image = self.kernel, store_evtchn = store_evtchn, console_evtchn = console_evtchn, cmdline = self.cmdline, ramdisk = self.ramdisk, flags = self.flags, - vcpus = self.vm.vcpus) + vcpus = self.vm.getVCpuCount()) if isinstance(ret, dict): self.set_vminfo(ret) return 0 @@ -297,22 +303,22 @@ def buildDomain(self): # Create an event channel - self.device_channel = channel.eventChannel(0, self.vm.domid) + self.device_channel = channel.eventChannel(0, self.vm.getDomain()) log.info("VMX device model port: %d", self.device_channel.port2) if self.vm.store_channel: store_evtchn = self.vm.store_channel.port2 else: store_evtchn = 0 - ret = xc.vmx_build(dom = self.vm.domid, + ret = xc.vmx_build(dom = self.vm.getDomain(), image = self.kernel, control_evtchn = self.device_channel.port2, store_evtchn = store_evtchn, - memsize = self.vm.memory, + memsize = self.vm.getMemoryTarget(), memmap = self.memmap_value, cmdline = self.cmdline, ramdisk = self.ramdisk, flags = self.flags, - vcpus = self.vm.vcpus) + vcpus = self.vm.getVCpuCount()) if isinstance(ret, dict): self.set_vminfo(ret) return 0 @@ -391,7 +397,7 @@ elif vnc: ret = ret + ['-vnc', '-k', 'en-us'] if vnc: - vncport = int(self.vm.domid) + 5900 + vncport = int(self.vm.getDomain()) + 5900 ret = ret + ['-vncport', '%d' % vncport] return ret @@ -405,9 +411,9 @@ vnc = self.vncParams() if len(vnc): args = args + vnc - args = args + ([ "-d", "%d" % self.vm.domid, + args = args + ([ "-d", "%d" % self.vm.getDomain(), "-p", "%d" % self.device_channel.port1, - "-m", "%s" % self.vm.memory ]) + "-m", "%s" % self.vm.getMemoryTarget() ]) args = args + self.dmargs env = dict(os.environ) env['DISPLAY'] = self.display diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/scheduler.py --- a/tools/python/xen/xend/scheduler.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/scheduler.py Mon Sep 19 10:51:05 2005 @@ -13,11 +13,12 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ import threading -def later(delay, fn, args=(), kwargs={}): +def later(delay, fn, *args, **kwargs): """Schedule a function to be called later. @param delay: delay in seconds @@ -29,7 +30,7 @@ timer.start() return timer -def now(fn, args=(), kwargs={}): +def now(fn, *args, **kwargs): """Schedule a function to be called now. @param fn: function diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/SrvDomainDir.py --- a/tools/python/xen/xend/server/SrvDomainDir.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Mon Sep 19 10:51:05 2005 @@ -85,7 +85,7 @@ def _op_create_cb(self, dominfo, configstring, req): """Callback to handle domain creation. """ - dom = dominfo.name + dom = dominfo.getName() domurl = "%s/%s" % (req.prePathURL(), dom) req.setResponseCode(http.CREATED, "created") req.setHeader("Location", domurl) @@ -112,7 +112,7 @@ fn = FormFn(self.xd.domain_restore, [['file', 'str']]) dominfo = fn(req.args) - dom = dominfo.name + dom = dominfo.getName() domurl = "%s/%s" % (req.prePathURL(), dom) req.setResponseCode(http.CREATED) req.setHeader("Location", domurl) @@ -152,12 +152,12 @@ domains = self.xd.list_sorted() req.write('<ul>') for d in domains: - req.write('<li><a href="%s%s"> Domain %s</a>' - % (url, d.name, d.name)) - req.write('id=%s' % d.domid) - req.write('memory=%d'% d.memory) - req.write('ssidref=%d'% d.ssidref) - req.write('</li>') + req.write('<li><a href="%s%s"> Domain %s</a>' + % (url, d.getName(), d.getName())) + req.write('id=%s' % d.getDomain()) + req.write('memory=%d'% d.getMemoryTarget()) + req.write('ssidref=%d'% d.getSsidref()) + req.write('</li>') req.write('</ul>') def form(self, req): diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/SrvNode.py --- a/tools/python/xen/xend/server/SrvNode.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/SrvNode.py Mon Sep 19 10:51:05 2005 @@ -15,7 +15,6 @@ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> #============================================================================ -import os from xen.web.SrvDir import SrvDir from xen.xend import sxp @@ -32,15 +31,15 @@ self.add('dmesg', 'SrvDmesg') self.add('log', 'SrvXendLog') - def op_shutdown(self, op, req): + def op_shutdown(self, _1, _2): val = self.xn.shutdown() return val - def op_reboot(self, op, req): + def op_reboot(self, _1, _2): val = self.xn.reboot() return val - def op_cpu_bvt_slice_set(self, op, req): + def op_cpu_bvt_slice_set(self, _, req): fn = FormFn(self.xn.cpu_bvt_slice_set, [['ctx_allow', 'int']]) val = fn(req.args, {}) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/SrvServer.py Mon Sep 19 10:51:05 2005 @@ -44,13 +44,17 @@ from xen.web.httpserver import HttpServer, UnixHttpServer -from xen.xend import XendRoot; xroot = XendRoot.instance() +from xen.xend import XendRoot from xen.xend import Vifctl from xen.xend.XendLogging import log from xen.web.SrvDir import SrvDir import time from SrvRoot import SrvRoot + + +xroot = XendRoot.instance() + class XendServers: diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/blkif.py --- a/tools/python/xen/xend/server/blkif.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/blkif.py Mon Sep 19 10:51:05 2005 @@ -13,322 +13,47 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ -"""Support for virtual block devices. -""" + +import re import string from xen.util import blkif -from xen.xend.XendError import XendError, VmError -from xen.xend.XendRoot import get_component -from xen.xend.XendLogging import log from xen.xend import sxp -from xen.xend import Blkctl -from xen.xend.xenstore import DBVar -from xen.xend.server.controller import Dev, DevController +from xen.xend.server.DevController import DevController -class BlkifBackend: - """ Handler for the 'back-end' channel to a block device driver domain - on behalf of a front-end domain. - Must be connected using connect() before it can be used. - """ - def __init__(self, controller, id, dom, recreate=False): - self.controller = controller - self.id = id - self.frontendDomain = self.controller.getDomain() - self.backendDomain = dom - self.destroyed = False - self.connected = False - self.status = None - - def init(self, recreate=False, reboot=False): - self.destroyed = False - self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED - self.frontendDomain = self.controller.getDomain() - - def __str__(self): - return ('<BlkifBackend frontend=%d backend=%d id=%d>' - % (self.frontendDomain, - self.backendDomain, - self.id)) - - def getId(self): - return self.id - - def connect(self, recreate=False): - """Connect to the blkif control interface. - - @param recreate: true if after xend restart - """ - log.debug("Connecting blkif %s", str(self)) - if recreate or self.connected: - self.connected = True - pass - - def destroy(self, change=False, reboot=False): - """Disconnect from the blkif control interface and destroy it. - """ - self.destroyed = True - # For change true need to notify front-end, or back-end will do it? - - def connectInterface(self, val): - self.status = BLKIF_INTERFACE_STATUS_CONNECTED - - def interfaceDisconnected(self): - self.status = BLKIF_INTERFACE_STATUS_DISCONNECTED - -class BlkDev(Dev): - """Info record for a block device. - """ - - __exports__ = Dev.__exports__ + [ - DBVar('dev', ty='str'), - DBVar('vdev', ty='int'), - DBVar('mode', ty='str'), - DBVar('viftype', ty='str'), - DBVar('params', ty='str'), - DBVar('node', ty='str'), - DBVar('device', ty='long'), - DBVar('dev_handle', ty='long'), - DBVar('start_sector', ty='long'), - DBVar('nr_sectors', ty='long'), - ] - - def __init__(self, controller, id, config, recreate=False): - Dev.__init__(self, controller, id, config, recreate=recreate) - self.dev = None - self.uname = None - self.vdev = None - self.mode = None - self.type = None - self.params = None - self.node = None - self.device = None - self.dev_handle = 0 - self.start_sector = None - self.nr_sectors = None - - self.frontendDomain = self.getDomain() - self.backendDomain = None - self.backendId = 0 - self.configure(self.config, recreate=recreate) - - def exportToDB(self, save=False): - Dev.exportToDB(self, save=save) - backend = self.getBackend() - - def init(self, recreate=False, reboot=False): - self.frontendDomain = self.getDomain() - backend = self.getBackend() - self.backendId = backend.domid - - def configure(self, config, change=False, recreate=False): - if change: - raise XendError("cannot reconfigure vbd") - self.config = config - self.uname = sxp.child_value(config, 'uname') - if not self.uname: - raise VmError('vbd: Missing uname') - # Split into type and type-specific params (which are passed to the - # type-specific control script). - (self.type, self.params) = string.split(self.uname, ':', 1) - self.dev = sxp.child_value(config, 'dev') - if not self.dev: - raise VmError('vbd: Missing dev') - self.mode = sxp.child_value(config, 'mode', 'r') - - self.vdev = blkif.blkdev_name_to_number(self.dev) - if not self.vdev: - raise VmError('vbd: Device not found: %s' % self.dev) - - try: - xd = get_component('xen.xend.XendDomain') - self.backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).domid - except: - raise XendError('invalid backend domain') - - return self.config - - def attach(self, recreate=False, change=False): - if recreate: - pass - else: - node = Blkctl.block('bind', self.type, self.params) - self.setNode(node) - self.attachBackend() - if change: - self.interfaceChanged() - - def unbind(self): - if self.node is None: return - log.debug("Unbinding vbd (type %s) from %s" - % (self.type, self.node)) - Blkctl.block('unbind', self.type, self.node) - - def setNode(self, node): - - # NOTE: - # This clause is testing code for storage system experiments. - # Add a new disk type that will just pass an opaque id in the - # dev_handle and use an experimental device type. - # Please contact andrew.warfield@xxxxxxxxxxxx with any concerns. - if self.type == 'parallax': - self.node = node - self.device = 61440 # (240,0) - self.dev_handle = long(self.params) - self.nr_sectors = long(0) - return - # done. - - mounted_mode = self.check_mounted(node) - if not '!' in self.mode and mounted_mode: - if mounted_mode == "w": - raise VmError("vbd: Segment %s is in writable use" % - self.uname) - elif 'w' in self.mode: - raise VmError("vbd: Segment %s is in read-only use" % - self.uname) - - segment = blkif.blkdev_segment(node) - if not segment: - raise VmError("vbd: Segment not found: uname=%s" % self.uname) - self.node = node - self.device = segment['device'] - self.start_sector = segment['start_sector'] - self.nr_sectors = segment['nr_sectors'] - - def check_mounted(self, name): - mode = blkif.mount_mode(name) - xd = get_component('xen.xend.XendDomain') - for vm in xd.list(): - ctrl = vm.getDeviceController(self.getType(), error=False) - if (not ctrl): continue - for dev in ctrl.getDevices(): - if dev is self: continue - if dev.type == 'phy' and name == blkif.expand_dev_name(dev.params): - mode = dev.mode - if 'w' in mode: - return 'w' - if mode and 'r' in mode: - return 'r' - return None - - def readonly(self): - return 'w' not in self.mode - - def sxpr(self): - val = ['vbd', - ['id', self.id], - ['vdev', self.vdev], - ['device', self.device], - ['mode', self.mode]] - if self.dev: - val.append(['dev', self.dev]) - if self.uname: - val.append(['uname', self.uname]) - if self.node: - val.append(['node', self.node]) - return val - - def getBackend(self): - return self.controller.getBackend(self.backendDomain) - - def refresh(self): - log.debug("Refreshing vbd domain=%d id=%s", self.frontendDomain, - self.id) - self.interfaceChanged() - - def destroy(self, change=False, reboot=False): - """Destroy the device. If 'change' is true notify the front-end interface. - - @param change: change flag - """ - self.destroyed = True - log.debug("Destroying vbd domain=%d id=%s", self.frontendDomain, - self.id) - if change: - self.interfaceChanged() - self.unbind() - - def interfaceChanged(self): - """Tell the back-end to notify the front-end that a device has been - added or removed. - """ - self.getBackend().interfaceChanged() - - def attachBackend(self): - """Attach the device to its controller. - - """ - self.getBackend().connect() - class BlkifController(DevController): """Block device interface controller. Handles all block devices for a domain. """ - def __init__(self, vm, recreate=False): + def __init__(self, vm): """Create a block device controller. """ - DevController.__init__(self, vm, recreate=recreate) - self.backends = {} - self.backendId = 0 + DevController.__init__(self, vm) - def initController(self, recreate=False, reboot=False): - self.destroyed = False - if reboot: - self.rebootBackends() - self.rebootDevices() - def sxpr(self): - val = ['blkif', ['dom', self.getDomain()]] - return val + def getDeviceDetails(self, config): + """@see DevController.getDeviceDetails""" + + typedev = sxp.child_value(config, 'dev') + if re.match('^ioemu:', typedev): + return - def rebootBackends(self): - for backend in self.backends.values(): - backend.init(reboot=True) + devid = blkif.blkdev_name_to_number(sxp.child_value(config, 'dev')) - def getBackendById(self, id): - return self.backends.get(id) + (typ, params) = string.split(sxp.child_value(config, 'uname'), ':', 1) + back = { 'type' : typ, + 'params' : params + } - def getBackendByDomain(self, dom): - for backend in self.backends.values(): - if backend.backendDomain == dom: - return backend - return None + if 'r' == sxp.child_value(config, 'mode', 'r'): + back['read-only'] = "" # existence indicates read-only - def getBackend(self, dom): - backend = self.getBackendByDomain(dom) - if backend: return backend - backend = BlkifBackend(self, self.backendId, dom) - self.backendId += 1 - self.backends[backend.getId()] = backend - backend.init() - return backend + front = { 'virtual-device' : "%i" % devid } - def newDevice(self, id, config, recreate=False): - """Create a device.. - - @param id: device id - @param config: device configuration - @param recreate: if true it's being recreated (after xend restart) - @type recreate: bool - @return: device - @rtype: BlkDev - """ - return BlkDev(self, id, config, recreate=recreate) - - def destroyController(self, reboot=False): - """Destroy the controller and all devices. - """ - self.destroyed = True - log.debug("Destroying blkif domain=%d", self.getDomain()) - self.destroyDevices(reboot=reboot) - self.destroyBackends(reboot=reboot) - - def destroyBackends(self, reboot=False): - for backend in self.backends.values(): - backend.destroy(reboot=reboot) + return (devid, back, front) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/channel.py --- a/tools/python/xen/xend/server/channel.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/channel.py Mon Sep 19 10:51:05 2005 @@ -43,33 +43,6 @@ interdomain = classmethod(interdomain) - def restoreFromDB(cls, db, dom1, dom2, port1=0, port2=0): - """Create an event channel using db info if available. - Inverse to saveToDB(). - - @param db db - @param dom1 - @param dom2 - @param port1 - @param port2 - """ - try: - dom1 = int(db['dom1'].getData()) - except: pass - try: - dom2 = int(db['dom2'].getData()) - except: pass - try: - port1 = int(db['port1'].getData()) - except: pass - try: - port2 = int(db['port2'].getData()) - except: pass - evtchn = cls.interdomain(dom1, dom2, port1=port1, port2=port2) - return evtchn - - restoreFromDB = classmethod(restoreFromDB) - def __init__(self, dom1, dom2, d): d['dom1'] = dom1 d['dom2'] = dom2 @@ -92,18 +65,6 @@ print 'EventChannel>close>', self evtchn_close(self.dom1, self.port1) evtchn_close(self.dom2, self.port2) - - def saveToDB(self, db, save=False): - """Save the event channel to the db so it can be restored later, - using restoreFromDB() on the class. - - @param db db - """ - db['dom1'] = str(self.dom1) - db['dom2'] = str(self.dom2) - db['port1'] = str(self.port1) - db['port2'] = str(self.port2) - db.saveDB(save=save) def sxpr(self): return ['event-channel', diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/netif.py --- a/tools/python/xen/xend/server/netif.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/netif.py Mon Sep 19 10:51:05 2005 @@ -13,396 +13,64 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ + """Support for virtual network interfaces. """ -import random - -from xen.util.mac import macFromString, macToString +import os from xen.xend import sxp -from xen.xend import Vifctl -from xen.xend.XendError import XendError, VmError -from xen.xend.XendLogging import log -from xen.xend import XendVnet -from xen.xend.XendRoot import get_component -from xen.xend.xenstore import DBVar -from xen.xend.server.controller import Dev, DevController +from xen.xend.server.DevController import DevController -class NetDev(Dev): - """A network device. - """ - # State: - # inherited + - # ./config - # ./mac - # ./be_mac - # ./bridge - # ./script - # ./ipaddr ? - # - # ./credit - # ./period - # - # ./vifctl: up/down? - # ./vifname - # - # - # Poss should have no backend state here - except for ref to backend's own tree - # for the device? And a status - the one we want. - # ./back/dom - # ./back/devid - id for back-end (netif_handle) - same as front/devid - # ./back/id - backend id (if more than one b/e per domain) - # ./back/status - # ./back/tx_shmem_frame - actually these belong in back-end state - # ./back/rx_shmem_frame - # - # ./front/dom - # ./front/devid - # ./front/status - need 2: one for requested, one for actual? Or drive from dev status - # and this is front status only. - # ./front/tx_shmem_frame - # ./front/rx_shmem_frame - # - # ./evtchn/front - here or in front/back? - # ./evtchn/back - # ./evtchn/status ? - # At present created by dev: but should be created unbound by front/back - # separately and then bound (by back)? +next_devid = 1 - __exports__ = Dev.__exports__ + [ - DBVar('config', ty='sxpr'), - DBVar('mac', ty='mac'), - DBVar('be_mac', ty='mac'), - DBVar('bridge', ty='str'), - DBVar('script', ty='str'), - DBVar('credit', ty='int'), - DBVar('period', ty='int'), - DBVar('vifname', ty='str'), - ] - def __init__(self, controller, id, config, recreate=False): - Dev.__init__(self, controller, id, config, recreate=recreate) - self.vif = int(self.id) - self.status = None - self.frontendDomain = self.getDomain() - self.backendDomain = None - self.credit = None - self.period = None - self.mac = None - self.be_mac = None - self.bridge = None - self.script = None - self.ipaddr = None - self.mtu = None - self.vifname = None - self.configure(self.config, recreate=recreate) - - def exportToDB(self, save=False): - Dev.exportToDB(self, save=save) - - def init(self, recreate=False, reboot=False): - self.destroyed = False - self.status = NETIF_INTERFACE_STATUS_DISCONNECTED - self.frontendDomain = self.getDomain() - - def _get_config_mac(self, config): - vmac = sxp.child_value(config, 'mac') - if not vmac: return None - try: - mac = macFromString(vmac) - except: - raise XendError("invalid mac: %s" % vmac) - return mac - - def _get_config_be_mac(self, config): - vmac = sxp.child_value(config, 'be_mac') - if not vmac: return None - try: - mac = macFromString(vmac) - except: - raise XendError("invalid backend mac: %s" % vmac) - return mac - - def _get_config_ipaddr(self, config): - ips = sxp.children(config, elt='ip') - if ips: - val = [] - for ipaddr in ips: - val.append(sxp.child0(ipaddr)) - else: - val = None - return val - - def _get_config_mtu(self, config): - mtu = sxp.child_value(config, 'mtu') - if not mtu: return None - try: - mtu = int(mtu) - except: - raise XendError("invalid mtu: %s" & mtu) - return mtu - - def configure(self, config, change=False, recreate=False): - if change: - return self.reconfigure(config) - self.config = config - self.mac = None - self.be_mac = None - self.bridge = None - self.script = None - self.ipaddr = [] - self.vifname = None - - self.vifname = sxp.child_value(config, 'vifname') - if self.vifname is None: - self.vifname = self.default_vifname() - if len(self.vifname) > 15: - raise XendError('invalid vifname: too long: ' + self.vifname) - mac = self._get_config_mac(config) - if mac is None: - raise XendError("invalid mac") - self.mac = mac - self.be_mac = self._get_config_be_mac(config) - self.bridge = sxp.child_value(config, 'bridge') - self.script = sxp.child_value(config, 'script') - self.ipaddr = self._get_config_ipaddr(config) or [] - self.mtu = self._get_config_mtu(config) - self._config_credit_limit(config) - - try: - if recreate: - self.backendDomain = int(sxp.child_value(config, 'backend', '0')) - else: - #todo: Code below will fail on xend restart when backend is not domain 0. - xd = get_component('xen.xend.XendDomain') - self.backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).domid - except: - raise XendError('invalid backend domain') - return self.config - - def reconfigure(self, config): - """Reconfigure the interface with new values. - Not all configuration parameters can be changed: - bridge, script and ip addresses can, - backend and mac cannot. - - To leave a parameter unchanged, omit it from the changes. - - @param config configuration changes - @return updated interface configuration - @raise XendError on errors - """ - changes = {} - mac = self._get_config_mac(config) - be_mac = self._get_config_be_mac(config) - bridge = sxp.child_value(config, 'bridge') - script = sxp.child_value(config, 'script') - ipaddr = self._get_config_ipaddr(config) - mtu = self._get_config_mtu(config) - - xd = get_component('xen.xend.XendDomain') - backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).domid - - if (mac is not None) and (mac != self.mac): - raise XendError("cannot change mac") - if (be_mac is not None) and (be_mac != self.be_mac): - raise XendError("cannot change backend mac") - if (backendDomain is not None) and (backendDomain != self.backendDomain): - raise XendError("cannot change backend") - if (bridge is not None) and (bridge != self.bridge): - changes['bridge'] = bridge - if (script is not None) and (script != self.script): - changes['script'] = script - if (ipaddr is not None) and (ipaddr != self.ipaddr): - changes['ipaddr'] = ipaddr - if (mtu is not None) and (mtu != self.mtu): - changes['mtu'] = mtu - - if changes: - self.vifctl("down") - for (k, v) in changes.items(): - setattr(self, k, v) - self.config = sxp.merge(config, self.config) - self.vifctl("up") - - self._config_credit_limit(config, change=True) - return self.config - - def _config_credit_limit(self, config, change=False): - period = sxp.child_value(config, 'period') - credit = sxp.child_value(config, 'credit') - if period and credit: - try: - period = int(period) - credit = int(credit) - except ex: - raise XendError('vif: invalid credit limit') - if change: - self.setCreditLimit(credit, period) - self.config = sxp.merge([sxp.name(self.config), - ['credit', credit], - ['period', period]], - self.config) - else: - self.period = period - self.credit = credit - elif period or credit: - raise XendError('vif: invalid credit limit') - - def sxpr(self): - vif = str(self.vif) - mac = self.get_mac() - val = ['vif', - ['id', self.id], - ['vif', vif], - ['mac', mac], - ['vifname', self.vifname], - ] - - if self.be_mac: - val.append(['be_mac', self.get_be_mac()]) - if self.bridge: - val.append(['bridge', self.bridge]) - if self.script: - val.append(['script', self.script]) - for ip in self.ipaddr: - val.append(['ip', ip]) - if self.credit: - val.append(['credit', self.credit]) - if self.period: - val.append(['period', self.period]) - return val - - def get_vifname(self): - """Get the virtual interface device name. - """ - return self.vifname - - def default_vifname(self): - return "vif%d.%d" % (self.frontendDomain, self.vif) - - def get_mac(self): - """Get the MAC address as a string. - """ - return macToString(self.mac) - - def get_be_mac(self): - """Get the backend MAC address as a string. - """ - return macToString(self.be_mac) - - def vifctl_params(self, vmname=None): - """Get the parameters to pass to vifctl. - """ - dom = self.frontendDomain - if vmname is None: - xd = get_component('xen.xend.XendDomain') - try: - vm = xd.domain_lookup(dom) - vmname = vm.name - except: - vmname = 'Domain-%d' % dom - return { 'domain': vmname, - 'vif' : self.get_vifname(), - 'mac' : self.get_mac(), - 'bridge': self.bridge, - 'script': self.script, - 'ipaddr': self.ipaddr, } - - def vifctl(self, op, vmname=None): - """Bring the device up or down. - The vmname is needed when bringing a device up for a new domain because - the domain is not yet in the table so we can't look its name up. - - @param op: operation name (up, down) - @param vmname: vmname - """ - if op == 'up': - Vifctl.set_vif_name(self.default_vifname(), self.vifname) - Vifctl.vifctl(op, **self.vifctl_params(vmname=vmname)) - vnet = XendVnet.instance().vnet_of_bridge(self.bridge) - if vnet: - vnet.vifctl(op, self.get_vifname(), self.get_mac()) - - def attach(self, recreate=False, change=False): - if recreate: - pass - else: - if self.credit and self.period: - #self.send_be_creditlimit(self.credit, self.period) - pass - self.vifctl('up', vmname=self.getDomainName()) - - def destroy(self, change=False, reboot=False): - """Destroy the device's resources and disconnect from the back-end - device controller. If 'change' is true notify the front-end interface. - - @param change: change flag - """ - self.destroyed = True - self.status = NETIF_INTERFACE_STATUS_CLOSED - log.debug("Destroying vif domain=%d vif=%d", self.frontendDomain, self.vif) - self.vifctl('down') - if change: - self.reportStatus() - - def setCreditLimit(self, credit, period): - #todo: these params should be in sxpr and vif config. - self.credit = credit - self.period = period - - def getCredit(self): - return self.credit - - def getPeriod(self): - return self.period - - def interfaceChanged(self): - """Notify the front-end that a device has been added or removed. - """ - pass - class NetifController(DevController): """Network interface controller. Handles all network devices for a domain. """ - def __init__(self, vm, recreate=False): - DevController.__init__(self, vm, recreate=recreate) + def __init__(self, vm): + DevController.__init__(self, vm) - def initController(self, recreate=False, reboot=False): - self.destroyed = False - if reboot: - self.rebootDevices() - def destroyController(self, reboot=False): - """Destroy the controller and all devices. - """ - self.destroyed = True - log.debug("Destroying netif domain=%d", self.getDomain()) - self.destroyDevices(reboot=reboot) + def getDeviceDetails(self, config): + """@see DevController.getDeviceDetails""" - def sxpr(self): - val = ['netif', ['dom', self.getDomain()]] - return val - - def newDevice(self, id, config, recreate=False): - """Create a network device. + global next_devid - @param id: interface id - @param config: device configuration - @param recreate: recreate flag (true after xend restart) - """ - return NetDev(self, id, config, recreate=recreate) + from xen.xend import XendRoot + xroot = XendRoot.instance() - def limitDevice(self, vif, credit, period): - if vif not in self.devices: - raise XendError('device does not exist for credit limit: vif' - + str(self.getDomain()) + '.' + str(vif)) - - dev = self.devices[vif] - return dev.setCreditLimit(credit, period) + def _get_config_ipaddr(config): + val = [] + for ipaddr in sxp.children(config, elt='ip'): + val.append(sxp.child0(ipaddr)) + return val + + devid = next_devid + next_devid += 1 + + script = os.path.join(xroot.network_script_dir, + sxp.child_value(config, 'script', + xroot.get_vif_script())) + bridge = sxp.child_value(config, 'bridge', + xroot.get_vif_bridge()) + mac = sxp.child_value(config, 'mac') + ipaddr = _get_config_ipaddr(config) + + back = { 'script' : script, + 'mac' : mac, + 'bridge' : bridge, + 'handle' : "%i" % devid } + if ipaddr: + back['ip'] = ' '.join(ipaddr) + + front = { 'handle' : "%i" % devid, + 'mac' : mac } + + return (devid, back, front) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/pciif.py Mon Sep 19 10:51:05 2005 @@ -13,16 +13,22 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ + import types -import xen.lowlevel.xc; xc = xen.lowlevel.xc.new() +import xen.lowlevel.xc; from xen.xend import sxp from xen.xend.XendError import VmError -from controller import Dev, DevController +from xen.xend.server.DevController import DevController + + +xc = xen.lowlevel.xc.new() + def parse_pci(val): """Parse a pci field. @@ -36,27 +42,32 @@ v = val return v -class PciDev(Dev): - def __init__(self, controller, id, config, recreate=False): - Dev.__init__(self, controller, id, config, recreate=recreate) - bus = sxp.child_value(self.config, 'bus') - if not bus: - raise VmError('pci: Missing bus') - dev = sxp.child_value(self.config, 'dev') - if not dev: - raise VmError('pci: Missing dev') - func = sxp.child_value(self.config, 'func') - if not func: - raise VmError('pci: Missing func') - try: - bus = parse_pci(bus) - dev = parse_pci(dev) - func = parse_pci(func) - except: - raise VmError('pci: invalid parameter') +class PciController(DevController): - def attach(self, recreate=False, change=False): + def __init__(self, vm): + DevController.__init__(self, vm) + + + def getDeviceDetails(self, config): + """@see DevController.getDeviceDetails""" + + def get_param(field): + try: + val = sxp.child_value(config, field) + + if not val: + raise VmError('pci: Missing %s config setting' % field) + + return parse_pci(val) + except: + raise VmError('pci: Invalid config setting %s: %s' % + (field, val)) + + bus = get_param('bus') + dev = get_param('dev') + func = get_param('func') + rc = xc.physdev_pci_access_modify(dom = self.getDomain(), bus = bus, dev = dev, @@ -64,13 +75,8 @@ enable = True) if rc < 0: #todo non-fatal - raise VmError('pci: Failed to configure device: bus=%s dev=%s func=%s' % - (bus, dev, func)) + raise VmError( + 'pci: Failed to configure device: bus=%s dev=%s func=%s' % + (bus, dev, func)) - def destroy(self, change=False, reboot=False): - pass - -class PciController(DevController): - - def newDevice(self, id, config, recreate=False): - return PciDev(self, id, config, recreate=recreate) + return (dev, {}, {}) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/tpmif.py --- a/tools/python/xen/xend/server/tpmif.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/tpmif.py Mon Sep 19 10:51:05 2005 @@ -1,45 +1,47 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx> # Copyright (C) 2005 IBM Corporation -# Authort: Stefan Berger, stefanb@xxxxxxxxxx -# Derived from netif.py: -# Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx> +# Author: Stefan Berger, stefanb@xxxxxxxxxx +# Copyright (C) 2005 XenSource Ltd +#============================================================================ + """Support for virtual TPM interfaces. """ -import random +from xen.xend import sxp +from xen.xend.XendLogging import log -from xen.xend import sxp -from xen.xend.XendError import XendError, VmError -from xen.xend.XendLogging import log -from xen.xend.XendRoot import get_component -from xen.xend.xenstore import DBVar +from xen.xend.server.DevController import DevController -from xen.xend.server.controller import Dev, DevController class TPMifController(DevController): """TPM interface controller. Handles all TPM devices for a domain. """ - def __init__(self, vm, recreate=False): - DevController.__init__(self, vm, recreate=recreate) + def __init__(self, vm): + DevController.__init__(self, vm) - def initController(self, recreate=False, reboot=False): - self.destroyed = False - def destroyController(self, reboot=False): - """Destroy the controller and all devices. - """ - self.destroyed = True - self.destroyDevices(reboot=reboot) + def getDeviceDetails(self, config): + """@see DevController.getDeviceDetails""" + + devid = int(sxp.child_value(config, 'instance', '0')) + log.error("The domain has a TPM with instance %d." % devid) - def sxpr(self): - val = ['tpmif', ['dom', self.getDomain()]] - return val + back = { 'instance' : "%i" % devid } + front = { 'handle' : "%i" % devid } - def newDevice(self, id, config, recreate=False): - """Create a TPM device. - - @param id: interface id - @param config: device configuration - @param recreate: recreate flag (true after xend restart) - """ - return None + return (devid, back, front) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/usbif.py --- a/tools/python/xen/xend/server/usbif.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/usbif.py Mon Sep 19 10:51:05 2005 @@ -1,185 +1,50 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ # Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx> # Copyright (C) 2004 Intel Research Cambridge # Copyright (C) 2004 Mark Williamson <mark.williamson@xxxxxxxxxxxx> +# Copyright (C) 2005 XenSource Ltd +#============================================================================ + + """Support for virtual USB hubs. """ -from xen.xend import sxp -from xen.xend.XendLogging import log -from xen.xend.XendError import XendError -from xen.xend.xenstore import DBVar - -from xen.xend.server.controller import Dev, DevController - -class UsbBackend: - """Handler for the 'back-end' channel to a USB device driver domain - on behalf of a front-end domain. - """ - def __init__(self, controller, id, dom): - self.controller = controller - self.id = id - self.destroyed = False - self.connected = False - self.connecting = False - self.frontendDomain = self.controller.getDomain() - self.backendDomain = dom - - def init(self, recreate=False, reboot=False): - pass - - def __str__(self): - return ('<UsbifBackend frontend=%d backend=%d id=%d>' - % (self.frontendDomain, - self.backendDomain, - self.id)) - - def connect(self, recreate=False): - """Connect the controller to the usbif control interface. - - @param recreate: true if after xend restart - """ - log.debug("Connecting usbif %s", str(self)) - if recreate or self.connected or self.connecting: - pass - - def destroy(self, reboot=False): - """Disconnect from the usbif control interface and destroy it. - """ - self.destroyed = True - - def interfaceChanged(self): - pass +from xen.xend.server.DevController import DevController -class UsbDev(Dev): +next_devid = 1 - __exports__ = Dev.__exports__ + [ - DBVar('port', ty='int'), - DBVar('path', ty='str'), - ] - - def __init__(self, controller, id, config, recreate=False): - Dev.__init__(self, controller, id, config, recreate=recreate) - self.port = id - self.path = None - self.frontendDomain = self.getDomain() - self.backendDomain = 0 - self.configure(self.config, recreate=recreate) - - def init(self, recreate=False, reboot=False): - self.destroyed = False - self.frontendDomain = self.getDomain() - - def configure(self, config, change=False, recreate=False): - if change: - raise XendError("cannot reconfigure usb") - #todo: FIXME: Use sxp access methods to get this value. - # Must not use direct indexing. - self.path = config[1][1] - - #todo: FIXME: Support configuring the backend domain. -## try: -## self.backendDomain = int(sxp.child_value(config, 'backend', '0')) -## except: -## raise XendError('invalid backend domain') - - def attach(self, recreate=False, change=False): - if recreate: - pass - else: - self.attachBackend() - if change: - self.interfaceChanged() - - def sxpr(self): - val = ['usb', - ['id', self.id], - ['port', self.port], - ['path', self.path], - ] - return val - - def getBackend(self): - return self.controller.getBackend(self.backendDomain) - - def destroy(self, change=False, reboot=False): - """Destroy the device. If 'change' is true notify the front-end interface. - - @param change: change flag - """ - self.destroyed = True - log.debug("Destroying usb domain=%d id=%s", self.frontendDomain, self.id) - if change: - self.interfaceChanged() - - def interfaceChanged(self): - """Tell the back-end to notify the front-end that a device has been - added or removed. - """ - self.getBackend().interfaceChanged() - - def attachBackend(self): - """Attach the device to its controller. - - """ - self.getBackend().connect() class UsbifController(DevController): """USB device interface controller. Handles all USB devices for a domain. """ - def __init__(self, vm, recreate=False): + def __init__(self, vm): """Create a USB device controller. """ - DevController.__init__(self, vm, recreate=recreate) - self.backends = {} - self.backendId = 0 + DevController.__init__(self, vm) - def init(self, recreate=False, reboot=False): - self.destroyed = False - if reboot: - self.rebootBackends() - self.rebootDevices() - def sxpr(self): - val = ['usbif', - ['dom', self.getDomain()]] - return val + def getDeviceDetails(self, _): + """@see DevController.getDeviceDetails""" - def newDevice(self, id, config, recreate=False): - return UsbDev(self, id, config, recreate=recreate) + global next_devid - def destroyController(self, reboot=False): - """Destroy the controller and all devices. - """ - self.destroyed = True - log.debug("Destroying blkif domain=%d", self.getDomain()) - self.destroyDevices(reboot=reboot) - self.destroyBackends(reboot=reboot) + devid = next_devid + next_devid += 1 - def rebootBackends(self): - for backend in self.backends.values(): - backend.init(reboot=True) - - def getBackendById(self, id): - return self.backends.get(id) - - def getBackendByDomain(self, dom): - for backend in self.backends.values(): - if backend.backendDomain == dom: - return backend - return None - - def getBackend(self, dom): - backend = self.getBackendByDomain(dom) - if backend: return backend - backend = UsbBackend(self, self.backendId, dom) - self.backendId += 1 - self.backends[backend.getId()] = backend - backend.init() - return backend - - def destroyBackends(self, reboot=False): - for backend in self.backends.values(): - backend.destroy(reboot=reboot) + return (devid, {}, {}) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/xenstore/xsobj.py --- a/tools/python/xen/xend/xenstore/xsobj.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/xenstore/xsobj.py Mon Sep 19 10:51:05 2005 @@ -469,9 +469,6 @@ n = n._addChild(x) return n - def getDB(self): - return self.__db__ - def setDB(self, db): if (db is not None) and not isinstance(db, XenNode): raise ValueError("invalid db") diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/xenstore/xstransact.py --- a/tools/python/xen/xend/xenstore/xstransact.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/xenstore/xstransact.py Mon Sep 19 10:51:05 2005 @@ -67,7 +67,12 @@ if not isinstance(d, dict): raise TypeError for key in d.keys(): - self._write(key, d[key], create, excl) + try: + self._write(key, d[key], create, excl) + except TypeError, msg: + raise TypeError('Writing %s: %s: %s' % + (key, str(d[key]), msg)) + elif isinstance(args[0], list): for l in args: if not len(l) == 2: @@ -84,10 +89,15 @@ return xshandle().rm(path) def remove(self, *args): - if len(args) == 0: - raise TypeError - for key in args: - self._remove(key) + """If no arguments are given, remove this transaction's path. + Otherwise, treat each argument as a subpath to this transaction's + path, and remove each of those instead. + """ + if len(args) == 0: + xshandle().rm(self.path) + else: + for key in args: + self._remove(key) def _list(self, key): path = "%s/%s" % (self.path, key) @@ -146,8 +156,8 @@ def Read(cls, path, *args): while True: - try: - t = cls(path) + t = cls(path) + try: v = t.read(*args) t.commit() return v @@ -165,8 +175,8 @@ def Write(cls, path, *args, **opts): while True: - try: - t = cls(path) + t = cls(path) + try: t.write(*args, **opts) t.commit() return @@ -183,9 +193,13 @@ Write = classmethod(Write) def Remove(cls, path, *args): - while True: - try: - t = cls(path) + """If only one argument is given (path), remove it. Otherwise, treat + each further argument as a subpath to the given path, and remove each + of those instead. This operation is performed inside a transaction. + """ + while True: + t = cls(path) + try: t.remove(*args) t.commit() return @@ -203,8 +217,8 @@ def List(cls, path, *args): while True: - try: - t = cls(path) + t = cls(path) + try: v = t.list(*args) t.commit() return v @@ -222,8 +236,8 @@ def Gather(cls, path, *args): while True: - try: - t = cls(path) + t = cls(path) + try: v = t.gather(*args) t.commit() return v @@ -241,8 +255,8 @@ def Store(cls, path, *args): while True: - try: - t = cls(path) + t = cls(path) + try: v = t.store(*args) t.commit() return v diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/xenstore/xswatch.py --- a/tools/python/xen/xend/xenstore/xswatch.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/xenstore/xswatch.py Mon Sep 19 10:51:05 2005 @@ -1,4 +1,5 @@ # Copyright (C) 2005 Christian Limpach <Christian.Limpach@xxxxxxxxxxxx> +# Copyright (C) 2005 XenSource Ltd # This file is subject to the terms and conditions of the GNU General # Public License. See the file "COPYING" in the main directory of @@ -15,7 +16,7 @@ xs = None xslock = threading.Lock() - def __init__(self, path, fn, args=(), kwargs={}): + def __init__(self, path, fn, *args, **kwargs): self.fn = fn self.args = args self.kwargs = kwargs @@ -46,11 +47,11 @@ cls.threadcond.release() while True: try: - (ord, owr, oer) = select.select([ cls.xs ], [], []) + (fd, _1, _2) = select.select([ cls.xs ], [], []) cls.xslock.acquire() # reconfirm ready to read with lock - (ord, owr, oer) = select.select([ cls.xs ], [], [], 0.001) - if not cls.xs in ord: + (fd, _1, _2) = select.select([ cls.xs ], [], [], 0.001) + if not cls.xs in fd: cls.xslock.release() continue we = cls.xs.read_watch() diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xm/create.py Mon Sep 19 10:51:05 2005 @@ -141,7 +141,7 @@ use="Domain memory in MB.") gopts.var('ssidref', val='SSIDREF', - fn=set_u32, default=-1, + fn=set_u32, default=0, use="Security Identifier.") gopts.var('maxmem', val='MEMORY', diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/DevController.py --- /dev/null Mon Sep 19 09:14:41 2005 +++ b/tools/python/xen/xend/server/DevController.py Mon Sep 19 10:51:05 2005 @@ -0,0 +1,203 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd +#============================================================================ + + +from xen.xend import sxp +from xen.xend.XendError import VmError +from xen.xend.XendLogging import log +from xen.xend.xenstore.xstransact import xstransact + + +class DevController: + """Abstract base class for a device controller. Device controllers create + appropriate entries in the store to trigger the creation, reconfiguration, + and destruction of devices in guest domains. Each subclass of + DevController is responsible for a particular device-class, and + understands the details of configuration specific to that device-class. + + DevController itself provides the functionality common to all device + creation tasks, as well as providing an interface to XendDomainInfo for + triggering those events themselves. + """ + + # Set when registered. + deviceClass = None + + + ## public: + + def __init__(self, vm): + self.vm = vm + + + def createDevice(self, config): + """Trigger the creation of a device with the given configuration. + + @return The ID for the newly created device. + """ + (devid, back, front) = self.getDeviceDetails(config) + + self.writeDetails(config, devid, back, front) + + return devid + + + def reconfigureDevice(self, devid, config): + """Reconfigure the specified device. + + The implementation here just raises VmError. This may be overridden + by those subclasses that can reconfigure their devices. + """ + raise VmError('%s devices may not be reconfigured' % self.deviceClass) + + + def destroyDevice(self, devid): + """Destroy the specified device. + + The implementation here simply deletes the appropriate paths from + the store. This may be overridden by subclasses who need to perform + other tasks on destruction. + """ + + frontpath = self.frontendPath(devid) + backpath = xstransact.Read("%s/backend" % frontpath) + + xstransact.Remove(frontpath) + xstransact.Remove(backpath) + + + def sxpr(self, devid): + """@return an s-expression describing the specified device. + """ + return [self.deviceClass, ['dom', self.vm.getDomain(), + 'id', devid]] + + + ## protected: + + def getDeviceDetails(self, config): + """Compute the details for creation of a device corresponding to the + given configuration. These details consist of a tuple of (devID, + backDetails, frontDetails), where devID is the ID for the new device, + and backDetails and frontDetails are the device configuration + specifics for the backend and frontend respectively. + + backDetails and frontDetails should be dictionaries, the keys and + values of which will be used as paths in the store. There is no need + for these dictionaries to include the references from frontend to + backend, nor vice versa, as these will be handled by DevController. + + Abstract; must be implemented by every subclass. + + @return (devID, backDetails, frontDetails), as specified above. + """ + + raise NotImplementedError() + + + def getDomain(self): + """Stub to {@link XendDomainInfo.getDomain}, for use by our + subclasses. + """ + return self.vm.getDomain() + + + def allocateDeviceID(self): + """Allocate a device ID, allocating them consecutively on a + per-domain, per-device-class basis, and using the store to record the + next available ID. + + This method is available to our subclasses, though it is not + compulsory to use it; subclasses may prefer to allocate IDs based upon + the device configuration instead. + """ + path = self.frontendMiscPath() + t = xstransact(path) + try: + result = t.read("nextDeviceID") + if result: + result = int(result) + else: + result = 1 + t.write("nextDeviceID", str(result + 1)) + t.commit() + return result + except: + t.abort() + raise + + + ## private: + + def writeDetails(self, config, devid, backDetails, frontDetails): + """Write the details in the store to trigger creation of a device. + The backend domain ID is taken from the given config, paths for + frontend and backend are computed, and these are written to the store + appropriately, including references from frontend to backend and vice + versa. + + @param config The configuration of the device, as given to + {@link #createDevice}. + @param devid As returned by {@link #getDeviceDetails}. + @param backDetails As returned by {@link #getDeviceDetails}. + @param frontDetails As returned by {@link #getDeviceDetails}. + """ + + import xen.xend.XendDomain + backdom = xen.xend.XendDomain.instance().domain_lookup_by_name( + sxp.child_value(config, 'backend', '0')) + + frontpath = self.frontendPath(devid) + backpath = self.backendPath(backdom, devid) + + frontDetails.update({ + 'backend' : backpath, + 'backend-id' : "%i" % backdom.getDomain() + }) + + + backDetails.update({ + 'domain' : self.vm.getName(), + 'frontend' : frontpath, + 'frontend-id' : "%i" % self.vm.getDomain() + }) + + log.debug('DevController: writing %s to %s.', str(frontDetails), + frontpath) + log.debug('DevController: writing %s to %s.', str(backDetails), + backpath) + + xstransact.Write(frontpath, frontDetails) + xstransact.Write(backpath, backDetails) + + + def backendPath(self, backdom, devid): + """@param backdom [XendDomainInfo] The backend domain info.""" + + return "%s/backend/%s/%s/%d" % (backdom.getPath(), + self.deviceClass, + self.vm.getUuid(), devid) + + + def frontendPath(self, devid): + return "%s/device/%s/%d" % (self.vm.getPath(), self.deviceClass, + devid) + + + def frontendMiscPath(self): + return "%s/device-misc/%s" % (self.vm.getPath(), self.deviceClass) diff -r cedb89d6b707 -r 308260e5868c tools/python/xen/xend/server/controller.py --- a/tools/python/xen/xend/server/controller.py Mon Sep 19 09:14:41 2005 +++ /dev/null Mon Sep 19 10:51:05 2005 @@ -1,423 +0,0 @@ -#============================================================================ -# This library is free software; you can redistribute it and/or -# modify it under the terms of version 2.1 of the GNU Lesser General Public -# License as published by the Free Software Foundation. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -#============================================================================ -# Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> -#============================================================================ - -"""General support for controllers, which handle devices -for a domain. -""" - -from xen.xend.XendError import XendError -from xen.xend.xenstore import DBVar - -DEBUG = 0 - -class DevControllerTable: - """Table of device controller classes, indexed by type name. - """ - - def __init__(self): - self.controllerClasses = {} - - def getDevControllerClass(self, type): - return self.controllerClasses.get(type) - - def addDevControllerClass(self, cls): - self.controllerClasses[cls.getType()] = cls - - def delDevControllerClass(self, type): - if type in self.controllerClasses: - del self.controllerClasses[type] - - def createDevController(self, type, vm, recreate=False): - cls = self.getDevControllerClass(type) - if not cls: - raise XendError("unknown device type: " + str(type)) - return cls.createDevController(vm, recreate=recreate) - -def getDevControllerTable(): - """Singleton constructor for the controller table. - """ - global devControllerTable - try: - devControllerTable - except: - devControllerTable = DevControllerTable() - return devControllerTable - -def addDevControllerClass(name, cls): - """Add a device controller class to the controller table. - """ - cls.type = name - getDevControllerTable().addDevControllerClass(cls) - - -def isDevControllerClass(name): - """@return True if a device controller class has been registered with - the controller table under the given name.""" - return name in getDevControllerTable().controllerClasses - - -def createDevController(name, vm, recreate=False): - return getDevControllerTable().createDevController(name, vm, recreate=recreate) - -class DevController: - """Abstract class for a device controller attached to a domain. - A device controller manages all the devices of a given type for a domain. - There is exactly one device controller for each device type for - a domain. - - """ - - # State: - # controller/<type> : for controller - # device/<type>/<id> : for each device - - def createDevController(cls, vm, recreate=False): - """Class method to create a dev controller. - """ - ctrl = cls(vm, recreate=recreate) - ctrl.initController(recreate=recreate) - ctrl.exportToDB() - return ctrl - - createDevController = classmethod(createDevController) - - def getType(cls): - return cls.type - - getType = classmethod(getType) - - __exports__ = [ - DBVar('type', 'str'), - DBVar('destroyed', 'bool'), - ] - - # Set when registered. - type = None - - def __init__(self, vm, recreate=False): - self.destroyed = False - self.vm = vm - self.db = self.getDB() - self.deviceId = 0 - self.devices = {} - self.device_order = [] - - def getDB(self): - """Get the db node to use for a controller. - """ - return self.vm.db.addChild("/controller/%s" % self.getType()) - - def getDevDB(self, id): - """Get the db node to use for a device. - """ - return self.vm.db.addChild("/device/%s/%s" % (self.getType(), id)) - - def exportToDB(self, save=False): - self.db.exportToDB(self, fields=self.__exports__, save=save) - - def importFromDB(self): - self.db.importFromDB(self, fields=self.__exports__) - - def getDevControllerType(self): - return self.dctype - - def getDomain(self): - return self.vm.getDomain() - - def getDomainName(self): - return self.vm.getName() - - def getDomainInfo(self): - return self.vm - - #---------------------------------------------------------------------------- - # Subclass interface. - # Subclasses should define the unimplemented methods.. - # Redefinitions must have the same arguments. - - def initController(self, recreate=False, reboot=False): - """Initialise the controller. Called when the controller is - first created, and again after the domain is rebooted (with reboot True). - If called with recreate True (and reboot False) the controller is being - recreated after a xend restart. - - As this can be a re-init (after reboot) any controller state should - be reset. For example the destroyed flag. - """ - self.destroyed = False - if reboot: - self.rebootDevices() - - def newDevice(self, id, config, recreate=False): - """Create a device with the given config. - Must be defined in subclass. - Called with recreate True when the device is being recreated after a - xend restart. - - @return device - """ - raise NotImplementedError() - - def createDevice(self, config, recreate=False, change=False): - """Create a device and attach to its front- and back-ends. - If recreate is true the device is being recreated after a xend restart. - If change is true the device is a change to an existing domain, - i.e. it is being added at runtime rather than when the domain is created. - """ - dev = self.newDevice(self.nextDeviceId(), config, recreate=recreate) - if self.vm.recreate: - dev.importFromDB() - dev.init(recreate=recreate) - self.addDevice(dev) - if not recreate: - dev.exportToDB() - dev.attach(recreate=recreate, change=change) - dev.exportToDB() - - return dev - - def configureDevice(self, id, config, change=False): - """Reconfigure an existing device. - May be defined in subclass.""" - dev = self.getDevice(id, error=True) - dev.configure(config, change=change) - - def destroyDevice(self, id, change=False, reboot=False): - """Destroy a device. - May be defined in subclass. - - If reboot is true the device is being destroyed for a domain reboot. - - The device is not deleted, since it may be recreated later. - """ - dev = self.getDevice(id, error=True) - dev.destroy(change=change, reboot=reboot) - return dev - - def deleteDevice(self, id, change=True): - """Destroy a device and delete it. - Normally called to remove a device from a domain at runtime. - """ - dev = self.destroyDevice(id, change=change) - self.removeDevice(dev) - - def destroyController(self, reboot=False): - """Destroy all devices and clean up. - May be defined in subclass. - If reboot is true the controller is being destroyed for a domain reboot. - Called at domain shutdown. - """ - self.destroyed = True - self.destroyDevices(reboot=reboot) - - #---------------------------------------------------------------------------- - - def isDestroyed(self): - return self.destroyed - - def getDevice(self, id, error=False): - dev = self.devices.get(int(id)) - if error and not dev: - raise XendError("invalid device id: " + str(id)) - return dev - - def getDeviceIds(self): - return [ dev.getId() for dev in self.device_order ] - - def getDevices(self): - return self.device_order - - def getDeviceConfig(self, id): - return self.getDevice(id).getConfig() - - def getDeviceConfigs(self): - return [ dev.getConfig() for dev in self.device_order ] - - def getDeviceSxprs(self): - return [ dev.sxpr() for dev in self.device_order ] - - def addDevice(self, dev): - self.devices[dev.getId()] = dev - self.device_order.append(dev) - return dev - - def removeDevice(self, dev): - if dev.getId() in self.devices: - del self.devices[dev.getId()] - if dev in self.device_order: - self.device_order.remove(dev) - - def rebootDevices(self): - for dev in self.getDevices(): - dev.reboot() - - def destroyDevices(self, reboot=False): - """Destroy all devices. - """ - for dev in self.getDevices(): - dev.destroy(reboot=reboot) - - def getMaxDeviceId(self): - maxid = 0 - for id in self.devices: - if id > maxid: - maxid = id - return maxid - - def nextDeviceId(self): - id = self.deviceId - self.deviceId += 1 - return id - - def getDeviceCount(self): - return len(self.devices) - -class Dev: - """Abstract class for a device attached to a device controller. - - @ivar id: identifier - @type id: int - @ivar controller: device controller - @type controller: DevController - """ - - # ./status : need 2: actual and requested? - # down-down: initial. - # up-up: fully up. - # down-up: down requested, still up. Watch front and back, when both - # down go to down-down. But what if one (or both) is not connected? - # Still have front/back trees with status? Watch front/status, back/status? - # up-down: up requested, still down. - # Back-end watches ./status, front/status - # Front-end watches ./status, back/status - # i.e. each watches the other 2. - # Each is status/request status/actual? - # - # backend? - # frontend? - - __exports__ = [ - DBVar('id', ty='int'), - DBVar('type', ty='str'), - DBVar('config', ty='sxpr'), - DBVar('destroyed', ty='bool'), - ] - - def __init__(self, controller, id, config, recreate=False): - self.controller = controller - self.id = id - self.config = config - self.destroyed = False - self.type = self.getType() - - self.db = controller.getDevDB(id) - - def exportToDB(self, save=False): - self.db.exportToDB(self, fields=self.__exports__, save=save) - - def importFromDB(self): - self.db.importFromDB(self, fields=self.__exports__) - - def getDomain(self): - return self.controller.getDomain() - - def getDomainName(self): - return self.controller.getDomainName() - - def getDomainInfo(self): - return self.controller.getDomainInfo() - - def getController(self): - return self.controller - - def getType(self): - return self.controller.getType() - - def getId(self): - return self.id - - def getConfig(self): - return self.config - - def isDestroyed(self): - return self.destroyed - - #---------------------------------------------------------------------------- - # Subclass interface. - # Define methods in subclass as needed. - # Redefinitions must have the same arguments. - - def init(self, recreate=False, reboot=False): - """Initialization. Called on initial create (when reboot is False) - and on reboot (when reboot is True). When xend is restarting is - called with recreate True. Define in subclass if needed. - - Device instance variables must be defined in the class constructor, - but given null or default values. The real values should be initialised - in this method. This allows devices to be re-initialised. - - Since this can be called to re-initialise a device any state flags - should be reset. - """ - self.destroyed = False - - def attach(self, recreate=False, change=False): - """Attach the device to its front and back ends. - Define in subclass if needed. - """ - pass - - def reboot(self): - """Reconnect the device when the domain is rebooted. - """ - self.init(reboot=True) - self.attach() - - def sxpr(self): - """Get the s-expression for the deivice. - Implement in a subclass if needed. - - @return: sxpr - """ - return self.getConfig() - - def configure(self, config, change=False): - """Reconfigure the device. - - Implement in subclass. - """ - raise NotImplementedError() - - def refresh(self): - """Refresh the device.. - Default no-op. Define in subclass if needed. - """ - pass - - def destroy(self, change=False, reboot=False): - """Destroy the device. - If change is True notify destruction (runtime change). - If reboot is True the device is being destroyed for a reboot. - Redefine in subclass if needed. - - Called at domain shutdown and when a device is deleted from - a running domain (with change True). - """ - self.destroyed = True - pass - - #---------------------------------------------------------------------------- _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |