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;
42 #include \"guestfs-py.h\"
44 /* This list should be freed (but not the strings) after use. */
46 get_string_list (PyObject *obj)
53 if (!PyList_Check (obj)) {
54 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
58 Py_ssize_t slen = PyList_Size (obj);
60 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
64 r = malloc (sizeof (char *) * (len+1));
66 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
70 for (i = 0; i < len; ++i)
71 r[i] = PyString_AsString (PyList_GetItem (obj, i));
78 put_string_list (char * const * const argv)
83 for (argc = 0; argv[argc] != NULL; ++argc)
86 list = PyList_New (argc);
87 for (i = 0; i < argc; ++i)
88 PyList_SetItem (list, i, PyString_FromString (argv[i]));
94 put_table (char * const * const argv)
96 PyObject *list, *item;
99 for (argc = 0; argv[argc] != NULL; ++argc)
102 list = PyList_New (argc >> 1);
103 for (i = 0; i < argc; i += 2) {
104 item = PyTuple_New (2);
105 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
106 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
107 PyList_SetItem (list, i >> 1, item);
114 free_strings (char **argv)
118 for (argc = 0; argv[argc] != NULL; ++argc)
125 let emit_put_list_function typ =
126 pr "static PyObject *\n";
127 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
129 pr " PyObject *list;\n";
132 pr " list = PyList_New (%ss->len);\n" typ;
133 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
134 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
135 pr " return list;\n";
140 (* Structures, turned into Python dictionaries. *)
143 pr "static PyObject *\n";
144 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
146 pr " PyObject *dict;\n";
148 pr " dict = PyDict_New ();\n";
152 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
153 pr " PyString_FromString (%s->%s));\n"
156 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
157 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
160 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
161 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
163 | name, (FBytes|FUInt64) ->
164 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
165 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
168 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
169 pr " PyLong_FromLongLong (%s->%s));\n"
172 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
173 pr " PyLong_FromUnsignedLong (%s->%s));\n"
176 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
177 pr " PyLong_FromLong (%s->%s));\n"
179 | name, FOptPercent ->
180 pr " if (%s->%s >= 0)\n" typ name;
181 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
182 pr " PyFloat_FromDouble ((double) %s->%s));\n"
185 pr " Py_INCREF (Py_None);\n";
186 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
189 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
190 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
192 pr " return dict;\n";
198 (* Emit a put_TYPE_list function definition only if that function is used. *)
201 | typ, (RStructListOnly | RStructAndList) ->
202 (* generate the function for typ *)
203 emit_put_list_function typ
204 | typ, _ -> () (* empty *)
205 ) (rstructs_used_by all_functions);
207 (* Python wrapper functions. *)
209 fun (name, (ret, args, optargs as style), _, _, _, _, _) ->
210 pr "static PyObject *\n";
211 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
214 pr " PyThreadState *py_save = NULL;\n";
215 pr " PyObject *py_g;\n";
216 pr " guestfs_h *g;\n";
217 pr " PyObject *py_r;\n";
219 if optargs <> [] then (
220 pr " struct guestfs_%s_argv optargs_s;\n" name;
221 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
225 | RErr | RInt _ | RBool _ -> pr " int r;\n"
226 | RInt64 _ -> pr " int64_t r;\n"
227 | RConstString _ | RConstOptString _ ->
228 pr " const char *r;\n"
229 | RString _ -> pr " char *r;\n"
230 | RStringList _ | RHashtable _ -> pr " char **r;\n"
231 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
232 | RStructList (_, typ) ->
233 pr " struct guestfs_%s_list *r;\n" typ
241 | Pathname n | Device n | Dev_or_Path n | String n | Key n
242 | FileIn n | FileOut n ->
243 pr " const char *%s;\n" n
244 | OptString n -> pr " const char *%s;\n" n
246 pr " const char *%s;\n" n;
247 pr " Py_ssize_t %s_size;\n" n
248 | StringList n | DeviceList n ->
249 pr " PyObject *py_%s;\n" n;
251 | Bool n -> pr " int %s;\n" n
252 | Int n -> pr " int %s;\n" n
253 | Int64 n -> pr " long long %s;\n" n
255 pr " long long %s_int64;\n" n;
259 if optargs <> [] then (
260 (* XXX This is horrible. We have to use sentinel values on the
261 * Python side to denote values not set.
263 (* Since we don't know if Python types will exactly match
264 * structure types, declare some local variables here.
269 | Int n -> pr " int optargs_t_%s = -1;\n" n
270 | Int64 n -> pr " long long optargs_t_%s = -1;\n" n
271 | String n -> pr " const char *optargs_t_%s = NULL;\n" n
278 if optargs <> [] then (
279 pr " optargs_s.bitmask = 0;\n";
283 (* Convert the required parameters. *)
284 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
287 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
288 | FileIn _ | FileOut _ -> pr "s"
289 | OptString _ -> pr "z"
290 | StringList _ | DeviceList _ -> pr "O"
291 | Bool _ -> pr "i" (* XXX Python has booleans? *)
293 | Int64 _ | Pointer _ ->
294 (* XXX Whoever thought it was a good idea to
295 * emulate C's int/long/long long in Python?
298 | BufferIn _ -> pr "s#"
301 (* Optional parameters. *)
302 if optargs <> [] then (
305 | Bool _ | Int _ -> pr "i"
307 | String _ -> pr "z" (* because we use None to mean not set *)
312 pr ":guestfs_%s\",\n" name;
316 | Pathname n | Device n | Dev_or_Path n | String n | Key n
317 | FileIn n | FileOut n -> pr ", &%s" n
318 | OptString n -> pr ", &%s" n
319 | StringList n | DeviceList n -> pr ", &py_%s" n
320 | Bool n -> pr ", &%s" n
321 | Int n -> pr ", &%s" n
322 | Int64 n -> pr ", &%s" n
323 | Pointer (_, n) -> pr ", &%s_int64" n
324 | BufferIn n -> pr ", &%s, &%s_size" n n
329 | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
334 pr " return NULL;\n";
336 pr " g = get_handle (py_g);\n";
339 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
340 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
342 | StringList n | DeviceList n ->
343 pr " %s = get_string_list (py_%s);\n" n n;
344 pr " if (!%s) return NULL;\n" n
346 pr " %s = (%s) (intptr_t) %s_int64;\n" n t n
351 if optargs <> [] then (
352 let uc_name = String.uppercase name in
355 let n = name_of_argt argt in
356 let uc_n = String.uppercase n in
357 pr " if (optargs_t_%s != " n;
359 | Bool _ | Int _ | Int64 _ -> pr "-1"
360 | String _ -> pr "NULL"
364 pr " optargs_s.%s = optargs_t_%s;\n" n n;
365 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
371 (* Release Python GIL while running. This code is from
372 * libvirt/python/typewrappers.h. Thanks to Dan Berrange for
373 * showing us how to do this properly.
375 pr " if (PyEval_ThreadsInitialized ())\n";
376 pr " py_save = PyEval_SaveThread ();\n";
380 pr " r = guestfs_%s " name
382 pr " r = guestfs_%s_argv " name;
383 generate_c_call_args ~handle:"g" style;
387 pr " if (PyEval_ThreadsInitialized ())\n";
388 pr " PyEval_RestoreThread (py_save);\n";
393 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
394 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
395 | BufferIn _ | Pointer _ -> ()
396 | StringList n | DeviceList n ->
400 (match errcode_of_ret ret with
401 | `CannotReturnError -> ()
402 | `ErrorIsMinusOne ->
403 pr " if (r == -1) {\n";
404 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
405 pr " return NULL;\n";
408 pr " if (r == NULL) {\n";
409 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
410 pr " return NULL;\n";
417 pr " Py_INCREF (Py_None);\n";
418 pr " py_r = Py_None;\n"
420 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
421 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
422 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
423 | RConstOptString _ ->
425 pr " py_r = PyString_FromString (r);\n";
427 pr " Py_INCREF (Py_None);\n";
428 pr " py_r = Py_None;\n";
431 pr " py_r = PyString_FromString (r);\n";
434 pr " py_r = put_string_list (r);\n";
435 pr " free_strings (r);\n"
436 | RStruct (_, typ) ->
437 pr " py_r = put_%s (r);\n" typ;
438 pr " guestfs_free_%s (r);\n" typ
439 | RStructList (_, typ) ->
440 pr " py_r = put_%s_list (r);\n" typ;
441 pr " guestfs_free_%s_list (r);\n" typ
443 pr " py_r = put_table (r);\n";
444 pr " free_strings (r);\n"
446 pr " py_r = PyString_FromStringAndSize (r, size);\n";
450 pr " return py_r;\n";
455 (* Table of functions. *)
456 pr "static PyMethodDef methods[] = {\n";
457 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
458 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
459 pr " { (char *) \"set_event_callback\",\n";
460 pr " py_guestfs_set_event_callback, METH_VARARGS, NULL },\n";
461 pr " { (char *) \"delete_event_callback\",\n";
462 pr " py_guestfs_delete_event_callback, METH_VARARGS, NULL },\n";
464 fun (name, _, _, _, _, _, _) ->
465 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
468 pr " { NULL, NULL, 0, NULL }\n";
475 initlibguestfsmod (void)
477 static int initialized = 0;
479 if (initialized) return;
480 Py_InitModule ((char *) \"libguestfsmod\", methods);
485 (* Generate Python module. *)
486 and generate_python_py () =
487 generate_header HashStyle LGPLv2plus;
490 u\"\"\"Python bindings for libguestfs
493 g = guestfs.GuestFS ()
494 g.add_drive_opts (\"guest.img\", format=\"raw\")
496 parts = g.list_partitions ()
498 The guestfs module provides a Python binding to the libguestfs API
499 for examining and modifying virtual machine disk images.
501 Amongst the things this is good for: making batch configuration
502 changes to guests, getting disk used/free statistics (see also:
503 virt-df), migrating between virtualization systems (see also:
504 virt-p2v), performing partial backups, performing partial guest
505 clones, cloning guests and changing registry/UUID/hostname info, and
508 Libguestfs uses Linux kernel and qemu code, and can access any type of
509 guest filesystem that Linux and qemu can, including but not limited
510 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
511 schemes, qcow, qcow2, vmdk.
513 Libguestfs provides ways to enumerate guest storage (eg. partitions,
514 LVs, what filesystem is in each LV, etc.). It can also run commands
515 in the context of the guest. Also you can access filesystems over
518 Errors which happen while using the API are turned into Python
519 RuntimeError exceptions.
521 To create a guestfs handle you usually have to perform the following
524 # Create the handle, call add_drive* at least once, and possibly
525 # several times if the guest has multiple block devices:
526 g = guestfs.GuestFS ()
527 g.add_drive_opts (\"guest.img\", format=\"raw\")
529 # Launch the qemu subprocess and wait for it to become ready:
532 # Now you can issue commands, for example:
542 fun (name, bitmask) ->
543 pr "EVENT_%s = 0x%x\n" (String.uppercase name) bitmask
549 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
552 \"\"\"Create a new libguestfs handle.\"\"\"
553 self._o = libguestfsmod.create ()
556 libguestfsmod.close (self._o)
558 def set_event_callback (self, cb, event_bitmask):
559 u\"\"\"Register an event callback.
561 Register \"cb\" as a callback function for all of the
562 events in \"event_bitmask\". \"event_bitmask\" should be
563 one or more \"guestfs.EVENT_*\" flags logically or'd together.
565 This function returns an event handle which can be used
566 to delete the callback (see \"delete_event_callback\").
568 The callback function receives 4 parameters:
570 cb (event, event_handle, buf, array)
572 \"event\" is one of the \"EVENT_*\" flags. \"buf\" is a
573 message buffer (only for some types of events). \"array\"
574 is an array of integers (only for some types of events).
576 You should read the documentation for
577 \"guestfs_set_event_callback\" in guestfs(3) before using
580 return libguestfsmod.set_event_callback (self._o, cb, event_bitmask)
582 def delete_event_callback (self, event_handle):
583 u\"\"\"Delete an event callback.\"\"\"
584 libguestfsmod.delete_event_callback (self._o, event_handle)
589 fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
590 pr " def %s (self" name;
591 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
594 | Bool n | Int n | Int64 n -> pr ", %s=-1" n
595 | String n -> pr ", %s=None" n
600 if not (List.mem NotInDocs flags) then (
601 let doc = replace_str longdesc "C<guestfs_" "C<g." in
604 | RErr | RInt _ | RInt64 _ | RBool _
605 | RConstOptString _ | RConstString _
606 | RString _ | RBufferOut _ -> doc
608 doc ^ "\n\nThis function returns a list of strings."
609 | RStruct (_, typ) ->
610 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
611 | RStructList (_, typ) ->
612 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
614 doc ^ "\n\nThis function returns a dictionary." in
616 if List.mem ProtocolLimitWarning flags then
617 doc ^ "\n\n" ^ protocol_limit_warning
620 if List.mem DangerWillRobinson flags then
621 doc ^ "\n\n" ^ danger_will_robinson
624 match deprecation_notice flags with
626 | Some txt -> doc ^ "\n\n" ^ txt in
627 let doc = pod2text ~width:60 name doc in
628 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
629 let doc = String.concat "\n " doc in
630 pr " u\"\"\"%s\"\"\"\n" doc;
632 (* Callers might pass in iterables instead of plain lists;
633 * convert those to plain lists because the C side of things
634 * cannot deal with iterables. (RHBZ#693306).
638 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
639 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
640 | BufferIn _ | Pointer _ -> ()
641 | StringList n | DeviceList n ->
642 pr " %s = list (%s)\n" n n
644 pr " return libguestfsmod.%s (self._o" name;
645 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);