# 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
|