bitkeeper revision 1.1716 (42b336f8VKVQeJVq9gIppvvdYPrMmw)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into freefall.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
This commit is contained in:
iap10@freefall.cl.cam.ac.uk committed 2005-06-17 20:47:52 +00:00
commit 86d6165ed3
53 files changed
+2136 -878

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ library_dirs = [ XEN_ROOT + "/tools/libxc",
XEN_ROOT + "/tools/xenstore",
]
libraries = [ "xc", "xenstore" ]
libraries = [ "xc", "xenstore-pic" ]
xc = Extension("xc",
extra_compile_args = extra_compile_args,
+255 -107
View File
@@ -1,3 +1,8 @@
/*
Python interface to the Xen Store Daemon.
Copyright (C) 2005 Mike Wray Hewlett-Packard
*/
#include <Python.h>
#include <stdio.h>
@@ -14,9 +19,9 @@
*/
/* Needed for Python versions earlier than 2.3. */
//#ifndef PyMODINIT_FUNC
//#define PyMODINIT_FUNC DL_EXPORT(void)
//#endif
#ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC DL_EXPORT(void)
#endif
#define PYPKG "xen.lowlevel.xs"
@@ -47,6 +52,53 @@ static inline PyObject *pyvalue_str(char *val) {
: PyErr_SetFromErrno(PyExc_RuntimeError));
}
#define xspy_read_doc "\n" \
"Read data from a path.\n" \
" path [string]: xenstore path\n" \
"\n" \
"Returns: [string] data read.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
char *path = NULL;
struct xs_handle *xh = xshandle(self);
char *xsval = NULL;
unsigned int xsval_n = 0;
PyObject *val = NULL;
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&path))
goto exit;
xsval = xs_read(xh, path, &xsval_n);
if (!xsval) {
val = pyvalue_int(0);
goto exit;
}
val = PyString_FromStringAndSize(xsval, xsval_n);
exit:
if (xsval)
free(xsval);
return val;
}
#define xspy_write_doc "\n" \
"Write data to a path.\n" \
" path [string] : xenstore path to write to\n." \
" data [string] : data to write.\n" \
" create [int] : create flag, default 0.\n" \
" excl [int] : exclusive flag, default 0.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", "data", "create", "excl", NULL };
@@ -77,53 +129,13 @@ static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
return val;
}
static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
char *path = NULL;
struct xs_handle *xh = xshandle(self);
char *xsval = NULL;
unsigned int xsval_n = 0;
PyObject *val = NULL;
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&path))
goto exit;
xsval = xs_read(xh, path, &xsval_n);
if (!xsval) {
val = pyvalue_int(0);
goto exit;
}
val = PyString_FromStringAndSize(xsval, xsval_n);
exit:
if (xsval)
free(xsval);
return val;
}
static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
char *path = NULL;
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
int xsval = 0;
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
xsval = xs_mkdir(xh, path);
val = pyvalue_int(xsval);
exit:
return val;
}
#define xspy_ls_doc "\n" \
"List a directory.\n" \
" path [string]: path to list.\n" \
"\n" \
"Returns: [string array] list of subdirectory names.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
{
@@ -153,6 +165,41 @@ static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
return val;
}
#define xspy_mkdir_doc "\n" \
"Make a directory.\n" \
" path [string]: path to directory to create.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
char *path = NULL;
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
int xsval = 0;
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
goto exit;
xsval = xs_mkdir(xh, path);
val = pyvalue_int(xsval);
exit:
return val;
}
#define xspy_rm_doc "\n" \
"Remove a path.\n" \
" path [string] : path to remove\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
@@ -173,6 +220,14 @@ static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
return val;
}
#define xspy_get_permissions_doc "\n" \
"Get the permissions for a path\n" \
" path [string]: xenstore path.\n" \
"\n" \
"Returns: permissions array.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
PyObject *kwds)
{
@@ -209,6 +264,15 @@ static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
return val;
}
#define xspy_set_permissions_doc "\n" \
"Set the permissions for a path\n" \
" path [string] : xenstore path.\n" \
" perms : permissions.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
PyObject *kwds)
{
@@ -275,12 +339,22 @@ static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
return val;
}
#define xspy_watch_doc "\n" \
"Watch a path, get notifications when it changes.\n" \
" path [string] : xenstore path.\n" \
" token [string] : returned in watch notification\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", "priority", NULL };
static char *arg_spec = "s|i";
static char *kwd_spec[] = { "path", "priority", "token", NULL };
static char *arg_spec = "s|is";
char *path = NULL;
int priority = 0;
char *token = "";
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
@@ -289,14 +363,22 @@ static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
&path, &priority))
&path, &priority, &token))
goto exit;
xsval = xs_watch(xh, path, priority);
xsval = xs_watch(xh, path, token, priority);
val = pyvalue_int(xsval);
exit:
return val;
}
#define xspy_read_watch_doc "\n" \
"Read a watch notification.\n" \
" path [string]: xenstore path.\n" \
"\n" \
"Returns: [tuple] (path, token).\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
PyObject *kwds)
{
@@ -305,25 +387,39 @@ static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
char *xsval = NULL;
char **xsval = NULL;
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
goto exit;
xsval = xs_read_watch(xh);
val = pyvalue_str(xsval);
if (!xsval) {
val = PyErr_SetFromErrno(PyExc_RuntimeError);
goto exit;
}
/* Create tuple (path, token). */
val = Py_BuildValue("(ss)", xsval[0], xsval[1]);
exit:
if (xsval)
free(xsval);
return val;
}
#define xspy_acknowledge_watch_doc "\n" \
"Acknowledge a watch notification that has been read.\n" \
" token [string] : returned in watch notification\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
PyObject *kwds)
{
static char *kwd_spec[] = { NULL };
static char *arg_spec = "";
static char *kwd_spec[] = { "token", NULL };
static char *arg_spec = "s";
char *token;
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
@@ -331,19 +427,29 @@ static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
goto exit;
xsval = xs_acknowledge_watch(xh);
xsval = xs_acknowledge_watch(xh, token);
val = pyvalue_int(xsval);
exit:
return val;
}
#define xspy_unwatch_doc "\n" \
"Stop watching a path.\n" \
" path [string] : xenstore path.\n" \
" token [string] : token from the watch.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { "path", NULL };
static char *arg_spec = "s|";
static char *kwd_spec[] = { "path", "token", NULL };
static char *arg_spec = "s|s";
char *path = NULL;
char *token = "";
struct xs_handle *xh = xshandle(self);
PyObject *val = NULL;
@@ -351,14 +457,24 @@ static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
if (!xh)
goto exit;
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
&token))
goto exit;
xsval = xs_unwatch(xh, path);
xsval = xs_unwatch(xh, path, token);
val = pyvalue_int(xsval);
exit:
return val;
}
#define xspy_transaction_start_doc "\n" \
"Start a transaction on a path.\n" \
"Only one transaction can be active at a time.\n" \
" path [string]: xenstore path.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
PyObject *kwds)
{
@@ -380,6 +496,15 @@ static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
return val;
}
#define xspy_transaction_end_doc "\n" \
"End the current transaction.\n" \
"Attempts to commit the transaction unless abort is true.\n" \
" abort [int]: Abort flag..\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
PyObject *kwds)
{
@@ -401,6 +526,17 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
return val;
}
#define xspy_introduce_domain_doc "\n" \
"Tell xenstore about a domain so it can talk to it.\n" \
" 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: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
PyObject *kwds)
{
@@ -429,6 +565,15 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
return val;
}
#define xspy_release_domain_doc "\n" \
"Tell xenstore to release its channel to a domain.\n" \
"Unless this is done the domain will not be released.\n" \
" dom [int]: domain id\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
PyObject *kwds)
{
@@ -453,6 +598,13 @@ static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
return val;
}
#define xspy_close_doc "\n" \
"Close the connection to xenstore.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { NULL };
@@ -473,6 +625,13 @@ static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
return val;
}
#define xspy_shutdown_doc "\n" \
"Shutdown the xenstore daemon.\n" \
"\n" \
"Returns: [int] 0 on success.\n" \
"Raises RuntimeError on error.\n" \
"\n"
static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwd_spec[] = { NULL };
@@ -492,49 +651,31 @@ static PyObject *xspy_shutdown(PyObject *self, PyObject *args, PyObject *kwds)
return val;
}
#define XSPY_METH(_name) \
#_name, \
(PyCFunction) xspy_ ## _name, \
(METH_VARARGS | METH_KEYWORDS)
// mtime
// ctime
#define XSPY_METH(_name) { \
.ml_name = #_name, \
.ml_meth = (PyCFunction) xspy_ ## _name, \
.ml_flags = (METH_VARARGS | METH_KEYWORDS), \
.ml_doc = xspy_ ## _name ## _doc }
static PyMethodDef xshandle_methods[] = {
{ XSPY_METH(read),
"read(path) : read data\n" },
{ XSPY_METH(write),
"write(path, data, [creat], [excl]): write data\n" },
{ XSPY_METH(ls),
"ls(path): list directory.\n" },
{ XSPY_METH(mkdir),
"mkdir(path): make a directory.\n" },
{ XSPY_METH(rm),
"rm(path): remove a path (dir must be empty).\n" },
{ XSPY_METH(get_permissions),
"get_permissions(path)\n" },
{ XSPY_METH(set_permissions),
"set_permissions(path)\n" },
{ XSPY_METH(watch),
"watch(path)\n" },
{ XSPY_METH(read_watch),
"read_watch()\n" },
{ XSPY_METH(acknowledge_watch),
"acknowledge_watch()\n" },
{ XSPY_METH(unwatch),
"unwatch()\n" },
{ XSPY_METH(transaction_start),
"transaction_start()\n" },
{ XSPY_METH(transaction_end),
"transaction_end([abort])\n" },
{ XSPY_METH(introduce_domain),
"introduce_domain(dom, page, port)\n" },
{ XSPY_METH(release_domain),
"release_domain(dom)\n" },
{ XSPY_METH(close),
"close()\n" },
{ XSPY_METH(shutdown),
"shutdown()\n" },
{ NULL, NULL, 0, NULL }
XSPY_METH(read),
XSPY_METH(write),
XSPY_METH(ls),
XSPY_METH(mkdir),
XSPY_METH(rm),
XSPY_METH(get_permissions),
XSPY_METH(set_permissions),
XSPY_METH(watch),
XSPY_METH(read_watch),
XSPY_METH(acknowledge_watch),
XSPY_METH(unwatch),
XSPY_METH(transaction_start),
XSPY_METH(transaction_end),
XSPY_METH(introduce_domain),
XSPY_METH(release_domain),
XSPY_METH(close),
XSPY_METH(shutdown),
{ /* Terminator. */ },
};
static PyObject *xshandle_getattr(PyObject *self, char *name)
@@ -604,8 +745,15 @@ static PyObject *xshandle_open(PyObject *self, PyObject *args, PyObject *kwds)
}
static PyMethodDef xs_methods[] = {
{ "open", (PyCFunction)xshandle_open, (METH_VARARGS | METH_KEYWORDS),
"Open a connection to the xenstore daemon.\n" },
{ .ml_name = "open",
.ml_meth = (PyCFunction)xshandle_open,
.ml_flags = (METH_VARARGS | METH_KEYWORDS),
.ml_doc = "\n"
"Open a connection to the xenstore daemon.\n"
"Returns: xs connection object.\n"
"Raises RuntimeError on error.\n"
"\n"
},
{ NULL, NULL, 0, NULL }
};
+1 -1
View File
@@ -72,7 +72,7 @@ static void set_cloexec(int fd)
static int xcs_ctrl_fd = -1; /* control connection to the xcs server. */
static int xcs_data_fd = -1; /* data connection to the xcs server. */
static u32 xcs_session_id = 0;
static unsigned long xcs_session_id = 0;
static int xcs_ctrl_send(xcs_msg_t *msg);
static int xcs_ctrl_read(xcs_msg_t *msg);
+38 -39
View File
@@ -157,7 +157,7 @@ class XendDomainInfo:
db = parentdb.addChild(uuid)
vm = cls(db)
vm.construct(config)
vm.saveDB(sync=True)
vm.saveToDB(sync=True)
return vm
create = classmethod(create)
@@ -193,7 +193,7 @@ class XendDomainInfo:
recreate = classmethod(recreate)
def restore(cls, parentdb, config, uuid=None):
def restore(cls, parentdb, config, uuid):
"""Create a domain and a VM object to do a restore.
@param parentdb: parent db
@@ -202,16 +202,20 @@ class XendDomainInfo:
"""
db = parentdb.addChild(uuid)
vm = cls(db)
dom = xc.domain_create()
vm.setdom(dom)
vm.dom_construct(vm.id, config)
vm.saveDB(sync=True)
id = xc.domain_create()
vm.setdom(id)
try:
vm.restore = True
vm.construct(config)
finally:
vm.restore = False
vm.exportToDB(save=True, sync=True)
return vm
restore = classmethod(restore)
__exports__ = [
DBVar('id', ty='str'),
DBVar('id', ty='int'),
DBVar('name', ty='str'),
DBVar('uuid', ty='str'),
DBVar('config', ty='sxpr'),
@@ -267,14 +271,17 @@ class XendDomainInfo:
def setDB(self, db):
self.db = db
def saveDB(self, save=False, sync=False):
def saveToDB(self, save=False, sync=False):
self.db.saveDB(save=save, sync=sync)
def exportToDB(self, save=False, sync=False):
if self.channel:
self.channel.saveToDB(self.db.addChild("channel"))
self.channel.saveToDB(self.db.addChild("channel"), save=save)
if self.store_channel:
self.store_channel.saveToDB(self.db.addChild("store_channel"))
self.store_channel.saveToDB(self.db.addChild("store_channel"),
save=save)
if self.image:
self.image.exportToDB(save=save, sync=sync)
self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
def importFromDB(self):
@@ -316,7 +323,7 @@ class XendDomainInfo:
self.state = state
self.state_updated.notifyAll()
self.state_updated.release()
self.saveDB()
self.saveToDB()
def state_wait(self, state):
self.state_updated.acquire()
@@ -325,14 +332,14 @@ class XendDomainInfo:
self.state_updated.release()
def __str__(self):
s = "domain"
s = "<domain"
s += " id=" + str(self.id)
s += " name=" + self.name
s += " memory=" + str(self.memory)
console = self.getConsole()
if console:
s += " console=" + str(console.console_port)
s += ""
s += ">"
return s
__repr__ = __str__
@@ -422,15 +429,19 @@ class XendDomainInfo:
sxpr.append(self.channel.sxpr())
if self.store_channel:
sxpr.append(self.store_channel.sxpr())
if self.store_mfn:
sxpr.append(['store_mfn', self.store_mfn])
console = self.getConsole()
if console:
sxpr.append(console.sxpr())
if self.restart_count:
sxpr.append(['restart_count', self.restart_count])
if self.restart_state:
sxpr.append(['restart_state', self.restart_state])
if self.restart_time:
sxpr.append(['restart_time', str(self.restart_time)])
devs = self.sxpr_devices()
if devs:
sxpr.append(devs)
@@ -546,7 +557,7 @@ class XendDomainInfo:
"""
self.create_channel()
self.image.createImage()
self.image.exportToDB()
self.exportToDB()
#if self.store_channel:
# self.db.introduceDomain(self.id,
# self.store_mfn,
@@ -558,7 +569,7 @@ class XendDomainInfo:
if self.dom_get(self.id):
return
self.id = None
self.saveDB(sync=True)
self.saveToDB(sync=True)
try:
# Todo: eventually will have to wait for devices to signal
# destruction before can delete the db.
@@ -614,7 +625,7 @@ class XendDomainInfo:
"""
self.cleanup()
self.destroy_domain()
self.saveDB()
self.saveToDB()
return 0
def is_terminated(self):
@@ -649,14 +660,13 @@ class XendDomainInfo:
cpu = int(sxp.child_value(self.config, 'cpu', '-1'))
except:
raise VmError('invalid cpu')
dom = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
id = self.image.initDomain(self.id, self.memory, cpu, self.cpu_weight)
log.debug('init_domain> Created domain=%d name=%s memory=%d',
dom, self.name, self.memory)
if not self.restore:
self.setdom(dom)
id, self.name, self.memory)
self.setdom(id)
def openChannel(self, key, local, remote):
"""Create a channel to the domain.
"""Create a control channel to the domain.
If saved info is available recreate the channel.
@param key db key for the saved data (if any)
@@ -670,6 +680,11 @@ class XendDomainInfo:
return chan
def eventChannel(self, key):
"""Create an event channel to the domain.
If saved info is available recreate the channel.
@param key db key for the saved data (if any)
"""
db = self.db.addChild(key)
return EventChannel.restoreFromDB(db, 0, self.id)
@@ -833,11 +848,12 @@ class XendDomainInfo:
self.state = STATE_VM_OK
self.shutdown_pending = None
self.restart_check()
self.exportToDB()
self.restart_state = STATE_RESTART_BOOTING
if self.bootloader:
self.config = self.bootloader_config()
self.construct(self.config)
self.saveDB()
self.saveToDB()
finally:
self.restart_state = None
@@ -911,23 +927,6 @@ class XendDomainInfo:
backend = blkif.getBackend(0)
backend.connect(recreate=self.recreate)
def dom_construct(self, dom, config):
"""Construct a vm for an existing domain.
@param dom: domain id
@param config: domain configuration
"""
d = dom_get(dom)
if not d:
raise VmError("Domain not found: %d" % dom)
try:
self.restore = True
self.setdom(dom)
self.memory = d['mem_kb']/1024
self.construct(config)
finally:
self.restore = False
def configure_fields(self):
"""Process the vm configuration fields using the registered handlers.
"""
+2 -2
View File
@@ -98,8 +98,8 @@ class ImageHandler:
self.db = vm.db.addChild('/image')
self.config = config
def exportToDB(self, save=False):
self.db.exportToDB(self, fields=self.__exports__, save=save)
def exportToDB(self, save=False, sync=False):
self.db.exportToDB(self, fields=self.__exports__, save=save, sync=sync)
def importFromDB(self):
self.db.importFromDB(self, fields=self.__exports__)
+8
View File
@@ -167,6 +167,7 @@ class BlkDev(Dev):
DBVar('params', ty='str'),
DBVar('node', ty='str'),
DBVar('device', ty='long'),
DBVar('dev_handle', ty='long'),
DBVar('start_sector', ty='long'),
DBVar('nr_sectors', ty='long'),
]
@@ -192,6 +193,13 @@ class BlkDev(Dev):
self.backendId = 0
self.configure(self.config, recreate=recreate)
def exportToDB(self, save=False):
Dev.exportToDB(self, save=save)
backend = self.getBackend()
if backend and backend.evtchn:
db = self.db.addChild("evtchn")
backend.evtchn.exportToDB(db, save=save)
def init(self, recreate=False, reboot=False):
self.frontendDomain = self.getDomain()
self.frontendChannel = self.getChannel()
+4 -4
View File
@@ -81,7 +81,7 @@ class EventChannel(dict):
evtchn_close(self.dom1, self.port1)
evtchn_close(self.dom2, self.port2)
def saveToDB(self, db):
def saveToDB(self, db, save=False):
"""Save the event channel to the db so it can be restored later,
using restoreFromDB() on the class.
@@ -91,7 +91,7 @@ class EventChannel(dict):
db['dom2'] = str(self.dom2)
db['port1'] = str(self.port1)
db['port2'] = str(self.port2)
db.saveDB()
db.saveDB(save=save)
def sxpr(self):
return ['event-channel',
@@ -339,7 +339,7 @@ class Channel:
# Make sure the port will deliver all the messages.
self.port.register(TYPE_WILDCARD)
def saveToDB(self, db):
def saveToDB(self, db, save=False):
"""Save the channel ports to the db so the channel can be restored later,
using restoreFromDB() on the factory.
@@ -348,7 +348,7 @@ class Channel:
if self.closed: return
db['local_port'] = str(self.getLocalPort())
db['remote_port'] = str(self.getRemotePort())
db.saveDB()
db.saveDB(save=save)
def getKey(self):
"""Get the channel key.
+2 -1
View File
@@ -214,7 +214,8 @@ class ConsoleDev(Dev, protocol.ServerFactory):
self.unix_listener = reactor.listenUNIX(path, self)
if xroot.get_xend_http_server():
interface = xroot.get_console_address()
self.tcp_listener = reactor.listenTCP(self.console_port, self, interface=interface)
self.tcp_listener = reactor.listenTCP(
self.console_port, self, interface=interface)
finally:
self.lock.release()
+20 -2
View File
@@ -66,11 +66,9 @@ class NetDev(Dev):
DBVar('be_mac', ty='mac'),
DBVar('bridge', ty='str'),
DBVar('script', ty='str'),
#DBVar('ipaddr'),
DBVar('credit', ty='int'),
DBVar('period', ty='int'),
DBVar('vifname', ty='str'),
DBVar('evtchn'), #todo: export fields (renamed)
]
def __init__(self, controller, id, config, recreate=False):
@@ -89,9 +87,16 @@ class NetDev(Dev):
self.bridge = None
self.script = None
self.ipaddr = None
self.mtu = None
self.vifname = None
self.configure(self.config, recreate=recreate)
def exportToDB(self, save=False):
Dev.exportToDB(self, save=save)
if self.evtchn:
db = self.db.addChild("evtchn")
self.evtchn.exportToDB(db, save=save)
def init(self, recreate=False, reboot=False):
self.destroyed = False
self.status = NETIF_INTERFACE_STATUS_DISCONNECTED
@@ -128,6 +133,15 @@ class NetDev(Dev):
val = None
return val
def _get_config_mtu(self, config):
mtu = sxp.child_value(config, 'mtu')
if not mtu: return None
try:
mtu = int(mtu)
except:
raise XendError("invalid mtu: %s" & mtu)
return mtu
def configure(self, config, change=False, recreate=False):
if change:
return self.reconfigure(config)
@@ -152,6 +166,7 @@ class NetDev(Dev):
self.bridge = sxp.child_value(config, 'bridge')
self.script = sxp.child_value(config, 'script')
self.ipaddr = self._get_config_ipaddr(config) or []
self.mtu = self._get_config_mtu(config)
self._config_credit_limit(config)
try:
@@ -183,6 +198,7 @@ class NetDev(Dev):
bridge = sxp.child_value(config, 'bridge')
script = sxp.child_value(config, 'script')
ipaddr = self._get_config_ipaddr(config)
mtu = self._get_config_mtu(config)
xd = get_component('xen.xend.XendDomain')
backendDomain = xd.domain_lookup_by_name(sxp.child_value(config, 'backend', '0')).id
@@ -199,6 +215,8 @@ class NetDev(Dev):
changes['script'] = script
if (ipaddr is not None) and (ipaddr != self.ipaddr):
changes['ipaddr'] = ipaddr
if (mtu is not None) and (mtu != self.mtu):
changes['mtu'] = mtu
if changes:
self.vifctl("down")
+172 -85
View File
@@ -2,7 +2,9 @@ import errno
import os
import os.path
import select
import socket
import sys
import threading
import time
from xen.lowlevel import xs
@@ -12,18 +14,26 @@ from xen.xend.PrettyPrint import prettyprint
SELECT_TIMEOUT = 2.0
def getEventPath(event):
return os.path.join("/_event", event)
if event and event.startswith("/"):
event = event[1:]
return os.path.join("/event", event)
def getEventIdPath(event):
return os.path.join(eventPath(event), "@eid")
return os.path.join(getEventPath(event), "@eid")
class Subscription:
def __init__(self, event, fn, id):
self.event = event
def __init__(self, path, fn, sid):
self.path = path
self.watcher = None
self.fn = fn
self.id = id
self.sid = sid
def getPath(self):
return self.path
def getSid(self):
return self.sid
def watch(self, watcher):
self.watcher = watcher
@@ -34,56 +44,61 @@ class Subscription:
if watcher:
self.watcher = None
watcher.delSubs(self)
return watcher
def notify(self, event):
def notify(self, token, path, val):
try:
self.fn(event, id)
except SystemExitException:
self.fn(self, token, path, val)
except SystemExit:
raise
except:
except Exception, ex:
pass
class Watcher:
def __init__(self, store, event):
self.path = getEventPath(event)
self.eidPath = getEventIdPath(event)
def __init__(self, store, path):
self.path = path
store.mkdirs(self.path)
if not store.exists(self.eidPath):
store.writeInt(self.eidPath, 0)
self.xs = None
self.subs = []
self.subscriptions = []
def __getattr__(self, k, v):
if k == "fileno":
if self.xs:
return self.xs.fileno
else:
return -1
def fileno(self):
if self.xs:
return self.xs.fileno
else:
return self.__dict__.get(k, v)
return -1
def getPath(self):
return self.path
def getToken(self):
return self.path
def addSubs(self, subs):
self.subs.append(subs)
self.subscriptions.append(subs)
self.watch()
def delSubs(self, subs):
self.subs.remove(subs)
if len(self.subs) == 0:
self.subscriptions.remove(subs)
if len(self.subscriptions) == 0:
self.unwatch()
def getEvent(self):
return self.event
def watch(self):
if self.xs: return
self.xs = xs.open()
self.xs.watch(path)
self.xs.watch(path=self.getPath(), token=self.getToken())
def unwatch(self):
if self.xs:
self.xs.unwatch(self.path)
self.xs.close()
## Possibly crashes xenstored.
## try:
## self.xs.unwatch(path=self.getPath(), token=self.getToken())
## except Exception, ex:
## print 'Watcher>unwatch>', ex
try:
self.xs.close()
except Exception, ex:
pass
self.xs = None
def watching(self):
@@ -91,23 +106,47 @@ class Watcher:
def getNotification(self):
p = self.xs.read_watch()
self.xs.acknowledge_watch()
eid = self.xs.readInt(self.eidPath)
self.xs.acknowledge_watch(p[1])
return p
def notify(self, subs):
p = self.getNotification()
for s in subs:
s.notify(p)
def notify(self):
try:
(path, token) = self.getNotification()
if path.endswith("@eid"):
pass
else:
val = self.xs.read(path)
for subs in self.subscriptions:
subs.notify(token, path, val)
except SystemExit:
raise
except Exception, ex:
raise
class EventWatcher(Watcher):
def __init__(self, store, path, event):
Watcher.__init__(self, store, path)
self.event = event
self.eidPath = getEventIdPath(event)
if not store.exists(self.eidPath):
store.write(self.eidPath, str(0))
def getEvent(self):
return self.event
def getToken(self):
return self.event
class XenStore:
xs = None
watchThread = None
subscription_id = 1
def __init__(self):
self.xs = None
#self.xs = xs.open()
self.subscription = {}
self.subscription_id = 0
self.events = {}
self.subscriptions = {}
self.watchers = {}
self.write("/", "")
def getxs(self):
@@ -118,9 +157,11 @@ class XenStore:
self.xs = xs.open()
ex = None
break
except SystemExit:
raise
except Exception, ex:
print >>stderr, "Exception connecting to xsdaemon:", ex
print >>stderr, "Trying again..."
print >>sys.stderr, "Exception connecting to xenstored:", ex
print >>sys.stderr, "Trying again..."
time.sleep(1)
else:
raise ex
@@ -214,73 +255,91 @@ class XenStore:
def write(self, path, data, create=True, excl=False):
self.mkdirs(path)
self.getxs().write(path, data, create=create, excl=excl)
try:
self.getxs().write(path, data, create=create, excl=excl)
except Exception, ex:
raise
def begin(self, path):
self.getxs().begin_transaction(path)
self.getxs().transaction_start(path)
def commit(self, abandon=False):
self.getxs().end_transaction(abort=abandon)
self.getxs().transaction_end(abort=abandon)
def watch(self, path, fn):
watcher = self.watchers.get(path)
if not watcher:
watcher = self.addWatcher(Watcher(self, path))
return self.addSubscription(watcher, fn)
def unwatch(self, sid):
s = self.subscriptions.get(sid)
if not s: return
del self.subscriptions[s.sid]
watcher = s.unwatch()
if watcher and not watcher.watching():
try:
del self.watchers[watcher.getPath()]
except:
pass
def subscribe(self, event, fn):
watcher = self.watchEvent(event)
self.subscription_id += 1
subs = Subscription(event, fn, self.subscription_id)
self.subscription[subs.id] = subs
subs.watch(watcher)
return subs.id
path = getEventPath(event)
watcher = self.watchers.get(path)
if not watcher:
watcher = self.addWatcher(EventWatcher(self, path, event))
return self.addSubscription(watcher, fn)
def unsubscribe(self, sid):
s = self.subscription.get(sid)
if not s: return
del self.subscription[s.id]
s.unwatch()
unwatchEvent(s.event)
unsubscribe = unwatch
def sendEvent(self, event, data):
eventPath = getEventPath(event)
eidPath = getEventIdPath(event)
try:
self.begin(eventPath)
#self.begin(eventPath)
self.mkdirs(eventPath)
eid = 1
if self.exists(eidPath):
eid = self.readInt(eidPath)
eid += 1
else:
eid = 1
self.writeInt(eidPath, eid)
try:
eid = int(self.read(eidPath))
eid += 1
except Exception, ex:
pass
self.write(eidPath, str(eid))
self.write(os.path.join(eventPath, str(eid)), data)
finally:
self.commit()
#self.commit()
pass
def watchEvent(self, event):
if event in self.events:
return
watcher = Watcher(event)
self.watchers[watcher.getEvent()] = watcher
def addWatcher(self, watcher):
self.watchers[watcher.getPath()] = watcher
self.watchStart()
return watcher
def unwatchEvent(self, event):
watcher = self.watchers.get(event)
if not watcher:
return
if not watcher.watching():
del self.watchers[event]
def addSubscription(self, watcher, fn):
self.subscription_id += 1
subs = Subscription(watcher.getPath(), fn, self.subscription_id)
self.subscriptions[subs.sid] = subs
subs.watch(watcher)
return subs.sid
def watchStart(self):
if self.watchThread: return
self.watchThread = threading.Thread(name="Watcher",
target=self.watchMain)
self.watchThread.setDaemon(True)
self.watchThread.start()
def watchMain(self):
try:
while True:
if self.watchThread is None: return
if not self.events:
if not self.watchers:
return
rd = self.watchers.values()
try:
(rd, wr, er) = select.select(rd, [], [], SELECT_TIMEOUT)
for watcher in rd:
(srd, swr, ser) = select.select(rd, [], [], SELECT_TIMEOUT)
for watcher in srd:
watcher.notify()
except socket.error, ex:
if ex.args[0] in (EAGAIN, EINTR):
@@ -304,6 +363,15 @@ def getXenStore():
xenstore = XenStore()
return xenstore
def sendEvent(event, val):
getXenStore.sendEvent(event, val)
def subscribe(event, fn):
return getXenStore().subscribe(event, fn)
def unsubscribe(sid):
getXenStore().unsubscribe(sid)
class XenNode:
def __init__(self, path="/", create=True):
@@ -315,6 +383,9 @@ class XenNode:
else:
raise ValueError("path does not exist: '%s'" % path)
def getStore(self):
return self.store
def relPath(self, path=""):
if not path:
return self.path
@@ -344,9 +415,7 @@ class XenNode:
return None
def setData(self, data, path=""):
path = self.relPath(path)
#print 'XenNode>setData>', 'path=', path, 'data=', data
return self.store.write(path, data)
return self.store.write(self.relPath(path), data)
def getLock(self):
return None
@@ -376,6 +445,24 @@ class XenNode:
def releaseDomain(self, dom):
self.store.releaseDomain(dom)
def watch(self, fn, path=""):
"""Watch a path for changes. The path is relative
to the node and defaults to the node itself.
"""
return self.store.watch(self.relPath(path), fn)
def unwatch(self, sid):
return self.store.unwatch(sid)
def subscribe(self, event, fn):
return self.store.subscribe(event, fn)
def unsubscribe(self, sid):
self.store.unsubscribe(sid)
def sendEvent(self, event, data):
return self.store.sendEvent(event, data)
def __repr__(self):
return "<XenNode %s>" % self.path
+60 -36
View File
@@ -1,6 +1,8 @@
import string
import types
from xen.xend.XendLogging import log
from xen.xend import sxp
from xsnode import XenNode
from xen.util.mac import macToString, macFromString
@@ -14,14 +16,19 @@ def hasAttr(obj, attr):
return hasattr(obj, attr)
def getAttr(obj, attr):
if isinstance(obj, dict):
return dict.get(attr)
else:
return getattr(obj, attr, None)
try:
if isinstance(obj, dict):
return obj.get(attr)
else:
return getattr(obj, attr, None)
except AttributeError:
return None
except LookupError:
return None
def setAttr(obj, attr, val):
if isinstance(obj, dict):
dict[attr] = val
obj[attr] = val
else:
setattr(obj, attr, val)
@@ -48,15 +55,15 @@ class DBConverter:
getConverter = classmethod(getConverter)
def convertToDB(cls, val, ty=None):
return cls.getConverter(ty).toDB(val)
def exportTypeToDB(cls, db, path, val, ty=None):
return cls.getConverter(ty).exportToDB(db, path, val)
convertToDB = classmethod(convertToDB)
exportTypeToDB = classmethod(exportTypeToDB)
def convertFromDB(cls, val, ty=None):
return cls.getConverter(ty).fromDB(val)
def importTypeFromDB(cls, db, path, ty=None):
return cls.getConverter(ty).importFromDB(db, path)
convertFromDB = classmethod(convertFromDB)
importTypeFromDB = classmethod(importTypeFromDB)
# Must define in subclass.
name = None
@@ -69,6 +76,26 @@ class DBConverter:
raise ValueError("invalid converter name: '%s'" % self.name)
self.converters[self.name] = self
def exportToDB(self, db, path, val):
if val is None:
return
try:
data = self.toDB(val)
except Exception, ex:
raise
setattr(db, path, data)
def importFromDB(self, db, path):
data = getAttr(db, path)
if data is None:
val = None
else:
try:
val = self.fromDB(data.getData())
except Exception, ex:
raise
return val
def toDB(self, val):
raise NotImplementedError()
@@ -178,10 +205,12 @@ class DBVar:
self.attr = varpath[-1]
def exportToDB(self, db, obj):
self.setDB(db, self.getObj(obj))
val = self.getObj(obj)
DBConverter.exportTypeToDB(db, self.path, val, ty=self.ty)
def importFromDB(self, db, obj):
self.setObj(obj, self.getDB(db))
val = DBConverter.importTypeFromDB(db, self.path, ty=self.ty)
self.setObj(obj, val)
def getObj(self, obj):
o = obj
@@ -200,23 +229,6 @@ class DBVar:
return
setAttr(o, self.attr, val)
def getDB(self, db):
try:
data = getattr(db, self.path)
except AttributeError:
return None
return DBConverter.convertFromDB(data, ty=self.ty)
def setDB(self, db, val):
# Don't set in db if val is None.
#print 'DBVar>setDB>', self.path, 'val=', val
if val is None:
return
data = DBConverter.convertToDB(val, ty=self.ty)
#print 'DBVar>setDB>', self.path, 'data=', data
setattr(db, self.path, data)
class DBMap(dict):
"""A persistent map. Extends dict with persistence.
Set and get values using the usual map syntax:
@@ -314,6 +326,21 @@ class DBMap(dict):
traceback.print_exc()
print 'DBMap>releaseDomain>', ex
pass # todo: don't ignore
def watch(self, fn, path=""):
return self.__db__.watch(fn, path=path)
def unwatch(self, sid):
return self.__db__.unwatch(sid)
def subscribe(self, event, fn):
return self.__db__.subscribe(event, fn)
def unsubscribe(self, sid):
return self.__db__.unsubscribe(sid)
def sendEvent(self, event, val):
return self.__db__.sendEvent(event, val)
def transactionBegin(self):
# Begin a transaction.
@@ -328,12 +355,6 @@ class DBMap(dict):
# We have changed values, what do we do?
pass
def watch(self, fn):
pass
def unwatch(self, watch):
pass
def checkName(self, k):
if k == "":
raise ValueError("invalid key, empty string")
@@ -456,6 +477,9 @@ class DBMap(dict):
n = n._addChild(x)
return n
def getDB(self):
return self.__db__
def setDB(self, db):
if (db is not None) and not isinstance(db, XenNode):
raise ValueError("invalid db")
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.