This commit is contained in:
djm@kirby.fc.hp.com committed 2005-10-24 09:08:13 -06:00
commit 8250e0c500
284 files changed
+8817 -8898

No files matched your search

+237 -137
View File
@@ -42,7 +42,7 @@ static PyObject *pyxc_domain_dumpcore(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
char *corefile;
static char *kwd_list[] = { "dom", "corefile", NULL };
@@ -77,29 +77,73 @@ static PyObject *pyxc_domain_create(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom = 0;
int ret;
u32 ssidref = 0x0;
uint32_t dom = 0;
int ret, i;
uint32_t ssidref = 0;
PyObject *pyhandle = NULL;
xen_domain_handle_t handle = {
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef };
static char *kwd_list[] = { "dom", "ssidref", NULL };
static char *kwd_list[] = { "dom", "ssidref", "handle", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwd_list,
&dom, &ssidref))
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiO", kwd_list,
&dom, &ssidref, &pyhandle))
return NULL;
if ( (ret = xc_domain_create(xc->xc_handle, ssidref, &dom)) < 0 )
if ( pyhandle != NULL )
{
if ( !PyList_Check(pyhandle) ||
(PyList_Size(pyhandle) != sizeof(xen_domain_handle_t)) )
{
out_exception:
errno = EINVAL;
PyErr_SetFromErrno(xc_error);
return NULL;
}
for ( i = 0; i < sizeof(xen_domain_handle_t); i++ )
{
PyObject *p = PyList_GetItem(pyhandle, i);
if ( !PyInt_Check(p) )
goto out_exception;
handle[i] = (uint8_t)PyInt_AsLong(p);
}
}
if ( (ret = xc_domain_create(xc->xc_handle, ssidref, handle, &dom)) < 0 )
return PyErr_SetFromErrno(xc_error);
return PyInt_FromLong(dom);
}
static PyObject *pyxc_domain_max_vcpus(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
uint32_t dom, max;
static char *kwd_list[] = { "dom", "max", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, &dom, &max) )
return NULL;
if ( xc_domain_max_vcpus(xc->xc_handle, dom, max) != 0 )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
return zero;
}
static PyObject *pyxc_domain_pause(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
static char *kwd_list[] = { "dom", NULL };
@@ -119,7 +163,7 @@ static PyObject *pyxc_domain_unpause(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
static char *kwd_list[] = { "dom", NULL };
@@ -139,7 +183,7 @@ static PyObject *pyxc_domain_destroy(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
static char *kwd_list[] = { "dom", NULL };
@@ -159,17 +203,25 @@ static PyObject *pyxc_domain_pincpu(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
int vcpu = 0;
cpumap_t cpumap = 0xFFFFFFFF;
uint32_t dom;
int vcpu = 0, i;
cpumap_t cpumap = ~0ULL;
PyObject *cpulist = NULL;
static char *kwd_list[] = { "dom", "vcpu", "cpumap", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
&dom, &vcpu, &cpumap) )
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|iO", kwd_list,
&dom, &vcpu, &cpulist) )
return NULL;
if ( xc_domain_pincpu(xc->xc_handle, dom, vcpu, &cpumap) != 0 )
if ( (cpulist != NULL) && PyList_Check(cpulist) )
{
cpumap = 0ULL;
for ( i = 0; i < PyList_Size(cpulist); i++ )
cpumap |= (cpumap_t)1 << PyInt_AsLong(PyList_GetItem(cpulist, i));
}
if ( xc_domain_pincpu(xc->xc_handle, dom, vcpu, cpumap) != 0 )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
@@ -182,7 +234,7 @@ static PyObject *pyxc_domain_setcpuweight(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
float cpuweight = 1;
static char *kwd_list[] = { "dom", "cpuweight", NULL };
@@ -198,14 +250,55 @@ static PyObject *pyxc_domain_setcpuweight(PyObject *self,
return zero;
}
static PyObject *pyxc_domain_sethandle(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
int i;
uint32_t dom;
PyObject *pyhandle;
xen_domain_handle_t handle;
static char *kwd_list[] = { "dom", "handle", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iO", kwd_list,
&dom, &pyhandle) )
return NULL;
if ( !PyList_Check(pyhandle) ||
(PyList_Size(pyhandle) != sizeof(xen_domain_handle_t)) )
{
out_exception:
errno = EINVAL;
PyErr_SetFromErrno(xc_error);
return NULL;
}
for ( i = 0; i < sizeof(xen_domain_handle_t); i++ )
{
PyObject *p = PyList_GetItem(pyhandle, i);
if ( !PyInt_Check(p) )
goto out_exception;
handle[i] = (uint8_t)PyInt_AsLong(p);
}
if ( xc_domain_sethandle(xc->xc_handle, dom, handle) < 0 )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
return zero;
}
static PyObject *pyxc_domain_getinfo(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
PyObject *list, *vcpu_list, *cpumap_list, *info_dict;
PyObject *list, *info_dict;
u32 first_dom = 0;
uint32_t first_dom = 0;
int max_doms = 1024, nr_doms, i, j;
xc_dominfo_t *info;
@@ -229,19 +322,14 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
list = PyList_New(nr_doms);
for ( i = 0 ; i < nr_doms; i++ )
{
vcpu_list = PyList_New(MAX_VIRT_CPUS);
cpumap_list = PyList_New(MAX_VIRT_CPUS);
for ( j = 0; j < MAX_VIRT_CPUS; j++ ) {
PyList_SetItem( vcpu_list, j,
Py_BuildValue("i", info[i].vcpu_to_cpu[j]));
PyList_SetItem( cpumap_list, j,
Py_BuildValue("i", info[i].cpumap[j]));
}
info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
PyObject *pyhandle = PyList_New(sizeof(xen_domain_handle_t));
for ( j = 0; j < sizeof(xen_domain_handle_t); j++ )
PyList_SetItem(pyhandle, j, PyInt_FromLong(info[i].handle[j]));
info_dict = Py_BuildValue("{s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i,s:i"
",s:l,s:L,s:l,s:i,s:i}",
"dom", info[i].domid,
"vcpus", info[i].vcpus,
"online_vcpus", info[i].nr_online_vcpus,
"max_vcpu_id", info[i].max_vcpu_id,
"dying", info[i].dying,
"crashed", info[i].crashed,
"shutdown", info[i].shutdown,
@@ -253,10 +341,8 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
"maxmem_kb", info[i].max_memkb,
"ssidref", info[i].ssidref,
"shutdown_reason", info[i].shutdown_reason);
PyDict_SetItemString( info_dict, "vcpu_to_cpu", vcpu_list );
PyDict_SetItemString( info_dict, "cpumap", cpumap_list );
PyList_SetItem( list, i, info_dict);
PyDict_SetItemString(info_dict, "handle", pyhandle);
PyList_SetItem(list, i, info_dict);
}
free(info);
@@ -264,15 +350,57 @@ static PyObject *pyxc_domain_getinfo(PyObject *self,
return list;
}
static PyObject *pyxc_vcpu_getinfo(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
PyObject *info_dict, *cpulist;
uint32_t dom, vcpu = 0;
xc_vcpuinfo_t info;
int rc, i;
cpumap_t cpumap;
static char *kwd_list[] = { "dom", "vcpu", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
&dom, &vcpu) )
return NULL;
rc = xc_domain_get_vcpu_info(xc->xc_handle, dom, vcpu, &info);
if ( rc < 0 )
return PyErr_SetFromErrno(xc_error);
info_dict = Py_BuildValue("{s:i,s:i,s:i,s:L,s:i}",
"online", info.online,
"blocked", info.blocked,
"running", info.running,
"cpu_time", info.cpu_time,
"cpu", info.cpu);
cpumap = info.cpumap;
cpulist = PyList_New(0);
for ( i = 0; cpumap != 0; i++ )
{
if ( cpumap & 1 )
PyList_Append(cpulist, PyInt_FromLong(i));
cpumap >>= 1;
}
PyDict_SetItemString(info_dict, "cpumap", cpulist);
return info_dict;
}
static PyObject *pyxc_linux_build(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
char *image, *ramdisk = NULL, *cmdline = "";
int flags = 0, vcpus = 1;
int flags = 0;
int store_evtchn, console_evtchn;
unsigned long store_mfn = 0;
unsigned long console_mfn = 0;
@@ -280,19 +408,17 @@ static PyObject *pyxc_linux_build(PyObject *self,
static char *kwd_list[] = { "dom", "store_evtchn",
"console_evtchn", "image",
/* optional */
"ramdisk", "cmdline", "flags",
"vcpus", NULL };
"ramdisk", "cmdline", "flags", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssii", kwd_list,
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiis|ssi", kwd_list,
&dom, &store_evtchn,
&console_evtchn, &image,
/* optional */
&ramdisk, &cmdline, &flags,
&vcpus) )
&ramdisk, &cmdline, &flags) )
return NULL;
if ( xc_linux_build(xc->xc_handle, dom, image,
ramdisk, cmdline, flags, vcpus,
ramdisk, cmdline, flags,
store_evtchn, &store_mfn,
console_evtchn, &console_mfn) != 0 )
return PyErr_SetFromErrno(xc_error);
@@ -303,28 +429,28 @@ static PyObject *pyxc_linux_build(PyObject *self,
}
static PyObject *pyxc_vmx_build(PyObject *self,
PyObject *args,
PyObject *kwds)
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
char *image;
int control_evtchn, store_evtchn;
int flags = 0, vcpus = 1;
int control_evtchn, store_evtchn;
int vcpus = 1;
int memsize;
unsigned long store_mfn = 0;
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
"memsize", "image", "flags", "vcpus", NULL };
"memsize", "image", "vcpus", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisi", kwd_list,
&dom, &control_evtchn, &store_evtchn,
&memsize, &image, &flags, &vcpus) )
&memsize, &image, &vcpus) )
return NULL;
if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn,
flags, vcpus, store_evtchn, &store_mfn) != 0 )
vcpus, store_evtchn, &store_mfn) != 0 )
return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
@@ -373,10 +499,10 @@ static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
u32 mcuadv;
uint32_t dom;
uint32_t mcuadv;
int warpback;
s32 warpvalue;
int32_t warpvalue;
long long warpl;
long long warpu;
@@ -401,10 +527,10 @@ static PyObject *pyxc_bvtsched_domain_get(PyObject *self,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 dom;
u32 mcuadv;
uint32_t dom;
uint32_t mcuadv;
int warpback;
s32 warpvalue;
int32_t warpvalue;
long long warpl;
long long warpu;
@@ -432,7 +558,7 @@ static PyObject *pyxc_evtchn_alloc_unbound(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom, remote_dom;
uint32_t dom, remote_dom;
int port;
static char *kwd_list[] = { "dom", "remote_dom", NULL };
@@ -454,7 +580,7 @@ static PyObject *pyxc_evtchn_status(PyObject *self,
XcObject *xc = (XcObject *)self;
PyObject *dict;
u32 dom = DOMID_SELF;
uint32_t dom = DOMID_SELF;
int port, ret;
xc_evtchn_status_t status;
@@ -507,7 +633,7 @@ static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
int bus, dev, func, enable, ret;
static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
@@ -631,13 +757,13 @@ static PyObject *pyxc_xeninfo(PyObject *self,
static PyObject *pyxc_sedf_domain_set(PyObject *self,
PyObject *args,
PyObject *kwds)
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 domid;
u64 period, slice, latency;
u16 extratime, weight;
uint32_t domid;
uint64_t period, slice, latency;
uint16_t extratime, weight;
static char *kwd_list[] = { "dom", "period", "slice",
"latency", "extratime", "weight",NULL };
@@ -654,13 +780,13 @@ static PyObject *pyxc_sedf_domain_set(PyObject *self,
}
static PyObject *pyxc_sedf_domain_get(PyObject *self,
PyObject *args,
PyObject *kwds)
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 domid;
u64 period, slice,latency;
u16 weight, extratime;
uint32_t domid;
uint64_t period, slice,latency;
uint16_t weight, extratime;
static char *kwd_list[] = { "dom", NULL };
@@ -671,34 +797,13 @@ static PyObject *pyxc_sedf_domain_get(PyObject *self,
&slice,&latency,&extratime,&weight) )
return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i}",
return Py_BuildValue("{s:i,s:L,s:L,s:L,s:i,s:i}",
"domain", domid,
"period", period,
"slice", slice,
"latency", latency,
"extratime", extratime);
}
static PyObject *pyxc_shadow_control(PyObject *self,
PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
u32 dom;
int op=0;
static char *kwd_list[] = { "dom", "op", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
&dom, &op) )
return NULL;
if ( xc_shadow_control(xc->xc_handle, dom, op, NULL, 0, NULL) < 0 )
return PyErr_SetFromErrno(xc_error);
Py_INCREF(zero);
return zero;
"extratime", extratime,
"weight", weight);
}
static PyObject *pyxc_domain_setmaxmem(PyObject *self,
@@ -707,7 +812,7 @@ static PyObject *pyxc_domain_setmaxmem(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
unsigned int maxmem_kb;
static char *kwd_list[] = { "dom", "maxmem_kb", NULL };
@@ -729,7 +834,7 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
{
XcObject *xc = (XcObject *)self;
u32 dom;
uint32_t dom;
unsigned long mem_kb;
unsigned int extent_order = 0 , address_bits = 0;
unsigned long nr_extents;
@@ -752,23 +857,6 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self,
return zero;
}
static PyObject *pyxc_init_store(PyObject *self, PyObject *args,
PyObject *kwds)
{
XcObject *xc = (XcObject *)self;
int remote_port;
static char *kwd_list[] = { "remote_port", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list,
&remote_port) )
return NULL;
return PyInt_FromLong(xc_init_store(xc->xc_handle, remote_port));
}
static PyMethodDef pyxc_methods[] = {
{ "handle",
(PyCFunction)pyxc_handle,
@@ -783,6 +871,14 @@ static PyMethodDef pyxc_methods[] = {
" dom [int, 0]: Domain identifier to use (allocated if zero).\n"
"Returns: [int] new domain identifier; -1 on error.\n" },
{ "domain_max_vcpus",
(PyCFunction)pyxc_domain_max_vcpus,
METH_VARARGS | METH_KEYWORDS, "\n"
"Set the maximum number of VCPUs a domain may create.\n"
" dom [int, 0]: Domain identifier to use.\n"
" max [int, 0]: New maximum number of VCPUs in domain.\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_dumpcore",
(PyCFunction)pyxc_domain_dumpcore,
METH_VARARGS | METH_KEYWORDS, "\n"
@@ -818,7 +914,7 @@ static PyMethodDef pyxc_methods[] = {
"Pin a VCPU to a specified set CPUs.\n"
" dom [int]: Identifier of domain to which VCPU belongs.\n"
" vcpu [int, 0]: VCPU being pinned.\n"
" cpumap [int, -1]: Bitmap of usable CPUs.\n\n"
" cpumap [list, []]: list of usable CPUs.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_setcpuweight",
@@ -829,6 +925,14 @@ static PyMethodDef pyxc_methods[] = {
" cpuweight [float, 1]: VCPU being pinned.\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_sethandle",
(PyCFunction)pyxc_domain_sethandle,
METH_VARARGS | METH_KEYWORDS, "\n"
"Set domain's opaque handle.\n"
" dom [int]: Identifier of domain.\n"
" handle [list of 16 ints]: New opaque handle.\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_getinfo",
(PyCFunction)pyxc_domain_getinfo,
METH_VARARGS | METH_KEYWORDS, "\n"
@@ -852,8 +956,21 @@ static PyMethodDef pyxc_methods[] = {
" maxmem_kb [int]: Maximum memory limit, in kilobytes\n"
" cpu_time [long]: CPU time consumed, in nanoseconds\n"
" shutdown_reason [int]: Numeric code from guest OS, explaining "
"reason why it shut itself down.\n"
" vcpu_to_cpu [[int]]: List that maps VCPUS to CPUS\n" },
"reason why it shut itself down.\n" },
{ "vcpu_getinfo",
(PyCFunction)pyxc_vcpu_getinfo,
METH_VARARGS | METH_KEYWORDS, "\n"
"Get information regarding a VCPU.\n"
" dom [int]: Domain to retrieve info about.\n"
" vcpu [int, 0]: VCPU to retrieve info about.\n\n"
"Returns: [dict]\n"
" online [int]: Bool - Is this VCPU currently online?\n"
" blocked [int]: Bool - Is this VCPU blocked waiting for an event?\n"
" running [int]: Bool - Is this VCPU currently running on a CPU?\n"
" cpu_time [long]: CPU time consumed, in nanoseconds\n"
" cpumap [int]: Bitmap of CPUs this VCPU can run on\n"
" cpu [int]: CPU that this VCPU is currently bound to\n" },
{ "linux_build",
(PyCFunction)pyxc_linux_build,
@@ -869,12 +986,10 @@ static PyMethodDef pyxc_methods[] = {
{ "vmx_build",
(PyCFunction)pyxc_vmx_build,
METH_VARARGS | METH_KEYWORDS, "\n"
"Build a new Linux guest OS.\n"
"Build a new VMX guest OS.\n"
" dom [int]: Identifier of domain to build into.\n"
" image [str]: Name of kernel image file. May be gzipped.\n"
" memmap [str]: Memory map.\n\n"
" ramdisk [str, n/a]: Name of ramdisk file, if any.\n"
" cmdline [str, n/a]: Kernel parameters, if any.\n\n"
" image [str]: Name of VMX loader image file.\n"
" vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "bvtsched_global_set",
@@ -995,14 +1110,6 @@ static PyMethodDef pyxc_methods[] = {
"Returns [dict]: information about Xen"
" [None]: on failure.\n" },
{ "shadow_control",
(PyCFunction)pyxc_shadow_control,
METH_VARARGS | METH_KEYWORDS, "\n"
"Set parameter for shadow pagetable interface\n"
" dom [int]: Identifier of domain.\n"
" op [int, 0]: operation\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_setmaxmem",
(PyCFunction)pyxc_domain_setmaxmem,
METH_VARARGS | METH_KEYWORDS, "\n"
@@ -1019,13 +1126,6 @@ static PyMethodDef pyxc_methods[] = {
" mem_kb [long]: .\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "init_store",
(PyCFunction)pyxc_init_store,
METH_VARARGS | METH_KEYWORDS, "\n"
"Initialize the store event channel and return the store page mfn.\n"
" remote_port [int]: store event channel port number.\n"
"Returns: [int] mfn on success; <0 on error.\n" },
{ NULL, NULL, 0, NULL }
};
+14 -10
View File
@@ -28,6 +28,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <xenctrl.h>
#include "xs.h"
/** @file
@@ -512,6 +513,7 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
again:
Py_BEGIN_ALLOW_THREADS
xsval = xs_read_watch(xh, &num);
Py_END_ALLOW_THREADS
@@ -528,8 +530,13 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
break;
}
if (i == PyList_Size(xsh->watches)) {
PyErr_SetString(PyExc_RuntimeError, "invalid token");
goto exit;
/* We do not have a registered watch for the one that has just fired.
Ignore this -- a watch that has been recently deregistered can still
have watches in transit. This is a blocking method, so go back to
read again.
*/
free(xsval);
goto again;
}
/* Create tuple (path, token). */
val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
@@ -679,7 +686,6 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
" dom [int] : domain id\n" \
" page [long] : address of domain's xenstore page\n" \
" port [int] : port the domain is using for xenstore\n" \
" path [string]: path to the domain's data in xenstore\n" \
"\n" \
"Returns None on success.\n" \
"Raises RuntimeError on error.\n" \
@@ -688,12 +694,11 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
PyObject *kwds)
{
static char *kwd_spec[] = { "dom", "page", "port", "path", NULL };
static char *arg_spec = "iiis|";
static char *kwd_spec[] = { "dom", "page", "port", NULL };
static char *arg_spec = "iii";
domid_t dom = 0;
unsigned long page = 0;
unsigned int port = 0;
char *path = NULL;
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
@@ -702,10 +707,10 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&dom, &page, &port, &path))
&dom, &page, &port))
goto exit;
Py_BEGIN_ALLOW_THREADS
xsval = xs_introduce_domain(xh, dom, page, port, path);
xsval = xs_introduce_domain(xh, dom, page, port);
Py_END_ALLOW_THREADS
if (!xsval) {
PyErr_SetFromErrno(PyExc_RuntimeError);
@@ -790,11 +795,10 @@ static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
}
#define xspy_get_domain_path_doc "\n" \
"Return store path of domain.\n" \
"Return store path of domain, whether or not the domain exists.\n" \
" domid [int]: domain id\n" \
"\n" \
"Returns: [string] domain store path.\n" \
" None if domid doesn't exist.\n" \
"Raises RuntimeError on error.\n" \
"\n"
+5 -1
View File
@@ -19,6 +19,10 @@
LIB_BIN_32 = "/usr/lib/xen/bin"
LIB_BIN_64 = "/usr/lib64/xen/bin"
## The architectures on which the LIB_BIN_64 directory is used. This
# deliberately excludes ia64.
LIB_64_ARCHS = [ 'x86_64', 'ppc64', 's390x', 'sparc64']
import os
import os.path
@@ -38,7 +42,7 @@ def pathTo(exe):
def path():
machine = os.uname()[4]
if machine.find('64') != -1 and os.path.exists(LIB_BIN_64):
if machine in LIB_64_ARCHS and os.path.exists(LIB_BIN_64):
return LIB_BIN_64
else:
return LIB_BIN_32
+150
View File
@@ -0,0 +1,150 @@
# 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) 2005 XenSource Ltd
import re
import sys
from xen.xend import sxp
from xen.xend.XendClient import server
from xen.xend.XendError import XendError
from xen.xend.xenstore.xstransact import xstransact
import xen.xend.XendProtocol
domain = None
domid = None
deviceClass = None
device = None
frontendPath = None
backendPath = None
def diagnose(dom):
global domain
global domid
global dompath
try:
domain = server.xend_domain(dom)
state = sxp.child_value(domain, 'state')
domid = int(sxp.child_value(domain, 'domid'))
name = sxp.child_value(domain, 'name')
dompath = '/local/domain/%d' % domid
print "Domain ID is %d." % domid
print "Domain name is %s." % name
if not state:
raise XendError("Cannot find state")
if state.find('c') != -1:
print "Domain has crashed."
diagnose_console()
diagnose_devices()
except xen.xend.XendProtocol.XendError, exn:
print exn
def diagnose_console():
port = xstransact.Read(dompath + '/console/port')
ringref = xstransact.Read(dompath + '/console/ring-ref')
tty = xstransact.Read(dompath + '/console/tty')
if not port:
print "Console port is missing; Xend has failed."
if not ringref:
print "Console ring-ref is missing; Xend has failed."
if not tty:
print "Console tty is missing; Xenconsoled has failed."
def diagnose_devices():
global deviceClass
global device
global frontendPath
global backendPath
device_path = dompath + '/device'
device_classes = xstransact.List(device_path)
print "Found %d device classes in use." % len(device_classes)
for dc in device_classes:
deviceClass = dc
device_class_path = device_path + '/' + deviceClass
devices = xstransact.List(device_class_path)
print "Found %d %s devices." % (len(devices), deviceClass)
for d in devices:
device = d
print "Found device %s, %s." % (deviceClass, device)
frontendPath = device_class_path + '/' + device
backendPath = xstransact.Read(frontendPath, 'backend')
if not backendPath:
print ("Cannot find backend path for device %s, %s." %
(deviceClass, device))
else:
backend_error = xstransact.Read(
backendPath.replace('backend/', 'error/backend/'),
'error')
if backend_error:
diagnose_device_error(backend_error)
def diagnose_device_error(err):
if re.search("2 reading .*/ring-ref and event-channel", err):
print ("Backend is stuck waiting for frontend for device %s, %s." %
(deviceClass, device))
diagnose_stuck_frontend()
else:
print ("Device %s, %s shows error %s." %
(deviceClass, device, err))
def diagnose_stuck_frontend():
if deviceClass == "vbd":
phy = xstransact.Read(backendPath, 'physical-device')
if phy:
print ("Device %s, %s hotplugging has completed successfully." %
(deviceClass, device))
else:
print ("Device %s, %s hotplugging failed." %
(deviceClass, device))
def main(argv = None):
if argv is None:
argv = sys.argv
diagnose(argv[1])
return 0
if __name__ == "__main__":
sys.exit(main())
-39
View File
@@ -1,39 +0,0 @@
# Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
# os.system() replacement which outputs through the logger
import popen2
import select
import string
from xen.xend.XendLogging import log
def runscript(cmd):
# split after first space, then grab last component of path
cmdname = "[%s] " % cmd.split()[0].split('/')[-1]
# run command and grab stdin, stdout and stderr
cout, cin, cerr = popen2.popen3(cmd)
# close stdin to get command to terminate if it waits for input
cin.close()
# wait for output and process
p = select.poll()
p.register(cout)
p.register(cerr)
stdout = ""
while True:
r = p.poll()
for (fd, event) in r:
if event == select.POLLHUP:
cout.close()
cerr.close()
return stdout
if fd == cout.fileno():
stdout = stdout + cout.readline()
if fd == cerr.fileno():
l = cerr.readline()
if l[0] == '-':
log.debug(cmdname + l[1:].rstrip())
elif l[0] == '*':
log.info(cmdname + l[1:].rstrip())
else:
log.error(cmdname + l.rstrip())
+1 -1
View File
@@ -86,7 +86,7 @@ class SrvBase(resource.Resource):
except Exception, exn:
log.exception("Request %s failed.", op)
if req.useSxp():
return ['xend.err', "Exception: " + str(exn)]
return ['xend.err', str(exn)]
else:
return "<p>%s</p>" % str(exn)
+8 -78
View File
@@ -19,87 +19,17 @@
"""Xend interface to networking control scripts.
"""
import os
import os.path
import xen.util.process
from xen.xend import XendRoot
xroot = XendRoot.instance()
import XendRoot
"""Where network control scripts live."""
SCRIPT_DIR = xroot.network_script_dir
def network(op, script=None, bridge=None, antispoof=None):
def network(op):
"""Call a network control script.
Xend calls this with op 'start' when it starts.
@param op: operation (start, stop, status)
@param script: network script name
@param bridge: xen bridge
@param antispoof: whether to enable IP antispoofing rules
@param op: operation (start, stop)
"""
if op not in ['start', 'stop', 'status']:
raise ValueError('Invalid operation:' + op)
if script is None:
script = xroot.get_network_script()
if bridge is None:
bridge = xroot.get_vif_bridge()
if antispoof is None:
antispoof = xroot.get_vif_antispoof()
script = os.path.join(SCRIPT_DIR, script)
args = [op]
args.append("bridge='%s'" % bridge)
if antispoof:
args.append("antispoof=yes")
else:
args.append("antispoof=no")
args = ' '.join(args)
ret = xen.util.process.runscript(script + ' ' + args)
if len(ret):
return ret.splitlines()[0]
def set_vif_name(vif_old, vif_new):
if vif_old == vif_new:
vif = vif_new
return vif
if os.system("ip link show %s" % vif_old) == 0:
os.system("ip link set %s down" % vif_old)
os.system("ip link set %s name %s" % (vif_old, vif_new))
os.system("ip link set %s up" % vif_new)
if os.system("ip link show %s" % vif_new) == 0:
vif = vif_new
else:
vif = vif_old
return vif
def vifctl(op, vif=None, script=None, domain=None, mac=None, bridge=None, ipaddr=None):
"""Call a vif control script.
Xend calls this when bringing vifs up or down.
@param op: vif operation (up, down)
@param vif: vif name
@param script: name of control script
@param domain: name of domain the vif is on
@param mac: vif MAC address
@param bridge: bridge to add the vif to
@param ipaddr: list of ipaddrs the vif may use
"""
if op not in ['up', 'down']:
raise ValueError('Invalid operation:' + op)
if script is None:
script = xroot.get_vif_script()
if bridge is None:
bridge = xroot.get_vif_bridge()
script = os.path.join(SCRIPT_DIR, script)
args = [op]
args.append("vif='%s'" % vif)
args.append("domain='%s'" % domain)
args.append("mac='%s'" % mac)
if bridge:
args.append("bridge='%s'" % bridge)
if ipaddr:
ips = ' '.join(ipaddr)
args.append("ip='%s'" % ips)
args = ' '.join(args)
ret = xen.util.process.runscript(script + ' ' + args)
if len(ret):
return ret.splitlines()[0]
if op not in ['start', 'stop']:
raise ValueError('Invalid operation: ' + op)
script = XendRoot.instance().get_network_script()
if script:
os.spawnl(os.P_WAIT, script, script, op)
+34 -28
View File
@@ -118,9 +118,11 @@ def restore(xd, fd):
dominfo = xd.restore_(vmconfig)
assert dominfo.store_channel
assert dominfo.console_channel
assert dominfo.getDomainPath()
store_port = dominfo.getStorePort()
console_port = dominfo.getConsolePort()
assert store_port
assert console_port
try:
l = read_exact(fd, sizeof_unsigned_long,
@@ -130,34 +132,21 @@ def restore(xd, fd):
raise XendError(
"not a valid guest state file: pfn count out of range")
store_evtchn = dominfo.store_channel
console_evtchn = dominfo.console_channel
cmd = [xen.util.auxbin.pathTo(XC_RESTORE), str(xc.handle()), str(fd),
str(dominfo.getDomid()), str(nr_pfns),
str(store_evtchn), str(console_evtchn)]
cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE),
xc.handle(), fd, dominfo.getDomid(), nr_pfns,
store_port, console_port])
log.debug("[xc_restore]: %s", string.join(cmd))
def restoreInputHandler(line, _):
m = re.match(r"^(store-mfn) (\d+)$", line)
if m:
store_mfn = int(m.group(2))
dominfo.setStoreRef(store_mfn)
log.debug("IntroduceDomain %d %d %d %s",
dominfo.getDomid(),
store_mfn,
dominfo.store_channel,
dominfo.getDomainPath())
IntroduceDomain(dominfo.getDomid(),
store_mfn,
dominfo.store_channel,
dominfo.getDomainPath())
else:
m = re.match(r"^(console-mfn) (\d+)$", line)
if m:
dominfo.setConsoleRef(int(m.group(2)))
handler = RestoreInputHandler()
forkHelper(cmd, fd, restoreInputHandler, True)
forkHelper(cmd, fd, handler.handler, True)
if handler.store_mfn is None or handler.console_mfn is None:
raise XendError('Could not read store/console MFN')
dominfo.unpause()
dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
return dominfo
except:
@@ -165,12 +154,29 @@ def restore(xd, fd):
raise
class RestoreInputHandler:
def __init__(self):
self.store_mfn = None
self.console_mfn = None
def handler(self, line, _):
m = re.match(r"^(store-mfn) (\d+)$", line)
if m:
self.store_mfn = int(m.group(2))
else:
m = re.match(r"^(console-mfn) (\d+)$", line)
if m:
self.console_mfn = int(m.group(2))
def forkHelper(cmd, fd, inputHandler, closeToChild):
child = xPopen3(cmd, True, -1, [fd, xc.handle()])
if closeToChild:
child.tochild.close()
lasterr = "error unknown"
try:
fds = [child.fromchild.fileno(),
child.childerr.fileno()]
+12 -6
View File
@@ -199,6 +199,9 @@ class Xend:
def xend_list_domains(self):
return self.xendGet(self.domainurl(), {'detail': '1'})
def xend_domain_vcpuinfo(self, dom):
return self.xendGet(self.domainurl(dom), {'op': 'vcpuinfo'})
def xend_domain_create(self, conf):
return self.xendPost(self.domainurl(),
{'op' : 'create',
@@ -255,7 +258,7 @@ class Xend:
return self.xendPost(self.domainurl(id),
{'op' : 'pincpu',
'vcpu' : vcpu,
'cpumap' : cpumap })
'cpumap' : str(cpumap) })
def xend_domain_cpu_bvt_set(self, id, mcuadv, warpback, warpvalue, warpl, warpu):
return self.xendPost(self.domainurl(id),
@@ -266,6 +269,10 @@ class Xend:
'warpl' : warpl,
'warpu' : warpu })
def xend_domain_cpu_sedf_get(self, id):
return self.xendPost(self.domainurl(id),
{'op' : 'cpu_sedf_get'})
def xend_domain_cpu_sedf_set(self, id, period, slice, latency, extratime, weight):
return self.xendPost(self.domainurl(id),
{'op' : 'cpu_sedf_set',
@@ -286,11 +293,10 @@ class Xend:
'target' : mem_target })
return val
def xend_domain_vcpu_hotplug(self, id, vcpu, state):
return self.xendPost(self.domainurl(id),
{'op' : 'vcpu_hotplug',
'vcpu' : vcpu,
'state' : state })
def xend_domain_set_vcpus(self, dom, vcpus):
return self.xendPost(self.domainurl(dom),
{'op' : 'set_vcpus',
'vcpus' : vcpus })
def xend_domain_vif_limit(self, id, vif, credit, period):
return self.xendPost(self.domainurl(id),
+37 -37
View File
@@ -21,8 +21,10 @@
Nothing here is persistent (across reboots).
Needs to be persistent for one uptime.
"""
import os
import logging
import os
import sys
import threading
import xen.lowlevel.xc
@@ -57,13 +59,16 @@ class XendDomain:
# So we stuff the XendDomain instance (self) into xroot's components.
xroot.add_component("xen.xend.XendDomain", self)
self.domains = {}
self.domains_lock = threading.Condition()
self.domains_lock = threading.RLock()
self.watchReleaseDomain()
self.domains_lock.acquire()
try:
self.refresh(True)
self._add_domain(
XendDomainInfo.recreate(self.xen_domains()[PRIV_DOMAIN],
True))
self.dom0_setup()
self.refresh(True)
finally:
self.domains_lock.release()
@@ -129,7 +134,14 @@ class XendDomain:
def dom0_setup(self):
"""Expects to be protected by the domains_lock."""
dom0 = self.domains[PRIV_DOMAIN]
dom0.dom0_enforce_vcpus()
# get max number of vcpus to use for dom0 from config
target = int(xroot.get_dom0_vcpus())
log.debug("number of vcpus to use is %d", target)
# target == 0 means use all processors
if target > 0:
dom0.setVCpuCount(target)
def _add_domain(self, info):
@@ -171,25 +183,23 @@ class XendDomain:
'Cannot recreate information for dying domain %d.'
' Xend will ignore this domain from now on.',
doms[d]['dom'])
elif d == PRIV_DOMAIN:
log.fatal(
"No record of privileged domain %d! Terminating.", d)
sys.exit(1)
else:
try:
dominfo = XendDomainInfo.recreate(doms[d])
self._add_domain(dominfo)
self._add_domain(
XendDomainInfo.recreate(doms[d], False))
except:
if d == PRIV_DOMAIN:
log.exception(
"Failed to recreate information for domain "
"%d. Doing nothing except crossing my "
"fingers.", d)
else:
log.exception(
"Failed to recreate information for domain "
"%d. Destroying it in the hope of "
"recovery.", d)
try:
xc.domain_destroy(dom = d)
except:
log.exception('Destruction of %d failed.', d)
log.exception(
"Failed to recreate information for domain "
"%d. Destroying it in the hope of "
"recovery.", d)
try:
xc.domain_destroy(dom = d)
except:
log.exception('Destruction of %d failed.', d)
## public:
@@ -318,12 +328,6 @@ class XendDomain:
n = len(matching)
if n == 1:
return matching[0]
elif n > 1:
log.error('Name uniqueness has been violated for name %s! '
'Recovering by renaming:', name)
for d in matching:
d.renameUniquely()
return None
finally:
self.domains_lock.release()
@@ -343,7 +347,7 @@ class XendDomain:
dominfo = self.domain_lookup(domid)
log.info("Domain %s (%d) unpaused.", dominfo.getName(),
dominfo.getDomid())
return xc.domain_unpause(dom=dominfo.getDomid())
return dominfo.unpause()
except Exception, ex:
raise XendError(str(ex))
@@ -354,7 +358,7 @@ class XendDomain:
dominfo = self.domain_lookup(domid)
log.info("Domain %s (%d) paused.", dominfo.getName(),
dominfo.getDomid())
return xc.domain_pause(dom=dominfo.getDomid())
return dominfo.pause()
except Exception, ex:
raise XendError(str(ex))
@@ -408,9 +412,12 @@ class XendDomain:
def domain_pincpu(self, domid, vcpu, cpumap):
"""Set which cpus vcpu can use
@param cpumap: bitmap of usable cpus
@param cpumap: string repr of list of usable cpus
"""
dominfo = self.domain_lookup(domid)
# convert cpumap string into a list of ints
cpumap = map(lambda x: int(x),
cpumap.replace("[", "").replace("]", "").split(","))
try:
return xc.domain_pincpu(dominfo.getDomid(), vcpu, cpumap)
except Exception, ex:
@@ -469,14 +476,7 @@ class XendDomain:
if not dev:
raise XendError("invalid vif")
return dev.setCreditLimit(credit, period)
def domain_shadow_control(self, domid, op):
"""Shadow page control."""
dominfo = self.domain_lookup(domid)
try:
return xc.shadow_control(dominfo.getDomid(), op)
except Exception, ex:
raise XendError(str(ex))
def domain_maxmem_set(self, domid, mem):
"""Set the memory limit for a domain.
+259 -296
View File
@@ -24,10 +24,10 @@ Author: Mike Wray <mike.wray@hp.com>
"""
import logging
import string
import time
import threading
import errno
import xen.lowlevel.xc
from xen.util import asserts
@@ -38,11 +38,10 @@ from xen.xend import scheduler
from xen.xend import sxp
from xen.xend import XendRoot
from xen.xend.XendBootloader import bootloader
from xen.xend.XendLogging import log
from xen.xend.XendError import XendError, VmError
from xen.xend.XendRoot import get_component
from uuid import getUuid
import uuid
from xen.xend.xenstore.xstransact import xstransact
from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
@@ -78,30 +77,26 @@ restart_modes = [
"rename-restart"
]
STATE_VM_OK = "ok"
STATE_VM_TERMINATED = "terminated"
"""Flag for a block device backend domain."""
SIF_BLK_BE_DOMAIN = (1<<4)
"""Flag for a net device backend domain."""
SIF_NET_BE_DOMAIN = (1<<5)
"""Flag for a TPM device backend domain."""
SIF_TPM_BE_DOMAIN = (1<<7)
STATE_DOM_OK = 1
STATE_DOM_SHUTDOWN = 2
SHUTDOWN_TIMEOUT = 30
DOMROOT = '/local/domain/'
VMROOT = '/vm/'
ZOMBIE_PREFIX = 'Zombie-'
"""Minimum time between domain restarts in seconds."""
MINIMUM_RESTART_TIME = 20
xc = xen.lowlevel.xc.new()
xroot = XendRoot.instance()
log = logging.getLogger("xend.XendDomainInfo")
#log.setLevel(logging.TRACE)
## Configuration entries that we expect to round-trip -- be read from the
# config file or xc, written to save-files (i.e. through sxpr), and reused as
@@ -111,6 +106,7 @@ xroot = XendRoot.instance()
# file, so those are handled separately.
ROUNDTRIPPING_CONFIG_ENTRIES = [
('name', str),
('uuid', str),
('ssidref', int),
('vcpus', int),
('vcpu_avail', int),
@@ -130,8 +126,6 @@ ROUNDTRIPPING_CONFIG_ENTRIES = [
# its VCPUs. This is translated to
# <dompath>/cpu/<id>/availability = {online,offline} for use
# by the guest domain.
# vcpu_to_cpu: the current mapping between virtual CPUs and the physical
# CPU it is using.
# 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
@@ -152,12 +146,10 @@ def create(config):
log.debug("XendDomainInfo.create(%s)", config)
vm = XendDomainInfo(getUuid(), parseConfig(config))
vm = XendDomainInfo(parseConfig(config))
try:
vm.construct()
vm.initDomain()
vm.construct_image()
vm.configure()
vm.storeVmDetails()
vm.storeDomDetails()
vm.refreshShutdown()
@@ -168,7 +160,7 @@ def create(config):
raise
def recreate(xeninfo):
def recreate(xeninfo, priv):
"""Create the VM object for an existing domain. The domain must not
be dying, as the paths in the store should already have been removed,
and asking us to recreate them causes problems."""
@@ -178,40 +170,43 @@ def recreate(xeninfo):
assert not xeninfo['dying']
domid = xeninfo['dom']
uuid1 = xeninfo['handle']
xeninfo['uuid'] = uuid.toString(uuid1)
dompath = GetDomainPath(domid)
if not dompath:
raise XendError(
'No domain path in store for existing domain %d' % domid)
log.info("Recreating domain %d, UUID %s.", domid, xeninfo['uuid'])
try:
dompath = GetDomainPath(domid)
if not dompath:
raise XendError(
'No domain path in store for existing domain %d' % domid)
vmpath = xstransact.Read(dompath, "vm")
if not vmpath:
raise XendError(
'No vm path in store for existing domain %d' % domid)
uuid = xstransact.Read(vmpath, "uuid")
if not uuid:
uuid2_str = xstransact.Read(vmpath, "uuid")
if not uuid2_str:
raise XendError(
'No vm/uuid path in store for existing domain %d' % domid)
log.info("Recreating domain %d, UUID %s.", domid, uuid)
uuid2 = uuid.fromString(uuid2_str)
vm = XendDomainInfo(uuid, xeninfo, domid, True)
if uuid1 != uuid2:
raise XendError(
'Uuid in store does not match uuid for existing domain %d: '
'%s != %s' % (domid, uuid2_str, xeninfo['uuid']))
vm = XendDomainInfo(xeninfo, domid, dompath, True)
except Exception, exn:
log.warn(str(exn))
if priv:
log.warn(str(exn))
uuid = getUuid()
log.info("Recreating domain %d with new UUID %s.", domid, uuid)
vm = XendDomainInfo(uuid, xeninfo, domid, True)
vm = XendDomainInfo(xeninfo, domid, dompath, True)
vm.removeDom()
vm.removeVm()
vm.storeVmDetails()
vm.storeDomDetails()
vm.create_channel()
if domid == 0:
vm.initStoreConnection()
vm.refreshShutdown(xeninfo)
return vm
@@ -224,15 +219,13 @@ def restore(config):
log.debug("XendDomainInfo.restore(%s)", config)
uuid = sxp.child_value(config, 'uuid')
vm = XendDomainInfo(uuid, parseConfig(config))
vm = XendDomainInfo(parseConfig(config))
try:
vm.construct()
vm.configure()
vm.create_channel()
vm.storeVmDetails()
vm.createDevices()
vm.createChannels()
vm.storeDomDetails()
vm.refreshShutdown()
return vm
except:
vm.destroy()
@@ -293,7 +286,7 @@ def parseConfig(config):
restart = get_cfg('restart')
if restart:
def handle_restart(event, val):
if not event in result:
if result[event] is None:
result[event] = val
if restart == "onreboot":
@@ -346,19 +339,16 @@ def dom_get(dom):
log.debug("domain_getinfo(%d) failed, ignoring: %s", dom, str(err))
return None
class XendDomainInfo:
"""Virtual machine object."""
"""Minimum time between domain restarts in seconds.
"""
MINIMUM_RESTART_TIME = 20
def __init__(self, info, domid = None, dompath = None, augment = False):
def __init__(self, uuid, info, domid = None, augment = False):
self.uuid = uuid
self.info = info
if not self.infoIsSet('uuid'):
self.info['uuid'] = uuid.toString(uuid.create())
if domid is not None:
self.domid = domid
elif 'dom' in info:
@@ -366,11 +356,8 @@ class XendDomainInfo:
else:
self.domid = None
self.vmpath = VMROOT + uuid
if self.domid is None:
self.dompath = None
else:
self.dompath = DOMROOT + str(self.domid)
self.vmpath = VMROOT + self.info['uuid']
self.dompath = dompath
if augment:
self.augmentInfo()
@@ -379,16 +366,18 @@ class XendDomainInfo:
self.image = None
self.store_channel = None
self.store_port = None
self.store_mfn = None
self.console_channel = None
self.console_port = None
self.console_mfn = None
self.state = STATE_VM_OK
self.state = STATE_DOM_OK
self.state_updated = threading.Condition()
self.refresh_shutdown_lock = threading.Condition()
## private:
def augmentInfo(self):
"""Augment self.info, as given to us through {@link #recreate}, with
values taken from the store. This recovers those values known to xend
@@ -436,7 +425,10 @@ class XendDomainInfo:
defaultInfo('on_crash', lambda: "restart")
defaultInfo('cpu', lambda: None)
defaultInfo('cpu_weight', lambda: 1.0)
defaultInfo('vcpus', lambda: 1)
defaultInfo('vcpus', lambda: int(1))
self.info['vcpus'] = int(self.info['vcpus'])
defaultInfo('vcpu_avail', lambda: (1 << self.info['vcpus']) - 1)
defaultInfo('bootloader', lambda: None)
defaultInfo('backend', lambda: [])
@@ -509,11 +501,6 @@ class XendDomainInfo:
if self.info['maxmem_KiB'] > self.info['memory_KiB']:
self.info['maxmem_KiB'] = self.info['memory_KiB']
# Validate the given backend names.
for s in self.info['backend']:
if s not in backendFlags:
raise VmError('Invalid backend type: %s' % s)
for (n, c) in self.info['device']:
if not n or not c or n not in controllerClasses:
raise VmError('invalid device (%s, %s)' %
@@ -541,28 +528,51 @@ class XendDomainInfo:
def gatherVm(self, *args):
return xstransact.Gather(self.vmpath, *args)
## public:
def storeVm(self, *args):
return xstransact.Store(self.vmpath, *args)
## private:
def readDom(self, *args):
return xstransact.Read(self.dompath, *args)
def writeDom(self, *args):
return xstransact.Write(self.dompath, *args)
## public:
def removeDom(self, *args):
return xstransact.Remove(self.dompath, *args)
def gatherDom(self, *args):
return xstransact.Gather(self.dompath, *args)
## private:
def storeDom(self, *args):
return xstransact.Store(self.dompath, *args)
## public:
def completeRestore(self, store_mfn, console_mfn):
log.debug("XendDomainInfo.completeRestore")
self.store_mfn = store_mfn
self.console_mfn = console_mfn
self.introduceDomain()
self.storeDomDetails()
self.refreshShutdown()
def storeVmDetails(self):
to_store = {
'uuid': self.uuid,
'uuid': self.info['uuid'],
# XXX
'memory/target': str(self.info['memory_KiB'])
@@ -585,26 +595,39 @@ class XendDomainInfo:
to_store = {
'domid': str(self.domid),
'vm': self.vmpath,
'console/limit': str(xroot.get_console_limit() * 1024),
'memory/target': str(self.info['memory_KiB'])
}
for (k, v) in self.info.items():
if v:
to_store[k] = str(v)
def f(n, v):
if v is not None:
to_store[n] = str(v)
f('console/port', self.console_port)
f('console/ring-ref', self.console_mfn)
f('store/port', self.store_port)
f('store/ring-ref', self.store_mfn)
to_store.update(self.vcpuDomDetails())
log.debug("Storing domain details: %s", to_store)
self.writeDom(to_store)
## private:
def vcpuDomDetails(self):
def availability(n):
if self.info['vcpu_avail'] & (1 << n):
return 'online'
else:
return 'offline'
result = {}
for v in range(0, self.info['vcpus']):
to_store["cpu/%d/availability" % v] = availability(v)
log.debug("Storing domain details: %s", to_store)
self.writeDom(to_store)
result["cpu/%d/availability" % v] = availability(v)
return result
def setDomid(self, domid):
@@ -629,12 +652,27 @@ class XendDomainInfo:
def getDomainPath(self):
return self.dompath
def getUuid(self):
return self.uuid
def getStorePort(self):
"""For use only by image.py and XendCheckpoint.py."""
return self.store_port
def getConsolePort(self):
"""For use only by image.py and XendCheckpoint.py"""
return self.console_port
def getVCpuCount(self):
return self.info['vcpus']
def setVCpuCount(self, vcpus):
self.info['vcpu_avail'] = (1 << vcpus) - 1
self.storeVm('vcpu_avail', self.info['vcpu_avail'])
self.writeDom(self.vcpuDomDetails())
def getSsidref(self):
return self.info['ssidref']
@@ -642,15 +680,6 @@ class XendDomainInfo:
"""Get this domain's target memory size, in KiB."""
return self.info['memory_KiB']
def setStoreRef(self, ref):
self.store_mfn = ref
self.storeDom("store/ring-ref", ref)
def getBackendFlags(self):
return reduce(lambda x, y: x | backendFlags[y],
self.info['backend'], 0)
def refreshShutdown(self, xeninfo = None):
# If set at the end of this method, a restart is required, with the
@@ -685,6 +714,11 @@ class XendDomainInfo:
return
elif xeninfo['crashed']:
if self.readDom('xend/shutdown_completed'):
# We've seen this shutdown already, but we are preserving
# the domain for debugging. Leave it alone.
return
log.warn('Domain has crashed: name=%s id=%d.',
self.info['name'], self.domid)
@@ -708,7 +742,7 @@ class XendDomainInfo:
self.clearRestart()
if reason == 'suspend':
self.state_set(STATE_VM_TERMINATED)
self.state_set(STATE_DOM_SHUTDOWN)
# Don't destroy the domain. XendCheckpoint will do
# this once it has finished.
elif reason in ['poweroff', 'reboot']:
@@ -716,6 +750,11 @@ class XendDomainInfo:
else:
self.destroy()
elif self.dompath is None:
# We have yet to manage to call introduceDomain on this
# domain. This can happen if a restore is in progress, or has
# failed. Ignore this domain.
pass
else:
# Domain is alive. If we are shutting it down, then check
# the timeout on that, and destroy it if necessary.
@@ -783,11 +822,6 @@ class XendDomainInfo:
## public:
def setConsoleRef(self, ref):
self.console_mfn = ref
self.storeDom("console/ring-ref", ref)
def setMemoryTarget(self, target):
"""Set the memory target of this domain.
@param target In MiB.
@@ -802,7 +836,7 @@ class XendDomainInfo:
"""Update with info from xc.domain_getinfo().
"""
log.debug("XendDomainInfo.update(%s) on domain %d", info, self.domid)
log.trace("XendDomainInfo.update(%s) on domain %d", info, self.domid)
if not info:
info = dom_get(self.domid)
@@ -813,7 +847,7 @@ class XendDomainInfo:
self.validateInfo()
self.refreshShutdown(info)
log.debug("XendDomainInfo.update done on domain %d: %s", self.domid,
log.trace("XendDomainInfo.update done on domain %d: %s", self.domid,
self.info)
@@ -821,19 +855,23 @@ class XendDomainInfo:
def state_set(self, state):
self.state_updated.acquire()
if self.state != state:
self.state = state
self.state_updated.notifyAll()
self.state_updated.release()
try:
if self.state != state:
self.state = state
self.state_updated.notifyAll()
finally:
self.state_updated.release()
## public:
def waitForShutdown(self):
self.state_updated.acquire()
while self.state == STATE_VM_OK:
self.state_updated.wait()
self.state_updated.release()
try:
while self.state == STATE_DOM_OK:
self.state_updated.wait()
finally:
self.state_updated.release()
def __str__(self):
@@ -865,12 +903,12 @@ class XendDomainInfo:
return self.getDeviceController(deviceClass).destroyDevice(devid)
## private:
def getDeviceSxprs(self, deviceClass):
return self.getDeviceController(deviceClass).sxprs()
## private:
def getDeviceConfigurations(self, deviceClass):
return self.getDeviceController(deviceClass).configurations()
@@ -887,7 +925,6 @@ class XendDomainInfo:
def sxpr(self):
sxpr = ['domain',
['domid', self.domid],
['uuid', self.uuid],
['memory', self.info['memory_KiB'] / 1024]]
for e in ROUNDTRIPPING_CONFIG_ENTRIES:
@@ -925,11 +962,6 @@ class XendDomainInfo:
if self.infoIsSet('cpu_time'):
sxpr.append(['cpu_time', self.info['cpu_time']/1e9])
sxpr.append(['vcpus', self.info['vcpus']])
if self.infoIsSet('cpumap'):
sxpr.append(['cpumap', self.info['cpumap']])
if self.infoIsSet('vcpu_to_cpu'):
sxpr.append(['cpu', self.info['vcpu_to_cpu'][0]])
sxpr.append(['vcpu_to_cpu', self.prettyVCpuMap()])
if self.infoIsSet('start_time'):
up_time = time.time() - self.info['start_time']
@@ -944,13 +976,38 @@ class XendDomainInfo:
return sxpr
def getVCPUInfo(self):
try:
def filter_cpumap(map, max):
return filter(lambda x: x >= 0, map[0:max])
# We include the domain name and ID, to help xm.
sxpr = ['domain',
['domid', self.domid],
['name', self.info['name']],
['vcpu_count', self.info['vcpus']]]
for i in range(0, self.info['vcpus']):
info = xc.vcpu_getinfo(self.domid, i)
sxpr.append(['vcpu',
['number', i],
['online', info['online']],
['blocked', info['blocked']],
['running', info['running']],
['cpu_time', info['cpu_time'] / 1e9],
['cpu', info['cpu']],
['cpumap', filter_cpumap(info['cpumap'],
self.info['vcpus'])]])
return sxpr
except RuntimeError, exn:
raise XendError(str(exn))
## private:
def prettyVCpuMap(self):
return '|'.join(map(str,
self.info['vcpu_to_cpu'][0:self.info['vcpus']]))
def check_name(self, name):
"""Check if a vm name is valid. Valid names contain alphabetic characters,
digits, or characters in '_-.:/+'.
@@ -988,18 +1045,29 @@ class XendDomainInfo:
self.domid,
self.info['ssidref'])
self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref'])
self.domid = xc.domain_create(
dom = 0, ssidref = self.info['ssidref'],
handle = uuid.fromString(self.info['uuid']))
if self.domid < 0:
raise VmError('Creating domain failed: name=%s' %
self.info['name'])
self.dompath = DOMROOT + str(self.domid)
self.dompath = GetDomainPath(self.domid)
# Ensure that the domain entry is clean. This prevents a stale
# shutdown_start_time from killing the domain, for example.
self.removeDom()
# Set maximum number of vcpus in domain
xc.domain_max_vcpus(self.domid, int(self.info['vcpus']))
def introduceDomain(self):
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)
def initDomain(self):
log.debug('XendDomainInfo.initDomain: %s %s %s',
@@ -1018,29 +1086,29 @@ class XendDomainInfo:
self.image.handleBootloading()
xc.domain_setcpuweight(self.domid, self.info['cpu_weight'])
# XXX Merge with configure_maxmem?
m = self.image.getDomainMemory(self.info['memory_KiB'])
xc.domain_setmaxmem(self.domid, m)
xc.domain_setmaxmem(self.domid, maxmem_kb = m)
xc.domain_memory_increase_reservation(self.domid, m, 0, 0)
cpu = self.info['cpu']
if cpu is not None and cpu != -1:
xc.domain_pincpu(self.domid, 0, 1 << cpu)
self.createChannels()
channel_details = self.image.createImage()
self.store_mfn = channel_details['store_mfn']
if 'console_mfn' in channel_details:
self.console_mfn = channel_details['console_mfn']
self.introduceDomain()
self.createDevices()
self.info['start_time'] = time.time()
log.debug('init_domain> Created domain=%d name=%s memory=%d',
self.domid, self.info['name'], self.info['memory_KiB'])
def construct_image(self):
"""Construct the boot image for the domain.
"""
self.create_channel()
self.image.createImage()
IntroduceDomain(self.domid, self.store_mfn,
self.store_channel, self.dompath)
## public:
@@ -1065,11 +1133,11 @@ class XendDomainInfo:
try:
if not self.info['name'].startswith(ZOMBIE_PREFIX):
self.info['name'] = self.generateZombieName()
self.info['name'] = ZOMBIE_PREFIX + self.info['name']
except:
log.exception("Renaming Zombie failed.")
self.state_set(STATE_VM_TERMINATED)
self.state_set(STATE_DOM_SHUTDOWN)
def cleanupVm(self):
@@ -1124,51 +1192,38 @@ class XendDomainInfo:
break
def eventChannel(self, path=None):
"""Create an event channel to the domain.
@param path under which port is stored in db
def createChannels(self):
"""Create the channels to the domain.
"""
if path:
try:
return int(self.readDom(path))
except:
# The port is not yet set, i.e. the channel has not yet been
# created.
pass
self.store_port = self.createChannel()
self.console_port = self.createChannel()
def createChannel(self):
"""Create an event channel to the domain.
"""
try:
port = xc.evtchn_alloc_unbound(dom=self.domid, remote_dom=0)
return xc.evtchn_alloc_unbound(dom=self.domid, remote_dom=0)
except:
log.exception("Exception in alloc_unbound(%d)", self.domid)
raise
self.storeDom(path, port)
return port
def create_channel(self):
"""Create the channels to the domain.
"""
self.store_channel = self.eventChannel("store/port")
self.console_channel = self.eventChannel("console/port")
## public:
def create_configured_devices(self):
for (n, c) in self.info['device']:
self.createDevice(n, c)
def create_devices(self):
def createDevices(self):
"""Create the devices for a vm.
@raise: VmError for invalid devices
"""
self.create_configured_devices()
for (n, c) in self.info['device']:
self.createDevice(n, c)
if self.image:
self.image.createDeviceModel()
## public:
def device_create(self, dev_config):
"""Create a new device.
@@ -1189,25 +1244,16 @@ class XendDomainInfo:
self.reconfigureDevice(deviceClass, devid, dev_config)
def pause(self):
xc.domain_pause(self.domid)
def unpause(self):
xc.domain_unpause(self.domid)
## private:
def restart_check(self):
"""Check if domain restart is OK.
To prevent restart loops, raise an error if it is
less than MINIMUM_RESTART_TIME seconds since the last restart.
"""
tnow = time.time()
if self.restart_time is not None:
tdelta = tnow - self.restart_time
if tdelta < self.MINIMUM_RESTART_TIME:
self.restart_cancel()
msg = 'VM %s restarting too fast' % self.info['name']
log.error(msg)
raise VmError(msg)
self.restart_time = tnow
self.restart_count += 1
def restart(self, rename = False):
"""Restart the domain after it has exited.
@@ -1215,8 +1261,6 @@ class XendDomainInfo:
False if it is to be destroyed.
"""
# self.restart_check()
config = self.sxpr()
if self.readVm('xend/restart_in_progress'):
@@ -1228,17 +1272,33 @@ class XendDomainInfo:
self.writeVm('xend/restart_in_progress', 'True')
now = time.time()
rst = self.readVm('xend/previous_restart_time')
log.error(rst)
if rst:
rst = float(rst)
timeout = now - rst
if timeout < MINIMUM_RESTART_TIME:
log.error(
'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.writeVm('xend/previous_restart_time', str(now))
try:
if rename:
self.preserveForRestart()
else:
self.destroy()
self.destroyDomain()
try:
xd = get_component('xen.xend.XendDomain')
new_dom = xd.domain_create(config)
try:
xc.domain_unpause(new_dom.getDomid())
new_dom.unpause()
except:
new_dom.destroy()
raise
@@ -1259,12 +1319,13 @@ class XendDomainInfo:
"""
new_name = self.generateUniqueName()
new_uuid = getUuid()
new_uuid = uuid.toString(uuid.create())
log.info("Renaming dead domain %s (%d, %s) to %s (%s).",
self.info['name'], self.domid, self.uuid, new_name, new_uuid)
self.info['name'], self.domid, self.info['uuid'],
new_name, new_uuid)
self.release_devices()
self.info['name'] = new_name
self.uuid = new_uuid
self.info['uuid'] = new_uuid
self.vmpath = VMROOT + new_uuid
self.storeVmDetails()
self.preserve()
@@ -1274,21 +1335,7 @@ class XendDomainInfo:
log.info("Preserving dead domain %s (%d).", self.info['name'],
self.domid)
self.storeDom('xend/shutdown_completed', 'True')
self.state_set(STATE_VM_TERMINATED)
## public:
def renameUniquely(self):
"""Rename this domain so that it has a unique name. This is used by
XendDomain to recover from non-uniqueness errors; we should never have
allowed the system to reach this state in the first place."""
new_name = self.generateUniqueName()
log.error('Renaming %s (%d, %s) to %s', self.info['name'], self.domid,
self.uuid, new_name)
self.setName(new_name)
self.state_set(STATE_DOM_SHUTDOWN)
# private:
@@ -1304,18 +1351,6 @@ class XendDomainInfo:
n += 1
def generateZombieName(self):
n = 0
name = ZOMBIE_PREFIX + self.info['name']
while True:
try:
self.check_name(name)
return name
except VmError:
n += 1
name = "%s%d-%s" % (ZOMBIE_PREFIX, n, self.info['name'])
def configure_bootloader(self):
if not self.info['bootloader']:
return
@@ -1337,75 +1372,12 @@ class XendDomainInfo:
self.config = sxp.merge(['vm', ['image', blcfg]], self.config)
def configure(self):
"""Configure a vm.
"""
self.configure_maxmem()
self.create_devices()
def configure_maxmem(self):
if self.image:
m = self.image.getDomainMemory(self.info['memory_KiB'])
xc.domain_setmaxmem(self.domid, maxmem_kb = m)
def vcpu_hotplug(self, vcpu, state):
"""Disable or enable VCPU in domain.
"""
if vcpu > self.info['vcpus']:
log.error("Invalid VCPU %d" % vcpu)
return
if int(state) == 0:
self.info['vcpu_avail'] &= ~(1 << vcpu)
availability = "offline"
else:
self.info['vcpu_avail'] &= (1 << vcpu)
availability = "online"
self.storeVm('vcpu_avail', self.info['vcpu_avail'])
self.storeDom("cpu/%d/availability" % vcpu, availability)
def send_sysrq(self, key):
asserts.isCharConvertible(key)
self.storeDom("control/sysrq", '%c' % key)
def initStoreConnection(self):
ref = xc.init_store(self.store_channel)
if ref and ref >= 0:
self.setStoreRef(ref)
try:
IntroduceDomain(self.domid, ref, self.store_channel,
self.dompath)
except RuntimeError, ex:
if ex.args[0] == errno.EISCONN:
pass
else:
raise
def dom0_enforce_vcpus(self):
dom = 0
# get max number of vcpus to use for dom0 from config
target = int(xroot.get_dom0_vcpus())
log.debug("number of vcpus to use is %d", target)
# target = 0 means use all processors
if target > 0:
# count the number of online vcpus (cpu values in v2c map >= 0)
vcpu_to_cpu = dom_get(dom)['vcpu_to_cpu']
vcpus_online = len(filter(lambda x: x >= 0, vcpu_to_cpu))
log.debug("found %d vcpus online", vcpus_online)
# disable any extra vcpus that are online over the requested target
for vcpu in range(target, vcpus_online):
log.info("enforcement is disabling DOM%d VCPU%d", dom, vcpu)
self.vcpu_hotplug(vcpu, 0)
def infoIsSet(self, name):
return name in self.info and self.info[name] is not None
@@ -1417,25 +1389,16 @@ class XendDomainInfo:
implements the device control specific to that device-class."""
controllerClasses = {}
"""A map of backend names and the corresponding flag."""
backendFlags = {}
def addControllerClass(device_class, backend_name, backend_flag, cls):
def addControllerClass(device_class, cls):
"""Register a subclass of DevController to handle the named device-class.
@param backend_flag One of the SIF_XYZ_BE_DOMAIN constants, or None if
no flag is to be set.
"""
cls.deviceClass = device_class
backendFlags[backend_name] = backend_flag
controllerClasses[device_class] = cls
from xen.xend.server import blkif, netif, tpmif, pciif, usbif
addControllerClass('vbd', 'blkif', SIF_BLK_BE_DOMAIN, blkif.BlkifController)
addControllerClass('vif', 'netif', SIF_NET_BE_DOMAIN, netif.NetifController)
addControllerClass('vtpm', 'tpmif', SIF_TPM_BE_DOMAIN, tpmif.TPMifController)
addControllerClass('pci', 'pciif', None, pciif.PciController)
addControllerClass('usb', 'usbif', None, usbif.UsbifController)
addControllerClass('vbd', blkif.BlkifController)
addControllerClass('vif', netif.NetifController)
addControllerClass('vtpm', tpmif.TPMifController)
addControllerClass('pci', pciif.PciController)
addControllerClass('usb', usbif.UsbifController)
+8
View File
@@ -27,6 +27,14 @@ __all__ = [ 'log', 'init', 'getLogFilename', 'addLogStderr',
'removeLogStderr' ]
if not 'TRACE' in logging.__dict__:
logging.TRACE = logging.DEBUG - 1
logging.addLevelName(logging.TRACE,'TRACE')
def trace(self, *args, **kwargs):
self.log(logging.TRACE, *args, **kwargs)
logging.Logger.trace = trace
log = logging.getLogger("xend")
+15 -9
View File
@@ -64,7 +64,7 @@ class XendRoot:
xend_address_default = ''
"""Default for the flag indicating whether xend should run a relocation server."""
xend_relocation_server_default = 'yes'
xend_relocation_server_default = 'no'
"""Default interface address the xend relocation server listens at. """
xend_relocation_address_default = ''
@@ -243,30 +243,36 @@ class XendRoot:
"""
return self.get_config_value("xend-unix-path", self.xend_unix_path_default)
def get_block_script(self, type):
return self.get_config_value('block-%s' % type, '')
def get_network_script(self):
return self.get_config_value('network-script', '')
"""@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')
if s:
return os.path.join(self.network_script_dir, s)
else:
return None
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', 'xen-br0')
return self.get_config_value('vif-bridge', 'xenbr0')
def get_vif_script(self):
return self.get_config_value('vif-script', 'vif-bridge')
def get_vif_antispoof(self):
return self.get_config_bool('vif-antispoof', 'yes')
def get_dom0_min_mem(self):
return self.get_config_int('dom0-min-mem', self.dom0_min_mem_default)
def get_dom0_vcpus(self):
return self.get_config_int('dom0-cpus', self.dom0_vcpus_default)
def get_console_limit(self):
return self.get_config_int('console-limit', 1024)
def instance():
"""Get an instance of XendRoot.
Use this instead of the constructor.
+38 -62
View File
@@ -66,7 +66,6 @@ class ImageHandler:
self.kernel = None
self.ramdisk = None
self.cmdline = None
self.flags = 0
self.configure(imageConfig, deviceConfig)
@@ -112,13 +111,13 @@ class ImageHandler:
"""Entry point to create domain memory image.
Override in subclass if needed.
"""
self.createDomain()
return self.createDomain()
def createDomain(self):
"""Build the domain boot image.
"""
# Set params and call buildDomain().
self.flags = self.vm.getBackendFlags()
if not os.path.isfile(self.kernel):
raise VmError('Kernel image does not exist: %s' % self.kernel)
@@ -130,10 +129,15 @@ class ImageHandler:
log.info("buildDomain os=%s dom=%d vcpus=%d", self.ostype,
self.vm.getDomid(), self.vm.getVCpuCount())
err = self.buildDomain()
if err != 0:
raise VmError('Building domain failed: ostype=%s dom=%d err=%d'
% (self.ostype, self.vm.getDomid(), err))
result = self.buildDomain()
if isinstance(result, dict):
return result
else:
raise VmError('Building domain failed: ostype=%s dom=%d err=%s'
% (self.ostype, self.vm.getDomid(), str(result)))
def getDomainMemory(self, mem):
"""@return The memory required, in KiB, by the domain to store the
@@ -153,26 +157,14 @@ class ImageHandler:
"""Extra cleanup on domain destroy (define in subclass if needed)."""
pass
def set_vminfo(self, d):
if d.has_key('store_mfn'):
self.vm.setStoreRef(d.get('store_mfn'))
if d.has_key('console_mfn'):
self.vm.setConsoleRef(d.get('console_mfn'))
class LinuxImageHandler(ImageHandler):
ostype = "linux"
def buildDomain(self):
if self.vm.store_channel:
store_evtchn = self.vm.store_channel
else:
store_evtchn = 0
if self.vm.console_channel:
console_evtchn = self.vm.console_channel
else:
console_evtchn = 0
store_evtchn = self.vm.getStorePort()
console_evtchn = self.vm.getConsolePort()
log.debug("dom = %d", self.vm.getDomid())
log.debug("image = %s", self.kernel)
@@ -180,21 +172,14 @@ class LinuxImageHandler(ImageHandler):
log.debug("console_evtchn = %d", console_evtchn)
log.debug("cmdline = %s", self.cmdline)
log.debug("ramdisk = %s", self.ramdisk)
log.debug("flags = %d", self.flags)
log.debug("vcpus = %d", self.vm.getVCpuCount())
ret = xc.linux_build(dom = self.vm.getDomid(),
image = self.kernel,
store_evtchn = store_evtchn,
console_evtchn = console_evtchn,
cmdline = self.cmdline,
ramdisk = self.ramdisk,
flags = self.flags,
vcpus = self.vm.getVCpuCount())
if isinstance(ret, dict):
self.set_vminfo(ret)
return 0
return ret
return xc.linux_build(dom = self.vm.getDomid(),
image = self.kernel,
store_evtchn = store_evtchn,
console_evtchn = console_evtchn,
cmdline = self.cmdline,
ramdisk = self.ramdisk)
class VmxImageHandler(ImageHandler):
@@ -219,45 +204,33 @@ class VmxImageHandler(ImageHandler):
self.dmargs += self.configVNC(imageConfig)
def createImage(self):
"""Create a VM for the VMX environment.
"""
self.createDomain()
def buildDomain(self):
# Create an event channel
self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(),
remote_dom=0)
log.info("VMX device model port: %d", self.device_channel)
if self.vm.store_channel:
store_evtchn = self.vm.store_channel
else:
store_evtchn = 0
store_evtchn = self.vm.getStorePort()
log.debug("dom = %d", self.vm.getDomid())
log.debug("image = %s", self.kernel)
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("flags = %d", self.flags)
log.debug("vcpus = %d", self.vm.getVCpuCount())
ret = xc.vmx_build(dom = self.vm.getDomid(),
image = self.kernel,
control_evtchn = self.device_channel,
store_evtchn = store_evtchn,
memsize = self.vm.getMemoryTarget() / 1024,
flags = self.flags,
vcpus = self.vm.getVCpuCount())
if isinstance(ret, dict):
self.set_vminfo(ret)
return 0
return ret
return xc.vmx_build(dom = self.vm.getDomid(),
image = self.kernel,
control_evtchn = self.device_channel,
store_evtchn = store_evtchn,
memsize = self.vm.getMemoryTarget() / 1024,
vcpus = self.vm.getVCpuCount())
# Return a list of cmd line args to the device models based on the
# xm config file
def parseDeviceModelArgs(self, imageConfig, deviceConfig):
dmargs = [ 'cdrom', 'boot', 'fda', 'fdb',
dmargs = [ 'cdrom', 'boot', 'fda', 'fdb', 'ne2000',
'localtime', 'serial', 'stdvga', 'isa', 'vcpus' ]
ret = []
for a in dmargs:
@@ -265,15 +238,17 @@ class VmxImageHandler(ImageHandler):
# python doesn't allow '-' in variable names
if a == 'stdvga': a = 'std-vga'
if a == 'ne2000': a = 'nic-ne2000'
# Handle booleans gracefully
if a in ['localtime', 'std-vga', 'isa']:
if a in ['localtime', 'std-vga', 'isa', 'nic-ne2000']:
if v != None: v = int(v)
if v: ret.append("-%s" % a)
else:
if v:
ret.append("-%s" % a)
ret.append("%s" % v)
log.debug("args: %s, val: %s" % (a,v))
if v:
ret.append("-%s" % a)
ret.append("%s" % v)
# Handle disk/network related options
for (name, info) in deviceConfig:
@@ -337,7 +312,8 @@ class VmxImageHandler(ImageHandler):
"-m", "%s" % (self.vm.getMemoryTarget() / 1024)])
args = args + self.dmargs
env = dict(os.environ)
env['DISPLAY'] = self.display
if self.display:
env['DISPLAY'] = self.display
log.info("spawning device models: %s %s", self.device_model, args)
self.pid = os.spawnve(os.P_NOWAIT, self.device_model, args, env)
log.info("device model pid: %d", self.pid)
@@ -82,7 +82,7 @@ class DevController:
if backpath:
xstransact.Remove(backpath)
else:
raise VmError("Device not connected")
raise VmError("Device %s not connected" % devid)
def configurations(self):
@@ -160,7 +160,7 @@ class DevController:
if result:
result = int(result)
else:
result = 1
result = 0
t.write("nextDeviceID", str(result + 1))
if t.commit():
return result
+16 -39
View File
@@ -14,6 +14,8 @@ import pwd
import re
import traceback
import xen.lowlevel.xc
from xen.xend.server import SrvServer
from xen.xend.XendLogging import log
@@ -32,34 +34,6 @@ class Daemon:
self.traceindent = 0
self.child = 0
def daemon_pids(self):
pids = []
pidex = '(?P<pid>\d+)'
pythonex = '(?P<python>\S*python\S*)'
cmdex = '(?P<cmd>.*)'
procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
xendre = re.compile('^\S+/xend\s*(start|restart)\s*.*$')
procs = os.popen('ps -e -o pid,args 2>/dev/null')
for proc in procs:
pm = procre.match(proc)
if not pm: continue
xm = xendre.match(pm.group('cmd'))
if not xm: continue
pids.append(int(pm.group('pid')))
return pids
def new_cleanup(self, kill=0):
err = 0
pids = self.daemon_pids()
if kill:
for pid in pids:
print "Killing daemon pid=%d" % pid
os.kill(pid, signal.SIGHUP)
elif pids:
err = 1
print "Daemon already running: ", pids
return err
def read_pid(self, pidfile):
"""Read process id from a file.
@@ -115,12 +89,9 @@ class Daemon:
os.remove(pidfile)
return running
def cleanup_xend(self, kill=False):
def cleanup_xend(self, kill):
return self.cleanup_process(XEND_PID_FILE, "xend", kill)
def cleanup(self, kill=False):
self.cleanup_xend(kill=kill)
def status(self):
"""Returns the status of the xend daemon.
The return value is defined by the LSB:
@@ -156,16 +127,13 @@ class Daemon:
# Detach from TTY.
os.setsid()
# Detach from standard file descriptors.
# I do this at the file-descriptor level: the overlying Python file
# objects also use fd's 0, 1 and 2.
# Detach from standard file descriptors, and redirect them to
# /dev/null or the log as appropriate.
os.close(0)
os.close(1)
os.close(2)
if XEND_DEBUG:
os.open('/dev/null', os.O_RDONLY)
# XXX KAF: Why doesn't this capture output from C extensions that
# fprintf(stdout) or fprintf(stderr) ??
os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT)
os.dup(1)
else:
@@ -180,7 +148,7 @@ class Daemon:
0 Success
4 Insufficient privileges
"""
xend_pid = self.cleanup_xend()
xend_pid = self.cleanup_xend(False)
if self.set_user():
return 4
@@ -294,11 +262,20 @@ class Daemon:
return 1
def stop(self):
return self.cleanup(kill=True)
result = self.cleanup_xend(True)
from xen.xend import Vifctl
Vifctl.network("stop")
return result
def run(self, status):
try:
log.info("Xend Daemon started")
xc = xen.lowlevel.xc.new()
xinfo = xc.xeninfo()
log.info("Xend changeset: %s.", xinfo['xen_changeset'])
del xc
event.listenEvent(self)
relocate.listenRelocation()
servers = SrvServer.create()
+22 -7
View File
@@ -89,7 +89,7 @@ class SrvDomain(SrvDir):
fn = FormFn(self.xd.domain_pincpu,
[['dom', 'int'],
['vcpu', 'int'],
['cpumap', 'int']])
['cpumap', 'str']])
val = fn(req.args, {'dom': self.dom.domid})
return val
@@ -105,6 +105,13 @@ class SrvDomain(SrvDir):
return val
def op_cpu_sedf_get(self, op, req):
fn = FormFn(self.xd.domain_cpu_sedf_get,
[['dom', 'int']])
val = fn(req.args, {'dom': self.dom.domid})
return val
def op_cpu_sedf_set(self, op, req):
fn = FormFn(self.xd.domain_cpu_sedf_set,
[['dom', 'int'],
@@ -146,13 +153,13 @@ class SrvDomain(SrvDir):
def op_device_destroy(self, op, req):
return self.call(self.dom.destroyDevice,
[['type', 'str'],
['dev', 'int']],
['dev', 'str']],
req)
def op_device_configure(self, op, req):
return self.call(self.dom.device_configure,
[['config', 'sxpr'],
['dev', 'int']],
['dev', 'str']],
req)
@@ -165,17 +172,25 @@ class SrvDomain(SrvDir):
val = fn(req.args, {'dom': self.dom.domid})
return val
def op_vcpu_hotplug(self, op, req):
return self.call(self.dom.vcpu_hotplug,
[['vcpu', 'int'],
['state', 'int']],
def op_set_vcpus(self, op, req):
return self.call(self.dom.setVCpuCount,
[['vcpus', 'int']],
req)
def op_vcpuinfo(self, _1, req):
return self.call(self.dom.getVCPUInfo, [], req)
def render_POST(self, req):
return self.perform(req)
def render_GET(self, req):
op = req.args.get('op')
if op and op[0] in ['vcpuinfo']:
return self.perform(req)
#
# XXX SMH: below may be useful once again if we ever try to get
# the raw 'web' interface to xend working once more. But for now
@@ -39,6 +39,7 @@
# todo Support security settings etc. in the config file.
# todo Support command-line args.
import fcntl
from threading import Thread
from xen.web.httpserver import HttpServer, UnixHttpServer
@@ -64,6 +65,11 @@ class XendServers:
self.servers.append(server)
def start(self, status):
# Running the network script will spawn another process, which takes
# the status fd with it unless we set FD_CLOEXEC. Failing to do this
# causes the read in SrvDaemon to hang even when we have written here.
fcntl.fcntl(status, fcntl.F_SETFD, fcntl.FD_CLOEXEC)
Vifctl.network('start')
threads = []
for server in self.servers:
+3 -4
View File
@@ -22,8 +22,9 @@ import string
from xen.util import blkif
from xen.xend import sxp
from xen.xend.XendError import VmError
from DevController import DevController
from xen.xend.server.DevController import DevController
class BlkifController(DevController):
@@ -96,6 +97,4 @@ class BlkifController(DevController):
if self.readBackend(i, 'dev') == devid:
DevController.destroyDevice(self, i)
return
# Try this, but it's almost certainly going to throw VmError,
# since we can't find the device.
DevController.destroyDevice(self, int(devid))
raise VmError("Device %s not connected" % devid)
+30
View File
@@ -0,0 +1,30 @@
import unittest
from xen.xend import uuid
class test_uuid(unittest.TestCase):
def testStringRoundtrip(self):
def t(inp):
self.assertEqual(uuid.fromString(uuid.toString(inp)), inp)
t(uuid.create())
t(uuid.create())
t(uuid.create())
t(uuid.create())
t(uuid.create())
def testToFromString(self):
def t(inp, expected):
self.assertEqual(uuid.toString(inp), expected)
self.assertEqual(uuid.fromString(expected), inp)
t([0 for i in range(0, 16)], "00000000-0000-0000-0000-000000000000")
t([185, 158, 125, 206, 250, 178, 125, 57, 2, 6, 162, 74, 178, 236,
196, 5], "b99e7dce-fab2-7d39-0206-a24ab2ecc405")
def test_suite():
return unittest.makeSuite(test_uuid)
+12 -8
View File
@@ -36,23 +36,27 @@ def getUuidUuidgen(random = True):
cmd += " -r"
else:
cmd += " -t"
return commands.getoutput(cmd)
return fromString(commands.getoutput(cmd))
def getUuidRandom():
"""Generate a random UUID."""
bytes = [ random.randint(0, 255) for i in range(0, 16) ]
# Encode the variant.
bytes[6] = (bytes[6] & 0x0f) | 0x40
bytes[8] = (bytes[8] & 0x3f) | 0x80
f = "%02x"
return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(bytes) )
return [ random.randint(0, 255) for i in range(0, 16) ]
#uuidFactory = getUuidUuidgen
uuidFactory = getUuidRandom
def getUuid():
def create():
return uuidFactory()
def toString(u):
f = "%02x"
return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(u) )
def fromString(s):
s = s.replace('-', '')
return [ int(s[i : i + 2], 16) for i in range(0, 32, 2) ]
@@ -14,6 +14,9 @@ from xen.xend.xenstore.xsutil import xshandle
class xstransact:
def __init__(self, path):
self.in_transaction = False # Set this temporarily -- if this
# constructor fails, then we need to
# protect __del__.
self.path = path.rstrip("/")
self.transaction = xshandle().transaction_start()
self.in_transaction = True
+2 -2
View File
@@ -19,8 +19,8 @@ def xshandle():
xs_lock.release()
return xs_handle
def IntroduceDomain(domid, page, port, path):
return xshandle().introduce_domain(domid, page, port, path)
def IntroduceDomain(domid, page, port):
return xshandle().introduce_domain(domid, page, port)
def GetDomainPath(domid):
return xshandle().get_domain_path(domid)
+11 -5
View File
@@ -10,6 +10,9 @@ import threading
from xen.lowlevel import xs
from xen.xend.xenstore.xsutil import xshandle
from xen.xend.XendLogging import log
class xswatch:
watchThread = None
@@ -41,10 +44,13 @@ class xswatch:
while True:
try:
we = cls.xs.read_watch()
except RuntimeError, ex:
print ex
raise
watch = we[1]
watch.fn(*watch.args, **watch.kwargs)
watch = we[1]
watch.fn(*watch.args, **watch.kwargs)
except:
log.exception("read_watch failed")
# Ignore this exception -- there's no point throwing it
# further on because that will just kill the watcher thread,
# which achieves nothing.
watchMain = classmethod(watchMain)
+5 -1
View File
@@ -364,6 +364,10 @@ gopts.var('nographic', val='no|yes',
fn=set_bool, default=0,
use="Should device models use graphics?")
gopts.var('ne2000', val='no|yes',
fn=set_bool, default=0,
use="Should device models use ne2000?")
gopts.var('vnc', val='',
fn=set_value, default=None,
use="""Should the device model use VNC?""")
@@ -540,7 +544,7 @@ def configure_vmx(opts, config_image, vals):
"""
args = [ 'memmap', 'device_model', 'vcpus', 'cdrom',
'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga',
'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display']
'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000']
for a in args:
if (vals.__dict__[a]):
config_image.append([a, vals.__dict__[a]])
+173 -107
View File
@@ -71,8 +71,7 @@ longhelp = """Usage: xm <subcommand> [args]
xm full list of subcommands:
Domain Commands:
console <DomId> attach to console of DomId
cpus-list <DomId> <VCpu> get the list of cpus for a VCPU
console <DomId> attach to console of DomId
create <ConfigFile> create a domain
destroy <DomId> terminate a domain immediately
domid <DomName> convert a domain name to a domain id
@@ -88,10 +87,9 @@ xm full list of subcommands:
shutdown [-w|-a] <DomId> shutdown a domain
sysrq <DomId> <letter> send a sysrq to a domain
unpause <DomId> unpause a paused domain
vcpu-enable <DomId> <VCPU> enable VCPU in a domain
vcpu-disable <DomId> <VCPU> disable VCPU in a domain
vcpu-list <DomId> get the list of VCPUs for a domain
vcpu-pin <DomId> <VCpu> <CPUS> set which cpus a VCPU can use.
set-vcpus <DomId> <VCPUs> enable the specified number of VCPUs in a domain
vcpu-list <DomId> list the VCPUs for a domain
vcpu-pin <DomId> <VCPU> <CPUs> set which cpus a VCPU can use.
Xen Host Commands:
dmesg [--clear] read or clear Xen's message buffer
@@ -169,11 +167,9 @@ def handle_xend_error(cmd, dom, ex):
if error == "Not found" and dom != None:
err("Domain '%s' not found when running 'xm %s'" % (dom, cmd))
sys.exit(1)
elif error == "Exception: Device not connected":
err("Device not connected")
sys.exit(1)
else:
raise ex
err(error)
sys.exit(1)
#########################################################################
@@ -211,6 +207,15 @@ def xm_restore(args):
if id is not None:
server.xend_domain_unpause(domid)
def getDomains(domain_names):
from xen.xend.XendClient import server
if domain_names:
return map(server.xend_domain, domain_names)
else:
return server.xend_list_domains()
def xm_list(args):
use_long = 0
show_vcpus = 0
@@ -220,80 +225,161 @@ def xm_list(args):
err(opterr)
sys.exit(1)
n = len(params)
for (k, v) in options:
if k in ['-l', '--long']:
use_long = 1
if k in ['-v', '--vcpus']:
show_vcpus = 1
from xen.xend.XendClient import server
if n == 0:
doms = server.xend_list_domains()
else:
doms = map(server.xend_domain, params)
if use_long:
for dom in doms:
PrettyPrint.prettyprint(doms)
else:
domsinfo = map(parse_doms_info, doms)
if show_vcpus:
print >>sys.stderr, (
"xm list -v is deprecated. Please use xm vcpu-list.")
xm_vcpu_list(params)
return
doms = getDomains(params)
if use_long:
map(PrettyPrint.prettyprint, doms)
else:
xm_brief_list(doms)
if show_vcpus:
xm_show_vcpus(domsinfo)
else:
xm_brief_list(domsinfo)
def parse_doms_info(info):
dominfo = {}
dominfo['dom'] = int(sxp.child_value(info, 'domid', '-1'))
dominfo['name'] = sxp.child_value(info, 'name', '??')
dominfo['mem'] = int(sxp.child_value(info, 'memory', '0'))
dominfo['cpu'] = str(sxp.child_value(info, 'cpu', '0'))
dominfo['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
# if there is more than 1 cpu, the value doesn't mean much
if dominfo['vcpus'] > 1:
dominfo['cpu'] = '-'
dominfo['state'] = sxp.child_value(info, 'state', '??')
dominfo['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
# security identifiers
if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
dominfo['ssidref1'] = int(sxp.child_value(info, 'ssidref', '0')) & 0xffff
dominfo['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 16) & 0xffff
# get out the vcpu information
dominfo['vcpulist'] = []
vcpu_to_cpu = sxp.child_value(info, 'vcpu_to_cpu', '-1').split('|')
cpumap = sxp.child_value(info, 'cpumap', [])
mask = ((int(sxp.child_value(info, 'vcpus', '0')))**2) - 1
count = 0
for cpu in vcpu_to_cpu:
vcpuinfo = {}
vcpuinfo['name'] = sxp.child_value(info, 'name', '??')
vcpuinfo['dom'] = int(sxp.child_value(info, 'domid', '-1'))
vcpuinfo['vcpu'] = int(count)
vcpuinfo['cpu'] = int(cpu)
vcpuinfo['cpumap'] = int(cpumap[count])&mask
count = count + 1
dominfo['vcpulist'].append(vcpuinfo)
return dominfo
def xm_brief_list(domsinfo):
print 'Name ID Mem(MiB) CPU VCPUs State Time(s)'
for dominfo in domsinfo:
if dominfo.has_key("ssidref1"):
print ("%(name)-16s %(dom)3d %(mem)8d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo)
else:
print ("%(name)-16s %(dom)3d %(mem)8d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f" % dominfo)
def get_info(n, t, d):
return t(sxp.child_value(info, n, d))
return {
'dom' : get_info('domid', int, -1),
'name' : get_info('name', str, '??'),
'mem' : get_info('memory', int, 0),
'vcpus' : get_info('vcpus', int, 0),
'state' : get_info('state', str, '??'),
'cpu_time' : get_info('cpu_time', float, 0),
'ssidref' : get_info('ssidref', int, 0),
}
def xm_brief_list(doms):
print 'Name ID Mem(MiB) VCPUs State Time(s)'
for dom in doms:
d = parse_doms_info(dom)
if (d['ssidref'] != 0):
d['ssidstr'] = (" s:%04x/p:%04x" %
((d['ssidref'] >> 16) & 0xffff,
d['ssidref'] & 0xffff))
else:
d['ssidstr'] = ""
print ("%(name)-32s %(dom)3d %(mem)8d %(vcpus)5d %(state)5s %(cpu_time)7.1f%(ssidstr)s" % d)
def xm_show_vcpus(domsinfo):
print 'Name Id VCPU CPU CPUMAP'
for dominfo in domsinfo:
for vcpuinfo in dominfo['vcpulist']:
print ("%(name)-16s %(dom)3d %(vcpu)4d %(cpu)3d 0x%(cpumap)x" %
vcpuinfo)
def xm_vcpu_list(args):
xm_list(["-v"] + args)
print 'Name ID VCPU CPU State Time(s) CPU Affinity'
from xen.xend.XendClient import server
if args:
dominfo = map(server.xend_domain_vcpuinfo, args)
else:
doms = server.xend_list_domains()
dominfo = map(
lambda x: server.xend_domain_vcpuinfo(sxp.child_value(x, 'name')),
doms)
for dom in dominfo:
def get_info(n):
return sxp.child_value(dom, n)
#
# convert a list of integers into a list of pairs indicating
# continuous sequences in the list:
#
# [0,1,2,3] -> [(0,3)]
# [1,2,4,5] -> [(1,2),(4,5)]
# [0] -> [(0,0)]
# [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
#
def list_to_rangepairs(cmap):
cmap.sort()
pairs = []
x = y = 0
for i in range(0,len(cmap)):
try:
if ((cmap[y+1] - cmap[i]) > 1):
pairs.append((cmap[x],cmap[y]))
x = y = i+1
else:
y = y + 1
# if we go off the end, then just add x to y
except IndexError:
pairs.append((cmap[x],cmap[y]))
return pairs
#
# Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
#
def format_pairs(pairs):
if not pairs:
return "no cpus"
out = ""
for f,s in pairs:
if (f==s):
out += '%d'%f
else:
out += '%d-%d'%(f,s)
out += ','
# trim trailing ','
return out[:-1]
def format_cpumap(cpumap):
cpumap = map(lambda x: int(x), cpumap)
cpumap.sort()
from xen.xend.XendClient import server
for x in server.xend_node()[1:]:
if len(x) > 1 and x[0] == 'nr_cpus':
nr_cpus = int(x[1])
cpumap = filter(lambda x: x < nr_cpus, cpumap)
if len(cpumap) == nr_cpus:
return "any cpu"
break
return format_pairs(list_to_rangepairs(cpumap))
name = get_info('name')
domid = int(get_info('domid'))
for vcpu in sxp.children(dom, 'vcpu'):
def vinfo(n, t):
return t(sxp.child_value(vcpu, n))
number = vinfo('number', int)
cpu = vinfo('cpu', int)
cpumap = format_cpumap(vinfo('cpumap', list))
online = vinfo('online', int)
cpu_time = vinfo('cpu_time', float)
running = vinfo('running', int)
blocked = vinfo('blocked', int)
if online:
c = str(cpu)
if running:
s = 'r'
else:
s = '-'
if blocked:
s += 'b'
else:
s += '-'
s += '-'
else:
c = "-"
s = "--p"
print (
"%(name)-32s %(domid)3d %(number)4d %(c)3s %(s)-3s %(cpu_time)7.1f %(cpumap)s" %
locals())
def xm_reboot(args):
arg_check(args,1,"reboot")
@@ -325,7 +411,6 @@ def xm_subcommand(command, args):
def cpu_make_map(cpulist):
cpus = []
cpumap = 0
for c in cpulist.split(','):
if c.find('-') != -1:
(x,y) = c.split('-')
@@ -334,14 +419,11 @@ def cpu_make_map(cpulist):
else:
cpus.append(int(c))
cpus.sort()
for c in cpus:
cpumap = cpumap | 1<<c
return cpumap
return cpus
def xm_vcpu_pin(args):
arg_check(args, 3, "vcpu-pin")
dom = args[0]
vcpu = int(args[1])
cpumap = cpu_make_map(args[2])
@@ -351,7 +433,7 @@ def xm_vcpu_pin(args):
def xm_mem_max(args):
arg_check(args, 2, "mem-max")
dom = args[0]
mem = int_unit(args[1], 'm')
@@ -360,35 +442,16 @@ def xm_mem_max(args):
def xm_mem_set(args):
arg_check(args, 2, "mem-set")
dom = args[0]
mem_target = int_unit(args[1], 'm')
from xen.xend.XendClient import server
server.xend_domain_mem_target_set(dom, mem_target)
# TODO: why does this lookup by name? and what if that fails!?
def xm_vcpu_enable(args):
arg_check(args, 2, "vcpu-enable")
name = args[0]
vcpu = int(args[1])
def xm_set_vcpus(args):
from xen.xend.XendClient import server
dom = server.xend_domain(name)
id = sxp.child_value(dom, 'domid')
server.xend_domain_vcpu_hotplug(id, vcpu, 1)
def xm_vcpu_disable(args):
arg_check(args, 2, "vcpu-disable")
name = args[0]
vcpu = int(args[1])
from xen.xend.XendClient import server
dom = server.xend_domain(name)
id = sxp.child_value(dom, 'domid')
server.xend_domain_vcpu_hotplug(id, vcpu, 0)
server.xend_domain_set_vcpus(args[0], int(args[1]))
def xm_domid(args):
name = args[0]
@@ -588,9 +651,7 @@ commands = {
"mem-set": xm_mem_set,
# cpu commands
"vcpu-pin": xm_vcpu_pin,
# "cpus-list": xm_cpus_list,
"vcpu-enable": xm_vcpu_enable,
"vcpu-disable": xm_vcpu_disable,
"set-vcpus": xm_set_vcpus,
"vcpu-list": xm_vcpu_list,
# special
"pause": xm_pause,
@@ -688,11 +749,16 @@ def main(argv=sys.argv):
if rc:
usage()
except socket.error, ex:
print >>sys.stderr, ex
err("Error connecting to xend, is xend running?")
if os.geteuid() != 0:
err("Most commands need root access. Please try again as root.")
else:
err("Error connecting to xend: %s. Is xend running?" % ex[1])
sys.exit(1)
except IOError:
err("Most commands need root access. Please try again as root")
if os.geteuid() != 0:
err("Most commands need root access. Please try again as root.")
else:
err("Error connecting to xend: %s." % ex[1])
sys.exit(1)
except xen.xend.XendError.XendError, ex:
if len(args) > 0:
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.