2 * Copyright (C) 2009-2011 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (* Please read generator/README first. *)
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
33 (* Generate Python C module. *)
34 let rec generate_python_c () =
35 generate_header CStyle LGPLv2plus;
44 #include \"guestfs-py.h\"
46 /* This list should be freed (but not the strings) after use. */
48 get_string_list (PyObject *obj)
55 if (!PyList_Check (obj)) {
56 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
60 Py_ssize_t slen = PyList_Size (obj);
62 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
66 r = malloc (sizeof (char *) * (len+1));
68 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
72 for (i = 0; i < len; ++i)
73 r[i] = PyString_AsString (PyList_GetItem (obj, i));
80 put_string_list (char * const * const argv)
85 for (argc = 0; argv[argc] != NULL; ++argc)
88 list = PyList_New (argc);
89 for (i = 0; i < argc; ++i)
90 PyList_SetItem (list, i, PyString_FromString (argv[i]));
96 put_table (char * const * const argv)
98 PyObject *list, *item;
101 for (argc = 0; argv[argc] != NULL; ++argc)
104 list = PyList_New (argc >> 1);
105 for (i = 0; i < argc; i += 2) {
106 item = PyTuple_New (2);
107 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
108 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
109 PyList_SetItem (list, i >> 1, item);
116 free_strings (char **argv)
120 for (argc = 0; argv[argc] != NULL; ++argc)
127 let emit_put_list_function typ =
128 pr "static PyObject *\n";
129 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
131 pr " PyObject *list;\n";
134 pr " list = PyList_New (%ss->len);\n" typ;
135 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
136 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
137 pr " return list;\n";
142 (* Structures, turned into Python dictionaries. *)
145 pr "static PyObject *\n";
146 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
148 pr " PyObject *dict;\n";
150 pr " dict = PyDict_New ();\n";
154 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
155 pr " PyString_FromString (%s->%s));\n"
158 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
159 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
162 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
163 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
165 | name, (FBytes|FUInt64) ->
166 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
167 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
170 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
171 pr " PyLong_FromLongLong (%s->%s));\n"
174 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
175 pr " PyLong_FromUnsignedLong (%s->%s));\n"
178 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
179 pr " PyLong_FromLong (%s->%s));\n"
181 | name, FOptPercent ->
182 pr " if (%s->%s >= 0)\n" typ name;
183 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
184 pr " PyFloat_FromDouble ((double) %s->%s));\n"
187 pr " Py_INCREF (Py_None);\n";
188 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
191 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
192 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
194 pr " return dict;\n";
200 (* Emit a put_TYPE_list function definition only if that function is used. *)
203 | typ, (RStructListOnly | RStructAndList) ->
204 (* generate the function for typ *)
205 emit_put_list_function typ
206 | typ, _ -> () (* empty *)
207 ) (rstructs_used_by all_functions);
209 (* Python wrapper functions. *)
211 fun (name, (ret, args, optargs as style), _, _, _, _, _) ->
212 pr "static PyObject *\n";
213 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
216 pr " PyThreadState *py_save = NULL;\n";
217 pr " PyObject *py_g;\n";
218 pr " guestfs_h *g;\n";
219 pr " PyObject *py_r;\n";
221 if optargs <> [] then (
222 pr " struct guestfs_%s_argv optargs_s;\n" name;
223 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
227 | RErr | RInt _ | RBool _ -> pr " int r;\n"
228 | RInt64 _ -> pr " int64_t r;\n"
229 | RConstString _ | RConstOptString _ ->
230 pr " const char *r;\n"
231 | RString _ -> pr " char *r;\n"
232 | RStringList _ | RHashtable _ -> pr " char **r;\n"
233 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
234 | RStructList (_, typ) ->
235 pr " struct guestfs_%s_list *r;\n" typ
243 | Pathname n | Device n | Dev_or_Path n | String n | Key n
244 | FileIn n | FileOut n ->
245 pr " const char *%s;\n" n
246 | OptString n -> pr " const char *%s;\n" n
248 pr " const char *%s;\n" n;
249 pr " Py_ssize_t %s_size;\n" n
250 | StringList n | DeviceList n ->
251 pr " PyObject *py_%s;\n" n;
253 | Bool n -> pr " int %s;\n" n
254 | Int n -> pr " int %s;\n" n
255 | Int64 n -> pr " long long %s;\n" n
257 pr " long long %s_int64;\n" n;
261 if optargs <> [] then (
262 (* XXX This is horrible. We have to use sentinel values on the
263 * Python side to denote values not set.
265 (* Since we don't know if Python types will exactly match
266 * structure types, declare some local variables here.
271 | Int n -> pr " int optargs_t_%s = -1;\n" n
272 | Int64 n -> pr " long long optargs_t_%s = -1;\n" n
273 | String n -> pr " const char *optargs_t_%s = NULL;\n" n
280 if optargs <> [] then (
281 pr " optargs_s.bitmask = 0;\n";
285 (* Convert the required parameters. *)
286 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
289 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
290 | FileIn _ | FileOut _ -> pr "s"
291 | OptString _ -> pr "z"
292 | StringList _ | DeviceList _ -> pr "O"
293 | Bool _ -> pr "i" (* XXX Python has booleans? *)
295 | Int64 _ | Pointer _ ->
296 (* XXX Whoever thought it was a good idea to
297 * emulate C's int/long/long long in Python?
300 | BufferIn _ -> pr "s#"
303 (* Optional parameters. *)
304 if optargs <> [] then (
307 | Bool _ | Int _ -> pr "i"
309 | String _ -> pr "z" (* because we use None to mean not set *)
314 pr ":guestfs_%s\",\n" name;
318 | Pathname n | Device n | Dev_or_Path n | String n | Key n
319 | FileIn n | FileOut n -> pr ", &%s" n
320 | OptString n -> pr ", &%s" n
321 | StringList n | DeviceList n -> pr ", &py_%s" n
322 | Bool n -> pr ", &%s" n
323 | Int n -> pr ", &%s" n
324 | Int64 n -> pr ", &%s" n
325 | Pointer (_, n) -> pr ", &%s_int64" n
326 | BufferIn n -> pr ", &%s, &%s_size" n n
331 | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
336 pr " return NULL;\n";
338 pr " g = get_handle (py_g);\n";
341 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
342 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
344 | StringList n | DeviceList n ->
345 pr " %s = get_string_list (py_%s);\n" n n;
346 pr " if (!%s) return NULL;\n" n
348 pr " %s = (%s) (intptr_t) %s_int64;\n" n t n
353 if optargs <> [] then (
354 let uc_name = String.uppercase name in
357 let n = name_of_argt argt in
358 let uc_n = String.uppercase n in
359 pr " if (optargs_t_%s != " n;
361 | Bool _ | Int _ | Int64 _ -> pr "-1"
362 | String _ -> pr "NULL"
366 pr " optargs_s.%s = optargs_t_%s;\n" n n;
367 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
373 (* Release Python GIL while running. This code is from
374 * libvirt/python/typewrappers.h. Thanks to Dan Berrange for
375 * showing us how to do this properly.
377 pr " if (PyEval_ThreadsInitialized ())\n";
378 pr " py_save = PyEval_SaveThread ();\n";
382 pr " r = guestfs_%s " name
384 pr " r = guestfs_%s_argv " name;
385 generate_c_call_args ~handle:"g" style;
389 pr " if (PyEval_ThreadsInitialized ())\n";
390 pr " PyEval_RestoreThread (py_save);\n";
395 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
396 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
397 | BufferIn _ | Pointer _ -> ()
398 | StringList n | DeviceList n ->
402 (match errcode_of_ret ret with
403 | `CannotReturnError -> ()
404 | `ErrorIsMinusOne ->
405 pr " if (r == -1) {\n";
406 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
407 pr " return NULL;\n";
410 pr " if (r == NULL) {\n";
411 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
412 pr " return NULL;\n";
419 pr " Py_INCREF (Py_None);\n";
420 pr " py_r = Py_None;\n"
422 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
423 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
424 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
425 | RConstOptString _ ->
427 pr " py_r = PyString_FromString (r);\n";
429 pr " Py_INCREF (Py_None);\n";
430 pr " py_r = Py_None;\n";
433 pr " py_r = PyString_FromString (r);\n";
436 pr " py_r = put_string_list (r);\n";
437 pr " free_strings (r);\n"
438 | RStruct (_, typ) ->
439 pr " py_r = put_%s (r);\n" typ;
440 pr " guestfs_free_%s (r);\n" typ
441 | RStructList (_, typ) ->
442 pr " py_r = put_%s_list (r);\n" typ;
443 pr " guestfs_free_%s_list (r);\n" typ
445 pr " py_r = put_table (r);\n";
446 pr " free_strings (r);\n"
448 pr " py_r = PyString_FromStringAndSize (r, size);\n";
452 pr " return py_r;\n";
457 (* Table of functions. *)
458 pr "static PyMethodDef methods[] = {\n";
459 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
460 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
461 pr " { (char *) \"set_event_callback\",\n";
462 pr " py_guestfs_set_event_callback, METH_VARARGS, NULL },\n";
463 pr " { (char *) \"delete_event_callback\",\n";
464 pr " py_guestfs_delete_event_callback, METH_VARARGS, NULL },\n";
466 fun (name, _, _, _, _, _, _) ->
467 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
470 pr " { NULL, NULL, 0, NULL }\n";
477 initlibguestfsmod (void)
479 static int initialized = 0;
481 if (initialized) return;
482 Py_InitModule ((char *) \"libguestfsmod\", methods);
487 (* Generate Python module. *)
488 and generate_python_py () =
489 generate_header HashStyle LGPLv2plus;
492 u\"\"\"Python bindings for libguestfs
495 g = guestfs.GuestFS ()
496 g.add_drive_opts (\"guest.img\", format=\"raw\")
498 parts = g.list_partitions ()
500 The guestfs module provides a Python binding to the libguestfs API
501 for examining and modifying virtual machine disk images.
503 Amongst the things this is good for: making batch configuration
504 changes to guests, getting disk used/free statistics (see also:
505 virt-df), migrating between virtualization systems (see also:
506 virt-p2v), performing partial backups, performing partial guest
507 clones, cloning guests and changing registry/UUID/hostname info, and
510 Libguestfs uses Linux kernel and qemu code, and can access any type of
511 guest filesystem that Linux and qemu can, including but not limited
512 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
513 schemes, qcow, qcow2, vmdk.
515 Libguestfs provides ways to enumerate guest storage (eg. partitions,
516 LVs, what filesystem is in each LV, etc.). It can also run commands
517 in the context of the guest. Also you can access filesystems over
520 Errors which happen while using the API are turned into Python
521 RuntimeError exceptions.
523 To create a guestfs handle you usually have to perform the following
526 # Create the handle, call add_drive* at least once, and possibly
527 # several times if the guest has multiple block devices:
528 g = guestfs.GuestFS ()
529 g.add_drive_opts (\"guest.img\", format=\"raw\")
531 # Launch the qemu subprocess and wait for it to become ready:
534 # Now you can issue commands, for example:
544 fun (name, bitmask) ->
545 pr "EVENT_%s = 0x%x\n" (String.uppercase name) bitmask
550 class ClosedHandle(ValueError):
554 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
557 \"\"\"Create a new libguestfs handle.\"\"\"
558 self._o = libguestfsmod.create ()
562 libguestfsmod.close (self._o)
564 def _check_not_closed (self):
566 raise ClosedHandle (\"GuestFS: method called on closed handle\")
569 u\"\"\"Explicitly close the guestfs handle.
571 The handle is closed implicitly when its reference count goes
572 to zero (eg. when it goes out of scope or the program ends).
574 This call is only needed if you want to force the handle to
575 close now. After calling this, the program must not call
576 any method on the handle (except the implicit call to
577 __del__ which happens when the final reference is cleaned up).
579 self._check_not_closed ()
580 libguestfsmod.close (self._o)
583 def set_event_callback (self, cb, event_bitmask):
584 u\"\"\"Register an event callback.
586 Register \"cb\" as a callback function for all of the
587 events in \"event_bitmask\". \"event_bitmask\" should be
588 one or more \"guestfs.EVENT_*\" flags logically or'd together.
590 This function returns an event handle which can be used
591 to delete the callback (see \"delete_event_callback\").
593 The callback function receives 4 parameters:
595 cb (event, event_handle, buf, array)
597 \"event\" is one of the \"EVENT_*\" flags. \"buf\" is a
598 message buffer (only for some types of events). \"array\"
599 is an array of integers (only for some types of events).
601 You should read the documentation for
602 \"guestfs_set_event_callback\" in guestfs(3) before using
605 self._check_not_closed ()
606 return libguestfsmod.set_event_callback (self._o, cb, event_bitmask)
608 def delete_event_callback (self, event_handle):
609 u\"\"\"Delete an event callback.\"\"\"
610 self._check_not_closed ()
611 libguestfsmod.delete_event_callback (self._o, event_handle)
616 fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
617 pr " def %s (self" name;
618 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
621 | Bool n | Int n | Int64 n -> pr ", %s=-1" n
622 | String n -> pr ", %s=None" n
627 if not (List.mem NotInDocs flags) then (
628 let doc = replace_str longdesc "C<guestfs_" "C<g." in
631 | RErr | RInt _ | RInt64 _ | RBool _
632 | RConstOptString _ | RConstString _
633 | RString _ | RBufferOut _ -> doc
635 doc ^ "\n\nThis function returns a list of strings."
636 | RStruct (_, typ) ->
637 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
638 | RStructList (_, typ) ->
639 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
641 doc ^ "\n\nThis function returns a dictionary." in
643 if List.mem ProtocolLimitWarning flags then
644 doc ^ "\n\n" ^ protocol_limit_warning
647 match deprecation_notice flags with
649 | Some txt -> doc ^ "\n\n" ^ txt in
650 let doc = pod2text ~width:60 name doc in
651 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
652 let doc = String.concat "\n " doc in
653 pr " u\"\"\"%s\"\"\"\n" doc;
655 (* Callers might pass in iterables instead of plain lists;
656 * convert those to plain lists because the C side of things
657 * cannot deal with iterables. (RHBZ#693306).
661 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
662 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
663 | BufferIn _ | Pointer _ -> ()
664 | StringList n | DeviceList n ->
665 pr " %s = list (%s)\n" n n
667 pr " self._check_not_closed ()\n";
668 pr " return libguestfsmod.%s (self._o" name;
669 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);