Merge latest xen-unstable into xen-ia64-unstable

This commit is contained in:
djm@kirby.fc.hp.com committed 2005-11-07 11:13:38 -06:00
commit c179fd9015
391 files changed
+48089 -2085

No files matched your search

+2 -1
View File
@@ -44,7 +44,8 @@ setup(name = 'xen',
'xen.web',
'xen.sv',
'xen.xend.tests'
'xen.xend.tests',
'xen.xm.tests'
],
ext_package = "xen.lowlevel",
ext_modules = [ xc, xs ]
+38 -4
View File
@@ -438,19 +438,20 @@ static PyObject *pyxc_vmx_build(PyObject *self,
char *image;
int control_evtchn, store_evtchn;
int vcpus = 1;
int lapic = 0;
int memsize;
unsigned long store_mfn = 0;
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
"memsize", "image", "vcpus", NULL };
"memsize", "image", "lapic", "vcpus", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisi", kwd_list,
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
&dom, &control_evtchn, &store_evtchn,
&memsize, &image, &vcpus) )
&memsize, &image, &lapic, &vcpus) )
return NULL;
if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn,
vcpus, store_evtchn, &store_mfn) != 0 )
lapic, vcpus, store_evtchn, &store_mfn) != 0 )
return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
@@ -857,6 +858,29 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
return zero;
}
static PyObject *pyxc_domain_ioport_permission(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
uint32_t dom;
int first_port, nr_ports, allow_access, ret;
static char *kwd_list[] = { "dom", "first_port", "nr_ports", "allow_access", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiii", kwd_list,
&dom, &first_port, &nr_ports, &allow_access) )
return NULL;
ret = xc_domain_ioport_permission(
xc->xc_handle, dom, first_port, nr_ports, allow_access);
if ( ret != 0 )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
return zero;
}
static PyMethodDef pyxc_methods[] = {
{ "handle",
(PyCFunction)pyxc_handle,
@@ -1126,6 +1150,16 @@ static PyMethodDef pyxc_methods[] = {
" mem_kb [long]: .\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_ioport_permission",
(PyCFunction)pyxc_domain_ioport_permission,
METH_VARARGS | METH_KEYWORDS, "\n"
"Allow a domain access to a range of IO ports\n"
" dom [int]: Identifier of domain to be allowed access.\n"
" first_port [int]: First IO port\n"
" nr_ports [int]: Number of IO ports\n"
" allow_access [int]: Non-zero means enable access; else disable access\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ NULL, NULL, 0, NULL }
};
+1 -1
View File
@@ -695,7 +695,7 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
PyObject *kwds)
{
static char *kwd_spec[] = { "dom", "page", "port", NULL };
static char *arg_spec = "iii";
static char *arg_spec = "ili";
domid_t dom = 0;
unsigned long page = 0;
unsigned int port = 0;
-3
View File
@@ -380,9 +380,6 @@ class SocketConnector:
self.state = "disconnected"
self.transport = None
def getDestination(self):
raise NotImplementedError()
def connectTransport(self):
raise NotImplementedError()
-6
View File
@@ -85,9 +85,6 @@ class TCPConnector(SocketConnector):
raise IOError("unknown service: " + ex)
return port
def getDestination(self):
return (self.host, self.port)
def connectTransport(self):
self.transport = TCPClientConnection(
self.host, self.port, self.bindAddress, self)
@@ -98,9 +95,6 @@ def listenTCP(port, factory, interface='', backlog=None):
l.startListening()
return l
def SetCloExec(SocketListener):
SocketListener.SetCloExec()
def connectTCP(host, port, factory, timeout=None, bindAddress=None):
c = TCPConnector(host, port, factory, timeout=timeout, bindAddress=bindAddress)
c.connect()
-3
View File
@@ -67,9 +67,6 @@ class UnixConnector(SocketConnector):
self.addr = path
self.timeout = timeout
def getDestination(self):
return self.addr
def connectTransport(self):
self.transport = UnixClientConnection(self.addr, self)
self.transport.connect(self.timeout)
+2 -1
View File
@@ -32,4 +32,5 @@ def network(op):
raise ValueError('Invalid operation: ' + op)
script = XendRoot.instance().get_network_script()
if script:
os.spawnl(os.P_WAIT, script, script, op)
script.insert(1, op)
os.spawnv(os.P_WAIT, script[0], script)
+32 -32
View File
@@ -7,9 +7,9 @@
import os
import re
import select
import string
import sxp
import threading
from struct import pack, unpack, calcsize
from xen.util.xpopen import xPopen3
@@ -81,6 +81,7 @@ def save(fd, dominfo, live):
log.info("Domain %d suspended.", dominfo.getDomid())
tochild.write("done\n")
tochild.flush()
log.debug('Written done')
forkHelper(cmd, fd, saveInputHandler, False)
@@ -176,43 +177,42 @@ def forkHelper(cmd, fd, inputHandler, closeToChild):
if closeToChild:
child.tochild.close()
lasterr = "error unknown"
thread = threading.Thread(target = slurp, args = (child.childerr,))
thread.start()
try:
fds = [child.fromchild.fileno(),
child.childerr.fileno()]
p = select.poll()
map(p.register, fds)
while len(fds) > 0:
r = p.poll()
for (fd, event) in r:
if event & select.POLLIN:
if fd == child.childerr.fileno():
lasterr = child.childerr.readline().rstrip()
log.error('%s', lasterr)
else:
l = child.fromchild.readline().rstrip()
while l:
log.debug('%s', l)
inputHandler(l, child.tochild)
try:
l = child.fromchild.readline().rstrip()
except:
l = None
try:
while 1:
line = child.fromchild.readline()
if line == "":
break
else:
line = line.rstrip()
log.debug('%s', line)
inputHandler(line, child.tochild)
if event & select.POLLERR:
raise XendError('Error reading from child process for %s',
cmd)
thread.join()
if event & select.POLLHUP:
fds.remove(fd)
p.unregister(fd)
except IOError, exn:
raise XendError('Error reading from child process for %s: %s' %
(cmd, exn))
finally:
child.fromchild.close()
child.childerr.close()
if not closeToChild:
child.tochild.close()
if child.wait() >> 8 == 127:
lasterr = "popen failed"
if child.wait() != 0:
raise XendError("%s failed: %s" % (string.join(cmd), lasterr))
status = child.wait()
if status >> 8 == 127:
raise XendError("%s failed: popen failed" % string.join(cmd))
elif status != 0:
raise XendError("%s failed" % string.join(cmd))
def slurp(file):
while 1:
line = file.readline()
if line == "":
break
else:
log.error('%s', line)
+34
View File
@@ -492,6 +492,40 @@ class XendDomain:
except Exception, ex:
raise XendError(str(ex))
def domain_ioport_range_enable(self, domid, first, last):
"""Enable access to a range of IO ports for a domain
@param first: first IO port
@param last: last IO port
@return: 0 on success, -1 on error
"""
dominfo = self.domain_lookup(domid)
nr_ports = last - first + 1
try:
return xc.domain_ioport_permission(dominfo.getDomid(),
first_port = first,
nr_ports = nr_ports,
allow_access = 1)
except Exception, ex:
raise XendError(str(ex))
def domain_ioport_range_disable(self, domid, first, last):
"""Disable access to a range of IO ports for a domain
@param first: first IO port
@param last: last IO port
@return: 0 on success, -1 on error
"""
dominfo = self.domain_lookup(domid)
nr_ports = last - first + 1
try:
return xc.domain_ioport_permission(dominfo.getDomid(),
first_port = first,
nr_ports = nr_ports,
allow_access = 0)
except Exception, ex:
raise XendError(str(ex))
def instance():
"""Singleton constructor. Use this instead of the class constructor.
+18 -8
View File
@@ -336,7 +336,7 @@ def dom_get(dom):
return domlist[0]
except Exception, err:
# ignore missing domain
log.debug("domain_getinfo(%d) failed, ignoring: %s", dom, str(err))
log.trace("domain_getinfo(%d) failed, ignoring: %s", dom, str(err))
return None
@@ -569,6 +569,8 @@ class XendDomainInfo:
self.storeDomDetails()
self.refreshShutdown()
log.debug("XendDomainInfo.completeRestore done")
def storeVmDetails(self):
to_store = {
@@ -595,6 +597,7 @@ class XendDomainInfo:
to_store = {
'domid': str(self.domid),
'vm': self.vmpath,
'name': self.info['name'],
'console/limit': str(xroot.get_console_limit() * 1024),
'memory/target': str(self.info['memory_KiB'])
}
@@ -1065,8 +1068,11 @@ class XendDomainInfo:
assert self.domid is not None
assert self.store_mfn is not None
assert self.store_port is not None
IntroduceDomain(self.domid, self.store_mfn, self.store_port)
try:
IntroduceDomain(self.domid, self.store_mfn, self.store_port)
except RuntimeError, exn:
raise XendError(str(exn))
def initDomain(self):
@@ -1274,7 +1280,6 @@ class XendDomainInfo:
now = time.time()
rst = self.readVm('xend/previous_restart_time')
log.error(rst)
if rst:
rst = float(rst)
timeout = now - rst
@@ -1283,8 +1288,8 @@ class XendDomainInfo:
'VM %s restarting too fast (%f seconds since the last '
'restart). Refusing to restart to avoid loops.',
self.info['name'], timeout)
self.destroy()
return
self.destroy()
return
self.writeVm('xend/previous_restart_time', str(now))
@@ -1305,7 +1310,11 @@ class XendDomainInfo:
except:
log.exception('Failed to restart domain %d.', self.domid)
finally:
self.removeVm('xend/restart_in_progress')
# new_dom's VM will be the same as this domain's VM, except where
# the rename flag has instructed us to call preserveForRestart.
# In that case, it is important that we use new_dom.removeVm, not
# self.removeVm.
new_dom.removeVm('xend/restart_in_progress')
# self.configure_bootloader()
# self.exportToDB()
@@ -1396,9 +1405,10 @@ def addControllerClass(device_class, cls):
controllerClasses[device_class] = cls
from xen.xend.server import blkif, netif, tpmif, pciif, usbif
from xen.xend.server import blkif, netif, tpmif, pciif, iopif, usbif
addControllerClass('vbd', blkif.BlkifController)
addControllerClass('vif', netif.NetifController)
addControllerClass('vtpm', tpmif.TPMifController)
addControllerClass('pci', pciif.PciController)
addControllerClass('ioports', iopif.IOPortsController)
addControllerClass('usb', usbif.UsbifController)
+12 -18
View File
@@ -17,7 +17,7 @@
#============================================================================
"""Xend root class.
Creates the event server and handles configuration.
Creates the servers and handles configuration.
Other classes get config variables by importing this module,
using instance() to get a XendRoot instance, and then
@@ -72,9 +72,6 @@ class XendRoot:
"""Default port xend serves HTTP at. """
xend_port_default = '8000'
"""Default port xend serves events at. """
xend_event_port_default = '8001'
"""Default port xend serves relocation at. """
xend_relocation_port_default = '8002'
@@ -114,7 +111,7 @@ class XendRoot:
"""
return self.components.get(name)
def _logError(self, fmt, args):
def _logError(self, fmt, *args):
"""Logging function to log to stderr. We use this for XendRoot log
messages because they may be logged before the logger has been
configured. Other components can safely use the logger.
@@ -144,7 +141,10 @@ class XendRoot:
config = sxp.parse(fin)
finally:
fin.close()
config.insert(0, 'xend-config')
if config is None:
config = ['xend-config']
else:
config.insert(0, 'xend-config')
self.config = config
except Exception, ex:
self._logError('Reading config file %s: %s',
@@ -207,21 +207,16 @@ class XendRoot:
"""
return self.get_config_int('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 self.get_config_int('xend-event-port', self.xend_event_port_default)
def get_xend_relocation_port(self):
"""Get the port xend listens at for connection to its relocation server.
"""
return self.get_config_int('xend-relocation-port', self.xend_relocation_port_default)
def get_xend_address(self):
"""Get the address xend listens at for its HTTP and event ports.
"""Get the address xend listens at for its HTTP port.
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.
to the HTTP port.
"""
return self.get_config_value('xend-address', self.xend_address_default)
@@ -229,7 +224,7 @@ class XendRoot:
"""Get the address xend listens at for its relocation server port.
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.
to the relocation port.
"""
return self.get_config_value('xend-relocation-address', self.xend_relocation_address_default)
@@ -250,7 +245,9 @@ class XendRoot:
s = self.get_config_value('network-script')
if s:
return os.path.join(self.network_script_dir, s)
result = s.split(" ")
result[0] = os.path.join(self.network_script_dir, result[0])
return result
else:
return None
@@ -258,9 +255,6 @@ class XendRoot:
def get_enable_dump(self):
return self.get_config_bool('enable-dump', 'no')
def get_vif_bridge(self):
return self.get_config_value('vif-bridge', 'xenbr0')
def get_vif_script(self):
return self.get_config_value('vif-script', 'vif-bridge')
+6
View File
@@ -203,6 +203,10 @@ class VmxImageHandler(ImageHandler):
self.dmargs += self.configVNC(imageConfig)
self.lapic = 0
lapic = sxp.child_value(imageConfig, 'lapic')
if not lapic is None:
self.lapic = int(lapic)
def buildDomain(self):
# Create an event channel
@@ -217,6 +221,7 @@ class VmxImageHandler(ImageHandler):
log.debug("control_evtchn = %d", self.device_channel)
log.debug("store_evtchn = %d", store_evtchn)
log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024)
log.debug("lapic = %d", self.lapic)
log.debug("vcpus = %d", self.vm.getVCpuCount())
return xc.vmx_build(dom = self.vm.getDomid(),
@@ -224,6 +229,7 @@ class VmxImageHandler(ImageHandler):
control_evtchn = self.device_channel,
store_evtchn = store_evtchn,
memsize = self.vm.getMemoryTarget() / 1024,
lapic = self.lapic,
vcpus = self.vm.getVCpuCount())
+55 -4
View File
@@ -16,12 +16,18 @@
# Copyright (C) 2005 XenSource Ltd
#============================================================================
from threading import Event
from xen.xend import sxp
from xen.xend.XendError import VmError
from xen.xend.XendLogging import log
from xen.xend.xenstore.xstransact import xstransact
from xen.xend.xenstore.xstransact import xstransact
from xen.xend.xenstore.xswatch import xswatch
DEVICE_CREATE_TIMEOUT = 120
HOTPLUG_STATUS_NODE = "hotplug-status"
HOTPLUG_STATUS_ERROR = "error"
class DevController:
"""Abstract base class for a device controller. Device controllers create
@@ -51,9 +57,23 @@ class DevController:
@return The ID for the newly created device.
"""
(devid, back, front) = self.getDeviceDetails(config)
if devid is None:
return 0
self.writeDetails(config, devid, back, front)
status, fn_ret = self.waitForBackend(devid)
if status:
self.destroyDevice(devid)
raise VmError( ("Device %s (%s) could not be connected. "
"Hotplug scripts not working")
% (devid, self.deviceClass))
elif fn_ret == HOTPLUG_STATUS_ERROR:
self.destroyDevice(devid)
raise VmError( ("Device %s (%s) could not be connected. "
"Backend device not found!")
% (devid, self.deviceClass))
return devid
@@ -69,11 +89,19 @@ class DevController:
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.
@param devid The device ID, or something device-specific from which
the device ID can be determined (such as a guest-side device name).
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. Further, the implementation here can only
accept integer device IDs, or values that can be converted to
integers. Subclasses may accept other values and convert them to
integers before passing them here.
"""
devid = int(devid)
frontpath = self.frontendPath(devid)
backpath = xstransact.Read(frontpath, "backend")
@@ -234,6 +262,29 @@ class DevController:
xstransact.Write(frontpath, frontDetails)
xstransact.Write(backpath, backDetails)
def waitForBackend(self,devid):
ev = Event()
def hotplugStatus():
status = self.readBackend(devid, HOTPLUG_STATUS_NODE)
if status is not None:
watch.xs.unwatch(backpath, watch)
hotplugStatus.value = status
ev.set()
hotplugStatus.value = None
frontpath = self.frontendPath(devid)
backpath = xstransact.Read(frontpath, "backend")
watch = xswatch(backpath, hotplugStatus)
ev.wait(DEVICE_CREATE_TIMEOUT)
if ev.isSet():
return (0, hotplugStatus.value)
else:
return (-1, hotplugStatus.value)
def backendPath(self, backdom, devid):
"""@param backdom [XendDomainInfo] The backend domain info."""
+1 -6
View File
@@ -19,7 +19,6 @@ import xen.lowlevel.xc
from xen.xend.server import SrvServer
from xen.xend.XendLogging import log
import event
import relocate
from params import *
@@ -262,10 +261,7 @@ class Daemon:
return 1
def stop(self):
result = self.cleanup_xend(True)
from xen.xend import Vifctl
Vifctl.network("stop")
return result
return self.cleanup_xend(True)
def run(self, status):
try:
@@ -276,7 +272,6 @@ class Daemon:
log.info("Xend changeset: %s.", xinfo['xen_changeset'])
del xc
event.listenEvent(self)
relocate.listenRelocation()
servers = SrvServer.create()
self.daemonize()
+4 -5
View File
@@ -25,7 +25,6 @@ from xen.xend import XendDomain
from xen.xend.XendDomainInfo import XendDomainInfo
from xen.xend.Args import FormFn
from xen.xend.XendError import XendError
from xen.xend.XendLogging import log
from xen.web.SrvDir import SrvDir
from SrvDomain import SrvDomain
@@ -52,7 +51,7 @@ class SrvDomainDir(SrvDir):
else:
return self.domain(x)
def op_create(self, op, req):
def op_create(self, _, req):
"""Create a domain.
Expects the domain config in request parameter 'config' in SXP format.
"""
@@ -66,12 +65,12 @@ class SrvDomainDir(SrvDir):
pin.input_eof()
config = pin.get_val()
ok = 1
except sxp.ParseError, ex:
errmsg = 'Invalid configuration ' + str(ex)
except Exception, ex:
print 'op_create> Exception in config', ex
traceback.print_exc()
errmsg = 'Configuration error ' + str(ex)
except sxp.ParseError, ex:
errmsg = 'Invalid configuration ' + str(ex)
if not ok:
raise XendError(errmsg)
try:
@@ -108,7 +107,7 @@ class SrvDomainDir(SrvDir):
"""
return req.threadRequest(self.do_restore, op, req)
def do_restore(self, op, req):
def do_restore(self, _, req):
fn = FormFn(self.xd.domain_restore,
[['file', 'str']])
dominfo = fn(req.args)
+1 -1
View File
@@ -43,7 +43,7 @@ class BlkifController(DevController):
dev = sxp.child_value(config, 'dev')
if re.match('^ioemu:', dev):
return (0,{},{})
return (None,{},{})
devid = blkif.blkdev_name_to_number(dev)
-195
View File
@@ -1,195 +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@hp.com>
# Copyright (C) 2005 XenSource Ltd
#============================================================================
import sys
import StringIO
from xen.web import protocol, tcp, unix
from xen.xend import scheduler
from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend.XendError import XendError
from xen.xend import XendLogging
from xen.xend import XendRoot
xroot = XendRoot.instance()
DEBUG = 0
class EventProtocol(protocol.Protocol):
"""Asynchronous handler for a connected event socket.
"""
def __init__(self, daemon):
#protocol.Protocol.__init__(self)
self.daemon = daemon
# Event queue.
self.queue = []
self.parser = sxp.Parser()
self.pretty = 1
def dataReceived(self, data):
try:
self.parser.input(data)
while(self.parser.ready()):
val = self.parser.get_val()
res = self.dispatch(val)
self.send_result(res)
if self.parser.at_eof():
self.loseConnection()
except SystemExit:
raise
except:
self.send_error()
def loseConnection(self):
if self.transport:
self.transport.loseConnection()
if self.connected:
scheduler.now(self.connectionLost)
def connectionLost(self, reason=None):
pass
def send_reply(self, sxpr):
io = StringIO.StringIO()
if self.pretty:
PrettyPrint.prettyprint(sxpr, out=io)
else:
sxp.show(sxpr, out=io)
print >> io
io.seek(0)
if self.transport:
return self.transport.write(io.getvalue())
else:
return 0
def send_result(self, res):
if res is None:
resp = ['ok']
else:
resp = ['ok', res]
return self.send_reply(resp)
def send_error(self):
(extype, exval) = sys.exc_info()[:2]
return self.send_reply(['err',
['type', str(extype)],
['value', str(exval)]])
def send_event(self, val):
return self.send_reply(['event', val[0], val[1]])
def queue_event(self, name, v):
# Despite the name we don't queue the event here.
# We send it because the transport will queue it.
self.send_event([name, v])
def opname(self, name):
return 'op_' + name.replace('.', '_')
def operror(self, name, req):
raise XendError('Invalid operation: ' +name)
def dispatch(self, req):
op_name = sxp.name(req)
op_method_name = self.opname(op_name)
op_method = getattr(self, op_method_name, self.operror)
return op_method(op_name, req)
def op_help(self, _1, _2):
def nameop(x):
if x.startswith('op_'):
return x[3:].replace('_', '.')
else:
return x
l = [ nameop(k) for k in dir(self) if k.startswith('op_') ]
return l
def op_quit(self, _1, _2):
self.loseConnection()
def op_exit(self, _1, _2):
sys.exit(0)
def op_pretty(self, _1, _2):
self.pretty = 1
def op_info(self, _1, _2):
val = ['info']
#val += self.daemon.blkifs()
#val += self.daemon.netifs()
#val += self.daemon.usbifs()
return val
def op_trace(self, _, v):
mode = (v[1] == 'on')
self.daemon.tracing(mode)
def op_log_stderr(self, _, v):
mode = v[1]
if mode == 'on':
XendLogging.addLogStderr()
else:
XendLogging.removeLogStderr()
def op_domain_ls(self, _1, _2):
xd = xroot.get_component("xen.xend.XendDomain")
return xd.list_names()
def op_domain_configure(self, _, v):
domid = sxp.child_value(v, "dom")
config = sxp.child_value(v, "config")
if domid is None:
raise XendError("missing domain id")
if config is None:
raise XendError("missing domain config")
xd = xroot.get_component("xen.xend.XendDomain")
xd.domain_configure(domid, config)
def op_domain_unpause(self, _, v):
domid = sxp.child_value(v, "dom")
if domid is None:
raise XendError("missing domain id")
xd = xroot.get_component("xen.xend.XendDomain")
xd.domain_unpause(domid)
class EventFactory(protocol.ServerFactory):
"""Asynchronous handler for the event server socket.
"""
def __init__(self, daemon):
protocol.ServerFactory.__init__(self)
self.daemon = daemon
def buildProtocol(self, _):
return EventProtocol(self.daemon)
def listenEvent(daemon):
factory = EventFactory(daemon)
if xroot.get_xend_unix_server():
path = '/var/lib/xend/event-socket'
unix.listenUNIX(path, factory)
if xroot.get_xend_http_server():
port = xroot.get_xend_event_port()
interface = xroot.get_xend_address()
tcp.listenTCP(port, factory, interface=interface)
+86
View File
@@ -0,0 +1,86 @@
#============================================================================
# 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@hp.com>
# Copyright (C) 2005 XenSource Ltd
# Copyright (C) 2005 Jody Belka
#============================================================================
import types
import xen.lowlevel.xc;
from xen.xend import sxp
from xen.xend.XendError import VmError
from xen.xend.server.DevController import DevController
xc = xen.lowlevel.xc.new()
def parse_ioport(val):
"""Parse an i/o port field.
"""
if isinstance(val, types.StringType):
radix = 10
if val.startswith('0x') or val.startswith('0X'):
radix = 16
v = int(val, radix)
else:
v = val
return v
class IOPortsController(DevController):
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('ioports: Missing %s config setting' % field)
return parse_ioport(val)
except:
raise VmError('ioports: Invalid config setting %s: %s' %
(field, val))
io_from = get_param('from')
io_to = get_param('to')
if io_to < io_from or io_to >= 65536:
raise VmError('ioports: Invalid i/o range: %s - %s' %
(io_from, io_to))
rc = xc.domain_ioport_permission(dom = self.getDomid(),
first_port = io_from,
nr_ports = io_to - io_from + 1,
allow_access = True)
if rc < 0:
#todo non-fatal
raise VmError(
'ioports: Failed to configure legacy i/o range: %s - %s' %
(io_from, io_to))
return (dev, {}, {})
+29 -6
View File
@@ -21,6 +21,7 @@
"""
import os
import random
from xen.xend import sxp
from xen.xend import XendRoot
@@ -31,6 +32,25 @@ from xen.xend.server.DevController import DevController
xroot = XendRoot.instance()
def randomMAC():
"""Generate a random MAC address.
Uses OUI (Organizationally Unique Identifier) AA:00:00, an
unassigned one that used to belong to DEC. The OUI list is
available at 'standards.ieee.org'.
The remaining 3 fields are random, with the first bit of the first
random field set 0.
@return: MAC address string
"""
mac = [ 0xaa, 0x00, 0x00,
random.randint(0x00, 0x7f),
random.randint(0x00, 0xff),
random.randint(0x00, 0xff) ]
return ':'.join(map(lambda x: "%02x" % x, mac))
class NetifController(DevController):
"""Network interface controller. Handles all network devices for a domain.
"""
@@ -51,22 +71,25 @@ class NetifController(DevController):
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')
bridge = sxp.child_value(config, 'bridge')
mac = sxp.child_value(config, 'mac')
ipaddr = _get_config_ipaddr(config)
devid = self.allocateDeviceID()
if not mac:
mac = randomMAC()
back = { 'script' : script,
'mac' : mac,
'bridge' : bridge,
'mac' : mac,
'handle' : "%i" % devid }
if ipaddr:
back['ip'] = ' '.join(ipaddr)
if bridge:
back['bridge'] = bridge
front = { 'handle' : "%i" % devid,
'mac' : mac }
'mac' : mac }
return (devid, back, front)
+1
View File
@@ -0,0 +1 @@
+2 -3
View File
@@ -5,15 +5,14 @@
# Public License. See the file "COPYING" in the main directory of
# this archive for more details.
import errno
import threading
from xen.lowlevel import xs
from xen.xend.xenstore.xsutil import xshandle
class xstransact:
def __init__(self, path):
assert path is not None
self.in_transaction = False # Set this temporarily -- if this
# constructor fails, then we need to
# protect __del__.
+139 -104
View File
@@ -19,7 +19,6 @@
"""Domain creation.
"""
import random
import os
import os.path
import string
@@ -34,7 +33,6 @@ from xen.xend import sxp
from xen.xend import PrettyPrint
from xen.xend.XendClient import server, XendError
from xen.xend.XendBootloader import bootloader
from xen.xend import XendRoot; xroot = XendRoot.instance()
from xen.util import blkif
from xen.xm.opts import *
@@ -158,6 +156,10 @@ gopts.var('cpu', val='CPU',
fn=set_int, default=None,
use="CPU to run the domain on.")
gopts.var('lapic', val='LAPIC',
fn=set_int, default=0,
use="Disable or enable local APIC of VMX domain.")
gopts.var('vcpus', val='VCPUS',
fn=set_int, default=1,
use="# of Virtual CPUS in domain.")
@@ -238,6 +240,12 @@ gopts.var('pci', val='BUS,DEV,FUNC',
For example '-pci c0,02,1a'.
The option may be repeated to add more than one pci device.""")
gopts.var('ioports', val='FROM[-TO]',
fn=append_value, default=[],
use="""Add a legacy I/O range to a domain, using given params (in hex).
For example '-ioports 02f8-02ff'.
The option may be repeated to add more than one i/o range.""")
gopts.var('usb', val='PATH',
fn=append_value, default=[],
use="""Add a physical USB port to a domain, as specified by the path
@@ -254,7 +262,7 @@ gopts.var('vif', val="mac=MAC,be_mac=MAC,bridge=BRIDGE,script=SCRIPT,backend=DOM
If mac is not specified a random MAC address is used.
The MAC address of the backend interface can be selected with be_mac.
If not specified then the network backend chooses it's own MAC address.
If bridge is not specified the default bridge is used.
If bridge is not specified the first bridge found 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
@@ -316,10 +324,6 @@ gopts.var('nfs_root', val="PATH",
fn=set_value, default=None,
use="Set the path of the root NFS directory.")
gopts.var('memmap', val='FILE',
fn=set_value, default='',
use="Path to memap SXP file.")
gopts.var('device_model', val='FILE',
fn=set_value, default='',
use="Path to device model program.")
@@ -377,9 +381,23 @@ gopts.var('sdl', val='',
use="""Should the device model use SDL?""")
gopts.var('display', val='DISPLAY',
fn=set_value, default='localhost:0',
fn=set_value, default=None,
use="X11 display to use")
def err(msg):
"""Print an error to stderr and exit.
"""
print >>sys.stderr, "Error:", msg
sys.exit(1)
def warn(msg):
"""Print a warning to stdout.
"""
print >>sys.stderr, "Warning:", msg
def strip(pre, s):
"""Strip prefix 'pre' if present.
"""
@@ -388,7 +406,7 @@ def strip(pre, s):
else:
return s
def configure_image(opts, vals):
def configure_image(vals):
"""Create the image config.
"""
config_image = [ vals.builder ]
@@ -407,7 +425,7 @@ def configure_image(opts, vals):
config_image.append(['vcpus', vals.vcpus])
return config_image
def configure_disks(opts, config_devs, vals):
def configure_disks(config_devs, vals):
"""Create the config for disks (virtual block devices).
"""
for (uname, dev, mode, backend) in vals.disk:
@@ -419,19 +437,26 @@ def configure_disks(opts, config_devs, vals):
config_vbd.append(['backend', backend])
config_devs.append(['device', config_vbd])
def configure_pci(opts, config_devs, vals):
def configure_pci(config_devs, vals):
"""Create the config for pci devices.
"""
for (bus, dev, func) in vals.pci:
config_pci = ['pci', ['bus', bus], ['dev', dev], ['func', func]]
config_devs.append(['device', config_pci])
def configure_usb(opts, config_devs, vals):
def configure_ioports(config_devs, vals):
"""Create the config for legacy i/o ranges.
"""
for (io_from, io_to) in vals.ioports:
config_ioports = ['ioports', ['from', io_from], ['to', io_to]]
config_devs.append(['device', config_ioports])
def configure_usb(config_devs, vals):
for path in vals.usb:
config_usb = ['usb', ['path', path]]
config_devs.append(['device', config_usb])
def configure_vtpm(opts, config_devs, vals):
def configure_vtpm(config_devs, vals):
"""Create the config for virtual TPM interfaces.
"""
vtpm = vals.vtpm
@@ -445,9 +470,9 @@ def configure_vtpm(opts, config_devs, vals):
else:
try:
if int(instance) == 0:
opts.err('VM config error: vTPM instance must not be 0.')
err('VM config error: vTPM instance must not be 0.')
except ValueError:
opts.err('Vm config error: could not parse instance number.')
err('Vm config error: could not parse instance number.')
backend = d.get('backend')
config_vtpm = ['vtpm']
if instance:
@@ -456,7 +481,7 @@ def configure_vtpm(opts, config_devs, vals):
config_vtpm.append(['backend', backend])
config_devs.append(['device', config_vtpm])
def configure_tpmif(opts, config_devs, vals):
def configure_tpmif(config_devs, vals):
"""Create the config for virtual TPM interfaces.
"""
tpmif = vals.tpmif
@@ -471,25 +496,7 @@ def configure_tpmif(opts, config_devs, vals):
config_devs.append(['device', config_tpmif])
def randomMAC():
"""Generate a random MAC address.
Uses OUI (Organizationally Unique Identifier) AA:00:00, an
unassigned one that used to belong to DEC. The OUI list is
available at 'standards.ieee.org'.
The remaining 3 fields are random, with the first bit of the first
random field set 0.
@return: MAC address string
"""
mac = [ 0xaa, 0x00, 0x00,
random.randint(0x00, 0x7f),
random.randint(0x00, 0xff),
random.randint(0x00, 0xff) ]
return ':'.join(map(lambda x: "%02x" % x, mac))
def configure_vifs(opts, config_devs, vals):
def configure_vifs(config_devs, vals):
"""Create the config for virtual network interfaces.
"""
vifs = vals.vif
@@ -499,8 +506,6 @@ def configure_vifs(opts, config_devs, vals):
if idx < len(vifs):
d = vifs[idx]
mac = d.get('mac')
if not mac:
mac = randomMAC()
be_mac = d.get('be_mac')
bridge = d.get('bridge')
script = d.get('script')
@@ -508,7 +513,7 @@ def configure_vifs(opts, config_devs, vals):
ip = d.get('ip')
vifname = d.get('vifname')
else:
mac = randomMAC()
mac = None
be_mac = None
bridge = None
script = None
@@ -516,7 +521,8 @@ def configure_vifs(opts, config_devs, vals):
ip = None
vifname = None
config_vif = ['vif']
config_vif.append(['mac', mac])
if mac:
config_vif.append(['mac', mac])
if vifname:
config_vif.append(['vifname', vifname])
if be_mac:
@@ -531,7 +537,7 @@ def configure_vifs(opts, config_devs, vals):
config_vif.append(['ip', ip])
config_devs.append(['device', config_vif])
def configure_vfr(opts, config, vals):
def configure_vfr(config, vals):
if not vals.ipaddr: return
config_vfr = ['vfr']
idx = 0 # No way of saying which IP is for which vif?
@@ -539,37 +545,42 @@ def configure_vfr(opts, config, vals):
config_vfr.append(['vif', ['id', idx], ['ip', ip]])
config.append(config_vfr)
def configure_vmx(opts, config_image, vals):
def configure_vmx(config_image, vals):
"""Create the config for VMX devices.
"""
args = [ 'memmap', 'device_model', 'vcpus', 'cdrom',
'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga',
'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000']
args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
'localtime', 'serial', 'macaddr', 'stdvga', 'isa', 'nographic',
'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
for a in args:
if (vals.__dict__[a]):
config_image.append([a, vals.__dict__[a]])
def run_bootloader(opts, vals):
def run_bootloader(vals):
if not os.access(vals.bootloader, os.X_OK):
opts.err("Bootloader isn't executable")
err("Bootloader isn't executable")
if len(vals.disk) < 1:
opts.err("No disks configured and boot loader requested")
err("No disks configured and boot loader requested")
(uname, dev, mode, backend) = vals.disk[0]
file = blkif.blkdev_uname_to_file(uname)
return bootloader(vals.bootloader, file, not vals.console_autoconnect,
vals.vcpus, vals.blentry)
def make_config(opts, vals):
def make_config(vals):
"""Create the domain configuration.
"""
config = ['vm',
['name', vals.name ],
['memory', vals.memory ],
['ssidref', vals.ssidref ]]
if vals.maxmem:
config.append(['maxmem', vals.maxmem])
config = ['vm']
def add_conf(n):
if hasattr(vals, n):
v = getattr(vals, n)
if v:
config.append([n, v])
map(add_conf, ['name', 'memory', 'ssidref', 'maxmem', 'restart',
'on_poweroff', 'on_reboot', 'on_crash'])
if vals.cpu is not None:
config.append(['cpu', vals.cpu])
if vals.cpu_weight is not None:
@@ -580,34 +591,27 @@ def make_config(opts, vals):
config.append(['backend', ['netif']])
if vals.tpmif:
config.append(['backend', ['tpmif']])
if vals.restart:
config.append(['restart', vals.restart])
if vals.on_poweroff:
config.append(['on_poweroff', vals.on_poweroff])
if vals.on_reboot:
config.append(['on_reboot', vals.on_reboot])
if vals.on_crash:
config.append(['on_crash', vals.on_crash])
if vals.bootloader:
config.append(['bootloader', vals.bootloader])
config_image = run_bootloader(opts, vals)
config_image = run_bootloader(vals)
else:
config_image = configure_image(opts, vals)
configure_vmx(opts, config_image, vals)
config.append(['image', config_image ])
config_image = configure_image(vals)
configure_vmx(config_image, vals)
config.append(['image', config_image])
config_devs = []
configure_disks(opts, config_devs, vals)
configure_pci(opts, config_devs, vals)
configure_vifs(opts, config_devs, vals)
configure_usb(opts, config_devs, vals)
configure_vtpm(opts, config_devs, vals)
configure_disks(config_devs, vals)
configure_pci(config_devs, vals)
configure_ioports(config_devs, vals)
configure_vifs(config_devs, vals)
configure_usb(config_devs, vals)
configure_vtpm(config_devs, vals)
config += config_devs
return config
def preprocess_disk(opts, vals):
def preprocess_disk(vals):
if not vals.disk: return
disk = []
for v in vals.disk:
@@ -618,23 +622,37 @@ def preprocess_disk(opts, vals):
elif n == 4:
pass
else:
opts.err('Invalid disk specifier: ' + v)
err('Invalid disk specifier: ' + v)
disk.append(d)
vals.disk = disk
def preprocess_pci(opts, vals):
def preprocess_pci(vals):
if not vals.pci: return
pci = []
for v in vals.pci:
d = v.split(',')
if len(d) != 3:
opts.err('Invalid pci specifier: ' + v)
err('Invalid pci specifier: ' + v)
# Components are in hex: add hex specifier.
hexd = map(lambda v: '0x'+v, d)
pci.append(hexd)
vals.pci = pci
def preprocess_vifs(opts, vals):
def preprocess_ioports(vals):
if not vals.ioports: return
ioports = []
for v in vals.ioports:
d = v.split('-')
if len(d) < 1 or len(d) > 2:
err('Invalid i/o port range specifier: ' + v)
if len(d) == 1:
d.append(d[0])
# Components are in hex: add hex specifier.
hexd = map(lambda v: '0x'+v, d)
ioports.append(hexd)
vals.ioports = ioports
def preprocess_vifs(vals):
if not vals.vif: return
vifs = []
for vif in vals.vif:
@@ -645,12 +663,12 @@ def preprocess_vifs(opts, vals):
k = k.strip()
v = v.strip()
if k not in ['mac', 'be_mac', 'bridge', 'script', 'backend', 'ip', 'vifname']:
opts.err('Invalid vif specifier: ' + vif)
err('Invalid vif specifier: ' + vif)
d[k] = v
vifs.append(d)
vals.vif = vifs
def preprocess_vtpm(opts, vals):
def preprocess_vtpm(vals):
if not vals.vtpm: return
vtpms = []
for vtpm in vals.vtpm:
@@ -661,12 +679,12 @@ def preprocess_vtpm(opts, vals):
k = k.strip()
v = v.strip()
if k not in ['backend', 'instance']:
opts.err('Invalid vtpm specifier: ' + vtpm)
err('Invalid vtpm specifier: ' + vtpm)
d[k] = v
vtpms.append(d)
vals.vtpm = vtpms
def preprocess_tpmif(opts, vals):
def preprocess_tpmif(vals):
if not vals.tpmif: return
tpmifs = []
for tpmif in vals.tpmif:
@@ -677,12 +695,12 @@ def preprocess_tpmif(opts, vals):
k = k.strip()
v = v.strip()
if k not in ['frontend']:
opts.err('Invalid tpmif specifier: ' + vtpm)
err('Invalid tpmif specifier: ' + vtpm)
d[k] = v
tpmifs.append(d)
vals.tpmif = tpmifs
def preprocess_ip(opts, vals):
def preprocess_ip(vals):
if vals.ip or vals.dhcp != 'off':
dummy_nfs_server = '1.2.3.4'
ip = (vals.ip
@@ -696,10 +714,10 @@ def preprocess_ip(opts, vals):
ip = ''
vals.cmdline_ip = ip
def preprocess_nfs(opts, vals):
def preprocess_nfs(vals):
if not vals.nfs_root: return
if not vals.nfs_server:
opts.err('Must set nfs root and nfs server')
err('Must set nfs root and nfs server')
nfs = 'nfsroot=' + vals.nfs_server + ':' + vals.nfs_root
vals.extra = nfs + ' ' + vals.extra
@@ -745,14 +763,14 @@ def spawn_vnc(display):
return VNC_BASE_PORT + display
def preprocess_vnc(opts, vals):
def preprocess_vnc(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 and vals.vncviewer) or vals.dryrun: return
vnc_display = choose_vnc_display()
if not vnc_display:
opts.warn("No free vnc display")
warn("No free vnc display")
return
print 'VNC=', vnc_display
vnc_port = spawn_vnc(vnc_display)
@@ -761,17 +779,18 @@ def preprocess_vnc(opts, vals):
vnc = 'VNC_VIEWER=%s:%d' % (vnc_host, vnc_port)
vals.extra = vnc + ' ' + vals.extra
def preprocess(opts, vals):
def preprocess(vals):
if not vals.kernel:
opts.err("No kernel specified")
preprocess_disk(opts, vals)
preprocess_pci(opts, vals)
preprocess_vifs(opts, vals)
preprocess_ip(opts, vals)
preprocess_nfs(opts, vals)
preprocess_vnc(opts, vals)
preprocess_vtpm(opts, vals)
preprocess_tpmif(opts, vals)
err("No kernel specified")
preprocess_disk(vals)
preprocess_pci(vals)
preprocess_ioports(vals)
preprocess_vifs(vals)
preprocess_ip(vals)
preprocess_nfs(vals)
preprocess_vnc(vals)
preprocess_vtpm(vals)
preprocess_tpmif(vals)
def make_domain(opts, config):
"""Create, build and start a domain.
@@ -792,14 +811,14 @@ def make_domain(opts, config):
import signal
if vncpid:
os.kill(vncpid, signal.SIGKILL)
opts.err(str(ex))
err(str(ex))
dom = sxp.child_value(dominfo, 'name')
if not opts.vals.paused:
if server.xend_domain_unpause(dom) < 0:
server.xend_domain_destroy(dom)
opts.err("Failed to unpause domain %s" % dom)
err("Failed to unpause domain %s" % dom)
opts.info("Started domain %s" % (dom))
return int(sxp.child_value(dominfo, 'domid'))
@@ -853,8 +872,8 @@ def balloon_out(dom0_min_mem, opts):
del xc
return ret
def main(argv):
random.seed()
def parseCommandLine(argv):
opts = gopts
args = opts.parse(argv)
if opts.vals.help:
@@ -862,25 +881,41 @@ def main(argv):
if opts.vals.help or opts.vals.help_config:
opts.load_defconfig(help=1)
if opts.vals.help or opts.vals.help_config:
return
return (None, None)
if not opts.vals.display:
opts.vals.display = os.getenv("DISPLAY")
# Process remaining args as config variables.
for arg in args:
if '=' in arg:
(var, val) = arg.strip().split('=', 1)
gopts.setvar(var.strip(), val.strip())
opts.vals.display = os.getenv("DISPLAY")
if opts.vals.config:
config = opts.vals.config
else:
opts.load_defconfig()
preprocess(opts, opts.vals)
preprocess(opts.vals)
if not opts.getopt('name') and opts.getopt('defconfig'):
opts.setopt('name', os.path.basename(opts.getopt('defconfig')))
config = make_config(opts, opts.vals)
config = make_config(opts.vals)
return (opts, config)
def main(argv):
(opts, config) = parseCommandLine(argv)
if not opts:
return
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
else:
from xen.xend import XendRoot
xroot = XendRoot.instance()
dom0_min_mem = xroot.get_dom0_min_mem()
if dom0_min_mem != 0:
if balloon_out(dom0_min_mem, opts):
+54 -4
View File
@@ -61,6 +61,8 @@ xm common subcommands:
top monitor system and domains in real-time
unpause <DomId> unpause a paused domain
<DomName> can be substituted for <DomId> in xm subcommands.
For a complete list of subcommands run 'xm help --long'
For more help on xm see the xm(1) man page
For more help on xm create, see the xmdomain.cfg(5) man page"""
@@ -110,6 +112,12 @@ xm full list of subcommands:
where <DevId> may either be the device ID
or the device name as mounted in the guest.
block-list <DomId> List virtual block devices for a domain
network-attach <DomID> [script=<script>] [ip=<ip>] [mac=<mac>]
[bridge=<bridge>] [backend=<backDomID>]
Create a new virtual network device
network-detach <DomId> <DevId> Destroy a domain's virtual network
device, where <DevId> is the device ID.
network-limit <DomId> <Vif> <Credit> <Period>
Limit the transmission rate of a virtual network interface
network-list <DomId> List virtual network interfaces for a domain
@@ -119,6 +127,8 @@ xm full list of subcommands:
vnet-create <config> create a vnet from a config file
vnet-delete <vnetid> delete a vnet
<DomName> can be substituted for <DomId> in xm subcommands.
For a short list of subcommands run 'xm help'
For more help on xm see the xm(1) man page
For more help on xm create, see the xmdomain.cfg(5) man page"""
@@ -450,10 +460,14 @@ def xm_mem_set(args):
server.xend_domain_mem_target_set(dom, mem_target)
def xm_set_vcpus(args):
arg_check(args, 2, "set-vcpus")
from xen.xend.XendClient import server
server.xend_domain_set_vcpus(args[0], int(args[1]))
def xm_domid(args):
arg_check(args, 1, "domid")
name = args[0]
from xen.xend.XendClient import server
@@ -461,6 +475,8 @@ def xm_domid(args):
print sxp.child_value(dom, 'domid')
def xm_domname(args):
arg_check(args, 1, "domname")
name = args[0]
from xen.xend.XendClient import server
@@ -584,14 +600,39 @@ def xm_block_attach(args):
from xen.xend.XendClient import server
server.xend_domain_device_create(dom, vbd)
def xm_block_detach(args):
arg_check(args,2,"block-detach")
def xm_network_attach(args):
n = len(args)
if n == 0:
usage("network-attach")
dom = args[0]
vif = ['vif']
for a in args[1:]:
vif.append(a.split("="))
from xen.xend.XendClient import server
server.xend_domain_device_create(dom, vif)
def detach(args, command, deviceClass):
arg_check(args, 2, command)
dom = args[0]
dev = args[1]
from xen.xend.XendClient import server
server.xend_domain_device_destroy(dom, 'vbd', dev)
server.xend_domain_device_destroy(dom, deviceClass, dev)
def xm_block_detach(args):
detach(args, 'block-detach', 'vbd')
def xm_network_detach(args):
detach(args, 'network-detach', 'vif')
def xm_vnet_list(args):
from xen.xend.XendClient import server
@@ -625,6 +666,10 @@ def xm_vnet_list(args):
def xm_vnet_create(args):
arg_check(args, 1, "vnet-create")
conf = args[0]
if not os.access(conf, os.R_OK):
print "File not found: %s" % conf
sys.exit(1)
from xen.xend.XendClient import server
server.xend_vnet_create(conf)
@@ -669,6 +714,8 @@ commands = {
"block-detach": xm_block_detach,
"block-list": xm_block_list,
# network
"network-attach": xm_network_attach,
"network-detach": xm_network_detach,
"network-limit": xm_network_limit,
"network-list": xm_network_list,
# vnet
@@ -754,7 +801,10 @@ def main(argv=sys.argv):
else:
err("Error connecting to xend: %s. Is xend running?" % ex[1])
sys.exit(1)
except IOError:
except KeyboardInterrupt:
print "Interrupted."
sys.exit(1)
except IOError, ex:
if os.geteuid() != 0:
err("Most commands need root access. Please try again as root.")
else:
+96
View File
@@ -0,0 +1,96 @@
import os
import os.path
import tempfile
import unittest
import xen.xend.XendRoot
xen.xend.XendRoot.XendRoot.config_default = '/dev/null'
import xen.xm.create
class test_create(unittest.TestCase):
def assertEqualModuloNulls_(self, a, b):
for k, v in a.iteritems():
if v:
self.failUnless(k in b, '%s not in b' % k)
self.assertEqual(v, b[k])
else:
self.assert_(k not in b or not b[k], '%s in b' % k)
def assertEqualModuloNulls(self, a, b):
self.assertEqualModuloNulls_(a, b)
self.assertEqualModuloNulls_(b, a)
def t(self, args, expected):
self.assertEqualModuloNulls(
xen.xm.create.parseCommandLine(args.split(' '))[0].vals.__dict__,
expected)
def testCommandLine(self):
(fd, fname) = tempfile.mkstemp()
try:
self.t('-f %s kernel=/mykernel display=fakedisplay '
'macaddr=ab:cd:ef:ed nics=0' % fname,
{ 'name' : os.path.basename(fname),
'xm_file' : fname,
'defconfig' : fname,
'kernel' : '/mykernel',
'display' : 'fakedisplay',
'macaddr' : 'ab:cd:ef:ed',
'memory' : 128,
'vcpus' : 1,
'boot' : 'c',
'dhcp' : 'off',
'interface' : 'eth0',
'path' : '.:/etc/xen',
'builder' : 'linux',
})
finally:
os.close(fd)
def testConfigFileAndCommandLine(self):
(fd, fname) = tempfile.mkstemp()
os.write(fd,
'''
name = "testname"
memory = 256
ssidref = 1
kernel = "/mykernel"
maxmem = 1024
cpu = 2
cpu_weight = 0.75
''')
try:
self.t('-f %s display=fakedisplay macaddr=ab:cd:ef:ed nics=0' %
fname,
{ 'name' : 'testname',
'xm_file' : fname,
'defconfig' : fname,
'kernel' : '/mykernel',
'display' : 'fakedisplay',
'macaddr' : 'ab:cd:ef:ed',
'memory' : 256,
'maxmem' : 1024,
'cpu' : 2,
'ssidref' : 1,
'cpu_weight' : 0.75,
'vcpus' : 1,
'boot' : 'c',
'dhcp' : 'off',
'interface' : 'eth0',
'path' : '.:/etc/xen',
'builder' : 'linux',
})
finally:
os.close(fd)
def test_suite():
return unittest.makeSuite(test_create)
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.