2 * Copyright (C) 2009-2010 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)
186 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
188 g = get_handle (py_g);
198 let emit_put_list_function typ =
199 pr "static PyObject *\n";
200 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
202 pr " PyObject *list;\n";
205 pr " list = PyList_New (%ss->len);\n" typ;
206 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
207 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
208 pr " return list;\n";
213 (* Structures, turned into Python dictionaries. *)
216 pr "static PyObject *\n";
217 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
219 pr " PyObject *dict;\n";
221 pr " dict = PyDict_New ();\n";
225 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
226 pr " PyString_FromString (%s->%s));\n"
229 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
230 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
233 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
234 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
236 | name, (FBytes|FUInt64) ->
237 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
238 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
241 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
242 pr " PyLong_FromLongLong (%s->%s));\n"
245 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
246 pr " PyLong_FromUnsignedLong (%s->%s));\n"
249 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
250 pr " PyLong_FromLong (%s->%s));\n"
252 | name, FOptPercent ->
253 pr " if (%s->%s >= 0)\n" typ name;
254 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
255 pr " PyFloat_FromDouble ((double) %s->%s));\n"
258 pr " Py_INCREF (Py_None);\n";
259 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
262 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
263 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
265 pr " return dict;\n";
271 (* Emit a put_TYPE_list function definition only if that function is used. *)
274 | typ, (RStructListOnly | RStructAndList) ->
275 (* generate the function for typ *)
276 emit_put_list_function typ
277 | typ, _ -> () (* empty *)
278 ) (rstructs_used_by all_functions);
280 (* Python wrapper functions. *)
282 fun (name, style, _, _, _, _, _) ->
283 pr "static PyObject *\n";
284 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
287 pr " PyObject *py_g;\n";
288 pr " guestfs_h *g;\n";
289 pr " PyObject *py_r;\n";
293 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
294 | RInt64 _ -> pr " int64_t r;\n"; "-1"
295 | RConstString _ | RConstOptString _ ->
296 pr " const char *r;\n"; "NULL"
297 | RString _ -> pr " char *r;\n"; "NULL"
298 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
299 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
300 | RStructList (_, typ) ->
301 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
304 pr " size_t size;\n";
309 | Pathname n | Device n | Dev_or_Path n | String n | Key n
310 | FileIn n | FileOut n ->
311 pr " const char *%s;\n" n
312 | OptString n -> pr " const char *%s;\n" n
314 pr " const char *%s;\n" n;
315 pr " Py_ssize_t %s_size;\n" n
316 | StringList n | DeviceList n ->
317 pr " PyObject *py_%s;\n" n;
319 | Bool n -> pr " int %s;\n" n
320 | Int n -> pr " int %s;\n" n
321 | Int64 n -> pr " long long %s;\n" n
326 (* Convert the parameters. *)
327 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
330 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
331 | FileIn _ | FileOut _ -> pr "s"
332 | OptString _ -> pr "z"
333 | StringList _ | DeviceList _ -> pr "O"
334 | Bool _ -> pr "i" (* XXX Python has booleans? *)
336 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
337 * emulate C's int/long/long long in Python?
339 | BufferIn _ -> pr "s#"
341 pr ":guestfs_%s\",\n" name;
345 | Pathname n | Device n | Dev_or_Path n | String n | Key n
346 | FileIn n | FileOut n -> pr ", &%s" n
347 | OptString n -> pr ", &%s" n
348 | StringList n | DeviceList n -> pr ", &py_%s" n
349 | Bool n -> pr ", &%s" n
350 | Int n -> pr ", &%s" n
351 | Int64 n -> pr ", &%s" n
352 | BufferIn n -> pr ", &%s, &%s_size" n n
356 pr " return NULL;\n";
358 pr " g = get_handle (py_g);\n";
361 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
362 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
364 | StringList n | DeviceList n ->
365 pr " %s = get_string_list (py_%s);\n" n n;
366 pr " if (!%s) return NULL;\n" n
371 pr " r = guestfs_%s " name;
372 generate_c_call_args ~handle:"g" style;
377 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
378 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
380 | StringList n | DeviceList n ->
384 pr " if (r == %s) {\n" error_code;
385 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
386 pr " return NULL;\n";
390 (match fst style with
392 pr " Py_INCREF (Py_None);\n";
393 pr " py_r = Py_None;\n"
395 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
396 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
397 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
398 | RConstOptString _ ->
400 pr " py_r = PyString_FromString (r);\n";
402 pr " Py_INCREF (Py_None);\n";
403 pr " py_r = Py_None;\n";
406 pr " py_r = PyString_FromString (r);\n";
409 pr " py_r = put_string_list (r);\n";
410 pr " free_strings (r);\n"
411 | RStruct (_, typ) ->
412 pr " py_r = put_%s (r);\n" typ;
413 pr " guestfs_free_%s (r);\n" typ
414 | RStructList (_, typ) ->
415 pr " py_r = put_%s_list (r);\n" typ;
416 pr " guestfs_free_%s_list (r);\n" typ
418 pr " py_r = put_table (r);\n";
419 pr " free_strings (r);\n"
421 pr " py_r = PyString_FromStringAndSize (r, size);\n";
425 pr " return py_r;\n";
430 (* Table of functions. *)
431 pr "static PyMethodDef methods[] = {\n";
432 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
433 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
435 fun (name, _, _, _, _, _, _) ->
436 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
439 pr " { NULL, NULL, 0, NULL }\n";
446 initlibguestfsmod (void)
448 static int initialized = 0;
450 if (initialized) return;
451 Py_InitModule ((char *) \"libguestfsmod\", methods);
456 (* Generate Python module. *)
457 and generate_python_py () =
458 generate_header HashStyle LGPLv2plus;
461 u\"\"\"Python bindings for libguestfs
464 g = guestfs.GuestFS ()
465 g.add_drive (\"guest.img\")
467 parts = g.list_partitions ()
469 The guestfs module provides a Python binding to the libguestfs API
470 for examining and modifying virtual machine disk images.
472 Amongst the things this is good for: making batch configuration
473 changes to guests, getting disk used/free statistics (see also:
474 virt-df), migrating between virtualization systems (see also:
475 virt-p2v), performing partial backups, performing partial guest
476 clones, cloning guests and changing registry/UUID/hostname info, and
479 Libguestfs uses Linux kernel and qemu code, and can access any type of
480 guest filesystem that Linux and qemu can, including but not limited
481 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
482 schemes, qcow, qcow2, vmdk.
484 Libguestfs provides ways to enumerate guest storage (eg. partitions,
485 LVs, what filesystem is in each LV, etc.). It can also run commands
486 in the context of the guest. Also you can access filesystems over
489 Errors which happen while using the API are turned into Python
490 RuntimeError exceptions.
492 To create a guestfs handle you usually have to perform the following
495 # Create the handle, call add_drive at least once, and possibly
496 # several times if the guest has multiple block devices:
497 g = guestfs.GuestFS ()
498 g.add_drive (\"guest.img\")
500 # Launch the qemu subprocess and wait for it to become ready:
503 # Now you can issue commands, for example:
511 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
514 \"\"\"Create a new libguestfs handle.\"\"\"
515 self._o = libguestfsmod.create ()
518 libguestfsmod.close (self._o)
523 fun (name, style, _, flags, _, _, longdesc) ->
525 generate_py_call_args ~handle:"self" (snd style);
528 if not (List.mem NotInDocs flags) then (
529 let doc = replace_str longdesc "C<guestfs_" "C<g." in
532 | RErr | RInt _ | RInt64 _ | RBool _
533 | RConstOptString _ | RConstString _
534 | RString _ | RBufferOut _ -> doc
536 doc ^ "\n\nThis function returns a list of strings."
537 | RStruct (_, typ) ->
538 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
539 | RStructList (_, typ) ->
540 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
542 doc ^ "\n\nThis function returns a dictionary." in
544 if List.mem ProtocolLimitWarning flags then
545 doc ^ "\n\n" ^ protocol_limit_warning
548 if List.mem DangerWillRobinson flags then
549 doc ^ "\n\n" ^ danger_will_robinson
552 match deprecation_notice flags with
554 | Some txt -> doc ^ "\n\n" ^ txt in
555 let doc = pod2text ~width:60 name doc in
556 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
557 let doc = String.concat "\n " doc in
558 pr " u\"\"\"%s\"\"\"\n" doc;
560 pr " return libguestfsmod.%s " name;
561 generate_py_call_args ~handle:"self._o" (snd style);
566 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
567 and generate_py_call_args ~handle args =
569 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;