mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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:
commit
86d6165ed3
53 files changed
+2136
-878
No files matched your search
@@ -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
@@ -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 }
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
"""
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||