bitkeeper revision 1.1159.170.110 (42527636gInunc40rkIVZVCuDC-_OQ)

Merge
This commit is contained in:
sd386@font.cl.cam.ac.uk committed 2005-04-05 11:27:50 +00:00
commit 2208888f15
444 files changed
+40955 -6684

No files matched your search

+12 -3
View File
@@ -1,9 +1,18 @@
all:
python setup.py build
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
all: build
build:
CFLAGS="$(CFLAGS)" python setup.py build
ifndef XEN_PYTHON_NATIVE_INSTALL
install: all
python setup.py install --home="$(prefix)/usr"
CFLAGS="$(CFLAGS)" python setup.py install --home="$(DESTDIR)/usr"
else
install: all
CFLAGS="$(CFLAGS)" python setup.py install --root="$(DESTDIR)"
endif
clean:
rm -rf build *.pyc *.pyo *.o *.a *~
+27
View File
@@ -259,6 +259,7 @@ static PyTypeObject xu_notifier_type = {
*/
#define TYPE(_x,_y) (((_x)<<8)|(_y))
#define P2C(_struct, _field, _ctype) \
do { \
PyObject *obj; \
@@ -279,6 +280,29 @@ static PyTypeObject xu_notifier_type = {
} \
xum->msg.length = sizeof(_struct); \
} while ( 0 )
/** Set a char[] field in a struct from a Python string.
* Can't do this in P2C because of the typing.
*/
#define P2CSTRING(_struct, _field) \
do { \
PyObject *obj; \
if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
{ \
if ( PyString_Check(obj) ) \
{ \
_struct * _cobj = (_struct *)&xum->msg.msg[0]; \
int _field_n = sizeof(_cobj->_field); \
memset(_cobj->_field, 0, _field_n); \
strncpy(_cobj->_field, \
PyString_AsString(obj), \
_field_n - 1); \
dict_items_parsed++; \
} \
} \
xum->msg.length = sizeof(_struct); \
} while ( 0 )
#define C2P(_struct, _field, _pytype, _ctype) \
do { \
PyObject *obj = Py ## _pytype ## _From ## _ctype \
@@ -647,6 +671,9 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args)
P2C(mem_request_t, target, u32);
P2C(mem_request_t, status, u32);
break;
case TYPE(CMSG_SHUTDOWN, CMSG_SHUTDOWN_SYSRQ):
P2C(shutdown_sysrq_t, key, char);
break;
}
if ( dict_items_parsed != PyDict_Size(payload) )
+2 -2
View File
@@ -1,3 +1,3 @@
SV_PORT = 8080
SV_ROOT = "/var/xen/sv/"
PID_FILE = "/var/xen/sv.pid"
SV_ROOT = "/var/lib/xen/sv/"
PID_FILE = "/var/run/xen-sv.pid"
+5
View File
@@ -78,6 +78,8 @@ class Args:
val = str(v)
elif type == 'sxpr':
val = self.sxpr(v)
elif type == 'bool':
val = self.bool(v)
else:
raise ArgError('invalid type:' + str(type))
return val
@@ -86,6 +88,9 @@ class Args:
except StandardError, ex:
raise ArgError(str(ex))
def bool(self, v):
return (v.lower() in ['on', 'yes', '1', 'true'])
def sxpr(self, v):
if isinstance(v, types.ListType):
val = v
+14
View File
@@ -37,6 +37,20 @@ def network(op, script=None, bridge=None, antispoof=None):
args = ' '.join(args)
os.system(script + ' ' + args)
def set_vif_name(vif_old, vif_new):
if vif_old == vif_new:
vif = vif_new
return vif
if os.system("ip link show %s" % vif_old) == 0:
os.system("ip link set %s down" % vif_old)
os.system("ip link set %s name %s" % (vif_old, vif_new))
os.system("ip link set %s up" % vif_new)
if os.system("ip link show %s" % vif_new) == 0:
vif = vif_new
else:
vif = vif_old
return vif
def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, ipaddr=[]):
"""Call a vif control script.
Xend calls this when bringing vifs up or down.
+2 -1
View File
@@ -449,9 +449,9 @@ class XendDomainInfo:
self.init_domain()
self.configure_console()
self.configure_backends()
self.construct_image()
self.configure_restart()
self.configure_backends()
deferred = self.configure()
def cberr(err):
self.destroy()
@@ -1227,6 +1227,7 @@ add_config_handler('memory', vm_field_ignore)
add_config_handler('cpu', vm_field_ignore)
add_config_handler('cpu_weight', vm_field_ignore)
add_config_handler('console', vm_field_ignore)
add_config_handler('restart', vm_field_ignore)
add_config_handler('image', vm_field_ignore)
add_config_handler('device', vm_field_ignore)
add_config_handler('backend', vm_field_ignore)
+91 -67
View File
@@ -6,12 +6,14 @@ import errno
import sys
import socket
import time
import types
from twisted.internet import reactor
from twisted.internet import defer
#defer.Deferred.debug = 1
from twisted.internet.protocol import Protocol
from twisted.internet.protocol import ClientFactory
from twisted.python.failure import Failure
import sxp
import XendDB
@@ -45,11 +47,9 @@ class Xfrd(Protocol):
sxp.show(req, out=self.transport)
def loseConnection(self):
print 'Xfrd>loseConnection>'
self.transport.loseConnection()
def connectionLost(self, reason):
print 'Xfrd>connectionLost>', reason
self.xinfo.connectionLost(reason)
def dataReceived(self, data):
@@ -70,17 +70,15 @@ class XfrdClientFactory(ClientFactory):
self.xinfo = xinfo
def startedConnecting(self, connector):
print 'Started to connect', 'self=', self, 'connector=', connector
pass
def buildProtocol(self, addr):
print 'buildProtocol>', addr
return Xfrd(self.xinfo)
def clientConnectionLost(self, connector, reason):
print 'clientConnectionLost>', 'connector=', connector, 'reason=', reason
pass
def clientConnectionFailed(self, connector, reason):
print 'clientConnectionFailed>', 'connector=', connector, 'reason=', reason
self.xinfo.error(reason)
class XfrdInfo:
@@ -90,7 +88,7 @@ class XfrdInfo:
"""Suspend timeout (seconds).
We set a timeout because suspending a domain can hang."""
timeout = 30
timeout = 10
def __init__(self):
from xen.xend import XendDomain
@@ -98,6 +96,9 @@ class XfrdInfo:
self.deferred = defer.Deferred()
self.suspended = {}
self.paused = {}
self.state = 'init'
# List of errors encountered.
self.errors = []
def vmconfig(self):
dominfo = self.xd.domain_get(self.src_dom)
@@ -107,12 +108,38 @@ class XfrdInfo:
val = None
return val
def add_error(self, err):
"""Add an error to the error list.
Returns the error added (which may have been unwrapped if it
was a Twisted Failure).
"""
while isinstance(err, Failure):
err = err.value
if err not in self.errors:
self.errors.append(err)
return err
def error_summary(self, msg=None):
"""Get a XendError summarising the errors (if any).
"""
if msg is None:
msg = "errors"
if self.errors:
errmsg = msg + ': ' + ', '.join(map(str, self.errors))
else:
errmsg = msg
return XendError(errmsg)
def get_errors(self):
"""Get the list of errors.
"""
return self.errors
def error(self, err):
print 'Error>', err
self.state = 'error'
self.add_error(err)
if not self.deferred.called:
print 'Error> calling errback'
self.deferred.errback(err)
self.deferred.errback(self.error_summary())
def dispatch(self, xfrd, val):
@@ -139,28 +166,23 @@ class XfrdInfo:
cbok(val)
def unknown(self, xfrd, val):
print 'unknown>', val
xfrd.loseConnection()
return None
def xfr_err(self, xfrd, val):
# If we get an error with non-zero code the operation failed.
# An error with code zero indicates hello success.
print 'xfr_err>', val
v = sxp.child0(val)
print 'xfr_err>', type(v), v
err = int(sxp.child0(val))
if not err: return
self.error(err);
self.error("transfer daemon (xfrd) error: " + str(err))
xfrd.loseConnection()
return None
def xfr_progress(self, xfrd, val):
print 'xfr_progress>', val
return None
def xfr_vm_destroy(self, xfrd, val):
print 'xfr_vm_destroy>', val
try:
vmid = sxp.child0(val)
val = self.xd.domain_destroy(vmid)
@@ -168,28 +190,32 @@ class XfrdInfo:
del self.paused[vmid]
if vmid in self.suspended:
del self.suspended[vmid]
except:
except StandardError, err:
self.add_error("vm_destroy failed")
self.add_error(err)
val = errno.EINVAL
return ['xfr.err', val]
def xfr_vm_pause(self, xfrd, val):
print 'xfr_vm_pause>', val
try:
vmid = sxp.child0(val)
val = self.xd.domain_pause(vmid)
self.paused[vmid] = 1
except:
except StandardError, err:
self.add_error("vm_pause failed")
self.add_error(err)
val = errno.EINVAL
return ['xfr.err', val]
def xfr_vm_unpause(self, xfrd, val):
print 'xfr_vm_unpause>', val
try:
vmid = sxp.child0(val)
val = self.xd.domain_unpause(vmid)
if vmid in self.paused:
del self.paused[vmid]
except:
except StandardError, err:
self.add_error("vm_unpause failed")
self.add_error(err)
val = errno.EINVAL
return ['xfr.err', val]
@@ -199,7 +225,6 @@ class XfrdInfo:
Suspending can hang, so we set a timeout and fail if it
takes too long.
"""
print 'xfr_vm_suspend>', val
try:
vmid = sxp.child0(val)
d = defer.Deferred()
@@ -208,15 +233,15 @@ class XfrdInfo:
# the domain died. Set a timeout and error handler so the subscriptions
# will be cleaned up if suspending hangs or there is an error.
def onSuspended(e, v):
print 'xfr_vm_suspend>onSuspended>', e, v
if v[1] != vmid: return
subscribe(on=0)
d.callback(v)
if not d.called:
d.callback(v)
def onDied(e, v):
print 'xfr_vm_suspend>onDied>', e, v
if v[1] != vmid: return
d.errback(XendError('Domain died'))
if not d.called:
d.errback(XendError('Domain %s died while suspending' % vmid))
def subscribe(on=1):
if on:
@@ -227,24 +252,25 @@ class XfrdInfo:
action('xend.domain.died', onDied)
def cberr(err):
print 'xfr_vm_suspend>cberr>', err
subscribe(on=0)
self.add_error("suspend failed")
self.add_error(err)
return err
d.addErrback(cberr)
d.setTimeout(self.timeout)
subscribe()
val = self.xd.domain_shutdown(vmid, reason='suspend')
self.suspended[vmid] = 1
d.addErrback(cberr)
d.setTimeout(self.timeout)
return d
except Exception, err:
print 'xfr_vm_suspend> Exception', err
self.add_error("suspend failed")
self.add_error(err)
traceback.print_exc()
val = errno.EINVAL
return ['xfr.err', val]
def connectionLost(self, reason=None):
print 'XfrdInfo>connectionLost>', reason
for vmid in self.suspended:
try:
self.xd.domain_destroy(vmid)
@@ -279,7 +305,7 @@ class XendMigrateInfo(XfrdInfo):
['id', self.xid ],
['state', self.state ],
['live', self.live ],
['resource', self.resource] ]
['resource', self.resource ] ]
sxpr_src = ['src', ['host', self.src_host], ['domain', self.src_dom] ]
sxpr.append(sxpr_src)
sxpr_dst = ['dst', ['host', self.dst_host] ]
@@ -291,12 +317,12 @@ class XendMigrateInfo(XfrdInfo):
def request(self, xfrd):
vmconfig = self.vmconfig()
if not vmconfig:
self.error(XendError("vm config not found"))
xfrd.loseConnection()
return
log.info('Migrate BEGIN: ' + str(self.sxpr()))
log.info('Migrate BEGIN: %s' % str(self.sxpr()))
eserver.inject('xend.domain.migrate',
[ self.dominfo.name, self.dominfo.id,
"begin", self.sxpr() ])
[ self.dominfo.name, self.dominfo.id, "begin", self.sxpr() ])
xfrd.request(['xfr.migrate',
self.src_dom,
vmconfig,
@@ -305,19 +331,6 @@ class XendMigrateInfo(XfrdInfo):
self.live,
self.resource ])
## def xfr_vm_suspend(self, xfrd, val):
## def cbok(val):
## # Special case for localhost: destroy devices early.
## if self.dst_host in ["localhost", "127.0.0.1"]:
## self.dominfo.restart_cancel()
## self.dominfo.cleanup()
## self.dominfo.destroy_console()
## return val
## d = XfrdInfo.xfr_vm_suspend(self, xfrd, val)
## d.addCallback(cbok)
## return d
def xfr_migrate_ok(self, xfrd, val):
dom = int(sxp.child0(val))
self.state = 'ok'
@@ -327,17 +340,15 @@ class XendMigrateInfo(XfrdInfo):
self.deferred.callback(self)
def connectionLost(self, reason=None):
print 'XfrdMigrateInfo>connectionLost>', reason
XfrdInfo.connectionLost(self, reason)
if self.state =='ok':
log.info('Migrate OK: ' + str(self.sxpr()))
else:
self.state = 'error'
self.error(XendError("migrate failed"))
self.error("migrate failed")
log.info('Migrate ERROR: ' + str(self.sxpr()))
eserver.inject('xend.domain.migrate',
[ self.dominfo.name, self.dominfo.id,
self.state, self.sxpr() ])
[ self.dominfo.name, self.dominfo.id, self.state, self.sxpr() ])
class XendSaveInfo(XfrdInfo):
"""Representation of a save in-progress and its interaction with xfrd.
@@ -361,16 +372,15 @@ class XendSaveInfo(XfrdInfo):
return sxpr
def request(self, xfrd):
print '***request>', self.vmconfig()
vmconfig = self.vmconfig()
if not vmconfig:
self.error(XendError("vm config not found"))
xfrd.loseConnection()
return
print '***request> begin'
log.info('Save BEGIN: ' + str(self.sxpr()))
eserver.inject('xend.domain.save',
[self.dominfo.name, self.dominfo.id,
"begin", self.sxpr()])
[ self.dominfo.name, self.dominfo.id,
"begin", self.sxpr() ])
xfrd.request(['xfr.save', self.src_dom, vmconfig, self.file ])
def xfr_save_ok(self, xfrd, val):
@@ -380,13 +390,12 @@ class XendSaveInfo(XfrdInfo):
self.deferred.callback(self)
def connectionLost(self, reason=None):
print 'XfrdSaveInfo>connectionLost>', reason
XfrdInfo.connectionLost(self, reason)
if self.state =='ok':
log.info('Save OK: ' + str(self.sxpr()))
else:
self.state = 'error'
self.error(XendError("save failed"))
self.error("save failed")
log.info('Save ERROR: ' + str(self.sxpr()))
eserver.inject('xend.domain.save',
[ self.dominfo.name, self.dominfo.id,
@@ -409,8 +418,9 @@ class XendRestoreInfo(XfrdInfo):
return sxpr
def request(self, xfrd):
print '***request>', self.file
log.info('restore BEGIN: ' + str(self.sxpr()))
eserver.inject('xend.restore', [ 'begin', self.sxpr()])
xfrd.request(['xfr.restore', self.file ])
def xfr_restore_ok(self, xfrd, val):
@@ -419,8 +429,17 @@ class XendRestoreInfo(XfrdInfo):
self.state = 'ok'
if not self.deferred.called:
self.deferred.callback(dominfo)
def connectionLost(self, reason=None):
XfrdInfo.connectionLost(self, reason)
if self.state =='ok':
log.info('Restore OK: ' + self.file)
else:
self.state = 'error'
self.error("restore failed")
log.info('Restore ERROR: ' + str(self.sxpr()))
eserver.inject('xend.restore', [ self.state, self.sxpr()])
class XendMigrate:
"""External api for interaction with xfrd for migrate and save.
Singleton.
@@ -445,7 +464,6 @@ class XendMigrate:
self.db.saveall("", self.session_db)
def sync_session(self, xid):
print 'sync_session>', type(xid), xid, self.session_db[xid]
self.db.save(xid, self.session_db[xid])
def close(self):
@@ -458,7 +476,6 @@ class XendMigrate:
self.sync_session(xid)
def _delete_session(self, xid):
print '***_delete_session>', xid
if xid in self.session:
del self.session[xid]
if xid in self.session_db:
@@ -482,16 +499,23 @@ class XendMigrate:
@param info: session
@return: deferred
"""
def cbremove(val):
print '***cbremove>', val
dfr = defer.Deferred()
def cbok(val):
self._delete_session(info.xid)
if not dfr.called:
dfr.callback(val)
return val
def cberr(err):
self._delete_session(info.xid)
if not dfr.called:
dfr.errback(err)
return err
self._add_session(info)
info.deferred.addCallback(cbremove)
info.deferred.addErrback(cbremove)
info.deferred.addCallback(cbok)
info.deferred.addErrback(cberr)
xcf = XfrdClientFactory(info)
reactor.connectTCP('localhost', XFRD_PORT, xcf)
return info.deferred
return dfr
def migrate_begin(self, dominfo, host, port=XFRD_PORT, live=0, resource=0):
"""Begin to migrate a domain to another host.
+64 -13
View File
@@ -2,6 +2,11 @@
"""Xend root class.
Creates the event server and handles configuration.
Other classes get config variables by importing this module,
using instance() to get a XendRoot instance, and then
the config functions (e.g. get_xend_port()) to get
configured values.
"""
import os
@@ -20,7 +25,7 @@ class XendRoot:
"""Root of the management classes."""
"""Default path to the root of the database."""
dbroot_default = "/var/xen/xend-db"
dbroot_default = "/var/lib/xen/xend-db"
"""Default path to the config file."""
config_default = "/etc/xen/xend-config.sxp"
@@ -34,17 +39,33 @@ class XendRoot:
"""Where block control scripts live."""
block_script_dir = "/etc/xen/scripts"
"""Default path to the log file. """
logfile_default = "/var/log/xend.log"
loglevel_default = 'DEBUG'
"""Default interface address xend listens at. """
xend_address_default = ''
"""Default port xend serves HTTP at. """
xend_port_default = '8000'
"""Default port xend serves events at. """
xend_event_port_default = '8001'
"""Default inteface address xend listens at for consoles."""
console_address_default = ''
"""Default port xend serves consoles at. """
console_port_base_default = '9600'
components = {}
def __init__(self):
self.dbroot = None
self.config_path = None
self.config = None
self.logger = None
self.logging = None
self.configure()
eserver.subscribe('xend.*', self.event_handler)
#eserver.subscribe('xend.domain.created', self.event_handler)
@@ -73,9 +94,9 @@ class XendRoot:
def _format(self, msg, args):
if args:
return str(msg)
else:
return str(msg) % args
else:
return str(msg)
def _log(self, mode, fmt, args):
"""Logging function that uses the logger if it exists, otherwise
@@ -90,7 +111,7 @@ class XendRoot:
if log:
getattr(log, mode)(fmt, *args)
else:
print >>stderr, "xend", "[%s]" % level, self._format(msg, args)
print >>sys.stderr, "xend", "[%s]" % level, self._format(fmt, args)
def logDebug(self, fmt, *args):
"""Log a debug message.
@@ -132,7 +153,6 @@ class XendRoot:
self.configure_logger()
self.dbroot = self.get_config_value("dbroot", self.dbroot_default)
def configure_logger(self):
logfile = self.get_config_value("logfile", self.logfile_default)
loglevel = self.get_config_value("loglevel", self.loglevel_default)
@@ -146,7 +166,7 @@ class XendRoot:
def get_logger(self):
"""Get the logger.
"""
return self.logging.getLogger()
return self.logging and self.logging.getLogger()
def get_dbroot(self):
"""Get the path to the database root.
@@ -160,14 +180,20 @@ class XendRoot:
"""
self.config_path = os.getenv(self.config_var, self.config_default)
if os.path.exists(self.config_path):
fin = file(self.config_path, 'rb')
#self.logInfo('Reading config file %s', self.config_path)
try:
config = sxp.parse(fin)
fin = file(self.config_path, 'rb')
try:
config = sxp.parse(fin)
finally:
fin.close()
config.insert(0, 'xend-config')
self.config = config
finally:
fin.close()
except Exception, ex:
self.logError('Reading config file %s: %s', self.config_path, str(ex))
raise
else:
self.logError('Config file does not exist: %s', self.config_path)
self.config = ['xend-config']
def get_config(self, name=None):
@@ -193,10 +219,35 @@ class XendRoot:
return sxp.child_value(self.config, name, val=val)
def get_xend_port(self):
return int(self.get_config_value('xend-port', '8000'))
"""Get the port xend listens at for its HTTP interface.
"""
return int(self.get_config_value('xend-port', self.xend_port_default))
def get_xend_event_port(self):
"""Get the port xend listens at for connection to its event server.
"""
return int(self.get_config_value('xend-event-port', self.xend_event_port_default))
def get_xend_address(self):
return self.get_config_value('xend-address', '')
"""Get the address xend listens at for its HTTP and event ports.
This defaults to the empty string which allows all hosts to connect.
If this is set to 'localhost' only the localhost will be able to connect
to the HTTP and event ports.
"""
return self.get_config_value('xend-address', self.xend_address_default)
def get_console_address(self):
"""Get the address xend listens at for its console ports.
This defaults to the empty string which allows all hosts to connect.
If this is set to 'localhost' only the localhost will be able to connect
to the console ports.
"""
return self.get_config_value('console-address', self.console_address_default)
def get_console_port_base(self):
"""Get the base port number used to generate console ports for domains.
"""
return int(self.get_config_value('console-port-base', self.console_port_base_default))
def get_block_script(self, type):
return self.get_config_value('block-%s' % type, '')
+2 -1
View File
@@ -106,7 +106,8 @@ class SrvBase(resource.Resource):
try:
val = op_method(op, req)
except Exception, err:
return self._perform_err(err, op, req)
self._perform_err(err, op, req)
return ''
if isinstance(val, defer.Deferred):
val.addCallback(self._perform_cb, op, req, dfr=1)
+13 -8
View File
@@ -15,6 +15,7 @@ import pwd
import re
import StringIO
import traceback
import time
from twisted.internet import pollreactor
pollreactor.install()
@@ -484,10 +485,12 @@ class Daemon:
# XXX KAF: Why doesn't this capture output from C extensions that
# fprintf(stdout) or fprintf(stderr) ??
os.open('/var/log/xend-debug.log', os.O_WRONLY|os.O_CREAT)
os.dup(1)
else:
os.open('/dev/null', os.O_RDWR)
os.dup(0)
os.dup(1)
os.open('/var/log/xend-debug.log', os.O_WRONLY|os.O_CREAT)
def start(self, trace=0):
"""Attempts to start the daemons.
@@ -514,8 +517,8 @@ class Daemon:
self.install_child_reaper()
if self.fork_pid(XEND_PID_FILE):
#Parent
pass
#Parent. Sleep to give child time to start.
time.sleep(1)
else:
# Child
self.tracing(trace)
@@ -593,10 +596,10 @@ class Daemon:
def set_user(self):
# Set the UID.
try:
os.setuid(pwd.getpwnam(USER)[2])
os.setuid(pwd.getpwnam(XEND_USER)[2])
return 0
except KeyError, error:
print "Error: no such user '%s'" % USER
print "Error: no such user '%s'" % XEND_USER
return 1
def stop(self):
@@ -606,7 +609,7 @@ class Daemon:
xroot = XendRoot.instance()
log.info("Xend Daemon started")
self.createFactories()
self.listenEvent()
self.listenEvent(xroot)
self.listenNotifier()
self.listenVirq()
SrvServer.create(bridge=1)
@@ -619,9 +622,11 @@ class Daemon:
self.netifCF = netif.NetifControllerFactory()
self.consoleCF = console.ConsoleControllerFactory()
def listenEvent(self):
def listenEvent(self, xroot):
protocol = EventFactory(self)
return reactor.listenTCP(EVENT_PORT, protocol)
port = xroot.get_xend_event_port()
interface = xroot.get_xend_address()
return reactor.listenTCP(port, protocol, interface=interface)
def listenNotifier(self):
protocol = NotifierProtocol(self.channelF)
+1 -1
View File
@@ -88,7 +88,7 @@ class SrvDir(SrvBase):
req.write('</body></html>')
return ''
except Exception, ex:
self._perform_err(ex, req)
self._perform_err(ex, "GET", req)
def ls(self, req, use_sxp=0):
url = req.prePathURL()
-17
View File
@@ -29,13 +29,8 @@ class SrvDomain(SrvDir):
[['dom', 'int'],
['config', 'sxpr']])
deferred = fn(req.args, {'dom': self.dom.dom})
deferred.addErrback(self._op_configure_err, req)
return deferred
def _op_configure_err(self, err, req):
req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
return str(err)
def op_unpause(self, op, req):
val = self.xd.domain_unpause(self.dom.name)
return val
@@ -68,16 +63,11 @@ class SrvDomain(SrvDir):
['file', 'str']])
deferred = fn(req.args, {'dom': self.dom.id})
deferred.addCallback(self._op_save_cb, req)
deferred.addErrback(self._op_save_err, req)
return deferred
def _op_save_cb(self, val, req):
return 0
def _op_save_err(self, err, req):
req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
return str(err)
def op_migrate(self, op, req):
fn = FormFn(self.xd.domain_migrate,
[['dom', 'str'],
@@ -85,9 +75,7 @@ class SrvDomain(SrvDir):
['live', 'int'],
['resource', 'int']])
deferred = fn(req.args, {'dom': self.dom.id})
print 'op_migrate>', deferred
deferred.addCallback(self._op_migrate_cb, req)
deferred.addErrback(self._op_migrate_err, req)
return deferred
def _op_migrate_cb(self, info, req):
@@ -101,11 +89,6 @@ class SrvDomain(SrvDir):
print '_op_migrate_cb> url=', url
return url
def _op_migrate_err(self, err, req):
print '_op_migrate_err>', err, req
req.setResponseCode(http.BAD_REQUEST, "Error: "+ str(err))
return str(err)
def op_pincpu(self, op, req):
fn = FormFn(self.xd.domain_pincpu,
[['dom', 'str'],
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""Example xend HTTP and console server.
+7 -2
View File
@@ -66,8 +66,11 @@ def blkdev_name_to_number(name):
if re.match( '/dev/sd[a-p]([0-9]|1[0-5])', n):
return 8 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:])
if re.match( '/dev/hd[a-p]([0-9]|[1-5][0-9]|6[0-3])', n):
return 3 * 256 + 16 * (ord(n[7:8]) - ord('a')) + int(n[8:])
if re.match( '/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?', n):
ide_majors = [ 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 ]
major = ide_majors[(ord(n[7:8]) - ord('a')) / 2]
minor = ((ord(n[7:8]) - ord('a')) % 2) * 64 + int(n[8:] or 0)
return major * 256 + minor
# see if this is a hex device number
if re.match( '^(0x)?[0-9a-fA-F]+$', name ):
@@ -178,6 +181,8 @@ class BlkifBackendInterface(controller.BackendInterface):
self.close()
d = defer.Deferred()
d.addCallback(cb_destroy)
if self.evtchn:
channel.eventChannelClose(self.evtchn)
self.send_be_disconnect(response=d)
def send_be_disconnect(self, response=None):
+25 -1
View File
@@ -11,7 +11,31 @@ VIRQ_CONSOLE = 3 # (DOM0) bytes received on emergency console.
VIRQ_DOM_EXC = 4 # (DOM0) Exceptional event for some domain.
def eventChannel(dom1, dom2):
return xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
"""Create an event channel between domains.
The returned dict contains dom1, dom2, port1 and port2 on success.
@return dict (empty on error)
"""
evtchn = xc.evtchn_bind_interdomain(dom1=dom1, dom2=dom2)
if evtchn:
evtchn['dom1'] = dom1
evtchn['dom2'] = dom2
return evtchn
def eventChannelClose(evtchn):
"""Close an event channel that was opened by eventChannel().
"""
def evtchn_close(dom, port):
if (dom is None) or (port is None): return
try:
xc.evtchn_close(dom=dom, port=port)
except Exception, ex:
pass
if not evtchn: return
evtchn_close(evtchn.get('dom1'), evtchn.get('port1'))
evtchn_close(evtchn.get('dom2'), evtchn.get('port2'))
class ChannelFactory:
"""Factory for creating channels.
+5 -2
View File
@@ -11,6 +11,8 @@ from xen.xend.XendError import XendError
from xen.xend import EventServer
eserver = EventServer.instance()
from xen.xend.XendLogging import log
from xen.xend import XendRoot
xroot = XendRoot.instance()
import controller
from messages import *
@@ -82,7 +84,7 @@ class ConsoleControllerFactory(controller.ControllerFactory):
def createController(self, dom, console_port=None):
if console_port is None:
console_port = CONSOLE_PORT_BASE + dom
console_port = xroot.get_console_port_base() + dom
for c in self.getControllers():
if c.console_port == console_port:
raise XendError('console port in use: ' + str(console_port))
@@ -191,7 +193,8 @@ class ConsoleController(controller.Controller):
pass
else:
f = ConsoleFactory(self, self.idx)
self.listener = reactor.listenTCP(self.console_port, f)
interface = xroot.get_console_address()
self.listener = reactor.listenTCP(self.console_port, f, interface=interface)
def connect(self, addr, conn):
"""Connect a TCP connection to the console.
+24 -5
View File
@@ -130,7 +130,13 @@ class NetDev(controller.SplitDev):
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")
@@ -140,7 +146,8 @@ class NetDev(controller.SplitDev):
self.ipaddr = self._get_config_ipaddr(config) or []
try:
self.backendDomain = int(sxp.child_value(config, 'backend', '0'))
xd = get_component('xen.xend.XendDomain')
self.backendDomain = int(xd.domain_lookup(sxp.child_value(config, 'backend', '0')).id)
except:
raise XendError('invalid backend domain')
@@ -161,7 +168,8 @@ class NetDev(controller.SplitDev):
bridge = sxp.child_value(config, 'bridge')
script = sxp.child_value(config, 'script')
ipaddr = self._get_config_ipaddr(config)
backendDomain = sxp.child_value(config, 'backend', '0')
xd = get_component('xen.xend.XendDomain')
backendDomain = str(xd.domain_lookup(sxp.child_value(config, 'backend', '0')).id)
if (mac is not None) and (mac != self.mac):
raise XendError("cannot change mac")
if (backendDomain is not None) and (backendDomain != str(self.backendDomain)):
@@ -187,7 +195,9 @@ class NetDev(controller.SplitDev):
val = ['vif',
['idx', self.idx],
['vif', vif],
['mac', mac]]
['mac', mac],
['vifname', self.vifname],
]
if self.bridge:
val.append(['bridge', self.bridge])
if self.script:
@@ -205,8 +215,11 @@ class NetDev(controller.SplitDev):
def get_vifname(self):
"""Get the virtual interface device name.
"""
return "vif%d.%d" % (self.controller.dom, self.vif)
return self.vifname
def default_vifname(self):
return "vif%d.%d" % (self.controller.dom, self.vif)
def get_mac(self):
"""Get the MAC address as a string.
"""
@@ -238,6 +251,8 @@ class NetDev(controller.SplitDev):
@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:
@@ -265,7 +280,9 @@ class NetDev(controller.SplitDev):
msg = packMsg('netif_be_create_t',
{ 'domid' : self.controller.dom,
'netif_handle' : self.vif,
'mac' : self.mac })
'mac' : self.mac,
#'vifname' : self.vifname
})
self.getBackendInterface().writeRequest(msg, response=d)
return d
@@ -286,6 +303,8 @@ class NetDev(controller.SplitDev):
if change:
self.reportStatus()
log.debug("Destroying vif domain=%d vif=%d", self.controller.dom, self.vif)
if self.evtchn:
channel.eventChannelClose(self.evtchn)
self.vifctl('down')
d = self.send_be_disconnect()
d.addCallback(cb_destroy)
+1 -5
View File
@@ -3,9 +3,5 @@ XEND_PID_FILE = '/var/run/xend.pid'
XFRD_PID_FILE = '/var/run/xfrd.pid'
XEND_TRACE_FILE = '/var/log/xend.trace'
USER = 'root'
EVENT_PORT = 8001
CONSOLE_PORT_BASE = 9600
XEND_USER = 'root'
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python
# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
"""
Input-driven parsing for s-expression (sxp) format.
+70 -2
View File
@@ -5,6 +5,7 @@
import random
import string
import sys
import socket
from xen.xend import sxp
from xen.xend import PrettyPrint
@@ -81,6 +82,14 @@ gopts.opt('console_autoconnect', short='c',
fn=set_true, default=0,
use="Connect to the console after the domain is created.")
gopts.var('vnc', val='no|yes',
fn=set_bool, default=None,
use="""Spawn a vncviewer listening for a vnc server in the domain.
The address of the vncviewer is passed to the domain on the kernel command
line using 'VNC_SERVER=<host>:<port>'. The port used by vnc is 5500 + DISPLAY.
A display value with a free port is chosen if possible.
""")
gopts.var('name', val='NAME',
fn=set_value, default=None,
use="Domain name. Must be unique.")
@@ -151,7 +160,7 @@ gopts.var('ipaddr', val="IPADDR",
fn=append_value, default=[],
use="Add an IP address to the domain.")
gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM",
gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM,vifname=NAME",
fn=append_value, default=[],
use="""Add a network interface with the given MAC address and bridge.
The vif is configured by calling the given configuration script.
@@ -159,6 +168,8 @@ gopts.var('vif', val="mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM",
If bridge is not specified the default bridge is used.
If script is not specified the default script is used.
If backend is not specified the default backend driver domain is used.
If vifname is not specified the backend virtual interface will have name vifD.N
where D is the domain id and N is the interface id.
This option may be repeated to add more than one vif.
Specifying vifs will increase the number of interfaces as needed.""")
@@ -289,14 +300,18 @@ def configure_vifs(config_devs, vals):
script = d.get('script')
backend = d.get('backend')
ip = d.get('ip')
vifname = d.get('vifname')
else:
mac = randomMAC()
bridge = None
script = None
backend = None
ip = None
vifname = None
config_vif = ['vif']
config_vif.append(['mac', mac])
if vifname:
config_vif.append(['vifname', vifname])
if bridge:
config_vif.append(['bridge', bridge])
if script:
@@ -383,7 +398,7 @@ def preprocess_vifs(opts, vals):
(k, v) = b.strip().split('=', 1)
k = k.strip()
v = v.strip()
if k not in ['mac', 'bridge', 'script', 'backend', 'ip']:
if k not in ['mac', 'bridge', 'script', 'backend', 'ip', 'vifname']:
opts.err('Invalid vif specifier: ' + vif)
d[k] = v
vifs.append(d)
@@ -409,6 +424,58 @@ def preprocess_nfs(opts, vals):
opts.err('Must set nfs root and nfs server')
nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
vals.extra = nfs + ' ' + vals.extra
def get_host_addr():
host = socket.gethostname()
addr = socket.gethostbyname(host)
return addr
VNC_BASE_PORT = 5500
def choose_vnc_display():
"""Try to choose a free vnc display.
"""
def netstat_local_ports():
"""Run netstat to get a list of the local ports in use.
"""
l = os.popen("netstat -nat").readlines()
r = []
# Skip 2 lines of header.
for x in l[2:]:
# Local port is field 3.
y = x.split()[3]
# Field is addr:port, split off the port.
y = y.split(':')[1]
r.append(int(y))
return r
ports = netstat_local_ports()
for d in range(1, 100):
port = VNC_BASE_PORT + d
if port in ports: continue
return d
return None
def spawn_vnc(display):
os.system("vncviewer -listen %d &" % display)
return VNC_BASE_PORT + display
def preprocess_vnc(opts, vals):
"""If vnc was specified, spawn a vncviewer in listen mode
and pass its address to the domain on the kernel command line.
"""
if not vals.vnc: return
vnc_display = choose_vnc_display()
if not vnc_display:
opts.warn("No free vnc display")
return
print 'VNC=', vnc_display
vnc_port = spawn_vnc(vnc_display)
if vnc_port > 0:
vnc_host = get_host_addr()
vnc = 'VNC_VIEWER=%s:%d' % (vnc_host, vnc_port)
vals.extra = vnc + ' ' + vals.extra
def preprocess(opts, vals):
if not vals.kernel:
@@ -418,6 +485,7 @@ def preprocess(opts, vals):
preprocess_vifs(opts, vals)
preprocess_ip(opts, vals)
preprocess_nfs(opts, vals)
preprocess_vnc(opts, vals)
def make_domain(opts, config):
"""Create, build and start a domain.
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.