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
32 (* Generate Python C module. *)
33 let rec generate_python_c () =
34 generate_header CStyle LGPLv2plus;
37 #define PY_SSIZE_T_CLEAN 1
40 #if PY_VERSION_HEX < 0x02050000
41 typedef int Py_ssize_t;
42 #define PY_SSIZE_T_MAX INT_MAX
43 #define PY_SSIZE_T_MIN INT_MIN
50 #include \"guestfs.h\"
52 #ifndef HAVE_PYCAPSULE_NEW
60 get_handle (PyObject *obj)
63 assert (obj != Py_None);
64 #ifndef HAVE_PYCAPSULE_NEW
65 return ((Pyguestfs_Object *) obj)->g;
67 return (guestfs_h*) PyCapsule_GetPointer(obj, \"guestfs_h\");
72 put_handle (guestfs_h *g)
75 #ifndef HAVE_PYCAPSULE_NEW
77 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
79 return PyCapsule_New ((void *) g, \"guestfs_h\", NULL);
83 /* This list should be freed (but not the strings) after use. */
85 get_string_list (PyObject *obj)
92 if (!PyList_Check (obj)) {
93 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
97 Py_ssize_t slen = PyList_Size (obj);
99 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
103 r = malloc (sizeof (char *) * (len+1));
105 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
109 for (i = 0; i < len; ++i)
110 r[i] = PyString_AsString (PyList_GetItem (obj, i));
117 put_string_list (char * const * const argv)
122 for (argc = 0; argv[argc] != NULL; ++argc)
125 list = PyList_New (argc);
126 for (i = 0; i < argc; ++i)
127 PyList_SetItem (list, i, PyString_FromString (argv[i]));
133 put_table (char * const * const argv)
135 PyObject *list, *item;
138 for (argc = 0; argv[argc] != NULL; ++argc)
141 list = PyList_New (argc >> 1);
142 for (i = 0; i < argc; i += 2) {
143 item = PyTuple_New (2);
144 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
145 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
146 PyList_SetItem (list, i >> 1, item);
153 free_strings (char **argv)
157 for (argc = 0; argv[argc] != NULL; ++argc)
163 py_guestfs_create (PyObject *self, PyObject *args)
167 g = guestfs_create ();
169 PyErr_SetString (PyExc_RuntimeError,
170 \"guestfs.create: failed to allocate handle\");
173 guestfs_set_error_handler (g, NULL, NULL);
174 /* This can return NULL, but in that case put_handle will have
175 * set the Python error string.
177 return put_handle (g);
181 py_guestfs_close (PyObject *self, PyObject *args)
183 PyThreadState *py_save = NULL;
187 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
189 g = get_handle (py_g);
191 if (PyEval_ThreadsInitialized ())
192 py_save = PyEval_SaveThread ();
194 if (PyEval_ThreadsInitialized ())
195 PyEval_RestoreThread (py_save);
203 let emit_put_list_function typ =
204 pr "static PyObject *\n";
205 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
207 pr " PyObject *list;\n";
210 pr " list = PyList_New (%ss->len);\n" typ;
211 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
212 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
213 pr " return list;\n";
218 (* Structures, turned into Python dictionaries. *)
221 pr "static PyObject *\n";
222 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
224 pr " PyObject *dict;\n";
226 pr " dict = PyDict_New ();\n";
230 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
231 pr " PyString_FromString (%s->%s));\n"
234 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
235 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
238 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
239 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
241 | name, (FBytes|FUInt64) ->
242 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
243 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
246 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
247 pr " PyLong_FromLongLong (%s->%s));\n"
250 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
251 pr " PyLong_FromUnsignedLong (%s->%s));\n"
254 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
255 pr " PyLong_FromLong (%s->%s));\n"
257 | name, FOptPercent ->
258 pr " if (%s->%s >= 0)\n" typ name;
259 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
260 pr " PyFloat_FromDouble ((double) %s->%s));\n"
263 pr " Py_INCREF (Py_None);\n";
264 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
267 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
268 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
270 pr " return dict;\n";
276 (* Emit a put_TYPE_list function definition only if that function is used. *)
279 | typ, (RStructListOnly | RStructAndList) ->
280 (* generate the function for typ *)
281 emit_put_list_function typ
282 | typ, _ -> () (* empty *)
283 ) (rstructs_used_by all_functions);
285 (* Python wrapper functions. *)
287 fun (name, (ret, args, optargs as style), _, _, _, _, _) ->
288 pr "static PyObject *\n";
289 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
292 pr " PyThreadState *py_save = NULL;\n";
293 pr " PyObject *py_g;\n";
294 pr " guestfs_h *g;\n";
295 pr " PyObject *py_r;\n";
297 if optargs <> [] then (
298 pr " struct guestfs_%s_argv optargs_s;\n" name;
299 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
303 | RErr | RInt _ | RBool _ -> pr " int r;\n"
304 | RInt64 _ -> pr " int64_t r;\n"
305 | RConstString _ | RConstOptString _ ->
306 pr " const char *r;\n"
307 | RString _ -> pr " char *r;\n"
308 | RStringList _ | RHashtable _ -> pr " char **r;\n"
309 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
310 | RStructList (_, typ) ->
311 pr " struct guestfs_%s_list *r;\n" typ
319 | Pathname n | Device n | Dev_or_Path n | String n | Key n
320 | FileIn n | FileOut n ->
321 pr " const char *%s;\n" n
322 | OptString n -> pr " const char *%s;\n" n
324 pr " const char *%s;\n" n;
325 pr " Py_ssize_t %s_size;\n" n
326 | StringList n | DeviceList n ->
327 pr " PyObject *py_%s;\n" n;
329 | Bool n -> pr " int %s;\n" n
330 | Int n -> pr " int %s;\n" n
331 | Int64 n -> pr " long long %s;\n" n
333 pr " long long %s_int64;\n" n;
337 if optargs <> [] then (
338 (* XXX This is horrible. We have to use sentinel values on the
339 * Python side to denote values not set.
341 (* Since we don't know if Python types will exactly match
342 * structure types, declare some local variables here.
347 | Int n -> pr " int optargs_t_%s = -1;\n" n
348 | Int64 n -> pr " long long optargs_t_%s = -1;\n" n
349 | String n -> pr " const char *optargs_t_%s = NULL;\n" n
356 if optargs <> [] then (
357 pr " optargs_s.bitmask = 0;\n";
361 (* Convert the required parameters. *)
362 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
365 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
366 | FileIn _ | FileOut _ -> pr "s"
367 | OptString _ -> pr "z"
368 | StringList _ | DeviceList _ -> pr "O"
369 | Bool _ -> pr "i" (* XXX Python has booleans? *)
371 | Int64 _ | Pointer _ ->
372 (* XXX Whoever thought it was a good idea to
373 * emulate C's int/long/long long in Python?
376 | BufferIn _ -> pr "s#"
379 (* Optional parameters. *)
380 if optargs <> [] then (
383 | Bool _ | Int _ -> pr "i"
385 | String _ -> pr "z" (* because we use None to mean not set *)
390 pr ":guestfs_%s\",\n" name;
394 | Pathname n | Device n | Dev_or_Path n | String n | Key n
395 | FileIn n | FileOut n -> pr ", &%s" n
396 | OptString n -> pr ", &%s" n
397 | StringList n | DeviceList n -> pr ", &py_%s" n
398 | Bool n -> pr ", &%s" n
399 | Int n -> pr ", &%s" n
400 | Int64 n -> pr ", &%s" n
401 | Pointer (_, n) -> pr ", &%s_int64" n
402 | BufferIn n -> pr ", &%s, &%s_size" n n
407 | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
412 pr " return NULL;\n";
414 pr " g = get_handle (py_g);\n";
417 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
418 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
420 | StringList n | DeviceList n ->
421 pr " %s = get_string_list (py_%s);\n" n n;
422 pr " if (!%s) return NULL;\n" n
424 pr " %s = (%s) (intptr_t) %s_int64;\n" n t n
429 if optargs <> [] then (
430 let uc_name = String.uppercase name in
433 let n = name_of_argt argt in
434 let uc_n = String.uppercase n in
435 pr " if (optargs_t_%s != " n;
437 | Bool _ | Int _ | Int64 _ -> pr "-1"
438 | String _ -> pr "NULL"
442 pr " optargs_s.%s = optargs_t_%s;\n" n n;
443 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
449 (* Release Python GIL while running. This code is from
450 * libvirt/python/typewrappers.h. Thanks to Dan Berrange for
451 * showing us how to do this properly.
453 pr " if (PyEval_ThreadsInitialized ())\n";
454 pr " py_save = PyEval_SaveThread ();\n";
458 pr " r = guestfs_%s " name
460 pr " r = guestfs_%s_argv " name;
461 generate_c_call_args ~handle:"g" style;
465 pr " if (PyEval_ThreadsInitialized ())\n";
466 pr " PyEval_RestoreThread (py_save);\n";
471 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
472 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
473 | BufferIn _ | Pointer _ -> ()
474 | StringList n | DeviceList n ->
478 (match errcode_of_ret ret with
479 | `CannotReturnError -> ()
480 | `ErrorIsMinusOne ->
481 pr " if (r == -1) {\n";
482 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
483 pr " return NULL;\n";
486 pr " if (r == NULL) {\n";
487 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
488 pr " return NULL;\n";
495 pr " Py_INCREF (Py_None);\n";
496 pr " py_r = Py_None;\n"
498 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
499 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
500 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
501 | RConstOptString _ ->
503 pr " py_r = PyString_FromString (r);\n";
505 pr " Py_INCREF (Py_None);\n";
506 pr " py_r = Py_None;\n";
509 pr " py_r = PyString_FromString (r);\n";
512 pr " py_r = put_string_list (r);\n";
513 pr " free_strings (r);\n"
514 | RStruct (_, typ) ->
515 pr " py_r = put_%s (r);\n" typ;
516 pr " guestfs_free_%s (r);\n" typ
517 | RStructList (_, typ) ->
518 pr " py_r = put_%s_list (r);\n" typ;
519 pr " guestfs_free_%s_list (r);\n" typ
521 pr " py_r = put_table (r);\n";
522 pr " free_strings (r);\n"
524 pr " py_r = PyString_FromStringAndSize (r, size);\n";
528 pr " return py_r;\n";
533 (* Table of functions. *)
534 pr "static PyMethodDef methods[] = {\n";
535 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
536 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
538 fun (name, _, _, _, _, _, _) ->
539 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
542 pr " { NULL, NULL, 0, NULL }\n";
549 initlibguestfsmod (void)
551 static int initialized = 0;
553 if (initialized) return;
554 Py_InitModule ((char *) \"libguestfsmod\", methods);
559 (* Generate Python module. *)
560 and generate_python_py () =
561 generate_header HashStyle LGPLv2plus;
564 u\"\"\"Python bindings for libguestfs
567 g = guestfs.GuestFS ()
568 g.add_drive_opts (\"guest.img\", format=\"raw\")
570 parts = g.list_partitions ()
572 The guestfs module provides a Python binding to the libguestfs API
573 for examining and modifying virtual machine disk images.
575 Amongst the things this is good for: making batch configuration
576 changes to guests, getting disk used/free statistics (see also:
577 virt-df), migrating between virtualization systems (see also:
578 virt-p2v), performing partial backups, performing partial guest
579 clones, cloning guests and changing registry/UUID/hostname info, and
582 Libguestfs uses Linux kernel and qemu code, and can access any type of
583 guest filesystem that Linux and qemu can, including but not limited
584 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
585 schemes, qcow, qcow2, vmdk.
587 Libguestfs provides ways to enumerate guest storage (eg. partitions,
588 LVs, what filesystem is in each LV, etc.). It can also run commands
589 in the context of the guest. Also you can access filesystems over
592 Errors which happen while using the API are turned into Python
593 RuntimeError exceptions.
595 To create a guestfs handle you usually have to perform the following
598 # Create the handle, call add_drive* at least once, and possibly
599 # several times if the guest has multiple block devices:
600 g = guestfs.GuestFS ()
601 g.add_drive_opts (\"guest.img\", format=\"raw\")
603 # Launch the qemu subprocess and wait for it to become ready:
606 # Now you can issue commands, for example:
614 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
617 \"\"\"Create a new libguestfs handle.\"\"\"
618 self._o = libguestfsmod.create ()
621 libguestfsmod.close (self._o)
626 fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
627 pr " def %s (self" name;
628 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
631 | Bool n | Int n | Int64 n -> pr ", %s=-1" n
632 | String n -> pr ", %s=None" n
637 if not (List.mem NotInDocs flags) then (
638 let doc = replace_str longdesc "C<guestfs_" "C<g." in
641 | RErr | RInt _ | RInt64 _ | RBool _
642 | RConstOptString _ | RConstString _
643 | RString _ | RBufferOut _ -> doc
645 doc ^ "\n\nThis function returns a list of strings."
646 | RStruct (_, typ) ->
647 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
648 | RStructList (_, typ) ->
649 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
651 doc ^ "\n\nThis function returns a dictionary." in
653 if List.mem ProtocolLimitWarning flags then
654 doc ^ "\n\n" ^ protocol_limit_warning
657 if List.mem DangerWillRobinson flags then
658 doc ^ "\n\n" ^ danger_will_robinson
661 match deprecation_notice flags with
663 | Some txt -> doc ^ "\n\n" ^ txt in
664 let doc = pod2text ~width:60 name doc in
665 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
666 let doc = String.concat "\n " doc in
667 pr " u\"\"\"%s\"\"\"\n" doc;
669 (* Callers might pass in iterables instead of plain lists;
670 * convert those to plain lists because the C side of things
671 * cannot deal with iterables. (RHBZ#693306).
675 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
676 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
677 | BufferIn _ | Pointer _ -> ()
678 | StringList n | DeviceList n ->
679 pr " %s = list (%s)\n" n n
681 pr " return libguestfsmod.%s (self._o" name;
682 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);