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, (ret, args, optargs as 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";
291 if optargs <> [] then (
292 pr " struct guestfs_%s_argv optargs_s;\n" name;
293 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
298 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
299 | RInt64 _ -> pr " int64_t r;\n"; "-1"
300 | RConstString _ | RConstOptString _ ->
301 pr " const char *r;\n"; "NULL"
302 | RString _ -> pr " char *r;\n"; "NULL"
303 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
304 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
305 | RStructList (_, typ) ->
306 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
309 pr " size_t size;\n";
314 | Pathname n | Device n | Dev_or_Path n | String n | Key n
315 | FileIn n | FileOut n ->
316 pr " const char *%s;\n" n
317 | OptString n -> pr " const char *%s;\n" n
319 pr " const char *%s;\n" n;
320 pr " Py_ssize_t %s_size;\n" n
321 | StringList n | DeviceList n ->
322 pr " PyObject *py_%s;\n" n;
324 | Bool n -> pr " int %s;\n" n
325 | Int n -> pr " int %s;\n" n
326 | Int64 n -> pr " long long %s;\n" n
329 if optargs <> [] then (
330 (* XXX This is horrible. We have to use sentinel values on the
331 * Python side to denote values not set.
333 (* Since we don't know if Python types will exactly match
334 * structure types, declare some local variables here.
339 | Int n -> pr " int optargs_t_%s = -1;\n" n
340 | Int64 n -> pr " long long optargs_t_%s = -1;\n" n
341 | String n -> pr " const char *optargs_t_%s = NULL;\n" n
348 if optargs <> [] then (
349 pr " optargs_s.bitmask = 0;\n";
353 (* Convert the required parameters. *)
354 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
357 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
358 | FileIn _ | FileOut _ -> pr "s"
359 | OptString _ -> pr "z"
360 | StringList _ | DeviceList _ -> pr "O"
361 | Bool _ -> pr "i" (* XXX Python has booleans? *)
363 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
364 * emulate C's int/long/long long in Python?
366 | BufferIn _ -> pr "s#"
369 (* Optional parameters. *)
370 if optargs <> [] then (
373 | Bool _ | Int _ -> pr "i"
375 | String _ -> pr "z" (* because we use None to mean not set *)
380 pr ":guestfs_%s\",\n" name;
384 | Pathname n | Device n | Dev_or_Path n | String n | Key n
385 | FileIn n | FileOut n -> pr ", &%s" n
386 | OptString n -> pr ", &%s" n
387 | StringList n | DeviceList n -> pr ", &py_%s" n
388 | Bool n -> pr ", &%s" n
389 | Int n -> pr ", &%s" n
390 | Int64 n -> pr ", &%s" n
391 | BufferIn n -> pr ", &%s, &%s_size" n n
396 | Bool n | Int n | Int64 n | String n -> pr ", &optargs_t_%s" n
401 pr " return NULL;\n";
403 pr " g = get_handle (py_g);\n";
406 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
407 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
409 | StringList n | DeviceList n ->
410 pr " %s = get_string_list (py_%s);\n" n n;
411 pr " if (!%s) return NULL;\n" n
416 if optargs <> [] then (
417 let uc_name = String.uppercase name in
420 let n = name_of_argt argt in
421 let uc_n = String.uppercase n in
422 pr " if (optargs_t_%s != " n;
424 | Bool _ | Int _ | Int64 _ -> pr "-1"
425 | String _ -> pr "NULL"
429 pr " optargs_s.%s = optargs_t_%s;\n" n n;
430 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n" uc_name uc_n;
437 pr " r = guestfs_%s " name
439 pr " r = guestfs_%s_argv " name;
440 generate_c_call_args ~handle:"g" style;
445 | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
446 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
448 | StringList n | DeviceList n ->
452 pr " if (r == %s) {\n" error_code;
453 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
454 pr " return NULL;\n";
460 pr " Py_INCREF (Py_None);\n";
461 pr " py_r = Py_None;\n"
463 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
464 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
465 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
466 | RConstOptString _ ->
468 pr " py_r = PyString_FromString (r);\n";
470 pr " Py_INCREF (Py_None);\n";
471 pr " py_r = Py_None;\n";
474 pr " py_r = PyString_FromString (r);\n";
477 pr " py_r = put_string_list (r);\n";
478 pr " free_strings (r);\n"
479 | RStruct (_, typ) ->
480 pr " py_r = put_%s (r);\n" typ;
481 pr " guestfs_free_%s (r);\n" typ
482 | RStructList (_, typ) ->
483 pr " py_r = put_%s_list (r);\n" typ;
484 pr " guestfs_free_%s_list (r);\n" typ
486 pr " py_r = put_table (r);\n";
487 pr " free_strings (r);\n"
489 pr " py_r = PyString_FromStringAndSize (r, size);\n";
493 pr " return py_r;\n";
498 (* Table of functions. *)
499 pr "static PyMethodDef methods[] = {\n";
500 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
501 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
503 fun (name, _, _, _, _, _, _) ->
504 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
507 pr " { NULL, NULL, 0, NULL }\n";
514 initlibguestfsmod (void)
516 static int initialized = 0;
518 if (initialized) return;
519 Py_InitModule ((char *) \"libguestfsmod\", methods);
524 (* Generate Python module. *)
525 and generate_python_py () =
526 generate_header HashStyle LGPLv2plus;
529 u\"\"\"Python bindings for libguestfs
532 g = guestfs.GuestFS ()
533 g.add_drive_opts (\"guest.img\", format=\"raw\")
535 parts = g.list_partitions ()
537 The guestfs module provides a Python binding to the libguestfs API
538 for examining and modifying virtual machine disk images.
540 Amongst the things this is good for: making batch configuration
541 changes to guests, getting disk used/free statistics (see also:
542 virt-df), migrating between virtualization systems (see also:
543 virt-p2v), performing partial backups, performing partial guest
544 clones, cloning guests and changing registry/UUID/hostname info, and
547 Libguestfs uses Linux kernel and qemu code, and can access any type of
548 guest filesystem that Linux and qemu can, including but not limited
549 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
550 schemes, qcow, qcow2, vmdk.
552 Libguestfs provides ways to enumerate guest storage (eg. partitions,
553 LVs, what filesystem is in each LV, etc.). It can also run commands
554 in the context of the guest. Also you can access filesystems over
557 Errors which happen while using the API are turned into Python
558 RuntimeError exceptions.
560 To create a guestfs handle you usually have to perform the following
563 # Create the handle, call add_drive* at least once, and possibly
564 # several times if the guest has multiple block devices:
565 g = guestfs.GuestFS ()
566 g.add_drive_opts (\"guest.img\", format=\"raw\")
568 # Launch the qemu subprocess and wait for it to become ready:
571 # Now you can issue commands, for example:
579 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
582 \"\"\"Create a new libguestfs handle.\"\"\"
583 self._o = libguestfsmod.create ()
586 libguestfsmod.close (self._o)
591 fun (name, (ret, args, optargs), _, flags, _, _, longdesc) ->
592 pr " def %s (self" name;
593 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
596 | Bool n | Int n | Int64 n -> pr ", %s=-1" n
597 | String n -> pr ", %s=None" n
602 if not (List.mem NotInDocs flags) then (
603 let doc = replace_str longdesc "C<guestfs_" "C<g." in
606 | RErr | RInt _ | RInt64 _ | RBool _
607 | RConstOptString _ | RConstString _
608 | RString _ | RBufferOut _ -> doc
610 doc ^ "\n\nThis function returns a list of strings."
611 | RStruct (_, typ) ->
612 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
613 | RStructList (_, typ) ->
614 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
616 doc ^ "\n\nThis function returns a dictionary." in
618 if List.mem ProtocolLimitWarning flags then
619 doc ^ "\n\n" ^ protocol_limit_warning
622 if List.mem DangerWillRobinson flags then
623 doc ^ "\n\n" ^ danger_will_robinson
626 match deprecation_notice flags with
628 | Some txt -> doc ^ "\n\n" ^ txt in
629 let doc = pod2text ~width:60 name doc in
630 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
631 let doc = String.concat "\n " doc in
632 pr " u\"\"\"%s\"\"\"\n" doc;
634 pr " return libguestfsmod.%s (self._o" name;
635 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);