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;
41 #include \"guestfs-py.h\"
43 /* This list should be freed (but not the strings) after use. */
45 get_string_list (PyObject *obj)
52 if (!PyList_Check (obj)) {
53 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
57 Py_ssize_t slen = PyList_Size (obj);
59 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
63 r = malloc (sizeof (char *) * (len+1));
65 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
69 for (i = 0; i < len; ++i)
70 r[i] = PyString_AsString (PyList_GetItem (obj, i));
77 put_string_list (char * const * const argv)
82 for (argc = 0; argv[argc] != NULL; ++argc)
85 list = PyList_New (argc);
86 for (i = 0; i < argc; ++i)
87 PyList_SetItem (list, i, PyString_FromString (argv[i]));
93 put_table (char * const * const argv)
95 PyObject *list, *item;
98 for (argc = 0; argv[argc] != NULL; ++argc)
101 list = PyList_New (argc >> 1);
102 for (i = 0; i < argc; i += 2) {
103 item = PyTuple_New (2);
104 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
105 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
106 PyList_SetItem (list, i >> 1, item);
113 free_strings (char **argv)
117 for (argc = 0; argv[argc] != NULL; ++argc)
124 let emit_put_list_function typ =
125 pr "static PyObject *\n";
126 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
128 pr " PyObject *list;\n";
131 pr " list = PyList_New (%ss->len);\n" typ;
132 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
133 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
134 pr " return list;\n";
139 (* Structures, turned into Python dictionaries. *)
142 pr "static PyObject *\n";
143 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
145 pr " PyObject *dict;\n";
147 pr " dict = PyDict_New ();\n";
151 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
152 pr " PyString_FromString (%s->%s));\n"
155 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
156 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
159 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
160 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
162 | name, (FBytes|FUInt64) ->
163 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
164 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
167 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
168 pr " PyLong_FromLongLong (%s->%s));\n"
171 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
172 pr " PyLong_FromUnsignedLong (%s->%s));\n"
175 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
176 pr " PyLong_FromLong (%s->%s));\n"
178 | name, FOptPercent ->
179 pr " if (%s->%s >= 0)\n" typ name;
180 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
181 pr " PyFloat_FromDouble ((double) %s->%s));\n"
184 pr " Py_INCREF (Py_None);\n";
185 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
188 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
189 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
191 pr " return dict;\n";
197 (* Emit a put_TYPE_list function definition only if that function is used. *)
200 | typ, (RStructListOnly | RStructAndList) ->
201 (* generate the function for typ *)
202 emit_put_list_function typ
203 | typ, _ -> () (* empty *)
204 ) (rstructs_used_by all_functions);
206 (* Python wrapper functions. *)
208 fun (name, (ret, args, optargs as style), _, _, _, _, _) ->
209 pr "static PyObject *\n";
210 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
213 pr " PyThreadState *py_save = NULL;\n";
214 pr " PyObject *py_g;\n";
215 pr " guestfs_h *g;\n";
216 pr " PyObject *py_r;\n";
218 if optargs <> [] then (
219 pr " struct guestfs_%s_argv optargs_s;\n" name;
220 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
224 | RErr | RInt _ | RBool _ -> pr " int r;\n"
225 | RInt64 _ -> pr " int64_t r;\n"
226 | RConstString _ | RConstOptString _ ->
227 pr " const char *r;\n"
228 | RString _ -> pr " char *r;\n"
229 | RStringList _ | RHashtable _ -> pr " char **r;\n"
230 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
231 | RStructList (_, typ) ->
232 pr " struct guestfs_%s_list *r;\n" typ
240 | Pathname n | Device n | Dev_or_Path n | String n | Key n
241 | FileIn n | FileOut n ->
242 pr " const char *%s;\n" n
243 | OptString n -> pr " const char *%s;\n" n
245 pr " const char *%s;\n" n;
246 pr " Py_ssize_t %s_size;\n" n
247 | StringList n | DeviceList n ->
248 pr " PyObject *py_%s;\n" n;
250 | Bool n -> pr " int %s;\n" n
251 | Int n -> pr " int %s;\n" n
252 | Int64 n -> pr " long long %s;\n" n
254 pr " long long %s_int64;\n" n;
258 if optargs <> [] then (
259 (* XXX This is horrible. We have to use sentinel values on the
260 * Python side to denote values not set.
262 (* Since we don't know if Python types will exactly match
263 * structure types, declare some local variables here.
268 | Int n -> pr " int optargs_t_%s = -1;\n" n
269 | Int64 n -> pr " long long optargs_t_%s = -1;\n" n
270 | String n -> pr " const char *optargs_t_%s = NULL;\n" n
277 if optargs <> [] then (
278 pr " optargs_s.bitmask = 0;\n";
282 (* Convert the required parameters. *)
283 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
286 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
287 | FileIn _ | FileOut _ -> pr "s"
288 | OptString _ -> pr "z"
289 | StringList _ | DeviceList _ -> pr "O"
290 | Bool _ -> pr "i" (* XXX Python has booleans? *)
292 | Int64 _ | Pointer _ ->
293 (* XXX Whoever thought it was a good idea to
294 * emulate C's int/long/long long in Python?
297 | BufferIn _ -> pr "s#"
300 (* Optional parameters. *)
301 if optargs <> [] then (
304 | Bool _ | Int _ -> pr "i"
306 | String _ -> pr "z" (* because we use None to mean not set *)
311 pr ":guestfs_%s\",\n" name;
315 | Pathname n | Device n | Dev_or_Path n | String n | Key n
316 | FileIn n | FileOut n -> pr ", &%s" n
317 | OptString n -> pr ", &%s" n
318 | StringList n | DeviceList n -> pr ", &py_%s" n
319 | Bool n -> pr ", &%s" n
320 | Int n -> pr ", &%s" n
321 | Int64 n -> pr ", &%s" n
322 | Pointer (_, n) -> pr ", &%s_int64" n
323 | BufferIn n -> pr ", &%s, &%s_size" n n
328 | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
333 pr " return NULL;\n";
335 pr " g = get_handle (py_g);\n";
338 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
339 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
341 | StringList n | DeviceList n ->
342 pr " %s = get_string_list (py_%s);\n" n n;
343 pr " if (!%s) return NULL;\n" n
345 pr " %s = (%s) (intptr_t) %s_int64;\n" n t n
350 if optargs <> [] then (
351 let uc_name = String.uppercase name in
354 let n = name_of_argt argt in
355 let uc_n = String.uppercase n in
356 pr " if (optargs_t_%s != " n;
358 | Bool _ | Int _ | Int64 _ -> pr "-1"
359 | String _ -> pr "NULL"
363 pr " optargs_s.%s = optargs_t_%s;\n" n n;
364 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
370 (* Release Python GIL while running. This code is from
371 * libvirt/python/typewrappers.h. Thanks to Dan Berrange for
372 * showing us how to do this properly.
374 pr " if (PyEval_ThreadsInitialized ())\n";
375 pr " py_save = PyEval_SaveThread ();\n";
379 pr " r = guestfs_%s " name
381 pr " r = guestfs_%s_argv " name;
382 generate_c_call_args ~handle:"g" style;
386 pr " if (PyEval_ThreadsInitialized ())\n";
387 pr " PyEval_RestoreThread (py_save);\n";
392 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
393 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
394 | BufferIn _ | Pointer _ -> ()
395 | StringList n | DeviceList n ->
399 (match errcode_of_ret ret with
400 | `CannotReturnError -> ()
401 | `ErrorIsMinusOne ->
402 pr " if (r == -1) {\n";
403 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
404 pr " return NULL;\n";
407 pr " if (r == NULL) {\n";
408 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
409 pr " return NULL;\n";
416 pr " Py_INCREF (Py_None);\n";
417 pr " py_r = Py_None;\n"
419 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
420 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
421 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
422 | RConstOptString _ ->
424 pr " py_r = PyString_FromString (r);\n";
426 pr " Py_INCREF (Py_None);\n";
427 pr " py_r = Py_None;\n";
430 pr " py_r = PyString_FromString (r);\n";
433 pr " py_r = put_string_list (r);\n";
434 pr " free_strings (r);\n"
435 | RStruct (_, typ) ->
436 pr " py_r = put_%s (r);\n" typ;
437 pr " guestfs_free_%s (r);\n" typ
438 | RStructList (_, typ) ->
439 pr " py_r = put_%s_list (r);\n" typ;
440 pr " guestfs_free_%s_list (r);\n" typ
442 pr " py_r = put_table (r);\n";
443 pr " free_strings (r);\n"
445 pr " py_r = PyString_FromStringAndSize (r, size);\n";
449 pr " return py_r;\n";
454 (* Table of functions. *)
455 pr "static PyMethodDef methods[] = {\n";
456 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
457 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
459 fun (name, _, _, _, _, _, _) ->
460 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
463 pr " { NULL, NULL, 0, NULL }\n";
470 initlibguestfsmod (void)
472 static int initialized = 0;
474 if (initialized) return;
475 Py_InitModule ((char *) \"libguestfsmod\", methods);
480 (* Generate Python module. *)
481 and generate_python_py () =
482 generate_header HashStyle LGPLv2plus;
485 u\"\"\"Python bindings for libguestfs
488 g = guestfs.GuestFS ()
489 g.add_drive_opts (\"guest.img\", format=\"raw\")
491 parts = g.list_partitions ()
493 The guestfs module provides a Python binding to the libguestfs API
494 for examining and modifying virtual machine disk images.
496 Amongst the things this is good for: making batch configuration
497 changes to guests, getting disk used/free statistics (see also:
498 virt-df), migrating between virtualization systems (see also:
499 virt-p2v), performing partial backups, performing partial guest
500 clones, cloning guests and changing registry/UUID/hostname info, and
503 Libguestfs uses Linux kernel and qemu code, and can access any type of
504 guest filesystem that Linux and qemu can, including but not limited
505 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
506 schemes, qcow, qcow2, vmdk.
508 Libguestfs provides ways to enumerate guest storage (eg. partitions,
509 LVs, what filesystem is in each LV, etc.). It can also run commands
510 in the context of the guest. Also you can access filesystems over
513 Errors which happen while using the API are turned into Python
514 RuntimeError exceptions.
516 To create a guestfs handle you usually have to perform the following
519 # Create the handle, call add_drive* at least once, and possibly
520 # several times if the guest has multiple block devices:
521 g = guestfs.GuestFS ()
522 g.add_drive_opts (\"guest.img\", format=\"raw\")
524 # Launch the qemu subprocess and wait for it to become ready:
527 # Now you can issue commands, for example:
535 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
538 \"\"\"Create a new libguestfs handle.\"\"\"
539 self._o = libguestfsmod.create ()
542 libguestfsmod.close (self._o)
547 fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
548 pr " def %s (self" name;
549 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
552 | Bool n | Int n | Int64 n -> pr ", %s=-1" n
553 | String n -> pr ", %s=None" n
558 if not (List.mem NotInDocs flags) then (
559 let doc = replace_str longdesc "C<guestfs_" "C<g." in
562 | RErr | RInt _ | RInt64 _ | RBool _
563 | RConstOptString _ | RConstString _
564 | RString _ | RBufferOut _ -> doc
566 doc ^ "\n\nThis function returns a list of strings."
567 | RStruct (_, typ) ->
568 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
569 | RStructList (_, typ) ->
570 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
572 doc ^ "\n\nThis function returns a dictionary." in
574 if List.mem ProtocolLimitWarning flags then
575 doc ^ "\n\n" ^ protocol_limit_warning
578 if List.mem DangerWillRobinson flags then
579 doc ^ "\n\n" ^ danger_will_robinson
582 match deprecation_notice flags with
584 | Some txt -> doc ^ "\n\n" ^ txt in
585 let doc = pod2text ~width:60 name doc in
586 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
587 let doc = String.concat "\n " doc in
588 pr " u\"\"\"%s\"\"\"\n" doc;
590 (* Callers might pass in iterables instead of plain lists;
591 * convert those to plain lists because the C side of things
592 * cannot deal with iterables. (RHBZ#693306).
596 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
597 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
598 | BufferIn _ | Pointer _ -> ()
599 | StringList n | DeviceList n ->
600 pr " %s = list (%s)\n" n n
602 pr " return libguestfsmod.%s (self._o" name;
603 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);