././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1746171070.9010868 libvirt-python-11.3.0/0000755000175000017500000000000015005072277013615 5ustar00jirkajirka././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1746171070.0 libvirt-python-11.3.0/AUTHORS0000644000175000017500000001022515005072276014664 0ustar00jirkajirka Libvirt Python Binding Authors ============================== The libvirt python binding is maintained by the libvirt development team, who can be contacted at libvir-list@redhat.com The individual contributors are Adam Litke Alex Jia Andrea Bolognani Ariel Otilibili Bastian Germann Beraldo Leal Boris Fiuczynski Brian Rak Chris Gunn Chris Lalancette Claudio Bley Cole Robinson Cédric Bosdonnat Dan Kenigsberg Daniel P. Berrange Daniel P. Berrangé Daniel Veillard Diego Elio Pettenò Dmitry Guryanov Don Dugger Doug Goldstein Edgar Kaziakhmedov Eric Blake Erik Skultety Erik Skultety Federico Simoncelli Giuseppe Scrivano Guan Qiang Guannan Ren Gui Jianfeng Guido Günther Han Han Hu Tao Jason Andryuk Jelle van der Waa Jim Fehlig Jim Meyering Jiri Denemark John Ferlan Jonathon Jongsma Jovanka Gulicoska Ján Tomko KAMEZAWA Hiroyuki Konstantin Khorenko Konstantin Neumoin Lai Jiangshan Laine Stump Lei Li Luyao Huang Marc Hartmayer Marcelo Cerri Marian Neagul Mark McLoughlin Markus Rothe Martin Kletzander MATSUDA Daiki Matthias Bolte Michal Privoznik Miloslav Trmač Minoru Usui Mo Yuxiang Nehal J Wani Nikunj A. Dadhania Nir Soffer Osier Yang Oskari Saarenmaa Pavel Boldin Pavel Hrdina Peng Hao Peter Krempa Philipp Hahn Pino Toscano Prabodh Agarwal Pradipta Kr. Banerjee Qiaowei Ren Radostin Stoyanov renlei4 Richard W.M. Jones Robie Basak Serge E. Hallyn Sergei Turchanov Stefan Berger SuhailAhmedVelorum Taizo ITO Taku Izumi Tomoki Sekiyama Tomáš Golembiovský Victor Stinner Viktor Mihajlovski Vincent Vanlaer Vincent Vanlaer w00506750 Wojtek Porczyk Wu Zongyong Xavier Fernandez Zeeshan Ali (Khattak) Zhou Yimin ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/CONTRIBUTING.rst0000644000175000017500000000177714612401403016260 0ustar00jirkajirka============================== Contributing to libvirt-python ============================== The libvirt Python API binding accepts code contributions via merge requests on the GitLab project: https://gitlab.com/libvirt/libvirt-python/-/merge_requests It is required that automated CI pipelines succeed before a merge request will be accepted. The global pipeline status for the ``master`` branch is visible at: https://gitlab.com/libvirt/libvirt-python/pipelines CI pipeline results for merge requests will be visible via the contributors' own private repository fork: https://gitlab.com/yourusername/libvirt-python/pipelines Contributions submitted to the project must be in compliance with the Developer Certificate of Origin Version 1.1. This is documented at: https://developercertificate.org/ To indicate compliance, each commit in a series must have a "Signed-off-by" tag with the submitter's name and email address. This can be added by passing the ``-s`` flag to ``git commit`` when creating the patches. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/COPYING0000644000175000017500000006363114612401403014647 0ustar00jirkajirka GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1746171070.0 libvirt-python-11.3.0/ChangeLog0000644000175000017500000152226115005072276015377 0ustar00jirkajirka 2025- 4- 1 Jiri Denemark Post-release version bump to 11.3.0 2025- 3- 26 SuhailAhmedVelorum Fixed minor typo in libvirt-override.py::openAuth TODO item 2025- 3- 25 Michal Privoznik Add support for domain NIC MAC address change event 2025- 3- 21 Michal Privoznik override: domain: Implement override for virDomainSetThrottleGroup() The bindings generator can't generate proper bindings for virDomainSetThrottleGroup() (because of typed parameters in the arguments) so implement it manually. 2025- 3- 21 Michal Privoznik override: domain: Implement override for virDomainGetAutostartOnce() The bindings generator can't generate proper bindings for virDomainGetAutostartOnce() (because of int* in the arguments) so implement it manually. 2025- 3- 21 Michal Privoznik Modernize typed parameter fetching in libvirt_virDomainSetBlockIoTune() Instead of fetching supported tunables and passing only those to the API (effectively ignoring unsupported ones), pass all tunables or error out on unsupported ones. 2025- 3- 3 Jiri Denemark Post-release version bump to 11.2.0 2025- 2- 17 Pavel Hrdina ci: refresh with 'lcitool manifest' 2025- 1- 15 Jiri Denemark Post-release version bump to 11.1.0 2024- 12- 2 Jiri Denemark Post-release version bump to 11.0.0 2024- 11- 18 Daniel P. Berrangé ci: refresh with 'lcitool manifest' Notable changes * openSUSE Leap updated to 15.6 * Switch to URLs for referencing projects in manifest 2024- 11- 1 Jiri Denemark Post-release version bump to 10.10.0 2024- 10- 22 Ariel Otilibili tox.ini: bumped Python Removed 3.8, added 3.13 [1]. [1] https://devguide.python.org/versions/ 2024- 10- 1 Jiri Denemark Post-release version bump to 10.9.0 2024- 9- 2 Jiri Denemark Post-release version bump to 10.8.0 2024- 8- 8 Ariel Otilibili example/domstart.py: Removed useless brackets for tuple unpacking 2024- 8- 8 Ariel Otilibili tox.ini: Bumped environment list for Python * aligned list with supported Python versions [1] * as of today, supported versions are 3.8 to 3.12 https://devguide.python.org/versions/ 2024- 8- 8 Ariel Otilibili Makefile: `make check` now computes env variable on the fly * env variable used to be Python3.6 * Python3.6 is end of life since December 2021 [1]. [1] https://devguide.python.org/versions/ 2024- 8- 5 Jiri Denemark Post-release version bump to 10.7.0 2024- 7- 1 Jiri Denemark Post-release version bump to 10.6.0 2024- 6- 11 Konstantin Khorenko examples/nodestat: Show memory pinning information again Resurrect the logic after it has been occasionally broken during fixing the syntax complains from python. Fixes: c588ba9 ("examples/nodestat: Fix None comparison") 2024- 6- 3 Jiri Denemark Post-release version bump to 10.5.0 2024- 5- 2 Michal Privoznik ci: Drop CentOS 8 Stream and switch F38 to 40, Ubuntu 20.04 to 22.04 There a lot happening here, but that's because otherwise lcitool fails to regenerate files. Firstly, CentOS 8 is dropped as it's unsupported now. Secondly, Fedora 40 is introduced and Fedora 38 is dropped. And lastly, Ubuntu 24.04 is introduced and Ubuntu 20.04 is dropped. 2024- 5- 2 Michal Privoznik test_aio.py: Fix skip message There are two unit tests in test_aio.py that are skipped if Python is too new (3.10 or newer). But the message printed when they are skipped mentions just 3.10 which is confusing. Change it to "3.10+". 2024- 5- 2 Michal Privoznik Switch to PyMODINIT_FUNC annotation Instead of doing some 'extern ...' declaration magic to force proper PyInit_libvirtmod*() symbol exposure in resulting .so we can use what Python already offers - PyMODINIT_FUNC macro and call it a day. 2024- 5- 2 Michal Privoznik generator.py: Drop build/ prefix from #include When -Ibuild flag is passed to compiler then build/ can be dropped from includes. This is safe to do, because the prefix is only on local includes (#include "") not system ones (#include <>). 2024- 5- 2 Michal Privoznik generator.py: Switch from ${module}-export.c to ${module}-export.c.inc The generator.py generates a (per module) table of functions it generated code for and stores it in ${module}-export.c file. The file is then #include-d in corresponding override.c in the table of all methods implemented in the module. Now, problem is with naming of the file because the ".c" suffix might suggest the file needs to be compiled. Well, it doesn't. It's way closer to being a header file, so change the suffix to ".c.inc". 2024- 5- 2 Michal Privoznik generator.py: Allow source and build dirs override Soon generator.py is going to be ran from a build directory which is different than the source directory. Allow specifying these directories on the cmd line. And while at it, introduce new "c+py" output mode in which both C and Python files are generated. While this is a fallback mode if no output mode is selected, we need this new mode so that aforementioned directories can be specified. 2024- 5- 2 Michal Privoznik setup.py: s/PY_VERSION/VERSION/ When generating spec file, @PY_VERSION@ is replaced with the current version of libvirt-python. Well, it's not as obvious as it could be: usually it's just @VERSION@. Worse, the PY_ prefix may mislead readers into thinking it refers to python version. Just drop the PY_ prefix. 2024- 5- 2 Jiri Denemark Post-release version bump to 10.4.0 2024- 5- 1 Jelle van der Waa examples: replace logging.warn with logging.warning logging.warn is an alias to logging.warning since Python 3.3 and will be removed in Python 3.13. 2024- 4- 30 Daniel P. Berrangé gitlab: stop using a venv when creating source/binary dist The change to use 'python -m build' in commit 333c8bef2bcca5ca7dbcdb5861a385d626e0feb9 Author: Erik Skultety Date: Tue Jun 20 12:19:40 2023 +0200 ci: Drop direct 'setup.py' usage resulted in the CI jobs all downloading latest setuptools and deps from pypi and running builds with them in a venv. IOW we ceased testing against the setuptools/wheel packages provided by the distro, which is the whole point of the CI. Passing the '-n -x' flags to 'python -m build' tells it to stop using a venv and not to check dependancies, thus letting it use what we pre-installed in the container. This doesn't work on CentOS Stream 8, however, so we revert to using the old setup.py approach. This is a short term issue, since Stream 8 is EOL at the end of May, so we'll be deleting all the Stream 8 jobs across libvirt CI very soon. 2024- 4- 25 Daniel P. Berrangé ci: refresh with lcitool manifest This pulls in the new wheel packages. 2024- 4- 25 Daniel P. Berrangé ci: add 'python3-wheel' as a dep The 'python -m build' command creates a source dist and a binary wheel. To be able run this command without creating a new venv and downloading from pypi, we need to pre-install the 'wheel' package. 2024- 4- 25 Daniel P. Berrangé ci: refresh with latest lcitool manifest Fixes logic that caused some jobs to mistakenly not be run when expected. 2024- 4- 2 Jiri Denemark Post-release version bump to 10.3.0 2024- 3- 1 Jiri Denemark Post-release version bump to 10.2.0 2024- 2- 27 Michal Privoznik ci: Switch native_git_build_job to c9s and resume api_coverage_job Currently, there's just one native_git_build_job - x86_64-centos-stream-8-git and this is a problem because that's the job that api_coverage_job then uses. But CentOS Stream 8 has too old lxml which then makes tests/test_api_coverage.py skip its run. By switching to CentOS Stream 9 the test can run happily again. 2024- 2- 27 Michal Privoznik test_api_coverage: Reflect different naming in python for virDomainFDAssociate() and virDomainRestoreParams() While virDomainRestoreParams() has 'virDomain' prefix (and thus is put into Domain class), it is really in the same family as virDomainRestore() or virDomainRestoreFlags() -> it acts upon virConnect object and thus belongs into Connect class. Then, virDomainFDAssociate is exposed as Domain.FDAssociate() but because of the way we would generate the method's name (fDAssociate) the test thinks it's not implemented. 2024- 2- 20 Vincent Vanlaer Fix memory leak in virStreamRecvFlags virStreamRecvFlags allocates a temporary buffer to store the received stream data in. This buffer was not freed on returns other than the normal return with data. 2024- 1- 19 Daniel P. Berrangé ci: refresh with latest 'lcitool manifest' This refresh gets rid of the split jobs for prebuilt and local container environments. 2024- 1- 15 Jiri Denemark Post-release version bump to 10.1.0 2024- 1- 8 Peter Krempa ci: Install built module for testing insde an venv Distros recently started to object to using 'pip' to install system-wide packages to prevent breakage. We were hacking-around that by using 'pip install --break-system-packages', but it's straightforward to simply create a venv with '--system-site-packages' and install it there. 2024- 1- 8 Peter Krempa ci: Update Fedora and Debian versions and regenerate Update: Debian-10 -> Debian-12 Fedora-37 -> Fedora-38 Fedora-38 -> Fedora-39 Also the artifacts from the Fedora 39 job are needed for the integration test suite in the main libvirt project. For Debian 12 we need to start using 'pip install --break-system-packages' as a hack to work around installation of the built package for testing. 2023- 12- 1 Jiri Denemark Post-release version bump to 10.0.0 2023- 11- 1 Jiri Denemark Post-release version bump to 9.10.0 2023- 10- 2 Jiri Denemark Post-release version bump to 9.9.0 2023- 9- 25 Daniel P. Berrangé Request the Python stable API when building We have Python 3.6 as a minimum version. If we set Py_LIMITED_API to 0x03060000, we'll get the stable python API associated with versions >= 3.6. This lets users compile once and have the libvirt binary module be loadable by any Python version >= 3.6, as described in: https://docs.python.org/3/c-api/stable.html 2023- 9- 25 Daniel P. Berrangé Use PySequence_GetItem preferentially Although marginally faster, PySequence_ITEM is not part of the stable API and also omits some safety checks. It is better for us to be using PySequence_GetItem instead. 2023- 9- 25 Daniel P. Berrangé add missing includes for C library functions We use various C library functions like printf, strcmp, free but don't have the corresponding #includes, getting them indirectly via Python.h. This is a bad idea as Python.h is not guaranteed to provided these, and indeed will omit them when Py_LIMITED_API is greater then 0x030a0000. 2023- 9- 25 Pino Toscano setup: simplify authors list generation Use a set to collect the authors from the git output with no duplicates, then sort the resulting set, and apply the wanted indentation. This method is more Pythonic, using a set to avoid duplicates; applying the indentation after the sorting makes the sorting slightly faster. 2023- 9- 25 Pino Toscano setup: switch away fron subprocess.Popen() Adopt subprocess.check_output() as more modern and higher-level way to invoke processes, checking that they succeed, and getting their output. 2023- 9- 25 Pino Toscano setup: remove unnecessary f-string The whole content of this f-string is a variable, so use that variable directly. 2023- 9- 25 Pino Toscano setup: invoke git commands properly Storing the git commands as single string, to split it by space later on, works only in case there are no spaces in the arguments, which is exactly what is in those commands. Instead, specify them directly as lists, with the options & arguments split in the right way. This fixes the generation of the AUTHORS and ChangeLog files. 2023- 9- 21 Daniel P. Berrangé gitlab: unset CFLAGS for rpm build Setting CFLAGS before invoking rpm-build causes replacement of the CFLAGS that RPM wants to set for python. This causes the loss of certain flags needed to turn on debug output and optimization. Previously this wasn't a problem as something in setuptools appears to have been adding -g anyway, but with the update to python 3.12 this now fully breaks. We should never have been setting CFLAGS during the RPM build so we drop it unconditionally for all distros. 2023- 9- 21 Daniel P. Berrangé Add binding for network metadata events 2023- 9- 1 Jiri Denemark Post-release version bump to 9.8.0 2023- 8- 21 Erik Skultety ci: lcitool: Maintain project package deps lists here Each respective project that lcitool knows about and currently maintains its list of package dependencies knows best what packages they actually depend on. If a new dependency is currently needed, first a change in lcitool is necessary before GitLab jobs and containers can be updated. Provided a mapping already exists in lcitool (which can quickly be added as an override via mappings.yml temporarily) we speed up the whole CI update process by one step. Note that starting this commit lcitool must be invoked as '$ lcitool -d/--data-dir ci/lcitool ...' to pick up the project dependency list correctly. 2023- 8- 1 Jiri Denemark Post-release version bump to 9.7.0 2023- 7- 3 Jiri Denemark Post-release version bump to 9.6.0 2023- 6- 22 Erik Skultety README: Drop direct 'setup.py' usage With all the bits in place we can now replace the direct 'setup.py' invocation examples with alternatives. 2023- 6- 22 Erik Skultety ci: Drop direct 'setup.py' usage With all the bits in place we can now drop the 'setup.py' invocations with preferred alternatives. This patch does a few things: - we don't run plain install because that always spins up a new build process regardless of whether there are build artifacts literally from the previous command, so instead we install the built wheel directly - when building, we build both the .whl binary and an sdist because we'll need the sdist for rpmbuild later in the CI job - we don't capture the 'build' path as a job artifact anymore, because that now only contains egg metadata, all the build artifacts are created by Python's build module under 'dist' so we capture that one instead - we always limit pytest to the 'tests' directory which was something 'setup.py test' used to do as a precaution measure, but setup.py no longer has the logic (which is fine) 2023- 6- 22 Erik Skultety spec: Invoke pytest properly With all the bits in place we can now drop the 'setup.py' invocations with preferred alternatives. The way to do this in a SPEC file is to use either of the following macros: %tox or %pytest - both of which automatically set paths for the test suite correctly which is something we used to do ourselves in our implementation of the setup.py's test command originally. That is wrong and with the migration to PEP-517 compliant builds it also won't work anymore properly, because there'd be no libs to import by mangling PYTHONPATH, we'd only get an sdist or a wheel, or in case of rpmbuild a preset buildroot environment. 2023- 6- 22 Erik Skultety setup: Drop the my_test command Direct setup.py invocations are being discouraged in favour of using Python's 'build' module. Therefore, we can't really make use of this command anymore since only wheels and tarballs are built with the 'build' module compared to the previous state of the art of dumping the freshly built modules and libraries directly inside the build directory. We'll have to encourage usage of tox which will install the package inside a virtualenvironment for the tests. Future patch will update the Makefile targets to make this easier for the end users. 2023- 6- 22 Erik Skultety setup: Drop the clean command Direct setup.py invocations are discouraged anyway, use git clean or 'make clean' instead. 2023- 6- 22 Erik Skultety Add pyproject.toml Given the missing setuptools keywords issue and hence having moved all the declarative stuff to setup.cfg this one is only a very basic one just to comply PEP-517 and foolproof this project for the future PyPa/pip changes. 2023- 6- 22 Erik Skultety Makefile: Add a 'test' rule to run the full tox execution This one should be used for the "full" test experience including any additional environments, test suites and linters we may introduce further down the road. 2023- 6- 22 Erik Skultety Makefile: Update targets according to the new way of building - drop direct setup.py invocations - clean the artifacts directly with 'rm' - use tox instead of invoking pytest otherwise we don't have a mechanism to test against the freshly built libvirt modules other than unpacking the built wheel and mangling the PYTHONPATH again - use direct rpmbuild invocation to build RPM (the rpm target in its current form didn't really work anyway) 2023- 6- 22 Erik Skultety setup: Query library version out of a file This makes it possible to programatically query the version in any stage of the build process, including Makefile etc. 2023- 6- 22 Erik Skultety Move declarative stuff out of setup.py to setup.cfg So, why using setup.cfg if pyproject.toml is the new best thing recommended everywhere? Well, quite a few of the fields we use with setuptools are setuptools-specific and haven't been introduced as keywords to pyproject.toml yet. There is a chance that these fields could be added via a dedicated 'tool.setuptools' TOML section, but none of it is officially documented and so it would be BETA at best anyway. Let's not try our luck and use a declarative config file tailored specifically to setuptools - setup.cfg. It's also unlikely we'd switch from setuptools to something else in the near future given the nature of building this project (i.e. building with C modules) and if so, it would likely not be a PyPa recommended PEP-517 compliant build system anyway, e.g. meson, so we're totally fine doing this. 2023- 6- 22 Erik Skultety README: Move the long_description from setup.py in here 2023- 6- 22 Erik Skultety MANIFEST.in: Cleanup When migrated to the PEP-517 compliant builds, some errors occurred due to missing or non-existent files mentioned in the MANIFEST. Notable changes: - README and MANIFEST files are automatically added to sdist per MANIFEST documentation - we want all tests/examples to be included, so use the 'graft' keyword instead of enumerating individual files - we want all *.[ch] files as those are needed for the build, so use 'include *.[ch]' instead of enumerating individual files - we want all *.xml files, so use 'include *.xml' - we want all *.py files - in case this is no longer the case in the future, we'll need to tweak that 'include' - we don't want any __pycache__ nor *.pyc build artifacts, so exclude them globally 2023- 6- 21 Erik Skultety ci: Refresh with latest lcitool changes - bump OpenSUSE Leap 15.4 -> 15.5 - add python3-build dependency (PEP-517) - add python3-venv dependency (PEP-517) 2023- 6- 9 Erik Skultety setup: styling: Fix last occurrence of os.path in favour of pathlib Commit e749b4cf forgot to update a couple more occurrences. Fixes: e749b4cf111bcfc9ceeb88be57dc1d810fc631d9 2023- 6- 9 Erik Skultety setup: Drop explicit creation of the build dir in sdist No need to do that since we'll create it in the top-level code as a first thing anyway. 2023- 6- 9 Erik Skultety setup: Use a simple helper to generate dist files from .in templates The code is almost identical in the impacted cases, so factor it out. 2023- 6- 9 Erik Skultety setup: styling: Use context managers more Some of the operations, namely file operations and spawning processes can utilize the power of context managers. Use them more, use them together. 2023- 6- 9 Erik Skultety setup: Move over from os.popen to subprocess.Popen subprocess is the high-level Pythonic interface providing more flexibility over the low-level os.popen stuff. It is recommended to always use subprocess over the direct 'os' interface. 2023- 6- 9 Erik Skultety setup: styling: More f-string conversions Fix a few more occurrences. Fixes: 745e5a8ca46feb1acf3382c38eb45c74c1c42489 2023- 6- 8 Erik Skultety MANIFEST.in: Add Makefile 2023- 6- 8 Erik Skultety tox.ini: Drop sanitytest execution Commit 60044515 renamed sanitytest to test_coverage_api but forgot to update the tox.ini file. Fixes: 60044515a256c36afad0fc5efcb7ea946eb93783 2023- 6- 8 Erik Skultety COPYING: Only ship a single license file COPYING The correct license we've used for a while is LGPLv2+, so drop the original. 2023- 6- 8 Erik Skultety setup: Simplify get_pkgconfig_data We don't need to do both None/non-None checks on the returned string. 2023- 6- 8 Erik Skultety setup: Move away from os.path to pathlib.Path Drops usage of the glob module along the way as pathlib integrates glob as well. 2023- 6- 7 Erik Skultety setup: styling: Don't mix top-level code with function/class definition It hinders readability so much when the top-level code that gets executed right away when setup.py is loaded is mixed in between type definitions. 2023- 6- 7 Erik Skultety setup: styling: Format multi-line arguments properly 2023- 6- 7 Erik Skultety setup: styling: Adopt f-strings in favour of old-style string formatting 2023- 6- 7 Erik Skultety setup: styling: Drop unexpected spaces when providing kwargs arguments 2023- 6- 7 Erik Skultety setup: styling: Replace apostrophes with quotes Let's standardize on usage of one and be consistent with it. 2023- 6- 7 Erik Skultety setup: styling: Fix method/function/class spacing 2 newlines in between classes/functions, 1 newline in between methods. 2023- 6- 7 Erik Skultety setup: Re-order the imports First go general, whole module imports, then specific symbol imports. 2023- 6- 7 Erik Skultety setup: Bump the minimum version of Python to 3.6 3.6 is already EOL, but many platforms still default to Python 3.6 when it comes to the default platform Python package. Since we don't rely on any 3.7+ features in the bindings at the moment, let's keep everyone's life simpler and stay with 3.6 for now, we can bump it again in the future. 2023- 6- 7 Erik Skultety setup: Reduce the Python classifiers to "Python :: 3" only We're not good at tracking all the released Python 3 versions (+ we don't support Python 2 anymore). Additionally, future patches will take care of reporting the minimum required version of Python anyway through the 'python_requires' field which shows up correctly in PyPI. 2023- 6- 1 Jiri Denemark Post-release version bump to 9.5.0 2023- 5- 31 Han Han virDomainMigrate3Params: Add missing params Add these missing migrate params: - VIR_MIGRATE_PARAM_DISKS_URI, since libvirt v6.8.0(49186372db) - VIR_MIGRATE_PARAM_TLS_DESTINATION, since libvirt v6.0.0(1b8af37213e) - VIR_MIGRATE_PARAM_COMPRESSION_ZLIB_LEVEL and VIR_MIGRATE_PARAM_COMPRESSION_ZSTD_LEVEL, since libvirt v9.4.0(150ae3e62b9) 2023- 5- 3 Erik Skultety ci: Drop Fedora 36 target 2023- 5- 3 Erik Skultety ci: Add Fedora 38 target 2023- 5- 3 Erik Skultety ci: Replace OpenSUSE Leap 15.4 target with Leap 15 name We now refer to the latest Leap 15.X simply as Leap 15 in lcitool. 2023- 5- 2 Jiri Denemark Post-release version bump to 9.4.0 2023- 4- 26 Daniel P. Berrangé rpm: convert license to SPDX format 2023- 4- 19 Jiri Denemark Post-release version bump to 9.3.0 2023- 4- 19 Daniel P. Berrangé setup: limit pytest to 'tests' subdir The libvirt git repo contains test data that represents the layout of files in sysfs, which has two subdirs that mutually reference each other with symlinks. When pytest does test discovery it will traverse every directory it finds underneath the libvirt-python checkout. Since we checkout libvirt as a sub-dir, pytest traverses everything in libvirt git and gets stuck in an infinite loop following symlinks in the libvirt test data. Telling pytest to only look at the 'tests' subdir avoids this extra traversal. 2023- 4- 19 Daniel P. Berrangé ci: pass --break-system-packages on Debian Sid Debian Sid python packages block users from installing packages using pip unless using a venv. A venv has no benefit when we are running in a throwaway container which has no need for software upgrades. 2023- 4- 19 Daniel P. Berrangé ci: mark bleeding edge distros as non-gating Fedora Rawhide, Debian Sid and OpenSUSE Tumbleweed are all liable to have sporadic failures due to being bleeding edge distros. Thus they should not gate contributor changes that are otherwise correct. 2023- 4- 19 Daniel P. Berrangé ci: regenerated with lcitool manifest This replaces OpenSUSE Leap 15.3 with 15.4 2023- 3- 1 Jiri Denemark Post-release version bump to 9.2.0 2023- 2- 13 Michal Privoznik Fix sign compare offenders In a few places we compare signed and unsigned integers. In majority of cases it's because the iteration variable is declared as ssize_t but then in the for() loop it's compared against an unsigned int. But there is one case where the opposite happens (libvirt_virDomainSendKey()), or where an UINT_MAX (which is inherently unsigned) is compared against signed long. Also, use this opportunity to decrease scope of 'j' variable inside of libvirt_virDomainInterfaceAddresses(). 2023- 2- 13 Michal Privoznik Stop typecasting libvirt_intWrap() arguments There's no need to explicitly typecast arguments passed to libvirt_intWrap() as they are int or long already. 2023- 2- 13 Michal Privoznik libvirt-override: Don't typecast strlen() in debug printings After some data was read from an incoming stream, we debug print their length using strlen() (assuming its text stream, not binary stream). Anyway, the debug format uses %d which then requires strlen() to be typecasted. Well, we can use %zu and drop the typecast. 2023- 2- 13 Michal Privoznik libvirt_virConnectOpenAuth: Avoid plain PyLong_AsLong() call When constructing the list of credentials to pass to virConnectOpenAuth(), the virConnectAuth.credtype member is set via plain PyLong_AsLong() without any error checking. Well, the code relies on virConnectOpenAuth() to do sanity check of passed arguments. Switch to libvirt_intUnwrap() which does check for errors and avoid needless trip to libvirt's public API upon error. 2023- 2- 13 Michal Privoznik libvirt_virNodeGetInfo fix 2023- 2- 13 Michal Privoznik typewrappers: Drop typecast in libvirt_intWrap() The libvirt_intWrap() accepts an integer and passes it to PyLong_FromLong() which accepts a long. It's perfectly okay to let compiler do that implicitly. 2023- 2- 13 Michal Privoznik typewrappers: Rework libvirt_uintWrap() Python C API offers PyLong_FromUnsignedLong() which allows us to drop typecast. 2023- 2- 13 Michal Privoznik typewrappers: Rework libvirt_uintUnwrap() Python C API offers PyLong_AsUnsignedLong() which already raises an exception on negative values. Rewrite our libvirt_uintUnwrap() to use that and drop check for negative values. 2023- 1- 16 Jiri Denemark Post-release version bump to 9.1.0 2023- 1- 12 Peter Krempa override: domain: Implement override for virDomainFDAssociate The bindings generator can't generate proper bindings for FD passing so the bindings need to be implemented manually both the python wrapper and the C backend. 2023- 1- 6 Erik Skultety ci: manifest: Define RPM artifacts for regular CentOS Stream 8 build Commit 7360326 missed the fact that artifacts were only defined for the libvirt Git type of libvirt-python build (git is cloned, libvirt is built and then libvirt-python) based on the 'native_git_build_job_prebuilt_env' job template whereas libvirt CI expects the RPM artifacts to come from a job based on the 'native_build_job' template instead. Note that this patch is a hotfix to something which requires a proper cleanup to stay consistent with the way we're handling the same thing in libvirt-perl. 2023- 1- 6 Erik Skultety .gitignore: Ignore more common Python build artifacts 2023- 1- 5 Erik Skultety ci: manifest: Define artifacts cache After commit 6e0d4d53 we lost RPM artifacts cache breaking the whole integration CI. The reason for that is that we manually defined the artifacts cache in gitlab.yml instead of manifest.yml. Naturally with the next lcitool update, gitlab.yml got overwritten according to manifest.yml which didn't define any artifacts cache. Fixes: 6e0d4d53d51e8aa9d537e404a886eab131e311cc 2023- 1- 5 Erik Skultety ci: manifest: Replace 'expiry' with 'expire_in' 'expiry' isn't a keyword in lcitool anymore, the only reason why everything has kept working despite lcitool updates is that lcitool sets 'expire_in' to 2 days by default. 2023- 1- 4 Erik Skultety ci: Refresh and add Fedora 37 target 2022- 12- 1 Jiri Denemark Post-release version bump to 9.0.0 2022- 11- 23 Daniel P. Berrangé rpm: add explicit build dep on python3-setuptools We previously got this implicitly via a dep from python3-pytest so never noticed that it was missing. The implicit dep is going away in rawhide real soon. 2022- 11- 1 Jiri Denemark Post-release version bump to 8.10.0 2022- 10- 13 Peter Krempa ci: Expose built RPMs as artifacts Expose the artifacts from the centos-stream-8/9 and fedora 35/36 jobs so that the main libvirt integration testing project can consume them. The new libvirt sub-rpm containing a python helper to access QMP directly requires python environment which we didn't yet install in the integration job. 2022- 10- 10 Chris Gunn Fix memory leak in libvirt_virStreamRecv. The libvirt_virStreamRecv function uses a temporary allocated buffer to receive data before copying the data into a Python byte array. But there are some error paths where this buffer is not freed. This change fixes that memory leak. 2022- 10- 3 Erik Skultety ci: Fix the stage of the api-coverage job The 'extends' stanza supports a list, however there's a merge algorithm in place where a subsequent list entry overwrites all conflicting settings from the previous one - which is exactly what happened here as the gitlab-build-{local,prebuilt}-env job template overwrote api-coverage's stage to 'builds' whereas the original was 'sanity_checks'. Fixes: 4733e2a2d13cb9a85127ba17c04cc29278b31e89 2022- 10- 3 Jiri Denemark Post-release version bump to 8.9.0 2022- 9- 30 Daniel P. Berrangé ci: refresh with latest lcitool manifest This refresh switches the CI for contributors to be triggered by merge requests. Pushing to a branch in a fork will no longer run CI pipelines, in order to avoid consuming CI minutes. To regain the original behaviour contributors can opt-in to a pipeline on push git push -o ci.variable=RUN_PIPELINE=1 This variable can also be set globally on the repository, though this is not recommended. Upstream repo pushes to branches will run CI. The use of containers has changed in this update, with only the upstream repo creating containers, in order to avoid consuming contributors' limited storage quotas. A fork with existing container images may delete them. Containers will be rebuilt upstream when pushing commits with CI changes to the default branch. Any other scenario with CI changes will simply install build pre-requisite packages in a throaway environment, using the ci/buildenv/ scripts. These scripts may also be used on a contributor's local machines. With pipelines triggered by merge requests, it is also now possible to workaround the inability of contributors to run pipelines if they have run out of CI quota. A project member can trigger a pipeline from the merge request, which will run in context of upstream, however, note this should only be done after reviewing the code for any malicious CI changes. 2022- 9- 9 Bastian Germann Link libvirtmod_* modules also with libvirt The -lvirt linker flag has to be added to the libvirtmod_qemu and libvirtmod_lxc modules as well. 2022- 9- 9 Bastian Germann Replace uint with unsigned int Mingw-w64 target does not support uint definition. 2022- 9- 1 Jiri Denemark Post-release version bump to 8.8.0 2022- 8- 1 Jiri Denemark Post-release version bump to 8.7.0 2022- 7- 8 Michal Privoznik libvirt-utils: Clear error when guessing typed param type Our APIs which accept typed parameters are usually exposed in python as accepting dictionary, for instance: virDomainSetIOThreadParams(..., virTypedParameterPtr params, ...) -> virDomain.setIOThreadParams(..., {}, ...) Now, before calling the C API, the dictionary is processed by virPyDictToTypedParams() which accepts an additional argument: array that hints types for each typed parameter. However, if a key is not in the array we guess what the correct type might be. This is done by attempting conversion from python into string, if that fails then into boolean, then into long, only to fall back to double. Now, for the long type we can have two cases: the value is non-negative (ULL) or it is negative (LL). Therefore, we firstly attempt ULL case and if that fails we stick with the latter. However, after we attempted the ULL conversion, python records an error internally (which is then queried via PyErr_Occurred()), but the error is never cleared out. This leads to spurious paths taken afterwards: e.g. when libvirt_longlongUnwrap() is trying to convert -1, it fails. But not rightfully - the PyErr_Occurred() check it performs has nothing to do with any of its actions, rather than our guessing work done before. Therefore, clear the error after we've guessed the type. 2022- 7- 8 Michal Privoznik Add VIR_DOMAIN_IOTHREAD_THREAD_POOL_{MIN,MAX} macros The python version of virDomainSetIOThreadParams (setIOThreadParams()), expects two arguments on input: the thread ID and a dictionary which is then translated into our typed parameters. During this translation we use a helper array which holds type for each typed parameter supported (virPyDomainSetIOThreadParams[]). Otherwise we guess what the correct type is. Now, when introducing VIR_DOMAIN_IOTHREAD_THREAD_POOL_{MIN,MAX} typed params into libvirt I forgot to update the array. Do that now. 2022- 7- 1 Jiri Denemark Post-release version bump to 8.6.0 2022- 6- 25 Pino Toscano setup: make 'clean' command compatible again with distutils After the switch of 'my_clean' to a simple Command, the 'clean' command has no more bits for options, resulting in distutils (either external or embedded in setuptools) complaining about it: distutils.errors.DistutilsClassError: command class must provide 'user_options' attribute (a list of tuples) To overcome that, provide all the standard bits from options, i.e. the 'user_options' list, and the 'initialize_options' & 'finalize_options' methods. In addition, add a dummy 'all' option, as distutils wants it: error: error in [...]/.pydistutils.cfg: command 'my_clean' has no such option 'all' Fixes commit a965c91c6fa1275613edbbef75c0422574eb9ff2 2022- 6- 8 Daniel P. Berrangé setup: advertize Python 3.9 and 3.10 support Add classifiers that indicate we intend to support python versions 3.9 and 3.10. 2022- 6- 8 Daniel P. Berrangé examples: remove use of deprecated setDaemon method In Python 3.10 the setDaemon method was deprecated. It is redundant since the 'daemon' parameter can be given when creating the thread, or the 'daemon' attribute can be set after it was created. 2022- 6- 8 Daniel P. Berrangé tests: expand AIO tests and add more comments Add a test for one more usage scenario that was possible in the past, whereby libvirt events are registered before starting the asyncio loop, but we let libvirt find the loop associated with the current thread. Skip the test relies on auto-creating an event loop with Python >= 3.10 since it now triggers a deprecation warning which will soon turn into a RuntimeError. 2022- 6- 8 Daniel P. Berrangé tests: use mocks to allow calling virEventRegisterImpl many times We currently have to run each of the test_aio.py test cases in a separate process, because libvirt.virEventRegisterImpl can only be called once per process. This leads to quite unpleasant console output when running tests. By introducing a mock for libvirt.virEventRegisterImpl we can regain the ability to run everything in a single process. The only caveat is that it relies on tests to fully cleanup, but in practice this is ok for our current tests. 2022- 6- 8 Chris Gunn tests: add libvirtaio test coverage 2022- 6- 8 Daniel P. Berrangé libvirtaio: add better docs on best practice usage pattern 2022- 6- 8 Daniel P. Berrangé libvirtio: lazy create the Event object in drain() The drain method uses an asyncio.Event object to be notified when other coroutines have removed all registered callbacks. The Event object needs to be associated with the coroutine that the event loop is running with and currently this is achieved by passing in the 'loop' parameter. Unfortunately Python 3.10 has removed the 'loop' parameter and now the object is associated implicitly with the current thread's event loop. At the time the virEventAsyncIOImpl constructor is called, however, there is no guarantee that an event loop has been set for the thread. The explicitly passed in 'loop' parameter would handle this scenario. For portability with Python >= 3.10 we need to delay creation of the Event object until we have a guarantee that there is a loop associated with the current thread. This is achieved by lazily creating the Event object inside the 'drain' method, which is expected to be invoked from coroutine context and thus ensure a loop is associated. 2022- 6- 8 Chris Gunn libvirtaio: convert to using 'async' / 'await' syntax The 'async' keyword is new in Python 3.5, as a way to declare that a method is a coroutine. This replaces the '@asyncio.coroutine' decorator that is deprecated since 3.8 and scheduled to be removed in 3.11 The 'await' keyword has to be used instead of 'yield' from any coroutines declared with 'async'. [DB: Split off from a larger patch mixing multiple changes] 2022- 6- 8 Chris Gunn libvirtaio: drop back compat for python < 3.4.4 setup.py ensures we have python >= 3.5, so there is no need to do back compat with the 'asyncio.ensure_future' method, which was new in 3.4.4 [DB: Split off from a larger patch mixing multiple changes] 2022- 6- 1 Jiri Denemark Post-release version bump to 8.5.0 2022- 5- 13 Michal Privoznik Add an override impl for virDomainRestoreParams and virDomainSaveParams 2022- 5- 2 Jiri Denemark Post-release version bump to 8.4.0 2022- 4- 21 Daniel P. Berrangé setup: switch to running API coverage test using pytest The API coverage test is no longer a special case. 2022- 4- 21 Daniel P. Berrangé sanitytest: skip tests when seeing broken lxml implementation The python lxml registers some global callbacks with libxml2. As a result when another user of libxml2 calls APIs, it can trigger the python callbacks that lxml previously registered. Execution of the python callbacks in this case is often unsafe and leads to SEGVs. This hasn't been a problem since the sanitytest.py test has been a standalone program we execute. When it gets turned into a real python unit test, it will run in the same process as all the other tests and trigger the crash. A mitigation was added in lxml 4.5.2 which is good enough to let us continuing using lxml. 2022- 4- 21 Daniel P. Berrangé sanitytest: turn into a normal python unittest The sanitytest.py file is now using the normal python unittest pattern, though we invoke the one test explicitly for now. 2022- 4- 21 Daniel P. Berrangé sanitytest: move function/enum identification into a helper method This is a step towards turning the sanitytest.py file into a normal python unittest. Best viewed with the '-b' flag to diff. 2022- 4- 21 Daniel P. Berrangé sanitytest: move class identification into a helper method This is a step towards turning the sanitytest.py file into a normal python unittest. Best viewed with the '-b' flag to diff. 2022- 4- 21 Daniel P. Berrangé sanitytest: move initial class method mapping into a helper method This is a step towards turning the sanitytest.py file into a normal python unittest. Best viewed with the '-b' flag to diff. 2022- 4- 21 Daniel P. Berrangé sanitytest: move class method mapping fixup into a helper method This is a step towards turning the sanitytest.py file into a normal python unittest. Best viewed with the '-b' flag to diff. 2022- 4- 21 Daniel P. Berrangé sanitytest: move C to python API mapping check into a helper method This is a step towards turning the sanitytest.py file into a normal python unittest. Best viewed with the '-b' flag to diff. 2022- 4- 21 Daniel P. Berrangé sanitytest: move python to C API mapping check into a helper method This is a step towards turning the sanitytest.py file into a normal python unittest. Best viewed with the '-b' flag to diff. 2022- 4- 21 Daniel P. Berrangé sanitytest: move C API binding check into a helper method This is a step towards turning the sanitytest.py file into a normal python unittest. Best viewed with the '-b' flag to diff. 2022- 4- 21 Daniel P. Berrangé sanitytest: stop passing python module path into sanity test We want to move over to make sanitytest.py operate like a more normal test script, which means making it self contained. The setup.py already sets the PYTHONPATH thanks to changes introduced in: commit eaded7bdadf3ccdc4b208ec0ed65a1b23b8b5f69 Author: Daniel P. Berrange Date: Tue Mar 18 11:11:48 2014 +0000 Add support for running unit tests with nose so passing the python module path into sanitytest.py is redundant. 2022- 4- 21 Daniel P. Berrangé sanitytest: stop passing API XML path into sanity test We want to move over to make sanitytest.py operate like a more normal test script, which means making it self contained. The test already knows how to find the libvirt API XML path using pkg-config and if an override location is required, this can be done by pointing $PKG_CONFIG_PATH to a suitable place. 2022- 4- 21 Daniel P. Berrangé setup: switch from distutils to setuptools The distutils package is deprecated and targetted for deletion in Python 3.12, so we need to switch to setuptools. Thanks to all the preceeding changes this is no more difficult than changing the import statements. Closes https://gitlab.com/libvirt/libvirt-python/-/issues/1 2022- 4- 21 Daniel P. Berrangé setup: remove use of distutils.util.get_platform The 'get_platform' function is used to determine the platform specific component of the build output directory containing the loadable modules and python code. There is no nice replacement for this function, but we can achieve our goal by simply scaning for the desired subdirectory, which should exist by the time 'test' runs. 2022- 4- 21 Daniel P. Berrangé setup: override 'build_ext' / 'build_py' commands rather than 'build' We override the 'build' command to invoke the code generator before the extensions are compiled. The 'build' command, however, is merely a wrapper around several other commands. It is possible for the user to directly invoke those commands, in which case our code generator won't get a chance to run: $ python setup.py build_ext running build_ext building 'libvirtmod' extension creating build/temp.linux-x86_64-3.10 creating build/temp.linux-x86_64-3.10/build gcc ..snip... -c build/libvirt.c -o build/temp.linux-x86_64-3.10/build/libvirt.o cc1: fatal error: build/libvirt.c: No such file or directory compilation terminated. error: command '/usr/lib64/ccache/gcc' failed with exit code 1 To solve this we instead override 'build_ext' and 'build_py'. This in turn means we call the generator to emit C code separately from Python code. 2022- 4- 21 Daniel P. Berrangé setup: replace distutils.dir_util.remove_tree with shutils The distutils.dir_util.remove_tree method has no compelling benefit over using the standard python shutils module. 2022- 4- 21 Daniel P. Berrangé setup: replace distutils.spawn with subprocess The distutils.spawn method has no compelling benefit over using the standard python subprocess module. 2022- 4- 21 Daniel P. Berrangé setup: replace distutils.spawn.find_executable with shutils The distutils.spawn.find_executable method has no compelling benefit over using the standard python shutils module. 2022- 4- 21 Daniel P. Berrangé setup: introduce an explicit check for pkg-config operation Instead of searching for the pkg-config binary manually, just try to run it and catch the exception raised if it isn't found. Use the --version flag as a way to validate that it is at least somewhat functional. 2022- 4- 21 Daniel P. Berrangé setup: stop inheriting from 'clean' command The default 'clean' command impl deletes only intermediate files from the 'build' directory. We've overridden it to delete everything. There is no benefit in inheriting from the default impl, given our subclass will delete everything. 2022- 4- 21 Daniel P. Berrangé setup: drop the 'rpm' command This duplicates funtionality already provided by the 'bdist_rpm' command. 2022- 4- 21 Daniel P. Berrangé generator: introduce ability to selectively generate code Currently we always generate both the C code and Python code at the same time. To cope with following changes to the build process, we want to be able to generate C and Python separately. 2022- 4- 21 Daniel P. Berrangé generator: rename methods for code generation The names make it clearer exactly what is being generated by each. 2022- 4- 21 Daniel P. Berrangé generator: split function skip logic out of C generator The python generator needs to know whether certain functions were skipped in the C generator. This is achieved by the C generator deleting skipped functions as it runs. This is an unhelpful side effect as it makes it impossible to run the python generator without first running the C generator. This refactors buildStubs to get rid of the global side effects it has, by providing some helper functions for buildWrappers to use. 2022- 4- 21 Daniel P. Berrangé generator: split function type validation out of C generator As a side effect of generating the C code, the buildStubs methods checks for various unsupported types and reports errors. This is an undesirable side effect, if we want to skip C code generation. Splitting function type validation out into a separate method allows better reuse. 2022- 4- 21 Daniel P. Berrangé generator: split loading of APIs out from writing stubs The buildStubs method has a side effect of loading and parsing the API XML files, which the buildWrappers method then relies on. Splitting API loading into a separate method will facilitate running only the buildWrappers method in future. 2022- 4- 21 Daniel P. Berrangé generator: merge python wrapper generator methods Instead of having three separate methods for generating python wrappers, merge them all together. 2022- 4- 21 Daniel P. Berrangé generator: refactor buildWrappers to make it more generic Prepare for using buildWrappers to generate code for the QEMU / LXC APIs too. 2022- 4- 21 Daniel P. Berrangé generator: simplify some repeated code patterns Now that we're using common data structures for all the main libvirt, QEMU and LXC APIs, several of the functions have code duplication that can be eliminated. 2022- 4- 21 Daniel P. Berrangé generator: use single function for registering all enums Now that we only use a single dict for tracking all enums, we only need a single function for registering them. 2022- 4- 21 Daniel P. Berrangé generator: use single dict for tracking all enums A single invokation of the generator only handles processing of one libvirt API module, so there is no need to use separate dicts for tracking enums. 2022- 4- 21 Daniel P. Berrangé generator: use single function for registering all functions Now that we only use a single dict for tracking all functions, we only need a single function for registering them. 2022- 4- 21 Daniel P. Berrangé generator: use single dict for tracking all skipped functions A single invokation of the generator only handles processing of one libvirt API module, so there is no need to use separate dicts for tracking skipped functions. 2022- 4- 21 Daniel P. Berrangé generator: use single dict for tracking all functions A single invokation of the generator only handles processing of one libvirt API module, so there is no need to use separate dicts for tracking functions. 2022- 4- 1 Jiri Denemark Post-release version bump to 8.3.0 2022- 3- 28 Daniel P. Berrangé gitlab: switch to using 'pip' for package installation The distutils/setuptools 'install' command is deprecated in favour of 'pip', and with recent versiosn, using it will create a bad install that triggers a traceback on all future use of setuptools: Traceback (most recent call last): File "/builds/berrange/libvirt-python/setup.py", line 328, in setup(name = 'libvirt-python', File "/usr/lib/python3.10/site-packages/setuptools/__init__.py", line 154, in setup _install_setup_requires(attrs) File "/usr/lib/python3.10/site-packages/setuptools/__init__.py", line 143, in _install_setup_requires dist = MinimalDistribution(attrs) File "/usr/lib/python3.10/site-packages/setuptools/__init__.py", line 135, in __init__ super().__init__(filtered) File "/usr/lib/python3.10/site-packages/setuptools/dist.py", line 456, in __init__ for ep in metadata.entry_points(group='distutils.setup_keywords'): File "/usr/lib64/python3.10/importlib/metadata/__init__.py", line 1009, in entry_points return SelectableGroups.load(eps).select(**params) File "/usr/lib64/python3.10/importlib/metadata/__init__.py", line 459, in load ordered = sorted(eps, key=by_group) File "/usr/lib64/python3.10/importlib/metadata/__init__.py", line 1006, in eps = itertools.chain.from_iterable( File "/usr/lib64/python3.10/importlib/metadata/_itertools.py", line 16, in unique_everseen k = key(element) File "/usr/lib64/python3.10/importlib/metadata/__init__.py", line 941, in _normalized_name return self._name_from_stem(stem) or super()._normalized_name File "/usr/lib64/python3.10/importlib/metadata/__init__.py", line 622, in _normalized_name return Prepared.normalize(self.name) File "/usr/lib64/python3.10/importlib/metadata/__init__.py", line 871, in normalize return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_') File "/usr/lib64/python3.10/re.py", line 209, in sub return _compile(pattern, flags).sub(repl, string, count) This is certainly a bug in distutils/setuptools, but given the 'install' command is deprecated, instead of waiting for a fix, just switch to the recommend 'pip install .' command. 2022- 3- 28 Daniel P. Berrangé ci: refresh from lcitool manifest This drops the CentOS 8 job and replaces Fedora 33 with 35. 2022- 3- 10 Michal Privoznik Implement virDomainQemuMonitorCommandWithFiles() override With libvirt-8.2.0 there's a new API: virDomainQemuMonitorCommandWithFiles(). Since the API has both input and output arguments we need to provide an alternative implementation. Moreover, since FD passing works only on UNIX-like systems we can query the returned FDs for their flags and construct mode for python File object. 2022- 3- 1 Jiri Denemark Post-release version bump to 8.2.0 2022- 2- 11 Daniel P. Berrangé add missing files to MANIFEST.in 2022- 1- 14 Jiri Denemark Post-release version bump to 8.1.0 2022- 1- 5 Daniel P. Berrangé Add an override impl for virDomainSetLaunchSecurityState 2021- 12- 1 Jiri Denemark Post-release version bump to 8.0.0 2021- 12- 1 Daniel P. Berrangé Switch to new GitHub repo-lockdown configuration The repo-lockdown service used to run as a bot outside GitHub, but has now switched to using the GitHub Actions workflow framework. This requires use of a new configuration file. 2021- 11- 1 Jiri Denemark Post-release version bump to 7.10.0 2021- 10- 8 Daniel P. Berrangé Add support for domain event for memory device size change 2021- 10- 1 Jiri Denemark Post-release version bump to 7.9.0 2021- 9- 24 Michal Privoznik sanitytest: Add virNetworkCreateXMLFlags() to list of name fixups When checking whether each C API is exported to Python and vice versa the sanitytest script is doing some name fixing. For instance virNetworkCreateXML() is translated into virConnect.networkCreateXML(). However, we have new C API on the way: virNetworkCreateXMLFlags() which is not on the list for these name fixups. Add it there. Mind you, the python code generator works just fine because generator.py:1082 compares just the prefix. 2021- 9- 21 Jonathon Jongsma Don't mention email patch submission in README Since patches are now submitted via gitlab merge requests, don't mention mailing list patch submission in the README. Point to the CONTRIBUTING file instead. 2021- 9- 21 Jonathon Jongsma Update readme to mention pytest instead of nose Commit a376a2ab switch from python-nose to python-pytest for tests, but the README was not updated. 2021- 9- 21 Jonathon Jongsma Add new autostart API for node devices Provide a manual override for the virNodeDeviceGetAutostart() API modeled on what's done for the network and storage APIs. 2021- 9- 2 Daniel P. Berrangé ci: remove obsolete refresh script and documentation We now use lcitool's manifest feature to generate files. 2021- 9- 2 Daniel P. Berrangé ci: re-generate containers/gitlab config from manifest This uses the command "lcitool manifest ci/manifest.yml" to re-generate all existing dockerfiles and gitlab CI config. 2021- 9- 2 Daniel P. Berrangé ci: define a CI manifest file This is to be used with the command "lcitool manifest ci/manifest.yml" to re-generate all existing dockerfiles and gitlab CI config. 2021- 9- 1 Daniel P. Berrangé rpm: drop support for RHEL-7 We no longer support libvirt on this distro 2021- 9- 1 Jiri Denemark Post-release version bump to 7.8.0 2021- 8- 2 Jiri Denemark Post-release version bump to 7.7.0 2021- 7- 27 Daniel P. Berrangé gitlab: use custom docker:dind image The current docker:dind container has broken default seccomp filter that results in clone3 being blocked, which in turn breaks Fedora 35 rawhide. This custom image has a workaround that causes the seccomp filter to return ENOSYS for clone3 instad of EPERM, thus triggering glibc to fallback to clone correctly. 2021- 7- 1 Jiri Denemark Post-release version bump to 7.6.0 2021- 6- 25 Peter Krempa Fix BlockThreshold Callback argument conversion once more The conversion was changed from "OssiiO" to "OssLLO". Unfortunately the arguments are unsigned long long, where the proper coversion character is 'K'. Fixes: https://gitlab.com/libvirt/libvirt-python/-/merge_requests/40 Fixes: fd069ac85c8cf1593587dc9287a3d5eb6bd4bdb9 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1976109 2021- 6- 1 Jiri Denemark Post-release version bump to 7.5.0 2021- 5- 27 w00506750 iothread: fix memory access out of bounds When the 'pcpu' is larger then the last 'iothr->cpumap' bits, set the list element to False to avoid out of bounds access 'iothr->cpumap'. Reviewed-by: Hogan Wang 2021- 5- 27 Jiri Denemark Post-release version bump to 7.4.0 2021- 5- 25 Daniel P. Berrangé containers: refresh containers with latest libvirt-ci 2021- 5- 25 Daniel P. Berrangé gitlab: don't set RPM variable on container job 2021- 5- 25 Daniel P. Berrangé gitlab: add OpenSUSE Tumbleweed container and build 2021- 5- 25 Daniel P. Berrangé gitlab: introduce Fedora 34 container and build 2021- 5- 25 Daniel P. Berrangé gitlab: rename opensuse-152 to opensuse-leap-152 2021- 5- 25 Daniel P. Berrangé gitlab: rename centos-stream to centos-stream-8 2021- 5- 25 Daniel P. Berrangé gitlab: drop Fedora 32 container and build 2021- 5- 25 Daniel P. Berrangé gitlab: drop centos-7 container and build 2021- 4- 15 Michal Privoznik generator.py: Untangle virNodeDevice name fixup The way that virNodeDevice method name fixup is written makes it hard to find via grep (matching the virNodeDevice prefix and then matching only the operation like "Get", "Lookup", ...). Expand the string matching to match the pattern of other cases. 2021- 4- 15 Michal Privoznik generator.py: Fix method names for new virNodeDevice*() APIs In the 7.3.0 release we are going to have three new public APIs: virNodeDeviceDefineXML() virNodeDeviceUndefine() virNodeDeviceCreate() The first one is slightly problematic, because it takes virConnectPtr argument and thus our generator wants to put its wrapper under virConnect python class, which is correct, but what's incorrect is the name it chooses for the method: defineXML(). Such method already exists and wraps virDomainDefineXML() around. Also, the name is rather confusing anyway - it's missing the 'nodeDevice' prefix. Fortunately, the fix is easy - add another case into nameFixup(). The story with virNodeDeviceCreate() is similar. Except, this time the class in which the method was put is correct. But the name is still wrong, because our generator matched 'virNodeDeviceCreate' thinking it's the good old virNodeDeviceCreateXML() API and "fixed" the name of the method to nodeDeviceCreate(). Luckily, virNodeDeviceUndefine() is just fine. 2021- 4- 12 Ján Tomko spec: use pytest instead of nose 2021- 4- 12 Daniel P. Berrangé rpm: use HTTPS for URLs 2021- 4- 9 Daniel P. Berrangé Don't run sanity checks by default The sanity check scripts verify that the binding covers all APIs in the libvirt library/headers being built against. This is primarily there for libvirt maintainers to identify when there are gaps in API coverage. This is not something downstream consumers of libvirt-python should be running themselves, so we shouldn't added it to tests by default. In addition if people are working on branches or submitting merge requests for python changes, we shouldn't block their work for failed API coverage sanity tests, if the python binding otherwise builds fine and passes regular unit tests. Thus, we introduce a new gitlab job "api-coverage" with some conditions: - If pushing to a branch, the job is treated as non-fatal - For regular scheduled builds, it is mandatory - Don't run in any other scenarios This job uses the artifacts from the centos-8-git-build job and re-runs the test suite, requesting the sanity tests to be run too. This will achieve the result of letting us see missing API coverage in nightly builds, without blocking other contributions. 2021- 4- 7 Ján Tomko tests: use assertEqual instead of assertEquals tests/test_conn.py:17: DeprecationWarning: Please use assertEqual instead. 2021- 4- 7 Ján Tomko ci: refresh containers for nose->pytest switch Matches libvirt-ci commit facd5d855c97bf5b127ff9bf245c8fdf514dd916 2021- 4- 7 Ján Tomko setup: use pytest instead of nose to run the test suite The software we use for running tests - nose - has been deprecated in favor of nose2. We don't use anything nose-specific, just unittest.TestCase, which pytest can handle just fine. Switch to using pytest, which we already use for libvirt-dbus. 2021- 4- 7 Ján Tomko setup: drop have_libvirtaio This function says we have libvirtaio on Python >= 3.3, however we already mandate Python >= 3.5 at the start of the file. 2021- 4- 7 Andrea Bolognani ci: Move dco job to sanity_checks stage If the DCO check fails we still want the pipeline to fail, but that doesn't mean there's no value in running the other jobs to get a better picture. 2021- 4- 7 Andrea Bolognani ci: Use 'extends' GitLab CI feature This is the recommended way to use templates in job definitions. 2021- 4- 6 Ján Tomko ci: drop openSUSE leap 15.1 in favor of 15.2 2021- 4- 6 Ján Tomko ci: refresh dockerfiles Refresh to match libvirt-ci commit 94c25bde639eb31ff2071fb6abfd3d5c777f4ab2 2021- 4- 1 Jiri Denemark Post-release version bump to 7.3.0 2021- 3- 1 Jiri Denemark Post-release version bump to 7.2.0 2021- 3- 1 renlei4 Fix wrong type for BlockThreshold Callback type of threshold and excess are unsigned long long, but PyObject_CallMethod incorrectly set it to int. if threshold or excess greater than 0x7FFFFFFF(max int), those variables will overflow. 2021- 2- 15 Daniel P. Berrangé Add impl override for virDomainGetMessages 2021- 2- 9 Beraldo Leal improving readme with requirements When installing this library in a fresh system, some basic packages are necessary to compile and run. This patch will add basic instructions with some requirements to help new contributors and users. 2021- 1- 15 Jiri Denemark Post-release version bump to 7.1.0 2020- 12- 15 Daniel P. Berrangé ci: refresh containers for CentOS-8 PowerTools repo rename A recent CentOS-8 update renamed the "PowerTools" repo to "powertools" and since dnf is case sensitive wrt repo names, this broke ability to build new containers. The refresh fixes the repo name and pulls in other misc improvements to containers. 2020- 12- 3 Daniel P. Berrangé Avoid signed/unsigned warnings in loop over SSH keys libvirt-override.c: In function ‘libvirt_virDomainAuthorizedSSHKeysGet’: libvirt-override.c:10455:19: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare] 10455 | for (i = 0; i < nkeys; i++) | ^ 2020- 12- 1 Daniel P. Berrangé gitlab: replace "libvirt-" prefix with "ci-" in dockerfiles This makes the dockerfile name match the output container name 2020- 12- 1 Daniel P. Berrangé gitlab: refresh containers with lcitool for fully minimized base 2020- 12- 1 Daniel P. Berrangé gitlab: re-generate container images from lcitool This introduces Fedora 33 and removes some redundant packages. 2020- 12- 1 Daniel P. Berrangé gitlab: move dockerfiles into ci/containers sub-directory This brings the repo into alignment with the main libvirt.git practice. 2020- 12- 1 Jiri Denemark Post-release version bump to 7.0.0 2020- 11- 27 Erik Skultety MANIFEST.in: Distribute MANIFEST.in in the source tarball Follow the same procedure as we do with specfiles in the main library where we distribute libvirt.spec.in along with the generated libvirt.spec inside the tarball. Fixes: https://gitlab.com/libvirt/libvirt-python/-/issues/5 2020- 11- 19 Michal Privoznik Implement virDomainAuthorizedSSHKeys{Get,Set} Both APIs work with string lists (the getter returns it, the setter gets keys to set from it) -> represent that as a python list. The rest is kept as is in C. 2020- 11- 12 Daniel P. Berrangé Add support for memory failure event callbacks 2020- 11- 12 Daniel P. Berrangé Replace deprecated PyEval_CallObject with PyObject_Call The former is deprecated since Python 3.9, and the latter has existed for all 3.x and probably before. 2020- 11- 12 Daniel P. Berrangé Pass -Werror when building extension This ensures we pick up warnings from new python headers or other problems. 2020- 11- 12 Daniel P. Berrangé Avoid truncating python version number when running sanity test The current code assumes the version number string will be only three characters long, which fails with "3.10". 2020- 11- 12 Daniel P. Berrangé Avoid use of thread function deprecated in 3.9 PyEval_ThreadsInitialized was deprecated in 3.9, with deletion targetted for 3.11. Furthermore since 3.7 it is guaranteed that threads are always initialized by Py_Initialize(), so checking it is redundant. 2020- 11- 6 Daniel P. Berrangé Add unit tests for openAuth method Validate that the type hinting is working as expected 2020- 11- 2 Jiri Denemark Post-release version bump to 6.10.0 2020- 10- 6 Daniel P. Berrangé gitlab: optimize CI job dependencies Allow more parallelization by giving explicit dependencies between jobs. 2020- 10- 6 Daniel P. Berrangé tests: start basic unit tests for more APIs To prevent regressions, especially with generated code, we need to have test coverage of more APIs. This starts off with coverage for object creation for all object types supported by the test driver currently. This exercises constructors which have been broken several times in the past. Related https://gitlab.com/libvirt/libvirt-python/-/issues/4 2020- 10- 6 Daniel P. Berrangé fix constructor param name for virDomainSnapshot / virDomainCheckpoint Fixes 7f021c21d6a091ca33615852d6061e75b2500f3f Resolves https://gitlab.com/libvirt/libvirt-python/-/issues/4 2020- 10- 1 Jiri Denemark Post-release version bump to 6.9.0 2020- 9- 1 Philipp Hahn generator: Work around type change a variable should not change its type. Reviewed-by: Ján Tomko 2020- 9- 1 Philipp Hahn generator: Add PEP 484 type annotations 2020- 9- 1 Philipp Hahn generator: Merge common code of print_function_wrapper 2020- 9- 1 Philipp Hahn generator: Merge code for __init__ genration 2020- 9- 1 Philipp Hahn generator: Expand tuple to names in for loop Assign tuple to multiple loop variables for better readability 2020- 9- 1 Philipp Hahn generator: break lines in generated code to be closes to pep8 which makes reading the generated code easier and reduces the number of issues found by flake8. 2020- 9- 1 Philipp Hahn generator: Use empty string instead of None for better type checking: both are bool()==False, but None is not str. 2020- 9- 1 Philipp Hahn generator: Convert to defaultdict() for nested dictionaries allows to remove the case distinction for "first" from "all other" cases. Reviewed-by: Ján Tomko 2020- 9- 1 Philipp Hahn generator: Move funcs_failed into buildStubs() The variables are local to that funcion 2020- 9- 1 Philipp Hahn generator: Convert list() to set() tuple() and list() are sequences, while dict() and set() are hash-based, which is more efficient for contains(). 2020- 9- 1 Philipp Hahn generator: Convert dict() to set() Python has a native type for set()s. 2020- 9- 1 Philipp Hahn generator: Simplify boolean condition no need to compare with None or empty string. 2020- 9- 1 Philipp Hahn generator: Simplify loop break 2020- 9- 1 Philipp Hahn generator: Simplify sorting Use sorted(..., key=...) instead of using explicit list.sort() 2020- 9- 1 Philipp Hahn generator: Fixed writing cached=None 2020- 9- 1 Philipp Hahn generator: Store arguments and return as tuple instead of list. 2020- 9- 1 Philipp Hahn generator: Expand tuple to names in for loop Assign tuple to multiple loop variables for better readability 2020- 9- 1 Philipp Hahn generator: Initialize with empty strings instead of using None as this has a different type. 2020- 9- 1 Philipp Hahn generator: Simplify XML attribute fetching Use attr.get(key, default) instead. Also use the empty sting "" as the default value instead of "None": Both are "False" when used as a bool()ean, but "None" would require an explicit check for "not None" in many places as str() and None have different types. Reviewed-by: Ján Tomko 2020- 9- 1 Philipp Hahn generator: Convert in_function to bool 2020- 9- 1 Philipp Hahn generator: Use string formatting instead of sting concatenating. 2020- 9- 1 Philipp Hahn generator: Use SAX method names directly instead of using legacy method names from xmllib. Depends: 3740a5e4c701281ac76a55e3f02b1d4221f1f9f0 2020- 9- 1 Philipp Hahn generator: Remove unused SAX content handler methods getmethodname() close() cdata() 2020- 9- 1 Philipp Hahn generator: Refactor parser creation to use closing context manager. 2020- 9- 1 Philipp Hahn generator: Open file with context manager 2020- 9- 1 Philipp Hahn generator: Use splitlines() instead of hand-coded implementation. 2020- 9- 1 Philipp Hahn generator: Just walk the dict instead of generating a list first. 2020- 9- 1 Philipp Hahn generator: Directly get dict length instead of generating a list and then counting the elements. 2020- 9- 1 Philipp Hahn generator: Walk only the values instead of the keys and then doing a lookup. 2020- 9- 1 Philipp Hahn generator: Use dict.item() to walk keys and values which saves a lookup of each key. 2020- 9- 1 Philipp Hahn generator: Check contained in hash directly instead of explicitly requesting only the keys as a list and converting that list to another list. Checking directly for an element to be contained in a hash is much more efficient as this is done using hashing O(1) instead of walking the list in half on average O(n). Reviewed-by: Ján Tomko 2020- 9- 1 Philipp Hahn generator: Initialize function_classes directly 2020- 9- 1 Philipp Hahn generator: Remove global declarations for variables with are not assigned. 2020- 9- 1 Philipp Hahn generator: Use string concatenation :%s,\(\w\+\)\s*=\s*\1\s*+,\1 +=, 2020- 9- 1 Philipp Hahn generator: Use increment assignment :%s,\(\w\+\)\s*=\s*\1\s*+,\1 +=, 2020- 9- 1 Philipp Hahn generator: Use enumerate() instead of manual iteration counting. 2020- 9- 1 Philipp Hahn generator: Simplify string concatentaion by using ''.join() instead of concatenating string fragments in a loop, which is slower as it required re-hashing the string multiple times. 2020- 9- 1 Philipp Hahn generator: Use more string formatting 2020- 9- 1 Philipp Hahn generator: Merge now identical if-elif-else cases Commit ca394b9f "generator: Fix parent type" fixed the case for creating `virStorage*` instances, which require a reference to `virConnect`, so the special handling for `._conn` is no longer needed. Commit ee5c856a "Remove legacy libvirtError arguments" removed the different arguments, so all cases are the same now. Reviewed-by: Ján Tomko 2020- 9- 1 Philipp Hahn generator: Fix return type on failure to return a negative value instead of None for consistency. 2020- 9- 1 Philipp Hahn generator: Remove useless sort key tuples are sorted by first component anyway. 2020- 9- 1 Philipp Hahn generator: Remove skipped_modules Unused. 2020- 9- 1 Philipp Hahn generator: Remove dead variable assignments 2020- 9- 1 Philipp Hahn generator: Use raw-string for regular expression "\(" is not a valid escape sequence for a Python string, but currently is passed on unmodified. This might breaks in the future when new escape sequences are introduced. > generator.py:1001:7: W605 invalid escape sequence '\(' > generator.py:1001:18: W605 invalid escape sequence '\)' Use raw python string instead. 2020- 9- 1 Philipp Hahn generator: Convert to 'not in' and 'is not' as recommended by pep8 2020- 9- 1 Philipp Hahn generator: Change type of quiet to bool Use `bool` instead of `int`. 2020- 9- 1 Philipp Hahn generator: Simplify exception handling sys.exc_info() returns a 3-tuple (type, value, traceback), where `value` is the instance captured by `except type as value`. 2020- 9- 1 Philipp Hahn generator: Cleanup imports Move imports to top Remove unused import string Remove duplicate import os 2020- 9- 1 Philipp Hahn generator: Do not use bare except as it also catches SystemExit, InterruptedError, SyntaxError and such. 2020- 9- 1 Jiri Denemark Post-release version bump to 6.8.0 2020- 8- 28 Philipp Hahn Revert "libvirtaio: Drop object(*args, **kwargs)" This reverts commit f4be03b330125ab1e5a2bb10b4f12674aeff4691. While object.__init__() does not expect any additional arguments, this construct is required for Pythons multiple inheritance implementation. The original author Wojtek Porczyk explained is this way: > I'm sorry I didn't notice this earlier, but the commit f4be03b3 dated > 2020-04-20 [0] is wrong. The super().__init__(*args, **kwargs) in > Callback.__init__ was there on purpose, because of how Python's inheritance in > new-style classes works. > > Let me explain this a bit, because it is not obvious. > > Suppose you had diamond inheritance like this: > > class A(object): pass > class B(A): pass > class C(A): pass > class D(B,C): pass > > And those classes needed a common function with varying arguments: > > class A(object): > def spam(self, a): print(f'A: {a}') > class B(A): > def spam(self, b): print(f'B: {b}') > class C(A): > def spam(self, c): print(f'C: {c}') > class D(B,C): > def spam(self, d): print(f'D: {d}') > > The way to call all parent's functions exactly once (as per MRO) and accept > all arguments and also forbid unknown arguments is to accept **kwargs > everywhere and pass them to super().spam(): > > class A: > def spam(self, a): > print(f'A: {a}') > class B(A): > def spam(self, b, **kwargs): > print(f'B: {b}') > super().spam(**kwargs) > class C(A): > def spam(self, c, **kwargs): > print(f'C: {c}') > super().spam(**kwargs) > class D(B, C): > def spam(self, d, **kwargs): > print(f'D: {d}') > super().spam(**kwargs) > > Let's run this: > > >>> B().spam(a=1, b=2) > B: 2 > A: 1 > >>> D().spam(a=1, b=2, c=3, d=4) > D: 4 > B: 2 > C: 3 > A: 1 > > You may notice that super() in B.spam refers to two different classes, either > A or C, depending on inheritance order in yet undefined classes (as of B's > definition). > > That's why the conclusion that super() in Callback.__init__ refers to object > is wrong. In this example, spam=__init__, A=object, B=Callback and C and D are > not yet written, but theoretically possible classes that could be written by > someone else. Why would they be needed, I don't know, but if someone writes > them, s/he would be out of options to invent new arguments to C.__init__. > > Note that super().__init__(*args, **kwargs) when super() refers to object > isn't harmful, and just ensures that args and kwargs are empty (i.e. no > unknown arguments were passed). In fact, this is exactly why object.__init__() > takes no arguments since Python 2.6 [1][2], as you correctly point out in the > commit message. > > I don't think this breaks anything (I very much doubt anyone would need to > write code that would trigger this), nevertheless, as the commit is both > pointless and wrong, and as the original author of libvirtaio I'd like to ask > for this commit to be reverted. If this breaks some static analysis tool, > could you just suppress it for this particular line? > > > [0] https://gitlab.com/libvirt/libvirt-python/-/commit/f4be03b330125ab1e5a2bb10b4f12674aeff4691 > [1] https://bugs.python.org/issue1683368 > [2] https://docs.python.org/3/whatsnew/2.6.html#porting-to-python-2-6 > (fourth point) > 2020- 8- 18 Philipp Hahn connect: Just clear all event handlers 2020- 8- 18 Philipp Hahn domain: Fix None comparison None should be compared with "is None" instead of "== None", as the later would invoke a "__cmp__()" method. 2020- 8- 18 Philipp Hahn stream: Return None from callback nobody evaluates the return value. 2020- 8- 18 Philipp Hahn stream: Convert type() to isinstance() 2020- 8- 18 Philipp Hahn stream: no type change static typing forbids re-declaring a variable with different types. Rename the variable. 2020- 8- 18 Philipp Hahn stream: Simplify boolean condition 2020- 8- 18 Philipp Hahn stream: Fix exception traceback handling sys.exc_info() returns a 3-tuple (type, value, traceback). Raising just `value` again looses the traceback information as this creates a new exception. Just use `raise` which re-raises the previous exception including the original traceback. FYI: There is a subtile difference between Python 2 and Python 3: > try: > raise ValueError() > except ValueError: > try: > raise TypeError() > except TypeError: > pass > raise With Python 3 the exception environment is dropped after the exception has been handled - as such Python 3 re-raises the outer ValueError. With Python 2 the last (inner) exception is raised: TypeError 2020- 8- 18 Philipp Hahn stream: Do not use bare except as it also catches SystemExit, InterruptedError, SyntaxError and such. 2020- 8- 18 Philipp Hahn override: Convert to list comprehension :%s/retlist = list()\n\s*\(for \w\+ in ret\):\n\s*retlist.append(\(.*\))\n\n\s*return retlist/return [\2 \1]/ 2020- 8- 18 Philipp Hahn override: Catch type error handler() should either return bytes or -2 or -3. Explicitly raise ValueError or TypeError to silence mypy. 2020- 8- 18 Philipp Hahn override: no type change static typing forbids re-declaring a variable with different types. Rename the variable. 2020- 8- 18 Philipp Hahn override: Add manual PEP 484 type annotations 2020- 8- 18 Philipp Hahn override: Simplify exception handling sys.exc_info() returns a 3-tuple (type, value, traceback), where `value` is the instance captured by `except type as value`. 2020- 8- 17 Vincent Vanlaer Include libvirt-qemu-override.py in sdist libvirt-qemu-override.py was introduced in e3da8f17 but never added to MANIFEST.in. It was therefore not contained in the official releases on libvirt.org. 2020- 8- 7 Philipp Hahn libvirtaio: Add manual PEP 484 type annotations 2020- 8- 6 Philipp Hahn libvirtaio: assert callback type self.callbacks contains a mix of FDCallback and TimeoutCallback, while the update code does not explicitly check for. 2020- 8- 6 Philipp Hahn libvirtaio: Fix return type libvirtaio.py:364: error: "virEventInvokeFreeCallback" does not return a value 2020- 8- 6 Philipp Hahn libvirtaio: Drop object(*args, **kwargs) object.__init__() does not expect those parameters. 2020- 8- 6 Philipp Hahn libvirtaio: Cleanup imports Move imports to top 2020- 8- 6 Philipp Hahn sanitytest: no type change static typing forbids re-declaring a variable with different types. Rename the variable. 2020- 8- 6 Philipp Hahn sanitytest: Use str.startswith() instead of str[0] 2020- 8- 6 Philipp Hahn sanitytest: Use set for tracking used functions 2020- 8- 6 Philipp Hahn sanitytest: Use 3-tuple for finalklassmap 2020- 8- 6 Philipp Hahn sanitytest: Use 3-tuple for basicklassmap 2020- 8- 6 Philipp Hahn sanitytest: Add PEP 484 type annotations 2020- 8- 6 Philipp Hahn sanitytest: Drop Python 2 compatibility Python 3 only has int, remove the Python 2 long type 2020- 8- 6 Philipp Hahn sanitytest: Drop else:pass useless 2020- 8- 6 Philipp Hahn sanitytest: Do not re-declare set is a built-in python type 2020- 8- 6 Philipp Hahn sanitytest: Convert type() to isinstance() 2020- 8- 6 Philipp Hahn sanitytest: Skip type annotations Teach sanitytest to ignore typing imports 2020- 8- 6 Philipp Hahn sanitytest: Remove unused import 2020- 8- 6 Philipp Hahn Remove legacy libvirtError arguments The fields have been deprecated in C with git:f60dc0bc09f09c6817d6706a9edb1579a3e2b2b8 They are only passed to the libvirtError constructor, but not stored for later or used anywhere else. sed -ri '/raise libvirtError/s/, \w+=self(\._dom)?//' *.py 2020- 8- 6 Philipp Hahn Normalize white space indent by 4 spaces one spaces around assignments 2020- 8- 6 Philipp Hahn examples/event-test: Fix remove return type The remove function are supposed to return 0 on success and -1 on failure. 2020- 8- 5 Philipp Hahn examples: Fix white space indent by 4 spaces one spaces around assignments 2020- 8- 5 Philipp Hahn examples: Replace sys.exit() with exit() No need to import sys. 2020- 8- 5 Philipp Hahn examples: Cleanup imports Break import into multiple lines as recommended by PEP-8 Move imports to top Remove unused imports 2020- 8- 5 Philipp Hahn examples: Do not use bare except as it also catches SystemExit, InterruptedError, SyntaxError and such. 2020- 8- 5 Philipp Hahn examples: Convert to ArgumentParser Replace getopt() and hand-rolled-parser with argparse.ArgumentParser. Fix wrong header comments copy-pasted from domstart.py 2020- 8- 5 Philipp Hahn examples: Add/fix PEP 484 type annotation 2020- 8- 5 Philipp Hahn examples: Add missing return values examples/dhcpleases.py:45: error: Missing return statement 2020- 8- 5 Philipp Hahn examples/nodestat: Fix None comparison "is" compares for "points to the same object", which for strings is the same as comparing the byte sequence itself as Python hashes each strings to only stores a unique copy of each string. > examples/nodestats.py:86:43: F632 use ==/!= to compare constant literals (str, bytes, int, float, tuple) > examples/nodestats.py:91:12: F632 use ==/!= to compare constant literals (str, bytes, int, float, tuple) > examples/nodestats.py:94:40: F632 use ==/!= to compare constant literals (str, bytes, int, float, tuple) Use "==" and "!=" for string comparsion. 2020- 8- 5 Philipp Hahn examples/consolecallback: Fix assorted errors Assert stream is opened before receiving bytes. Need to check for bytes() instead of [unicode]str(). 2020- 8- 5 Philipp Hahn examples/consolecallback: Add var to save callback > examples/consolecallback.py:98: error: "Console" has no attribute "stdin_watch" 2020- 8- 5 Philipp Hahn examples/esxlist: Fix Python 2 raw_input() which was renamed to input() for Python 3. 2020- 8- 5 Philipp Hahn examples/event-test: Use atexit for Python 3 Assigning sys.exitfunc no longer works with Python 3. Use atexit.register() instead. 2020- 8- 5 Philipp Hahn examples/event-test: Remove unneeded global statement It only needed when a value is assigned. 2020- 8- 5 Philipp Hahn examples/dhcp*: Fix None comparison None should be compared with "is None" instead of "== None", as the later would invoke a "__cmp__()" method. 2020- 8- 5 Philipp Hahn examples/*: Remove stray semicolon This is Python, not C 2020- 8- 4 Daniel P. Berrangé ci: refresh dockerfiles for changed libvirt build system Libvirt changed from autotools to meson. All the containers need refreshing and the CI recipes updated. 2020- 8- 2 Jiri Denemark Post-release version bump to 6.7.0 2020- 7- 27 Philipp Hahn generator: Fix parent type The constructors for virDomain, virStoragePool, virDomainCheckpoint, virDomainSnapshot expect virConnect as their first argument. The current code always uses `self`, which is okay when such an instance is created from a method of virConnect itself, but there are several cases where this is not the case: virDomain.migrate() -> virDomain virDomain.migrate2() -> virDomain virDomain.migrate3() -> virDomain virDomainCheckpoint.getParent() -> virDomainCheckpoint virDomainSnapshot.getParent() -> virDomainSnapshot virStorageVol.storagePoolLookupByVolume() -> virStoragePool > libvirt.py:1850: error: Argument 1 to "virDomain" has incompatible type "virDomain"; expected "virConnect" > libvirt.py:1871: error: Argument 1 to "virDomain" has incompatible type "virDomain"; expected "virConnect" > libvirt.py:1888: error: Argument 1 to "virDomain" has incompatible type "virDomain"; expected "virConnect" > libvirt.py:3422: error: Argument 1 to "virStorageVol" has incompatible type "virStoragePool"; expected "virConnect" > libvirt.py:6835: error: Argument 1 to "virDomainCheckpoint" has incompatible type "virDomainCheckpoint"; expected "virDomain" > libvirt.py:6943: error: Argument 1 to "virDomainSnapshot" has incompatible type "virDomainSnapshot"; expected "virDomain" >>> import libvirt >>> con = libvirt.open('test:///default') >>> dom = con.lookupByName("test") >>> first = dom.checkpointCreateXML("""First""") >>> first.domain() ^^^^^^ >>> second = dom.checkpointCreateXML("""Second""") >>> parent = second.getParent() >>> parent.domain() ^^^^^^^^^^^^^^^^ 2020- 7- 27 Philipp Hahn debug: Fix bit-rot in debug output Let the compiler optimize out the printf() call instead of doing it with the pre-processor as the later does not catch format string errors or the following case, where NULLSTR() is used but not defined: > libvirt-qemu-override.c: In function ‘libvirt_qemu_virConnectDomainQemuMonitorEventRegister’: > libvirt-qemu-override.c:271:34: warning: implicit declaration of function ‘NULLSTR’; did you mean ‘NULL’? [-Wimplicit-function-declaration] > 271 | pyobj_conn, pyobj_dom, NULLSTR(event), pyobj_cbData, flags); > | ^~~~~~~ > libvirt-qemu-override.c:39:28: note: in definition of macro ‘DEBUG’ > 39 | while (0) {printf(fmt, __VA_ARGS__);} > | ^~~~~~~~~~~ > libvirt-qemu-override.c:270:11: warning: format ‘%s’ expects argument of type ‘char *’, but argument 4 has type ‘int’ [-Wformat=] > 270 | DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventRegister(%p %p %s %p %x) called\n", > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > 271 | pyobj_conn, pyobj_dom, NULLSTR(event), pyobj_cbData, flags); > | ~~~~~~~~~~~~~~ > | | > | int > libvirt-qemu-override.c:39:23: note: in definition of macro ‘DEBUG’ > 39 | while (0) {printf(fmt, __VA_ARGS__);} > | ^~~ > libvirt-qemu-override.c:270:73: note: format string is defined here > 270 | DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventRegister(%p %p %s %p %x) called\n", > | ~^ > | | > | char * > | %d Copy the definition of NULLSTR from libvirt/src/internal.h to typewrappers.h 2020- 7- 27 Philipp Hahn libvirtaio: Fix return types of callback libvirt defines the signature for the callback functions, e.g. the functions for remove() must return -1 on error and 0 on success. Raising an exception violates that contract. _remove_timeout() did not explicitly handle a double-remove and implicitly passed on the exception. update() expects no return value, so remove the pointless return to pass on None. 2020- 7- 27 Philipp Hahn qemu-api: Fix return type The API XML description uses "C types": "str *" is not valid. 2020- 7- 27 Philipp Hahn generator: Fix domainCheckpoint.listAllChildren() virDomainCheckpoint(dom, _obj) expects a reference to the virDomain as its first argument, but virDomainCheckpoint.listAllChildren() passes `self` instead: libvirt.py:7056: error: Argument 1 to "virDomainCheckpoint" has incompatible type "virDomainCheckpoint"; expected "virDomain" >>> import libvirt >>> con = libvirt.open('test:///default') >>> dom = con.lookupByName("test") >>> first = dom.checkpointCreateXML("""First""") >>> second = dom.checkpointCreateXML("""Second""") >>> child, = first.listAllChildren() >>> second.domain() ^^^^^^^^^ >>> child.domain() ^^^^^^^^^^^^^^^^^^^ 2020- 7- 27 Philipp Hahn generator: Fix domainSnapshot.listAllChildren() virDomainSnapshot(dom, _obj) expects a reference to the virDomain as its first argument, but virDomainSnapshot.listAllChildren() passes `self` instead: libvirt.py:6459: error: Argument 1 to "virDomainSnapshot" has incompatible type "virDomainSnapshot"; expected "virDomain" >>> import libvirt >>> con = libvirt.open('test:///default') >>> dom = con.lookupByName("test") >>> first = dom.snapshotCreateXML("""First""") >>> second = dom.snapshotCreateXML("""Second""") >>> child, = first.listAllChildren() >>> second.domain() ^^^^^^^^^ >>> child.domain() ^^^^^^^^^^^^^^^^^ 2020- 7- 27 Philipp Hahn generator: Fix string formatting remove excessive arguments. 2020- 7- 27 Philipp Hahn generator: Fix undefined variables file generator.py:931:15: F821 undefined name 'file' generator.py:951:15: F821 undefined name 'file' 2020- 7- 22 Jiri Denemark Post-release version bump to 6.6.0 2020- 7- 17 Radostin Stoyanov generator: Fix typos 2020- 7- 15 Radostin Stoyanov examples: Refactor domipaddrs This patch makes domipaddrs example compatible with Python3. 2020- 7- 6 Cole Robinson Fix PY_SSIZE_T_CLEAN deprecation warning Seen running on fedora 32: DeprecationWarning: PY_SSIZE_T_CLEAN will be required for '#' formats ret = libvirtmod.virDomainLookupByUUID(self._o, uuid) This comes from here: https://bugs.python.org/issue36381 See the section about PY_SSIZE_T_CLEAN here: https://docs.python.org/3/c-api/arg.html#strings-and-buffers Solution is to use Py_ssize_t instead of int for unpacked '#' values, combined with defined PY_SSIZE_T_CLEAN before importing Python.h. The latter turns these deprecation warnings into runtime segfaults though if we missed an instance. I verified the virt-manager's test suite works fine after this change 2020- 7- 5 Cole Robinson generator: Fix SyntaxWarning $ ./setup.py build running build /usr/bin/pkg-config --print-errors --atleast-version=0.9.11 libvirt /usr/bin/python3 generator.py libvirt /usr/share/libvirt/api/libvirt-api.xml generator.py:1562: SyntaxWarning: "is" with a literal. Did you mean "=="? if classname is "virStorageVol": ... 2020- 7- 3 Michal Privoznik virStream: Use larger buffer for sendAll/recvAll methods There are four methods which receive/send entire stream (sendAll(), recvAll(), sparseSendAll() and sparseRecvAll()). All these have an intermediary buffer which is either filled by incoming stream and passed to a user provided callback to handle the data, or the other way round - user fills it with data they want to send and the buffer is handed over to virStream. But the buffer is incredibly small which leads to smaller packets being sent and thus increased overhead. What we can do is to use the same buffer as their C counterparts do (e.g. virStreamSendAll()) - they all use VIR_NET_MESSAGE_LEGACY_PAYLOAD_MAX long buffer (which is the maximum size of a stream packet we send) - this is almost exactly 256KiB (it's 256KiB - 24B for the header). Reviewed-by: Pavel Hrdina 2020- 7- 3 Michal Privoznik MANIFEST: Distribute sparsestream.py example Reviewed-by: Pavel Hrdina 2020- 6- 8 Daniel P. Berrangé setup: post-release version bump to 6.5.0 2020- 5- 22 Andrea Bolognani ci: Test installation 2020- 5- 22 Andrea Bolognani ci: Make job skips more flexible Instead of hardcoding the names of the targets for which certain steps should be skipped, use a separate variable to store that information. 2020- 5- 14 Daniel P. Berrangé examples: remove docs about non-existent XML files The docs refers to XML files that don't exist in the python binding since it was split off from the main libvirt.git repo. Fixes #3 2020- 5- 14 Daniel P. Berrangé Drop largely empty and unused NEWS file We bundle a git generated ChangeLog file in the dist, and never add any entries to the NEWS file. Fixes #2 2020- 5- 14 Daniel P. Berrangé gitlab: add testing of the rpmbuild process 2020- 5- 5 Daniel P. Berrangé gitlab: add CONTRIBUTING.rst file to indicate use of merge requests With the introduction of automated CI pipelines, we are now ready to switch to using merge requests for the project. With this switch we longer wish to have patches sent to the mailing list, and thus the git-publish config is removed. 2020- 5- 5 Daniel P. Berrangé setup: post-release version bump to 6.4.0 2020- 5- 5 Daniel Veillard Release of libvirt-python 6.3.0 * setup.py: updated for the release 2020- 5- 1 Daniel P. Berrangé gitlab: fix typo s/perl/python/ in docker cached image name Reported-by: Pavel Hrdina 2020- 5- 1 Daniel P. Berrangé travis: delete redundant configuration Now that we're standardizing on GitLab CI for both official gating CI and developer CI, there's no compelling reason to continue to support Travis CI. Reviewed-by: Andrea Bolognani 2020- 5- 1 Daniel P. Berrangé gitlab: introduce CI jobs testing git master & distro libvirt The python build needs to validate two axis - A variety of libvirt versions - A variety of python versions We get coverage for both these axis by running a build against the distro provided libvirt packages. All that is then missing is a build against the latest libvirt git master, which only needs to be run on a single distro, for which CentOS 8 is picked as a stable long life base. Reviewed-by: Andrea Bolognani 2020- 5- 1 Daniel P. Berrangé test: workaround missing VIR_TYPED_PARAM enums in API definition On Ubuntu 18.04 with libvirt 4.0.0 libvirt-python build fails running test /usr/bin/python3 sanitytest.py build/lib.linux-x86_64-3.6 /usr/share/libvirt/api/libvirt-api.xml Cannot get a value of enum VIR_TYPED_PARAM_BOOLEAN (originally VIR_DOMAIN_BLKIO_PARAM_BOOLEAN) Cannot get a value of enum VIR_TYPED_PARAM_DOUBLE (originally VIR_DOMAIN_BLKIO_PARAM_DOUBLE) Cannot get a value of enum VIR_TYPED_PARAM_INT (originally VIR_DOMAIN_BLKIO_PARAM_INT) ...snip... The code generated for the binding is still correct and so we can just whitelist this error scenario. 2020- 4- 30 Daniel P. Berrangé gitlab: add CI job for validating DCO signoff This job uses the shared "check-dco" image to validate that all commits on a branch in a developer's repo fork have a suitable 2020- 4- 27 Philipp Hahn examples: Fix connection error handling 2 Fix two more cases in examples as libvirt.open*() does not return None but raises an exception Fixes: 283e2bc693746164b22226e14d6fe3ccd38a07bf Reviewed-by: Michal Privoznik 2020- 4- 22 Daniel P. Berrangé setup: require python >= 3.5 to build Python 3.5 is the oldest Python version available across our supported build platforms. Reviewed-by: Philipp Hahn 2020- 4- 20 Philipp Hahn examples: Fix connection error handling libvirt.open*() does not return None but raises an exception 2020- 4- 7 Daniel P. Berrangé github: enable lockdown of issues and merge requests Libvirt uses GitHub as an automated read-only mirror. The goals were to have a disaster recovery backup for libvirt.org, a way to make it easy for people to clone their own private copy of libvirt Git, and finally as a way to interact with apps like Travis. The project description was set to a message telling people that we don't respond to pull requests. This was quite a negative message to potential contributors, and also did not give them any guidance about the right way to submit to libvirt. Many also missed the description and submitted issues or pull requests regardless. It is possible to disable the issue tracker in GitHub, but there is no way to disable merge requests. Disabling the issue tracker would also leave the problem of users not being given any positive information about where they should be reporting instead. There is a fairly new 3rd party application built for GitHub that provides a bot which auto-responds to both issues and merge requests, closing and locking them, with a arbitrary comment: https://github.com/apps/repo-lockdown This commit adds a suitable configuration file for libvirt, which tries to give a positive response to user's issue/pullreq and guide them to the desired contribution path on GitLab. Reviewed-by: Andrea Bolognani Reviewed-by: Pavel Hrdina Reviewed-by: Eric Blake 2020- 4- 2 Daniel Veillard Release of libvirt-python 6.2.0 * setup.py: bumped version to 6.2.0 2020- 3- 30 Radostin Stoyanov tox: Test with Python 3.6, 3.7 and 3.8 Support for Python 2.X has been dropped with commit b22e4f2. Reviewed-by: Michal Privoznik 2020- 3- 3 Daniel Veillard Release of libvirt-python 6.1.0 * setup.py : updated for release 2020- 1- 16 Daniel P. Berrangé gitpublish: add 'libvirt-' to subject prefix Reviewed-by: Ján Tomko 2020- 1- 15 Daniel Veillard Release of libvirt-python-6.0.0 * setup.py: updated for the release 2020- 1- 3 Daniel P. Berrangé Add overrides for network port UUID getter/lookup methods The generator creates broken code for all these methods. Reviewed-by: Fabiano Fidêncio 2020- 1- 3 Daniel P. Berrangé fix class type instantiated when listing network ports Reviewed-by: Erik Skultety 2019- 12- 9 Andrea Bolognani setup: Accept 'nosetests3' as nosetests binary This is the name used on Ubuntu. Reviewed-by: Daniel P. Berrangé 2019- 12- 6 Daniel P. Berrangé Fix RPM deps for centos 7 Reviewed-by: Andrea Bolognani 2019- 12- 4 Daniel P. Berrangé Drop support for python 2 python2 will be end of life by the time of the next libvirt release. All our supported build targets, including CentOS7, have a python3 build available. Reviewed-by: Michal Privoznik 2019- 12- 2 Daniel Veillard Release of libvirt-python 5.10.0 * setup.py: update for release 2019- 11- 28 Pavel Hrdina generator.py: add mapping for VIR_DOMAIN_QEMU_AGENT_COMMAND_* Libvirt commit <95f5ac9ae52455e9da47afc95fa31c9456ac27ae> changed the VIR_DOMAIN_QEMU_AGENT_COMMAND_* enum values to use different enum values instead of direct numbers. We need to translate it back. Traceback (most recent call last): File "generator.py", line 2143, in qemuBuildWrappers(sys.argv[1]) File "generator.py", line 2008, in qemuBuildWrappers items.sort(key=lambda i: (int(i[1]), i[0])) File "generator.py", line 2008, in items.sort(key=lambda i: (int(i[1]), i[0])) ValueError: invalid literal for int() with base 10: 'VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_BLOCK' Reviewed-by: Peter Krempa 2019- 11- 6 Daniel Veillard Release of libvirt-python 5.9.0 * setup.py: update for release 2019- 10- 5 Daniel Veillard Release of libvirt-python 5.8.0 * setup.py: updated version 2019- 9- 23 Pavel Hrdina virDomainMigrate3Params: add missing parallel connections param Introduced in libvirt 5.2.0 by commit . Reported-by: Liping Cheng Reviewed-by: Daniel P. Berrangé 2019- 9- 23 Pavel Hrdina virDomainMigrate3Params: add missing bandwidth postcopy param Introduced in libvirt 5.1.0 by commit . Reviewed-by: Daniel P. Berrangé 2019- 9- 20 Daniel P. Berrangé Custom impl for virConnectSetIdentity which can't be generated Reviewed-by: Pavel Hrdina 2019- 9- 20 Pavel Hrdina virDomainMemoryStats: include hugetlb pgalloc and pgfail Introduced in libvirt 5.4.0 by commit . Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1683516 Reviewed-by: Daniel P. Berrangé 2019- 9- 20 Pavel Hrdina virDomainMemoryStats: include disk caches Introduced in libvirt 4.6.0 by commit . Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1683516 Reviewed-by: Daniel P. Berrangé 2019- 9- 12 Daniel P. Berrangé sanitytest: whitelist 'network' method as having no C impl 2019- 9- 12 Daniel P. Berrangé generator: fix constructor for virNetworkPort The virNetworkPort class is passed both the virNetwork parent python class and the virNetworkPort C object. This needs special handling in the generator, similar to how virDomainSnapshots are dealt with. Reviewed-by: Michal Privoznik 2019- 9- 5 Cole Robinson Fix -Wsign-compare warnings libvirt-override.c: In function ‘libvirt_virConnectBaselineHypervisorCPU’: libvirt-override.c:9946:23: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare] libvirt-override.c:9961:19: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare] Use ssize_t as was similarly done in 75ec2acb6163b Reviewed-by: Ján Tomko Reviewed-by: Pavel Hrdina 2019- 9- 3 Daniel Veillard Release of libvirt-python 5.7.0 2019- 9- 3 Nir Soffer spec: Build python2 package in fedora < 31 Since commit ee0cfbe65c5d (spec: Unconditionally build python2 on Fedora) python2-libvirt is not built on any Fedora version. Fix the spec to drop python2-libvirt on Fedora 31. Reviewed-by: Cole Robinson 2019- 8- 29 Michal Privoznik Implement virDomainGetGuestInfo Reviewed-by: Daniel P. Berrangé 2019- 8- 5 Daniel Veillard Release of libvirt-python-5.6.0 * setup.py: updated for new release 2019- 7- 29 Eric Blake Define virDomainCheckpointPtr typedef on old libvirt Needed prior to 5.6.0 2019- 7- 29 Eric Blake Add virDomainCheckpoint APIs Copies heavily from existing virDomainSnapshot handling, regarding what special cases the generator has to be taught and what overrides need to be written. Reviewed-by: Daniel P. Berrangé 2019- 7- 9 Cole Robinson spec: Bump minimum supported Fedora version to 29 Reviewed-by: Fabiano Fidêncio 2019- 7- 9 Cole Robinson spec: Unconditionally build python2 on Fedora In Fedora we are currently shipping python2 bindings for all builds, so this conditional is out of date. Fedora 31 may be the time that python2 bindings are dropped: https://fedoraproject.org/wiki/Changes/F31_Mass_Python_2_Package_Removal But I think it's better to wait for that to actually happen before we change this again Reviewed-by: Fabiano Fidêncio 2019- 7- 2 Daniel Veillard Release of libvirt-python 5.5.0 * setup.py: update for release 2019- 6- 26 Sergei Turchanov Fix regression in lxcOpenNamespace This fixes regression caused by the 1d39dbaf637db03f6e597ed56b96aa065710b4a1 fdlist[i] erroneously was replaced by fdlist[1] which caused lxcOpenNamespace to return a list with identical elements. Reviewed-by: Ján Tomko 2019- 6- 20 Daniel P. Berrangé Add new override file to dist 2019- 6- 20 Daniel P. Berrangé Add missing impl of virNetworkListAllPorts This API needs manual impl as the generator cannot cope 2019- 6- 20 Daniel P. Berrangé sanitytest: add some special cases for virNetworkPort APIs 2019- 6- 20 Daniel P. Berrangé generator: fix naming of getter APIs for virNetworkPort 2019- 6- 20 Daniel P. Berrangé Define virNetworkPortPtr typedef on old libvirt 2019- 6- 20 Daniel P. Berrangé Fix syntax error with missing ; and too many ) 2019- 6- 20 Daniel P. Berrangé Add support for virNetworkPort object & APIs Define the various rules in the generator to wire up methods into the virNetwork class and create the new virNetworkPort class. Reviewed-by: Pavel Hrdina Reviewed-by: Ján Tomko 2019- 6- 3 Daniel Veillard Release of Libvirt-python 5.4.0 2019- 5- 4 Daniel Veillard Release of libvirt-python 5.3.0 * setup.py: bumped release version 2019- 4- 29 Michal Privoznik Allow virConnect.getDomainCapabilities() to have no arguments Our C API allows no values to be passed (well, it accepts all NULLs). There's no reason that python binding should require all arguments. Reviewed-by: Kashyap Chamarthy 2019- 4- 4 Daniel P. Berrangé rpm: use new python macros for build/install rules The new %py{2,3}_{build,install} macros ensure that the right compiler and linker flags are used when building python modules. Reviewed-by: Andrea Bolognani 2019- 4- 3 Daniel Veillard Release of libvirt-python 5.2.0 * setup.py: bumped release version up 2019- 3- 12 Nir Soffer Fix handling of optional params in blockCopy() Commit 2b4bd07e0a22 (Add check for params, nparams being a dictionary) changed the way the optional params argument is treated. If libvirt.virDomain.blockCopy() is called without specifying params, params is None, and the call will fail with: TypeError: block params must be a dictionary This is wrong as params is defined as kwarg, breaking existing libvirt users like oVirt. Add a check for Py_None, so we accept either a dict or None and fail with TypeError with anything else. Resolves: https://bugzilla.redhat.com/1687114 2019- 3- 4 Daniel Veillard Release of libvirt-python 5.1.0 * setup.py: updated for release 2019- 2- 25 Pavel Hrdina Fix virDomainPinIOThread typed params check The VIR_DOMAIN_IOTHREAD_POLL_SHRINK is unsigned int. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1680546 2019- 2- 7 Eric Blake generator.py: typo fix 2019- 1- 24 Daniel P. Berrangé travis: add testing of 5.0.0 release Update to test against very latest release. Since we dropped two python versions, we can afford to add new libvirt version without dropping a previous one. Reviewed-by: Cole Robinson 2019- 1- 24 Daniel P. Berrangé travis: switch from trusty to xenial dist The trusty gnutls version is too old to support modern libvirt Reviewed-by: Cole Robinson 2019- 1- 24 Daniel P. Berrangé travis: remove python 2.6 and 3.6 from build matrix The lxml package that we download with pip no longer supports either of these versions of python. Reviewed-by: Cole Robinson 2019- 1- 22 Daniel P. Berrangé rpm spec: remove %{extra_release} from spec The %{extra_release} field was previously populated by data from the old autobuild.sh file but is no longer used. 2019- 1- 15 Daniel Veillard Release of libvirt-python 5.0.0 * setup.py: updated for release 2018- 12- 3 Daniel Veillard Release of libvirt-python-4.10.0 * setup.py: update to bump release number 2018- 11- 26 Philipp Hahn Add daemon to list of shutdown reasons Add the support to work with libvirt commit 66a85cb13. 2018- 11- 20 John Ferlan Fix copy paste error on the version check value 2018- 11- 20 John Ferlan Implement API binding for virDomainSetIOThreadParams Similar to libvirt_virDomainBlockCopy (and migration API's). Create the code for the new API. Reviewed-by: Pavel Hrdina 2018- 11- 20 John Ferlan Add check for params, nparams being a dictionary If PyDict_Check fails, we should force an error rather than blindly continuing on. Reviewed-by: Pavel Hrdina 2018- 11- 20 John Ferlan Add missing virPyDictToTypedParams for libvirt_virDomainBlockCopy Need to free params like similar API's such as libvirt_virDomainMigrate3 and libvirt_virDomainMigrateToURI3. Reviewed-by: Pavel Hrdina 2018- 11- 20 John Ferlan Fix typos in virDomainSetSchedulerParameters name Reviewed-by: Pavel Hrdina 2018- 11- 4 Daniel Veillard Release of libvirt-python 4.9.0 * setup.py: update for new release 2018- 11- 1 Philipp Hahn event-test.py: Report ERROR events VIR_DOMAIN_EVENT_ID_IO_ERROR and VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON callbacks receive the same 'action' parameter, so also translate that numeric action to a descriptive text for the first callback. 2018- 11- 1 Philipp Hahn event-test.py: Fix ERROR event ERROR_EVENTS translates the numeric 'action' argument to a description, not the 'reason' argument which already contains a descriptive string like 'enospc'. > Traceback (most recent call last): > File "/usr/lib/python2.7/dist-packages/libvirt.py", line 4661, in _dispatchDomainEventIOErrorReasonCallback > reason, opaque) > File "libvirt-python/examples/event-test.py", line 536, in myDomainEventIOErrorReasonCallback > dom.name(), dom.ID(), srcpath, devalias, action, ERROR_EVENTS[reason])) > File "libvirt-python/examples/event-test.py", line 474, in __getitem__ > data = self.args[item] > TypeError: tuple indices must be integers, not str Fixes: f5928c6711654f1496707ca77f626b3192843d57 2018- 10- 1 Daniel Veillard Release of libvirt-python 4.8.0 - setup.py : updated for release 2018- 9- 24 Philipp Hahn event-test.py: Fix blanks Closer to pep8 2018- 9- 24 Philipp Hahn event-test.py: Convert CONNECTION events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert SECRET events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert DEVICE events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert STORAGE events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert NETWORK events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert TRAY events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert DISK events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert GRAPHICS events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert AGENT events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert ERROR events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert WATCHDOG events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert BLOCKJOB events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Convert LIVECYCLE events to use new Description class 2018- 9- 24 Philipp Hahn event-test.py: Add class for event descriptions 2018- 9- 24 Philipp Hahn event-test.py: Simplify event ID lists by directly building the list with the IDs instead of appending them explicitly. 2018- 9- 24 Philipp Hahn event-test.py: Merge livecycle callbacks Registering the same function twice using the old domainEventRegister() interface would not work, as the function reference is used for un-registering. But it is not a problem with the new interface domainEventRegisterAny(), as that returns a unique ID. While at it also demonstrate the 'opaque' mechanism. 2018- 9- 24 Philipp Hahn event-test.py: Use __file__ instead of sys.argv[0] 2018- 9- 24 Philipp Hahn event-test.py: Add missing globale statement to fix loop termination on exit. 2018- 9- 24 Philipp Hahn event-test.py: Remove dead assignment variable is unused 2018- 9- 24 Philipp Hahn event-test.py: Remove extra parenthesis 2018- 9- 24 Philipp Hahn event-test.py: Handle closed connection If libvirtd terminates while event-test.py has an open connection to it, it will crash with the following traceback: > myConnectionCloseCallback: qemu:///session: Error > Exception in thread libvirtEventLoop: > Traceback (most recent call last): > File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner > self.run() > File "/usr/lib/python2.7/threading.py", line 754, in run > self.__target(*self.__args, **self.__kwargs) > File "examples/event-test.py", line 424, in virEventLoopPollRun > eventLoop.run_loop() > File "examples/event-test.py", line 242, in run_loop > self.run_once() > File "examples/event-test.py", line 187, in run_once > libvirt.virEventInvokeFreeCallback(opaque) > AttributeError: 'module' object has no attribute 'virEventInvokeFreeCallback' > > libvirt: XML-RPC error : internal error: client socket is closed > Traceback (most recent call last): > File "examples/event-test.py", line 872, in > main() > File "examples/event-test.py", line 854, in main > vc.secretEventDeregisterAny(id) > File "/usr/lib/python2.7/dist-packages/libvirt.py", line 4987, in secretEventDeregisterAny > if ret == -1: raise libvirtError ('virConnectSecretEventDeregisterAny() failed', conn=self) > libvirt.libvirtError: internal error: client socket is closed > Closing qemu:///session Skip unregistering the event callbacks and closing the connection if the connection is already broken / closed. 2018- 9- 24 Philipp Hahn event-test.py: Sync list of domain lifecycle events Add new events to prevent crash: > Traceback (most recent call last): > File "/usr/lib/python2.7/dist-packages/libvirt.py", line 4601, in _dispatchDomainEventCallbacks > cb(self, virDomain(self, _obj=dom), event, detail, opaque) > File "libvirt-python/examples/event-test.py", line 505, in myDomainEventCallback1 > domDetailToString(event, detail))) > File "libvirt-python/examples/event-test.py", line 484, in domDetailToString > return domEventStrings[event][detail] > IndexError: tuple index out of range 2018- 9- 3 Daniel Veillard Release of libvirt-python=4.7.0 * setup.py: updated for release 2018- 8- 6 Daniel Veillard Release of libvirt-python-4.6.0 * setup.py: updated for release 2018- 7- 23 Daniel P. Berrangé rpm: update min required rhel/fedora Reviewed-by: Andrea Bolognani 2018- 7- 23 Daniel P. Berrangé rpm: add BuildRequires on gcc The gcc RPM is no longer part of the default build root. Reviewed-by: Andrea Bolognani 2018- 7- 23 Daniel P. Berrangé rpm: use the versioned python2 macro names The use of non-versioned python2 macro names is deprecated in Fedora Reviewed-by: Andrea Bolognani 2018- 7- 16 Daniel P. Berrangé travis: add libvirt 4.5.0 version to build matrix 2018- 7- 16 Daniel P. Berrangé fix build with older libvirt missing virNWFilterBindingPtr While we correctly disable all public API bindings that rely on virNWFilterBindingPtr, the generator is still creating a helper function that needs it - libvirt_virNWFilterBinding_pointer. Making this helper conditional is a little hairy, so just provide a trivial typedef to keep it happy. 2018- 7- 10 Cole Robinson spec: Remove Group: and %defattr These are only needed for RHEL5 builds, which are no longer supported https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/message/CMCUBB4SWS3URHTRRS3OPFM4HF5CGKBW/ https://fedoraproject.org/wiki/RPMGroups 2018- 7- 2 Daniel Veillard Release of libvirt-python-4.5.0 * setup.py: updated for release 2018- 6- 28 Daniel P. Berrangé Fix bugs in nwfilter binding APIs We did not correctly mangle the API names in two cases, and we also forgot to specialize the lookup method name in the sanity test. 2018- 6- 28 Daniel P. Berrangé Add support for nwfilter binding objects / apis 2018- 6- 27 Cole Robinson libvirtaio: Fix compat with python 3.7 In python 3.7, async is now a keyword, so this throws a syntax error: File "/usr/lib64/python3.7/site-packages/libvirtaio.py", line 49 from asyncio import async as ensure_future ^ SyntaxError: invalid syntax Switch to getattr trickery to accomplish the same goal Reviewed-by: Pavel Hrdina Reviewed-by: Andrea Bolognani 2018- 6- 14 Erik Skultety Add support for virNodeGetSEVInfo This binding allows to query the AMD's SEV firmware for various platform specific things, like a PDH certificate and a certificate chain to establish a trusted connection with the firmware. Because the API uses typed params, it's exempted from generation. Reviewed-by: Ján Tomko 2018- 6- 14 Erik Skultety Add support for virDomainGetLaunchSecurityInfo Libvirt recently introduced support for getting launch security parameters, most notably AMD SEV VM memory measurement. This API can't be generated as it's using typed parameters which we need to allocate. Reviewed-by: Ján Tomko 2018- 6- 12 Pavel Hrdina libvirt_charPtrUnwrap: remove unnecessary check of returned string Function libvirt_charPtrUnwrap() either fails or always sets the unwrapped string so there is no need to check it explicitly. Reviewed-by: Ján Tomko 2018- 6- 12 Pavel Hrdina libvirt-override: Reset exception if the error is ignored In virConnectCredCallbackWrapper() we ignore the error case of libvirt_charPtrUnwrap() function so we should also reset the exception. Reviewed-by: Ján Tomko 2018- 6- 12 Pavel Hrdina typewrappers: Fix libvirt_charPtrUnwrap to set an exception if it fails If the function fails it should always set an exception. Reviewed-by: Ján Tomko 2018- 6- 12 Pavel Hrdina libvirt-utils: remove unused py_str function Commit <57a160b5248ba47d4e1c9d22d95847dad8e0524f> removed last usage but did not remove the function itself. Reviewed-by: Ján Tomko 2018- 6- 6 Daniel P. Berrangé Blacklist virGetLastError{Code,Domain} These methods will not be exposed to apps, since we auto raise all errors. 2018- 6- 4 Daniel Veillard Release of libvirt-python-4.4.0 * setup.py: update for release 2018- 6- 1 Jiri Denemark Add support for virConnectBaselineHypervisorCPU The python bindings for this API cannot be generated because are generator is not capable of handling string arrays (char **) parameters. https://bugzilla.redhat.com/show_bug.cgi?id=1584676 Reviewed-by: Ján Tomko 2018- 5- 22 Michal Privoznik event-test.py: Sync list of storage lifecycle events https://bugzilla.redhat.com/show_bug.cgi?id=1578337 Since libvirt 3.8.0 we have 6 events: defined, undefined, started, stopped, created, deleted. However, the last two were missing in a string list that translates libvirt events (int) into human readable strings. Reviewed-by: Pavel Hrdina 2018- 5- 16 Marc Hartmayer Allow virConnect to be used as a context manager The libvirt python bindings are now more 'pythonic' as virConnect can now be used as a context manager. For example, it's possible to write the following code: with libvirt.open() as conn: # do something with the connection... print(conn.listAllDomains()) At the end of this with-block the connection will be closed automatically. Reviewed-by: Bjoern Walk Reviewed-by: Boris Fiuczynski 2018- 5- 16 Marc Hartmayer libvirt-override.py: remove unused import Reviewed-by: Boris Fiuczynski Reviewed-by: Bjoern Walk 2018- 5- 16 Boris Fiuczynski libvirt-override.py: fix sparseSendAll Variable ret is used before assignment. 2018- 5- 16 Marc Hartmayer libvirt_qemu/lxc: fix a namespace issue Reviewed-by: Bjoern Walk Reviewed-by: Boris Fiuczynski 2018- 5- 16 Marc Hartmayer libvirt_qemu/lxc: import 'sys' package This fixes the pylint [1] warning "E: 25,16: Undefined variable 'sys' (undefined-variable)". [1] https://www.pylint.org/ Reviewed-by: Boris Fiuczynski Reviewed-by: Bjoern Walk 2018- 5- 3 Andrea Bolognani maint: Drop autobuild.sh The Test-AutoBuild project, that this script is supposed to be used with, hasn't seen any activity in ~7 years; these days, libvirt-python CI builds are happening on the Jenkins-based CentOS CI environment under the libvirt umbrella[1], and in that context the script is not used at all. [1] https://ci.centos.org/view/libvirt/ Reviewed-by: Daniel P. Berrangé 2018- 4- 24 Daniel P. Berrangé git: add config file telling git-publish how to send patches The "git-publish" tool is a useful git extension for sending patch series for code review. It automatically creates versioned tags each time code on a branch is sent, so that there is a record of each version. It also remembers the cover letter so it does not need re-entering each time the series is reposted. With this config file present it is now sufficient[1] to run $ git publish to send all patches in a branch to the list for review, with the correct subject prefix added for this non-core libvirt module. [1] Assuming your $HOME/.gitconfig has an SMTP server listed at least e.g. [sendemail] smtpserver = smtp.example.com 2018- 4- 19 Daniel P. Berrangé Fix build with older libvirt versions The libvirt python module is supposed to build with historical versions of the API back to 0.9.1, which means all constants / methods must be wrapped in conditionals. This was accidentally forgotten in: commit 314b2346df2d8e2d7d705b003c693b4fa0189bdf Author: Edgar Kaziakhmedov Date: Wed Feb 7 17:49:30 2018 +0300 Set hints for virPyDictToTypedParams Predefine hints for all parameters possible to avoid wrong type convert. This broke the build against any libvirt < 2.0.0 Reviewed-by: Ján Tomko 2018- 4- 3 Daniel P. Berrangé Post-release version bump to 4.3.0 2018- 3- 23 Daniel P. Berrangé Disable Python 2 on future RHEL and Fedora > 29 The end of Python 2 is nearing, so declare when it will be removed from libvirt Python binding RPMs. NB, this doesn't imply we'll be removing py2 support from upstream libvirt-python on the same timeframe - we'll consider what todo wrt that when upstream Python 2 finally goes EOL. Reviewed-by: Jiri Denemark 2018- 3- 5 Daniel P. Berrangé Post-release version bump to 4.2.0 2018- 3- 5 Daniel Veillard Release of libvirt-python 4.1.0 2018- 2- 19 Pavel Hrdina Fix virPyDictToTypedParams type hint for block copy params Reviewed-by: Daniel P. Berrangé 2018- 2- 19 Pavel Hrdina Add missing virPyDictToTypedParams hint for migration params Reviewed-by: Daniel P. Berrangé 2018- 2- 19 Pavel Hrdina Fix order of virPyDictToTypedParams hints This corresponds to the order in libvirt-domain.h header file. Reviewed-by: Daniel P. Berrangé 2018- 2- 19 Pavel Hrdina Use static variables to store virPyDictToTypedParams hints There is no need to have dynamic allocation every time the API is called. Rewrites commit <314b2346df>. Reviewed-by: Daniel P. Berrangé 2018- 2- 19 Edgar Kaziakhmedov Set hints for virPyDictToTypedParams Predefine hints for all parameters possible to avoid wrong type convert. 2018- 2- 9 Daniel P. Berrangé tests: add special case for virStoragePoolLookupByTargetPath This new API trips up the sanity test for checking mapping of all C APIs into Python. 2018- 2- 6 Jiri Denemark event-test.py: Remove extra ( in --help output 2018- 1- 19 Daniel Veillard Release of libvirt-python-4.0.0 2018- 1- 12 Daniel P. Berrange Use python*_sitearch macros instead of manually defining the dir Note we use python_sitearch not python2_sitearch, since the former is more portable. Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Fix filtering of RPM provides for .so files Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Require libvirt native version matching py version by default Although we're capable of building against any libvirt >= 0.9.11, 99% of the time we want RPM builds to be done against matching libvirt version, otherwise we might silently build against an unexpected/wrong version. We don't support building against a native libvirt that's newer than the python binding, since the generator may incorrectly handle new APIs. So use == instead of >= too. Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Turn on python3 sub-RPMs for RHEL > 7 It is expected that future RHEL-8 will have python3 by default, so enable that. It is unclear whether python2 will still be available, so leave that enabled for now. Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Adapt to rename of py2 RPMs from python- to python2- prefix Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Add emacs mode marker to activate rpm-spec highlighting Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Add checks for min supported distros Be clear about which distros we aim to support with the specfile, so we know what we can cleanup in the spec later. Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Allow override of which sub-RPMs to build Allow using rpmbuild --define "with_python2 0" to override the default logic about which python sub-RPMs to build Reviewed-by: Pavel Hrdina 2018- 1- 12 Daniel P. Berrange Allow disabling of python2 RPM build With Fedora modularity, it is possible to have add-on repos for multiple versions of python3. It is thus desirable to be able to build libvirt-python in these repos, with only the python3 sub-RPMs enabled. Thus also helps if future RHEL/Fedora drop python2 entirely from their default repos. Reviewed-by: Pavel Hrdina 2017- 12- 11 Peng Hao libvirt-python : PyObject memory leak libvirt_virConnectDomainEventTunableCallback leak a PyObject. 2017- 12- 4 Daniel Veillard Release of libvirt-python 3.10.0 2017- 11- 30 Cédric Bosdonnat Don't hardcode interpreter path This is particularly useful on operating systems that don't ship Python as part of the base system (eg. FreeBSD) while still working just as well as it did before on Linux. Reviewed-by: Daniel P. Berrange 2017- 11- 2 Daniel Veillard Release of libvirt-python-3.9.0 2017- 9- 29 Nir Soffer Unify whitespace around *_ALLOW_THREADS macros Most of the code treats libvirt API calls as separate block, keeping one blank line before the LIBVIRT_BEGIN_ALLOW_THREAD, and one blank line after LIBVIRT_END_ALLOW_THREADS. Unify the whitespace so all calls wrapped with these macros are treated as a separate block. 2017- 9- 27 Nir Soffer Release the GIL during virDomainGetMemoryStats & virDomainGetDiskErrors We discovered that the entire python process get stuck for about 30 seconds when calling virDomain.getMemoryStats() if libvirt is stuck in virConnect.getAllDomainStats() on inaccessible storage. This blocking cause a horrible mess in oVirt. This patches adds the standard *_ALLOW_THREADS around the call to avoid this unwanted blocking. 2017- 9- 26 Daniel P. Berrange Avoid implicit treatment of an arithmetic result as a boolean Latest GCC versions are unhappy with us treating an integer arithmetic result as a boolean: libvirt-utils.c: In function ‘virReallocN’: libvirt-utils.c:111:23: warning: ‘*’ in boolean context, suggest ‘&&’ instead [-Wint-in-bool-context] if (!tmp && (size * count)) { ~~~~~~^~~~~~~~ Add an explicit comparison '!= 0' to keep it happy, since its suggestion to use '&&' is nonsense. 2017- 9- 26 Daniel P. Berrange Fix comparisons between signed & unsigned integers When python3 builds C modules, it adds the -Wsign-compare flag to GCC. This creates lots of warnings where we compare a 'size_t' value against an 'int' value due to signed/unsigned difference. Change all the size_t types to ssize_t to address this. 2017- 9- 26 Wojtek Porczyk libvirtaio: add .drain() coroutine The intended use is to ensure that the implementation is empty, which is one way to ensure that all connections were properly closed and file descriptors reclaimed. 2017- 9- 26 Wojtek Porczyk libvirtaio: keep track of the current implementation Since 7534c19 it is not possible to register event implementation twice. Instead, allow for retrieving the current one, should it be needed afterwards. 2017- 9- 26 Wojtek Porczyk libvirtaio: fix closing of the objects - Descriptor.close() was a dead code, never used. - TimeoutCallback.close(), as a cleanup function, should have called super() as last statement, not first 2017- 9- 26 Wojtek Porczyk libvirtaio: do not double-add callbacks This was a harmless bug, without any impact, but it is wrong to manage the collection of callbacks from it's members. 2017- 9- 26 Wojtek Porczyk libvirtaio: cache the list of callbacks when calling When the callback causes something that results in changes wrt registered handles, python aborts iteration. Relevant error message: Exception in callback None() handle: Traceback (most recent call last): File "/usr/lib64/python3.5/asyncio/events.py", line 126, in _run self._callback(*self._args) File "/usr/lib64/python3.5/site-packages/libvirtaio.py", line 99, in _handle for callback in self.callbacks.values(): RuntimeError: dictionary changed size during iteration QubesOS/qubes-issues#2805 2017- 9- 26 Wojtek Porczyk libvirtaio: add more debug logging This logging is helpful for tracing problems with unclosed connections and leaking file descriptors. 2017- 9- 19 Daniel P. Berrange Add travis build config Enable builds on several python versions, and against several versions of libvirt. Ideally we would build all the way back to 0.9.11, since that is the min supported libvirt for python binding. It is not possible to build this old libvirt version on modern distros though, so using 1.2.0 as the oldest for now. Reviewed-by: Martin Kletzander 2017- 9- 18 Daniel P. Berrange Skip sparseRecvAll / sparseSendAll in sanity test The sanity test check aims to ensure that every function listed in the Python code maps to a corresponding C function. The Sparse send/recv methods are special though - we're never calling the corresponding C APIs, instead we have a pure python impl. 2017- 9- 6 Daniel P. Berrange Post-release version bump to 3.8.0 2017- 9- 6 Daniel P. Berrange Report an error if registering an event loop twice The C library will now ignore an attempt to register an event loop twice. It is unable to report an error in this case though due to the C API returning 'void'. To improve this we must manually report an error at the python level. 2017- 9- 6 Daniel P. Berrange Remove unused variables for event callbacks 2017- 9- 4 Daniel P. Berrange Change Obsoletes to an explicit version We only want to obsolete versions which actually had the original name, not all future versions. 2017- 9- 4 Daniel Veillard Release of libvirt-python 3.7.0 * setup.py: updated for release 2017- 8- 26 John Ferlan Implement virDomainMigrateGetMaxDowntime Add override code for virDomainMigrateGetMaxDowntime 2017- 8- 26 John Ferlan Introduce virDomainMigrateGetMaxDowntime API Introduce wrapper for virDomainMigrateGetMaxDowntime 2017- 8- 10 Daniel P. Berrange Fix package name in description of sub-RPMs 2017- 8- 10 Daniel P. Berrange Revert "rpm: assume python3 is always available" This reverts commit b302b6d884ad4c6c917203a463f3377f3615b030. Only drop the Fedora 18 test - RHEL must still build without python 3 2017- 8- 10 Daniel P. Berrange rpm: rename packages to python2-libvirt / python3-libvirt This complies with Fedora naming policy for python packages Reviewed-by: Martin Kletzander 2017- 8- 10 Daniel P. Berrange rpm: assume python3 is always available Reviewed-by: Martin Kletzander 2017- 8- 2 Tomáš Golembiovský virDomainMemoryStats: include usable memory and last update We've forgot to include VIR_DOMAIN_MEMORY_STAT_USABLE and VIR_DOMAIN_MEMORY_STAT_LAST_UPDATE constants. 2017- 8- 2 Daniel Veillard Release of libvirt-python-3.6.0 virtually identical to 3.5.0 except for the bump of version in setup.py 2017- 7- 4 Daniel Veillard Release of libvirt-python-3.5.0 * setup.py: bump version number 2017- 6- 20 Martin Kletzander Add details for shutdown event In commit a8eba5036cb4b0e2ec827e9e6e019ce70e451377, libvirt added support for two more details. In python bindings it all worked fine automagically except an example that was not updated. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1463188 2017- 6- 2 Daniel Veillard Release of libvirt-python-3.4.0 2017- 5- 24 Daniel P. Berrange Fix error check for virDomainGetTime method The virDomainGetTime returns either a dict or None, but the python glue layer for checking for '-1'. Thus it failed to raise an exception on error. 2017- 5- 24 Michal Privoznik examples: Introduce sparsestream.py Sparse streams are not that straight forward to use for the very first time. Especially the sparseRecvAll() and sparseSendAll() methods which expects callbacks. What we can do to make it easier for developers is to have an example where they can take an inspiration from. 2017- 5- 24 Michal Privoznik virStream: Introduce virStreamSparse{Recv,Send}All Yet again, our parser is not capable of generating proper wrapper. To be fair, this one wold be really tough anyway. 2017- 5- 23 Michal Privoznik virStream: Introduce virStreamRecvFlags Yet again, we need a custom wrapper over virStreamRecvFlags because our generator is not capable of generating it. 2017- 5- 23 Michal Privoznik Implement virStreamSendHole/virStreamRecvHole The return value for virStreamRecvHole is slightly different to its C counterpart. In python, either it returns the hole size or None if C API fails. 2017- 5- 17 Xavier Fernandez Use better comparison in virStream.sendAll for Python 3 In Python 3, if the file is open in binary mode, @got will end up being equal to b"" and b"" != "" in Python 3. 2017- 5- 15 Martin Kletzander spec: Install egg-info with rpm package This was being done due to now deprecated policy and that file should be installed so that pip can recognize that the packages is already installed in the system. 2017- 5- 5 Daniel Veillard Release of libvirt-python-3.3.0 2017- 4- 4 Daniel P. Berrange event-test: add ability to run the asyncio event loop The event test program '--loop' arg is modified to take the name of an event loop impl to run. eg 'event-test.py --loop asyncio' 2017- 4- 4 Daniel P. Berrange event-test: rename example event loop impl Use the name 'Poll' instead of 'Pure' for the event loop demo, since there's now a second pure python loop impl available. 2017- 4- 4 Daniel P. Berrange event-test: unregister callbacks & close conn on exit In order to test cleanup code paths we must unregister all callbacks and close the connection on shutdown. Since cleanup happens in the background, we do a short sleep to allow the main loop to run its cleanup too. 2017- 4- 4 Daniel P. Berrange event-test: add timeout to exit event loop 2017- 4- 4 Daniel P. Berrange event-test: free opaque data when removing callbacks The pure python event loop impl has to call libvirt.virEventInvokeFreeCallback to free the event opaque data from a clean stack context 2017- 4- 4 Wojtek Porczyk Add asyncio event loop implementation This is usable only on python >= 3.4 (or 3.3 with out-of-tree asyncio), however it should be harmless for anyone with older python versions. In simplest case, to have the callbacks queued on the default loop: >>> import libvirtaio >>> libvirtaio.virEventRegisterAsyncIOImpl() The function is not present on non-compatible platforms. 2017- 4- 4 Wojtek Porczyk Allow for ff callbacks to be called by custom event implementations The documentation says: > If the opaque user data requires free'ing when the handle is > unregistered, then a 2nd callback can be supplied for this purpose. > This callback needs to be invoked from a clean stack. If 'ff' > callbacks are invoked directly from the virEventRemoveHandleFunc they > will likely deadlock in libvirt. And they did deadlock. In removeTimeout too. Now we supply a custom function to pick it from the opaque blob and fire. 2017- 4- 2 Daniel Veillard Release of libvirt-python-3.2.0 * setup.py: bumped version 2017- 3- 29 Peter Krempa event: Add handler for block threshold event Unfortunately python doesn't generate those. 2017- 3- 29 Peter Krempa event: fix comment for _dispatchDomainEventMetadataChangeCallback The comment was copied from the device removal failed event. 2017- 1- 27 Daniel P. Berrange Removed unused 'functions_list_exception_test' code from generator The 'functions_list_exception_test' data structure and associated code in the generator is inherited from libxml. This has never been used in libvirt, so delete it to simplify the generator. 2017- 1- 27 Daniel P. Berrange Removed unused 'converter_type' code from generator The 'converter_type' data structure and associated code in the generator is inherited from libxml. This has never been used in libvirt, so delete it to simplify the generator. 2017- 1- 27 Daniel P. Berrange Removed unused 'classes_ancestor' code from generator The 'classes_ancestor' data structure and associated code in the generator is inherited from libxml. This has never been used in libvirt, so delete it to simplify the generator. 2017- 1- 27 Daniel P. Berrange Removed unused 'py_return_types' code from generator The 'py_return_types' data structure and associated code in the generator is inherited from libxml. This has never been used in libvirt, so delete it to simplify the generator. 2017- 1- 27 Daniel P. Berrange Removed unused 'foreign_encoding_args' code from generator The 'foreign_encoding_args' data structure and associated code in the generator is inherited from libxml. This has never been used in libvirt, so delete it to simplify the generator. 2017- 1- 27 Daniel P. Berrange Removed unused 'function_post' code from generator The 'function_post' data structure and associated code in the generator is inherited from libxml. This has never been used in libvirt, so delete it to simplify the generator. 2017- 1- 27 Daniel P. Berrange Removed unused 'reference_keepers' code from generator The 'reference_keepers' data structure and associated code in the generator is inherited from libxml. This has never been used in libvirt, so delete it to simplify the generator. 2017- 1- 27 Daniel P. Berrange Protect against user accidentally calling constructors directly When using libvirt python you must never call the object constructors directly, as these are expecting to be passed a wrapped C object. For example import libvirt c = libvirt.virConnect("qemu:///system") c.listAllDomains() will mysteriously segfault. With this change the user now gets an slightly more helpful error Traceback (most recent call last): File "", line 1, in File "/home/berrange/src/virt/libvirt-python/build/libvirt.py", line 3409, in __init__ raise Exception("Expected a wrapped C Object but got %s" % type(_obj)) Exception: Expected a wrapped C Object but got 2017- 1- 18 Wu Zongyong Fix the incorrect memory freeing which will result in crash Commit id '71fd95409' neglected to adjust a couple of API's do that now. The number of elements in new_params is equal to the length of info, instead of nparams, so it's wrong to free new_params using nparams. 2017- 1- 18 John Ferlan Post-release version bump to 3.1.0 2017- 1- 17 Daniel Veillard Release of libvirt-python-3.0.0 2017- 1- 10 Michal Privoznik examples: Update event-test.py With recent changes there are new events known to libvirt. Reflect those changes in our event-test.py example script. 2017- 1- 10 Daniel P. Berrange Fix typos in previous secrets event patch 2017- 1- 9 Daniel P. Berrange Add support for domain metadata change event 2017- 1- 9 Daniel P. Berrange Add support for secret event APIs 2016- 12- 21 Daniel P. Berrange Add override impl for virStorageVolGetInfoFlags 2016- 12- 21 Daniel P. Berrange Remove bogus \o escape in regex One of the regexes has a bogus \o instead of plain 'o'. Somehow this magically worked on all versions of python, until 3.6 came along and complained 2016- 12- 14 Daniel P. Berrange Fix running of nosetests on python 3 Previously the way Fedora installed /usr/bin/nosetests allowed it to be invoked with either python 2 or 3. Since Fedora 25 though, it contains a module name that only exists on python 2. So we need to be more intelligent and pick a different nosetests binary per version. 2016- 12- 13 Prabodh Agarwal HACKING: fix grammar 2016- 12- 5 Daniel P. Berrange Fill out more fields for PKG-INFO file Ensure the description and license are set in PKG-INFO, and clarify the summary field. 2016- 11- 11 Konstantin Neumoin don't overrun buffer when converting cpumap If we pass large(more than cpunum) cpu mask to any libvirt_virDomainPin* function, it could leads to crash. So we have to check tuple size in virPyCpumapConvert and ignore extra tuple members. Since we allocate a zeroed buffer, we don't need to bother with setting the bits to zero. 2016- 11- 11 Konstantin Neumoin move cpumap conversion code to a common helper All libvirt_virDomainPin* functions do the same thing for convert pycpumap to cpumap, so this patch moves all common logic to new helper - virPyCpumapConvert. 2016- 11- 2 Pavel Hrdina Post-release version bump to 2.5.0 2016- 11- 1 Daniel Veillard Release of libvirt-2.4.0 * setup.py: just bumped up the release number 2016- 9- 19 Peter Krempa override: Properly override wrapper for virDomainGetGuestVcpus Without the change to libvirt-override-api.xml generator.py would generate the following function header: def guestVcpus(self, params, nparams, flags=0): Since @params and @nparams are output-only in C and the python C implementation actualy creates a dict from them we should not need to pass them. Add the API definition to drop the two unnecessary args: def guestVcpus(self, flags=0): The code did not work at all until this change as the C impl expects only two arguments but the python required use of four. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1377071 2016- 9- 19 Peter Krempa Post-release version bump to 2.3.0 2016- 8- 24 Michal Privoznik PyArg_ParseTuple: Provide correct function names At the end of the format string we put :virFunctionName where ':' says "this is the end of argument list", and virFunctionName is the prefix for error messages then. However, in some cases we have had wrong names there. Some of them are actually quite funny: xmlRegisterErrorHandler. 2016- 8- 17 Jovanka Gulicoska event-test: support node device update callback 2016- 8- 17 Jovanka Gulicoska Add support for node device update callback 2016- 8- 2 Jovanka Gulicoska event-test: Add node device lifecycle event tests 2016- 8- 2 Jovanka Gulicoska Python binding for node poll lifecycle events API 2016- 8- 2 Cole Robinson Post-release version bump to 2.2.0 2016- 7- 28 Markus Rothe allow pkg-config binary to be set by env https://bugzilla.redhat.com/show_bug.cgi?id=1350523 2016- 7- 25 Pavel Hrdina Post-release version bump to 2.1.0 2016- 7- 23 Pavel Hrdina Fix crash in storage pool refresh callback Fixes copy-paste typo introduced by commit cb84e36c. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1354271 2016- 6- 24 Daniel P. Berrange Add support for storage pool refesh callback 2016- 6- 24 Daniel P. Berrange Fix signedness of arg to virDomainGetGuestVcpus 2016- 6- 23 Michal Privoznik Add support for virDomainGetGuestVcpus This function has virTypedParameterPtr as one of the args and our generator is unable to deal with that. Therefore we must provide implementation. 2016- 6- 16 Jovanka Gulicoska event-test: Add storage pool lifecycle event tests 2016- 6- 16 Jovanka Gulicoska Python binding for storage pool lifecycle events API Code matches the network event API implementation 2016- 6- 14 Daniel P. Berrange Post-release version bump to 2.0.0 2016- 6- 4 Daniel Veillard Release of libvirt-python-1.3.5 * setup.py: bumped to 1.3.5, the release is virtually identical to 1.3.4 2016- 4- 21 Peter Krempa generator.py: Consider symbols from libvirt-common Some of the libvirt public API was moved into the libvirt-common.h file. We should consider it while building python too. 2016- 4- 20 Cole Robinson spec: Don't pull in dependencies for example scripts If the scripts are marked as executable, RPM magic will scan them for dependencies, which can pull in python2 for the python3 package 2016- 4- 18 Pavel Hrdina fix crash in getAllDomainStats Commits 1d39dbaf and 827ed9b4 broke the libvirt-python API by removing virDomainRef() and virDomainFree(). virDomainStatsRecordListFree() will free that domain pointer and later when virDomain (python object) call its destructor and tries to free that same pointer again. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1326839 2016- 4- 18 Peter Krempa event: Add support VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED 2016- 4- 18 Peter Krempa Post-release version bump to 1.3.4 2016- 4- 6 Daniel Veillard Release of libvirt-python-1.3.3 2016- 3- 31 Qiaowei Ren python: add python binding for Perf API This patch adds the python binding for virDomainSetPerfEvents and virDomainSetPerfEvents API. 2016- 3- 8 Jiri Denemark Add support for JOB_COMPLETED event 2016- 2- 23 Pavel Hrdina libvirt-override: fix PyArg_ParseTuple for size_t Format string uses 'n' for Py_ssize_t but size_t is unsigned long, we need to use 'k'. 2016- 2- 23 Pavel Hrdina libvirt-override: fix PyArg_ParseTuple for unsigned long long Format string uses 'L' for long long type and 'K' for unsigned long long type. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1260356 2016- 2- 23 Pavel Hrdina libvirt-override: fix PyArg_ParseTuple for unsigned int Format string uses 'i' for int type and 'I' for unsigned int type. 2016- 2- 23 Pavel Hrdina libvirt-override: all flags should be defined as unsigned int 2016- 1- 18 Jiri Denemark Add support for MIGRATION_ITERATION event 2016- 1- 18 Jiri Denemark setup: Use cflags and ldflags properly The setup.py script reads cflags and ldflags from pkg-config and uses them when compiling/linking C modules. Since both cflags and ldflags may include multiple compiler arguments we need to split them rather than concatenating them into a single argument. 2016- 1- 18 Jiri Denemark Post-release version bump to 1.3.2 2016- 1- 17 Daniel Veillard Version bump to 1.3.1 For release but no change from 1.3.0 2015- 11- 24 Pavel Hrdina Post-release version bump to 1.3.0 2015- 10- 31 Pavel Hrdina fix crash introduced by commit 1d39dbaf Some of the libvirt_*Wrap functions steals the reference and we need to set the item in array to NULL no not free it on success. Those three places was accidentally removed by commit 1d39dbaf. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1270977 2015- 10- 15 Martin Kletzander Post-release version bump to 1.2.21 2015- 10- 5 Pavel Hrdina use VIR_PY_DICT_SET_GOTO 2015- 10- 5 Pavel Hrdina use VYR_PY_LIST_SET_GOTO and VIR_PY_LIST_APPEND_GOTO 2015- 10- 5 Pavel Hrdina use VIR_PY_TUPLE_GOTO 2015- 10- 5 Pavel Hrdina utils: introduce new macro helpers for tuple, list and dict objects 2015- 10- 5 Pavel Hrdina improve usage of cleanup paths This removes several code duplicates and also some unusual code structures. 2015- 10- 5 Pavel Hrdina drop unnecessary py_retval variable 2015- 10- 5 Pavel Hrdina change the order of some statements This change makes it easier to free allocated object especially for python objects. We can benefit from the fact, that if you call Py_DECREF on any python object it will also remove reference for all assigned object to the root object. For example, calling Py_DECREF on dict will also remove reference recursively on all elements in that dictionary. Our job is then just call Py_DECREF on the root element and don't care about anything else. 2015- 10- 5 Pavel Hrdina Must check return value for all Py*_New functions If the function fails, we need to cleanup memory and return NULL. 2015- 10- 5 Pavel Hrdina use Py_CLEAR instead of Py_XDECREF followed by NULL assignment 2015- 10- 5 Pavel Hrdina Use VIR_PY_NONE instead of increment and Py_None To insert Py_None into some other python object like dict or tuple, you need to increase reference to the Py_None. We have a macro to do that. 2015- 10- 5 Pavel Hrdina Return NULL and set an exception if allocation fails This is a recommended work-flow for allocation failures and we should follow it. 2015- 10- 5 Pavel Hrdina Return correct python object In case of error without setting an python exception we need to return a correct python object. For functions that returns anything else than a number the return value is 'None', otherwise it's '-1'. 2015- 10- 5 Pavel Hrdina Return NULL if python exception is set There is a rule, python API fails, it also in those cases sets an exception. We should follow those rules and in those cases return NULL. 2015- 10- 5 Pavel Hrdina wrap lines to 80 columns 2015- 10- 5 Pavel Hrdina fix indentation 2015- 10- 5 Pavel Hrdina indent labels by one space 2015- 10- 5 Pavel Hrdina cleanup functions definition Follow the libvirt hacking guide and make the code consistent. 2015- 10- 5 Pavel Hrdina Move utils and shared code into libvirt-utils 2015- 10- 5 Pavel Hrdina drop unnecessary goto 2015- 10- 5 Pavel Hrdina remove useless check for NULL before Py_XDECREF 2015- 10- 5 Pavel Hrdina refactor the function to not override python exceptions 2015- 10- 5 Pavel Hrdina update virDomainGetVcpus xml API description Python api returns a tuple with the vcpus information. 2015- 10- 2 Daniel Veillard Release of libvirt-python-1.2.20 2015- 9- 21 Luyao Huang generator: fix build fail with old xml lib https://bugzilla.redhat.com/show_bug.cgi?id=1222795#c6 if build libvirt-python with some old xml lib (python-pyxml), build will fail and error like this: File "generator.py", line 139, in start if "string" in attrs: File "/usr/local/lib/python2.7/site-packages/_xmlplus/sax/xmlreader.py" \ , line 316, in __getitem__ return self._attrs[name] KeyError: 0 This is an old issue and have been mentioned in commit 3ae0a76d. There is no __contains__ in class AttributesImpl, python will use __getitem__ in this place, so we will get error. Let's use 'YYY in XXX.keys()' to avoid this issue. 2015- 8- 26 Luyao Huang examples: small fix for nodestats.py example Add nodestats.py in MANIFEST.in and add a small description for nodestats.py in README 2015- 8- 3 Jiri Denemark Check return value of PyList_Append libvirt_virDomainGetSecurityLabelList called PyList_Append without checking its return value. While looking at it I noticed the function did not properly check several other return values either so I fixed them all. https://bugzilla.redhat.com/show_bug.cgi?id=1249511 2015- 8- 3 Jiri Denemark Post-release version bump to 1.2.19 2015- 8- 3 Daniel Veillard Forgot to bump version to 1.2.18 2015- 7- 30 Peter Krempa iothread: Fix crash if virDomainGetIOThreadInfo returns error The cleanup portion of libvirt_virDomainGetIOThreadInfo would try to clean the returned structures but the count of iothreads was set to -1. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1248295 2015- 7- 17 Michal Privoznik examples: Introduce nodestats example So, this is an exercise to show libvirt capabilities. Firstly, for each host NUMA nodes some statistics are printed out, i.e. total memory and free memory. Then, for each running domain, that has memory strictly bound to certain host nodes, a small statistics of how much memory it takes is printed out too. For instance: # ./examples/nodestats.py NUMA stats NUMA nodes: 0 1 2 3 MemTotal: 3950 3967 3937 3943 MemFree: 66 56 42 41 Domain 'fedora': Overall memory: 1536 MiB Domain 'fedora22': Overall memory: 2048 MiB Domain 'fedora21': Overall memory: 1024 MiB nodes 0-1 Node 0: 1024 MiB nodes 0-1 Domain 'gentoo': Overall memory: 4096 MiB nodes 0-3 Node 0: 1024 MiB nodes 0 Node 1: 1024 MiB nodes 1 Node 2: 1024 MiB nodes 2 Node 3: 1024 MiB nodes 3 We can see 4 host NUMA nodes, all of them having roughly 4GB of RAM. Yeah, all of them has nearly all the memory consumed. Then, there are four domains running. For instance, domain 'fedora' has 1.5GB memory which is not pinned onto any specific host NUMA node. Domain 'gentoo' on the other hand has 4GB memory and has 4 NUMA nodes which are pinned 1:1 to host nodes. 2015- 6- 29 Pavel Boldin virPyDictToTypedParams: packing lists of values Pack a list or a tuple of values passed to a Python method to the multi-value parameter. 2015- 6- 28 Martin Kletzander Revert "Change livbirt version to 1.3.0 for the next release" This reverts commit 751e016f09a6a0dd372667bdd2b322731718e359. Since Admin API was deferred for a release and the minor version bump didn't happen, it must not happen in libvirt-python either, for compatibility reasons. 2015- 6- 16 Martin Kletzander Change livbirt version to 1.3.0 for the next release Since the background for Admin API is merged upstream, we are bumping the minor release version as discussed previously 2015- 6- 8 Jiri Denemark Provide symbolic names for typed parameters https://bugzilla.redhat.com/show_bug.cgi?id=1222795 2015- 6- 5 Jiri Denemark Post-release version bump to 1.2.17 2015- 6- 1 Daniel P. Berrange Include tests in MANIFEST The unit tests were missing from the tar.gz archives due to not being listed in the MANIFEST.in file 2015- 5- 28 Jim Fehlig Fix duplicate entries in AUTHORS The generated AUTHORS file contains many duplicates. If an author has N commits, there will be N entries for the author in AUTHORS. Check if an author already exists in the list before appending. While at it, add a .mailmap (derived from libivrt's .mailmap) to futher tidy the generated AUTHORS list. 2015- 5- 20 Guido Günther Sort tuples on both items In order to achieve reproducible builds[0] we want the items within enums always generated in the same order so sort on both items in the tuple. [0] https://wiki.debian.org/ReproducibleBuilds/About 2015- 5- 20 Guido Günther Simplify sorting funcs.keys() can't be None, only the empty array 2015- 5- 20 Guido Günther Sort dictionary keys In order to achive reproducible builds[0] we want functions and enums always generated in the same order. [0] https://wiki.debian.org/ReproducibleBuilds/About 2015- 5- 11 Peter Krempa examples: Add example to make guest agent lifecycle event useful This example allows to use the guest agent event and metadata to track vCPU count set via the guest agent (agent-based onlining/offlining) and keep it persistent accross domain restarts. The daemon listens for the agent lifecycle event, and if it's received it looks into doman's metadata to see whether a desired count was set and issues the guest agent command. 2015- 5- 11 Peter Krempa Post-release version bump to 1.2.16 2015- 4- 22 Victor Stinner libvirt-python: add classifiers to setup.py Add the Python 3 classifier, needed by the caniusepython3 tool to check if dependencies of a projects are Python 3 compatible: https://caniusepython3.com/ 2015- 4- 22 Victor Stinner Add tox.ini to run tests on Python 2.6, 2.7 & 3.4 2015- 4- 22 Victor Stinner sanitytest.py parameters are now optional When called without parameters, sanitytest.py doesn't touch sys.path and locates itself the patch to the libvirt-api.xml file using pkg-config. This change makes possible to run sanitytest.py from tox. 2015- 4- 15 Ján Tomko Implement the DEVICE_ADDED event 2015- 4- 2 Jiri Denemark Post-release version bump to 1.2.15 2015- 3- 28 Pavel Hrdina Expose virDomainInterfacesAddresses to python binding examples/Makefile.am: * Add new file domipaddrs.py examples/README: * Add documentation for the python example libvirt-override-api.xml: * Add new symbol for virDomainInterfacesAddresses libvirt-override.c: * Hand written python api Example: $ python examples/domipaddrs.py qemu:///system f18 Interface MAC address Protocol Address vnet0 52:54:00:20:70:3d ipv4 192.168.105.240/16 2015- 3- 26 Ján Tomko Rename virDomainGetIOThreadsInfo to virDomainGetIOThreadInfo 2015- 3- 26 Ján Tomko Rename virDomainIOThreadsInfoFree to virDomainIOThreadInfoFree 2015- 3- 19 Pavel Hrdina Post-release version bump to 1.2.14 2015- 3- 11 John Ferlan Support virDomainPinIOThread Support the libvirt_virDomainSetIOThreads method using code that mimics the existing libvirt_virDomainPinVcpuFlags method The following is a sample session assuming guest 'iothr-gst' has IOThreads configured (it's currently running, too) >>> import libvirt >>> con=libvirt.open("qemu:///system") >>> dom=con.lookupByName('iothr-gst') >>> dom.ioThreadsInfo() [(1, [False, False, True, False]), (2, [False, False, False, True]), (3, [True, True, True, True])] >>> cpumap=(True,True,True,False) >>> dom.pinIOThread(3,cpumap) 0 >>> print dom.ioThreadsInfo() [(1, [False, False, True, False]), (2, [False, False, False, True]), (3, [True, True, True, False])] >>> merge 2015- 3- 11 John Ferlan Support virDomainGetIOThreadsInfo and virDomainIOThreadsInfoFree Add support for the libvirt_virDomainGetIOThreadsInfo method. This code mostly follows the libvirt_virDomainGetVcpuPinInfo method, but also takes some from the libvirt_virNodeGetCPUMap method with respect to building the cpumap into the returned tuple rather than two separate tuples which vcpu pinning generates Assuming two domains, one with IOThreads defined (eg, 'iothr-gst') and one without ('noiothr-gst'), execute the following in an 'iothr.py' file: import libvirt con=libvirt.open("qemu:///system") dom=con.lookupByName('iothr-gst') print dom.ioThreadsInfo() dom2=con.lookupByName('noiothr-gst') print dom2.ioThreadsInfo() $ python iothr.py [(1, [False, False, True, False]), (2, [False, False, False, True]), (3, [True, True, True, True])] [] $ 2015- 3- 5 Ján Tomko Clarify description for virNodeGetSecurityModel s/host/hypervisor/ to match the wording used by the C binding. https://bugzilla.redhat.com/show_bug.cgi?id=1198518 2015- 1- 27 Daniel P. Berrange Post-release version bump to 1.2.13 2015- 1- 19 Pavel Hrdina sanitytest: fix mapping test for virDomainDefineXMLFlags The libvirt API has in the name "virDomain" but it's correctly mapped into "virConnect" class. Create an exception in the sanity test. 2015- 1- 15 Eric Blake build: make it easier to backport event ids In some cases, it is very easy for downstream distros to backport enum values without requiring a .so bump. Keying the conditional code off of the upstream version where the enum value was added is not ideal, because downstream then has to patch that the feature is available in their build that still reports an earlier version number. For example, if RHEL 7 backports events from 1.2.11 into a build based on 1.2.8, building the python bindings would warn: libvirt-override.c: In function ‘libvirt_virConnectDomainEventRegisterAny’: libvirt-override.c:6653:5: warning: enumeration value ‘VIR_DOMAIN_EVENT_ID_TUNABLE’ not handled in switch [-Wswitch] switch ((virDomainEventID) eventID) { ^ libvirt-override.c:6653:5: warning: enumeration value ‘VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE’ not handled in switch [-Wswitch] The solution is simple - use feature-based probes instead of version probes. Since we already scrape the XML API document of whatever libvirt build we are binding, and that XML already documents any downstream enum additions, we can use those as the features for gating conditional compilation. * generator.py (enum): Track event id names. (buildStubs): Output define wrappers for events. * libvirt-override.c (libvirt_virConnectDomainEventBalloonChangeCallback) (libvirt_virConnectDomainEventPMSuspendDiskCallback) (libvirt_virConnectDomainEventDeviceRemovedCallback) (libvirt_virConnectDomainEventTunableCallback) (libvirt_virConnectDomainEventAgentLifecycleCallback) (libvirt_virConnectDomainEventRegisterAny): Use them. 2014- 12- 16 Michal Privoznik Bump version to 1.2.12 for new dev cycle 2014- 12- 11 Richard W.M. Jones Add c_pointer method to classes. This returns the raw C pointer to the underlying object, eg: conn = libvirt.open(None) print "0x%x" % conn.c_pointer() # returns virConnectPtr of the connection dom = conn.lookupByName("test") print "0x%x" % dom.c_pointer() # returns virDomainPtr of the domain The reason behind this is to allow us to transparently pass Python dom objects through the libguestfs Python API. https://bugzilla.redhat.com/show_bug.cgi?id=1075164 2014- 12- 2 Tomoki Sekiyama override: iterate virDomainFSInfo.devAliases using ndevAliases Currently devAliases in virDomainFSInfo struct are iterated as a NULL-terminated list, but that is not guaranteed. It should use ndevAliases which stores the number of the items in devAliases. 2014- 12- 1 Pavel Hrdina fix examples The dhcpleases example had an old usage of print function. The formating of leases record was also wrong. The event-test example had an old usage of exceptions. It's mainly to make examples compatible with python3. 2014- 11- 24 Peter Krempa event: Add bindings for agent lifecycle event Also add the example. 2014- 11- 24 Tomoki Sekiyama override: Implement bindings for virDomainGetFSInfo as domain.fsInfo Implement the function which returns a list of tuples, that contains members of virDomainFSInfo struct. 2014- 11- 11 Luyao Huang Add dict check for setTime and allow pass 'seconds' parameter When pass None or a empty dictionary to time, it will report error. This commit allows a one-element dictionary which contains just 'seconds' field, which results in the same as passing 0 for 'nseconds' field. Moreover, dict is checked for unknown fields. 2014- 11- 6 Jiri Denemark Check return value of libvirt_uintUnwrap libvirt_virDomainSendKey didn't check whether libvirt_uintUnwrap succeeded or not. https://bugzilla.redhat.com/show_bug.cgi?id=1161039 2014- 11- 3 John Ferlan Bump version to 1.2.11 for new dev cycle 2014- 10- 28 Dmitry Guryanov fix libvirt headers list Since libvirt.h has been split out, generator.py should be fixed accordingly. So add full list of header files. 2014- 10- 22 Pavel Hrdina virDomainBlockCopy: initialize flags to 0 An optional argument if not passed isn't modified by the PyArg_ParseTuple function. 2014- 10- 22 Pavel Hrdina flags cannot get right value for blockCopy function When use blockCopy, flags cannot get a right value, because PyArg_ParseTuple want to get 6 parameters and blockCopy only pass 5. Flags will get a unpredictable value, this will make the function fail with error: unsupported flags (0x7f6c) in function qemuDomainBlockCopy 2014- 10- 22 Peter Krempa Fix rest of unsigned integer handling As in the previous patch, fix all places where 'flags' is converted as a signed argument to unsigned including the python code generator. 2014- 10- 22 Luyao Huang Fix parsing of 'flags' argument for bulk stats functions When 'flags' is set to 'libvirt.VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, python will report a error: OverflowError: signed integer is greater than maximum as VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS is defined as 1<<31. This happens as PyArg_ParseTuple's formatting string containing 'i' as a modifier expects a signed integer. With python >= 2.3, 'I' means unsigned int and 'i' means int so we should use 'I' in the formatting string. See: https://docs.python.org/2/c-api/arg.html 2014- 10- 22 Peter Krempa Fix function name when parsing arguments in libvirt_virNodeAllocPages The override function was copied&pasted from virConnectGetAllDomainStats and the function name after the colon was not changed. Fix the issue as an invalid name would appear in the error message. 2014- 10- 20 Luyao Huang Improve error output when use getTime with a nonzero flags. When give a nonzero flags to getTime, c_retval will get -1 and goto cleanup. But py_retval still is NULL, so set py_retval = VIR_PY_NONE. This will make the output message more correct. 2014- 10- 16 Pradipta Kr. Banerjee Change the comment in getPyNodeCPUCount method reflecting correct called methods Comment mentions virGetNodeCPUMap whereas the actual method is virNodeGetCPUMap. Similarly comment mentions virGetNodeInfo whereas the actual method is virNodeGetInfo 2014- 10- 7 Pavel Hrdina setup.py: fix rpm build to return 1 on error 2014- 10- 7 Martin Kletzander sanitytest: define long for python version >= 3 Commit c58c7f362aab37e4961407c2efc8a74925ed9c37 fixed 32-bit python build but broke build with python3 due to the lack of 'long' in the newer version of python. This patch aims to fix it with a simple string comparison of sys.version and '3'. 2014- 10- 7 Martin Kletzander sanitytest: count with the fact that large enums can be long On 32-bit systems, one new flag that has the value of 1 << 31, namely VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS, fails to fit into an 'int' on python and is therefore of type 'long'. Fix sanitytest to count with such fact in order to avoid build failures on 32-bit systems. 2014- 10- 6 Martin Kletzander sanitytest: check for exported enums We are already collecting list of enums exported and list of enums we want to have available. Event though there was an issue with one enum fixed with 014d9bbaf368b33a881f1d6b2fd8a5dd285a4f71, there was no test for it and this commit tries to fix that. 2014- 10- 2 Pavel Hrdina Post-release version bump for new dev cycle 2014- 9- 30 Pavel Hrdina implement new tunable event Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1147639 2014- 9- 26 Michal Privoznik Implement new virNodeAllocPages API 2014- 9- 12 Michal Privoznik generator: Free strings after libvirt_charPtrWrap https://bugzilla.redhat.com/show_bug.cgi?id=1140998 Up till bb3301ba the wrapper was freeing the passed strings for us. However that changed after the commit. So now we don't free any strings which results in memory leaks as reported upstream [1]: ==14265== 2,407 bytes in 1 blocks are definitely lost in loss record 1,457 of 1,550 ==14265== at 0x4C2845D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==14265== by 0x5C46624: xdr_string (in /usr/lib64/libc-2.17.so) ==14265== by 0xCFD9FCD: xdr_remote_nonnull_string (remote_protocol.c:31) ==14265== by 0xCFDC2C8: xdr_remote_domain_get_xml_desc_ret (remote_protocol.c:1617) ==14265== by 0xCFF0811: virNetMessageDecodePayload (virnetmessage.c:407) ==14265== by 0xCFE68FB: virNetClientProgramCall (virnetclientprogram.c:379) ==14265== by 0xCFBE8B1: callFull.isra.2 (remote_driver.c:6578) ==14265== by 0xCFC7F04: remoteDomainGetXMLDesc (remote_driver.c:6600) ==14265== by 0xCF8167C: virDomainGetXMLDesc (libvirt.c:4380) ==14265== by 0xCC2C4DF: libvirt_virDomainGetXMLDesc (libvirt.c:1141) ==14265== by 0x4F12B93: PyEval_EvalFrameEx (in /usr/lib64/libpython2.7.so.1.0) ==14265== by 0x4F141AC: PyEval_EvalCodeEx (in /usr/lib64/libpython2.7.so.1.0) The python documentation clearly advise us to call free() [2]. From an example in their docs: PyObject *res; char *buf = (char *) malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); ...Do some I/O operation involving buf... res = PyString_FromString(buf); free(buf); /* malloc'ed */ return res; Moreover, instead of using VIR_FREE() (which we are not exporting), I'll just go with bare free(). 1: https://www.redhat.com/archives/libvir-list/2014-September/msg00736.html 2: https://docs.python.org/2/c-api/memory.html 2014- 9- 2 Peter Krempa override: Fix two uninitialized variables in convertDomainStatsRecord py_record_domain and py_record_stats would be accessed uninitialized if an out-of-memory condition would happen in the first loop. Unlikely, but coverity complained. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1136354 2014- 9- 2 Pavel Hrdina libvirt-override: fix some build warnings Remove unused label 'cleanup' in 'libvirt_virConnectGetAllDomainStats' function and remove unused variable 'conn' in function 'libvirt_virDomainListGetStats'. 2014- 9- 2 Michal Privoznik Post-release version bump for new dev cycle 2014- 9- 1 Pavel Hrdina Implement API bindings for virDomainBlockCopy 2014- 9- 1 Pavel Hrdina API: Implement bindings for virDomainListGetStats Implement the function by returning a list of tuples instead the array of virDomainStatsRecords and store the typed parameters as dict. 2014- 9- 1 Peter Krempa API: Implement bindings for virConnectGetAllDomainStats Implement the function by returning a list of tuples instead the array of virDomainStatsRecords and store the typed parameters as dict. 2014- 9- 1 Peter Krempa API: Skip 'virDomainStatsRecordListFree' The new API function doesn't make sense to be exported in python. The bindings will return native types instead of the struct array. 2014- 9- 1 Pavel Hrdina generator: resolve one level of enum reference In the libvirt.h we have one enum defined by references from another enum and it leads in wrong order of definitons in python code. To prevent this we should resolve that references before we generate the python code. For now we have only one level of references so we will count with that in the generator but we should update it in the future to be more flexible. 2014- 8- 19 Mo Yuxiang build: Fix build warning on libvirt-python On compiling libvirt-python, we get such a warning: libvirt-qemu-override.c: In function ‘libvirt_qemu_virConnectDomainQemuMonitorEventRegister’: libvirt-qemu-override.c:304: warning: suggest explicit braces to avoid ambiguous ‘else’ Py_DECREF is a macro using if/else on older Python releases. The solution is to add braces. Python 2.7 and newer has the macro wrapped in a do { } while(0) block. 2014- 8- 11 Zhou Yimin Fix libvirt_longlongWrap returning a very large value If hypervisor is not Xen, the errs in struct _virDomainBlockStats will be -1. But in KVM when we call domain.blockStats(), errs is 18446744073709551615. To fix that, this patch has two changes: 1. Replace use of the PyLong_FromUnsignedLongLong with PyLong_FromLongLong in function libvirt_longlongWrap 2. If the paramemter of libvirt_longlongWrap is unsigned long long, use libvirt_ulonglongWrap instead because of above change. After this patch, errs is -1 which is consistent with virDomainBlockStats api. 2014- 8- 4 Eric Blake maint: document use of libvirt's run script Ever since libvirt commit 78c09530, it's easier to just use the run script. * README: Mention run script. 2014- 8- 4 Eric Blake Bump version to 1.2.8 for new dev cycle 2014- 7- 29 Jiri Denemark spec: Reorganize to satisfy buggy spectool spectool parses a specfile and strips everything but a preamble. However, if the first section is preceded by %if clause, it keeps it there which then makes rpmbuild complain about unmatched %if. Let's make the buggy tool happy by moving sections around so that the first one is not in any conditional. 2014- 7- 22 Martin Kletzander Bump version to 1.2.7 for new dev cycle 2014- 6- 27 Nehal J Wani Implement new virNetworkGetDHCPLeases API This API returns a list of DHCP leases for all network interfaces connected to the given virtual network or limited output just for one interface if mac is specified. Example Output: [{'iface': 'virbr3', 'ipaddr': '192.168.150.181', 'hostname': 'ubuntu14', 'expirytime': 1403737495L, 'prefix': 24, 'clientid': None, 'mac': '52:54:00:e8:73:eb', 'iaid': None, 'type': 0}, {'iface': 'virbr3', 'ipaddr': '2001:db8:ca2:2:1::bd', 'hostname': 'fedora20-test', 'expirytime': 1403738587L, 'prefix': 64, 'clientid': '00:04:b1:d8:86:42:e1:6a:aa:cf:d5:86:94:23:6f:94:04:cd', 'mac': '52:54:00:5b:40:98', 'iaid': '5980312', 'type': 1}] 2014- 6- 25 Eric Blake maint: document development against uninstalled libvirt Thanks to Dan's recent work in libvirt.git, it is much easier to develop against uninstalled libvirt. Mention how. * README: More details. 2014- 6- 25 Nehal J Wani build: use correct int conversion in NodeGetFreePages Commit c8ba859bc7 introduced a compiler warning while un-wrapping a python object to uint in libvirt_virNodeGetFreePages. On compiling libvirt-python against libvirt 1.2.6, we get: libvirt-override.c: In function ‘libvirt_virNodeGetFreePages’: libvirt-override.c:7811:9: warning: pointer targets in passing argument 2 of ‘libvirt_intUnwrap’ differ in signedness [-Wpointer-sign] if (libvirt_intUnwrap(tmp, &pages[i]) < 0) ^ In file included from libvirt-override.c:24:0: typewrappers.h:169:5: note: expected ‘int *’ but argument is of type ‘unsigned int *’ int libvirt_intUnwrap(PyObject *obj, int *val); ^ 2014- 6- 20 Michal Privoznik Implement new virNodeGetFreePages API The API expose information on host's free pages counts. For easier access, in python this API returns a dictionary such as: In [4]: conn.getFreePages([2048,1*1024*1024], -1, 5) Out[4]: {-1: {2048: 114, 1048576: 4}, 0: {2048: 3, 1048576: 1}, 1: {2048: 100, 1048576: 1}, 2: {2048: 10, 1048576: 1}, 3: {2048: 1, 1048576: 1}} At the top level of the returned dictionary there's a pair of and another dictionary that contains detailed information on each supported page size. The information then consists of fairs of and . 2014- 6- 19 Jason Andryuk Correct virDomainMigrateToURI3 definition dconnuri is a string, so update the definition to match. Without this, the generated python would fail when passed a string. 2014- 6- 18 Eric Blake build: provide wrapper makefile After years of finger training, I'm so used to 'make check' just working, that I lose quite a bit of time re-learning that in this project, it is spelled 'python setup.py build check'. A shim makefile bridges the gap. * Makefile: New file. 2014- 6- 18 Eric Blake event-test: add missing events Update the example to be able to trace all events. * examples/event-test.py (main): Match full list of domain events. (myDomainEventIOErrorReasonCallback) (myDomainEventControlErrorCallback) (myDomainEventBlockJobCallback, myDomainEventBlockJob2Callback) (blockJobTypeToString, blockJobStatusToString): New functions. 2014- 6- 18 Eric Blake blockjob: support new BLOCK_JOB_2 event Libvirt 1.2.6 is introducing a new block job event that passes disk information by target device rather than host file name. At the python level, we are just a passthrough, so we can reuse all the existing code and just wire up the new enum value. * libvirt-override-virConnect.py (_dispatchDomainEventBlockPullCallback): Rename... (_dispatchDomainEventBlockJobCallback): ...to this, and make generic to both events. * libvirt-override.c (libvirt_virConnectDomainEventBlockJobCallback): Match naming. (libvirt_virConnectDomainEventRegisterAny): Allow new registration. 2014- 6- 2 Martin Kletzander Bump version to 1.2.6 for new dev cycle 2014- 5- 27 Martin Kletzander fix leak in memoryStats with older python libvirt_virDomainMemoryStats() function creates a dictionary without any checks whether the additions were successful, whether the python objects were created and, most importantly, without decrementing the reference count on the objects added to the dictionary. This is somehow not an issue with current upstream versions, however with python 2.6 this exposes a leak in our bindings. The following patch works on both old and new CPython versions and is already used in other parts of the code, so it's also most straightforward. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1099860 2014- 5- 20 Michal Privoznik Implement virDomain{Get,Set}Time APIs While the setter can be generated automatically, the getter is not. However, it would be a lot easier if they both share the same logic: a python dictionary to represent the time: dict['seconds'] to represent seconds, and dict['nseconds'] to represent nanoseconds. 2014- 5- 16 Tomoki Sekiyama override: add virDomainFSFreeze and virDomainFSThaw API Add binding for the new virDomainFSFreeze and virDomainFSThaw functions added in libvirt 1.2.5. These require override since these take a list of mountpoints path string. The methods are named 'fsFreeze' and 'fsThaw'. 2014- 5- 5 Martin Kletzander Bump version to 1.2.5 for new dev cycle 2014- 4- 7 Laine Stump build: add BuildRequires for python-lxml and python3-lxml python-lxml is likely always already present anyway (due to so many packages being dependent on it), but at least on my F20 system, python3-lxml wasn't installed, leading to a failure of "python setup.py rpm" without an informative error message. 2014- 4- 7 Laine Stump increment version post-release As is now done with libvirt. git head will always have the version number of the expected *next* release. 2014- 4- 2 Daniel P. Berrange Fix nosetests usage with python3 Add RPM deps on python/python3-nose, make RPM build run the test suite and invoke nosetests using correct python binary 2014- 3- 31 Brian Rak Fix potential crash when setting partial cpu/memory/numa/interface limits on domains The number of parameters in new_params is not guaranteed to be the same as the number of parameters in params. Use the correct count when freeing new_params to avoid crashes. 2014- 3- 25 Cole Robinson setup.py: Allow running --help or clean without pkg-config If pkg-config isn't installed, or a too old libvirt, we can't even do 'python setup.py --help' without throwing an exception. Have the pkg-config checks and validation only throw an exception if being called from the 'build' step. https://bugzilla.redhat.com/show_bug.cgi?id=1074170 2014- 3- 25 Cole Robinson setup.py: Make have_libvirt_lxc a function This means we call it twice for a build operation, but I don't think that's a big deal. 2014- 3- 25 Cole Robinson setup.py: Move module list building to its own function Makes it a bit more clear what all that code is used for, rather than intermixing it with function definitions. Besides the comment additions, this is a no-op and just reindents the block, into a function. 2014- 3- 25 Cole Robinson setup.py: Remove unused import 2014- 3- 25 Eric Blake qemu: support arbitrary monitor events Wrap the new virConnectDomainQemuMonitorEventRegister function added in libvirt 1.2.3. This patch copies heavily from network events (commit 6ea5be0) and from event loop callbacks in libvirt-override.c, since in the libvirt_qemu module, we must expose top-level functions rather than class members. * generator.py (qemu_skip_function): Don't generate event code. (qemuBuildWrappers): Delay manual portion until after imports. * libvirt-qemu-override.py (qemuMonitorEventRegister) (qemuMonitorEventDeregister): New file. * libvirt-qemu-override.c (libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc) (libvirt_qemu_virConnectDomainQemuMonitorEventCallback) (libvirt_qemu_virConnectDomainQemuMonitorEventRegister) (libvirt_qemu_virConnectDomainQemuMonitorEventDeregister) (libvirt_qemu_lookupPythonFunc, getLibvirtQemuDictObject) (getLibvirtQemuModuleObject): New functions. 2014- 3- 25 Eric Blake event: fix domain reference bugs Noticed this bug while adding qemu monitor events; there's probably lots of other misuse of libvirt_virDomainPtrWrap, but for now I'm limiting the fix to all copied-and-pasted event callbacks, since I'm about to copy it again in the next patch. While at it, check for failure to extract the "conn" key from the opaque callback struct, and hoist that check to occur before we reach the point where it is harder to undo on failure (the network code was the only code that had it in the right place, but then it failed to restore thread state on failure). The graphics callback is still not clean; but incremental improvements are better than nothing. * libvirt-override.c (libvirt_virConnectDomainEventCallback) (libvirt_virConnectDomainEvetnLifecycleCallback) (libvirt_virConnectDomainEventGenericCallback) (libvirt_virConnectDomainEventRTCChangeCallback) (libvirt_virConnectDomainEventWatchdogCallback) (libvirt_virConnectDomainEventIOErrorCallback) (libvirt_virConnectDomainEventIOErrorReasonCallback) (libvirt_virConnectDomainEventGraphicsCallback) (libvirt_virConnectDomainEventBlockJobCallback) (libvirt_virConnectDomainEventDiskChangeCallback) (libvirt_virConnectDomainEventTrayChangeCallback) (libvirt_virConnectDomainEventPMWakeupCallback) (libvirt_virConnectDomainEventPMSuspendCallback) (libvirt_virConnectDomainEventBalloonChangeCallback) (libvirt_virConnectDomainEventPMSuspendDiskCallback) (libvirt_virConnectDomainEventDeviceRemovedCallback): Don't pass NULL to PyObject_CallMethod. (libvirt_virConnectNetworkEventLifecycleCallback): Likewise, and don't corrupt thread state. 2014- 3- 25 Martin Kletzander generator: Add virConnectDomainQemuMonitorEventCallback to skipped_types 2014- 3- 24 Eric Blake maint: balance {} usage Emacs gets lost when finding function boundaries when #ifdef sections do not have balanced {}. * libvirt-override.c (libvirt_PyString_Check): New define. (virPyDictToTypedParams): Avoid unbalanced {} across ifdef. 2014- 3- 24 Peter Krempa maint: Add ctags configuration file and ignore the output Add the config file to ease creation of tags to help navigation in editors. 2014- 3- 24 Eric Blake maint: set up preferred emacs settings Copy the relevant settings from libvirt.git, so that emacs users maintain the style previously used before the two repos split. * .dir-locals.el: New file. 2014- 3- 21 Eric Blake maint: ignore .pyc files * .gitignore: Add exemption. 2014- 3- 20 Cole Robinson override: Return NULL on python failure in getCPUModelNames Eric pointed this out on the last patch, but I pushed it before noticing his message. 2014- 3- 20 Cole Robinson override: GetCPUModelNames should return None on failure Right now, on failure, libvirt.py doesn't raise an exception and just returns -1 to the user. 2014- 3- 19 Daniel P. Berrange Add test for setting scheduler parameters Add a test setting scheduler parameters to validate the previous bugfix to strncpy of field names. 2014- 3- 19 Daniel P. Berrange Add support for running unit tests with nose Make the 'python setup.py test' able to run unit tests found under tests/ through the 'nosetests' command 2014- 3- 18 Michal Privoznik setPyVirTypedParameter: free whole return variable on error The @ret value is built in a loop. However, if in one iteration there's an error, we should free all the fields built so far. For instance, if there's an error and the previous item was type of VIR_TYPED_PARAM_STRING we definitely must free it. 2014- 3- 18 Michal Privoznik setPyVirTypedParameter: Copy full field name In the setPyVirTypedParameter we try to produce virTypedParameter array from a python dictionary. However, when copying field name into item in returned array, we use strncpy() as the field name is fixed length array. To determine its size we use sizeof() but mistakenly dereference it resulting in sizeof(char) which equals to 1 byte. Moreover, there's no need for using sizeof() when we have a global macro to tell us the length of the field name: VIR_TYPED_PARAM_FIELD_LENGTH. And since array is allocated using VIR_ALLOC() we are sure the memory is initially filled with zeros. Hence, there's no need to terminate string we've just copied into field name with '\0' character. It's there for sure too as we copy up to field length - 1. 2014- 3- 3 Daniel P. Berrange Post release version bump to 1.2.3 2014- 3- 2 Daniel Veillard Release of libvirt-python 1.2.2 2014- 2- 20 Martin Kletzander generator: Skip exporting only sentinels When enum type has '_LAST' in its name, but is not the last type in that enum, it's skipped even though it shouldn't be. Currently, this is the case for only VIR_NETWORK_UPDATE_COMMAND_ADD_LAST inside an enum virNetworkUpdateCommand. Also, since _LAST types can have other enums instead of values, that needs to be filtered out using a try-except when converting the value. 2014- 2- 13 Philipp Hahn Fix stream related spelling mistakes Consistent spelling of all-uppercase I/O. 2014- 2- 12 Eric Blake examples: demonstrate network events Commit 6ea5be0 added network event callback support, so we might as well demonstrate that it works by updating our example. * examples/event-test.py: Add network event, fix typos. 2014- 2- 4 Eric Blake maint: ignore editor files * .gitignore: Exclude emacs cruft. 2014- 2- 3 Eric Blake Merge tag 'v1.2.1' Release of libvirt-python-1.2.1 2014- 1- 23 Robie Basak Fix calling of virStreamSend method Change d40861 removed the 'len' argument from the virStreamSend C level wrapper, but forgot to remove it from the python level wrapper. Reported-by: Robie Basak 2014- 1- 16 Daniel Veillard Release of libvirt-python-1.2.1 2014- 1- 11 Doug Goldstein virStream.sendAll() fix raising an undeclared var The exception is raised from the variable 'e', which was undeclared in this context. Used code that is compatible with old and new Python versions. 2014- 1- 2 Doug Goldstein Add space after comma for consistency with code style 2013- 12- 30 Doug Goldstein define __GNUC_PREREQ macro before using it We brought over use of the __GNUC_PREREQ macro from libvirt but didn't bring over the definition of it. This brings over the macro from libvirt sources. 2013- 12- 12 Daniel P. Berrange Rewrite libvirt_charPtrUnwrap to work with Python 3.0->3.2 The PyUnicode_AsUTF8 method doesn't exist prior to Python 3.3. It is also somewhat inefficient, so rewrite it to use an intermediate PyBytes object. 2013- 12- 12 Daniel P. Berrange Add python3 to the automated build and RPM This updates autobuild.sh to test the python3 build process. The RPM specfile is changed to build a libvirt-python3 RPM on Fedora > 18 2013- 12- 11 Daniel P. Berrange Skip network event callbacks in sanity test 2013- 12- 11 Daniel P. Berrange Fix return type in override method for virStreamRecv The virStreamRecv override returns a PyObject not an int 2013- 12- 11 Daniel P. Berrange sanitytest: remove use of string.lower() Call lower() directly on the string object instance, not the class 2013- 12- 11 Daniel P. Berrange sanitytest: Fix broken comparison between int and string Python2 was forgiving of a comparison between an int and string but Python3 gets very upset. 2013- 12- 11 Daniel P. Berrange override: Switch virStreamSend wrapper to use libvirt_charPtrSizeUnwrap Instead of using a 'z#i' format string to receive byte array, use 'O' and then libvirt_charPtrSizeUnwrap. This lets us hide the Python 3 vs 2 differences in typewrappers.c 2013- 12- 11 Daniel P. Berrange override: Conditionalize use of PyString_Check and PyInt_Check The PyString and PyInt classes are gone in Python 3, so we must conditionalize their use to be Python 2 only. 2013- 12- 11 Daniel P. Berrange typewrappers: PyInt/PyLong merge for Python3 In Python3 the PyInt / PyLong types have merged into a single PyLong type. Conditionalize the use of PyInt to Python 2 only 2013- 12- 11 Daniel P. Berrange typewrappers: Replace use of PyString class Replace use of PyString with either PyBytes or PyUnicode. The former is used for buffers with explicit sizes, which are used by APIs processing raw bytes. 2013- 12- 11 Daniel P. Berrange override: Replace PyInt_AsLong with helper Replace use of the PyInt_AsLong libvirt_intUnwrap helper. This isolates the need for Python3 specific code in one place 2013- 12- 11 Daniel P. Berrange override: Replace Py{Int,Long}_FromLong with helpers Replace use of the PyInt_FromLong and PyLong_FromLongLong with libvirt_{int,uint,longlong,ulonglong}Wrap helpers. This isolates the need for Python3 specific code in one place. 2013- 12- 11 Daniel P. Berrange override: Replace PyString_AsString with libvirt_charPtrUnwrap Replace calls to PyString_AsString with the helper method libvirt_charPtrUnwrap. This isolates the code that will change in Python3. In making this change, all callers now have responsibility for free'ing the string. 2013- 12- 11 Daniel P. Berrange override: Replace PyString_FromString with libvirt_constcharPtrWrap Make use of libvirt_constcharPtrWrap in all override code, to match generated code. This will isolate Python3 specific changes in one place. 2013- 12- 11 Daniel P. Berrange sanitytest: Fix libvirtError class handling for Python 2.4 The Exception class hiearchy in Python 2.4 reports different data types than in later Python versions. As a result the type(libvirt.libvirtError) does not return 'type'. We just special case handling of this class. 2013- 12- 11 Daniel P. Berrange override: Fix native module registration to work with Python3 The way native modules are registered has completely changed, so the code must be #ifdef'd for Python2 & 3 2013- 12- 11 Daniel P. Berrange examples: Ensure we write bytes to the self-pipe Strings in python3 default to unicode, so when writing to the self-pipe we must be sure to use bytes by calling the encode() method. 2013- 12- 11 Daniel P. Berrange examples: Invoke print("...") instead of print "..." The 'print' method must be called as a function in python3, ie with brackets. 2013- 12- 11 Daniel P. Berrange Don't free passed in args in libvirt_charPtrWrap / libvirt_charPtrSizeWrap Functions should not make assumptions about the memory management callers use for parameters 2013- 12- 11 Cédric Bosdonnat Added python binding for the new network events API The new network events code requires manual binding code to be written. 2013- 12- 9 Doug Goldstein test: Invoke print("...") instead of print "..." The 'print' statement no longer exists in Python 3 and now must be called as a function. This is compatible down to Python 2.4 as we are not using any special syntax of the function. 2013- 12- 9 Doug Goldstein override: Fix exception handling syntax Python 3 no longer accepts 'except Exception, e:' as valid while Python 2.4 does not accept the new syntax 'except Exception as e:' so this uses a fall back method that is compatible with both. 2013- 12- 9 Daniel P. Berrange generator: Sort enums and functions when generating code To assist in diff comparisons between code generated with different versions of Python, do an explicit sort of all functions and enums. 2013- 12- 9 Daniel P. Berrange generator: Remove use of string.replace and string.find functions Call the 'replace' and 'find' functions directly on the string variables, instead of via the 'string' module. Python3 only accepts the latter syntax 2013- 12- 9 Daniel P. Berrange generator: Update to use sort() 'key' param The sort() method previously took either a comparator function or a key function. Only the latter is supported in Python3. 2013- 12- 9 Daniel P. Berrange generator: Remove use of 'has_key' function The code 'XXX.has_key(YYYY)' must be changed to be of the form 'YYY in XXXX' which works in Python2 and 3 As an added complication, if 'YYY in XXX' is used against an object overriding the '__getitem__' method it does not work in Python 2.4. Instead we must use 'YYY in XXX.keys()' 2013- 12- 5 Doug Goldstein Update exception catching in generated code Use a syntax for exception handling that works in both Python 2 and Python 3. The new syntax is 'except Exception as e:' but this does not work in older Pythons so we use the most compatible way by just catching the exception and getting the type and the exception value after the fact. 2013- 12- 5 Doug Goldstein generator: Support exceptions in Python 2 and 3 Use a syntax for exception handling that works in both Python 2 and Python 3 2013- 12- 5 Doug Goldstein setup: Drop unused exception variable Drop the unused exception variable in setup.py. This has the benefit of dropping syntax that is not valid with Python 3. 2013- 12- 4 Daniel P. Berrange generator: Cast iterators to a list() explicitly In python3 various methods list 'dict.keys()' do not return a list, so we must explicitly cast the result. 2013- 12- 4 Daniel P. Berrange Revert "Optimize callback lookup in event handlers" This reverts commit 084729e26905f574b8c057cc4c732b1b6ce852d3. The PyImport_ImportModuleNoBlock method does not exist in python 2.4 2013- 12- 4 Daniel P. Berrange Revert accidental change to exception handling syntax The previous commit changed the exception handling syntax to use 'as' instead of a ','. This doesn't work with python 2.4 2013- 12- 4 Daniel P. Berrange generator: Invoke print("...") instead of print "..." The 'print' method must be called as a function in python3, ie with brackets. 2013- 12- 4 Daniel P. Berrange generator: Remove string.lower(XXX) with XXX.lower() In python3 the string.lower() method doesn't exist, the lower() function can only be executed against a string variable directly. Python2 supported both approaches so this change is compatible 2013- 12- 4 Daniel P. Berrange generator: Don't use 'list' as a variable name In python3 if we use 'list' as a variable name it causes it to hide the corresponding 'list()' function from the entire function that holds the variable. 2013- 12- 4 Daniel P. Berrange Optimize callback lookup in event handlers The event handler code currently invokes PyImport_ImportModule which is very heavyweight. This is not in fact required, since we know the libvirt module has already been imported. We can thus use PyImport_ImportModuleNoBlock and do away with the global variables caching the imported module reference. 2013- 12- 4 Daniel P. Berrange Fix use of virDomainEventRegister in python bindings If an app used the virDomainEventRegister binding instead of the virDomainEventRegisterAny binding, it would never have its callback invoked. This is because the code for dispatching from the C libvirt_virConnectDomainEventCallback method was totally fubar. If DEBUG macro was set in the python build the error would become visible "libvirt_virConnectDomainEventCallback dom_class is not a class!" The code in libvirt_virConnectDomainEventCallback was inexplicably complex and has apparently never worked. The fix is to write it the same way as the other callback handlers. 2013- 12- 3 Doug Goldstein setup: Use user requested python binary When setup.py is kicked off with a python interpreter other than the system 'python', (e.g. python2.7 setup.py build) the build process would switch to 'python' and not use python2.7 as requested by the user. We should always respect the user requested python interpreter and use it. 2013- 11- 28 Daniel P. Berrange Improve quality of sanitytest check Validate that every public API method is mapped into the python and that every python method has a sane C API. 2013- 11- 28 Daniel P. Berrange Skip copying manually written python for C APIs which don't exist If the libvirt-override-virXXXX.py file has methods which call C APIs that don't exist in the version of libvirt built against we need to skip copying their code. eg for 0.9.13 libvirt we should not copy the 'listAllDomains' method. The way this works is that it breaks the override file into individual methods by looking for ' def '. It then collects the contents until the next method start, whereupon it looks for a libvirtmod.XXXXXX API call. It checks if the XXXXX part is present in the XML description we have, and if not, it discards the entire method. 2013- 11- 28 Daniel P. Berrange Fix misc RPM specfile flaws Fix the RPM summary line, add placeholder %changelog tag, make %setup quiet, add Url: tag and filter out bogus provides and add example programs as docs. 2013- 11- 28 Daniel P. Berrange Fix code for avoiding overrides of non-existant functions When reading/writing a global variable from inside a method it must be declared as a global, otherwise a local variable by the same name will be used. Special case the virConnectListDomainsID method which is bizarrely renamed for no obvious reason. 2013- 11- 28 Daniel P. Berrange Deal with old filenames for events/error functions Older libvirt has files named 'events' and 'virterror' rather than 'virevent' and 'virerror'. This is visible in the API XML files. We must look for both names to ensure we don't lose generation of methods with older versions of libvirt. 2013- 11- 27 Daniel P. Berrange Add missing binding of security model/label APIs The virNodeGetSecurityModel, virDomainGetSecurityLabel and virDomainGetSecurityLabelList methods were disabled in the python binding for inexplicable reasons. 2013- 11- 27 Daniel P. Berrange Avoid generating the methods in multiple classes The python code generator tries to figure out what class a method should be in by looking at the list of arguments for any which are object types. Unfortunately missing break statements meant that methods which have multiple object arguments (eg migrate as a virDomainPtr followed by a virConnectPtr) got added to multiple classes. The following incorrect methods are removed by this change virStream.download (dup of virStorageVol.download) virStream.screenshot (dup of virDomain.screenshot) virStream.upload (dup of virStorageVol.upload) virConnect.migrate (dup of virDomain.migrate) virConnect.migrate2 (dup of virDomain.migrate2) virConnect.migrate3 (dup of virDomain.migrate3) virConnect.migrateToURI3 (dup of virDomain.migrateToURI3) 2013- 11- 27 Daniel P. Berrange Make block pull event dispatcher private The method dispatchDomainEventBlockPullCallback which is used internally to dispatch block pull events to the python application code was missing the leading '_', to denote that it was private. All other event callback helpers have a leading '_'. No application should have been using this so it is justifiable to rename it. 2013- 11- 27 Daniel P. Berrange Don't include virDomainSnapshotRef in python API The reference counting API is for internal use only. Attempts to use it from python application code will cause havoc. 2013- 11- 26 Doug Goldstein Call virGetLastError from mod rather than py wrapper All other code always calls the methods from the mod rather than using the python wrapper so this matches the state of all other callers. 2013- 11- 26 Don Dugger Return right error code for baselineCPU This Python interface code is returning a -1 on errors for the `baselineCPU' API. Since this API is supposed to return a pointer the error return value should really be VIR_PY_NONE. 2013- 11- 26 Martin Kletzander Make setup.py executable 2013- 11- 26 Daniel P. Berrange Update README file contents and add HACKING file The previous README file from the python code is more like a HACKING file. Rename it and update the content. Then add a basic README file 2013- 11- 25 Eric Blake maint: next release is 1.2.0 No other hits for: git grep '1\.1\.5' * libvirt-utils.h: Fix comment. 2013- 11- 22 Daniel P. Berrange Ensure API overrides only used if API exists Entries in the -overrides.xml files should only be recorded if the API also exists in the main API XML file. 2013- 11- 22 Daniel P. Berrange Relax min required libvirt to version 0.9.11 2013- 11- 22 Doug Goldstein virConnectGetCPUModelNames API appeared in 1.1.3 2013- 11- 22 Daniel P. Berrange VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED appeared in 1.1.1 2013- 11- 22 Doug Goldstein virDomainCreateXMLWithFiles and virDomainCreateWithFiles APIs appeared in 1.1.1 virDomainCreateXMLWithFiles() and virDomainCreateWithFiles() were not added to libvirt until 1.1.1 2013- 11- 22 Doug Goldstein virDomainMigrate3 and virDomainMigrateToURI3 appeared in 1.1.0 The functions virDomainMigrate3 and virDomainMigrateToURI3 were not added to libvirt until v1.1.0. 2013- 11- 22 Doug Goldstein virTypedParams* API appeared in 1.0.2 and used in 1.1.0 When building against versions of libvirt prior to 1.0.2, we can not provide wrappers for virTypedParams* APIs. In addition we don't need to have the helper APIs until 1.1.0 when the first API we wrap starts to use them. 2013- 11- 22 Doug Goldstein virDomainMigrateGetCompressionCache API appeared in 1.0.3 2013- 11- 22 Doug Goldstein virDomainGetJobStats API appeared in 1.0.3 2013- 11- 22 Doug Goldstein virNodeGetCPUMap API appeared in 1.0.0 2013- 11- 22 Daniel P. Berrange VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK appeared in 1.0.0 2013- 11- 22 Doug Goldstein virStoragePoolListAllVolumes API appeared in 0.10.2 2013- 11- 22 Doug Goldstein virNode{Get,Set}MemoryParameters API appeared in 0.10.2 2013- 11- 22 Doug Goldstein virConnectListAll* APIs appeared in 0.10.2 2013- 11- 22 Daniel P. Berrange virDomainQemuAgentCommand appeared in 0.10.0 2013- 11- 22 Doug Goldstein virDomainPinEmulator and virDomainGetEmulatorPinInfo APIs appeared in 0.10.0 2013- 11- 22 Daniel P. Berrange VIR_DOMAIN_EVENT_ID_BALLOON_CHANGED appeared in 0.10.0 2013- 11- 22 Doug Goldstein virConnect{Unr,R}egisterCloseCallback API appeared in 0.10.0 2013- 11- 22 Doug Goldstein virDomainSnapshotListAllChildren API appeared in 0.9.13 2013- 11- 22 Doug Goldstein virConnectListAllDomains API appeared in 0.9.13 2013- 11- 22 Doug Goldstein virDomainListAllSnapshots API appeared in 0.9.13 2013- 11- 22 Doug Goldstein Don't build LXC module when building less than 1.0.2 The functions that the LXC module wraps did not appear until 1.0.2 so we can't build the module unless we're building against 1.0.2 or newer. 2013- 11- 22 Doug Goldstein Create array of modules to be built Create an array of modules to be built to allow for flexibility to enable or disable some modules in the future and allow for additional modules to be added easily 2013- 11- 22 Doug Goldstein Break generator.py to be called per module Since we don't always want to build all the modules, and there might be more modules added in the future but we want to retain backwards compatibility with older libvirts, change generator.py to be called once per module instead of with all modules at once. 2013- 11- 22 Daniel P. Berrange Setup distutils build system Create a setup.py for building libvirt python code and add supporting files 2013- 11- 22 Daniel P. Berrange Add execute permission for sanitytest.py 2013- 11- 22 Daniel P. Berrange Add build/ to python module path for sanitytest.py The generated libvirt.py modules will be in the build/ directory, so santitytest.py must use that directory. 2013- 11- 22 Doug Goldstein Import some virTypedParams* APIs from libvirt virTypedParamsClear() and virTypedParamsFree() were introduced in libvirt 1.0.2. In an effort to keep the code clean bring these two functions to libvirt-python if we're building against a version of libvirt that's older than 1.0.2 2013- 11- 22 Doug Goldstein Import LIBVIR_CHECK_VERSION macro from libvirt Add LIBVIR_CHECK_VERSION from libvirt upstream so that we can check the version of the library we are compiling against and support a range of libvirt versions. The macro was added to libvirt in 1.2.0 so we must provide it if its not defined. 2013- 11- 22 Daniel P. Berrange Import VIR_FORCE_CLOSE macro from libvirt Import the macro for safely closing file descriptors 2013- 11- 22 Daniel P. Berrange Remove use of virStrcpyStatic 2013- 11- 22 Daniel P. Berrange Import VIR_ALLOC / VIR_ALLOC_N / VIR_REALLOC_N functions Import the libvirt memory allocation functions, stripping the OOM testing and error reporting pieces. 2013- 11- 22 Daniel P. Berrange Import code annotation macros from libvirt Import ATTRIBUTE_RETURN_CHECK, ATTRIBUTE_UNUSED & ATTRIBUTE_NONNULL macros 2013- 11- 22 Daniel P. Berrange Import gnulib's ignore_value macro 2013- 11- 22 Daniel P. Berrange Import gnulib's xalloc_oversized macro 2013- 11- 22 Daniel P. Berrange Add decl of MIN macro 2013- 11- 22 Daniel P. Berrange Import STREQ macro from libvirt 2013- 11- 22 Daniel P. Berrange Update header file includes We're no longer using automake, so files are not required. Also remove of all libvirt internal util header files. Reference generated header files in build/ subdir. 2013- 11- 22 Daniel P. Berrange Update generator for new code layout Change the generator.py to - Take XML API file names on command line - Generate data in build/ directory instead of cwd 2013- 11- 22 Daniel P. Berrange Remove obsolete Makefile.am We are no longer using automake, so Makefile.am is obsolete 2013- 11- 22 Daniel P. Berrange Move python example programs into python/examples/ subdirectory 2013- 11- 22 Daniel P. Berrange Mostly revert "python: remove virConnectGetCPUModelNames from globals" This reverts commit 6b90d7428d72e92db292a9228c44701bfd5003c9. The original problem was that libvirt_virConnectGetCPUModelNames was listed twice in the exports table, once automatically from the generator and once from the manual override. We merely needed to list it in the skip_impl list, and not delete the manually written code entirely. 2013- 11- 21 Doug Goldstein python: remove virConnectGetCPUModelNames from globals Commit de51dc9c9aed0e615c8b301cccb89f4859324eb0 primarily added virConnectGetCPUModelNames as libvirt.getCPUModelNames(conn, arch) instead of libvirt.virConnect.getCPUModelNames(arch) so revert the code that does the former while leaving the code that does the later. This is the rest of the patch that was ACK'd by Dan but I committed only the partial patch in 6a8b8ae. 2013- 11- 21 Doug Goldstein python: remove virConnectGetCPUModelNames from globals Commit de51dc9c9aed0e615c8b301cccb89f4859324eb0 primarily added virConnectGetCPUModelNames as libvirt.getCPUModelNames(conn, arch) instead of libvirt.virConnect.getCPUModelNames(arch) so revert the code that does the former while leaving the code that does the later. 2013- 11- 20 Eric Blake maint: fix comma style issues: python Most of our code base uses space after comma but not before; fix the remaining uses before adding a syntax check. * python/libvirt-override.c: Consistently use commas. 2013- 11- 19 Doug Goldstein Add missing break to switch-case block The case label for VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED did not have its own break statement but relied on falling through which we probably don't want. 2013- 10- 22 Marian Neagul python: Fix Create*WithFiles filefd passing Commit d76227be added functions virDomainCreateWithFiles and virDomainCreateXMLWithFiles, but there was a little piece missing in python bindings. This patch fixes proper passing of file descriptors in the overwrites of these functions. 2013- 10- 21 Daniel P. Berrange Don't link virt-login-shell against libvirt.so (CVE-2013-4400) The libvirt.so library has far too many library deps to allow linking against it from setuid programs. Those libraries can do stuff in __attribute__((constructor) functions which is not setuid safe. The virt-login-shell needs to link directly against individual files that it uses, with all library deps turned off except for libxml2 and libselinux. Create a libvirt-setuid-rpc-client.la library which is linked to by virt-login-shell. A config-post.h file allows this library to disable all external deps except libselinux and libxml2. 2013- 10- 14 Eric Blake maint: avoid 'const fooPtr' in python bindings 'const fooPtr' is the same as 'foo * const' (the pointer won't change, but it's contents can). But in general, if an interface is trying to be const-correct, it should be using 'const foo *' (the pointer is to data that can't be changed). Fix up offenders in the python bindings. * python/generator.py (py_types): Drop useless conversions. * python/libvirt-override.c (getPyVirTypedParameter) (setPyVirTypedParameter): Use intended type. 2013- 9- 30 Michal Privoznik python: Document virNodeGetInfo bug The memory size in virNodeGetInfo python API binding is reported in MiB instead of KiB (like we have in C struct). However, there already might be applications out there relying on this inconsistence so we can't simply fix it. Document this sad fact as known bug. 2013- 9- 23 Giuseppe Scrivano python: add bindings for virConnectGetCPUModelNames 2013- 9- 23 Giuseppe Scrivano libvirt: add new public API virConnectGetCPUModelNames The new function virConnectGetCPUModelNames allows to retrieve the list of CPU models known by the hypervisor for a specific architecture. 2013- 9- 20 Daniel P. Berrange Fix potential use of uninitialized value in virDomainGetVcpuPinInfo The virDomainGetVcpuPinInfo python wrapper had a potential use of uninitialized values 2013- 9- 10 Oskari Saarenmaa docs, comments: minor typo fixes 2013- 9- 4 Eric Blake build: enforce makefile conditional style Automake has builtin support to prevent botched conditional nesting, but only if you use: if FOO else !FOO endif !FOO An example error message when using the wrong name: daemon/Makefile.am:378: error: else reminder (LIBVIRT_INIT_SCRIPT_SYSTEMD_TRUE) incompatible with current conditional: LIBVIRT_INIT_SCRIPT_SYSTEMD_FALSE daemon/Makefile.am:381: error: endif reminder (LIBVIRT_INIT_SCRIPT_SYSTEMD_TRUE) incompatible with current conditional: LIBVIRT_INIT_SCRIPT_SYSTEMD_FALSE As our makefiles tend to have quite a bit of nested conditionals, it's better to take advantage of the benefits of the build system double-checking that our conditionals are well-nested, but that requires a syntax check to enforce our usage style. Alas, unlike C preprocessor and spec files, we can't use indentation to make it easier to see how deeply nesting goes. * cfg.mk (sc_makefile_conditionals): New rule. * daemon/Makefile.am: Enforce the style. * gnulib/tests/Makefile.am: Likewise. * python/Makefile.am: Likewise. * src/Makefile.am: Likewise. * tests/Makefile.am: Likewise. * tools/Makefile.am: Likewise. 2013- 9- 3 Ján Tomko Fix leaks in python bindings https://bugzilla.redhat.com/show_bug.cgi?id=1003828 2013- 8- 29 Guan Qiang python: Fix a PyList usage mistake Fix PyList usage mistake in Function libvirt_lxc_virDomainLxcOpenNamespace. https://bugzilla.redhat.com/show_bug.cgi?id=1002383 2013- 8- 23 Claudio Bley python: simplify complicated conditional assignment 2013- 8- 23 Claudio Bley Test for object identity when checking for None in Python Consistently use "is" or "is not" to compare variables to None, because doing so is preferrable, as per PEP 8 (http://www.python.org/dev/peps/pep-0008/#programming-recommendations): > Comparisons to singletons like None should always be done with is or > is not, never the equality operators. 2013- 8- 22 Guido Günther python: Use RELRO_LDFLAGS and NO_INDIRECT_LDFLAGS A readonly GOT and detecting indirect linkage is useful here too. 2013- 7- 30 Daniel P. Berrange Delete obsolete / unused python test files The python/tests directory contains a number of so called "tests" for the python API. These are all hardcoded to look for Xen and cannot be run in any automated fashion, and no one is ever manually running them. Given that they don't meaningully contribute to the test coverage, delete them. For some reason these tests were also copied into the filesystem as part of 'make install'. The change to the RPM in commit 3347a4203278ec93d7b0ceb88b5ed10e4f14765c caused a build failure, since it removed the code which deleted these installed tests. 2013- 7- 29 Cole Robinson python: Drop TODO File hasn't been really touched for 7 years. And with recent rawhide changes it contributed to an RPM build failure. Let's drop it. This also removes installation of a libvirt-python doc dir, so drop handling of it from the RPM spec. 2013- 7- 19 Eric Blake maint: split long lines in Makefiles Makefiles are another easy file to enforce line limits. Mostly straightforward; interesting tricks worth noting: src/Makefile.am: $(confdir) was already defined, use it in more places tests/Makefile.am: path_add and VG required some interesting compression * cfg.mk (sc_prohibit_long_lines): Add another test. * Makefile.am: Fix offenders. * daemon/Makefile.am: Likewise. * docs/Makefile.am: Likewise. * python/Makefile.am: Likewise. * src/Makefile.am: Likewise. * tests/Makefile.am: Likewise. 2013- 7- 18 Jiri Denemark Add VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED event 2013- 7- 18 Daniel P. Berrange Introduce new domain create APIs to pass pre-opened FDs to LXC With container based virt, it is useful to be able to pass pre-opened file descriptors to the container init process. This allows for containers to be auto-activated from incoming socket connections, passing the active socket into the container. To do this, introduce a pair of new APIs, virDomainCreateXMLWithFiles and virDomainCreateWithFiles, which accept an array of file descriptors. For the LXC driver, UNIX file descriptor passing will be used to send them to libvirtd, which will them pass them down to libvirt_lxc, which will then pass them to the container init process. This will only be implemented for LXC right now, but the design is generic enough it could work with other hypervisors, hence I suggest adding this to libvirt.so, rather than libvirt-lxc.so 2013- 7- 15 Guannan Ren python: return dictionary without value in case of no blockjob Currently, when there is no blockjob, dom.blockJobInfo('vda') still reports error because it doesn't distinguish return value 0 from -1. libvirt.libvirtError: virDomainGetBlockJobInfo() failed virDomainGetBlockJobInfo() API return value: -1 in case of failure, 0 when nothing found, 1 found. And use PyDict_SetItemString instead of PyDict_SetItem when key is of string type. PyDict_SetItemString increments key/value reference count, so call Py_DECREF() for value. For key, we don't need to do this, because PyDict_SetItemString will handle it internally. 2013- 7- 10 Daniel P. Berrange Convert 'int i' to 'size_t i' in python/ files Convert the type of loop iterators named 'i', 'j', k', 'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or 'unsigned int', also santizing 'ii', 'jj', 'kk' to use the normal 'i', 'j', 'k' naming 2013- 7- 10 Michal Privoznik viralloc: Report OOM error on failure Similarly to VIR_STRDUP, we want the OOM error to be reported in VIR_ALLOC and friends. 2013- 6- 24 Jiri Denemark python: Add bindings for extensible migration APIs The patch implements wrappers for virDomainMigrate3 and virDomainMigrateToURI3. 2013- 6- 24 Jiri Denemark Extensible migration APIs This patch introduces two new APIs virDomainMigrate3 and virDomainMigrateToURI3 that may be used in place of their older variants. These new APIs take optional migration parameters (such as bandwidth, domain XML, ...) in an array of virTypedParameters, which makes adding new parameters easier as there's no need to introduce new APIs whenever a new migration parameter needs to be added. Both APIs are backward compatible and will automatically use older migration calls in case the new calls are not supported as long as the typed parameters array does not contain any parameter which was not supported by the older calls. 2013- 5- 28 Eric Blake syntax: prefer space after semicolon in for loop I noticed several unusual spacings in for loops, and decided to fix them up. See the next commit for the syntax check that found all of these. * examples/domsuspend/suspend.c (main): Fix spacing. * python/libvirt-override.c: Likewise. * src/conf/interface_conf.c: Likewise. * src/security/virt-aa-helper.c: Likewise. * src/util/virconf.c: Likewise. * src/util/virhook.c: Likewise. * src/util/virlog.c: Likewise. * src/util/virsocketaddr.c: Likewise. * src/util/virsysinfo.c: Likewise. * src/util/viruuid.c: Likewise. * src/vbox/vbox_tmpl.c: Likewise. * src/xen/xen_hypervisor.c: Likewise. * tools/virsh-domain-monitor.c (vshDomainStateToString): Drop default case, to let compiler check us. * tools/virsh-domain.c (vshDomainVcpuStateToString): Likewise. 2013- 5- 21 Osier Yang python: Remove the whitespace before ";" 2013- 5- 20 Eric Blake maint: use LGPL correctly Several files called out COPYING or COPYING.LIB instead of using the normal boilerplate. It's especially important that we don't call out COPYING from an LGPL file, since COPYING is traditionally used for the GPL. A few files were lacking copyright altogether. * src/rpc/gendispatch.pl: Add missing copyright. * Makefile.nonreentrant: Likewise. * src/check-symfile.pl: Likewise. * src/check-symsorting.pl: Likewise. * src/driver.h: Likewise. * src/internal.h: Likewise. * tools/libvirt-guests.sh.in: Likewise. * tools/virt-pki-validate.in: Mention copyright in comment, not just code. * tools/virt-sanlock-cleanup.in: Likewise. * src/rpc/genprotocol.pl: Spell out license terms. * src/xen/xend_internal.h: Likewise. * src/xen/xend_internal.c: Likewise. * Makefile.am: Likewise. * daemon/Makefile.am: Likewise. * docs/Makefile.am: Likewise. * docs/schemas/Makefile.am: Likewise. * examples/apparmor/Makefile.am: Likewise. * examples/domain-events/events-c/Makefile.am: Likewise. * examples/dominfo/Makefile.am: Likewise. * examples/domsuspend/Makefile.am: Likewise. * examples/hellolibvirt/Makefile.am: Likewise. * examples/openauth/Makefile.am: Likewise. * examples/python/Makefile.am: Likewise. * examples/systemtap/Makefile.am: Likewise. * examples/xml/nwfilter/Makefile.am: Likewise. * gnulib/lib/Makefile.am: Likewise. * gnulib/tests/Makefile.am: Likewise. * include/Makefile.am: Likewise. * include/libvirt/Makefile.am: Likewise. * python/Makefile.am: Likewise. * python/tests/Makefile.am: Likewise. * src/Makefile.am: Likewise. * tests/Makefile.am: Likewise. * tools/Makefile.am: Likewise. * configure.ac: Likewise. 2013- 5- 9 Daniel P. Berrange Fix build of python bindings on Python 2.4 The PyDict_Next method on Python <= 2.4 used 'int' instead of "Py_ssize_t" for the 'pos' parameter 2013- 5- 6 Eric Blake build: clean up stray files found by 'make distcheck' 'make distcheck' complained: ERROR: files left in build directory after distclean: ./python/libvirt.pyc ./tests/commandhelper.log Problems introduced in commits f015495 and 25ea8e4 (both v1.0.3). * tests/commandtest.c (test21): Check (and clean) log file. * tests/commanddata/test21.log: New file. * python/Makefile.am (CLEANFILES): Clean up compiled python files. 2013- 5- 2 Eric Blake build: always include sanitytest in tarball The libvirt 1.0.5 tarball is missing a file which renders 'make check' broken; first reported on list by Guido Günther. * python/Makefile.am (EXTRA_DIST): Hoist sanitytest.py out of HAVE_PYTHON conditional. 2013- 5- 2 Michal Privoznik virutil: Move string related functions to virstring.c The source code base needs to be adapted as well. Some files include virutil.h just for the string related functions (here, the include is substituted to match the new file), some include virutil.h without any need (here, the include is removed), and some require both. 2013- 4- 19 Eric Blake docs: fix usage of 'onto' http://www.uhv.edu/ac/newsletters/writing/grammartip2009.07.01.htm (and several other sites) give hints that 'onto' is best used if you can also add 'up' just before it and still make sense. In many cases in the code base, we really want the two-word form, or even a simplification to just 'on' or 'to'. * docs/hacking.html.in: Use correct 'on to'. * python/libvirt-override.c: Likewise. * src/lxc/lxc_controller.c: Likewise. * src/util/virpci.c: Likewise. * daemon/THREADS.txt: Use simpler 'on'. * docs/formatdomain.html.in: Better usage. * docs/internals/rpc.html.in: Likewise. * src/conf/domain_event.c: Likewise. * src/rpc/virnetclient.c: Likewise. * tests/qemumonitortestutils.c: Likewise. * HACKING: Regenerate. 2013- 4- 18 Osier Yang syntax-check: Only allows to include public headers in external tools With this patch, include public headers in "" form is only allowed for "internal.h". And only the external tools (examples|tools|python |include/libvirt) can include the public headers in <> form. 2013- 3- 26 Guannan Ren python: set default value to optional arguments When prefixing with string (optional) or optional in the description of arguments to libvirt C APIs, in python, these arguments will be set as optional arugments, for example: * virDomainSaveFlags: * @domain: a domain object * @to: path for the output file * @dxml: (optional) XML config for adjusting guest xml used on restore * @flags: bitwise-OR of virDomainSaveRestoreFlags the corresponding python APIs is restoreFlags(self, frm, dxml=None, flags=0) The following python APIs are changed to: blockCommit(self, disk, base, top, bandwidth=0, flags=0) blockPull(self, disk, bandwidth=0, flags=0) blockRebase(self, disk, base, bandwidth=0, flags=0) migrate(self, dconn, flags=0, dname=None, uri=None, bandwidth=0) migrate2(self, dconn, dxml=None, flags=0, dname=None, uri=None, bandwidth=0) migrateToURI(self, duri, flags=0, dname=None, bandwidth=0) migrateToURI2(self, dconnuri=None, miguri=None, dxml=None, flags=0, \ dname=None, bandwidth=0) saveFlags(self, to, dxml=None, flags=0) migrate(self, domain, flags=0, dname=None, uri=None, bandwidth=0) migrate2(self, domain, dxml=None, flags=0, dname=None, uri=None, bandwidth=0) restoreFlags(self, frm, dxml=None, flags=0) 2013- 3- 22 Guannan Ren python:remove semicolon in python code This breaked "make syntax-check" testing Pushed under trivial rule 2013- 3- 22 Guannan Ren make: regenerate bindings when .py changes 2013- 3- 22 Guannan Ren python: treat flags as default argument with value 0 The following four functions have not changed because default arguments have to come after positional arguments. Changing them will break the the binding APIs. migrate(self, dconn, flags, dname, uri, bandwidth): migrate2(self, dconn, dxml, flags, dname, uri, bandwidth): migrateToURI(self, duri, flags, dname, bandwidth): migrateToURI2(self, dconnuri, miguri, dxml, flags, dname, bandwidth): 2013- 3- 21 Peter Krempa python: Fix emulatorpin API bindings The addition of emulator pinning APIs didn't think of doing the right job with python APIs for them. The default generator produced unusable code for this. This patch switches to proper code as in the case of domain Vcpu pining. This change can be classified as a python API-breaker but in the state the code was before I doubt anyone was able to use it successfully. 2013- 3- 21 Guannan Ren python: fix bindings that don't raise an exception For example: >>> dom.memoryStats() libvir: QEMU Driver error : Requested operation is not valid:\ domain is not running There are six such python API functions like so. The root reason is that generator.py script checks the type of return value of a python stub function defined in libvirt-api.xml or libvirt-override-api.xml to see whether to add the raise clause or not in python wrapper code in libvirt.py. The type of return value is supposed to be C types. For those stub functions which return python non-integer data type like string, list, tuple, dictionary, the existing type in functions varies from each other which leads problem like this. Currently, in generator.py, it maintains a buggy whitelist for stub functions returning a list type. I think it is easy to forget adding new function name in the whitelist. This patch makes the value of type consistent with C type "char *" in libvirt-override-api.xml. For python, any of types could be printed as string, so I choose "char *" in this case. And the comment in xml could explain it when adding new function definition. ... - + ... 2013- 3- 13 Daniel P. Berrange Apply security label when entering LXC namespaces Add a new virDomainLxcEnterSecurityLabel() function as a counterpart to virDomainLxcEnterNamespaces(), which can change the current calling process to have a new security context. This call runs client side, not in libvirtd so we can't use the security driver infrastructure. When entering a namespace, the process spawned from virsh will default to running with the security label of virsh. The actual desired behaviour is to run with the security label of the container most of the time. So this changes virsh lxc-enter-namespace command to invoke the virDomainLxcEnterSecurityLabel method. The current behaviour is: LABEL PID TTY TIME CMD system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 1 pts/0 00:00:00 systemd system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 3 pts/1 00:00:00 sh system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 24 ? 00:00:00 systemd-journal system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 29 ? 00:00:00 dhclient staff_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 47 ? 00:00:00 ps Note the ps command is running as unconfined_t, After this patch, The new behaviour is this: virsh -c lxc:/// lxc-enter-namespace dan -- /bin/ps -eZ LABEL PID TTY TIME CMD system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 1 pts/0 00:00:00 systemd system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 3 pts/1 00:00:00 sh system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 24 ? 00:00:00 systemd-journal system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 32 ? 00:00:00 dhclient system_u:system_r:svirt_lxc_net_t:s0:c0.c1023 38 ? 00:00:00 ps The '--noseclabel' flag can be used to skip security labelling. 2013- 3- 1 Guannan Ren python: fix fd leak in generator.py 2013- 3- 1 Guannan Ren python: fix typoes and repeated global vars references 2013- 2- 22 Jiri Denemark python: Implement virDomainMigrateGetCompressionCache wrapper 2013- 2- 22 Jiri Denemark Introduce virDomainMigrate*CompressionCache APIs Introduce virDomainMigrateGetCompressionCache and virDomainMigrateSetCompressionCache APIs. 2013- 2- 22 Jiri Denemark python: Implement virDomainGetJobStats wrapper 2013- 2- 22 Jiri Denemark Introduce virDomainGetJobStats API This is an extensible version of virDomainGetJobInfo. 2013- 2- 11 Guido Günther Check if classes are derived from object This makes sure we don't regress to old style classes 2013- 2- 7 Guido Günther Remove more trailing semicolons in Python files 2013- 2- 7 Guido Günther Cosmetics: Remove semicolons It's Python, not C 2013- 2- 5 Jiri Denemark sanitytest.py: Do not rely on system libvirt When running sanitytest.py we should not rely on libvirt library installed on the system. And since we generate a nice wrapper called "run" that sets both PYTHON_PATH and LD_LIBRARY_PATH, we should just use it rather than trying to duplicate it in the Makefile. 2013- 2- 5 Daniel P. Berrange Fix missing error constants in libvirt python module The previous change to the generator, changed too much - only the functions are in 'virerror.c', the constants remained in 'virerror.h' which could not be renamed for API compat reasons. Add a test case to sanity check the generated python bindings 2013- 1- 31 Serge Hallyn complete virterror->virerror name change Without these two string changes in generator.py, the virGetLastError wrapper does not get created in /usr/share/pyshared/libvirt.py. Noticed when running tests with virt-install. 2013- 1- 24 Jiri Denemark python: Fix bindings for virDomainSnapshotGet{Domain,Connect} https://bugzilla.redhat.com/show_bug.cgi?id=895882 virDomainSnapshot.getDomain() and virDomainSnapshot.getConnect() wrappers around virDomainSnapshotGet{Domain,Connect} were not supposed to be ever implemented. The class should contain proper domain() and connect() accessors that fetch python objects stored internally within the class. While domain() was already provided, connect() was missing. This patch adds connect() method to virDomainSnapshot class and reimplements getDomain() and getConnect() methods as aliases to domain() and connect() for backward compatibility. 2013- 1- 24 Daniel P. Berrange Make python objects inherit from 'object' base class As of python >= 2.2, it is recommended that all objects inherit from the 'object' base class. We already require python >= 2.3 for libvirt for thread macro support, so we should follow this best practice. See also http://stackoverflow.com/questions/4015417/python-class-inherits-object 2013- 1- 18 Jiri Denemark Introduce virTypedParamsClear public API The function is just a renamed public version of former virTypedParameterArrayClear. 2013- 1- 18 Jiri Denemark Add virTypedParams* APIs Working with virTypedParameters in clients written in C is ugly and requires all clients to duplicate the same code. This set of APIs makes this code for manipulating with virTypedParameters integral part of libvirt so that all clients may benefit from it. 2013- 1- 17 Jiri Denemark python: Avoid freeing uninitialized new_params pointer 2013- 1- 14 Daniel P. Berrange Fix build due to previous LXC patch Mark virDomainLxcEnterNamespace as skipped in python binding and remove reference to lxcDomainOpenNamespace which doesn't arrive until a later patch 2013- 1- 14 Daniel P. Berrange Introduce an LXC specific public API & library This patch introduces support for LXC specific public APIs. In common with what was done for QEMU, this creates a libvirt_lxc.so library and libvirt/libvirt-lxc.h header file. The actual APIs are int virDomainLxcOpenNamespace(virDomainPtr domain, int **fdlist, unsigned int flags); int virDomainLxcEnterNamespace(virDomainPtr domain, unsigned int nfdlist, int *fdlist, unsigned int *noldfdlist, int **oldfdlist, unsigned int flags); which provide a way to use the setns() system call to move the calling process into the container's namespace. It is not practical to write in a generically applicable manner. The nearest that we could get to such an API would be an API which allows to pass a command + argv to be executed inside a container. Even if we had such a generic API, this LXC specific API is still useful, because it allows the caller to maintain the current process context, in particular any I/O streams they have open. NB the virDomainLxcEnterNamespace() API is special in that it runs client side, so does not involve the internal driver API. 2012- 12- 28 Michal Privoznik python: Adapt to virevent rename With our recent renames under src/util/* we forgot to adapt python wrapper code generator. This results in some methods being not exposed: $ python examples/domain-events/events-python/event-test.py Using uri:qemu:///system Traceback (most recent call last): File "examples/domain-events/events-python/event-test.py", line 585, in main() File "examples/domain-events/events-python/event-test.py", line 543, in main virEventLoopPureStart() File "examples/domain-events/events-python/event-test.py", line 416, in virEventLoopPureStart virEventLoopPureRegister() File "examples/domain-events/events-python/event-test.py", line 397, in virEventLoopPureRegister libvirt.virEventRegisterImpl(virEventAddHandleImpl, AttributeError: 'module' object has no attribute 'virEventRegisterImpl' 2012- 12- 21 Daniel P. Berrange Rename util.{c,h} to virutil.{c,h} 2012- 12- 21 Daniel P. Berrange Rename memory.{c,h} to viralloc.{c,h} 2012- 12- 4 Osier Yang Fix the indention Introduced by commit 1465876a, pushed under build-breaker && trivial rule. 2012- 12- 4 Daniel P. Berrange Bind connection close callback APIs to python binding Add code in the python binding to cope with the new APIs virConnectRegisterCloseCallback and virConnectUnregisterCloseCallback. Also demonstrate their use in the python domain events demo 2012- 11- 15 Viktor Mihajlovski python: Use virNodeGetCPUMap where possible Modified the places where virNodeGetInfo was used for the purpose of obtaining the maximum node CPU number. Transparently falling back to virNodeGetInfo in case of failure. Wrote a utility function getPyNodeCPUCount for that purpose. 2012- 11- 2 Daniel P. Berrange Remove spurious whitespace between function name & open brackets The libvirt coding standard is to use 'function(...args...)' instead of 'function (...args...)'. A non-trivial number of places did not follow this rule and are fixed in this patch. 2012- 10- 25 Eric Blake maint: consistent whitespace after 'if' Noticed during the review of the previous patch. * python/libvirt-override.c: Use space between 'if ('. 2012- 10- 25 Viktor Mihajlovski virNodeGetCPUMap: Add python binding Added a method getCPUMap to virConnect. It can be used as follows: import libvirt import sys import os conn = libvirt.openReadOnly(None) if conn == None: print 'Failed to open connection to the hypervisor' sys.exit(1) try: (cpus, cpumap, online) = conn.getCPUMap(0) except: print 'Failed to extract the node cpu map information' sys.exit(1) print 'CPUs total %d, online %d' % (cpus, online) print 'CPU map %s' % str(cpumap) del conn print "OK" sys.exit(0) 2012- 10- 24 Viktor Mihajlovski virNodeGetCPUMap: Define public API. Adding a new API to obtain information about the host node's present, online and offline CPUs. int virNodeGetCPUMap(virConnectPtr conn, unsigned char **cpumap, unsigned int *online, unsigned int flags); The function will return the number of CPUs present on the host or -1 on failure; If cpumap is non-NULL virNodeGetCPUMap will allocate an array containing a bit map representation of the online CPUs. It's the callers responsibility to deallocate cpumap using free(). If online is non-NULL, the variable pointed to will contain the number of online host node CPUs. The variable flags has been added to support future extensions and must be set to 0. Extend the driver structure by nodeGetCPUMap entry in support of the new API virNodeGetCPUMap. Added implementation of virNodeGetCPUMap to libvirt.c 2012- 10- 15 Martin Kletzander Add support for SUSPEND_DISK event This patch adds support for SUSPEND_DISK event; both lifecycle and separated. The support is added for QEMU, machines are changed to PMSUSPENDED, but as QEMU sends SHUTDOWN afterwards, the state changes to shut-off. This and much more needs to be done in order for libvirt to work with transient devices, wake-ups etc. This patch is not aiming for that functionality. 2012- 10- 13 Guido Günther Properly parse (unsigned) long long This fixes problems on platforms where sizeof(long) != sizeof(long long) like ia32. 2012- 10- 8 Guannan Ren python: keep consistent handling of Python integer conversion libvirt_ulonglongUnwrap requires the integer type of python obj. But libvirt_longlongUnwrap still could handle python obj of Pyfloat_type which causes the float value to be rounded up to an integer. For example >>> dom.setSchedulerParameters({'vcpu_quota': 0.88}) 0 libvirt_longlongUnwrap treats 0.88 as a valid value 0 However >>> dom.setSchedulerParameters({'cpu_shares': 1000.22}) libvirt_ulonglongUnwrap will throw out an error "TypeError: an integer is required" The patch make this consistent. 2012- 10- 8 Guannan Ren python: cleanup vcpu related binding APIs libvirt_virDomainGetVcpus: add error handling, return -1 instead of None libvirt_virDomainPinVcpu and libvirt_virDomainPinVcpuFlags: check the type of argument make use of libvirt_boolUnwrap Set bitmap according to these values which are contained in given argument of vcpu tuple and turn off these bit corresponding to missing vcpus in argument tuple The original way ignored the error info from PyTuple_GetItem if index is out of range. "IndexError: tuple index out of range" The error message will only be raised on next command in interactive mode. 2012- 9- 28 Guannan Ren python: return error if PyObject obj is NULL for unwrapper helper functions The result is indeterminate for NULL argument to python functions as follows. It's better to return negative value in these situations. PyObject_IsTrue will segfault if the argument is NULL PyFloat_AsDouble(NULL) is -1.000000 PyLong_AsUnsignedLongLong(NULL) is 0.000000 2012- 9- 17 Osier Yang node_memory: Expose the APIs to Python bindings * python/libvirt-override-api.xml: (Add document to describe the APIs). * python/libvirt-override.c: (Implement the API wrappers manually) 2012- 9- 17 Osier Yang node_memory: Define the APIs to get/set memory parameters * include/libvirt/libvirt.h.in: (Add macros for the param fields, declare the APIs). * src/driver.h: (New methods for the driver struct) * src/libvirt.c: (Implement the public APIs) * src/libvirt_public.syms: (Export the public symbols) 2012- 9- 17 Osier Yang list: Expose virConnectListAllSecrets to Python binding The implementation is done manually as the generator does not support wrapping lists of C pointers into Python objects. python/libvirt-override-api.xml: Document python/libvirt-override-virConnect.py: Implementation for listAllSecrets. python/libvirt-override.c: Implementation for the wrapper. 2012- 9- 17 Osier Yang list: Define new API virConnectListAllSecrets This is to list the secret objects. Supports to filter the secrets by its storage location, and whether it's private or not. include/libvirt/libvirt.h.in: Declare enum virConnectListAllSecretFlags and virConnectListAllSecrets. python/generator.py: Skip auto-generating src/driver.h: (virDrvConnectListAllSecrets) src/libvirt.c: Implement the public API src/libvirt_public.syms: Export the symbol to public 2012- 9- 17 Osier Yang list: Expose virConnectListAllNWFilters to Python binding The implementation is done manually as the generator does not support wrapping lists of C pointers into Python objects. python/libvirt-override-api.xml: Document python/libvirt-override-virConnect.py: * Implementation for listAllNWFilters. python/libvirt-override.c: Implementation for the wrapper. 2012- 9- 17 Osier Yang list: Define new API virConnectListAllNWFilters This is to list the network filter objects. No flags are supported include/libvirt/libvirt.h.in: Declare enum virConnectListAllNWFilterFlags and virConnectListAllNWFilters. python/generator.py: Skip auto-generating src/driver.h: (virDrvConnectListAllNWFilters) src/libvirt.c: Implement the public API src/libvirt_public.syms: Export the symbol to public 2012- 9- 17 Osier Yang list: Expose virConnectListAllNodeDevices to Python binding The implementation is done manually as the generator does not support wrapping lists of C pointers into Python objects. python/libvirt-override-api.xml: Document python/libvirt-override-virConnect.py: * Implementation for listAllNodeDevices. python/libvirt-override.c: Implementation for the wrapper. 2012- 9- 17 Osier Yang list: Define new API virConnectListAllNodeDevices This is to list the node device objects, supports to filter the results by capability types. include/libvirt/libvirt.h.in: Declare enum virConnectListAllNodeDeviceFlags and virConnectListAllNodeDevices. python/generator.py: Skip auto-generating src/driver.h: (virDrvConnectListAllNodeDevices) src/libvirt.c: Implement the public API src/libvirt_public.syms: Export the symbol to public 2012- 9- 12 Osier Yang list: Expose virConnectListAllInterfaces to Python binding The implementation is done manually as the generator does not support wrapping lists of C pointers into Python objects. python/libvirt-override-api.xml: Document python/libvirt-override-virConnect.py: * New file, includes implementation of listAllInterfaces. python/libvirt-override.c: Implementation for the wrapper. 2012- 9- 12 Osier Yang list: Define new API virConnectListAllInterfaces This is to list the interface objects, supported filtering flags are: active|inactive. include/libvirt/libvirt.h.in: Declare enum virConnectListAllInterfaceFlags and virConnectListAllInterfaces. python/generator.py: Skip auto-generating src/driver.h: (virDrvConnectListAllInterfaces) src/libvirt.c: Implement the public API src/libvirt_public.syms: Export the symbol to public 2012- 9- 11 Federico Simoncelli python: Initialize new_params in virDomainSetSchedulerParameters The new_params variable must be initialized in case the virDomainGetSchedulerParameters call fails and we hit the cleanup section before actually allocating the new parameters. 2012- 9- 11 Daniel P. Berrange Check against python None type when filling in auth parameters When deciding whether to provide an auth function callback in openAuth(), credcb was checked against NULL, when it really needs to be checked against Py_None 2012- 9- 11 Daniel P. Berrange Print any exception that occurs in authentication callback If an exception occurs in the python callback for openAuth() the stack trace isn't seen by the apps, since this code is called from libvirt context. To aid diagnostics, print the error to stderr at least 2012- 9- 11 Daniel P. Berrange Fix crash passing an empty list to python openAuth() API If passing a 'credtype' parameter which was an empty list to the python openAuth() API, the 'credtype' field in the virConnectAuth struct would not be initialized. This lead to a crash when later trying to free that field. 2012- 9- 11 Osier Yang list: Expose virConnectListAllNetworks to Python binding The implementation is done manually as the generator does not support wrapping lists of C pointers into Python objects. python/libvirt-override-api.xml: Document python/libvirt-override-virConnect.py: Implement listAllNetworks. python/libvirt-override.c: Implementation for the wrapper. 2012- 9- 11 Osier Yang list: Define new API virConnectListAllNetworks This is to list the network objects, supported filtering flags are: active|inactive, persistent|transient, autostart|no-autostart. include/libvirt/libvirt.h.in: Declare enum virConnectListAllNetworkFlags and virConnectListAllNetworks. python/generator.py: Skip auto-generating src/driver.h: (virDrvConnectListAllNetworks) src/libvirt.c: Implement the public API src/libvirt_public.syms: Export the symbol to public 2012- 9- 10 Osier Yang list: Expose virStoragePoolListAllVolumes to Python binding The implementation is done manually as the generator does not support wrapping lists of C pointers into Python objects. python/libvirt-override-api.xml: Document python/libvirt-override-virStoragePool.py: * New file, includes implementation of listAllVolumes. python/libvirt-override.c: Implementation for the wrapper. 2012- 9- 10 Osier Yang list: Define new API virStoragePoolListAllVolumes Simply returns the storage volume objects. No supported filter flags. include/libvirt/libvirt.h.in: Declare the API python/generator.py: Skip the function for generating. virStoragePool.py will be added in later patch. src/driver.h: virDrvStoragePoolListVolumesFlags src/libvirt.c: Implementation for the API. src/libvirt_public.syms: Export the symbol to public 2012- 9- 7 Jiri Denemark Fix PMSuspend and PMWakeup events The unused reason parameter of PM{Suspend,Wakeup} event callbacks was completely ignored in lot of places and those events were not actually working at all. 2012- 9- 6 Osier Yang python: Expose virStorageListAllStoragePools to python binding The implementation is done manually as the generator does not support wrapping lists of C pointers into Python objects. python/libvirt-override-api.xml: Document python/libvirt-override-virConnect.py: Add listAllStoragePools python/libvirt-override.c: Implementation for the wrapper. 2012- 9- 6 Osier Yang list: Define new API virStorageListAllStoragePools This introduces a new API to list the storage pool objects, 4 groups of flags are provided to filter the returned pools: * Active or not * Autostarting or not * Persistent or not * And the pool type. include/libvirt/libvirt.h.in: New enum virConnectListAllStoragePoolFlags; Declare the API. python/generator.py: Skip the generating src/driver.h: (virDrvConnectListAllStoragePools) src/libvirt.c: Implementation for the API. src/libvirt_public.syms: Export the symbol. 2012- 8- 31 Eric Blake python: don't mask libvirt errors A user reported this crash when using python bindings: File "/home/nox/workspace/NOX/src/NOX/hooks.py", line 134, in trigger hook.trigger(event) File "/home/nox/workspace/NOX/src/NOX/hooks.py", line 33, in trigger self.handlers[event]() File "/home/nox/workspace/NOX/hooks/volatility.py", line 81, in memory_dump for block in Memory(self.ctx): File "/home/see/workspace/NOX/src/NOX/lib/libtools.py", line 179, in next libvirt.VIR_MEMORY_PHYSICAL) File "/usr/lib/python2.7/dist-packages/libvirt.py", line 1759, in memoryPeek ret = libvirtmod.virDomainMemoryPeek(self._o, start, size, flags) SystemError: error return without exception set In the python bindings, returning NULL makes python think an exception was thrown, while returning the None object lets the wrappers know that a libvirt error exists. Reported by Nox DaFox, fix suggested by Dan Berrange. * python/libvirt-override.c (libvirt_virDomainBlockPeek) (libvirt_virDomainMemoryPeek): Return python's None object, so wrapper knows to check libvirt error. 2012- 8- 23 MATSUDA Daiki agent: add python module support Add virDomainQemuAgentCommand() support function to python module. 2012- 8- 23 MATSUDA Daiki agent: add virDrvDomainQemuAgentCommand prototype for drivers. Add virDrvDomainQemuAgentCommand prototype for drivers. Add virDomainQemuAgentCommand() for virDrvDomainQemuAgentCommand. 2012- 8- 20 Marcelo Cerri Update the remote API This patch updates libvirt's API to allow applications to inspect the full list of security labels of a domain. 2012- 7- 30 Peter Krempa python: Don't generate bodies for close callback functions Commit 6ed5a1b9bd6240b8f2736790e48dd1c284c2e0e1 adds close callback functions to the public API but doesn't add python implementation. This patch sets the function to be written manually (to fix the build), but doesn't implement them yet. 2012- 7- 14 Daniel P. Berrange Define public API for receiving guest memory balloon events When the guest changes its memory balloon applications may want to know what the new value is, without having to periodically poll on XML / domain info. Introduce a "balloon change" event to let apps see this * include/libvirt/libvirt.h.in: Define the virConnectDomainEventBalloonChangeCallback callback and VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE constant * python/libvirt-override-virConnect.py, python/libvirt-override.c: Wire up helpers for new event * daemon/remote.c: Helper for serializing balloon event * examples/domain-events/events-c/event-test.c, examples/domain-events/events-python/event-test.py: Add example of balloon event usage * src/conf/domain_event.c, src/conf/domain_event.h: Handling of balloon events * src/remote/remote_driver.c: Add handler of balloon events * src/remote/remote_protocol.x: Define wire protocol for balloon events * src/remote_protocol-structs: Likewise. 2012- 6- 19 Eric Blake list: provide python bindings for snapshots This adds support for the new virDomainListAllSnapshots (a domain function) and virDomainSnapshotListAllChildren (a snapshot function) to the libvirt-python bindings. The implementation is done manually as the generator does not support wrapping lists of C pointers into python objects. * python/libvirt-override.c (libvirt_virDomainListAllSnapshots) (libvirt_virDomainSnapshotListAllChildren): New functions. * python/libvirt-override-api.xml: Document them. * python/libvirt-override-virDomain.py (listAllSnapshots): New file. * python/libvirt-override-virDomainSnapshot.py (listAllChildren): Likewise. * python/Makefile.am (CLASSES_EXTRA): Ship them. 2012- 6- 19 Eric Blake list: add virDomainListAllSnapshots API There was an inherent race between virDomainSnapshotNum() and virDomainSnapshotListNames(), where an additional snapshot could be created in the meantime, or where a snapshot could be deleted before converting the name back to a virDomainSnapshotPtr. It was also an awkward name: the function operates on domains, not domain snapshots. virDomainSnapshotListChildrenNames() suffered from the same inherent race, although its naming was nicer. This patch makes things nicer by grabbing a snapshot list atomically, in the format most useful to the user. * include/libvirt/libvirt.h.in (virDomainListAllSnapshots) (virDomainSnapshotListAllChildren): New declarations. * src/libvirt.c (virDomainSnapshotListNames) (virDomainSnapshotListChildrenNames): Add cross-references. (virDomainListAllSnapshots, virDomainSnapshotListAllChildren): New functions. * src/libvirt_public.syms (LIBVIRT_0.9.13): Export them. * src/driver.h (virDrvDomainListAllSnapshots) (virDrvDomainSnapshotListAllChildren): New callbacks. * python/generator.py (skip_function): Prepare for later hand-written versions. 2012- 6- 18 Peter Krempa python: add API exports for virConnectListAllDomains() This patch adds export of the new API function virConnectListAllDomains() to the libvirt-python bindings. The virConnect object now has method "listAllDomains" that takes only the flags parameter and returns a python list of virDomain object corresponding to virDomainPtrs returned by the underlying api. The implementation is done manually as the generator does not support wrapping list of virDomainPtrs into virDomain objects. 2012- 6- 18 Peter Krempa lib: Add public api to enable atomic listing of guest This patch adds a new public api that lists domains. The new approach is different from those used before. There are key points to this: 1) The list is acquired atomically and contains both active and inactive domains (guests). This eliminates the need to call two different list APIs, where the state might change in between the calls. 2) The returned list consists of virDomainPtrs instead of names or ID's that have to be converted to virDomainPtrs anyways using separate calls for each one of them. This is more convenient and saves hypervisor calls. 3) The returned list is auto-allocated. This saves a lot of hassle for the users. 4) Built in support for filtering. The API call supports various filtering flags that modify the output list according to user needs. Available filter groups: Domain status: VIR_CONNECT_LIST_DOMAINS_ACTIVE, VIR_CONNECT_LIST_DOMAINS_INACTIVE Domain persistence: VIR_CONNECT_LIST_DOMAINS_PERSISTENT, VIR_CONNECT_LIST_DOMAINS_TRANSIENT Domain state: VIR_CONNECT_LIST_DOMAINS_RUNNING, VIR_CONNECT_LIST_DOMAINS_PAUSED, VIR_CONNECT_LIST_DOMAINS_SHUTOFF, VIR_CONNECT_LIST_DOMAINS_OTHER Existence of managed save image: VIR_CONNECT_LIST_DOMAINS_MANAGEDSAVE, VIR_CONNECT_LIST_DOMAINS_NO_MANAGEDSAVE Auto-start option: VIR_CONNECT_LIST_DOMAINS_AUTOSTART, VIR_CONNECT_LIST_DOMAINS_NO_AUTOSTART Existence of snapshot: VIR_CONNECT_LIST_DOMAINS_HAS_SNAPSHOT, VIR_CONNECT_LIST_DOMAINS_NO_SNAPSHOT 5) The python binding returns a list of domain objects that is very neat to work with. The only problem with this approach is no support from code generators so both RPC code and python bindings had to be written manually. *include/libvirt/libvirt.h.in: - add API prototype - clean up whitespace mistakes nearby *python/generator.py: - inhibit generation of the bindings for the new api *src/driver.h: - add driver prototype - clean up some whitespace mistakes nearby *src/libvirt.c: - add public implementation *src/libvirt_public.syms: - export the new symbol 2012- 6- 12 Eric Blake python: fix snapshot listing bugs Python exceptions are different than libvirt errors, and we had some corner case bugs on OOM situations. * python/libvirt-override.c (libvirt_virDomainSnapshotListNames) (libvirt_virDomainSnapshotListChildrenNames): Use correct error returns, avoid segv on OOM, and avoid memory leaks on error. 2012- 6- 12 Eric Blake python: use simpler methods * python/libvirt-override.c (libvirt_virDomainGetVcpus) (libvirt_virDomainGetVcpuPinInfo): Use Py_XDECREF instead of open-coding it. 2012- 5- 4 Osier Yang Coverity: Fix the forward_null error in Python binding codes Related coverity log: Error: FORWARD_NULL: /builddir/build/BUILD/libvirt-0.9.10/python/libvirt-override.c:355: assign_zero: Assigning: "params" = 0. /builddir/build/BUILD/libvirt-0.9.10/python/libvirt-override.c:458: var_deref_model: Passing null variable "params" to function "getPyVirTypedParameter", which dereferences it. (The dereference is assumed on the basis of the 'nonnull' parameter attribute.) 2012- 4- 27 Cole Robinson python: Fix doc directory name for stable releases We were using the libvirt release version (like 0.9.11) and not the configure version (which for stable releases is 0.9.11.X) Most other places got this right so hopefully that's all the fallout from the version format change :) 2012- 4- 10 Stefan Berger Fix compilation error on 32bit Below code failed to compile on a 32 bit machine with error typewrappers.c: In function 'libvirt_intUnwrap': typewrappers.c:135:5: error: logical 'and' of mutually exclusive tests is always false [-Werror=logical-op] cc1: all warnings being treated as errors The patch fixes this error. 2012- 3- 31 Eric Blake python: improve conversion validation Laszlo Ersek pointed out that in trying to convert a long to an unsigned int, we used: long long_val = ...; if ((unsigned int)long_val == long_val) According to C99 integer promotion rules, the if statement is equivalent to: (unsigned long)(unsigned int)long_val == (unsigned long)long_val since you get an unsigned comparison if at least one side is unsigned, using the largest rank of the two sides; but on 32-bit platforms, where unsigned long and unsigned int are the same size, this comparison is always true and ends up converting negative long_val into posigive unsigned int values, rather than rejecting the negative value as we had originally intended (python longs are unbounded size, and we don't want to do silent modulo arithmetic when converting to C code). Fix this by using direct comparisons, rather than casting. * python/typewrappers.c (libvirt_intUnwrap, libvirt_uintUnwrap) (libvirt_ulongUnwrap, libvirt_ulonglongUnwrap): Fix conversion checks. 2012- 3- 28 Guannan Ren python: make python APIs use these helper functions *setPyVirTypedParameter *libvirt_virDomainGetCPUStats 2012- 3- 28 Guannan Ren python: Add new helper functions for python to C integral conversion int libvirt_intUnwrap(PyObject *obj, int *val); int libvirt_uintUnwrap(PyObject *obj, unsigned int *val); int libvirt_longUnwrap(PyObject *obj, long *val); int libvirt_ulongUnwrap(PyObject *obj, unsigned long *val); int libvirt_longlongUnwrap(PyObject *obj, long long *val); int libvirt_ulonglongUnwrap(PyObject *obj, unsigned long long *val); int libvirt_doubleUnwrap(PyObject *obj, double *val); int libvirt_boolUnwrap(PyObject *obj, bool *val); 2012- 3- 26 Martin Kletzander Cleanup for a return statement in source files Return statements with parameter enclosed in parentheses were modified and parentheses were removed. The whole change was scripted, here is how: List of files was obtained using this command: git grep -l -e '\ Add support for the suspend event This patch introduces a new event type for the QMP event SUSPEND: VIR_DOMAIN_EVENT_ID_PMSUSPEND The event doesn't take any data, but considering there might be reason for wakeup in future, the callback definition is: typedef void (*virConnectDomainEventSuspendCallback)(virConnectPtr conn, virDomainPtr dom, int reason, void *opaque); "reason" is unused currently, always passes "0". 2012- 3- 23 Osier Yang Add support for the wakeup event This patch introduces a new event type for the QMP event WAKEUP: VIR_DOMAIN_EVENT_ID_PMWAKEUP The event doesn't take any data, but considering there might be reason for wakeup in future, the callback definition is: typedef void (*virConnectDomainEventWakeupCallback)(virConnectPtr conn, virDomainPtr dom, int reason, void *opaque); "reason" is unused currently, always passes "0". 2012- 3- 23 Osier Yang Add support for event tray moved of removable disks This patch introduces a new event type for the QMP event DEVICE_TRAY_MOVED, which occurs when the tray of a removable disk is moved (i.e opened or closed): VIR_DOMAIN_EVENT_ID_TRAY_CHANGE The event's data includes the device alias and the reason for tray status' changing, which indicates why the tray status was changed. Thus the callback definition for the event is: enum { VIR_DOMAIN_EVENT_TRAY_CHANGE_OPEN = 0, VIR_DOMAIN_EVENT_TRAY_CHANGE_CLOSE, \#ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_EVENT_TRAY_CHANGE_LAST \#endif } virDomainEventTrayChangeReason; typedef void (*virConnectDomainEventTrayChangeCallback)(virConnectPtr conn, virDomainPtr dom, const char *devAlias, int reason, void *opaque); 2012- 3- 22 Guannan Ren python: add virDomainGetCPUStats python binding API dom.getCPUStats(True, 0) [{'cpu_time': 24699446159L, 'system_time': 10870000000L, 'user_time': 950000000L}] dom.getCPUStats(False, 0) [{'cpu_time': 8535292289L}, {'cpu_time': 1005395355L}, {'cpu_time': 9351766377L}, {'cpu_time': 5813545649L}] *generator.py Add a new naming rule *libvirt-override-api.xml The API function description *libvirt-override.c Implement it. 2012- 3- 22 Alex Jia python: Avoid memory leaks on libvirt_virNodeGetCPUStats Detected by valgrind. Leaks are introduced in commit 4955602. * python/libvirt-override.c (libvirt_virNodeGetCPUStats): fix memory leaks and improve codes return value. For details, please see the following link: RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=770943 2012- 3- 21 Alex Jia python: Avoid memory leaks on libvirt_virNodeGetMemoryStats Detected by valgrind. Leaks are introduced in commit 17c7795. * python/libvirt-override.c (libvirt_virNodeGetMemoryStats): fix memory leaks and improve codes return value. For details, please see the following link: RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=770944 2012- 3- 20 Eric Blake python: always include config.h first On RHEL 5.7, I got this compilation failure: In file included from /usr/include/python2.4/pyport.h:98, from /usr/include/python2.4/Python.h:55, from libvirt.c:3: ../gnulib/lib/time.h:468: error: expected ';', ',' or ')' before '__timer' Turns out that our '#define restrict __restrict' from config.h wasn't being picked up. Gnulib _requires_ that all .c files include first, otherwise the gnulib header overrides tend to misbehave. Problem introduced by patch c700613b8. * python/generator.py (buildStubs): Include first. 2012- 2- 16 Alex Jia python: Expose virDomain{G,S}etInterfaceParameters APIs in python binding The v4 patch corrects indentation issues. The v3 patch follows latest python binding codes and change 'size' type from int to Py_ssize_t. An simple example to show how to use it: #!/usr/bin/env python import libvirt conn = libvirt.open(None) dom = conn.lookupByName('foo') print dom.interfaceParameters('vnet0', 0) params = {'outbound.peak': 10, 'inbound.peak': 10, 'inbound.burst': 20, 'inbound.average': 20, 'outbound.average': 30, 'outbound.burst': 30} print dom.setInterfaceParameters('vnet0', params, 0) print dom.interfaceParameters('vnet0', 0) 2012- 2- 11 Guannan Ren python: make other APIs share common {get, set}PyVirTypedParameter *libvirt_virDomainBlockStatsFlags *libvirt_virDomainGetSchedulerParameters *libvirt_virDomainGetSchedulerParametersFlags *libvirt_virDomainSetSchedulerParameters *libvirt_virDomainSetSchedulerParametersFlags *libvirt_virDomainSetBlkioParameters *libvirt_virDomainGetBlkioParameters *libvirt_virDomainSetMemoryParameters *libvirt_virDomainGetMemoryParameters *libvirt_virDomainSetBlockIoTune *libvirt_virDomainGetBlockIoTune 2012- 2- 9 Guannan Ren python: refactoring virTypedParameter conversion for NUMA tuning APIs *getPyVirTypedParameter *setPyVirTypedParameter *virDomainSetNumaParameters *virDomainGetNumaParameters 2012- 2- 9 Osier Yang python: Correct arguments number for migrateSetMaxSpeed The API definition accepts "flags" argument, however, the implementation ignores it, though "flags" is unused currently, we should expose it instead of hard coding, the API implementation inside hypervisor driver is responsible to check if the passed "flags" is valid. 2012- 2- 8 Eric Blake python: drop unused function Gcc warned about an unused static function. * python/libvirt-qemu-override.c (py_str): Delete. 2012- 2- 7 Michal Privoznik pyhton: Don't link against libvirt_util.la As we already link with libvirt.la which contains libvirt_utils.la. Double linking causes global symbols to be presented twice and thus confusion. This partially reverts c700613b8d463212d142c97108b7a2352e23e559 2012- 2- 3 Eric Blake maint: consolidate several .gitignore files Unlike .cvsignore under CVS, git allows for ignoring nested names. We weren't very consistent where new tests were being ignored (some in .gitignore, some in tests/.gitignore), and I found it easier to just consolidate everything. * .gitignore: Subsume entries from subdirectories. * daemon/.gitignore: Delete. * docs/.gitignore: Likewise. * docs/devhelp/.gitignore: Likewise. * docs/html/.gitignore: Likewise. * examples/dominfo/.gitignore: Likewise. * examples/domsuspend/.gitignore: Likewise. * examples/hellolibvirt/.gitignore: Likewise. * examples/openauth/.gitignore: Likewise. * examples/domain-events/events-c/.gitignore: Likewise. * include/libvirt/.gitignore: Likewise. * src/.gitignore: Likewise. * src/esx/.gitignore: Likewise. * tests/.gitignore: Likewise. * tools/.gitignore: Likewise. 2012- 2- 3 Martin Kletzander Added missing memory reporting into python bindings Two types of memory stats were not reported by python bindings. This patch fixes both of them. 2012- 2- 3 Eric Blake python: use libvirt_util to avoid raw free This patch starts the process of elevating the python binding code to be on the same level as the rest of libvirt when it comes to requiring good coding styles. Statically linking against the libvirt_util library makes it much easier to write good code, rather than having to open-code and reinvent things locally. Done by global search and replace of s/free(/VIR_FREE(/, followed by hand-inspection of remaining malloc and redundant memset. * cfg.mk (exclude_file_name_regexp--sc_prohibit_raw_allocation): Remove python from exemption. * python/Makefile.am (INCLUDES): Add gnulib and src/util. Drop $(top_builddir)/$(subdir), as automake already guarantees that. (mylibs, myqemulibs): Pull in libvirt_util and gnulib. (libvirtmod_la_CFLAGS): Catch compiler warnings if configured to use -Werror. * python/typewrappers.c (libvirt_charPtrSizeWrap) (libvirt_charPtrWrap): Convert free to VIR_FREE. * python/generator.py (print_function_wrapper): Likewise. * python/libvirt-override.c: Likewise. 2012- 2- 3 Eric Blake python: drop redundant function I noticed some redundant code while preparing my next patch. * python/generator.py (py_types): Fix 'const char *' mapping. * python/typewrappers.h (libvirt_charPtrConstWrap): Drop. * python/typewrappers.c (libvirt_charPtrConstWrap): Delete, since it is identical to libvirt_constcharPtrWrap. 2012- 2- 3 Eric Blake build: clean up CPPFLAGS/INCLUDES usage Our syntax checker missed all-lower-case variables (this will be fixed by the next .gnulib update). Additionally, anywhere that we mix in-tree files with generated files, automake recommends listing builddir prior to srcdir for VPATH builds. * src/Makefile.am (*_la_CFLAGS): Favor $(top_srcdir). (INCLUDES): Likewise, and follow automake recommendations on builddir before srcdir. * python/Makefile.am (INCLUDES): Swap directory order. * tests/Makefile.am (INCLUDES): Likewise. * tools/Makefile.am (INCLUDES): Likewise. * daemon/Makefile.am (INCLUDES): Likewise. (libvirtd.init, libvirtd.service): Favor $(). * examples/hellolibvirt/Makefile.am (hellolibvirt_LDADD): Likewise. * examples/openauth/Makefile.am (openauth_LDADD): Likewise. * examples/dominfo/Makefile.am (INCLUDES): Drop dead include. * examples/domsuspend/Makefile.am (INCLUDES): Likewise. 2012- 2- 1 Jiri Denemark python: Add binding for virDomainGetDiskErrors 2012- 2- 1 Jiri Denemark virDomainGetDiskErrors public API We already provide ways to detect when a domain has been paused as a result of I/O error, but there was no way of getting the exact error or even the device that experienced it. This new API may be used for both. 2012- 2- 1 Alex Jia python: correct a copy-paste error * python/libvirt-override-virStream.py: fix a copy-paste error in sendAll(). 2012- 1- 28 KAMEZAWA Hiroyuki Add new public API virDomainGetCPUStats() add new API virDomainGetCPUStats() for getting cpu accounting information per real cpus which is used by a domain. The API is designed to allow future extensions for additional statistics. based on ideas by Lai Jiangshan and Eric Blake. * src/libvirt_public.syms: add API for LIBVIRT_0.9.10 * src/libvirt.c: define virDomainGetCPUStats() * include/libvirt/libvirt.h.in: add virDomainGetCPUStats() header * src/driver.h: add driver API * python/generator.py: add python API (as not implemented) 2012- 1- 28 Zeeshan Ali (Khattak) resize: add virStorageVolResize() API Add a new function to allow changing of capacity of storage volumes. Plan out several flags, even if not all of them will be implemented up front. Expose the new command via 'virsh vol-resize'. 2012- 1- 20 Eric Blake API: make declaration of _LAST enum values conditional Although this is a public API break, it only affects users that were compiling against *_LAST values, and can be trivially worked around without impacting compilation against older headers, by the user defining VIR_ENUM_SENTINELS before using libvirt.h. It is not an ABI break, since enum values do not appear as .so entry points. Meanwhile, it prevents users from using non-stable enum values without explicitly acknowledging the risk of doing so. See this list discussion: https://www.redhat.com/archives/libvir-list/2012-January/msg00804.html * include/libvirt/libvirt.h.in: Hide all sentinels behind LIBVIRT_ENUM_SENTINELS, and add missing sentinels. * src/internal.h (VIR_DEPRECATED): Allow inclusion after libvirt.h. (LIBVIRT_ENUM_SENTINELS): Expose sentinels internally. * daemon/libvirtd.h: Use the sentinels. * src/remote/remote_protocol.x (includes): Don't expose sentinels. * python/generator.py (enum): Likewise. * tests/cputest.c (cpuTestCompResStr): Silence compiler warning. * tools/virsh.c (vshDomainStateReasonToString) (vshDomainControlStateToString): Likewise. 2011- 12- 29 Hu Tao domiftune: Add API virDomain{S,G}etInterfaceParameters The APIs are used to set/get domain's network interface's parameters. Currently supported parameters are bandwidth settings. * include/libvirt/libvirt.h.in: new API and parameters definition * python/generator.py: skip the Python API generation * src/driver.h: add new entry to the driver structure * src/libvirt_public.syms: export symbols 2011- 12- 29 Daniel Veillard remove a static limit on max domains in python bindings * python/libvirt-override.c: remove the predefined array in the virConnectListDomainsID binding and call virConnectNumOfDomains to do a proper allocation 2011- 12- 29 Alex Jia python: Fix problems of virDomain{Set, Get}BlockIoTune bindings The parameter 'params' is useless for virDomainGetBlockIoTune API, and the return value type should be a virTypedParameterPtr but not integer. And "PyArg_ParseTuple" in functions libvirt_virDomain{Set,Get}BlockIoTune misses format unit for "format" argument. * libvirt-override-api.xml: Remove useless the parameter 'params' from virDomainGetBlockIoTune API, and change return value type from integer to virTypedParameterPtr. * python/libvirt-override.c: Add the missed format units. RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=770683 2011- 12- 20 Hu Tao add new API virDomain{G, S}etNumaParameters Set up the types for the numa functions and insert them into the virDriver structure definition. 2011- 12- 19 Alex Jia python: plug memory leak on libvirt_virConnectOpenAuth * Detected by valgrind. Leak introduced in commit 5ab109f. * python/libvirt-override.c: avoid memory leak on libvirt_virConnectOpenAuth. * How to reproduce? % valgrind -v --leak-check=full virt-clone --print-xml Note: it can hit the issue although options are incomplete. * Actual valgrind result: ==1801== 12 bytes in 1 blocks are definitely lost in loss record 25 of 3,270 ==1801== at 0x4A05FDE: malloc (vg_replace_malloc.c:236) ==1801== by 0xCF1F60E: libvirt_virConnectOpenAuth (libvirt-override.c:1507) ==1801== by 0x3AFEEDE7F3: PyEval_EvalFrameEx (ceval.c:3794) ==1801== by 0x3AFEEDF99E: PyEval_EvalFrameEx (ceval.c:3880) ==1801== by 0x3AFEEDF99E: PyEval_EvalFrameEx (ceval.c:3880) ==1801== by 0x3AFEEDF99E: PyEval_EvalFrameEx (ceval.c:3880) ==1801== by 0x3AFEEDF99E: PyEval_EvalFrameEx (ceval.c:3880) ==1801== by 0x3AFEEE0466: PyEval_EvalCodeEx (ceval.c:3044) ==1801== by 0x3AFEEE0541: PyEval_EvalCode (ceval.c:545) ==1801== by 0x3AFEEFB88B: run_mod (pythonrun.c:1351) ==1801== by 0x3AFEEFB95F: PyRun_FileExFlags (pythonrun.c:1337) ==1801== by 0x3AFEEFCE4B: PyRun_SimpleFileExFlags (pythonrun.c:941) 2011- 12- 15 Osier Yang python: Expose blockPeek and memoryPeek in Python binding A simple example to show how to use it: \#! /usr/bin/python import os import sys import libvirt disk = "/var/lib/libvirt/images/test.img" conn = libvirt.open(None) dom = conn.lookupByName('test') mem_contents = dom.memoryPeek(0, 32, libvirt.VIR_MEMORY_VIRTUAL); sys.stdout.write(mem_contents) % python test.py | hexdump 0000000 1660 0209 0000 0000 0000 0000 0000 0000 0000010 0000 0000 0000 0000 d3a0 01d0 0000 0000 0000020 2011- 12- 13 Peter Krempa python: Fix export of virDomainSnapshotListChildrenNames Commit f2013c9dd1ce468b8620ee35c232a93ef7026fb0 added implementation of virDomainSnapshotListChildrenNames override export, but registration of the newly exported function was not added. *python/libvirt-override.c: - register export of function 2011- 12- 5 Peter Krempa python: Expose binding for virNodeGetMemoryStats() This patch adds binding for virNodeGetMemoryStats method of libvirtd. Return value is represented as a python dictionary mapping field names to values. 2011- 12- 5 Peter Krempa python: Expose binding for virNodeGetCPUStats() This patch adds binding for virNodeGetCPUStats method of libvirtd. Return value is represented as a python dictionary mapping field names to values. 2011- 11- 30 Lei Li Support virDomain{Set, Get}BlockIoTune in the python API Python support for both setting and getting block I/O throttle. 2011- 11- 30 Lei Li Add new API virDomain{Set, Get}BlockIoTune This patch add new pulic API virDomainSetBlockIoTune and virDomainGetBlockIoTune. 2011- 10- 31 Matthias Bolte python: Fix documentation of virStream recv This was fixed in be757a3f7baf93b for libvirt.c. 2011- 10- 25 Michal Privoznik startupPolicy: Emit event on disk source dropping If a disk source gets dropped because it is not accessible, mgmt application might want to be informed about this. Therefore we need to emit an event. The event presented in this patch is however a bit superset of what written above. The reason is simple: an intention to be easily expanded, e.g. on 'user ejected disk in guest' events. Therefore, callback gets source string and disk alias (which should be unique among a domain) and reason (an integer); 2011- 10- 17 Philipp Hahn Fix two comments related to error handling 2011- 10- 10 Eric Blake snapshot: new virDomainSnapshotListChildrenNames API The previous API addition allowed traversal up the hierarchy; this one makes it easier to traverse down the hierarchy. In the python bindings, virDomainSnapshotNumChildren can be generated, but virDomainSnapshotListChildrenNames had to copy from the hand-written example of virDomainSnapshotListNames. * include/libvirt/libvirt.h.in (virDomainSnapshotNumChildren) (virDomainSnapshotListChildrenNames): New prototypes. (VIR_DOMAIN_SNAPSHOT_LIST_DESCENDANTS): New flag alias. * src/libvirt.c (virDomainSnapshotNumChildren) (virDomainSnapshotListChildrenNames): New functions. * src/libvirt_public.syms: Export them. * src/driver.h (virDrvDomainSnapshotNumChildren) (virDrvDomainSnapshotListChildrenNames): New callbacks. * python/generator.py (skip_impl, nameFixup): Update lists. * python/libvirt-override-api.xml: Likewise. * python/libvirt-override.c (libvirt_virDomainSnapshotListChildrenNames): New wrapper function. 2011- 10- 10 Eric Blake maint: typo fixes I noticed a couple typos in recent commits, and fixed the remaining instances of them. * docs/internals/command.html.in: Fix spelling errors. * include/libvirt/libvirt.h.in (virConnectDomainEventCallback): Likewise. * python/libvirt-override.py (virEventAddHandle): Likewise. * src/lxc/lxc_container.c (lxcContainerChild): Likewise. * src/util/hash.c (virHashCreateFull): Likewise. * src/storage/storage_backend_logical.c (virStorageBackendLogicalMakeVol): Likewise. * src/esx/esx_driver.c (esxFormatVMXFileName): Likewise. * src/vbox/vbox_tmpl.c (vboxIIDIsEqual_v3_x): Likewise. 2011- 9- 16 Jiri Denemark python: Fix bindings generated in VPATH build 2011- 9- 15 Cole Robinson python: Fix libvirt.py generation to include virterror info Recent generator refactoring broke libvirt.py. With this patch, libvirt.py is generated exactly the same as before offending commit 9eba0d25. 2011- 9- 14 Osier Yang qemu_api: Update Makefile to generate libvirtmod_qemu lib 2011- 9- 14 Osier Yang qemu_api: Update Py binding generator to generate files for QEMU APIs It will generate: libvirt-qemu.py libvirt-qemu.h libvirt-qemu.c libvirt-qemu-export.c 2011- 9- 14 Osier Yang qemu_api: Add override XML and C files for QEMU APIs There is only one function (virDomainQemuMonitorCommand) need to be hand-craft. 2011- 9- 6 Osier Yang latency: Expose the new API for Python binding 2011- 9- 1 Jim Fehlig Add public API for getting migration speed Includes impl of python binding since the generator was not able to cope. Note: Requires gendispatch.pl patch from Matthias Bolte https://www.redhat.com/archives/libvir-list/2011-August/msg01367.html 2011- 8- 2 Eric Blake python: avoid unlikely sign extension bug Detected by Coverity; same analysis as for commit f73198df. * python/libvirt-override.c (libvirt_virDomainGetVcpuPinInfo): Use correct type. 2011- 7- 29 Matthias Bolte freebsd: Fix build problem due to picking up the wrong libvirt.h Gettext annoyingly modifies CPPFLAGS in-place, putting -I/usr/local/include into the search patch if libintl headers must be used from that location. But since we must support automake 1.9.6 which lacks AM_CPPFLAGS, and since CPPFLAGS is used prior to INCLUDES, this means that the build picks up the _old_ installed libvirt.h in priority to the in-tree version, leading to all sorts of weird build failures on FreeBSD. Fix this by teaching configure to undo gettext's actions, but to keep any changes required by gettext at the end of INCLUDES after all in-tree locations are used first. Also requires adding a wrapper Makefile.am and making gnulib-tool create just gnulib.mk files during the bootstrap process. 2011- 7- 28 Eric Blake maint: add missing copyright notices I went with the shorter license notice used by src/libvirt.c, rather than spelling out the full LGPLv2+ clause into each of these files. * configure.ac: Declare copyright. * all Makefile.am: Likewise. 2011- 7- 28 Hu Tao python: add python binding for virDomainSetMemoryParameters 2011- 7- 28 Hu Tao python: add python binding for virDomainGetMemoryParameters 2011- 7- 28 Hu Tao python: add python binding for virDomainSetBlkioParameters 2011- 7- 28 Hu Tao python: add python binding for virDomainGetBlkioParameters 2011- 7- 27 Lai Jiangshan send-key: Implement Python API 2011- 7- 26 Cole Robinson python: Properly report errors if virStreamRecv fails We only want to raise the special value -2. -1 should return None which tells the bindings to throw an exception. 2011- 7- 25 Cole Robinson python: Handle embedded NUL in stream.send data Otherwise things like volume upload are only useful with text data. 2011- 7- 25 Taku Izumi python: add Python binding for virDomainGetVcpuPinInfo API This patch adds the Python bindings for virDomainGetVcpuPinInfo API. * python/generator.py: add it to generator skip list * python/libvirt-override-api.xml: provide an override description * python/libvirt-override.c: provide an override binding implementation 2011- 7- 25 Taku Izumi python: add Python binding for virDomainPinVcpusFlags API This patch adds the Python bindings for virDomainPinVcpuFlags API. * python/generator.py: add it to the generator skip list * python/libvirt-override-api.xml: provide override description * python/libvirt-override.c: provide override bindings implementation 2011- 7- 25 Taku Izumi python: add Python binding for virDomainGetSchedulerParametersFlags API This patch adds the Python bindings for virDomainGetSchedulerParametersFlags API. 2011- 7- 25 Taku Izumi python: add Python binding for virDomainGetSchedulerParametersFlags API This patch adds the Python bindings for virDomainGetSchedulerParametersFlags API. * python/libvirt-override-api.xml: provide and override description * python/libvirt-override.c: implement the bindings 2011- 7- 22 Adam Litke Asynchronous event for BlockJob completion When an operation started by virDomainBlockPull completes (either with success or with failure), raise an event to indicate the final status. This API allow users to avoid polling on virDomainGetBlockJobInfo if they would prefer to use an event mechanism. * daemon/remote.c: Dispatch events to client * include/libvirt/libvirt.h.in: Define event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle the new event * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for block_stream completion and emit a libvirt block pull event * src/remote/remote_driver.c: Receive and dispatch events to application * src/remote/remote_protocol.x: Wire protocol definition for the event * src/remote_protocol-structs: structure definitions for protocol verification * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for BLOCK_STREAM_COMPLETED event from QEMU monitor 2011- 7- 22 Adam Litke Enable virDomainBlockPull in the python API virDomainGetBlockJobInfo requires manual override since it returns a custom type. * python/generator.py: reenable bindings for this entry point * python/libvirt-override-api.xml python/libvirt-override.c: manual overrides 2011- 7- 22 Adam Litke Add new API virDomainBlockPull* to headers Set up the types for the block pull functions and insert them into the virDriver structure definition. Symbols are exported in this patch to prevent documentation compile failures. * include/libvirt/libvirt.h.in: new API * src/driver.h: add the new entry to the driver structure * python/generator.py: fix compiler errors, the actual python bindings * are implemented later * src/libvirt_public.syms: export symbols * docs/apibuild.py: Extend 'unsigned long' parameter exception to this * API 2011- 7- 21 Matthias Bolte python: Fix makefile rule for code generation Commit 8665f85523f0451c changed generated.stamp to $(GENERATE).stamp, but missed one instance in the CLEANFILES list. This can break the build in case the generated code is deleted but the .stamp file stays around and therefore the code isn't regenerated. 2011- 7- 19 Daniel P. Berrange Quieten build & ensure API build scripts exit with non-zero status The current API build scripts will continue and exit with a zero status even if they find problems. This has been the cause of many build problems, or hidden build errors, in the past. Change the scripts so they always exit with a non-zero status for any problems they do not understand. Also turn off all debug output by default so they respect $(AM_V_GEN) * docs/Makefile.am: Use $(AM_V_GEN) for API/HTML scripts * docs/apibuild.py, python/generator.py: Exit with non-zero status if problems are found. Also be silent, not outputting any debug messages. * src/Makefile.am: Use $(AM_V_GEN) for ESX generator * python/Makefile.am: Tweak rule 2011- 7- 13 Eric Blake python: prefer unsigned flags * python/libvirt-override.c (libvirt_virConnectOpenAuth) (libvirt_virDomainSnapshotListNames) (libvirt_virDomainRevertToSnapshot): Change flags type. 2011- 7- 7 Matthias Bolte python: Fix bogus label placement 2011- 7- 1 Eric Blake build: consistently use CFLAGS According to the automake manual, CPPFLAGS (aka INCLUDES, as spelled in automake 1.9.6) should only include -I, -D, and -U directives; more generic directives like -Wall belong in CFLAGS since they affect more phases of the build process. Therefore, we should be sticking CFLAGS additions into a CFLAGS container, not a CPPFLAGS container. * src/Makefile.am (libvirt_driver_vmware_la_CFLAGS): Use AM_CFLAGS. (INCLUDES): Move CFLAGS items... (AM_CFLAGS): ...to their proper location. * python/Makefile.am (INCLUDES, AM_CFLAGS): Likewise. * tests/Makefile.am (INCLUDES, AM_CFLAGS): Likewise. (commandtest_CFLAGS, commandhelper_CFLAGS) (virnetmessagetest_CFLAGS, virnetsockettest_CFLAGS): Use AM_CFLAGS. 2011- 6- 24 Matthias Bolte python: Don't declare Py_ssize_t for Python 2.6 Commit cd48c3f4e95597 added a Py_ssize_t typedef for Python < 2.7. But Py_ssize_t was added in Python 2.5. This makes the build fail for Python 2.6. Adjust the check to match Python < 2.5 to fix this. 2011- 6- 24 Eric Blake Revert "Add new API virDomainBlockPull* to headers" This reverts commit 7d56a16d036d9aa7292e10e884c129742036f8a7. Conflicts: python/generator.py src/libvirt_public.syms 2011- 6- 24 Eric Blake Revert "Enable virDomainBlockPull in the python API." This reverts commit d74b86f5d6ecae3d18a391f90a918fcac75914db. Conflicts: python/generator.py 2011- 6- 24 Eric Blake Revert "Asynchronous event for BlockPull completion" This reverts commit 12cd77a0c58a80179182f7d09e8e73f9f66b4677. Conflicts: python/libvirt-override-virConnect.py python/libvirt-override.c src/remote/remote_protocol.x 2011- 6- 24 Eric Blake build: avoid python 2.4 build failure I'm not sure when Py_ssize_t was introduced; but Fedora 14 Python 2.7 has it, while RHEL 5 Python 2.4 lacks it. It should be easy enough to adjust if someone runs into problems. * python/typewrappers.h (Py_ssize_t): Define for older python. 2011- 6- 24 Eric Blake build: avoid python 2.4 build failure On RHEL 5, I got: /usr/bin/python ./generator.py /usr/bin/python File "./generator.py", line 427 "virStreamFree", # Needed in custom virStream __del__, but free shouldn't ^ SyntaxError: invalid syntax * python/generator.py (function_skip_python_impl): Use same syntax as other skip lists. 2011- 6- 23 Cole Robinson python: Generate virStreamFree but don't expose in bindings Turns out I was right in removing this the first time :) This is needed in our custom __del__ function, but the C code wasn't being generated. Add new infrastructure to do what we want 2011- 6- 21 Cole Robinson python: Mark event callback wrappers as private These functions aren't intended to be called directly by users, so mark them as private. While we're at it, remove unneeded exception handling, and break some long lines. 2011- 6- 21 Cole Robinson python: events: Fix C->Python handle callback prototype If registering our own event loop implementation written in python, any handles or timeouts callbacks registered by libvirt C code must be wrapped in a python function. There is some argument trickery that makes this all work, by wrapping the user passed opaque value in a tuple, along with the callback function. Problem is, the current setup requires the user's event loop to know about this trickery, rather than just treating the opaque value as truly opaque. Fix this in a backwards compatible manner, and adjust the example python event loop to do things the proper way. 2011- 6- 21 Cole Robinson python: Add bindings for virEvent*Handle/Timeout 2011- 6- 21 Cole Robinson Promote virEvent*Handle/Timeout to public API Since we virEventRegisterDefaultImpl is now a public API, callers need a way to invoke the default registered Handle and Timeout functions. We already have general functions for these internally, so promote them to the public API. v2: Actually add APIs to libvirt.h 2011- 6- 21 Cole Robinson python: Implement virStreamSend/RecvAll helpers Pure python implementation. The handler callbacks have been altered a bit compared to the C API: RecvAll doesn't pass length of the data read since that can be trivially obtained from python string objects, and SendAll requires the handler to return the string data to send rather than store the data in a string pointer. 2011- 6- 21 Cole Robinson python: Implement virStreamSend/Recv The return values for the python version are different that the C version of virStreamSend: on success we return a string, an error raises an exception, and if the stream would block we return int(-2). We need to do this since strings aren't passed by reference in python. 2011- 6- 20 Cole Robinson python: Implement bindings for virStreamEventAddCallback v2: Don't generate virStreamFree 2011- 6- 20 Cole Robinson python: generator: Don't print warning if nothing to warn about 2011- 6- 20 Cole Robinson python: libvirt-override: use simpler debug In a couple instances we have to mark a debug variable as ATTRIBUTE_UNUSED to avoid warnings. v2: Use #if 0 to comment out debug define 2011- 6- 16 Jiri Denemark Introduce virDomainGetControlInfo API The API can be used to query current state of an interface to VMM used to control a domain. In QEMU world this translates into monitor connection. 2011- 6- 15 Adam Litke Asynchronous event for BlockPull completion When an operation started by virDomainBlockPullAll completes (either with success or with failure), raise an event to indicate the final status. This allows an API user to avoid polling on virDomainBlockPullInfo if they would prefer to use the event mechanism. * daemon/remote.c: Dispatch events to client * include/libvirt/libvirt.h.in: Define event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle the new event * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for block_stream completion and emit a libvirt block pull event * src/remote/remote_driver.c: Receive and dispatch events to application * src/remote/remote_protocol.x: Wire protocol definition for the event * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for BLOCK_STREAM_COMPLETED event from QEMU monitor 2011- 6- 15 Adam Litke Enable virDomainBlockPull in the python API. virDomainBlockPullAll and virDomainBlockPullAbort are handled automatically. virDomainBlockPull and virDomainBlockPullInfo require manual overrides since they return a custom type. * python/generator.py: reenable bindings for this entry point * python/libvirt-override-api.xml python/libvirt-override.c: manual overrides Acked-by: Daniel P. Berrange 2011- 6- 15 Adam Litke Add new API virDomainBlockPull* to headers Set up the types for the block pull functions and insert them into the virDriver structure definition. Symbols are exported in this patch to prevent documentation compile failures. * include/libvirt/libvirt.h.in: new API * src/driver.h: add the new entry to the driver structure * python/generator.py: fix compiler errors, the actual python bindings are implemented later * src/libvirt_public.syms: export symbols 2011- 6- 14 Minoru Usui virNodeGetMemoryStats: Expose new API 2011- 6- 14 Minoru Usui virNodeGetCPUStats: Expose new API 2011- 6- 14 Lai Jiangshan send-key: Defining the public API Add public virDomainSendKey() and enum libvirt_keycode_set for the @codeset. Python version of virDomainSendKey() has not been implemented yet, it will be done soon. 2011- 6- 13 Hu Tao Deprecate several CURRENT/LIVE/CONFIG enums This patch deprecates following enums: VIR_DOMAIN_MEM_CURRENT VIR_DOMAIN_MEM_LIVE VIR_DOMAIN_MEM_CONFIG VIR_DOMAIN_VCPU_LIVE VIR_DOMAIN_VCPU_CONFIG VIR_DOMAIN_DEVICE_MODIFY_CURRENT VIR_DOMAIN_DEVICE_MODIFY_LIVE VIR_DOMAIN_DEVICE_MODIFY_CONFIG And modify internal codes to use virDomainModificationImpact. 2011- 6- 8 Eric Blake python: avoid unlikely sign extension bug Detected by Coverity. cpumap was allocated with a value of (unsigned short)*(int), which is an int computation, and then promotes to size_t. On a 64-bit platform, this fails if bit 32 of the product is set (because of sign extension giving a HUGE value to malloc), even though a naive programmer would assume that since the first value is unsigned, the product is also unsigned and at most 4GB would be allocated. Won't bite in practice (the product should never be that large), but worth using the right types to begin with, so that we are now computing (unsigned short)*(size_t). * python/libvirt-override.c (libvirt_virDomainGetVcpus): Use correct type. 2011- 5- 29 Daniel P. Berrange Introduce a new event emitted when a virtualization failure occurs This introduces a new domain VIR_DOMAIN_EVENT_ID_CONTROL_ERROR Which uses the existing generic callback typedef void (*virConnectDomainEventGenericCallback)(virConnectPtr conn, virDomainPtr dom, void *opaque); This event is intended to be emitted when there is a failure in some part of the domain virtualization system. Whether the domain continues to run/exist after the failure is an implementation detail specific to the hypervisor. The idea is that with some types of failure, hypervisors may prefer to leave the domain running in a "degraded" mode of operation. For example, if something goes wrong with the QEMU monitor, it is possible to leave the guest OS running quite happily. The mgmt app will simply loose the ability todo various tasks. The mgmt app can then choose how/when to deal with the failure that occured. * daemon/remote.c: Dispatch of new event * examples/domain-events/events-c/event-test.c: Demo catch of event * include/libvirt/libvirt.h.in: Define event ID and callback * src/conf/domain_event.c, src/conf/domain_event.h: Internal event handling * src/remote/remote_driver.c: Receipt of new event from daemon * src/remote/remote_protocol.x: Wire protocol for new event * src/remote_protocol-structs: add new event for checks 2011- 5- 29 Eric Blake sched: introduce virDomainGetSchedulerParametersFlags If we can choose live or config when setting, then we need to be able to choose which one we are querying. Also, make the documentation clear that set must use a non-empty subset (some of the hypervisors fail if params is NULL). * include/libvirt/libvirt.h.in (virDomainGetSchedulerParametersFlags): New prototype. * src/libvirt.c (virDomainGetSchedulerParametersFlags): Implement it. * src/libvirt_public.syms: Export it. * python/generator.py (skip_impl): Don't auto-generate. * src/driver.h (virDrvDomainGetSchedulerParametersFlags): New callback. 2011- 5- 29 Eric Blake libvirt.h: avoid regression, and document preferred name Commit 824dcaff was a regression (thankfully unreleased) for any client code that used 'struct _virSchedParameter' directly rather than the preferred virSchedParameter typedef. Adding a #define avoids even that API change, while rearranging the file makes it clear what the old vs. new API is. * include/libvirt/libvirt.h.in: Rearrange older names to the bottom and improve documentation on preferred names. (virDomainGetSchedulerParameters, virDomainSetSchedulerParameters) (virDomainSetSchedulerParametersFlags) (virDomainSetBlkioParameters, virDomainGetBlkioParameters) (virDomainSetMemoryParameters, virDomainGetMemoryParameters): Use newer type names. * python/libvirt-override.c: Adjust code generation to cope. Suggested by Daniel P. Berrange. 2011- 5- 24 Michal Privoznik python: Don't free must-not-free variables py_str() function call PyString_AsString(). As written in documentation, the caller must not free the returned value, because it points to some internal structures. 2011- 5- 23 Michal Privoznik python: Fix typo in bindings This typo caused a bug in which we wanted to free() invalid pointer. 2011- 5- 18 Eric Blake libvirt.h: consolidate typed parameter handling The new type is identical to the three old types that it replaces, and by creating a common type, this allows future patches to share common code that manipulates typed parameters. This change is backwards-compatible in API (recompilation works without any edits) and ABI (an older client that has not been recompiled uses the same layout) for code using only public names; only code using private names (those beginning with _) will have to adapt. * include/libvirt/libvirt.h.in (virTypedParameterType) (VIR_TYPED_PARAM_FIELD_LENGTH, _virTypedParameter): New enum, macro, and type. (virSchedParameter, virBlkioParameter, virMemoryParameter): Rewrite in terms of a common type, while keeping all old public names for backwards compatibility. (struct _virSchedParameter, struct _virBlkioParameter) (struct _virMemoryParameter): Delete - these are private names. * python/generator.py (enum): Cope with the refactoring. 2011- 5- 17 Hu Tao introduce virDomainSetSchedulerParametersFlags This new function allows aditional flags to be passed into from the virsh command line. 2011- 5- 16 Jiri Denemark virDomainGetState public API This API is supposed to replace virDomainGetInfo when the only purpose of calling it is getting current domain status. 2011- 3- 14 Jiri Denemark python: Use hardcoded python path in libvirt.py This partially reverts (and fixes that part in a different way) commit e4384459c93e3e786aa483c7f077d1d22148f689, which replaced ``/usr/bin/python'' with ``/usr/bin/env python'' in all examples or scripts used during build to generate other files. However, python bindings module is compiled and linked against a specific python discovered or explicitly provided in configure phase. Thus libvirt.py, which is generated and installed into the system, should use the same python binary for which the module has been built. The hunk in Makefile.am replaces $(srcdir) with $(PYTHON), which might seem wrong but it is not. generator.py didn't use any of its command line arguments so passing $(srcdir) to it was redundant. 2011- 3- 11 Gui Jianfeng libvirt: add virDomain{Get,Set}BlkioParameters Add virDomainSetBlkioParameters virDomainGetBlkioParameters 2011- 2- 21 Eric Blake maint: fix grammar in error message * python/tests/create.py: Use correct wording. 2011- 2- 18 Jiri Denemark maint: Expand tabs in python code Also cfg.mk is tweaked to force this for all future changes to *.py files. 2011- 1- 10 Cole Robinson python: Use PyCapsule API if available On Fedore 14, virt-manager spews a bunch of warnings to the console: /usr/lib64/python2.7/site-packages/libvirt.py:1781: PendingDeprecationWarning: The CObject type is marked Pending Deprecation in Python 2.7. Please use capsule objects instead. Have libvirt use the capsule API if available. I've verified this compiles fine on older python (2.6 in RHEL6 which doesn't have capsules), and virt-manager seems to function fine. 2010- 11- 14 Matthias Bolte Use python discovered through env instead of hardcoding a path This is more flexible regarding the location of the python binary but doesn't allow to pass the -u flag. The -i flag can be passed from inside the script using the PYTHONINSPECT env variable. This fixes a problem with the esx_vi_generator.py on FreeBSD. 2010- 10- 12 Matthias Bolte Fix several minor problems introduced by the memtune series Add proper documentation to the new VIR_DOMAIN_MEMORY_* macros in libvirt.h.in to placate apibuild.py. Mark args as unused in for libvirt_virDomain{Get,Set}MemoryParameters in the Python bindings and add both to the libvirtMethods array. Update remote_protocol-structs to placate make syntax-check. Undo unintended modifications in vboxDomainGetInfo. Update the function table of the VirtualBox and XenAPI drivers. 2010- 10- 12 Nikunj A. Dadhania Adding structure and defines for virDomainSet/GetMemoryParameters This patch adds a structure virMemoryParameter, it contains the name of the parameter and the type of the parameter along with a union. dv: + rename enums to VIR_DOMAIN_MEMORY_PARAM_* + remove some extraneous tabs v4: + Add unsigned int flags to the public api for future extensions v3: + Protoype for virDomainGetMemoryParameters and dummy python binding. v2: + Includes dummy python bindings for the library to build cleanly. + Define string constants like "hard_limit", etc. + re-order this patch. 2010- 9- 27 Dan Kenigsberg python: drop unnecessary conn assignment Since 554d82a200289938d5639a782a9f12e3e2e968f0, conn is unused. Let's drop it - but keep the signature of the constructor for backward compatibility. 2010- 7- 23 Philipp Hahn Fix SEGV on exit after domainEventDeregister() When the last callback is removed using domainEventDeregister(), the events dispatcher is deregistered from the C-library, but domainEventsCallbacks is still an empty list. On shutdown __del__() deregisters the dispatacher again, which SEGVs # You need the event-loop implementation from the Python examples; # give the file a name which is importable by Python. ln examples/domain-events/events-python/event-test.py eloop.py python -c 'from eloop import * import sys def dump(*args): print " ".join(map(str, args)) virEventLoopPureStart() c = libvirt.open("xen:///") c.domainEventRegister(dump, None) c.domainEventDeregister(dump) sys.exit(0)' domainEventDeregister() needs to delete domainEventCallbacks so subsequent calls to __del__() and domainEventRegister() choose the right code paths. Setting it to None is not enough, since calling domainEventRegiser() again would trigger an TypeError. 2010- 7- 14 Cole Robinson python: Fix IOErrorReasonCallback bindings A copy and paste error was causing us to dispatch the incorrect routine. Spotted by Dan Kenigsberg. 2010- 7- 12 Daniel P. Berrange Ensure we return the callback ID in python events binding A missing return statement in the python binding meant that the callers could not get the callback ID, and thus not be able to unregister event callbacks * python/libvirt-override-virConnect.py: Add missing return statement 2010- 6- 25 Daniel P. Berrange Add missing parameter in python Disk IO error callback The IO error callback was forgetting to pass the action parameter, causing a stack trace when IO errors arrive * python/libvirt-override-virConnect.py: Add missing action parameter in IO error callback 2010- 6- 18 Philipp Hahn Fix description of virStorageVolGetInfo() Probably a copy-paste-bug in python/libvirt-override-api.xml: virStorageVolGetInfo() extracts information about a "storage volume", not the "storage pool" as virStoragePoolGetInfo() does. 2010- 6- 15 Eric Blake maint: simplify some ignore files * .hgignore: Delete, no longer used. * examples/python/.gitignore: Delete, covered globally. * include/.gitignore: Likewise. * python/tests/.gitignore: Likewise. * docs/schemas/.gitignore: Likewise. * tests/xml2sexprdata/.gitignore: Likewise. * tests/sexpr2xmldata/.gitignore: Likewise. * tests/confdata/.gitignore: Likewise. * tests/xencapsdata/.gitignore: Likewise. * tests/xmconfigdata/.gitignore: Likewise. * tests/xml2sexprdata/.gitignore: Likewise. 2010- 5- 20 Chris Lalancette Fix up the python bindings for snapshotting. This involved a few fixes. To start with, an virDomainSnapshot object is really tied to a domain, not a connection, so we have to generate a slightly different object so that we can get at self._dom for the object. Next, we had to "dummy" up an override piece of XML with a bogus argument that the function doesn't actually take. That's so that the generator places virDomainRevertToSnapshot underneath the correct class (namely, the virDomain class). Finally, we had to hand-implement the virDomainRevertToSnapshot implementation, ignoring the bogus pointer we are being passed. With all of this in place, I was able to successfully take a snapshot and revert to it using only the Python bindings. 2010- 5- 18 Jim Meyering python: don't ignore virInitialize failure in module initialization * python/libvirt-override.c (initlibvirtmod): Upon virInitialize failure, skip the Py_InitModule call. 2010- 4- 30 Daniel P. Berrange Add support for another explicit IO error event This introduces a new event type VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR event, but also includes a string describing the cause of the event. Thus there is a new callback definition for this event type typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn, virDomainPtr dom, const char *srcPath, const char *devAlias, int action, const char *reason, void *opaque); This is currently wired up to the QEMU block IO error events * daemon/remote.c: Dispatch IO error events to client * examples/domain-events/events-c/event-test.c: Watch for IO error events * include/libvirt/libvirt.h.in: Define new IO error event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle IO error events * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for block IO errors and emit a libvirt IO error event * src/remote/remote_driver.c: Receive and dispatch IO error events to application * src/remote/remote_protocol.x: Wire protocol definition for IO error events * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event from QEMU monitor 2010- 4- 29 Daniel P. Berrange Implement python binding for virDomainGetBlockInfo This binds the virDomainGetBlockInfo API to python's blockInfo method on the domain object >>> c = libvirt.openReadOnly('qemu:///session') >>> d = c.lookupByName('demo') >>> f = d.blockInfo("/dev/loop0", 0) >>> print f [1048576000L, 104857600L, 104857600L] * python/libvirt-override-api.xml: Define override signature * python/generator.py: Skip C impl generator for virDomainGetBlockInfo * python/libvirt-override.c: Manual impl of virDomainGetBlockInfo 2010- 4- 29 Stefan Berger nwfilter: python bindings for nwfilter I have primarily followed the pattern of the 'secret' driver to provide support for the missing python bindings for the network filter API. 2010- 4- 20 Philipp Hahn Don't ship generated python/libvirt.? files. libvirt.c and libvirt.h are auto-generated files. Mentioning their names in *_SOURCES includes them in the distribution. During an out-of-tree build these shipped files are included instead of the auto-generated version, potentially breaking the build (as it happend in 0.8.0, because the shipped libvirt.h was missing the declaration for 'libvirt_virDomainUpdateDeviceFlags') Use the nodist_*_SOURCES automake variable instead. 2010- 4- 20 Daniel P. Berrange Fixup python binding for virDomainSnapshot APIs The generator code was totally wrong for the virDomainSnapshot APIs, not generating the wrapper class, and giving methods the wrong names * generator.py: Set metadata for virDomainSnapshot type & APIs * libvirt-override-api.xml, libvirt-override.c: Hand-code the virDomainSnapshotListNames glue layer 2010- 4- 9 Daniel P. Berrange More event callback fixes In a couple of cases typos meant we were firing the wrong type of event. In the python code my previous commit accidentally missed some chunks of the code. * python/libvirt-override-virConnect.py: Add missing python glue accidentally left out of previous commit * src/conf/domain_event.c, src/qemu/qemu_monitor_json.c: Fix typos in event name / method name to invoke 2010- 4- 8 Daniel P. Berrange Fix up python bindings for new event callbacks The generator was disabled for the new event callbacks, since they need to be hand written. This patch adds the C and python glue to expose the new APIs in the python binding. The python example program is extended to demonstrate of the code * python/libvirt-override.c: Registration and dispatch of events at the C layer * python/libvirt-override-virConnect.py: Python glue for events * examples/domain-events/events-python/event-test.py: Demo use of new event callbacks 2010- 4- 5 Chris Lalancette Snapshot API framework. 2010- 3- 26 Stefan Berger Core driver implementation with ebtables support This patch implements the core driver and provides - management functionality for managing the filter XMLs - compiling the internal filter representation into ebtables rules - applying ebtables rules on a network (tap,macvtap) interface - tearing down ebtables rules that were applied on behalf of an interface - updating of filters while VMs are running and causing the firewalls to be rebuilt - other bits and pieces 2010- 3- 26 Daniel P. Berrange Add domain events for graphics network clients This introduces a new event type VIR_DOMAIN_EVENT_ID_GRAPHICS The same event can be emitted in 3 scenarios typedef enum { VIR_DOMAIN_EVENT_GRAPHICS_CONNECT = 0, VIR_DOMAIN_EVENT_GRAPHICS_INITIALIZE, VIR_DOMAIN_EVENT_GRAPHICS_DISCONNECT, } virDomainEventGraphicsPhase; Connect/disconnect are triggered at socket accept/close. The initialize phase is immediately after the protocol setup and authentication has completed. ie when the client is authorized and about to start interacting with the graphical desktop This event comes with *a lot* of potential information - IP address, port & address family of client - IP address, port & address family of server - Authentication scheme (arbitrary string) - Authenticated subject identity. A subject may have multiple identities with some authentication schemes. For example, vencrypt+sasl results in a x509dname and saslUsername identities. This results in a very complicated callback :-( typedef enum { VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV4, VIR_DOMAIN_EVENT_GRAPHICS_ADDRESS_IPV6, } virDomainEventGraphicsAddressType; struct _virDomainEventGraphicsAddress { int family; const char *node; const char *service; }; typedef struct _virDomainEventGraphicsAddress virDomainEventGraphicsAddress; typedef virDomainEventGraphicsAddress *virDomainEventGraphicsAddressPtr; struct _virDomainEventGraphicsSubject { int nidentity; struct { const char *type; const char *name; } *identities; }; typedef struct _virDomainEventGraphicsSubject virDomainEventGraphicsSubject; typedef virDomainEventGraphicsSubject *virDomainEventGraphicsSubjectPtr; typedef void (*virConnectDomainEventGraphicsCallback)(virConnectPtr conn, virDomainPtr dom, int phase, virDomainEventGraphicsAddressPtr local, virDomainEventGraphicsAddressPtr remote, const char *authScheme, virDomainEventGraphicsSubjectPtr subject, void *opaque); The wire protocol is similarly complex struct remote_domain_event_graphics_address { int family; remote_nonnull_string node; remote_nonnull_string service; }; const REMOTE_DOMAIN_EVENT_GRAPHICS_IDENTITY_MAX = 20; struct remote_domain_event_graphics_identity { remote_nonnull_string type; remote_nonnull_string name; }; struct remote_domain_event_graphics_msg { remote_nonnull_domain dom; int phase; remote_domain_event_graphics_address local; remote_domain_event_graphics_address remote; remote_nonnull_string authScheme; remote_domain_event_graphics_identity subject; }; This is currently implemented in QEMU for the VNC graphics protocol, but designed to be usable with SPICE graphics in the future too. * daemon/remote.c: Dispatch graphics events to client * examples/domain-events/events-c/event-test.c: Watch for graphics events * include/libvirt/libvirt.h.in: Define new graphics event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle graphics events * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for VNC events and emit a libvirt graphics event * src/remote/remote_driver.c: Receive and dispatch graphics events to application * src/remote/remote_protocol.x: Wire protocol definition for graphics events * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for VNC_CONNECTED, VNC_INITIALIZED & VNC_DISCONNETED events from QEMU monitor 2010- 3- 26 Daniel P. Berrange Add support for an explicit IO error event This introduces a new event type VIR_DOMAIN_EVENT_ID_IO_ERROR This event includes the action that is about to be taken as a result of the watchdog triggering typedef enum { VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0, VIR_DOMAIN_EVENT_IO_ERROR_PAUSE, VIR_DOMAIN_EVENT_IO_ERROR_REPORT, } virDomainEventIOErrorAction; In addition it has the source path of the disk that had the error and its unique device alias. It does not include the target device name (/dev/sda), since this would preclude triggering IO errors from other file backed devices (eg serial ports connected to a file) Thus there is a new callback definition for this event type typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn, virDomainPtr dom, const char *srcPath, const char *devAlias, int action, void *opaque); This is currently wired up to the QEMU block IO error events * daemon/remote.c: Dispatch IO error events to client * examples/domain-events/events-c/event-test.c: Watch for IO error events * include/libvirt/libvirt.h.in: Define new IO error event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle IO error events * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for block IO errors and emit a libvirt IO error event * src/remote/remote_driver.c: Receive and dispatch IO error events to application * src/remote/remote_protocol.x: Wire protocol definition for IO error events * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event from QEMU monitor 2010- 3- 26 Daniel P. Berrange Add support for an explicit watchdog event This introduces a new event type VIR_DOMAIN_EVENT_ID_WATCHDOG This event includes the action that is about to be taken as a result of the watchdog triggering typedef enum { VIR_DOMAIN_EVENT_WATCHDOG_NONE = 0, VIR_DOMAIN_EVENT_WATCHDOG_PAUSE, VIR_DOMAIN_EVENT_WATCHDOG_RESET, VIR_DOMAIN_EVENT_WATCHDOG_POWEROFF, VIR_DOMAIN_EVENT_WATCHDOG_SHUTDOWN, VIR_DOMAIN_EVENT_WATCHDOG_DEBUG, } virDomainEventWatchdogAction; Thus there is a new callback definition for this event type typedef void (*virConnectDomainEventWatchdogCallback)(virConnectPtr conn, virDomainPtr dom, int action, void *opaque); * daemon/remote.c: Dispatch watchdog events to client * examples/domain-events/events-c/event-test.c: Watch for watchdog events * include/libvirt/libvirt.h.in: Define new watchdg event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle watchdog events * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for watchdogs and emit a libvirt watchdog event * src/remote/remote_driver.c: Receive and dispatch watchdog events to application * src/remote/remote_protocol.x: Wire protocol definition for watchdog events * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for WATCHDOG event from QEMU monitor 2010- 3- 26 Daniel P. Berrange Add support for an explicit RTC change event This introduces a new event type VIR_DOMAIN_EVENT_ID_RTC_CHANGE This event includes the new UTC offset measured in seconds. Thus there is a new callback definition for this event type typedef void (*virConnectDomainEventRTCChangeCallback)(virConnectPtr conn, virDomainPtr dom, long long utcoffset, void *opaque); If the guest XML configuration for the is set to offset='variable', then the XML will automatically be updated with the new UTC offset value. This ensures that during migration/save/restore the new offset is preserved. * daemon/remote.c: Dispatch RTC change events to client * examples/domain-events/events-c/event-test.c: Watch for RTC change events * include/libvirt/libvirt.h.in: Define new RTC change event ID and callback signature * src/conf/domain_event.c, src/conf/domain_event.h, src/libvirt_private.syms: Extend API to handle RTC change events * src/qemu/qemu_driver.c: Connect to the QEMU monitor event for RTC changes and emit a libvirt RTC change event * src/remote/remote_driver.c: Receive and dispatch RTC change events to application * src/remote/remote_protocol.x: Wire protocol definition for RTC change events * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, src/qemu/qemu_monitor_json.c: Watch for RTC_CHANGE event from QEMU monitor 2010- 3- 26 Daniel P. Berrange Introduce a new public API for domain events The current API for domain events has a number of problems - Only allows for domain lifecycle change events - Does not allow the same callback to be registered multiple times - Does not allow filtering of events to a specific domain This introduces a new more general purpose domain events API typedef enum { VIR_DOMAIN_EVENT_ID_LIFECYCLE = 0, /* virConnectDomainEventCallback */ ...more events later.. } int virConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, /* Optional, to filter */ int eventID, virConnectDomainEventGenericCallback cb, void *opaque, virFreeCallback freecb); int virConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID); Since different event types can received different data in the callback, the API is defined with a generic callback. Specific events will each have a custom signature for their callback. Thus when registering an event it is neccessary to cast the callback to the generic signature eg int myDomainEventCallback(virConnectPtr conn, virDomainPtr dom, int event, int detail, void *opaque) { ... } virConnectDomainEventRegisterAny(conn, NULL, VIR_DOMAIN_EVENT_ID_LIFECYCLE, VIR_DOMAIN_EVENT_CALLBACK(myDomainEventCallback) NULL, NULL); The VIR_DOMAIN_EVENT_CALLBACK() macro simply does a "bad" cast to the generic signature * include/libvirt/libvirt.h.in: Define new APIs for registering domain events * src/driver.h: Internal driver entry points for new events APIs * src/libvirt.c: Wire up public API to driver API for events APIs * src/libvirt_public.syms: Export new APIs * src/esx/esx_driver.c, src/lxc/lxc_driver.c, src/opennebula/one_driver.c, src/openvz/openvz_driver.c, src/phyp/phyp_driver.c, src/qemu/qemu_driver.c, src/remote/remote_driver.c, src/test/test_driver.c, src/uml/uml_driver.c, src/vbox/vbox_tmpl.c, src/xen/xen_driver.c, src/xenapi/xenapi_driver.c: Stub out new API entries 2010- 3- 17 Philip Hahn python: Fix networkLookupByUUID According to: http://libvirt.org/html/libvirt-libvirt.html#virNetworkLookupByUUID virNetworkLookupByUUID() expects a virConnectPtr as its first argument, thus making it a method of the virConnect Python class. Currently it's a method of libvirt.virNetwork. @@ -805,13 +805,6 @@ class virNetwork: if ret == -1: raise libvirtError ('virNetworkGetAutostart() failed', net=self) return ret - def networkLookupByUUID(self, uuid): - """Try to lookup a network on the given hypervisor based on its UUID. """ - ret = libvirtmod.virNetworkLookupByUUID(self._o, uuid) - if ret is None:raise libvirtError('virNetworkLookupByUUID() failed', net=self) - __tmp = virNetwork(self, _obj=ret) - return __tmp - class virInterface: def __init__(self, conn, _obj=None): self._conn = conn @@ -1689,6 +1682,13 @@ class virConnect: __tmp = virDomain(self,_obj=ret) return __tmp + def networkLookupByUUID(self, uuid): + """Try to lookup a network on the given hypervisor based on its UUID. """ + ret = libvirtmod.virNetworkLookupByUUID(self._o, uuid) + if ret is None:raise libvirtError('virNetworkLookupByUUID() failed', conn=self) + __tmp = virNetwork(self, _obj=ret) + return __tmp + 2010- 3- 9 Eric Blake build: consistently indent preprocessor directives * global: patch created by running: for f in $(git ls-files '*.[ch]') ; do cppi $f > $f.t && mv $f.t $f done 2010- 3- 2 Daniel P. Berrange Introduce public API for domain async job handling Introduce a new public API that provides a way to get progress info on currently running jobs on a virDomainpPtr. APIs that are initially within scope of this idea are virDomainMigrate virDomainMigrateToURI virDomainSave virDomainRestore virDomainCoreDump These all take a potentially long time and benefit from monitoring. The virDomainJobInfo struct allows for various pieces of information to be reported - Percentage completion - Time - Overall data - Guest memory data - Guest disk/file data * include/libvirt/libvirt.h.in: Add virDomainGetJobInfo * python/generator.py, python/libvirt-override-api.xml, python/libvirt-override.c: Override for virDomainGetJobInfo API * python/typewrappers.c, python/typewrappers.h: Introduce wrapper for unsigned long long type 2010- 2- 17 Cole Robinson python: Actually add virConnectGetVersion to generated bindings The recent commit to implement a python version of this function didn't drop an explicit 'ignore' check in the generator, so this never ended up in the bindings. 2010- 2- 16 Jim Meyering libvirt-override.c: avoid a leak upon call with invalid argument * python/libvirt-override.c (libvirt_virConnectBaselineCPU): Don't leak the xmlcpus buffer upon encountering a non-string list element. 2010- 2- 12 Jiri Denemark virConnectBaselineCPU public API 2010- 1- 22 Taizo ITO Add virConnectGetVersion Python API adds a new python API call for retrieving the running hypervisor version used by a connection: virConnectGetVersion * python/generator.py: skip virConnectGetVersion from autogenerated * python/libvirt-override-api.xml python/libvirt-override.c: define direct native bindings 2010- 1- 18 Jim Meyering gnulib added a new syntax-check test: use $(VAR), not @VAR@ The latter is not officially "wrong", but *is* terribly anachronistic. I think automake documentation or comments call that syntax obsolescent. * cfg.mk (_makefile_at_at_check_exceptions): Exempt @SCHEMADIR@ and @SYSCONFDIR@ uses -- there are no Makefile variables for those. * docs/Makefile.am: Use $(INSTALL), not @INSTALL@. * examples/dominfo/Makefile.am: Similar. * examples/domsuspend/Makefile.am: Similar. * proxy/Makefile.am: Similar. * python/Makefile.am: Similar. * python/tests/Makefile.am: Similar. * src/Makefile.am: Similar. * tests/Makefile.am: Similar. 2010- 1- 6 Diego Elio Pettenò Disable building of static Python module * python/Makefile.am: python modules are loaded at runtime so the static version is not needed, avoid building it 2009- 12- 20 Adam Litke python: Add python bindings for virDomainMemoryStats Enable virDomainMemoryStats in the python API. dom.memoryStats() will return a dictionary containing the supported statistics. A dictionary is required because the meaining of each quantity cannot be inferred from its index in a list. * python/generator.py: reenable bindings for this entry point * python/libvirt-override-api.xml python/libvirt-override.c: the generator can't handle this new function, add the new binding, and the XML description 2009- 12- 20 Adam Litke Add new API virDomainMemoryStats to header and drivers Set up the types for the domainMemoryStats function and insert it into the virDriver structure definition. Because of static initializers, update every driver and set the new field to NULL. * include/libvirt/libvirt.h.in: new API * src/driver.h src/*/*_driver.c src/vbox/vbox_tmpl.c: add the new entry to the driver structure * python/generator.py: fix compiler errors, the actual python binding is implemented later 2009- 12- 14 Matthias Bolte Fix install location for Python bindings Commit 66137344feb488ea87b0d92f3c03844d9a7a7786 changed the Python detection mechanism in configure to use AM_PATH_PYTHON. This results in a changed install location for the Python bindings, at least on Fedora 12 64bit systems. Before this commit libvirt.py and libvirtmod.so were installed to /usr/lib64/python2.6/site-packages After this commit they are installed to /usr/lib/python2.6/site-packages Mixed Python packages (containing *.py and *.so files) should be installed to the pyexecdir directory detected by AM_PATH_PYTHON. This restores the install location from before the AM_PATH_PYTHON commit. * configure.in: remove unnecessary pythondir export * python/Makefile.am: switch from pythondir to pyexecdir 2009- 12- 8 Matthias Bolte Use AM_PATH_PYTHON and python-config to detect Python configuration Using AM_PATH_PYTHON solves the site-packages directory problem. At least in Ubuntu with Python 2.6 and later site-packages is renamed to dist-packages and site-packages is not part of sys.path anymore. So installing the libvirt Python bindings to site-packages renders them unusable, because they can be imported from there without manually including site-packages into sys.path. AM_PATH_PYTHON detects the correct site-packages/dist-packages directory. python-config --includes gives the correct include path for the Python header files. The old probing code stays there as fallback mechanism. * configure.in: use AM_PATH_PYTHON and python-config * python/Makefile.am: remove -I because PYTHON_INCLUDES contains it now 2009- 11- 26 Daniel P. Berrange Fix threading problems in python bindings * libvirt-override.c: Add many missing calls to allow threading when entering C code, otherwise python blocks & then deadlocks when we have an async event to dispatch back into python code. Fix return value check for virDomainPinVcpu binding. 2009- 11- 20 Cole Robinson python: Actually implement list*Interfaces bindings * python/generator.py python/libvirt-override-api.xml python/libvirt-override.c: implement the bindings for virConnectListInterfaces() and virConnectListDefinedInterfaces() 2009- 11- 12 Cole Robinson Add virConnectGetLibvirtVersion API There is currently no way to determine the libvirt version of a remote libvirtd we are connected to. This is a useful piece of data to enable feature detection. 2009- 11- 3 Dan Kenigsberg give up python interpreter lock before calling cb suggested by danpb on irc, patch by danken fixed for proper C syntax * python/libvirt-override.c: on event callback release the python interpreter lock and take it again when coming back so that the callback can reinvoke libvirt. 2009- 10- 5 Cole Robinson python: Add a newline after custom classes In the generated bindings, custom classes are squashed against the following class, which hurts readability. 2009- 10- 5 Cole Robinson python: Fix generated virInterface method names A mistake in the generator was causing virInterface methods to be generated with unpredicatable names ('ceUndefine', instead of just 'undefine'). This fixes the method names to match existing convention. Does anyone care if we are breaking API compat? My guess is that no one is using the python interface bindings yet. 2009- 10- 5 Cole Robinson python: Use a pure python implementation of 'vir*GetConnect' The API docs explictly warn that we shouldn't use the C vir*GetConnect calls in bindings: doing so can close the internal connection pointer and cause things to get screwy. Implement these calls in python. 2009- 10- 5 Cole Robinson python: Don't generate bindings for vir*Ref They are only for use in implementing the bindings, so shouldn't be exposed to regular API users. 2009- 10- 5 Cole Robinson python: Don't generate conflicting conn.createXML functions. A special case in the generator wasn't doing its job, and duplicate conn.createXML functions were being generated. The bindings diff is: @@ -1079,14 +1079,6 @@ class virConnect: return __tmp def createXML(self, xmlDesc, flags): - """Create a new device on the VM host machine, for example, - virtual HBAs created using vport_create. """ - ret = libvirtmod.virNodeDeviceCreateXML(self._o, xmlDesc, flags) - if ret is None:raise libvirtError('virNodeDeviceCreateXML() failed', conn=self) - __tmp = virNodeDevice(self, _obj=ret) - return __tmp - - def createXML(self, xmlDesc, flags): """Launch a new guest domain, based on an XML description similar to the one returned by virDomainGetXMLDesc() This function may requires privileged access to the hypervisor. @@ -1327,6 +1319,14 @@ class virConnect: __tmp = virNetwork(self, _obj=ret) return __tmp + def nodeDeviceCreateXML(self, xmlDesc, flags): + """Create a new device on the VM host machine, for example, + virtual HBAs created using vport_create. """ + ret = libvirtmod.virNodeDeviceCreateXML(self._o, xmlDesc, flags) + if ret is None:raise libvirtError('virNodeDeviceCreateXML() failed', conn=self) + __tmp = virNodeDevice(self, _obj=ret) + return __tmp + def nodeDeviceLookupByName(self, name): """Lookup a node device by its name. """ ret = libvirtmod.virNodeDeviceLookupByName(self._o, name) 2009- 10- 5 Cole Robinson python: Remove use of xmllib in generator.py xmllib has been deprecated since python 2.0, and running the generator throws a warning. Move to using xml.sax 2009- 10- 5 Cole Robinson python: Remove FastParser from generator. FastParser uses sgmlop, a non-standard python module meant as a replacement for xmllib (which is deprecated since python 2.0). Fedora doesn't even carry this module, and the generator doesn't have high performance requirements, so just rip the code out. 2009- 9- 29 Daniel P. Berrange Add public API definition for data stream handling * include/libvirt/libvirt.h.in: Public API contract for virStreamPtr object * src/libvirt_public.syms: Export data stream APIs * src/libvirt_private.syms: Export internal helper APIs * src/libvirt.c: Data stream API driver dispatch * src/datatypes.h, src/datatypes.c: Internal helpers for virStreamPtr object * src/driver.h: Define internal driver API for streams * .x-sc_avoid_write: Ignore src/libvirt.c because it trips up on comments including write() * python/Makefile.am: Add libvirt-override-virStream.py * python/generator.py: Add rules for virStreamPtr class * python/typewrappers.h, python/typewrappers.c: Wrapper for virStreamPtr * docs/libvirt-api.xml, docs/libvirt-refs.xml: Regenerate with new APIs 2009- 9- 28 Daniel P. Berrange Fix API doc extractor to stop munging comment formatting The python method help docs are copied across from the C funtion comments, but in the process all line breaks and indentation was being lost. This made the resulting text and code examples completely unreadable. Both the API doc extractor and the python generator were destroying whitespace & this fixes them to preserve it exactly. * docs/apibuild.py: Preserve all whitespace when extracting function comments. Print function comment inside a Misc syntax-check fixes 2009- 9- 21 Daniel P. Berrange Re-arrange python generator to make it clear what's auto-generated * README: New file describing what each file is used for * livvirt-override.c, libvirt-override.py, libvirt-override-api.xml, libvirt-override-virConnect.py: Manually written code overriding the generator * typewrappers.c, typewrappers.h: Data type wrappers * generator.py: Automatically pre-prend contents of libvirt-override.py to generated libvirt.py. Output into libvirt.py directly instead of libvirtclass.py. Don't generate libvirtclass.txt at all. Write C files into libvirt.c/.h directly * Makefile.am: Remove rule for creating libvirt.py from libvirt-override.py and libvirtclass.py, since generator.py does it directly 2009- 9- 14 Daniel P. Berrange Add usage type/id as a public API property of virSecret * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in: Add virSecretGetUsageType, virSecretGetUsageID and virLookupSecretByUsage * python/generator.py: Mark virSecretGetUsageType, virSecretGetUsageID as not throwing exceptions * qemud/remote.c: Implement dispatch for virLookupSecretByUsage * qemud/remote_protocol.x: Add usage type & ID as attributes of remote_nonnull_secret. Add RPC calls for new public APIs * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.c, src/datatypes.h: Add usageType and usageID as properties of virSecretPtr * src/driver.h: Add virLookupSecretByUsage driver entry point * src/libvirt.c: Implement virSecretGetUsageType, virSecretGetUsageID and virLookupSecretByUsage * src/libvirt_public.syms: Export virSecretGetUsageType, virSecretGetUsageID and virLookupSecretByUsage * src/remote_internal.c: Implement virLookupSecretByUsage entry * src/secret_conf.c, src/secret_conf.h: Remove the virSecretUsageType enum, now in public API. Make volume path mandatory when parsing XML * src/secret_driver.c: Enforce usage uniqueness when defining secrets. Implement virSecretLookupByUsage api method * src/virsh.c: Include usage for secret-list command 2009- 9- 14 Daniel P. Berrange Fix UUID handling in secrets/storage encryption APIs Convert all the secret/storage encryption APIs / wire format to handle UUIDs in raw format instead of non-canonical printable format. Guarentees data format correctness. * docs/schemas/storageencryption.rng: Make UUID mandatory for a secret and validate fully * docs/schemas/secret.rng: Fully validate UUID * include/libvirt/libvirt.h, include/libvirt/libvirt.h.in, Add virSecretLookupByUUID and virSecretGetUUID. Make virSecretGetUUIDString follow normal API design pattern * python/generator.py: Skip generation of virSecretGetUUID, virSecretGetUUIDString and virSecretLookupByUUID * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretGetUUID,virSecretGetUUIDString and virSecretLookupByUUID * qemud/remote.c: s/virSecretLookupByUUIDString/virSecretLookupByUUID/ Fix get_nonnull_secret/make_nonnull_secret to use unsigned char * qemud/remote_protocol.x: Fix remote_nonnull_secret to use a remote_uuid instead of remote_nonnull_string for UUID field. Rename REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING to REMOTE_PROC_SECRET_LOOKUP_BY_UUID_STRING and make it take an remote_uuid value * qemud/remote_dispatch_args.h, qemud/remote_dispatch_prototypes.h, qemud/remote_dispatch_ret.h, qemud/remote_dispatch_table.h, qemud/remote_protocol.c, qemud/remote_protocol.h: Re-generate * src/datatypes.h, src/datatypes.c: Store UUID in raw format instead of printable. Change virGetSecret to use raw format UUID * src/driver.h: Rename virDrvSecretLookupByUUIDString to virDrvSecretLookupByUUID and use raw format UUID * src/libvirt.c: Add virSecretLookupByUUID and virSecretGetUUID and re-implement virSecretLookupByUUIDString and virSecretGetUUIDString in terms of those * src/libvirt_public.syms: Add virSecretLookupByUUID and virSecretGetUUID * src/remote_internal.c: Rename remoteSecretLookupByUUIDString to remoteSecretLookupByUUID. Fix typo in args for remoteSecretDefineXML impl. Use raw UUID format for get_nonnull_secret and make_nonnull_secret * src/storage_encryption_conf.c, src/storage_encryption_conf.h: Storage UUID in raw format, and require it to be present in XML. Use UUID parser to validate. * secret_conf.h, secret_conf.c: Generate a UUID if none is provided. Storage UUID in raw format. * src/secret_driver.c: Adjust to deal with raw UUIDs. Save secrets in a filed with printable UUID, instead of base64 UUID. * src/virsh.c: Adjust for changed public API contract of virSecretGetUUIDString. * src/storage_Backend.c: DOn't undefine secret we just generated upon successful volume creation. Fix to handle raw UUIDs. Generate a non-clashing UUID * src/qemu_driver.c: Change to use lookupByUUID instead of lookupByUUIDString 2009- 9- 3 Jim Meyering python: let libvirt_virConnectDomainEventCallback indicate success * python/libvir.c (libvirt_virConnectDomainEventCallback): Return 0 when successful, rather than always returning -1. clang flagged this function for its dead-store of "ret=0". Once "ret" was set to 0, it was never used, and the function would always return -1. 2009- 9- 1 Miloslav Trmač Secret manipulation API docs refresh & wire up python generator Sample session: >>> import libvirt >>> c = libvirt.open('qemu:///session') >>> c.listSecrets() ['12247729-47d2-a783-88ce-b329d4781cd3', 'reee', 'abc'] >>> s = c.secretDefineXML("\nSomething for use\n/foo/bar\n\n") >>> s.UUIDString() '340c2dfb-811b-eda8-da9e-25ccd7bfd650' >>> s.XMLDesc() "\n 340c2dfb-811b-eda8-da9e-25ccd7bfd650\n Something for use\n /foo/bar\n\n" >>> s.setValue('abc\0xx\xffx') 0 >>> s.value() 'abc\x00xx\xffx' >>> s.undefine() 0 * python/generator.py: Add rules for virSecret APIs * python/libvir.c, python/libvirt-python-api.xml: Manual impl of virSecretSetValue, virSecretGetValue$ and virConnectListSecrets APIs * python/libvirt_wrap.h, python/types.c: Wrapper for virSecret objects * docs/libvirt-api.xml, docs/libvirt-refs.xml, docs/html/libvirt-virterror.html, docs/html/libvirt-libvirt.html, docs/devhelp/libvirt-virterror.html, docs/devhelp/libvirt-libvirt.html: Re-generate with 'make api' 2009- 7- 26 Cole Robinson python: Raise exceptions if virDomain*Stats fail. The generator couldn't tell that the stats return values were pointers. Stick a white list in the function which tries to make this distinction. 2009- 7- 16 Jim Meyering remove all trailing blank lines by running this command: git ls-files -z | xargs -0 perl -pi -0777 -e 's/\n\n+$/\n/' This is in preparation for a more strict make syntax-check rule that will detect trailing blank lines. 2009- 7- 8 Jim Meyering remove all .cvsignore files 2009- 7- 6 Dan Kenigsberg Fix python examples to use read-write conn * docs/examples/python/domstart.py python/tests/create.py: The two example were broken as they needed full-access connection but only opened read-only connections 2009- 5- 28 Daniel P. Berrange Fix python domain events example & binding 2009- 5- 21 Daniel P. Berrange Add virInterface APIs to python code generator 2009- 5- 19 Cole Robinson Better error reporting if 'import libvirtmod' fails Don't squash a possibly legitimate libvirtmod error (e.g. some from clashing libvirt.so versions) with 'Cannot import cygvirtmod' 2009- 4- 1 Daniel P. Berrange Fix crash after calling virConnectClose 2009- 4- 1 Daniel P. Berrange Fix generation of networkCreateXML and storagePoolCreateXML 2009- 3- 3 Jim Meyering update .gitignore and .hgignore files 2009- 3- 3 Daniel P. Berrange Internal driver API for sVirt support (James Morris & Dan Walsh) 2009- 3- 2 Daniel P. Berrange Ignore some generated autotools files in example app 2009- 2- 26 Daniel Veillard * python/Makefile.am: avoid a parallel make issue #472702 provided by Michael Marineau Daniel 2009- 2- 16 Cole Robinson Fix building python bindings: Skip bindings for virSaveLastError and virFreeError 2009- 1- 20 Daniel P. Berrange Use global thread-local error for all python error reporting 2008- 12- 18 Daniel P. Berrange Replace __FUNCTION__ with __func__ for better portability (John Levon) 2008- 12- 18 Daniel P. Berrange Fix gcc-ism in python build (John Levon) 2008- 12- 15 Jim Meyering syntax-check: enforce the no-cvs-keywords prohibition * Makefile.maint (sc_prohibit_cvs_keyword): New rule. Suggested by Daniel Veillard. The new test exposed two uses of $Date$. * docs/Goals: Don't use $Date$. * python/TODO: Likewise. 2008- 11- 25 Daniel P. Berrange Support domain lifecycle events for Xen (Ben Guthro & Daniel Berrange) 2008- 11- 24 Daniel P. Berrange Fix python bindings events code (David Lively) 2008- 11- 21 Daniel P. Berrange Python binding for node device APIs (David Lively) 2008- 11- 19 Daniel P. Berrange Add a virFreeCallback to event loop APIs 2008- 11- 19 Daniel P. Berrange Change public API for virEventAddHandle to allow multiple registrations per FD 2008- 11- 19 Daniel P. Berrange Add a virFreeCallback to virDomainEventRegister (from David Lively) 2008- 11- 17 Daniel P. Berrange Add domain events detail information 2008- 11- 17 Daniel P. Berrange Fix domain events python thread safety & incorrect enum generation 2008- 10- 31 Daniel Veillard * python/virConnect.py: needed for events from the python bindings by Ben Guthro daniel 2008- 10- 31 Daniel Veillard * python/Makefile.am python/generator.py python/libvir.c python/libvir.py python/libvirt_wrap.h python/types.c: adds support for events from the python bindings, also improves the generator allowing to embbed per function definition files, patch by Ben Guthro * examples/domain-events/events-python/event-test.py: also adds a programming example Daniel 2008- 10- 23 Daniel Veillard Massive patch adding event APIs by Ben Guthro * include/libvirt/libvirt.h include/libvirt/libvirt.h.in src/libvirt.c src/libvirt_sym.version: new libvirt event entry points, big patch provided by Ben Guthro * Makefile.am configure.in src/driver.h src/event.c src/event.h src/internal.h src/libvirt.c src/libvirt_sym.version src/lxc_driver.c src/openvz_driver.c src/qemu_conf.h src/qemu_driver.c src/remote_internal.c src/storage_backend_fs.c src/test.c qemud/event.c qemud/event.h qemud/mdns.c qemud/qemud.c qemud/qemud.h qemud/remote.c qemud/remote_dispatch_localvars.h qemud/remote_dispatch_proc_switch.h qemud/remote_dispatch_prototypes.h qemud/remote_protocol.c qemud/remote_protocol.h qemud/remote_protocol.x proxy/Makefile.am python/generator.py: Not much is left untouched by the patch adding the events support * docs/libvirt-api.xml docs/libvirt-refs.xml docs/html/libvirt-libvirt.html: regenerated the docs * examples/domain-events/events-c/Makefile.am examples/domain-events/events-c/event-test.c: a test example * AUTHORS: added Ben Guthro daniel 2008- 10- 17 Jim Meyering generate .gitignore files from .cvsignore ones * Makefile.maint (sync-vcs-ignore-files): New target. Prompted by a patch from James Morris. http://thread.gmane.org/gmane.comp.emulators.libvirt/8619/focus=8773 Add all (now-generated) .gitignore files. * .gitignore: New file. * build-aux/.gitignore: New file. * docs/.gitignore: New file. * docs/devhelp/.gitignore: New file. * docs/examples/.gitignore: New file. * docs/examples/python/.gitignore: New file. * gnulib/lib/.gitignore: New file. * gnulib/lib/arpa/.gitignore: New file. * gnulib/lib/netinet/.gitignore: New file. * gnulib/lib/sys/.gitignore: New file. * gnulib/tests/.gitignore: New file. * include/.gitignore: New file. * include/libvirt/.gitignore: New file. * po/.gitignore: New file. * proxy/.gitignore: New file. * python/.gitignore: New file. * python/tests/.gitignore: New file. * qemud/.gitignore: New file. * src/.gitignore: New file. * tests/.gitignore: New file. * tests/confdata/.gitignore: New file. * tests/sexpr2xmldata/.gitignore: New file. * tests/virshdata/.gitignore: New file. * tests/xencapsdata/.gitignore: New file. * tests/xmconfigdata/.gitignore: New file. * tests/xml2sexprdata/.gitignore: New file. 2008- 10- 1 Daniel Veillard Xen interface order and fix python parallel build * src/xend_internal.c: fix ordering when parsing multiple Xen interfaces, patch by Jim Fehlig * python/Makefile.am: fix parallel build Daniel 2008- 8- 22 Daniel P. Berrange Use libvirt error message for python exceptions 2008- 8- 12 Daniel Veillard Fix connection lookup in python storage instances * python/generator.py: patch from Cole Robinson trying to fix problem of connection lookup when creating storage instances Daniel 2008- 7- 25 Daniel Veillard Skip python bindings for virDomainBlockPeek and virDomainMemoryPeek * python/generator.py: skip generation for virDomainBlockPeek and virDomainMemoryPeek as they break the build Daniel 2008- 7- 9 Daniel P. Berrange Ignore JIT'd python files 2008- 6- 25 Daniel Veillard * python/types.c: patch from Ryan Scott to remove misplaced verbosity when compiling in debug mode. Daniel 2008- 6- 11 Daniel Veillard * python/libvir.py python/libvirt-python-api.xml: more python cleanups by Cole Robinson Daniel 2008- 6- 10 Daniel Veillard * python/generator.py python/libvir.c python/libvirt-python-api.xml: Apply patch from Cole Robinson fixing UUIDString for python Daniel 2008- 5- 29 Daniel P. Berrange Fix python code generation for storage APIs 2008- 5- 21 Daniel P. Berrange Don't free C object after destroy method in python 2008- 4- 18 Daniel P. Berrange Python header workaround 2008- 4- 18 Jim Meyering Work around Python.h name-space pollution. * python/libvir.c (HAVE_PTHREAD_H): #undef. Without this, we'd get a redefinition warning. 2008- 4- 10 Jim Meyering convert TAB-based indentation in C sources to use only spaces Done using this command (also includes .c.in and .h.in files): for i in $(g ls-files|grep -E '\.[ch](\.in)?$'|grep -v gnulib); do expand -i $i > j && mv j $i;done 2008- 4- 10 Jim Meyering remove Vim and Emacs variable settings from C source files Done with these commands: git grep -l Local.variab|xargs \ perl -0x3b -pi -e 's,\n+/\*\n \* vim:(.|\n)*,\n,' git grep -l Local.variab|xargs \ perl -0x3b -pi -e 's,\n+/\*\n \* Local variables:\n(.|\n)*,\n,' 2008- 4- 8 Daniel Veillard Fix potential infinite loop in python generator * python/generator.py: fix an infinite loop bug Daniel 2008- 3- 14 Richard W.M. Jones Fix typo "informations" -> "information" (Atsushi SAKAI and Saori FUKUTA). 2008- 2- 29 Richard W.M. Jones Many typos fixed (Atsushi SAKAI). 2008- 2- 20 Daniel P. Berrange Added python binding for storage APIs 2008- 2- 7 Daniel Veillard Python bindings return values fixes * python/libvir.c: apply patch from Cole Robinson to provide return values for manulally written python bindings. Daniel 2008- 2- 5 Jim Meyering Remove all trailing blanks; turn on the rule to detect them. * Makefile.cfg (local-checks-to-skip): Remove sc_trailing_blank. * .x-sc_trailing_blank: New file, to exempt the few binary files. 2008- 1- 29 Jim Meyering Enable the -requiring test; fix violations Use , not "config.h", per autoconf documentation. * Makefile.cfg (local-checks-to-skip) [sc_require_config_h]: Enable. * .x-sc_require_config_h: New file, to list exempted files. * Makefile.am (EXTRA_DIST): Add .x-sc_require_config_h. 2008- 1- 29 Jim Meyering Given code like if (foo) free (foo); remove the useless "if (foo) " part. Likewise, given if (foo != NULL) free (foo); remove the useless "if" test. * proxy/libvirt_proxy.c: Remove unnecessary "if" test before free. * python/generator.py: Likewise. * qemud/qemud.c: Likewise. * src/buf.c: Likewise. * src/conf.c: Likewise. * src/hash.c: Likewise. * src/iptables.c: Likewise. * src/libvirt.c: Likewise. * src/openvz_conf.c: Likewise. * src/qemu_conf.c: Likewise. * src/qemu_driver.c: Likewise. * src/remote_internal.c: Likewise. * src/test.c: Likewise. * src/virsh.c: Likewise. * src/virterror.c: Likewise. * src/xen_internal.c: Likewise. * src/xen_unified.c: Likewise. * src/xend_internal.c: Likewise. * src/xm_internal.c: Likewise. * src/xml.c: Likewise. * src/xmlrpc.c: Likewise. * src/xs_internal.c: Likewise. * tests/testutils.c: Likewise. * tests/xencapstest.c: Likewise. * tests/xmconfigtest.c: Likewise. 2008- 1- 21 Daniel P. Berrange Make python generator fail build on any missing APIs 2008- 1- 21 Daniel P. Berrange Add missing vcpu/schedular APIs to python binding 2008- 1- 17 Jim Meyering Handle PyTuple_New's malloc failure. * python/libvir.c (libvirt_virDomainBlockStats): Handle a NULL return from PyTuple_New. (libvirt_virDomainInterfaceStats, libvirt_virGetLastError): Likewise. (libvirt_virConnGetLastError): Likewise. 2008- 1- 17 Jim Meyering Factor out some duplication. * python/libvir.c (VIR_PY_NONE): New macro, to encapsulate a common two-statement sequence. Replace all such 2-stmt sequences. 2007- 12- 11 Jim Meyering Use a variable name as sizeof argument, not a type name. Given code like: T *var = calloc (n, sizeof (T)); Convert to this: T *var = calloc (n, sizeof (*var)); This first-cut change adjusts all malloc, calloc, and realloc statements. The only binary differences are in remote_internal.c (due to the bug fix) and in xmlrpc.c (due to factorization). * python/libvir.c: As above. * qemud/event.c: Likewise. * qemud/mdns.c: Likewise. * qemud/qemud.c: Likewise. * qemud/remote.c: Likewise. * src/bridge.c: Likewise. * src/buf.c: Likewise. * src/conf.c: Likewise. * src/hash.c: Likewise. * src/iptables.c: Likewise. * src/openvz_conf.c: Likewise. * src/qemu_conf.c: Likewise. * src/qemu_driver.c: Likewise. * src/test.c: Likewise. * src/xen_internal.c: Likewise. * src/xen_unified.c: Likewise. * src/xm_internal.c: Likewise. * src/xml.c: Likewise. * tests/qemuxml2argvtest.c: Likewise. * src/xmlrpc.c (xmlRpcValuePtr): Likewise, and minor factorization. * src/remote_internal.c (remoteAuthMakeCredentials): Use the right type when allocating space for an array of cred _pointers_. 2007- 12- 7 Jim Meyering Include "config.h" in remaining non-generated files. * proxy/libvirt_proxy.c: Likewise. * python/libvir.c: Likewise. * python/types.c: Likewise. * src/event.c: Likewise. * src/xm_internal.c: Likewise. * tests/reconnect.c: Likewise. * tests/testutils.c: Likewise. 2007- 12- 7 Daniel Veillard * python/generator.py python/libvir.c python/libvirt-python-api.xml: add a python binding for virNodeGetCellsFreeMemory Daniel 2007- 12- 5 Daniel P. Berrange Add manual impl of virConnectOpenAuth python binding 2007- 12- 5 Richard W.M. Jones Wed Dec 5 13:48:00 UTC 2007 Richard W.M. Jones * python/libvir.c, python/libvirt_wrap.h, qemud/qemud.c, qemud/remote.c, src/internal.h, src/openvz_conf.c, src/openvz_driver.c, src/proxy_internal.h, src/qemu_conf.c, src/qemu_driver.c, src/remote_internal.h, src/test.h, src/util.c, src/xen_unified.c, src/xen_unified.h, tests/nodeinfotest.c, tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c, tests/reconnect.c, tests/sexpr2xmltest.c, tests/virshtest.c, tests/xencapstest.c, tests/xmconfigtest.c, tests/xml2sexprtest.c: Change #include <> to #include "" for local includes. Removed many includes from src/internal.h and put them in the C files which actually use them. Removed - unused. Added a comment around __func__. Removed a clashing redefinition of VERSION symbol. All limits (PATH_MAX etc) now done in src/internal.h, so we don't need to include those headers in other files. 2007- 11- 30 Richard W.M. Jones Fri Nov 30 11:04:00 GMT 2007 Richard W.M. Jones * python/libvir.c, python/libvir.py: Make Python aware that the C bindings module is called cygvirtmod.dll when compiled by CYGWIN. * python/Makefile.am: Remove symlink libvirtmod.dll -> cygvirtmod.dll no longer necessary because of the above. * configure.in: Remove AM_CONDITIONAL(CYGWIN). 2007- 11- 29 Richard W.M. Jones Thu Nov 29 17:40:00 GMT 2007 Richard W.M. Jones * configure.in: Added CYGWIN_EXTRA_LDFLAGS, CYGWIN_EXTRA_LIBADD, CYGWIN_EXTRA_PYTHON_LIBADD, CYGWIN automake conditional. * src/Makefile.am: Extra flags required to build DLL of libvirt for Cygwin. * python/Makefile.am: Extra flags and rule required to build Python module for Cygwin. 2007- 11- 15 Jim Meyering Make "make distcheck" work. * Makefile.am: Expand some "*" wildcards, and (for now) disable the relatively unimportant, distuninstallcheck target. Fix a few redirect-directly-to-target bugs. Add a few $(srcdir)/ prefixes and add an uninstall-local rule. * docs/Makefile.am: More of the same. Split some long lines. * python/Makefile.am: Likewise. * python/tests/Makefile.am: Likewise. * qemud/Makefile.am: Likewise. * tests/Makefile.am: Remove the directories already listed in SUBDIRS. * docs/examples/index.py: Adapt to produce the desired changes in docs/examples/Makefile.am. Also, sort *.c, so results are reproducible, and emit a comment telling emacs and vi that the file is read-only. * docs/examples/Makefile.am: Regenerate. Author: Jim Meyering 2007- 9- 30 Daniel Veillard * python/generator.py python/libvir.c python/libvirt-python-api.xml: provide bindings for block and interface statistics Daniel 2007- 7- 24 Daniel Veillard * libvirt.spec.in NEWS docs/* po/*: preparing release 0.3.1 * src/libvirt.c python/generator.py: some cleanup and warnings from Richard W.M. Jones Daniel 2007- 6- 26 Richard W.M. Jones Tue Jun 26 14:40:00 BST 2007 Richard W.M. Jones * src/remote_internal.c, python/Makefile.am: Python bindings fixed, and now building virConnect.getHostname and virConnect.getURI. Fixed a problem which stopped libvirt.py from being (re-)built. Rearranged python/Makefile.am to make it cleaner and clearer. 2007- 6- 25 Richard W.M. Jones Mon Jun 25 16:55:00 BST 2007 Richard W.M. Jones * include/libvirt/libvirt.h.in, src/libvirt.c, src/libvirt_sym.version, python/generator.py: Added virDomainGetConnect and virNetworkGetConnect to allow us to get the "hidden" connection associated with each domain or network. 2007- 6- 15 Richard W.M. Jones Fri Jun 15 08:53:00 BST 2007 Richard W.M. Jones * src/internal.h, src/virsh.c: Replace _N with N_ so that Solaris builds work (Mark Johnson). * src/virsh.c: Add a couple of missing error messages (Mark Johnson). * python/types.c: Fix NULL pointer deref on DEBUG build (Mark Johnson). * src/virsh.c: Spelling fix (Mark Johnson). 2007- 5- 29 Richard W.M. Jones +Tue May 29 15:56:00 BST 2007 Richard W.M. Jones + + * python/generator.py, python/libvir.c, python/libvir.py: + Wrap the virGetVersion call as Python libvirt.getVersion. + + * src/libvirt.c: Change virGetVersion so that the driver name + is case insensitive. + 2007- 4- 16 Daniel P. Berrange Fixed exception reporting for domain/network operations 2007- 4- 10 Daniel P. Berrange Added vir*GetAutostart APIs to python 2007- 3- 28 Richard W.M. Jones * python/generator.py: Python bindings now throw exceptions in almost all cases where an error is encountered in the underlying libvirt code. 2007- 3- 16 Daniel Veillard * python/generator.py: patch from Tatsuro Enokura to fix virNetworkDefine binding Daniel 2007- 3- 15 Daniel Veillard * python/generator.py: fix the python binding generation for virNetworkLookup...() functions, which were clashing with equivalent virConnLookup...() equivalents, as reported by Tatsuro Enokura Daniel 2007- 3- 9 Daniel P. Berrange Added python bindings for networking APIs 2007- 3- 6 Daniel P. Berrange Fixed up numerous compiler warnings 2007- 3- 1 Mark McLoughlin Thu Mar 01 16:17:48 EST 2007 Mark McLoughlin * acinclude.m4: add LIBVIRT_COMPILE_WARNINGS, copied from GNOME but with a few more flags we'd been using. * configure.in: use that instead of setting CFLAGS directly. * proxy/Makefile.am, python/Makefile.am, qemud/Makefile.am, src/Makefile.am, tests/Makefile.am: use $(WARN_CFLAGS) 2007- 2- 14 Daniel P. Berrange Blacklist vshRunConsole from python 2007- 1- 23 Mark McLoughlin Mon Jan 23 14:36:18 IST 2007 Mark McLoughlin * include/libvirt/libvirt.h.in: add VIR_UUID_BUFLEN and VIR_UUID_STRING_BUFLEN * libvirt/proxy/libvirt_proxy.c, libvirt/src/hash.c, libvirt/src/internal.h, libvirt/src/libvirt.c, libvirt/src/proxy_internal.c, libvirt/src/test.c, libvirt/src/virsh.c, libvirt/src/xend_internal.c, libvirt/src/xm_internal.c, libvirt/src/xml.c, libvirt/python/libvir.c: use them 2006- 11- 16 Daniel P. Berrange Added binding for virConnectListDefinedDomains api 2006- 11- 15 Daniel P. Berrange Fix unsigned long wraparound in python binding 2006- 11- 10 Daniel P. Berrange Fixed string concatenation in case where there is no lower level error 2006- 11- 9 Daniel Veillard * python/generator.py: changed the generator to generate a reference from Domain class instances to the Connect they were issued from should fix rhbz#204490 * docs//*: rebuilt Daniel 2006- 11- 7 Daniel P. Berrange Propagate libvirt errors back with python exceptions 2006- 10- 24 Daniel P. Berrange Make python bindings threaded, by dropping/acquiring Python GIL where needed 2006- 8- 29 Daniel Veillard * python/libvir.c: Pete Vetere pointed out a bug in string cast when handling errors in Python Daniel 2006- 8- 4 Daniel Veillard * python/generator.py: fix the generator when handling long integers Dan Berrange reported problems due to this when using virDomainSetMemory bindings Daniel 2006- 7- 5 Mark McLoughlin unleash the hush puppies 2006- 6- 26 Daniel Veillard * configure.in libvirt.spec.in docs/examples/* include/Makefile.am include/libvirt/virterror.h python/generator.py python/libvir.c python/libvirt_wrap.h src/driver.h src/internal.h src/test.h src/virsh.c src/virterror.c src/xend_internal.c src/xend_internal.h src/xml.c src/xml.h: moved the includes from include/ to include/libvirt to reflect the installed include tree. This avoid using "" in the includes themselves. Daniel 2006- 3- 29 Daniel Veillard * python/libvir.c: fixed a bug in the new wrapper * python/tests/Makefile.am python/tests/node.py: added a new test for the new API * python/tests/create.py: remove a debug Daniel 2006- 3- 29 Daniel Veillard * include/libvirt.h[.in] include/virterror.h src/driver.h src/internal.h src/libvirt_sym.version src/xen_internal.c src/xs_internal.c: added a new entry point to get node hardware informations virGetNodeInfo, and associated driver hook. * src/xend_internal.c: implemented the node and version information hooks for the Xen Daemon * python/libvir.c python/libvirt-python-api.xml python/generator.py: also added Python bindings for the new call Daniel 2006- 3- 28 Daniel Veillard * python/libvir.c: call the initialize entry point * src/libvirt_sym.version: add initialize entry point * src/libvirt.c: make sure we always initialize the lib * python/tests/*.py: start updating exemple for exception handling as pointed by Jim Meyering Daniel 2006- 3- 28 Daniel Veillard * doc/site.xsl doc/libvir.html doc/*: added informations about the Perl bindings, regenerated * python/libvirt_wrap.h: added a missing include. Daniel 2006- 3- 23 Daniel Veillard * src/xs_internal.c src/xs_internal.h include/virterror.h src/virterror.c: created a new module related to Xen Store accesses * src/libvirt.c src/xen_internal.[ch] src/xend_internal.[ch]: nearly completed the separation of the code from the different modules Daniel 2006- 3- 22 Daniel Veillard * python/tests/create.py: add one more image path * src/libvirt.c src/xend_internal.c src/xend_internal.h: more work on the xend refactoring Daniel 2006- 3- 22 Daniel Veillard * python/tests/create.py: adapt to new naming scheme in FC5 Daniel 2006- 2- 28 Daniel Veillard * NEWS configure.in libvirt.spec.in include/libvirt.h docs/*: preparing release 0.0.6 Daniel 2006- 2- 28 Daniel Veillard Fixed the test, daniel 2006- 2- 28 Daniel Veillard * TODO: updated * python/Makefile.am python/generator.py python/libvir.c python/libvir.py: improved python binding, raise exception when an instance creation or lookup fails, and add support for the global error handler, per conn handler still needed * python/tests/error.py python/tests/Makefile.am: adding a regression test Daniel 2006- 2- 24 Daniel Veillard * python/generator.py python/libvir.c python/libvirt-python-api.xml: UUID strings can contain zeroes, so the autogenerated conversion functions don't work. Daniel 2006- 2- 23 Daniel Veillard * src/libvirt.c: fixing a bug before the release of 0.0.5 * python/generator.py python/libvir.c python/libvirt-python-api.xml: also fixing the binding for getting a domain UUID * python/tests/Makefile.am python/tests/uuid.py: added a test for the new UUID API Daniel 2006- 2- 23 Daniel Veillard * python/tests/Makefile.am: added the create.py in the regression tests Daniel 2006- 2- 21 Daniel Veillard * TODO: updated * python/tests/Makefile.am: fix a small PYTHONPATH bug * docs//*: fixed the xsl a bit for toc names, added doc for the python bindings, regenerated Daniel 2006- 2- 20 Daniel Veillard * docs/examples/examples.xsl docs/examples/index.html docs/site.xsl: integates the examples page in the web site * docs//* : fixed generator and rebuilt the docs * python/tests/basic.py python/tests/create.py: couple cleanups Daniel 2006- 2- 17 Daniel Veillard * python/tests/create.py: trying to make test more generic, but it's difficult since it requires a system image * src/libvirt.c src/xend_internal.c: fixed the shutdown API which was broken due to a bad reason at the xend level. Daniel 2006- 2- 16 Daniel Veillard * configure.in src/Makefile.am: adding dependency to libxml2 * include/libvirt.h* src/libvirt.c src/xend_internal.[ch] src/xml.[ch]: added XML parsing for Xen domain descriptions needed for creates, plugged in a converter to s-exp and xend call. Modified the virDomainCreateLinux() to reflect that XML based description. Seems to work. * python/tests/create.py: added a test case which seems to work not tested much yet * docs/*: regenerated Daniel 2006- 2- 15 Daniel Veillard * configure.in libvirt.spec.in include/libvirt.h.in python/Makefile.am src/Makefile.am: fix rpm packaging problems whith head, more LIBVIR -> LIBVIRT changes. Daniel 2006- 2- 14 Daniel Veillard * Makefile.am configure.in python/Makefile.am python/tests/Makefile.am python/tests/basic.py: added first python test script and a 'make tests' target Daniel 2006- 2- 10 Daniel Veillard * python/libvir.c: fixed one more problem prior to 0.0.4 Daniel 2006- 2- 9 Daniel Veillard * //* : renamed the project libvirt , this affects all makefiles, the specs, the icons, the docs, etc ... * configure.in: prepare for 0.0.3 Daniel 2006- 1- 31 Daniel Veillard * python/*: update of the python bindings, fix names, add missing features like list of domains and domain info extraction Daniel 2006- 1- 28 Daniel Veillard * python/libvir.c: fix a stupid bug in python bindings (DomainDestroy is still mishandled though) Daniel 2006- 1- 26 Daniel Veillard * TODO: updated * docs/search.php: use the new web site design * python/generator.py: fix a generation bug on python keyword Daniel 2005- 12- 19 Daniel Veillard * Makefile.am configure.in libvir.spec.in python/*: added a first version for python bindings, heavilly based on libxml2/libxslt way of doing things, maybe this need to be revisited. Added packaging too. * src/hash.h: fixed the Copyright notice. Daniel ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/HACKING0000644000175000017500000000272314612401403014576 0ustar00jirkajirka libvirt Python Bindings Hacking =============================== Most of the libvirt python binding code is automatically generated using the script generator.py, and the API description that the libvirt library installs at the location shown by pkg-config, with this command: $ pkg-config --variable libvirt_api libvirt /usr/share/libvirt/api/libvirt-api.xml Some of the API descriptions in the primary XML files are not directly usable by the code generator. Thus there are overrides in - libvirt-override-api.xml - libvirt-qemu-override-api.xml - libvirt-lxc-override-api.xml For stuff which the generator can't cope with at all there are some hand written source files - libvirt-override.c - low level binding to libvirt.so - libvirt-qemu-override.c - low level binding to libvirt-qemu.so - libvirt-lxc-override.c - low level binding to libvirt-lxc.so - libvirt-override.py - high level overrides in the global namespace - libvirt-override-virConnect.py - high level overrides in the virConnect class - libvirt-override-virDomain.py - high level overrides in the virDomain class - libvirt-override-virDomainCheckpoint.py - high level overrides in the virDomainCheckpoint class - libvirt-override-virDomainSnapshot.py - high level overrides in the virDomainSnapshot class - libvirt-override-virStoragePool.py - high level overrides in the virStoragePool class - libvirt-override-virStream.py - high level overrides in the virStream class ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/MANIFEST.in0000644000175000017500000000050614612401403015342 0ustar00jirkajirkagraft tests graft examples include AUTHORS include COPYING include CONTRIBUTING.rst include HACKING include VERSION include requirements-test.txt include tox.ini include Makefile include ChangeLog include libvirt-python.spec include *.[ch] include *.xml include *.py global-exclude */__pycache__/* global-exclude *.py[cod] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1725270620.0 libvirt-python-11.3.0/Makefile0000644000175000017500000000065514665305134015265 0ustar00jirkajirka# Shim wrapper around setup.py to allow for familiar build targets PYTHON ?= python VERSION := $(shell $(PYTHON) -c 'import sys; print("{}{}".format(sys.version_info.major, sys.version_info.minor))') all: $(PYTHON) -m build install: all $(PYTHON) -m pip install . clean: rm -rf build/ dist/ check: all tox -e py$(VERSION) test: all tox rpm: all rpmbuild -ta dist/libvirt-python-$(shell tr -d '\n' < VERSION).tar.gz ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1746171070.9010584 libvirt-python-11.3.0/PKG-INFO0000644000175000017500000000475715005072277014727 0ustar00jirkajirkaMetadata-Version: 2.1 Name: libvirt-python Version: 11.3.0 Summary: The libvirt virtualization API python binding Home-page: http://www.libvirt.org Maintainer: Libvirt Maintainers Maintainer-email: libvir-list@redhat.com Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Classifier: Programming Language :: Python :: 3 :: Only Requires-Python: >=3.6 Description-Content-Type: text/x-rst License-File: COPYING Libvirt Python Binding README ============================= This package provides a module that permits applications written in the Python 3.x programming language to call the interface supplied by the libvirt library, to manage the virtualization capabilities of recent versions of Linux (and other OSes). As such, the module exposes Python bindings to to the libvirt.so, libvirt-qemu.so and libvirt-lxc.so library APIs. It is written to build against any version of libvirt that is 0.9.11 or newer. This code is distributed under the terms of the LGPL version 2 or later. Requirements ------------ To build the libvirt python binary requires the GCC and pkg-config tools, and development headers for the libvirt and python libraries. Building and installing ----------------------- The module can be built by following the normal python module build process $ python3 -m build for testing and distributing purposes or it can be installed directly via pip as $ python3 -m pip install . without explicit building. In order to test the package, you'll need either tox or at least pytest, depending on whether you want to test an already installed package in which case the latter is sufficient or if you wish to test in a virtual environment you'd need tox. Depending on your preferred setup, you can run the tests either as $ python3 -m pytest or as $ tox A makefile shim is also provided for your convenience, so that you don't have to care about the exact operations mentioned above and instead you simply do $ make && make check As of libvirt 1.2.6, it is possible to develop against an uninstalled libvirt.git checkout, by setting PKG_CONFIG_PATH and LD_LIBRARY_PATH environment variables to point into that libvirt tree; you can even automate this by using libvirt's run script: /path/to/libvirt/run python3 -m build Patches for this code should be submitted as merge requests to the project page on gitlab. See CONTRIBUTING.rst for more information. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/README0000644000175000017500000000370414612401403014467 0ustar00jirkajirkaLibvirt Python Binding README ============================= This package provides a module that permits applications written in the Python 3.x programming language to call the interface supplied by the libvirt library, to manage the virtualization capabilities of recent versions of Linux (and other OSes). As such, the module exposes Python bindings to to the libvirt.so, libvirt-qemu.so and libvirt-lxc.so library APIs. It is written to build against any version of libvirt that is 0.9.11 or newer. This code is distributed under the terms of the LGPL version 2 or later. Requirements ------------ To build the libvirt python binary requires the GCC and pkg-config tools, and development headers for the libvirt and python libraries. Building and installing ----------------------- The module can be built by following the normal python module build process $ python3 -m build for testing and distributing purposes or it can be installed directly via pip as $ python3 -m pip install . without explicit building. In order to test the package, you'll need either tox or at least pytest, depending on whether you want to test an already installed package in which case the latter is sufficient or if you wish to test in a virtual environment you'd need tox. Depending on your preferred setup, you can run the tests either as $ python3 -m pytest or as $ tox A makefile shim is also provided for your convenience, so that you don't have to care about the exact operations mentioned above and instead you simply do $ make && make check As of libvirt 1.2.6, it is possible to develop against an uninstalled libvirt.git checkout, by setting PKG_CONFIG_PATH and LD_LIBRARY_PATH environment variables to point into that libvirt tree; you can even automate this by using libvirt's run script: /path/to/libvirt/run python3 -m build Patches for this code should be submitted as merge requests to the project page on gitlab. See CONTRIBUTING.rst for more information. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1746171068.0 libvirt-python-11.3.0/VERSION0000644000175000017500000000000715005072274014657 0ustar00jirkajirka11.3.0 ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1746171070.877473 libvirt-python-11.3.0/build/0000755000175000017500000000000015005072277014714 5ustar00jirkajirka././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1746171070.900771 libvirt-python-11.3.0/build/libvirt_python.egg-info/0000755000175000017500000000000015005072277021462 5ustar00jirkajirka././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1746171070.0 libvirt-python-11.3.0/build/libvirt_python.egg-info/SOURCES.txt0000644000175000017500000000243315005072276023347 0ustar00jirkajirkaAUTHORS CONTRIBUTING.rst COPYING ChangeLog HACKING MANIFEST.in Makefile README VERSION generator.py libvirt-lxc-override-api.xml libvirt-lxc-override.c libvirt-override-api.xml libvirt-override-virConnect.py libvirt-override-virDomain.py libvirt-override-virDomainCheckpoint.py libvirt-override-virDomainSnapshot.py libvirt-override-virNetwork.py libvirt-override-virStoragePool.py libvirt-override-virStream.py libvirt-override.c libvirt-override.py libvirt-python.spec libvirt-qemu-override-api.xml libvirt-qemu-override.c libvirt-qemu-override.py libvirt-utils.c libvirt-utils.h libvirtaio.py pyproject.toml requirements-test.txt setup.cfg setup.py tox.ini typewrappers.c typewrappers.h examples/README examples/consolecallback.py examples/dhcpleases.py examples/dominfo.py examples/domipaddrs.py examples/domrestore.py examples/domsave.py examples/domstart.py examples/esxlist.py examples/event-test.py examples/nodestats.py examples/sparsestream.py examples/topology.py examples/guest-vcpus/guest-vcpu-daemon.py examples/guest-vcpus/guest-vcpu.py tests/eventmock.py tests/test_aio.py tests/test_api_coverage.py tests/test_conn.py tests/test_domain.py tests/test_domain_checkpoint.py tests/test_domain_snapshot.py tests/test_interface.py tests/test_network.py tests/test_nodedev.py tests/test_storage.py././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1746171070.8966155 libvirt-python-11.3.0/examples/0000755000175000017500000000000015005072277015433 5ustar00jirkajirka././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/README0000644000175000017500000000307014612401403016301 0ustar00jirkajirkaSome simple examples on how to use the Python API for libvirt The examples are: dominfo.py - print information about a running domU based on the results of virDomainGetInfo and virDomainGetXMLDesc domstart.py - create a domU from an XML description if the domU isn't running yet domsave.py - save all running domU's into a directory domrestore.py - restore domU's from their saved files in a directory esxlist.py - list active domains of an VMware ESX host and print some info. also demonstrates how to use the libvirt.openAuth() method dhcpleases.py - list dhcp leases for a given virtual network domipaddrs.py - list IP addresses for guest domains guest-vcpus - two helpers to make the guest agent event useful with agent based vCPU state modification nodestats.py - print total memory and free memory for each host NUMA node and the memory strictly bound to certain host nodes for each running domain. Some additional notes for the esxlist.py example: You may see remote errors complaining about missing certificates: Cannot access CA certificate '/usr/local/etc/pki/CA/cacert.pem': No such file or directory This is expected, libvirt tries to find network and storage drivers for ESX, but those are not implemented yet (November 2009). While searching for this drivers, libvirt may try to start a local libvirtd instance, but fails because of the missing certificates. It'll warn about that: Failed to find the network: Is the daemon running? This is also expected and can be ignored. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714641003.0 libvirt-python-11.3.0/examples/consolecallback.py0000644000175000017500000000634714614654153021142 0ustar00jirkajirka#!/usr/bin/env python3 # consolecallback - provide a persistent console that survives guest reboots import os import logging import libvirt import tty import termios import atexit from argparse import ArgumentParser from typing import Optional # noqa F401 def reset_term() -> None: termios.tcsetattr(0, termios.TCSADRAIN, attrs) def error_handler(unused, error) -> None: # The console stream errors on VM shutdown; we don't care if error[0] == libvirt.VIR_ERR_RPC and error[1] == libvirt.VIR_FROM_STREAMS: return logging.warning(error) class Console(object): def __init__(self, uri: str, uuid: str) -> None: self.uri = uri self.uuid = uuid self.connection = libvirt.open(uri) self.domain = self.connection.lookupByUUIDString(uuid) self.state = self.domain.state(0) self.connection.domainEventRegister(lifecycle_callback, self) self.stream = None # type: Optional[libvirt.virStream] self.run_console = True self.stdin_watch = -1 logging.info("%s initial state %d, reason %d", self.uuid, self.state[0], self.state[1]) def check_console(console: Console) -> bool: if (console.state[0] == libvirt.VIR_DOMAIN_RUNNING or console.state[0] == libvirt.VIR_DOMAIN_PAUSED): if console.stream is None: console.stream = console.connection.newStream(libvirt.VIR_STREAM_NONBLOCK) console.domain.openConsole(None, console.stream, 0) console.stream.eventAddCallback(libvirt.VIR_STREAM_EVENT_READABLE, stream_callback, console) else: if console.stream: console.stream.eventRemoveCallback() console.stream = None return console.run_console def stdin_callback(watch: int, fd: int, events: int, console: Console) -> None: readbuf = os.read(fd, 1024) if readbuf.startswith(b""): console.run_console = False return if console.stream: console.stream.send(readbuf) def stream_callback(stream: libvirt.virStream, events: int, console: Console) -> None: try: assert console.stream received_data = console.stream.recv(1024) except Exception: return os.write(0, received_data) def lifecycle_callback(connection: libvirt.virConnect, domain: libvirt.virDomain, event: int, detail: int, console: Console) -> None: console.state = console.domain.state(0) logging.info("%s transitioned to state %d, reason %d", console.uuid, console.state[0], console.state[1]) # main parser = ArgumentParser(epilog="Example: %(prog)s 'qemu:///system' '32ad945f-7e78-c33a-e96d-39f25e025d81'") parser.add_argument("uri") parser.add_argument("uuid") args = parser.parse_args() print("Escape character is ^]") logging.basicConfig(filename='msg.log', level=logging.DEBUG) logging.info("URI: %s", args.uri) logging.info("UUID: %s", args.uuid) libvirt.virEventRegisterDefaultImpl() libvirt.registerErrorHandler(error_handler, None) atexit.register(reset_term) attrs = termios.tcgetattr(0) tty.setraw(0) console = Console(args.uri, args.uuid) console.stdin_watch = libvirt.virEventAddHandle(0, libvirt.VIR_EVENT_HANDLE_READABLE, stdin_callback, console) while check_console(console): libvirt.virEventRunDefaultImpl() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/dhcpleases.py0000755000175000017500000000317714612401403020121 0ustar00jirkajirka#!/usr/bin/env python3 """ Print leases info for a given virtual network """ import libvirt import time from argparse import ArgumentParser parser = ArgumentParser(description=__doc__) parser.add_argument("uri", nargs="?", default=None) parser.add_argument("network") args = parser.parse_args() try: conn = libvirt.open(args.uri) except libvirt.libvirtError: print("Unable to open connection to libvirt") exit(1) try: net = conn.networkLookupByName(args.network) except libvirt.libvirtError: print("Network %s not found" % args.network) exit(0) leases = net.DHCPLeases() if not leases: print("Failed to get leases for %s" % net.name()) exit(0) def toIPAddrType(addrType: int) -> str: if addrType == libvirt.VIR_IP_ADDR_TYPE_IPV4: return "ipv4" elif addrType == libvirt.VIR_IP_ADDR_TYPE_IPV6: return "ipv6" return "Unknown" print(" {0:20} {1:18} {2:9} {3:25} {4:15} {5}".format("Expiry Time", "MAC address", "Protocol", "IP address", "Hostname", "Client ID or DUID")) print("-" * 115) for lease in leases: print(" {0:20} {1:18} {2:9} {3:25} {4:15} {5}".format( time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(lease['expirytime'])), lease['mac'], toIPAddrType(lease['type']), "{}/{}".format(lease['ipaddr'], lease['prefix']), lease['hostname'], lease['clientid'] )) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/dominfo.py0000755000175000017500000000407314612401403017435 0ustar00jirkajirka#!/usr/bin/env python3 """ Print information about the domain DOMAIN """ import libvirt import libxml2 from argparse import ArgumentParser from typing import Any parser = ArgumentParser(description=__doc__) parser.add_argument("domain") args = parser.parse_args() def print_section(title: str) -> None: print("\n%s" % title) print("=" * 60) def print_entry(key: str, value: Any) -> None: print("%-10s %-10s" % (key, value)) def print_xml(key: str, ctx, path: str) -> str: res = ctx.xpathEval(path) if res is None or len(res) == 0: value = "Unknown" else: value = res[0].content print_entry(key, value) return value # Connect to libvirt try: conn = libvirt.openReadOnly(None) except libvirt.libvirtError: print('Failed to open connection to the hypervisor') exit(1) try: dom = conn.lookupByName(args.domain) # Annoyiingly, libvirt prints its own error message here except libvirt.libvirtError: print("Domain %s is not running" % args.domain) exit(0) info = dom.info() print_section("Domain info") print_entry("State:", info[0]) print_entry("MaxMem:", info[1]) print_entry("UsedMem:", info[2]) print_entry("VCPUs:", info[3]) # Read some info from the XML desc xmldesc = dom.XMLDesc(0) doc = libxml2.parseDoc(xmldesc) ctx = doc.xpathNewContext() print_section("Kernel") print_xml("Type:", ctx, "/domain/os/type") print_xml("Kernel:", ctx, "/domain/os/kernel") print_xml("initrd:", ctx, "/domain/os/initrd") print_xml("cmdline:", ctx, "/domain/os/cmdline") print_section("Devices") devs = ctx.xpathEval("/domain/devices/*") for d in devs: ctx.setContextNode(d) # import pdb; pdb.set_trace() type = print_xml("Type:", ctx, "@type") if type == "file": print_xml("Source:", ctx, "source/@file") print_xml("Target:", ctx, "target/@dev") elif type == "block": print_xml("Source:", ctx, "source/@dev") print_xml("Target:", ctx, "target/@dev") elif type == "bridge": print_xml("Source:", ctx, "source/@bridge") print_xml("MAC Addr:", ctx, "mac/@address") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/domipaddrs.py0000755000175000017500000000304014612401403020121 0ustar00jirkajirka#!/usr/bin/env python3 """ Print domain interfaces along with their MAC and IP addresses """ import libvirt from argparse import ArgumentParser IPTYPE = { libvirt.VIR_IP_ADDR_TYPE_IPV4: "ipv4", libvirt.VIR_IP_ADDR_TYPE_IPV6: "ipv6", } def print_dom_ifaces(dom: libvirt.virDomain) -> None: ifaces = dom.interfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE) if ifaces is None: print("Failed to get domain interfaces") exit(0) print(" {0:10} {1:20} {2:12} {3}".format( "Interface", "MAC address", "Protocol", "Address")) for (name, val) in ifaces.items(): if val['addrs']: for addr in val['addrs']: print(" {0:10} {1:19} {2:12} {3}/{4}".format( name, val['hwaddr'], IPTYPE[addr['type']], addr['addr'], addr['prefix'])) else: print(" {0:10} {1:19} {2:12} {3}".format(name, val['hwaddr'], "N/A", "N/A")) if __name__ == "__main__": parser = ArgumentParser(description=__doc__) parser.add_argument("uri", nargs="?", default=None) parser.add_argument("domain") args = parser.parse_args() try: conn = libvirt.open(args.uri) except libvirt.libvirtError: raise SystemExit("Unable to open connection to libvirt") try: dom = conn.lookupByName(args.domain) except libvirt.libvirtError: print("Domain %s not found" % args.domain) exit(0) print_dom_ifaces(dom) conn.close() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/domrestore.py0000755000175000017500000000126214612401403020162 0ustar00jirkajirka#!/usr/bin/env python3 """ Restore all the domains contained in DIR. It is assumed that all files in DIR are images of domU's previously created with save. """ import libvirt import os from argparse import ArgumentParser parser = ArgumentParser(description=__doc__) parser.add_argument("dir") args = parser.parse_args() imgs = os.listdir(args.dir) try: conn = libvirt.open(None) except libvirt.libvirtError: print('Failed to open connection to the hypervisor') exit(1) for img in imgs: file = os.path.join(args.dir, img) print("Restoring %s ... " % img) ret = conn.restore(file) if ret == 0: print("done") else: print("error %d" % ret) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/domsave.py0000755000175000017500000000137214612401403017437 0ustar00jirkajirka#!/usr/bin/env python3 """ Save all currently running domU's into DIR. DIR must exist and be writable by this process. """ import libvirt import os from argparse import ArgumentParser parser = ArgumentParser(description=__doc__) parser.add_argument("dir") args = parser.parse_args() try: conn = libvirt.open(None) except libvirt.libvirtError: print('Failed to open connection to the hypervisor') exit(1) doms = conn.listDomainsID() for id in doms: if id == 0: continue dom = conn.lookupByID(id) print("Saving %s[%d] ... " % (dom.name(), id)) path = os.path.join(args.dir, dom.name()) ret = dom.save(path) if ret == 0: print("done") else: print("error %d" % ret) # import pdb; pdb.set_trace() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1725270620.0 libvirt-python-11.3.0/examples/domstart.py0000755000175000017500000000232514665305134017651 0ustar00jirkajirka#!/usr/bin/env python3 """ Check that the domain described by DOMAIN.XML is running. If the domain is not running, create it. """ import libvirt import libxml2 from argparse import ArgumentParser from typing import Tuple # Parse the XML description of domU from FNAME # and return a tuple (name, xmldesc) where NAME # is the name of the domain, and xmldesc is the contetn of FNAME def read_domain(fname: str) -> Tuple[str, str]: fp = open(fname, "r") xmldesc = fp.read() fp.close() doc = libxml2.parseDoc(xmldesc) name = doc.xpathNewContext().xpathEval("/domain/name")[0].content return (name, xmldesc) parser = ArgumentParser(description=__doc__) parser.add_argument("file", metavar="DOMAIN.XML", help="XML configuration of the domain in libvirt's XML format") args = parser.parse_args() name, xmldesc = read_domain(args.file) try: conn = libvirt.open(None) except libvirt.libvirtError: print('Failed to open connection to the hypervisor') exit(1) try: dom = conn.lookupByName(name) except libvirt.libvirtError: print("Starting domain %s ... " % name) dom = conn.createLinux(xmldesc, 0) if dom is None: print("failed") exit(1) else: print("done") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/esxlist.py0000755000175000017500000001171214612401403017473 0ustar00jirkajirka#!/usr/bin/env python3 """ List active domains of an ESX host and print some info. """ # also demonstrates how to use the libvirt.openAuth() method import libvirt import libxml2 import getpass from argparse import ArgumentParser from typing import Any, List # This is the callback method passed to libvirt.openAuth() (see below). # # The credentials argument is a list of credentials that libvirt (actually # the ESX driver) would like to request. An element of this list is itself a # list containing 5 items (4 inputs, 1 output): # - the credential type, e.g. libvirt.VIR_CRED_AUTHNAME # - a prompt to be displayed to the user # - a challenge, the ESX driver sets this to the hostname to allow automatic # distinction between requests for ESX and vCenter credentials # - a default result for the request # - a place to store the actual result for the request # # The user_data argument is the user data item of the auth argument (see below) # passed to libvirt.openAuth(). def request_credentials(credentials: List[List], user_data: Any) -> int: for credential in credentials: if credential[0] == libvirt.VIR_CRED_AUTHNAME: # prompt the user to input a authname. display the provided message credential[4] = input(credential[1] + ": ") # if the user just hits enter raw_input() returns an empty string. # in this case return the default result through the last item of # the list if len(credential[4]) == 0: credential[4] = credential[3] elif credential[0] == libvirt.VIR_CRED_NOECHOPROMPT: # use the getpass module to prompt the user to input a password. # display the provided message and return the result through the # last item of the list credential[4] = getpass.getpass(credential[1] + ": ") else: return -1 return 0 def print_section(title: str) -> None: print("\n%s" % title) print("=" * 60) def print_entry(key: str, value: Any) -> None: print("%-10s %-10s" % (key, value)) def print_xml(key: str, ctx, path: str) -> str: res = ctx.xpathEval(path) if res is None or len(res) == 0: value = "Unknown" else: value = res[0].content print_entry(key, value) return value parser = ArgumentParser(description=__doc__) parser.add_argument("hostname") args = parser.parse_args() # Connect to libvirt uri = "esx://%s/?no_verify=1" % args.hostname # The auth argument is a list that contains 3 items: # - a list of supported credential types # - a callable that takes 2 arguments # - user data that will be passed to the callable as second argument # # In this example the supported credential types are VIR_CRED_AUTHNAME and # VIR_CRED_NOECHOPROMPT, the callable is the unbound method request_credentials # (see above) and the user data is None. # # libvirt (actually the ESX driver) will call the callable to request # credentials in order to log into the ESX host. The callable would also be # called if the connection URI would reference a vCenter to request credentials # in order to log into the vCenter auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], request_credentials, None] try: conn = libvirt.openAuth(uri, auth, 0) except libvirt.libvirtError: print("Failed to open connection to %s" % args.hostname) exit(1) state_names = { libvirt.VIR_DOMAIN_RUNNING: "running", libvirt.VIR_DOMAIN_BLOCKED: "idle", libvirt.VIR_DOMAIN_PAUSED: "paused", libvirt.VIR_DOMAIN_SHUTDOWN: "in shutdown", libvirt.VIR_DOMAIN_SHUTOFF: "shut off", libvirt.VIR_DOMAIN_CRASHED: "crashed", libvirt.VIR_DOMAIN_NOSTATE: "no state", } for id in conn.listDomainsID(): domain = conn.lookupByID(id) info = domain.info() print_section("Domain " + domain.name()) print_entry("ID:", id) print_entry("UUID:", domain.UUIDString()) print_entry("State:", state_names[info[0]]) print_entry("MaxMem:", info[1]) print_entry("UsedMem:", info[2]) print_entry("VCPUs:", info[3]) # Read some info from the XML desc print_section("Devices of " + domain.name()) xmldesc = domain.XMLDesc(0) doc = libxml2.parseDoc(xmldesc) ctx = doc.xpathNewContext() devs = ctx.xpathEval("/domain/devices/*") first = True for d in devs: ctx.setContextNode(d) if not first: print("------------------------------------------------------------") else: first = False print_entry("Device", d.name) type = print_xml("Type:", ctx, "@type") if type == "file": print_xml("Source:", ctx, "source/@file") print_xml("Target:", ctx, "target/@dev") elif type == "block": print_xml("Source:", ctx, "source/@dev") print_xml("Target:", ctx, "target/@dev") elif type == "bridge": print_xml("Source:", ctx, "source/@bridge") print_xml("MAC Addr:", ctx, "mac/@address") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1743501822.0 libvirt-python-11.3.0/examples/event-test.py0000755000175000017500000010762614772734776020145 0ustar00jirkajirka#!/usr/bin/env python3 # # # ############################################################################## # Start off by implementing a general purpose event loop for anyone's use ############################################################################## import atexit import os import libvirt import select import errno import time import threading from argparse import ArgumentParser from typing import Any, Callable, Dict, List, Optional, TypeVar # noqa F401 _T = TypeVar("_T") _EventCallback = Callable[[int, int, int, _T], None] _TimerCallback = Callable[[int, _T], None] # This example can use three different event loop impls. It defaults # to a portable pure-python impl based on poll that is implemented # in this file. # # When Python >= 3.4, it can optionally use an impl based on the # new asyncio module. # # Finally, it can also use the libvirt native event loop impl # # This setting thus allows 'poll', 'native' or 'asyncio' as valid # choices # event_impl = "poll" do_debug = False def debug(msg: str) -> None: if do_debug: print(msg) # # This general purpose event loop will support waiting for file handle # I/O and errors events, as well as scheduling repeatable timers with # a fixed interval. # # It is a pure python implementation based around the poll() API # class virEventLoopPoll: # This class contains the data we need to track for a # single file handle class virEventLoopPollHandle: def __init__(self, handle: int, fd: int, events: int, cb: _EventCallback, opaque: _T): self.handle = handle self.fd = fd self.events = events self.cb = cb self.opaque = opaque def get_id(self) -> int: return self.handle def get_fd(self) -> int: return self.fd def get_events(self) -> int: return self.events def set_events(self, events: int): self.events = events def dispatch(self, events: int): self.cb(self.handle, self.fd, events, self.opaque) # This class contains the data we need to track for a # single periodic timer class virEventLoopPollTimer: def __init__(self, timer: int, interval: int, cb: _TimerCallback, opaque: _T): self.timer = timer self.interval = interval self.cb = cb self.opaque = opaque self.lastfired = 0 def get_id(self) -> int: return self.timer def get_interval(self) -> int: return self.interval def set_interval(self, interval: int): self.interval = interval def get_last_fired(self) -> int: return self.lastfired def set_last_fired(self, now: int): self.lastfired = now def dispatch(self) -> None: self.cb(self.timer, self.opaque) def __init__(self): self.poll = select.poll() self.pipetrick = os.pipe() self.pendingWakeup = False self.runningPoll = False self.nextHandleID = 1 self.nextTimerID = 1 self.handles = [] # type: List[virEventLoopPollHandle] self.timers = [] # type: List[virEventLoopPollTimer] self.cleanup = [] self.quit = False # The event loop can be used from multiple threads at once. # Specifically while the main thread is sleeping in poll() # waiting for events to occur, another thread may come along # and add/update/remove a file handle, or timer. When this # happens we need to interrupt the poll() sleep in the other # thread, so that it'll see the file handle / timer changes. # # Using OS level signals for this is very unreliable and # hard to implement correctly. Thus we use the real classic # "self pipe" trick. A anonymous pipe, with one end registered # with the event loop for input events. When we need to force # the main thread out of a poll() sleep, we simple write a # single byte of data to the other end of the pipe. debug("Self pipe watch %d write %d" % (self.pipetrick[0], self.pipetrick[1])) self.poll.register(self.pipetrick[0], select.POLLIN) # Calculate when the next timeout is due to occur, returning # the absolute timestamp for the next timeout, or 0 if there is # no timeout due def next_timeout(self) -> int: next = 0 for t in self.timers: last = t.get_last_fired() interval = t.get_interval() if interval < 0: continue if next == 0 or (last + interval) < next: next = last + interval return next # Lookup a virEventLoopPollHandle object based on file descriptor def get_handle_by_fd(self, fd: int) -> Optional[virEventLoopPollHandle]: for h in self.handles: if h.get_fd() == fd: return h return None # Lookup a virEventLoopPollHandle object based on its event loop ID def get_handle_by_id(self, handleID: int) -> Optional[virEventLoopPollHandle]: for h in self.handles: if h.get_id() == handleID: return h return None # This is the heart of the event loop, performing one single # iteration. It asks when the next timeout is due, and then # calculates the maximum amount of time it is able to sleep # for in poll() pending file handle events. # # It then goes into the poll() sleep. # # When poll() returns, there will zero or more file handle # events which need to be dispatched to registered callbacks # It may also be time to fire some periodic timers. # # Due to the coarse granularity of scheduler timeslices, if # we ask for a sleep of 500ms in order to satisfy a timer, we # may return up to 1 scheduler timeslice early. So even though # our sleep timeout was reached, the registered timer may not # technically be at its expiry point. This leads to us going # back around the loop with a crazy 5ms sleep. So when checking # if timeouts are due, we allow a margin of 20ms, to avoid # these pointless repeated tiny sleeps. def run_once(self) -> None: sleep = -1 # type: float self.runningPoll = True for opaque in self.cleanup: libvirt.virEventInvokeFreeCallback(opaque) self.cleanup = [] try: next = self.next_timeout() debug("Next timeout due at %d" % next) if next > 0: now = int(time.time() * 1000) if now >= next: sleep = 0 else: sleep = (next - now) / 1000.0 debug("Poll with a sleep of %d" % sleep) events = self.poll.poll(sleep) # Dispatch any file handle events that occurred for (fd, revents) in events: # See if the events was from the self-pipe # telling us to wakup. if so, then discard # the data just continue if fd == self.pipetrick[0]: self.pendingWakeup = False os.read(fd, 1) continue h = self.get_handle_by_fd(fd) if h: debug("Dispatch fd %d handle %d events %d" % (fd, h.get_id(), revents)) h.dispatch(self.events_from_poll(revents)) now = int(time.time() * 1000) for t in self.timers: interval = t.get_interval() if interval < 0: continue want = t.get_last_fired() + interval # Deduct 20ms, since scheduler timeslice # means we could be ever so slightly early if now >= want - 20: debug("Dispatch timer %d now %s want %s" % (t.get_id(), str(now), str(want))) t.set_last_fired(now) t.dispatch() except (os.error, select.error) as e: if e.args[0] != errno.EINTR: raise finally: self.runningPoll = False # Actually run the event loop forever def run_loop(self) -> None: self.quit = False while not self.quit: self.run_once() def interrupt(self) -> None: if self.runningPoll and not self.pendingWakeup: self.pendingWakeup = True os.write(self.pipetrick[1], 'c'.encode("UTF-8")) # Registers a new file handle 'fd', monitoring for 'events' (libvirt # event constants), firing the callback cb() when an event occurs. # Returns a unique integer identier for this handle, that should be # used to later update/remove it def add_handle(self, fd: int, events: int, cb: _EventCallback, opaque: _T) -> int: handleID = self.nextHandleID + 1 self.nextHandleID = self.nextHandleID + 1 h = self.virEventLoopPollHandle(handleID, fd, events, cb, opaque) self.handles.append(h) self.poll.register(fd, self.events_to_poll(events)) self.interrupt() debug("Add handle %d fd %d events %d" % (handleID, fd, events)) return handleID # Registers a new timer with periodic expiry at 'interval' ms, # firing cb() each time the timer expires. If 'interval' is -1, # then the timer is registered, but not enabled # Returns a unique integer identier for this handle, that should be # used to later update/remove it def add_timer(self, interval: int, cb: _TimerCallback, opaque: _T) -> int: timerID = self.nextTimerID + 1 self.nextTimerID = self.nextTimerID + 1 h = self.virEventLoopPollTimer(timerID, interval, cb, opaque) self.timers.append(h) self.interrupt() debug("Add timer %d interval %d" % (timerID, interval)) return timerID # Change the set of events to be monitored on the file handle def update_handle(self, handleID: int, events: int) -> None: h = self.get_handle_by_id(handleID) if h: h.set_events(events) self.poll.unregister(h.get_fd()) self.poll.register(h.get_fd(), self.events_to_poll(events)) self.interrupt() debug("Update handle %d fd %d events %d" % (handleID, h.get_fd(), events)) # Change the periodic frequency of the timer def update_timer(self, timerID: int, interval: int) -> None: for h in self.timers: if h.get_id() == timerID: h.set_interval(interval) self.interrupt() debug("Update timer %d interval %d" % (timerID, interval)) break # Stop monitoring for events on the file handle def remove_handle(self, handleID: int) -> int: handles = [] for h in self.handles: if h.get_id() == handleID: debug("Remove handle %d fd %d" % (handleID, h.get_fd())) self.poll.unregister(h.get_fd()) self.cleanup.append(h.opaque) else: handles.append(h) self.handles = handles self.interrupt() return 0 # Stop firing the periodic timer def remove_timer(self, timerID: int) -> int: timers = [] for h in self.timers: if h.get_id() != timerID: timers.append(h) else: debug("Remove timer %d" % timerID) self.cleanup.append(h.opaque) self.timers = timers self.interrupt() return 0 # Convert from libvirt event constants, to poll() events constants def events_to_poll(self, events: int) -> int: ret = 0 if events & libvirt.VIR_EVENT_HANDLE_READABLE: ret |= select.POLLIN if events & libvirt.VIR_EVENT_HANDLE_WRITABLE: ret |= select.POLLOUT if events & libvirt.VIR_EVENT_HANDLE_ERROR: ret |= select.POLLERR if events & libvirt.VIR_EVENT_HANDLE_HANGUP: ret |= select.POLLHUP return ret # Convert from poll() event constants, to libvirt events constants def events_from_poll(self, events: int) -> int: ret = 0 if events & select.POLLIN: ret |= libvirt.VIR_EVENT_HANDLE_READABLE if events & select.POLLOUT: ret |= libvirt.VIR_EVENT_HANDLE_WRITABLE if events & select.POLLNVAL: ret |= libvirt.VIR_EVENT_HANDLE_ERROR if events & select.POLLERR: ret |= libvirt.VIR_EVENT_HANDLE_ERROR if events & select.POLLHUP: ret |= libvirt.VIR_EVENT_HANDLE_HANGUP return ret ########################################################################### # Now glue an instance of the general event loop into libvirt's event loop ########################################################################### # This single global instance of the event loop wil be used for # monitoring libvirt events eventLoop = virEventLoopPoll() # This keeps track of what thread is running the event loop, # (if it is run in a background thread) eventLoopThread = None # These next set of 6 methods are the glue between the official # libvirt events API, and our particular impl of the event loop # # There is no reason why the 'virEventLoopPoll' has to be used. # An application could easily may these 6 glue methods hook into # another event loop such as GLib's, or something like the python # Twisted event framework. def virEventAddHandleImpl(fd: int, events: int, cb: _EventCallback, opaque: _T) -> int: return eventLoop.add_handle(fd, events, cb, opaque) def virEventUpdateHandleImpl(handleID: int, events: int) -> None: return eventLoop.update_handle(handleID, events) def virEventRemoveHandleImpl(handleID: int) -> int: return eventLoop.remove_handle(handleID) def virEventAddTimerImpl(interval: int, cb: _TimerCallback, opaque: _T) -> int: return eventLoop.add_timer(interval, cb, opaque) def virEventUpdateTimerImpl(timerID: int, interval: int) -> None: return eventLoop.update_timer(timerID, interval) def virEventRemoveTimerImpl(timerID: int) -> int: return eventLoop.remove_timer(timerID) # This tells libvirt what event loop implementation it # should use def virEventLoopPollRegister() -> None: libvirt.virEventRegisterImpl(virEventAddHandleImpl, virEventUpdateHandleImpl, virEventRemoveHandleImpl, virEventAddTimerImpl, virEventUpdateTimerImpl, virEventRemoveTimerImpl) # Directly run the event loop in the current thread def virEventLoopPollRun() -> None: eventLoop.run_loop() def virEventLoopAIORun(loop) -> None: import asyncio asyncio.set_event_loop(loop) loop.run_forever() def virEventLoopNativeRun() -> None: while True: libvirt.virEventRunDefaultImpl() # Spawn a background thread to run the event loop def virEventLoopPollStart() -> None: global eventLoopThread virEventLoopPollRegister() eventLoopThread = threading.Thread(target=virEventLoopPollRun, name="libvirtEventLoop", daemon=True) eventLoopThread.start() def virEventLoopAIOStart() -> None: global eventLoopThread import libvirtaio import asyncio loop = asyncio.new_event_loop() libvirtaio.virEventRegisterAsyncIOImpl(loop=loop) eventLoopThread = threading.Thread(target=virEventLoopAIORun, args=(loop,), name="libvirtEventLoop", daemon=True) eventLoopThread.start() def virEventLoopNativeStart() -> None: global eventLoopThread libvirt.virEventRegisterDefaultImpl() eventLoopThread = threading.Thread(target=virEventLoopNativeRun, name="libvirtEventLoop", daemon=True) eventLoopThread.start() ########################################################################## # Everything that now follows is a simple demo of domain lifecycle events ########################################################################## class Description(object): __slots__ = ('desc', 'args') def __init__(self, *args, **kwargs) -> None: self.desc = kwargs.get('desc') self.args = args def __str__(self) -> str: return self.desc or '' def __getitem__(self, item: int) -> 'Description': try: data = self.args[item] except IndexError: return self.__class__(desc=str(item)) if isinstance(data, str): return self.__class__(desc=data) elif isinstance(data, (list, tuple)): desc, args = data return self.__class__(*args, desc=desc) raise TypeError(args) DOM_EVENTS = Description( ("Defined", ("Added", "Updated", "Renamed", "Snapshot")), ("Undefined", ("Removed", "Renamed")), ("Started", ("Booted", "Migrated", "Restored", "Snapshot", "Wakeup")), ("Suspended", ("Paused", "Migrated", "IOError", "Watchdog", "Restored", "Snapshot", "API error", "Postcopy", "Postcopy failed")), ("Resumed", ("Unpaused", "Migrated", "Snapshot", "Postcopy")), ("Stopped", ("Shutdown", "Destroyed", "Crashed", "Migrated", "Saved", "Failed", "Snapshot", "Daemon")), ("Shutdown", ("Finished", "On guest request", "On host request")), ("PMSuspended", ("Memory", "Disk")), ("Crashed", ("Panicked",)), ) BLOCK_JOB_TYPES = Description("unknown", "Pull", "Copy", "Commit", "ActiveCommit") BLOCK_JOB_STATUS = Description("Completed", "Failed", "Canceled", "Ready") WATCHDOG_ACTIONS = Description("none", "Pause", "Reset", "Poweroff", "Shutdown", "Debug", "Inject NMI") ERROR_EVENTS = Description("None", "Pause", "Report") AGENT_STATES = Description("unknown", "connected", "disconnected") AGENT_REASONS = Description("unknown", "domain started", "channel event") GRAPHICS_PHASES = Description("Connect", "Initialize", "Disconnect") DISK_EVENTS = Description("Change missing on start", "Drop missing on start") TRAY_EVENTS = Description("Opened", "Closed") def myDomainEventCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, event: int, detail: int, opaque: _T) -> None: print("myDomainEventCallback%s EVENT: Domain %s(%s) %s %s" % ( opaque, dom.name(), dom.ID(), DOM_EVENTS[event], DOM_EVENTS[event][detail])) def myDomainEventRebootCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, opaque: _T) -> None: print("myDomainEventRebootCallback: Domain %s(%s)" % ( dom.name(), dom.ID())) def myDomainEventRTCChangeCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, utcoffset: int, opaque: _T) -> None: print("myDomainEventRTCChangeCallback: Domain %s(%s) %d" % ( dom.name(), dom.ID(), utcoffset)) def myDomainEventWatchdogCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, action: int, opaque: _T) -> None: print("myDomainEventWatchdogCallback: Domain %s(%s) %s" % ( dom.name(), dom.ID(), WATCHDOG_ACTIONS[action])) def myDomainEventIOErrorCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, srcpath: str, devalias: str, action: int, opaque: _T) -> None: print("myDomainEventIOErrorCallback: Domain %s(%s) %s %s %s" % ( dom.name(), dom.ID(), srcpath, devalias, ERROR_EVENTS[action])) def myDomainEventIOErrorReasonCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, srcpath: str, devalias: str, action: int, reason: int, opaque: _T) -> None: print("myDomainEventIOErrorReasonCallback: Domain %s(%s) %s %s %s %s" % ( dom.name(), dom.ID(), srcpath, devalias, ERROR_EVENTS[action], reason)) def myDomainEventGraphicsCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, phase: int, localAddr: str, remoteAddr: str, authScheme: str, subject: str, opaque: _T) -> None: print("myDomainEventGraphicsCallback: Domain %s(%s) %s %s" % ( dom.name(), dom.ID(), GRAPHICS_PHASES[phase], authScheme)) def myDomainEventControlErrorCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, opaque: _T) -> None: print("myDomainEventControlErrorCallback: Domain %s(%s)" % ( dom.name(), dom.ID())) def myDomainEventBlockJobCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, disk, type: int, status: int, opaque: _T) -> None: print("myDomainEventBlockJobCallback: Domain %s(%s) %s on disk %s %s" % ( dom.name(), dom.ID(), BLOCK_JOB_TYPES[type], disk, BLOCK_JOB_STATUS[status])) def myDomainEventDiskChangeCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, oldSrcPath: str, newSrcPath: str, devAlias: str, reason: int, opaque: _T) -> None: print("myDomainEventDiskChangeCallback: Domain %s(%s) disk change oldSrcPath: %s newSrcPath: %s devAlias: %s reason: %s" % ( dom.name(), dom.ID(), oldSrcPath, newSrcPath, devAlias, DISK_EVENTS[reason])) def myDomainEventTrayChangeCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, devAlias: str, reason: int, opaque: _T) -> None: print("myDomainEventTrayChangeCallback: Domain %s(%s) tray change devAlias: %s reason: %s" % ( dom.name(), dom.ID(), devAlias, TRAY_EVENTS[reason])) def myDomainEventPMWakeupCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, reason: int, opaque: _T) -> None: print("myDomainEventPMWakeupCallback: Domain %s(%s) system pmwakeup" % ( dom.name(), dom.ID())) def myDomainEventPMSuspendCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, reason: int, opaque: _T) -> None: print("myDomainEventPMSuspendCallback: Domain %s(%s) system pmsuspend" % ( dom.name(), dom.ID())) def myDomainEventBalloonChangeCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, actual: int, opaque: _T) -> None: print("myDomainEventBalloonChangeCallback: Domain %s(%s) %d" % ( dom.name(), dom.ID(), actual)) def myDomainEventPMSuspendDiskCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, reason: int, opaque: _T) -> None: print("myDomainEventPMSuspendDiskCallback: Domain %s(%s) system pmsuspend_disk" % ( dom.name(), dom.ID())) def myDomainEventDeviceRemovedCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, dev: str, opaque: _T) -> None: print("myDomainEventDeviceRemovedCallback: Domain %s(%s) device removed: %s" % ( dom.name(), dom.ID(), dev)) def myDomainEventBlockJob2Callback(conn: libvirt.virConnect, dom: libvirt.virDomain, disk: str, type: int, status: int, opaque: _T) -> None: print("myDomainEventBlockJob2Callback: Domain %s(%s) %s on disk %s %s" % ( dom.name(), dom.ID(), BLOCK_JOB_TYPES[type], disk, BLOCK_JOB_STATUS[status])) def myDomainEventTunableCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, params: Dict[str, Any], opaque: _T) -> None: print("myDomainEventTunableCallback: Domain %s(%s) %s" % ( dom.name(), dom.ID(), params)) def myDomainEventAgentLifecycleCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, state: int, reason: int, opaque: _T) -> None: print("myDomainEventAgentLifecycleCallback: Domain %s(%s) %s %s" % ( dom.name(), dom.ID(), AGENT_STATES[state], AGENT_REASONS[reason])) def myDomainEventDeviceAddedCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, dev: str, opaque: _T) -> None: print("myDomainEventDeviceAddedCallback: Domain %s(%s) device added: %s" % ( dom.name(), dom.ID(), dev)) def myDomainEventMigrationIteration(conn: libvirt.virConnect, dom: libvirt.virDomain, iteration: int, opaque: _T) -> None: print("myDomainEventMigrationIteration: Domain %s(%s) started migration iteration %d" % ( dom.name(), dom.ID(), iteration)) def myDomainEventJobCompletedCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, params: Dict[str, Any], opaque: _T) -> None: print("myDomainEventJobCompletedCallback: Domain %s(%s) %s" % ( dom.name(), dom.ID(), params)) def myDomainEventDeviceRemovalFailedCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, dev: str, opaque: _T) -> None: print("myDomainEventDeviceRemovalFailedCallback: Domain %s(%s) failed to remove device: %s" % ( dom.name(), dom.ID(), dev)) def myDomainEventMetadataChangeCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, mtype: int, nsuri: str, opaque: _T) -> None: print("myDomainEventMetadataChangeCallback: Domain %s(%s) changed metadata mtype=%d nsuri=%s" % ( dom.name(), dom.ID(), mtype, nsuri)) def myDomainEventBlockThresholdCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, dev: str, path: str, threshold: int, excess: int, opaque: _T) -> None: print("myDomainEventBlockThresholdCallback: Domain %s(%s) block device %s(%s) threshold %d exceeded by %d" % ( dom.name(), dom.ID(), dev, path, threshold, excess)) def myDomainEventMemoryFailureCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, recipient: int, action: int, flags: int, opaque: _T) -> None: print("myDomainEventMemoryFailureCallback: Domain %s(%s) memory failure recipient %d action %d flags %d" % ( dom.name(), dom.ID(), recipient, action, flags)) def myDomainEventMemoryDeviceSizeChangeCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, recipient: int, action: int, flags: int, opaque: _T) -> None: print("myDomainEventMemoryDeviceSizeChangeCallback: Domain %s(%s) memory device size change alias %s size %d" % ( dom.name(), dom.ID(), alias, size)) def myDomainEventNICMACChangeCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, alias: str, oldMAC: str, newMAC: str, opaque: _T) -> None: print("myDomainEventNICMACChangeCallback: Domain %s(%s) NIC MAC change alias %s old MAC: %s new MAC: %s" % ( dom.name(), dom.ID(), alias, oldMAC, newMAC)) ########################################################################## # Network events ########################################################################## NET_EVENTS = Description( ("Defined", ("Added",)), ("Undefined", ("Removed",)), ("Started", ("Started",)), ("Stopped", ("Stopped",)), ) def myNetworkEventLifecycleCallback(conn: libvirt.virConnect, net: libvirt.virNetwork, event: int, detail: int, opaque: _T) -> None: print("myNetworkEventLifecycleCallback: Network %s %s %s" % ( net.name(), NET_EVENTS[event], NET_EVENTS[event][detail])) def myNetworkEventMetadataChangeCallback(conn: libvirt.virConnect, dom: libvirt.virNetwork, mtype: int, nsuri: str, opaque: _T) -> None: print("myNetworkEventMetadataChangeCallback: Network %s(%s) changed metadata mtype=%d nsuri=%s" % ( dom.name(), dom.ID(), mtype, nsuri)) ########################################################################## # Storage pool events ########################################################################## STORAGE_EVENTS = Description( ("Defined", ()), ("Undefined", ()), ("Started", ()), ("Stopped", ()), ("Created", ()), ("Deleted", ()), ) def myStoragePoolEventLifecycleCallback(conn: libvirt.virConnect, pool: libvirt.virStoragePool, event: int, detail: int, opaque: _T) -> None: print("myStoragePoolEventLifecycleCallback: Storage pool %s %s %s" % ( pool.name(), STORAGE_EVENTS[event], STORAGE_EVENTS[event][detail])) def myStoragePoolEventRefreshCallback(conn: libvirt.virConnect, pool: libvirt.virStoragePool, opaque: _T) -> None: print("myStoragePoolEventRefreshCallback: Storage pool %s" % pool.name()) ########################################################################## # Node device events ########################################################################## DEVICE_EVENTS = Description( ("Created", ()), ("Deleted", ()), ) def myNodeDeviceEventLifecycleCallback(conn: libvirt.virConnect, dev: libvirt.virNodeDevice, event: int, detail: int, opaque: _T) -> None: print("myNodeDeviceEventLifecycleCallback: Node device %s %s %s" % ( dev.name(), DEVICE_EVENTS[event], DEVICE_EVENTS[event][detail])) def myNodeDeviceEventUpdateCallback(conn: libvirt.virConnect, dev: libvirt.virNodeDevice, opaque: _T) -> None: print("myNodeDeviceEventUpdateCallback: Node device %s" % dev.name()) ########################################################################## # Secret events ########################################################################## SECRET_EVENTS = Description( ("Defined", ()), ("Undefined", ()), ) def mySecretEventLifecycleCallback(conn: libvirt.virConnect, secret: libvirt.virSecret, event: int, detail: int, opaque: _T) -> None: print("mySecretEventLifecycleCallback: Secret %s %s %s" % ( secret.UUIDString(), SECRET_EVENTS[event], SECRET_EVENTS[event][detail])) def mySecretEventValueChanged(conn: libvirt.virConnect, secret: libvirt.virSecret, opaque: _T) -> None: print("mySecretEventValueChanged: Secret %s" % secret.UUIDString()) ########################################################################## # Set up and run the program ########################################################################## run = True CONNECTION_EVENTS = Description("Error", "End-of-file", "Keepalive", "Client") def myConnectionCloseCallback(conn: libvirt.virConnect, reason: int, opaque: _T) -> None: print("myConnectionCloseCallback: %s: %s" % ( conn.getURI(), CONNECTION_EVENTS[reason])) global run run = False def main() -> None: parser = ArgumentParser() parser.add_argument("--debug", "-d", action="store_true", help="Print debug output") parser.add_argument("--loop", "-l", choices=("native", "poll", "asyncio"), default=event_impl, help="Choose event-loop-implementation") parser.add_argument("--timeout", type=int, default=None, help="Quit after SECS seconds running") parser.add_argument("uri", nargs="?", default="qemu:///system") args = parser.parse_args() if args.debug: global do_debug do_debug = True print("Using uri '%s' and event loop '%s'" % (args.uri, args.loop)) # Run a background thread with the event loop if args.loop == "poll": virEventLoopPollStart() elif args.loop == "asyncio": virEventLoopAIOStart() else: virEventLoopNativeStart() vc = libvirt.openReadOnly(args.uri) # Close connection on exit (to test cleanup paths) def exit() -> None: print("Closing " + vc.getURI()) if run: vc.close() atexit.register(exit) vc.registerCloseCallback(myConnectionCloseCallback, None) # Add 2 lifecycle callbacks to prove this works with more than just one vc.domainEventRegister(myDomainEventCallback, 1) domcallbacks = [ vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, myDomainEventCallback, 2), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_REBOOT, myDomainEventRebootCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_RTC_CHANGE, myDomainEventRTCChangeCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_WATCHDOG, myDomainEventWatchdogCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR, myDomainEventIOErrorCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_GRAPHICS, myDomainEventGraphicsCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON, myDomainEventIOErrorReasonCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_CONTROL_ERROR, myDomainEventControlErrorCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB, myDomainEventBlockJobCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_DISK_CHANGE, myDomainEventDiskChangeCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_TRAY_CHANGE, myDomainEventTrayChangeCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_PMWAKEUP, myDomainEventPMWakeupCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_PMSUSPEND, myDomainEventPMSuspendCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE, myDomainEventBalloonChangeCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK, myDomainEventPMSuspendDiskCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED, myDomainEventDeviceRemovedCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2, myDomainEventBlockJob2Callback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_TUNABLE, myDomainEventTunableCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE, myDomainEventAgentLifecycleCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_ADDED, myDomainEventDeviceAddedCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION, myDomainEventMigrationIteration, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_JOB_COMPLETED, myDomainEventJobCompletedCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED, myDomainEventDeviceRemovalFailedCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_METADATA_CHANGE, myDomainEventMetadataChangeCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE, myDomainEventMemoryFailureCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE, myDomainEventMemoryDeviceSizeChangeCallback, None), vc.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE, myDomainEventNICMACChangeCallback, None), ] netcallbacks = [ vc.networkEventRegisterAny(None, libvirt.VIR_NETWORK_EVENT_ID_LIFECYCLE, myNetworkEventLifecycleCallback, None), vc.networkEventRegisterAny(None, libvirt.VIR_NETWORK_EVENT_ID_METADATA_CHANGE, myNetworkEventMetadataChangeCallback, None), ] poolcallbacks = [ vc.storagePoolEventRegisterAny(None, libvirt.VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE, myStoragePoolEventLifecycleCallback, None), vc.storagePoolEventRegisterAny(None, libvirt.VIR_STORAGE_POOL_EVENT_ID_REFRESH, myStoragePoolEventRefreshCallback, None), ] devcallbacks = [ vc.nodeDeviceEventRegisterAny(None, libvirt.VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE, myNodeDeviceEventLifecycleCallback, None), vc.nodeDeviceEventRegisterAny(None, libvirt.VIR_NODE_DEVICE_EVENT_ID_UPDATE, myNodeDeviceEventUpdateCallback, None), ] seccallbacks = [ vc.secretEventRegisterAny(None, libvirt.VIR_SECRET_EVENT_ID_LIFECYCLE, mySecretEventLifecycleCallback, None), vc.secretEventRegisterAny(None, libvirt.VIR_SECRET_EVENT_ID_VALUE_CHANGED, mySecretEventValueChanged, None), ] vc.setKeepAlive(5, 3) # The rest of your app would go here normally, but for sake # of demo we'll just go to sleep. The other option is to # run the event loop in your main thread if your app is # totally event based. count = 0 while run and (args.timeout is None or count < args.timeout): count = count + 1 time.sleep(1) # If the connection was closed, we cannot unregister anything. # Just abort now. if not run: return vc.domainEventDeregister(myDomainEventCallback) for id in seccallbacks: vc.secretEventDeregisterAny(id) for id in devcallbacks: vc.nodeDeviceEventDeregisterAny(id) for id in poolcallbacks: vc.storagePoolEventDeregisterAny(id) for id in netcallbacks: vc.networkEventDeregisterAny(id) for id in domcallbacks: vc.domainEventDeregisterAny(id) vc.unregisterCloseCallback() vc.close() # Allow delayed event loop cleanup to run, just for sake of testing time.sleep(2) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000003300000000000010211 xustar0027 mtime=1746171070.896949 libvirt-python-11.3.0/examples/guest-vcpus/0000755000175000017500000000000015005072277017720 5ustar00jirkajirka././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/guest-vcpus/guest-vcpu-daemon.py0000755000175000017500000000745014612401403023634 0ustar00jirkajirka#!/usr/bin/env python3 """ This service waits for the guest agent lifecycle event and reissues guest agent calls to modify the cpu count according to the metadata set by guest-vcpu.py example """ import libvirt import threading from xml.dom import minidom import time from argparse import ArgumentParser uri = "qemu:///system" customXMLuri = "guest-cpu.python.libvirt.org" connectRetryTimeout = 5 class workerData: def __init__(self): self.doms = list() self.conn = None self.cond = threading.Condition() def notify(self): self.cond.acquire() self.cond.notify() self.cond.release() def waitNotify(self): self.cond.acquire() self.cond.wait() self.cond.release() def addDomainNotify(self, dom): self.doms.append(dom) self.notify() def closeConnectNotify(self): conn = self.conn self.conn = None conn.close() self.notify() def setConnect(self, conn): self.conn = conn def hasConn(self): return self.conn is not None def hasDom(self): return len(self.doms) > 0 def getDom(self): return self.doms.pop() def setDoms(self, doms): self.doms = doms def virEventLoopNativeRun(): while True: libvirt.virEventRunDefaultImpl() def handleAgentLifecycleEvent(conn, dom, state, reason, opaque): if state == libvirt.VIR_CONNECT_DOMAIN_EVENT_AGENT_LIFECYCLE_STATE_CONNECTED: opaque.addDomainNotify(dom) def handleConnectClose(conn, reason, opaque): print('Disconnected from ' + uri) opaque.closeConnectNotify() def handleLibvirtLibraryError(opaque, error): pass def processAgentConnect(dom): try: cpus = dom.metadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, customXMLuri, libvirt.VIR_DOMAIN_AFFECT_LIVE) doc = minidom.parseString(cpus) ncpus = int(doc.getElementsByTagName('ncpus')[0].getAttribute('count')) except Exception: return try: dom.setVcpusFlags(ncpus, libvirt.VIR_DOMAIN_AFFECT_LIVE | libvirt.VIR_DOMAIN_VCPU_GUEST) print("set vcpu count for domain " + dom.name() + " to " + str(ncpus)) except Exception: print("failed to set vcpu count for domain " + dom.name()) def work(): data = workerData() print("Using uri: " + uri) while True: if not data.hasConn(): try: conn = libvirt.open(uri) except libvirt.libvirtError: print('Failed to connect to ' + uri + ', retry in ' + str(connectRetryTimeout)) + ' seconds' time.sleep(connectRetryTimeout) continue print('Connected to ' + uri) data.setConnect(conn) conn.registerCloseCallback(handleConnectClose, data) conn.setKeepAlive(5, 3) conn.domainEventRegisterAny(None, libvirt.VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE, handleAgentLifecycleEvent, data) data.setDoms(conn.listAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE)) while data.hasConn() and data.hasDom(): processAgentConnect(data.getDom()) data.waitNotify() def main(): libvirt.virEventRegisterDefaultImpl() libvirt.registerErrorHandler(handleLibvirtLibraryError, None) worker = threading.Thread(target=work) worker.setDaemon(True) worker.start() eventLoop = threading.Thread(target=virEventLoopNativeRun) eventLoop.setDaemon(True) eventLoop.start() while True: time.sleep(1) if __name__ == "__main__": parser = ArgumentParser(description=__doc__) parser.add_argument("uri", nargs="?", default=uri) args = parser.parse_args() uri = args.uri main() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/guest-vcpus/guest-vcpu.py0000755000175000017500000000306414612401403022370 0ustar00jirkajirka#!/usr/bin/env python3 """ Sets the vCPU count via the guest agent and sets the metadata element used by guest-vcpu-daemon.py example """ import libvirt from argparse import ArgumentParser customXMLuri = "guest-cpu.python.libvirt.org" parser = ArgumentParser(description=__doc__) parser.add_argument("--config", "-c", action="store_true", help="Modify persistent domain configuration") parser.add_argument("--live", "-l", action="store_true", help="Modify live domain configuration") parser.add_argument("domain") parser.add_argument("count", type=int) parser.add_argument("uri", nargs="?", default="qemu:///system") args = parser.parse_args() flags = (libvirt.VIR_DOMAIN_AFFECT_CONFIG if args.config else 0) | (libvirt.VIR_DOMAIN_AFFECT_LIVE if args.live else 0) conn = libvirt.open(args.uri) dom = conn.lookupByName(args.domain) if flags == 0 or args.config: confvcpus = dom.vcpusFlags(libvirt.VIR_DOMAIN_AFFECT_CONFIG) if confvcpus < args.count: print("Persistent domain configuration has only " + str(confvcpus) + " vcpus configured") exit(1) if flags == 0 or args.live: livevcpus = dom.vcpusFlags(libvirt.VIR_DOMAIN_AFFECT_LIVE) if livevcpus < args.count: print("Live domain configuration has only " + str(livevcpus) + " vcpus configured") exit(1) if flags == 0 or args.live: dom.setVcpusFlags(args.count, libvirt.VIR_DOMAIN_AFFECT_LIVE | libvirt.VIR_DOMAIN_VCPU_GUEST) meta = "" dom.setMetadata(libvirt.VIR_DOMAIN_METADATA_ELEMENT, meta, "guestvcpudaemon", customXMLuri, flags) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1719825184.0 libvirt-python-11.3.0/examples/nodestats.py0000755000175000017500000000533614640471440020022 0ustar00jirkajirka#!/usr/bin/env python3 # Print some host NUMA node statistics # # Authors: # Michal Privoznik import libvirt from xml.dom import minidom import libxml2 from typing import Any, Dict # noqa F401 def xpath_eval(ctxt, path: str) -> str: res = ctxt.xpathEval(path) if res is None or len(res) == 0: value = '' else: value = res[0].content return value try: conn = libvirt.openReadOnly(None) except libvirt.libvirtError: print("Failed to connect to the hypervisor") exit(1) try: capsXML = conn.getCapabilities() except libvirt.libvirtError: print("Failed to request capabilities") exit(1) caps = minidom.parseString(capsXML) cells = caps.getElementsByTagName("cells")[0] nodesIDs = [ int(proc.getAttribute("id")) for proc in cells.getElementsByTagName("cell") ] nodesMem = [ conn.getMemoryStats(int(proc)) for proc in nodesIDs ] doms = conn.listAllDomains(libvirt.VIR_CONNECT_LIST_DOMAINS_ACTIVE) domsStrict = [ proc for proc in doms if proc.numaParameters()["numa_mode"] == libvirt.VIR_DOMAIN_NUMATUNE_MEM_STRICT ] domsStrictCfg = {} # type: Dict[libvirt.virDomain, Dict[str, Dict[str, Any]]] for dom in domsStrict: xmlStr = dom.XMLDesc() doc = libxml2.parseDoc(xmlStr) ctxt = doc.xpathNewContext() domsStrictCfg[dom] = {} pin = ctxt.xpathEval("string(/domain/numatune/memory/@nodeset)") memsize = ctxt.xpathEval("string(/domain/memory)") domsStrictCfg[dom]["memory"] = {"size": int(memsize), "pin": pin} for memnode in ctxt.xpathEval("/domain/numatune/memnode"): ctxt.setContextNode(memnode) cellid = xpath_eval(ctxt, "@cellid") nodeset = xpath_eval(ctxt, "@nodeset") nodesize = xpath_eval(ctxt, "/domain/cpu/numa/cell[@id='%s']/@memory" % cellid) domsStrictCfg[dom][cellid] = {"size": int(nodesize), "pin": nodeset} print("NUMA stats") print("NUMA nodes:\t" + "\t".join(str(node) for node in nodesIDs)) print("MemTotal:\t" + "\t".join(str(i.get("total") // 1024) for i in nodesMem)) # type: ignore print("MemFree:\t" + "\t".join(str(i.get("free") // 1024) for i in nodesMem)) # type: ignore for dom, v in domsStrictCfg.items(): print("Domain '%s':\t" % dom.name()) toPrint = "\tOverall memory: %d MiB" % (v["memory"]["size"] // 1024) if v["memory"]["pin"] is not None and v["memory"]["pin"] != "": toPrint = toPrint + " nodes %s" % v["memory"]["pin"] print(toPrint) for k, node in sorted(v.items()): if k == "memory": continue toPrint = "\tNode %s:\t%d MiB" % (k, node["size"] // 1024) if node["pin"] is not None and node["pin"] != "": toPrint = toPrint + " nodes %s" % node["pin"] print(toPrint) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/sparsestream.py0000755000175000017500000000742114612401403020513 0ustar00jirkajirka#!/usr/bin/env python3 """ Either uploads local FILE to libvirt VOLUME, or downloads libvirt VOLUME into local FILE while preserving FILE/VOLUME sparseness """ # Example of sparse streams usage # # Authors: # Michal Privoznik import libvirt import os from argparse import ArgumentParser def bytesWriteHandler(stream: libvirt.virStream, buf: bytes, opaque: int) -> int: fd = opaque return os.write(fd, buf) def bytesReadHandler(stream: libvirt.virStream, nbytes: int, opaque: int) -> bytes: fd = opaque return os.read(fd, nbytes) def recvSkipHandler(stream: libvirt.virStream, length: int, opaque: int) -> None: fd = opaque cur = os.lseek(fd, length, os.SEEK_CUR) return os.ftruncate(fd, cur) def sendSkipHandler(stream: libvirt.virStream, length: int, opaque: int) -> int: fd = opaque return os.lseek(fd, length, os.SEEK_CUR) def holeHandler(stream: libvirt.virStream, opaque: int): fd = opaque cur = os.lseek(fd, 0, os.SEEK_CUR) try: data = os.lseek(fd, cur, os.SEEK_DATA) except OSError as e: if e.errno != 6: raise e else: data = -1 # There are three options: # 1) data == cur; @cur is in data # 2) data > cur; @cur is in a hole, next data at @data # 3) data < 0; either @cur is in trailing hole, or @cur is beyond EOF. if data < 0: # case 3 inData = False eof = os.lseek(fd, 0, os.SEEK_END) if (eof < cur): raise RuntimeError("Current position in file after EOF: %d" % cur) sectionLen = eof - cur else: if (data > cur): # case 2 inData = False sectionLen = data - cur else: # case 1 inData = True # We don't know where does the next hole start. Let's find out. # Here we get the same options as above hole = os.lseek(fd, data, os.SEEK_HOLE) if hole < 0: # case 3. But wait a second. There is always a trailing hole. # Do the best what we can here raise RuntimeError("No trailing hole") if (hole == data): # case 1. Again, this is suspicious. The reason we are here is # because we are in data. But at the same time we are in a # hole. WAT? raise RuntimeError("Impossible happened") else: # case 2 sectionLen = hole - data os.lseek(fd, cur, os.SEEK_SET) return [inData, sectionLen] def download(vol: libvirt.virStorageVol, st: libvirt.virStream, filename: str) -> None: offset = 0 length = 0 fd = os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, mode=0o0660) vol.download(st, offset, length, libvirt.VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM) st.sparseRecvAll(bytesWriteHandler, recvSkipHandler, fd) os.close(fd) def upload(vol: libvirt.virStorageVol, st: libvirt.virStream, filename: str) -> None: offset = 0 length = 0 fd = os.open(filename, os.O_RDONLY) vol.upload(st, offset, length, libvirt.VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM) st.sparseSendAll(bytesReadHandler, holeHandler, sendSkipHandler, fd) os.close(fd) # main parser = ArgumentParser(description=__doc__) parser.add_argument("uri") group = parser.add_mutually_exclusive_group(required=True) group.add_argument("--upload", action="store_const", const=upload, dest="operation") group.add_argument("--download", action="store_const", const=download, dest="operation") parser.add_argument("volume") parser.add_argument("file") args = parser.parse_args() conn = libvirt.open(args.uri) vol = conn.storageVolLookupByKey(args.volume) st = conn.newStream() args.operation(vol, st, args.file) st.finish() conn.close() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/examples/topology.py0000755000175000017500000000232314612401403017652 0ustar00jirkajirka#!/usr/bin/env python3 # Parse topology information from the capabilities XML and use # them to calculate host topology # # Authors: # Amador Pahim # Peter Krempa import libvirt from xml.dom import minidom try: conn = libvirt.openReadOnly(None) except libvirt.libvirtError: print('Failed to connect to the hypervisor') exit(1) try: capsXML = conn.getCapabilities() except libvirt.libvirtError: print('Failed to request capabilities') exit(1) caps = minidom.parseString(capsXML) host = caps.getElementsByTagName('host')[0] cells = host.getElementsByTagName('cells')[0] total_cpus = cells.getElementsByTagName('cpu').length socketIds = [] siblingsIds = [] socketIds = [ proc.getAttribute('socket_id') for proc in cells.getElementsByTagName('cpu') if proc.getAttribute('socket_id') not in socketIds ] siblingsIds = [ proc.getAttribute('siblings') for proc in cells.getElementsByTagName('cpu') if proc.getAttribute('siblings') not in siblingsIds ] print("Host topology") print("NUMA nodes:", cells.getAttribute('num')) print(" Sockets:", len(set(socketIds))) print(" Cores:", len(set(siblingsIds))) print(" Threads:", total_cpus) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1743501822.0 libvirt-python-11.3.0/generator.py0000755000175000017500000021157414772734776016215 0ustar00jirkajirka#!/usr/bin/env python3 # # generate python wrappers from the XML API description # import os import re import sys import xml.sax from contextlib import closing from collections import defaultdict from typing import Dict, IO, List, Optional, Set, Tuple, Union # noqa F401 ArgumentType = Tuple[str, str, str] FunctionType = Tuple[str, ArgumentType, List[ArgumentType], str, str, str] EnumValue = Union[str, int] EnumType = Dict[str, EnumValue] functions = {} # type: Dict[str, FunctionType] enums = defaultdict(dict) # type: Dict[str, EnumType] # { enumType: { enumConstant: enumValue } } event_ids = [] # type: List[str] params = [] # type: List[Tuple[str, str]] # [ (paramName, paramValue)... ] quiet = True ####################################################################### # # That part if purely the API acquisition phase from the # libvirt API description # ####################################################################### debug = 0 onlyOverrides = False sourceDir = "." buildDir = "build" libvirt_headers = [ "libvirt", "libvirt-common", "libvirt-domain", "libvirt-domain-checkpoint", "libvirt-domain-snapshot", "libvirt-event", "libvirt-host", "libvirt-interface", "libvirt-network", "libvirt-nodedev", "libvirt-nwfilter", "libvirt-secret", "libvirt-storage", "libvirt-stream", ] def openSourceFile(file: str, mode: str = "r", optional: bool = False): path = os.path.join(sourceDir, file) if optional and not os.path.exists(path): return None return open(path, mode) def parse(data: IO[str]) -> None: target = docParser() with closing(xml.sax.make_parser()) as parser: parser.setContentHandler(target) parser.parse(data) class docParser(xml.sax.handler.ContentHandler): def __init__(self) -> None: self._data = [] # type: List[str] self.in_function = False def characters(self, text: str) -> None: if debug: print("data %s" % text) self._data.append(text) def startElement(self, tag: str, attrs: Dict[str, str]) -> None: if debug: print("start %s, %s" % (tag, attrs)) if tag == 'function': self._data = [] self.in_function = True self.function_cond = '' self.function_args = [] # type: List[ArgumentType] self.function_descr = '' self.function_return = None # type: Optional[ArgumentType] self.function = attrs.get('name', '') self.function_file = attrs.get('file', '') self.function_module = attrs.get('module', '') elif tag == 'cond': self._data = [] elif tag == 'info': self._data = [] elif tag == 'arg': if self.in_function: self.function_arg_name = attrs.get('name', '') if self.function_arg_name == 'from': self.function_arg_name = 'frm' self.function_arg_type = attrs.get('type', '') self.function_arg_info = attrs.get('info', '') elif tag == 'return': if self.in_function: self.function_return_type = attrs.get('type', '') self.function_return_info = attrs.get('info', '') self.function_return_field = attrs.get('field', '') elif tag == 'enum': # enums come from header files, hence virterror.h files = libvirt_headers + ["virerror", "virterror", "libvirt-lxc", "libvirt-qemu"] if attrs['file'] in files: enum(attrs['type'], attrs['name'], attrs['value']) elif tag == "macro": if "string" in attrs: params.append((attrs['name'], attrs['string'])) def endElement(self, tag: str) -> None: if debug: print("end %s" % tag) if tag == 'function': # functions come from source files, hence 'virerror.c' if self.function: assert self.function_return modules = libvirt_headers + ["event", "virevent", "virerror", "virterror", "libvirt-lxc", "libvirt-qemu"] files = ["python", "python-lxc", "python-qemu"] if (self.function_module in modules or self.function_file in files): function(self.function, self.function_descr, self.function_return, self.function_args, self.function_file, self.function_module, self.function_cond) self.in_function = False elif tag == 'arg': if self.in_function: self.function_args.append((self.function_arg_name, self.function_arg_type, self.function_arg_info)) elif tag == 'return': if self.in_function: self.function_return = (self.function_return_type, self.function_return_info, self.function_return_field) elif tag == 'info': str = ''.join(self._data) if self.in_function: self.function_descr = str elif tag == 'cond': str = ''.join(self._data) if self.in_function: self.function_cond = str def function(name: str, desc: str, ret: ArgumentType, args: List[ArgumentType], file: str, module: str, cond: str) -> None: if onlyOverrides and name not in functions: return if name == "virConnectListDomains": name = "virConnectListDomainsID" functions[name] = (desc, ret, args, file, module, cond) def enum(type: str, name: str, value: EnumValue) -> None: if (name.startswith('VIR_DOMAIN_EVENT_ID_') or name.startswith('VIR_NETWORK_EVENT_ID_')): event_ids.append(name) if value == 'VIR_TYPED_PARAM_INT': value = 1 elif value == 'VIR_TYPED_PARAM_UINT': value = 2 elif value == 'VIR_TYPED_PARAM_LLONG': value = 3 elif value == 'VIR_TYPED_PARAM_ULLONG': value = 4 elif value == 'VIR_TYPED_PARAM_DOUBLE': value = 5 elif value == 'VIR_TYPED_PARAM_BOOLEAN': value = 6 elif value == 'VIR_DOMAIN_AFFECT_CURRENT': value = 0 elif value == 'VIR_DOMAIN_AFFECT_LIVE': value = 1 elif value == 'VIR_DOMAIN_AFFECT_CONFIG': value = 2 elif value == 'VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_BLOCK': value = -2 elif value == 'VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_DEFAULT': value = -1 elif value == 'VIR_DOMAIN_AGENT_RESPONSE_TIMEOUT_NOWAIT': value = 0 if onlyOverrides and name not in enums[type]: return enums[type][name] = value ####################################################################### # # Some filtering rules to drop functions/types which should not # be exposed as-is on the Python interface # ####################################################################### skipped_types = { # 'int *': "usually a return type", 'virConnectDomainEventCallback': "No function types in python", 'virConnectDomainEventGenericCallback': "No function types in python", 'virConnectDomainEventRTCChangeCallback': "No function types in python", 'virConnectDomainEventWatchdogCallback': "No function types in python", 'virConnectDomainEventIOErrorCallback': "No function types in python", 'virConnectDomainEventGraphicsCallback': "No function types in python", 'virConnectDomainQemuMonitorEventCallback': "No function types in python", 'virStreamEventCallback': "No function types in python", 'virEventHandleCallback': "No function types in python", 'virEventTimeoutCallback': "No function types in python", 'virDomainBlockJobInfoPtr': "Not implemented yet", } ####################################################################### # # Table of remapping to/from the python type or class to the C # counterpart. # ####################################################################### py_types = { 'void': ('', '', '', ''), 'int': ('i', '', "int", "int"), 'long': ('l', '', "long", "long"), 'double': ('d', '', "double", "double"), 'unsigned int': ('I', '', "int", "int"), 'unsigned long': ('l', '', "long", "long"), 'long long': ('L', '', "longlong", "long long"), 'unsigned long long': ('L', '', "longlong", "long long"), 'unsigned char *': ('z', '', "charPtr", "char *"), 'char *': ('z', '', "charPtr", "char *"), 'const char *': ('z', '', "constcharPtr", "const char *"), 'size_t': ('n', '', "size_t", "size_t"), 'virDomainPtr': ('O', "virDomain", "virDomainPtr", "virDomainPtr"), 'virDomain *': ('O', "virDomain", "virDomainPtr", "virDomainPtr"), 'const virDomain *': ('O', "virDomain", "virDomainPtr", "virDomainPtr"), 'virNetworkPtr': ('O', "virNetwork", "virNetworkPtr", "virNetworkPtr"), 'virNetwork *': ('O', "virNetwork", "virNetworkPtr", "virNetworkPtr"), 'const virNetwork *': ('O', "virNetwork", "virNetworkPtr", "virNetworkPtr"), 'virNetworkPortPtr': ('O', "virNetworkPort", "virNetworkPortPtr", "virNetworkPortPtr"), 'virNetworkPort *': ('O', "virNetworkPort", "virNetworkPortPtr", "virNetworkPortPtr"), 'const virNetworkPort *': ('O', "virNetworkPort", "virNetworkPortPtr", "virNetworkPortPtr"), 'virInterfacePtr': ('O', "virInterface", "virInterfacePtr", "virInterfacePtr"), 'virInterface *': ('O', "virInterface", "virInterfacePtr", "virInterfacePtr"), 'const virInterface *': ('O', "virInterface", "virInterfacePtr", "virInterfacePtr"), 'virStoragePoolPtr': ('O', "virStoragePool", "virStoragePoolPtr", "virStoragePoolPtr"), 'virStoragePool *': ('O', "virStoragePool", "virStoragePoolPtr", "virStoragePoolPtr"), 'const virStoragePool *': ('O', "virStoragePool", "virStoragePoolPtr", "virStoragePoolPtr"), 'virStorageVolPtr': ('O', "virStorageVol", "virStorageVolPtr", "virStorageVolPtr"), 'virStorageVol *': ('O', "virStorageVol", "virStorageVolPtr", "virStorageVolPtr"), 'const virStorageVol *': ('O', "virStorageVol", "virStorageVolPtr", "virStorageVolPtr"), 'virConnectPtr': ('O', "virConnect", "virConnectPtr", "virConnectPtr"), 'virConnect *': ('O', "virConnect", "virConnectPtr", "virConnectPtr"), 'const virConnect *': ('O', "virConnect", "virConnectPtr", "virConnectPtr"), 'virNodeDevicePtr': ('O', "virNodeDevice", "virNodeDevicePtr", "virNodeDevicePtr"), 'virNodeDevice *': ('O', "virNodeDevice", "virNodeDevicePtr", "virNodeDevicePtr"), 'const virNodeDevice *': ('O', "virNodeDevice", "virNodeDevicePtr", "virNodeDevicePtr"), 'virSecretPtr': ('O', "virSecret", "virSecretPtr", "virSecretPtr"), 'virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"), 'const virSecret *': ('O', "virSecret", "virSecretPtr", "virSecretPtr"), 'virNWFilterPtr': ('O', "virNWFilter", "virNWFilterPtr", "virNWFilterPtr"), 'virNWFilter *': ('O', "virNWFilter", "virNWFilterPtr", "virNWFilterPtr"), 'const virNWFilter *': ('O', "virNWFilter", "virNWFilterPtr", "virNWFilterPtr"), 'virNWFilterBindingPtr': ('O', "virNWFilterBinding", "virNWFilterBindingPtr", "virNWFilterBindingPtr"), 'virNWFilterBinding *': ('O', "virNWFilterBinding", "virNWFilterBindingPtr", "virNWFilterBindingPtr"), 'const virNWFilterBinding *': ('O', "virNWFilterBinding", "virNWFilterBindingPtr", "virNWFilterBindingPtr"), 'virStreamPtr': ('O', "virStream", "virStreamPtr", "virStreamPtr"), 'virStream *': ('O', "virStream", "virStreamPtr", "virStreamPtr"), 'const virStream *': ('O', "virStream", "virStreamPtr", "virStreamPtr"), 'virDomainCheckpointPtr': ('O', "virDomainCheckpoint", "virDomainCheckpointPtr", "virDomainCheckpointPtr"), 'virDomainCheckpoint *': ('O', "virDomainCheckpoint", "virDomainCheckpointPtr", "virDomainCheckpointPtr"), 'const virDomainCheckpoint *': ('O', "virDomainCheckpoint", "virDomainCheckpointPtr", "virDomainCheckpointPtr"), 'virDomainSnapshotPtr': ('O', "virDomainSnapshot", "virDomainSnapshotPtr", "virDomainSnapshotPtr"), 'virDomainSnapshot *': ('O', "virDomainSnapshot", "virDomainSnapshotPtr", "virDomainSnapshotPtr"), 'const virDomainSnapshot *': ('O', "virDomainSnapshot", "virDomainSnapshotPtr", "virDomainSnapshotPtr"), } # type: Dict[str, Tuple[str, str, str, str]] ####################################################################### # # This part writes the C <-> Python stubs libvirt.[ch] and # the table libvirt-export.c.inc to add when registering the Python module # ####################################################################### # Class methods which are written by hand in libvirt.c but the Python-level # code is still automatically generated (so they are not in skip_function()). skip_impl = { 'virConnectGetVersion', 'virConnectGetLibVersion', 'virConnectListDomainsID', 'virConnectListDefinedDomains', 'virConnectListNetworks', 'virConnectListDefinedNetworks', 'virConnectListSecrets', 'virConnectListInterfaces', 'virConnectListStoragePools', 'virConnectListDefinedStoragePools', 'virConnectListStorageVols', 'virConnectListDefinedStorageVols', 'virConnectListDefinedInterfaces', 'virConnectListNWFilters', 'virDomainSnapshotListNames', 'virDomainSnapshotListChildrenNames', 'virConnGetLastError', 'virGetLastError', 'virDomainGetInfo', 'virDomainGetState', 'virDomainGetControlInfo', 'virDomainGetBlockInfo', 'virDomainGetJobInfo', 'virDomainGetJobStats', 'virNodeGetInfo', 'virNodeGetSecurityModel', 'virDomainGetSecurityLabel', 'virDomainGetSecurityLabelList', 'virDomainGetUUID', 'virDomainGetUUIDString', 'virDomainLookupByUUID', 'virNetworkGetUUID', 'virNetworkGetUUIDString', 'virNetworkLookupByUUID', 'virNetworkPortGetUUID', 'virNetworkPortGetUUIDString', 'virNetworkPortLookupByUUID', 'virDomainGetAutostart', 'virNetworkGetAutostart', 'virDomainBlockStats', 'virDomainInterfaceStats', 'virDomainMemoryStats', 'virNodeGetCellsFreeMemory', 'virDomainGetSchedulerType', 'virDomainGetSchedulerParameters', 'virDomainGetSchedulerParametersFlags', 'virDomainSetSchedulerParameters', 'virDomainSetSchedulerParametersFlags', 'virDomainSetBlkioParameters', 'virDomainGetBlkioParameters', 'virDomainSetMemoryParameters', 'virDomainGetMemoryParameters', 'virDomainSetNumaParameters', 'virDomainGetNumaParameters', 'virDomainGetVcpus', 'virDomainPinVcpu', 'virDomainPinVcpuFlags', 'virDomainGetVcpuPinInfo', 'virDomainGetEmulatorPinInfo', 'virDomainPinEmulator', 'virDomainGetIOThreadInfo', 'virDomainPinIOThread', 'virDomainSetIOThreadParams', 'virSecretGetValue', 'virSecretSetValue', 'virSecretGetUUID', 'virSecretGetUUIDString', 'virSecretLookupByUUID', 'virNWFilterGetUUID', 'virNWFilterGetUUIDString', 'virNWFilterLookupByUUID', 'virStoragePoolGetUUID', 'virStoragePoolGetUUIDString', 'virStoragePoolLookupByUUID', 'virStoragePoolGetInfo', 'virStorageVolGetInfo', 'virStorageVolGetInfoFlags', 'virStoragePoolGetAutostart', 'virStoragePoolListVolumes', 'virDomainBlockPeek', 'virDomainMemoryPeek', 'virEventRegisterImpl', 'virNodeListDevices', 'virNodeDeviceListCaps', 'virConnectBaselineCPU', 'virDomainRevertToSnapshot', 'virDomainSendKey', 'virNodeGetCPUStats', 'virNodeGetMemoryStats', 'virDomainGetBlockJobInfo', 'virDomainMigrateGetCompressionCache', 'virDomainMigrateGetMaxSpeed', 'virDomainMigrateGetMaxDowntime', 'virDomainBlockStatsFlags', 'virDomainSetBlockIoTune', 'virDomainGetBlockIoTune', 'virDomainSetInterfaceParameters', 'virDomainGetInterfaceParameters', 'virDomainGetCPUStats', 'virDomainGetDiskErrors', 'virNodeGetMemoryParameters', 'virNodeSetMemoryParameters', 'virConnectSetIdentity', 'virNodeGetCPUMap', 'virDomainMigrate3', 'virDomainMigrateToURI3', 'virConnectGetCPUModelNames', 'virNodeGetFreePages', 'virNetworkGetDHCPLeases', 'virDomainBlockCopy', 'virNodeAllocPages', 'virDomainGetFSInfo', 'virDomainInterfaceAddresses', 'virDomainGetPerfEvents', 'virDomainSetPerfEvents', 'virDomainGetGuestVcpus', 'virConnectBaselineHypervisorCPU', 'virDomainGetLaunchSecurityInfo', 'virDomainSetLaunchSecurityState', 'virNodeGetSEVInfo', 'virNetworkPortGetParameters', 'virNetworkPortSetParameters', 'virDomainGetGuestInfo', 'virDomainAuthorizedSSHKeysGet', 'virDomainAuthorizedSSHKeysSet', 'virDomainGetMessages', 'virNodeDeviceGetAutostart', 'virDomainSaveParams', 'virDomainRestoreParams', 'virDomainGetAutostartOnce', 'virDomainSetThrottleGroup', 'virDomainLxcOpenNamespace', 'virDomainQemuMonitorCommand', 'virDomainQemuAgentCommand', } # These are functions which the generator skips completely - no python # or C code is generated. Generally should not be used for any more # functions than those already listed skip_function = { 'virConnectListDomains', # Python API is called virConnectListDomainsID for unknown reasons 'virConnSetErrorFunc', # Not used in Python API XXX is this a bug ? 'virResetError', # Not used in Python API XXX is this a bug ? 'virGetVersion', # Python C code is manually written 'virSetErrorFunc', # Python API is called virRegisterErrorHandler for unknown reasons 'virConnCopyLastError', # Python API is called virConnGetLastError instead 'virCopyLastError', # Python API is called virGetLastError instead 'virConnectOpenAuth', # Python C code is manually written 'virDefaultErrorFunc', # Python virErrorFuncHandler impl calls this from C 'virConnectDomainEventRegister', # overridden in virConnect.py 'virConnectDomainEventDeregister', # overridden in virConnect.py 'virConnectDomainEventRegisterAny', # overridden in virConnect.py 'virConnectDomainEventDeregisterAny', # overridden in virConnect.py 'virConnectNetworkEventRegisterAny', # overridden in virConnect.py 'virConnectNetworkEventDeregisterAny', # overridden in virConnect.py 'virConnectStoragePoolEventRegisterAny', # overridden in virConnect.py 'virConnectStoragePoolEventDeregisterAny', # overridden in virConnect.py 'virConnectNodeDeviceEventRegisterAny', # overridden in virConnect.py 'virConnectNodeDeviceEventDeregisterAny', # overridden in virConnect.py 'virConnectSecretEventRegisterAny', # overridden in virConnect.py 'virConnectSecretEventDeregisterAny', # overridden in virConnect.py 'virSaveLastError', # We have our own python error wrapper 'virFreeError', # Only needed if we use virSaveLastError 'virConnectListAllDomains', # overridden in virConnect.py 'virDomainListAllCheckpoints', # overridden in virDomain.py 'virDomainCheckpointListAllChildren', # overridden in virDomainCheckpoint.py 'virDomainListAllSnapshots', # overridden in virDomain.py 'virDomainSnapshotListAllChildren', # overridden in virDomainSnapshot.py 'virConnectListAllStoragePools', # overridden in virConnect.py 'virStoragePoolListAllVolumes', # overridden in virStoragePool.py 'virConnectListAllNetworks', # overridden in virConnect.py 'virNetworkListAllPorts', # overridden in virConnect.py 'virConnectListAllInterfaces', # overridden in virConnect.py 'virConnectListAllNodeDevices', # overridden in virConnect.py 'virConnectListAllNWFilters', # overridden in virConnect.py 'virConnectListAllNWFilterBindings', # overridden in virConnect.py 'virConnectListAllSecrets', # overridden in virConnect.py 'virConnectGetAllDomainStats', # overridden in virConnect.py 'virDomainListGetStats', # overridden in virConnect.py 'virDomainFDAssociate', # overridden in virDomain.py 'virStreamRecvAll', # Pure python libvirt-override-virStream.py 'virStreamSendAll', # Pure python libvirt-override-virStream.py 'virStreamRecv', # overridden in libvirt-override-virStream.py 'virStreamSend', # overridden in libvirt-override-virStream.py 'virStreamRecvHole', # overridden in libvirt-override-virStream.py 'virStreamSendHole', # overridden in libvirt-override-virStream.py 'virStreamRecvFlags', # overridden in libvirt-override-virStream.py 'virStreamSparseRecvAll', # overridden in libvirt-override-virStream.py 'virStreamSparseSendAll', # overridden in libvirt-override-virStream.py 'virConnectUnregisterCloseCallback', # overridden in virConnect.py 'virConnectRegisterCloseCallback', # overridden in virConnect.py 'virDomainCreateXMLWithFiles', # overridden in virConnect.py 'virDomainCreateWithFiles', # overridden in virDomain.py 'virDomainFSFreeze', # overridden in virDomain.py 'virDomainFSThaw', # overridden in virDomain.py 'virDomainGetTime', # overridden in virDomain.py 'virDomainSetTime', # overridden in virDomain.py # 'Ref' functions have no use for bindings users. "virConnectRef", "virDomainRef", "virInterfaceRef", "virNetworkRef", "virNetworkPortRef", "virNodeDeviceRef", "virSecretRef", "virNWFilterRef", "virNWFilterBindingRef", "virStoragePoolRef", "virStorageVolRef", "virStreamRef", "virDomainCheckpointRef", "virDomainSnapshotRef", # This functions shouldn't be called via the bindings (and even the docs # contain an explicit warning to that effect). The equivalent should be # implemented in pure python for each class "virDomainGetConnect", "virInterfaceGetConnect", "virNetworkGetConnect", "virNetworkPortGetNetwork", "virSecretGetConnect", "virNWFilterGetConnect", "virStoragePoolGetConnect", "virStorageVolGetConnect", "virDomainCheckpointGetConnect", "virDomainCheckpointGetDomain", "virDomainSnapshotGetConnect", "virDomainSnapshotGetDomain", # only useful in C code, python code uses dict for typed parameters "virTypedParamsAddBoolean", "virTypedParamsAddDouble", "virTypedParamsAddFromString", "virTypedParamsAddInt", "virTypedParamsAddLLong", "virTypedParamsAddString", "virTypedParamsAddUInt", "virTypedParamsAddULLong", "virTypedParamsClear", "virTypedParamsFree", "virTypedParamsGet", "virTypedParamsGetBoolean", "virTypedParamsGetDouble", "virTypedParamsGetInt", "virTypedParamsGetLLong", "virTypedParamsGetString", "virTypedParamsGetUInt", "virTypedParamsGetULLong", 'virNetworkDHCPLeaseFree', # only useful in C, python code uses list 'virDomainStatsRecordListFree', # only useful in C, python uses dict 'virDomainFSInfoFree', # only useful in C, python code uses list 'virDomainIOThreadInfoFree', # only useful in C, python code uses list 'virDomainInterfaceFree', # only useful in C, python code uses list "virDomainLxcEnterNamespace", "virDomainLxcEnterSecurityLabel", # "virDomainQemuAttach", 'virConnectDomainQemuMonitorEventRegister', # overridden in -qemu.py 'virConnectDomainQemuMonitorEventDeregister', # overridden in -qemu.py 'virDomainQemuMonitorCommandWithFiles', # overridden in -qemu.py } # Generate C code, but skip python impl function_skip_python_impl = { "virStreamFree", # Needed in custom virStream __del__, but free shouldn't # be exposed in bindings } function_skip_index_one = { "virDomainRevertToSnapshot", } def validate_function(name): (desc, ret, args, file, mod, cond) = functions[name] if name in skip_function: return [] if name in skip_impl: return [] failed = False unknown = [] for a_name, a_type, a_info in args: # This should be correct if a_type[0:6] == "const ": a_type = a_type[6:] if a_type in skipped_types: return [] if a_type not in py_types: unknown.append(a_type) r_type, r_info, r_field = ret if r_type in skipped_types: return [] if r_type != 'void' and r_type not in py_types: unknown.append(r_type) return unknown def validate_functions(): unknown_types = defaultdict(list) # type: Dict[str, List[str]] funcs_failed = [] # type: List[str] for name in sorted(functions): unknown = validate_function(name) if unknown: funcs_failed.append(name) for thetype in unknown: unknown_types[thetype].append(name) if unknown_types: print("Missing type converters: ") for type, count in unknown_types.items(): print("%s:%d " % (type, len(count))) for f in funcs_failed: print("ERROR: failed %s" % f) if funcs_failed: return -1 return 0 def skip_both_impl(name: str) -> bool: if name in skip_function: return True (desc, ret, args, file, mod, cond) = functions[name] for a_name, a_type, a_info in args: # This should be correct if a_type[0:6] == "const ": a_type = a_type[6:] if a_type in skipped_types: return True r_type, r_info, r_field = ret if r_type in skipped_types: return True return False def skip_c_impl(name: str) -> bool: if skip_both_impl(name): return True if name in skip_impl: return True return False def skip_py_impl(name: str) -> bool: if skip_both_impl(name): return True if name in function_skip_python_impl: return True return False def print_function_wrapper(package: str, name: str, output: IO[str], export: IO[str], include: IO[str]) -> bool: """ :returns: True if generated, False if skipped """ (desc, ret, args, file, mod, cond) = functions[name] if skip_c_impl(name): return False c_call = "" format = "" format_args = "" c_args = "" c_return = "" c_convert = "" num_bufs = 0 for a_name, a_type, a_info in args: # This should be correct if a_type[0:6] == "const ": a_type = a_type[6:] c_args += " %s %s;\n" % (a_type, a_name) if a_type in py_types: (f, t, n, c) = py_types[a_type] if f: format += f if t: format_args += ", &pyobj_%s" % (a_name) c_args += " PyObject *pyobj_%s;\n" % (a_name) c_convert += \ " %s = (%s) Py%s_Get(pyobj_%s);\n" % ( a_name, a_type, t, a_name) else: format_args += ", &%s" % (a_name) if f == 't#': format_args += ", &py_buffsize%d" % num_bufs c_args += " int py_buffsize%d;\n" % num_bufs num_bufs += 1 if c_call: c_call += ", " c_call += "%s" % (a_name) else: raise Exception("Unexpected type %s in function %s" % (a_type, name)) if format: format += ":%s" % (name) r_type, r_info, r_field = ret if r_type == 'void': if file == "python_accessor": if args[1][1] == "char *": c_call = "\n VIR_FREE(%s->%s);\n" % ( args[0][0], args[1][0]) c_call += " %s->%s = (%s)strdup((const xmlChar *)%s);\n" % ( args[0][0], args[1][0], args[1][1], args[1][0]) else: c_call = "\n %s->%s = %s;\n" % (args[0][0], args[1][0], args[1][0]) else: c_call = "\n %s(%s);\n" % (name, c_call) ret_convert = " Py_INCREF(Py_None);\n return Py_None;\n" elif r_type in py_types: (f, t, n, c) = py_types[r_type] c_return = " %s c_retval;\n" % (r_type) if file == "python_accessor" and r_field: c_call = "\n c_retval = %s->%s;\n" % (args[0][0], r_field) else: c_call = "\n c_retval = %s(%s);\n" % (name, c_call) ret_convert = " py_retval = libvirt_%sWrap((%s) c_retval);\n" % (n, c) if n == "charPtr": ret_convert += " free(c_retval);\n" ret_convert += " return py_retval;\n" else: raise Exception("Unexpected type %s in function %s" % (r_type, name)) if cond: include.write("#if %s\n" % cond) export.write("#if %s\n" % cond) output.write("#if %s\n" % cond) include.write("PyObject * ") include.write("%s_%s(PyObject *self, PyObject *args);\n" % (package, name)) export.write(" { (char *)\"%s\", %s_%s, METH_VARARGS, NULL },\n" % (name, package, name)) if file == "python": # Those have been manually generated if cond: include.write("#endif\n") export.write("#endif\n") output.write("#endif\n") return True if file == "python_accessor" and r_type != "void" and not r_field: # Those have been manually generated if cond: include.write("#endif\n") export.write("#endif\n") output.write("#endif\n") return True output.write("PyObject *\n") output.write("%s_%s(PyObject *self ATTRIBUTE_UNUSED," % (package, name)) output.write(" PyObject *args") if format == "": output.write(" ATTRIBUTE_UNUSED") output.write(") {\n") if r_type != 'void': output.write(" PyObject *py_retval;\n") if c_return: output.write(c_return) if c_args: output.write(c_args) if format: output.write("\n if (!PyArg_ParseTuple(args, (char *)\"%s\"%s))\n" % (format, format_args)) output.write(" return NULL;\n") if c_convert: output.write(c_convert + "\n") output.write(" LIBVIRT_BEGIN_ALLOW_THREADS;") output.write(c_call) output.write(" LIBVIRT_END_ALLOW_THREADS;\n") output.write(ret_convert) output.write("}\n\n") if cond: include.write("#endif /* %s */\n" % cond) export.write("#endif /* %s */\n" % cond) output.write("#endif /* %s */\n" % cond) return True def print_c_pointer(classname: str, output: IO[str], export: IO[str], include: IO[str]) -> None: output.write("PyObject *\n") output.write("libvirt_%s_pointer(PyObject *self ATTRIBUTE_UNUSED, PyObject *args)\n" % classname) output.write("{\n") output.write(" %sPtr ptr;\n" % classname) output.write(" PyObject *pyptr;\n") output.write(" PyObject *pylong;\n") output.write("\n") output.write(" if (!PyArg_ParseTuple(args, (char *) \"O\", &pyptr))\n") output.write(" return NULL;\n") output.write(" ptr = (%sPtr) Py%s_Get(pyptr);\n" % (classname, classname)) output.write(" pylong = PyLong_FromVoidPtr(ptr);\n") output.write(" return pylong;\n") output.write("}\n") output.write("\n") include.write("PyObject *libvirt_%s_pointer(PyObject *self, PyObject *args);\n" % classname) export.write(" { (char *)\"%s_pointer\", libvirt_%s_pointer, METH_VARARGS, NULL },\n" % (classname, classname)) def load_apis(module: str, api_xml: str): global onlyOverrides try: onlyOverrides = False with open(api_xml) as stream: parse(stream) except IOError as msg: print(api_xml, ":", msg) sys.exit(1) n = len(functions) if not quiet: print("Found %d functions in %s" % ((n), api_xml)) override_api_xml = "%s-override-api.xml" % module py_types['pythonObject'] = ('O', "pythonObject", "pythonObject", "pythonObject") try: onlyOverrides = True with openSourceFile(override_api_xml) as stream: parse(stream) except IOError as msg: print(override_api_xml, ":", msg) if not quiet: # XXX: This is not right, same function already in @functions # will be overwritten. print("Found %d functions in %s" % (len(functions) - n, override_api_xml)) def emit_c_code(module: str) -> None: package = module.replace('-', '_') nb_wrap = 0 header_file = "%s/%s.h" % (buildDir, module) export_file = "%s/%s-export.c.inc" % (buildDir, module) wrapper_file = "%s/%s.c" % (buildDir, module) include = open(header_file, "w") include.write("/* Generated by generator.py */\n\n") export = open(export_file, "w") export.write("/* Generated by generator.py */\n\n") wrapper = open(wrapper_file, "w") wrapper.write("/* Generated by generator.py */\n\n") wrapper.write("#include \n") wrapper.write("#include \n") wrapper.write("#include \n" % (module,)) wrapper.write("#include \"typewrappers.h\"\n") wrapper.write("#include \"%s.h\"\n\n" % (module)) for function in sorted(functions): if print_function_wrapper(package, function, wrapper, export, include): nb_wrap += 1 if module == "libvirt": # Write C pointer conversion functions. for classname in primary_classes: print_c_pointer(classname, wrapper, export, include) # Write define wrappers around event id enums, so that the # preprocessor can see which enums were available. for event_id in event_ids: include.write("#define %s %s\n" % (event_id, event_id)) include.close() export.close() wrapper.close() if not quiet: print("Generated %d wrapper functions" % nb_wrap) ####################################################################### # # This part writes part of the Python front-end classes based on # mapping rules between types and classes and also based on function # renaming to get consistent function names at the Python level # ####################################################################### # # The type automatically remapped to generated classes # "C-type" -> (accessor, create, class, parent-class) # classes_type = { "virDomainPtr": ("._o", "virDomain(%(p)s, _obj=%(o)s)", "virDomain", "virConnect"), "virDomain *": ("._o", "virDomain(%(p)s, _obj=%(o)s)", "virDomain", "virConnect"), "virNetworkPtr": ("._o", "virNetwork(%(p)s, _obj=%(o)s)", "virNetwork", "virConnect"), "virNetwork *": ("._o", "virNetwork(%(p)s, _obj=%(o)s)", "virNetwork", "virConnect"), "virNetworkPortPtr": ("._o", "virNetworkPort(%(p)s, _obj=%(o)s)", "virNetworkPort", "virNetwork"), "virNetworkPort *": ("._o", "virNetworkPort(%(p)s, _obj=%(o)s)", "virNetworkPort", "virNetwork"), "virInterfacePtr": ("._o", "virInterface(%(p)s, _obj=%(o)s)", "virInterface", "virConnect"), "virInterface *": ("._o", "virInterface(%(p)s, _obj=%(o)s)", "virInterface", "virConnect"), "virStoragePoolPtr": ("._o", "virStoragePool(%(p)s, _obj=%(o)s)", "virStoragePool", "virConnect"), "virStoragePool *": ("._o", "virStoragePool(%(p)s, _obj=%(o)s)", "virStoragePool", "virConnect"), "virStorageVolPtr": ("._o", "virStorageVol(%(p)s, _obj=%(o)s)", "virStorageVol", "virConnect"), "virStorageVol *": ("._o", "virStorageVol(%(p)s, _obj=%(o)s)", "virStorageVol", "virConnect"), "virNodeDevicePtr": ("._o", "virNodeDevice(%(p)s, _obj=%(o)s)", "virNodeDevice", "virConnect"), "virNodeDevice *": ("._o", "virNodeDevice(%(p)s, _obj=%(o)s)", "virNodeDevice", "virConnect"), "virSecretPtr": ("._o", "virSecret(%(p)s, _obj=%(o)s)", "virSecret", "virConnect"), "virSecret *": ("._o", "virSecret(%(p)s, _obj=%(o)s)", "virSecret", "virConnect"), "virNWFilterPtr": ("._o", "virNWFilter(%(p)s, _obj=%(o)s)", "virNWFilter", "virConnect"), "virNWFilter *": ("._o", "virNWFilter(%(p)s, _obj=%(o)s)", "virNWFilter", "virConnect"), "virNWFilterBindingPtr": ("._o", "virNWFilterBinding(%(p)s, _obj=%(o)s)", "virNWFilterBinding", "virConnect"), "virNWFilterBinding *": ("._o", "virNWFilterBinding(%(p)s, _obj=%(o)s)", "virNWFilterBinding", "virConnect"), "virStreamPtr": ("._o", "virStream(%(p)s, _obj=%(o)s)", "virStream", "virConnect"), "virStream *": ("._o", "virStream(%(p)s, _obj=%(o)s)", "virStream", "virConnect"), "virConnectPtr": ("._o", "virConnect(_obj=%(o)s)", "virConnect", ""), "virConnect *": ("._o", "virConnect(_obj=%(o)s)", "virConnect", ""), "virDomainCheckpointPtr": ("._o", "virDomainCheckpoint(%(p)s, _obj=%(o)s)", "virDomainCheckpoint", "virDomain"), "virDomainCheckpoint *": ("._o", "virDomainCheckpoint(%(p)s, _obj=%(o)s)", "virDomainCheckpoint", "virDomain"), "virDomainSnapshotPtr": ("._o", "virDomainSnapshot(%(p)s, _obj=%(o)s)", "virDomainSnapshot", "virDomain"), "virDomainSnapshot *": ("._o", "virDomainSnapshot(%(p)s, _obj=%(o)s)", "virDomainSnapshot", "virDomain"), } primary_classes = ["virDomain", "virNetwork", "virNetworkPort", "virInterface", "virStoragePool", "virStorageVol", "virConnect", "virNodeDevice", "virSecret", "virNWFilter", "virNWFilterBinding", "virStream", "virDomainCheckpoint", "virDomainSnapshot"] classes_destructors = { "virDomain": "virDomainFree", "virNetwork": "virNetworkFree", "virNetworkPort": "virNetworkPortFree", "virInterface": "virInterfaceFree", "virStoragePool": "virStoragePoolFree", "virStorageVol": "virStorageVolFree", "virNodeDevice": "virNodeDeviceFree", "virSecret": "virSecretFree", "virNWFilter": "virNWFilterFree", "virNWFilterBinding": "virNWFilterBindingFree", "virDomainCheckpoint": "virDomainCheckpointFree", "virDomainSnapshot": "virDomainSnapshotFree", # We hand-craft __del__ for this one # "virStream": "virStreamFree", } class_skip_connect_impl = { "virConnect", } class_domain_impl = { "virDomainCheckpoint", "virDomainSnapshot", } class_network_impl = { "virNetworkPort", } functions_noexcept = { 'virDomainGetID', 'virDomainGetName', 'virNetworkGetName', 'virInterfaceGetName', 'virStoragePoolGetName', 'virStorageVolGetName', 'virStorageVolGetkey', 'virNodeDeviceGetName', 'virNodeDeviceGetParent', 'virSecretGetUsageType', 'virSecretGetUsageID', 'virNWFilterGetName', 'virNWFilterBindingGetFilterName', 'virNWFilterBindingGetPortDev', } function_classes = { "None": [] } # type: Dict[str, List[Tuple[int, str, str, ArgumentType, List[ArgumentType], str, str]]] # Functions returning an integral type which need special rules to # check for errors and raise exceptions. functions_int_exception_test = { 'virDomainGetMaxMemory': "%s == 0", } functions_int_default_test = "%s == -1" def is_integral_type(name: str) -> bool: return re.search("^(unsigned)? ?(int|long)$", name) is not None def is_optional_arg(info: str) -> bool: return re.search(r"^\(?optional\)?", info) is not None def is_python_noninteger_type(name: str) -> bool: return name[-1:] == "*" def nameFixup(name: str, classe: str, type: str, file: str) -> str: # avoid a disastrous clash listname = classe + "List" l = len(classe) if name[0:l] == listname: func = name[l:] func = func[0:1].lower() + func[1:] elif name[0:16] == "virNetworkDefine": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:19] == "virNetworkCreateXML": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:16] == "virNetworkLookup": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:23] == "virNetworkPortCreateXML": func = name[10:] func = func[0:1].lower() + func[1:] elif name[0:20] == "virNetworkPortLookup": func = name[10:] func = func[0:1].lower() + func[1:] elif name[0:18] == "virInterfaceDefine": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:21] == "virInterfaceCreateXML": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:18] == "virInterfaceLookup": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:15] == "virSecretDefine": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:15] == "virSecretLookup": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:27] == "virNWFilterBindingCreateXML": func = name[3:] func = func[0:3].lower() + func[3:] elif name[0:24] == "virNWFilterBindingLookup": func = name[3:] func = func[0:3].lower() + func[3:] elif name[0:24] == "virNWFilterBindingDefine": func = name[3:] func = func[0:3].lower() + func[3:] elif name[0:24] == "virNWFilterBindingLookup": func = name[3:] func = func[0:3].lower() + func[3:] elif name[0:17] == "virNWFilterDefine": func = name[3:] func = func[0:3].lower() + func[3:] elif name[0:17] == "virNWFilterLookup": func = name[3:] func = func[0:3].lower() + func[3:] elif name[0:20] == "virStoragePoolDefine": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:23] == "virStoragePoolCreateXML": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:20] == "virStoragePoolLookup": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:19] == "virStorageVolDefine": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:19] == "virStorageVolLookup": func = name[3:] func = func[0:1].lower() + func[1:] elif name[0:20] == "virDomainGetCPUStats": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:24] == "virDomainGetIOThreadInfo": func = name[12:] func = func[0:2].lower() + func[2:] elif name[0:18] == "virDomainGetFSInfo": func = name[12:] func = func[0:2].lower() + func[2:] elif name[0:12] == "virDomainGet": func = name[12:] func = func[0:1].lower() + func[1:] elif name[0:31] == "virDomainCheckpointLookupByName": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:28] == "virDomainCheckpointCreateXML": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:19] == "virDomainCheckpoint": func = name[19:] func = func[0:1].lower() + func[1:] elif name[0:29] == "virDomainSnapshotLookupByName": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:26] == "virDomainSnapshotListNames": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:28] == "virDomainSnapshotNumChildren": func = name[17:] func = func[0:1].lower() + func[1:] elif name[0:20] == "virDomainSnapshotNum": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:26] == "virDomainSnapshotCreateXML": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:24] == "virDomainSnapshotCurrent": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:17] == "virDomainSnapshot": func = name[17:] func = func[0:1].lower() + func[1:] elif name[0:9] == "virDomain": func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:17] == "virNetworkPortGet": func = name[17:] func = func[0:1].lower() + func[1:] elif name[0:13] == "virNetworkGet": func = name[13:] func = func[0:1].lower() + func[1:] func = func.replace("dHCP", "DHCP") elif name[0:14] == "virNetworkPort": func = name[14:] func = func[0:1].lower() + func[1:] elif name[0:10] == "virNetwork": func = name[10:] func = func[0:1].lower() + func[1:] elif name[0:15] == "virInterfaceGet": func = name[15:] func = func[0:1].lower() + func[1:] elif name[0:12] == "virInterface": func = name[12:] func = func[0:1].lower() + func[1:] elif name[0:12] == 'virSecretGet': func = name[12:] func = func[0:1].lower() + func[1:] elif name[0:9] == 'virSecret': func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:21] == 'virNWFilterBindingGet': func = name[21:] func = func[0:1].lower() + func[1:] elif name[0:18] == 'virNWFilterBinding': func = name[18:] func = func[0:1].lower() + func[1:] elif name[0:14] == 'virNWFilterGet': func = name[14:] func = func[0:1].lower() + func[1:] elif name[0:11] == 'virNWFilter': func = name[11:] func = func[0:1].lower() + func[1:] elif name[0:12] == 'virStreamNew': func = "newStream" elif name[0:9] == 'virStream': func = name[9:] func = func[0:1].lower() + func[1:] elif name[0:17] == "virStoragePoolGet": func = name[17:] func = func[0:1].lower() + func[1:] elif name[0:14] == "virStoragePool": func = name[14:] func = func[0:1].lower() + func[1:] elif name[0:16] == "virStorageVolGet": func = name[16:] func = func[0:1].lower() + func[1:] elif name[0:13] == "virStorageVol": func = name[13:] func = func[0:1].lower() + func[1:] elif name[0:16] == "virNodeDeviceGet": func = name[16].lower() + name[17:] elif name[0:19] == "virNodeDeviceLookup": func = name[3].lower() + name[4:] elif name[0:22] == "virNodeDeviceCreateXML": func = name[3].lower() + name[4:] elif name[0:19] == "virNodeDeviceDefine": func = name[3].lower() + name[4:] elif name[0:13] == "virNodeDevice": func = name[13].lower() + name[14:] elif name[0:7] == "virNode": func = name[7:] func = func[0:1].lower() + func[1:] elif name[0:10] == "virConnect": func = name[10:] func = func[0:1].lower() + func[1:] elif name[0:3] == "xml": func = name[3:] func = func[0:1].lower() + func[1:] else: func = name if func == "iD": func = "ID" if func == "uUID": func = "UUID" if func == "uUIDString": func = "UUIDString" if func == "oSType": func = "OSType" if func == "xMLDesc": func = "XMLDesc" if func == "mACString": func = "MACString" return func def functionSortKey(info: Tuple) -> Tuple[str, str]: (index, func, name, ret, args, filename, mod) = info return func, filename def writeDoc(module: str, name: str, args: List[ArgumentType], indent: str, output: IO) -> None: if not functions[name][0]: return val = functions[name][0] val = val.replace("NULL", "None") sep = '\n%s' % (indent,) output.write('%s"""%s """\n' % (indent, sep.join(val.splitlines()))) def emit_py_code(module: str) -> None: package = module.replace('-', '_') if module == "libvirt": pymod = "libvirtmod" cygmod = "cygvirtmod" elif module == "libvirt-lxc": pymod = "libvirtmod_lxc" cygmod = "cygvirtmod_lxc" elif module == "libvirt-qemu": pymod = "libvirtmod_qemu" cygmod = "cygvirtmod_qemu" else: raise Exception("Unknown module '%s'" % module) for tinfo in classes_type.values(): function_classes[tinfo[2]] = [] # # Build the list of C types to look for ordered to start # with primary classes # ctypes = [] # type: List[str] classes_list = [] # type: List[str] ctypes_processed = set() # type: Set[str] classes_processed = set() # type: Set[str] for classe in primary_classes: classes_list.append(classe) classes_processed.add(classe) for type, tinfo in classes_type.items(): if tinfo[2] == classe: ctypes.append(type) ctypes_processed.add(type) for type, tinfo in classes_type.items(): if type in ctypes_processed: continue if tinfo[2] not in classes_processed: classes_list.append(tinfo[2]) classes_processed.add(tinfo[2]) ctypes.append(type) ctypes_processed.add(type) for name, (desc, ret, args, file, mod, cond) in functions.items(): if skip_py_impl(name): continue for type in ctypes: classe = classes_type[type][2] if name[0:3] == "vir" and len(args) >= 1 and args[0][1] == type: func = nameFixup(name, classe, type, file) info = (0, func, name, ret, args, file, mod) function_classes[classe].append(info) break elif name[0:3] == "vir" and len(args) >= 2 and args[1][1] == type \ and file != "python_accessor" and name not in function_skip_index_one: func = nameFixup(name, classe, type, file) info = (1, func, name, ret, args, file, mod) function_classes[classe].append(info) break else: func = nameFixup(name, "None", file, file) info = (0, func, name, ret, args, file, mod) function_classes['None'].append(info) classes_file = "%s/%s.py" % (buildDir, package) extra_file = "%s-override.py" % module extra = openSourceFile(extra_file, "r", True) classes = open(classes_file, "w") classes.write("#\n") classes.write("# WARNING WARNING WARNING WARNING\n") classes.write("#\n") classes.write("# This file is automatically written by generator.py. Any changes\n") classes.write("# made here will be lost.\n") classes.write("#\n") classes.write("# To change the manually written methods edit %s-override.py\n" % (module,)) classes.write("# To change the automatically written methods edit generator.py\n") classes.write("#\n") classes.write("# WARNING WARNING WARNING WARNING\n") classes.write("#\n") classes.write("try:\n") classes.write(" import %s # type: ignore\n" % pymod) classes.write("except ImportError as lib_e:\n") classes.write(" try:\n") classes.write(" import %s as %s # type: ignore\n" % (cygmod, pymod)) classes.write(" except ImportError as cyg_e:\n") classes.write(" if \"No module named\" in str(cyg_e):\n") classes.write(" raise lib_e\n\n") if module != "libvirt": classes.write("import libvirt\n") classes.write("\n") if extra: classes.write("# WARNING WARNING WARNING WARNING\n") classes.write("#\n") classes.write("# Manually written part of python bindings for %s\n" % module) classes.writelines(extra.readlines()) classes.write("#\n") classes.write("# WARNING WARNING WARNING WARNING\n") classes.write("#\n") classes.write("# Automatically written part of python bindings for %s\n" % module) classes.write("#\n") classes.write("# WARNING WARNING WARNING WARNING\n") if extra: extra.close() if "None" in function_classes: flist = function_classes["None"] oldfile = "" for (index, func, name, ret, args, file, mod) in sorted(flist, key=functionSortKey): if file != oldfile: classes.write("#\n# Functions from module %s\n#\n\n" % file) oldfile = file classes.write("def %s(" % func) for n, (a_name, a_type, a_info) in enumerate(args): if n != 0: classes.write(", ") classes.write("%s" % a_name) if a_name == "flags" or is_optional_arg(a_info): if is_integral_type(a_type): classes.write("=0") else: classes.write("=None") classes.write("):\n") writeDoc(module, name, args, ' ', classes) for a_name, a_type, a_info in args: if a_type in classes_type: classes.write(" if %s is None:\n" " %s__o = None\n" % (a_name, a_name)) classes.write(" else:\n" " %s__o = %s%s\n" % (a_name, a_name, classes_type[a_type][0])) r_type, r_info, r_field = ret if r_type != "void": classes.write(" ret = ") else: classes.write(" ") classes.write("%s.%s(" % (pymod, name)) for n, (a_name, a_type, a_info) in enumerate(args): if n != 0: classes.write(", ") classes.write("%s" % a_name) if a_type in classes_type: classes.write("__o") classes.write(")\n") if r_type != "void": if r_type in classes_type: # # Raise an exception # if name in functions_noexcept: classes.write(" if ret is None:\n" " return None\n") else: classes.write( " if ret is None:\n" " raise libvirtError('%s() failed')\n" % (name)) tinfo = classes_type[r_type] classes.write(" return ") classes.write(tinfo[1] % {"o": "ret"}) classes.write("\n") # For functions returning an integral type there are # several things that we can do, depending on the # contents of functions_int_*: elif is_integral_type(r_type): if name not in functions_noexcept: test = functions_int_exception_test.get(name, functions_int_default_test) % ("ret",) classes.write( " if %s:\n" " raise libvirtError('%s() failed')\n" % (test, name)) classes.write(" return ret\n") elif is_python_noninteger_type(r_type): if name not in functions_noexcept: classes.write( " if ret is None:\n" " raise libvirtError('%s() failed')\n" % (name,)) classes.write(" return ret\n") else: classes.write(" return ret\n") classes.write("\n") modclasses = [] if module == "libvirt": modclasses = classes_list for classname in modclasses: PARENTS = { "virConnect": "self._conn", "virDomain": "self._dom", "virNetwork": "self._net", classname: "self", } if classname == "None": pass else: classes.write("class %s(object):\n" % (classname)) if classname == "virStorageVol": classes.write(" # The size (in bytes) of buffer used in sendAll(),\n") classes.write(" # recvAll(), sparseSendAll() and sparseRecvAll()\n") classes.write(" # methods. This corresponds to the size of payload\n") classes.write(" # of a stream packet.\n") classes.write(" streamBufSize = 262120\n\n") if classname in ["virDomain", "virNetwork", "virInterface", "virStoragePool", "virStorageVol", "virNodeDevice", "virSecret", "virStream", "virNWFilter", "virNWFilterBinding"]: classes.write(" def __init__(self, conn, _obj=None):\n") classes.write(" self._conn = conn\n") elif classname in ["virDomainCheckpoint", "virDomainSnapshot"]: classes.write(" def __init__(self, dom, _obj=None):\n") classes.write(" self._dom = dom\n") classes.write(" self._conn = dom.connect()\n") elif classname in ["virNetworkPort"]: classes.write(" def __init__(self, net, _obj=None) -> None:\n") classes.write(" self._net = net\n") classes.write(" self._conn = net.connect()\n") else: classes.write(" def __init__(self, _obj=None):\n") classes.write(" if type(_obj).__name__ not in [\"PyCapsule\", \"PyCObject\"]:\n") classes.write(" raise Exception(\"Expected a wrapped C Object but got %s\" % type(_obj))\n") classes.write(" self._o = _obj\n\n") destruct = None if classname in classes_destructors: classes.write(" def __del__(self):\n") classes.write(" if self._o is not None:\n") classes.write(" %s.%s(self._o)\n" % (pymod, classes_destructors[classname])) classes.write(" self._o = None\n\n") destruct = classes_destructors[classname] if classname not in class_skip_connect_impl: # Build python safe 'connect' method classes.write(" def connect(self):\n") classes.write(" return self._conn\n\n") if classname in class_domain_impl: classes.write(" def domain(self):\n") classes.write(" return self._dom\n\n") if classname in class_network_impl: classes.write(" def network(self):\n") classes.write(" return self._net\n\n") classes.write(" def c_pointer(self):\n") classes.write(" \"\"\"Get C pointer to underlying object\"\"\"\n") classes.write(" return %s.%s_pointer(self._o)\n\n" % (pymod, classname)) flist = function_classes[classname] oldfile = "" for (index, func, name, ret, args, file, mod) in sorted(flist, key=functionSortKey): # # Do not provide as method the destructors for the class # to avoid double free # if name == destruct: continue if file != oldfile: if file == "python_accessor": classes.write(" # accessors for %s\n" % (classname)) else: classes.write(" #\n") classes.write(" # %s functions from module %s\n" % ( classname, file)) classes.write(" #\n\n") oldfile = file classes.write(" def %s(self" % func) for n, (a_name, a_type, a_info) in enumerate(args): if n != index: classes.write(", %s" % a_name) if a_name == "flags" or is_optional_arg(a_info): if is_integral_type(a_type): classes.write("=0") else: classes.write("=None") classes.write("):\n") writeDoc(module, name, args, ' ', classes) for n, (a_name, a_type, a_info) in enumerate(args): if a_type in classes_type: if n != index: classes.write(" if %s is None:\n" " %s__o = None\n" % (a_name, a_name)) classes.write(" else:\n" " %s__o = %s%s\n" % (a_name, a_name, classes_type[a_type][0])) r_type, r_info, r_field = ret if r_type != "void": classes.write(" ret = ") else: classes.write(" ") classes.write("%s.%s(" % (pymod, name)) for n, (a_name, a_type, a_info) in enumerate(args): if n != 0: classes.write(", ") if n != index: classes.write("%s" % a_name) if a_type in classes_type: classes.write("__o") else: classes.write("self") if a_type in classes_type: classes.write(classes_type[a_type][0]) classes.write(")\n") if name == "virConnectClose": classes.write(" self._o = None\n") # For functions returning object types: if r_type != "void": if r_type in classes_type: # # Raise an exception # if name in functions_noexcept: classes.write( " if ret is None:\n" " return None\n") else: classes.write( " if ret is None:\n" " raise libvirtError('%s() failed')\n" % (name,)) # # generate the returned class wrapper for the object # tinfo = classes_type[r_type] classes.write(" __tmp = ") classes.write(tinfo[1] % {"o": "ret", "p": PARENTS[tinfo[3]]}) classes.write("\n") # # return the class # classes.write(" return __tmp\n") # For functions returning an integral type there # are several things that we can do, depending on # the contents of functions_int_*: elif is_integral_type(r_type): if name not in functions_noexcept: test = functions_int_exception_test.get(name, functions_int_default_test) % ("ret",) classes.write( " if %s:\n" " raise libvirtError('%s() failed')\n" % (test, name)) classes.write(" return ret\n") elif is_python_noninteger_type(r_type): if name not in functions_noexcept: classes.write( " if ret is None:\n" " raise libvirtError('%s() failed')\n" % (name,)) classes.write(" return ret\n") else: classes.write(" return ret\n") classes.write("\n") # Append ".py" to class def, iff it exists class_override = "%s-override-%s.py" % (module, classname) extra = openSourceFile(class_override, "r", True) if extra: classes.write(" #\n") classes.write(" # %s methods from %s.py (hand coded)\n" % (classname, classname)) classes.write(" #\n") cached = None # Since we compile with older libvirt, we don't want to pull # in manually written python methods which call C methods # that don't exist. This code attempts to detect which # methods to skip by looking at the libvirtmod.XXXX calls def shouldSkip(lines: List[str]) -> bool: for line in lines: offset = line.find(pymod + ".") if offset != -1: func = line[offset + 11:] offset = func.find("(") func = func[0:offset] if not skip_c_impl(func) and func != "virConnectListDomains": return True return False for line in extra.readlines(): offset = line.find(" def ") if offset != -1: name = line[offset + 5:] offset = name.find("(") name = name[0:offset] if cached: if not shouldSkip(cached): classes.writelines(cached) if name == "__del__": cached = None classes.write(line) else: cached = [line] else: if cached: cached.append(line) else: classes.write(line) if cached is not None and not shouldSkip(cached): classes.writelines(cached) classes.write("\n") extra.close() direct_functions = {} if module != "libvirt": direct_functions = functions classes.write("#\n# Functions from module %s\n#\n\n" % module) # # Generate functions directly, no classes # for name, (desc, ret, args, file, mod, cond) in sorted(direct_functions.items()): if skip_py_impl(name): continue func = nameFixup(name, 'None', '', '') classes.write("def %s(" % func) for n, (a_name, a_type, a_info) in enumerate(args): if n != 0: classes.write(", ") classes.write("%s" % a_name) classes.write("):\n") writeDoc(module, name, args, ' ', classes) r_type, r_info, r_field = ret if r_type != "void": classes.write(" ret = ") else: classes.write(" ") classes.write("%s.%s(" % (pymod, name)) conn = None for n, (a_name, a_type, a_info) in enumerate(args): if a_type == "virConnectPtr": conn = a_name if n != 0: classes.write(", ") if a_type in ["virDomainPtr", "virConnectPtr"]: # FIXME: This might have problem if the function # has multiple args which are objects. classes.write("%s.%s" % (a_name, "_o")) else: classes.write("%s" % a_name) classes.write(")\n") if r_type != "void": classes.write(" if ret is None:\n" " raise libvirt.libvirtError('%s() failed')\n" % (name,)) if r_type == "virDomainPtr": classes.write(" __tmp = libvirt.virDomain(%s, _obj=ret)\n" % (conn,)) classes.write(" return __tmp\n") else: classes.write(" return ret\n") classes.write("\n") # # Generate enum constants # def enumsSortKey(data: Tuple[str, EnumValue]) -> Tuple[Union[int, float], str]: try: value = int(data[1]) # type: Union[int, float] except ValueError: value = float('inf') return value, data[0] # Resolve only one level of reference def resolveEnum(enum: EnumType, data: EnumType) -> EnumType: for name, val in enum.items(): try: int(val) except ValueError: enum[name] = data[val] # type: ignore return enum enumvals = list(enums.items()) # convert list of dicts to one dict enumData = {} # type: EnumType for type, enum in enumvals: enumData.update(enum) for type, enum in sorted(enumvals): classes.write("# %s\n" % type) items = sorted(resolveEnum(enum, enumData).items(), key=enumsSortKey) if items[-1][0].endswith('_LAST'): del items[-1] for name, value in items: classes.write("%s = %s\n" % (name, value)) classes.write("\n") if params: classes.write("# typed parameter names\n") for name, value in params: classes.write("%s = \"%s\"\n" % (name, value)) classes.close() if sys.argv[1] not in ["libvirt", "libvirt-lxc", "libvirt-qemu"]: print("ERROR: unknown module %s" % sys.argv[1]) sys.exit(1) if len(sys.argv) == 6: buildDir = sys.argv[5] if len(sys.argv) >= 5: sourceDir = sys.argv[4] load_apis(sys.argv[1], sys.argv[2]) if validate_functions() < 0: sys.exit(1) quiet = False if not os.path.exists("build"): os.mkdir("build") output = None if len(sys.argv) >= 4: output = sys.argv[3] if output == "c" or output == "c+py" or output is None: emit_c_code(sys.argv[1]) if output == "py" or output == "c+py" or output is None: emit_py_code(sys.argv[1]) sys.exit(0) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1648809002.0 libvirt-python-11.3.0/libvirt-lxc-override-api.xml0000664000175000017500000000134114221552052021154 0ustar00jirkajirka ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1715606996.0 libvirt-python-11.3.0/libvirt-lxc-override.c0000644000175000017500000000611314620412724020033 0ustar00jirkajirka/* * libvir.c: this modules implements the main part of the glue of the * libvir library and the Python interpreter. It provides the * entry points where an automatically generated stub is * unpractical * * Copyright (C) 2012-2019 Red Hat, Inc. * * Daniel Veillard */ /* Horrible kludge to work around even more horrible name-space pollution via Python.h. That file includes /usr/include/python3.x/pyconfig*.h, which has over 180 autoconf-style HAVE_* definitions. Shame on them. */ #undef HAVE_PTHREAD_H #include #include #include #include "typewrappers.h" #include "libvirt-utils.h" #include "libvirt-lxc.h" #if 0 # define DEBUG_ERROR 1 #endif #if DEBUG_ERROR # define DEBUG(fmt, ...) \ printf(fmt, __VA_ARGS__) #else # define DEBUG(fmt, ...) \ while (0) {printf(fmt, __VA_ARGS__);} #endif /************************************************************************ * * * Statistics * * * ************************************************************************/ static PyObject * libvirt_lxc_virDomainLxcOpenNamespace(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; virDomainPtr domain; PyObject *pyobj_domain; unsigned int flags; int c_retval; int *fdlist = NULL; ssize_t i; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainLxcOpenNamespace", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (domain == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainLxcOpenNamespace(domain, &fdlist, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(0)) == NULL) goto error; for (i = 0; i < c_retval; i++) VIR_PY_LIST_APPEND_GOTO(py_retval, libvirt_intWrap(fdlist[i]), error); cleanup: VIR_FREE(fdlist); return py_retval; error: for (i = 0; i < c_retval; i++) { VIR_FORCE_CLOSE(fdlist[i]); } Py_CLEAR(py_retval); goto cleanup; } /************************************************************************ * * * The registration stuff * * * ************************************************************************/ static PyMethodDef libvirtLxcMethods[] = { #include "libvirt-lxc-export.c.inc" {(char *) "virDomainLxcOpenNamespace", libvirt_lxc_virDomainLxcOpenNamespace, METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, #ifndef __CYGWIN__ "libvirtmod_lxc", #else "cygvirtmod_lxc", #endif NULL, -1, libvirtLxcMethods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC #ifndef __CYGWIN__ PyInit_libvirtmod_lxc #else PyInit_cygvirtmod_lxc #endif (void) { PyObject *module; if (virInitialize() < 0) return NULL; module = PyModule_Create(&moduledef); return module; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1743501822.0 libvirt-python-11.3.0/libvirt-override-api.xml0000644000175000017500000016547614772734776020444 0ustar00jirkajirka Returns the running hypervisor version of the connection host Returns the libvirt version of the connection host Returns the list of the ID of the domains on the hypervisor list the defined domains, stores the pointers to the names in @names returns list of all defined domains list the networks, stores the pointers to the names in @names list the defined networks, stores the pointers to the names in @names returns list of all networks Try to lookup a domain on the given hypervisor based on its UUID. Try to lookup a network on the given hypervisor based on its UUID. Try to lookup a port on the given network based on its UUID. Extract information about a domain. Note that if the connection used to get the domain is limited only a partial set of the information can be extracted. Extract domain state. Extract details about current state of control interface to a domain. Extract information about a domain block device size Extract information about an active job being processed for a domain. Extract information about an active job being processed for a domain. Extract hardware information about the Node. Note that the memory size is reported in MiB instead of KiB. Extract information about the hypervisor security model Extract information about the domain security label. Only the first label will be returned. Extract information about the domain security label. A list of all labels will be returned. Extract node's CPU statistics. Extract node's memory statistics. Extract the UUID unique Identifier of a domain. Fetch globally unique ID of the domain as a string. Extract the UUID unique Identifier of a network. Fetch globally unique ID of the network as a string. Extract the UUID unique Identifier of a network port. Fetch globally unique ID of the network port as a string. Extract the UUID unique Identifier of a storage pool. Fetch globally unique ID of the storage pool as a string. Extract the autostart flag for a network. Extract the autostart flag for a domain Extract the autostart flag for a storage pool Extract the autostart flag for a node device. Extracts block device statistics for a domain Extracts block device statistics parameters of a running domain Extracts CPU statistics for a running domain. On success it will return a list of data of dictionary type. If boolean total is False or 0, the first element of the list refers to CPU0 on the host, second element is CPU1, and so on. The format of data struct is as follows: [{cpu_time:xxx}, {cpu_time:xxx}, ...] If it is True or 1, it returns total domain CPU statistics in the format of [{cpu_time:xxx, user_time:xxx, system_time:xxx}] Extracts interface device statistics for a domain Extracts memory statistics for a domain Returns the available memory for a list of cells Get the scheduler parameters, the @params array will be filled with the values. Get the scheduler parameters Get the scheduler type. Extract information about virtual CPUs of domain, store it in info array and also in cpumaps. Dynamically change the real CPUs which can be allocated to a virtual CPU. This function requires privileged access to the hypervisor. Dynamically change the real CPUs which can be allocated to a virtual CPU. This function requires privileged access to the hypervisor. Query the CPU affinity setting of all virtual CPUs of domain Query the CPU affinity setting of the emulator process of domain Dynamically change the real CPUs which can be allocated to the emulator process of a domain. This function requires privileged access to the hypervisor. Query the CPU affinity setting of the IOThreads of the domain Dynamically change the real CPUs which can be allocated to an IOThread. This function requires privileged access to the hypervisor. Dynamically allow changing the IOThread polling related parameters. This function requires privileged access to the hypervisor. Change the scheduler parameters Change the scheduler parameters Change the blkio tunables Get the blkio parameters Change the memory tunables Get the memory parameters Change the NUMA tunables Get the NUMA parameters Get all perf events setting. Enable or disable the particular list of perf events Change the bandwidth tunables for a interface device Get the bandwidth tunables for a interface device list the storage pools, stores the pointers to the names in @names list the defined storage pool, stores the pointers to the names in @names returns list of all storage pools list the storage volumes, stores the pointers to the names in @names return list of storage volume objects Extract information about a storage pool. Note that if the connection used to get the domain is limited only a partial set of the information can be extracted. Extract information about a storage volume. Note that if the connection used to get the domain is limited only a partial set of the information can be extracted. Extract information about a storage volume. Note that if the connection used to get the domain is limited only a partial set of the information can be extracted. list the node devices returns list of all host node devices list the node device's capabilities Fetches the value associated with a secret. List the defined secret IDs returns list of all interfaces Associates a value with a secret. Try to lookup a secret on the given hypervisor based on its UUID. Extract the UUID unique Identifier of a secret. Fetch globally unique ID of the secret as a string. List the defined network filters returns list of all network fitlers returns list of all network fitler bindings Try to lookup a network filter on the given hypervisor based on its UUID. Extract the UUID unique Identifier of a network filter. Fetch globally unique ID of the network filter as a string. list the running interfaces, stores the pointers to the names in @names list the defined interfaces, stores the pointers to the names in @names returns list of all interfaces Computes the most feature-rich CPU which is compatible with all given host CPUs. Get the list of supported CPU models. collect the list of snapshot names for the given domain returns the list of snapshots for the given domain collect the list of child snapshot names for the given snapshot returns the list of child snapshots for the given snapshot revert the domain to the given snapshot returns the list of checkpoints for the given domain collect the list of child checkpoint names for the given checkpoint Get progress information for a block job Get current size of the cache (in bytes) used for compressing repeatedly transferred memory pages during live migration. Get currently configured maximum migration speed for a domain Get the current value of the maximum downtime (in milliseconds) allowed during a migration of a guest. Migrate the domain object from its current host to the destination host given by dconn (a connection to the destination host). Migrate the domain object from its current host to the destination host given by URI. Change the I/O tunables for a block device Get the I/O tunables for a block device Read the contents of domain's disk device Read the contents of domain's memory Extract errors on disk devices. Change the node memory tunables Get the node memory parameters Get node CPU information Returns the number of available pages for a list of cells and page sizes Returns a list of dhcp leases for interfaces connected to the given virtual network Copy the guest-visible contents of a disk image to a new file described by destxml Allocate or free some pages in the huge pages pool Get a list of mapping information for each mounted file systems within the specified guest and the disks. returns a dictionary of domain interfaces along with their MAC and IP addresses returns a dictionary containing information regarding guest vcpus Computes the most feature-rich CPU which is compatible with all given CPUs and can be provided by the specified hypervisor. Get launch security info for a domain Get platform specific information from the SEV firmware Query domain capabilities Change the port tunables Get the port parameters Get aggregated info from guest agent Override the default identity information associated with the connection. Fetch list of public SSH authorized keys for given user in domain. Manipulate set of public SSH authorized keys for given user in domain. Fetch list of messages reported against domain. Set a launch security secret in the guest's memory. This method will suspend a domain and save its memory contents to a file on disk. This method will restore a domain saved to disk. Provides a boolean value indicating whether the domain is configured to be automatically started the next time the host machine boots only. Add throttlegroup or change all of the throttlegroup options within specific domain. ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1743501822.0 libvirt-python-11.3.0/libvirt-override-virConnect.py0000644000175000017500000007620614772734776021625 0ustar00jirkajirka def __del__(self) -> None: try: self.domainEventCallbacks.clear() del self.domainEventCallbacks libvirtmod.virConnectDomainEventDeregister(self._o, self) except AttributeError: pass if self._o is not None: libvirtmod.virConnectClose(self._o) self._o = None def __enter__(self) -> 'virConnect': return self def __exit__(self, exc_type_: Optional[Type[BaseException]], exc_value_: Optional[BaseException], traceback_: Optional[TracebackType]) -> None: self.close() def domainEventDeregister(self, cb: _DomainCB) -> None: """Removes a Domain Event Callback. De-registering for a domain callback will disable delivery of this event type """ try: del self.domainEventCallbacks[cb] if len(self.domainEventCallbacks) == 0: del self.domainEventCallbacks ret = libvirtmod.virConnectDomainEventDeregister(self._o, self) if ret == -1: raise libvirtError('virConnectDomainEventDeregister() failed') except AttributeError: pass def domainEventRegister(self, cb: _DomainCB, opaque: _T) -> None: """Adds a Domain Event Callback. Registering for a domain callback will enable delivery of the events """ try: self.domainEventCallbacks[cb] = opaque except AttributeError: self.domainEventCallbacks = {cb: opaque} # type: Dict[_DomainCB, _T] ret = libvirtmod.virConnectDomainEventRegister(self._o, self) if ret == -1: raise libvirtError('virConnectDomainEventRegister() failed') def _dispatchDomainEventCallbacks(self, dom: 'virDomain', event: int, detail: int) -> None: """Dispatches events to python user domain event callbacks """ try: for cb, opaque in self.domainEventCallbacks.items(): cb(self, virDomain(self, _obj=dom), event, detail, opaque) except AttributeError: pass def _dispatchDomainEventLifecycleCallback(self, dom: 'virDomain', event: int, detail: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain lifecycle event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), event, detail, opaque) return 0 def _dispatchDomainEventGenericCallback(self, dom: 'virDomain', cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain generic event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), opaque) return 0 def _dispatchDomainEventRTCChangeCallback(self, dom: 'virDomain', offset: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain RTC change event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), offset, opaque) return 0 def _dispatchDomainEventWatchdogCallback(self, dom: 'virDomain', action: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain watchdog event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), action, opaque) return 0 def _dispatchDomainEventIOErrorCallback(self, dom: 'virDomain', srcPath: str, devAlias: str, action: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain IO error event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), srcPath, devAlias, action, opaque) return 0 def _dispatchDomainEventIOErrorReasonCallback(self, dom: 'virDomain', srcPath: str, devAlias: str, action: int, reason: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain IO error event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), srcPath, devAlias, action, reason, opaque) return 0 def _dispatchDomainEventGraphicsCallback(self, dom: 'virDomain', phase: int, localAddr: Any, remoteAddr: Any, authScheme: str, subject: Any, cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain graphics event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), phase, localAddr, remoteAddr, authScheme, subject, opaque) return 0 def _dispatchDomainEventBlockJobCallback(self, dom: 'virDomain', disk: str, type: int, status: int, cbData: Dict[str, Any]) -> None: """Dispatches events to python user domain blockJob/blockJob2 event callbacks """ try: cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), disk, type, status, opaque) except AttributeError: pass def _dispatchDomainEventDiskChangeCallback(self, dom: 'virDomain', oldSrcPath: str, newSrcPath: str, devAlias: str, reason: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain diskChange event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), oldSrcPath, newSrcPath, devAlias, reason, opaque) return 0 def _dispatchDomainEventTrayChangeCallback(self, dom: 'virDomain', devAlias: str, reason: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain trayChange event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), devAlias, reason, opaque) return 0 def _dispatchDomainEventPMWakeupCallback(self, dom: 'virDomain', reason: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain pmwakeup event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), reason, opaque) return 0 def _dispatchDomainEventPMSuspendCallback(self, dom: 'virDomain', reason: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain pmsuspend event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), reason, opaque) return 0 def _dispatchDomainEventBalloonChangeCallback(self, dom: 'virDomain', actual: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user domain balloon change event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), actual, opaque) return 0 def _dispatchDomainEventPMSuspendDiskCallback(self, dom: 'virDomain', reason: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain pmsuspend-disk event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), reason, opaque) return 0 def _dispatchDomainEventDeviceRemovedCallback(self, dom: 'virDomain', devAlias: str, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain device removed event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), devAlias, opaque) return 0 def _dispatchDomainEventTunableCallback(self, dom: 'virDomain', params: Any, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain tunable event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), params, opaque) return 0 def _dispatchDomainEventAgentLifecycleCallback(self, dom: 'virDomain', state: int, reason: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain agent lifecycle event callback """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), state, reason, opaque) return 0 def _dispatchDomainEventDeviceAddedCallback(self, dom: 'virDomain', devAlias: str, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain device added event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), devAlias, opaque) return 0 def _dispatchDomainEventMigrationIterationCallback(self, dom: 'virDomain', iteration: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain migration iteration event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), iteration, opaque) return 0 def _dispatchDomainEventJobCompletedCallback(self, dom: 'virDomain', params: Dict[str, Any], cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain job completed callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), params, opaque) return 0 def _dispatchDomainEventDeviceRemovalFailedCallback(self, dom: 'virDomain', devAlias: str, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain device removal failed event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), devAlias, opaque) return 0 def _dispatchDomainEventMetadataChangeCallback(self, dom: 'virDomain', mtype: int, nsuri: str, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain metadata change event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), mtype, nsuri, opaque) return 0 def _dispatchDomainEventBlockThresholdCallback(self, dom: 'virDomain', dev: str, path: str, threshold: int, excess: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain block device threshold event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), dev, path, threshold, excess, opaque) return 0 def _dispatchDomainEventMemoryFailureCallback(self, dom: 'virDomain', recipient: int, action: int, flags: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain memory failure event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), recipient, action, flags, opaque) return 0 def _dispatchDomainEventMemoryDeviceSizeChangeCallback(self, dom: 'virDomain', alias: str, size: int, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain memory device size change event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), alias, size, opaque) return 0 def _dispatchDomainEventNICMACChangeCallback(self, dom: 'virDomain', alias: str, oldMAC: str, newMAC: str, cbData: Dict[str, Any]) -> int: """Dispatches event to python user domain NIC MAC change event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virDomain(self, _obj=dom), alias, oldMAC, newMAC, opaque) return 0 def domainEventDeregisterAny(self, callbackID: int) -> None: """Removes a Domain Event Callback. De-registering for a domain callback will disable delivery of this event type """ try: ret = libvirtmod.virConnectDomainEventDeregisterAny(self._o, callbackID) if ret == -1: raise libvirtError('virConnectDomainEventDeregisterAny() failed') del self.domainEventCallbackID[callbackID] except AttributeError: pass def _dispatchNetworkEventLifecycleCallback(self, net: 'virNetwork', event: int, detail: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user network lifecycle event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virNetwork(self, _obj=net), event, detail, opaque) return 0 def _dispatchNetworkEventMetadataChangeCallback(self, dom: 'virNetwork', mtype: int, nsuri: str, cbData: Dict[str, Any]) -> int: """Dispatches event to python user network metadata change event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virNetwork(self, _obj=dom), mtype, nsuri, opaque) return 0 def networkEventDeregisterAny(self, callbackID: int) -> None: """Removes a Network Event Callback. De-registering for a network callback will disable delivery of this event type""" try: ret = libvirtmod.virConnectNetworkEventDeregisterAny(self._o, callbackID) if ret == -1: raise libvirtError('virConnectNetworkEventDeregisterAny() failed') del self.networkEventCallbackID[callbackID] except AttributeError: pass def networkEventRegisterAny(self, net: Optional['virNetwork'], eventID: int, cb: Callable, opaque: _T) -> int: """Adds a Network Event Callback. Registering for a network callback will enable delivery of the events""" if not hasattr(self, 'networkEventCallbackID'): self.networkEventCallbackID = {} # type: Dict[int, _T] cbData = {"cb": cb, "conn": self, "opaque": opaque} if net is None: ret = libvirtmod.virConnectNetworkEventRegisterAny(self._o, None, eventID, cbData) else: ret = libvirtmod.virConnectNetworkEventRegisterAny(self._o, net._o, eventID, cbData) if ret == -1: raise libvirtError('virConnectNetworkEventRegisterAny() failed') self.networkEventCallbackID[ret] = opaque return ret def domainEventRegisterAny(self, dom: Optional['virDomain'], eventID: int, cb: Callable, opaque: _T) -> int: """Adds a Domain Event Callback. Registering for a domain callback will enable delivery of the events """ if not hasattr(self, 'domainEventCallbackID'): self.domainEventCallbackID = {} # type: Dict[int, _T] cbData = {"cb": cb, "conn": self, "opaque": opaque} if dom is None: ret = libvirtmod.virConnectDomainEventRegisterAny(self._o, None, eventID, cbData) else: ret = libvirtmod.virConnectDomainEventRegisterAny(self._o, dom._o, eventID, cbData) if ret == -1: raise libvirtError('virConnectDomainEventRegisterAny() failed') self.domainEventCallbackID[ret] = opaque return ret def _dispatchStoragePoolEventLifecycleCallback(self, pool: 'virStoragePool', event: int, detail: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user storage pool lifecycle event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virStoragePool(self, _obj=pool), event, detail, opaque) return 0 def _dispatchStoragePoolEventGenericCallback(self, pool: 'virStoragePool', cbData: Dict[str, Any]) -> int: """Dispatches events to python user storage pool generic event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virStoragePool(self, _obj=pool), opaque) return 0 def storagePoolEventDeregisterAny(self, callbackID: int) -> None: """Removes a Storage Pool Event Callback. De-registering for a storage pool callback will disable delivery of this event type""" try: ret = libvirtmod.virConnectStoragePoolEventDeregisterAny(self._o, callbackID) if ret == -1: raise libvirtError('virConnectStoragePoolEventDeregisterAny() failed') del self.storagePoolEventCallbackID[callbackID] except AttributeError: pass def storagePoolEventRegisterAny(self, pool: Optional['virStoragePool'], eventID: int, cb: Callable, opaque: _T) -> int: """Adds a Storage Pool Event Callback. Registering for a storage pool callback will enable delivery of the events""" if not hasattr(self, 'storagePoolEventCallbackID'): self.storagePoolEventCallbackID = {} # type: Dict[int, _T] cbData = {"cb": cb, "conn": self, "opaque": opaque} if pool is None: ret = libvirtmod.virConnectStoragePoolEventRegisterAny(self._o, None, eventID, cbData) else: ret = libvirtmod.virConnectStoragePoolEventRegisterAny(self._o, pool._o, eventID, cbData) if ret == -1: raise libvirtError('virConnectStoragePoolEventRegisterAny() failed') self.storagePoolEventCallbackID[ret] = opaque return ret def _dispatchNodeDeviceEventLifecycleCallback(self, dev: 'virNodeDevice', event: int, detail: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user node device lifecycle event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virNodeDevice(self, _obj=dev), event, detail, opaque) return 0 def _dispatchNodeDeviceEventGenericCallback(self, dev: 'virNodeDevice', cbData: Dict[str, Any]) -> int: """Dispatches events to python user node device generic event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virNodeDevice(self, _obj=dev), opaque) return 0 def nodeDeviceEventDeregisterAny(self, callbackID: int) -> None: """Removes a Node Device Event Callback. De-registering for a node device callback will disable delivery of this event type""" try: ret = libvirtmod.virConnectNodeDeviceEventDeregisterAny(self._o, callbackID) if ret == -1: raise libvirtError('virConnectNodeDeviceEventDeregisterAny() failed') del self.nodeDeviceEventCallbackID[callbackID] except AttributeError: pass def nodeDeviceEventRegisterAny(self, dev: Optional['virNodeDevice'], eventID: int, cb: Callable, opaque: _T) -> int: """Adds a Node Device Event Callback. Registering for a node device callback will enable delivery of the events""" if not hasattr(self, 'nodeDeviceEventCallbackID'): self.nodeDeviceEventCallbackID = {} # type: Dict[int, _T] cbData = {"cb": cb, "conn": self, "opaque": opaque} if dev is None: ret = libvirtmod.virConnectNodeDeviceEventRegisterAny(self._o, None, eventID, cbData) else: ret = libvirtmod.virConnectNodeDeviceEventRegisterAny(self._o, dev._o, eventID, cbData) if ret == -1: raise libvirtError('virConnectNodeDeviceEventRegisterAny() failed') self.nodeDeviceEventCallbackID[ret] = opaque return ret def _dispatchSecretEventLifecycleCallback(self, secret: 'virSecret', event: int, detail: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user secret lifecycle event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virSecret(self, _obj=secret), event, detail, opaque) return 0 def _dispatchSecretEventGenericCallback(self, secret: 'virSecret', cbData: Dict[str, Any]) -> int: """Dispatches events to python user secret generic event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, virSecret(self, _obj=secret), opaque) return 0 def secretEventDeregisterAny(self, callbackID: int) -> None: """Removes a Secret Event Callback. De-registering for a secret callback will disable delivery of this event type""" try: ret = libvirtmod.virConnectSecretEventDeregisterAny(self._o, callbackID) if ret == -1: raise libvirtError('virConnectSecretEventDeregisterAny() failed') del self.secretEventCallbackID[callbackID] except AttributeError: pass def secretEventRegisterAny(self, secret: Optional['virSecret'], eventID: int, cb: Callable, opaque: _T) -> int: """Adds a Secret Event Callback. Registering for a secret callback will enable delivery of the events""" if not hasattr(self, 'secretEventCallbackID'): self.secretEventCallbackID = {} # type: Dict[int, _T] cbData = {"cb": cb, "conn": self, "opaque": opaque} if secret is None: ret = libvirtmod.virConnectSecretEventRegisterAny(self._o, None, eventID, cbData) else: ret = libvirtmod.virConnectSecretEventRegisterAny(self._o, secret._o, eventID, cbData) if ret == -1: raise libvirtError('virConnectSecretEventRegisterAny() failed') self.secretEventCallbackID[ret] = opaque return ret def listAllDomains(self, flags: int = 0) -> List['virDomain']: """List all domains and returns a list of domain objects""" ret = libvirtmod.virConnectListAllDomains(self._o, flags) if ret is None: raise libvirtError("virConnectListAllDomains() failed") return [virDomain(self, _obj=domptr) for domptr in ret] def listAllStoragePools(self, flags: int = 0) -> List['virStoragePool']: """Returns a list of storage pool objects""" ret = libvirtmod.virConnectListAllStoragePools(self._o, flags) if ret is None: raise libvirtError("virConnectListAllStoragePools() failed") return [virStoragePool(self, _obj=poolptr) for poolptr in ret] def listAllNetworks(self, flags: int = 0) -> List['virNetwork']: """Returns a list of network objects""" ret = libvirtmod.virConnectListAllNetworks(self._o, flags) if ret is None: raise libvirtError("virConnectListAllNetworks() failed") return [virNetwork(self, _obj=netptr) for netptr in ret] def listAllInterfaces(self, flags: int = 0) -> List['virInterface']: """Returns a list of interface objects""" ret = libvirtmod.virConnectListAllInterfaces(self._o, flags) if ret is None: raise libvirtError("virConnectListAllInterfaces() failed") return [virInterface(self, _obj=ifaceptr) for ifaceptr in ret] def listAllDevices(self, flags: int = 0) -> List['virNodeDevice']: """Returns a list of host node device objects""" ret = libvirtmod.virConnectListAllNodeDevices(self._o, flags) if ret is None: raise libvirtError("virConnectListAllNodeDevices() failed") return [virNodeDevice(self, _obj=devptr) for devptr in ret] def listAllNWFilters(self, flags: int = 0) -> List['virNWFilter']: """Returns a list of network filter objects""" ret = libvirtmod.virConnectListAllNWFilters(self._o, flags) if ret is None: raise libvirtError("virConnectListAllNWFilters() failed") return [virNWFilter(self, _obj=filter_ptr) for filter_ptr in ret] def listAllNWFilterBindings(self, flags: int = 0) -> List['virNWFilterBinding']: """Returns a list of network filter binding objects""" ret = libvirtmod.virConnectListAllNWFilterBindings(self._o, flags) if ret is None: raise libvirtError("virConnectListAllNWFilterBindings() failed") return [virNWFilterBinding(self, _obj=filter_ptr) for filter_ptr in ret] def listAllSecrets(self, flags: int = 0) -> List['virSecret']: """Returns a list of secret objects""" ret = libvirtmod.virConnectListAllSecrets(self._o, flags) if ret is None: raise libvirtError("virConnectListAllSecrets() failed") return [virSecret(self, _obj=secret_ptr) for secret_ptr in ret] def _dispatchCloseCallback(self, reason: int, cbData: Dict[str, Any]) -> int: """Dispatches events to python user close callback""" cb = cbData["cb"] opaque = cbData["opaque"] cb(self, reason, opaque) return 0 def unregisterCloseCallback(self) -> None: """Removes a close event callback""" ret = libvirtmod.virConnectUnregisterCloseCallback(self._o) if ret == -1: raise libvirtError('virConnectUnregisterCloseCallback() failed') def registerCloseCallback(self, cb: Callable, opaque: _T) -> int: """Adds a close event callback, providing a notification when a connection fails / closes""" cbData = {"cb": cb, "conn": self, "opaque": opaque} ret = libvirtmod.virConnectRegisterCloseCallback(self._o, cbData) if ret == -1: raise libvirtError('virConnectRegisterCloseCallback() failed') return ret def createXMLWithFiles(self, xmlDesc: str, files: List[int], flags: int = 0) -> 'virDomain': """Launch a new guest domain, based on an XML description similar to the one returned by virDomainGetXMLDesc() This function may require privileged access to the hypervisor. The domain is not persistent, so its definition will disappear when it is destroyed, or if the host is restarted (see virDomainDefineXML() to define persistent domains). @files provides an array of file descriptors which will be made available to the 'init' process of the guest. The file handles exposed to the guest will be renumbered to start from 3 (ie immediately following stderr). This is only supported for guests which use container based virtualization technology. If the VIR_DOMAIN_START_PAUSED flag is set, the guest domain will be started, but its CPUs will remain paused. The CPUs can later be manually started using virDomainResume. If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest domain will be automatically destroyed when the virConnectPtr object is finally released. This will also happen if the client application crashes / loses its connection to the libvirtd daemon. Any domains marked for auto destroy will block attempts at migration, save-to-file, or snapshots. """ ret = libvirtmod.virDomainCreateXMLWithFiles(self._o, xmlDesc, files, flags) if ret is None: raise libvirtError('virDomainCreateXMLWithFiles() failed') __tmp = virDomain(self, _obj=ret) return __tmp def getAllDomainStats(self, stats: int = 0, flags: int = 0) -> List[Tuple['virDomain', Dict[str, Any]]]: """Query statistics for all domains on a given connection. Report statistics of various parameters for a running VM according to @stats field. The statistics are returned as an array of structures for each queried domain. The structure contains an array of typed parameters containing the individual statistics. The typed parameter name for each statistic field consists of a dot-separated string containing name of the requested group followed by a group specific description of the statistic value. The statistic groups are enabled using the @stats parameter which is a binary-OR of enum virDomainStatsTypes. The following groups are available (although not necessarily implemented for each hypervisor): VIR_DOMAIN_STATS_STATE: Return domain state and reason for entering that state. The typed parameter keys are in this format: "state.state" - state of the VM, returned as int from virDomainState enum "state.reason" - reason for entering given state, returned as int from virDomain*Reason enum corresponding to given state. Using 0 for @stats returns all stats groups supported by the given hypervisor. Specifying VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS as @flags makes the function return error in case some of the stat types in @stats were not recognized by the daemon. Similarly to virConnectListAllDomains, @flags can contain various flags to filter the list of domains to provide stats for. VIR_CONNECT_GET_ALL_DOMAINS_STATS_ACTIVE selects online domains while VIR_CONNECT_GET_ALL_DOMAINS_STATS_INACTIVE selects offline ones. VIR_CONNECT_GET_ALL_DOMAINS_STATS_PERSISTENT and VIR_CONNECT_GET_ALL_DOMAINS_STATS_TRANSIENT allow to filter the list according to their persistence. To filter the list of VMs by domain state @flags can contain VIR_CONNECT_GET_ALL_DOMAINS_STATS_RUNNING, VIR_CONNECT_GET_ALL_DOMAINS_STATS_PAUSED, VIR_CONNECT_GET_ALL_DOMAINS_STATS_SHUTOFF and/or VIR_CONNECT_GET_ALL_DOMAINS_STATS_OTHER for all other states. """ ret = libvirtmod.virConnectGetAllDomainStats(self._o, stats, flags) if ret is None: raise libvirtError("virConnectGetAllDomainStats() failed") return [(virDomain(self, _obj=elem[0]), elem[1]) for elem in ret] def domainListGetStats(self, doms: List['virDomain'], stats: int = 0, flags: int = 0) -> List[Tuple['virDomain', Dict[str, Any]]]: """ Query statistics for given domains. Report statistics of various parameters for a running VM according to @stats field. The statistics are returned as an array of structures for each queried domain. The structure contains an array of typed parameters containing the individual statistics. The typed parameter name for each statistic field consists of a dot-separated string containing name of the requested group followed by a group specific description of the statistic value. The statistic groups are enabled using the @stats parameter which is a binary-OR of enum virDomainStatsTypes. The following groups are available (although not necessarily implemented for each hypervisor): VIR_DOMAIN_STATS_STATE: Return domain state and reason for entering that state. The typed parameter keys are in this format: "state.state" - state of the VM, returned as int from virDomainState enum "state.reason" - reason for entering given state, returned as int from virDomain*Reason enum corresponding to given state. Using 0 for @stats returns all stats groups supported by the given hypervisor. Specifying VIR_CONNECT_GET_ALL_DOMAINS_STATS_ENFORCE_STATS as @flags makes the function return error in case some of the stat types in @stats were not recognized by the daemon. Get statistics about domains provided as a list in @doms. @stats is a bit field selecting requested statistics types.""" domlist = list() for dom in doms: if not isinstance(dom, virDomain): raise libvirtError("domain list contains non-domain elements") domlist.append(dom._o) ret = libvirtmod.virDomainListGetStats(self._o, domlist, stats, flags) if ret is None: raise libvirtError("virDomainListGetStats() failed") return [(virDomain(self, _obj=elem[0]), elem[1]) for elem in ret] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-override-virDomain.py0000644000175000017500000001277414612401403021406 0ustar00jirkajirka def listAllSnapshots(self, flags: int = 0) -> List['virDomainSnapshot']: """List all snapshots and returns a list of snapshot objects""" ret = libvirtmod.virDomainListAllSnapshots(self._o, flags) if ret is None: raise libvirtError("virDomainListAllSnapshots() failed") return [virDomainSnapshot(self, _obj=snapptr) for snapptr in ret] def listAllCheckpoints(self, flags: int = 0) -> List['virDomainCheckpoint']: """List all checkpoints and returns a list of checkpoint objects""" ret = libvirtmod.virDomainListAllCheckpoints(self._o, flags) if ret is None: raise libvirtError("virDomainListAllCheckpoints() failed") return [virDomainCheckpoint(self, _obj=chkptr) for chkptr in ret] def createWithFiles(self, files: List[int], flags: int = 0) -> 'virDomain': """Launch a defined domain. If the call succeeds the domain moves from the defined to the running domains pools. @files provides an array of file descriptors which will be made available to the 'init' process of the guest. The file handles exposed to the guest will be renumbered to start from 3 (ie immediately following stderr). This is only supported for guests which use container based virtualization technology. If the VIR_DOMAIN_START_PAUSED flag is set, or if the guest domain has a managed save image that requested paused state (see virDomainManagedSave()) the guest domain will be started, but its CPUs will remain paused. The CPUs can later be manually started using virDomainResume(). In all other cases, the guest domain will be running. If the VIR_DOMAIN_START_AUTODESTROY flag is set, the guest domain will be automatically destroyed when the virConnectPtr object is finally released. This will also happen if the client application crashes / loses its connection to the libvirtd daemon. Any domains marked for auto destroy will block attempts at migration, save-to-file, or snapshots. If the VIR_DOMAIN_START_BYPASS_CACHE flag is set, and there is a managed save file for this domain (created by virDomainManagedSave()), then libvirt will attempt to bypass the file system cache while restoring the file, or fail if it cannot do so for the given system; this can allow less pressure on file system cache, but also risks slowing loads from NFS. If the VIR_DOMAIN_START_FORCE_BOOT flag is set, then any managed save file for this domain is discarded, and the domain boots from scratch. """ ret = libvirtmod.virDomainCreateWithFiles(self._o, files, flags) if ret == -1: raise libvirtError('virDomainCreateWithFiles() failed') return ret def fsFreeze(self, mountpoints: List[str] = None, flags: int = 0) -> int: """Freeze specified filesystems within the guest """ ret = libvirtmod.virDomainFSFreeze(self._o, mountpoints, flags) if ret == -1: raise libvirtError('virDomainFSFreeze() failed') return ret def fsThaw(self, mountpoints: List[str] = None, flags: int = 0) -> int: """Thaw specified filesystems within the guest """ ret = libvirtmod.virDomainFSThaw(self._o, mountpoints, flags) if ret == -1: raise libvirtError('virDomainFSThaw() failed') return ret def getTime(self, flags: int = 0) -> int: """Extract information about guest time """ ret = libvirtmod.virDomainGetTime(self._o, flags) if ret is None: raise libvirtError('virDomainGetTime() failed') return ret def setTime(self, time: int = None, flags: int = 0) -> int: """Set guest time to the given value. @time is a dict containing 'seconds' field for seconds and 'nseconds' field for nanoseconds """ ret = libvirtmod.virDomainSetTime(self._o, time, flags) if ret == -1: raise libvirtError('virDomainSetTime() failed') return ret def FDAssociate(self, name: str, files: List[int], flags: int = 0) -> int: """Associate the array of FDs passed as @fds with the domain object under @name. The FDs are associated as long as the connection used to associated exists and are disposed of afterwards. FD may still be kept open by the hypervisor for as long as it's needed. Security labelling (e.g. via the selinux) may be applied on the passed FDs when requiredg for usage by the VM. By default libvirt does not restore the seclabels on the FDs afterwards to avoid keeping it open unnecessarily. Restoring of the security label can be requested by passing either VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_RESTORE for a best-effort attempt to restore the security label after use. Requesting the restore of security label will require that the file descriptors are kept open for the whole time they are used by the hypervisor, or other additional overhead. In certain cases usage of the fd group would imply read-only access. Passing VIR_DOMAIN_FD_ASSOCIATE_SECLABEL_WRITABLE in @flags ensures that a writable security label is picked in case when the file represented by the fds may be used in write mode. """ ret = libvirtmod.virDomainFDAssociate(self._o, name, files, flags) if ret == -1: raise libvirtError('virDomainFDAssociate() failed') return ret ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-override-virDomainCheckpoint.py0000644000175000017500000000131414612401403023402 0ustar00jirkajirka def getConnect(self) -> 'virConnect': """Get the connection that owns the domain that a checkpoint was created for""" return self.connect() def getDomain(self) -> 'virDomain': """Get the domain that a checkpoint was created for""" return self.domain() def listAllChildren(self, flags: int = 0) -> List['virDomainCheckpoint']: """List all child checkpoints and returns a list of checkpoint objects""" ret = libvirtmod.virDomainCheckpointListAllChildren(self._o, flags) if ret is None: raise libvirtError("virDomainCheckpointListAllChildren() failed") return [virDomainCheckpoint(self.domain(), _obj=chkptr) for chkptr in ret] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-override-virDomainSnapshot.py0000644000175000017500000000127614612401403023121 0ustar00jirkajirka def getConnect(self) -> 'virConnect': """Get the connection that owns the domain that a snapshot was created for""" return self.connect() def getDomain(self) -> 'virDomain': """Get the domain that a snapshot was created for""" return self.domain() def listAllChildren(self, flags: int = 0) -> List['virDomainSnapshot']: """List all child snapshots and returns a list of snapshot objects""" ret = libvirtmod.virDomainSnapshotListAllChildren(self._o, flags) if ret is None: raise libvirtError("virDomainSnapshotListAllChildren() failed") return [virDomainSnapshot(self.domain(), _obj=snapptr) for snapptr in ret] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-override-virNetwork.py0000644000175000017500000000057514612401403021624 0ustar00jirkajirka def listAllPorts(self, flags: int = 0) -> List['virNetworkPort']: """List all ports on the network and returns a list of network port objects""" ret = libvirtmod.virNetworkListAllPorts(self._o, flags) if ret is None: raise libvirtError("virNetworkListAllPorts() failed") return [virNetworkPort(self, _obj=domptr) for domptr in ret] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-override-virStoragePool.py0000644000175000017500000000061414612401403022423 0ustar00jirkajirka def listAllVolumes(self, flags: int = 0) -> List['virStorageVol']: """List all storage volumes and returns a list of storage volume objects""" ret = libvirtmod.virStoragePoolListAllVolumes(self._o, flags) if ret is None: raise libvirtError("virStoragePoolListAllVolumes() failed") return [virStorageVol(self._conn, _obj=volptr) for volptr in ret] ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-override-virStream.py0000644000175000017500000002627514612401403021433 0ustar00jirkajirka def __del__(self) -> None: try: if self.cb: libvirtmod.virStreamEventRemoveCallback(self._o) except AttributeError: pass if self._o is not None: libvirtmod.virStreamFree(self._o) self._o = None def _dispatchStreamEventCallback(self, events: int, cbData: Dict[str, Any]) -> int: """ Dispatches events to python user's stream event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(self, events, opaque) return 0 def eventAddCallback(self, events: int, cb: Callable[['virStream', int, _T], None], opaque: _T) -> None: self.cb = cb cbData = {"stream": self, "cb": cb, "opaque": opaque} ret = libvirtmod.virStreamEventAddCallback(self._o, events, cbData) if ret == -1: raise libvirtError('virStreamEventAddCallback() failed') def recvAll(self, handler: Callable[['virStream', bytes, _T], int], opaque: _T) -> None: """Receive the entire data stream, sending the data to the requested data sink. This is simply a convenient alternative to virStreamRecv, for apps that do blocking-I/O. A hypothetical handler function looks like: def handler(stream, # virStream instance buf, # string containing received data opaque): # extra data passed to recvAll as opaque fd = opaque return os.write(fd, buf) """ while True: got = self.recv(virStorageVol.streamBufSize) if got == -2: raise libvirtError("cannot use recvAll with " "nonblocking stream") if len(got) == 0: break try: ret = handler(self, got, opaque) if isinstance(ret, int) and ret < 0: raise RuntimeError("recvAll handler returned %d" % ret) except BaseException: try: self.abort() except Exception: pass raise def sendAll(self, handler: Callable[['virStream', int, _T], bytes], opaque: _T) -> None: """ Send the entire data stream, reading the data from the requested data source. This is simply a convenient alternative to virStreamSend, for apps that do blocking-I/O. A hypothetical handler function looks like: def handler(stream, # virStream instance nbytes, # int amt of data to read opaque): # extra data passed to recvAll as opaque fd = opaque return os.read(fd, nbytes) """ while True: try: got = handler(self, virStorageVol.streamBufSize, opaque) except BaseException: try: self.abort() except Exception: pass raise if not got: break ret = self.send(got) if ret == -2: raise libvirtError("cannot use sendAll with " "nonblocking stream") def recv(self, nbytes: int) -> bytes: """Reads a series of bytes from the stream. This method may block the calling application for an arbitrary amount of time. Errors are not guaranteed to be reported synchronously with the call, but may instead be delayed until a subsequent call. On success, the received data is returned. On failure, an exception is raised. If the stream is a NONBLOCK stream and the request would block, integer -2 is returned. """ ret = libvirtmod.virStreamRecv(self._o, nbytes) if ret is None: raise libvirtError('virStreamRecv() failed') return ret def send(self, data: bytes) -> int: """Write a series of bytes to the stream. This method may block the calling application for an arbitrary amount of time. Once an application has finished sending data it should call virStreamFinish to wait for successful confirmation from the driver, or detect any error This method may not be used if a stream source has been registered Errors are not guaranteed to be reported synchronously with the call, but may instead be delayed until a subsequent call. """ ret = libvirtmod.virStreamSend(self._o, data) if ret == -1: raise libvirtError('virStreamSend() failed') return ret def recvHole(self, flags: int = 0) -> int: """This method is used to determine the length in bytes of the empty space to be created in a stream's target file when uploading or downloading sparsely populated files. This is the counterpart to sendHole. """ ret = libvirtmod.virStreamRecvHole(self._o, flags) if ret is None: raise libvirtError('virStreamRecvHole() failed') return ret def sendHole(self, length: int, flags: int = 0) -> int: """Rather than transmitting empty file space, this method directs the stream target to create length bytes of empty space. This method would be used when uploading or downloading sparsely populated files to avoid the needless copy of empty file space. """ ret = libvirtmod.virStreamSendHole(self._o, length, flags) if ret == -1: raise libvirtError('virStreamSendHole() failed') return ret def recvFlags(self, nbytes: int, flags: int = 0) -> Union[bytes, int]: """Reads a series of bytes from the stream. This method may block the calling application for an arbitrary amount of time. This is just like recv except it has flags argument. Errors are not guaranteed to be reported synchronously with the call, but may instead be delayed until a subsequent call. On success, the received data is returned. On failure, an exception is raised. If the stream is a NONBLOCK stream and the request would block, integer -2 is returned. """ ret = libvirtmod.virStreamRecvFlags(self._o, nbytes, flags) if ret is None: raise libvirtError('virStreamRecvFlags() failed') return ret def sparseRecvAll(self, handler: Callable[['virStream', bytes, _T], Union[bytes, int]], holeHandler: Callable[['virStream', int, _T], Optional[int]], opaque: _T) -> None: """Receive the entire data stream, sending the data to the requested data sink handler and calling the skip holeHandler to generate holes for sparse stream targets. This is simply a convenient alternative to recvFlags, for apps that do blocking-I/O and want to preserve sparseness. Hypothetical callbacks can look like this: def handler(stream, # virStream instance buf, # string containing received data opaque): # extra data passed to sparseRecvAll as opaque fd = opaque return os.write(fd, buf) def holeHandler(stream, # virStream instance length, # number of bytes to skip opaque): # extra data passed to sparseRecvAll as opaque fd = opaque cur = os.lseek(fd, length, os.SEEK_CUR) return os.ftruncate(fd, cur) # take this extra step to # actually allocate the hole """ while True: want = virStorageVol.streamBufSize got = self.recvFlags(want, VIR_STREAM_RECV_STOP_AT_HOLE) if got == -2: raise libvirtError("cannot use sparseRecvAll with " "nonblocking stream") elif got == -3: length = self.recvHole() if length is None: self.abort() raise RuntimeError("recvHole handler failed") ret_hole = holeHandler(self, length, opaque) if isinstance(ret_hole, int) and ret_hole < 0: self.abort() raise RuntimeError("holeHandler handler returned %d" % ret_hole) continue elif isinstance(got, int): raise ValueError(got) elif not isinstance(got, bytes): raise TypeError(type(got)) if len(got) == 0: break ret_data = handler(self, got, opaque) if isinstance(ret_data, int) and ret_data < 0: self.abort() raise RuntimeError("sparseRecvAll handler returned %d" % ret_data) def sparseSendAll(self, handler: Callable[['virStream', int, _T], Union[bytes, int]], holeHandler: Callable[['virStream', _T], Tuple[bool, int]], skipHandler: Callable[['virStream', int, _T], int], opaque: _T) -> None: """Send the entire data stream, reading the data from the requested data source. This is simply a convenient alternative to virStreamSend, for apps that do blocking-I/O and want to preserve sparseness. Hypothetical callbacks can look like this: def handler(stream, # virStream instance nbytes, # int amt of data to read opaque): # extra data passed to sparseSendAll as opaque fd = opaque return os.read(fd, nbytes) def holeHandler(stream, # virStream instance opaque): # extra data passed to sparseSendAll as opaque fd = opaque cur = os.lseek(fd, 0, os.SEEK_CUR) # ... find out current section and its boundaries # and set inData = True/False and sectionLen correspondingly os.lseek(fd, cur, os.SEEK_SET) return [inData, sectionLen] def skipHandler(stream, # virStream instance length, # number of bytes to skip opaque): # extra data passed to sparseSendAll as opaque fd = opaque return os.lseek(fd, length, os.SEEK_CUR) """ while True: [inData, sectionLen] = holeHandler(self, opaque) if not inData and sectionLen > 0: if (self.sendHole(sectionLen) < 0 or skipHandler(self, sectionLen, opaque) < 0): self.abort() continue want = virStorageVol.streamBufSize if (want > sectionLen): want = sectionLen got = handler(self, want, opaque) if isinstance(got, int) and got < 0: self.abort() raise RuntimeError("sparseSendAll handler returned %d" % got) if not got: break assert isinstance(got, bytes) ret = self.send(got) if ret == -2: raise libvirtError("cannot use sparseSendAll with " "nonblocking stream") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1743501822.0 libvirt-python-11.3.0/libvirt-override.c0000644000175000017500000122244514772734776017306 0ustar00jirkajirka/* * libvir.c: this modules implements the main part of the glue of the * libvir library and the Python interpreter. It provides the * entry points where an automatically generated stub is * unpractical * * Copyright (C) 2005-2019 Red Hat, Inc. * * Daniel Veillard */ /* Horrible kludge to work around even more horrible name-space pollution via Python.h. That file includes /usr/include/python3.x/pyconfig*.h, which has over 180 autoconf-style HAVE_* definitions. Shame on them. */ #undef HAVE_PTHREAD_H /* We want to see *_LAST enums. */ #define VIR_ENUM_SENTINELS #define PY_SSIZE_T_CLEAN #include #include #include #include #include #include #include "typewrappers.h" #include "libvirt.h" #include "libvirt-utils.h" #if 0 # define DEBUG_ERROR 1 #endif #if DEBUG_ERROR # define DEBUG(fmt, ...) \ printf(fmt, __VA_ARGS__) #else # define DEBUG(fmt, ...) \ while (0) {printf(fmt, __VA_ARGS__);} #endif /* * Utility function to retrieve the number of node CPUs present. * It first tries virNodeGetCPUMap, which will return the * number reliably, if available. * As a fallback and for compatibility with backlevel libvirt * versions virNodeGetInfo will be called to calculate the * CPU number, which has the potential to return a too small * number if some host CPUs are offline. */ static int getPyNodeCPUCount(virConnectPtr conn) { int i_retval; #if LIBVIR_CHECK_VERSION(1, 0, 0) LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetCPUMap(conn, NULL, NULL, 0); LIBVIRT_END_ALLOW_THREADS; #else /* fallback: use nodeinfo */ virNodeInfo nodeinfo; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetInfo(conn, &nodeinfo); LIBVIRT_END_ALLOW_THREADS; if (i_retval >= 0) i_retval = VIR_NODEINFO_MAXCPUS(nodeinfo); #endif /* LIBVIR_CHECK_VERSION(1, 0, 0) */ return i_retval; } /************************************************************************ * * * Statistics * * * ************************************************************************/ static PyObject * libvirt_virDomainBlockStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; char * path; int c_retval; virDomainBlockStatsStruct stats; PyObject *info; if (!PyArg_ParseTuple(args, (char *)"Oz:virDomainBlockStats", &pyobj_domain, &path)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainBlockStats(domain, path, &stats, sizeof(stats)); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; /* convert to a Python tuple of long objects */ if ((info = PyTuple_New(5)) == NULL) return NULL; VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_longlongWrap(stats.rd_req), error); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_longlongWrap(stats.rd_bytes), error); VIR_PY_TUPLE_SET_GOTO(info, 2, libvirt_longlongWrap(stats.wr_req), error); VIR_PY_TUPLE_SET_GOTO(info, 3, libvirt_longlongWrap(stats.wr_bytes), error); VIR_PY_TUPLE_SET_GOTO(info, 4, libvirt_longlongWrap(stats.errs), error); return info; error: Py_DECREF(info); return NULL; } static PyObject * libvirt_virDomainBlockStatsFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; int i_retval; int nparams = 0; unsigned int flags; virTypedParameterPtr params; const char *path; if (!PyArg_ParseTuple(args, (char *)"OzI:virDomainBlockStatsFlags", &pyobj_domain, &path, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainBlockStatsFlags(domain, path, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainBlockStatsFlags(domain, path, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *totalbool; PyObject *ret = NULL; PyObject *error = NULL; int ncpus = -1, start_cpu = 0; int sumparams = 0, nparams = -1; ssize_t i; int i_retval; unsigned int flags; bool totalflag; virTypedParameterPtr params = NULL, cpuparams; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainGetCPUStats", &pyobj_domain, &totalbool, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (libvirt_boolUnwrap(totalbool, &totalflag) < 0) return NULL; if ((ret = PyList_New(0)) == NULL) return NULL; if (!totalflag) { LIBVIRT_BEGIN_ALLOW_THREADS; ncpus = virDomainGetCPUStats(domain, NULL, 0, 0, 0, flags); LIBVIRT_END_ALLOW_THREADS; if (ncpus < 0) { error = VIR_PY_NONE; goto error; } LIBVIRT_BEGIN_ALLOW_THREADS; nparams = virDomainGetCPUStats(domain, NULL, 0, 0, 1, flags); LIBVIRT_END_ALLOW_THREADS; if (nparams < 0) { error = VIR_PY_NONE; goto error; } sumparams = nparams * MIN(ncpus, 128); if (VIR_ALLOC_N(params, sumparams) < 0) { error = PyErr_NoMemory(); goto error; } while (ncpus) { int queried_ncpus = MIN(ncpus, 128); if (nparams) { LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetCPUStats(domain, params, nparams, start_cpu, queried_ncpus, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { error = VIR_PY_NONE; goto error; } } else { i_retval = 0; } for (i = 0; i < queried_ncpus; i++) { cpuparams = ¶ms[i * nparams]; VIR_PY_LIST_APPEND_GOTO(ret, getPyVirTypedParameter(cpuparams, i_retval), error); } start_cpu += queried_ncpus; ncpus -= queried_ncpus; virTypedParamsClear(params, sumparams); } } else { LIBVIRT_BEGIN_ALLOW_THREADS; nparams = virDomainGetCPUStats(domain, NULL, 0, -1, 1, flags); LIBVIRT_END_ALLOW_THREADS; if (nparams < 0) { error = VIR_PY_NONE; goto error; } if (nparams) { sumparams = nparams; if (VIR_ALLOC_N(params, nparams) < 0) { error = PyErr_NoMemory(); goto error; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetCPUStats(domain, params, nparams, -1, 1, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { error = VIR_PY_NONE; goto error; } } else { i_retval = 0; } VIR_PY_LIST_APPEND_GOTO(ret, getPyVirTypedParameter(params, i_retval), error); } virTypedParamsFree(params, sumparams); return ret; error: virTypedParamsFree(params, sumparams); Py_DECREF(ret); return error; } static PyObject * libvirt_virDomainInterfaceStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; char * path; int c_retval; virDomainInterfaceStatsStruct stats; PyObject *info; if (!PyArg_ParseTuple(args, (char *)"Oz:virDomainInterfaceStats", &pyobj_domain, &path)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainInterfaceStats(domain, path, &stats, sizeof(stats)); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; /* convert to a Python tuple of long objects */ if ((info = PyTuple_New(8)) == NULL) return NULL; VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_longlongWrap(stats.rx_bytes), error); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_longlongWrap(stats.rx_packets), error); VIR_PY_TUPLE_SET_GOTO(info, 2, libvirt_longlongWrap(stats.rx_errs), error); VIR_PY_TUPLE_SET_GOTO(info, 3, libvirt_longlongWrap(stats.rx_drop), error); VIR_PY_TUPLE_SET_GOTO(info, 4, libvirt_longlongWrap(stats.tx_bytes), error); VIR_PY_TUPLE_SET_GOTO(info, 5, libvirt_longlongWrap(stats.tx_packets), error); VIR_PY_TUPLE_SET_GOTO(info, 6, libvirt_longlongWrap(stats.tx_errs), error); VIR_PY_TUPLE_SET_GOTO(info, 7, libvirt_longlongWrap(stats.tx_drop), error); return info; error: Py_DECREF(info); return NULL; } static PyObject * libvirt_virDomainMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; unsigned int nr_stats; size_t i; virDomainMemoryStatStruct stats[VIR_DOMAIN_MEMORY_STAT_NR]; PyObject *info; PyObject *key = NULL, *val = NULL; if (!PyArg_ParseTuple(args, (char *)"O:virDomainMemoryStats", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; nr_stats = virDomainMemoryStats(domain, stats, VIR_DOMAIN_MEMORY_STAT_NR, 0); LIBVIRT_END_ALLOW_THREADS; if (nr_stats == (unsigned int)-1) return VIR_PY_NONE; /* convert to a Python dictionary */ if ((info = PyDict_New()) == NULL) return NULL; for (i = 0; i < nr_stats; i++) { switch (stats[i].tag) { case VIR_DOMAIN_MEMORY_STAT_SWAP_IN: key = libvirt_constcharPtrWrap("swap_in"); break; case VIR_DOMAIN_MEMORY_STAT_SWAP_OUT: key = libvirt_constcharPtrWrap("swap_out"); break; case VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT: key = libvirt_constcharPtrWrap("major_fault"); break; case VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT: key = libvirt_constcharPtrWrap("minor_fault"); break; case VIR_DOMAIN_MEMORY_STAT_UNUSED: key = libvirt_constcharPtrWrap("unused"); break; case VIR_DOMAIN_MEMORY_STAT_AVAILABLE: key = libvirt_constcharPtrWrap("available"); break; case VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON: key = libvirt_constcharPtrWrap("actual"); break; case VIR_DOMAIN_MEMORY_STAT_RSS: key = libvirt_constcharPtrWrap("rss"); break; #if LIBVIR_CHECK_VERSION(2, 1, 0) case VIR_DOMAIN_MEMORY_STAT_USABLE: key = libvirt_constcharPtrWrap("usable"); break; case VIR_DOMAIN_MEMORY_STAT_LAST_UPDATE: key = libvirt_constcharPtrWrap("last_update"); break; #endif /* LIBVIR_CHECK_VERSION(2, 1, 0) */ #if LIBVIR_CHECK_VERSION(4, 6, 0) case VIR_DOMAIN_MEMORY_STAT_DISK_CACHES: key = libvirt_constcharPtrWrap("disk_caches"); break; #endif /* LIBVIR_CHECK_VERSION(4, 6, 0) */ #if LIBVIR_CHECK_VERSION(5, 4, 0) case VIR_DOMAIN_MEMORY_STAT_HUGETLB_PGALLOC: key = libvirt_constcharPtrWrap("hugetlb_pgalloc"); break; case VIR_DOMAIN_MEMORY_STAT_HUGETLB_PGFAIL: key = libvirt_constcharPtrWrap("hugetlb_pgfail"); break; #endif /* LIBVIR_CHECK_VERSION(5, 4, 0) */ default: continue; } val = libvirt_ulonglongWrap(stats[i].val); VIR_PY_DICT_SET_GOTO(info, key, val, error); } return info; error: Py_DECREF(info); return NULL; } static PyObject * libvirt_virDomainGetSchedulerType(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; char *c_retval; int nparams; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetScedulerType", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_NONE; /* convert to a Python tuple of long objects */ if ((info = PyTuple_New(2)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_constcharPtrWrap(c_retval), error); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_intWrap(nparams), error); cleanup: VIR_FREE(c_retval); return info; error: Py_CLEAR(info); goto cleanup; } static PyObject * libvirt_virDomainGetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; char *c_retval; int i_retval; int nparams = 0; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetScedulerParameters", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_NONE; VIR_FREE(c_retval); if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetSchedulerParameters(domain, params, &nparams); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainGetSchedulerParametersFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; char *c_retval; int i_retval; int nparams = 0; unsigned int flags; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetScedulerParametersFlags", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_NONE; VIR_FREE(c_retval); if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetSchedulerParametersFlags(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainSetSchedulerParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; PyObject *ret = NULL; char *c_retval; int i_retval; int nparams = 0; Py_ssize_t size = 0; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OO:virDomainSetSchedulerParameters", &pyobj_domain, &info)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_INT_FAIL; VIR_FREE(c_retval); if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Domain has no settable attributes"); return NULL; } if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetSchedulerParameters(domain, params, &nparams); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainSetSchedulerParameters(domain, new_params, size); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virDomainSetSchedulerParametersFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; PyObject *ret = NULL; char *c_retval; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainSetSchedulerParametersFlags", &pyobj_domain, &info, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSchedulerType(domain, &nparams); LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_INT_FAIL; VIR_FREE(c_retval); if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Domain has no settable attributes"); return NULL; } if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetSchedulerParametersFlags(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainSetSchedulerParametersFlags(domain, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virDomainSetBlkioParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; PyObject *ret = NULL; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainSetBlkioParameters", &pyobj_domain, &info, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetBlkioParameters(domain, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_INT_FAIL; if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Domain has no settable attributes"); return NULL; } if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetBlkioParameters(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainSetBlkioParameters(domain, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virDomainGetBlkioParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; int i_retval; int nparams = 0; unsigned int flags; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetBlkioParameters", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetBlkioParameters(domain, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetBlkioParameters(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainSetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; PyObject *ret = NULL; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainSetMemoryParameters", &pyobj_domain, &info, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetMemoryParameters(domain, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_INT_FAIL; if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Domain has no settable attributes"); return NULL; } if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetMemoryParameters(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainSetMemoryParameters(domain, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virDomainGetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; int i_retval; int nparams = 0; unsigned int flags; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetMemoryParameters", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetMemoryParameters(domain, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetMemoryParameters(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainSetNumaParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; PyObject *ret = NULL; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainSetNumaParameters", &pyobj_domain, &info, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetNumaParameters(domain, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_INT_FAIL; if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Domain has no settable attributes"); return NULL; } if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetNumaParameters(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainSetNumaParameters(domain, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virDomainGetNumaParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; int i_retval; int nparams = 0; unsigned int flags; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetNumaParameters", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetNumaParameters(domain, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetNumaParameters(domain, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainSetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; PyObject *ret = NULL; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; const char *device = NULL; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OzOI:virDomainSetInterfaceParameters", &pyobj_domain, &device, &info, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetInterfaceParameters(domain, device, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_INT_FAIL; if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Domain has no settable attributes"); return NULL; } if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetInterfaceParameters(domain, device, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainSetInterfaceParameters(domain, device, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virDomainGetInterfaceParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; int i_retval; int nparams = 0; unsigned int flags; const char *device = NULL; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"OzI:virDomainGetInterfaceParameters", &pyobj_domain, &device, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetInterfaceParameters(domain, device, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetInterfaceParameters(domain, device, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainGetVcpus(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *pyretval = NULL; PyObject *pycpuinfo = NULL, *pycpumap = NULL; PyObject *error = NULL; virDomainInfo dominfo; virVcpuInfoPtr cpuinfo = NULL; unsigned char *cpumap = NULL; ssize_t cpumaplen, i; int i_retval, cpunum; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetVcpus", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetInfo(domain, &dominfo); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (VIR_ALLOC_N(cpuinfo, dominfo.nrVirtCpu) < 0) return PyErr_NoMemory(); cpumaplen = VIR_CPU_MAPLEN(cpunum); if (xalloc_oversized(dominfo.nrVirtCpu, cpumaplen) || VIR_ALLOC_N(cpumap, dominfo.nrVirtCpu * cpumaplen) < 0) { error = PyErr_NoMemory(); goto cleanup; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetVcpus(domain, cpuinfo, dominfo.nrVirtCpu, cpumap, cpumaplen); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { error = VIR_PY_NONE; goto cleanup; } /* convert to a Python tuple of long objects */ if ((pyretval = PyTuple_New(2)) == NULL) goto cleanup; if ((pycpuinfo = PyList_New(dominfo.nrVirtCpu)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyretval, 0, pycpuinfo, cleanup); if ((pycpumap = PyList_New(dominfo.nrVirtCpu)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyretval, 1, pycpumap, cleanup); for (i = 0; i < dominfo.nrVirtCpu; i++) { PyObject *info = PyTuple_New(4); if (info == NULL) goto cleanup; VIR_PY_LIST_SET_GOTO(pycpuinfo, i, info, cleanup); VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_intWrap(cpuinfo[i].number), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_intWrap(cpuinfo[i].state), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 2, libvirt_ulonglongWrap(cpuinfo[i].cpuTime), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 3, libvirt_intWrap(cpuinfo[i].cpu), cleanup); } for (i = 0; i < dominfo.nrVirtCpu; i++) { PyObject *info = PyTuple_New(cpunum); ssize_t j; if (info == NULL) goto cleanup; VIR_PY_LIST_SET_GOTO(pycpumap, i, info, cleanup); for (j = 0; j < cpunum; j++) { VIR_PY_TUPLE_SET_GOTO(info, j, PyBool_FromLong(VIR_CPU_USABLE(cpumap, cpumaplen, i, j)), cleanup); } } VIR_FREE(cpuinfo); VIR_FREE(cpumap); return pyretval; cleanup: VIR_FREE(cpuinfo); VIR_FREE(cpumap); Py_XDECREF(pyretval); return error; } static PyObject * libvirt_virDomainPinVcpu(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *pycpumap; PyObject *ret = NULL; unsigned char *cpumap; int cpumaplen, vcpu, cpunum; int i_retval; if (!PyArg_ParseTuple(args, (char *)"OiO:virDomainPinVcpu", &pyobj_domain, &vcpu, &pycpumap)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_INT_FAIL; if (virPyCpumapConvert(cpunum, pycpumap, &cpumap, &cpumaplen) < 0) return NULL; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainPinVcpu(domain, vcpu, cpumap, cpumaplen); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: VIR_FREE(cpumap); return ret; } static PyObject * libvirt_virDomainPinVcpuFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *pycpumap; PyObject *ret = NULL; unsigned char *cpumap; int cpumaplen, vcpu, cpunum; unsigned int flags; int i_retval; if (!PyArg_ParseTuple(args, (char *)"OiOI:virDomainPinVcpuFlags", &pyobj_domain, &vcpu, &pycpumap, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_INT_FAIL; if (virPyCpumapConvert(cpunum, pycpumap, &cpumap, &cpumaplen) < 0) return NULL; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainPinVcpuFlags(domain, vcpu, cpumap, cpumaplen, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: VIR_FREE(cpumap); return ret; } static PyObject * libvirt_virDomainGetVcpuPinInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *pycpumaps = NULL, *error = NULL; virDomainInfo dominfo; unsigned char *cpumaps = NULL; ssize_t cpumaplen, vcpu, pcpu; unsigned int flags; int i_retval, cpunum; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetVcpuPinInfo", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetInfo(domain, &dominfo); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; cpumaplen = VIR_CPU_MAPLEN(cpunum); if (xalloc_oversized(dominfo.nrVirtCpu, cpumaplen) || VIR_ALLOC_N(cpumaps, dominfo.nrVirtCpu * cpumaplen) < 0) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetVcpuPinInfo(domain, dominfo.nrVirtCpu, cpumaps, cpumaplen, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { error = VIR_PY_NONE; goto cleanup; } if ((pycpumaps = PyList_New(dominfo.nrVirtCpu)) == NULL) goto cleanup; for (vcpu = 0; vcpu < dominfo.nrVirtCpu; vcpu++) { PyObject *mapinfo = PyTuple_New(cpunum); if (mapinfo == NULL) goto cleanup; VIR_PY_LIST_SET_GOTO(pycpumaps, vcpu, mapinfo, cleanup); for (pcpu = 0; pcpu < cpunum; pcpu++) { VIR_PY_TUPLE_SET_GOTO(mapinfo, pcpu, PyBool_FromLong(VIR_CPU_USABLE(cpumaps, cpumaplen, vcpu, pcpu)), cleanup); } } VIR_FREE(cpumaps); return pycpumaps; cleanup: VIR_FREE(cpumaps); Py_XDECREF(pycpumaps); return error; } #if LIBVIR_CHECK_VERSION(0, 10, 0) static PyObject * libvirt_virDomainPinEmulator(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *pycpumap; unsigned char *cpumap = NULL; int cpumaplen, cpunum; int i_retval; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainPinEmulator", &pyobj_domain, &pycpumap, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_INT_FAIL; if (virPyCpumapConvert(cpunum, pycpumap, &cpumap, &cpumaplen) < 0) return NULL; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainPinEmulator(domain, cpumap, cpumaplen, flags); LIBVIRT_END_ALLOW_THREADS; VIR_FREE(cpumap); if (i_retval < 0) return VIR_PY_INT_FAIL; return VIR_PY_INT_SUCCESS; } static PyObject * libvirt_virDomainGetEmulatorPinInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *pycpumap; unsigned char *cpumap; ssize_t cpumaplen; ssize_t pcpu; unsigned int flags; int ret; int cpunum; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetEmulatorPinInfo", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_NONE; cpumaplen = VIR_CPU_MAPLEN(cpunum); if (VIR_ALLOC_N(cpumap, cpumaplen) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virDomainGetEmulatorPinInfo(domain, cpumap, cpumaplen, flags); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { VIR_FREE(cpumap); return VIR_PY_NONE; } if (!(pycpumap = PyTuple_New(cpunum))) { VIR_FREE(cpumap); return NULL; } for (pcpu = 0; pcpu < cpunum; pcpu++) { VIR_PY_TUPLE_SET_GOTO(pycpumap, pcpu, PyBool_FromLong(VIR_CPU_USABLE(cpumap, cpumaplen, 0, pcpu)), error); } cleanup: VIR_FREE(cpumap); return pycpumap; error: Py_CLEAR(pycpumap); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ #if LIBVIR_CHECK_VERSION(1, 2, 14) static PyObject * libvirt_virDomainGetIOThreadInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *py_retval = NULL; PyObject *py_iothrinfo = NULL; virDomainIOThreadInfoPtr *iothrinfo = NULL; unsigned int flags; ssize_t pcpu, i; int niothreads, cpunum; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetIOThreadInfo", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; niothreads = virDomainGetIOThreadInfo(domain, &iothrinfo, flags); LIBVIRT_END_ALLOW_THREADS; if (niothreads < 0) { py_retval = VIR_PY_NONE; goto cleanup; } /* convert to a Python list */ if ((py_iothrinfo = PyList_New(niothreads)) == NULL) goto cleanup; /* NOTE: If there are zero IOThreads we will return an empty list */ for (i = 0; i < niothreads; i++) { PyObject *iothrtpl = NULL; PyObject *iothrmap = NULL; virDomainIOThreadInfoPtr iothr = iothrinfo[i]; if (iothr == NULL) { py_retval = VIR_PY_NONE; goto cleanup; } if ((iothrtpl = PyTuple_New(2)) == NULL) goto cleanup; VIR_PY_LIST_SET_GOTO(py_iothrinfo, i, iothrtpl, cleanup); /* 0: IOThread ID */ VIR_PY_TUPLE_SET_GOTO(iothrtpl, 0, libvirt_uintWrap(iothr->iothread_id), cleanup); /* 1: CPU map */ if ((iothrmap = PyList_New(cpunum)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(iothrtpl, 1, iothrmap, cleanup); for (pcpu = 0; pcpu < cpunum; pcpu++) if (VIR_CPU_MAPLEN(pcpu + 1) > iothr->cpumaplen) { VIR_PY_LIST_SET_GOTO(iothrmap, pcpu, PyBool_FromLong(0), cleanup); } else { VIR_PY_LIST_SET_GOTO(iothrmap, pcpu, PyBool_FromLong(VIR_CPU_USED(iothr->cpumap, pcpu)), cleanup); } } py_retval = py_iothrinfo; py_iothrinfo = NULL; cleanup: if (niothreads > 0) { for (i = 0; i < niothreads; i++) virDomainIOThreadInfoFree(iothrinfo[i]); } VIR_FREE(iothrinfo); Py_XDECREF(py_iothrinfo); return py_retval; } static PyObject * libvirt_virDomainPinIOThread(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *pycpumap; PyObject *ret = NULL; unsigned char *cpumap; int cpumaplen, iothread_val, cpunum; unsigned int flags; int i_retval; if (!PyArg_ParseTuple(args, (char *)"OiOI:virDomainPinIOThread", &pyobj_domain, &iothread_val, &pycpumap, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((cpunum = getPyNodeCPUCount(virDomainGetConnect(domain))) < 0) return VIR_PY_INT_FAIL; if (virPyCpumapConvert(cpunum, pycpumap, &cpumap, &cpumaplen) < 0) return NULL; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainPinIOThread(domain, iothread_val, cpumap, cpumaplen, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: VIR_FREE(cpumap); return ret; } #endif /* LIBVIR_CHECK_VERSION(1, 2, 14) */ #if LIBVIR_CHECK_VERSION(4, 10, 0) static virPyTypedParamsHint virPyDomainSetIOThreadParams[] = { { VIR_DOMAIN_IOTHREAD_POLL_MAX_NS, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_IOTHREAD_POLL_GROW, VIR_TYPED_PARAM_UINT }, { VIR_DOMAIN_IOTHREAD_POLL_SHRINK, VIR_TYPED_PARAM_UINT }, # if LIBVIR_CHECK_VERSION(8, 5, 0) { VIR_DOMAIN_IOTHREAD_THREAD_POOL_MIN, VIR_TYPED_PARAM_INT }, { VIR_DOMAIN_IOTHREAD_THREAD_POOL_MAX, VIR_TYPED_PARAM_INT }, # endif /* LIBVIR_CHECK_VERSION(8, 5, 0) */ }; static PyObject * libvirt_virDomainSetIOThreadParams(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; PyObject *pyobj_dict = NULL; virDomainPtr dom; int iothread_val; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags; int c_retval; if (!PyArg_ParseTuple(args, (char *)"OiOI:virDomainSetIOThreadParams", &pyobj_dom, &iothread_val, &pyobj_dict, &flags)) return NULL; if (PyDict_Check(pyobj_dict)) { if (virPyDictToTypedParams(pyobj_dict, ¶ms, &nparams, virPyDomainSetIOThreadParams, VIR_N_ELEMENTS(virPyDomainSetIOThreadParams)) < 0) { return NULL; } } else { PyErr_Format(PyExc_TypeError, "IOThread polling params must be " "a dictionary"); return NULL; } dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSetIOThreadParams(dom, iothread_val, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(c_retval); } #endif /* LIBVIR_CHECK_VERSION(4, 10, 0) */ /************************************************************************ * * * Global error handler at the Python level * * * ************************************************************************/ static PyObject *libvirt_virPythonErrorFuncHandler = NULL; static PyObject *libvirt_virPythonErrorFuncCtxt = NULL; static PyObject * libvirt_virGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args ATTRIBUTE_UNUSED) { virError *err; PyObject *info; if ((err = virGetLastError()) == NULL) return VIR_PY_NONE; if ((info = PyTuple_New(9)) == NULL) return NULL; VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_intWrap(err->code), error); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_intWrap(err->domain), error); VIR_PY_TUPLE_SET_GOTO(info, 2, libvirt_constcharPtrWrap(err->message), error); VIR_PY_TUPLE_SET_GOTO(info, 3, libvirt_intWrap(err->level), error); VIR_PY_TUPLE_SET_GOTO(info, 4, libvirt_constcharPtrWrap(err->str1), error); VIR_PY_TUPLE_SET_GOTO(info, 5, libvirt_constcharPtrWrap(err->str2), error); VIR_PY_TUPLE_SET_GOTO(info, 6, libvirt_constcharPtrWrap(err->str3), error); VIR_PY_TUPLE_SET_GOTO(info, 7, libvirt_intWrap(err->int1), error); VIR_PY_TUPLE_SET_GOTO(info, 8, libvirt_intWrap(err->int2), error); return info; error: Py_XDECREF(info); return NULL; } static PyObject * libvirt_virConnGetLastError(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virError *err; PyObject *info; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConGetLastError", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; err = virConnGetLastError(conn); LIBVIRT_END_ALLOW_THREADS; if (err == NULL) return VIR_PY_NONE; if ((info = PyTuple_New(9)) == NULL) return NULL; VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_intWrap(err->code), error); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_intWrap(err->domain), error); VIR_PY_TUPLE_SET_GOTO(info, 2, libvirt_constcharPtrWrap(err->message), error); VIR_PY_TUPLE_SET_GOTO(info, 3, libvirt_intWrap(err->level), error); VIR_PY_TUPLE_SET_GOTO(info, 4, libvirt_constcharPtrWrap(err->str1), error); VIR_PY_TUPLE_SET_GOTO(info, 5, libvirt_constcharPtrWrap(err->str2), error); VIR_PY_TUPLE_SET_GOTO(info, 6, libvirt_constcharPtrWrap(err->str3), error); VIR_PY_TUPLE_SET_GOTO(info, 7, libvirt_intWrap(err->int1), error); VIR_PY_TUPLE_SET_GOTO(info, 8, libvirt_intWrap(err->int2), error); return info; error: Py_XDECREF(info); return NULL; } static void libvirt_virErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, virErrorPtr err) { PyObject *list = NULL, *info = NULL; PyObject *result; DEBUG("libvirt_virErrorFuncHandler(%p, %s, ...) called\n", ctx, err->message); if ((err == NULL) || (err->code == VIR_ERR_OK)) return; LIBVIRT_ENSURE_THREAD_STATE; if ((libvirt_virPythonErrorFuncHandler == NULL) || (libvirt_virPythonErrorFuncHandler == Py_None)) { virDefaultErrorFunc(err); } else { if ((list = PyTuple_New(2)) == NULL) goto cleanup; Py_XINCREF(libvirt_virPythonErrorFuncCtxt); VIR_PY_TUPLE_SET_GOTO(list, 0, libvirt_virPythonErrorFuncCtxt, cleanup); if ((info = PyTuple_New(9)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(list, 1, info, cleanup); VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_intWrap(err->code), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_intWrap(err->domain), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 2, libvirt_constcharPtrWrap(err->message), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 3, libvirt_intWrap(err->level), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 4, libvirt_constcharPtrWrap(err->str1), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 5, libvirt_constcharPtrWrap(err->str2), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 6, libvirt_constcharPtrWrap(err->str3), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 7, libvirt_intWrap(err->int1), cleanup); VIR_PY_TUPLE_SET_GOTO(info, 8, libvirt_intWrap(err->int2), cleanup); /* TODO pass conn and dom if available */ result = PyObject_Call(libvirt_virPythonErrorFuncHandler, list, NULL); Py_XDECREF(result); } cleanup: Py_XDECREF(list); LIBVIRT_RELEASE_THREAD_STATE; } static PyObject * libvirt_virRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) { PyObject *py_retval; PyObject *pyobj_f; PyObject *pyobj_ctx; if (!PyArg_ParseTuple(args, (char *) "OO:virRegisterErrorHandler", &pyobj_f, &pyobj_ctx)) return NULL; DEBUG("libvirt_virRegisterErrorHandler(%p, %p) called\n", pyobj_ctx, pyobj_f); virSetErrorFunc(NULL, libvirt_virErrorFuncHandler); Py_XDECREF(libvirt_virPythonErrorFuncHandler); Py_XDECREF(libvirt_virPythonErrorFuncCtxt); if ((pyobj_f == Py_None) && (pyobj_ctx == Py_None)) { libvirt_virPythonErrorFuncHandler = NULL; libvirt_virPythonErrorFuncCtxt = NULL; } else { Py_XINCREF(pyobj_ctx); Py_XINCREF(pyobj_f); /* TODO: check f is a function ! */ libvirt_virPythonErrorFuncHandler = pyobj_f; libvirt_virPythonErrorFuncCtxt = pyobj_ctx; } py_retval = libvirt_intWrap(1); return py_retval; } static int virConnectCredCallbackWrapper(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata) { PyObject *list = NULL; PyObject *pycred; PyObject *pyauth = (PyObject *)cbdata; PyObject *pycbdata; PyObject *pycb; PyObject *pyret = NULL; int ret = -1; size_t i; LIBVIRT_ENSURE_THREAD_STATE; pycb = PyList_GetItem(pyauth, 1); pycbdata = PyList_GetItem(pyauth, 2); if ((list = PyTuple_New(2)) == NULL) goto cleanup; if ((pycred = PyTuple_New(ncred)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(list, 0, pycred, cleanup); for (i = 0; i < ncred; i++) { PyObject *pycreditem; if ((pycreditem = PyList_New(5)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pycred, i, pycreditem, cleanup); VIR_PY_LIST_SET_GOTO(pycreditem, 0, libvirt_intWrap(cred[i].type), cleanup); VIR_PY_LIST_SET_GOTO(pycreditem, 1, libvirt_constcharPtrWrap(cred[i].prompt), cleanup); if (cred[i].challenge) { VIR_PY_LIST_SET_GOTO(pycreditem, 2, libvirt_constcharPtrWrap(cred[i].challenge), cleanup); } else { VIR_PY_LIST_SET_GOTO(pycreditem, 2, VIR_PY_NONE, cleanup); } if (cred[i].defresult) { VIR_PY_LIST_SET_GOTO(pycreditem, 3, libvirt_constcharPtrWrap(cred[i].defresult), cleanup); } else { VIR_PY_LIST_SET_GOTO(pycreditem, 3, VIR_PY_NONE, cleanup); } VIR_PY_LIST_SET_GOTO(pycreditem, 4, VIR_PY_NONE, cleanup); } Py_XINCREF(pycbdata); VIR_PY_TUPLE_SET_GOTO(list, 1, pycbdata, cleanup); PyErr_Clear(); pyret = PyObject_Call(pycb, list, NULL); if (PyErr_Occurred()) { PyErr_Print(); goto cleanup; } ret = PyLong_AsLong(pyret); if (ret == 0) { for (i = 0; i < ncred; i++) { PyObject *pycreditem; PyObject *pyresult; char *result = NULL; pycreditem = PyTuple_GetItem(pycred, i); pyresult = PyList_GetItem(pycreditem, 4); if (pyresult != Py_None) { libvirt_charPtrUnwrap(pyresult, &result); PyErr_Clear(); } if (result != NULL) { cred[i].result = result; cred[i].resultlen = strlen(result); } else { cred[i].result = NULL; cred[i].resultlen = 0; } } } cleanup: Py_XDECREF(list); Py_XDECREF(pyret); LIBVIRT_RELEASE_THREAD_STATE; return ret; } static PyObject * libvirt_virConnectOpenAuth(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; virConnectPtr c_retval = NULL; char * name; unsigned int flags; PyObject *pyauth; PyObject *pycredcb; PyObject *pycredtype; virConnectAuth auth; memset(&auth, 0, sizeof(auth)); if (!PyArg_ParseTuple(args, (char *)"zOI:virConnectOpenAuth", &name, &pyauth, &flags)) return NULL; pycredtype = PyList_GetItem(pyauth, 0); pycredcb = PyList_GetItem(pyauth, 1); auth.ncredtype = PyList_Size(pycredtype); if (auth.ncredtype) { size_t i; if (VIR_ALLOC_N(auth.credtype, auth.ncredtype) < 0) return PyErr_NoMemory(); for (i = 0; i < auth.ncredtype; i++) { PyObject *val; val = PyList_GetItem(pycredtype, i); if (libvirt_intUnwrap(val, &auth.credtype[i]) < 0) goto cleanup; } } if (pycredcb && pycredcb != Py_None) auth.cb = virConnectCredCallbackWrapper; auth.cbdata = pyauth; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectOpenAuth(name, &auth, flags); LIBVIRT_END_ALLOW_THREADS; cleanup: VIR_FREE(auth.credtype); py_retval = libvirt_virConnectPtrWrap((virConnectPtr) c_retval); return py_retval; } /************************************************************************ * * * Wrappers for functions where generator fails * * * ************************************************************************/ static PyObject * libvirt_virGetVersion(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { char *type = NULL; unsigned long libVer, typeVer = 0; int c_retval; if (!PyArg_ParseTuple(args, (char *) "|s:virGetVersion", &type)) return NULL; LIBVIRT_BEGIN_ALLOW_THREADS; if (type == NULL) c_retval = virGetVersion(&libVer, NULL, NULL); else c_retval = virGetVersion(&libVer, type, &typeVer); LIBVIRT_END_ALLOW_THREADS; if (c_retval == -1) return VIR_PY_NONE; if (type == NULL) return libvirt_intWrap(libVer); else return Py_BuildValue((char *) "kk", libVer, typeVer); } static PyObject * libvirt_virConnectGetVersion(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned long hvVersion; int c_retval; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectGetVersion", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectGetVersion(conn, &hvVersion); LIBVIRT_END_ALLOW_THREADS; if (c_retval == -1) return VIR_PY_INT_FAIL; return libvirt_intWrap(hvVersion); } #if LIBVIR_CHECK_VERSION(1, 1, 3) static PyObject * libvirt_virConnectGetCPUModelNames(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval; virConnectPtr conn; PyObject *rv = NULL, *pyobj_conn; char **models = NULL; ssize_t i; unsigned int flags = 0; const char *arch = NULL; if (!PyArg_ParseTuple(args, (char *)"OsI:virConnectGetCPUModelNames", &pyobj_conn, &arch, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectGetCPUModelNames(conn, arch, &models, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval == -1) return VIR_PY_NONE; if ((rv = PyList_New(c_retval)) == NULL) goto error; for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(rv, i, libvirt_constcharPtrWrap(models[i]), error); done: if (models) { for (i = 0; i < c_retval; i++) VIR_FREE(models[i]); VIR_FREE(models); } return rv; error: Py_CLEAR(rv); goto done; } #endif /* LIBVIR_CHECK_VERSION(1, 1, 3) */ static PyObject * libvirt_virConnectGetLibVersion(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned long libVer; int c_retval; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectGetLibVersion", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectGetLibVersion(conn, &libVer); LIBVIRT_END_ALLOW_THREADS; if (c_retval == -1) return VIR_PY_INT_FAIL; return libvirt_intWrap(libVer); } static PyObject * libvirt_virConnectListDomainsID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int *ids = NULL, c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListDomains", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDomains(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(ids, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDomains(conn, ids, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (ids) for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_intWrap(ids[i]), error); cleanup: VIR_FREE(ids); return py_retval; error: VIR_FREE(ids); Py_XDECREF(py_retval); return NULL; } #if LIBVIR_CHECK_VERSION(0, 9, 13) static PyObject * libvirt_virConnectListAllDomains(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virDomainPtr *doms = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllDomains", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllDomains(conn, &doms, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virDomainPtrWrap(doms[i]), error); /* python steals the pointer */ doms[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (doms[i]) virDomainFree(doms[i]); VIR_FREE(doms); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 9, 13) */ static PyObject * libvirt_virConnectListDefinedDomains(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListDefinedDomains", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedDomains(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedDomains(conn, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) { for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); } cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(5, 6, 0) static PyObject * libvirt_virDomainListAllCheckpoints(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; virDomainCheckpointPtr *chks = NULL; int c_retval; ssize_t i; virDomainPtr dom; PyObject *pyobj_dom; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainListAllCheckpoints", &pyobj_dom, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainListAllCheckpoints(dom, &chks, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virDomainCheckpointPtrWrap(chks[i]), error); chks[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (chks[i]) virDomainCheckpointFree(chks[i]); VIR_FREE(chks); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } static PyObject * libvirt_virDomainCheckpointListAllChildren(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; virDomainCheckpointPtr *chks = NULL; int c_retval; ssize_t i; virDomainCheckpointPtr parent; PyObject *pyobj_parent; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainCheckpointListAllChildren", &pyobj_parent, &flags)) return NULL; parent = (virDomainCheckpointPtr) PyvirDomainCheckpoint_Get(pyobj_parent); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainCheckpointListAllChildren(parent, &chks, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virDomainCheckpointPtrWrap(chks[i]), error); chks[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (chks[i]) virDomainCheckpointFree(chks[i]); VIR_FREE(chks); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(5, 6, 0) */ static PyObject * libvirt_virDomainSnapshotListNames(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virDomainPtr dom; PyObject *pyobj_dom; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainSnapshotListNames", &pyobj_dom, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSnapshotNum(dom, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSnapshotListNames(dom, names, c_retval, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } py_retval = PyList_New(c_retval); if (!py_retval) goto cleanup; for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 9, 13) static PyObject * libvirt_virDomainListAllSnapshots(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; virDomainSnapshotPtr *snaps = NULL; int c_retval; ssize_t i; virDomainPtr dom; PyObject *pyobj_dom; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainListAllSnapshots", &pyobj_dom, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainListAllSnapshots(dom, &snaps, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virDomainSnapshotPtrWrap(snaps[i]), error); snaps[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (snaps[i]) virDomainSnapshotFree(snaps[i]); VIR_FREE(snaps); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 9, 13) */ static PyObject * libvirt_virDomainSnapshotListChildrenNames(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virDomainSnapshotPtr snap; PyObject *pyobj_snap; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainSnapshotListChildrenNames", &pyobj_snap, &flags)) return NULL; snap = (virDomainSnapshotPtr) PyvirDomainSnapshot_Get(pyobj_snap); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSnapshotNumChildren(snap, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSnapshotListChildrenNames(snap, names, c_retval, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 9, 13) static PyObject * libvirt_virDomainSnapshotListAllChildren(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; virDomainSnapshotPtr *snaps = NULL; int c_retval; ssize_t i; virDomainSnapshotPtr parent; PyObject *pyobj_parent; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainSnapshotListAllChildren", &pyobj_parent, &flags)) return NULL; parent = (virDomainSnapshotPtr) PyvirDomainSnapshot_Get(pyobj_parent); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSnapshotListAllChildren(parent, &snaps, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virDomainSnapshotPtrWrap(snaps[i]), error); snaps[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (snaps[i]) virDomainSnapshotFree(snaps[i]); VIR_FREE(snaps); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 9, 13) */ static PyObject * libvirt_virDomainRevertToSnapshot(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval; virDomainSnapshotPtr snap; PyObject *pyobj_snap; PyObject *pyobj_dom; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainRevertToSnapshot", &pyobj_dom, &pyobj_snap, &flags)) return NULL; snap = (virDomainSnapshotPtr) PyvirDomainSnapshot_Get(pyobj_snap); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainRevertToSnapshot(snap, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_INT_FAIL; return libvirt_intWrap(c_retval); } static PyObject * libvirt_virDomainGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; virDomainInfo info; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetInfo", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetInfo(domain, &info); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(5)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_intWrap(info.state), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_ulongWrap(info.maxMem), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_ulongWrap(info.memory), error); VIR_PY_LIST_SET_GOTO(py_retval, 3, libvirt_intWrap(info.nrVirtCpu), error); VIR_PY_LIST_SET_GOTO(py_retval, 4, libvirt_ulonglongWrap(info.cpuTime), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virDomainGetState(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; int state; int reason; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetState", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetState(domain, &state, &reason, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(2)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_intWrap(state), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_intWrap(reason), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virDomainGetControlInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; virDomainControlInfo info; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetControlInfo", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetControlInfo(domain, &info, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(3)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_intWrap(info.state), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_intWrap(info.details), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_ulonglongWrap(info.stateTime), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virDomainGetBlockInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; virDomainBlockInfo info; const char *path; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OzI:virDomainGetBlockInfo", &pyobj_domain, &path, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetBlockInfo(domain, path, &info, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(3)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_ulonglongWrap(info.capacity), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_ulonglongWrap(info.allocation), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_ulonglongWrap(info.physical), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virNodeGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virConnectPtr conn; PyObject *pyobj_conn; virNodeInfo info; if (!PyArg_ParseTuple(args, (char *)"O:virNodeGetInfo", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetInfo(conn, &info); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(8)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_constcharPtrWrap(&info.model[0]), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_ulongWrap(info.memory >> 10), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_intWrap(info.cpus), error); VIR_PY_LIST_SET_GOTO(py_retval, 3, libvirt_intWrap(info.mhz), error); VIR_PY_LIST_SET_GOTO(py_retval, 4, libvirt_intWrap(info.nodes), error); VIR_PY_LIST_SET_GOTO(py_retval, 5, libvirt_intWrap(info.sockets), error); VIR_PY_LIST_SET_GOTO(py_retval, 6, libvirt_intWrap(info.cores), error); VIR_PY_LIST_SET_GOTO(py_retval, 7, libvirt_intWrap(info.threads), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virNodeGetSecurityModel(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virConnectPtr conn; PyObject *pyobj_conn; virSecurityModel model; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetSecurityModel", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetSecurityModel(conn, &model); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(2)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_constcharPtrWrap(&model.model[0]), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_constcharPtrWrap(&model.doi[0]), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virDomainGetSecurityLabel(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virDomainPtr dom; PyObject *pyobj_dom; virSecurityLabel label; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetSecurityLabel", &pyobj_dom)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSecurityLabel(dom, &label); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(2)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_constcharPtrWrap(&label.label[0]), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_boolWrap(label.enforcing), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } #if LIBVIR_CHECK_VERSION(0, 10, 0) static PyObject * libvirt_virDomainGetSecurityLabelList(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virDomainPtr dom; PyObject *pyobj_dom; virSecurityLabel *labels = NULL; ssize_t i; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetSecurityLabelList", &pyobj_dom)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetSecurityLabelList(dom, &labels); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(0))) goto error; for (i = 0 ; i < c_retval ; i++) { PyObject *entry; if (!(entry = PyList_New(2))) goto error; VIR_PY_LIST_APPEND_GOTO(py_retval, entry, error); VIR_PY_LIST_SET_GOTO(entry, 0, libvirt_constcharPtrWrap(&labels[i].label[0]), error); VIR_PY_LIST_SET_GOTO(entry, 1, libvirt_boolWrap(labels[i].enforcing), error); } cleanup: VIR_FREE(labels); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ static PyObject * libvirt_virDomainGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned char uuid[VIR_UUID_BUFLEN]; virDomainPtr domain; PyObject *pyobj_domain; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetUUID", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (domain == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetUUID(domain, &uuid[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_charPtrSizeWrap((char *) &uuid[0], VIR_UUID_BUFLEN); } static PyObject * libvirt_virDomainGetUUIDString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virDomainPtr dom; PyObject *pyobj_dom; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetUUIDString", &pyobj_dom)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); if (dom == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetUUIDString(dom, &uuidstr[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_constcharPtrWrap((char *) &uuidstr[0]); } static PyObject * libvirt_virDomainLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr c_retval; virConnectPtr conn; PyObject *pyobj_conn; unsigned char * uuid; Py_ssize_t len; if (!PyArg_ParseTuple(args, (char *)"Oz#:virDomainLookupByUUID", &pyobj_conn, &uuid, &len)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if ((uuid == NULL) || (len != VIR_UUID_BUFLEN)) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainLookupByUUID(conn, uuid); LIBVIRT_END_ALLOW_THREADS; return libvirt_virDomainPtrWrap((virDomainPtr) c_retval); } static PyObject * libvirt_virConnectListNetworks(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListNetworks", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfNetworks(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListNetworks(conn, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } static PyObject * libvirt_virConnectListDefinedNetworks(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListDefinedNetworks", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedNetworks(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedNetworks(conn, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virConnectListAllNetworks(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virNetworkPtr *nets = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllNetworks", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllNetworks(conn, &nets, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virNetworkPtrWrap(nets[i]), error); nets[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (nets[i]) virNetworkFree(nets[i]); VIR_FREE(nets); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ static PyObject * libvirt_virNetworkGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned char uuid[VIR_UUID_BUFLEN]; virNetworkPtr domain; PyObject *pyobj_domain; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virNetworkGetUUID", &pyobj_domain)) return NULL; domain = (virNetworkPtr) PyvirNetwork_Get(pyobj_domain); if (domain == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkGetUUID(domain, &uuid[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_charPtrSizeWrap((char *) &uuid[0], VIR_UUID_BUFLEN); } static PyObject * libvirt_virNetworkGetUUIDString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virNetworkPtr net; PyObject *pyobj_net; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virNetworkGetUUIDString", &pyobj_net)) return NULL; net = (virNetworkPtr) PyvirNetwork_Get(pyobj_net); if (net == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkGetUUIDString(net, &uuidstr[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_constcharPtrWrap((char *) &uuidstr[0]); } static PyObject * libvirt_virNetworkLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virNetworkPtr c_retval; virConnectPtr conn; PyObject *pyobj_conn; unsigned char * uuid; Py_ssize_t len; if (!PyArg_ParseTuple(args, (char *)"Oz#:virNetworkLookupByUUID", &pyobj_conn, &uuid, &len)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if ((uuid == NULL) || (len != VIR_UUID_BUFLEN)) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkLookupByUUID(conn, uuid); LIBVIRT_END_ALLOW_THREADS; return libvirt_virNetworkPtrWrap((virNetworkPtr) c_retval); } static PyObject * libvirt_virDomainGetAutostart(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval, autostart; virDomainPtr domain; PyObject *pyobj_domain; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetAutostart", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetAutostart(domain, &autostart); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_INT_FAIL; return libvirt_intWrap(autostart); } static PyObject * libvirt_virNetworkGetAutostart(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval, autostart; virNetworkPtr network; PyObject *pyobj_network; if (!PyArg_ParseTuple(args, (char *)"O:virNetworkGetAutostart", &pyobj_network)) return NULL; network = (virNetworkPtr) PyvirNetwork_Get(pyobj_network); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkGetAutostart(network, &autostart); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_INT_FAIL; return libvirt_intWrap(autostart); } #if LIBVIR_CHECK_VERSION(7, 8, 0) static PyObject * libvirt_virNodeDeviceGetAutostart(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval, autostart; virNodeDevicePtr dev; PyObject *pyobj_dev; if (!PyArg_ParseTuple(args, (char *)"O:virNodeDeviceGetAutostart", &pyobj_dev)) return NULL; dev = (virNodeDevicePtr) PyvirNodeDevice_Get(pyobj_dev); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceGetAutostart(dev, &autostart); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_INT_FAIL; return libvirt_intWrap(autostart); } #endif /* LIBVIR_CHECK_VERSION(7, 8, 0) */ static PyObject * libvirt_virNodeGetCellsFreeMemory(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; PyObject *pyobj_conn; int startCell, maxCells, c_retval; ssize_t i; virConnectPtr conn; unsigned long long *freeMems; if (!PyArg_ParseTuple(args, (char *)"Oii:virNodeGetCellsFreeMemory", &pyobj_conn, &startCell, &maxCells)) return NULL; if ((startCell < 0) || (maxCells <= 0) || (startCell + maxCells > 10000)) return VIR_PY_NONE; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if (VIR_ALLOC_N(freeMems, maxCells) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetCellsFreeMemory(conn, freeMems, startCell, maxCells); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_ulonglongWrap(freeMems[i]), error); cleanup: VIR_FREE(freeMems); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } static PyObject * libvirt_virNodeGetCPUStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *ret = NULL; PyObject *key = NULL; PyObject *val = NULL; PyObject *pyobj_conn; virConnectPtr conn; unsigned int flags; int cpuNum, c_retval; ssize_t i; int nparams = 0; virNodeCPUStatsPtr stats = NULL; if (!PyArg_ParseTuple(args, (char *)"OiI:virNodeGetCPUStats", &pyobj_conn, &cpuNum, &flags)) return ret; conn = (virConnectPtr)(PyvirConnect_Get(pyobj_conn)); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetCPUStats(conn, cpuNum, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (nparams) { if (VIR_ALLOC_N(stats, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetCPUStats(conn, cpuNum, stats, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { VIR_FREE(stats); return VIR_PY_NONE; } } if (!(ret = PyDict_New())) goto error; for (i = 0; i < nparams; i++) { key = libvirt_constcharPtrWrap(stats[i].field); val = libvirt_ulonglongWrap(stats[i].value); VIR_PY_DICT_SET_GOTO(ret, key, val, error); } cleanup: VIR_FREE(stats); return ret; error: Py_CLEAR(ret); goto cleanup; } static PyObject * libvirt_virNodeGetMemoryStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *ret = NULL; PyObject *key = NULL; PyObject *val = NULL; PyObject *pyobj_conn; virConnectPtr conn; unsigned int flags; int cellNum, c_retval; ssize_t i; int nparams = 0; virNodeMemoryStatsPtr stats = NULL; if (!PyArg_ParseTuple(args, (char *)"OiI:virNodeGetMemoryStats", &pyobj_conn, &cellNum, &flags)) return NULL; conn = (virConnectPtr)(PyvirConnect_Get(pyobj_conn)); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetMemoryStats(conn, cellNum, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (nparams) { if (VIR_ALLOC_N(stats, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetMemoryStats(conn, cellNum, stats, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { VIR_FREE(stats); return VIR_PY_NONE; } } if (!(ret = PyDict_New())) goto error; for (i = 0; i < nparams; i++) { key = libvirt_constcharPtrWrap(stats[i].field); val = libvirt_ulonglongWrap(stats[i].value); VIR_PY_DICT_SET_GOTO(ret, key, val, error); } cleanup: VIR_FREE(stats); return ret; error: Py_CLEAR(ret); goto cleanup; } static PyObject * libvirt_virConnectListStoragePools(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListStoragePools", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfStoragePools(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListStoragePools(conn, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } static PyObject * libvirt_virConnectListDefinedStoragePools(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListDefinedStoragePools", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedStoragePools(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedStoragePools(conn, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) { for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); } cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virConnectListAllStoragePools(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virStoragePoolPtr *pools = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllStoragePools", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllStoragePools(conn, &pools, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virStoragePoolPtrWrap(pools[i]), error); /* python steals the pointer */ pools[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (pools[i]) virStoragePoolFree(pools[i]); VIR_FREE(pools); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ static PyObject * libvirt_virStoragePoolListVolumes(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virStoragePoolPtr pool; PyObject *pyobj_pool; if (!PyArg_ParseTuple(args, (char *)"O:virStoragePoolListVolumes", &pyobj_pool)) return NULL; pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolNumOfVolumes(pool); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolListVolumes(pool, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virStoragePoolListAllVolumes(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; virStoragePoolPtr pool; virStorageVolPtr *vols = NULL; int c_retval = 0; ssize_t i; unsigned int flags; PyObject *pyobj_pool; if (!PyArg_ParseTuple(args, (char *)"OI:virStoragePoolListAllVolumes", &pyobj_pool, &flags)) return NULL; pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolListAllVolumes(pool, &vols, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virStorageVolPtrWrap(vols[i]), error); /* python steals the pointer */ vols[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (vols[i]) virStorageVolFree(vols[i]); VIR_FREE(vols); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ static PyObject * libvirt_virStoragePoolGetAutostart(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval, autostart; virStoragePoolPtr pool; PyObject *pyobj_pool; if (!PyArg_ParseTuple(args, (char *)"O:virStoragePoolGetAutostart", &pyobj_pool)) return NULL; pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolGetAutostart(pool, &autostart); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_INT_FAIL; return libvirt_intWrap(autostart); } static PyObject * libvirt_virStoragePoolGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virStoragePoolPtr pool; PyObject *pyobj_pool; virStoragePoolInfo info; if (!PyArg_ParseTuple(args, (char *)"O:virStoragePoolGetInfo", &pyobj_pool)) return NULL; pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolGetInfo(pool, &info); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(4)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_intWrap(info.state), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_ulonglongWrap(info.capacity), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_ulonglongWrap(info.allocation), error); VIR_PY_LIST_SET_GOTO(py_retval, 3, libvirt_ulonglongWrap(info.available), error); return py_retval; error: Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virStorageVolGetInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virStorageVolPtr pool; PyObject *pyobj_pool; virStorageVolInfo info; if (!PyArg_ParseTuple(args, (char *)"O:virStorageVolGetInfo", &pyobj_pool)) return NULL; pool = (virStorageVolPtr) PyvirStorageVol_Get(pyobj_pool); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStorageVolGetInfo(pool, &info); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(3)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_intWrap(info.type), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_ulonglongWrap(info.capacity), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_ulonglongWrap(info.allocation), error); return py_retval; error: Py_DECREF(py_retval); return NULL; } #if LIBVIR_CHECK_VERSION(3, 0, 0) static PyObject * libvirt_virStorageVolGetInfoFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virStorageVolPtr pool; PyObject *pyobj_pool; virStorageVolInfo info; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virStorageVolGetInfoFlags", &pyobj_pool, &flags)) return NULL; pool = (virStorageVolPtr) PyvirStorageVol_Get(pyobj_pool); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStorageVolGetInfoFlags(pool, &info, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(3)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_intWrap(info.type), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_ulonglongWrap(info.capacity), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_ulonglongWrap(info.allocation), error); return py_retval; error: Py_DECREF(py_retval); return NULL; } #endif static PyObject * libvirt_virStoragePoolGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned char uuid[VIR_UUID_BUFLEN]; virStoragePoolPtr pool; PyObject *pyobj_pool; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virStoragePoolGetUUID", &pyobj_pool)) return NULL; pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool); if (pool == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolGetUUID(pool, &uuid[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_charPtrSizeWrap((char *) &uuid[0], VIR_UUID_BUFLEN); } static PyObject * libvirt_virStoragePoolGetUUIDString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virStoragePoolPtr pool; PyObject *pyobj_pool; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virStoragePoolGetUUIDString", &pyobj_pool)) return NULL; pool = (virStoragePoolPtr) PyvirStoragePool_Get(pyobj_pool); if (pool == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolGetUUIDString(pool, &uuidstr[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_constcharPtrWrap((char *) &uuidstr[0]); } static PyObject * libvirt_virStoragePoolLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virStoragePoolPtr c_retval; virConnectPtr conn; PyObject *pyobj_conn; unsigned char * uuid; Py_ssize_t len; if (!PyArg_ParseTuple(args, (char *)"Oz#:virStoragePoolLookupByUUID", &pyobj_conn, &uuid, &len)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if ((uuid == NULL) || (len != VIR_UUID_BUFLEN)) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virStoragePoolLookupByUUID(conn, uuid); LIBVIRT_END_ALLOW_THREADS; return libvirt_virStoragePoolPtrWrap((virStoragePoolPtr) c_retval); } static PyObject * libvirt_virNodeListDevices(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; char *cap; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OzI:virNodeListDevices", &pyobj_conn, &cap, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeNumOfDevices(conn, cap, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeListDevices(conn, cap, names, c_retval, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virConnectListAllNodeDevices(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virNodeDevicePtr *devices = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllNodeDevices", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllNodeDevices(conn, &devices, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virNodeDevicePtrWrap(devices[i]), error); /* python steals the pointer */ devices[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (devices[i]) virNodeDeviceFree(devices[i]); VIR_FREE(devices); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ static PyObject * libvirt_virNodeDeviceListCaps(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virNodeDevicePtr dev; PyObject *pyobj_dev; if (!PyArg_ParseTuple(args, (char *)"O:virNodeDeviceListCaps", &pyobj_dev)) return NULL; dev = (virNodeDevicePtr) PyvirNodeDevice_Get(pyobj_dev); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceNumOfCaps(dev); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeDeviceListCaps(dev, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } static PyObject * libvirt_virSecretGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned char uuid[VIR_UUID_BUFLEN]; virSecretPtr secret; PyObject *pyobj_secret; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virSecretGetUUID", &pyobj_secret)) return NULL; secret = (virSecretPtr) PyvirSecret_Get(pyobj_secret); if (secret == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virSecretGetUUID(secret, &uuid[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_charPtrSizeWrap((char *) &uuid[0], VIR_UUID_BUFLEN); } static PyObject * libvirt_virSecretGetUUIDString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virSecretPtr dom; PyObject *pyobj_dom; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virSecretGetUUIDString", &pyobj_dom)) return NULL; dom = (virSecretPtr) PyvirSecret_Get(pyobj_dom); if (dom == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virSecretGetUUIDString(dom, &uuidstr[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_constcharPtrWrap((char *) &uuidstr[0]); } static PyObject * libvirt_virSecretLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virSecretPtr c_retval; virConnectPtr conn; PyObject *pyobj_conn; unsigned char * uuid; Py_ssize_t len; if (!PyArg_ParseTuple(args, (char *)"Oz#:virSecretLookupByUUID", &pyobj_conn, &uuid, &len)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if ((uuid == NULL) || (len != VIR_UUID_BUFLEN)) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virSecretLookupByUUID(conn, uuid); LIBVIRT_END_ALLOW_THREADS; return libvirt_virSecretPtrWrap((virSecretPtr) c_retval); } static PyObject * libvirt_virConnectListSecrets(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **uuids = NULL; virConnectPtr conn; int c_retval; ssize_t i; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListSecrets", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfSecrets(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(uuids, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListSecrets(conn, uuids, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (uuids) { for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(uuids[i]), error); } cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(uuids[i]); VIR_FREE(uuids); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virConnectListAllSecrets(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virSecretPtr *secrets = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllSecrets", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllSecrets(conn, &secrets, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virSecretPtrWrap(secrets[i]), error); /* python steals the pointer */ secrets[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (secrets[i]) virSecretFree(secrets[i]); VIR_FREE(secrets); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ static PyObject * libvirt_virSecretGetValue(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; unsigned char *c_retval; size_t size; virSecretPtr secret; PyObject *pyobj_secret; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virSecretGetValue", &pyobj_secret, &flags)) return NULL; secret = (virSecretPtr) PyvirSecret_Get(pyobj_secret); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virSecretGetValue(secret, &size, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval == NULL) return VIR_PY_NONE; py_retval = libvirt_charPtrSizeWrap((char*)c_retval, size); VIR_FREE(c_retval); return py_retval; } static PyObject * libvirt_virSecretSetValue(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval; virSecretPtr secret; PyObject *pyobj_secret; const char *value; Py_ssize_t size; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"Oz#I:virSecretSetValue", &pyobj_secret, &value, &size, &flags)) return NULL; secret = (virSecretPtr) PyvirSecret_Get(pyobj_secret); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virSecretSetValue(secret, (const unsigned char *)value, (size_t) size, flags); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(c_retval); } static PyObject * libvirt_virNWFilterGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned char uuid[VIR_UUID_BUFLEN]; virNWFilterPtr nwfilter; PyObject *pyobj_nwfilter; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virNWFilterGetUUID", &pyobj_nwfilter)) return NULL; nwfilter = (virNWFilterPtr) PyvirNWFilter_Get(pyobj_nwfilter); if (nwfilter == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNWFilterGetUUID(nwfilter, &uuid[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_charPtrSizeWrap((char *) &uuid[0], VIR_UUID_BUFLEN); } static PyObject * libvirt_virNWFilterGetUUIDString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virNWFilterPtr nwfilter; PyObject *pyobj_nwfilter; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virNWFilterGetUUIDString", &pyobj_nwfilter)) return NULL; nwfilter = (virNWFilterPtr) PyvirNWFilter_Get(pyobj_nwfilter); if (nwfilter == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNWFilterGetUUIDString(nwfilter, &uuidstr[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_constcharPtrWrap((char *) &uuidstr[0]); } static PyObject * libvirt_virNWFilterLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virNWFilterPtr c_retval; virConnectPtr conn; PyObject *pyobj_conn; unsigned char * uuid; Py_ssize_t len; if (!PyArg_ParseTuple(args, (char *)"Oz#:virNWFilterLookupByUUID", &pyobj_conn, &uuid, &len)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if ((uuid == NULL) || (len != VIR_UUID_BUFLEN)) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNWFilterLookupByUUID(conn, uuid); LIBVIRT_END_ALLOW_THREADS; return libvirt_virNWFilterPtrWrap((virNWFilterPtr) c_retval); } static PyObject * libvirt_virConnectListNWFilters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **uuids = NULL; virConnectPtr conn; int c_retval; ssize_t i; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListNWFilters", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfNWFilters(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(uuids, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListNWFilters(conn, uuids, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (uuids) for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(uuids[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(uuids[i]); VIR_FREE(uuids); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virConnectListAllNWFilters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virNWFilterPtr *filters = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllNWFilters", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllNWFilters(conn, &filters, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virNWFilterPtrWrap(filters[i]), error); /* python steals the pointer */ filters[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (filters[i]) virNWFilterFree(filters[i]); VIR_FREE(filters); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ #if LIBVIR_CHECK_VERSION(4, 5, 0) static PyObject * libvirt_virConnectListAllNWFilterBindings(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virNWFilterBindingPtr *bindings = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllNWFilterBindings", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllNWFilterBindings(conn, &bindings, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virNWFilterBindingPtrWrap(bindings[i]), error); /* python steals the pointer */ bindings[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (bindings[i]) virNWFilterBindingFree(bindings[i]); VIR_FREE(bindings); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(4, 5, 0) */ static PyObject * libvirt_virConnectListInterfaces(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListInterfaces", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfInterfaces(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListInterfaces(conn, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } static PyObject * libvirt_virConnectListDefinedInterfaces(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char **names = NULL; int c_retval; ssize_t i; virConnectPtr conn; PyObject *pyobj_conn; if (!PyArg_ParseTuple(args, (char *)"O:virConnectListDefinedInterfaces", &pyobj_conn)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectNumOfDefinedInterfaces(conn); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (c_retval) { if (VIR_ALLOC_N(names, c_retval) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListDefinedInterfaces(conn, names, c_retval); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if ((py_retval = PyList_New(c_retval)) == NULL) goto cleanup; if (names) { for (i = 0; i < c_retval; i++) VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_constcharPtrWrap(names[i]), error); } cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) VIR_FREE(names[i]); VIR_FREE(names); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virConnectListAllInterfaces(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virConnectPtr conn; virInterfacePtr *ifaces = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virConnectListAllInterfaces", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virConnectListAllInterfaces(conn, &ifaces, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virInterfacePtrWrap(ifaces[i]), error); /* python steals the pointer */ ifaces[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (ifaces[i]) virInterfaceFree(ifaces[i]); VIR_FREE(ifaces); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ static PyObject * libvirt_virConnectBaselineCPU(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *list; virConnectPtr conn; unsigned int flags; char **xmlcpus = NULL; int ncpus = 0; char *base_cpu; PyObject *pybase_cpu; ssize_t i, j; if (!PyArg_ParseTuple(args, (char *)"OOI:virConnectBaselineCPU", &pyobj_conn, &list, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if (PyList_Check(list)) { ncpus = PyList_Size(list); if (VIR_ALLOC_N(xmlcpus, ncpus) < 0) return PyErr_NoMemory(); for (i = 0; i < ncpus; i++) { if (libvirt_charPtrUnwrap(PyList_GetItem(list, i), &(xmlcpus[i])) < 0) { for (j = 0 ; j < i ; j++) VIR_FREE(xmlcpus[j]); VIR_FREE(xmlcpus); return NULL; } } } LIBVIRT_BEGIN_ALLOW_THREADS; base_cpu = virConnectBaselineCPU(conn, (const char **)xmlcpus, ncpus, flags); LIBVIRT_END_ALLOW_THREADS; for (i = 0 ; i < ncpus ; i++) VIR_FREE(xmlcpus[i]); VIR_FREE(xmlcpus); if (base_cpu == NULL) return VIR_PY_NONE; pybase_cpu = libvirt_constcharPtrWrap(base_cpu); VIR_FREE(base_cpu); return pybase_cpu; } static PyObject * libvirt_virDomainGetJobInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; virDomainJobInfo info; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetJobInfo", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetJobInfo(domain, &info); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if ((py_retval = PyList_New(12)) == NULL) return NULL; VIR_PY_LIST_SET_GOTO(py_retval, 0, libvirt_intWrap(info.type), error); VIR_PY_LIST_SET_GOTO(py_retval, 1, libvirt_ulonglongWrap(info.timeElapsed), error); VIR_PY_LIST_SET_GOTO(py_retval, 2, libvirt_ulonglongWrap(info.timeRemaining), error); VIR_PY_LIST_SET_GOTO(py_retval, 3, libvirt_ulonglongWrap(info.dataTotal), error); VIR_PY_LIST_SET_GOTO(py_retval, 4, libvirt_ulonglongWrap(info.dataProcessed), error); VIR_PY_LIST_SET_GOTO(py_retval, 5, libvirt_ulonglongWrap(info.dataRemaining), error); VIR_PY_LIST_SET_GOTO(py_retval, 6, libvirt_ulonglongWrap(info.memTotal), error); VIR_PY_LIST_SET_GOTO(py_retval, 7, libvirt_ulonglongWrap(info.memProcessed), error); VIR_PY_LIST_SET_GOTO(py_retval, 8, libvirt_ulonglongWrap(info.memRemaining), error); VIR_PY_LIST_SET_GOTO(py_retval, 9, libvirt_ulonglongWrap(info.fileTotal), error); VIR_PY_LIST_SET_GOTO(py_retval, 10, libvirt_ulonglongWrap(info.fileProcessed), error); VIR_PY_LIST_SET_GOTO(py_retval, 11, libvirt_ulonglongWrap(info.fileRemaining), error); return py_retval; error: Py_DECREF(py_retval); return NULL; } #if LIBVIR_CHECK_VERSION(1, 0, 3) static PyObject * libvirt_virDomainGetJobStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; virDomainPtr domain; unsigned int flags; virTypedParameterPtr params = NULL; int nparams = 0; int type; PyObject *dict = NULL; int rc; if (!PyArg_ParseTuple(args, (char *) "OI:virDomainGetJobStats", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; rc = virDomainGetJobStats(domain, &type, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (rc < 0) return VIR_PY_NONE; if (!(dict = getPyVirTypedParameter(params, nparams))) goto cleanup; VIR_PY_DICT_SET_GOTO(dict, libvirt_constcharPtrWrap("type"), libvirt_intWrap(type), error); cleanup: virTypedParamsFree(params, nparams); return dict; error: Py_CLEAR(dict); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(1, 0, 3) */ static PyObject * libvirt_virDomainGetBlockJobInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; const char *path; unsigned int flags; virDomainBlockJobInfo info; int c_ret; PyObject *dict; if (!PyArg_ParseTuple(args, (char *)"OzI:virDomainGetBlockJobInfo", &pyobj_domain, &path, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_ret = virDomainGetBlockJobInfo(domain, path, &info, flags); LIBVIRT_END_ALLOW_THREADS; if (c_ret < 0) return VIR_PY_NONE; if ((dict = PyDict_New()) == NULL) return NULL; if (c_ret == 0) return dict; VIR_PY_DICT_SET_GOTO(dict, libvirt_constcharPtrWrap("type"), libvirt_intWrap(info.type), error); VIR_PY_DICT_SET_GOTO(dict, libvirt_constcharPtrWrap("bandwidth"), libvirt_ulongWrap(info.bandwidth), error); VIR_PY_DICT_SET_GOTO(dict, libvirt_constcharPtrWrap("cur"), libvirt_ulonglongWrap(info.cur), error); VIR_PY_DICT_SET_GOTO(dict, libvirt_constcharPtrWrap("end"), libvirt_ulonglongWrap(info.end), error); return dict; error: Py_DECREF(dict); return NULL; } static virPyTypedParamsHint virPyDomainSetBlockIoTuneParams[] = { { VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC, VIR_TYPED_PARAM_ULLONG }, #if LIBVIR_CHECK_VERSION(1, 2, 11) { VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC, VIR_TYPED_PARAM_ULLONG }, #endif /* LIBVIR_CHECK_VERSION(1, 2, 11) */ #if LIBVIR_CHECK_VERSION(2, 4, 0) { VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX_LENGTH, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_LENGTH, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX_LENGTH, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_LENGTH, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_LENGTH, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_LENGTH, VIR_TYPED_PARAM_ULLONG }, #endif /* LIBVIR_CHECK_VERSION(2, 4, 0) */ #if LIBVIR_CHECK_VERSION(3, 0, 0) { VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME, VIR_TYPED_PARAM_STRING }, #endif /* LIBVIR_CHECK_VERSION(3, 0, 0) */ }; static PyObject * libvirt_virDomainSetBlockIoTune(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain = NULL; PyObject *pyobj_dict = NULL; virTypedParameterPtr params = NULL; int nparams = 0; int c_retval; const char *disk; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OzOI:virDomainSetBlockIoTune", &pyobj_domain, &disk, &pyobj_dict, &flags)) return NULL; if (PyDict_Check(pyobj_dict)) { if (virPyDictToTypedParams(pyobj_dict, ¶ms, &nparams, virPyDomainSetBlockIoTuneParams, VIR_N_ELEMENTS(virPyDomainSetBlockIoTuneParams)) < 0) { return NULL; } } else { PyErr_Format(PyExc_TypeError, "Need non-empty dictionary to set attributes"); return NULL; } domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSetBlockIoTune(domain, disk, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(c_retval); } static PyObject * libvirt_virDomainGetBlockIoTune(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *ret = NULL; int i_retval; int nparams = 0; const char *disk; unsigned int flags; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"OzI:virDomainGetBlockIoTune", &pyobj_domain, &disk, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetBlockIoTune(domain, disk, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetBlockIoTune(domain, disk, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virDomainGetDiskErrors(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = VIR_PY_NONE; virDomainPtr domain; PyObject *pyobj_domain; unsigned int flags; virDomainDiskErrorPtr disks = NULL; unsigned int ndisks; int count; ssize_t i; if (!PyArg_ParseTuple(args, (char *) "OI:virDomainGetDiskErrors", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; count = virDomainGetDiskErrors(domain, NULL, 0, 0); LIBVIRT_END_ALLOW_THREADS; if (count < 0) return VIR_PY_NONE; ndisks = count; if (ndisks) { if (VIR_ALLOC_N(disks, ndisks) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; count = virDomainGetDiskErrors(domain, disks, ndisks, 0); LIBVIRT_END_ALLOW_THREADS; if (count < 0) { py_retval = VIR_PY_NONE; goto cleanup; } } if (!(py_retval = PyDict_New())) goto cleanup; for (i = 0; i < count; i++) { VIR_PY_DICT_SET_GOTO(py_retval, libvirt_constcharPtrWrap(disks[i].disk), libvirt_intWrap(disks[i].error), error); } cleanup: if (count > 0) for (i = 0; i < count; i++) VIR_FREE(disks[i].disk); VIR_FREE(disks); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #if LIBVIR_CHECK_VERSION(1, 2, 14) static PyObject * libvirt_virDomainInterfaceAddresses(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = VIR_PY_NONE; PyObject *pyobj_domain; virDomainPtr domain; virDomainInterfacePtr *ifaces = NULL; unsigned int source; unsigned int flags; int ifaces_count = 0; ssize_t i; if (!PyArg_ParseTuple(args, (char *) "OII:virDomainInterfaceAddresses", &pyobj_domain, &source, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; ifaces_count = virDomainInterfaceAddresses(domain, &ifaces, source, flags); LIBVIRT_END_ALLOW_THREADS; if (ifaces_count < 0) goto cleanup; if (!(py_retval = PyDict_New())) goto error; for (i = 0; i < ifaces_count; i++) { virDomainInterfacePtr iface = ifaces[i]; PyObject *py_addrs = NULL; PyObject *py_iface = NULL; size_t j; if (!(py_iface = PyDict_New())) goto error; VIR_PY_DICT_SET_GOTO(py_retval, libvirt_charPtrWrap(iface->name), py_iface, error); if (iface->naddrs) { if (!(py_addrs = PyList_New(iface->naddrs))) { goto error; } } else { py_addrs = VIR_PY_NONE; } VIR_PY_DICT_SET_GOTO(py_iface, libvirt_constcharPtrWrap("addrs"), py_addrs, error); VIR_PY_DICT_SET_GOTO(py_iface, libvirt_constcharPtrWrap("hwaddr"), libvirt_constcharPtrWrap(iface->hwaddr), error); for (j = 0; j < iface->naddrs; j++) { virDomainIPAddressPtr addr = &(iface->addrs[j]); PyObject *py_addr = PyDict_New(); if (!py_addr) goto error; VIR_PY_LIST_SET_GOTO(py_addrs, j, py_addr, error); VIR_PY_DICT_SET_GOTO(py_addr, libvirt_constcharPtrWrap("addr"), libvirt_constcharPtrWrap(addr->addr), error); VIR_PY_DICT_SET_GOTO(py_addr, libvirt_constcharPtrWrap("prefix"), libvirt_uintWrap(addr->prefix), error); VIR_PY_DICT_SET_GOTO(py_addr, libvirt_constcharPtrWrap("type"), libvirt_intWrap(addr->type), error); } } cleanup: if (ifaces && ifaces_count > 0) { for (i = 0; i < ifaces_count; i++) { virDomainInterfaceFree(ifaces[i]); } } VIR_FREE(ifaces); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(1, 2, 14) */ /******************************************* * Helper functions to avoid importing modules * for every callback *******************************************/ static PyObject *libvirt_module = NULL; static PyObject *libvirt_dict = NULL; static PyObject * getLibvirtModuleObject(void) { if (libvirt_module) return libvirt_module; // PyImport_ImportModule returns a new reference /* Bogus (char *) cast for RHEL-5 python API brokenness */ libvirt_module = PyImport_ImportModule((char *)"libvirt"); if (!libvirt_module) { DEBUG("%s Error importing libvirt module\n", __FUNCTION__); PyErr_Print(); return NULL; } return libvirt_module; } static PyObject * getLibvirtDictObject(void) { if (libvirt_dict) return libvirt_dict; // PyModule_GetDict returns a borrowed reference libvirt_dict = PyModule_GetDict(getLibvirtModuleObject()); if (!libvirt_dict) { DEBUG("%s Error importing libvirt dictionary\n", __FUNCTION__); PyErr_Print(); return NULL; } Py_INCREF(libvirt_dict); return libvirt_dict; } static PyObject * libvirt_lookupPythonFunc(const char *funcname) { PyObject *python_cb; /* Lookup the python callback */ python_cb = PyDict_GetItemString(getLibvirtDictObject(), funcname); if (!python_cb) { DEBUG("%s: Error finding %s\n", __FUNCTION__, funcname); PyErr_Print(); PyErr_Clear(); return NULL; } if (!PyCallable_Check(python_cb)) { DEBUG("%s: %s is not callable\n", __FUNCTION__, funcname); return NULL; } return python_cb; } /******************************************* * Domain Events *******************************************/ static int libvirt_virConnectDomainEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int event, int detail, void *opaque) { PyObject *pyobj_ret = NULL; PyObject *pyobj_conn = (PyObject*)opaque; PyObject *pyobj_dom; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventCallbacks", (char*)"Oii", pyobj_dom, event, detail); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static PyObject * libvirt_virConnectDomainEventRegister(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) { PyObject *pyobj_conn; /* virConnectPtr */ PyObject *pyobj_conn_inst; /* virConnect Python object */ virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "OO:virConnectDomainEventRegister", &pyobj_conn, &pyobj_conn_inst)) return NULL; DEBUG("libvirt_virConnectDomainEventRegister(%p %p) called\n", pyobj_conn, pyobj_conn_inst); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); Py_INCREF(pyobj_conn_inst); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectDomainEventRegister(conn, libvirt_virConnectDomainEventCallback, pyobj_conn_inst, NULL); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(ret); } static PyObject * libvirt_virConnectDomainEventDeregister(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *pyobj_conn_inst; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "OO:virConnectDomainEventDeregister", &pyobj_conn, &pyobj_conn_inst)) return NULL; DEBUG("libvirt_virConnectDomainEventDeregister(%p) called\n", pyobj_conn); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectDomainEventDeregister(conn, libvirt_virConnectDomainEventCallback); LIBVIRT_END_ALLOW_THREADS; Py_DECREF(pyobj_conn_inst); return libvirt_intWrap(ret); } /******************************************* * Event Impl *******************************************/ static PyObject *addHandleObj; static PyObject *updateHandleObj; static PyObject *removeHandleObj; static PyObject *addTimeoutObj; static PyObject *updateTimeoutObj; static PyObject *removeTimeoutObj; static int libvirt_virEventAddHandleFunc(int fd, int event, virEventHandleCallback cb, void *opaque, virFreeCallback ff) { PyObject *result; PyObject *python_cb = NULL; PyObject *cb_args = NULL; PyObject *pyobj_args = NULL; int retval = -1; LIBVIRT_ENSURE_THREAD_STATE; if ((pyobj_args = PyTuple_New(4)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 0, libvirt_intWrap(fd), cleanup); VIR_PY_TUPLE_SET_GOTO(pyobj_args, 1, libvirt_intWrap(event), cleanup); /* Lookup the python callback */ python_cb = libvirt_lookupPythonFunc("_eventInvokeHandleCallback"); if (!python_cb) { goto cleanup; } Py_INCREF(python_cb); VIR_PY_TUPLE_SET_GOTO(pyobj_args, 2, python_cb, cleanup); if ((cb_args = PyTuple_New(3)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 3, cb_args, cleanup); /* If changing contents of the opaque object, please also change * virEventInvokeFreeCallback() in libvirt-override.py */ VIR_PY_TUPLE_SET_GOTO(cb_args, 0, libvirt_virEventHandleCallbackWrap(cb), cleanup); VIR_PY_TUPLE_SET_GOTO(cb_args, 1, libvirt_virVoidPtrWrap(opaque), cleanup); VIR_PY_TUPLE_SET_GOTO(cb_args, 2, libvirt_virFreeCallbackWrap(ff), cleanup); result = PyObject_Call(addHandleObj, pyobj_args, NULL); if (!result) { PyErr_Print(); PyErr_Clear(); } else { libvirt_intUnwrap(result, &retval); } Py_XDECREF(result); cleanup: Py_XDECREF(pyobj_args); LIBVIRT_RELEASE_THREAD_STATE; return retval; } static void libvirt_virEventUpdateHandleFunc(int watch, int event) { PyObject *result = NULL; PyObject *pyobj_args; LIBVIRT_ENSURE_THREAD_STATE; if ((pyobj_args = PyTuple_New(2)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 0, libvirt_intWrap(watch), cleanup); VIR_PY_TUPLE_SET_GOTO(pyobj_args, 1, libvirt_intWrap(event), cleanup); result = PyObject_Call(updateHandleObj, pyobj_args, NULL); if (!result) { PyErr_Print(); PyErr_Clear(); } cleanup: Py_XDECREF(result); Py_XDECREF(pyobj_args); LIBVIRT_RELEASE_THREAD_STATE; } static int libvirt_virEventRemoveHandleFunc(int watch) { PyObject *result = NULL; PyObject *pyobj_args; int retval = -1; LIBVIRT_ENSURE_THREAD_STATE; if ((pyobj_args = PyTuple_New(1)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 0, libvirt_intWrap(watch), cleanup); result = PyObject_Call(removeHandleObj, pyobj_args, NULL); if (result) { retval = 0; } else { PyErr_Print(); PyErr_Clear(); } cleanup: Py_XDECREF(result); Py_XDECREF(pyobj_args); LIBVIRT_RELEASE_THREAD_STATE; return retval; } static int libvirt_virEventAddTimeoutFunc(int timeout, virEventTimeoutCallback cb, void *opaque, virFreeCallback ff) { PyObject *result = NULL; PyObject *python_cb = NULL; PyObject *cb_args = NULL; PyObject *pyobj_args = NULL; int retval = -1; LIBVIRT_ENSURE_THREAD_STATE; if ((pyobj_args = PyTuple_New(3)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 0, libvirt_intWrap(timeout), cleanup); /* Lookup the python callback */ python_cb = libvirt_lookupPythonFunc("_eventInvokeTimeoutCallback"); if (!python_cb) { goto cleanup; } Py_INCREF(python_cb); VIR_PY_TUPLE_SET_GOTO(pyobj_args, 1, python_cb, cleanup); if ((cb_args = PyTuple_New(3)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 2, cb_args, cleanup); /* If changing contents of the opaque object, please also change * virEventInvokeFreeCallback() in libvirt-override.py */ VIR_PY_TUPLE_SET_GOTO(cb_args, 0, libvirt_virEventTimeoutCallbackWrap(cb), cleanup); VIR_PY_TUPLE_SET_GOTO(cb_args, 1, libvirt_virVoidPtrWrap(opaque), cleanup); VIR_PY_TUPLE_SET_GOTO(cb_args, 2, libvirt_virFreeCallbackWrap(ff), cleanup); result = PyObject_Call(addTimeoutObj, pyobj_args, NULL); if (!result) { PyErr_Print(); PyErr_Clear(); } else { libvirt_intUnwrap(result, &retval); } cleanup: Py_XDECREF(result); Py_XDECREF(pyobj_args); LIBVIRT_RELEASE_THREAD_STATE; return retval; } static void libvirt_virEventUpdateTimeoutFunc(int timer, int timeout) { PyObject *result = NULL; PyObject *pyobj_args; LIBVIRT_ENSURE_THREAD_STATE; if ((pyobj_args = PyTuple_New(2)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 0, libvirt_intWrap(timer), cleanup); VIR_PY_TUPLE_SET_GOTO(pyobj_args, 1, libvirt_intWrap(timeout), cleanup); result = PyObject_Call(updateTimeoutObj, pyobj_args, NULL); if (!result) { PyErr_Print(); PyErr_Clear(); } cleanup: Py_XDECREF(result); Py_XDECREF(pyobj_args); LIBVIRT_RELEASE_THREAD_STATE; } static int libvirt_virEventRemoveTimeoutFunc(int timer) { PyObject *result = NULL; PyObject *pyobj_args; int retval = -1; LIBVIRT_ENSURE_THREAD_STATE; if ((pyobj_args = PyTuple_New(1)) == NULL) goto cleanup; VIR_PY_TUPLE_SET_GOTO(pyobj_args, 0, libvirt_intWrap(timer), cleanup); result = PyObject_Call(removeTimeoutObj, pyobj_args, NULL); if (result) { retval = 0; } else { PyErr_Print(); PyErr_Clear(); } cleanup: Py_XDECREF(result); Py_XDECREF(pyobj_args); LIBVIRT_RELEASE_THREAD_STATE; return retval; } static PyObject * libvirt_virEventRegisterImpl(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { if (addHandleObj || updateHandleObj || removeHandleObj || addTimeoutObj || updateTimeoutObj || removeTimeoutObj) { PyErr_SetString(PyExc_RuntimeError, "Event loop is already registered"); return NULL; } /* Parse and check arguments */ if (!PyArg_ParseTuple(args, (char *) "OOOOOO:virEventRegisterImpl", &addHandleObj, &updateHandleObj, &removeHandleObj, &addTimeoutObj, &updateTimeoutObj, &removeTimeoutObj) || !PyCallable_Check(addHandleObj) || !PyCallable_Check(updateHandleObj) || !PyCallable_Check(removeHandleObj) || !PyCallable_Check(addTimeoutObj) || !PyCallable_Check(updateTimeoutObj) || !PyCallable_Check(removeTimeoutObj)) return NULL; /* Inc refs since we're holding on to these objects until * the next call (if any) to this function. */ Py_INCREF(addHandleObj); Py_INCREF(updateHandleObj); Py_INCREF(removeHandleObj); Py_INCREF(addTimeoutObj); Py_INCREF(updateTimeoutObj); Py_INCREF(removeTimeoutObj); /* Now register our C EventImpl, which will dispatch * to the Python callbacks passed in as args. */ LIBVIRT_BEGIN_ALLOW_THREADS; virEventRegisterImpl(libvirt_virEventAddHandleFunc, libvirt_virEventUpdateHandleFunc, libvirt_virEventRemoveHandleFunc, libvirt_virEventAddTimeoutFunc, libvirt_virEventUpdateTimeoutFunc, libvirt_virEventRemoveTimeoutFunc); LIBVIRT_END_ALLOW_THREADS; return VIR_PY_INT_SUCCESS; } static PyObject * libvirt_virEventInvokeHandleCallback(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int watch, fd, event; PyObject *py_f; PyObject *py_opaque; virEventHandleCallback cb; void *opaque; if (!PyArg_ParseTuple(args, (char *) "iiiOO:virEventInvokeHandleCallback", &watch, &fd, &event, &py_f, &py_opaque)) return NULL; cb = (virEventHandleCallback) PyvirEventHandleCallback_Get(py_f); opaque = (void *) PyvirVoidPtr_Get(py_opaque); if (cb) { LIBVIRT_BEGIN_ALLOW_THREADS; cb(watch, fd, event, opaque); LIBVIRT_END_ALLOW_THREADS; } return VIR_PY_INT_SUCCESS; } static PyObject * libvirt_virEventInvokeTimeoutCallback(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int timer; PyObject *py_f; PyObject *py_opaque; virEventTimeoutCallback cb; void *opaque; if (!PyArg_ParseTuple(args, (char *) "iOO:virEventInvokeTimeoutCallback", &timer, &py_f, &py_opaque)) return NULL; cb = (virEventTimeoutCallback) PyvirEventTimeoutCallback_Get(py_f); opaque = (void *) PyvirVoidPtr_Get(py_opaque); if (cb) { LIBVIRT_BEGIN_ALLOW_THREADS; cb(timer, opaque); LIBVIRT_END_ALLOW_THREADS; } return VIR_PY_INT_SUCCESS; } static PyObject * libvirt_virEventInvokeFreeCallback(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_f; PyObject *py_opaque; virFreeCallback cb; void *opaque; if (!PyArg_ParseTuple(args, (char *) "OO:virEventInvokeFreeCallback", &py_f, &py_opaque)) return NULL; cb = (virFreeCallback) PyvirEventHandleCallback_Get(py_f); opaque = (void *) PyvirVoidPtr_Get(py_opaque); if (cb) { LIBVIRT_BEGIN_ALLOW_THREADS; cb(opaque); LIBVIRT_END_ALLOW_THREADS; } return VIR_PY_INT_SUCCESS; } static void libvirt_virEventHandleCallback(int watch, int fd, int events, void *opaque) { PyObject *pyobj_cbData = (PyObject *)opaque; PyObject *pyobj_ret; PyObject *python_cb; LIBVIRT_ENSURE_THREAD_STATE; /* Lookup the python callback */ python_cb = libvirt_lookupPythonFunc("_dispatchEventHandleCallback"); if (!python_cb) { goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the pure python dispatcher */ pyobj_ret = PyObject_CallFunction(python_cb, (char *)"iiiO", watch, fd, events, pyobj_cbData); Py_DECREF(pyobj_cbData); if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); } cleanup: LIBVIRT_RELEASE_THREAD_STATE; } static PyObject * libvirt_virEventAddHandle(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_cbData; virEventHandleCallback cb = libvirt_virEventHandleCallback; int events; int fd; int ret; if (!PyArg_ParseTuple(args, (char *) "iiO:virEventAddHandle", &fd, &events, &pyobj_cbData)) return NULL; Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virEventAddHandle(fd, events, cb, pyobj_cbData, NULL); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static void libvirt_virEventTimeoutCallback(int timer, void *opaque) { PyObject *pyobj_cbData = (PyObject *)opaque; PyObject *pyobj_ret; PyObject *python_cb; LIBVIRT_ENSURE_THREAD_STATE; /* Lookup the python callback */ python_cb = libvirt_lookupPythonFunc("_dispatchEventTimeoutCallback"); if (!python_cb) { goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the pure python dispatcher */ pyobj_ret = PyObject_CallFunction(python_cb, (char *)"iO", timer, pyobj_cbData); Py_DECREF(pyobj_cbData); if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); } cleanup: LIBVIRT_RELEASE_THREAD_STATE; } static PyObject * libvirt_virEventAddTimeout(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_cbData; virEventTimeoutCallback cb = libvirt_virEventTimeoutCallback; int timeout; int ret; if (!PyArg_ParseTuple(args, (char *) "iO:virEventAddTimeout", &timeout, &pyobj_cbData)) return NULL; Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virEventAddTimeout(timeout, cb, pyobj_cbData, NULL); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static void libvirt_virConnectDomainEventFreeFunc(void *opaque) { PyObject *pyobj_conn = (PyObject*)opaque; LIBVIRT_ENSURE_THREAD_STATE; Py_DECREF(pyobj_conn); LIBVIRT_RELEASE_THREAD_STATE; } static int libvirt_virConnectDomainEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int event, int detail, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventLifecycleCallback", (char*)"OiiO", pyobj_dom, event, detail, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventGenericCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventGenericCallback", (char*)"OO", pyobj_dom, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventRTCChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, long long utcoffset, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventRTCChangeCallback", (char*)"OLO", pyobj_dom, (PY_LONG_LONG)utcoffset, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventWatchdogCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int action, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventWatchdogCallback", (char*)"OiO", pyobj_dom, action, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *srcPath, const char *devAlias, int action, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventIOErrorCallback", (char*)"OssiO", pyobj_dom, srcPath, devAlias, action, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventIOErrorReasonCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *srcPath, const char *devAlias, int action, const char *reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventIOErrorReasonCallback", (char*)"OssisO", pyobj_dom, srcPath, devAlias, action, reason, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int phase, virDomainEventGraphicsAddressPtr local, virDomainEventGraphicsAddressPtr remote, const char *authScheme, virDomainEventGraphicsSubjectPtr subject, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom = NULL; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; PyObject *pyobj_local = NULL; PyObject *pyobj_remote = NULL; PyObject *pyobj_subject = NULL; int ret = -1; ssize_t i; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); if ((pyobj_local = PyDict_New()) == NULL) goto cleanup; VIR_PY_DICT_SET_GOTO(pyobj_local, libvirt_constcharPtrWrap("family"), libvirt_intWrap(local->family), cleanup); VIR_PY_DICT_SET_GOTO(pyobj_local, libvirt_constcharPtrWrap("node"), libvirt_constcharPtrWrap(local->node), cleanup); VIR_PY_DICT_SET_GOTO(pyobj_local, libvirt_constcharPtrWrap("service"), libvirt_constcharPtrWrap(local->service), cleanup); if ((pyobj_remote = PyDict_New()) == NULL) goto cleanup; VIR_PY_DICT_SET_GOTO(pyobj_remote, libvirt_constcharPtrWrap("family"), libvirt_intWrap(remote->family), cleanup); VIR_PY_DICT_SET_GOTO(pyobj_remote, libvirt_constcharPtrWrap("node"), libvirt_constcharPtrWrap(remote->node), cleanup); VIR_PY_DICT_SET_GOTO(pyobj_remote, libvirt_constcharPtrWrap("service"), libvirt_constcharPtrWrap(remote->service), cleanup); if ((pyobj_subject = PyList_New(subject->nidentity)) == NULL) goto cleanup; for (i = 0; i < subject->nidentity; i++) { PyObject *pair = PyTuple_New(2); if (pair == NULL) goto cleanup; VIR_PY_LIST_SET_GOTO(pyobj_subject, i, pair, cleanup); VIR_PY_TUPLE_SET_GOTO(pair, 0, libvirt_constcharPtrWrap(subject->identities[i].type), cleanup); VIR_PY_TUPLE_SET_GOTO(pair, 1, libvirt_constcharPtrWrap(subject->identities[i].name), cleanup); } /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventGraphicsCallback", (char*)"OiOOsOO", pyobj_dom, phase, pyobj_local, pyobj_remote, authScheme, pyobj_subject, pyobj_cbData); cleanup: Py_DECREF(pyobj_cbData); Py_XDECREF(pyobj_dom); if (!pyobj_ret) { Py_XDECREF(pyobj_local); Py_XDECREF(pyobj_remote); Py_XDECREF(pyobj_subject); DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventBlockJobCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *disk, int type, int status, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventBlockJobCallback", (char*)"OsiiO", pyobj_dom, disk, type, status, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventDiskChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *oldSrcPath, const char *newSrcPath, const char *devAlias, int reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventDiskChangeCallback", (char*)"OsssiO", pyobj_dom, oldSrcPath, newSrcPath, devAlias, reason, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventTrayChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *devAlias, int reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventTrayChangeCallback", (char*)"OsiO", pyobj_dom, devAlias, reason, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventPMWakeupCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventPMWakeupCallback", (char*)"OiO", pyobj_dom, reason, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectDomainEventPMSuspendCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventPMSuspendCallback", (char*)"OiO", pyobj_dom, reason, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #ifdef VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE static int libvirt_virConnectDomainEventBalloonChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, unsigned long long actual, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventBalloonChangeCallback", (char*)"OLO", pyobj_dom, (PY_LONG_LONG)actual, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE */ #ifdef VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK static int libvirt_virConnectDomainEventPMSuspendDiskCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventPMSuspendDiskCallback", (char*)"OiO", pyobj_dom, reason, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK */ #ifdef VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED static int libvirt_virConnectDomainEventDeviceRemovedCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *devAlias, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventDeviceRemovedCallback", (char*)"OsO", pyobj_dom, devAlias, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED */ #ifdef VIR_DOMAIN_EVENT_ID_TUNABLE static int libvirt_virConnectDomainEventTunableCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, virTypedParameterPtr params, int nparams, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; PyObject *pyobj_dict = NULL; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; pyobj_dict = getPyVirTypedParameter(params, nparams); if (!pyobj_dict) goto cleanup; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventTunableCallback", (char*)"OOO", pyobj_dom, pyobj_dict, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } Py_XDECREF(pyobj_dict); LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_TUNABLE */ #ifdef VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE static int libvirt_virConnectDomainEventAgentLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int state, int reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventAgentLifecycleCallback", (char*)"OiiO", pyobj_dom, state, reason, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE */ #ifdef VIR_DOMAIN_EVENT_ID_DEVICE_ADDED static int libvirt_virConnectDomainEventDeviceAddedCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *devAlias, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventDeviceAddedCallback", (char*)"OsO", pyobj_dom, devAlias, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_DEVICE_ADDED */ #ifdef VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION static int libvirt_virConnectDomainEventMigrationIterationCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int iteration, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventMigrationIterationCallback", (char*)"OiO", pyobj_dom, iteration, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION */ #ifdef VIR_DOMAIN_EVENT_ID_JOB_COMPLETED static int libvirt_virConnectDomainEventJobCompletedCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, virTypedParameterPtr params, int nparams, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; PyObject *pyobj_dict = NULL; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; pyobj_dict = getPyVirTypedParameter(params, nparams); if (!pyobj_dict) goto cleanup; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventJobCompletedCallback", (char*)"OOO", pyobj_dom, pyobj_dict, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); Py_XDECREF(pyobj_dict); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_JOB_COMPLETED */ #ifdef VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED static int libvirt_virConnectDomainEventDeviceRemovalFailedCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *devAlias, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventDeviceRemovalFailedCallback", (char*)"OsO", pyobj_dom, devAlias, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED */ #ifdef VIR_DOMAIN_EVENT_ID_METADATA_CHANGE static int libvirt_virConnectDomainEventMetadataChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int type, const char *nsuri, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventMetadataChangeCallback", (char*)"OisO", pyobj_dom, type, nsuri, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_METADATA_CHANGE */ #ifdef VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD static int libvirt_virConnectDomainEventBlockThresholdCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *dev, const char *path, unsigned long long threshold, unsigned long long excess, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventBlockThresholdCallback", (char*)"OssKKO", pyobj_dom, dev, path, threshold, excess, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD */ #ifdef VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE static int libvirt_virConnectDomainEventMemoryFailureCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, int recipient, int action, unsigned int flags, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventMemoryFailureCallback", (char*)"OiiiO", pyobj_dom, recipient, action, flags, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE */ #ifdef VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE static int libvirt_virConnectDomainEventMemoryDeviceSizeChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *alias, unsigned long long size, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventMemoryDeviceSizeChangeCallback", (char*)"OsKO", pyobj_dom, alias, size, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE */ #ifdef VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE static int libvirt_virConnectDomainEventNICMACChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *alias, const char *oldMAC, const char *newMAC, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchDomainEventNICMACChangeCallback", (char*)"OsssO", pyobj_dom, alias, oldMAC, newMAC, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE */ static PyObject * libvirt_virConnectDomainEventRegisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; /* return value */ PyObject *pyobj_conn; /* virConnectPtr */ PyObject *pyobj_dom; PyObject *pyobj_cbData; /* hash of callback data */ int eventID; virConnectPtr conn; int ret = 0; virConnectDomainEventGenericCallback cb = NULL; virDomainPtr dom; if (!PyArg_ParseTuple(args, (char *) "OOiO:virConnectDomainEventRegisterAny", &pyobj_conn, &pyobj_dom, &eventID, &pyobj_cbData)) return NULL; DEBUG("libvirt_virConnectDomainEventRegister(%p %p %d %p) called\n", pyobj_conn, pyobj_dom, eventID, pyobj_cbData); conn = PyvirConnect_Get(pyobj_conn); if (pyobj_dom == Py_None) dom = NULL; else dom = PyvirDomain_Get(pyobj_dom); switch ((virDomainEventID) eventID) { case VIR_DOMAIN_EVENT_ID_LIFECYCLE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventLifecycleCallback); break; case VIR_DOMAIN_EVENT_ID_REBOOT: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGenericCallback); break; case VIR_DOMAIN_EVENT_ID_RTC_CHANGE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventRTCChangeCallback); break; case VIR_DOMAIN_EVENT_ID_WATCHDOG: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventWatchdogCallback); break; case VIR_DOMAIN_EVENT_ID_IO_ERROR: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorCallback); break; case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorReasonCallback); break; case VIR_DOMAIN_EVENT_ID_GRAPHICS: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGraphicsCallback); break; case VIR_DOMAIN_EVENT_ID_CONTROL_ERROR: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGenericCallback); break; case VIR_DOMAIN_EVENT_ID_BLOCK_JOB: #ifdef VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 case VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2: #endif /* VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 */ cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventBlockJobCallback); break; case VIR_DOMAIN_EVENT_ID_DISK_CHANGE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDiskChangeCallback); break; case VIR_DOMAIN_EVENT_ID_TRAY_CHANGE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventTrayChangeCallback); break; case VIR_DOMAIN_EVENT_ID_PMWAKEUP: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventPMWakeupCallback); break; case VIR_DOMAIN_EVENT_ID_PMSUSPEND: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventPMSuspendCallback); break; #ifdef VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE case VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventBalloonChangeCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_BALLOON_CHANGE */ #ifdef VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK case VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventPMSuspendDiskCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_PMSUSPEND_DISK */ #ifdef VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDeviceRemovedCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_DEVICE_REMOVED */ #ifdef VIR_DOMAIN_EVENT_ID_TUNABLE case VIR_DOMAIN_EVENT_ID_TUNABLE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventTunableCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_TUNABLE */ #ifdef VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE case VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventAgentLifecycleCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_AGENT_LIFECYCLE */ #ifdef VIR_DOMAIN_EVENT_ID_DEVICE_ADDED case VIR_DOMAIN_EVENT_ID_DEVICE_ADDED: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDeviceAddedCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_DEVICE_ADDED */ #ifdef VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION case VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventMigrationIterationCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_MIGRATION_ITERATION */ #ifdef VIR_DOMAIN_EVENT_ID_JOB_COMPLETED case VIR_DOMAIN_EVENT_ID_JOB_COMPLETED: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventJobCompletedCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_JOB_COMPLETED */ #ifdef VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED case VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventDeviceRemovalFailedCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_DEVICE_REMOVAL_FAILED */ #ifdef VIR_DOMAIN_EVENT_ID_METADATA_CHANGE case VIR_DOMAIN_EVENT_ID_METADATA_CHANGE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventMetadataChangeCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_METADATA_CHANGE */ #ifdef VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD case VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventBlockThresholdCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD */ #ifdef VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE case VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventMemoryFailureCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE */ #ifdef VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE case VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventMemoryDeviceSizeChangeCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE */ #ifdef VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE case VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE: cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventNICMACChangeCallback); break; #endif /* VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE */ case VIR_DOMAIN_EVENT_ID_LAST: break; } if (!cb) { return VIR_PY_INT_FAIL; } Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectDomainEventRegisterAny(conn, dom, eventID, cb, pyobj_cbData, libvirt_virConnectDomainEventFreeFunc); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } py_retval = libvirt_intWrap(ret); return py_retval; } static PyObject * libvirt_virConnectDomainEventDeregisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; int callbackID; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "Oi:virConnectDomainEventDeregister", &pyobj_conn, &callbackID)) return NULL; DEBUG("libvirt_virConnectDomainEventDeregister(%p) called\n", pyobj_conn); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectDomainEventDeregisterAny(conn, callbackID); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(ret); } #if LIBVIR_CHECK_VERSION(1, 2, 1) static void libvirt_virConnectNetworkEventFreeFunc(void *opaque) { PyObject *pyobj_conn = (PyObject*)opaque; LIBVIRT_ENSURE_THREAD_STATE; Py_DECREF(pyobj_conn); LIBVIRT_RELEASE_THREAD_STATE; } static int libvirt_virConnectNetworkEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virNetworkPtr net, int event, int detail, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_net; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virNetworkPtr */ virNetworkRef(net); if (!(pyobj_net = libvirt_virNetworkPtrWrap(net))) { virNetworkFree(net); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchNetworkEventLifecycleCallback", (char*)"OiiO", pyobj_net, event, detail, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_net); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #ifdef VIR_NETWORK_EVENT_ID_METADATA_CHANGE static int libvirt_virConnectNetworkEventMetadataChangeCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virNetworkPtr dom, int type, const char *nsuri, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virNetworkPtr */ virNetworkRef(dom); if (!(pyobj_dom = libvirt_virNetworkPtrWrap(dom))) { virNetworkFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchNetworkEventMetadataChangeCallback", (char*)"OisO", pyobj_dom, type, nsuri, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } #endif /* VIR_NETWORK_EVENT_ID_METADATA_CHANGE */ static PyObject * libvirt_virConnectNetworkEventRegisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; /* virConnectPtr */ PyObject *pyobj_net; PyObject *pyobj_cbData; /* hash of callback data */ int eventID; virConnectPtr conn; int ret = 0; virConnectNetworkEventGenericCallback cb = NULL; virNetworkPtr net; if (!PyArg_ParseTuple(args, (char *) "OOiO:virConnectNetworkEventRegisterAny", &pyobj_conn, &pyobj_net, &eventID, &pyobj_cbData)) return NULL; DEBUG("libvirt_virConnectNetworkEventRegister(%p %p %d %p) called\n", pyobj_conn, pyobj_net, eventID, pyobj_cbData); conn = PyvirConnect_Get(pyobj_conn); if (pyobj_net == Py_None) net = NULL; else net = PyvirNetwork_Get(pyobj_net); switch ((virNetworkEventID) eventID) { case VIR_NETWORK_EVENT_ID_LIFECYCLE: cb = VIR_NETWORK_EVENT_CALLBACK(libvirt_virConnectNetworkEventLifecycleCallback); break; #ifdef VIR_NETWORK_EVENT_ID_METADATA_CHANGE case VIR_NETWORK_EVENT_ID_METADATA_CHANGE: cb = VIR_NETWORK_EVENT_CALLBACK(libvirt_virConnectNetworkEventMetadataChangeCallback); break; #endif /* VIR_NETWORK_EVENT_ID_METADATA_CHANGE */ case VIR_NETWORK_EVENT_ID_LAST: break; } if (!cb) { return VIR_PY_INT_FAIL; } Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectNetworkEventRegisterAny(conn, net, eventID, cb, pyobj_cbData, libvirt_virConnectNetworkEventFreeFunc); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static PyObject * libvirt_virConnectNetworkEventDeregisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; int callbackID; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "Oi:virConnectNetworkEventDeregister", &pyobj_conn, &callbackID)) return NULL; DEBUG("libvirt_virConnectNetworkEventDeregister(%p) called\n", pyobj_conn); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectNetworkEventDeregisterAny(conn, callbackID); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(ret); } #endif /* LIBVIR_CHECK_VERSION(1, 2, 1)*/ #if LIBVIR_CHECK_VERSION(0, 10, 0) static void libvirt_virConnectCloseCallbackDispatch(virConnectPtr conn ATTRIBUTE_UNUSED, int reason, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_ret; PyObject *pyobj_conn; PyObject *dictKey; LIBVIRT_ENSURE_THREAD_STATE; Py_INCREF(pyobj_cbData); dictKey = libvirt_constcharPtrWrap("conn"); pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchCloseCallback", (char*)"iO", reason, pyobj_cbData); Py_DECREF(pyobj_cbData); if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); } LIBVIRT_RELEASE_THREAD_STATE; } static PyObject * libvirt_virConnectRegisterCloseCallback(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; /* virConnectPtr */ PyObject *pyobj_cbData; /* hash of callback data */ virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "OO:virConnectRegisterCloseCallback", &pyobj_conn, &pyobj_cbData)) return NULL; DEBUG("libvirt_virConnectRegisterCloseCallback(%p %p) called\n", pyobj_conn, pyobj_cbData); conn = PyvirConnect_Get(pyobj_conn); Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectRegisterCloseCallback(conn, libvirt_virConnectCloseCallbackDispatch, pyobj_cbData, libvirt_virConnectDomainEventFreeFunc); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static PyObject * libvirt_virConnectUnregisterCloseCallback(PyObject * self ATTRIBUTE_UNUSED, PyObject * args) { PyObject *pyobj_conn; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "O:virConnectUnregisterCloseCallback", &pyobj_conn)) return NULL; DEBUG("libvirt_virConnectDomainEventUnregister(%p) called\n", pyobj_conn); conn = PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectUnregisterCloseCallback(conn, libvirt_virConnectCloseCallbackDispatch); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(ret); } #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ static void libvirt_virStreamEventFreeFunc(void *opaque) { PyObject *pyobj_stream = (PyObject*)opaque; LIBVIRT_ENSURE_THREAD_STATE; Py_DECREF(pyobj_stream); LIBVIRT_RELEASE_THREAD_STATE; } static void libvirt_virStreamEventCallback(virStreamPtr st ATTRIBUTE_UNUSED, int events, void *opaque) { PyObject *pyobj_cbData = (PyObject *)opaque; PyObject *pyobj_stream; PyObject *pyobj_ret; PyObject *dictKey; LIBVIRT_ENSURE_THREAD_STATE; Py_INCREF(pyobj_cbData); dictKey = libvirt_constcharPtrWrap("stream"); pyobj_stream = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Call the pure python dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_stream, (char *)"_dispatchStreamEventCallback", (char *)"iO", events, pyobj_cbData); Py_DECREF(pyobj_cbData); if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); } LIBVIRT_RELEASE_THREAD_STATE; } static PyObject * libvirt_virStreamEventAddCallback(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_stream; PyObject *pyobj_cbData; virStreamPtr stream; virStreamEventCallback cb = libvirt_virStreamEventCallback; int ret; int events; if (!PyArg_ParseTuple(args, (char *) "OiO:virStreamEventAddCallback", &pyobj_stream, &events, &pyobj_cbData)) return NULL; DEBUG("libvirt_virStreamEventAddCallback(%p, %d, %p) called\n", pyobj_stream, events, pyobj_cbData); stream = PyvirStream_Get(pyobj_stream); Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virStreamEventAddCallback(stream, events, cb, pyobj_cbData, libvirt_virStreamEventFreeFunc); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static PyObject * libvirt_virStreamRecv(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_stream; PyObject *rv; virStreamPtr stream; char *buf = NULL; int ret; int nbytes; if (!PyArg_ParseTuple(args, (char *) "Oi:virStreamRecv", &pyobj_stream, &nbytes)) { return NULL; } stream = PyvirStream_Get(pyobj_stream); if (VIR_ALLOC_N(buf, nbytes+1 > 0 ? nbytes+1 : 1) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virStreamRecv(stream, buf, nbytes); LIBVIRT_END_ALLOW_THREADS; buf[ret > -1 ? ret : 0] = '\0'; DEBUG("StreamRecv ret=%d strlen=%zu\n", ret, strlen(buf)); if (ret == -2) { VIR_FREE(buf); return libvirt_intWrap(ret); } if (ret < 0) { VIR_FREE(buf); return VIR_PY_NONE; } rv = libvirt_charPtrSizeWrap((char *) buf, (Py_ssize_t) ret); VIR_FREE(buf); return rv; } static PyObject * libvirt_virStreamSend(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_stream; PyObject *pyobj_data; virStreamPtr stream; char *data; Py_ssize_t datalen; int ret; if (!PyArg_ParseTuple(args, (char *) "OO:virStreamSend", &pyobj_stream, &pyobj_data)) return NULL; stream = PyvirStream_Get(pyobj_stream); libvirt_charPtrSizeUnwrap(pyobj_data, &data, &datalen); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virStreamSend(stream, data, datalen); LIBVIRT_END_ALLOW_THREADS; DEBUG("StreamSend ret=%d\n", ret); return libvirt_intWrap(ret); } static PyObject * libvirt_virDomainSendKey(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; PyObject *pyobj_list; int codeset; int holdtime; unsigned int flags; int ret; ssize_t i; unsigned int keycodes[VIR_DOMAIN_SEND_KEY_MAX_KEYS]; int nkeycodes; if (!PyArg_ParseTuple(args, (char *)"OiiOII:virDomainSendKey", &pyobj_domain, &codeset, &holdtime, &pyobj_list, &nkeycodes, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (!PyList_Check(pyobj_list)) { return VIR_PY_INT_FAIL; } if (nkeycodes != PyList_Size(pyobj_list) || nkeycodes > VIR_DOMAIN_SEND_KEY_MAX_KEYS) { return VIR_PY_INT_FAIL; } for (i = 0; i < nkeycodes; i++) { if (libvirt_uintUnwrap(PyList_GetItem(pyobj_list, i), &keycodes[i]) < 0) return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; ret = virDomainSendKey(domain, codeset, holdtime, keycodes, nkeycodes, flags); LIBVIRT_END_ALLOW_THREADS; DEBUG("virDomainSendKey ret=%d\n", ret); return libvirt_intWrap(ret); } #if LIBVIR_CHECK_VERSION(1, 0, 3) static PyObject * libvirt_virDomainMigrateGetCompressionCache(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; virDomainPtr domain; unsigned int flags; unsigned long long cacheSize; int rc; if (!PyArg_ParseTuple(args, (char *) "OI:virDomainMigrateGetCompressionCache", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; rc = virDomainMigrateGetCompressionCache(domain, &cacheSize, flags); LIBVIRT_END_ALLOW_THREADS; if (rc < 0) return VIR_PY_NONE; return libvirt_ulonglongWrap(cacheSize); } #endif /* LIBVIR_CHECK_VERSION(1, 0, 3) */ static PyObject * libvirt_virDomainMigrateGetMaxSpeed(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval; unsigned long bandwidth; virDomainPtr domain; PyObject *pyobj_domain; unsigned int flags = 0; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainMigrateGetMaxSpeed", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainMigrateGetMaxSpeed(domain, &bandwidth, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_INT_FAIL; return libvirt_ulongWrap(bandwidth); } #if LIBVIR_CHECK_VERSION(3, 7, 0) static PyObject * libvirt_virDomainMigrateGetMaxDowntime(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; virDomainPtr domain; unsigned int flags; unsigned long long downtime; int rc; if (!PyArg_ParseTuple(args, (char *) "OI:virDomainMigrateGetMaxDowntime", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; rc = virDomainMigrateGetMaxDowntime(domain, &downtime, flags); LIBVIRT_END_ALLOW_THREADS; if (rc < 0) return VIR_PY_NONE; return libvirt_ulonglongWrap(downtime); } #endif /* LIBVIR_CHECK_VERSION(3, 7, 0) */ #if LIBVIR_CHECK_VERSION(1, 1, 0) static virPyTypedParamsHint virPyDomainMigrate3Params[] = { # ifdef VIR_MIGRATE_PARAM_URI { VIR_MIGRATE_PARAM_URI, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_DEST_NAME { VIR_MIGRATE_PARAM_DEST_NAME, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_DEST_XML { VIR_MIGRATE_PARAM_DEST_XML, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_PERSIST_XML { VIR_MIGRATE_PARAM_PERSIST_XML, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_BANDWIDTH { VIR_MIGRATE_PARAM_BANDWIDTH, VIR_TYPED_PARAM_ULLONG }, # endif # ifdef VIR_MIGRATE_PARAM_GRAPHICS_URI { VIR_MIGRATE_PARAM_GRAPHICS_URI, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_LISTEN_ADDRESS { VIR_MIGRATE_PARAM_LISTEN_ADDRESS, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_MIGRATE_DISKS { VIR_MIGRATE_PARAM_MIGRATE_DISKS, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_DISKS_PORT { VIR_MIGRATE_PARAM_DISKS_PORT, VIR_TYPED_PARAM_INT }, # endif # ifdef VIR_MIGRATE_PARAM_COMPRESSION { VIR_MIGRATE_PARAM_COMPRESSION, VIR_TYPED_PARAM_STRING }, # endif # ifdef VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL { VIR_MIGRATE_PARAM_COMPRESSION_MT_LEVEL, VIR_TYPED_PARAM_INT }, # endif # ifdef VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS { VIR_MIGRATE_PARAM_COMPRESSION_MT_THREADS, VIR_TYPED_PARAM_INT }, # endif # ifdef VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS { VIR_MIGRATE_PARAM_COMPRESSION_MT_DTHREADS, VIR_TYPED_PARAM_INT }, # endif # ifdef VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE { VIR_MIGRATE_PARAM_COMPRESSION_XBZRLE_CACHE, VIR_TYPED_PARAM_ULLONG }, # endif # ifdef VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL { VIR_MIGRATE_PARAM_AUTO_CONVERGE_INITIAL, VIR_TYPED_PARAM_INT }, # endif # ifdef VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT { VIR_MIGRATE_PARAM_AUTO_CONVERGE_INCREMENT, VIR_TYPED_PARAM_INT }, # endif # ifdef VIR_MIGRATE_PARAM_BANDWIDTH_POSTCOPY { VIR_MIGRATE_PARAM_BANDWIDTH_POSTCOPY, VIR_TYPED_PARAM_ULLONG }, # endif # ifdef VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONS { VIR_MIGRATE_PARAM_PARALLEL_CONNECTIONS, VIR_TYPED_PARAM_INT }, # endif # ifdef VIR_MIGRATE_PARAM_DISKS_URI { VIR_MIGRATE_PARAM_DISKS_URI, VIR_TYPED_PARAM_STRING }, #endif #ifdef VIR_MIGRATE_PARAM_TLS_DESTINATION { VIR_MIGRATE_PARAM_TLS_DESTINATION, VIR_TYPED_PARAM_STRING }, #endif #ifdef VIR_MIGRATE_PARAM_COMPRESSION_ZLIB_LEVEL { VIR_MIGRATE_PARAM_COMPRESSION_ZLIB_LEVEL, VIR_TYPED_PARAM_INT }, #endif #ifdef VIR_MIGRATE_PARAM_COMPRESSION_ZSTD_LEVEL { VIR_MIGRATE_PARAM_COMPRESSION_ZSTD_LEVEL, VIR_TYPED_PARAM_INT }, #endif }; static PyObject * libvirt_virDomainMigrate3(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; virDomainPtr domain; PyObject *pyobj_dconn; virConnectPtr dconn; PyObject *dict; unsigned int flags; virTypedParameterPtr params; int nparams = 0; virDomainPtr ddom = NULL; if (!PyArg_ParseTuple(args, (char *) "OOOI:virDomainMigrate3", &pyobj_domain, &pyobj_dconn, &dict, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); dconn = (virConnectPtr) PyvirConnect_Get(pyobj_dconn); if (!PyDict_Check(dict)) { PyErr_Format(PyExc_TypeError, "migration params must be a dictionary"); return NULL; } if (virPyDictToTypedParams(dict, ¶ms, &nparams, virPyDomainMigrate3Params, VIR_N_ELEMENTS(virPyDomainMigrate3Params)) < 0) { return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; ddom = virDomainMigrate3(domain, dconn, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_virDomainPtrWrap(ddom); } static PyObject * libvirt_virDomainMigrateToURI3(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; virDomainPtr domain; char *dconnuri; PyObject *dict; unsigned int flags; virTypedParameterPtr params; int nparams; int ret = -1; if (!PyArg_ParseTuple(args, (char *) "OzOI:virDomainMigrate3", &pyobj_domain, &dconnuri, &dict, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (!PyDict_Check(dict)) { PyErr_Format(PyExc_TypeError, "migration params must be a dictionary"); return NULL; } if (virPyDictToTypedParams(dict, ¶ms, &nparams, virPyDomainMigrate3Params, VIR_N_ELEMENTS(virPyDomainMigrate3Params)) < 0) { return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; ret = virDomainMigrateToURI3(domain, dconnuri, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(ret); } #endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */ static PyObject * libvirt_virDomainBlockPeek(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; const char *disk; unsigned long long offset; size_t size; char *buf; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OzKkI:virDomainBlockPeek", &pyobj_domain, &disk, &offset, &size, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (VIR_ALLOC_N(buf, size) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainBlockPeek(domain, disk, offset, size, buf, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } py_retval = libvirt_charPtrSizeWrap(buf, size); cleanup: VIR_FREE(buf); return py_retval; } static PyObject * libvirt_virDomainMemoryPeek(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; unsigned long long start; size_t size; char *buf; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OKkI:virDomainMemoryPeek", &pyobj_domain, &start, &size, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (VIR_ALLOC_N(buf, size) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainMemoryPeek(domain, start, size, buf, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } py_retval = libvirt_charPtrSizeWrap(buf, size); cleanup: VIR_FREE(buf); return py_retval; } #if LIBVIR_CHECK_VERSION(0, 10, 2) static PyObject * libvirt_virNodeSetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virConnectPtr conn; PyObject *pyobj_conn, *info; PyObject *ret = NULL; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virNodeSetMemoryParameters", &pyobj_conn, &info, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetMemoryParameters(conn, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_INT_FAIL; if (nparams == 0) { PyErr_Format(PyExc_LookupError, "no settable attributes"); return NULL; } if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetMemoryParameters(conn, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeSetMemoryParameters(conn, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virNodeGetMemoryParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virConnectPtr conn; PyObject *pyobj_conn; PyObject *ret = NULL; int i_retval; int nparams = 0; unsigned int flags; virTypedParameterPtr params; if (!PyArg_ParseTuple(args, (char *)"OI:virNodeGetMemoryParameters", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetMemoryParameters(conn, NULL, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if (!nparams) return PyDict_New(); if (VIR_ALLOC_N(params, nparams) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetMemoryParameters(conn, params, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ #if LIBVIR_CHECK_VERSION(1, 0, 0) static PyObject * libvirt_virNodeGetCPUMap(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virConnectPtr conn; PyObject *pyobj_conn; PyObject *ret = NULL; PyObject *pycpumap = NULL; int i_retval; unsigned char *cpumap = NULL; unsigned int online = 0; unsigned int flags; ssize_t i; if (!PyArg_ParseTuple(args, (char *)"OI:virNodeGetCPUMap", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetCPUMap(conn, &cpumap, &online, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_NONE; if ((ret = PyTuple_New(3)) == NULL) goto error; /* 0: number of CPUs */ VIR_PY_TUPLE_SET_GOTO(ret, 0, libvirt_intWrap(i_retval), error); /* 1: CPU map */ if ((pycpumap = PyList_New(i_retval)) == NULL) goto error; VIR_PY_TUPLE_SET_GOTO(ret, 1, pycpumap, error); for (i = 0; i < i_retval; i++) VIR_PY_LIST_SET_GOTO(pycpumap, i, PyBool_FromLong(VIR_CPU_USED(cpumap, i)), error); /* 2: number of online CPUs */ VIR_PY_TUPLE_SET_GOTO(ret, 2, libvirt_uintWrap(online), error); cleanup: VIR_FREE(cpumap); return ret; error: Py_CLEAR(ret); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(1, 0, 0) */ #if LIBVIR_CHECK_VERSION(1, 1, 1) static PyObject * libvirt_virDomainCreateWithFiles(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; PyObject *pyobj_files; unsigned int flags; unsigned int nfiles; int *files = NULL; size_t i; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainCreateWithFiles", &pyobj_domain, &pyobj_files, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); nfiles = PyList_Size(pyobj_files); if (VIR_ALLOC_N(files, nfiles) < 0) return PyErr_NoMemory(); for (i = 0; i < nfiles; i++) { PyObject *pyfd; int fd; pyfd = PyList_GetItem(pyobj_files, i); if (libvirt_intUnwrap(pyfd, &fd) < 0) goto cleanup; files[i] = fd; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainCreateWithFiles(domain, nfiles, files, flags); LIBVIRT_END_ALLOW_THREADS; py_retval = libvirt_intWrap(c_retval); cleanup: VIR_FREE(files); return py_retval; } static PyObject * libvirt_virDomainCreateXMLWithFiles(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; virDomainPtr c_retval; virConnectPtr conn; PyObject *pyobj_conn; char * xmlDesc; PyObject *pyobj_files; unsigned int flags; unsigned int nfiles; int *files = NULL; size_t i; if (!PyArg_ParseTuple(args, (char *)"OzOI:virDomainCreateXMLWithFiles", &pyobj_conn, &xmlDesc, &pyobj_files, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); nfiles = PyList_Size(pyobj_files); if (VIR_ALLOC_N(files, nfiles) < 0) return PyErr_NoMemory(); for (i = 0; i < nfiles; i++) { PyObject *pyfd; int fd; pyfd = PyList_GetItem(pyobj_files, i); if (libvirt_intUnwrap(pyfd, &fd) < 0) goto cleanup; files[i] = fd; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainCreateXMLWithFiles(conn, xmlDesc, nfiles, files, flags); LIBVIRT_END_ALLOW_THREADS; py_retval = libvirt_virDomainPtrWrap((virDomainPtr) c_retval); cleanup: VIR_FREE(files); return py_retval; } #endif /* LIBVIR_CHECK_VERSION(1, 1, 1) */ #if LIBVIR_CHECK_VERSION(1, 2, 5) static PyObject * libvirt_virDomainFSFreeze(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; PyObject *pyobj_list; unsigned int flags; unsigned int nmountpoints = 0; char **mountpoints = NULL; size_t i = 0; size_t j = 0; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainFSFreeze", &pyobj_domain, &pyobj_list, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (PyList_Check(pyobj_list)) { nmountpoints = PyList_Size(pyobj_list); if (VIR_ALLOC_N(mountpoints, nmountpoints) < 0) return PyErr_NoMemory(); for (i = 0; i < nmountpoints; i++) { if (libvirt_charPtrUnwrap(PyList_GetItem(pyobj_list, i), mountpoints+i) < 0) goto cleanup; } } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainFSFreeze(domain, (const char **) mountpoints, nmountpoints, flags); LIBVIRT_END_ALLOW_THREADS; py_retval = libvirt_intWrap(c_retval); cleanup: for (j = 0 ; j < i ; j++) VIR_FREE(mountpoints[j]); VIR_FREE(mountpoints); return py_retval; } static PyObject * libvirt_virDomainFSThaw(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; PyObject *pyobj_list; unsigned int flags; unsigned int nmountpoints = 0; char **mountpoints = NULL; size_t i = 0; size_t j = 0; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainFSThaw", &pyobj_domain, &pyobj_list, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (PyList_Check(pyobj_list)) { nmountpoints = PyList_Size(pyobj_list); if (VIR_ALLOC_N(mountpoints, nmountpoints) < 0) return PyErr_NoMemory(); for (i = 0; i < nmountpoints; i++) { if (libvirt_charPtrUnwrap(PyList_GetItem(pyobj_list, i), mountpoints+i) < 0) goto cleanup; } } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainFSThaw(domain, (const char **) mountpoints, nmountpoints, flags); LIBVIRT_END_ALLOW_THREADS; py_retval = libvirt_intWrap(c_retval); cleanup: for (j = 0 ; j < i ; j++) VIR_FREE(mountpoints[j]); VIR_FREE(mountpoints); return py_retval; } static PyObject * libvirt_virDomainGetTime(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; PyObject *dict = NULL; PyObject *pyobj_domain; virDomainPtr domain; long long seconds; unsigned int nseconds; unsigned int flags; int c_retval; if (!PyArg_ParseTuple(args, (char*)"OI:virDomainGetTime", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (!(dict = PyDict_New())) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetTime(domain, &seconds, &nseconds, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } VIR_PY_DICT_SET_GOTO(dict, libvirt_constcharPtrWrap("seconds"), libvirt_longlongWrap(seconds), cleanup); VIR_PY_DICT_SET_GOTO(dict, libvirt_constcharPtrWrap("nseconds"), libvirt_longlongWrap(nseconds), cleanup); py_retval = dict; dict = NULL; cleanup: Py_XDECREF(dict); return py_retval; } static PyObject * libvirt_virDomainSetTime(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; PyObject *pyobj_seconds; PyObject *pyobj_nseconds; PyObject *py_dict; virDomainPtr domain; long long seconds = 0; unsigned int nseconds = 0; unsigned int flags; ssize_t py_dict_size = 0; int c_retval; if (!PyArg_ParseTuple(args, (char*)"OOI:virDomainSetTime", &pyobj_domain, &py_dict, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (PyDict_Check(py_dict)) { py_dict_size = PyDict_Size(py_dict); if ((pyobj_seconds = PyDict_GetItemString(py_dict, "seconds"))) { if (libvirt_longlongUnwrap(pyobj_seconds, &seconds) < 0) return NULL; } else { PyErr_Format(PyExc_LookupError, "Dictionary must contains 'seconds'"); return NULL; } if ((pyobj_nseconds = PyDict_GetItemString(py_dict, "nseconds"))) { if (libvirt_uintUnwrap(pyobj_nseconds, &nseconds) < 0) return NULL; } else if (py_dict_size > 1) { PyErr_Format(PyExc_LookupError, "Dictionary contains unknown key"); return NULL; } } else if (py_dict != Py_None || !flags) { PyErr_Format(PyExc_TypeError, "time must be a dictionary " "or None with flags set"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSetTime(domain, seconds, nseconds, flags); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(c_retval); } #endif /* LIBVIR_CHECK_VERSION(1, 2, 5) */ #if LIBVIR_CHECK_VERSION(1, 2, 6) static PyObject * libvirt_virNodeGetFreePages(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; PyObject *pyobj_conn; PyObject *pyobj_pagesize; PyObject *pyobj_counts = NULL; virConnectPtr conn; unsigned int *pages = NULL; int startCell; unsigned int cellCount; unsigned int flags; unsigned long long *counts = NULL; int c_retval; ssize_t pyobj_pagesize_size, i, j; if (!PyArg_ParseTuple(args, (char *)"OOiII:virNodeGetFreePages", &pyobj_conn, &pyobj_pagesize, &startCell, &cellCount, &flags)) return NULL; if (!PyList_Check(pyobj_pagesize)) { PyErr_Format(PyExc_TypeError, "pagesize must be list"); return NULL; } if (cellCount == 0) { PyErr_Format(PyExc_LookupError, "cellCount must not be zero"); return NULL; } conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); pyobj_pagesize_size = PyList_Size(pyobj_pagesize); if (VIR_ALLOC_N(pages, pyobj_pagesize_size) < 0 || VIR_ALLOC_N(counts, pyobj_pagesize_size * cellCount) < 0) { PyErr_NoMemory(); goto cleanup; } if (!(pyobj_counts = PyDict_New())) goto cleanup; for (i = 0; i < pyobj_pagesize_size; i++) { PyObject *tmp = PyList_GetItem(pyobj_pagesize, i); if (libvirt_uintUnwrap(tmp, &pages[i]) < 0) goto cleanup; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeGetFreePages(conn, pyobj_pagesize_size, pages, startCell, cellCount, counts, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } for (i = 0; i < c_retval;) { PyObject *per_node = NULL; if (!(per_node = PyDict_New())) goto cleanup; VIR_PY_DICT_SET_GOTO(pyobj_counts, libvirt_intWrap(startCell + i/pyobj_pagesize_size), per_node, cleanup); for (j = 0; j < pyobj_pagesize_size; j ++) VIR_PY_DICT_SET_GOTO(per_node, libvirt_intWrap(pages[j]), libvirt_intWrap(counts[i + j]), cleanup); i += pyobj_pagesize_size; } py_retval = pyobj_counts; pyobj_counts = NULL; cleanup: Py_XDECREF(pyobj_counts); VIR_FREE(pages); VIR_FREE(counts); return py_retval; } static PyObject * libvirt_virNetworkGetDHCPLeases(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; PyObject *py_lease = NULL; virNetworkPtr network; PyObject *pyobj_network; unsigned int flags; virNetworkDHCPLeasePtr *leases = NULL; int leases_count; char *mac = NULL; ssize_t i; if (!PyArg_ParseTuple(args, (char *) "OzI:virNetworkGetDHCPLeases", &pyobj_network, &mac, &flags)) return NULL; network = (virNetworkPtr) PyvirNetwork_Get(pyobj_network); LIBVIRT_BEGIN_ALLOW_THREADS; leases_count = virNetworkGetDHCPLeases(network, mac, &leases, flags); LIBVIRT_END_ALLOW_THREADS; if (leases_count < 0) { py_retval = VIR_PY_NONE; goto cleanup; } if (!(py_retval = PyList_New(leases_count))) goto error; for (i = 0; i < leases_count; i++) { virNetworkDHCPLeasePtr lease = leases[i]; if ((py_lease = PyDict_New()) == NULL) goto error; VIR_PY_LIST_SET_GOTO(py_retval, i, py_lease, error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("iface"), libvirt_charPtrWrap(lease->iface), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("expirytime"), libvirt_longlongWrap(lease->expirytime), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("type"), libvirt_intWrap(lease->type), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("mac"), libvirt_charPtrWrap(lease->mac), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("ipaddr"), libvirt_charPtrWrap(lease->ipaddr), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("prefix"), libvirt_uintWrap(lease->prefix), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("hostname"), libvirt_charPtrWrap(lease->hostname), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("clientid"), libvirt_charPtrWrap(lease->clientid), error); VIR_PY_DICT_SET_GOTO(py_lease, libvirt_constcharPtrWrap("iaid"), libvirt_charPtrWrap(lease->iaid), error); } cleanup: if (leases_count > 0) for (i = 0; i < leases_count; i++) virNetworkDHCPLeaseFree(leases[i]); VIR_FREE(leases); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(1, 2, 6) */ #if LIBVIR_CHECK_VERSION(1, 2, 8) static PyObject * convertDomainStatsRecord(virDomainStatsRecordPtr *records, int nrecords) { PyObject *py_retval; PyObject *py_record; PyObject *py_record_stats = NULL; virDomainPtr dom = NULL; ssize_t i; if (!(py_retval = PyList_New(nrecords))) return NULL; for (i = 0; i < nrecords; i++) { if (!(py_record = PyTuple_New(2))) goto error; VIR_PY_LIST_SET_GOTO(py_retval, i, py_record, error); dom = records[i]->dom; virDomainRef(dom); VIR_PY_TUPLE_SET_GOTO(py_record, 0, libvirt_virDomainPtrWrap(dom), error); dom = NULL; if (!(py_record_stats = getPyVirTypedParameter(records[i]->params, records[i]->nparams))) goto error; VIR_PY_TUPLE_SET_GOTO(py_record, 1, py_record_stats, error); } return py_retval; error: if (dom) virDomainFree(dom); Py_XDECREF(py_retval); return NULL; } static PyObject * libvirt_virConnectGetAllDomainStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval; virConnectPtr conn; virDomainStatsRecordPtr *records; int nrecords; unsigned int flags; unsigned int stats; if (!PyArg_ParseTuple(args, (char *)"OII:virConnectGetAllDomainStats", &pyobj_conn, &stats, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; nrecords = virConnectGetAllDomainStats(conn, stats, &records, flags); LIBVIRT_END_ALLOW_THREADS; if (nrecords < 0) return VIR_PY_NONE; py_retval = convertDomainStatsRecord(records, nrecords); virDomainStatsRecordListFree(records); return py_retval; } static PyObject * libvirt_virDomainListGetStats(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval; PyObject *py_domlist; virDomainStatsRecordPtr *records = NULL; virDomainPtr *doms = NULL; int nrecords; int ndoms; ssize_t i; unsigned int flags; unsigned int stats; if (!PyArg_ParseTuple(args, (char *)"OOII:virDomainListGetStats", &pyobj_conn, &py_domlist, &stats, &flags)) return NULL; if (PyList_Check(py_domlist)) { ndoms = PyList_Size(py_domlist); if (VIR_ALLOC_N(doms, ndoms + 1) < 0) return PyErr_NoMemory(); for (i = 0; i < ndoms; i++) doms[i] = PyvirDomain_Get(PyList_GetItem(py_domlist, i)); } LIBVIRT_BEGIN_ALLOW_THREADS; nrecords = virDomainListGetStats(doms, stats, &records, flags); LIBVIRT_END_ALLOW_THREADS; if (nrecords < 0) { py_retval = VIR_PY_NONE; goto cleanup; } py_retval = convertDomainStatsRecord(records, nrecords); cleanup: virDomainStatsRecordListFree(records); VIR_FREE(doms); return py_retval; } static virPyTypedParamsHint virPyDomainBlockCopyParams[] = { { VIR_DOMAIN_BLOCK_COPY_BANDWIDTH, VIR_TYPED_PARAM_ULLONG }, { VIR_DOMAIN_BLOCK_COPY_GRANULARITY, VIR_TYPED_PARAM_UINT }, { VIR_DOMAIN_BLOCK_COPY_BUF_SIZE, VIR_TYPED_PARAM_ULLONG }, }; static PyObject * libvirt_virDomainBlockCopy(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; PyObject *pyobj_dict = NULL; virDomainPtr dom; char *disk = NULL; char *destxml = NULL; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags = 0; int c_retval; if (!PyArg_ParseTuple(args, (char *) "Ozz|OI:virDomainBlockCopy", &pyobj_dom, &disk, &destxml, &pyobj_dict, &flags)) return NULL; if (PyDict_Check(pyobj_dict)) { if (virPyDictToTypedParams(pyobj_dict, ¶ms, &nparams, virPyDomainBlockCopyParams, VIR_N_ELEMENTS(virPyDomainBlockCopyParams)) < 0) { return NULL; } } else if (pyobj_dict != Py_None) { PyErr_Format(PyExc_TypeError, "block params must be a dictionary"); return NULL; } dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainBlockCopy(dom, disk, destxml, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(c_retval); } #endif /* LIBVIR_CHECK_VERSION(1, 2, 8) */ #if LIBVIR_CHECK_VERSION(1, 2, 9) static PyObject * libvirt_virNodeAllocPages(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *pyobj_pages; Py_ssize_t size = 0; Py_ssize_t pos = 0; PyObject *key, *value; virConnectPtr conn; unsigned int npages = 0; unsigned int *pageSizes = NULL; unsigned long long *pageCounts = NULL; int startCell = -1; unsigned int cellCount = 1; unsigned int flags = VIR_NODE_ALLOC_PAGES_ADD; int c_retval; if (!PyArg_ParseTuple(args, (char *)"OOiII:virNodeAllocPages", &pyobj_conn, &pyobj_pages, &startCell, &cellCount, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if ((size = PyDict_Size(pyobj_pages)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to pages attribute"); return NULL; } if (VIR_ALLOC_N(pageSizes, size) < 0 || VIR_ALLOC_N(pageCounts, size) < 0) { PyErr_NoMemory(); goto error; } while (PyDict_Next(pyobj_pages, &pos, &key, &value)) { if (libvirt_uintUnwrap(key, &pageSizes[npages]) < 0 || libvirt_ulonglongUnwrap(value, &pageCounts[npages]) < 0) goto error; npages++; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNodeAllocPages(conn, npages, pageSizes, pageCounts, startCell, cellCount, flags); LIBVIRT_END_ALLOW_THREADS; VIR_FREE(pageSizes); VIR_FREE(pageCounts); return libvirt_intWrap(c_retval); error: VIR_FREE(pageSizes); VIR_FREE(pageCounts); return NULL; } #endif /* LIBVIR_CHECK_VERSION(1, 2, 8) */ #if LIBVIR_CHECK_VERSION(1, 2, 11) static PyObject * libvirt_virDomainGetFSInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; unsigned int flags; virDomainFSInfoPtr *fsinfo = NULL; int c_retval, i; size_t j; PyObject *py_retval = NULL; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetFSInfo", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetFSInfo(domain, &fsinfo, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } /* convert to a Python list */ if ((py_retval = PyList_New(c_retval)) == NULL) goto error; for (i = 0; i < c_retval; i++) { virDomainFSInfoPtr fs = fsinfo[i]; PyObject *info, *alias; if (fs == NULL) goto error; info = PyTuple_New(4); if (info == NULL) goto error; VIR_PY_LIST_SET_GOTO(py_retval, i, info, error); VIR_PY_TUPLE_SET_GOTO(info, 0, libvirt_constcharPtrWrap(fs->mountpoint), error); VIR_PY_TUPLE_SET_GOTO(info, 1, libvirt_constcharPtrWrap(fs->name), error); VIR_PY_TUPLE_SET_GOTO(info, 2, libvirt_constcharPtrWrap(fs->fstype), error); alias = PyList_New(0); if (alias == NULL) goto error; VIR_PY_TUPLE_SET_GOTO(info, 3, alias, error); for (j = 0; j < fs->ndevAlias; j++) VIR_PY_LIST_APPEND_GOTO(alias, libvirt_constcharPtrWrap(fs->devAlias[j]), error); } cleanup: if (c_retval > 0) for (i = 0; i < c_retval; i++) virDomainFSInfoFree(fsinfo[i]); VIR_FREE(fsinfo); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(1, 2, 11) */ #if LIBVIR_CHECK_VERSION(1, 3, 3) static PyObject * libvirt_virDomainGetPerfEvents(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; virDomainPtr domain; virTypedParameterPtr params = NULL; int nparams = 0; PyObject *dict = NULL; unsigned int flags; int rc; if (!PyArg_ParseTuple(args, (char *) "OI:virDomainGetPerfEvents", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; rc = virDomainGetPerfEvents(domain, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (rc < 0) return VIR_PY_NONE; if (!(dict = getPyVirTypedParameter(params, nparams))) goto cleanup; cleanup: virTypedParamsFree(params, nparams); return dict; } static PyObject * libvirt_virDomainSetPerfEvents(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain, *info; PyObject *ret = NULL; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainSetPerfEvents", &pyobj_domain, &info, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetPerfEvents(domain, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_INT_FAIL; if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Domain has no settable attributes"); return NULL; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainSetPerfEvents(domain, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } #endif /* LIBVIR_CHECK_VERSION(1, 3, 3) */ #if LIBVIR_CHECK_VERSION(2, 0, 0) static void libvirt_virConnectStoragePoolEventFreeFunc(void *opaque) { PyObject *pyobj_conn = (PyObject*)opaque; LIBVIRT_ENSURE_THREAD_STATE; Py_DECREF(pyobj_conn); LIBVIRT_RELEASE_THREAD_STATE; } static int libvirt_virConnectStoragePoolEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolPtr pool, int event, int detail, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_pool; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virStoragePoolPtr */ virStoragePoolRef(pool); if (!(pyobj_pool = libvirt_virStoragePoolPtrWrap(pool))) { virStoragePoolFree(pool); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchStoragePoolEventLifecycleCallback", (char*)"OiiO", pyobj_pool, event, detail, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_pool); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectStoragePoolEventGenericCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolPtr pool, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_pool; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virStoragePoolPtr */ virStoragePoolRef(pool); if (!(pyobj_pool = libvirt_virStoragePoolPtrWrap(pool))) { virStoragePoolFree(pool); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchStoragePoolEventGenericCallback", (char*)"OO", pyobj_pool, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_pool); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static PyObject * libvirt_virConnectStoragePoolEventRegisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; /* virConnectPtr */ PyObject *pyobj_pool; PyObject *pyobj_cbData; /* hash of callback data */ int eventID; virConnectPtr conn; int ret = 0; virConnectStoragePoolEventGenericCallback cb = NULL; virStoragePoolPtr pool; if (!PyArg_ParseTuple(args, (char *) "OOiO:virConnectStoragePoolEventRegisterAny", &pyobj_conn, &pyobj_pool, &eventID, &pyobj_cbData)) return NULL; DEBUG("libvirt_virConnectStoragePoolEventRegister(%p %p %d %p) called\n", pyobj_conn, pyobj_pool, eventID, pyobj_cbData); conn = PyvirConnect_Get(pyobj_conn); if (pyobj_pool == Py_None) pool = NULL; else pool = PyvirStoragePool_Get(pyobj_pool); switch ((virStoragePoolEventID) eventID) { case VIR_STORAGE_POOL_EVENT_ID_LIFECYCLE: cb = VIR_STORAGE_POOL_EVENT_CALLBACK(libvirt_virConnectStoragePoolEventLifecycleCallback); break; case VIR_STORAGE_POOL_EVENT_ID_REFRESH: cb = VIR_STORAGE_POOL_EVENT_CALLBACK(libvirt_virConnectStoragePoolEventGenericCallback); break; case VIR_STORAGE_POOL_EVENT_ID_LAST: break; } if (!cb) { return VIR_PY_INT_FAIL; } Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectStoragePoolEventRegisterAny(conn, pool, eventID, cb, pyobj_cbData, libvirt_virConnectStoragePoolEventFreeFunc); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static PyObject * libvirt_virConnectStoragePoolEventDeregisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; int callbackID; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "Oi:virConnectStoragePoolEventDeregisterAny", &pyobj_conn, &callbackID)) return NULL; DEBUG("libvirt_virConnectStoragePoolEventDeregister(%p) called\n", pyobj_conn); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectStoragePoolEventDeregisterAny(conn, callbackID); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(ret); } static PyObject * libvirt_virDomainGetGuestVcpus(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; virDomainPtr domain; virTypedParameterPtr params = NULL; unsigned int nparams = 0; unsigned int flags; int i_retval; PyObject *ret = NULL; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetGuestVcpus", &pyobj_domain, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetGuestVcpus(domain, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } #endif /* LIBVIR_CHECK_VERSION(2, 0, 0)*/ #if LIBVIR_CHECK_VERSION(2, 2, 0) static void libvirt_virConnectNodeDeviceEventFreeFunc(void *opaque) { PyObject *pyobj_conn = (PyObject*)opaque; LIBVIRT_ENSURE_THREAD_STATE; Py_DECREF(pyobj_conn); LIBVIRT_RELEASE_THREAD_STATE; } static int libvirt_virConnectNodeDeviceEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeDevicePtr dev, int event, int detail, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dev; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virNodeDevicePtr */ virNodeDeviceRef(dev); if (!(pyobj_dev = libvirt_virNodeDevicePtrWrap(dev))) { virNodeDeviceFree(dev); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchNodeDeviceEventLifecycleCallback", (char*)"OiiO", pyobj_dev, event, detail, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dev); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectNodeDeviceEventGenericCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeDevicePtr dev, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dev; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virNodeDevicePtr */ virNodeDeviceRef(dev); if (!(pyobj_dev = libvirt_virNodeDevicePtrWrap(dev))) { virNodeDeviceFree(dev); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchNodeDeviceEventGenericCallback", (char*)"OO", pyobj_dev, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dev); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static PyObject * libvirt_virConnectNodeDeviceEventRegisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; /* virConnectPtr */ PyObject *pyobj_dev; PyObject *pyobj_cbData; /* hash of callback data */ int eventID; virConnectPtr conn; int ret = 0; virConnectNodeDeviceEventGenericCallback cb = NULL; virNodeDevicePtr dev; if (!PyArg_ParseTuple(args, (char *) "OOiO:virConnectNodeDeviceEventRegisterAny", &pyobj_conn, &pyobj_dev, &eventID, &pyobj_cbData)) return NULL; DEBUG("libvirt_virConnectNodeDeviceEventRegister(%p %p %d %p) called\n", pyobj_conn, pyobj_dev, eventID, pyobj_cbData); conn = PyvirConnect_Get(pyobj_conn); if (pyobj_dev == Py_None) dev = NULL; else dev = PyvirNodeDevice_Get(pyobj_dev); switch ((virNodeDeviceEventID) eventID) { case VIR_NODE_DEVICE_EVENT_ID_LIFECYCLE: cb = VIR_NODE_DEVICE_EVENT_CALLBACK(libvirt_virConnectNodeDeviceEventLifecycleCallback); break; case VIR_NODE_DEVICE_EVENT_ID_UPDATE: cb = VIR_NODE_DEVICE_EVENT_CALLBACK(libvirt_virConnectNodeDeviceEventGenericCallback); break; case VIR_NODE_DEVICE_EVENT_ID_LAST: break; } if (!cb) { return VIR_PY_INT_FAIL; } Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectNodeDeviceEventRegisterAny(conn, dev, eventID, cb, pyobj_cbData, libvirt_virConnectNodeDeviceEventFreeFunc); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static PyObject * libvirt_virConnectNodeDeviceEventDeregisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; int callbackID; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "Oi:virConnectNodeDeviceEventDeregister", &pyobj_conn, &callbackID)) return NULL; DEBUG("libvirt_virConnectNodeDeviceEventDeregister(%p) called\n", pyobj_conn); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectNodeDeviceEventDeregisterAny(conn, callbackID); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(ret); } #endif /* LIBVIR_CHECK_VERSION(2, 2, 0)*/ #if LIBVIR_CHECK_VERSION(3, 0, 0) static void libvirt_virConnectSecretEventFreeFunc(void *opaque) { PyObject *pyobj_conn = (PyObject*)opaque; LIBVIRT_ENSURE_THREAD_STATE; Py_DECREF(pyobj_conn); LIBVIRT_RELEASE_THREAD_STATE; } static int libvirt_virConnectSecretEventLifecycleCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virSecretPtr secret, int event, int detail, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_secret; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virSecretPtr */ virSecretRef(secret); if (!(pyobj_secret = libvirt_virSecretPtrWrap(secret))) { virSecretFree(secret); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchSecretEventLifecycleCallback", (char*)"OiiO", pyobj_secret, event, detail, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_secret); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static int libvirt_virConnectSecretEventGenericCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virSecretPtr secret, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_secret; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; int ret = -1; LIBVIRT_ENSURE_THREAD_STATE; if (!(dictKey = libvirt_constcharPtrWrap("conn"))) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virSecretPtr */ virSecretRef(secret); if (!(pyobj_secret = libvirt_virSecretPtrWrap(secret))) { virSecretFree(secret); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallMethod(pyobj_conn, (char*)"_dispatchSecretEventGenericCallback", (char*)"OO", pyobj_secret, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_secret); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); ret = 0; } LIBVIRT_RELEASE_THREAD_STATE; return ret; } static PyObject * libvirt_virConnectSecretEventRegisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; /* virConnectPtr */ PyObject *pyobj_secret; PyObject *pyobj_cbData; /* hash of callback data */ int eventID; virConnectPtr conn; int ret = 0; virConnectSecretEventGenericCallback cb = NULL; virSecretPtr secret; if (!PyArg_ParseTuple(args, (char *) "OOiO:virConnectSecretEventRegisterAny", &pyobj_conn, &pyobj_secret, &eventID, &pyobj_cbData)) return NULL; DEBUG("libvirt_virConnectSecretEventRegister(%p %p %d %p) called\n", pyobj_conn, pyobj_secret, eventID, pyobj_cbData); conn = PyvirConnect_Get(pyobj_conn); if (pyobj_secret == Py_None) secret = NULL; else secret = PyvirSecret_Get(pyobj_secret); switch ((virSecretEventID) eventID) { case VIR_SECRET_EVENT_ID_LIFECYCLE: cb = VIR_SECRET_EVENT_CALLBACK(libvirt_virConnectSecretEventLifecycleCallback); break; case VIR_SECRET_EVENT_ID_VALUE_CHANGED: cb = VIR_SECRET_EVENT_CALLBACK(libvirt_virConnectSecretEventGenericCallback); break; case VIR_SECRET_EVENT_ID_LAST: break; } if (!cb) { return VIR_PY_INT_FAIL; } Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectSecretEventRegisterAny(conn, secret, eventID, cb, pyobj_cbData, libvirt_virConnectSecretEventFreeFunc); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } return libvirt_intWrap(ret); } static PyObject * libvirt_virConnectSecretEventDeregisterAny(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; int callbackID; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "Oi:virConnectSecretEventDeregister", &pyobj_conn, &callbackID)) return NULL; DEBUG("libvirt_virConnectSecretEventDeregister(%p) called\n", pyobj_conn); conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectSecretEventDeregisterAny(conn, callbackID); LIBVIRT_END_ALLOW_THREADS; return libvirt_intWrap(ret); } #endif /* LIBVIR_CHECK_VERSION(3, 0, 0)*/ #if LIBVIR_CHECK_VERSION(3, 4, 0) static PyObject * libvirt_virStreamRecvHole(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_stream; virStreamPtr stream; long long length = -1; unsigned int flags; int ret; if (!PyArg_ParseTuple(args, (char *) "OI:virStreamRecvHole", &pyobj_stream, &flags)) return NULL; stream = PyvirStream_Get(pyobj_stream); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virStreamRecvHole(stream, &length, flags); LIBVIRT_END_ALLOW_THREADS; DEBUG("StreamRecvHole ret=%d length=%lld\n", ret, length); if (ret < 0) return VIR_PY_NONE; return libvirt_longlongWrap(length); } static PyObject * libvirt_virStreamSendHole(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_stream; virStreamPtr stream; long long length; unsigned int flags; int ret; if (!PyArg_ParseTuple(args, (char *) "OLI:virStreamSendHole", &pyobj_stream, &length, &flags)) return NULL; stream = PyvirStream_Get(pyobj_stream); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virStreamSendHole(stream, length, flags); LIBVIRT_END_ALLOW_THREADS; DEBUG("StreamSendHole ret=%d\n", ret); return libvirt_intWrap(ret); } static PyObject * libvirt_virStreamRecvFlags(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_stream; PyObject *rv; virStreamPtr stream; char *buf = NULL; size_t nbytes; unsigned int flags; int ret; if (!PyArg_ParseTuple(args, (char *) "OkI:virStreamRecvFlags", &pyobj_stream, &nbytes, &flags)) return NULL; stream = PyvirStream_Get(pyobj_stream); if (VIR_ALLOC_N(buf, nbytes + 1) < 0) return PyErr_NoMemory(); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virStreamRecvFlags(stream, buf, nbytes, flags); LIBVIRT_END_ALLOW_THREADS; buf[ret > -1 ? ret : 0] = '\0'; DEBUG("StreamRecvFlags ret=%d strlen=%zu\n", ret, strlen(buf)); if (ret == -2 || ret == -3) { rv = libvirt_intWrap(ret); } else if (ret < 0) { rv = VIR_PY_NONE; } else { rv = libvirt_charPtrSizeWrap((char *) buf, (Py_ssize_t) ret); } VIR_FREE(buf); return rv; } #endif /* LIBVIR_CHECK_VERSION(3, 4, 0) */ #if LIBVIR_CHECK_VERSION(4, 4, 0) static PyObject * libvirt_virConnectBaselineHypervisorCPU(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virConnectPtr conn; PyObject *pyobj_conn; char *emulator; char *arch; char *machine; char *virttype; PyObject *list; unsigned int flags; char **xmlCPUs = NULL; int ncpus = 0; ssize_t i; char *cpu; PyObject *ret = NULL; if (!PyArg_ParseTuple(args, (char *)"OzzzzOI:virConnectBaselineHypervisorCPU", &pyobj_conn, &emulator, &arch, &machine, &virttype, &list, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if (PyList_Check(list)) { ncpus = PyList_Size(list); if (VIR_ALLOC_N(xmlCPUs, ncpus) < 0) return PyErr_NoMemory(); for (i = 0; i < ncpus; i++) { if (libvirt_charPtrUnwrap(PyList_GetItem(list, i), &(xmlCPUs[i])) < 0) goto cleanup; } } LIBVIRT_BEGIN_ALLOW_THREADS; cpu = virConnectBaselineHypervisorCPU(conn, emulator, arch, machine, virttype, (const char **)xmlCPUs, ncpus, flags); LIBVIRT_END_ALLOW_THREADS; ret = libvirt_constcharPtrWrap(cpu); cleanup: for (i = 0; i < ncpus; i++) VIR_FREE(xmlCPUs[i]); VIR_FREE(xmlCPUs); VIR_FREE(cpu); return ret; } #endif /* LIBVIR_CHECK_VERSION(4, 4, 0) */ #if LIBVIR_CHECK_VERSION(4, 5, 0) static PyObject * libvirt_virDomainGetLaunchSecurityInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; PyObject *ret = NULL; virDomainPtr dom = NULL; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags = 0; int i_retval; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetLaunchSecurityInfo", &pyobj_dom, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } static PyObject * libvirt_virNodeGetSEVInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn = NULL; PyObject *ret = NULL; virConnectPtr conn = NULL; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags = 0; int i_retval; if (!PyArg_ParseTuple(args, (char *)"OI:virNodeGetSEVInfo", &pyobj_conn, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNodeGetSEVInfo(conn, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_NONE; goto cleanup; } ret = getPyVirTypedParameter(params, nparams); cleanup: virTypedParamsFree(params, nparams); return ret; } #endif /* LIBVIR_CHECK_VERSION(4, 5, 0) */ #if LIBVIR_CHECK_VERSION(5, 5, 0) static PyObject * libvirt_virNetworkListAllPorts(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn; PyObject *py_retval = NULL; virNetworkPtr conn; virNetworkPortPtr *doms = NULL; int c_retval = 0; ssize_t i; unsigned int flags; if (!PyArg_ParseTuple(args, (char *)"OI:virNetworkListAllPorts", &pyobj_conn, &flags)) return NULL; conn = (virNetworkPtr) PyvirNetwork_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkListAllPorts(conn, &doms, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; if (!(py_retval = PyList_New(c_retval))) goto cleanup; for (i = 0; i < c_retval; i++) { VIR_PY_LIST_SET_GOTO(py_retval, i, libvirt_virNetworkPortPtrWrap(doms[i]), error); /* python steals the pointer */ doms[i] = NULL; } cleanup: for (i = 0; i < c_retval; i++) if (doms[i]) virNetworkPortFree(doms[i]); VIR_FREE(doms); return py_retval; error: Py_CLEAR(py_retval); goto cleanup; } static PyObject * libvirt_virNetworkPortSetParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virNetworkPortPtr port; PyObject *pyobj_port, *info; PyObject *ret = NULL; int i_retval; int nparams = 0; Py_ssize_t size = 0; unsigned int flags; virTypedParameterPtr params = NULL, new_params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virNetworkPortSetParameters", &pyobj_port, &info, &flags)) return NULL; port = (virNetworkPortPtr) PyvirNetworkPort_Get(pyobj_port); if ((size = PyDict_Size(info)) < 0) return NULL; if (size == 0) { PyErr_Format(PyExc_LookupError, "Need non-empty dictionary to set attributes"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNetworkPortGetParameters(port, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) return VIR_PY_INT_FAIL; if (nparams == 0) { PyErr_Format(PyExc_LookupError, "Port has no settable attributes"); return NULL; } new_params = setPyVirTypedParameter(info, params, nparams); if (!new_params) goto cleanup; LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virNetworkPortSetParameters(port, new_params, size, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); virTypedParamsFree(new_params, size); return ret; } static PyObject * libvirt_virNetworkPortGetParameters(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_port; virNetworkPortPtr port; virTypedParameterPtr params = NULL; int nparams = 0; PyObject *dict = NULL; unsigned int flags; int rc; if (!PyArg_ParseTuple(args, (char *) "OI:virNetworkPortGetParameters", &pyobj_port, &flags)) return NULL; port = (virNetworkPortPtr) PyvirNetworkPort_Get(pyobj_port); LIBVIRT_BEGIN_ALLOW_THREADS; rc = virNetworkPortGetParameters(port, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (rc < 0) return VIR_PY_NONE; dict = getPyVirTypedParameter(params, nparams); virTypedParamsFree(params, nparams); return dict; } static PyObject * libvirt_virNetworkPortGetUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { unsigned char uuid[VIR_UUID_BUFLEN]; virNetworkPortPtr port; PyObject *pyobj_port; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virNetworkPortGetUUID", &pyobj_port)) return NULL; port = (virNetworkPortPtr) PyvirNetworkPort_Get(pyobj_port); if (port == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkPortGetUUID(port, &uuid[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_charPtrSizeWrap((char *) &uuid[0], VIR_UUID_BUFLEN); } static PyObject * libvirt_virNetworkPortGetUUIDString(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virNetworkPortPtr port; PyObject *pyobj_port; int c_retval; if (!PyArg_ParseTuple(args, (char *)"O:virNetworkPortGetUUIDString", &pyobj_port)) return NULL; port = (virNetworkPortPtr) PyvirNetworkPort_Get(pyobj_port); if (port == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkPortGetUUIDString(port, &uuidstr[0]); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; return libvirt_constcharPtrWrap((char *) &uuidstr[0]); } static PyObject * libvirt_virNetworkPortLookupByUUID(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virNetworkPortPtr c_retval; virNetworkPtr net; PyObject *pyobj_net; unsigned char *uuid; Py_ssize_t len; if (!PyArg_ParseTuple(args, (char *)"Oz#:virNetworkPortLookupByUUID", &pyobj_net, &uuid, &len)) return NULL; net = (virNetworkPtr) PyvirNetwork_Get(pyobj_net); if ((uuid == NULL) || (len != VIR_UUID_BUFLEN)) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virNetworkPortLookupByUUID(net, uuid); LIBVIRT_END_ALLOW_THREADS; return libvirt_virNetworkPortPtrWrap((virNetworkPortPtr) c_retval); } #endif /* LIBVIR_CHECK_VERSION(5, 5, 0) */ #if LIBVIR_CHECK_VERSION(5, 7, 0) static PyObject * libvirt_virDomainGetGuestInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; PyObject *dict = NULL; virDomainPtr dom = NULL; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int types; unsigned int flags; int rc; if (!PyArg_ParseTuple(args, (char *) "OII:virDomainGetGuestInfo", &pyobj_dom, &types, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; rc = virDomainGetGuestInfo(dom, types, ¶ms, &nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (rc < 0) return VIR_PY_NONE; dict = getPyVirTypedParameter(params, nparams); virTypedParamsFree(params, nparams); return dict; } #endif /* LIBVIR_CHECK_VERSION(5, 7, 0) */ #if LIBVIR_CHECK_VERSION(5, 8, 0) static virPyTypedParamsHint virPyConnectSetIdentityParams[] = { { VIR_CONNECT_IDENTITY_USER_NAME, VIR_TYPED_PARAM_STRING }, { VIR_CONNECT_IDENTITY_UNIX_USER_ID, VIR_TYPED_PARAM_ULLONG }, { VIR_CONNECT_IDENTITY_GROUP_NAME, VIR_TYPED_PARAM_STRING }, { VIR_CONNECT_IDENTITY_UNIX_GROUP_ID, VIR_TYPED_PARAM_ULLONG }, { VIR_CONNECT_IDENTITY_PROCESS_ID, VIR_TYPED_PARAM_LLONG }, { VIR_CONNECT_IDENTITY_PROCESS_TIME, VIR_TYPED_PARAM_ULLONG }, { VIR_CONNECT_IDENTITY_SASL_USER_NAME, VIR_TYPED_PARAM_STRING }, { VIR_CONNECT_IDENTITY_X509_DISTINGUISHED_NAME, VIR_TYPED_PARAM_STRING }, { VIR_CONNECT_IDENTITY_SELINUX_CONTEXT, VIR_TYPED_PARAM_STRING }, }; static PyObject * libvirt_virConnectSetIdentity(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virConnectPtr conn; PyObject *pyobj_conn, *dict; PyObject *ret = NULL; int i_retval; int nparams = 0; unsigned int flags; virTypedParameterPtr params = NULL; if (!PyArg_ParseTuple(args, (char *)"OOI:virConnectSetIdentity", &pyobj_conn, &dict, &flags)) return NULL; conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); if (!PyDict_Check(dict)) { PyErr_Format(PyExc_TypeError, "migration params must be a dictionary"); return NULL; } if (virPyDictToTypedParams(dict, ¶ms, &nparams, virPyConnectSetIdentityParams, VIR_N_ELEMENTS(virPyConnectSetIdentityParams)) < 0) { return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; i_retval = virConnectSetIdentity(conn, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; if (i_retval < 0) { ret = VIR_PY_INT_FAIL; goto cleanup; } ret = VIR_PY_INT_SUCCESS; cleanup: virTypedParamsFree(params, nparams); return ret; } #endif /* LIBVIR_CHECK_VERSION(5, 8, 0) */ #if LIBVIR_CHECK_VERSION(6, 10, 0) static PyObject * libvirt_virDomainAuthorizedSSHKeysGet(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; virDomainPtr dom = NULL; const char *user = NULL; char **keys = NULL; int nkeys; int i; unsigned int flags; PyObject *ret = NULL; if (!PyArg_ParseTuple(args, (char *)"OsI:virDomainAuthorizedSSHKeysGet", &pyobj_dom, &user, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; nkeys = virDomainAuthorizedSSHKeysGet(dom, user, &keys, flags); LIBVIRT_END_ALLOW_THREADS; if (nkeys < 0) return VIR_PY_NONE; if ((ret = PyList_New(nkeys)) == NULL) goto error; for (i = 0; i < nkeys; i++) VIR_PY_LIST_SET_GOTO(ret, i, libvirt_constcharPtrWrap(keys[i]), error); done: for (i = 0; i < nkeys; i++) VIR_FREE(keys[i]); VIR_FREE(keys); return ret; error: Py_CLEAR(ret); goto done; } static PyObject * libvirt_virDomainAuthorizedSSHKeysSet(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; virDomainPtr dom = NULL; const char *user = NULL; PyObject *pyobj_keys = NULL; char **keys = NULL; int nkeys = 0; int i; unsigned int flags; int c_retval; PyObject *py_retval = NULL; if (!PyArg_ParseTuple(args, (char *)"OsOI:virDomainAuthorizedSSHKeysSet", &pyobj_dom, &user, &pyobj_keys, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); if (PyList_Check(pyobj_keys)) { nkeys = PyList_Size(pyobj_keys); if (VIR_ALLOC_N(keys, nkeys) < 0) return PyErr_NoMemory(); for (i = 0; i < nkeys; i++) { if (libvirt_charPtrUnwrap(PyList_GetItem(pyobj_keys, i), &(keys[i])) < 0) goto cleanup; } } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainAuthorizedSSHKeysSet(dom, user, (const char **)keys, nkeys, flags); LIBVIRT_END_ALLOW_THREADS; py_retval = libvirt_intWrap(c_retval); cleanup: for (i = 0 ; i < nkeys ; i++) VIR_FREE(keys[i]); VIR_FREE(keys); return py_retval; } #endif /* LIBVIR_CHECK_VERSION(6, 10, 0) */ #if LIBVIR_CHECK_VERSION(7, 1, 0) static PyObject * libvirt_virDomainGetMessages(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; virDomainPtr dom = NULL; char **msgs = NULL; int nmsgs; int i; unsigned int flags; PyObject *ret = NULL; if (!PyArg_ParseTuple(args, (char *)"OI:virDomainGetMessages", &pyobj_dom, &flags)) return NULL; dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; nmsgs = virDomainGetMessages(dom, &msgs, flags); LIBVIRT_END_ALLOW_THREADS; if (nmsgs < 0) return VIR_PY_NONE; if ((ret = PyList_New(nmsgs)) == NULL) goto error; for (i = 0; i < nmsgs; i++) VIR_PY_LIST_SET_GOTO(ret, i, libvirt_constcharPtrWrap(msgs[i]), error); done: for (i = 0; i < nmsgs; i++) VIR_FREE(msgs[i]); VIR_FREE(msgs); return ret; error: Py_CLEAR(ret); goto done; } #endif /* LIBVIR_CHECK_VERSION(7, 1, 0) */ #if LIBVIR_CHECK_VERSION(8, 0, 0) static virPyTypedParamsHint virPyDomainSetLaunchSecurityStateParams[] = { { VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET, VIR_TYPED_PARAM_STRING }, { VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_HEADER, VIR_TYPED_PARAM_STRING }, { VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_SET_ADDRESS, VIR_TYPED_PARAM_ULLONG }, }; static PyObject * libvirt_virDomainSetLaunchSecurityState(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; PyObject *pyobj_dict = NULL; virDomainPtr dom; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags; int c_retval; if (!PyArg_ParseTuple(args, (char *)"OOI:virDomainSetLaunchSecurityState", &pyobj_dom, &pyobj_dict, &flags)) return NULL; if (PyDict_Check(pyobj_dict)) { if (virPyDictToTypedParams(pyobj_dict, ¶ms, &nparams, virPyDomainSetLaunchSecurityStateParams, VIR_N_ELEMENTS(virPyDomainSetLaunchSecurityStateParams)) < 0) { return NULL; } } else { PyErr_Format(PyExc_TypeError, "Launch security state params must be " "a dictionary"); return NULL; } dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSetLaunchSecurityState(dom, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(c_retval); } #endif /* LIBVIR_CHECK_VERSION(8, 0, 0) */ #if LIBVIR_CHECK_VERSION(8, 4, 0) static virPyTypedParamsHint virPyDomainSaveParams[] = { { VIR_DOMAIN_SAVE_PARAM_FILE, VIR_TYPED_PARAM_STRING }, { VIR_DOMAIN_SAVE_PARAM_DXML, VIR_TYPED_PARAM_STRING }, }; static PyObject * libvirt_virDomainSaveParams(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_dom = NULL; PyObject *pyobj_dict = NULL; virDomainPtr dom; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags = 0; int c_retval; if (!PyArg_ParseTuple(args, (char *)"OO|I:virDomainSaveParams", &pyobj_dom, &pyobj_dict, &flags)) return NULL; if (PyDict_Check(pyobj_dict)) { if (virPyDictToTypedParams(pyobj_dict, ¶ms, &nparams, virPyDomainSaveParams, VIR_N_ELEMENTS(virPyDomainSaveParams)) < 0) { return NULL; } } else { PyErr_Format(PyExc_TypeError, "Save params must be a dictionary"); return NULL; } dom = (virDomainPtr) PyvirDomain_Get(pyobj_dom); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSaveParams(dom, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(c_retval); } static PyObject * libvirt_virDomainRestoreParams(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_conn = NULL; PyObject *pyobj_dict = NULL; virConnectPtr conn; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags = 0; int c_retval; if (!PyArg_ParseTuple(args, (char *)"OO|I:virDomainRestoreParams", &pyobj_conn, &pyobj_dict, &flags)) return NULL; if (PyDict_Check(pyobj_dict)) { if (virPyDictToTypedParams(pyobj_dict, ¶ms, &nparams, virPyDomainSaveParams, VIR_N_ELEMENTS(virPyDomainSaveParams)) < 0) { return NULL; } } else { PyErr_Format(PyExc_TypeError, "Restore params must be a dictionary"); return NULL; } conn = (virConnectPtr) PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainRestoreParams(conn, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(c_retval); } #endif /* LIBVIR_CHECK_VERSION(8, 4, 0) */ #if LIBVIR_CHECK_VERSION(9, 0, 0) static PyObject * libvirt_virDomainFDAssociate(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval = NULL; int c_retval; virDomainPtr domain; PyObject *pyobj_domain; PyObject *pyobj_files; const char *name = NULL; unsigned int flags; unsigned int nfiles; int *files = NULL; size_t i; if (!PyArg_ParseTuple(args, (char *)"OsOI:virDomainFDAssociate", &pyobj_domain, &name, &pyobj_files, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); nfiles = PyList_Size(pyobj_files); if (VIR_ALLOC_N(files, nfiles) < 0) return PyErr_NoMemory(); for (i = 0; i < nfiles; i++) { PyObject *pyfd; int fd; pyfd = PyList_GetItem(pyobj_files, i); if (libvirt_intUnwrap(pyfd, &fd) < 0) goto cleanup; files[i] = fd; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainFDAssociate(domain, name, nfiles, files, flags); LIBVIRT_END_ALLOW_THREADS; py_retval = libvirt_intWrap(c_retval); cleanup: VIR_FREE(files); return py_retval; } #endif /* LIBVIR_CHECK_VERSION(9, 0, 0) */ #if LIBVIR_CHECK_VERSION(11, 2, 0) static PyObject * libvirt_virDomainGetAutostartOnce(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { int c_retval, autostart; virDomainPtr domain; PyObject *pyobj_domain; if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetAutostartOnce", &pyobj_domain)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainGetAutostartOnce(domain, &autostart); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_INT_FAIL; return libvirt_intWrap(autostart); } static PyObject * libvirt_virDomainSetThrottleGroup(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { virDomainPtr domain; PyObject *pyobj_domain; const char *group = NULL; PyObject *pyobj_dict = NULL; virTypedParameterPtr params = NULL; int nparams = 0; unsigned int flags = 0; int c_retval; if (!PyArg_ParseTuple(args, (char *)"OsO|I:virDomainSetThrottleGroup", &pyobj_domain, &group, &pyobj_dict, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (PyDict_Check(pyobj_dict)) { if (virPyDictToTypedParams(pyobj_dict, ¶ms, &nparams, virPyDomainSetBlockIoTuneParams, VIR_N_ELEMENTS(virPyDomainSetBlockIoTuneParams)) < 0) { return NULL; } } else { PyErr_Format(PyExc_TypeError, "Restore params must be a dictionary"); return NULL; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainSetThrottleGroup(domain, group, params, nparams, flags); LIBVIRT_END_ALLOW_THREADS; virTypedParamsFree(params, nparams); return libvirt_intWrap(c_retval); } #endif /* LIBVIR_CHECK_VERSION(11, 2, 0) */ /************************************************************************ * * * The registration stuff * * * ************************************************************************/ static PyMethodDef libvirtMethods[] = { #include "libvirt-export.c.inc" {(char *) "virGetVersion", libvirt_virGetVersion, METH_VARARGS, NULL}, {(char *) "virConnectGetVersion", libvirt_virConnectGetVersion, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(1, 1, 3) {(char *) "virConnectGetCPUModelNames", libvirt_virConnectGetCPUModelNames, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 1, 3) */ {(char *) "virConnectGetLibVersion", libvirt_virConnectGetLibVersion, METH_VARARGS, NULL}, {(char *) "virConnectOpenAuth", libvirt_virConnectOpenAuth, METH_VARARGS, NULL}, {(char *) "virConnectListDomainsID", libvirt_virConnectListDomainsID, METH_VARARGS, NULL}, {(char *) "virConnectListDefinedDomains", libvirt_virConnectListDefinedDomains, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 9, 13) {(char *) "virConnectListAllDomains", libvirt_virConnectListAllDomains, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 9, 13) */ {(char *) "virConnectDomainEventRegister", libvirt_virConnectDomainEventRegister, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventDeregister", libvirt_virConnectDomainEventDeregister, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventRegisterAny", libvirt_virConnectDomainEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectDomainEventDeregisterAny", libvirt_virConnectDomainEventDeregisterAny, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(1, 2, 1) {(char *) "virConnectNetworkEventRegisterAny", libvirt_virConnectNetworkEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectNetworkEventDeregisterAny", libvirt_virConnectNetworkEventDeregisterAny, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 1) */ #if LIBVIR_CHECK_VERSION(0, 10, 0) {(char *) "virConnectRegisterCloseCallback", libvirt_virConnectRegisterCloseCallback, METH_VARARGS, NULL}, {(char *) "virConnectUnregisterCloseCallback", libvirt_virConnectUnregisterCloseCallback, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ {(char *) "virStreamEventAddCallback", libvirt_virStreamEventAddCallback, METH_VARARGS, NULL}, {(char *) "virStreamRecv", libvirt_virStreamRecv, METH_VARARGS, NULL}, {(char *) "virStreamSend", libvirt_virStreamSend, METH_VARARGS, NULL}, {(char *) "virDomainGetInfo", libvirt_virDomainGetInfo, METH_VARARGS, NULL}, {(char *) "virDomainGetState", libvirt_virDomainGetState, METH_VARARGS, NULL}, {(char *) "virDomainGetControlInfo", libvirt_virDomainGetControlInfo, METH_VARARGS, NULL}, {(char *) "virDomainGetBlockInfo", libvirt_virDomainGetBlockInfo, METH_VARARGS, NULL}, {(char *) "virNodeGetInfo", libvirt_virNodeGetInfo, METH_VARARGS, NULL}, {(char *) "virNodeGetSecurityModel", libvirt_virNodeGetSecurityModel, METH_VARARGS, NULL}, {(char *) "virDomainGetSecurityLabel", libvirt_virDomainGetSecurityLabel, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 0) {(char *) "virDomainGetSecurityLabelList", libvirt_virDomainGetSecurityLabelList, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ {(char *) "virNodeGetCPUStats", libvirt_virNodeGetCPUStats, METH_VARARGS, NULL}, {(char *) "virNodeGetMemoryStats", libvirt_virNodeGetMemoryStats, METH_VARARGS, NULL}, {(char *) "virDomainGetUUID", libvirt_virDomainGetUUID, METH_VARARGS, NULL}, {(char *) "virDomainGetUUIDString", libvirt_virDomainGetUUIDString, METH_VARARGS, NULL}, {(char *) "virDomainLookupByUUID", libvirt_virDomainLookupByUUID, METH_VARARGS, NULL}, {(char *) "virRegisterErrorHandler", libvirt_virRegisterErrorHandler, METH_VARARGS, NULL}, {(char *) "virGetLastError", libvirt_virGetLastError, METH_VARARGS, NULL}, {(char *) "virConnGetLastError", libvirt_virConnGetLastError, METH_VARARGS, NULL}, {(char *) "virConnectListNetworks", libvirt_virConnectListNetworks, METH_VARARGS, NULL}, {(char *) "virConnectListDefinedNetworks", libvirt_virConnectListDefinedNetworks, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virConnectListAllNetworks", libvirt_virConnectListAllNetworks, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ {(char *) "virNetworkGetUUID", libvirt_virNetworkGetUUID, METH_VARARGS, NULL}, {(char *) "virNetworkGetUUIDString", libvirt_virNetworkGetUUIDString, METH_VARARGS, NULL}, {(char *) "virNetworkLookupByUUID", libvirt_virNetworkLookupByUUID, METH_VARARGS, NULL}, {(char *) "virDomainGetAutostart", libvirt_virDomainGetAutostart, METH_VARARGS, NULL}, {(char *) "virNetworkGetAutostart", libvirt_virNetworkGetAutostart, METH_VARARGS, NULL}, {(char *) "virDomainBlockStats", libvirt_virDomainBlockStats, METH_VARARGS, NULL}, {(char *) "virDomainBlockStatsFlags", libvirt_virDomainBlockStatsFlags, METH_VARARGS, NULL}, {(char *) "virDomainGetCPUStats", libvirt_virDomainGetCPUStats, METH_VARARGS, NULL}, {(char *) "virDomainInterfaceStats", libvirt_virDomainInterfaceStats, METH_VARARGS, NULL}, {(char *) "virDomainMemoryStats", libvirt_virDomainMemoryStats, METH_VARARGS, NULL}, {(char *) "virNodeGetCellsFreeMemory", libvirt_virNodeGetCellsFreeMemory, METH_VARARGS, NULL}, {(char *) "virDomainGetSchedulerType", libvirt_virDomainGetSchedulerType, METH_VARARGS, NULL}, {(char *) "virDomainGetSchedulerParameters", libvirt_virDomainGetSchedulerParameters, METH_VARARGS, NULL}, {(char *) "virDomainGetSchedulerParametersFlags", libvirt_virDomainGetSchedulerParametersFlags, METH_VARARGS, NULL}, {(char *) "virDomainSetSchedulerParameters", libvirt_virDomainSetSchedulerParameters, METH_VARARGS, NULL}, {(char *) "virDomainSetSchedulerParametersFlags", libvirt_virDomainSetSchedulerParametersFlags, METH_VARARGS, NULL}, {(char *) "virDomainSetBlkioParameters", libvirt_virDomainSetBlkioParameters, METH_VARARGS, NULL}, {(char *) "virDomainGetBlkioParameters", libvirt_virDomainGetBlkioParameters, METH_VARARGS, NULL}, {(char *) "virDomainSetMemoryParameters", libvirt_virDomainSetMemoryParameters, METH_VARARGS, NULL}, {(char *) "virDomainGetMemoryParameters", libvirt_virDomainGetMemoryParameters, METH_VARARGS, NULL}, {(char *) "virDomainSetNumaParameters", libvirt_virDomainSetNumaParameters, METH_VARARGS, NULL}, {(char *) "virDomainGetNumaParameters", libvirt_virDomainGetNumaParameters, METH_VARARGS, NULL}, {(char *) "virDomainSetInterfaceParameters", libvirt_virDomainSetInterfaceParameters, METH_VARARGS, NULL}, {(char *) "virDomainGetInterfaceParameters", libvirt_virDomainGetInterfaceParameters, METH_VARARGS, NULL}, {(char *) "virDomainGetVcpus", libvirt_virDomainGetVcpus, METH_VARARGS, NULL}, {(char *) "virDomainPinVcpu", libvirt_virDomainPinVcpu, METH_VARARGS, NULL}, {(char *) "virDomainPinVcpuFlags", libvirt_virDomainPinVcpuFlags, METH_VARARGS, NULL}, {(char *) "virDomainGetVcpuPinInfo", libvirt_virDomainGetVcpuPinInfo, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 0) {(char *) "virDomainGetEmulatorPinInfo", libvirt_virDomainGetEmulatorPinInfo, METH_VARARGS, NULL}, {(char *) "virDomainPinEmulator", libvirt_virDomainPinEmulator, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ #if LIBVIR_CHECK_VERSION(1, 2, 14) {(char *) "virDomainGetIOThreadInfo", libvirt_virDomainGetIOThreadInfo, METH_VARARGS, NULL}, {(char *) "virDomainPinIOThread", libvirt_virDomainPinIOThread, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 14) */ #if LIBVIR_CHECK_VERSION(4, 10, 0) {(char *) "virDomainSetIOThreadParams", libvirt_virDomainSetIOThreadParams, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(4, 10, 0) */ {(char *) "virConnectListStoragePools", libvirt_virConnectListStoragePools, METH_VARARGS, NULL}, {(char *) "virConnectListDefinedStoragePools", libvirt_virConnectListDefinedStoragePools, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virConnectListAllStoragePools", libvirt_virConnectListAllStoragePools, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ {(char *) "virStoragePoolGetAutostart", libvirt_virStoragePoolGetAutostart, METH_VARARGS, NULL}, {(char *) "virStoragePoolListVolumes", libvirt_virStoragePoolListVolumes, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virStoragePoolListAllVolumes", libvirt_virStoragePoolListAllVolumes, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ {(char *) "virStoragePoolGetInfo", libvirt_virStoragePoolGetInfo, METH_VARARGS, NULL}, {(char *) "virStorageVolGetInfo", libvirt_virStorageVolGetInfo, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(3, 0, 0) {(char *) "virStorageVolGetInfoFlags", libvirt_virStorageVolGetInfoFlags, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(3, 0, 0) */ {(char *) "virStoragePoolGetUUID", libvirt_virStoragePoolGetUUID, METH_VARARGS, NULL}, {(char *) "virStoragePoolGetUUIDString", libvirt_virStoragePoolGetUUIDString, METH_VARARGS, NULL}, {(char *) "virStoragePoolLookupByUUID", libvirt_virStoragePoolLookupByUUID, METH_VARARGS, NULL}, {(char *) "virEventRegisterImpl", libvirt_virEventRegisterImpl, METH_VARARGS, NULL}, {(char *) "virEventAddHandle", libvirt_virEventAddHandle, METH_VARARGS, NULL}, {(char *) "virEventAddTimeout", libvirt_virEventAddTimeout, METH_VARARGS, NULL}, {(char *) "virEventInvokeHandleCallback", libvirt_virEventInvokeHandleCallback, METH_VARARGS, NULL}, {(char *) "virEventInvokeTimeoutCallback", libvirt_virEventInvokeTimeoutCallback, METH_VARARGS, NULL}, {(char *) "virEventInvokeFreeCallback", libvirt_virEventInvokeFreeCallback, METH_VARARGS, NULL}, {(char *) "virNodeListDevices", libvirt_virNodeListDevices, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virConnectListAllNodeDevices", libvirt_virConnectListAllNodeDevices, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ {(char *) "virNodeDeviceListCaps", libvirt_virNodeDeviceListCaps, METH_VARARGS, NULL}, {(char *) "virSecretGetUUID", libvirt_virSecretGetUUID, METH_VARARGS, NULL}, {(char *) "virSecretGetUUIDString", libvirt_virSecretGetUUIDString, METH_VARARGS, NULL}, {(char *) "virSecretLookupByUUID", libvirt_virSecretLookupByUUID, METH_VARARGS, NULL}, {(char *) "virConnectListSecrets", libvirt_virConnectListSecrets, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virConnectListAllSecrets", libvirt_virConnectListAllSecrets, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ {(char *) "virSecretGetValue", libvirt_virSecretGetValue, METH_VARARGS, NULL}, {(char *) "virSecretSetValue", libvirt_virSecretSetValue, METH_VARARGS, NULL}, {(char *) "virNWFilterGetUUID", libvirt_virNWFilterGetUUID, METH_VARARGS, NULL}, {(char *) "virNWFilterGetUUIDString", libvirt_virNWFilterGetUUIDString, METH_VARARGS, NULL}, {(char *) "virNWFilterLookupByUUID", libvirt_virNWFilterLookupByUUID, METH_VARARGS, NULL}, {(char *) "virConnectListNWFilters", libvirt_virConnectListNWFilters, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virConnectListAllNWFilters", libvirt_virConnectListAllNWFilters, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ #if LIBVIR_CHECK_VERSION(4, 5, 0) {(char *) "virConnectListAllNWFilterBindings", libvirt_virConnectListAllNWFilterBindings, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(4, 5, 0) */ {(char *) "virConnectListInterfaces", libvirt_virConnectListInterfaces, METH_VARARGS, NULL}, {(char *) "virConnectListDefinedInterfaces", libvirt_virConnectListDefinedInterfaces, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virConnectListAllInterfaces", libvirt_virConnectListAllInterfaces, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ {(char *) "virConnectBaselineCPU", libvirt_virConnectBaselineCPU, METH_VARARGS, NULL}, {(char *) "virDomainGetJobInfo", libvirt_virDomainGetJobInfo, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(1, 0, 3) {(char *) "virDomainGetJobStats", libvirt_virDomainGetJobStats, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 0, 3) */ #if LIBVIR_CHECK_VERSION(5, 6, 0) {(char *) "virDomainListAllCheckpoints", libvirt_virDomainListAllCheckpoints, METH_VARARGS, NULL}, {(char *) "virDomainCheckpointListAllChildren", libvirt_virDomainCheckpointListAllChildren, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(5, 6, 0) */ {(char *) "virDomainSnapshotListNames", libvirt_virDomainSnapshotListNames, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 9, 13) {(char *) "virDomainListAllSnapshots", libvirt_virDomainListAllSnapshots, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 9, 13) */ {(char *) "virDomainSnapshotListChildrenNames", libvirt_virDomainSnapshotListChildrenNames, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 9, 13) {(char *) "virDomainSnapshotListAllChildren", libvirt_virDomainSnapshotListAllChildren, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 9, 13) */ {(char *) "virDomainRevertToSnapshot", libvirt_virDomainRevertToSnapshot, METH_VARARGS, NULL}, {(char *) "virDomainGetBlockJobInfo", libvirt_virDomainGetBlockJobInfo, METH_VARARGS, NULL}, {(char *) "virDomainSetBlockIoTune", libvirt_virDomainSetBlockIoTune, METH_VARARGS, NULL}, {(char *) "virDomainGetBlockIoTune", libvirt_virDomainGetBlockIoTune, METH_VARARGS, NULL}, {(char *) "virDomainSendKey", libvirt_virDomainSendKey, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(1, 0, 3) {(char *) "virDomainMigrateGetCompressionCache", libvirt_virDomainMigrateGetCompressionCache, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 0, 3) */ {(char *) "virDomainMigrateGetMaxSpeed", libvirt_virDomainMigrateGetMaxSpeed, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(3, 7, 0) {(char *) "virDomainMigrateGetMaxDowntime", libvirt_virDomainMigrateGetMaxDowntime, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(3, 7, 0) */ {(char *) "virDomainMigrateGetMaxSpeed", libvirt_virDomainMigrateGetMaxSpeed, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(1, 1, 0) {(char *) "virDomainMigrate3", libvirt_virDomainMigrate3, METH_VARARGS, NULL}, {(char *) "virDomainMigrateToURI3", libvirt_virDomainMigrateToURI3, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */ {(char *) "virDomainBlockPeek", libvirt_virDomainBlockPeek, METH_VARARGS, NULL}, {(char *) "virDomainMemoryPeek", libvirt_virDomainMemoryPeek, METH_VARARGS, NULL}, {(char *) "virDomainGetDiskErrors", libvirt_virDomainGetDiskErrors, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 2) {(char *) "virNodeGetMemoryParameters", libvirt_virNodeGetMemoryParameters, METH_VARARGS, NULL}, {(char *) "virNodeSetMemoryParameters", libvirt_virNodeSetMemoryParameters, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 2) */ #if LIBVIR_CHECK_VERSION(1, 0, 0) {(char *) "virNodeGetCPUMap", libvirt_virNodeGetCPUMap, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 0, 0) */ #if LIBVIR_CHECK_VERSION(1, 1, 1) {(char *) "virDomainCreateXMLWithFiles", libvirt_virDomainCreateXMLWithFiles, METH_VARARGS, NULL}, {(char *) "virDomainCreateWithFiles", libvirt_virDomainCreateWithFiles, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 1, 1) */ #if LIBVIR_CHECK_VERSION(1, 2, 5) {(char *) "virDomainFSFreeze", libvirt_virDomainFSFreeze, METH_VARARGS, NULL}, {(char *) "virDomainFSThaw", libvirt_virDomainFSThaw, METH_VARARGS, NULL}, {(char *) "virDomainGetTime", libvirt_virDomainGetTime, METH_VARARGS, NULL}, {(char *) "virDomainSetTime", libvirt_virDomainSetTime, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 5) */ #if LIBVIR_CHECK_VERSION(1, 2, 6) {(char *) "virNodeGetFreePages", libvirt_virNodeGetFreePages, METH_VARARGS, NULL}, {(char *) "virNetworkGetDHCPLeases", libvirt_virNetworkGetDHCPLeases, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 6) */ #if LIBVIR_CHECK_VERSION(1, 2, 8) {(char *) "virConnectGetAllDomainStats", libvirt_virConnectGetAllDomainStats, METH_VARARGS, NULL}, {(char *) "virDomainListGetStats", libvirt_virDomainListGetStats, METH_VARARGS, NULL}, {(char *) "virDomainBlockCopy", libvirt_virDomainBlockCopy, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 8) */ #if LIBVIR_CHECK_VERSION(1, 2, 9) {(char *) "virNodeAllocPages", libvirt_virNodeAllocPages, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 9) */ #if LIBVIR_CHECK_VERSION(1, 2, 11) {(char *) "virDomainGetFSInfo", libvirt_virDomainGetFSInfo, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 11) */ #if LIBVIR_CHECK_VERSION(1, 2, 14) {(char *) "virDomainInterfaceAddresses", libvirt_virDomainInterfaceAddresses, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 14) */ #if LIBVIR_CHECK_VERSION(1, 3, 3) {(char *) "virDomainGetPerfEvents", libvirt_virDomainGetPerfEvents, METH_VARARGS, NULL}, {(char *) "virDomainSetPerfEvents", libvirt_virDomainSetPerfEvents, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 3, 3) */ #if LIBVIR_CHECK_VERSION(2, 0, 0) {(char *) "virConnectStoragePoolEventRegisterAny", libvirt_virConnectStoragePoolEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectStoragePoolEventDeregisterAny", libvirt_virConnectStoragePoolEventDeregisterAny, METH_VARARGS, NULL}, {(char *) "virDomainGetGuestVcpus", libvirt_virDomainGetGuestVcpus, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(2, 0, 0) */ #if LIBVIR_CHECK_VERSION(2, 2, 0) {(char *) "virConnectNodeDeviceEventRegisterAny", libvirt_virConnectNodeDeviceEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectNodeDeviceEventDeregisterAny", libvirt_virConnectNodeDeviceEventDeregisterAny, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(2, 2, 0) */ #if LIBVIR_CHECK_VERSION(3, 0, 0) {(char *) "virConnectSecretEventRegisterAny", libvirt_virConnectSecretEventRegisterAny, METH_VARARGS, NULL}, {(char *) "virConnectSecretEventDeregisterAny", libvirt_virConnectSecretEventDeregisterAny, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(3, 0, 0) */ #if LIBVIR_CHECK_VERSION(3, 4, 0) {(char *) "virStreamRecvHole", libvirt_virStreamRecvHole, METH_VARARGS, NULL}, {(char *) "virStreamSendHole", libvirt_virStreamSendHole, METH_VARARGS, NULL}, {(char *) "virStreamRecvFlags", libvirt_virStreamRecvFlags, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(3, 4, 0) */ #if LIBVIR_CHECK_VERSION(4, 4, 0) {(char *) "virConnectBaselineHypervisorCPU", libvirt_virConnectBaselineHypervisorCPU, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(4, 4, 0) */ #if LIBVIR_CHECK_VERSION(4, 5, 0) {(char *) "virDomainGetLaunchSecurityInfo", libvirt_virDomainGetLaunchSecurityInfo, METH_VARARGS, NULL}, {(char *) "virNodeGetSEVInfo", libvirt_virNodeGetSEVInfo, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(4, 5, 0) */ #if LIBVIR_CHECK_VERSION(5, 5, 0) {(char *) "virNetworkListAllPorts", libvirt_virNetworkListAllPorts, METH_VARARGS, NULL}, {(char *) "virNetworkPortSetParameters", libvirt_virNetworkPortSetParameters, METH_VARARGS, NULL}, {(char *) "virNetworkPortGetParameters", libvirt_virNetworkPortGetParameters, METH_VARARGS, NULL}, {(char *) "virNetworkPortGetUUID", libvirt_virNetworkPortGetUUID, METH_VARARGS, NULL}, {(char *) "virNetworkPortGetUUIDString", libvirt_virNetworkPortGetUUIDString, METH_VARARGS, NULL}, {(char *) "virNetworkPortLookupByUUID", libvirt_virNetworkPortLookupByUUID, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(5, 5, 0) */ #if LIBVIR_CHECK_VERSION(5, 7, 0) {(char *) "virDomainGetGuestInfo", libvirt_virDomainGetGuestInfo, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(5, 7, 0) */ #if LIBVIR_CHECK_VERSION(5, 8, 0) {(char *) "virConnectSetIdentity", libvirt_virConnectSetIdentity, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(5, 8, 0) */ #if LIBVIR_CHECK_VERSION(6, 10, 0) {(char *) "virDomainAuthorizedSSHKeysGet", libvirt_virDomainAuthorizedSSHKeysGet, METH_VARARGS, NULL}, {(char *) "virDomainAuthorizedSSHKeysSet", libvirt_virDomainAuthorizedSSHKeysSet, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(6, 10, 0) */ #if LIBVIR_CHECK_VERSION(7, 1, 0) {(char *) "virDomainGetMessages", libvirt_virDomainGetMessages, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(7, 1, 0) */ #if LIBVIR_CHECK_VERSION(7, 8, 0) {(char *) "virNodeDeviceGetAutostart", libvirt_virNodeDeviceGetAutostart, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(7, 8, 0) */ #if LIBVIR_CHECK_VERSION(8, 0, 0) {(char *) "virDomainSetLaunchSecurityState", libvirt_virDomainSetLaunchSecurityState, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(8, 0, 0) */ #if LIBVIR_CHECK_VERSION(8, 4, 0) {(char *) "virDomainSaveParams", libvirt_virDomainSaveParams, METH_VARARGS, NULL}, {(char *) "virDomainRestoreParams", libvirt_virDomainRestoreParams, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(8, 4, 0) */ #if LIBVIR_CHECK_VERSION(9, 0, 0) {(char *) "virDomainFDAssociate", libvirt_virDomainFDAssociate, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(9, 0, 0) */ #if LIBVIR_CHECK_VERSION(11, 2, 0) {(char *) "virDomainGetAutostartOnce", libvirt_virDomainGetAutostartOnce, METH_VARARGS, NULL}, {(char *) "virDomainSetThrottleGroup", libvirt_virDomainSetThrottleGroup, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(11, 2, 0) */ {NULL, NULL, 0, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, #ifndef __CYGWIN__ "libvirtmod", #else "cygvirtmod", #endif NULL, -1, libvirtMethods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC #ifndef __CYGWIN__ PyInit_libvirtmod #else PyInit_cygvirtmod #endif (void) { PyObject *module; if (virInitialize() < 0) return NULL; module = PyModule_Create(&moduledef); return module; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1743501822.0 libvirt-python-11.3.0/libvirt-override.py0000644000175000017500000002354614772734776017514 0ustar00jirkajirka from types import TracebackType from typing import Any, Callable, Dict, List, Optional, overload, Tuple, Type, TypeVar, Union _T = TypeVar('_T') _EventCB = Callable[[int, int, int, _T], None] _EventAddHandleFunc = Callable[[int, int, _EventCB, _T], int] _EventUpdateHandleFunc = Callable[[int, int], None] _EventRemoveHandleFunc = Callable[[int], int] _TimerCB = Callable[[int, _T], None] _EventAddTimeoutFunc = Callable[[int, _TimerCB, _T], int] _EventUpdateTimeoutFunc = Callable[[int, int], None] _EventRemoveTimeoutFunc = Callable[[int], int] _DomainCB = Callable[['virConnect', 'virDomain', int, int, _T], Optional[int]] _BlkioParameter = Dict[str, Any] _MemoryParameter = Dict[str, Any] _SchedParameter = Dict[str, Any] _TypedParameter = Dict[str, Any] # The root of all libvirt errors. class libvirtError(Exception): def __init__(self, defmsg: str) -> None: # Never call virConnGetLastError(). # virGetLastError() is now thread local err = libvirtmod.virGetLastError() # type: Optional[Tuple[int, int, str, int, str, Optional[str], Optional[str], int, int]] if err is None: msg = defmsg else: msg = err[2] Exception.__init__(self, msg) self.err = err def get_error_code(self) -> Optional[int]: if self.err is None: return None return self.err[0] def get_error_domain(self) -> Optional[int]: if self.err is None: return None return self.err[1] def get_error_message(self) -> Optional[str]: if self.err is None: return None return self.err[2] def get_error_level(self) -> Optional[int]: if self.err is None: return None return self.err[3] def get_str1(self) -> Optional[str]: if self.err is None: return None return self.err[4] def get_str2(self) -> Optional[str]: if self.err is None: return None return self.err[5] def get_str3(self) -> Optional[str]: if self.err is None: return None return self.err[6] def get_int1(self) -> Optional[int]: if self.err is None: return None return self.err[7] def get_int2(self) -> Optional[int]: if self.err is None: return None return self.err[8] # # register the libvirt global error handler # def registerErrorHandler(f: Callable[[_T, List], None], ctx: _T) -> int: """Register a Python function for error reporting. The function is called back as f(ctx, error), with error being a list of information about the error being raised. Returns 1 in case of success.""" return libvirtmod.virRegisterErrorHandler(f, ctx) def openAuth(uri: str, auth: List, flags: int = 0) -> 'virConnect': # TODO: The C code requires a List and there is not *Mutable*Tuple for a better description such as # auth: Tuple[List[int], Callable[[List[MutableTuple[int, str, str, str, Any]], _T], int], _T] """ This function should be called first to get a connection to the Hypervisor. If necessary, authentication will be performed fetching credentials via the callback. See :py:func:`open` for notes about environment variables which can have an effect on opening drivers and freeing the connection resources. :param str uri: (Optional) connection URI, see https://libvirt.org/uri.html :param auth: a list that contains 3 items: - a list of supported credential types - a callable that takes 2 arguments (credentials, user-data) and returns 0 on succcess and -1 on errors. The credentials argument is a list of credentials that libvirt (actually the ESX driver) would like to request. An element of this list is itself a list containing 5 items (4 inputs, 1 output): - the credential type, e.g. :py:const:`libvirt.VIR_CRED_AUTHNAME` - a prompt to be displayed to the user - a challenge, the ESX driver sets this to the hostname to allow automatic distinction between requests for ESX and vCenter credentials - a default result for the request - a place to store the actual result for the request - user data that will be passed to the callable as second argument :param int flags: bitwise-OR of virConnectFlags :returns: a :py:class:`virConnect` instance on success. :raises libvirtError: on errors. """ ret = libvirtmod.virConnectOpenAuth(uri, auth, flags) if ret is None: raise libvirtError('virConnectOpenAuth() failed') return virConnect(_obj=ret) # # Return library version. # def getVersion(name: Optional[str] = None) -> int: """If no name parameter is passed (or name is None) then the version of the libvirt library is returned as an integer. If a name is passed and it refers to a driver linked to the libvirt library, then this returns a tuple of (library version, driver version). If the name passed refers to a non-existent driver, then you will get the exception 'no support for hypervisor'. Versions numbers are integers: 1000000*major + 1000*minor + release.""" if name is None: ret = libvirtmod.virGetVersion() else: ret = libvirtmod.virGetVersion(name) if ret is None: raise libvirtError("virGetVersion() failed") return ret # # Invoke an EventHandle callback # @overload def _eventInvokeHandleCallback(watch: int, fd: int, event: int, opaque: Tuple[_EventCB, _T], opaquecompat: None = None) -> None: ... # noqa E704 @overload # noqa F811 def _eventInvokeHandleCallback(watch: int, fd: int, event: int, opaque: _EventCB, opaquecompat: _T = None) -> None: ... # noqa E704 def _eventInvokeHandleCallback(watch: int, fd: int, event: int, opaque: Union[Tuple[_EventCB, _T], _EventCB], opaquecompat: Optional[_T] = None) -> None: # noqa F811 """ Invoke the Event Impl Handle Callback in C """ # libvirt 0.9.2 and earlier required custom event loops to know # that opaque=(cb, original_opaque) and pass the values individually # to this wrapper. This should handle the back compat case, and make # future invocations match the virEventHandleCallback prototype if opaquecompat: callback = opaque opaque_ = opaquecompat else: assert isinstance(opaque, tuple) callback = opaque[0] opaque_ = opaque[1] libvirtmod.virEventInvokeHandleCallback(watch, fd, event, callback, opaque_) # # Invoke an EventTimeout callback # def _eventInvokeTimeoutCallback(timer: int, opaque: Union[Tuple[_TimerCB, _T], _TimerCB], opaquecompat: Optional[_T] = None) -> None: """ Invoke the Event Impl Timeout Callback in C """ # libvirt 0.9.2 and earlier required custom event loops to know # that opaque=(cb, original_opaque) and pass the values individually # to this wrapper. This should handle the back compat case, and make # future invocations match the virEventTimeoutCallback prototype if opaquecompat: callback = opaque opaque_ = opaquecompat else: assert isinstance(opaque, tuple) callback = opaque[0] opaque_ = opaque[1] libvirtmod.virEventInvokeTimeoutCallback(timer, callback, opaque_) def _dispatchEventHandleCallback(watch: int, fd: int, events: int, cbData: Dict[str, Any]) -> int: cb = cbData["cb"] opaque = cbData["opaque"] cb(watch, fd, events, opaque) return 0 def _dispatchEventTimeoutCallback(timer: int, cbData: Dict[str, Any]) -> int: cb = cbData["cb"] opaque = cbData["opaque"] cb(timer, opaque) return 0 def virEventAddHandle(fd: int, events: int, cb: _EventCB, opaque: _T) -> int: """ register a callback for monitoring file handle events @fd: file handle to monitor for events @events: bitset of events to watch from virEventHandleType constants @cb: callback to invoke when an event occurs @opaque: user data to pass to callback Example callback prototype is: def cb(watch, # int id of the handle fd, # int file descriptor the event occurred on events, # int bitmap of events that have occurred opaque): # opaque data passed to eventAddHandle """ cbData = {"cb": cb, "opaque": opaque} ret = libvirtmod.virEventAddHandle(fd, events, cbData) if ret == -1: raise libvirtError('virEventAddHandle() failed') return ret def virEventAddTimeout(timeout: int, cb: _TimerCB, opaque: _T) -> int: """ register a callback for a timer event @timeout: time between events in milliseconds @cb: callback to invoke when an event occurs @opaque: user data to pass to callback Setting timeout to -1 will disable the timer. Setting the timeout to zero will cause it to fire on every event loop iteration. Example callback prototype is: def cb(timer, # int id of the timer opaque): # opaque data passed to eventAddTimeout """ cbData = {"cb": cb, "opaque": opaque} ret = libvirtmod.virEventAddTimeout(timeout, cbData) if ret == -1: raise libvirtError('virEventAddTimeout() failed') return ret # # a caller for the ff callbacks for custom event loop implementations # def virEventInvokeFreeCallback(opaque: Any) -> None: """ Execute callback which frees the opaque buffer @opaque: the opaque object passed to addHandle or addTimeout WARNING: This function should not be called from any call by libvirt's core. It will most probably cause deadlock in C-level libvirt code. Instead it should be scheduled and called from implementation's stack. See https://libvirt.org/html/libvirt-libvirt-event.html#virEventAddHandleFunc for more information. This function is not dependent on any event loop implementation. """ libvirtmod.virEventInvokeFreeCallback(opaque[2], opaque[1]) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1746171070.0 libvirt-python-11.3.0/libvirt-python.spec0000644000175000017500000000524615005072276017471 0ustar00jirkajirka# -*- rpm-spec -*- # This spec file assumes you are building on a Fedora or RHEL version # that's still supported by the vendor. It may work on other distros # or versions, but no effort will be made to ensure that going forward %define min_rhel 8 %define min_fedora 33 %if (0%{?fedora} && 0%{?fedora} >= %{min_fedora}) || (0%{?rhel} && 0%{?rhel} >= %{min_rhel}) %define supported_platform 1 %else %define supported_platform 0 %endif Summary: The libvirt virtualization API python3 binding Name: libvirt-python Version: 11.3.0 Release: 1%{?dist} Source0: https://libvirt.org/sources/python/%{name}-%{version}.tar.gz Url: https://libvirt.org License: LGPL-2.1-or-later BuildRequires: libvirt-devel == %{version} BuildRequires: python3-devel BuildRequires: python3-pytest BuildRequires: python3-lxml BuildRequires: python3-setuptools BuildRequires: gcc # Don't want provides for python shared objects %{?filter_provides_in: %filter_provides_in %{python3_sitearch}/.*\.so} %{?filter_setup} %description The libvirt-python package contains a module that permits applications written in the Python programming language to use the interface supplied by the libvirt library to use the virtualization capabilities of recent versions of Linux (and other OSes). %package -n python3-libvirt Summary: The libvirt virtualization API python3 binding Url: http://libvirt.org License: LGPLv2+ %{?python_provide:%python_provide python3-libvirt} Provides: libvirt-python3 = %{version}-%{release} Obsoletes: libvirt-python3 <= 3.6.0-1%{?dist} %description -n python3-libvirt The python3-libvirt package contains a module that permits applications written in the Python 3.x programming language to use the interface supplied by the libvirt library to use the virtualization capabilities of recent versions of Linux (and other OSes). %prep %setup -q # Unset execute bit for example scripts; it can introduce spurious # RPM dependencies, like /usr/bin/python3 # for the -python3 package find examples -type f -exec chmod 0644 \{\} \; %build %if ! %{supported_platform} echo "This RPM requires either Fedora >= %{min_fedora} or RHEL >= %{min_rhel}" exit 1 %endif %py3_build %install %py3_install %check %pytest %files -n python3-libvirt %doc ChangeLog AUTHORS README COPYING examples/ %{python3_sitearch}/libvirt.py* %{python3_sitearch}/libvirtaio.py* %{python3_sitearch}/libvirt_qemu.py* %{python3_sitearch}/libvirt_lxc.py* %{python3_sitearch}/__pycache__/libvirt.cpython-*.py* %{python3_sitearch}/__pycache__/libvirt_qemu.cpython-*.py* %{python3_sitearch}/__pycache__/libvirt_lxc.cpython-*.py* %{python3_sitearch}/__pycache__/libvirtaio.cpython-*.py* %{python3_sitearch}/libvirtmod* %{python3_sitearch}/*egg-info %changelog ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-qemu-override-api.xml0000644000175000017500000000215714612401403021336 0ustar00jirkajirka Send an arbitrary monitor command through qemu monitor of domain Send a Guest Agent command to domain ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1715606996.0 libvirt-python-11.3.0/libvirt-qemu-override.c0000644000175000017500000003314514620412724020221 0ustar00jirkajirka/* * libvir.c: this modules implements the main part of the glue of the * libvir library and the Python interpreter. It provides the * entry points where an automatically generated stub is * unpractical * * Copyright (C) 2011-2019 Red Hat, Inc. * * Daniel Veillard */ /* Horrible kludge to work around even more horrible name-space pollution via Python.h. That file includes /usr/include/python3.x/pyconfig*.h, which has over 180 autoconf-style HAVE_* definitions. Shame on them. */ #undef HAVE_PTHREAD_H #include #include #include #include #include "typewrappers.h" #include "libvirt-utils.h" #include "libvirt-qemu.h" #ifndef __CYGWIN__ # include #endif #if 0 # define DEBUG_ERROR 1 #endif #if DEBUG_ERROR # define DEBUG(fmt, ...) \ printf(fmt, __VA_ARGS__) #else # define DEBUG(fmt, ...) \ while (0) {printf(fmt, __VA_ARGS__);} #endif /******************************************* * Helper functions to avoid importing modules * for every callback *******************************************/ #if LIBVIR_CHECK_VERSION(1, 2, 3) static PyObject *libvirt_qemu_module; static PyObject *libvirt_qemu_dict; static PyObject * getLibvirtQemuModuleObject(void) { if (libvirt_qemu_module) return libvirt_qemu_module; // PyImport_ImportModule returns a new reference /* Bogus (char *) cast for RHEL-5 python API brokenness */ libvirt_qemu_module = PyImport_ImportModule((char *)"libvirt_qemu"); if (!libvirt_qemu_module) { DEBUG("%s Error importing libvirt_qemu module\n", __FUNCTION__); PyErr_Print(); return NULL; } return libvirt_qemu_module; } static PyObject * getLibvirtQemuDictObject(void) { if (libvirt_qemu_dict) return libvirt_qemu_dict; // PyModule_GetDict returns a borrowed reference libvirt_qemu_dict = PyModule_GetDict(getLibvirtQemuModuleObject()); if (!libvirt_qemu_dict) { DEBUG("%s Error importing libvirt_qemu dictionary\n", __FUNCTION__); PyErr_Print(); return NULL; } Py_INCREF(libvirt_qemu_dict); return libvirt_qemu_dict; } static PyObject * libvirt_qemu_lookupPythonFunc(const char *funcname) { PyObject *python_cb; /* Lookup the python callback */ python_cb = PyDict_GetItemString(getLibvirtQemuDictObject(), funcname); if (!python_cb) { DEBUG("%s: Error finding %s\n", __FUNCTION__, funcname); PyErr_Print(); PyErr_Clear(); return NULL; } if (!PyCallable_Check(python_cb)) { DEBUG("%s: %s is not callable\n", __FUNCTION__, funcname); return NULL; } return python_cb; } #endif /* LIBVIR_CHECK_VERSION(1, 2, 3) */ /************************************************************************ * * * Statistics * * * ************************************************************************/ static PyObject * libvirt_qemu_virDomainQemuMonitorCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char *result = NULL; virDomainPtr domain; PyObject *pyobj_domain; unsigned int flags; char *cmd; int c_retval; if (!PyArg_ParseTuple(args, (char *)"OzI:virDomainQemuMonitorCommand", &pyobj_domain, &cmd, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (domain == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainQemuMonitorCommand(domain, cmd, &result, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) return VIR_PY_NONE; py_retval = libvirt_constcharPtrWrap(result); VIR_FREE(result); return py_retval; } #if LIBVIR_CHECK_VERSION(0, 10, 0) static PyObject * libvirt_qemu_virDomainQemuAgentCommand(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; char *result = NULL; virDomainPtr domain; PyObject *pyobj_domain; int timeout; unsigned int flags; char *cmd; if (!PyArg_ParseTuple(args, (char *)"OziI:virDomainQemuAgentCommand", &pyobj_domain, &cmd, &timeout, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); if (domain == NULL) return VIR_PY_NONE; LIBVIRT_BEGIN_ALLOW_THREADS; result = virDomainQemuAgentCommand(domain, cmd, timeout, flags); LIBVIRT_END_ALLOW_THREADS; if (!result) return VIR_PY_NONE; py_retval = libvirt_constcharPtrWrap(result); VIR_FREE(result); return py_retval; } #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ #if LIBVIR_CHECK_VERSION(1, 2, 3) static void libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc(void *opaque) { PyObject *pyobj_conn = (PyObject*)opaque; LIBVIRT_ENSURE_THREAD_STATE; Py_DECREF(pyobj_conn); LIBVIRT_RELEASE_THREAD_STATE; } static void libvirt_qemu_virConnectDomainQemuMonitorEventCallback(virConnectPtr conn ATTRIBUTE_UNUSED, virDomainPtr dom, const char *event, long long seconds, unsigned int micros, const char *details, void *opaque) { PyObject *pyobj_cbData = (PyObject*)opaque; PyObject *pyobj_dom; PyObject *pyobj_ret = NULL; PyObject *pyobj_conn; PyObject *dictKey; PyObject *pyobj_cb; LIBVIRT_ENSURE_THREAD_STATE; pyobj_cb = libvirt_qemu_lookupPythonFunc("_dispatchQemuMonitorEventCallback"); if (!pyobj_cb) goto cleanup; dictKey = libvirt_constcharPtrWrap("conn"); if (!dictKey) goto cleanup; pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey); Py_DECREF(dictKey); /* Create a python instance of this virDomainPtr */ virDomainRef(dom); if (!(pyobj_dom = libvirt_virDomainPtrWrap(dom))) { virDomainFree(dom); goto cleanup; } Py_INCREF(pyobj_cbData); /* Call the Callback Dispatcher */ pyobj_ret = PyObject_CallFunction(pyobj_cb, (char *)"OOsLIsO", pyobj_conn, pyobj_dom, event, seconds, micros, details, pyobj_cbData); Py_DECREF(pyobj_cbData); Py_DECREF(pyobj_dom); cleanup: if (!pyobj_ret) { DEBUG("%s - ret:%p\n", __FUNCTION__, pyobj_ret); PyErr_Print(); } else { Py_DECREF(pyobj_ret); } LIBVIRT_RELEASE_THREAD_STATE; } static PyObject * libvirt_qemu_virConnectDomainQemuMonitorEventRegister(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; PyObject *pyobj_conn; PyObject *pyobj_dom; PyObject *pyobj_cbData; const char *event; virConnectPtr conn; int ret = 0; virConnectDomainQemuMonitorEventCallback cb = NULL; virDomainPtr dom; unsigned int flags; if (!PyArg_ParseTuple(args, (char *) "OOzOI:virConnectDomainQemuMonitorEventRegister", &pyobj_conn, &pyobj_dom, &event, &pyobj_cbData, &flags)) return NULL; DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventRegister(%p %p %s %p %x) called\n", pyobj_conn, pyobj_dom, NULLSTR(event), pyobj_cbData, flags); conn = PyvirConnect_Get(pyobj_conn); if (pyobj_dom == Py_None) dom = NULL; else dom = PyvirDomain_Get(pyobj_dom); cb = libvirt_qemu_virConnectDomainQemuMonitorEventCallback; Py_INCREF(pyobj_cbData); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectDomainQemuMonitorEventRegister(conn, dom, event, cb, pyobj_cbData, libvirt_qemu_virConnectDomainQemuMonitorEventFreeFunc, flags); LIBVIRT_END_ALLOW_THREADS; if (ret < 0) { Py_DECREF(pyobj_cbData); } py_retval = libvirt_intWrap(ret); return py_retval; } static PyObject * libvirt_qemu_virConnectDomainQemuMonitorEventDeregister(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *py_retval; PyObject *pyobj_conn; int callbackID; virConnectPtr conn; int ret = 0; if (!PyArg_ParseTuple(args, (char *) "Oi:virConnectDomainQemuMonitorEventDeregister", &pyobj_conn, &callbackID)) return NULL; DEBUG("libvirt_qemu_virConnectDomainQemuMonitorEventDeregister(%p) called\n", pyobj_conn); conn = PyvirConnect_Get(pyobj_conn); LIBVIRT_BEGIN_ALLOW_THREADS; ret = virConnectDomainQemuMonitorEventDeregister(conn, callbackID); LIBVIRT_END_ALLOW_THREADS; py_retval = libvirt_intWrap(ret); return py_retval; } #endif /* LIBVIR_CHECK_VERSION(1, 2, 3) */ #if LIBVIR_CHECK_VERSION(8, 2, 0) static PyObject * libvirt_qemu_virDomainQemuMonitorCommandWithFiles(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { PyObject *pyobj_domain; const char *cmd; PyObject *pyobj_files; unsigned int flags; virDomainPtr domain; unsigned int ninfiles; int *infiles = NULL; unsigned int noutfiles = 0; int *outfiles = NULL; char *result = NULL; size_t i; PyObject *py_outfiles = NULL; PyObject *py_retval = NULL; int c_retval; if (!PyArg_ParseTuple(args, (char *) "Os|OI:virDomainQemuMonitorCommandWithFiles", &pyobj_domain, &cmd, &pyobj_files, &flags)) return NULL; domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); ninfiles = PyList_Size(pyobj_files); if (VIR_ALLOC_N(infiles, ninfiles) < 0) return PyErr_NoMemory(); for (i = 0; i < ninfiles; i++) { PyObject *pyfd; int fd; pyfd = PyList_GetItem(pyobj_files, i); if (libvirt_intUnwrap(pyfd, &fd) < 0) goto cleanup; infiles[i] = fd; } LIBVIRT_BEGIN_ALLOW_THREADS; c_retval = virDomainQemuMonitorCommandWithFiles(domain, cmd, ninfiles, infiles, &noutfiles, &outfiles, &result, flags); LIBVIRT_END_ALLOW_THREADS; if (c_retval < 0) { py_retval = VIR_PY_NONE; goto cleanup; } if (!(py_outfiles = PyList_New(0)) || !(py_retval = PyTuple_New(2))) { goto error; } for (i = 0; i < noutfiles; i++) { int fd = outfiles[i]; const char *mode = "r+b"; /* Since FD passing works only on UNIX-like systems, we can do this. */ #ifndef __CYGWIN__ int fflags; if ((fflags = fcntl(fd, F_GETFL)) < 0) goto error; switch (fflags & (O_ACCMODE | O_APPEND)) { case O_RDONLY: mode = "rb"; break; case O_WRONLY: mode = "wb"; break; case O_RDWR: mode = "r+b"; break; case O_WRONLY | O_APPEND: mode = "ab"; break; case O_RDWR | O_APPEND: mode = "a+b"; break; } #endif VIR_PY_LIST_APPEND_GOTO(py_outfiles, PyFile_FromFd(fd, NULL, mode, 0, NULL, NULL, NULL, 1), error); } VIR_PY_TUPLE_SET_GOTO(py_retval, 0, libvirt_charPtrWrap(result), error); VIR_PY_TUPLE_SET_GOTO(py_retval, 1, py_outfiles, error); /* stolen by py_retval */ py_outfiles = NULL; cleanup: Py_XDECREF(py_outfiles); VIR_FREE(result); VIR_FREE(outfiles); VIR_FREE(infiles); return py_retval; error: while (noutfiles > 0) { VIR_FORCE_CLOSE(outfiles[--noutfiles]); } Py_CLEAR(py_retval); goto cleanup; } #endif /* LIBVIR_CHECK_VERSION(8, 2, 0) */ /************************************************************************ * * * The registration stuff * * * ************************************************************************/ static PyMethodDef libvirtQemuMethods[] = { #include "libvirt-qemu-export.c.inc" {(char *) "virDomainQemuMonitorCommand", libvirt_qemu_virDomainQemuMonitorCommand, METH_VARARGS, NULL}, #if LIBVIR_CHECK_VERSION(0, 10, 0) {(char *) "virDomainQemuAgentCommand", libvirt_qemu_virDomainQemuAgentCommand, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(0, 10, 0) */ #if LIBVIR_CHECK_VERSION(1, 2, 3) {(char *) "virConnectDomainQemuMonitorEventRegister", libvirt_qemu_virConnectDomainQemuMonitorEventRegister, METH_VARARGS, NULL}, {(char *) "virConnectDomainQemuMonitorEventDeregister", libvirt_qemu_virConnectDomainQemuMonitorEventDeregister, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(1, 2, 3) */ #if LIBVIR_CHECK_VERSION(8, 2, 0) {(char *) "virDomainQemuMonitorCommandWithFiles", libvirt_qemu_virDomainQemuMonitorCommandWithFiles, METH_VARARGS, NULL}, #endif /* LIBVIR_CHECK_VERSION(8, 2, 0) */ {NULL, NULL, 0, NULL} }; static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, #ifndef __CYGWIN__ "libvirtmod_qemu", #else "cygvirtmod_qemu", #endif NULL, -1, libvirtQemuMethods, NULL, NULL, NULL, NULL }; PyMODINIT_FUNC #ifndef __CYGWIN__ PyInit_libvirtmod_qemu #else PyInit_cygvirtmod_qemu #endif (void) { PyObject *module; if (virInitialize() < 0) return NULL; module = PyModule_Create(&moduledef); return module; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-qemu-override.py0000644000175000017500000000657414612401403020426 0ustar00jirkajirkafrom typing import Any, Callable, Dict, List, IO def _dispatchQemuMonitorEventCallback(conn: libvirt.virConnect, dom: libvirt.virDomain, event: str, seconds: int, micros: int, details: str, cbData: Dict[str, Any]) -> int: """Dispatches events to python user qemu monitor event callbacks """ cb = cbData["cb"] opaque = cbData["opaque"] cb(conn, libvirt.virDomain(conn, _obj=dom), event, seconds, micros, details, opaque) return 0 def qemuMonitorEventDeregister(conn: libvirt.virConnect, callbackID: int) -> None: """Removes a qemu monitor event callback. De-registering for a callback will disable delivery of this event type""" try: ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventDeregister(conn._o, callbackID) if ret == -1: raise libvirt.libvirtError('virConnectDomainQemuMonitorEventDeregister() failed') del conn.qemuMonitorEventCallbackID[callbackID] # type: ignore except AttributeError: pass def qemuMonitorEventRegister(conn: libvirt.virConnect, dom: libvirt.virDomain, event: str, cb: Callable[[libvirt.virConnect, libvirt.virDomain, str, int, int, str, libvirt._T], None], opaque: libvirt._T, flags: int = 0) -> int: """Adds a qemu monitor event callback. Registering for a monitor callback will enable delivery of the events""" if not hasattr(conn, 'qemuMonitorEventCallbackID'): conn.qemuMonitorEventCallbackID = {} # type: ignore cbData = {"cb": cb, "conn": conn, "opaque": opaque} if dom is None: ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventRegister(conn._o, None, event, cbData, flags) else: ret = libvirtmod_qemu.virConnectDomainQemuMonitorEventRegister(conn._o, dom._o, event, cbData, flags) if ret == -1: raise libvirt.libvirtError('virConnectDomainQemuMonitorEventRegister() failed') conn.qemuMonitorEventCallbackID[ret] = opaque # type: ignore return ret def qemuMonitorCommandWithFiles(domain: libvirt.virDomain, cmd: str, files: List[int] = [], flags: int = 0) -> (str, List[IO]): """This API is QEMU specific, so it will only work with hypervisor connections to the QEMU driver with local connections using the unix socket. Send an arbitrary monitor command @cmd with file descriptors @files to domain through the QEMU monitor and optionally return a list of files in the returned tuple. There are several requirements to safely and successfully use this API: - A @cmd that queries state without making any modifications is safe - A @cmd that alters state that is also tracked by libvirt is unsafe, and may cause libvirtd to crash - A @cmd that alters state not tracked by the current version of libvirt is possible as a means to test new qemu features before they have support in libvirt, but no guarantees are made to safety If VIR_DOMAIN_QEMU_MONITOR_COMMAND_HMP is set, the command is considered to be a human monitor command and libvirt will automatically convert it into QMP if needed. In that case the @result will also be converted back from QMP. Returns a tuple consisting of the string output from @cmd and a list of files respectively.""" ret = libvirtmod_qemu.virDomainQemuMonitorCommandWithFiles(domain._o, cmd, files, flags) if ret is None: raise libvirt.libvirtError('virDomainQemuMonitorCommandWithFiles() failed') return ret ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-utils.c0000644000175000017500000003751614612401403016574 0ustar00jirkajirka/* * libvirt-utils.c: misc helper APIs for python binding * * Copyright (C) 2013-2019 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . * */ #include #include /* Ugly python defines that, which is also defined in errno.h */ #undef _POSIC_C_SOURCE /* We want to see *_LAST enums. */ #define VIR_ENUM_SENTINELS #include #include #include #include #include #include "libvirt-utils.h" #include "typewrappers.h" /** * virAlloc: * @ptrptr: pointer to pointer for address of allocated memory * @size: number of bytes to allocate * * Allocate 'size' bytes of memory. Return the address of the * allocated memory in 'ptrptr'. The newly allocated memory is * filled with zeros. * * Returns -1 on failure to allocate, zero on success */ int virAlloc(void *ptrptr, size_t size) { *(void **)ptrptr = calloc(1, size); if (*(void **)ptrptr == NULL) { return -1; } return 0; } /** * virAllocN: * @ptrptr: pointer to pointer for address of allocated memory * @size: number of bytes to allocate * @count: number of elements to allocate * * Allocate an array of memory 'count' elements long, * each with 'size' bytes. Return the address of the * allocated memory in 'ptrptr'. The newly allocated * memory is filled with zeros. * * Returns -1 on failure to allocate, zero on success */ int virAllocN(void *ptrptr, size_t size, size_t count) { *(void**)ptrptr = calloc(count, size); if (*(void**)ptrptr == NULL) { return -1; } return 0; } /** * virReallocN: * @ptrptr: pointer to pointer for address of allocated memory * @size: number of bytes to allocate * @count: number of elements in array * * Resize the block of memory in 'ptrptr' to be an array of * 'count' elements, each 'size' bytes in length. Update 'ptrptr' * with the address of the newly allocated memory. On failure, * 'ptrptr' is not changed and still points to the original memory * block. Any newly allocated memory in 'ptrptr' is uninitialized. * * Returns -1 on failure to allocate, zero on success */ int virReallocN(void *ptrptr, size_t size, size_t count) { void *tmp; if (xalloc_oversized(count, size)) { errno = ENOMEM; return -1; } tmp = realloc(*(void**)ptrptr, size * count); if (!tmp && ((size * count) != 0)) { return -1; } *(void**)ptrptr = tmp; return 0; } /** * virFree: * @ptrptr: pointer to pointer for address of memory to be freed * * Release the chunk of memory in the pointer pointed to by * the 'ptrptr' variable. After release, 'ptrptr' will be * updated to point to NULL. */ void virFree(void *ptrptr) { int save_errno = errno; free(*(void**)ptrptr); *(void**)ptrptr = NULL; errno = save_errno; } int virFileClose(int *fdptr) { int saved_errno = 0; int rc = 0; saved_errno = errno; if (*fdptr < 0) return 0; rc = close(*fdptr); *fdptr = -1; errno = saved_errno; return rc; } #if ! LIBVIR_CHECK_VERSION(1, 0, 2) /** * virTypedParamsClear: * @params: the array of the typed parameters * @nparams: number of parameters in the @params array * * Frees all memory used by string parameters. The memory occupied by @params * is not free; use virTypedParamsFree if you want it to be freed too. * * Returns nothing. */ void virTypedParamsClear(virTypedParameterPtr params, int nparams) { size_t i; if (!params) return; for (i = 0; i < nparams; i++) { if (params[i].type == VIR_TYPED_PARAM_STRING) VIR_FREE(params[i].value.s); } } /** * virTypedParamsFree: * @params: the array of the typed parameters * @nparams: number of parameters in the @params array * * Frees all memory used by string parameters and the memory occuiped by * @params. * * Returns nothing. */ void virTypedParamsFree(virTypedParameterPtr params, int nparams) { virTypedParamsClear(params, nparams); VIR_FREE(params); } #endif /* ! LIBVIR_CHECK_VERSION(1, 0, 2) */ /* Helper function to convert a virTypedParameter output array into a * Python dictionary for return to the user. Return NULL on failure, * after raising a python exception. */ PyObject * getPyVirTypedParameter(const virTypedParameter *params, int nparams) { PyObject *key, *val, *info; ssize_t i; if ((info = PyDict_New()) == NULL) return NULL; for (i = 0; i < nparams; i++) { switch (params[i].type) { case VIR_TYPED_PARAM_INT: val = libvirt_intWrap(params[i].value.i); break; case VIR_TYPED_PARAM_UINT: val = libvirt_intWrap(params[i].value.ui); break; case VIR_TYPED_PARAM_LLONG: val = libvirt_longlongWrap(params[i].value.l); break; case VIR_TYPED_PARAM_ULLONG: val = libvirt_ulonglongWrap(params[i].value.ul); break; case VIR_TYPED_PARAM_DOUBLE: val = PyFloat_FromDouble(params[i].value.d); break; case VIR_TYPED_PARAM_BOOLEAN: val = PyBool_FromLong(params[i].value.b); break; case VIR_TYPED_PARAM_STRING: val = libvirt_constcharPtrWrap(params[i].value.s); break; default: /* Possible if a newer server has a bug and sent stuff we * don't recognize. */ PyErr_Format(PyExc_LookupError, "Type value \"%d\" not recognized", params[i].type); val = NULL; break; } key = libvirt_constcharPtrWrap(params[i].field); VIR_PY_DICT_SET_GOTO(info, key, val, cleanup); } return info; cleanup: Py_DECREF(info); return NULL; } /* Allocate a new typed parameter array with the same contents and * length as info, and using the array params of length nparams as * hints on what types to use when creating the new array. The caller * must clear the array before freeing it. Return NULL on failure, * after raising a python exception. */ virTypedParameterPtr setPyVirTypedParameter(PyObject *info, const virTypedParameter *params, int nparams) { PyObject *key, *value; Py_ssize_t pos = 0; virTypedParameterPtr temp = NULL, ret = NULL; Py_ssize_t size; ssize_t i; if ((size = PyDict_Size(info)) < 0) return NULL; /* Libvirt APIs use NULL array and 0 size as a special case; * setting should have at least one parameter. */ if (size == 0) { PyErr_Format(PyExc_LookupError, "Dictionary must not be empty"); return NULL; } if (VIR_ALLOC_N(ret, size) < 0) { PyErr_NoMemory(); return NULL; } temp = &ret[0]; while (PyDict_Next(info, &pos, &key, &value)) { char *keystr = NULL; if (libvirt_charPtrUnwrap(key, &keystr) < 0) goto cleanup; for (i = 0; i < nparams; i++) { if (STREQ(params[i].field, keystr)) break; } if (i == nparams) { PyErr_Format(PyExc_LookupError, "Attribute name \"%s\" could not be recognized", keystr); VIR_FREE(keystr); goto cleanup; } strncpy(temp->field, keystr, VIR_TYPED_PARAM_FIELD_LENGTH - 1); temp->type = params[i].type; VIR_FREE(keystr); switch (params[i].type) { case VIR_TYPED_PARAM_INT: if (libvirt_intUnwrap(value, &temp->value.i) < 0) goto cleanup; break; case VIR_TYPED_PARAM_UINT: if (libvirt_uintUnwrap(value, &temp->value.ui) < 0) goto cleanup; break; case VIR_TYPED_PARAM_LLONG: if (libvirt_longlongUnwrap(value, &temp->value.l) < 0) goto cleanup; break; case VIR_TYPED_PARAM_ULLONG: if (libvirt_ulonglongUnwrap(value, &temp->value.ul) < 0) goto cleanup; break; case VIR_TYPED_PARAM_DOUBLE: if (libvirt_doubleUnwrap(value, &temp->value.d) < 0) goto cleanup; break; case VIR_TYPED_PARAM_BOOLEAN: { bool b; if (libvirt_boolUnwrap(value, &b) < 0) goto cleanup; temp->value.b = b; break; } case VIR_TYPED_PARAM_STRING: { char *string_val; if (libvirt_charPtrUnwrap(value, &string_val) < 0) goto cleanup; temp->value.s = string_val; break; } default: /* Possible if a newer server has a bug and sent stuff we * don't recognize. */ PyErr_Format(PyExc_LookupError, "Type value \"%d\" not recognized", params[i].type); goto cleanup; } temp++; } return ret; cleanup: virTypedParamsFree(ret, size); return NULL; } /* While these appeared in libvirt in 1.0.2, we only * need them in the python from 1.1.0 onwards */ #if LIBVIR_CHECK_VERSION(1, 1, 0) int virPyDictToTypedParamOne(virTypedParameterPtr *params, int *n, int *max, virPyTypedParamsHintPtr hints, int nhints, const char *keystr, PyObject *value) { int rv = -1, type = -1; ssize_t i; for (i = 0; i < nhints; i++) { if (STREQ(hints[i].name, keystr)) { type = hints[i].type; break; } } if (type == -1) { if (libvirt_PyString_Check(value)) { type = VIR_TYPED_PARAM_STRING; } else if (PyBool_Check(value)) { type = VIR_TYPED_PARAM_BOOLEAN; } else if (PyLong_Check(value)) { unsigned long long ull = PyLong_AsUnsignedLongLong(value); if (ull == (unsigned long long) -1 && PyErr_Occurred()) { type = VIR_TYPED_PARAM_LLONG; PyErr_Clear(); } else { type = VIR_TYPED_PARAM_ULLONG; } } else if (PyFloat_Check(value)) { type = VIR_TYPED_PARAM_DOUBLE; } } if (type == -1) { PyErr_Format(PyExc_TypeError, "Unknown type of \"%s\" field", keystr); goto cleanup; } switch ((virTypedParameterType) type) { case VIR_TYPED_PARAM_INT: { int val; if (libvirt_intUnwrap(value, &val) < 0 || virTypedParamsAddInt(params, n, max, keystr, val) < 0) goto cleanup; break; } case VIR_TYPED_PARAM_UINT: { unsigned int val; if (libvirt_uintUnwrap(value, &val) < 0 || virTypedParamsAddUInt(params, n, max, keystr, val) < 0) goto cleanup; break; } case VIR_TYPED_PARAM_LLONG: { long long val; if (libvirt_longlongUnwrap(value, &val) < 0 || virTypedParamsAddLLong(params, n, max, keystr, val) < 0) goto cleanup; break; } case VIR_TYPED_PARAM_ULLONG: { unsigned long long val; if (libvirt_ulonglongUnwrap(value, &val) < 0 || virTypedParamsAddULLong(params, n, max, keystr, val) < 0) goto cleanup; break; } case VIR_TYPED_PARAM_DOUBLE: { double val; if (libvirt_doubleUnwrap(value, &val) < 0 || virTypedParamsAddDouble(params, n, max, keystr, val) < 0) goto cleanup; break; } case VIR_TYPED_PARAM_BOOLEAN: { bool val; if (libvirt_boolUnwrap(value, &val) < 0 || virTypedParamsAddBoolean(params, n, max, keystr, val) < 0) goto cleanup; break; } case VIR_TYPED_PARAM_STRING: { char *val;; if (libvirt_charPtrUnwrap(value, &val) < 0 || virTypedParamsAddString(params, n, max, keystr, val) < 0) { VIR_FREE(val); goto cleanup; } VIR_FREE(val); break; } case VIR_TYPED_PARAM_LAST: break; /* unreachable */ } rv = 0; cleanup: return rv; } /* Automatically convert dict into type parameters based on types reported * by python. All integer types are converted into LLONG (in case of a negative * value) or ULLONG (in case of a positive value). If you need different * handling, use @hints to explicitly specify what types should be used for * specific parameters. */ int virPyDictToTypedParams(PyObject *dict, virTypedParameterPtr *ret_params, int *ret_nparams, virPyTypedParamsHintPtr hints, int nhints) { PyObject *key; PyObject *value; Py_ssize_t pos = 0; virTypedParameterPtr params = NULL; int n = 0; int max = 0; int ret = -1; char *keystr = NULL; *ret_params = NULL; *ret_nparams = 0; if (PyDict_Size(dict) < 0) return -1; while (PyDict_Next(dict, &pos, &key, &value)) { if (libvirt_charPtrUnwrap(key, &keystr) < 0) goto cleanup; if (PyList_Check(value) || PyTuple_Check(value)) { Py_ssize_t i, size = PySequence_Size(value); for (i = 0; i < size; i++) { PyObject *v = PySequence_GetItem(value, i); if (virPyDictToTypedParamOne(¶ms, &n, &max, hints, nhints, keystr, v) < 0) goto cleanup; } } else if (virPyDictToTypedParamOne(¶ms, &n, &max, hints, nhints, keystr, value) < 0) goto cleanup; VIR_FREE(keystr); } *ret_params = params; *ret_nparams = n; params = NULL; ret = 0; cleanup: VIR_FREE(keystr); virTypedParamsFree(params, n); return ret; } #endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */ /* virPyCpumapConvert * @cpunum: the number of physical cpus of the host. * @pycpumap: source cpu map, python tuple of bools. * @cpumapptr: destination cpu map. * @cpumaplen: destination cpu map length. * * Helper function to convert a pycpumap to char*. * * Returns 0 on success, -1 on failure with error set. */ int virPyCpumapConvert(int cpunum, PyObject *pycpumap, unsigned char **cpumapptr, int *cpumaplen) { int tuple_size; ssize_t i; *cpumapptr = NULL; if (!PyTuple_Check(pycpumap)) { PyErr_SetString(PyExc_TypeError, "Unexpected type, tuple is required"); return -1; } *cpumaplen = VIR_CPU_MAPLEN(cpunum); if ((tuple_size = PyTuple_Size(pycpumap)) == -1) return -1; if (VIR_ALLOC_N(*cpumapptr, *cpumaplen) < 0) { PyErr_NoMemory(); return -1; } for (i = 0; i < cpunum && i < tuple_size; i++) { PyObject *flag = PyTuple_GetItem(pycpumap, i); bool b; if (!flag || libvirt_boolUnwrap(flag, &b) < 0) { VIR_FREE(*cpumapptr); return -1; } if (b) VIR_USE_CPU(*cpumapptr, i); } return 0; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirt-utils.h0000644000175000017500000003173214612401403016573 0ustar00jirkajirka/* * libvirt-utils.h: misc helper APIs for python binding * * Copyright (C) 2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . * */ #ifndef __LIBVIRT_UTILS_H__ # define __LIBVIRT_UTILS_H__ # include # include # define STREQ(a,b) (strcmp(a,b) == 0) # ifndef MIN # define MIN(a,b) (((a) < (b)) ? (a) : (b)) # endif /** * libvirt.h provides this as of version 1.2.0, but we want to be able * to support older versions of libvirt so copy and paste the macro from * libvirt.h */ # ifndef LIBVIR_CHECK_VERSION # define LIBVIR_CHECK_VERSION(major, minor, micro) \ ((major) * 1000000 + (minor) * 1000 + (micro) <= LIBVIR_VERSION_NUMBER) # endif /* Return 1 if an array of N objects, each of size S, cannot exist due to size arithmetic overflow. S must be positive and N must be nonnegative. This is a macro, not a function, so that it works correctly even when SIZE_MAX < N. By gnulib convention, SIZE_MAX represents overflow in size calculations, so the conservative dividend to use here is SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. However, malloc (SIZE_MAX) fails on all known hosts where sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for exactly-SIZE_MAX allocations on such hosts; this avoids a test and branch when S is known to be 1. */ # define xalloc_oversized(n, s) \ ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) /* The __attribute__((__warn_unused_result__)) feature is available in gcc versions 3.4 and newer, while the typeof feature has been available since 2.7 at least. */ # if 3 < __GNUC__ + (4 <= __GNUC_MINOR__) # define ignore_value(x) \ (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; })) # else # define ignore_value(x) ((void) (x)) # endif # ifdef __GNUC__ # ifndef __GNUC_PREREQ # if defined __GNUC__ && defined __GNUC_MINOR__ # define __GNUC_PREREQ(maj, min) \ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) # else # define __GNUC_PREREQ(maj, min) 0 # endif # endif /* __GNUC_PREREQ */ /** * ATTRIBUTE_UNUSED: * * Macro to flag consciously unused parameters to functions */ # ifndef ATTRIBUTE_UNUSED # define ATTRIBUTE_UNUSED __attribute__((__unused__)) # endif /* gcc's handling of attribute nonnull is less than stellar - it does * NOT improve diagnostics, and merely allows gcc to optimize away * null code checks even when the caller manages to pass null in spite * of the attribute, leading to weird crashes. Coverity, on the other * hand, knows how to do better static analysis based on knowing * whether a parameter is nonnull. Make this attribute conditional * based on whether we are compiling for real or for analysis, while * still requiring correct gcc syntax when it is turned off. See also * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17308 */ # ifndef ATTRIBUTE_NONNULL # if __GNUC_PREREQ (3, 3) # if STATIC_ANALYSIS # define ATTRIBUTE_NONNULL(m) __attribute__((__nonnull__(m))) # else # define ATTRIBUTE_NONNULL(m) __attribute__(()) # endif # else # define ATTRIBUTE_NONNULL(m) # endif # endif # ifndef ATTRIBUTE_RETURN_CHECK # if __GNUC_PREREQ (3, 4) # define ATTRIBUTE_RETURN_CHECK __attribute__((__warn_unused_result__)) # else # define ATTRIBUTE_RETURN_CHECK # endif # endif # else # ifndef ATTRIBUTE_UNUSED # define ATTRIBUTE_UNUSED # endif # ifndef ATTRIBUTE_NONNULL # define ATTRIBUTE_NONNULL(m) # endif # ifndef ATTRIBUTE_RETURN_CHECK # define ATTRIBUTE_RETURN_CHECK # endif # endif /* __GNUC__ */ /* Don't call these directly - use the macros below */ int virAlloc(void *ptrptr, size_t size) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); int virAllocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); int virReallocN(void *ptrptr, size_t size, size_t count) ATTRIBUTE_RETURN_CHECK ATTRIBUTE_NONNULL(1); void virFree(void *ptrptr) ATTRIBUTE_NONNULL(1); # define libvirt_PyString_Check PyUnicode_Check #define VIR_N_ELEMENTS(array) (sizeof(array) / sizeof(*(array))) /* The two-statement sequence "Py_INCREF(Py_None); return Py_None;" is so common that we encapsulate it here. Now, each use is simply return VIR_PY_NONE; */ #define VIR_PY_NONE (Py_INCREF (Py_None), Py_None) #define VIR_PY_INT_FAIL (libvirt_intWrap(-1)) #define VIR_PY_INT_SUCCESS (libvirt_intWrap(0)) /** * VIR_PY_TUPLE_SET_GOTO: * @TUPLE: a pointer to a tuple object * @INDEX: a position in the tuple object * @VALUE: a pointer to a python object to add into the tuple * @GOTO: a label to jump to in case of error * * Add the new value to specific place into the python tuple object. In case of * error it will jump to provided label and DECREF the value to not leak memory. */ #define VIR_PY_TUPLE_SET_GOTO(TUPLE, INDEX, VALUE, GOTO) \ do { \ PyObject *tmpVal = VALUE; \ if (!tmpVal || PyTuple_SetItem(TUPLE, INDEX, tmpVal) < 0) \ goto GOTO; \ } while (0) /** * VIR_PY_LIST_SET_GOTO: * @LIST: a pointer to a list object * @INDEX: a position in the list object * @VALUE: a pointer to a python object to add into the list * @GOTO: a label to jump to in case of error * * Add the new value to specific place into the python list object. In case of * error it will jump to provided label and DECREF the value to not leak memory. */ #define VIR_PY_LIST_SET_GOTO(LIST, INDEX, VALUE, GOTO) \ do { \ PyObject *tmpVal = VALUE; \ if (!tmpVal || PyList_SetItem(LIST, INDEX, tmpVal) < 0) \ goto GOTO; \ } while (0) /** * VIR_PY_LIST_APPEND_GOTO: * @LIST: a pointer to a python list object * @VALUE: a pointer to a python object to add into the list * @GOTO: a label to jump to in case of error * * Append the new value into the end of the python list object. In case of * error it will jump to provided label and DECREF the value to not leak memory. */ #define VIR_PY_LIST_APPEND_GOTO(LIST, VALUE, GOTO) \ do { \ PyObject *tmpVal = VALUE; \ if (!tmpVal || PyList_Append(LIST, tmpVal) < 0) { \ Py_XDECREF(tmpVal); \ goto GOTO; \ } \ Py_DECREF(tmpVal); \ } while (0) /** * VIR_PY_DICT_SET_GOTO: * @DICT: a pointer to a python dict object * @KEY: a pointer to a python string object which will be used as a key * @VALUE: a pointer to a python object to add into the dict under provided key * @GOTO: a label to jump to in case of error * * Add a new pair of key:value into the python dict object. In case of error it * will jump to provided label. It will DECREF both key and value in case of * success or error. */ #define VIR_PY_DICT_SET_GOTO(DICT, KEY, VALUE, GOTO) \ do { \ PyObject *tmpKey = KEY; \ PyObject *tmpVal = VALUE; \ if (!tmpKey || !tmpVal || \ PyDict_SetItem(DICT, tmpKey, tmpVal) < 0) { \ Py_XDECREF(tmpKey); \ Py_XDECREF(tmpVal); \ goto GOTO; \ } \ Py_DECREF(tmpKey); \ Py_DECREF(tmpVal); \ } while (0) /** * VIR_ALLOC: * @ptr: pointer to hold address of allocated memory * * Allocate sizeof(*ptr) bytes of memory and store * the address of allocated memory in 'ptr'. Fill the * newly allocated memory with zeros. * * This macro is safe to use on arguments with side effects. * * Returns -1 on failure (with OOM error reported), 0 on success */ # define VIR_ALLOC(ptr) virAlloc(&(ptr), sizeof(*(ptr))) /** * VIR_ALLOC_N: * @ptr: pointer to hold address of allocated memory * @count: number of elements to allocate * * Allocate an array of 'count' elements, each sizeof(*ptr) * bytes long and store the address of allocated memory in * 'ptr'. Fill the newly allocated memory with zeros. * * This macro is safe to use on arguments with side effects. * * Returns -1 on failure (with OOM error reported), 0 on success */ # define VIR_ALLOC_N(ptr, count) virAllocN(&(ptr), sizeof(*(ptr)), (count)) /** * VIR_REALLOC_N: * @ptr: pointer to hold address of allocated memory * @count: number of elements to allocate * * Re-allocate an array of 'count' elements, each sizeof(*ptr) * bytes long and store the address of allocated memory in * 'ptr'. If 'ptr' grew, the added memory is uninitialized. * * This macro is safe to use on arguments with side effects. * * Returns -1 on failure (with OOM error reported), 0 on success */ # define VIR_REALLOC_N(ptr, count) virReallocN(&(ptr), sizeof(*(ptr)), (count)) /** * VIR_FREE: * @ptr: pointer holding address to be freed * * Free the memory stored in 'ptr' and update to point * to NULL. * * This macro is safe to use on arguments with side effects. */ # if !STATIC_ANALYSIS /* The ternary ensures that ptr is a pointer and not an integer type, * while evaluating ptr only once. This gives us extra compiler * safety when compiling under gcc. For now, we intentionally cast * away const, since a number of callers safely pass const char *. */ # define VIR_FREE(ptr) virFree((void *) (1 ? (const void *) &(ptr) : (ptr))) # else /* The Coverity static analyzer considers the else path of the "?:" and * flags the VIR_FREE() of the address of the address of memory as a * RESOURCE_LEAK resulting in numerous false positives (eg, VIR_FREE(&ptr)) */ # define VIR_FREE(ptr) virFree((void *) &(ptr)) # endif /* Don't call this directly - use the macro below */ int virFileClose(int *fdptr) ATTRIBUTE_RETURN_CHECK; # define VIR_FORCE_CLOSE(FD) \ ignore_value(virFileClose(&(FD))) # if ! LIBVIR_CHECK_VERSION(1, 0, 2) void virTypedParamsClear(virTypedParameterPtr params, int nparams); void virTypedParamsFree(virTypedParameterPtr params, int nparams); # endif /* ! LIBVIR_CHECK_VERSION(1, 0, 2) */ PyObject * getPyVirTypedParameter(const virTypedParameter *params, int nparams); virTypedParameterPtr setPyVirTypedParameter(PyObject *info, const virTypedParameter *params, int nparams) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); # if LIBVIR_CHECK_VERSION(1, 1, 0) typedef struct { const char *name; int type; } virPyTypedParamsHint; typedef virPyTypedParamsHint *virPyTypedParamsHintPtr; int virPyDictToTypedPramaOne(virTypedParameterPtr *params, int *n, int *max, virPyTypedParamsHintPtr hints, int nhints, const char *keystr, PyObject *value); int virPyDictToTypedParams(PyObject *dict, virTypedParameterPtr *ret_params, int *ret_nparams, virPyTypedParamsHintPtr hints, int nhints) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); # endif /* LIBVIR_CHECK_VERSION(1, 1, 0) */ int virPyCpumapConvert(int cpunum, PyObject *pycpumap, unsigned char **cpumapptr, int *cpumaplen); #endif /* __LIBVIRT_UTILS_H__ */ ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/libvirtaio.py0000644000175000017500000004107514612401403016330 0ustar00jirkajirka# # libvirtaio -- asyncio adapter for libvirt # Copyright (C) 2017 Wojtek Porczyk # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, see # . # '''Libvirt event loop implementation using asyncio Register the implementation of default loop: import asyncio import libvirtaio async def myapp(): libvirtaio.virEventRegisterAsyncIOImpl() conn = libvirt.open("test:///default") For compatibility with Python < 3.7: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(myapp()) asyncio.set_event_loop(None) loop.close() If Python >= 3.7 can be required then asyncio.run(myapp()) .. seealso:: https://libvirt.org/html/libvirt-libvirt-event.html ''' import asyncio import itertools import logging import warnings import libvirt from typing import Any, Callable, Dict, Generator, Optional, TypeVar # noqa F401 _T = TypeVar('_T') __author__ = 'Wojtek Porczyk ' __license__ = 'LGPL-2.1+' __all__ = [ 'getCurrentImpl', 'virEventAsyncIOImpl', 'virEventRegisterAsyncIOImpl', ] class Callback(object): '''Base class for holding callback :param virEventAsyncIOImpl impl: the implementation in which we run :param cb: the callback itself :param opaque: the opaque tuple passed by libvirt ''' # pylint: disable=too-few-public-methods _iden_counter = itertools.count() def __init__(self, impl: "virEventAsyncIOImpl", cb: Callable[[int, _T], None], opaque: _T, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) # type: ignore self.iden = next(self._iden_counter) self.impl = impl self.cb = cb self.opaque = opaque def __repr__(self) -> str: return '<{} iden={}>'.format(self.__class__.__name__, self.iden) def close(self) -> None: '''Schedule *ff* callback''' self.impl.log.debug('callback %d close(), scheduling ff', self.iden) self.impl.schedule_ff_callback(self.iden, self.opaque) # # file descriptors # class Descriptor(object): '''Manager of one file descriptor :param virEventAsyncIOImpl impl: the implementation in which we run :param int fd: the file descriptor ''' def __init__(self, impl: "virEventAsyncIOImpl", fd: int) -> None: self.impl = impl self.fd = fd self.callbacks = {} # type: Dict def _handle(self, event: int) -> None: '''Dispatch the event to the descriptors :param int event: The event (from libvirt's constants) being dispatched ''' for callback in list(self.callbacks.values()): if callback.event is not None and callback.event & event: callback.cb(callback.iden, self.fd, event, callback.opaque) def update(self) -> None: '''Register or unregister callbacks at event loop This should be called after change of any ``.event`` in callbacks. ''' # It seems like loop.add_{reader,writer} can be run multiple times # and will still register the callback only once. Likewise, # remove_{reader,writer} may be run even if the reader/writer # is not registered (and will just return False). # For the edge case of empty callbacks, any() returns False. if any(callback.event & ~( libvirt.VIR_EVENT_HANDLE_READABLE | libvirt.VIR_EVENT_HANDLE_WRITABLE) for callback in self.callbacks.values()): warnings.warn( 'The only event supported are VIR_EVENT_HANDLE_READABLE ' 'and VIR_EVENT_HANDLE_WRITABLE', UserWarning) if any(callback.event & libvirt.VIR_EVENT_HANDLE_READABLE for callback in self.callbacks.values()): self.impl.loop.add_reader( self.fd, self._handle, libvirt.VIR_EVENT_HANDLE_READABLE) else: self.impl.loop.remove_reader(self.fd) if any(callback.event & libvirt.VIR_EVENT_HANDLE_WRITABLE for callback in self.callbacks.values()): self.impl.loop.add_writer( self.fd, self._handle, libvirt.VIR_EVENT_HANDLE_WRITABLE) else: self.impl.loop.remove_writer(self.fd) def add_handle(self, callback: "FDCallback") -> None: '''Add a callback to the descriptor :param FDCallback callback: the callback to add :rtype: None After adding the callback, it is immediately watched. ''' self.callbacks[callback.iden] = callback self.update() def remove_handle(self, iden: int) -> None: '''Remove a callback from the descriptor :param int iden: the identifier of the callback :returns: the callback :rtype: FDCallback After removing the callback, the descriptor may be unwatched, if there are no more handles for it. ''' callback = self.callbacks.pop(iden) self.update() return callback class DescriptorDict(dict): '''Descriptors collection This is used internally by virEventAsyncIOImpl to hold descriptors. ''' def __init__(self, impl: "virEventAsyncIOImpl") -> None: super().__init__() self.impl = impl def __missing__(self, fd: int) -> Descriptor: descriptor = Descriptor(self.impl, fd) self[fd] = descriptor return descriptor class FDCallback(Callback): '''Callback for file descriptor (watcher) :param Descriptor descriptor: the descriptor manager :param int event: bitset of events on which to fire the callback ''' # pylint: disable=too-few-public-methods def __init__(self, *args: Any, descriptor: Descriptor, event: int, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.descriptor = descriptor self.event = event def __repr__(self) -> str: return '<{} iden={} fd={} event={}>'.format( self.__class__.__name__, self.iden, self.descriptor.fd, self.event) def update(self, event: int) -> None: '''Update the callback and fix descriptor's watchers''' self.event = event self.descriptor.update() # # timeouts # class TimeoutCallback(Callback): '''Callback for timer''' def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.timeout = -1 self._task = None def __repr__(self) -> str: return '<{} iden={} timeout={}>'.format( self.__class__.__name__, self.iden, self.timeout) async def _timer(self) -> Generator[Any, None, None]: '''An actual timer running on the event loop. This is a coroutine. ''' while True: try: if self.timeout > 0: timeout = self.timeout * 1e-3 self.impl.log.debug('sleeping %r', timeout) await asyncio.sleep(timeout) else: # scheduling timeout for next loop iteration await asyncio.sleep(0) except asyncio.CancelledError: self.impl.log.debug('timer %d cancelled', self.iden) break self.cb(self.iden, self.opaque) self.impl.log.debug('timer %r callback ended', self.iden) def update(self, timeout: int) -> None: '''Start or the timer, possibly updating timeout''' self.timeout = timeout if self.timeout >= 0 and self._task is None: self.impl.log.debug('timer %r start', self.iden) self._task = asyncio.ensure_future(self._timer(), loop=self.impl.loop) elif self.timeout < 0 and self._task is not None: self.impl.log.debug('timer %r stop', self.iden) self._task.cancel() # pylint: disable=no-member self._task = None def close(self) -> None: '''Stop the timer and call ff callback''' self.update(timeout=-1) super(TimeoutCallback, self).close() # # main implementation # class virEventAsyncIOImpl(object): '''Libvirt event adapter to asyncio. :param loop: asyncio's event loop If *loop* is not specified, the current (or default) event loop is used. ''' def __init__(self, loop: asyncio.AbstractEventLoop = None) -> None: self.loop = loop or asyncio.get_event_loop() self.callbacks = {} # type: Dict[int, Callback] self.descriptors = DescriptorDict(self) self.log = logging.getLogger(self.__class__.__name__) self._pending = 0 # Transient asyncio.Event instance dynamically created # and destroyed by drain() # NOTE invariant: _finished.is_set() iff _pending == 0 self._finished = None def __repr__(self) -> str: return '<{} callbacks={} descriptors={}>'.format( type(self).__name__, self.callbacks, self.descriptors) def _pending_inc(self) -> None: '''Increase the count of pending affairs. Do not use directly.''' self._pending += 1 if self._finished is not None: self._finished.clear() def _pending_dec(self) -> None: '''Decrease the count of pending affairs. Do not use directly.''' assert self._pending > 0 self._pending -= 1 if self._pending == 0 and self._finished is not None: self._finished.set() def register(self) -> "virEventAsyncIOImpl": '''Register this instance as event loop implementation''' # pylint: disable=bad-whitespace self.log.debug('register()') libvirt.virEventRegisterImpl( self._add_handle, self._update_handle, self._remove_handle, self._add_timeout, self._update_timeout, self._remove_timeout) return self def schedule_ff_callback(self, iden: int, opaque: _T) -> None: '''Schedule a ff callback from one of the handles or timers''' asyncio.ensure_future(self._ff_callback(iden, opaque), loop=self.loop) async def _ff_callback(self, iden: int, opaque: _T) -> None: '''Directly free the opaque object This is a coroutine. ''' self.log.debug('ff_callback(iden=%d, opaque=...)', iden) libvirt.virEventInvokeFreeCallback(opaque) self._pending_dec() async def drain(self) -> None: '''Wait for the implementation to become idle. This is a coroutine. ''' self.log.debug('drain()') if self._pending: assert self._finished is None self._finished = asyncio.Event() await self._finished.wait() self._finished = None assert self._pending == 0 self.log.debug('drain ended') def is_idle(self) -> bool: '''Returns False if there are leftovers from a connection Those may happen if there are sematical problems while closing a connection. For example, not deregistered events before .close(). ''' return not self.callbacks and not self._pending def _add_handle(self, fd: int, event: int, cb: libvirt._EventCB, opaque: _T) -> int: '''Register a callback for monitoring file handle events :param int fd: file descriptor to listen on :param int event: bitset of events on which to fire the callback :param cb: the callback to be called when an event occurrs :param opaque: user data to pass to the callback :rtype: int :returns: handle watch number to be used for updating and unregistering for events .. seealso:: https://libvirt.org/html/libvirt-libvirt-event.html#virEventAddHandleFuncFunc ''' callback = FDCallback(self, cb, opaque, descriptor=self.descriptors[fd], event=event) assert callback.iden not in self.callbacks self.log.debug('add_handle(fd=%d, event=%d, cb=..., opaque=...) = %d', fd, event, callback.iden) self.callbacks[callback.iden] = callback self.descriptors[fd].add_handle(callback) self._pending_inc() return callback.iden def _update_handle(self, watch: int, event: int) -> None: '''Change event set for a monitored file handle :param int watch: file descriptor watch to modify :param int event: new events to listen on .. seealso:: https://libvirt.org/html/libvirt-libvirt-event.html#virEventUpdateHandleFunc ''' self.log.debug('update_handle(watch=%d, event=%d)', watch, event) callback = self.callbacks[watch] assert isinstance(callback, FDCallback) callback.update(event=event) def _remove_handle(self, watch: int) -> int: '''Unregister a callback from a file handle. :param int watch: file descriptor watch to stop listening on :returns: -1 on error, 0 on success .. seealso:: https://libvirt.org/html/libvirt-libvirt-event.html#virEventRemoveHandleFunc ''' self.log.debug('remove_handle(watch=%d)', watch) try: callback = self.callbacks.pop(watch) except KeyError as err: self.log.warning('remove_handle(): no such handle: %r', err.args[0]) return -1 assert isinstance(callback, FDCallback) fd = callback.descriptor.fd assert callback is self.descriptors[fd].remove_handle(watch) if len(self.descriptors[fd].callbacks) == 0: del self.descriptors[fd] callback.close() return 0 def _add_timeout(self, timeout: int, cb: libvirt._TimerCB, opaque: _T) -> int: '''Register a callback for a timer event :param int timeout: the timeout to monitor :param cb: the callback to call when timeout has expired :param opaque: user data to pass to the callback :rtype: int :returns: a timer value .. seealso:: https://libvirt.org/html/libvirt-libvirt-event.html#virEventAddTimeoutFunc ''' callback = TimeoutCallback(self, cb, opaque) assert callback.iden not in self.callbacks self.log.debug('add_timeout(timeout=%d, cb=..., opaque=...) = %d', timeout, callback.iden) self.callbacks[callback.iden] = callback callback.update(timeout=timeout) self._pending_inc() return callback.iden def _update_timeout(self, timer: int, timeout: int) -> None: '''Change frequency for a timer :param int timer: the timer to modify :param int timeout: the new timeout value in ms .. seealso:: https://libvirt.org/html/libvirt-libvirt-event.html#virEventUpdateTimeoutFunc ''' self.log.debug('update_timeout(timer=%d, timeout=%d)', timer, timeout) callback = self.callbacks[timer] assert isinstance(callback, TimeoutCallback) callback.update(timeout=timeout) def _remove_timeout(self, timer: int) -> int: '''Unregister a callback for a timer :param int timer: the timer to remove :returns: -1 on error, 0 on success .. seealso:: https://libvirt.org/html/libvirt-libvirt-event.html#virEventRemoveTimeoutFunc ''' self.log.debug('remove_timeout(timer=%d)', timer) try: callback = self.callbacks.pop(timer) except KeyError as err: self.log.warning('remove_timeout(): no such timeout: %r', err.args[0]) return -1 callback.close() return 0 _current_impl = None # type: Optional[virEventAsyncIOImpl] def getCurrentImpl() -> Optional[virEventAsyncIOImpl]: '''Return the current implementation, or None if not yet registered''' return _current_impl def virEventRegisterAsyncIOImpl(loop: asyncio.AbstractEventLoop = None) -> virEventAsyncIOImpl: '''Arrange for libvirt's callbacks to be dispatched via asyncio event loop The implementation object is returned, but in normal usage it can safely be discarded. ''' global _current_impl _current_impl = virEventAsyncIOImpl(loop=loop).register() return _current_impl ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/pyproject.toml0000644000175000017500000000012114612401403016511 0ustar00jirkajirka[build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1648809002.0 libvirt-python-11.3.0/requirements-test.txt0000664000175000017500000000001214221552052020042 0ustar00jirkajirkanose lxml ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1746171070.9019244 libvirt-python-11.3.0/setup.cfg0000644000175000017500000000117715005072277015444 0ustar00jirkajirka[metadata] name = libvirt-python version = file: VERSION description = The libvirt virtualization API python binding long_description = file: README long_description_content_type = text/x-rst url = http://www.libvirt.org maintainer = Libvirt Maintainers maintainer_email = libvir-list@redhat.com license_files = COPYING classifiers = Development Status :: 5 - Production/Stable Intended Audience :: Developers License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+) Programming Language :: Python :: 3 :: Only [options] python_requires = >=3.6 package_dir = =build [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1715606996.0 libvirt-python-11.3.0/setup.py0000755000175000017500000002135114620412724015331 0ustar00jirkajirka#!/usr/bin/env python3 import sys import re import shutil import subprocess import time from pathlib import Path from setuptools import setup, Extension from setuptools.command.build_ext import build_ext from setuptools.command.build_py import build_py from setuptools.command.sdist import sdist def getVersion(): with open("VERSION") as f: return f.read().strip() def check_pkgcfg(): try: proc = subprocess.run(["pkg-config", "--version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) if proc.returncode != 0: print("pkg-config binary does not appear to be functional") sys.exit(1) except FileNotFoundError: print("pkg-config binary is required to compile libvirt-python") sys.exit(1) def check_minimum_libvirt_version(): subprocess.check_call(["pkg-config", "--print-errors", f"--atleast-version={MIN_LIBVIRT}", "libvirt"]) def have_libvirt_lxc(): proc = subprocess.run(["pkg-config", f"--atleast-version={MIN_LIBVIRT_LXC}", "libvirt"]) if proc.returncode == 0: return True return False def get_pkgconfig_data(args, mod, required=True): """Run pkg-config to and return content associated with it""" cmd = ["pkg-config"] + args + [mod] output = subprocess.check_output(cmd, universal_newlines=True) for line in output.splitlines(): if line == "": if required: args_str = " ".join(args) raise Exception(f"Cannot determine '{args_str}' from " "libvirt pkg-config file") line = "" return line.strip() def get_api_xml_files(): """Check with pkg-config that libvirt is present and extract the API XML file paths we need from it""" libvirt_api = get_pkgconfig_data(["--variable", "libvirt_api"], "libvirt") offset = libvirt_api.index("-api.xml") libvirt_qemu_api = libvirt_api[0:offset] + "-qemu-api.xml" offset = libvirt_api.index("-api.xml") libvirt_lxc_api = libvirt_api[0:offset] + "-lxc-api.xml" return (libvirt_api, libvirt_qemu_api, libvirt_lxc_api) def get_module_lists(): """ Determine which modules we are actually building, and all their required config """ c_modules = [] py_modules = [] ldflags = get_pkgconfig_data(["--libs-only-L"], "libvirt", False).split() cflags = get_pkgconfig_data(["--cflags"], "libvirt", False).split() cflags += ["-Ibuild"] cflags += ["-Wp,-DPy_LIMITED_API=0x03060000"] module = Extension("libvirtmod", sources=[ "libvirt-override.c", "build/libvirt.c", "typewrappers.c", "libvirt-utils.c" ], libraries=["virt"], include_dirs=["."]) module.extra_compile_args.extend(cflags) module.extra_link_args.extend(ldflags) c_modules.append(module) py_modules.append("libvirt") moduleqemu = Extension("libvirtmod_qemu", sources=[ "libvirt-qemu-override.c", "build/libvirt-qemu.c", "typewrappers.c", "libvirt-utils.c" ], libraries=["virt-qemu", "virt"], include_dirs=["."]) moduleqemu.extra_compile_args.extend(cflags) moduleqemu.extra_link_args.extend(ldflags) c_modules.append(moduleqemu) py_modules.append("libvirt_qemu") if have_libvirt_lxc(): modulelxc = Extension("libvirtmod_lxc", sources=[ "libvirt-lxc-override.c", "build/libvirt-lxc.c", "typewrappers.c", "libvirt-utils.c" ], libraries=["virt-lxc", "virt"], include_dirs=["."]) modulelxc.extra_compile_args.extend(cflags) modulelxc.extra_link_args.extend(ldflags) c_modules.append(modulelxc) py_modules.append("libvirt_lxc") py_modules.append("libvirtaio") return c_modules, py_modules ################### # Custom commands # ################### class my_build_ext(build_ext): def run(self): check_minimum_libvirt_version() apis = get_api_xml_files() subprocess.check_call([sys.executable, "generator.py", "libvirt", apis[0], "c"]) subprocess.check_call([sys.executable, "generator.py", "libvirt-qemu", apis[1], "c"]) if have_libvirt_lxc(): subprocess.check_call([sys.executable, "generator.py", "libvirt-lxc", apis[2], "c"]) build_ext.run(self) class my_build_py(build_py): def run(self): check_minimum_libvirt_version() apis = get_api_xml_files() subprocess.check_call([sys.executable, "generator.py", "libvirt", apis[0], "py"]) subprocess.check_call([sys.executable, "generator.py", "libvirt-qemu", apis[1], "py"]) if have_libvirt_lxc(): subprocess.check_call([sys.executable, "generator.py", "libvirt-lxc", apis[2], "py"]) shutil.copy("libvirtaio.py", "build") build_py.run(self) class my_sdist(sdist): user_options = sdist.user_options description = "Update libvirt-python.spec; build sdist-tarball." def initialize_options(self): self.snapshot = None sdist.initialize_options(self) def finalize_options(self): if self.snapshot is not None: self.snapshot = 1 sdist.finalize_options(self) @staticmethod def _gen_from_in(file_in, file_out, replace_pattern, replace): with open(file_in) as f_in, open(file_out, "w") as f_out: for line in f_in: f_out.write(line.replace(replace_pattern, replace)) def gen_rpm_spec(self): return self._gen_from_in("libvirt-python.spec.in", "libvirt-python.spec", "@VERSION@", getVersion()) def gen_authors(self): cmd = ["git", "log", "--pretty=format:%aN <%aE>"] output = subprocess.check_output(cmd, universal_newlines=True) git_authors = {line.strip() for line in output.splitlines()} authors = sorted(git_authors, key=str.lower) authors = [" " + author for author in authors] self._gen_from_in("AUTHORS.in", "AUTHORS", "@AUTHORS@", "\n".join(authors)) def gen_changelog(self): cmd = ["git", "log", "--pretty=format:%H:%ct %an <%ae>%n%n%s%n%b%n"] with open("ChangeLog", "w") as f_out: output = subprocess.check_output(cmd, universal_newlines=True) for line in output.splitlines(): m = re.match(r"([a-f0-9]+):(\d+)\s(.*)", line) if m: t = time.gmtime(int(m.group(2))) fmt = "{: 04d}-{: 02d}-{: 02d} {}\n" f_out.write(fmt.format(t.tm_year, t.tm_mon, t.tm_mday, m.group(3))) else: if re.match(r"Signed-off-by", line): continue f_out.write(" " + line.strip() + "\n") def run(self): if Path(".git").exists(): try: self.gen_rpm_spec() self.gen_authors() self.gen_changelog() sdist.run(self) finally: files = [ "libvirt-python.spec", "AUTHORS", "ChangeLog" ] for f in files: try: Path(f).unlink() except FileNotFoundError: pass else: sdist.run(self) ################## # Invoke setup() # ################## if sys.version_info < (3, 6): print("libvirt-python requires Python >= 3.6 to build") sys.exit(1) MIN_LIBVIRT = "0.9.11" MIN_LIBVIRT_LXC = "1.0.2" # Hack to stop "pip install" failing with error # about missing "build" dir. Path("build").mkdir(exist_ok=True) check_pkgcfg() _c_modules, _py_modules = get_module_lists() setup( ext_modules=_c_modules, py_modules=_py_modules, package_dir={ '': 'build' }, cmdclass={ "build_ext": my_build_ext, "build_py": my_build_py, "sdist": my_sdist, }, ) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1746171070.9005516 libvirt-python-11.3.0/tests/0000755000175000017500000000000015005072277014757 5ustar00jirkajirka././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/eventmock.py0000644000175000017500000000532614612401403017320 0ustar00jirkajirka import libvirt import libvirtmod _add_handle_impl = None _update_handle_impl = None _remove_handle_impl = None _add_timeout_impl = None _update_timeout_impl = None _remove_timeout_impl = None _registered = False def _add_handle(fd: int, event: int, cb: libvirt._EventCB, opaque: libvirt._T) -> int: global _add_handle_impl assert _add_handle_impl != None return _add_handle_impl(fd, event, cb, opaque) def _update_handle(watch: int, event: int) -> None: global _update_handle_impl assert _update_handle_impl != None _update_handle_impl(watch, event) def _remove_handle(watch: int) -> int: global _remove_handle_impl assert _remove_handle_impl != None return _remove_handle_impl(watch) def _add_timeout(timeout: int, cb: libvirt._TimerCB, opaque: libvirt._T) -> int: global _add_timeout_impl assert _add_timeout_impl != None return _add_timeout_impl(timeout, cb, opaque) def _update_timeout(timer: int, timeout: int) -> None: global _update_timeout_impl assert _update_timeout_impl != None _update_timeout_impl(timer, timeout) def _remove_timeout(timer: int) -> int: global _remove_timeout_impl assert _remove_timeout_impl != None return _remove_timeout_impl(timer) # libvirt.virEventRegisterImpl() is a one time call per process # This method is intended to be used with mock patching, so that # tests can get the appearance of being able to call # virEventRegisterImpl many times. # # Note, this relies on the tests closing all connection objects # and not leaving any handles/timers pending when they stop # running their event loop impl. def virEventRegisterImplMock(add_handle_impl, update_handle_impl, remove_handle_impl, add_timeout_impl, update_timeout_impl, remove_timeout_impl): global _add_handle_impl global _update_handle_impl global _remove_handle_impl global _add_timeout_impl global _update_timeout_impl global _remove_timeout_impl _add_handle_impl = add_handle_impl _update_handle_impl = update_handle_impl _remove_handle_impl = remove_handle_impl _add_timeout_impl = add_timeout_impl _update_timeout_impl = update_timeout_impl _remove_timeout_impl = remove_timeout_impl global _registered if not _registered: libvirtmod.virEventRegisterImpl(_add_handle, _update_handle, _remove_timeout, _add_timeout, _update_timeout, _remove_timeout) _registered = True ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1715606996.0 libvirt-python-11.3.0/tests/test_aio.py0000644000175000017500000001360214620412724017137 0ustar00jirkajirkaimport asyncio import libvirt import libvirtaio import sys import unittest from unittest import mock import eventmock class TestLibvirtAio(unittest.TestCase): async def _run(self, register): def lifecycleCallback(conn, dom, event, detail, domainChangedEvent): if (event == libvirt.VIR_DOMAIN_EVENT_STOPPED or event == libvirt.VIR_DOMAIN_EVENT_STARTED): domainChangedEvent.set() if register: libvirtEvents = libvirtaio.virEventRegisterAsyncIOImpl() else: libvirtEvents = libvirtaio.getCurrentImpl() conn = libvirt.open("test:///default") dom = conn.lookupByName("test") eventRegistered = False domainStopped = False try: # Ensure the VM is running. self.assertEqual([libvirt.VIR_DOMAIN_RUNNING, libvirt.VIR_DOMAIN_RUNNING_UNKNOWN], dom.state()) self.assertTrue(libvirtEvents.is_idle()) # Register VM start/stopped event handler. domainChangedEvent = asyncio.Event() conn.domainEventRegisterAny(dom, libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE, lifecycleCallback, domainChangedEvent) eventRegistered = True self.assertFalse(libvirtEvents.is_idle()) # Stop the VM. dom.destroy() domainStopped = True # Ensure domain stopped event is received. await asyncio.wait_for(domainChangedEvent.wait(), 2) self.assertEqual([libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_SHUTOFF_DESTROYED], dom.state()) # Start the VM. domainChangedEvent.clear() domainStopped = False dom.create() # Ensure domain started event is received. await asyncio.wait_for(domainChangedEvent.wait(), 2) self.assertEqual([libvirt.VIR_DOMAIN_RUNNING, libvirt.VIR_DOMAIN_RUNNING_BOOTED], dom.state()) self.assertFalse(libvirtEvents.is_idle()) # Deregister the VM start/stopped event handler. eventRegistered = False conn.domainEventDeregisterAny(libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE) # Wait for event queue to clear. await libvirtEvents.drain() # Make sure event queue is cleared. self.assertTrue(libvirtEvents.is_idle()) finally: if eventRegistered: conn.domainEventDeregisterAny(libvirt.VIR_DOMAIN_EVENT_ID_LIFECYCLE) if domainStopped: dom.create() @mock.patch('libvirt.virEventRegisterImpl', side_effect=eventmock.virEventRegisterImplMock) def testEventsWithManualLoopSetup(self, mock_event_register): # Register libvirt events after starting the asyncio loop. # # Manually create and set the event loop against this # thread. loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(self._run(register=True)) loop.close() asyncio.set_event_loop(None) mock_event_register.assert_called_once() @mock.patch('libvirt.virEventRegisterImpl', side_effect=eventmock.virEventRegisterImplMock) @unittest.skipIf(sys.version_info < (3,7), "test requires Python 3.7+") def testEventsWithAsyncioRun(self, mock_event_register): # Register libvirt events after starting the asyncio loop. # # Use asyncio helper to create and set the event loop # against this thread. asyncio.run(self._run(register=True)) mock_event_register.assert_called_once() @mock.patch('libvirt.virEventRegisterImpl', side_effect=eventmock.virEventRegisterImplMock) def testEventsPreInitExplicit(self, mock_event_register): # Register libvirt events before starting the asyncio loop. # # Tell virEventRegisterAsyncIOImpl() explicitly what loop # to use before we set a loop for this thread. loop = asyncio.new_event_loop() libvirtaio.virEventRegisterAsyncIOImpl(loop) asyncio.set_event_loop(loop) loop.run_until_complete(self._run(register=False)) loop.close() asyncio.set_event_loop(None) mock_event_register.assert_called_once() @mock.patch('libvirt.virEventRegisterImpl', side_effect=eventmock.virEventRegisterImplMock) @unittest.skipIf(sys.version_info >= (3,10), "test incompatible with 3.10+") def testEventsPreInitImplicit(self, mock_event_register): # Register libvirt events before starting the asyncio loop. # # Allow virEventRegisterAsyncIOImpl() to implicitly find the # loop we set for this thread. loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) libvirtaio.virEventRegisterAsyncIOImpl() loop.run_until_complete(self._run(register=False)) loop.close() asyncio.set_event_loop(None) mock_event_register.assert_called_once() @mock.patch('libvirt.virEventRegisterImpl', side_effect=eventmock.virEventRegisterImplMock) @unittest.skipIf(sys.version_info >= (3,10), "test incompatible with 3.10+") def testEventsImplicitLoopInit(self, mock_event_register): # Register libvirt events before starting the asyncio loop. # # Let virEventRegisterAsyncIOImpl() auto-create a default # event loop, which we then register against this thread. # # Historically this often worked if called from the main thead, # but since Python 3.10 this triggers a deprecation warning, # which will turn into a RuntimeError in a later release. libvirtaio.virEventRegisterAsyncIOImpl() loop = asyncio.get_event_loop() loop.run_until_complete(self._run(register=False)) loop.close() asyncio.set_event_loop(None) mock_event_register.assert_called_once() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_api_coverage.py0000644000175000017500000003763214612401403021015 0ustar00jirkajirka#!/usr/bin/env python3 import sys from typing import Dict, List, Set, Tuple # noqa F401 import libvirt import unittest import os def get_libvirt_api_xml_path(): import subprocess args = ["pkg-config", "--variable", "libvirt_api", "libvirt"] proc = subprocess.Popen(args, stdout=subprocess.PIPE) stdout, _ = proc.communicate() if proc.returncode: sys.exit(proc.returncode) return stdout.splitlines()[0] # Identify all functions and enums in public API def identify_functions_enums(tree): enumvals = {} # type: Dict[str, Dict[str, int]] second_pass = [] # type: List[str] wantenums = [] # type: List[str] wantfunctions = [] # type: List[str] wantfunctions = tree.xpath('/api/files/file/exports[@type="function"]/@symbol') for n in tree.xpath('/api/symbols/enum'): typ = n.attrib['type'] name = n.attrib['name'] val = n.attrib['value'] if typ not in enumvals: enumvals[typ] = {} # If the value cannot be converted to int, it is reference to # another enum and needs to be sorted out later on try: val = int(val) except ValueError: second_pass.append(n) continue enumvals[typ][name] = int(val) for n in second_pass: typ = n.attrib['type'] name = n.attrib['name'] val = n.attrib['value'] for v in enumvals.values(): if val in v: val = int(v[val]) break # Version 4.0.0 was broken as missing VIR_TYPED_PARAM enums # constants. This is harmless from POV of validating API # coverage so ignore this error. if (not isinstance(val, int) and not val.startswith("VIR_TYPED_PARAM_")): fail = True print("Cannot get a value of enum %s (originally %s)" % (val, name)) enumvals[typ][name] = val for n in tree.xpath('/api/files/file/exports[@type="enum"]/@symbol'): for enumval in enumvals.values(): if n in enumval: enumv = enumval break # Eliminate sentinels if n.endswith('_LAST') and enumv[n] == max(enumv.values()): continue wantenums.append(n) return wantfunctions, wantenums, enumvals # Identify all classes and methods in the 'libvirt' python module def identify_class_methods(wantenums, enumvals): gotenums = [] # type: List[str] gottypes = [] # type: List[str] gotfunctions = {"libvirt": []} # type: Dict[str, List[str]] for name in dir(libvirt): if name.startswith('_'): continue thing = getattr(libvirt, name) # Special-case libvirtError to deal with python 2.4 difference # in Exception class type reporting. if isinstance(thing, int): gotenums.append(name) elif getattr(thing, "__module__", "") == "typing": continue elif type(thing) == type or name == "libvirtError": gottypes.append(name) gotfunctions[name] = [] elif callable(thing): gotfunctions["libvirt"].append(name) for enum in wantenums: if enum not in gotenums: fail = True for typ, enumval in enumvals.items(): if enum in enumval: raise Exception("Missing exported enum %s of type %s" % (enum, typ)) for klassname in gottypes: klassobj = getattr(libvirt, klassname) for name in dir(klassobj): if name.startswith('_'): continue if name == 'c_pointer': continue thing = getattr(klassobj, name) if callable(thing): gotfunctions[klassname].append(name) return gotfunctions, gottypes # First cut at mapping of C APIs to python classes + methods def basic_class_method_mapping(wantfunctions, gottypes): basicklassmap = {} # type: Dict[str, Tuple[str, str, str]] for cname in wantfunctions: name = cname # Some virConnect APIs have stupid names if name[0:7] == "virNode" and name[0:13] != "virNodeDevice": name = "virConnect" + name[7:] if name[0:7] == "virConn" and name[0:10] != "virConnect": name = "virConnect" + name[7:] # The typed param APIs are only for internal use if name[0:14] == "virTypedParams": continue if name[0:23] == "virNetworkDHCPLeaseFree": continue if name[0:28] == "virDomainStatsRecordListFree": continue if name[0:19] == "virDomainFSInfoFree": continue if name[0:25] == "virDomainIOThreadInfoFree": continue if name[0:22] == "virDomainInterfaceFree": continue if name[0:21] == "virDomainListGetStats": name = "virConnectDomainListGetStats" # These aren't functions, they're callback signatures if name in ["virConnectAuthCallbackPtr", "virConnectCloseFunc", "virStreamSinkFunc", "virStreamSourceFunc", "virStreamEventCallback", "virEventHandleCallback", "virEventTimeoutCallback", "virFreeCallback", "virStreamSinkHoleFunc", "virStreamSourceHoleFunc", "virStreamSourceSkipFunc"]: continue if name[0:21] == "virConnectDomainEvent" and name[-8:] == "Callback": continue if name[0:22] == "virConnectNetworkEvent" and name[-8:] == "Callback": continue if (name.startswith("virConnectStoragePoolEvent") and name.endswith("Callback")): continue if (name.startswith("virConnectNodeDeviceEvent") and name.endswith("Callback")): continue if (name.startswith("virConnectSecretEvent") and name.endswith("Callback")): continue # virEvent APIs go into main 'libvirt' namespace not any class if name[0:8] == "virEvent": if name[-4:] == "Func": continue basicklassmap[name] = ("libvirt", name, cname) else: found = False # To start with map APIs to classes based on the # naming prefix. Mistakes will be fixed in next # loop for klassname in gottypes: klen = len(klassname) if name[0:klen] == klassname: found = True if name not in basicklassmap: basicklassmap[name] = (klassname, name[klen:], cname) elif len(basicklassmap[name]) < klen: basicklassmap[name] = (klassname, name[klen:], cname) # Anything which can't map to a class goes into the # global namespaces if not found: basicklassmap[name] = ("libvirt", name[3:], cname) return basicklassmap # Deal with oh so many special cases in C -> python mapping def fixup_class_method_mapping(basicklassmap): finalklassmap = {} # type: Dict[str, Tuple[str, str, str]] for name, (klass, func, cname) in sorted(basicklassmap.items()): # The object lifecycle APIs are irrelevant since they're # used inside the object constructors/destructors. if func in ["Ref", "Free", "New", "GetConnect", "GetDomain", "GetNetwork"]: if klass == "virStream" and func == "New": klass = "virConnect" func = "NewStream" else: continue # All the error handling methods need special handling if klass == "libvirt": if func in ["CopyLastError", "DefaultErrorFunc", "ErrorFunc", "FreeError", "SaveLastError", "ResetError"]: continue elif func in ["GetLastError", "GetLastErrorMessage", "GetLastErrorCode", "GetLastErrorDomain", "ResetLastError", "Initialize"]: func = "vir" + func elif func == "SetErrorFunc": func = "RegisterErrorHandler" elif klass == "virConnect": if func in ["CopyLastError", "SetErrorFunc"]: continue elif func in ["GetLastError", "ResetLastError"]: func = "virConn" + func # Remove 'Get' prefix from most APIs, except those in virConnect # and virDomainSnapshot namespaces which stupidly used a different # convention which we now can't fix without breaking API if func[0:3] == "Get" and klass not in ["virConnect", "virDomainCheckpoint", "virDomainSnapshot", "libvirt"]: if func not in ["GetCPUStats", "GetTime"]: func = func[3:] # The object creation and lookup APIs all have to get re-mapped # into the parent class if func in ["CreateXML", "CreateLinux", "CreateXMLWithFiles", "DefineXML", "CreateXMLFrom", "LookupByUUID", "LookupByUUIDString", "LookupByVolume" "LookupByName", "LookupByID", "LookupByName", "LookupByKey", "LookupByPath", "LookupByMACString", "LookupByUsage", "LookupByVolume", "LookupByTargetPath", "LookupSCSIHostByWWN", "LookupByPortDev", "Restore", "RestoreFlags", "RestoreParams", "SaveImageDefineXML", "SaveImageGetXMLDesc", "DefineXMLFlags", "CreateXMLFlags"]: if klass != "virDomain": func = klass[3:] + func if klass in ["virDomainCheckpoint", "virDomainSnapshot"]: klass = "virDomain" func = func[6:] elif klass == "virStorageVol" and func in ["StorageVolCreateXMLFrom", "StorageVolCreateXML"]: klass = "virStoragePool" func = func[10:] elif klass == "virNetworkPort": klass = "virNetwork" func = func[7:] elif func == "StoragePoolLookupByVolume": klass = "virStorageVol" elif func == "StorageVolLookupByName": klass = "virStoragePool" else: klass = "virConnect" # The open methods get remapped to primary namespace if klass == "virConnect" and func in ["Open", "OpenAuth", "OpenReadOnly"]: klass = "libvirt" # These are inexplicably renamed in the python API if func == "ListDomains": func = "ListDomainsID" elif func == "ListAllNodeDevices": func = "ListAllDevices" elif func == "ListNodeDevices": func = "ListDevices" # The virInterfaceChangeXXXX APIs go into virConnect. Stupidly # they have lost their 'interface' prefix in names, but we can't # fix this name if func[0:6] == "Change": klass = "virConnect" # Need to special case the checkpoint and snapshot APIs if klass == "virDomainSnapshot" and func in ["Current", "ListNames", "Num"]: klass = "virDomain" func = "snapshot" + func # Names should start with lowercase letter... func = func[0:1].lower() + func[1:] if func[0:8] == "nWFilter": func = "nwfilter" + func[8:] if func[0:8] == "fSFreeze" or func[0:6] == "fSThaw" or func[0:6] == "fSInfo": func = "fs" + func[2:] if func[0:12] == "iOThreadInfo": func = "ioThreadInfo" if klass == "virNetwork": func = func.replace("dHCP", "DHCP") # ...except when they don't. More stupid naming # decisions we can't fix if func == "iD": func = "ID" if func == "uUID": func = "UUID" if func == "uUIDString": func = "UUIDString" if func == "oSType": func = "OSType" if func == "xMLDesc": func = "XMLDesc" if func == "mACString": func = "MACString" if func == "fDAssociate": func = "FDAssociate" finalklassmap[name] = (klass, func, cname) return finalklassmap # Validate that every C API is mapped to a python API def validate_c_to_python_api_mappings(finalklassmap, gotfunctions): usedfunctions = set() # type: Set[str] for name, (klass, func, cname) in sorted(finalklassmap.items()): if func in gotfunctions[klass]: usedfunctions.add("%s.%s" % (klass, func)) else: raise Exception("%s -> %s.%s (C API not mapped to python)" % (name, klass, func)) return usedfunctions # Validate that every python API has a corresponding C API def validate_python_to_c_api_mappings(gotfunctions, usedfunctions): for klass in gotfunctions: if klass == "libvirtError": continue for func in sorted(gotfunctions[klass]): # These are pure python methods with no C APi if func in ["connect", "getConnect", "domain", "getDomain", "virEventInvokeFreeCallback", "network", "sparseRecvAll", "sparseSendAll"]: continue key = "%s.%s" % (klass, func) if key not in usedfunctions: raise Exception("%s.%s (Python API not mapped to C)" % (klass, func)) # Validate that all the low level C APIs have binding def validate_c_api_bindings_present(finalklassmap): for name, (klass, func, cname) in sorted(finalklassmap.items()): pyname = cname if pyname == "virSetErrorFunc": pyname = "virRegisterErrorHandler" elif pyname == "virConnectListDomains": pyname = "virConnectListDomainsID" # These exist in C and exist in python, but we've got # a pure-python impl so don't check them if name in ["virStreamRecvAll", "virStreamSendAll", "virStreamSparseRecvAll", "virStreamSparseSendAll"]: continue try: thing = getattr(libvirt.libvirtmod, pyname) except AttributeError: raise Exception("libvirt.libvirtmod.%s (C binding does not exist)" % pyname) # Historically python lxml is incompatible with any other # use of libxml2 in the same process. Merely importing # 'lxml.etree' will result in libvirt's use of libxml2 # triggering a SEGV: # # https://bugs.launchpad.net/lxml/+bug/1748019 # # per the last comment though, it was somewhat improved by # # https://github.com/lxml/lxml/commit/fa1d856cad369d0ac64323ddec14b02281491706 # # so if we have version >= 4.5.2, we are safe to import # lxml.etree for the purposes of unit tests at least def broken_lxml(): import lxml if not hasattr(lxml, "__version__"): return True digits = [int(d) for d in lxml.__version__.split(".")] # We have 3 digits in versions today, but be paranoid # for possible future changes. if len(digits) != 3: return False version = (digits[0] * 1000 * 1000) + (digits[1] * 1000) + digits[2] if version < 4005002: return True return False api_test_flag = unittest.skipUnless( os.environ.get('LIBVIRT_API_COVERAGE', False), "API coverage test is only for upstream maintainers", ) lxml_broken_flag = unittest.skipIf( broken_lxml(), "lxml version clashes with libxml usage from libvirt" ) @api_test_flag @lxml_broken_flag class LibvirtAPICoverage(unittest.TestCase): def test_libvirt_api(self): xml = get_libvirt_api_xml_path() import lxml.etree with open(xml, "r") as fp: tree = lxml.etree.parse(fp) wantfunctions, wantenums, enumvals = identify_functions_enums(tree) gotfunctions, gottypes = identify_class_methods(wantenums, enumvals) basicklassmap = basic_class_method_mapping(wantfunctions, gottypes) finalklassmap = fixup_class_method_mapping(basicklassmap) usedfunctions = validate_c_to_python_api_mappings(finalklassmap, gotfunctions) validate_python_to_c_api_mappings(gotfunctions, usedfunctions) validate_c_api_bindings_present(finalklassmap) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_conn.py0000644000175000017500000000550414612401403017317 0ustar00jirkajirkaimport unittest import libvirt import tempfile import contextlib import os class TestLibvirtConn(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") def tearDown(self): self.conn = None def testConnDomainList(self): doms = self.conn.listAllDomains() self.assertEqual(len(doms), 1) self.assertEqual(type(doms[0]), libvirt.virDomain) self.assertEqual(doms[0].name(), "test") class TestLibvirtConnAuth(unittest.TestCase): connXML = """ marin srinivasa """ def setUp(self): def noop(msg, opaque): pass libvirt.registerErrorHandler(noop, None) @contextlib.contextmanager def tempxmlfile(content): try: fp = tempfile.NamedTemporaryFile(delete=False, prefix="libvirt-python-test", suffix=".xml") fname = fp.name fp.write(content.encode("utf8")) fp.close() yield fname finally: os.unlink(fname) def authHelper(self, username, password): with TestLibvirtConnAuth.tempxmlfile(self.connXML) as fname: magic = 142857 def authCB(creds, opaque): if opaque != magic: return -1 for cred in creds: if (cred[0] == libvirt.VIR_CRED_AUTHNAME and username is not None): cred[4] = username return 0 elif (cred[0] == libvirt.VIR_CRED_PASSPHRASE and password is not None): cred[4] = password return 0 return -1 return 0 auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_ECHOPROMPT, libvirt.VIR_CRED_REALM, libvirt.VIR_CRED_PASSPHRASE, libvirt.VIR_CRED_NOECHOPROMPT, libvirt.VIR_CRED_EXTERNAL], authCB, magic] return libvirt.openAuth("test://" + fname, auth, 0) def testOpenAuthGood(self): conn = self.authHelper("srinivasa", "87539319") def testOpenAuthBad(self): try: conn = self.authHelper("srinivasa", "2147483647") raise Exception("Unexpected open success") except libvirt.libvirtError as ex: pass def testOpenAuthNone(self): try: conn = self.authHelper(None, None) raise Exception("Unexpected open success") except libvirt.libvirtError as ex: pass ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_domain.py0000644000175000017500000000136614612401403017633 0ustar00jirkajirkaimport unittest import libvirt class TestLibvirtDomain(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") self.dom = self.conn.lookupByName("test") def tearDown(self): self.dom = None self.conn = None def testDomainSchedParams(self): params = self.dom.schedulerParameters() self.assertEqual(len(params), 1) self.assertTrue("weight" in params) params["weight"] = 100 self.dom.setSchedulerParameters(params) @unittest.skipIf(libvirt.getVersion() == 4000000, "test driver screenshot broken in 4.0.0") def testScreenshot(self): stream = self.conn.newStream() ss = self.dom.screenshot(stream, 0, 0) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_domain_checkpoint.py0000644000175000017500000000105014612401403022030 0ustar00jirkajirkaimport unittest import libvirt class TestLibvirtDomainCheckpoint(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") self.dom = self.conn.lookupByName("test") def tearDown(self): self.dom = None self.conn = None @unittest.skipUnless(hasattr(libvirt.virDomain, "checkpointCreateXML"), "checkpoints not supported in this libvirt") def testCheckpointCreate(self): cp = self.dom.checkpointCreateXML("") cp.delete() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_domain_snapshot.py0000644000175000017500000000061614612401403021547 0ustar00jirkajirkaimport unittest import libvirt class TestLibvirtDomainSnapshot(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") self.dom = self.conn.lookupByName("test") def tearDown(self): self.dom = None self.conn = None def testSnapCreate(self): snap = self.dom.snapshotCreateXML("") snap.delete() ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_interface.py0000644000175000017500000000055714612401403020325 0ustar00jirkajirkaimport unittest import libvirt class TestLibvirtInterface(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") self.iface = self.conn.interfaceLookupByName("eth1") def tearDown(self): self.iface = None self.conn = None def testAttr(self): self.assertEqual(self.iface.name(), "eth1") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_network.py0000644000175000017500000000055314612401403020052 0ustar00jirkajirkaimport unittest import libvirt class TestLibvirtNetwork(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") self.net = self.conn.networkLookupByName("default") def tearDown(self): self.net = None self.conn = None def testAttr(self): self.assertEqual(self.net.name(), "default") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_nodedev.py0000644000175000017500000000057414612401403020010 0ustar00jirkajirkaimport unittest import libvirt class TestLibvirtNodeDev(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") self.nodedev = self.conn.nodeDeviceLookupByName("computer") def tearDown(self): self.nodedev = None self.conn = None def testAttr(self): self.assertEqual(self.nodedev.name(), "computer") ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/tests/test_storage.py0000644000175000017500000000113014612401403020015 0ustar00jirkajirkaimport unittest import libvirt class TestLibvirtStorage(unittest.TestCase): def setUp(self): self.conn = libvirt.open("test:///default") self.pool = self.conn.storagePoolLookupByName("default-pool") def tearDown(self): self.pool = None self.conn = None def testAttr(self): self.assertEqual(self.pool.name(), "default-pool") def testVol(self): volxml = ''' raw.img 10 1000 ''' vol = self.pool.createXML(volxml) ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1730452597.0 libvirt-python-11.3.0/tox.ini0000644000175000017500000000014714711116165015130 0ustar00jirkajirka[tox] envlist = py39,py310,py311,py312,py313 [testenv] deps= lxml pytest commands= pytest ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/typewrappers.c0000644000175000017500000002501014612401403016512 0ustar00jirkajirka/* * types.c: converter functions between the internal representation * and the Python objects * * Copyright (C) 2005-2019 Red Hat, Inc. * * Daniel Veillard */ /* Horrible kludge to work around even more horrible name-space pollution * via Python.h. That file includes /usr/include/python3.x/pyconfig*.h, * which has over 180 autoconf-style HAVE_* definitions. Shame on them. */ #undef HAVE_PTHREAD_H #include #include #include "typewrappers.h" #include "libvirt-utils.h" static PyObject * libvirt_buildPyObject(void *cobj, const char *name, PyCapsule_Destructor destr) { return PyCapsule_New(cobj, name, destr); } PyObject * libvirt_intWrap(int val) { return PyLong_FromLong(val); } PyObject * libvirt_uintWrap(unsigned int val) { return PyLong_FromUnsignedLong(val); } PyObject * libvirt_longWrap(long val) { return PyLong_FromLong(val); } PyObject * libvirt_ulongWrap(unsigned long val) { return PyLong_FromLong(val); } PyObject * libvirt_longlongWrap(long long val) { return PyLong_FromLongLong(val); } PyObject * libvirt_ulonglongWrap(unsigned long long val) { return PyLong_FromUnsignedLongLong(val); } PyObject * libvirt_charPtrSizeWrap(char *str, Py_ssize_t size) { if (str == NULL) { return VIR_PY_NONE; } return PyBytes_FromStringAndSize(str, size); } PyObject * libvirt_charPtrWrap(char *str) { if (str == NULL) { return VIR_PY_NONE; } return PyUnicode_FromString(str); } PyObject * libvirt_constcharPtrWrap(const char *str) { if (str == NULL) { return VIR_PY_NONE; } return PyUnicode_FromString(str); } PyObject * libvirt_boolWrap(int val) { if (val) Py_RETURN_TRUE; else Py_RETURN_FALSE; } int libvirt_intUnwrap(PyObject *obj, int *val) { long long_val; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } /* If obj is type of PyInt_Type, PyInt_AsLong converts it * to C long type directly. If it is of PyLong_Type, PyInt_AsLong * will call PyLong_AsLong() to deal with it automatically. */ long_val = PyLong_AsLong(obj); if ((long_val == -1) && PyErr_Occurred()) return -1; #if LONG_MAX != INT_MAX if (long_val >= INT_MIN && long_val <= INT_MAX) { *val = long_val; } else { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C int"); return -1; } #else *val = long_val; #endif return 0; } int libvirt_uintUnwrap(PyObject *obj, unsigned int *val) { unsigned long long_val; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } long_val = PyLong_AsUnsignedLong(obj); if ((long_val == (unsigned long)-1) && PyErr_Occurred()) return -1; if (long_val <= UINT_MAX) { *val = long_val; } else { PyErr_SetString(PyExc_OverflowError, "Python int too large to convert to C unsigned int"); return -1; } return 0; } int libvirt_longUnwrap(PyObject *obj, long *val) { long long_val; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } long_val = PyLong_AsLong(obj); if ((long_val == -1) && PyErr_Occurred()) return -1; *val = long_val; return 0; } int libvirt_ulongUnwrap(PyObject *obj, unsigned long *val) { long long_val; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } long_val = PyLong_AsLong(obj); if ((long_val == -1) && PyErr_Occurred()) return -1; if (long_val >= 0) { *val = long_val; } else { PyErr_SetString(PyExc_OverflowError, "negative Python int cannot be converted to C unsigned long"); return -1; } return 0; } int libvirt_longlongUnwrap(PyObject *obj, long long *val) { long long llong_val = -1; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } if (PyLong_Check(obj)) llong_val = PyLong_AsLongLong(obj); else PyErr_SetString(PyExc_TypeError, "an integer is required"); if ((llong_val == -1) && PyErr_Occurred()) return -1; *val = llong_val; return 0; } int libvirt_ulonglongUnwrap(PyObject *obj, unsigned long long *val) { unsigned long long ullong_val = -1; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } if (PyLong_Check(obj)) { ullong_val = PyLong_AsUnsignedLongLong(obj); } else { PyErr_SetString(PyExc_TypeError, "an integer is required"); } if ((ullong_val == (unsigned long long)-1) && PyErr_Occurred()) return -1; *val = ullong_val; return 0; } int libvirt_doubleUnwrap(PyObject *obj, double *val) { double double_val; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } double_val = PyFloat_AsDouble(obj); if ((double_val == -1) && PyErr_Occurred()) return -1; *val = double_val; return 0; } int libvirt_boolUnwrap(PyObject *obj, bool *val) { int ret; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } if ((ret = PyObject_IsTrue(obj)) < 0) return ret; *val = ret > 0; return 0; } int libvirt_charPtrUnwrap(PyObject *obj, char **str) { PyObject *bytes; const char *ret; *str = NULL; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } if (!(bytes = PyUnicode_AsUTF8String(obj))) return -1; ret = PyBytes_AsString(bytes); if (ret) { *str = strdup(ret); if (!*str) PyErr_NoMemory(); } Py_DECREF(bytes); return ret && *str ? 0 : -1; } int libvirt_charPtrSizeUnwrap(PyObject *obj, char **str, Py_ssize_t *size) { *str = NULL; *size = 0; if (!obj) { PyErr_SetString(PyExc_TypeError, "unexpected type"); return -1; } return PyBytes_AsStringAndSize(obj, str, size); } PyObject * libvirt_virDomainPtrWrap(virDomainPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virDomainPtr", NULL); return ret; } PyObject * libvirt_virNetworkPtrWrap(virNetworkPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virNetworkPtr", NULL); return ret; } PyObject * libvirt_virNetworkPortPtrWrap(virNetworkPortPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virNetworkPortPtr", NULL); return ret; } PyObject * libvirt_virInterfacePtrWrap(virInterfacePtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virInterfacePtr", NULL); return ret; } PyObject * libvirt_virStoragePoolPtrWrap(virStoragePoolPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virStoragePoolPtr", NULL); return ret; } PyObject * libvirt_virStorageVolPtrWrap(virStorageVolPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virStorageVolPtr", NULL); return ret; } PyObject * libvirt_virConnectPtrWrap(virConnectPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virConnectPtr", NULL); return ret; } PyObject * libvirt_virNodeDevicePtrWrap(virNodeDevicePtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virNodeDevicePtr", NULL); return ret; } PyObject * libvirt_virSecretPtrWrap(virSecretPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virSecretPtr", NULL); return ret; } PyObject * libvirt_virNWFilterPtrWrap(virNWFilterPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virNWFilterPtr", NULL); return ret; } PyObject * libvirt_virNWFilterBindingPtrWrap(virNWFilterBindingPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virNWFilterBindingPtr", NULL); return ret; } PyObject * libvirt_virStreamPtrWrap(virStreamPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virStreamPtr", NULL); return ret; } PyObject * libvirt_virDomainCheckpointPtrWrap(virDomainCheckpointPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virDomainCheckpointPtr", NULL); return ret; } PyObject * libvirt_virDomainSnapshotPtrWrap(virDomainSnapshotPtr node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virDomainSnapshotPtr", NULL); return ret; } PyObject * libvirt_virEventHandleCallbackWrap(virEventHandleCallback node) { PyObject *ret; if (node == NULL) { printf("%s: WARNING - Wrapping None\n", __func__); return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virEventHandleCallback", NULL); return ret; } PyObject * libvirt_virEventTimeoutCallbackWrap(virEventTimeoutCallback node) { PyObject *ret; if (node == NULL) { printf("%s: WARNING - Wrapping None\n", __func__); return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virEventTimeoutCallback", NULL); return ret; } PyObject * libvirt_virFreeCallbackWrap(virFreeCallback node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "virFreeCallback", NULL); return ret; } PyObject * libvirt_virVoidPtrWrap(void* node) { PyObject *ret; if (node == NULL) { return VIR_PY_NONE; } ret = libvirt_buildPyObject(node, "void*", NULL); return ret; } ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1714029315.0 libvirt-python-11.3.0/typewrappers.h0000644000175000017500000002202214612401403016517 0ustar00jirkajirka/* * libvirt_wrap.h: type wrappers for libvir python bindings * * Copyright (C) 2005, 2011-2012 Red Hat, Inc. * * Daniel Veillard */ #include #include #include #include #ifdef __GNUC__ # ifdef ATTRIBUTE_UNUSED # undef ATTRIBUTE_UNUSED # endif # ifndef ATTRIBUTE_UNUSED # define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) # endif /* ATTRIBUTE_UNUSED */ #else # define ATTRIBUTE_UNUSED #endif #if !LIBVIR_CHECK_VERSION(4, 5, 0) typedef struct _virNWFilterBinding *virNWFilterBindingPtr; #endif #if !LIBVIR_CHECK_VERSION(5, 5, 0) typedef struct _virNetworkPort *virNetworkPortPtr; #endif #if !LIBVIR_CHECK_VERSION(5, 6, 0) typedef struct _virDomainCheckpoint *virDomainCheckpointPtr; #endif #define PyvirConnect_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirConnect_Object *)(v))->obj)) typedef struct { PyObject_HEAD virConnectPtr obj; } PyvirConnect_Object; #define PyvirDomain_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirDomain_Object *)(v))->obj)) typedef struct { PyObject_HEAD virDomainPtr obj; } PyvirDomain_Object; #define PyvirNetwork_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirNetwork_Object *)(v))->obj)) typedef struct { PyObject_HEAD virNetworkPtr obj; } PyvirNetwork_Object; #define PyvirNetworkPort_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirNetworkPort_Object *)(v))->obj)) typedef struct { PyObject_HEAD virNetworkPortPtr obj; } PyvirNetworkPort_Object; #define PyvirInterface_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirInterface_Object *)(v))->obj)) typedef struct { PyObject_HEAD virInterfacePtr obj; } PyvirInterface_Object; #define PyvirStoragePool_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirStoragePool_Object *)(v))->obj)) typedef struct { PyObject_HEAD virStoragePoolPtr obj; } PyvirStoragePool_Object; #define PyvirStorageVol_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirStorageVol_Object *)(v))->obj)) typedef struct { PyObject_HEAD virStorageVolPtr obj; } PyvirStorageVol_Object; #define PyvirNodeDevice_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirNodeDevice_Object *)(v))->obj)) typedef struct { PyObject_HEAD virNodeDevicePtr obj; } PyvirNodeDevice_Object; #define PyvirSecret_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirSecret_Object *)(v))->obj)) typedef struct { PyObject_HEAD virSecretPtr obj; } PyvirSecret_Object; #define PyvirNWFilter_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirNWFilter_Object *)(v))->obj)) typedef struct { PyObject_HEAD virNWFilterPtr obj; } PyvirNWFilter_Object; #define PyvirNWFilterBinding_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirNWFilterBinding_Object *)(v))->obj)) typedef struct { PyObject_HEAD virNWFilterBindingPtr obj; } PyvirNWFilterBinding_Object; #define PyvirStream_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirStream_Object *)(v))->obj)) typedef struct { PyObject_HEAD virStreamPtr obj; } PyvirStream_Object; #define PyvirDomainCheckpoint_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirDomainCheckpoint_Object *)(v))->obj)) typedef struct { PyObject_HEAD virDomainCheckpointPtr obj; } PyvirDomainCheckpoint_Object; #define PyvirDomainSnapshot_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirDomainSnapshot_Object *)(v))->obj)) typedef struct { PyObject_HEAD virDomainSnapshotPtr obj; } PyvirDomainSnapshot_Object; #define PyvirEventHandleCallback_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirEventHandleCallback_Object *)(v))->obj)) typedef struct { PyObject_HEAD virEventHandleCallback obj; } PyvirEventHandleCallback_Object; #define PyvirEventTimeoutCallback_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirEventTimeoutCallback_Object *)(v))->obj)) typedef struct { PyObject_HEAD virEventTimeoutCallback obj; } PyvirEventTimeoutCallback_Object; #define PyvirFreeCallback_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirFreeCallback_Object *)(v))->obj)) typedef struct { PyObject_HEAD virFreeCallback obj; } PyvirFreeCallback_Object; #define PyvirVoidPtr_Get(v) (((v) == Py_None) ? NULL : \ (((PyvirVoidPtr_Object *)(v))->obj)) typedef struct { PyObject_HEAD void* obj; } PyvirVoidPtr_Object; PyObject * libvirt_intWrap(int val); PyObject * libvirt_uintWrap(unsigned int val); PyObject * libvirt_longWrap(long val); PyObject * libvirt_ulongWrap(unsigned long val); PyObject * libvirt_longlongWrap(long long val); PyObject * libvirt_ulonglongWrap(unsigned long long val); PyObject * libvirt_charPtrWrap(char *str); PyObject * libvirt_charPtrSizeWrap(char *str, Py_ssize_t size); PyObject * libvirt_constcharPtrWrap(const char *str); PyObject * libvirt_boolWrap(int val); int libvirt_intUnwrap(PyObject *obj, int *val); int libvirt_uintUnwrap(PyObject *obj, unsigned int *val); int libvirt_longUnwrap(PyObject *obj, long *val); int libvirt_ulongUnwrap(PyObject *obj, unsigned long *val); int libvirt_longlongUnwrap(PyObject *obj, long long *val); int libvirt_ulonglongUnwrap(PyObject *obj, unsigned long long *val); int libvirt_doubleUnwrap(PyObject *obj, double *val); int libvirt_boolUnwrap(PyObject *obj, bool *val); int libvirt_charPtrUnwrap(PyObject *obj, char **str); int libvirt_charPtrSizeUnwrap(PyObject *obj, char **str, Py_ssize_t *size); PyObject * libvirt_virConnectPtrWrap(virConnectPtr node); PyObject * libvirt_virDomainPtrWrap(virDomainPtr node); PyObject * libvirt_virNetworkPtrWrap(virNetworkPtr node); PyObject * libvirt_virNetworkPortPtrWrap(virNetworkPortPtr node); PyObject * libvirt_virInterfacePtrWrap(virInterfacePtr node); PyObject * libvirt_virStoragePoolPtrWrap(virStoragePoolPtr node); PyObject * libvirt_virStorageVolPtrWrap(virStorageVolPtr node); PyObject * libvirt_virEventHandleCallbackWrap(virEventHandleCallback node); PyObject * libvirt_virEventTimeoutCallbackWrap(virEventTimeoutCallback node); PyObject * libvirt_virFreeCallbackWrap(virFreeCallback node); PyObject * libvirt_virVoidPtrWrap(void* node); PyObject * libvirt_virNodeDevicePtrWrap(virNodeDevicePtr node); PyObject * libvirt_virSecretPtrWrap(virSecretPtr node); PyObject * libvirt_virNWFilterPtrWrap(virNWFilterPtr node); PyObject * libvirt_virNWFilterBindingPtrWrap(virNWFilterBindingPtr node); PyObject * libvirt_virStreamPtrWrap(virStreamPtr node); PyObject * libvirt_virDomainCheckpointPtrWrap(virDomainCheckpointPtr node); PyObject * libvirt_virDomainSnapshotPtrWrap(virDomainSnapshotPtr node); /* Provide simple macro statement wrappers (adapted from GLib, in turn from Perl): * LIBVIRT_STMT_START { statements; } LIBVIRT_STMT_END; * can be used as a single statement, as in * if (x) LIBVIRT_STMT_START { ... } LIBVIRT_STMT_END; else ... * * When GCC is compiling C code in non-ANSI mode, it will use the * compiler __extension__ to wrap the statements within `({' and '})' braces. * When compiling on platforms where configure has defined * HAVE_DOWHILE_MACROS, statements will be wrapped with `do' and `while (0)'. * For any other platforms (SunOS4 is known to have this issue), wrap the * statements with `if (1)' and `else (void) 0'. */ #if !(defined (LIBVIRT_STMT_START) && defined (LIBVIRT_STMT_END)) # if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) # define LIBVIRT_STMT_START (void) __extension__ ( # define LIBVIRT_STMT_END ) # else /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */ # if defined (HAVE_DOWHILE_MACROS) # define LIBVIRT_STMT_START do # define LIBVIRT_STMT_END while (0) # else /* !HAVE_DOWHILE_MACROS */ # define LIBVIRT_STMT_START if (1) # define LIBVIRT_STMT_END else (void) 0 # endif /* !HAVE_DOWHILE_MACROS */ # endif /* !(__GNUC__ && !__STRICT_ANSI__ && !__cplusplus) */ #endif #if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 7 # define LIBVIRT_BEGIN_ALLOW_THREADS \ LIBVIRT_STMT_START { \ PyThreadState *_save = NULL; \ if (PyEval_ThreadsInitialized()) \ _save = PyEval_SaveThread(); # define LIBVIRT_END_ALLOW_THREADS \ if (PyEval_ThreadsInitialized()) \ PyEval_RestoreThread(_save); \ } LIBVIRT_STMT_END # define LIBVIRT_ENSURE_THREAD_STATE \ LIBVIRT_STMT_START { \ PyGILState_STATE _save = PyGILState_UNLOCKED; \ if (PyEval_ThreadsInitialized()) \ _save = PyGILState_Ensure(); # define LIBVIRT_RELEASE_THREAD_STATE \ if (PyEval_ThreadsInitialized()) \ PyGILState_Release(_save); \ } LIBVIRT_STMT_END #else # define LIBVIRT_BEGIN_ALLOW_THREADS \ LIBVIRT_STMT_START { \ PyThreadState *_save = PyEval_SaveThread(); # define LIBVIRT_END_ALLOW_THREADS \ PyEval_RestoreThread(_save); \ } LIBVIRT_STMT_END # define LIBVIRT_ENSURE_THREAD_STATE \ LIBVIRT_STMT_START { \ PyGILState_STATE _save = PyGILState_Ensure(); # define LIBVIRT_RELEASE_THREAD_STATE \ PyGILState_Release(_save); \ } LIBVIRT_STMT_END #endif #ifndef NULLSTR #define NULLSTR(s) ((s) ? (s) : "") #endif