mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Merge with xen-ia64-unstable.hg
This commit is contained in:
commit
0511df5aec
70 files changed
+3366
-347
No files matched your search
+12
-1
@@ -30,6 +30,13 @@ xs = Extension("xs",
|
||||
libraries = libraries,
|
||||
sources = [ "xen/lowlevel/xs/xs.c" ])
|
||||
|
||||
scf = Extension("scf",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = include_dirs + [ "xen/lowlevel/scf" ],
|
||||
library_dirs = library_dirs,
|
||||
libraries = libraries,
|
||||
sources = [ "xen/lowlevel/scf/scf.c" ])
|
||||
|
||||
acm = Extension("acm",
|
||||
extra_compile_args = extra_compile_args,
|
||||
include_dirs = include_dirs + [ "xen/lowlevel/acm" ],
|
||||
@@ -37,6 +44,10 @@ acm = Extension("acm",
|
||||
libraries = libraries,
|
||||
sources = [ "xen/lowlevel/acm/acm.c" ])
|
||||
|
||||
modules = [ xc, xs, acm ]
|
||||
if os.uname()[0] == 'SunOS':
|
||||
modules.append(scf)
|
||||
|
||||
setup(name = 'xen',
|
||||
version = '3.0',
|
||||
description = 'Xen',
|
||||
@@ -56,7 +67,7 @@ setup(name = 'xen',
|
||||
'xen.xm.tests'
|
||||
],
|
||||
ext_package = "xen.lowlevel",
|
||||
ext_modules = [ xc, xs, acm ]
|
||||
ext_modules = modules
|
||||
)
|
||||
|
||||
os.chdir('logging')
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include <libscf.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define XEND_FMRI "svc:/system/xen/xend:default"
|
||||
#define XEND_PG "config"
|
||||
|
||||
static PyObject *scf_exc;
|
||||
|
||||
static void *
|
||||
scf_exception(const char *err, const char *value)
|
||||
{
|
||||
int scferr = scf_error();
|
||||
const char *scfstrerr = scf_strerror(scferr);
|
||||
PyObject *obj = Py_BuildValue("(isss)", scferr, err, scfstrerr, value);
|
||||
PyErr_SetObject(scf_exc, obj);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyscf_get_bool(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", NULL };
|
||||
scf_simple_prop_t *prop;
|
||||
uint8_t *val;
|
||||
char *name;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
|
||||
return (NULL);
|
||||
|
||||
prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
|
||||
|
||||
if (prop == NULL)
|
||||
return (scf_exception("scf_simple_prop_get() failed", name));
|
||||
|
||||
if ((val = scf_simple_prop_next_boolean(prop)) == NULL)
|
||||
return (scf_exception("scf_simple_prop_next_boolean() failed",
|
||||
name));
|
||||
|
||||
if (*val) {
|
||||
scf_simple_prop_free(prop);
|
||||
Py_INCREF(Py_True);
|
||||
return (Py_True);
|
||||
}
|
||||
|
||||
scf_simple_prop_free(prop);
|
||||
Py_INCREF(Py_False);
|
||||
return (Py_False);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyscf_get_int(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", NULL };
|
||||
scf_simple_prop_t *prop;
|
||||
PyObject *obj;
|
||||
int64_t *val;
|
||||
char *name;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
|
||||
return (NULL);
|
||||
|
||||
prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
|
||||
|
||||
if (prop == NULL)
|
||||
return (scf_exception("scf_simple_prop_get() failed", name));
|
||||
|
||||
if ((val = scf_simple_prop_next_integer(prop)) == NULL)
|
||||
return (scf_exception("scf_simple_prop_next_integer() failed",
|
||||
name));
|
||||
|
||||
obj = PyInt_FromLong((long)*val);
|
||||
scf_simple_prop_free(prop);
|
||||
return (obj);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyscf_get_string(PyObject *o, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "name", NULL };
|
||||
scf_simple_prop_t *prop;
|
||||
PyObject *obj;
|
||||
char *name;
|
||||
char *str;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &name))
|
||||
return (NULL);
|
||||
|
||||
prop = scf_simple_prop_get(NULL, XEND_FMRI, XEND_PG, name);
|
||||
|
||||
if (prop == NULL)
|
||||
return (scf_exception("scf_simple_prop_get() failed", name));
|
||||
|
||||
if ((str = scf_simple_prop_next_astring(prop)) == NULL) {
|
||||
scf_simple_prop_free(prop);
|
||||
return (scf_exception("scf_simple_prop_next_astring() failed",
|
||||
name));
|
||||
}
|
||||
|
||||
obj = PyString_FromString(str);
|
||||
scf_simple_prop_free(prop);
|
||||
return (obj);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(pyscf_get_bool__doc__,
|
||||
"get_bool(name) - get the value of the named boolean property");
|
||||
PyDoc_STRVAR(pyscf_get_int__doc__,
|
||||
"get_int(name) - get the value of the named integer property");
|
||||
PyDoc_STRVAR(pyscf_get_string__doc__,
|
||||
"get_string(name) - get the value of the named string property");
|
||||
|
||||
static struct PyMethodDef pyscf_module_methods[] = {
|
||||
{ "get_bool", (PyCFunction) pyscf_get_bool,
|
||||
METH_VARARGS|METH_KEYWORDS, pyscf_get_bool__doc__ },
|
||||
{ "get_int", (PyCFunction) pyscf_get_int,
|
||||
METH_VARARGS|METH_KEYWORDS, pyscf_get_int__doc__ },
|
||||
{ "get_string", (PyCFunction) pyscf_get_string,
|
||||
METH_VARARGS|METH_KEYWORDS, pyscf_get_string__doc__ },
|
||||
{ NULL, NULL, 0, NULL }
|
||||
};
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initscf(void)
|
||||
{
|
||||
PyObject *m;
|
||||
m = Py_InitModule("scf", pyscf_module_methods);
|
||||
|
||||
scf_exc = PyErr_NewException("scf.error", NULL, NULL);
|
||||
Py_INCREF(scf_exc);
|
||||
PyModule_AddObject(m, "error", scf_exc);
|
||||
PyModule_AddIntConstant(m, "SCF_ERROR_NOT_FOUND", SCF_ERROR_NOT_FOUND);
|
||||
}
|
||||
@@ -160,6 +160,20 @@ static PyObject *pyxc_domain_destroy(XcObject *self, PyObject *args)
|
||||
return dom_op(self, args, xc_domain_destroy);
|
||||
}
|
||||
|
||||
static PyObject *pyxc_domain_shutdown(XcObject *self, PyObject *args)
|
||||
{
|
||||
uint32_t dom, reason;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &dom, &reason))
|
||||
return NULL;
|
||||
|
||||
if (xc_domain_shutdown(self->xc_handle, dom, reason) != 0)
|
||||
return pyxc_error_to_exception();
|
||||
|
||||
Py_INCREF(zero);
|
||||
return zero;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *pyxc_vcpu_setaffinity(XcObject *self,
|
||||
PyObject *args,
|
||||
@@ -1029,6 +1043,14 @@ static PyMethodDef pyxc_methods[] = {
|
||||
" dom [int]: Identifier of domain to be destroyed.\n\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "domain_shutdown",
|
||||
(PyCFunction)pyxc_domain_shutdown,
|
||||
METH_VARARGS, "\n"
|
||||
"Shutdown a domain.\n"
|
||||
" dom [int, 0]: Domain identifier to use.\n"
|
||||
" reason [int, 0]: Reason for shutdown.\n"
|
||||
"Returns: [int] 0 on success; -1 on error.\n" },
|
||||
|
||||
{ "vcpu_setaffinity",
|
||||
(PyCFunction)pyxc_vcpu_setaffinity,
|
||||
METH_VARARGS | METH_KEYWORDS, "\n"
|
||||
|
||||
@@ -256,6 +256,7 @@ class UnixXMLRPCRequestHandler(XMLRPCRequestHandler):
|
||||
|
||||
class UnixXMLRPCServer(TCPXMLRPCServer):
|
||||
address_family = socket.AF_UNIX
|
||||
allow_address_reuse = True
|
||||
|
||||
def __init__(self, addr, allowed, xenapi, logRequests = 1):
|
||||
mkdir.parents(os.path.dirname(addr), stat.S_IRWXU, True)
|
||||
|
||||
@@ -294,8 +294,6 @@ class HttpServer:
|
||||
|
||||
backlog = 5
|
||||
|
||||
closed = False
|
||||
|
||||
def __init__(self, root, interface, port=8080):
|
||||
self.root = root
|
||||
self.interface = interface
|
||||
@@ -303,6 +301,7 @@ class HttpServer:
|
||||
# ready indicates when we are ready to begin accept connections
|
||||
# it should be set after a successful bind
|
||||
self.ready = False
|
||||
self.closed = False
|
||||
|
||||
def run(self):
|
||||
self.bind()
|
||||
@@ -317,7 +316,6 @@ class HttpServer:
|
||||
def stop(self):
|
||||
self.close()
|
||||
|
||||
|
||||
def bind(self):
|
||||
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
flags = fcntl.fcntl(self.socket.fileno(), fcntl.F_GETFD)
|
||||
@@ -334,7 +332,10 @@ class HttpServer:
|
||||
|
||||
def close(self):
|
||||
self.closed = True
|
||||
self.ready = False
|
||||
try:
|
||||
# shutdown socket explicitly to allow reuse
|
||||
self.socket.shutdown(socket.SHUT_RDWR)
|
||||
self.socket.close()
|
||||
except:
|
||||
pass
|
||||
@@ -345,6 +346,9 @@ class HttpServer:
|
||||
def getResource(self, req):
|
||||
return self.root.getRequestResource(req)
|
||||
|
||||
def shutdown(self):
|
||||
self.close()
|
||||
|
||||
|
||||
class UnixHttpServer(HttpServer):
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"""
|
||||
import os
|
||||
|
||||
import XendRoot
|
||||
import XendOptions
|
||||
|
||||
|
||||
def network(op):
|
||||
@@ -30,7 +30,7 @@ def network(op):
|
||||
"""
|
||||
if op not in ['start', 'stop']:
|
||||
raise ValueError('Invalid operation: ' + op)
|
||||
script = XendRoot.instance().get_network_script()
|
||||
script = XendOptions.instance().get_network_script()
|
||||
if script:
|
||||
script.insert(1, op)
|
||||
os.spawnv(os.P_WAIT, script[0], script)
|
||||
@@ -22,11 +22,14 @@ from xen.xend.XendConfig import XendConfig
|
||||
from xen.xend.XendConstants import *
|
||||
|
||||
SIGNATURE = "LinuxGuestRecord"
|
||||
QEMU_SIGNATURE = "QemuDeviceModelRecord"
|
||||
dm_batch = 512
|
||||
XC_SAVE = "xc_save"
|
||||
XC_RESTORE = "xc_restore"
|
||||
|
||||
|
||||
sizeof_int = calcsize("i")
|
||||
sizeof_unsigned_int = calcsize("I")
|
||||
sizeof_unsigned_long = calcsize("L")
|
||||
|
||||
|
||||
@@ -69,6 +72,11 @@ def save(fd, dominfo, network, live, dst):
|
||||
"could not write guest state file: config len")
|
||||
write_exact(fd, config, "could not write guest state file: config")
|
||||
|
||||
image_cfg = dominfo.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
|
||||
if hvm:
|
||||
log.info("save hvm domain")
|
||||
# xc_save takes three customization parameters: maxit, max_f, and
|
||||
# flags the last controls whether or not save is 'live', while the
|
||||
# first two further customize behaviour when 'live' save is
|
||||
@@ -76,7 +84,7 @@ def save(fd, dominfo, network, live, dst):
|
||||
# libxenguest; see the comments and/or code in xc_linux_save() for
|
||||
# more information.
|
||||
cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(fd),
|
||||
str(dominfo.getDomid()), "0", "0", str(int(live)) ]
|
||||
str(dominfo.getDomid()), "0", "0", str(int(live) | (int(hvm) << 2)) ]
|
||||
log.debug("[xc_save]: %s", string.join(cmd))
|
||||
|
||||
def saveInputHandler(line, tochild):
|
||||
@@ -90,12 +98,29 @@ def save(fd, dominfo, network, live, dst):
|
||||
log.info("Domain %d suspended.", dominfo.getDomid())
|
||||
dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3,
|
||||
domain_name)
|
||||
#send signal to device model for save
|
||||
if hvm:
|
||||
log.info("release_devices for hvm domain")
|
||||
dominfo._releaseDevices(True)
|
||||
tochild.write("done\n")
|
||||
tochild.flush()
|
||||
log.debug('Written done')
|
||||
|
||||
forkHelper(cmd, fd, saveInputHandler, False)
|
||||
|
||||
# put qemu device model state
|
||||
if hvm:
|
||||
write_exact(fd, QEMU_SIGNATURE, "could not write qemu signature")
|
||||
qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(), os.O_RDONLY)
|
||||
while True:
|
||||
buf = os.read(qemu_fd, dm_batch)
|
||||
if len(buf):
|
||||
write_exact(fd, buf, "could not write device model state")
|
||||
else:
|
||||
break
|
||||
os.close(qemu_fd)
|
||||
os.remove("/tmp/xen.qemu-dm.%d" % dominfo.getDomid())
|
||||
|
||||
dominfo.destroyDomain()
|
||||
try:
|
||||
dominfo.setName(domain_name)
|
||||
@@ -149,19 +174,49 @@ def restore(xd, fd, dominfo = None, paused = False):
|
||||
|
||||
nr_pfns = (dominfo.getMemoryTarget() + 3) / 4
|
||||
|
||||
# if hvm, pass mem size to calculate the store_mfn
|
||||
hvm = 0
|
||||
apic = 0
|
||||
pae = 0
|
||||
image_cfg = dominfo.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
if hvm:
|
||||
# the 'memory' in config has been removed
|
||||
hvm = dominfo.info['memory_static_min']
|
||||
apic = dominfo.info['image']['hvm'].get('apic', 0)
|
||||
pae = dominfo.info['image']['hvm'].get('pae', 0)
|
||||
log.info("restore hvm domain %d, mem=%d, apic=%d, pae=%d",
|
||||
dominfo.domid, hvm, apic, pae)
|
||||
|
||||
try:
|
||||
l = read_exact(fd, sizeof_unsigned_long,
|
||||
"not a valid guest state file: pfn count read")
|
||||
if hvm:
|
||||
l = read_exact(fd, sizeof_unsigned_int,
|
||||
"not a valid hvm guest state file: pfn count read")
|
||||
nr_pfns = unpack("I", l)[0] # native sizeof int
|
||||
else:
|
||||
l = read_exact(fd, sizeof_unsigned_long,
|
||||
"not a valid guest state file: pfn count read")
|
||||
|
||||
max_pfn = unpack("L", l)[0] # native sizeof long
|
||||
if max_pfn > 16*1024*1024: # XXX
|
||||
raise XendError(
|
||||
"not a valid guest state file: pfn count out of range")
|
||||
|
||||
balloon.free(xc.pages_to_kib(nr_pfns))
|
||||
shadow = dominfo.info['shadow_memory']
|
||||
log.debug("restore:shadow=0x%x, _static_max=0x%x, _static_min=0x%x, "
|
||||
"nr_pfns=0x%x.", dominfo.info['shadow_memory'],
|
||||
dominfo.info['memory_static_max'],
|
||||
dominfo.info['memory_static_min'], nr_pfns)
|
||||
|
||||
|
||||
balloon.free(xc.pages_to_kib(nr_pfns) + shadow * 1024)
|
||||
|
||||
shadow_cur = xc.shadow_mem_control(dominfo.getDomid(), shadow)
|
||||
dominfo.info['shadow_memory'] = shadow_cur
|
||||
|
||||
cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
|
||||
fd, dominfo.getDomid(), max_pfn,
|
||||
store_port, console_port])
|
||||
store_port, console_port, hvm, pae, apic])
|
||||
log.debug("[xc_restore]: %s", string.join(cmd))
|
||||
|
||||
handler = RestoreInputHandler()
|
||||
@@ -171,10 +226,30 @@ def restore(xd, fd, dominfo = None, paused = False):
|
||||
if handler.store_mfn is None or handler.console_mfn is None:
|
||||
raise XendError('Could not read store/console MFN')
|
||||
|
||||
os.read(fd, 1) # Wait for source to close connection
|
||||
dominfo.waitForDevices() # Wait for backends to set up
|
||||
if not paused:
|
||||
dominfo.unpause()
|
||||
|
||||
# get qemu state and create a tmp file for dm restore
|
||||
if hvm:
|
||||
qemu_signature = read_exact(fd, len(QEMU_SIGNATURE),
|
||||
"invalid device model signature read")
|
||||
if qemu_signature != QEMU_SIGNATURE:
|
||||
raise XendError("not a valid device model state: found '%s'" %
|
||||
qemu_signature)
|
||||
qemu_fd = os.open("/tmp/xen.qemu-dm.%d" % dominfo.getDomid(),
|
||||
os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
|
||||
while True:
|
||||
buf = os.read(fd, dm_batch)
|
||||
if len(buf):
|
||||
write_exact(qemu_fd, buf,
|
||||
"could not write dm state to tmp file")
|
||||
else:
|
||||
break
|
||||
os.close(qemu_fd)
|
||||
|
||||
|
||||
os.read(fd, 1) # Wait for source to close connection
|
||||
|
||||
dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
|
||||
|
||||
|
||||
@@ -78,6 +78,25 @@ def scrub_password(data):
|
||||
else:
|
||||
return data
|
||||
|
||||
#
|
||||
# CPU fields:
|
||||
#
|
||||
# vcpus_number -- the maximum number of vcpus that this domain may ever have.
|
||||
# aka XendDomainInfo.getVCpuCount().
|
||||
# vcpus -- the legacy configuration name for above.
|
||||
# max_vcpu_id -- vcpus_number - 1. This is given to us by Xen.
|
||||
#
|
||||
# cpus -- the list of pCPUs available to each vCPU.
|
||||
#
|
||||
# vcpu_avail: a bitmap telling the guest domain whether it may use each of
|
||||
# its VCPUs. This is translated to
|
||||
# <dompath>/cpu/<id>/availability = {online,offline} for use
|
||||
# by the guest domain.
|
||||
# online_vpcus -- the number of VCPUs currently up, as reported by Xen. This
|
||||
# is changed by changing vcpu_avail, and waiting for the
|
||||
# domain to respond.
|
||||
#
|
||||
|
||||
|
||||
# Mapping from XendConfig configuration keys to the old
|
||||
# legacy configuration keys that map directly.
|
||||
@@ -185,7 +204,7 @@ LEGACY_CFG_TYPES = {
|
||||
'uuid': str,
|
||||
'name': str,
|
||||
'vcpus': int,
|
||||
'vcpu_avail': int,
|
||||
'vcpu_avail': long,
|
||||
'memory': int,
|
||||
'shadow_memory': int,
|
||||
'maxmem': int,
|
||||
@@ -355,9 +374,6 @@ class XendConfig(dict):
|
||||
'cpu_weight': 256,
|
||||
'cpu_cap': 0,
|
||||
'vcpus_number': 1,
|
||||
'online_vcpus': 1,
|
||||
'max_vcpu_id': 0,
|
||||
'vcpu_avail': 1,
|
||||
'console_refs': [],
|
||||
'vif_refs': [],
|
||||
'vbd_refs': [],
|
||||
@@ -389,7 +405,7 @@ class XendConfig(dict):
|
||||
event)
|
||||
|
||||
def _vcpus_sanity_check(self):
|
||||
if self.get('vcpus_number') != None:
|
||||
if 'vcpus_number' in self and 'vcpu_avail' not in self:
|
||||
self['vcpu_avail'] = (1 << self['vcpus_number']) - 1
|
||||
|
||||
def _uuid_sanity_check(self):
|
||||
@@ -405,7 +421,7 @@ class XendConfig(dict):
|
||||
def _dominfo_to_xapi(self, dominfo):
|
||||
self['domid'] = dominfo['domid']
|
||||
self['online_vcpus'] = dominfo['online_vcpus']
|
||||
self['max_vcpu_id'] = dominfo['max_vcpu_id']
|
||||
self['vcpus_number'] = dominfo['max_vcpu_id'] + 1
|
||||
self['memory_dynamic_min'] = (dominfo['mem_kb'] + 1023)/1024
|
||||
self['memory_dynamic_max'] = (dominfo['maxmem_kb'] + 1023)/1024
|
||||
self['cpu_time'] = dominfo['cpu_time']/1e9
|
||||
@@ -636,9 +652,6 @@ class XendConfig(dict):
|
||||
self['memory_dynamic_max'] = self['memory_static_max']
|
||||
self['memory_dynamic_min'] = self['memory_static_min']
|
||||
|
||||
# make sure max_vcpu_id is set correctly
|
||||
self['max_vcpu_id'] = self['vcpus_number'] - 1
|
||||
|
||||
# set device references in the configuration
|
||||
self['devices'] = cfg.get('devices', {})
|
||||
|
||||
@@ -720,13 +733,11 @@ class XendConfig(dict):
|
||||
_set_cfg_if_exists('on_xend_stop')
|
||||
_set_cfg_if_exists('on_xend_start')
|
||||
_set_cfg_if_exists('vcpu_avail')
|
||||
_set_cfg_if_exists('max_vcpu_id') # needed for vcpuDomDetails
|
||||
_set_cfg_if_exists('cpu_weight')
|
||||
_set_cfg_if_exists('cpu_cap')
|
||||
|
||||
# Parse and store runtime configuration
|
||||
_set_cfg_if_exists('start_time')
|
||||
_set_cfg_if_exists('online_vcpus')
|
||||
_set_cfg_if_exists('cpu_time')
|
||||
_set_cfg_if_exists('shutdown_reason')
|
||||
_set_cfg_if_exists('up_time')
|
||||
@@ -1115,19 +1126,17 @@ class XendConfig(dict):
|
||||
# configuration
|
||||
log.debug("update_with_image_sxp(%s)" % scrub_password(image_sxp))
|
||||
|
||||
kernel_args = ""
|
||||
# user-specified args must come last: previous releases did this and
|
||||
# some domU kernels rely upon the ordering.
|
||||
kernel_args = sxp.child_value(image_sxp, 'args', '')
|
||||
|
||||
# attempt to extract extra arguments from SXP config
|
||||
arg_ip = sxp.child_value(image_sxp, 'ip')
|
||||
if arg_ip and not re.search(r'ip=[^ ]+', kernel_args):
|
||||
kernel_args += 'ip=%s ' % arg_ip
|
||||
kernel_args = 'ip=%s ' % arg_ip + kernel_args
|
||||
arg_root = sxp.child_value(image_sxp, 'root')
|
||||
if arg_root and not re.search(r'root=', kernel_args):
|
||||
kernel_args += 'root=%s ' % arg_root
|
||||
|
||||
# user-specified args must come last: previous releases did this and
|
||||
# some domU kernels rely upon the ordering.
|
||||
kernel_args += sxp.child_value(image_sxp, 'args', '')
|
||||
kernel_args = 'root=%s ' % arg_root + kernel_args
|
||||
|
||||
if bootloader:
|
||||
self['_temp_using_bootloader'] = '1'
|
||||
|
||||
@@ -32,7 +32,7 @@ import threading
|
||||
import xen.lowlevel.xc
|
||||
|
||||
|
||||
from xen.xend import XendRoot, XendCheckpoint, XendDomainInfo
|
||||
from xen.xend import XendOptions, XendCheckpoint, XendDomainInfo
|
||||
from xen.xend.PrettyPrint import prettyprint
|
||||
from xen.xend.XendConfig import XendConfig
|
||||
from xen.xend.XendError import XendError, XendInvalidDomain, VmError
|
||||
@@ -51,7 +51,7 @@ from xen.util import mkdir, security
|
||||
from xen.xend import uuid
|
||||
|
||||
xc = xen.lowlevel.xc.xc()
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
__all__ = [ "XendDomain" ]
|
||||
|
||||
@@ -214,7 +214,7 @@ class XendDomain:
|
||||
@rtype: String
|
||||
@return: Path.
|
||||
"""
|
||||
dom_path = xroot.get_xend_domains_path()
|
||||
dom_path = xoptions.get_xend_domains_path()
|
||||
if domuuid:
|
||||
dom_path = os.path.join(dom_path, domuuid)
|
||||
return dom_path
|
||||
@@ -361,7 +361,7 @@ class XendDomain:
|
||||
|
||||
def _setDom0CPUCount(self):
|
||||
"""Sets the number of VCPUs dom0 has. Retreived from the
|
||||
Xend configuration, L{XendRoot}.
|
||||
Xend configuration, L{XendOptions}.
|
||||
|
||||
@requires: Expects to be protected by domains_lock.
|
||||
@rtype: None
|
||||
@@ -369,7 +369,7 @@ class XendDomain:
|
||||
dom0 = self.privilegedDomain()
|
||||
|
||||
# get max number of vcpus to use for dom0 from config
|
||||
target = int(xroot.get_dom0_vcpus())
|
||||
target = int(xoptions.get_dom0_vcpus())
|
||||
log.debug("number of vcpus to use is %d", target)
|
||||
|
||||
# target == 0 means use all processors
|
||||
@@ -1164,7 +1164,7 @@ class XendDomain:
|
||||
dominfo.checkLiveMigrateMemory()
|
||||
|
||||
if port == 0:
|
||||
port = xroot.get_xend_relocation_port()
|
||||
port = xoptions.get_xend_relocation_port()
|
||||
try:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.connect((dst, port))
|
||||
|
||||
@@ -38,7 +38,7 @@ from xen.util.blkif import blkdev_uname_to_file
|
||||
from xen.util import security
|
||||
|
||||
from xen.xend import balloon, sxp, uuid, image, arch, osdep
|
||||
from xen.xend import XendRoot, XendNode, XendConfig
|
||||
from xen.xend import XendOptions, XendNode, XendConfig
|
||||
|
||||
from xen.xend.XendConfig import scrub_password
|
||||
from xen.xend.XendBootloader import bootloader
|
||||
@@ -54,31 +54,12 @@ MIGRATE_TIMEOUT = 30.0
|
||||
BOOTLOADER_LOOPBACK_DEVICE = '/dev/xvdp'
|
||||
|
||||
xc = xen.lowlevel.xc.xc()
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
log = logging.getLogger("xend.XendDomainInfo")
|
||||
#log.setLevel(logging.TRACE)
|
||||
|
||||
|
||||
#
|
||||
# There are a number of CPU-related fields:
|
||||
#
|
||||
# vcpus: the number of virtual CPUs this domain is configured to use.
|
||||
# vcpu_avail: a bitmap telling the guest domain whether it may use each of
|
||||
# its VCPUs. This is translated to
|
||||
# <dompath>/cpu/<id>/availability = {online,offline} for use
|
||||
# by the guest domain.
|
||||
# cpumap: a list of bitmaps, one for each VCPU, giving the physical
|
||||
# CPUs that that VCPU may use.
|
||||
# cpu: a configuration setting requesting that VCPU 0 is pinned to
|
||||
# the specified physical CPU.
|
||||
#
|
||||
# vcpus and vcpu_avail settings persist with the VM (i.e. they are persistent
|
||||
# across save, restore, migrate, and restart). The other settings are only
|
||||
# specific to the domain, so are lost when the VM moves.
|
||||
#
|
||||
|
||||
|
||||
def create(config):
|
||||
"""Creates and start a VM using the supplied configuration.
|
||||
|
||||
@@ -451,6 +432,16 @@ class XendDomainInfo:
|
||||
self._removeVm('xend/previous_restart_time')
|
||||
self.storeDom("control/shutdown", reason)
|
||||
|
||||
## shutdown hypercall for hvm domain desides xenstore write
|
||||
image_cfg = self.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
if hvm:
|
||||
for code in DOMAIN_SHUTDOWN_REASONS.keys():
|
||||
if DOMAIN_SHUTDOWN_REASONS[code] == reason:
|
||||
break
|
||||
xc.domain_shutdown(self.domid, code)
|
||||
|
||||
|
||||
def pause(self):
|
||||
"""Pause domain
|
||||
|
||||
@@ -614,7 +605,7 @@ class XendDomainInfo:
|
||||
['name', self.info['name_label']],
|
||||
['vcpu_count', self.info['vcpus_number']]]
|
||||
|
||||
for i in range(0, self.info['max_vcpu_id']+1):
|
||||
for i in range(0, self.info['vcpus_number']):
|
||||
info = xc.vcpu_getinfo(self.domid, i)
|
||||
|
||||
sxpr.append(['vcpu',
|
||||
@@ -739,7 +730,7 @@ class XendDomainInfo:
|
||||
'domid': str(self.domid),
|
||||
'vm': self.vmpath,
|
||||
'name': self.info['name_label'],
|
||||
'console/limit': str(xroot.get_console_limit() * 1024),
|
||||
'console/limit': str(xoptions.get_console_limit() * 1024),
|
||||
'memory/target': str(self.info['memory_static_min'] * 1024)
|
||||
}
|
||||
|
||||
@@ -898,8 +889,9 @@ class XendDomainInfo:
|
||||
self._writeDom(self._vcpuDomDetails())
|
||||
else:
|
||||
self.info['vcpus_number'] = vcpus
|
||||
self.info['online_vcpus'] = vcpus
|
||||
xen.xend.XendDomain.instance().managed_config_save(self)
|
||||
log.info("Set VCPU count on domain %s to %d", self.info['name_label'],
|
||||
vcpus)
|
||||
|
||||
def getLabel(self):
|
||||
return security.get_security_info(self.info, 'label')
|
||||
@@ -976,7 +968,7 @@ class XendDomainInfo:
|
||||
self.info['name_label'], self.domid)
|
||||
self._writeVm(LAST_SHUTDOWN_REASON, 'crash')
|
||||
|
||||
if xroot.get_enable_dump():
|
||||
if xoptions.get_enable_dump():
|
||||
try:
|
||||
self.dumpCore()
|
||||
except XendError:
|
||||
@@ -1228,8 +1220,11 @@ class XendDomainInfo:
|
||||
if self.image:
|
||||
self.image.createDeviceModel()
|
||||
|
||||
def _releaseDevices(self):
|
||||
def _releaseDevices(self, suspend = False):
|
||||
"""Release all domain's devices. Nothrow guarantee."""
|
||||
if suspend and self.image:
|
||||
self.image.destroy(suspend)
|
||||
return
|
||||
|
||||
while True:
|
||||
t = xstransact("%s/device" % self.dompath)
|
||||
@@ -1381,7 +1376,7 @@ class XendDomainInfo:
|
||||
# this is done prior to memory allocation to aide in memory
|
||||
# distribution for NUMA systems.
|
||||
if self.info['cpus'] is not None and len(self.info['cpus']) > 0:
|
||||
for v in range(0, self.info['max_vcpu_id']+1):
|
||||
for v in range(0, self.info['vcpus_number']):
|
||||
xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
|
||||
|
||||
# Use architecture- and image-specific calculations to determine
|
||||
@@ -1395,6 +1390,7 @@ class XendDomainInfo:
|
||||
self.info['shadow_memory'] * 1024,
|
||||
self.info['memory_static_max'] * 1024)
|
||||
|
||||
log.debug("_initDomain:shadow_memory=0x%x, memory_static_max=0x%x, memory_static_min=0x%x.", self.info['shadow_memory'], self.info['memory_static_max'], self.info['memory_static_min'],)
|
||||
# Round shadow up to a multiple of a MiB, as shadow_mem_control
|
||||
# takes MiB and we must not round down and end up under-providing.
|
||||
shadow = ((shadow + 1023) / 1024) * 1024
|
||||
@@ -1494,6 +1490,16 @@ class XendDomainInfo:
|
||||
self.console_mfn = console_mfn
|
||||
|
||||
self._introduceDomain()
|
||||
image_cfg = self.info.get('image', {})
|
||||
hvm = image_cfg.has_key('hvm')
|
||||
if hvm:
|
||||
self.image = image.create(self,
|
||||
self.info,
|
||||
self.info['image'],
|
||||
self.info['devices'])
|
||||
if self.image:
|
||||
self.image.createDeviceModel(True)
|
||||
self.image.register_shutdown_watch()
|
||||
self._storeDomDetails()
|
||||
self._registerWatches()
|
||||
self.refreshShutdown()
|
||||
@@ -2028,8 +2034,8 @@ class XendDomainInfo:
|
||||
# TODO: spec says that key is int, however, python does not allow
|
||||
# non-string keys to dictionaries.
|
||||
vcpu_util = {}
|
||||
if 'max_vcpu_id' in self.info and self.domid != None:
|
||||
for i in range(0, self.info['max_vcpu_id']+1):
|
||||
if 'vcpus_number' in self.info and self.domid != None:
|
||||
for i in range(0, self.info['vcpus_number']):
|
||||
info = xc.vcpu_getinfo(self.domid, i)
|
||||
vcpu_util[str(i)] = info['cpu_time']/1000000000.0
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ from xen.util import Brctl
|
||||
|
||||
from xen.xend import uuid
|
||||
from xen.xend.XendError import XendError, NetworkAlreadyConnected
|
||||
from xen.xend.XendRoot import instance as xendroot
|
||||
from xen.xend.XendOptions import instance as xendoptions
|
||||
from xen.xend.XendStorageRepository import XendStorageRepository
|
||||
from xen.xend.XendLogging import log
|
||||
from xen.xend.XendPIF import *
|
||||
@@ -45,7 +45,7 @@ class XendNode:
|
||||
"""
|
||||
|
||||
self.xc = xen.lowlevel.xc.xc()
|
||||
self.state_store = XendStateStore(xendroot().get_xend_state_path())
|
||||
self.state_store = XendStateStore(xendoptions().get_xend_state_path())
|
||||
|
||||
# load host state from XML file
|
||||
saved_host = self.state_store.load_state('host')
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
Creates the servers and handles configuration.
|
||||
|
||||
Other classes get config variables by importing this module,
|
||||
using instance() to get a XendRoot instance, and then
|
||||
using instance() to get a XendOptions instance, and then
|
||||
the config functions (e.g. get_xend_port()) to get
|
||||
configured values.
|
||||
"""
|
||||
@@ -33,14 +33,11 @@ import sys
|
||||
from xen.xend import sxp, osdep, XendLogging
|
||||
from xen.xend.XendError import XendError
|
||||
|
||||
class XendRoot:
|
||||
"""Root of the management classes."""
|
||||
if os.uname()[0] == 'SunOS':
|
||||
from xen.lowlevel import scf
|
||||
|
||||
"""Default path to the config file."""
|
||||
config_default = "/etc/xen/xend-config.sxp"
|
||||
|
||||
"""Environment variable used to override config_default."""
|
||||
config_var = "XEND_CONFIG"
|
||||
class XendOptions:
|
||||
"""Configuration options."""
|
||||
|
||||
"""Where network control scripts live."""
|
||||
network_script_dir = osdep.scripts_dir
|
||||
@@ -75,10 +72,10 @@ class XendRoot:
|
||||
xend_relocation_address_default = ''
|
||||
|
||||
"""Default port xend serves HTTP at. """
|
||||
xend_port_default = '8000'
|
||||
xend_port_default = 8000
|
||||
|
||||
"""Default port xend serves relocation at. """
|
||||
xend_relocation_port_default = '8002'
|
||||
xend_relocation_port_default = 8002
|
||||
|
||||
xend_relocation_hosts_allow_default = ''
|
||||
|
||||
@@ -92,9 +89,9 @@ class XendRoot:
|
||||
"""Default path the unix-domain server listens at."""
|
||||
xend_unix_path_default = '/var/lib/xend/xend-socket'
|
||||
|
||||
dom0_min_mem_default = '0'
|
||||
dom0_min_mem_default = 0
|
||||
|
||||
dom0_vcpus_default = '0'
|
||||
dom0_vcpus_default = 0
|
||||
|
||||
vncpasswd_default = None
|
||||
|
||||
@@ -107,16 +104,17 @@ class XendRoot:
|
||||
"""Default xend management state storage."""
|
||||
xend_state_path_default = '/var/lib/xend/state'
|
||||
|
||||
components = {}
|
||||
"""Default type of backend network interfaces"""
|
||||
netback_type = osdep.netback_type
|
||||
|
||||
"""Default script to configure a backend network interface"""
|
||||
vif_script = osdep.vif_script
|
||||
|
||||
def __init__(self):
|
||||
self.config_path = None
|
||||
self.config = None
|
||||
self.configure()
|
||||
|
||||
|
||||
def _logError(self, fmt, *args):
|
||||
"""Logging function to log to stderr. We use this for XendRoot log
|
||||
"""Logging function to log to stderr. We use this for XendOptions log
|
||||
messages because they may be logged before the logger has been
|
||||
configured. Other components can safely use the logger.
|
||||
"""
|
||||
@@ -125,81 +123,25 @@ class XendRoot:
|
||||
|
||||
def configure(self):
|
||||
self.set_config()
|
||||
XendLogging.init(self.get_config_value("logfile",
|
||||
XendLogging.init(self.get_config_string("logfile",
|
||||
self.logfile_default),
|
||||
self.get_config_value("loglevel",
|
||||
self.get_config_string("loglevel",
|
||||
self.loglevel_default))
|
||||
|
||||
|
||||
def set_config(self):
|
||||
"""If the config file exists, read it. If not, ignore it.
|
||||
|
||||
The config file is a sequence of sxp forms.
|
||||
"""
|
||||
self.config_path = os.getenv(self.config_var, self.config_default)
|
||||
if os.path.exists(self.config_path):
|
||||
try:
|
||||
fin = file(self.config_path, 'rb')
|
||||
try:
|
||||
config = sxp.parse(fin)
|
||||
finally:
|
||||
fin.close()
|
||||
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',
|
||||
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):
|
||||
"""Get the configuration element with the given name, or
|
||||
the whole configuration if no name is given.
|
||||
|
||||
@param name: element name (optional)
|
||||
@return: config or none
|
||||
"""
|
||||
if name is None:
|
||||
val = self.config
|
||||
else:
|
||||
val = sxp.child(self.config, name)
|
||||
return val
|
||||
|
||||
def get_config_value(self, name, val=None):
|
||||
"""Get the value of an atomic configuration element.
|
||||
|
||||
@param name: element name
|
||||
@param val: default value (optional, defaults to None)
|
||||
@return: value
|
||||
"""
|
||||
return sxp.child_value(self.config, name, val=val)
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_config_bool(self, name, val=None):
|
||||
v = string.lower(str(self.get_config_value(name, val)))
|
||||
if v in ['yes', 'y', '1', 'on', 'true', 't']:
|
||||
return True
|
||||
if v in ['no', 'n', '0', 'off', 'false', 'f']:
|
||||
return False
|
||||
raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
|
||||
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_config_int(self, name, val=None):
|
||||
v = self.get_config_value(name, val)
|
||||
try:
|
||||
return int(v)
|
||||
except Exception:
|
||||
raise XendError("invalid xend config %s: expected int: %s" % (name, v))
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_config_string(self, name, val=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_xen_api_server(self):
|
||||
"""Get the Xen-API server configuration.
|
||||
"""
|
||||
return self.get_config_value('xen-api-server',
|
||||
self.xen_api_server_default)
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_xend_http_server(self):
|
||||
"""Get the flag indicating whether xend should run an http server.
|
||||
@@ -232,7 +174,7 @@ class XendRoot:
|
||||
self.xend_relocation_port_default)
|
||||
|
||||
def get_xend_relocation_hosts_allow(self):
|
||||
return self.get_config_value("xend-relocation-hosts-allow",
|
||||
return self.get_config_string("xend-relocation-hosts-allow",
|
||||
self.xend_relocation_hosts_allow_default)
|
||||
|
||||
def get_xend_address(self):
|
||||
@@ -241,7 +183,7 @@ class XendRoot:
|
||||
If this is set to 'localhost' only the localhost will be able to connect
|
||||
to the HTTP port.
|
||||
"""
|
||||
return self.get_config_value('xend-address', self.xend_address_default)
|
||||
return self.get_config_string('xend-address', self.xend_address_default)
|
||||
|
||||
def get_xend_relocation_address(self):
|
||||
"""Get the address xend listens at for its relocation server port.
|
||||
@@ -249,7 +191,7 @@ class XendRoot:
|
||||
If this is set to 'localhost' only the localhost will be able to connect
|
||||
to the relocation port.
|
||||
"""
|
||||
return self.get_config_value('xend-relocation-address', self.xend_relocation_address_default)
|
||||
return self.get_config_string('xend-relocation-address', self.xend_relocation_address_default)
|
||||
|
||||
def get_xend_unix_server(self):
|
||||
"""Get the flag indicating whether xend should run a unix-domain server.
|
||||
@@ -259,23 +201,23 @@ class XendRoot:
|
||||
def get_xend_unix_path(self):
|
||||
"""Get the path the xend unix-domain server listens at.
|
||||
"""
|
||||
return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
|
||||
return self.get_config_string("xend-unix-path", self.xend_unix_path_default)
|
||||
|
||||
def get_xend_domains_path(self):
|
||||
""" Get the path for persistent domain configuration storage
|
||||
"""
|
||||
return self.get_config_value("xend-domains-path", self.xend_domains_path_default)
|
||||
return self.get_config_string("xend-domains-path", self.xend_domains_path_default)
|
||||
|
||||
def get_xend_state_path(self):
|
||||
""" Get the path for persistent domain configuration storage
|
||||
"""
|
||||
return self.get_config_value("xend-state-path", self.xend_state_path_default)
|
||||
return self.get_config_string("xend-state-path", self.xend_state_path_default)
|
||||
|
||||
def get_network_script(self):
|
||||
"""@return the script used to alter the network configuration when
|
||||
Xend starts and stops, or None if no such script is specified."""
|
||||
|
||||
s = self.get_config_value('network-script')
|
||||
s = self.get_config_string('network-script')
|
||||
|
||||
if s:
|
||||
result = s.split(" ")
|
||||
@@ -286,13 +228,13 @@ class XendRoot:
|
||||
|
||||
def get_external_migration_tool(self):
|
||||
"""@return the name of the tool to handle virtual TPM migration."""
|
||||
return self.get_config_value('external-migration-tool', self.external_migration_tool_default)
|
||||
return self.get_config_string('external-migration-tool', self.external_migration_tool_default)
|
||||
|
||||
def get_enable_dump(self):
|
||||
return self.get_config_bool('enable-dump', 'no')
|
||||
|
||||
def get_vif_script(self):
|
||||
return self.get_config_value('vif-script', 'vif-bridge')
|
||||
return self.get_config_string('vif-script', self.vif_script)
|
||||
|
||||
def get_dom0_min_mem(self):
|
||||
return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
|
||||
@@ -304,19 +246,128 @@ class XendRoot:
|
||||
return self.get_config_int('console-limit', 1024)
|
||||
|
||||
def get_vnclisten_address(self):
|
||||
return self.get_config_value('vnc-listen', self.xend_vnc_listen_default)
|
||||
return self.get_config_string('vnc-listen', self.xend_vnc_listen_default)
|
||||
|
||||
def get_vncpasswd_default(self):
|
||||
return self.get_config_value('vncpasswd',
|
||||
return self.get_config_string('vncpasswd',
|
||||
self.vncpasswd_default)
|
||||
|
||||
class XendOptionsFile(XendOptions):
|
||||
|
||||
"""Default path to the config file."""
|
||||
config_default = "/etc/xen/xend-config.sxp"
|
||||
|
||||
"""Environment variable used to override config_default."""
|
||||
config_var = "XEND_CONFIG"
|
||||
|
||||
def set_config(self):
|
||||
"""If the config file exists, read it. If not, ignore it.
|
||||
|
||||
The config file is a sequence of sxp forms.
|
||||
"""
|
||||
self.config_path = os.getenv(self.config_var, self.config_default)
|
||||
if os.path.exists(self.config_path):
|
||||
try:
|
||||
fin = file(self.config_path, 'rb')
|
||||
try:
|
||||
config = sxp.parse(fin)
|
||||
finally:
|
||||
fin.close()
|
||||
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',
|
||||
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_value(self, name, val=None):
|
||||
"""Get the value of an atomic configuration element.
|
||||
|
||||
@param name: element name
|
||||
@param val: default value (optional, defaults to None)
|
||||
@return: value
|
||||
"""
|
||||
return sxp.child_value(self.config, name, val=val)
|
||||
|
||||
def get_config_bool(self, name, val=None):
|
||||
v = string.lower(str(self.get_config_value(name, val)))
|
||||
if v in ['yes', 'y', '1', 'on', 'true', 't']:
|
||||
return True
|
||||
if v in ['no', 'n', '0', 'off', 'false', 'f']:
|
||||
return False
|
||||
raise XendError("invalid xend config %s: expected bool: %s" % (name, v))
|
||||
|
||||
def get_config_int(self, name, val=None):
|
||||
v = self.get_config_value(name, val)
|
||||
try:
|
||||
return int(v)
|
||||
except Exception:
|
||||
raise XendError("invalid xend config %s: expected int: %s" % (name, v))
|
||||
|
||||
def get_config_string(self, name, val=None):
|
||||
return self.get_config_value(name, val)
|
||||
|
||||
def get_xen_api_server(self):
|
||||
"""Get the Xen-API server configuration.
|
||||
"""
|
||||
return self.get_config_value('xen-api-server',
|
||||
self.xen_api_server_default)
|
||||
|
||||
if os.uname()[0] == 'SunOS':
|
||||
class XendOptionsSMF(XendOptions):
|
||||
|
||||
def set_config(self):
|
||||
pass
|
||||
|
||||
def get_config_bool(self, name, val=None):
|
||||
try:
|
||||
return scf.get_bool(name)
|
||||
except scf.error, e:
|
||||
if e[0] == scf.SCF_ERROR_NOT_FOUND:
|
||||
return val
|
||||
else:
|
||||
raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
|
||||
|
||||
def get_config_int(self, name, val=None):
|
||||
try:
|
||||
return scf.get_int(name)
|
||||
except scf.error, e:
|
||||
if e[0] == scf.SCF_ERROR_NOT_FOUND:
|
||||
return val
|
||||
else:
|
||||
raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
|
||||
|
||||
def get_config_string(self, name, val=None):
|
||||
try:
|
||||
return scf.get_string(name)
|
||||
except scf.error, e:
|
||||
if e[0] == scf.SCF_ERROR_NOT_FOUND:
|
||||
return val
|
||||
else:
|
||||
raise XendError("option %s: %s:%s" % (name, e[1], e[2]))
|
||||
|
||||
def get_xen_api_server(self):
|
||||
# When the new server is a supported configuration, we should
|
||||
# expand this.
|
||||
return [["unix"]]
|
||||
|
||||
def instance():
|
||||
"""Get an instance of XendRoot.
|
||||
"""Get an instance of XendOptions.
|
||||
Use this instead of the constructor.
|
||||
"""
|
||||
global inst
|
||||
try:
|
||||
inst
|
||||
except:
|
||||
inst = XendRoot()
|
||||
if os.uname()[0] == 'SunOS':
|
||||
inst = XendOptionsSMF()
|
||||
else:
|
||||
inst = XendOptionsFile()
|
||||
return inst
|
||||
@@ -24,7 +24,7 @@ import types
|
||||
from encode import *
|
||||
from xen.xend import sxp
|
||||
|
||||
from xen.xend import XendRoot
|
||||
from xen.xend import XendOptions
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
@@ -34,7 +34,7 @@ HTTP_ACCEPTED = 202
|
||||
HTTP_NO_CONTENT = 204
|
||||
|
||||
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
|
||||
class XendError(RuntimeError):
|
||||
@@ -218,7 +218,7 @@ class UnixXendClientProtocol(HttpXendClientProtocol):
|
||||
|
||||
def __init__(self, path=None):
|
||||
if path is None:
|
||||
path = xroot.get_xend_unix_path()
|
||||
path = xoptions.get_xend_unix_path()
|
||||
self.path = path
|
||||
|
||||
def makeConnection(self, _):
|
||||
|
||||
@@ -22,7 +22,7 @@ import time
|
||||
import xen.lowlevel.xc
|
||||
|
||||
import XendDomain
|
||||
import XendRoot
|
||||
import XendOptions
|
||||
from XendLogging import log
|
||||
from XendError import VmError
|
||||
|
||||
@@ -107,11 +107,11 @@ def free(need_mem):
|
||||
# usage, so we recheck the required alloc each time around the loop, but
|
||||
# track the last used value so that we don't trigger too many watches.
|
||||
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
xc = xen.lowlevel.xc.xc()
|
||||
|
||||
try:
|
||||
dom0_min_mem = xroot.get_dom0_min_mem() * 1024
|
||||
dom0_min_mem = xoptions.get_dom0_min_mem() * 1024
|
||||
|
||||
retries = 0
|
||||
sleep_time = SLEEP_TIME_GROWTH
|
||||
|
||||
@@ -173,7 +173,7 @@ class ImageHandler:
|
||||
"""Build the domain. Define in subclass."""
|
||||
raise NotImplementedError()
|
||||
|
||||
def createDeviceModel(self):
|
||||
def createDeviceModel(self, restore = False):
|
||||
"""Create device model for the domain (define in subclass if needed)."""
|
||||
pass
|
||||
|
||||
@@ -377,11 +377,12 @@ class HVMImageHandler(ImageHandler):
|
||||
# xm config file
|
||||
def parseDeviceModelArgs(self, imageConfig, deviceConfig):
|
||||
dmargs = [ 'boot', 'fda', 'fdb', 'soundhw',
|
||||
'localtime', 'serial', 'stdvga', 'isa', 'vcpus',
|
||||
'localtime', 'serial', 'stdvga', 'isa',
|
||||
'acpi', 'usb', 'usbdevice', 'keymap' ]
|
||||
ret = []
|
||||
hvmDeviceConfig = imageConfig['hvm']['devices']
|
||||
|
||||
|
||||
ret = ['-vcpus', str(self.vm.getVCpuCount())]
|
||||
|
||||
for a in dmargs:
|
||||
v = hvmDeviceConfig.get(a)
|
||||
|
||||
@@ -461,14 +462,14 @@ class HVMImageHandler(ImageHandler):
|
||||
vnclisten = imageConfig.get('vnclisten')
|
||||
|
||||
if not(vnclisten):
|
||||
vnclisten = (xen.xend.XendRoot.instance().
|
||||
vnclisten = (xen.xend.XendOptions.instance().
|
||||
get_vnclisten_address())
|
||||
if vnclisten:
|
||||
ret += ['-vnclisten', vnclisten]
|
||||
|
||||
vncpasswd = vncpasswd_vmconfig
|
||||
if vncpasswd is None:
|
||||
vncpasswd = (xen.xend.XendRoot.instance().
|
||||
vncpasswd = (xen.xend.XendOptions.instance().
|
||||
get_vncpasswd_default())
|
||||
if vncpasswd is None:
|
||||
raise VmError('vncpasswd is not set up in ' +
|
||||
@@ -478,7 +479,7 @@ class HVMImageHandler(ImageHandler):
|
||||
|
||||
return ret
|
||||
|
||||
def createDeviceModel(self):
|
||||
def createDeviceModel(self, restore = False):
|
||||
if self.pid:
|
||||
return
|
||||
# Execute device model.
|
||||
@@ -487,6 +488,8 @@ class HVMImageHandler(ImageHandler):
|
||||
args = args + ([ "-d", "%d" % self.vm.getDomid(),
|
||||
"-m", "%s" % (self.getRequiredInitialReservation() / 1024)])
|
||||
args = args + self.dmargs
|
||||
if restore:
|
||||
args = args + ([ "-loadvm", "/tmp/xen.qemu-dm.%d" % self.vm.getDomid() ])
|
||||
env = dict(os.environ)
|
||||
if self.display:
|
||||
env['DISPLAY'] = self.display
|
||||
@@ -505,12 +508,16 @@ class HVMImageHandler(ImageHandler):
|
||||
self.register_reboot_feature_watch()
|
||||
self.pid = self.vm.gatherDom(('image/device-model-pid', int))
|
||||
|
||||
def destroy(self):
|
||||
def destroy(self, suspend = False):
|
||||
self.unregister_shutdown_watch()
|
||||
self.unregister_reboot_feature_watch();
|
||||
if self.pid:
|
||||
try:
|
||||
os.kill(self.pid, signal.SIGKILL)
|
||||
sig = signal.SIGKILL
|
||||
if suspend:
|
||||
log.info("use sigusr1 to signal qemu %d", self.pid)
|
||||
sig = signal.SIGUSR1
|
||||
os.kill(self.pid, sig)
|
||||
except OSError, exn:
|
||||
log.exception(exn)
|
||||
try:
|
||||
|
||||
@@ -33,9 +33,19 @@ _pygrub_path = {
|
||||
"SunOS": "/usr/lib/xen/bin/pygrub"
|
||||
}
|
||||
|
||||
_netback_type = {
|
||||
"SunOS": "SUNW_mac"
|
||||
}
|
||||
|
||||
_vif_script = {
|
||||
"SunOS": "vif-vnic"
|
||||
}
|
||||
|
||||
def _get(var, default=None):
|
||||
return var.get(os.uname()[0], default)
|
||||
|
||||
scripts_dir = _get(_scripts_dir, "/etc/xen/scripts")
|
||||
xend_autorestart = _get(_xend_autorestart)
|
||||
pygrub_path = _get(_pygrub_path, "/usr/bin/pygrub")
|
||||
netback_type = _get(_netback_type, "netfront")
|
||||
vif_script = _get(_vif_script, "vif-bridge")
|
||||
@@ -19,7 +19,7 @@
|
||||
from threading import Event
|
||||
import types
|
||||
|
||||
from xen.xend import sxp, XendRoot
|
||||
from xen.xend import sxp, XendOptions
|
||||
from xen.xend.XendError import VmError
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
@@ -50,7 +50,7 @@ xenbusState = {
|
||||
'Closed' : 6,
|
||||
}
|
||||
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
xenbusState.update(dict(zip(xenbusState.values(), xenbusState.keys())))
|
||||
|
||||
@@ -324,7 +324,7 @@ class DevController:
|
||||
Make sure that the migration has finished and only
|
||||
then return from the call.
|
||||
"""
|
||||
tool = xroot.get_external_migration_tool()
|
||||
tool = xoptions.get_external_migration_tool()
|
||||
if tool:
|
||||
log.info("Calling external migration tool for step %d" % step)
|
||||
fd = os.popen("%s -type %s -step %d -host %s -domname %s" %
|
||||
@@ -341,7 +341,7 @@ class DevController:
|
||||
""" Recover from device migration. The given step was the
|
||||
last one that was successfully executed.
|
||||
"""
|
||||
tool = xroot.get_external_migration_tool()
|
||||
tool = xoptions.get_external_migration_tool()
|
||||
if tool:
|
||||
log.info("Calling external migration tool")
|
||||
fd = os.popen("%s -type %s -step %d -host %s -domname %s -recover" %
|
||||
|
||||
@@ -25,7 +25,7 @@ class SrvRoot(SrvDir):
|
||||
"""Server sub-components. Each entry is (name, class), where
|
||||
'name' is the entry name and 'class' is the name of its class.
|
||||
"""
|
||||
#todo Get this list from the XendRoot config.
|
||||
#todo Get this list from the XendOptions config.
|
||||
subdirs = [
|
||||
('node', 'SrvNode' ),
|
||||
('domain', 'SrvDomainDir' ),
|
||||
|
||||
@@ -48,7 +48,7 @@ from threading import Thread
|
||||
|
||||
from xen.web.httpserver import HttpServer, UnixHttpServer
|
||||
|
||||
from xen.xend import XendNode, XendRoot, XendAPI
|
||||
from xen.xend import XendNode, XendOptions, XendAPI
|
||||
from xen.xend import Vifctl
|
||||
from xen.xend.XendLogging import log
|
||||
from xen.xend.XendClient import XEN_API_SOCKET
|
||||
@@ -57,7 +57,7 @@ from xen.web.SrvDir import SrvDir
|
||||
from SrvRoot import SrvRoot
|
||||
from XMLRPCServer import XMLRPCServer
|
||||
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
|
||||
class XendServers:
|
||||
@@ -65,6 +65,7 @@ class XendServers:
|
||||
def __init__(self, root):
|
||||
self.servers = []
|
||||
self.root = root
|
||||
self.running = False
|
||||
self.cleaningUp = False
|
||||
self.reloadingConfig = False
|
||||
|
||||
@@ -79,6 +80,7 @@ class XendServers:
|
||||
server.shutdown()
|
||||
except:
|
||||
pass
|
||||
self.running = False
|
||||
|
||||
def reloadConfig(self, signum = 0, frame = None):
|
||||
log.debug("SrvServer.reloadConfig()")
|
||||
@@ -107,13 +109,12 @@ class XendServers:
|
||||
if server.ready:
|
||||
continue
|
||||
|
||||
thread = Thread(target=server.run, name=server.__class__.__name__)
|
||||
if isinstance(server, HttpServer):
|
||||
thread.setDaemon(True)
|
||||
thread = Thread(target=server.run,
|
||||
name=server.__class__.__name__)
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
|
||||
|
||||
# check for when all threads have initialized themselves and then
|
||||
# close the status pipe
|
||||
|
||||
@@ -143,47 +144,32 @@ class XendServers:
|
||||
status.close()
|
||||
status = None
|
||||
|
||||
# Interruptible Thread.join - Python Bug #1167930
|
||||
# Replaces: for t in threads: t.join()
|
||||
# Reason: The above will cause python signal handlers to be
|
||||
# blocked so we're not able to catch SIGTERM in any
|
||||
# way for cleanup
|
||||
runningThreads = threads
|
||||
while len(runningThreads) > 0:
|
||||
try:
|
||||
for t in threads:
|
||||
t.join(1.0)
|
||||
runningThreads = [t for t in threads
|
||||
if t.isAlive() and not t.isDaemon()]
|
||||
if self.cleaningUp and len(runningThreads) > 0:
|
||||
log.debug("Waiting for %s." %
|
||||
[x.getName() for x in runningThreads])
|
||||
except:
|
||||
pass
|
||||
|
||||
# loop to keep main thread alive until it receives a SIGTERM
|
||||
self.running = True
|
||||
while self.running:
|
||||
time.sleep(100000000)
|
||||
|
||||
if self.reloadingConfig:
|
||||
log.info("Restarting all XML-RPC and Xen-API servers...")
|
||||
self.cleaningUp = False
|
||||
self.reloadingConfig = False
|
||||
xroot.set_config()
|
||||
new_servers = [x for x in self.servers
|
||||
if isinstance(x, HttpServer)]
|
||||
self.servers = new_servers
|
||||
xoptions.set_config()
|
||||
self.servers = []
|
||||
_loadConfig(self, self.root, True)
|
||||
else:
|
||||
break
|
||||
|
||||
def _loadConfig(servers, root, reload):
|
||||
if not reload and xroot.get_xend_http_server():
|
||||
if xoptions.get_xend_http_server():
|
||||
servers.add(HttpServer(root,
|
||||
xroot.get_xend_address(),
|
||||
xroot.get_xend_port()))
|
||||
if not reload and xroot.get_xend_unix_server():
|
||||
path = xroot.get_xend_unix_path()
|
||||
xoptions.get_xend_address(),
|
||||
xoptions.get_xend_port()))
|
||||
if xoptions.get_xend_unix_server():
|
||||
path = xoptions.get_xend_unix_path()
|
||||
log.info('unix path=' + path)
|
||||
servers.add(UnixHttpServer(root, path))
|
||||
|
||||
api_cfg = xroot.get_xen_api_server()
|
||||
api_cfg = xoptions.get_xen_api_server()
|
||||
if api_cfg:
|
||||
try:
|
||||
addrs = [(str(x[0]).split(':'),
|
||||
@@ -218,10 +204,10 @@ def _loadConfig(servers, root, reload):
|
||||
except TypeError, exn:
|
||||
log.error('Xen-API server configuration %s is invalid.', api_cfg)
|
||||
|
||||
if xroot.get_xend_tcp_xmlrpc_server():
|
||||
if xoptions.get_xend_tcp_xmlrpc_server():
|
||||
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False, True))
|
||||
|
||||
if xroot.get_xend_unix_xmlrpc_server():
|
||||
if xoptions.get_xend_unix_xmlrpc_server():
|
||||
servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False))
|
||||
|
||||
|
||||
|
||||
@@ -179,21 +179,24 @@ class XMLRPCServer:
|
||||
# Custom runloop so we can cleanup when exiting.
|
||||
# -----------------------------------------------------------------
|
||||
try:
|
||||
self.server.socket.settimeout(1.0)
|
||||
while self.running:
|
||||
self.server.handle_request()
|
||||
finally:
|
||||
self.cleanup()
|
||||
self.shutdown()
|
||||
|
||||
def cleanup(self):
|
||||
log.debug("XMLRPCServer.cleanup()")
|
||||
log.debug('XMLRPCServer.cleanup()')
|
||||
try:
|
||||
self.server.socket.close()
|
||||
if hasattr(self, 'server'):
|
||||
# shutdown socket explicitly to allow reuse
|
||||
self.server.socket.shutdown(socket.SHUT_RDWR)
|
||||
self.server.socket.close()
|
||||
except Exception, exn:
|
||||
log.exception(exn)
|
||||
pass
|
||||
|
||||
def shutdown(self):
|
||||
self.running = False
|
||||
self.ready = False
|
||||
|
||||
if self.ready:
|
||||
self.ready = False
|
||||
self.cleanup()
|
||||
@@ -24,10 +24,10 @@ import os
|
||||
import random
|
||||
import re
|
||||
|
||||
from xen.xend import XendRoot
|
||||
from xen.xend import XendOptions
|
||||
from xen.xend.server.DevController import DevController
|
||||
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
def randomMAC():
|
||||
"""Generate a random MAC address.
|
||||
@@ -138,8 +138,8 @@ class NetifController(DevController):
|
||||
def getDeviceDetails(self, config):
|
||||
"""@see DevController.getDeviceDetails"""
|
||||
|
||||
script = os.path.join(xroot.network_script_dir,
|
||||
config.get('script', xroot.get_vif_script()))
|
||||
script = os.path.join(xoptions.network_script_dir,
|
||||
config.get('script', xoptions.get_vif_script()))
|
||||
typ = config.get('type')
|
||||
bridge = config.get('bridge')
|
||||
mac = config.get('mac')
|
||||
@@ -150,9 +150,8 @@ class NetifController(DevController):
|
||||
|
||||
devid = self.allocateDeviceID()
|
||||
|
||||
# The default type is 'netfront'.
|
||||
if not typ:
|
||||
typ = 'netfront'
|
||||
typ = xoptions.netback_type
|
||||
|
||||
if not mac:
|
||||
mac = randomMAC()
|
||||
@@ -190,7 +189,7 @@ class NetifController(DevController):
|
||||
(script, ip, bridge, mac, typ, vifname, rate, uuid) = devinfo
|
||||
|
||||
if script:
|
||||
network_script_dir = xroot.network_script_dir + os.sep
|
||||
network_script_dir = xoptions.network_script_dir + os.sep
|
||||
result['script'] = script.replace(network_script_dir, "")
|
||||
if ip:
|
||||
result['ip'] = ip
|
||||
|
||||
@@ -24,7 +24,7 @@ from xen.web import protocol, tcp, unix
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import XendDomain
|
||||
from xen.xend import XendRoot
|
||||
from xen.xend import XendOptions
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
@@ -114,15 +114,15 @@ class RelocationProtocol(protocol.Protocol):
|
||||
|
||||
|
||||
def listenRelocation():
|
||||
xroot = XendRoot.instance()
|
||||
if xroot.get_xend_unix_server():
|
||||
xoptions = XendOptions.instance()
|
||||
if xoptions.get_xend_unix_server():
|
||||
path = '/var/lib/xend/relocation-socket'
|
||||
unix.UnixListener(path, RelocationProtocol)
|
||||
if xroot.get_xend_relocation_server():
|
||||
port = xroot.get_xend_relocation_port()
|
||||
interface = xroot.get_xend_relocation_address()
|
||||
if xoptions.get_xend_relocation_server():
|
||||
port = xoptions.get_xend_relocation_port()
|
||||
interface = xoptions.get_xend_relocation_address()
|
||||
|
||||
hosts_allow = xroot.get_xend_relocation_hosts_allow()
|
||||
hosts_allow = xoptions.get_xend_relocation_hosts_allow()
|
||||
if hosts_allow == '':
|
||||
hosts_allow = None
|
||||
else:
|
||||
|
||||
@@ -2,9 +2,9 @@ import os
|
||||
import re
|
||||
import unittest
|
||||
|
||||
import xen.xend.XendRoot
|
||||
import xen.xend.XendOptions
|
||||
|
||||
xen.xend.XendRoot.XendRoot.config_default = '/dev/null'
|
||||
xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
|
||||
|
||||
from xen.xend.server import netif
|
||||
|
||||
@@ -13,7 +13,7 @@ FAKE_DOMID = 42
|
||||
FAKE_DEVID = 63
|
||||
|
||||
|
||||
xroot = xen.xend.XendRoot.instance()
|
||||
xoptions = xen.xend.XendOptions.instance()
|
||||
|
||||
|
||||
class test_controllers(unittest.TestCase):
|
||||
@@ -36,8 +36,8 @@ class test_controllers(unittest.TestCase):
|
||||
|
||||
self.assertEqual(backdets['handle'], str(FAKE_DEVID))
|
||||
self.assertEqual(backdets['script'],
|
||||
os.path.join(xroot.network_script_dir,
|
||||
xroot.get_vif_script()))
|
||||
os.path.join(xoptions.network_script_dir,
|
||||
xoptions.get_vif_script()))
|
||||
self.assertValidMac(backdets['mac'], expectedMac)
|
||||
|
||||
self.assertEqual(frontdets['handle'], str(FAKE_DEVID))
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
"""Support for virtual TPM interfaces."""
|
||||
|
||||
from xen.xend import XendRoot
|
||||
from xen.xend import XendOptions
|
||||
from xen.xend.XendLogging import log
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend.XendConstants import DEV_MIGRATE_TEST, VTPM_DELETE_SCRIPT
|
||||
@@ -29,7 +29,7 @@ from xen.xend.server.DevController import DevController
|
||||
import os
|
||||
import re
|
||||
|
||||
xroot = XendRoot.instance()
|
||||
xoptions = XendOptions.instance()
|
||||
|
||||
def destroy_vtpmstate(name):
|
||||
if os.path.exists(VTPM_DELETE_SCRIPT):
|
||||
@@ -88,7 +88,7 @@ class TPMifController(DevController):
|
||||
def migrate(self, deviceConfig, network, dst, step, domName):
|
||||
"""@see DevContoller.migrate"""
|
||||
if network:
|
||||
tool = xroot.get_external_migration_tool()
|
||||
tool = xoptions.get_external_migration_tool()
|
||||
if tool != '':
|
||||
log.info("Request to network-migrate device to %s. step=%d.",
|
||||
dst, step)
|
||||
@@ -116,7 +116,7 @@ class TPMifController(DevController):
|
||||
def recover_migrate(self, deviceConfig, network, dst, step, domName):
|
||||
"""@see DevContoller.recover_migrate"""
|
||||
if network:
|
||||
tool = xroot.get_external_migration_tool()
|
||||
tool = xoptions.get_external_migration_tool()
|
||||
if tool != '':
|
||||
log.info("Request to recover network-migrated device. last good step=%d.",
|
||||
step)
|
||||
|
||||
@@ -52,7 +52,7 @@ class VfbifController(DevController):
|
||||
if config.has_key("vncpasswd"):
|
||||
passwd = config["vncpasswd"]
|
||||
else:
|
||||
passwd = xen.xend.XendRoot.instance().get_vncpasswd_default()
|
||||
passwd = xen.xend.XendOptions.instance().get_vncpasswd_default()
|
||||
if passwd:
|
||||
self.vm.storeVm("vncpasswd", passwd)
|
||||
log.debug("Stored a VNC password for vfb access")
|
||||
@@ -66,7 +66,7 @@ class VfbifController(DevController):
|
||||
elif config.has_key("vncdisplay"):
|
||||
args += ["--vncport", "%d" % (5900 + int(config["vncdisplay"]))]
|
||||
vnclisten = config.get("vnclisten",
|
||||
xen.xend.XendRoot.instance().get_vnclisten_address())
|
||||
xen.xend.XendOptions.instance().get_vnclisten_address())
|
||||
args += [ "--listen", vnclisten ]
|
||||
spawn_detached(args[0], args + std_args, os.environ)
|
||||
elif t == "sdl":
|
||||
|
||||
@@ -190,6 +190,10 @@ gopts.var('vcpus', val='VCPUS',
|
||||
fn=set_int, default=1,
|
||||
use="# of Virtual CPUS in domain.")
|
||||
|
||||
gopts.var('vcpu_avail', val='VCPUS',
|
||||
fn=set_long, default=None,
|
||||
use="Bitmask for virtual CPUs to make available immediately.")
|
||||
|
||||
gopts.var('cpu_cap', val='CAP',
|
||||
fn=set_int, default=None,
|
||||
use="""Set the maximum amount of cpu.
|
||||
@@ -740,7 +744,7 @@ def make_config(vals):
|
||||
|
||||
map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
|
||||
'restart', 'on_poweroff',
|
||||
'on_reboot', 'on_crash', 'vcpus', 'features',
|
||||
'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
|
||||
'on_xend_start', 'on_xend_stop'])
|
||||
|
||||
if vals.uuid is not None:
|
||||
|
||||
@@ -693,12 +693,15 @@ def parse_doms_info(info):
|
||||
up_time = time.time() - start_time
|
||||
|
||||
return {
|
||||
'domid' : get_info('domid', str, ''),
|
||||
'name' : get_info('name', str, '??'),
|
||||
'domid' : get_info('domid', str, ''),
|
||||
'name' : get_info('name', str, '??'),
|
||||
'mem' : get_info('memory_dynamic_min', int, 0),
|
||||
'vcpus' : get_info('online_vcpus', int, 0),
|
||||
'state' : get_info('state', str, ''),
|
||||
'cpu_time' : get_info('cpu_time', float, 0),
|
||||
'state' : get_info('state', str, ''),
|
||||
'cpu_time' : get_info('cpu_time', float, 0.0),
|
||||
# VCPUs is the number online when the VM is up, or the number
|
||||
# configured otherwise.
|
||||
'vcpus' : get_info('online_vcpus', int,
|
||||
get_info('vcpus', int, 0)),
|
||||
'up_time' : up_time,
|
||||
'seclabel' : security.get_security_printlabel(info),
|
||||
}
|
||||
|
||||
@@ -571,6 +571,14 @@ def set_int(opt, k, v):
|
||||
opt.opts.err('Invalid value: ' + str(v))
|
||||
opt.set(v)
|
||||
|
||||
def set_long(opt, k, v):
|
||||
"""Set an option to a long integer value."""
|
||||
try:
|
||||
v = long(v)
|
||||
except:
|
||||
opt.opts.err('Invalid value: ' + str(v))
|
||||
opt.set(v)
|
||||
|
||||
def set_float(opt, k, v):
|
||||
"""Set an option to a float value."""
|
||||
try:
|
||||
|
||||
@@ -3,9 +3,9 @@ import os.path
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import xen.xend.XendRoot
|
||||
import xen.xend.XendOptions
|
||||
|
||||
xen.xend.XendRoot.XendRoot.config_default = '/dev/null'
|
||||
xen.xend.XendOptions.XendOptions.config_default = '/dev/null'
|
||||
|
||||
import xen.xm.create
|
||||
|
||||
|
||||