direct-io.hg

view tools/python/xen/lowlevel/xs/xs.c @ 7480:a90d670c98b9

Change the semantics of GetDomainPath so that it always succeeds, regardless of
whether a domain has been introduced to the store. Added a separate message
XS_IS_DOMAIN_INTRODUCED and API for that (xs_is_domain_introduced) to determine
whether the domain has really been introduced. This change means that the
tools can determine the correct domain path earlier in the domain creation
process, which is particularly a factor with live migration, as it allows us
to create the devices earlier in the process, and unpause the new domain before
performing the introduce. Until recently we already had these features, but
the simplification of the interface between xend and xenstored caused breakage.

No longer clear out the domain path when a domain is introduced -- this was a
hack to work around the recent problematic semantics of GetDomainPath.

Do not write the contents of the info block to the store. All the configuration
info is written to the /vm path, and anything else in the info block is either
dealt with explicitly or is ephemeral and has no place in the store.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@leeni.uk.xensource.com
date Sun Oct 23 22:45:15 2005 +0100 (2005-10-23)
parents 75ec60b67f64
children 52f17d78dcd5
line source
1 /*
2 * Python interface to the Xen Store Daemon.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of version 2.1 of the GNU Lesser General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Copyright (C) 2005 Mike Wray Hewlett-Packard
18 * Copyright (C) 2005 Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
19 *
20 */
22 #include <Python.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
31 #include <xenctrl.h>
32 #include "xs.h"
34 /** @file
35 * Python interface to the Xen Store Daemon (xs).
36 */
38 /* Needed for Python versions earlier than 2.3. */
39 #ifndef PyMODINIT_FUNC
40 #define PyMODINIT_FUNC DL_EXPORT(void)
41 #endif
43 #define PYPKG "xen.lowlevel.xs"
45 /** Python wrapper round an xs handle.
46 */
47 typedef struct XsHandle {
48 PyObject_HEAD;
49 struct xs_handle *xh;
50 PyObject *watches;
51 } XsHandle;
53 static inline struct xs_handle *xshandle(PyObject *self)
54 {
55 struct xs_handle *xh = ((XsHandle*)self)->xh;
56 if (!xh)
57 PyErr_SetString(PyExc_RuntimeError, "invalid xenstore daemon handle");
58 return xh;
59 }
61 static inline PyObject *pyvalue_int(int val) {
62 return (val
63 ? PyInt_FromLong(val)
64 : PyErr_SetFromErrno(PyExc_RuntimeError));
65 }
67 static inline PyObject *pyvalue_str(char *val) {
68 return (val
69 ? PyString_FromString(val)
70 : PyErr_SetFromErrno(PyExc_RuntimeError));
71 }
73 #define xspy_read_doc "\n" \
74 "Read data from a path.\n" \
75 " path [string]: xenstore path\n" \
76 "\n" \
77 "Returns: [string] data read.\n" \
78 " None if key doesn't exist.\n" \
79 "Raises RuntimeError on error.\n" \
80 "\n"
82 static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
83 {
84 static char *kwd_spec[] = { "transaction", "path", NULL };
85 static char *arg_spec = "ss";
86 char *path = NULL;
88 struct xs_handle *xh = xshandle(self);
89 char *xsval = NULL;
90 unsigned int xsval_n = 0;
91 PyObject *val = NULL;
93 struct xs_transaction_handle *th;
94 char *thstr;
96 if (!xh)
97 goto exit;
98 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
99 &thstr, &path))
100 goto exit;
102 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
104 Py_BEGIN_ALLOW_THREADS
105 xsval = xs_read(xh, th, path, &xsval_n);
106 Py_END_ALLOW_THREADS
107 if (!xsval) {
108 if (errno == ENOENT) {
109 Py_INCREF(Py_None);
110 val = Py_None;
111 } else
112 PyErr_SetFromErrno(PyExc_RuntimeError);
113 goto exit;
114 }
115 val = PyString_FromStringAndSize(xsval, xsval_n);
116 exit:
117 if (xsval)
118 free(xsval);
119 return val;
120 }
122 #define xspy_write_doc "\n" \
123 "Write data to a path.\n" \
124 " path [string] : xenstore path to write to\n." \
125 " data [string] : data to write.\n" \
126 "\n" \
127 "Returns None on success.\n" \
128 "Raises RuntimeError on error.\n" \
129 "\n"
131 static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
132 {
133 static char *kwd_spec[] = { "transaction", "path", "data", NULL };
134 static char *arg_spec = "sss#";
135 char *path = NULL;
136 char *data = NULL;
137 int data_n = 0;
139 struct xs_handle *xh = xshandle(self);
140 PyObject *val = NULL;
141 int xsval = 0;
143 struct xs_transaction_handle *th;
144 char *thstr;
146 if (!xh)
147 goto exit;
148 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
149 &thstr, &path, &data, &data_n))
150 goto exit;
152 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
154 Py_BEGIN_ALLOW_THREADS
155 xsval = xs_write(xh, th, path, data, data_n);
156 Py_END_ALLOW_THREADS
157 if (!xsval) {
158 PyErr_SetFromErrno(PyExc_RuntimeError);
159 goto exit;
160 }
161 Py_INCREF(Py_None);
162 val = Py_None;
163 exit:
164 return val;
165 }
167 #define xspy_ls_doc "\n" \
168 "List a directory.\n" \
169 " path [string]: path to list.\n" \
170 "\n" \
171 "Returns: [string array] list of subdirectory names.\n" \
172 " None if key doesn't exist.\n" \
173 "Raises RuntimeError on error.\n" \
174 "\n"
176 static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
177 {
178 static char *kwd_spec[] = { "transaction", "path", NULL };
179 static char *arg_spec = "ss";
180 char *path = NULL;
182 struct xs_handle *xh = xshandle(self);
183 PyObject *val = NULL;
184 char **xsval = NULL;
185 unsigned int xsval_n = 0;
186 int i;
188 struct xs_transaction_handle *th;
189 char *thstr;
191 if (!xh)
192 goto exit;
193 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
194 &thstr, &path))
195 goto exit;
198 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
200 Py_BEGIN_ALLOW_THREADS
201 xsval = xs_directory(xh, th, path, &xsval_n);
202 Py_END_ALLOW_THREADS
203 if (!xsval) {
204 if (errno == ENOENT) {
205 Py_INCREF(Py_None);
206 val = Py_None;
207 } else
208 PyErr_SetFromErrno(PyExc_RuntimeError);
209 goto exit;
210 }
211 val = PyList_New(xsval_n);
212 for (i = 0; i < xsval_n; i++)
213 PyList_SetItem(val, i, PyString_FromString(xsval[i]));
214 free(xsval);
215 exit:
216 return val;
217 }
219 #define xspy_mkdir_doc "\n" \
220 "Make a directory.\n" \
221 " path [string]: path to directory to create.\n" \
222 "\n" \
223 "Returns None on success.\n" \
224 "Raises RuntimeError on error.\n" \
225 "\n"
227 static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
228 {
229 static char *kwd_spec[] = { "transaction", "path", NULL };
230 static char *arg_spec = "ss";
231 char *path = NULL;
233 struct xs_handle *xh = xshandle(self);
234 PyObject *val = NULL;
235 int xsval = 0;
237 struct xs_transaction_handle *th;
238 char *thstr;
240 if (!xh)
241 goto exit;
242 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
243 &thstr, &path))
244 goto exit;
246 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
248 Py_BEGIN_ALLOW_THREADS
249 xsval = xs_mkdir(xh, th, path);
250 Py_END_ALLOW_THREADS
251 if (!xsval) {
252 PyErr_SetFromErrno(PyExc_RuntimeError);
253 goto exit;
254 }
255 Py_INCREF(Py_None);
256 val = Py_None;
257 exit:
258 return val;
259 }
261 #define xspy_rm_doc "\n" \
262 "Remove a path.\n" \
263 " path [string] : path to remove\n" \
264 "\n" \
265 "Returns None on success.\n" \
266 "Raises RuntimeError on error.\n" \
267 "\n"
269 static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
270 {
271 static char *kwd_spec[] = { "transaction", "path", NULL };
272 static char *arg_spec = "ss";
273 char *path = NULL;
275 struct xs_handle *xh = xshandle(self);
276 PyObject *val = NULL;
277 int xsval = 0;
279 struct xs_transaction_handle *th;
280 char *thstr;
282 if (!xh)
283 goto exit;
284 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
285 &thstr, &path))
286 goto exit;
288 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
290 Py_BEGIN_ALLOW_THREADS
291 xsval = xs_rm(xh, th, path);
292 Py_END_ALLOW_THREADS
293 if (!xsval && errno != ENOENT) {
294 PyErr_SetFromErrno(PyExc_RuntimeError);
295 goto exit;
296 }
297 Py_INCREF(Py_None);
298 val = Py_None;
299 exit:
300 return val;
301 }
303 #define xspy_get_permissions_doc "\n" \
304 "Get the permissions for a path\n" \
305 " path [string]: xenstore path.\n" \
306 "\n" \
307 "Returns: permissions array.\n" \
308 "Raises RuntimeError on error.\n" \
309 "\n"
311 static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
312 PyObject *kwds)
313 {
314 static char *kwd_spec[] = { "transaction", "path", NULL };
315 static char *arg_spec = "ss";
316 char *path = NULL;
318 struct xs_handle *xh = xshandle(self);
319 PyObject *val = NULL;
320 struct xs_permissions *perms;
321 unsigned int perms_n = 0;
322 int i;
324 struct xs_transaction_handle *th;
325 char *thstr;
327 if (!xh)
328 goto exit;
329 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
330 &thstr, &path))
331 goto exit;
333 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
335 Py_BEGIN_ALLOW_THREADS
336 perms = xs_get_permissions(xh, th, path, &perms_n);
337 Py_END_ALLOW_THREADS
338 if (!perms) {
339 PyErr_SetFromErrno(PyExc_RuntimeError);
340 goto exit;
341 }
342 val = PyList_New(perms_n);
343 for (i = 0; i < perms_n; i++, perms++) {
344 PyObject *p = Py_BuildValue("{s:i,s:i,s:i}",
345 "dom", perms->id,
346 "read", (perms->perms & XS_PERM_READ),
347 "write", (perms->perms & XS_PERM_WRITE));
348 PyList_SetItem(val, i, p);
349 }
350 exit:
351 return val;
352 }
354 #define xspy_set_permissions_doc "\n" \
355 "Set the permissions for a path\n" \
356 " path [string] : xenstore path.\n" \
357 " perms : permissions.\n" \
358 "\n" \
359 "Returns None on success.\n" \
360 "Raises RuntimeError on error.\n" \
361 "\n"
363 static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
364 PyObject *kwds)
365 {
366 static char *kwd_spec[] = { "transaction", "path", "perms", NULL };
367 static char *arg_spec = "ssO";
368 char *path = NULL;
369 PyObject *perms = NULL;
370 static char *perm_names[] = { "dom", "read", "write", NULL };
371 static char *perm_spec = "i|iiii";
373 struct xs_handle *xh = xshandle(self);
374 int i, xsval;
375 struct xs_permissions *xsperms = NULL;
376 int xsperms_n = 0;
377 PyObject *tuple0 = NULL;
378 PyObject *val = NULL;
380 struct xs_transaction_handle *th;
381 char *thstr;
383 if (!xh)
384 goto exit;
385 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
386 &thstr, &path, &perms))
387 goto exit;
389 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
391 if (!PyList_Check(perms)) {
392 PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
393 goto exit;
394 }
395 xsperms_n = PyList_Size(perms);
396 xsperms = calloc(xsperms_n, sizeof(struct xs_permissions));
397 if (!xsperms) {
398 PyErr_SetString(PyExc_RuntimeError, "out of memory");
399 goto exit;
400 }
401 tuple0 = PyTuple_New(0);
402 if (!tuple0)
403 goto exit;
404 for (i = 0; i < xsperms_n; i++) {
405 /* Domain the permissions apply to. */
406 int dom = 0;
407 /* Read/write perms. Set these. */
408 int p_read = 0, p_write = 0;
409 PyObject *p = PyList_GetItem(perms, i);
410 if (!PyArg_ParseTupleAndKeywords(tuple0, p, perm_spec, perm_names,
411 &dom, &p_read, &p_write))
412 goto exit;
413 xsperms[i].id = dom;
414 if (p_read)
415 xsperms[i].perms |= XS_PERM_READ;
416 if (p_write)
417 xsperms[i].perms |= XS_PERM_WRITE;
418 }
419 Py_BEGIN_ALLOW_THREADS
420 xsval = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
421 Py_END_ALLOW_THREADS
422 if (!xsval) {
423 PyErr_SetFromErrno(PyExc_RuntimeError);
424 goto exit;
425 }
426 Py_INCREF(Py_None);
427 val = Py_None;
428 exit:
429 Py_XDECREF(tuple0);
430 if (xsperms)
431 free(xsperms);
432 return val;
433 }
435 #define xspy_watch_doc "\n" \
436 "Watch a path, get notifications when it changes.\n" \
437 " path [string] : xenstore path.\n" \
438 " token [string] : returned in watch notification.\n" \
439 "\n" \
440 "Returns None on success.\n" \
441 "Raises RuntimeError on error.\n" \
442 "\n"
444 /* Each 10 bits takes ~ 3 digits, plus one, plus one for nul terminator. */
445 #define MAX_STRLEN(x) ((sizeof(x) * CHAR_BIT + CHAR_BIT-1) / 10 * 3 + 2)
447 static PyObject *xspy_watch(PyObject *self, PyObject *args, PyObject *kwds)
448 {
449 static char *kwd_spec[] = { "path", "token", NULL };
450 static char *arg_spec = "sO";
451 char *path = NULL;
452 PyObject *token;
453 char token_str[MAX_STRLEN(unsigned long) + 1];
454 int i;
456 XsHandle *xsh = (XsHandle *)self;
457 struct xs_handle *xh = xshandle(self);
458 PyObject *val = NULL;
459 int xsval = 0;
461 if (!xh)
462 goto exit;
463 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
464 &path, &token))
465 goto exit;
466 Py_INCREF(token);
467 sprintf(token_str, "%li", (unsigned long)token);
468 Py_BEGIN_ALLOW_THREADS
469 xsval = xs_watch(xh, path, token_str);
470 Py_END_ALLOW_THREADS
471 if (!xsval) {
472 PyErr_SetFromErrno(PyExc_RuntimeError);
473 Py_DECREF(token);
474 goto exit;
475 }
477 for (i = 0; i < PyList_Size(xsh->watches); i++) {
478 if (PyList_GetItem(xsh->watches, i) == Py_None) {
479 PyList_SetItem(xsh->watches, i, token);
480 break;
481 }
482 }
483 if (i == PyList_Size(xsh->watches))
484 PyList_Append(xsh->watches, token);
485 Py_INCREF(Py_None);
486 val = Py_None;
487 exit:
488 return val;
489 }
491 #define xspy_read_watch_doc "\n" \
492 "Read a watch notification.\n" \
493 "\n" \
494 "Returns: [tuple] (path, token).\n" \
495 "Raises RuntimeError on error.\n" \
496 "\n"
498 static PyObject *xspy_read_watch(PyObject *self, PyObject *args,
499 PyObject *kwds)
500 {
501 static char *kwd_spec[] = { NULL };
502 static char *arg_spec = "";
504 XsHandle *xsh = (XsHandle *)self;
505 struct xs_handle *xh = xshandle(self);
506 PyObject *val = NULL;
507 char **xsval = NULL;
508 PyObject *token;
509 int i;
510 unsigned int num;
512 if (!xh)
513 goto exit;
514 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
515 goto exit;
516 again:
517 Py_BEGIN_ALLOW_THREADS
518 xsval = xs_read_watch(xh, &num);
519 Py_END_ALLOW_THREADS
520 if (!xsval) {
521 PyErr_SetFromErrno(PyExc_RuntimeError);
522 goto exit;
523 }
524 if (sscanf(xsval[XS_WATCH_TOKEN], "%li", (unsigned long *)&token) != 1) {
525 PyErr_SetString(PyExc_RuntimeError, "invalid token");
526 goto exit;
527 }
528 for (i = 0; i < PyList_Size(xsh->watches); i++) {
529 if (token == PyList_GetItem(xsh->watches, i))
530 break;
531 }
532 if (i == PyList_Size(xsh->watches)) {
533 /* We do not have a registered watch for the one that has just fired.
534 Ignore this -- a watch that has been recently deregistered can still
535 have watches in transit. This is a blocking method, so go back to
536 read again.
537 */
538 free(xsval);
539 goto again;
540 }
541 /* Create tuple (path, token). */
542 val = Py_BuildValue("(sO)", xsval[XS_WATCH_PATH], token);
543 exit:
544 if (xsval)
545 free(xsval);
546 return val;
547 }
549 #define xspy_unwatch_doc "\n" \
550 "Stop watching a path.\n" \
551 " path [string] : xenstore path.\n" \
552 " token [string] : token from the watch.\n" \
553 "\n" \
554 "Returns None on success.\n" \
555 "Raises RuntimeError on error.\n" \
556 "\n"
558 static PyObject *xspy_unwatch(PyObject *self, PyObject *args, PyObject *kwds)
559 {
560 static char *kwd_spec[] = { "path", "token", NULL };
561 static char *arg_spec = "sO";
562 char *path = NULL;
563 PyObject *token;
564 char token_str[MAX_STRLEN(unsigned long) + 1];
565 int i;
567 XsHandle *xsh = (XsHandle *)self;
568 struct xs_handle *xh = xshandle(self);
569 PyObject *val = NULL;
570 int xsval = 0;
572 if (!xh)
573 goto exit;
574 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path,
575 &token))
576 goto exit;
577 sprintf(token_str, "%li", (unsigned long)token);
578 Py_BEGIN_ALLOW_THREADS
579 xsval = xs_unwatch(xh, path, token_str);
580 Py_END_ALLOW_THREADS
581 if (!xsval)
582 PyErr_SetFromErrno(PyExc_RuntimeError);
583 else {
584 Py_INCREF(Py_None);
585 val = Py_None;
586 }
587 for (i = 0; i < PyList_Size(xsh->watches); i++) {
588 if (token == PyList_GetItem(xsh->watches, i)) {
589 Py_INCREF(Py_None);
590 PyList_SetItem(xsh->watches, i, Py_None);
591 break;
592 }
593 }
594 exit:
595 return val;
596 }
598 #define xspy_transaction_start_doc "\n" \
599 "Start a transaction.\n" \
600 "\n" \
601 "Returns transaction handle on success.\n" \
602 "Raises RuntimeError on error.\n" \
603 "\n"
605 static PyObject *xspy_transaction_start(PyObject *self, PyObject *args,
606 PyObject *kwds)
607 {
608 static char *kwd_spec[] = { NULL };
609 static char *arg_spec = "";
610 char *path = NULL;
612 struct xs_handle *xh = xshandle(self);
613 PyObject *val = NULL;
614 struct xs_transaction_handle *th;
615 char thstr[20];
617 if (!xh)
618 goto exit;
619 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
620 goto exit;
621 Py_BEGIN_ALLOW_THREADS
622 th = xs_transaction_start(xh);
623 Py_END_ALLOW_THREADS
624 if (th == NULL) {
625 PyErr_SetFromErrno(PyExc_RuntimeError);
626 goto exit;
627 }
629 sprintf(thstr, "%lX", (unsigned long)th);
630 val = PyString_FromString(thstr);
631 exit:
632 return val;
633 }
635 #define xspy_transaction_end_doc "\n" \
636 "End the current transaction.\n" \
637 "Attempts to commit the transaction unless abort is true.\n" \
638 " abort [int]: abort flag (default 0).\n" \
639 "\n" \
640 "Returns True on success, False if you need to try again.\n" \
641 "Raises RuntimeError on error.\n" \
642 "\n"
644 static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
645 PyObject *kwds)
646 {
647 static char *kwd_spec[] = { "transaction", "abort", NULL };
648 static char *arg_spec = "s|i";
649 int abort = 0;
651 struct xs_handle *xh = xshandle(self);
652 PyObject *val = NULL;
653 int xsval = 0;
655 struct xs_transaction_handle *th;
656 char *thstr;
658 if (!xh)
659 goto exit;
660 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
661 &thstr, &abort))
662 goto exit;
664 th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
666 Py_BEGIN_ALLOW_THREADS
667 xsval = xs_transaction_end(xh, th, abort);
668 Py_END_ALLOW_THREADS
669 if (!xsval) {
670 if (errno == EAGAIN) {
671 Py_INCREF(Py_False);
672 val = Py_False;
673 goto exit;
674 }
675 PyErr_SetFromErrno(PyExc_RuntimeError);
676 goto exit;
677 }
678 Py_INCREF(Py_True);
679 val = Py_True;
680 exit:
681 return val;
682 }
684 #define xspy_introduce_domain_doc "\n" \
685 "Tell xenstore about a domain so it can talk to it.\n" \
686 " dom [int] : domain id\n" \
687 " page [long] : address of domain's xenstore page\n" \
688 " port [int] : port the domain is using for xenstore\n" \
689 "\n" \
690 "Returns None on success.\n" \
691 "Raises RuntimeError on error.\n" \
692 "\n"
694 static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
695 PyObject *kwds)
696 {
697 static char *kwd_spec[] = { "dom", "page", "port", NULL };
698 static char *arg_spec = "iii";
699 domid_t dom = 0;
700 unsigned long page = 0;
701 unsigned int port = 0;
703 struct xs_handle *xh = xshandle(self);
704 PyObject *val = NULL;
705 int xsval = 0;
707 if (!xh)
708 goto exit;
709 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
710 &dom, &page, &port))
711 goto exit;
712 Py_BEGIN_ALLOW_THREADS
713 xsval = xs_introduce_domain(xh, dom, page, port);
714 Py_END_ALLOW_THREADS
715 if (!xsval) {
716 PyErr_SetFromErrno(PyExc_RuntimeError);
717 goto exit;
718 }
719 Py_INCREF(Py_None);
720 val = Py_None;
721 exit:
722 return val;
723 }
725 #define xspy_release_domain_doc "\n" \
726 "Tell xenstore to release its channel to a domain.\n" \
727 "Unless this is done the domain will not be released.\n" \
728 " dom [int]: domain id\n" \
729 "\n" \
730 "Returns None on success.\n" \
731 "Raises RuntimeError on error.\n" \
732 "\n"
734 static PyObject *xspy_release_domain(PyObject *self, PyObject *args,
735 PyObject *kwds)
736 {
737 static char *kwd_spec[] = { "dom", NULL };
738 static char *arg_spec = "i|";
739 domid_t dom;
741 struct xs_handle *xh = xshandle(self);
742 PyObject *val = NULL;
743 int xsval = 0;
745 if (!xh)
746 goto exit;
747 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
748 &dom))
749 goto exit;
750 Py_BEGIN_ALLOW_THREADS
751 xsval = xs_release_domain(xh, dom);
752 Py_END_ALLOW_THREADS
753 if (!xsval) {
754 PyErr_SetFromErrno(PyExc_RuntimeError);
755 goto exit;
756 }
757 Py_INCREF(Py_None);
758 val = Py_None;
759 exit:
760 return val;
761 }
763 #define xspy_close_doc "\n" \
764 "Close the connection to xenstore.\n" \
765 "\n" \
766 "Returns None on success.\n" \
767 "Raises RuntimeError on error.\n" \
768 "\n"
770 static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
771 {
772 static char *kwd_spec[] = { NULL };
773 static char *arg_spec = "";
774 int i;
776 XsHandle *xsh = (XsHandle *)self;
777 struct xs_handle *xh = xshandle(self);
778 PyObject *val = NULL;
780 if (!xh)
781 goto exit;
782 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec))
783 goto exit;
784 for (i = 0; i < PyList_Size(xsh->watches); i++) {
785 /* TODO: xs_unwatch watches */
786 Py_INCREF(Py_None);
787 PyList_SetItem(xsh->watches, i, Py_None);
788 }
789 xs_daemon_close(xh);
790 xsh->xh = NULL;
791 Py_INCREF(Py_None);
792 val = Py_None;
793 exit:
794 return val;
795 }
797 #define xspy_get_domain_path_doc "\n" \
798 "Return store path of domain, whether or not the domain exists.\n" \
799 " domid [int]: domain id\n" \
800 "\n" \
801 "Returns: [string] domain store path.\n" \
802 "Raises RuntimeError on error.\n" \
803 "\n"
805 static PyObject *xspy_get_domain_path(PyObject *self, PyObject *args,
806 PyObject *kwds)
807 {
808 static char *kwd_spec[] = { "domid", NULL };
809 static char *arg_spec = "i";
810 int domid = 0;
812 struct xs_handle *xh = xshandle(self);
813 char *xsval = NULL;
814 PyObject *val = NULL;
816 if (!xh)
817 goto exit;
818 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
819 &domid))
820 goto exit;
821 Py_BEGIN_ALLOW_THREADS
822 xsval = xs_get_domain_path(xh, domid);
823 Py_END_ALLOW_THREADS
824 if (!xsval) {
825 if (errno == ENOENT) {
826 Py_INCREF(Py_None);
827 val = Py_None;
828 } else
829 PyErr_SetFromErrno(PyExc_RuntimeError);
830 goto exit;
831 }
832 val = PyString_FromString(xsval);
833 free(xsval);
834 exit:
835 return val;
836 }
838 #define XSPY_METH(_name) { \
839 .ml_name = #_name, \
840 .ml_meth = (PyCFunction) xspy_ ## _name, \
841 .ml_flags = (METH_VARARGS | METH_KEYWORDS), \
842 .ml_doc = xspy_ ## _name ## _doc }
844 static PyMethodDef xshandle_methods[] = {
845 XSPY_METH(read),
846 XSPY_METH(write),
847 XSPY_METH(ls),
848 XSPY_METH(mkdir),
849 XSPY_METH(rm),
850 XSPY_METH(get_permissions),
851 XSPY_METH(set_permissions),
852 XSPY_METH(watch),
853 XSPY_METH(read_watch),
854 XSPY_METH(unwatch),
855 XSPY_METH(transaction_start),
856 XSPY_METH(transaction_end),
857 XSPY_METH(introduce_domain),
858 XSPY_METH(release_domain),
859 XSPY_METH(close),
860 XSPY_METH(get_domain_path),
861 { /* Terminator. */ },
862 };
864 static PyObject *xshandle_getattr(PyObject *self, char *name)
865 {
866 PyObject *val = NULL;
867 val = Py_FindMethod(xshandle_methods, self, name);
868 return val;
869 }
871 static void xshandle_dealloc(PyObject *self)
872 {
873 XsHandle *xh = (XsHandle*)self;
874 if (xh->xh) {
875 xs_daemon_close(xh->xh);
876 xh->xh = NULL;
877 }
878 PyObject_Del(self);
879 }
881 static PyTypeObject xshandle_type = {
882 PyObject_HEAD_INIT(&PyType_Type)
883 0,
884 "xshandle",
885 sizeof(XsHandle),
886 0,
887 xshandle_dealloc, /* tp_dealloc */
888 NULL, /* tp_print */
889 xshandle_getattr, /* tp_getattr */
890 NULL, /* tp_setattr */
891 NULL, /* tp_compare */
892 NULL, /* tp_repr */
893 NULL, /* tp_as_number */
894 NULL, /* tp_as_sequence */
895 NULL, /* tp_as_mapping */
896 NULL /* tp_hash */
897 };
899 static PyObject *xshandle_open(PyObject *self, PyObject *args, PyObject *kwds)
900 {
901 static char *kwd_spec[] = { "readonly", NULL };
902 static char *arg_spec = "|i";
903 int readonly = 0;
905 XsHandle *xsh = NULL;
906 PyObject *val = NULL;
908 if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
909 &readonly))
910 return NULL;
912 xsh = PyObject_New(XsHandle, &xshandle_type);
913 if (!xsh)
914 return NULL;
915 xsh->watches = PyList_New(0);
916 if (!xsh->watches)
917 goto exit;
918 xsh->xh = (readonly ? xs_daemon_open_readonly() : xs_daemon_open());
919 if (!xsh->xh) {
920 Py_DECREF(xsh->watches);
921 PyErr_SetFromErrno(PyExc_RuntimeError);
922 goto exit;
923 }
924 val = (PyObject *)xsh;
925 return val;
926 exit:
927 PyObject_Del(xsh);
928 return NULL;
929 }
931 static PyMethodDef xs_methods[] = {
932 { .ml_name = "open",
933 .ml_meth = (PyCFunction)xshandle_open,
934 .ml_flags = (METH_VARARGS | METH_KEYWORDS),
935 .ml_doc = "\n"
936 "Open a connection to the xenstore daemon.\n"
937 "Returns: xs connection object.\n"
938 "Raises RuntimeError on error.\n"
939 "\n"
940 },
941 { /* Terminator. */ }
942 };
944 PyMODINIT_FUNC initxs (void)
945 {
946 PyObject *module;
948 module = Py_InitModule(PYPKG, xs_methods);
949 }