mirror of
				https://gitlab.com/libvirt/libvirt.git
				synced 2025-10-30 20:24:58 +03:00 
			
		
		
		
	Compare commits
	
		
			81 Commits
		
	
	
		
			v11.9.0-rc
			...
			v0.9.6-mai
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 610112ba00 | ||
|  | be7a5de9d0 | ||
|  | 86d330daa0 | ||
|  | b5a34d96ff | ||
|  | bebe5122b9 | ||
|  | 687c089380 | ||
|  | f527b94607 | ||
|  | 96d4cd58f5 | ||
|  | c84053c2ab | ||
|  | a1ceef9b42 | ||
|  | 6cde2d3965 | ||
|  | 2f809dba2c | ||
|  | b50badc5ee | ||
|  | 85fc04dd1b | ||
|  | 06e1daac70 | ||
|  | fb68e28304 | ||
|  | 64b8925c37 | ||
|  | fcc2893679 | ||
|  | b598d0864d | ||
|  | 2bdc05d1a4 | ||
|  | da8ab75e90 | ||
|  | a822202d6c | ||
|  | c12c765f83 | ||
|  | aa041fcef0 | ||
|  | 0e4efa3d53 | ||
|  | 26ceca4b02 | ||
|  | 1a6bad7108 | ||
|  | fcf32fc978 | ||
|  | 0bff012ddc | ||
|  | d6f20a2dfa | ||
|  | dac6e9a210 | ||
|  | b4e9a21c3b | ||
|  | 8bd5c79224 | ||
|  | b0200c81ec | ||
|  | 8213166b92 | ||
|  | 3f769afc45 | ||
|  | 766be49f17 | ||
|  | 3d8f56d129 | ||
|  | f20331c810 | ||
|  | 0f1bc306d3 | ||
|  | 4f5f16eea9 | ||
|  | 24c17ed1ec | ||
|  | abf4ab4827 | ||
|  | 25eeffcb17 | ||
|  | 96c3c2752e | ||
|  | 43b7292293 | ||
|  | abb78d4ec2 | ||
|  | 49bc39be66 | ||
|  | 208d5836c8 | ||
|  | 5b5b1150cf | ||
|  | 3cbb1385e9 | ||
|  | 757316875c | ||
|  | a261feba42 | ||
|  | cd921a5572 | ||
|  | 505c99f62e | ||
|  | 77874a2791 | ||
|  | 7de869fc03 | ||
|  | 4e9e178e3c | ||
|  | abb78a216c | ||
|  | 643ac7203a | ||
|  | e11aa0262b | ||
|  | 4744461619 | ||
|  | e95df90dbb | ||
|  | 56fb0c0695 | ||
|  | 5ede14ef8e | ||
|  | f0ba1c096a | ||
|  | 42419b2891 | ||
|  | 762801607a | ||
|  | d20a6240b3 | ||
|  | bf887b8bb5 | ||
|  | bf09c64ada | ||
|  | dc738b8395 | ||
|  | f2b5c5ff22 | ||
|  | c6ead37ba1 | ||
|  | 472e49f558 | ||
|  | 2ce01ba20f | ||
|  | bf540af8b3 | ||
|  | fc9a66cfb1 | ||
|  | 776124e6f0 | ||
|  | d20f5421a9 | ||
|  | 64eadd9a7b | 
| @@ -1,17 +0,0 @@ | ||||
| ( | ||||
|  (c-mode . ( | ||||
|             (c-file-style . "K&R") | ||||
|             (indent-tabs-mode . nil) | ||||
|             (c-indent-level . 4) | ||||
|             (c-basic-offset . 4) | ||||
|             )) | ||||
|  (html-mode . ( | ||||
| 	       (indent-tabs-mode . nil) | ||||
| 	       )) | ||||
|  (sh-mode . ( | ||||
| 	     (indent-tabs-mode . nil) | ||||
| 	     )) | ||||
|  (nxml-mode . ( | ||||
| 	       (indent-tabs-mode . nil) | ||||
| 	       )) | ||||
|  ) | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -37,6 +37,7 @@ | ||||
| /configure | ||||
| /configure.lineno | ||||
| /daemon/*_dispatch.h | ||||
| /docs/apibuild.py.stamp | ||||
| /docs/hvsupport.html.in | ||||
| /docs/libvirt-qemu-*.xml | ||||
| /gnulib/lib/* | ||||
|   | ||||
							
								
								
									
										1
									
								
								.gnulib
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								.gnulib
									
									
									
									
									
								
							 Submodule .gnulib deleted from da1717b7f9
									
								
							
							
								
								
									
										32
									
								
								.mailmap
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								.mailmap
									
									
									
									
									
								
							| @@ -1,32 +0,0 @@ | ||||
| # 'git shortlog --help' and look for mailmap for the format of each line | ||||
|  | ||||
| # Email consolidation: | ||||
| # <Preferred address in AUTHORS> <other alias used by same author> | ||||
|  | ||||
| <amy.griffis@hp.com> <aron.griffis@hp.com> | ||||
| <bozzolan@gmail.com> <redshift@gmx.com> | ||||
| <charles_duffy@messageone.com> <charles@dyfis.net> | ||||
| <dfj@redhat.com> <dfj@dfj.bne.redhat.com> | ||||
| <eblake@redhat.com> <ebb9@byu.net> | ||||
| <gdolley@arpnetworks.com> <gdolley@ucla.edu> | ||||
| <gerhard.stenzel@de.ibm.com> <gstenzel@linux.vnet.ibm.com> | ||||
| <jamie@canonical.com> <jamie@ubuntu.com> | ||||
| <laine@redhat.com> <laine@laine.org> | ||||
| <meyering@redhat.com> <jim@meyering.net> | ||||
| <socketpair@gmail.com> <socketpair gmail com> | ||||
| <soren@linux2go.dk> <soren@ubuntu.com> | ||||
| <jfehlig@suse.com> <jfehlig@novell.com> | ||||
| <jfehlig@suse.com> <jfehlig@linux-ypgk.site> | ||||
| <jclift@redhat.com> <justin@salasaga.org> | ||||
| <berrange@redhat.com> <dan@berrange.com> | ||||
| <soren@linux2go.dk> <soren@canonical.com> | ||||
| <cfergeau@redhat.com> <teuf@gnome.org> | ||||
| <wency@cn.fujitsu.com> <wency cn fujitsu com> | ||||
| <cardoe@cardoe.com> <cardoe@gentoo.org> | ||||
| <fsimonce@redhat.com> <federico.simoncelli@gmail.com> | ||||
| <marcandre.lureau@redhat.com> <marcandre.lureau@gmail.com> | ||||
| <supriyak@linux.vnet.ibm.com> <supriyak@in.ibm.com> | ||||
|  | ||||
| # Name consolidation: | ||||
| # Preferred author spelling <preferred email> | ||||
| Alex Jia <ajia@redhat.com> | ||||
							
								
								
									
										206
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										206
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -1,206 +0,0 @@ | ||||
|    libvirt Authors | ||||
|    =============== | ||||
|  | ||||
| The libvirt project was initiated by: | ||||
|  | ||||
|   Daniel Veillard      <veillard@redhat.com> or <daniel@veillard.com> | ||||
|  | ||||
| The primary maintainers and people with commit access rights: | ||||
|  | ||||
|   Daniel Veillard      <veillard@redhat.com> | ||||
|   Daniel Berrange      <berrange@redhat.com> | ||||
|   Richard W.M. Jones   <rjones@redhat.com> | ||||
|   Mark McLoughlin      <markmc@redhat.com> | ||||
|   Anthony Liguori      <aliguori@us.ibm.com> | ||||
|   Jim Meyering         <meyering@redhat.com> | ||||
|   Jim Fehlig           <jfehlig@suse.com> | ||||
|   Chris Lalancette     <clalance@redhat.com> | ||||
|   Cole Robinson        <crobinso@redhat.com> | ||||
|   Guido Günther        <agx@sigxcpu.org> | ||||
|   John Levon           <john.levon@sun.com> | ||||
|   Matthias Bolte       <matthias.bolte@googlemail.com> | ||||
|   Jiří Denemark        <jdenemar@redhat.com> | ||||
|   Dave Allan           <dallan@redhat.com> | ||||
|   Laine Stump          <laine@redhat.com> | ||||
|   Stefan Berger        <stefanb@us.ibm.com> | ||||
|   Eric Blake           <eblake@redhat.com> | ||||
|   Justin Clift         <jclift@redhat.com> | ||||
|   Osier Yang           <jyang@redhat.com> | ||||
|   Wen Congyang         <wency@cn.fujitsu.com> | ||||
|   Michal Prívozník     <mprivozn@redhat.com> | ||||
|  | ||||
| Previous maintainers: | ||||
|   Karel Zak            <kzak@redhat.com> | ||||
|   Atsushi SAKAI        <sakaia@jp.fujitsu.com> | ||||
|   Dave Leskovec        <dlesko@linux.vnet.ibm.com> | ||||
|   Dan Smith            <danms@us.ibm.com> | ||||
|  | ||||
| Patches have also been contributed by: | ||||
|  | ||||
|   David Lutterkort     <dlutter@redhat.com> | ||||
|   Andrew Puch          <apuch@redhat.com> | ||||
|   Philippe Berthault   <philippe.berthault@Bull.net> | ||||
|   Hugh Brock           <hbrock@redhat.com> | ||||
|   Michel Ponceau       <michel.ponceau@bull.net> | ||||
|   Jeremy Katz          <katzj@redhat.com> | ||||
|   Pete Vetere          <pvetere@redhat.com> | ||||
|   Kazuki Mizushima     <mizushima.kazuk@jp.fujitsu.com> | ||||
|   Saori Fukuta         <fukuta.saori@jp.fujitsu.com> | ||||
|   Tatsuro Enokura      <fj7716hz@aa.jp.fujitsu.com> | ||||
|   Takahashi Tomohiro   <takatom@jp.fujitsu.com> | ||||
|   Nobuhiro Itou        <fj0873gn@aa.jp.fujitsu.com> | ||||
|   Masayuki Sunou       <fj1826dm@aa.jp.fujitsu.com> | ||||
|   Mark Johnson         <johnson.nh@gmail.com> | ||||
|   Christian Ehrhardt   <ehrhardt@linux.vnet.ibm.com> | ||||
|   Shuveb Hussain       <shuveb@binarykarma.com> | ||||
|   Jim Paris            <jim@jtan.com> | ||||
|   Daniel Hokka Zakrisson <daniel@hozac.com> | ||||
|   Mads Chr. Olesen     <shiyee@shiyee.dk> | ||||
|   Anton Protopopov     <aspsk2@gmail.com> | ||||
|   Stefan de Konink     <dekonink@kinkrsoftware.nl> | ||||
|   Kaitlin Rupert       <kaitlin@linux.vnet.ibm.com> | ||||
|   Evgeniy Sokolov      <evg@openvz.org> | ||||
|   David Lively         <dlively@virtualiron.com> | ||||
|   Charles Duffy        <Charles_Duffy@messageone.com> | ||||
|   Nguyen Anh Quynh     <aquynh@gmail.com> | ||||
|   James Morris         <jmorris@namei.org> | ||||
|   Chris Wright         <chrisw@redhat.com> | ||||
|   Ben Guthro           <ben.guthro@gmail.com> | ||||
|   Shigeki Sakamoto     <fj0588di@aa.jp.fujitsu.com> | ||||
|   Gerd von Egidy       <lists@egidy.de> | ||||
|   Itamar Heim          <iheim@redhat.com> | ||||
|   Markus Armbruster    <armbru@redhat.com> | ||||
|   Ryota Ozaki          <ozaki.ryota@gmail.com> | ||||
|   James Morris         <jmorris@namei.org> | ||||
|   Daniel J Walsh       <dwalsh@redhat.com> | ||||
|   Maximilian Wilhelm   <max@rfc2324.org> | ||||
|   Pritesh Kothari      <Pritesh.Kothari@Sun.COM> | ||||
|   Amit Shah            <amit.shah@redhat.com> | ||||
|   Florian Vichot       <florian.vichot@diateam.net> | ||||
|   Takahashi Tomohiro   <takatom@jp.fujitsu.com> | ||||
|   Serge E. Hallyn      <serue@us.ibm.com> | ||||
|   Soren Hansen         <soren@linux2go.dk> | ||||
|   Abel Míguez Rodríguez<amiguezr@pdi.ucm.es> | ||||
|   Doug Goldstein       <cardoe@cardoe.com> | ||||
|   Javier Fontan        <jfontan@gmail.com> | ||||
|   Federico Simoncelli  <fsimonce@redhat.com> | ||||
|   Amy Griffis          <amy.griffis@hp.com> | ||||
|   Henrik Persson E     <henrik.e.persson@ericsson.com> | ||||
|   Satoru SATOH         <satoru.satoh@gmail.com> | ||||
|   Paolo Bonzini        <pbonzini@redhat.com> | ||||
|   Miloslav Trmač       <mitr@redhat.com> | ||||
|   Jamie Strandboge     <jamie@canonical.com> | ||||
|   Gerhard Stenzel      <gerhard.stenzel@de.ibm.com> | ||||
|   Matthew Booth        <mbooth@redhat.com> | ||||
|   Diego Elio Pettenò   <flameeyes@gmail.com> | ||||
|   Adam Litke           <agl@us.ibm.com> | ||||
|   Steve Yarmie         <steve.yarmie@gmail.com> | ||||
|   Dan Kenigsberg       <danken@redhat.com> | ||||
|   Yuji NISHIDA         <nishidy@nict.go.jp> | ||||
|   Dustin Xiong         <x_k_123@hotmail.com> | ||||
|   Rolf Eike Beer       <eike@sf-mail.de> | ||||
|   Wolfgang Mauerer     <wolfgang.mauerer@siemens.com> | ||||
|   Philipp Hahn         <hahn@univention.de> | ||||
|   Ed Swierk            <eswierk@aristanetworks.com> | ||||
|   Paolo Smiraglia      <paolo.smiraglia@gmail.com> | ||||
|   Sharadha Prabhakar   <sharadha.prabhakar@citrix.com> | ||||
|   Chris Wong           <wongc-redhat@hoku.net> | ||||
|   Daniel Berteaud      <daniel@firewall-services.com> | ||||
|   Dustin Kirkland      <kirkland@canonical.com> | ||||
|   Luiz Capitulino      <lcapitulino@redhat.com> | ||||
|   Ryan Harper          <ryanh@us.ibm.com> | ||||
|   Spencer Shimko       <sshimko@tresys.com> | ||||
|   Marco Bozzolan       <bozzolan@gmail.com> | ||||
|   Alex Williamson      <alex.williamson@redhat.com> | ||||
|   Ersek Laszlo         <lacos@caesar.elte.hu> | ||||
|   Kenneth Nagin        <NAGIN@il.ibm.com> | ||||
|   Klaus Ethgen         <Klaus@Ethgen.de> | ||||
|   Bryan Kearney        <bkearney@redhat.com> | ||||
|   Darry L. Pierce      <dpierce@redhat.com> | ||||
|   David Jorm           <dfj@redhat.com> | ||||
|   Eduardo Otubo        <otubo@linux.vnet.ibm.com> | ||||
|   Garry Dolley         <gdolley@arpnetworks.com> | ||||
|   Harshavardhana       <harsha@gluster.com> | ||||
|   Jonas Eriksson       <jonas.j.eriksson@ericsson.com> | ||||
|   Jun Koi              <junkoi2004@gmail.com> | ||||
|   Olivier Fourdan      <ofourdan@redhat.com> | ||||
|   Ron Yorston          <rmy@tigress.co.uk> | ||||
|   Shahar Klein         <shaharklein@yahoo.com> | ||||
|   Taizo ITO            <taizo.ito@hde.co.jp> | ||||
|   Thomas Treutner      <thomas@scripty.at> | ||||
|   Jean-Baptiste Rouault <jean-baptiste.rouault@diateam.net> | ||||
|   Марк Коренберг       <socketpair@gmail.com> | ||||
|   Alan Pevec           <apevec@redhat.com> | ||||
|   Aurelien Rougemont   <beorn@binaries.fr> | ||||
|   Patrick Dignan       <pat_dignan@dell.com> | ||||
|   Serge Hallyn         <serge.hallyn@canonical.com> | ||||
|   Nikunj A. Dadhania   <nikunj@linux.vnet.ibm.com> | ||||
|   Lai Jiangshan        <laijs@cn.fujitsu.com> | ||||
|   Harsh Prateek Bora   <harsh@linux.vnet.ibm.com> | ||||
|   John Morrissey       <jwm@horde.net> | ||||
|   KAMEZAWA Hiroyuki    <kamezawa.hiroyu@jp.fujitsu.com> | ||||
|   Hu Tao               <hutao@cn.fujitsu.com> | ||||
|   Laurent Léonard      <laurent@open-minds.org> | ||||
|   MORITA Kazutaka      <morita.kazutaka@lab.ntt.co.jp> | ||||
|   Josh Durgin          <joshd@hq.newdream.net> | ||||
|   Roopa Prabhu         <roprabhu@cisco.com> | ||||
|   Paweł Krześniak      <pawel.krzesniak@gmail.com> | ||||
|   Kay Schubert         <kayegypt@web.de> | ||||
|   Marc-André Lureau    <marcandre.lureau@redhat.com> | ||||
|   Juerg Haefliger      <juerg.haefliger@hp.com> | ||||
|   Matthias Dahl        <mdvirt@designassembly.de> | ||||
|   Niels de Vos         <ndevos@redhat.com> | ||||
|   Davidlohr Bueso      <dave@gnu.org> | ||||
|   Alon Levy            <alevy@redhat.com> | ||||
|   Hero Phương          <herophuong93@gmail.com> | ||||
|   Zdenek Styblik       <stybla@turnovfree.net> | ||||
|   Gui Jianfeng         <guijianfeng@cn.fujitsu.com> | ||||
|   Michal Novotny       <minovotn@redhat.com> | ||||
|   Christophe Fergeau   <cfergeau@redhat.com> | ||||
|   Markus Groß          <gross@univention.de> | ||||
|   Phil Petty           <phpetty@cisco.com> | ||||
|   Taku Izumi           <izumi.taku@jp.fujitsu.com> | ||||
|   Minoru Usui          <usui@mxm.nes.nec.co.jp> | ||||
|   Tiziano Mueller      <dev-zero@gentoo.org> | ||||
|   Thibault VINCENT     <thibault.vincent@smartjog.com> | ||||
|   Naoya Horiguchi      <n-horiguchi@ah.jp.nec.com> | ||||
|   Jesse Cook           <code.crashenx@gmail.com> | ||||
|   Alexander Todorov    <atodorov@otb.bg> | ||||
|   Richard Laager       <rlaager@wiktel.com> | ||||
|   Mark Wu              <dwu@redhat.com> | ||||
|   Yufang Zhang         <yuzhang@redhat.com> | ||||
|   Supriya Kannery      <supriyak@linux.vnet.ibm.com> | ||||
|   Dirk Herrendoerfer   <d.herrendoerfer@herrendoerfer.name> | ||||
|   Taisuke Yamada       <tai@rakugaki.org> | ||||
|   Heath Petersen       <HeathPetersen@Kandre.com> | ||||
|   Neil Wilson          <neil@aldur.co.uk> | ||||
|   Ohad Levy            <ohadlevy@gmail.com> | ||||
|   Michael Chapman      <mike@very.puzzling.org> | ||||
|   Daniel Gollub        <gollub@b1-systems.de> | ||||
|   David S. Wang        <dwang2@cisco.com> | ||||
|   Ruben Kerkhof        <ruben@rubenkerkhof.com> | ||||
|   Scott Moser          <smoser@ubuntu.com> | ||||
|   Guannan Ren          <gren@redhat.com> | ||||
|   John Williams        <john.williams@petalogix.com> | ||||
|   Michael Santos       <michael.santos@gmail.com> | ||||
|   Alex Jia             <ajia@redhat.com> | ||||
|   Oskari Saarenmaa     <os@ohmu.fi> | ||||
|   Peter Krempa         <pkrempa@redhat.com> | ||||
|   Nan Zhang            <nzhang@redhat.com> | ||||
|   Wieland Hoffmann     <themineo@googlemail.com> | ||||
|   Douglas Schilling Landgraf <dougsland@redhat.com> | ||||
|   Tom Vijlbrief        <tom.vijlbrief@xs4all.nl> | ||||
|   Shradha Shah         <sshah@solarflare.com> | ||||
|   Steve Hodgson        <shodgson@solarflare.com> | ||||
|   Xu He Jie            <xuhj@linux.vnet.ibm.com> | ||||
|   Lei Li               <lilei@linux.vnet.ibm.com> | ||||
|   Matthias Witte       <witte@netzquadrat.de> | ||||
|  | ||||
|   [....send patches to get your name here....] | ||||
|  | ||||
| The libvirt Logo was designed by Diana Fong | ||||
|  | ||||
| -- End | ||||
| ;; Local Variables: | ||||
| ;; coding: utf-8 | ||||
| ;; End: | ||||
							
								
								
									
										508
									
								
								COPYING.LIB
									
									
									
									
									
								
							
							
						
						
									
										508
									
								
								COPYING.LIB
									
									
									
									
									
								
							| @@ -1,508 +0,0 @@ | ||||
|  | ||||
|                   GNU LESSER GENERAL PUBLIC LICENSE | ||||
|                        Version 2.1, February 1999 | ||||
|  | ||||
|  Copyright (C) 1991, 1999 Free Software Foundation, Inc. | ||||
|      59 Temple Place, Suite 330, Boston, MA  02111-1307  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. | ||||
| ^L | ||||
|   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. | ||||
| ^L | ||||
|                   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. | ||||
| ^L | ||||
|   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. | ||||
| ^L | ||||
|   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. | ||||
| ^L | ||||
|   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. | ||||
| ^L | ||||
|   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. | ||||
| ^L | ||||
|   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 | ||||
| ^L | ||||
|            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. | ||||
|  | ||||
|  | ||||
|     <one line to give the library's name and a brief idea of what it does.> | ||||
|     Copyright (C) <year>  <name of author> | ||||
|  | ||||
|     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., 59 Temple Place, Suite 330, Boston, MA 02111-1307  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. | ||||
|  | ||||
|   <signature of Ty Coon>, 1 April 1990 | ||||
|   Ty Coon, President of Vice | ||||
|  | ||||
| That's all there is to it! | ||||
							
								
								
									
										16699
									
								
								ChangeLog-old
									
									
									
									
									
								
							
							
						
						
									
										16699
									
								
								ChangeLog-old
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										707
									
								
								HACKING
									
									
									
									
									
								
							
							
						
						
									
										707
									
								
								HACKING
									
									
									
									
									
								
							| @@ -1,707 +0,0 @@ | ||||
| -*- buffer-read-only: t -*- vi: set ro: | ||||
| DO NOT EDIT THIS FILE!  IT IS GENERATED AUTOMATICALLY! | ||||
|  | ||||
|  | ||||
|  | ||||
|                          Contributor guidelines | ||||
|                          ====================== | ||||
|  | ||||
|  | ||||
|  | ||||
| General tips for contributing patches | ||||
| ===================================== | ||||
| (1) Discuss any large changes on the mailing list first. Post patches early and | ||||
| listen to feedback. | ||||
|  | ||||
| (2) Post patches in unified diff format. A command similar to this should work: | ||||
|  | ||||
|   diff -urp libvirt.orig/ libvirt.modified/ > libvirt-myfeature.patch | ||||
|  | ||||
| or: | ||||
|  | ||||
|   git diff > libvirt-myfeature.patch | ||||
|  | ||||
| (3) Split large changes into a series of smaller patches, self-contained if | ||||
| possible, with an explanation of each patch and an explanation of how the | ||||
| sequence of patches fits together. | ||||
|  | ||||
| (4) Make sure your patches apply against libvirt GIT. Developers only follow GIT | ||||
| and don't care much about released versions. | ||||
|  | ||||
| (5) Run the automated tests on your code before submitting any changes. In | ||||
| particular, configure with compile warnings set to -Werror: | ||||
|  | ||||
|   ./configure --enable-compile-warnings=error | ||||
|  | ||||
| and run the tests: | ||||
|  | ||||
|   make check | ||||
|   make syntax-check | ||||
|   make -C tests valgrind | ||||
|  | ||||
| The latter test checks for memory leaks. | ||||
|  | ||||
| If you encounter any failing tests, the VIR_TEST_DEBUG environment variable | ||||
| may provide extra information to debug the failures. Larger values of | ||||
| VIR_TEST_DEBUG may provide larger amounts of information: | ||||
|  | ||||
|   VIR_TEST_DEBUG=1 make check    (or) | ||||
|   VIR_TEST_DEBUG=2 make check | ||||
|  | ||||
| Also, individual tests can be run from inside the "tests/" directory, like: | ||||
|  | ||||
|   ./qemuxml2xmltest | ||||
|  | ||||
| (6) Update tests and/or documentation, particularly if you are adding a new | ||||
| feature or changing the output of a program. | ||||
|  | ||||
|  | ||||
|  | ||||
| There is more on this subject, including lots of links to background reading | ||||
| on the subject, on | ||||
|  | ||||
|   Richard Jones' guide to working with open source projects | ||||
|   http://et.redhat.com/~rjones/how-to-supply-code-to-open-source-projects/ | ||||
|  | ||||
|  | ||||
| Code indentation | ||||
| ================ | ||||
| Libvirt's C source code generally adheres to some basic code-formatting | ||||
| conventions. The existing code base is not totally consistent on this front, | ||||
| but we do prefer that contributed code be formatted similarly. In short, use | ||||
| spaces-not-TABs for indentation, use 4 spaces for each indentation level, and | ||||
| other than that, follow the K&R style. | ||||
|  | ||||
| If you use Emacs, add the following to one of one of your start-up files | ||||
| (e.g., ~/.emacs), to help ensure that you get indentation right: | ||||
|  | ||||
|   ;;; When editing C sources in libvirt, use this style. | ||||
|   (defun libvirt-c-mode () | ||||
|     "C mode with adjusted defaults for use with libvirt." | ||||
|     (interactive) | ||||
|     (c-set-style "K&R") | ||||
|     (setq indent-tabs-mode nil) ; indent using spaces, not TABs | ||||
|     (setq c-indent-level 4) | ||||
|     (setq c-basic-offset 4)) | ||||
|   (add-hook 'c-mode-hook | ||||
|             '(lambda () (if (string-match "/libvirt" (buffer-file-name)) | ||||
|                             (libvirt-c-mode)))) | ||||
|  | ||||
| If you use vim, append the following to your ~/.vimrc file: | ||||
|  | ||||
|   set nocompatible | ||||
|   filetype on | ||||
|   set autoindent | ||||
|   set smartindent | ||||
|   set cindent | ||||
|   set tabstop=8 | ||||
|   set shiftwidth=4 | ||||
|   set expandtab | ||||
|   set cinoptions=(0,:0,l1,t0 | ||||
|   filetype plugin indent on | ||||
|   au FileType make setlocal noexpandtab | ||||
|   au BufRead,BufNewFile *.am setlocal noexpandtab | ||||
|   match ErrorMsg /\s\+$\| \+\ze\t/ | ||||
|  | ||||
| Or if you don't want to mess your ~/.vimrc up, you can save the above into a | ||||
| file called .lvimrc (not .vimrc) located at the root of libvirt source, then | ||||
| install a vim script from | ||||
| http://www.vim.org/scripts/script.php?script_id=1408, which will load the | ||||
| .lvimrc only when you edit libvirt code. | ||||
|  | ||||
|  | ||||
| Code formatting (especially for new code) | ||||
| ========================================= | ||||
| With new code, we can be even more strict. Please apply the following function | ||||
| (using GNU indent) to any new code. Note that this also gives you an idea of | ||||
| the type of spacing we prefer around operators and keywords: | ||||
|  | ||||
|   indent-libvirt() | ||||
|   { | ||||
|     indent -bad -bap -bbb -bli4 -br -ce -brs -cs -i4 -l75 -lc75 \ | ||||
|       -sbi4 -psl -saf -sai -saw -sbi4 -ss -sc -cdw -cli4 -npcs -nbc \ | ||||
|       --no-tabs "$@" | ||||
|   } | ||||
|  | ||||
| Note that sometimes you'll have to post-process that output further, by piping | ||||
| it through "expand -i", since some leading TABs can get through. Usually | ||||
| they're in macro definitions or strings, and should be converted anyhow. | ||||
|  | ||||
| Libvirt requires a C99 compiler for various reasons. However, most of the code | ||||
| base prefers to stick to C89 syntax unless there is a compelling reason | ||||
| otherwise. For example, it is preferable to use "/* */" comments rather than | ||||
| "//". Also, when declaring local variables, the prevailing style has been to | ||||
| declare them at the beginning of a scope, rather than immediately before use. | ||||
|  | ||||
|  | ||||
| Curly braces | ||||
| ============ | ||||
| Omit the curly braces around an "if", "while", "for" etc. body only when that | ||||
| body occupies a single line. In every other case we require the braces. This | ||||
| ensures that it is trivially easy to identify a single-'statement' loop: each | ||||
| has only one 'line' in its body. | ||||
|  | ||||
| Omitting braces with a single-line body is fine: | ||||
|  | ||||
|   while (expr) // one-line body -> omitting curly braces is ok | ||||
|       single_line_stmt(); | ||||
|  | ||||
| However, the moment your loop/if/else body extends onto a second line, for | ||||
| whatever reason (even if it's just an added comment), then you should add | ||||
| braces. Otherwise, it would be too easy to insert a statement just before that | ||||
| comment (without adding braces), thinking it is already a multi-statement loop: | ||||
|  | ||||
|   while (true) // BAD! multi-line body with no braces | ||||
|       /* comment... */ | ||||
|       single_line_stmt(); | ||||
|  | ||||
| Do this instead: | ||||
|  | ||||
|   while (true) { // Always put braces around a multi-line body. | ||||
|       /* comment... */ | ||||
|       single_line_stmt(); | ||||
|   } | ||||
|  | ||||
| There is one exception: when the second body line is not at the same | ||||
| indentation level as the first body line: | ||||
|  | ||||
|   if (expr) | ||||
|       die("a diagnostic that would make this line" | ||||
|           " extend past the 80-column limit")); | ||||
|  | ||||
| It is safe to omit the braces in the code above, since the further-indented | ||||
| second body line makes it obvious that this is still a single-statement body. | ||||
|  | ||||
| To reiterate, don't do this: | ||||
|  | ||||
|   if (expr)            // BAD: no braces around... | ||||
|       while (expr_2) { // ... a multi-line body | ||||
|           ... | ||||
|       } | ||||
|  | ||||
| Do this, instead: | ||||
|  | ||||
|   if (expr) { | ||||
|       while (expr_2) { | ||||
|           ... | ||||
|       } | ||||
|   } | ||||
|  | ||||
| However, there is one exception in the other direction, when even a one-line | ||||
| block should have braces. That occurs when that one-line, brace-less block is | ||||
| an "if" or "else" block, and the counterpart block *does* use braces. In that | ||||
| case, put braces around both blocks. Also, if the "else" block is much shorter | ||||
| than the "if" block, consider negating the "if"-condition and swapping the | ||||
| bodies, putting the short block first and making the longer, multi-line block | ||||
| be the "else" block. | ||||
|  | ||||
|   if (expr) { | ||||
|       ... | ||||
|       ... | ||||
|   } | ||||
|   else | ||||
|       x = y;    // BAD: braceless "else" with braced "then", | ||||
|                 // and short block last | ||||
|  | ||||
|   if (expr) | ||||
|       x = y;    // BAD: braceless "if" with braced "else" | ||||
|   else { | ||||
|       ... | ||||
|       ... | ||||
|   } | ||||
|  | ||||
| Keeping braces consistent and putting the short block first is preferred, | ||||
| especially when the multi-line body is more than a few lines long, because it | ||||
| is easier to read and grasp the semantics of an if-then-else block when the | ||||
| simpler block occurs first, rather than after the more involved block: | ||||
|  | ||||
|   if (!expr) { | ||||
|     x = y; // putting the smaller block first is more readable | ||||
|   } else { | ||||
|       ... | ||||
|       ... | ||||
|   } | ||||
|  | ||||
| But if negating a complex condition is too ugly, then at least add braces: | ||||
|  | ||||
|   if (complex expr not worth negating) { | ||||
|       ... | ||||
|       ... | ||||
|   } else { | ||||
|       x = y; | ||||
|   } | ||||
|  | ||||
|  | ||||
| Preprocessor | ||||
| ============ | ||||
| For variadic macros, stick with C99 syntax: | ||||
|  | ||||
|   #define vshPrint(_ctl, ...) fprintf(stdout, __VA_ARGS__) | ||||
|  | ||||
| Use parenthesis when checking if a macro is defined, and use indentation to | ||||
| track nesting: | ||||
|  | ||||
|   #if defined(HAVE_POSIX_FALLOCATE) && !defined(HAVE_FALLOCATE) | ||||
|   # define fallocate(a,ignored,b,c) posix_fallocate(a,b,c) | ||||
|   #endif | ||||
|  | ||||
|  | ||||
| C types | ||||
| ======= | ||||
| Use the right type. | ||||
|  | ||||
| Scalars | ||||
| ------- | ||||
| - If you're using "int" or "long", odds are good that there's a better type. | ||||
|  | ||||
| - If a variable is counting something, be sure to declare it with an unsigned | ||||
| type. | ||||
|  | ||||
| - If it's memory-size-related, use "size_t" (use "ssize_t" only if required). | ||||
|  | ||||
| - If it's file-size related, use uintmax_t, or maybe "off_t". | ||||
|  | ||||
| - If it's file-offset related (i.e., signed), use "off_t". | ||||
|  | ||||
| - If it's just counting small numbers use "unsigned int"; (on all but oddball | ||||
| embedded systems, you can assume that that type is at least four bytes wide). | ||||
|  | ||||
| - If a variable has boolean semantics, give it the "bool" type and use the | ||||
| corresponding "true" and "false" macros. It's ok to include <stdbool.h>, since | ||||
| libvirt's use of gnulib ensures that it exists and is usable. | ||||
|  | ||||
| - In the unusual event that you require a specific width, use a standard type | ||||
| like "int32_t", "uint32_t", "uint64_t", etc. | ||||
|  | ||||
| - While using "bool" is good for readability, it comes with minor caveats: | ||||
|  | ||||
| -- Don't use "bool" in places where the type size must be constant across all | ||||
| systems, like public interfaces and on-the-wire protocols. Note that it would | ||||
| be possible (albeit wasteful) to use "bool" in libvirt's logical wire | ||||
| protocol, since XDR maps that to its lower-level "bool_t" type, which *is* | ||||
| fixed-size. | ||||
|  | ||||
| -- Don't compare a bool variable against the literal, "true", since a value with | ||||
| a logical non-false value need not be "1". I.e., don't write "if (seen == | ||||
| true) ...". Rather, write "if (seen)...". | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| Of course, take all of the above with a grain of salt. If you're about to use | ||||
| some system interface that requires a type like "size_t", "pid_t" or "off_t", | ||||
| use matching types for any corresponding variables. | ||||
|  | ||||
| Also, if you try to use e.g., "unsigned int" as a type, and that conflicts | ||||
| with the signedness of a related variable, sometimes it's best just to use the | ||||
| *wrong* type, if 'pulling the thread' and fixing all related variables would | ||||
| be too invasive. | ||||
|  | ||||
| Finally, while using descriptive types is important, be careful not to go | ||||
| overboard. If whatever you're doing causes warnings, or requires casts, then | ||||
| reconsider or ask for help. | ||||
|  | ||||
| Pointers | ||||
| -------- | ||||
| Ensure that all of your pointers are 'const-correct'. Unless a pointer is used | ||||
| to modify the pointed-to storage, give it the "const" attribute. That way, the | ||||
| reader knows up-front that this is a read-only pointer. Perhaps more | ||||
| importantly, if we're diligent about this, when you see a non-const pointer, | ||||
| you're guaranteed that it is used to modify the storage it points to, or it is | ||||
| aliased to another pointer that is. | ||||
|  | ||||
|  | ||||
| Low level memory management | ||||
| =========================== | ||||
| Use of the malloc/free/realloc/calloc APIs is deprecated in the libvirt | ||||
| codebase, because they encourage a number of serious coding bugs and do not | ||||
| enable compile time verification of checks for NULL. Instead of these | ||||
| routines, use the macros from memory.h. | ||||
|  | ||||
| - To allocate a single object: | ||||
|  | ||||
|   virDomainPtr domain; | ||||
|  | ||||
|   if (VIR_ALLOC(domain) < 0) { | ||||
|       virReportOOMError(); | ||||
|       return NULL; | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| - To allocate an array of objects: | ||||
|  | ||||
|   virDomainPtr domains; | ||||
|   size_t ndomains = 10; | ||||
|  | ||||
|   if (VIR_ALLOC_N(domains, ndomains) < 0) { | ||||
|       virReportOOMError(); | ||||
|       return NULL; | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| - To allocate an array of object pointers: | ||||
|  | ||||
|   virDomainPtr *domains; | ||||
|   size_t ndomains = 10; | ||||
|  | ||||
|   if (VIR_ALLOC_N(domains, ndomains) < 0) { | ||||
|       virReportOOMError(); | ||||
|       return NULL; | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| - To re-allocate the array of domains to be 1 element longer (however, note that | ||||
| repeatedly expanding an array by 1 scales quadratically, so this is | ||||
| recommended only for smaller arrays): | ||||
|  | ||||
|   virDomainPtr domains; | ||||
|   size_t ndomains = 0; | ||||
|  | ||||
|   if (VIR_EXPAND_N(domains, ndomains, 1) < 0) { | ||||
|       virReportOOMError(); | ||||
|       return NULL; | ||||
|   } | ||||
|   domains[ndomains - 1] = domain; | ||||
|  | ||||
|  | ||||
|  | ||||
| - To ensure an array has room to hold at least one more element (this approach | ||||
| scales better, but requires tracking allocation separately from usage) | ||||
|  | ||||
|   virDomainPtr domains; | ||||
|   size_t ndomains = 0; | ||||
|   size_t ndomains_max = 0; | ||||
|  | ||||
|   if (VIR_RESIZE_N(domains, ndomains_max, ndomains, 1) < 0) { | ||||
|       virReportOOMError(); | ||||
|       return NULL; | ||||
|   } | ||||
|   domains[ndomains++] = domain; | ||||
|  | ||||
|  | ||||
|  | ||||
| - To trim an array of domains from its allocated size down to the actual used | ||||
| size: | ||||
|  | ||||
|   virDomainPtr domains; | ||||
|   size_t ndomains = x; | ||||
|   size_t ndomains_max = y; | ||||
|  | ||||
|   VIR_SHRINK_N(domains, ndomains_max, ndomains_max - ndomains); | ||||
|  | ||||
|  | ||||
|  | ||||
| - To free an array of domains: | ||||
|  | ||||
|   virDomainPtr domains; | ||||
|   size_t ndomains = x; | ||||
|   size_t ndomains_max = y; | ||||
|   size_t i; | ||||
|  | ||||
|   for (i = 0; i < ndomains; i++) | ||||
|       VIR_FREE(domains[i]); | ||||
|   VIR_FREE(domains); | ||||
|   ndomains_max = ndomains = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| File handling | ||||
| ============= | ||||
| Usage of the "fdopen()", "close()", "fclose()" APIs is deprecated in libvirt | ||||
| code base to help avoiding double-closing of files or file descriptors, which | ||||
| is particulary dangerous in a multi-threaded applications. Instead of these | ||||
| APIs, use the macros from virfile.h | ||||
|  | ||||
| - Open a file from a file descriptor: | ||||
|  | ||||
|   if ((file = VIR_FDOPEN(fd, "r")) == NULL) { | ||||
|       virReportSystemError(errno, "%s", | ||||
|                            _("failed to open file from file descriptor")); | ||||
|       return -1; | ||||
|   } | ||||
|   /* fd is now invalid; only access the file using file variable */ | ||||
|  | ||||
|  | ||||
|  | ||||
| - Close a file descriptor: | ||||
|  | ||||
|   if (VIR_CLOSE(fd) < 0) { | ||||
|       virReportSystemError(errno, "%s", _("failed to close file")); | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| - Close a file: | ||||
|  | ||||
|   if (VIR_FCLOSE(file) < 0) { | ||||
|       virReportSystemError(errno, "%s", _("failed to close file")); | ||||
|   } | ||||
|  | ||||
|  | ||||
|  | ||||
| - Close a file or file descriptor in an error path, without losing the previous | ||||
| "errno" value: | ||||
|  | ||||
|   VIR_FORCE_CLOSE(fd); | ||||
|   VIR_FORCE_FCLOSE(file); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| String comparisons | ||||
| ================== | ||||
| Do not use the strcmp, strncmp, etc functions directly. Instead use one of the | ||||
| following semantically named macros | ||||
|  | ||||
| - For strict equality: | ||||
|  | ||||
|   STREQ(a,b) | ||||
|   STRNEQ(a,b) | ||||
|  | ||||
|  | ||||
|  | ||||
| - For case insensitive equality: | ||||
|  | ||||
|   STRCASEEQ(a,b) | ||||
|   STRCASENEQ(a,b) | ||||
|  | ||||
|  | ||||
|  | ||||
| - For strict equality of a substring: | ||||
|  | ||||
|   STREQLEN(a,b,n) | ||||
|   STRNEQLEN(a,b,n) | ||||
|  | ||||
|  | ||||
|  | ||||
| - For case insensitive equality of a substring: | ||||
|  | ||||
|   STRCASEEQLEN(a,b,n) | ||||
|   STRCASENEQLEN(a,b,n) | ||||
|  | ||||
|  | ||||
|  | ||||
| - For strict equality of a prefix: | ||||
|  | ||||
|   STRPREFIX(a,b) | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| String copying | ||||
| ============== | ||||
| Do not use the strncpy function. According to the man page, it does *not* | ||||
| guarantee a NULL-terminated buffer, which makes it extremely dangerous to use. | ||||
| Instead, use one of the functionally equivalent functions: | ||||
|  | ||||
|   virStrncpy(char *dest, const char *src, size_t n, size_t destbytes) | ||||
|  | ||||
| The first three arguments have the same meaning as for strncpy; namely the | ||||
| destination, source, and number of bytes to copy, respectively. The last | ||||
| argument is the number of bytes available in the destination string; if a copy | ||||
| of the source string (including a \0) will not fit into the destination, no | ||||
| bytes are copied and the routine returns NULL. Otherwise, n bytes from the | ||||
| source are copied into the destination and a trailing \0 is appended. | ||||
|  | ||||
|   virStrcpy(char *dest, const char *src, size_t destbytes) | ||||
|  | ||||
| Use this variant if you know you want to copy the entire src string into dest. | ||||
| Note that this is a macro, so arguments could be evaluated more than once. | ||||
| This is equivalent to virStrncpy(dest, src, strlen(src), destbytes) | ||||
|  | ||||
|   virStrcpyStatic(char *dest, const char *src) | ||||
|  | ||||
| Use this variant if you know you want to copy the entire src string into dest | ||||
| *and* you know that your destination string is a static string (i.e. that | ||||
| sizeof(dest) returns something meaningful). Note that this is a macro, so | ||||
| arguments could be evaluated more than once. This is equivalent to | ||||
| virStrncpy(dest, src, strlen(src), sizeof(dest)). | ||||
|  | ||||
|  | ||||
| Variable length string buffer | ||||
| ============================= | ||||
| If there is a need for complex string concatenations, avoid using the usual | ||||
| sequence of malloc/strcpy/strcat/snprintf functions and make use of the | ||||
| virBuffer API described in buf.h | ||||
|  | ||||
| Typical usage is as follows: | ||||
|  | ||||
|   char * | ||||
|   somefunction(...) | ||||
|   { | ||||
|      virBuffer buf = VIR_BUFFER_INITIALIZER; | ||||
|  | ||||
|      ... | ||||
|  | ||||
|      virBufferAddLit(&buf, "<domain>\n"); | ||||
|      virBufferAsprintf(&buf, "  <memory>%d</memory>\n", memory); | ||||
|      ... | ||||
|      virBufferAddLit(&buf, "</domain>\n"); | ||||
|  | ||||
|      ... | ||||
|  | ||||
|      if (virBufferError(&buf)) { | ||||
|          virBufferFreeAndReset(&buf); | ||||
|          virReportOOMError(); | ||||
|          return NULL; | ||||
|      } | ||||
|  | ||||
|      return virBufferContentAndReset(&buf); | ||||
|   } | ||||
|  | ||||
|  | ||||
| Include files | ||||
| ============= | ||||
| There are now quite a large number of include files, both libvirt internal and | ||||
| external, and system includes. To manage all this complexity it's best to | ||||
| stick to the following general plan for all *.c source files: | ||||
|  | ||||
|   /* | ||||
|    * Copyright notice | ||||
|    * .... | ||||
|    * .... | ||||
|    * .... | ||||
|    * | ||||
|    */ | ||||
|  | ||||
|   #include <config.h>             Must come first in every file. | ||||
|  | ||||
|   #include <stdio.h>              Any system includes you need. | ||||
|   #include <string.h> | ||||
|   #include <limits.h> | ||||
|  | ||||
|   #if HAVE_NUMACTL                Some system includes aren't supported | ||||
|   # include <numa.h>              everywhere so need these #if guards. | ||||
|   #endif | ||||
|  | ||||
|   #include "internal.h"           Include this first, after system includes. | ||||
|  | ||||
|   #include "util.h"               Any libvirt internal header files. | ||||
|   #include "buf.h" | ||||
|  | ||||
|   static int | ||||
|   myInternalFunc()                The actual code. | ||||
|   { | ||||
|       ... | ||||
|  | ||||
| Of particular note: *Do not* include libvirt/libvirt.h or libvirt/virterror.h. | ||||
| It is included by "internal.h" already and there are some special reasons why | ||||
| you cannot include these files explicitly. | ||||
|  | ||||
|  | ||||
| Printf-style functions | ||||
| ====================== | ||||
| Whenever you add a new printf-style function, i.e., one with a format string | ||||
| argument and following "..." in its prototype, be sure to use gcc's printf | ||||
| attribute directive in the prototype. For example, here's the one for | ||||
| virAsprintf, in util.h: | ||||
|  | ||||
|   int virAsprintf(char **strp, const char *fmt, ...) | ||||
|       ATTRIBUTE_FORMAT(printf, 2, 3); | ||||
|  | ||||
| This makes it so gcc's -Wformat and -Wformat-security options can do their | ||||
| jobs and cross-check format strings with the number and types of arguments. | ||||
|  | ||||
| When printing to a string, consider using virBuffer for incremental | ||||
| allocations, virAsprintf for a one-shot allocation, and snprintf for | ||||
| fixed-width buffers. Do not use sprintf, even if you can prove the buffer | ||||
| won't overflow, since gnulib does not provide the same portability guarantees | ||||
| for sprintf as it does for snprintf. | ||||
|  | ||||
|  | ||||
| Use of goto | ||||
| =========== | ||||
| The use of goto is not forbidden, and goto is widely used throughout libvirt. | ||||
| While the uncontrolled use of goto will quickly lead to unmaintainable code, | ||||
| there is a place for it in well structured code where its use increases | ||||
| readability and maintainability. In general, if goto is used for error | ||||
| recovery, it's likely to be ok, otherwise, be cautious or avoid it all | ||||
| together. | ||||
|  | ||||
| The typical use of goto is to jump to cleanup code in the case of a long list | ||||
| of actions, any of which may fail and cause the entire operation to fail. In | ||||
| this case, a function will have a single label at the end of the function. | ||||
| It's almost always ok to use this style. In particular, if the cleanup code | ||||
| only involves free'ing memory, then having multiple labels is overkill. | ||||
| VIR_FREE() and every function named XXXFree() in libvirt is required to handle | ||||
| NULL as its arg. Thus you can safely call free on all the variables even if | ||||
| they were not yet allocated (yes they have to have been initialized to NULL). | ||||
| This is much simpler and clearer than having multiple labels. | ||||
|  | ||||
| There are a couple of signs that a particular use of goto is not ok: | ||||
|  | ||||
| - You're using multiple labels. If you find yourself using multiple labels, | ||||
| you're strongly encouraged to rework your code to eliminate all but one of | ||||
| them. | ||||
|  | ||||
| - The goto jumps back up to a point above the current line of code being | ||||
| executed. Please use some combination of looping constructs to re-execute code | ||||
| instead; it's almost certainly going to be more understandable by others. One | ||||
| well-known exception to this rule is restarting an i/o operation following | ||||
| EINTR. | ||||
|  | ||||
| - The goto jumps down to an arbitrary place in the middle of a function followed | ||||
| by further potentially failing calls. You should almost certainly be using a | ||||
| conditional and a block instead of a goto. Perhaps some of your function's | ||||
| logic would be better pulled out into a helper function. | ||||
|  | ||||
|  | ||||
|  | ||||
| Although libvirt does not encourage the Linux kernel wind/unwind style of | ||||
| multiple labels, there's a good general discussion of the issue archived at | ||||
|  | ||||
|   KernelTrap | ||||
|   http://kerneltrap.org/node/553/2131 | ||||
|  | ||||
| When using goto, please use one of these standard labels if it makes sense: | ||||
|  | ||||
|       error: A path only taken upon return with an error code | ||||
|     cleanup: A path taken upon return with success code + optional error | ||||
|   no_memory: A path only taken upon return with an OOM error code | ||||
|       retry: If needing to jump upwards (e.g., retry on EINTR) | ||||
|  | ||||
|  | ||||
| Libvirt committer guidelines | ||||
| ============================ | ||||
| The AUTHORS files indicates the list of people with commit access right who | ||||
| can actually merge the patches. | ||||
|  | ||||
| The general rule for committing a patch is to make sure it has been reviewed | ||||
| properly in the mailing-list first, usually if a couple of people gave an ACK | ||||
| or +1 to a patch and nobody raised an objection on the list it should be good | ||||
| to go. If the patch touches a part of the code where you're not the main | ||||
| maintainer, or where you do not have a very clear idea of how things work, | ||||
| it's better to wait for a more authoritative feedback though. Before | ||||
| committing, please also rebuild locally, run 'make check syntax-check', and | ||||
| make sure you don't raise errors. Try to look for warnings too; for example, | ||||
| configure with | ||||
|  | ||||
|   --enable-compile-warnings=error | ||||
|  | ||||
| which adds -Werror to compile flags, so no warnings get missed | ||||
|  | ||||
| An exception to 'review and approval on the list first' is fixing failures to | ||||
| build: | ||||
|  | ||||
| - if a recently committed patch breaks compilation on a platform or for a given | ||||
| driver, then it's fine to commit a minimal fix directly without getting the | ||||
| review feedback first | ||||
|  | ||||
| - if make check or make syntax-check breaks, if there is an obvious fix, it's | ||||
| fine to commit immediately. The patch should still be sent to the list (or | ||||
| tell what the fix was if trivial), and 'make check syntax-check' should pass | ||||
| too, before committing anything | ||||
|  | ||||
| - fixes for documentation and code comments can be managed in the same way, but | ||||
| still make sure they get reviewed if non-trivial. | ||||
							
								
								
									
										92
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								Makefile.am
									
									
									
									
									
								
							| @@ -1,92 +0,0 @@ | ||||
| ## Process this file with automake to produce Makefile.in | ||||
|  | ||||
| ## Copyright (C) 2005-2011 Red Hat, Inc. | ||||
| ## See COPYING.LIB for the License of this software | ||||
|  | ||||
| LCOV = lcov | ||||
| GENHTML = genhtml | ||||
|  | ||||
| SUBDIRS = gnulib/lib include src daemon tools docs gnulib/tests \ | ||||
|   python tests po examples/domain-events/events-c examples/hellolibvirt \ | ||||
|   examples/dominfo examples/domsuspend examples/python examples/apparmor \ | ||||
|   examples/xml/nwfilter examples/openauth examples/systemtap | ||||
|  | ||||
| ACLOCAL_AMFLAGS = -I m4 -I gnulib/m4 | ||||
|  | ||||
| XML_EXAMPLES = \ | ||||
|   $(patsubst $(srcdir)/%,%,$(wildcard $(addprefix $(srcdir)/examples/xml/, \ | ||||
| 					test/*.xml storage/*.xml))) | ||||
|  | ||||
| EXTRA_DIST = \ | ||||
|   ChangeLog-old \ | ||||
|   libvirt.spec libvirt.spec.in \ | ||||
|   mingw32-libvirt.spec.in \ | ||||
|   libvirt.pc.in \ | ||||
|   autobuild.sh \ | ||||
|   Makefile.nonreentrant \ | ||||
|   autogen.sh \ | ||||
|   cfg.mk \ | ||||
|   examples/domain-events/events-python \ | ||||
|   $(XML_EXAMPLES) | ||||
|  | ||||
| pkgconfigdir = $(libdir)/pkgconfig | ||||
| pkgconfig_DATA = libvirt.pc | ||||
|  | ||||
| NEWS: $(top_srcdir)/docs/news.xsl $(top_srcdir)/docs/news.html.in | ||||
| 	-@(if [ -x $(XSLTPROC) ] ; then				\ | ||||
| 	  $(XSLTPROC) --nonet $(top_srcdir)/docs/news.xsl	\ | ||||
| 	     $(top_srcdir)/docs/news.html.in			\ | ||||
| 	   | perl -0777 -pe 's/\n\n+$$/\n/'			\ | ||||
| 	   | perl -pe 's/[ \t]+$$//'				\ | ||||
| 	   > $@-t && mv $@-t $@ ; fi ); | ||||
|  | ||||
| $(top_srcdir)/HACKING: $(top_srcdir)/docs/hacking1.xsl $(top_srcdir)/docs/hacking2.xsl \ | ||||
|                        $(top_srcdir)/docs/wrapstring.xsl $(top_srcdir)/docs/hacking.html.in | ||||
| 	-@(if [ -x $(XSLTPROC) ] ; then \ | ||||
| 	   $(XSLTPROC) --nonet $(top_srcdir)/docs/hacking1.xsl $(top_srcdir)/docs/hacking.html.in | \ | ||||
| 	   $(XSLTPROC) --nonet $(top_srcdir)/docs/hacking2.xsl - \ | ||||
| 	   | perl -0777 -pe 's/\n\n+$$/\n/' \ | ||||
| 	   > $@-t && mv $@-t $@ ; fi ); | ||||
|  | ||||
| rpm: clean | ||||
| 	@(unset CDPATH ; $(MAKE) dist && rpmbuild -ta $(distdir).tar.gz) | ||||
|  | ||||
| check-local: all tests | ||||
|  | ||||
| tests: | ||||
| 	@(cd docs/examples ; $(MAKE) MAKEFLAGS+=--silent tests) | ||||
| 	@(if [ "$(pythondir)" != "" ] ; then cd python ; \ | ||||
| 	  $(MAKE) MAKEFLAGS+=--silent tests ; fi) | ||||
|  | ||||
| cov: clean-cov | ||||
| 	mkdir $(top_builddir)/coverage | ||||
| 	$(LCOV) -c -o $(top_builddir)/coverage/libvirt.info.tmp \ | ||||
| 	  -d $(top_builddir)/src  -d $(top_builddir)/daemon \ | ||||
| 	  -d $(top_builddir)/tests | ||||
| 	$(LCOV) -r $(top_builddir)/coverage/libvirt.info.tmp \ | ||||
| 	  -o $(top_builddir)/coverage/libvirt.info | ||||
| 	rm $(top_builddir)/coverage/libvirt.info.tmp | ||||
| 	$(GENHTML) --show-details -t "libvirt" -o $(top_builddir)/coverage \ | ||||
| 	  --legend $(top_builddir)/coverage/libvirt.info | ||||
|  | ||||
| clean-cov: | ||||
| 	rm -rf $(top_builddir)/coverage | ||||
|  | ||||
| MAINTAINERCLEANFILES = .git-module-status | ||||
|  | ||||
| # disable this check | ||||
| distuninstallcheck: | ||||
|  | ||||
| dist-hook: gen-ChangeLog | ||||
|  | ||||
| # Generate the ChangeLog file (with all entries since the switch to git) | ||||
| # and insert it into the directory we're about to use to create a tarball. | ||||
| gen_start_date = 2009-07-04 | ||||
| .PHONY: gen-ChangeLog | ||||
| gen-ChangeLog: | ||||
| 	if test -d .git; then					\ | ||||
| 	  $(top_srcdir)/build-aux/gitlog-to-changelog		\ | ||||
| 	    --since=$(gen_start_date) > $(distdir)/cl-t;	\ | ||||
| 	  rm -f $(distdir)/ChangeLog;				\ | ||||
| 	  mv $(distdir)/cl-t $(distdir)/ChangeLog;		\ | ||||
| 	fi | ||||
| @@ -1,100 +0,0 @@ | ||||
|  | ||||
| # | ||||
| # Generated by running the following on Fedora 9: | ||||
| # | ||||
| #  nm -D --defined-only /lib/libc.so.6  \ | ||||
| #      | grep '_r$' \ | ||||
| #      | awk '{print $3}' \ | ||||
| #      | grep -v __ \ | ||||
| #      | grep -v qsort \ # Red herring since we don't need to pass extra args to qsort comparator | ||||
| #      | grep -v readdir \ # This is safe as long as each DIR * instance is only used by one thread | ||||
| #      | sort \ | ||||
| #      | uniq \ | ||||
| #      | sed -e 's/_r//' | ||||
| # | ||||
| # Also manually add in all inet_* functions some of which | ||||
| # are not threadsafe and do not have _r variants. They are | ||||
| # all deprecated in favour of getnameinfo/getaddrinfo | ||||
| # | ||||
|  | ||||
| NON_REENTRANT = | ||||
| NON_REENTRANT += asctime | ||||
| NON_REENTRANT += ctime | ||||
| NON_REENTRANT += drand48 | ||||
| NON_REENTRANT += ecvt | ||||
| NON_REENTRANT += erand48 | ||||
| NON_REENTRANT += ether_aton | ||||
| NON_REENTRANT += ether_ntoa | ||||
| NON_REENTRANT += fcvt | ||||
| NON_REENTRANT += fgetgrent | ||||
| NON_REENTRANT += fgetpwent | ||||
| NON_REENTRANT += fgetspent | ||||
| NON_REENTRANT += getaliasbyname | ||||
| NON_REENTRANT += getaliasent | ||||
| NON_REENTRANT += getdate | ||||
| NON_REENTRANT += getgrent | ||||
| NON_REENTRANT += getgrgid | ||||
| NON_REENTRANT += getgrnam | ||||
| NON_REENTRANT += gethostbyaddr | ||||
| NON_REENTRANT += gethostbyname2 | ||||
| NON_REENTRANT += gethostbyname | ||||
| NON_REENTRANT += gethostent | ||||
| NON_REENTRANT += getlogin | ||||
| NON_REENTRANT += getmntent | ||||
| NON_REENTRANT += getnetbyaddr | ||||
| NON_REENTRANT += getnetbyname | ||||
| NON_REENTRANT += getnetent | ||||
| NON_REENTRANT += getnetgrent | ||||
| NON_REENTRANT += getprotobyname | ||||
| NON_REENTRANT += getprotobynumber | ||||
| NON_REENTRANT += getprotoent | ||||
| NON_REENTRANT += getpwent | ||||
| NON_REENTRANT += getpwnam | ||||
| NON_REENTRANT += getpwuid | ||||
| NON_REENTRANT += getrpcbyname | ||||
| NON_REENTRANT += getrpcbynumber | ||||
| NON_REENTRANT += getrpcent | ||||
| NON_REENTRANT += getservbyname | ||||
| NON_REENTRANT += getservbyport | ||||
| NON_REENTRANT += getservent | ||||
| NON_REENTRANT += getspent | ||||
| NON_REENTRANT += getspnam | ||||
| NON_REENTRANT += getutent | ||||
| NON_REENTRANT += getutid | ||||
| NON_REENTRANT += getutline | ||||
| NON_REENTRANT += gmtime | ||||
| NON_REENTRANT += hcreate | ||||
| NON_REENTRANT += hdestroy | ||||
| NON_REENTRANT += hsearch | ||||
| NON_REENTRANT += initstate | ||||
| NON_REENTRANT += jrand48 | ||||
| NON_REENTRANT += lcong48 | ||||
| NON_REENTRANT += localtime | ||||
| NON_REENTRANT += lrand48 | ||||
| NON_REENTRANT += mrand48 | ||||
| NON_REENTRANT += nrand48 | ||||
| NON_REENTRANT += ptsname | ||||
| NON_REENTRANT += qecvt | ||||
| NON_REENTRANT += qfcvt | ||||
| NON_REENTRANT += random | ||||
| NON_REENTRANT += rand | ||||
| NON_REENTRANT += seed48 | ||||
| NON_REENTRANT += setstate | ||||
| NON_REENTRANT += sgetspent | ||||
| NON_REENTRANT += srand48 | ||||
| NON_REENTRANT += srandom | ||||
| NON_REENTRANT += strerror | ||||
| NON_REENTRANT += strtok | ||||
| NON_REENTRANT += tmpnam | ||||
| NON_REENTRANT += ttyname | ||||
| NON_REENTRANT += inet_addr | ||||
| NON_REENTRANT += inet_aton | ||||
| NON_REENTRANT += inet_lnaof | ||||
| NON_REENTRANT += inet_makeaddr | ||||
| NON_REENTRANT += inet_netof | ||||
| NON_REENTRANT += inet_network | ||||
| NON_REENTRANT += inet_nsap_addr | ||||
| NON_REENTRANT += inet_nsap_ntoa | ||||
| NON_REENTRANT += inet_ntoa | ||||
| NON_REENTRANT += inet_ntop | ||||
| NON_REENTRANT += inet_pton | ||||
							
								
								
									
										14
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								README
									
									
									
									
									
								
							| @@ -1,13 +1 @@ | ||||
|  | ||||
|          LibVirt : simple API for virtualization | ||||
|  | ||||
|   Libvirt is a C toolkit to interact with the virtualization capabilities | ||||
| of recent versions of Linux (and other OSes). It is free software | ||||
| available under the GNU Lesser General Public License. Virtualization of | ||||
| the Linux Operating System means the ability to run multiple instances of | ||||
| Operating Systems concurrently on a single hardware system where the basic | ||||
| resources are driven by a Linux instance. The library aim at providing | ||||
| long term stable C API initially for the Xen paravirtualization but | ||||
| should be able to integrate other virtualization mechanisms if needed. | ||||
|  | ||||
| Daniel Veillard <veillard@redhat.com> | ||||
| This branch is no longer maintained upstream. | ||||
|   | ||||
| @@ -1,57 +0,0 @@ | ||||
| -*- outline -*- | ||||
|  | ||||
| These notes intend to help people working on the checked-out sources. | ||||
| These requirements do not apply when building from a distribution tarball. | ||||
| See also HACKING for more detailed libvirt contribution guidelines. | ||||
|  | ||||
| * Requirements | ||||
|  | ||||
| We've opted to keep only the highest-level sources in the GIT repository. | ||||
| This eases our maintenance burden, (fewer merges etc.), but imposes more | ||||
| requirements on anyone wishing to build from the just-checked-out sources. | ||||
| Note the requirements to build the released archive are much less and | ||||
| are just the requirements of the standard ./configure && make procedure. | ||||
| Specific development tools and versions will be checked for and listed by | ||||
| the bootstrap script. | ||||
|  | ||||
| Valgrind <http://valgrind.org/> is also highly recommended, if | ||||
| Valgrind supports your architecture. See also README-valgrind. | ||||
|  | ||||
| While building from a just-cloned source tree may require installing a | ||||
| few prerequisites, later, a plain `git pull && make' should be sufficient. | ||||
|  | ||||
| * First GIT checkout | ||||
|  | ||||
| You can get a copy of the source repository like this: | ||||
|  | ||||
|         $ git clone git://libvirt.org/libvirt | ||||
|         $ cd libvirt | ||||
|  | ||||
| As an optional step, if you already have a copy of the gnulib git | ||||
| repository on your hard drive, then you can use it as a reference to | ||||
| reduce download time and disk space requirements: | ||||
|  | ||||
|         $ export GNULIB_SRCDIR=/path/to/gnulib | ||||
|  | ||||
| The next step is to get all required pieces from gnulib, | ||||
| to run autoreconf, and to invoke ./configure: | ||||
|  | ||||
|         $ ./autogen.sh | ||||
|  | ||||
| And there you are!  Just | ||||
|  | ||||
|         $ make | ||||
|         $ make check | ||||
|  | ||||
| At this point, there should be no difference between your local copy, | ||||
| and the GIT master copy: | ||||
|  | ||||
|         $ git diff | ||||
|  | ||||
| should output no difference. | ||||
|  | ||||
| Enjoy! | ||||
|  | ||||
| Local Variables: | ||||
| indent-tabs-mode: nil | ||||
| End: | ||||
							
								
								
									
										22
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								TODO
									
									
									
									
									
								
							| @@ -1,22 +0,0 @@ | ||||
|          libvirt TODO list | ||||
|          ================= | ||||
|  | ||||
| The TODO list changes frequently, so is maintained online | ||||
| in the libvirt bugzilla | ||||
|  | ||||
|   http://bugzilla.redhat.com/ | ||||
|  | ||||
| Search against | ||||
|  | ||||
|     Product: Virtualization Tools | ||||
|   Component: libvirt | ||||
|     Subject: RFE | ||||
|  | ||||
| Or browse dependent bugs under | ||||
|  | ||||
|   https://bugzilla.redhat.com/show_bug.cgi?id=libvirtTodo | ||||
|  | ||||
| Summarized reports automatically generated from bugzilla | ||||
| and provided online at | ||||
|  | ||||
|   http://libvirt.org/todo.html | ||||
							
								
								
									
										102
									
								
								autobuild.sh
									
									
									
									
									
								
							
							
						
						
									
										102
									
								
								autobuild.sh
									
									
									
									
									
								
							| @@ -1,102 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| set -e | ||||
| set -v | ||||
|  | ||||
| # Make things clean. | ||||
|  | ||||
| test -n "$1" && RESULTS=$1 || RESULTS=results.log | ||||
| : ${AUTOBUILD_INSTALL_ROOT=$HOME/builder} | ||||
|  | ||||
| test -f Makefile && make -k distclean || : | ||||
| rm -rf coverage | ||||
|  | ||||
| rm -rf build | ||||
| mkdir build | ||||
| cd build | ||||
|  | ||||
| ../autogen.sh --prefix="$AUTOBUILD_INSTALL_ROOT" \ | ||||
|   --enable-test-coverage \ | ||||
|   --enable-compile-warnings=error | ||||
|  | ||||
| # If the MAKEFLAGS envvar does not yet include a -j option, | ||||
| # add -jN where N depends on the number of processors. | ||||
| case $MAKEFLAGS in | ||||
|   *-j*) ;; | ||||
|   *) n=$(getconf _NPROCESSORS_ONLN 2> /dev/null) | ||||
|     test "$n" -gt 0 || n=1 | ||||
|     n=$(expr $n + 1) | ||||
|     MAKEFLAGS="$MAKEFLAGS -j$n" | ||||
|     export MAKEFLAGS | ||||
|     ;; | ||||
| esac | ||||
|  | ||||
| make | ||||
| make install | ||||
|  | ||||
| # set -o pipefail is a bashism; this use of exec is the POSIX alternative | ||||
| exec 3>&1 | ||||
| st=$( | ||||
|   exec 4>&1 >&3 | ||||
|   { make check syntax-check 2>&1 3>&- 4>&-; echo $? >&4; } | tee "$RESULTS" | ||||
| ) | ||||
| exec 3>&- | ||||
| test "$st" = 0 | ||||
| test -x /usr/bin/lcov && make cov | ||||
|  | ||||
| rm -f *.tar.gz | ||||
| make dist | ||||
|  | ||||
| if [ -n "$AUTOBUILD_COUNTER" ]; then | ||||
|   EXTRA_RELEASE=".auto$AUTOBUILD_COUNTER" | ||||
| else | ||||
|   NOW=`date +"%s"` | ||||
|   EXTRA_RELEASE=".$USER$NOW" | ||||
| fi | ||||
|  | ||||
| if [ -f /usr/bin/rpmbuild ]; then | ||||
|   rpmbuild --nodeps \ | ||||
|      --define "extra_release $EXTRA_RELEASE" \ | ||||
|      --define "_sourcedir `pwd`" \ | ||||
|      -ba --clean libvirt.spec | ||||
| fi | ||||
|  | ||||
| if [ -x /usr/bin/i686-pc-mingw32-gcc ]; then | ||||
|   make distclean | ||||
|  | ||||
|   PKG_CONFIG_PATH="$AUTOBUILD_INSTALL_ROOT/i686-pc-mingw32/sys-root/mingw/lib/pkgconfig" \ | ||||
|   CC="i686-pc-mingw32-gcc" \ | ||||
|   ../configure \ | ||||
|     --build=$(uname -m)-pc-linux \ | ||||
|     --host=i686-pc-mingw32 \ | ||||
|     --prefix="$AUTOBUILD_INSTALL_ROOT/i686-pc-mingw32/sys-root/mingw" \ | ||||
|     --enable-compile-warnings=error \ | ||||
|     --without-sasl \ | ||||
|     --without-avahi \ | ||||
|     --without-polkit \ | ||||
|     --without-python \ | ||||
|     --without-xen \ | ||||
|     --without-qemu \ | ||||
|     --without-lxc \ | ||||
|     --without-uml \ | ||||
|     --without-vbox \ | ||||
|     --without-openvz \ | ||||
|     --without-phyp \ | ||||
|     --without-netcf \ | ||||
|     --without-audit \ | ||||
|     --without-dtrace \ | ||||
|     --without-libvirtd | ||||
|  | ||||
|   make | ||||
|   make install | ||||
|  | ||||
|   #set -o pipefail | ||||
|   #make check 2>&1 | tee "$RESULTS" | ||||
|  | ||||
|   if [ -f /usr/bin/rpmbuild ]; then | ||||
|     rpmbuild --nodeps \ | ||||
|        --define "extra_release $EXTRA_RELEASE" \ | ||||
|        --define "_sourcedir `pwd`" \ | ||||
|        -ba --clean mingw32-libvirt.spec | ||||
|   fi | ||||
| fi | ||||
							
								
								
									
										84
									
								
								autogen.sh
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								autogen.sh
									
									
									
									
									
								
							| @@ -1,84 +0,0 @@ | ||||
| #!/bin/sh | ||||
| # Run this to generate all the initial makefiles, etc. | ||||
|  | ||||
| srcdir=`dirname "$0"` | ||||
| test -z "$srcdir" && srcdir=. | ||||
|  | ||||
| THEDIR=`pwd` | ||||
| cd "$srcdir" | ||||
|  | ||||
| test -f src/libvirt.c || { | ||||
|     echo "You must run this script in the top-level libvirt directory" | ||||
|     exit 1 | ||||
| } | ||||
|  | ||||
|  | ||||
| EXTRA_ARGS= | ||||
| no_git= | ||||
| if test "x$1" = "x--no-git"; then | ||||
|   no_git=" $1" | ||||
|   shift | ||||
| fi | ||||
| if test "x$1" = "x--system"; then | ||||
|     shift | ||||
|     prefix=/usr | ||||
|     libdir=$prefix/lib | ||||
|     sysconfdir=/etc | ||||
|     localstatedir=/var | ||||
|     if [ -d /usr/lib64 ]; then | ||||
|       libdir=$prefix/lib64 | ||||
|     fi | ||||
|     EXTRA_ARGS="--prefix=$prefix --sysconfdir=$sysconfdir --localstatedir=$localstatedir --libdir=$libdir" | ||||
|     echo "Running ./configure with $EXTRA_ARGS $@" | ||||
| else | ||||
|     if test -z "$*" && test ! -f "$THEDIR/config.status"; then | ||||
|         echo "I am going to run ./configure with no arguments - if you wish " | ||||
|         echo "to pass any to it, please specify them on the $0 command line." | ||||
|     fi | ||||
| fi | ||||
|  | ||||
| # Compute the hash we'll use to determine whether rerunning bootstrap | ||||
| # is required.  The first is just the SHA1 that selects a gnulib snapshot. | ||||
| # The second ensures that whenever we change the set of gnulib modules used | ||||
| # by this package, we rerun bootstrap to pull in the matching set of files. | ||||
| bootstrap_hash() | ||||
| { | ||||
|     git submodule status | sed 's/^[ +-]//;s/ .*//' | ||||
|     git hash-object bootstrap.conf | ||||
| } | ||||
|  | ||||
| # Ensure that whenever we pull in a gnulib update or otherwise change to a | ||||
| # different version (i.e., when switching branches), we also rerun ./bootstrap. | ||||
| # Also, running 'make rpm' tends to litter the po/ directory, and some people | ||||
| # like to run 'git clean -x -f po' to fix it; but only ./bootstrap regenerates | ||||
| # the required file po/Makevars. | ||||
| # Only run bootstrap from a git checkout, never from a tarball. | ||||
| if test -d .git; then | ||||
|     curr_status=.git-module-status | ||||
|     t=$(bootstrap_hash; git diff .gnulib) | ||||
|     if test "$t" = "$(cat $curr_status 2>/dev/null)" \ | ||||
|         && test -f "po/Makevars"; then | ||||
|         # good, it's up to date, all we need is autoreconf | ||||
|         autoreconf -if | ||||
|     else | ||||
|         echo running bootstrap$no_git... | ||||
|         ./bootstrap$no_git --bootstrap-sync && bootstrap_hash > $curr_status \ | ||||
|             || { echo "Failed to bootstrap, please investigate."; exit 1; } | ||||
|     fi | ||||
| fi | ||||
|  | ||||
| cd "$THEDIR" | ||||
|  | ||||
| if test "x$OBJ_DIR" != x; then | ||||
|     mkdir -p "$OBJ_DIR" | ||||
|     cd "$OBJ_DIR" | ||||
| fi | ||||
|  | ||||
| if test -z "$*" && test -f config.status; then | ||||
|     ./config.status --recheck | ||||
| else | ||||
|     $srcdir/configure $EXTRA_ARGS "$@" | ||||
| fi && { | ||||
|     echo | ||||
|     echo "Now type 'make' to compile libvirt." | ||||
| } | ||||
							
								
								
									
										971
									
								
								bootstrap
									
									
									
									
									
								
							
							
						
						
									
										971
									
								
								bootstrap
									
									
									
									
									
								
							| @@ -1,971 +0,0 @@ | ||||
| #! /bin/sh | ||||
| # Print a version string. | ||||
| scriptversion=2011-08-11.17; # UTC | ||||
|  | ||||
| # Bootstrap this package from checked-out sources. | ||||
|  | ||||
| # Copyright (C) 2003-2011 Free Software Foundation, Inc. | ||||
|  | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, either version 3 of the License, or | ||||
| # (at your option) any later version. | ||||
|  | ||||
| # This program 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 General Public License for more details. | ||||
|  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| # Originally written by Paul Eggert.  The canonical version of this | ||||
| # script is maintained as build-aux/bootstrap in gnulib, however, to | ||||
| # be useful to your project, you should place a copy of it under | ||||
| # version control in the top-level directory of your project.  The | ||||
| # intent is that all customization can be done with a bootstrap.conf | ||||
| # file also maintained in your version control; gnulib comes with a | ||||
| # template build-aux/bootstrap.conf to get you started. | ||||
|  | ||||
| # Please report bugs or propose patches to bug-gnulib@gnu.org. | ||||
|  | ||||
| nl=' | ||||
| ' | ||||
|  | ||||
| # Ensure file names are sorted consistently across platforms. | ||||
| LC_ALL=C | ||||
| export LC_ALL | ||||
|  | ||||
| local_gl_dir=gl | ||||
|  | ||||
| # Temporary directory names. | ||||
| bt='._bootmp' | ||||
| bt_regex=`echo "$bt"| sed 's/\./[.]/g'` | ||||
| bt2=${bt}2 | ||||
| me=$0 | ||||
|  | ||||
| usage() { | ||||
|   cat <<EOF | ||||
| Usage: $me [OPTION]... | ||||
| Bootstrap this package from the checked-out sources. | ||||
|  | ||||
| Options: | ||||
|  --gnulib-srcdir=DIRNAME  specify the local directory where gnulib | ||||
|                           sources reside.  Use this if you already | ||||
|                           have gnulib sources on your machine, and | ||||
|                           do not want to waste your bandwidth downloading | ||||
|                           them again.  Defaults to \$GNULIB_SRCDIR | ||||
|  --bootstrap-sync         if this bootstrap script is not identical to | ||||
|                           the version in the local gnulib sources, | ||||
|                           update this script, and then restart it with | ||||
|                           /bin/sh or the shell \$CONFIG_SHELL | ||||
|  --no-bootstrap-sync      do not check whether bootstrap is out of sync | ||||
|  --copy                   copy files instead of creating symbolic links | ||||
|  --force                  attempt to bootstrap even if the sources seem | ||||
|                           not to have been checked out | ||||
|  --no-git                 do not use git to update gnulib.  Requires that | ||||
|                           --gnulib-srcdir point to a correct gnulib snapshot | ||||
|  --skip-po                do not download po files | ||||
|  | ||||
| If the file $me.conf exists in the same directory as this script, its | ||||
| contents are read as shell variables to configure the bootstrap. | ||||
|  | ||||
| For build prerequisites, environment variables like \$AUTOCONF and \$AMTAR | ||||
| are honored. | ||||
|  | ||||
| Running without arguments will suffice in most cases. | ||||
| EOF | ||||
| } | ||||
|  | ||||
| # Configuration. | ||||
|  | ||||
| # Name of the Makefile.am | ||||
| gnulib_mk=gnulib.mk | ||||
|  | ||||
| # List of gnulib modules needed. | ||||
| gnulib_modules= | ||||
|  | ||||
| # Any gnulib files needed that are not in modules. | ||||
| gnulib_files= | ||||
|  | ||||
| # A function to be called to edit gnulib.mk right after it's created. | ||||
| # Override it via your own definition in bootstrap.conf. | ||||
| gnulib_mk_hook() { :; } | ||||
|  | ||||
| # A function to be called after everything else in this script. | ||||
| # Override it via your own definition in bootstrap.conf. | ||||
| bootstrap_epilogue() { :; } | ||||
|  | ||||
| # The command to download all .po files for a specified domain into | ||||
| # a specified directory.  Fill in the first %s is the domain name, and | ||||
| # the second with the destination directory.  Use rsync's -L and -r | ||||
| # options because the latest/%s directory and the .po files within are | ||||
| # all symlinks. | ||||
| po_download_command_format=\ | ||||
| "rsync --delete --exclude '*.s1' -Lrtvz \ | ||||
|  'translationproject.org::tp/latest/%s/' '%s'" | ||||
|  | ||||
| extract_package_name=' | ||||
|   /^AC_INIT(/{ | ||||
|      /.*,.*,.*, */{ | ||||
|        s/// | ||||
|        s/[][]//g | ||||
|        s/)$// | ||||
|        p | ||||
|        q | ||||
|      } | ||||
|      s/AC_INIT(\[*// | ||||
|      s/]*,.*// | ||||
|      s/^GNU // | ||||
|      y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ | ||||
|      s/[^A-Za-z0-9_]/-/g | ||||
|      p | ||||
|   } | ||||
| ' | ||||
| package=`sed -n "$extract_package_name" configure.ac` || exit | ||||
| gnulib_name=lib$package | ||||
|  | ||||
| build_aux=build-aux | ||||
| source_base=lib | ||||
| m4_base=m4 | ||||
| doc_base=doc | ||||
| tests_base=tests | ||||
| gnulib_extra_files='' | ||||
|  | ||||
| # Additional gnulib-tool options to use.  Use "\newline" to break lines. | ||||
| gnulib_tool_option_extras= | ||||
|  | ||||
| # Other locale categories that need message catalogs. | ||||
| EXTRA_LOCALE_CATEGORIES= | ||||
|  | ||||
| # Additional xgettext options to use.  Use "\\\newline" to break lines. | ||||
| XGETTEXT_OPTIONS='\\\ | ||||
|  --flag=_:1:pass-c-format\\\ | ||||
|  --flag=N_:1:pass-c-format\\\ | ||||
|  --flag=error:3:c-format --flag=error_at_line:5:c-format\\\ | ||||
| ' | ||||
|  | ||||
| # Package bug report address and copyright holder for gettext files | ||||
| COPYRIGHT_HOLDER='Free Software Foundation, Inc.' | ||||
| MSGID_BUGS_ADDRESS=bug-$package@gnu.org | ||||
|  | ||||
| # Files we don't want to import. | ||||
| excluded_files= | ||||
|  | ||||
| # File that should exist in the top directory of a checked out hierarchy, | ||||
| # but not in a distribution tarball. | ||||
| checkout_only_file=README-hacking | ||||
|  | ||||
| # Whether to use copies instead of symlinks. | ||||
| copy=false | ||||
|  | ||||
| # Set this to '.cvsignore .gitignore' in bootstrap.conf if you want | ||||
| # those files to be generated in directories like lib/, m4/, and po/. | ||||
| # Or set it to 'auto' to make this script select which to use based | ||||
| # on which version control system (if any) is used in the source directory. | ||||
| vc_ignore=auto | ||||
|  | ||||
| # Set this to true in bootstrap.conf to enable --bootstrap-sync by | ||||
| # default. | ||||
| bootstrap_sync=false | ||||
|  | ||||
| # Use git to update gnulib sources | ||||
| use_git=true | ||||
|  | ||||
| # find_tool ENVVAR NAMES... | ||||
| # ------------------------- | ||||
| # Search for a required program.  Use the value of ENVVAR, if set, | ||||
| # otherwise find the first of the NAMES that can be run (i.e., | ||||
| # supports --version).  If found, set ENVVAR to the program name, | ||||
| # die otherwise. | ||||
| find_tool () | ||||
| { | ||||
|   find_tool_envvar=$1 | ||||
|   shift | ||||
|   find_tool_names=$@ | ||||
|   eval "find_tool_res=\$$find_tool_envvar" | ||||
|   if test x"$find_tool_res" = x; then | ||||
|     for i | ||||
|     do | ||||
|       if ($i --version </dev/null) >/dev/null 2>&1; then | ||||
|        find_tool_res=$i | ||||
|        break | ||||
|       fi | ||||
|     done | ||||
|   else | ||||
|     find_tool_error_prefix="\$$find_tool_envvar: " | ||||
|   fi | ||||
|   if test x"$find_tool_res" = x; then | ||||
|     echo >&2 "$me: one of these is required: $find_tool_names" | ||||
|     exit 1 | ||||
|   fi | ||||
|   ($find_tool_res --version </dev/null) >/dev/null 2>&1 || { | ||||
|     echo >&2 "$me: ${find_tool_error_prefix}cannot run $find_tool_res --version" | ||||
|     exit 1 | ||||
|   } | ||||
|   eval "$find_tool_envvar=\$find_tool_res" | ||||
|   eval "export $find_tool_envvar" | ||||
| } | ||||
|  | ||||
| # Find sha1sum, named gsha1sum on MacPorts, and shasum on MacOS 10.6. | ||||
| find_tool SHA1SUM sha1sum gsha1sum shasum | ||||
|  | ||||
| # Override the default configuration, if necessary. | ||||
| # Make sure that bootstrap.conf is sourced from the current directory | ||||
| # if we were invoked as "sh bootstrap". | ||||
| case "$0" in | ||||
|   */*) test -r "$0.conf" && . "$0.conf" ;; | ||||
|   *) test -r "$0.conf" && . ./"$0.conf" ;; | ||||
| esac | ||||
|  | ||||
| # Extra files from gnulib, which override files from other sources. | ||||
| test -z "${gnulib_extra_files}" && \ | ||||
|   gnulib_extra_files=" | ||||
|         $build_aux/install-sh | ||||
|         $build_aux/missing | ||||
|         $build_aux/mdate-sh | ||||
|         $build_aux/texinfo.tex | ||||
|         $build_aux/depcomp | ||||
|         $build_aux/config.guess | ||||
|         $build_aux/config.sub | ||||
|         doc/INSTALL | ||||
| " | ||||
|  | ||||
| if test "$vc_ignore" = auto; then | ||||
|   vc_ignore= | ||||
|   test -d .git && vc_ignore=.gitignore | ||||
|   test -d CVS && vc_ignore="$vc_ignore .cvsignore" | ||||
| fi | ||||
|  | ||||
| # Translate configuration into internal form. | ||||
|  | ||||
| # Parse options. | ||||
|  | ||||
| for option | ||||
| do | ||||
|   case $option in | ||||
|   --help) | ||||
|     usage | ||||
|     exit;; | ||||
|   --gnulib-srcdir=*) | ||||
|     GNULIB_SRCDIR=`expr "X$option" : 'X--gnulib-srcdir=\(.*\)'`;; | ||||
|   --skip-po) | ||||
|     SKIP_PO=t;; | ||||
|   --force) | ||||
|     checkout_only_file=;; | ||||
|   --copy) | ||||
|     copy=true;; | ||||
|   --bootstrap-sync) | ||||
|     bootstrap_sync=true;; | ||||
|   --no-bootstrap-sync) | ||||
|     bootstrap_sync=false;; | ||||
|   --no-git) | ||||
|     use_git=false;; | ||||
|   *) | ||||
|     echo >&2 "$0: $option: unknown option" | ||||
|     exit 1;; | ||||
|   esac | ||||
| done | ||||
|  | ||||
| if $use_git || test -d "$GNULIB_SRCDIR"; then | ||||
|   : | ||||
| else | ||||
|   echo "$0: Error: --no-git requires --gnulib-srcdir" >&2 | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then | ||||
|   echo "$0: Bootstrapping from a non-checked-out distribution is risky." >&2 | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| # Ensure that lines starting with ! sort last, per gitignore conventions | ||||
| # for whitelisting exceptions after a more generic blacklist pattern. | ||||
| sort_patterns() { | ||||
|   sort -u "$@" | sed '/^!/ { | ||||
|     H | ||||
|     d | ||||
|   } | ||||
|   $ { | ||||
|     P | ||||
|     x | ||||
|     s/^\n// | ||||
|   }' | sed '/^$/d' | ||||
| } | ||||
|  | ||||
| # If $STR is not already on a line by itself in $FILE, insert it, | ||||
| # sorting the new contents of the file and replacing $FILE with the result. | ||||
| insert_sorted_if_absent() { | ||||
|   file=$1 | ||||
|   str=$2 | ||||
|   test -f $file || touch $file | ||||
|   echo "$str" | sort_patterns - $file | cmp - $file > /dev/null \ | ||||
|     || { echo "$str" | sort_patterns - $file > $file.bak \ | ||||
|       && mv $file.bak $file; } \ | ||||
|     || exit 1 | ||||
| } | ||||
|  | ||||
| # Adjust $PATTERN for $VC_IGNORE_FILE and insert it with | ||||
| # insert_sorted_if_absent. | ||||
| insert_vc_ignore() { | ||||
|   vc_ignore_file="$1" | ||||
|   pattern="$2" | ||||
|   case $vc_ignore_file in | ||||
|   *.gitignore) | ||||
|     # A .gitignore entry that does not start with `/' applies | ||||
|     # recursively to subdirectories, so prepend `/' to every | ||||
|     # .gitignore entry. | ||||
|     pattern=`echo "$pattern" | sed s,^,/,`;; | ||||
|   esac | ||||
|   insert_sorted_if_absent "$vc_ignore_file" "$pattern" | ||||
| } | ||||
|  | ||||
| # Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. | ||||
| found_aux_dir=no | ||||
| grep '^[	 ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \ | ||||
|     >/dev/null && found_aux_dir=yes | ||||
| grep '^[	 ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \ | ||||
|     >/dev/null && found_aux_dir=yes | ||||
| if test $found_aux_dir = no; then | ||||
|   echo "$0: expected line not found in configure.ac. Add the following:" >&2 | ||||
|   echo "  AC_CONFIG_AUX_DIR([$build_aux])" >&2 | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| # If $build_aux doesn't exist, create it now, otherwise some bits | ||||
| # below will malfunction.  If creating it, also mark it as ignored. | ||||
| if test ! -d $build_aux; then | ||||
|   mkdir $build_aux | ||||
|   for dot_ig in x $vc_ignore; do | ||||
|     test $dot_ig = x && continue | ||||
|     insert_vc_ignore $dot_ig $build_aux | ||||
|   done | ||||
| fi | ||||
|  | ||||
| # Note this deviates from the version comparison in automake | ||||
| # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a | ||||
| # but this should suffice as we won't be specifying old | ||||
| # version formats or redundant trailing .0 in bootstrap.conf. | ||||
| # If we did want full compatibility then we should probably | ||||
| # use m4_version_compare from autoconf. | ||||
| sort_ver() { # sort -V is not generally available | ||||
|   ver1="$1" | ||||
|   ver2="$2" | ||||
|  | ||||
|   # split on '.' and compare each component | ||||
|   i=1 | ||||
|   while : ; do | ||||
|     p1=$(echo "$ver1" | cut -d. -f$i) | ||||
|     p2=$(echo "$ver2" | cut -d. -f$i) | ||||
|     if [ ! "$p1" ]; then | ||||
|       echo "$1 $2" | ||||
|       break | ||||
|     elif [ ! "$p2" ]; then | ||||
|       echo "$2 $1" | ||||
|       break | ||||
|     elif [ ! "$p1" = "$p2" ]; then | ||||
|       if [ "$p1" -gt "$p2" ] 2>/dev/null; then # numeric comparison | ||||
|         echo "$2 $1" | ||||
|       elif [ "$p2" -gt "$p1" ] 2>/dev/null; then # numeric comparison | ||||
|         echo "$1 $2" | ||||
|       else # numeric, then lexicographic comparison | ||||
|         lp=$(printf "$p1\n$p2\n" | LANG=C sort -n | tail -n1) | ||||
|         if [ "$lp" = "$p2" ]; then | ||||
|           echo "$1 $2" | ||||
|         else | ||||
|           echo "$2 $1" | ||||
|         fi | ||||
|       fi | ||||
|       break | ||||
|     fi | ||||
|     i=$(($i+1)) | ||||
|   done | ||||
| } | ||||
|  | ||||
| get_version() { | ||||
|   app=$1 | ||||
|  | ||||
|   $app --version >/dev/null 2>&1 || return 1 | ||||
|  | ||||
|   $app --version 2>&1 | | ||||
|   sed -n '# Move version to start of line. | ||||
|           s/.*[v ]\([0-9]\)/\1/ | ||||
|  | ||||
|           # Skip lines that do not start with version. | ||||
|           /^[0-9]/!d | ||||
|  | ||||
|           # Remove characters after the version. | ||||
|           s/[^.a-z0-9-].*// | ||||
|  | ||||
|           # The first component must be digits only. | ||||
|           s/^\([0-9]*\)[a-z-].*/\1/ | ||||
|  | ||||
|           #the following essentially does s/5.005/5.5/ | ||||
|           s/\.0*\([1-9]\)/.\1/g | ||||
|           p | ||||
|           q' | ||||
| } | ||||
|  | ||||
| check_versions() { | ||||
|   ret=0 | ||||
|  | ||||
|   while read app req_ver; do | ||||
|     # We only need libtoolize from the libtool package. | ||||
|     if test "$app" = libtool; then | ||||
|       app=libtoolize | ||||
|     fi | ||||
|     # Exempt git if --no-git is in effect. | ||||
|     if test "$app" = git; then | ||||
|       $use_git || continue | ||||
|     fi | ||||
|     # Honor $APP variables ($TAR, $AUTOCONF, etc.) | ||||
|     appvar=`echo $app | tr '[a-z]-' '[A-Z]_'` | ||||
|     test "$appvar" = TAR && appvar=AMTAR | ||||
|     case $appvar in | ||||
|         GZIP) ;; # Do not use $GZIP:  it contains gzip options. | ||||
|         *) eval "app=\${$appvar-$app}" ;; | ||||
|     esac | ||||
|     if [ "$req_ver" = "-" ]; then | ||||
|       # Merely require app to exist; not all prereq apps are well-behaved | ||||
|       # so we have to rely on $? rather than get_version. | ||||
|       $app --version >/dev/null 2>&1 | ||||
|       if [ 126 -le $? ]; then | ||||
|         echo "$me: Error: '$app' not found" >&2 | ||||
|         ret=1 | ||||
|       fi | ||||
|     else | ||||
|       # Require app to produce a new enough version string. | ||||
|       inst_ver=$(get_version $app) | ||||
|       if [ ! "$inst_ver" ]; then | ||||
|         echo "$me: Error: '$app' not found" >&2 | ||||
|         ret=1 | ||||
|       else | ||||
|         latest_ver=$(sort_ver $req_ver $inst_ver | cut -d' ' -f2) | ||||
|         if [ ! "$latest_ver" = "$inst_ver" ]; then | ||||
|           echo "$me: Error: '$app' version == $inst_ver is too old" >&2 | ||||
|           echo "       '$app' version >= $req_ver is required" >&2 | ||||
|           ret=1 | ||||
|         fi | ||||
|       fi | ||||
|     fi | ||||
|   done | ||||
|  | ||||
|   return $ret | ||||
| } | ||||
|  | ||||
| print_versions() { | ||||
|   echo "Program    Min_version" | ||||
|   echo "----------------------" | ||||
|   printf %s "$buildreq" | ||||
|   echo "----------------------" | ||||
|   # can't depend on column -t | ||||
| } | ||||
|  | ||||
| use_libtool=0 | ||||
| # We'd like to use grep -E, to see if any of LT_INIT, | ||||
| # AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac, | ||||
| # but that's not portable enough (e.g., for Solaris). | ||||
| grep '^[	 ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \ | ||||
|   && use_libtool=1 | ||||
| grep '^[	 ]*LT_INIT' configure.ac >/dev/null \ | ||||
|   && use_libtool=1 | ||||
| if test $use_libtool = 1; then | ||||
|   find_tool LIBTOOLIZE glibtoolize libtoolize | ||||
| fi | ||||
|  | ||||
| if ! printf "$buildreq" | check_versions; then | ||||
|   echo >&2 | ||||
|   if test -f README-prereq; then | ||||
|     echo "$0: See README-prereq for how to get the prerequisite programs" >&2 | ||||
|   else | ||||
|     echo "$0: Please install the prerequisite programs" >&2 | ||||
|   fi | ||||
|   exit 1 | ||||
| fi | ||||
|  | ||||
| echo "$0: Bootstrapping from checked-out $package sources..." | ||||
|  | ||||
| # See if we can use gnulib's git-merge-changelog merge driver. | ||||
| if test -d .git && (git --version) >/dev/null 2>/dev/null ; then | ||||
|   if git config merge.merge-changelog.driver >/dev/null ; then | ||||
|     : | ||||
|   elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then | ||||
|     echo "$0: initializing git-merge-changelog driver" | ||||
|     git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver' | ||||
|     git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B' | ||||
|   else | ||||
|     echo "$0: consider installing git-merge-changelog from gnulib" | ||||
|   fi | ||||
| fi | ||||
|  | ||||
|  | ||||
| cleanup_gnulib() { | ||||
|   status=$? | ||||
|   rm -fr "$gnulib_path" | ||||
|   exit $status | ||||
| } | ||||
|  | ||||
| git_modules_config () { | ||||
|   test -f .gitmodules && git config --file .gitmodules "$@" | ||||
| } | ||||
|  | ||||
| gnulib_path=`git_modules_config submodule.gnulib.path` | ||||
| test -z "$gnulib_path" && gnulib_path=gnulib | ||||
|  | ||||
| # Get gnulib files. | ||||
|  | ||||
| case ${GNULIB_SRCDIR--} in | ||||
| -) | ||||
|   if git_modules_config submodule.gnulib.url >/dev/null; then | ||||
|     echo "$0: getting gnulib files..." | ||||
|     git submodule init || exit $? | ||||
|     git submodule update || exit $? | ||||
|  | ||||
|   elif [ ! -d "$gnulib_path" ]; then | ||||
|     echo "$0: getting gnulib files..." | ||||
|  | ||||
|     trap cleanup_gnulib 1 2 13 15 | ||||
|  | ||||
|     shallow= | ||||
|     git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' | ||||
|     git clone $shallow git://git.sv.gnu.org/gnulib "$gnulib_path" || | ||||
|       cleanup_gnulib | ||||
|  | ||||
|     trap - 1 2 13 15 | ||||
|   fi | ||||
|   GNULIB_SRCDIR=$gnulib_path | ||||
|   ;; | ||||
| *) | ||||
|   # Use GNULIB_SRCDIR as a reference. | ||||
|   if test -d "$GNULIB_SRCDIR"/.git && \ | ||||
|         git_modules_config submodule.gnulib.url >/dev/null; then | ||||
|     echo "$0: getting gnulib files..." | ||||
|     if git submodule -h|grep -- --reference > /dev/null; then | ||||
|       # Prefer the one-liner available in git 1.6.4 or newer. | ||||
|       git submodule update --init --reference "$GNULIB_SRCDIR" \ | ||||
|         "$gnulib_path" || exit $? | ||||
|     else | ||||
|       # This fallback allows at least git 1.5.5. | ||||
|       if test -f "$gnulib_path"/gnulib-tool; then | ||||
|         # Since file already exists, assume submodule init already complete. | ||||
|         git submodule update || exit $? | ||||
|       else | ||||
|         # Older git can't clone into an empty directory. | ||||
|         rmdir "$gnulib_path" 2>/dev/null | ||||
|         git clone --reference "$GNULIB_SRCDIR" \ | ||||
|           "$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \ | ||||
|           && git submodule init && git submodule update \ | ||||
|           || exit $? | ||||
|       fi | ||||
|     fi | ||||
|     GNULIB_SRCDIR=$gnulib_path | ||||
|   fi | ||||
|   ;; | ||||
| esac | ||||
|  | ||||
| if $bootstrap_sync; then | ||||
|   cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || { | ||||
|     echo "$0: updating bootstrap and restarting..." | ||||
|     exec sh -c \ | ||||
|       'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \ | ||||
|       -- "$GNULIB_SRCDIR/build-aux/bootstrap" \ | ||||
|       "$0" "$@" --no-bootstrap-sync | ||||
|   } | ||||
| fi | ||||
|  | ||||
| gnulib_tool=$GNULIB_SRCDIR/gnulib-tool | ||||
| <$gnulib_tool || exit | ||||
|  | ||||
| # Get translations. | ||||
|  | ||||
| download_po_files() { | ||||
|   subdir=$1 | ||||
|   domain=$2 | ||||
|   echo "$me: getting translations into $subdir for $domain..." | ||||
|   cmd=`printf "$po_download_command_format" "$domain" "$subdir"` | ||||
|   eval "$cmd" | ||||
| } | ||||
|  | ||||
| # Mirror .po files to $po_dir/.reference and copy only the new | ||||
| # or modified ones into $po_dir.  Also update $po_dir/LINGUAS. | ||||
| # Note po files that exist locally only are left in $po_dir but will | ||||
| # not be included in LINGUAS and hence will not be distributed. | ||||
| update_po_files() { | ||||
|   # Directory containing primary .po files. | ||||
|   # Overwrite them only when we're sure a .po file is new. | ||||
|   po_dir=$1 | ||||
|   domain=$2 | ||||
|  | ||||
|   # Mirror *.po files into this dir. | ||||
|   # Usually contains *.s1 checksum files. | ||||
|   ref_po_dir="$po_dir/.reference" | ||||
|  | ||||
|   test -d $ref_po_dir || mkdir $ref_po_dir || return | ||||
|   download_po_files $ref_po_dir $domain \ | ||||
|     && ls "$ref_po_dir"/*.po 2>/dev/null | | ||||
|       sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS" || return | ||||
|  | ||||
|   langs=`cd $ref_po_dir && echo *.po|sed 's/\.po//g'` | ||||
|   test "$langs" = '*' && langs=x | ||||
|   for po in $langs; do | ||||
|     case $po in x) continue;; esac | ||||
|     new_po="$ref_po_dir/$po.po" | ||||
|     cksum_file="$ref_po_dir/$po.s1" | ||||
|     if ! test -f "$cksum_file" || | ||||
|         ! test -f "$po_dir/$po.po" || | ||||
|         ! $SHA1SUM -c --status "$cksum_file" \ | ||||
|             < "$new_po" > /dev/null; then | ||||
|       echo "$me: updated $po_dir/$po.po..." | ||||
|       cp "$new_po" "$po_dir/$po.po" \ | ||||
|           && $SHA1SUM < "$new_po" > "$cksum_file" | ||||
|     fi | ||||
|   done | ||||
| } | ||||
|  | ||||
| case $SKIP_PO in | ||||
| '') | ||||
|   if test -d po; then | ||||
|     update_po_files po $package || exit | ||||
|   fi | ||||
|  | ||||
|   if test -d runtime-po; then | ||||
|     update_po_files runtime-po $package-runtime || exit | ||||
|   fi;; | ||||
| esac | ||||
|  | ||||
| symlink_to_dir() | ||||
| { | ||||
|   src=$1/$2 | ||||
|   dst=${3-$2} | ||||
|  | ||||
|   test -f "$src" && { | ||||
|  | ||||
|     # If the destination directory doesn't exist, create it. | ||||
|     # This is required at least for "lib/uniwidth/cjk.h". | ||||
|     dst_dir=`dirname "$dst"` | ||||
|     if ! test -d "$dst_dir"; then | ||||
|       mkdir -p "$dst_dir" | ||||
|  | ||||
|       # If we've just created a directory like lib/uniwidth, | ||||
|       # tell version control system(s) it's ignorable. | ||||
|       # FIXME: for now, this does only one level | ||||
|       parent=`dirname "$dst_dir"` | ||||
|       for dot_ig in x $vc_ignore; do | ||||
|         test $dot_ig = x && continue | ||||
|         ig=$parent/$dot_ig | ||||
|         insert_vc_ignore $ig `echo "$dst_dir"|sed 's,.*/,,'` | ||||
|       done | ||||
|     fi | ||||
|  | ||||
|     if $copy; then | ||||
|       { | ||||
|         test ! -h "$dst" || { | ||||
|           echo "$me: rm -f $dst" && | ||||
|           rm -f "$dst" | ||||
|         } | ||||
|       } && | ||||
|       test -f "$dst" && | ||||
|       cmp -s "$src" "$dst" || { | ||||
|         echo "$me: cp -fp $src $dst" && | ||||
|         cp -fp "$src" "$dst" | ||||
|       } | ||||
|     else | ||||
|       # Leave any existing symlink alone, if it already points to the source, | ||||
|       # so that broken build tools that care about symlink times | ||||
|       # aren't confused into doing unnecessary builds.  Conversely, if the | ||||
|       # existing symlink's time stamp is older than the source, make it afresh, | ||||
|       # so that broken tools aren't confused into skipping needed builds.  See | ||||
|       # <http://lists.gnu.org/archive/html/bug-gnulib/2011-05/msg00326.html>. | ||||
|       test -h "$dst" && | ||||
|       src_ls=`ls -diL "$src" 2>/dev/null` && set $src_ls && src_i=$1 && | ||||
|       dst_ls=`ls -diL "$dst" 2>/dev/null` && set $dst_ls && dst_i=$1 && | ||||
|       test "$src_i" = "$dst_i" && | ||||
|       both_ls=`ls -dt "$src" "$dst"` && | ||||
|       test "X$both_ls" = "X$dst$nl$src" || { | ||||
|         dot_dots= | ||||
|         case $src in | ||||
|         /*) ;; | ||||
|         *) | ||||
|           case /$dst/ in | ||||
|           *//* | */../* | */./* | /*/*/*/*/*/) | ||||
|              echo >&2 "$me: invalid symlink calculation: $src -> $dst" | ||||
|              exit 1;; | ||||
|           /*/*/*/*/)	dot_dots=../../../;; | ||||
|           /*/*/*/)	dot_dots=../../;; | ||||
|           /*/*/)	dot_dots=../;; | ||||
|           esac;; | ||||
|         esac | ||||
|  | ||||
|         echo "$me: ln -fs $dot_dots$src $dst" && | ||||
|         ln -fs "$dot_dots$src" "$dst" | ||||
|       } | ||||
|     fi | ||||
|   } | ||||
| } | ||||
|  | ||||
| cp_mark_as_generated() | ||||
| { | ||||
|   cp_src=$1 | ||||
|   cp_dst=$2 | ||||
|  | ||||
|   if cmp -s "$cp_src" "$GNULIB_SRCDIR/$cp_dst"; then | ||||
|     symlink_to_dir "$GNULIB_SRCDIR" "$cp_dst" | ||||
|   elif cmp -s "$cp_src" "$local_gl_dir/$cp_dst"; then | ||||
|     symlink_to_dir $local_gl_dir "$cp_dst" | ||||
|   else | ||||
|     case $cp_dst in | ||||
|       *.[ch])             c1='/* '; c2=' */';; | ||||
|       *.texi)             c1='@c '; c2=     ;; | ||||
|       *.m4|*/Make*|Make*) c1='# ' ; c2=     ;; | ||||
|       *)                  c1=     ; c2=     ;; | ||||
|     esac | ||||
|  | ||||
|     # If the destination directory doesn't exist, create it. | ||||
|     # This is required at least for "lib/uniwidth/cjk.h". | ||||
|     dst_dir=`dirname "$cp_dst"` | ||||
|     test -d "$dst_dir" || mkdir -p "$dst_dir" | ||||
|  | ||||
|     if test -z "$c1"; then | ||||
|       cmp -s "$cp_src" "$cp_dst" || { | ||||
|         # Copy the file first to get proper permissions if it | ||||
|         # doesn't already exist.  Then overwrite the copy. | ||||
|         echo "$me: cp -f $cp_src $cp_dst" && | ||||
|         rm -f "$cp_dst" && | ||||
|         cp "$cp_src" "$cp_dst-t" && | ||||
|         sed "s!$bt_regex/!!g" "$cp_src" > "$cp_dst-t" && | ||||
|         mv -f "$cp_dst-t" "$cp_dst" | ||||
|       } | ||||
|     else | ||||
|       # Copy the file first to get proper permissions if it | ||||
|       # doesn't already exist.  Then overwrite the copy. | ||||
|       cp "$cp_src" "$cp_dst-t" && | ||||
|       ( | ||||
|         echo "$c1-*- buffer-read-only: t -*- vi: set ro:$c2" && | ||||
|         echo "${c1}DO NOT EDIT! GENERATED AUTOMATICALLY!$c2" && | ||||
|         sed "s!$bt_regex/!!g" "$cp_src" | ||||
|       ) > $cp_dst-t && | ||||
|       if cmp -s "$cp_dst-t" "$cp_dst"; then | ||||
|         rm -f "$cp_dst-t" | ||||
|       else | ||||
|         echo "$me: cp $cp_src $cp_dst # with edits" && | ||||
|         mv -f "$cp_dst-t" "$cp_dst" | ||||
|       fi | ||||
|     fi | ||||
|   fi | ||||
| } | ||||
|  | ||||
| version_controlled_file() { | ||||
|   dir=$1 | ||||
|   file=$2 | ||||
|   found=no | ||||
|   if test -d CVS; then | ||||
|     grep -F "/$file/" $dir/CVS/Entries 2>/dev/null | | ||||
|              grep '^/[^/]*/[0-9]' > /dev/null && found=yes | ||||
|   elif test -d .git; then | ||||
|     git rm -n "$dir/$file" > /dev/null 2>&1 && found=yes | ||||
|   elif test -d .svn; then | ||||
|     svn log -r HEAD "$dir/$file" > /dev/null 2>&1 && found=yes | ||||
|   else | ||||
|     echo "$me: no version control for $dir/$file?" >&2 | ||||
|   fi | ||||
|   test $found = yes | ||||
| } | ||||
|  | ||||
| slurp() { | ||||
|   for dir in . `(cd $1 && find * -type d -print)`; do | ||||
|     copied= | ||||
|     sep= | ||||
|     for file in `ls -a $1/$dir`; do | ||||
|       case $file in | ||||
|       .|..) continue;; | ||||
|       # FIXME: should all file names starting with "." be ignored? | ||||
|       .*) continue;; | ||||
|       esac | ||||
|       test -d $1/$dir/$file && continue | ||||
|       for excluded_file in $excluded_files; do | ||||
|         test "$dir/$file" = "$excluded_file" && continue 2 | ||||
|       done | ||||
|       if test $file = Makefile.am && test "X$gnulib_mk" != XMakefile.am; then | ||||
|         copied=$copied${sep}$gnulib_mk; sep=$nl | ||||
|         remove_intl='/^[^#].*\/intl/s/^/#/;'"s!$bt_regex/!!g" | ||||
|         sed "$remove_intl" $1/$dir/$file | | ||||
|         cmp - $dir/$gnulib_mk > /dev/null || { | ||||
|           echo "$me: Copying $1/$dir/$file to $dir/$gnulib_mk ..." && | ||||
|           rm -f $dir/$gnulib_mk && | ||||
|           sed "$remove_intl" $1/$dir/$file >$dir/$gnulib_mk && | ||||
|           gnulib_mk_hook $dir/$gnulib_mk | ||||
|         } | ||||
|       elif { test "${2+set}" = set && test -r $2/$dir/$file; } || | ||||
|            version_controlled_file $dir $file; then | ||||
|         echo "$me: $dir/$file overrides $1/$dir/$file" | ||||
|       else | ||||
|         copied=$copied$sep$file; sep=$nl | ||||
|         cp_mark_as_generated $1/$dir/$file $dir/$file | ||||
|       fi || exit | ||||
|     done | ||||
|  | ||||
|     for dot_ig in x $vc_ignore; do | ||||
|       test $dot_ig = x && continue | ||||
|       ig=$dir/$dot_ig | ||||
|       if test -n "$copied"; then | ||||
|         insert_vc_ignore $ig "$copied" | ||||
|         # If an ignored file name ends with .in.h, then also add | ||||
|         # the name with just ".h".  Many gnulib headers are generated, | ||||
|         # e.g., stdint.in.h -> stdint.h, dirent.in.h ->..., etc. | ||||
|         # Likewise for .gperf -> .h, .y -> .c, and .sin -> .sed | ||||
|         f=`echo "$copied" | | ||||
|           sed ' | ||||
|             s/\.in\.h$/.h/ | ||||
|             s/\.sin$/.sed/ | ||||
|             s/\.y$/.c/ | ||||
|             s/\.gperf$/.h/ | ||||
|           ' | ||||
|         ` | ||||
|         insert_vc_ignore $ig "$f" | ||||
|  | ||||
|         # For files like sys_stat.in.h and sys_time.in.h, record as | ||||
|         # ignorable the directory we might eventually create: sys/. | ||||
|         f=`echo "$copied"|sed 's/sys_.*\.in\.h$/sys/'` | ||||
|         insert_vc_ignore $ig "$f" | ||||
|       fi | ||||
|     done | ||||
|   done | ||||
| } | ||||
|  | ||||
|  | ||||
| # Create boot temporary directories to import from gnulib and gettext. | ||||
| rm -fr $bt $bt2 && | ||||
| mkdir $bt $bt2 || exit | ||||
|  | ||||
| # Import from gnulib. | ||||
|  | ||||
| gnulib_tool_options="\ | ||||
|  --import\ | ||||
|  --no-changelog\ | ||||
|  --aux-dir $bt/$build_aux\ | ||||
|  --doc-base $bt/$doc_base\ | ||||
|  --lib $gnulib_name\ | ||||
|  --m4-base $bt/$m4_base/\ | ||||
|  --source-base $bt/$source_base/\ | ||||
|  --tests-base $bt/$tests_base\ | ||||
|  --local-dir $local_gl_dir\ | ||||
|  $gnulib_tool_option_extras\ | ||||
| " | ||||
| if test $use_libtool = 1; then | ||||
|   case "$gnulib_tool_options " in | ||||
|     *' --libtool '*) ;; | ||||
|     *) gnulib_tool_options="$gnulib_tool_options --libtool" ;; | ||||
|   esac | ||||
| fi | ||||
| echo "$0: $gnulib_tool $gnulib_tool_options --import ..." | ||||
| $gnulib_tool $gnulib_tool_options --import $gnulib_modules && | ||||
| slurp $bt || exit | ||||
|  | ||||
| for file in $gnulib_files; do | ||||
|   symlink_to_dir "$GNULIB_SRCDIR" $file || exit | ||||
| done | ||||
|  | ||||
|  | ||||
| # Import from gettext. | ||||
| with_gettext=yes | ||||
| grep '^[	 ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \ | ||||
|     with_gettext=no | ||||
|  | ||||
| if test $with_gettext = yes; then | ||||
|   echo "$0: (cd $bt2; ${AUTOPOINT-autopoint}) ..." | ||||
|   cp configure.ac $bt2 && | ||||
|   (cd $bt2 && ${AUTOPOINT-autopoint} && rm configure.ac) && | ||||
|   slurp $bt2 $bt || exit | ||||
| fi | ||||
| rm -fr $bt $bt2 || exit | ||||
|  | ||||
| # Remove any dangling symlink matching "*.m4" or "*.[ch]" in some | ||||
| # gnulib-populated directories.  Such .m4 files would cause aclocal to fail. | ||||
| # The following requires GNU find 4.2.3 or newer.  Considering the usual | ||||
| # portability constraints of this script, that may seem a very demanding | ||||
| # requirement, but it should be ok.  Ignore any failure, which is fine, | ||||
| # since this is only a convenience to help developers avoid the relatively | ||||
| # unusual case in which a symlinked-to .m4 file is git-removed from gnulib | ||||
| # between successive runs of this script. | ||||
| find "$m4_base" "$source_base" \ | ||||
|   -depth \( -name '*.m4' -o -name '*.[ch]' \) \ | ||||
|   -type l -xtype l -delete > /dev/null 2>&1 | ||||
|  | ||||
| # Reconfigure, getting other files. | ||||
|  | ||||
| # Skip autoheader if it's not needed. | ||||
| grep -E '^[	 ]*AC_CONFIG_HEADERS?\>' configure.ac >/dev/null || | ||||
|   AUTOHEADER=true | ||||
|  | ||||
| for command in \ | ||||
|   libtool \ | ||||
|   "${ACLOCAL-aclocal} --force -I '$m4_base' $ACLOCAL_FLAGS" \ | ||||
|   "${AUTOCONF-autoconf} --force" \ | ||||
|   "${AUTOHEADER-autoheader} --force" \ | ||||
|   "${AUTOMAKE-automake} --add-missing --copy --force-missing" | ||||
| do | ||||
|   if test "$command" = libtool; then | ||||
|     test $use_libtool = 0 \ | ||||
|       && continue | ||||
|     command="${LIBTOOLIZE-libtoolize} -c -f" | ||||
|   fi | ||||
|   echo "$0: $command ..." | ||||
|   eval "$command" || exit | ||||
| done | ||||
|  | ||||
|  | ||||
| # Get some extra files from gnulib, overriding existing files. | ||||
| for file in $gnulib_extra_files; do | ||||
|   case $file in | ||||
|   */INSTALL) dst=INSTALL;; | ||||
|   build-aux/*) dst=$build_aux/`expr "$file" : 'build-aux/\(.*\)'`;; | ||||
|   *) dst=$file;; | ||||
|   esac | ||||
|   symlink_to_dir "$GNULIB_SRCDIR" $file $dst || exit | ||||
| done | ||||
|  | ||||
| if test $with_gettext = yes; then | ||||
|   # Create gettext configuration. | ||||
|   echo "$0: Creating po/Makevars from po/Makevars.template ..." | ||||
|   rm -f po/Makevars | ||||
|   sed ' | ||||
|     /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/ | ||||
|     /^COPYRIGHT_HOLDER *=/s/=.*/= '"$COPYRIGHT_HOLDER"'/ | ||||
|     /^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$MSGID_BUGS_ADDRESS"'| | ||||
|     /^XGETTEXT_OPTIONS *=/{ | ||||
|       s/$/ \\/ | ||||
|       a\ | ||||
|           '"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+} | ||||
|     } | ||||
|   ' po/Makevars.template >po/Makevars || exit 1 | ||||
|  | ||||
|   if test -d runtime-po; then | ||||
|     # Similarly for runtime-po/Makevars, but not quite the same. | ||||
|     rm -f runtime-po/Makevars | ||||
|     sed ' | ||||
|       /^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/ | ||||
|       /^subdir *=.*/s/=.*/= runtime-po/ | ||||
|       /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/ | ||||
|       /^XGETTEXT_OPTIONS *=/{ | ||||
|         s/$/ \\/ | ||||
|         a\ | ||||
|             '"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+} | ||||
|       } | ||||
|     ' po/Makevars.template >runtime-po/Makevars || exit 1 | ||||
|  | ||||
|     # Copy identical files from po to runtime-po. | ||||
|     (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po) | ||||
|   fi | ||||
| fi | ||||
|  | ||||
| bootstrap_epilogue | ||||
|  | ||||
| echo "$0: done.  Now you can run './configure'." | ||||
|  | ||||
| # Local variables: | ||||
| # eval: (add-hook 'write-file-hooks 'time-stamp) | ||||
| # time-stamp-start: "scriptversion=" | ||||
| # time-stamp-format: "%:y-%02m-%02d.%02H" | ||||
| # time-stamp-time-zone: "UTC" | ||||
| # time-stamp-end: "; # UTC" | ||||
| # End: | ||||
							
								
								
									
										214
									
								
								bootstrap.conf
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								bootstrap.conf
									
									
									
									
									
								
							| @@ -1,214 +0,0 @@ | ||||
| # Bootstrap configuration. | ||||
|  | ||||
| # Copyright (C) 2010-2011 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 program 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA | ||||
|  | ||||
|  | ||||
| # gnulib modules used by this package. | ||||
| gnulib_modules=' | ||||
| accept | ||||
| areadlink | ||||
| base64 | ||||
| bind | ||||
| byteswap | ||||
| c-ctype | ||||
| c-strcase | ||||
| c-strcasestr | ||||
| calloc-posix | ||||
| canonicalize-lgpl | ||||
| chown | ||||
| close | ||||
| connect | ||||
| configmake | ||||
| count-one-bits | ||||
| crypto/md5 | ||||
| dirname-lgpl | ||||
| environ | ||||
| fclose | ||||
| fcntl | ||||
| fcntl-h | ||||
| ffs | ||||
| fnmatch | ||||
| fsync | ||||
| func | ||||
| getaddrinfo | ||||
| getcwd-lgpl | ||||
| gethostname | ||||
| getpass | ||||
| getpeername | ||||
| getsockname | ||||
| gettext-h | ||||
| gettimeofday | ||||
| gitlog-to-changelog | ||||
| gnumakefile | ||||
| ignore-value | ||||
| inet_pton | ||||
| intprops | ||||
| ioctl | ||||
| largefile | ||||
| listen | ||||
| maintainer-makefile | ||||
| manywarnings | ||||
| mkstemp | ||||
| mkstemps | ||||
| mktempd | ||||
| netdb | ||||
| nonblocking | ||||
| passfd | ||||
| perror | ||||
| physmem | ||||
| pipe-posix | ||||
| pipe2 | ||||
| poll | ||||
| posix-shell | ||||
| pthread | ||||
| pthread_sigmask | ||||
| recv | ||||
| random_r | ||||
| sched | ||||
| send | ||||
| setsockopt | ||||
| sigaction | ||||
| sigpipe | ||||
| snprintf | ||||
| socket | ||||
| stdarg | ||||
| stpcpy | ||||
| strchrnul | ||||
| strdup-posix | ||||
| strndup | ||||
| strerror | ||||
| strerror_r-posix | ||||
| strptime | ||||
| strsep | ||||
| strtok_r | ||||
| sys_stat | ||||
| sys_wait | ||||
| termios | ||||
| time_r | ||||
| timegm | ||||
| uname | ||||
| useless-if-before-free | ||||
| usleep | ||||
| vasprintf | ||||
| verify | ||||
| vc-list-files | ||||
| vsnprintf | ||||
| waitpid | ||||
| warnings | ||||
| ' | ||||
|  | ||||
| # Additional xgettext options to use.  Use "\\\newline" to break lines. | ||||
| XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\ | ||||
|  --flag=virAsprintf:2:c-format\\\ | ||||
|  --from-code=UTF-8\\\ | ||||
| ' | ||||
|  | ||||
| # This is not a GNU package, so the default bug address is invalid, | ||||
| # and the translation project is not in use. | ||||
| MSGID_BUGS_ADDRESS=libvir-list@redhat.com | ||||
| COPYRIGHT_HOLDER='Red Hat, Inc.' | ||||
| SKIP_PO=true | ||||
|  | ||||
| # Enable copy-mode for MSYS/MinGW. MSYS' ln doesn't work well in the way | ||||
| # bootstrap uses it with relative paths. | ||||
| if test -n "$MSYSTEM"; then | ||||
|     copy=true | ||||
| fi | ||||
|  | ||||
| # If "AM_GNU_GETTEXT(external" or "AM_GNU_GETTEXT([external]" | ||||
| # appears in configure.ac, exclude some unnecessary files. | ||||
| # Without grep's -E option (not portable enough, pre-configure), | ||||
| # the following test is ugly.  Also, this depends on the existence | ||||
| # of configure.ac, not the obsolescent-named configure.in.  But if | ||||
| # you're using this infrastructure, you should care about such things. | ||||
|  | ||||
| gettext_external=0 | ||||
| grep '^[	 ]*AM_GNU_GETTEXT(external\>' configure.ac > /dev/null && | ||||
|   gettext_external=1 | ||||
| grep '^[	 ]*AM_GNU_GETTEXT(\[external\]' configure.ac > /dev/null && | ||||
|   gettext_external=1 | ||||
|  | ||||
| if test $gettext_external = 1; then | ||||
|   # Gettext supplies these files, but we don't need them since | ||||
|   # we don't have an intl subdirectory. | ||||
|   excluded_files=' | ||||
|       m4/glibc2.m4 | ||||
|       m4/intdiv0.m4 | ||||
|       m4/lcmessage.m4 | ||||
|       m4/uintmax_t.m4 | ||||
|       m4/ulonglong.m4 | ||||
|       m4/visibility.m4 | ||||
|   ' | ||||
| fi | ||||
|  | ||||
| # Tell gnulib to: | ||||
| #   require LGPLv2+ | ||||
| #   put *.m4 files in new gnulib/m4/ dir | ||||
| #   put *.[ch] files in new gnulib/lib/ dir. | ||||
| #   import gnulib tests in new gnulib/tests/ dir. | ||||
| gnulib_name=libgnu | ||||
| m4_base=gnulib/m4 | ||||
| source_base=gnulib/lib | ||||
| tests_base=gnulib/tests | ||||
| gnulib_tool_option_extras="\ | ||||
|  --lgpl=2\ | ||||
|  --with-tests\ | ||||
| " | ||||
|  | ||||
| # Convince bootstrap to use multiple m4 directories. | ||||
| : ${ACLOCAL=aclocal} | ||||
| ACLOCAL="$ACLOCAL -I m4" | ||||
| export ACLOCAL | ||||
|  | ||||
| # Build prerequisites | ||||
| buildreq="\ | ||||
| autoconf   2.59 | ||||
| automake   1.9.6 | ||||
| autopoint  - | ||||
| gettext    0.17 | ||||
| git        1.5.5 | ||||
| gzip       - | ||||
| libtool    - | ||||
| perl       5.5 | ||||
| pkg-config - | ||||
| rpcgen     - | ||||
| tar        - | ||||
| " | ||||
|  | ||||
| # Automake requires that ChangeLog exist. | ||||
| touch ChangeLog || exit 1 | ||||
|  | ||||
| # Override bootstrap's list - we don't use mdate-sh or texinfo.tex. | ||||
| gnulib_extra_files=" | ||||
|         $build_aux/install-sh | ||||
|         $build_aux/missing | ||||
|         $build_aux/depcomp | ||||
|         $build_aux/config.guess | ||||
|         $build_aux/config.sub | ||||
|         doc/INSTALL | ||||
| " | ||||
|  | ||||
|  | ||||
| bootstrap_epilogue() | ||||
| { | ||||
|   # Change paths in gnulib/tests/gnulib.mk from "../../.." to "../..", | ||||
|   # then ensure that gnulib/tests/Makefile.in is up-to-date. | ||||
|   m=gnulib/tests/gnulib.mk | ||||
|   sed 's,\.\./\.\./\.\.,../..,g' $m > $m-t | ||||
|   mv -f $m-t $m | ||||
|   ${AUTOMAKE-automake} gnulib/tests/Makefile | ||||
| } | ||||
							
								
								
									
										742
									
								
								cfg.mk
									
									
									
									
									
								
							
							
						
						
									
										742
									
								
								cfg.mk
									
									
									
									
									
								
							| @@ -1,742 +0,0 @@ | ||||
| # Customize Makefile.maint.                           -*- makefile -*- | ||||
| # Copyright (C) 2008-2011 Red Hat, Inc. | ||||
| # Copyright (C) 2003-2008 Free Software Foundation, Inc. | ||||
|  | ||||
| # This program is free software: you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation, either version 3 of the License, or | ||||
| # (at your option) any later version. | ||||
|  | ||||
| # This program 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 General Public License for more details. | ||||
|  | ||||
| # You should have received a copy of the GNU General Public License | ||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  | ||||
| # Use alpha.gnu.org for alpha and beta releases. | ||||
| # Use ftp.gnu.org for major releases. | ||||
| gnu_ftp_host-alpha = alpha.gnu.org | ||||
| gnu_ftp_host-beta = alpha.gnu.org | ||||
| gnu_ftp_host-major = ftp.gnu.org | ||||
| gnu_rel_host = $(gnu_ftp_host-$(RELEASE_TYPE)) | ||||
|  | ||||
| url_dir_list = \ | ||||
|   ftp://$(gnu_rel_host)/gnu/coreutils | ||||
|  | ||||
| # We use .gnulib, not gnulib. | ||||
| gnulib_dir = $(srcdir)/.gnulib | ||||
|  | ||||
| # List of additional files that we want to pick up in our POTFILES.in | ||||
| # This is all gnulib files, as well as generated files for RPC code. | ||||
| generated_files = \ | ||||
|   $(srcdir)/daemon/*_dispatch.h \ | ||||
|   $(srcdir)/src/remote/*_client_bodies.h \ | ||||
|   $(srcdir)/src/remote/*_protocol.[ch] \ | ||||
|   $(srcdir)/gnulib/lib/*.[ch] | ||||
|  | ||||
| # Tests not to run as part of "make distcheck". | ||||
| local-checks-to-skip =			\ | ||||
|   changelog-check			\ | ||||
|   check-AUTHORS				\ | ||||
|   makefile-check			\ | ||||
|   makefile_path_separator_check		\ | ||||
|   patch-check				\ | ||||
|   sc_GPL_version			\ | ||||
|   sc_always_defined_macros		\ | ||||
|   sc_cast_of_alloca_return_value	\ | ||||
|   sc_cross_check_PATH_usage_in_tests	\ | ||||
|   sc_dd_max_sym_length			\ | ||||
|   sc_error_exit_success			\ | ||||
|   sc_file_system			\ | ||||
|   sc_immutable_NEWS			\ | ||||
|   sc_makefile_path_separator_check	\ | ||||
|   sc_obsolete_symbols			\ | ||||
|   sc_prohibit_S_IS_definition		\ | ||||
|   sc_prohibit_atoi_atof			\ | ||||
|   sc_prohibit_hash_without_use		\ | ||||
|   sc_prohibit_jm_in_m4			\ | ||||
|   sc_prohibit_quote_without_use		\ | ||||
|   sc_prohibit_quotearg_without_use	\ | ||||
|   sc_prohibit_stat_st_blocks		\ | ||||
|   sc_root_tests				\ | ||||
|   sc_space_tab				\ | ||||
|   sc_sun_os_names			\ | ||||
|   sc_system_h_headers			\ | ||||
|   sc_texinfo_acronym			\ | ||||
|   sc_tight_scope			\ | ||||
|   sc_two_space_separator_in_usage	\ | ||||
|   sc_error_message_uppercase		\ | ||||
|   sc_program_name			\ | ||||
|   sc_require_test_exit_idiom		\ | ||||
|   sc_makefile_check			\ | ||||
|   sc_useless_cpp_parens | ||||
|  | ||||
| # Files that should never cause syntax check failures. | ||||
| VC_LIST_ALWAYS_EXCLUDE_REGEX = \ | ||||
|   (^(HACKING|docs/(news\.html\.in|.*\.patch))|\.po)$$ | ||||
|  | ||||
| # Functions like free() that are no-ops on NULL arguments. | ||||
| useless_free_options =				\ | ||||
|   --name=VIR_FREE				\ | ||||
|   --name=qemuCapsFree				\ | ||||
|   --name=qemuMigrationCookieFree                \ | ||||
|   --name=qemuMigrationCookieGraphicsFree        \ | ||||
|   --name=sexpr_free				\ | ||||
|   --name=virBandwidthDefFree			\ | ||||
|   --name=virBitmapFree                          \ | ||||
|   --name=virCPUDefFree				\ | ||||
|   --name=virCapabilitiesFree			\ | ||||
|   --name=virCapabilitiesFreeGuest		\ | ||||
|   --name=virCapabilitiesFreeGuestDomain		\ | ||||
|   --name=virCapabilitiesFreeGuestFeature	\ | ||||
|   --name=virCapabilitiesFreeGuestMachine	\ | ||||
|   --name=virCapabilitiesFreeHostNUMACell	\ | ||||
|   --name=virCapabilitiesFreeMachines		\ | ||||
|   --name=virCgroupFree				\ | ||||
|   --name=virCommandFree				\ | ||||
|   --name=virConfFreeList			\ | ||||
|   --name=virConfFreeValue			\ | ||||
|   --name=virDomainActualNetDefFree		\ | ||||
|   --name=virDomainChrDefFree			\ | ||||
|   --name=virDomainChrSourceDefFree		\ | ||||
|   --name=virDomainControllerDefFree		\ | ||||
|   --name=virDomainDefFree			\ | ||||
|   --name=virDomainDeviceDefFree			\ | ||||
|   --name=virDomainDiskDefFree			\ | ||||
|   --name=virDomainEventCallbackListFree		\ | ||||
|   --name=virDomainEventFree			\ | ||||
|   --name=virDomainEventQueueFree		\ | ||||
|   --name=virDomainEventStateFree		\ | ||||
|   --name=virDomainFSDefFree			\ | ||||
|   --name=virDomainGraphicsDefFree		\ | ||||
|   --name=virDomainHostdevDefFree		\ | ||||
|   --name=virDomainInputDefFree			\ | ||||
|   --name=virDomainNetDefFree			\ | ||||
|   --name=virDomainObjFree			\ | ||||
|   --name=virDomainSmartcardDefFree		\ | ||||
|   --name=virDomainSnapshotDefFree		\ | ||||
|   --name=virDomainSnapshotObjFree		\ | ||||
|   --name=virDomainSoundDefFree			\ | ||||
|   --name=virDomainVideoDefFree			\ | ||||
|   --name=virDomainWatchdogDefFree		\ | ||||
|   --name=virFileDirectFdFree			\ | ||||
|   --name=virHashFree				\ | ||||
|   --name=virInterfaceDefFree			\ | ||||
|   --name=virInterfaceIpDefFree			\ | ||||
|   --name=virInterfaceObjFree			\ | ||||
|   --name=virInterfaceProtocolDefFree		\ | ||||
|   --name=virJSONValueFree			\ | ||||
|   --name=virLastErrFreeData			\ | ||||
|   --name=virNetMessageFree                      \ | ||||
|   --name=virNetClientFree                       \ | ||||
|   --name=virNetClientProgramFree                \ | ||||
|   --name=virNetClientStreamFree                 \ | ||||
|   --name=virNetServerFree                       \ | ||||
|   --name=virNetServerClientFree                 \ | ||||
|   --name=virNetServerMDNSFree                   \ | ||||
|   --name=virNetServerMDNSEntryFree              \ | ||||
|   --name=virNetServerMDNSGroupFree              \ | ||||
|   --name=virNetServerProgramFree                \ | ||||
|   --name=virNetServerServiceFree                \ | ||||
|   --name=virNetSocketFree                       \ | ||||
|   --name=virNetSASLContextFree                  \ | ||||
|   --name=virNetSASLSessionFree                  \ | ||||
|   --name=virNetTLSSessionFree                   \ | ||||
|   --name=virNWFilterDefFree			\ | ||||
|   --name=virNWFilterEntryFree			\ | ||||
|   --name=virNWFilterHashTableFree		\ | ||||
|   --name=virNWFilterIPAddrLearnReqFree		\ | ||||
|   --name=virNWFilterIncludeDefFree		\ | ||||
|   --name=virNWFilterObjFree			\ | ||||
|   --name=virNWFilterRuleDefFree			\ | ||||
|   --name=virNWFilterRuleInstFree		\ | ||||
|   --name=virNetworkDefFree			\ | ||||
|   --name=virNetworkObjFree			\ | ||||
|   --name=virNodeDeviceDefFree			\ | ||||
|   --name=virNodeDeviceObjFree			\ | ||||
|   --name=virSecretDefFree			\ | ||||
|   --name=virStorageEncryptionFree		\ | ||||
|   --name=virStorageEncryptionSecretFree		\ | ||||
|   --name=virStorageFileFreeMetadata		\ | ||||
|   --name=virStoragePoolDefFree			\ | ||||
|   --name=virStoragePoolObjFree			\ | ||||
|   --name=virStoragePoolSourceFree		\ | ||||
|   --name=virStorageVolDefFree			\ | ||||
|   --name=virThreadPoolFree			\ | ||||
|   --name=xmlBufferFree				\ | ||||
|   --name=xmlFree				\ | ||||
|   --name=xmlFreeDoc				\ | ||||
|   --name=xmlXPathFreeContext			\ | ||||
|   --name=xmlXPathFreeObject | ||||
|  | ||||
| # The following template was generated by this command: | ||||
| # make ID && aid free|grep '^vi'|sed 's/ .*//;s/^/#   /' | ||||
| # N virBufferFreeAndReset | ||||
| # y virCPUDefFree | ||||
| # y virCapabilitiesFree | ||||
| # y virCapabilitiesFreeGuest | ||||
| # y virCapabilitiesFreeGuestDomain | ||||
| # y virCapabilitiesFreeGuestFeature | ||||
| # y virCapabilitiesFreeGuestMachine | ||||
| # y virCapabilitiesFreeHostNUMACell | ||||
| # y virCapabilitiesFreeMachines | ||||
| # N virCapabilitiesFreeNUMAInfo FIXME | ||||
| # y virCgroupFree | ||||
| # N virConfFree               (diagnoses the "error") | ||||
| # y virConfFreeList | ||||
| # y virConfFreeValue | ||||
| # y virDomainChrDefFree | ||||
| # y virDomainControllerDefFree | ||||
| # y virDomainDefFree | ||||
| # y virDomainDeviceDefFree | ||||
| # y virDomainDiskDefFree | ||||
| # y virDomainEventCallbackListFree | ||||
| # y virDomainEventFree | ||||
| # y virDomainEventQueueFree | ||||
| # y virDomainFSDefFree | ||||
| # n virDomainFree | ||||
| # n virDomainFreeName (can't fix -- returns int) | ||||
| # y virDomainGraphicsDefFree | ||||
| # y virDomainHostdevDefFree | ||||
| # y virDomainInputDefFree | ||||
| # y virDomainNetDefFree | ||||
| # y virDomainObjFree | ||||
| # y virDomainSnapshotDefFree | ||||
| # n virDomainSnapshotFree (returns int) | ||||
| # n virDomainSnapshotFreeName (returns int) | ||||
| # y virDomainSnapshotObjFree | ||||
| # y virDomainSoundDefFree | ||||
| # y virDomainVideoDefFree | ||||
| # y virDomainWatchdogDefFree | ||||
| # n virDrvNodeGetCellsFreeMemory (returns int) | ||||
| # n virDrvNodeGetFreeMemory (returns long long) | ||||
| # n virFree - dereferences param | ||||
| # n virFreeError | ||||
| # n virHashFree (takes 2 args) | ||||
| # y virInterfaceDefFree | ||||
| # n virInterfaceFree (returns int) | ||||
| # n virInterfaceFreeName | ||||
| # y virInterfaceIpDefFree | ||||
| # y virInterfaceObjFree | ||||
| # n virInterfaceObjListFree | ||||
| # y virInterfaceProtocolDefFree | ||||
| # y virJSONValueFree | ||||
| # y virLastErrFreeData | ||||
| # y virNWFilterDefFree | ||||
| # y virNWFilterEntryFree | ||||
| # n virNWFilterFree (returns int) | ||||
| # y virNWFilterHashTableFree | ||||
| # y virNWFilterIPAddrLearnReqFree | ||||
| # y virNWFilterIncludeDefFree | ||||
| # n virNWFilterFreeName (returns int) | ||||
| # y virNWFilterObjFree | ||||
| # n virNWFilterObjListFree FIXME | ||||
| # y virNWFilterRuleDefFree | ||||
| # n virNWFilterRuleFreeInstanceData (typedef) | ||||
| # y virNWFilterRuleInstFree | ||||
| # y virNetworkDefFree | ||||
| # n virNetworkFree (returns int) | ||||
| # n virNetworkFreeName (returns int) | ||||
| # y virNetworkObjFree | ||||
| # n virNetworkObjListFree FIXME | ||||
| # n virNodeDevCapsDefFree FIXME | ||||
| # y virNodeDeviceDefFree | ||||
| # n virNodeDeviceFree (returns int) | ||||
| # y virNodeDeviceObjFree | ||||
| # n virNodeDeviceObjListFree FIXME | ||||
| # n virNodeGetCellsFreeMemory (returns int) | ||||
| # n virNodeGetFreeMemory (returns non-void) | ||||
| # y virSecretDefFree | ||||
| # n virSecretFree (returns non-void) | ||||
| # n virSecretFreeName (2 args) | ||||
| # n virSecurityLabelDefFree FIXME | ||||
| # n virStorageBackendDiskMakeFreeExtent (returns non-void) | ||||
| # y virStorageEncryptionFree | ||||
| # y virStorageEncryptionSecretFree | ||||
| # n virStorageFreeType (enum) | ||||
| # y virStoragePoolDefFree | ||||
| # n virStoragePoolFree (returns non-void) | ||||
| # n virStoragePoolFreeName (returns non-void) | ||||
| # y virStoragePoolObjFree | ||||
| # n virStoragePoolObjListFree FIXME | ||||
| # y virStoragePoolSourceFree | ||||
| # y virStorageVolDefFree | ||||
| # n virStorageVolFree (returns non-void) | ||||
| # n virStorageVolFreeName (returns non-void) | ||||
| # n virStreamFree | ||||
|  | ||||
| # Avoid uses of write(2).  Either switch to streams (fwrite), or use | ||||
| # the safewrite wrapper. | ||||
| sc_avoid_write: | ||||
| 	@prohibit='\<write *\('						\ | ||||
| 	in_vc_files='\.c$$'						\ | ||||
| 	halt='consider using safewrite instead of write'		\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # In debug statements, print flags as bitmask and mode_t as octal. | ||||
| sc_flags_debug: | ||||
| 	@prohibit='\<mode=%[0-9.]*[diux]'				\ | ||||
| 	halt='use %o to debug mode_t values'				\ | ||||
| 	  $(_sc_search_regexp) | ||||
| 	@prohibit='[Ff]lags=%[0-9.]*l*[diou]'				\ | ||||
| 	halt='use %x to debug flag values'				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Prefer 'unsigned int flags', along with checks for unknown flags. | ||||
| # For historical reasons, we are stuck with 'unsigned long flags' in | ||||
| # migration, so check for those known 4 instances and no more in public | ||||
| # API.  Also check that no flags are marked unused, and 'unsigned' should | ||||
| # appear before any declaration of a flags variable (achieved by | ||||
| # prohibiting the word prior to the type from ending in anything other | ||||
| # than d).  The existence of long long, and of documentation about | ||||
| # flags, makes the regex in the third test slightly harder. | ||||
| sc_flags_usage: | ||||
| 	@test "$$(cat $(srcdir)/include/libvirt/libvirt.h.in		\ | ||||
| 	    $(srcdir)/include/libvirt/virterror.h			\ | ||||
| 	    $(srcdir)/include/libvirt/libvirt-qemu.h			\ | ||||
| 	  | grep -c '\(long\|unsigned\) flags')" != 4 &&		\ | ||||
| 	  { echo '$(ME): new API should use "unsigned int flags"' 1>&2;	\ | ||||
| 	    exit 1; } || : | ||||
| 	@prohibit=' flags ''ATTRIBUTE_UNUSED'				\ | ||||
| 	halt='flags should be checked with virCheckFlags'		\ | ||||
| 	  $(_sc_search_regexp) | ||||
| 	@prohibit='^[^@]*([^d] (int|long long)|[^dg] long) flags[;,)]'	\ | ||||
| 	halt='flags should be unsigned'					\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Avoid functions that should only be called via macro counterparts. | ||||
| sc_prohibit_internal_functions: | ||||
| 	@prohibit='vir(Free|AllocN?|ReallocN|File(Close|Fclose|Fdopen)) *\(' \ | ||||
| 	halt='use VIR_ macros instead of internal functions'		\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Avoid functions that can lead to double-close bugs. | ||||
| sc_prohibit_close: | ||||
| 	@prohibit='([^>.]|^)\<[fp]?close *\('				\ | ||||
| 	halt='use VIR_{FORCE_}[F]CLOSE instead of [f]close'		\ | ||||
| 	  $(_sc_search_regexp) | ||||
| 	@prohibit='\<fdopen *\('					\ | ||||
| 	halt='use VIR_FDOPEN instead of fdopen'				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Prefer virCommand for all child processes. | ||||
| sc_prohibit_fork_wrappers: | ||||
| 	@prohibit='= *\<(fork|popen|system) *\('			\ | ||||
| 	halt='use virCommand for child processes'			\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # access with X_OK accepts directories, but we can't exec() those. | ||||
| # access with F_OK or R_OK is okay, though. | ||||
| sc_prohibit_access_xok: | ||||
| 	@prohibit='access''(at)? *\(.*X_OK'				\ | ||||
| 	halt='use virFileIsExecutable instead of access''(,X_OK)'	\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Similar to the gnulib maint.mk rule for sc_prohibit_strcmp | ||||
| # Use STREQLEN or STRPREFIX rather than comparing strncmp == 0, or != 0. | ||||
| sc_prohibit_strncmp: | ||||
| 	@grep -nE '! *str''ncmp *\(|\<str''ncmp *\(.+\) *[!=]='		\ | ||||
| 	    $$($(VC_LIST_EXCEPT))					\ | ||||
| 	  | grep -vE ':# *define STR(N?EQLEN|PREFIX)\(' &&		\ | ||||
| 	  { echo '$(ME): use STREQLEN or STRPREFIX instead of str''ncmp' \ | ||||
| 		1>&2; exit 1; } || : | ||||
|  | ||||
| # Use virAsprintf rather than as'printf since *strp is undefined on error. | ||||
| sc_prohibit_asprintf: | ||||
| 	@prohibit='\<v?a[s]printf\>'					\ | ||||
| 	halt='use virAsprintf, not as'printf				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Prefer virSetUIDGID. | ||||
| sc_prohibit_setuid: | ||||
| 	@prohibit='\<set(re)?[ug]id\> *\('				\ | ||||
| 	halt='use virSetUIDGID, not raw set*id'				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Use snprintf rather than s'printf, even if buffer is provably large enough, | ||||
| # since gnulib has more guarantees for snprintf portability | ||||
| sc_prohibit_sprintf: | ||||
| 	@prohibit='\<[s]printf\>'					\ | ||||
| 	halt='use snprintf, not s'printf				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| sc_prohibit_strncpy: | ||||
| 	@prohibit='strncpy *\('						\ | ||||
| 	halt='use virStrncpy, not strncpy'				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| sc_prohibit_readlink: | ||||
| 	@prohibit='readlink *\('					\ | ||||
| 	halt='use virFileResolveLink, not readlink'			\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| sc_prohibit_gethostname: | ||||
| 	@prohibit='gethostname *\('					\ | ||||
| 	halt='use virGetHostname, not gethostname'			\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| sc_prohibit_gettext_noop: | ||||
| 	@prohibit='gettext_noop *\('					\ | ||||
| 	halt='use N_, not gettext_noop'					\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| sc_prohibit_VIR_ERR_NO_MEMORY: | ||||
| 	@prohibit='\<V''IR_ERR_NO_MEMORY\>'				\ | ||||
| 	halt='use virReportOOMError, not V'IR_ERR_NO_MEMORY		\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Use a subshell for each function, to give the optimal warning message. | ||||
| include $(srcdir)/Makefile.nonreentrant | ||||
| sc_prohibit_nonreentrant: | ||||
| 	@fail=0 ; \ | ||||
| 	for i in $(NON_REENTRANT) ; \ | ||||
| 	do \ | ||||
| 	    (prohibit="\\<$$i *\\("					\ | ||||
| 	     halt="use $${i}_r, not $$i"				\ | ||||
| 	     $(_sc_search_regexp)					\ | ||||
| 	    ) || fail=1;						\ | ||||
| 	done ; \ | ||||
| 	exit $$fail | ||||
|  | ||||
| # Prohibit the inclusion of <ctype.h>. | ||||
| sc_prohibit_ctype_h: | ||||
| 	@prohibit='^# *include  *<ctype\.h>'				\ | ||||
| 	halt="don't use ctype.h; instead, use c-ctype.h"		\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Ensure that no C source file, docs, or rng schema uses TABs for | ||||
| # indentation.  Also match *.h.in files, to get libvirt.h.in.  Exclude | ||||
| # files in gnulib, since they're imported. | ||||
| space_indent_files=(\.(rng|s?[ch](\.in)?|html.in|py)|(daemon|tools)/.*\.in) | ||||
| sc_TAB_in_indentation: | ||||
| 	@prohibit='^ *	'						\ | ||||
| 	in_vc_files='$(space_indent_files)$$'				\ | ||||
| 	halt='indent with space, not TAB, in C, sh, html, py, and RNG schemas' \ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| ctype_re = isalnum|isalpha|isascii|isblank|iscntrl|isdigit|isgraph|islower\ | ||||
| |isprint|ispunct|isspace|isupper|isxdigit|tolower|toupper | ||||
|  | ||||
| sc_avoid_ctype_macros: | ||||
| 	@prohibit='\b($(ctype_re)) *\('					\ | ||||
| 	halt="don't use ctype macros (use c-ctype.h)"			\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| sc_avoid_strcase: | ||||
| 	@prohibit='\bstrn?case(cmp|str) *\('				\ | ||||
| 	halt="don't use raw strcase functions (use c-strcase instead)"	\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| sc_prohibit_virBufferAdd_with_string_literal: | ||||
| 	@prohibit='\<virBufferAdd *\([^,]+, *"[^"]'			\ | ||||
| 	halt='use virBufferAddLit, not virBufferAdd, with a string literal' \ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Not only do they fail to deal well with ipv6, but the gethostby* | ||||
| # functions are also not thread-safe. | ||||
| sc_prohibit_gethostby: | ||||
| 	@prohibit='\<gethostby(addr|name2?) *\('			\ | ||||
| 	halt='use getaddrinfo, not gethostby*'				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # raw xmlGetProp requires some nasty casts | ||||
| sc_prohibit_xmlGetProp: | ||||
| 	@prohibit='\<xmlGetProp *\('					\ | ||||
| 	halt='use virXMLPropString, not xmlGetProp'			\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # ATTRIBUTE_UNUSED should only be applied in implementations, not | ||||
| # header declarations | ||||
| sc_avoid_attribute_unused_in_header: | ||||
| 	@prohibit='^[^#]*ATTRIBUTE_UNUSED([^:]|$$)'			\ | ||||
| 	in_vc_files='\.h$$'						\ | ||||
| 	halt='use ATTRIBUTE_UNUSED in .c rather than .h files'		\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Many of the function names below came from this filter: | ||||
| # git grep -B2 '\<_('|grep -E '\.c- *[[:alpha:]_][[:alnum:]_]* ?\(.*[,;]$' \ | ||||
| # |sed 's/.*\.c-  *//'|perl -pe 's/ ?\(.*//'|sort -u \ | ||||
| # |grep -vE '^(qsort|if|close|assert|fputc|free|N_|vir.*GetName|.*Unlock|virNodeListDevices|virHashRemoveEntry|freeaddrinfo|.*[fF]ree|xdrmem_create|xmlXPathFreeObject|virUUIDFormat|openvzSetProgramSentinal|polkit_action_unref)$' | ||||
|  | ||||
| msg_gen_function = | ||||
| msg_gen_function += ESX_ERROR | ||||
| msg_gen_function += ESX_VI_ERROR | ||||
| msg_gen_function += HYPERV_ERROR | ||||
| msg_gen_function += PHYP_ERROR | ||||
| msg_gen_function += VIR_ERROR | ||||
| msg_gen_function += VMX_ERROR | ||||
| msg_gen_function += XENXS_ERROR | ||||
| msg_gen_function += eventReportError | ||||
| msg_gen_function += ifaceError | ||||
| msg_gen_function += interfaceReportError | ||||
| msg_gen_function += iptablesError | ||||
| msg_gen_function += lxcError | ||||
| msg_gen_function += libxlError | ||||
| msg_gen_function += macvtapError | ||||
| msg_gen_function += networkReportError | ||||
| msg_gen_function += nodeReportError | ||||
| msg_gen_function += openvzError | ||||
| msg_gen_function += pciReportError | ||||
| msg_gen_function += qemuReportError | ||||
| msg_gen_function += qemudDispatchClientFailure | ||||
| msg_gen_function += regerror | ||||
| msg_gen_function += remoteError | ||||
| msg_gen_function += remoteDispatchFormatError | ||||
| msg_gen_function += statsError | ||||
| msg_gen_function += streamsReportError | ||||
| msg_gen_function += usbReportError | ||||
| msg_gen_function += umlReportError | ||||
| msg_gen_function += vah_error | ||||
| msg_gen_function += vah_warning | ||||
| msg_gen_function += vboxError | ||||
| msg_gen_function += virCommandError | ||||
| msg_gen_function += virConfError | ||||
| msg_gen_function += virCPUReportError | ||||
| msg_gen_function += virEventError | ||||
| msg_gen_function += virDomainReportError | ||||
| msg_gen_function += virGenericReportError | ||||
| msg_gen_function += virHashError | ||||
| msg_gen_function += virHookReportError | ||||
| msg_gen_function += virInterfaceReportError | ||||
| msg_gen_function += virJSONError | ||||
| msg_gen_function += virLibConnError | ||||
| msg_gen_function += virLibDomainError | ||||
| msg_gen_function += virLibDomainSnapshotError | ||||
| msg_gen_function += virLibInterfaceError | ||||
| msg_gen_function += virLibNetworkError | ||||
| msg_gen_function += virLibNodeDeviceError | ||||
| msg_gen_function += virLibNWFilterError | ||||
| msg_gen_function += virLibSecretError | ||||
| msg_gen_function += virLibStoragePoolError | ||||
| msg_gen_function += virLibStorageVolError | ||||
| msg_gen_function += virNetworkReportError | ||||
| msg_gen_function += virNodeDeviceReportError | ||||
| msg_gen_function += virNWFilterReportError | ||||
| msg_gen_function += virRaiseError | ||||
| msg_gen_function += virReportErrorHelper | ||||
| msg_gen_function += virReportSystemError | ||||
| msg_gen_function += virSecretReportError | ||||
| msg_gen_function += virSecurityReportError | ||||
| msg_gen_function += virSexprError | ||||
| msg_gen_function += virSmbiosReportError | ||||
| msg_gen_function += virSocketError | ||||
| msg_gen_function += virStatsError | ||||
| msg_gen_function += virStorageReportError | ||||
| msg_gen_function += virUtilError | ||||
| msg_gen_function += virXMLError | ||||
| msg_gen_function += virXenInotifyError | ||||
| msg_gen_function += virXenStoreError | ||||
| msg_gen_function += virXendError | ||||
| msg_gen_function += vmwareError | ||||
| msg_gen_function += xenapiSessionErrorHandler | ||||
| msg_gen_function += xenUnifiedError | ||||
| msg_gen_function += xenXMError | ||||
|  | ||||
| # Uncomment the following and run "make syntax-check" to see diagnostics | ||||
| # that are not yet marked for translation, but that need to be rewritten | ||||
| # so that they are translatable. | ||||
| # msg_gen_function += fprintf | ||||
| # msg_gen_function += testError | ||||
| # msg_gen_function += virXenError | ||||
| # msg_gen_function += vshPrint | ||||
| # msg_gen_function += vshError | ||||
|  | ||||
| func_or := $(shell printf '$(msg_gen_function)'|tr -s '[[:space:]]' '|') | ||||
| func_re := ($(func_or)) | ||||
|  | ||||
| # Look for diagnostics that aren't marked for translation. | ||||
| # This won't find any for which error's format string is on a separate line. | ||||
| # The sed filters eliminate false-positives like these: | ||||
| #    _("...: " | ||||
| #    "%s", _("no storage vol w..." | ||||
| sc_libvirt_unmarked_diagnostics: | ||||
| 	@grep -nE							\ | ||||
| 	    '\<$(func_re) *\([^"]*"[^"]*[a-z]{3}' $$($(VC_LIST_EXCEPT))	\ | ||||
| 	  | grep -v '_''(' &&						\ | ||||
| 	  { echo '$(ME): found unmarked diagnostic(s)' 1>&2;		\ | ||||
| 	    exit 1; } || : | ||||
| 	@{ grep     -nE '\<$(func_re) *\(.*;$$' $$($(VC_LIST_EXCEPT));   \ | ||||
| 	   grep -A1 -nE '\<$(func_re) *\(.*,$$' $$($(VC_LIST_EXCEPT)); } \ | ||||
| 	   | sed 's/_("[^"][^"]*"//;s/[	 ]"%s"//'			\ | ||||
| 	   | grep '[	 ]"' &&						\ | ||||
| 	  { echo '$(ME): found unmarked diagnostic(s)' 1>&2;		\ | ||||
| 	    exit 1; } || : | ||||
|  | ||||
| # Like the above, but prohibit a newline at the end of a diagnostic. | ||||
| # This is subject to false positives partly because it naively looks for | ||||
| # `\n"', which may not be the end of the string, and also because it takes | ||||
| # two lines of context (the -A2) after the line with the function name. | ||||
| # FIXME: this rule might benefit from a separate function list, in case | ||||
| # there are functions to which this one applies but that do not get marked | ||||
| # diagnostics. | ||||
| sc_prohibit_newline_at_end_of_diagnostic: | ||||
| 	@grep -A2 -nE							\ | ||||
| 	    '\<$(func_re) *\(' $$($(VC_LIST_EXCEPT))			\ | ||||
| 	    | grep '\\n"'						\ | ||||
| 	  && { echo '$(ME): newline at end of message(s)' 1>&2;		\ | ||||
| 	    exit 1; } || : | ||||
|  | ||||
| # Enforce recommended preprocessor indentation style. | ||||
| sc_preprocessor_indentation: | ||||
| 	@if cppi --version >/dev/null 2>&1; then			\ | ||||
| 	  $(VC_LIST_EXCEPT) | grep '\.[ch]$$' | xargs cppi -a -c	\ | ||||
| 	    || { echo '$(ME): incorrect preprocessor indentation' 1>&2;	\ | ||||
| 		exit 1; };						\ | ||||
| 	else								\ | ||||
| 	  echo '$(ME): skipping test $@: cppi not installed' 1>&2;	\ | ||||
| 	fi | ||||
|  | ||||
| sc_copyright_format: | ||||
| 	@require='Copyright .*Red 'Hat', Inc\.'				\ | ||||
| 	containing='Copyright .*Red 'Hat				\ | ||||
| 	halt='Red Hat copyright is missing Inc.'			\ | ||||
| 	  $(_sc_search_regexp) | ||||
| 	@prohibit='Copyright [^(].*Red 'Hat				\ | ||||
| 	halt='consistently use (C) in Red Hat copyright'		\ | ||||
| 	  $(_sc_search_regexp) | ||||
| 	@prohibit='\<Red''Hat\>'					\ | ||||
| 	halt='spell Red Hat as two words'				\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # Some functions/macros produce messages intended solely for developers | ||||
| # and maintainers.  Do not mark them for translation. | ||||
| sc_prohibit_gettext_markup: | ||||
| 	@prohibit='\<VIR_(WARN|INFO|DEBUG) *\(_\('			\ | ||||
| 	halt='do not mark these strings for translation'		\ | ||||
| 	  $(_sc_search_regexp) | ||||
|  | ||||
| # We don't use this feature of maint.mk. | ||||
| prev_version_file = /dev/null | ||||
|  | ||||
| ifeq (0,$(MAKELEVEL)) | ||||
|   _curr_status = .git-module-status | ||||
|   # The sed filter accommodates those who check out on a commit from which | ||||
|   # no tag is reachable.  In that case, git submodule status prints a "-" | ||||
|   # in column 1 and does not print a "git describe"-style string after the | ||||
|   # submodule name.  Contrast these: | ||||
|   # -b653eda3ac4864de205419d9f41eec267cb89eeb .gnulib | ||||
|   #  b653eda3ac4864de205419d9f41eec267cb89eeb .gnulib (v0.0-2286-gb653eda) | ||||
|   # $ cat .git-module-status | ||||
|   # b653eda3ac4864de205419d9f41eec267cb89eeb | ||||
|   _submodule_hash = sed 's/^[ +-]//;s/ .*//' | ||||
|   _update_required := $(shell						\ | ||||
|       cd '$(srcdir)';							\ | ||||
|       test -d .git || { echo 0; exit; };				\ | ||||
|       test -f po/Makevars || { echo 1; exit; };				\ | ||||
|       actual=$$(git submodule status | $(_submodule_hash);		\ | ||||
| 		git hash-object bootstrap.conf;				\ | ||||
| 		git diff .gnulib);					\ | ||||
|       stamp="$$($(_submodule_hash) $(_curr_status) 2>/dev/null)";	\ | ||||
|       test "$$stamp" = "$$actual"; echo $$?) | ||||
|   _clean_requested = $(filter %clean,$(MAKECMDGOALS)) | ||||
|   ifeq (1,$(_update_required)$(_clean_requested)) | ||||
|     $(info INFO: gnulib update required; running ./autogen.sh first) | ||||
| Makefile: _autogen | ||||
|   endif | ||||
| endif | ||||
|  | ||||
| # Give credit where due: | ||||
| # Ensure that each commit author email address (possibly mapped via | ||||
| # git log's .mailmap) appears in our AUTHORS file. | ||||
| sc_check_author_list: | ||||
| 	@fail=0;							\ | ||||
| 	for i in $$(git log --pretty=format:%aE%n|sort -u|grep -v '^$$'); do \ | ||||
| 	  sanitized=$$(echo "$$i"|LC_ALL=C sed 's/\([^a-zA-Z0-9_@-]\)/\\\1/g'); \ | ||||
| 	  grep -iq "<$$sanitized>" $(srcdir)/AUTHORS			\ | ||||
| 	    || { printf '%s\n' "$$i" >&2; fail=1; };			\ | ||||
| 	done;								\ | ||||
| 	test $$fail = 1							\ | ||||
| 	  && echo '$(ME): committer(s) not listed in AUTHORS' >&2;	\ | ||||
| 	test $$fail = 0 | ||||
|  | ||||
| # It is necessary to call autogen any time gnulib changes.  Autogen | ||||
| # reruns configure, then we regenerate all Makefiles at once. | ||||
| .PHONY: _autogen | ||||
| _autogen: | ||||
| 	$(srcdir)/autogen.sh | ||||
| 	./config.status | ||||
|  | ||||
| # regenerate HACKING as part of the syntax-check | ||||
| syntax-check: $(top_srcdir)/HACKING | ||||
|  | ||||
| # sc_po_check can fail if generated files are not built first | ||||
| sc_po_check: \ | ||||
| 		$(srcdir)/daemon/remote_dispatch.h \ | ||||
| 		$(srcdir)/daemon/qemu_dispatch.h \ | ||||
| 		$(srcdir)/src/remote/remote_client_bodies.h | ||||
| $(srcdir)/daemon/remote_dispatch.h: $(srcdir)/src/remote/remote_protocol.x | ||||
| 	$(MAKE) -C daemon remote_dispatch.h | ||||
| $(srcdir)/daemon/qemu_dispatch.h: $(srcdir)/src/remote/qemu_protocol.x | ||||
| 	$(MAKE) -C daemon qemu_dispatch.h | ||||
| $(srcdir)/src/remote/remote_client_bodies.h: $(srcdir)/src/remote/remote_protocol.x | ||||
| 	$(MAKE) -C src remote/remote_client_bodies.h | ||||
|  | ||||
| # List all syntax-check exemptions: | ||||
| exclude_file_name_regexp--sc_avoid_strcase = ^tools/virsh\.c$$ | ||||
|  | ||||
| _src1=libvirt|fdstream|qemu/qemu_monitor|util/(command|util)|xen/xend_internal|rpc/virnetsocket | ||||
| exclude_file_name_regexp--sc_avoid_write = \ | ||||
|   ^(src/($(_src1))|daemon/libvirtd|tools/console|tests/(shunload|virnettlscontext)test)\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_bindtextdomain = ^(tests|examples)/ | ||||
|  | ||||
| exclude_file_name_regexp--sc_flags_usage = ^docs/ | ||||
|  | ||||
| exclude_file_name_regexp--sc_libvirt_unmarked_diagnostics = \ | ||||
|   ^src/rpc/gendispatch\.pl$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_po_check = ^(docs/|src/rpc/gendispatch\.pl$$) | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_VIR_ERR_NO_MEMORY = \ | ||||
|   ^(include/libvirt/virterror\.h|daemon/dispatch\.c|src/util/virterror\.c)$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_access_xok = ^src/util/util\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \ | ||||
|   ^python/(libvirt-(qemu-)?override|typewrappers)\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_asprintf = \ | ||||
|   ^(bootstrap.conf$$|src/util/util\.c$$|examples/domain-events/events-c/event-test\.c$$) | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_close = \ | ||||
|   (\.p[yl]$$|^docs/|^(src/util/virfile\.c|src/libvirt\.c)$$) | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_empty_lines_at_EOF = \ | ||||
|   (^tests/qemuhelpdata/|\.(gif|ico|png)$$) | ||||
|  | ||||
| _src2=src/(util/command|libvirt|lxc/lxc_controller) | ||||
| exclude_file_name_regexp--sc_prohibit_fork_wrappers = \ | ||||
|   (^($(_src2)|tests/testutils|daemon/libvirtd)\.c$$) | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_gethostname = ^src/util/util\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_internal_functions = \ | ||||
|   ^src/(util/(memory|util|virfile)\.[hc]|esx/esx_vi\.c)$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_newline_at_end_of_diagnostic = \ | ||||
|   ^src/rpc/gendispatch\.pl$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_nonreentrant = \ | ||||
|   ^((po|tests)/|docs/.*py$$|tools/(virsh|console)\.c$$) | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_readlink = ^src/util/util\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_setuid = ^src/util/util\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_sprintf = ^docs/hacking\.html\.in$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_strncpy = \ | ||||
|   ^(src/util/util|tools/virsh)\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_prohibit_xmlGetProp = ^src/util/xml\.c$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_require_config_h = ^examples/ | ||||
|  | ||||
| exclude_file_name_regexp--sc_require_config_h_first = ^examples/ | ||||
|  | ||||
| exclude_file_name_regexp--sc_trailing_blank = \.(fig|gif|ico|png)$$ | ||||
|  | ||||
| exclude_file_name_regexp--sc_unmarked_diagnostics = \ | ||||
|   ^(docs/apibuild.py|tests/virt-aa-helper-test)$$ | ||||
							
								
								
									
										2690
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										2690
									
								
								configure.ac
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										14
									
								
								daemon/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								daemon/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,14 +0,0 @@ | ||||
| *.la | ||||
| *.lo | ||||
| .deps | ||||
| .libs | ||||
| Makefile | ||||
| Makefile.in | ||||
| libvirt_qemud | ||||
| libvirtd | ||||
| libvirtd.init | ||||
| libvirtd*.logrotate | ||||
| libvirtd.8 | ||||
| libvirtd.8.in | ||||
| libvirtd.pod | ||||
| probes.h | ||||
| @@ -1,326 +0,0 @@ | ||||
| ## Process this file with automake to produce Makefile.in | ||||
|  | ||||
| ## Copyright (C) 2005-2011 Red Hat, Inc. | ||||
| ## See COPYING.LIB for the License of this software | ||||
|  | ||||
| INCLUDES = \ | ||||
| 	-I$(top_srcdir)/gnulib/lib -I../gnulib/lib \ | ||||
| 	-I$(top_srcdir)/include -I$(top_builddir)/include \ | ||||
| 	-I$(top_srcdir)/src \ | ||||
| 	-I$(top_srcdir)/src/util \ | ||||
| 	-I$(top_srcdir)/src/conf \ | ||||
| 	-I$(top_srcdir)/src/rpc \ | ||||
| 	-I$(top_srcdir)/src/remote \ | ||||
| 	$(GETTEXT_CPPFLAGS) | ||||
|  | ||||
| CLEANFILES = | ||||
|  | ||||
| DAEMON_GENERATED =					\ | ||||
| 		$(srcdir)/remote_dispatch.h		\ | ||||
| 		$(srcdir)/qemu_dispatch.h | ||||
|  | ||||
| DAEMON_SOURCES =					\ | ||||
| 		libvirtd.c libvirtd.h			\ | ||||
| 		remote.c remote.h			\ | ||||
| 		stream.c stream.h			\ | ||||
| 		../src/remote/remote_protocol.c		\ | ||||
| 		../src/remote/qemu_protocol.c		\ | ||||
| 		$(DAEMON_GENERATED) | ||||
|  | ||||
| DISTCLEANFILES = | ||||
| EXTRA_DIST =						\ | ||||
| 	remote_dispatch.h				\ | ||||
| 	qemu_dispatch.h					\ | ||||
| 	libvirtd.conf					\ | ||||
| 	libvirtd.init.in				\ | ||||
| 	libvirtd.upstart				\ | ||||
| 	libvirtd.policy-0				\ | ||||
| 	libvirtd.policy-1				\ | ||||
| 	libvirtd.sasl					\ | ||||
| 	libvirtd.sysconf				\ | ||||
| 	libvirtd.aug                                    \ | ||||
| 	libvirtd.logrotate.in                           \ | ||||
| 	libvirtd.qemu.logrotate.in                      \ | ||||
| 	libvirtd.lxc.logrotate.in                       \ | ||||
| 	libvirtd.uml.logrotate.in                       \ | ||||
| 	test_libvirtd.aug                               \ | ||||
| 	THREADS.txt					\ | ||||
| 	libvirtd.pod.in					\ | ||||
| 	libvirtd.8.in					\ | ||||
| 	libvirtd.stp					\ | ||||
| 	$(DAEMON_SOURCES) | ||||
|  | ||||
| BUILT_SOURCES = | ||||
|  | ||||
| REMOTE_PROTOCOL = $(top_srcdir)/src/remote/remote_protocol.x | ||||
| QEMU_PROTOCOL = $(top_srcdir)/src/remote/qemu_protocol.x | ||||
|  | ||||
| $(srcdir)/remote_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \ | ||||
| 		$(REMOTE_PROTOCOL) | ||||
| 	$(AM_V_GEN)perl -w $(srcdir)/../src/rpc/gendispatch.pl -b remote \ | ||||
| 	  $(REMOTE_PROTOCOL) > $@ | ||||
|  | ||||
| $(srcdir)/qemu_dispatch.h: $(srcdir)/../src/rpc/gendispatch.pl \ | ||||
| 		$(QEMU_PROTOCOL) | ||||
| 	$(AM_V_GEN)perl -w $(srcdir)/../src/rpc/gendispatch.pl -b qemu \ | ||||
| 	  $(QEMU_PROTOCOL) > $@ | ||||
|  | ||||
| if WITH_LIBVIRTD | ||||
|  | ||||
| man8_MANS = libvirtd.8 | ||||
|  | ||||
| sbin_PROGRAMS = libvirtd | ||||
|  | ||||
| confdir = $(sysconfdir)/libvirt/ | ||||
| conf_DATA = libvirtd.conf | ||||
|  | ||||
| augeasdir = $(datadir)/augeas/lenses | ||||
| augeas_DATA = libvirtd.aug | ||||
|  | ||||
| augeastestsdir = $(datadir)/augeas/lenses/tests | ||||
| augeastests_DATA = test_libvirtd.aug | ||||
|  | ||||
| libvirtd.8: $(srcdir)/libvirtd.8.in | ||||
| 	sed \ | ||||
| 	    -e 's![@]sysconfdir[@]!$(sysconfdir)!g' \ | ||||
| 	    -e 's![@]localstatedir[@]!$(localstatedir)!g' \ | ||||
| 	    -e 's![@]remote_pid_file[@]!$(REMOTE_PID_FILE)!g' \ | ||||
| 	    < $< > $@-t | ||||
| 	mv $@-t $@ | ||||
|  | ||||
| libvirtd_SOURCES = $(DAEMON_SOURCES) | ||||
|  | ||||
| #-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED=1 -D_POSIX_C_SOURCE=199506L | ||||
| libvirtd_CFLAGS = \ | ||||
| 	$(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(SASL_CFLAGS) \ | ||||
| 	$(XDR_CFLAGS) $(POLKIT_CFLAGS) \ | ||||
| 	$(WARN_CFLAGS) \ | ||||
| 	$(COVERAGE_CFLAGS) \ | ||||
| 	-DQEMUD_PID_FILE="\"$(QEMUD_PID_FILE)\"" \ | ||||
| 	-DREMOTE_PID_FILE="\"$(REMOTE_PID_FILE)\"" | ||||
|  | ||||
| libvirtd_LDFLAGS =					\ | ||||
| 	$(WARN_CFLAGS)					\ | ||||
| 	$(COVERAGE_LDFLAGS) | ||||
|  | ||||
| libvirtd_LDADD =					\ | ||||
| 	$(LIBXML_LIBS)					\ | ||||
| 	$(GNUTLS_LIBS)					\ | ||||
| 	$(SASL_LIBS)					\ | ||||
| 	$(POLKIT_LIBS) | ||||
|  | ||||
| libvirtd_LDADD += \ | ||||
| 	../src/libvirt-net-rpc-server.la \ | ||||
| 	../src/libvirt-net-rpc.la \ | ||||
| 	../src/libvirt-qemu.la | ||||
|  | ||||
| if ! WITH_DRIVER_MODULES | ||||
| if WITH_QEMU | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_qemu.la | ||||
| endif | ||||
|  | ||||
| if WITH_LXC | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_lxc.la | ||||
| endif | ||||
|  | ||||
| if WITH_LIBXL | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_libxl.la | ||||
| endif | ||||
|  | ||||
| if WITH_UML | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_uml.la | ||||
| endif | ||||
|  | ||||
| if WITH_STORAGE_DIR | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_storage.la | ||||
| endif | ||||
|  | ||||
| if WITH_NETWORK | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_network.la | ||||
| endif | ||||
|  | ||||
| if WITH_NETCF | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_interface.la | ||||
| endif | ||||
|  | ||||
| if WITH_NODE_DEVICES | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_nodedev.la | ||||
| endif | ||||
|  | ||||
| if WITH_SECRETS | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_secret.la | ||||
| endif | ||||
|  | ||||
| if WITH_NWFILTER | ||||
|     libvirtd_LDADD += ../src/libvirt_driver_nwfilter.la | ||||
| endif | ||||
| endif | ||||
|  | ||||
| libvirtd_LDADD += ../src/libvirt.la | ||||
|  | ||||
| if HAVE_POLKIT | ||||
| if HAVE_POLKIT0 | ||||
| policydir = $(datadir)/PolicyKit/policy | ||||
| policyfile = libvirtd.policy-0 | ||||
| else | ||||
| policydir = $(datadir)/polkit-1/actions | ||||
| policyfile = libvirtd.policy-1 | ||||
| endif | ||||
| endif | ||||
|  | ||||
| if WITH_DTRACE | ||||
| libvirtd_LDADD += probes.o | ||||
| nodist_libvirtd_SOURCES = probes.h | ||||
|  | ||||
| BUILT_SOURCES += probes.h | ||||
|  | ||||
| tapsetdir = $(datadir)/systemtap/tapset | ||||
| tapset_DATA = libvirtd.stp | ||||
|  | ||||
| probes.h: probes.d | ||||
| 	$(AM_V_GEN)$(DTRACE) -o $@ -h -s $< | ||||
|  | ||||
| probes.o: probes.d | ||||
| 	$(AM_V_GEN)$(DTRACE) -o $@ -G -s $< | ||||
|  | ||||
| CLEANFILES += probes.h probes.o | ||||
| endif | ||||
|  | ||||
| install-data-local: install-init install-data-sasl install-data-polkit \ | ||||
| 		    install-logrotate | ||||
| 	mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt | ||||
| 	mkdir -p $(DESTDIR)$(localstatedir)/run/libvirt | ||||
| 	mkdir -p $(DESTDIR)$(localstatedir)/lib/libvirt | ||||
|  | ||||
| uninstall-local:: uninstall-init uninstall-data-sasl uninstall-data-polkit | ||||
| 	rmdir $(DESTDIR)$(localstatedir)/log/libvirt || : | ||||
| 	rmdir $(DESTDIR)$(localstatedir)/run/libvirt || : | ||||
| 	rmdir $(DESTDIR)$(localstatedir)/lib/libvirt || : | ||||
|  | ||||
| if HAVE_POLKIT | ||||
| install-data-polkit:: install-init | ||||
| 	mkdir -p $(DESTDIR)$(policydir) | ||||
| 	$(INSTALL_DATA) $(srcdir)/$(policyfile) $(DESTDIR)$(policydir)/org.libvirt.unix.policy | ||||
| uninstall-data-polkit:: install-init | ||||
| 	rm -f $(DESTDIR)$(policydir)/org.libvirt.unix.policy | ||||
| else | ||||
| install-data-polkit:: | ||||
| uninstall-data-polkit:: | ||||
| endif | ||||
|  | ||||
| remote.c: $(DAEMON_GENERATED) | ||||
| remote.h: $(DAEMON_GENERATED) | ||||
|  | ||||
| LOGROTATE_CONFS = libvirtd.qemu.logrotate libvirtd.lxc.logrotate \ | ||||
| 		  libvirtd.uml.logrotate libvirtd.logrotate | ||||
|  | ||||
| BUILT_SOURCES += $(LOGROTATE_CONFS) | ||||
|  | ||||
| libvirtd.logrotate: libvirtd.logrotate.in | ||||
| 	sed							\ | ||||
| 	    -e 's![@]localstatedir[@]!$(localstatedir)!g'	\ | ||||
| 	    < $< > $@-t | ||||
| 	mv $@-t $@ | ||||
|  | ||||
| libvirtd.qemu.logrotate: libvirtd.qemu.logrotate.in | ||||
| 	sed							\ | ||||
| 	    -e 's![@]localstatedir[@]!$(localstatedir)!g'	\ | ||||
| 	    < $< > $@-t | ||||
| 	mv $@-t $@ | ||||
|  | ||||
| libvirtd.lxc.logrotate: libvirtd.lxc.logrotate.in | ||||
| 	$(AM_V_GEN)sed						\ | ||||
| 	    -e 's![@]localstatedir[@]!$(localstatedir)!g'	\ | ||||
| 	    < $< > $@-t &&					\ | ||||
| 	    mv $@-t $@ | ||||
|  | ||||
| libvirtd.uml.logrotate: libvirtd.uml.logrotate.in | ||||
| 	$(AM_V_GEN)sed						\ | ||||
| 	    -e 's![@]localstatedir[@]!$(localstatedir)!g'	\ | ||||
| 	    < $< > $@-t &&					\ | ||||
| 	    mv $@-t $@ | ||||
|  | ||||
| install-logrotate: $(LOGROTATE_CONFS) | ||||
| 	mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt/qemu/ | ||||
| 	mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt/lxc/ | ||||
| 	mkdir -p $(DESTDIR)$(localstatedir)/log/libvirt/uml/ | ||||
| 	mkdir -p $(DESTDIR)$(sysconfdir)/logrotate.d/ | ||||
| 	$(INSTALL_DATA) libvirtd.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd | ||||
| 	$(INSTALL_DATA) libvirtd.qemu.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.qemu | ||||
| 	$(INSTALL_DATA) libvirtd.lxc.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.lxc | ||||
| 	$(INSTALL_DATA) libvirtd.uml.logrotate $(DESTDIR)$(sysconfdir)/logrotate.d/libvirtd.uml | ||||
|  | ||||
| if LIBVIRT_INIT_SCRIPT_RED_HAT | ||||
| install-init: libvirtd.init | ||||
| 	mkdir -p $(DESTDIR)$(sysconfdir)/rc.d/init.d | ||||
| 	$(INSTALL_SCRIPT) libvirtd.init \ | ||||
| 	  $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd | ||||
| 	mkdir -p $(DESTDIR)$(sysconfdir)/sysconfig | ||||
| 	$(INSTALL_DATA) $(srcdir)/libvirtd.sysconf \ | ||||
| 	  $(DESTDIR)$(sysconfdir)/sysconfig/libvirtd | ||||
|  | ||||
| uninstall-init: | ||||
| 	rm -f $(DESTDIR)$(sysconfdir)/rc.d/init.d/libvirtd \ | ||||
| 		$(DESTDIR)$(sysconfdir)/sysconfig/libvirtd | ||||
|  | ||||
| BUILT_SOURCES += libvirtd.init | ||||
|  | ||||
| libvirtd.init: libvirtd.init.in $(top_builddir)/config.status | ||||
| 	$(AM_V_GEN)sed					\ | ||||
| 	    -e s!\@localstatedir\@!@localstatedir@!g	\ | ||||
| 	    -e s!\@sbindir\@!@sbindir@!g		\ | ||||
| 	    -e s!\@sysconfdir\@!@sysconfdir@!g		\ | ||||
| 	    < $< > $@-t &&				\ | ||||
| 	    chmod a+x $@-t &&				\ | ||||
| 	    mv $@-t $@ | ||||
|  | ||||
| check-local: | ||||
| 	$(AM_V_GEN)if test -x '$(AUGPARSE)'; then \ | ||||
| 	  '$(AUGPARSE)' -I $(srcdir) $(srcdir)/test_libvirtd.aug; \ | ||||
| 	fi | ||||
|  | ||||
| else | ||||
|  | ||||
| install-init: | ||||
| uninstall-init: | ||||
| libvirtd.init: | ||||
|  | ||||
| endif # LIBVIRT_INIT_SCRIPT_RED_HAT | ||||
|  | ||||
| # This must be added last, since functions it provides/replaces | ||||
| # are used by nearly every other library. | ||||
| libvirtd_LDADD += ../gnulib/lib/libgnu.la $(LIBSOCKET) | ||||
|  | ||||
| else # WITH_LIBVIRTD | ||||
| install-data-local: install-data-sasl | ||||
| uninstall-local:: uninstall-data-sasl | ||||
| endif # WITH_LIBVIRTD | ||||
|  | ||||
| # This is needed for 'make dist' too, so can't wrap in WITH_LIBVIRTD. | ||||
| EXTRA_DIST += probes.d libvirtd.stp | ||||
|  | ||||
| POD2MAN = pod2man -c "Virtualization Support" \ | ||||
| 			-r "$(PACKAGE)-$(VERSION)" -s 8 | ||||
|  | ||||
| $(srcdir)/libvirtd.8.in: libvirtd.pod.in | ||||
| 	$(AM_V_GEN)$(POD2MAN) $< $@ | ||||
|  | ||||
| # This is needed for clients too, so can't wrap in | ||||
| # the WITH_LIBVIRTD conditional | ||||
| if HAVE_SASL | ||||
| install-data-sasl: | ||||
| 	mkdir -p $(DESTDIR)$(sysconfdir)/sasl2/ | ||||
| 	$(INSTALL_DATA) $(srcdir)/libvirtd.sasl $(DESTDIR)$(sysconfdir)/sasl2/libvirt.conf | ||||
|  | ||||
| uninstall-data-sasl: | ||||
| 	rm -f $(DESTDIR)$(sysconfdir)/sasl2/libvirt.conf | ||||
| 	rmdir $(DESTDIR)$(sysconfdir)/sasl2/ | ||||
| else | ||||
| install-data-sasl: | ||||
| uninstall-data-sasl: | ||||
| endif | ||||
|  | ||||
|  | ||||
| CLEANFILES += $(BUILT_SOURCES) $(man8_MANS) | ||||
| CLEANFILES += *.cov *.gcov .libs/*.gcda .libs/*.gcno *.gcno *.gcda | ||||
| MAINTAINERCLEANFILES = $(srcdir)/libvirtd.8.in $(DAEMON_GENERATED) | ||||
| @@ -1,52 +0,0 @@ | ||||
|  | ||||
|      Threading in the libvirtd daemon | ||||
|      ================================ | ||||
|  | ||||
| To allow efficient processing of RPC requests, the libvirtd daemon | ||||
| makes use of threads. | ||||
|  | ||||
|  - The process leader. This is the initial thread of control | ||||
|    when the daemon starts running. It is responsible for | ||||
|    initializing all the state, and starting the event loop. | ||||
|    Once that's all done, this thread does nothing except | ||||
|    wait for the event loop to quit, thus indicating an orderly | ||||
|    shutdown is required. | ||||
|  | ||||
|  - The event loop. This thread runs the event loop, sitting | ||||
|    in poll() on all monitored file handles, and calculating | ||||
|    and dispatching any timers that may be registered. When | ||||
|    this thread quits, the entire daemon will shutdown. | ||||
|  | ||||
|  - The workers. These 'n' threads all sit around waiting to | ||||
|    process incoming RPC requests. Since RPC requests may take | ||||
|    a long time to complete, with long idle periods, there will | ||||
|    be quite a few workers running. | ||||
|  | ||||
| The use of threads obviously requires locking to ensure safety when | ||||
| accessing/changing data structures. | ||||
|  | ||||
|  - the top level lock is on 'struct qemud_server'. This must be | ||||
|    held before acquiring any other lock | ||||
|  | ||||
|  - Each 'struct qemud_client' object has a lock. The server lock | ||||
|    must be held before acquiring it. Once the client lock is acquired | ||||
|    the server lock can (optionally) be dropped. | ||||
|  | ||||
|  - The event loop has its own self-contained lock. You can ignore | ||||
|    this as a caller of virEvent APIs. | ||||
|  | ||||
|  | ||||
| The server lock is used in conjunction with a condition variable | ||||
| to pass jobs from the event loop thread to the workers. The main | ||||
| event loop thread handles I/O from the client socket, and once a | ||||
| complete RPC message has been read off the wire (and optionally | ||||
| decrypted), it will be placed onto the 'dx' job queue for the | ||||
| associated client object. The job condition will be signalled and | ||||
| a worker will wakup and process it. | ||||
|  | ||||
| The worker thread must quickly drop its locks on the server and | ||||
| client to allow the main event loop thread to continue running | ||||
| with its other work. Critically important, is that now libvirt | ||||
| API call will ever be made with the server or client locks held. | ||||
|  | ||||
| -- End | ||||
| @@ -1,88 +0,0 @@ | ||||
| (* /etc/libvirt/libvirtd.conf *) | ||||
|  | ||||
| module Libvirtd = | ||||
|    autoload xfm | ||||
|  | ||||
|    let eol   = del /[ \t]*\n/ "\n" | ||||
|    let value_sep   = del /[ \t]*=[ \t]*/  " = " | ||||
|    let indent = del /[ \t]*/ "" | ||||
|  | ||||
|    let array_sep  = del /,[ \t\n]*/ ", " | ||||
|    let array_start = del /\[[ \t\n]*/ "[ " | ||||
|    let array_end = del /\]/ "]" | ||||
|  | ||||
|    let str_val = del /\"/ "\"" . store /[^\"]*/ . del /\"/ "\"" | ||||
|    let bool_val = store /0|1/ | ||||
|    let int_val = store /[0-9]+/ | ||||
|    let str_array_element = [ seq "el" . str_val ] . del /[ \t\n]*/ "" | ||||
|    let str_array_val = counter "el" . array_start . ( str_array_element . ( array_sep . str_array_element ) * ) ? . array_end | ||||
|  | ||||
|    let str_entry       (kw:string) = [ key kw . value_sep . str_val ] | ||||
|    let bool_entry      (kw:string) = [ key kw . value_sep . bool_val ] | ||||
|    let int_entry      (kw:string) = [ key kw . value_sep . int_val ] | ||||
|    let str_array_entry (kw:string) = [ key kw . value_sep . str_array_val ] | ||||
|  | ||||
|  | ||||
|    (* Config entry grouped by function - same order as example config *) | ||||
|    let network_entry = bool_entry "listen_tls" | ||||
|                      | bool_entry "listen_tcp" | ||||
|                      | str_entry "tls_port" | ||||
|                      | str_entry "tcp_port" | ||||
|                      | str_entry "listen_addr" | ||||
|                      | bool_entry "mdns_adv" | ||||
|                      | str_entry "mdns_name" | ||||
|  | ||||
|    let sock_acl_entry = str_entry "unix_sock_group" | ||||
|                       | str_entry "unix_sock_ro_perms" | ||||
|                       | str_entry "unix_sock_rw_perms" | ||||
|                       | str_entry "unix_sock_dir" | ||||
|  | ||||
|    let authentication_entry = str_entry "auth_unix_ro" | ||||
|                             | str_entry "auth_unix_rw" | ||||
|                             | str_entry "auth_tcp" | ||||
|                             | str_entry "auth_tls" | ||||
|  | ||||
|    let certificate_entry = str_entry "key_file" | ||||
|                          | str_entry "cert_file" | ||||
|                          | str_entry "ca_file" | ||||
|                          | str_entry "crl_file" | ||||
|  | ||||
|    let authorization_entry = bool_entry "tls_no_verify_certificate" | ||||
|                            | bool_entry "tls_no_sanity_certificate" | ||||
|                            | str_array_entry "tls_allowed_dn_list" | ||||
|                            | str_array_entry "sasl_allowed_username_list" | ||||
|  | ||||
|    let processing_entry = int_entry "min_workers" | ||||
|                         | int_entry "max_workers" | ||||
|                         | int_entry "max_clients" | ||||
|                         | int_entry "max_requests" | ||||
|                         | int_entry "max_client_requests" | ||||
|                         | int_entry "prio_workers" | ||||
|  | ||||
|    let logging_entry = int_entry "log_level" | ||||
|                      | str_entry "log_filters" | ||||
|                      | str_entry "log_outputs" | ||||
|  | ||||
|    let auditing_entry = int_entry "audit_level" | ||||
|                       | bool_entry "audit_logging" | ||||
|  | ||||
|    (* Each enty in the config is one of the following three ... *) | ||||
|    let entry = network_entry | ||||
|              | sock_acl_entry | ||||
|              | authentication_entry | ||||
|              | certificate_entry | ||||
|              | authorization_entry | ||||
|              | processing_entry | ||||
|              | logging_entry | ||||
|              | auditing_entry | ||||
|    let comment = [ label "#comment" . del /#[ \t]*/ "# " .  store /([^ \t\n][^\n]*)?/ . del /\n/ "\n" ] | ||||
|    let empty = [ label "#empty" . eol ] | ||||
|  | ||||
|    let record = indent . entry . eol | ||||
|  | ||||
|    let lns = ( record | comment | empty ) * | ||||
|  | ||||
|    let filter = incl "/etc/libvirt/libvirtd.conf" | ||||
|               . Util.stdexcl | ||||
|  | ||||
|    let xfm = transform lns filter | ||||
							
								
								
									
										1601
									
								
								daemon/libvirtd.c
									
									
									
									
									
								
							
							
						
						
									
										1601
									
								
								daemon/libvirtd.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,368 +0,0 @@ | ||||
| # Master libvirt daemon configuration file | ||||
| # | ||||
| # For further information consult http://libvirt.org/format.html | ||||
| # | ||||
| # NOTE: the tests/daemon-conf regression test script requires | ||||
| # that each "PARAMETER = VALUE" line in this file have the parameter | ||||
| # name just after a leading "#". | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Network connectivity controls | ||||
| # | ||||
|  | ||||
| # Flag listening for secure TLS connections on the public TCP/IP port. | ||||
| # NB, must pass the --listen flag to the libvirtd process for this to | ||||
| # have any effect. | ||||
| # | ||||
| # It is necessary to setup a CA and issue server certificates before | ||||
| # using this capability. | ||||
| # | ||||
| # This is enabled by default, uncomment this to disable it | ||||
| #listen_tls = 0 | ||||
|  | ||||
| # Listen for unencrypted TCP connections on the public TCP/IP port. | ||||
| # NB, must pass the --listen flag to the libvirtd process for this to | ||||
| # have any effect. | ||||
| # | ||||
| # Using the TCP socket requires SASL authentication by default. Only | ||||
| # SASL mechanisms which support data encryption are allowed. This is | ||||
| # DIGEST_MD5 and GSSAPI (Kerberos5) | ||||
| # | ||||
| # This is disabled by default, uncomment this to enable it. | ||||
| #listen_tcp = 1 | ||||
|  | ||||
|  | ||||
|  | ||||
| # Override the port for accepting secure TLS connections | ||||
| # This can be a port number, or service name | ||||
| # | ||||
| #tls_port = "16514" | ||||
|  | ||||
| # Override the port for accepting insecure TCP connections | ||||
| # This can be a port number, or service name | ||||
| # | ||||
| #tcp_port = "16509" | ||||
|  | ||||
|  | ||||
| # Override the default configuration which binds to all network | ||||
| # interfaces. This can be a numeric IPv4/6 address, or hostname | ||||
| # | ||||
| #listen_addr = "192.168.0.1" | ||||
|  | ||||
|  | ||||
| # Flag toggling mDNS advertizement of the libvirt service. | ||||
| # | ||||
| # Alternatively can disable for all services on a host by | ||||
| # stopping the Avahi daemon | ||||
| # | ||||
| # This is enabled by default, uncomment this to disable it | ||||
| #mdns_adv = 0 | ||||
|  | ||||
| # Override the default mDNS advertizement name. This must be | ||||
| # unique on the immediate broadcast network. | ||||
| # | ||||
| # The default is "Virtualization Host HOSTNAME", where HOSTNAME | ||||
| # is subsituted for the short hostname of the machine (without domain) | ||||
| # | ||||
| #mdns_name = "Virtualization Host Joe Demo" | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # UNIX socket access controls | ||||
| # | ||||
|  | ||||
| # Set the UNIX domain socket group ownership. This can be used to | ||||
| # allow a 'trusted' set of users access to management capabilities | ||||
| # without becoming root. | ||||
| # | ||||
| # This is restricted to 'root' by default. | ||||
| #unix_sock_group = "libvirt" | ||||
|  | ||||
| # Set the UNIX socket permissions for the R/O socket. This is used | ||||
| # for monitoring VM status only | ||||
| # | ||||
| # Default allows any user. If setting group ownership may want to | ||||
| # restrict this to: | ||||
| #unix_sock_ro_perms = "0777" | ||||
|  | ||||
| # Set the UNIX socket permissions for the R/W socket. This is used | ||||
| # for full management of VMs | ||||
| # | ||||
| # Default allows only root. If PolicyKit is enabled on the socket, | ||||
| # the default will change to allow everyone (eg, 0777) | ||||
| # | ||||
| # If not using PolicyKit and setting group ownership for access | ||||
| # control then you may want to relax this to: | ||||
| #unix_sock_rw_perms = "0770" | ||||
|  | ||||
| # Set the name of the directory in which sockets will be found/created. | ||||
| #unix_sock_dir = "/var/run/libvirt" | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Authentication. | ||||
| # | ||||
| #  - none: do not perform auth checks. If you can connect to the | ||||
| #          socket you are allowed. This is suitable if there are | ||||
| #          restrictions on connecting to the socket (eg, UNIX | ||||
| #          socket permissions), or if there is a lower layer in | ||||
| #          the network providing auth (eg, TLS/x509 certificates) | ||||
| # | ||||
| #  - sasl: use SASL infrastructure. The actual auth scheme is then | ||||
| #          controlled from /etc/sasl2/libvirt.conf. For the TCP | ||||
| #          socket only GSSAPI & DIGEST-MD5 mechanisms will be used. | ||||
| #          For non-TCP or TLS sockets,  any scheme is allowed. | ||||
| # | ||||
| #  - polkit: use PolicyKit to authenticate. This is only suitable | ||||
| #            for use on the UNIX sockets. The default policy will | ||||
| #            require a user to supply their own password to gain | ||||
| #            full read/write access (aka sudo like), while anyone | ||||
| #            is allowed read/only access. | ||||
| # | ||||
| # Set an authentication scheme for UNIX read-only sockets | ||||
| # By default socket permissions allow anyone to connect | ||||
| # | ||||
| # To restrict monitoring of domains you may wish to enable | ||||
| # an authentication mechanism here | ||||
| #auth_unix_ro = "none" | ||||
|  | ||||
| # Set an authentication scheme for UNIX read-write sockets | ||||
| # By default socket permissions only allow root. If PolicyKit | ||||
| # support was compiled into libvirt, the default will be to | ||||
| # use 'polkit' auth. | ||||
| # | ||||
| # If the unix_sock_rw_perms are changed you may wish to enable | ||||
| # an authentication mechanism here | ||||
| #auth_unix_rw = "none" | ||||
|  | ||||
| # Change the authentication scheme for TCP sockets. | ||||
| # | ||||
| # If you don't enable SASL, then all TCP traffic is cleartext. | ||||
| # Don't do this outside of a dev/test scenario. For real world | ||||
| # use, always enable SASL and use the GSSAPI or DIGEST-MD5 | ||||
| # mechanism in /etc/sasl2/libvirt.conf | ||||
| #auth_tcp = "sasl" | ||||
|  | ||||
| # Change the authentication scheme for TLS sockets. | ||||
| # | ||||
| # TLS sockets already have encryption provided by the TLS | ||||
| # layer, and limited authentication is done by certificates | ||||
| # | ||||
| # It is possible to make use of any SASL authentication | ||||
| # mechanism as well, by using 'sasl' for this option | ||||
| #auth_tls = "none" | ||||
|  | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # TLS x509 certificate configuration | ||||
| # | ||||
|  | ||||
|  | ||||
| # Override the default server key file path | ||||
| # | ||||
| #key_file = "/etc/pki/libvirt/private/serverkey.pem" | ||||
|  | ||||
| # Override the default server certificate file path | ||||
| # | ||||
| #cert_file = "/etc/pki/libvirt/servercert.pem" | ||||
|  | ||||
| # Override the default CA certificate path | ||||
| # | ||||
| #ca_file = "/etc/pki/CA/cacert.pem" | ||||
|  | ||||
| # Specify a certificate revocation list. | ||||
| # | ||||
| # Defaults to not using a CRL, uncomment to enable it | ||||
| #crl_file = "/etc/pki/CA/crl.pem" | ||||
|  | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Authorization controls | ||||
| # | ||||
|  | ||||
|  | ||||
| # Flag to disable verification of our own server certificates | ||||
| # | ||||
| # When libvirtd starts it performs some sanity checks against | ||||
| # its own certificates. | ||||
| # | ||||
| # Default is to always run sanity checks. Uncommenting this | ||||
| # will disable sanity checks which is not a good idea | ||||
| #tls_no_sanity_certificate = 1 | ||||
|  | ||||
| # Flag to disable verification of client certificates | ||||
| # | ||||
| # Client certificate verification is the primary authentication mechanism. | ||||
| # Any client which does not present a certificate signed by the CA | ||||
| # will be rejected. | ||||
| # | ||||
| # Default is to always verify. Uncommenting this will disable | ||||
| # verification - make sure an IP whitelist is set | ||||
| #tls_no_verify_certificate = 1 | ||||
|  | ||||
|  | ||||
| # A whitelist of allowed x509  Distinguished Names | ||||
| # This list may contain wildcards such as | ||||
| # | ||||
| #    "C=GB,ST=London,L=London,O=Red Hat,CN=*" | ||||
| # | ||||
| # See the POSIX fnmatch function for the format of the wildcards. | ||||
| # | ||||
| # NB If this is an empty list, no client can connect, so comment out | ||||
| # entirely rather than using empty list to disable these checks | ||||
| # | ||||
| # By default, no DN's are checked | ||||
| #tls_allowed_dn_list = ["DN1", "DN2"] | ||||
|  | ||||
|  | ||||
| # A whitelist of allowed SASL usernames. The format for usernames | ||||
| # depends on the SASL authentication mechanism. Kerberos usernames | ||||
| # look like username@REALM | ||||
| # | ||||
| # This list may contain wildcards such as | ||||
| # | ||||
| #    "*@EXAMPLE.COM" | ||||
| # | ||||
| # See the POSIX fnmatch function for the format of the wildcards. | ||||
| # | ||||
| # NB If this is an empty list, no client can connect, so comment out | ||||
| # entirely rather than using empty list to disable these checks | ||||
| # | ||||
| # By default, no Username's are checked | ||||
| #sasl_allowed_username_list = ["joe@EXAMPLE.COM", "fred@EXAMPLE.COM" ] | ||||
|  | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Processing controls | ||||
| # | ||||
|  | ||||
| # The maximum number of concurrent client connections to allow | ||||
| # over all sockets combined. | ||||
| #max_clients = 20 | ||||
|  | ||||
|  | ||||
| # The minimum limit sets the number of workers to start up | ||||
| # initially. If the number of active clients exceeds this, | ||||
| # then more threads are spawned, upto max_workers limit. | ||||
| # Typically you'd want max_workers to equal maximum number | ||||
| # of clients allowed | ||||
| #min_workers = 5 | ||||
| #max_workers = 20 | ||||
|  | ||||
|  | ||||
| # The number of priority workers. If all workers from above | ||||
| # pool will stuck, some calls marked as high priority | ||||
| # (notably domainDestroy) can be executed in this pool. | ||||
| #prio_workers = 5 | ||||
|  | ||||
| # Total global limit on concurrent RPC calls. Should be | ||||
| # at least as large as max_workers. Beyond this, RPC requests | ||||
| # will be read into memory and queued. This directly impact | ||||
| # memory usage, currently each request requires 256 KB of | ||||
| # memory. So by default upto 5 MB of memory is used | ||||
| # | ||||
| # XXX this isn't actually enforced yet, only the per-client | ||||
| # limit is used so far | ||||
| #max_requests = 20 | ||||
|  | ||||
| # Limit on concurrent requests from a single client | ||||
| # connection. To avoid one client monopolizing the server | ||||
| # this should be a small fraction of the global max_requests | ||||
| # and max_workers parameter | ||||
| #max_client_requests = 5 | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Logging controls | ||||
| # | ||||
|  | ||||
| # Logging level: 4 errors, 3 warnings, 2 informations, 1 debug | ||||
| # basically 1 will log everything possible | ||||
| #log_level = 3 | ||||
|  | ||||
| # Logging filters: | ||||
| # A filter allows to select a different logging level for a given category | ||||
| # of logs | ||||
| # The format for a filter is: | ||||
| #    x:name | ||||
| #      where name is a match string e.g. remote or qemu | ||||
| # the x prefix is the minimal level where matching messages should be logged | ||||
| #    1: DEBUG | ||||
| #    2: INFO | ||||
| #    3: WARNING | ||||
| #    4: ERROR | ||||
| # | ||||
| # Multiple filter can be defined in a single @filters, they just need to be | ||||
| # separated by spaces. | ||||
| # | ||||
| # e.g: | ||||
| # log_filters="3:remote 4:event" | ||||
| # to only get warning or errors from the remote layer and only errors from | ||||
| # the event layer. | ||||
|  | ||||
| # Logging outputs: | ||||
| # An output is one of the places to save logging informations | ||||
| # The format for an output can be: | ||||
| #    x:stderr | ||||
| #      output goes to stderr | ||||
| #    x:syslog:name | ||||
| #      use syslog for the output and use the given name as the ident | ||||
| #    x:file:file_path | ||||
| #      output to a file, with the given filepath | ||||
| # In all case the x prefix is the minimal level, acting as a filter | ||||
| #    1: DEBUG | ||||
| #    2: INFO | ||||
| #    3: WARNING | ||||
| #    4: ERROR | ||||
| # | ||||
| # Multiple output can be defined, they just need to be separated by spaces. | ||||
| # e.g.: | ||||
| # log_outputs="3:syslog:libvirtd" | ||||
| # to log all warnings and errors to syslog under the libvirtd ident | ||||
|  | ||||
| # Log debug buffer size: default 64 | ||||
| # The daemon keeps an internal debug log buffer which will be dumped in case | ||||
| # of crash or upon receiving a SIGUSR2 signal. This setting allows to override | ||||
| # the default buffer size in kilobytes. | ||||
| # If value is 0 or less the debug log buffer is deactivated | ||||
| #log_buffer_size = 64 | ||||
|  | ||||
|  | ||||
| ################################################################## | ||||
| # | ||||
| # Auditing | ||||
| # | ||||
| # This setting allows usage of the auditing subsystem to be altered: | ||||
| # | ||||
| #   audit_level == 0  -> disable all auditing | ||||
| #   audit_level == 1  -> enable auditing, only if enabled on host (default) | ||||
| #   audit_level == 2  -> enable auditing, and exit if disabled on host | ||||
| # | ||||
| #audit_level = 2 | ||||
| # | ||||
| # If set to 1, then audit messages will also be sent | ||||
| # via libvirt logging infrastructure. Defaults to 0 | ||||
| # | ||||
| #audit_logging = 1 | ||||
|  | ||||
| ################################################################### | ||||
| # UUID of the host: | ||||
| # Provide the UUID of the host here in case the command | ||||
| # 'dmidecode -s system-uuid' does not provide a valid uuid. In case | ||||
| # 'dmidecode' does not provide a valid UUID and none is provided here, a | ||||
| # temporary UUID will be generated. | ||||
| # Keep the format of the example UUID below. UUID must not have all digits | ||||
| # be the same. | ||||
|  | ||||
| # NB This default all-zeros UUID will not work. Replace | ||||
| # it with the output of the 'uuidgen' command and then | ||||
| # uncomment this entry | ||||
| #host_uuid = "00000000-0000-0000-0000-000000000000" | ||||
| @@ -1,120 +0,0 @@ | ||||
| /* | ||||
|  * libvirtd.h: daemon data structure definitions | ||||
|  * | ||||
|  * Copyright (C) 2006-2011 Red Hat, Inc. | ||||
|  * Copyright (C) 2006 Daniel P. Berrange | ||||
|  * | ||||
|  * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA | ||||
|  * | ||||
|  * Author: Daniel P. Berrange <berrange@redhat.com> | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef QEMUD_INTERNAL_H__ | ||||
| # define QEMUD_INTERNAL_H__ | ||||
|  | ||||
| # include <config.h> | ||||
|  | ||||
| # include <rpc/types.h> | ||||
| # include <rpc/xdr.h> | ||||
| # include "remote_protocol.h" | ||||
| # include "qemu_protocol.h" | ||||
| # include "logging.h" | ||||
| # include "threads.h" | ||||
| # include "network.h" | ||||
| # if HAVE_SASL | ||||
| #  include "virnetsaslcontext.h" | ||||
| # endif | ||||
| # include "virnetserverprogram.h" | ||||
|  | ||||
| # if WITH_DTRACE | ||||
| #  ifndef LIBVIRTD_PROBES_H | ||||
| #   define LIBVIRTD_PROBES_H | ||||
| #   include "probes.h" | ||||
| #  endif /* LIBVIRTD_PROBES_H */ | ||||
|  | ||||
| /* Systemtap 1.2 headers have a bug where they cannot handle a | ||||
|  * variable declared with array type.  Work around this by casting all | ||||
|  * arguments.  This is some gross use of the preprocessor because | ||||
|  * PROBE is a var-arg macro, but it is better than the alternative of | ||||
|  * making all callers to PROBE have to be aware of the issues.  And | ||||
|  * hopefully, if we ever add a call to PROBE with other than 2 or 3 | ||||
|  * end arguments, you can figure out the pattern to extend this hack. | ||||
|  */ | ||||
| #  define VIR_COUNT_ARGS(...) VIR_ARG5(__VA_ARGS__, 4, 3, 2, 1) | ||||
| #  define VIR_ARG5(_1, _2, _3, _4, _5, ...) _5 | ||||
| #  define VIR_ADD_CAST_EXPAND(a, b, ...) VIR_ADD_CAST_PASTE(a, b, __VA_ARGS__) | ||||
| #  define VIR_ADD_CAST_PASTE(a, b, ...) a##b(__VA_ARGS__) | ||||
|  | ||||
| /* The double cast is necessary to silence gcc warnings; any pointer | ||||
|  * can safely go to intptr_t and back to void *, which collapses | ||||
|  * arrays into pointers; while any integer can be widened to intptr_t | ||||
|  * then cast to void *.  */ | ||||
| #  define VIR_ADD_CAST(a) ((void *)(intptr_t)(a)) | ||||
| #  define VIR_ADD_CAST2(a, b)                           \ | ||||
|     VIR_ADD_CAST(a), VIR_ADD_CAST(b) | ||||
| #  define VIR_ADD_CAST3(a, b, c)                        \ | ||||
|     VIR_ADD_CAST(a), VIR_ADD_CAST(b), VIR_ADD_CAST(c) | ||||
|  | ||||
| #  define VIR_ADD_CASTS(...)                                            \ | ||||
|     VIR_ADD_CAST_EXPAND(VIR_ADD_CAST, VIR_COUNT_ARGS(__VA_ARGS__),      \ | ||||
|                         __VA_ARGS__) | ||||
|  | ||||
| #  define PROBE_EXPAND(NAME, ARGS) NAME(ARGS) | ||||
| #  define PROBE(NAME, FMT, ...)                              \ | ||||
|     VIR_DEBUG_INT("trace." __FILE__ , __func__, __LINE__,    \ | ||||
|                   #NAME ": " FMT, __VA_ARGS__);              \ | ||||
|     if (LIBVIRTD_ ## NAME ## _ENABLED()) {                   \ | ||||
|         PROBE_EXPAND(LIBVIRTD_ ## NAME,                      \ | ||||
|                      VIR_ADD_CASTS(__VA_ARGS__));            \ | ||||
|     } | ||||
| # else | ||||
| #  define PROBE(NAME, FMT, ...)                              \ | ||||
|     VIR_DEBUG_INT("trace." __FILE__, __func__, __LINE__,     \ | ||||
|                   #NAME ": " FMT, __VA_ARGS__); | ||||
| # endif | ||||
|  | ||||
| typedef struct daemonClientStream daemonClientStream; | ||||
| typedef daemonClientStream *daemonClientStreamPtr; | ||||
| typedef struct daemonClientPrivate daemonClientPrivate; | ||||
| typedef daemonClientPrivate *daemonClientPrivatePtr; | ||||
|  | ||||
| /* Stores the per-client connection state */ | ||||
| struct daemonClientPrivate { | ||||
|     /* Hold while accessing any data except conn */ | ||||
|     virMutex lock; | ||||
|  | ||||
|     int domainEventCallbackID[VIR_DOMAIN_EVENT_ID_LAST]; | ||||
|  | ||||
| # if HAVE_SASL | ||||
|     virNetSASLSessionPtr sasl; | ||||
| # endif | ||||
|  | ||||
|     /* This is only valid if a remote open call has been made on this | ||||
|      * connection, otherwise it will be NULL.  Also if remote close is | ||||
|      * called, it will be set back to NULL if that succeeds. | ||||
|      */ | ||||
|     virConnectPtr conn; | ||||
|  | ||||
|     daemonClientStreamPtr streams; | ||||
| }; | ||||
|  | ||||
| # if HAVE_SASL | ||||
| extern virNetSASLContextPtr saslCtxt; | ||||
| # endif | ||||
| extern virNetServerProgramPtr remoteProgram; | ||||
| extern virNetServerProgramPtr qemuProgram; | ||||
|  | ||||
| #endif | ||||
| @@ -1,118 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| # the following is the LSB init header see | ||||
| # http://www.linux-foundation.org/spec//booksets/LSB-Core-generic/LSB-Core-generic.html#INITSCRCOMCONV | ||||
| # | ||||
| ### BEGIN INIT INFO | ||||
| # Provides: libvirtd | ||||
| # Required-Start: $network messagebus | ||||
| # Should-Start: $named | ||||
| # Should-Start: xend | ||||
| # Should-Start: hal | ||||
| # Should-Start: avahi-daemon | ||||
| # Required-Stop: $network messagebus | ||||
| # Should-Stop: $named | ||||
| # Default-Start: 3 4 5 | ||||
| # Short-Description: daemon for libvirt virtualization API | ||||
| # Description: This is a daemon for managing guest instances | ||||
| #              and libvirt virtual networks | ||||
| #              See http://libvirt.org | ||||
| ### END INIT INFO | ||||
|  | ||||
| # the following is chkconfig init header | ||||
| # | ||||
| # libvirtd:   guest and virtual network management daemon | ||||
| # | ||||
| # chkconfig: 345 97 03 | ||||
| # description:  This is a daemon for managing guest instances \ | ||||
| #               and libvirt virtual networks \ | ||||
| #               See http://libvirt.org | ||||
| # | ||||
| # processname: libvirtd | ||||
| # pidfile: @localstatedir@/run/libvirtd.pid | ||||
| # | ||||
|  | ||||
| # Source function library. | ||||
| . @sysconfdir@/rc.d/init.d/functions | ||||
|  | ||||
| SERVICE=libvirtd | ||||
| PROCESS=libvirtd | ||||
| PIDFILE=@localstatedir@/run/$SERVICE.pid | ||||
|  | ||||
| LIBVIRTD_CONFIG= | ||||
| LIBVIRTD_ARGS= | ||||
| KRB5_KTNAME=/etc/libvirt/krb5.tab | ||||
|  | ||||
| test -f @sysconfdir@/sysconfig/libvirtd && . @sysconfdir@/sysconfig/libvirtd | ||||
|  | ||||
| export QEMU_AUDIO_DRV | ||||
| export SDL_AUDIODRIVER | ||||
|  | ||||
| LIBVIRTD_CONFIG_ARGS= | ||||
| if [ -n "$LIBVIRTD_CONFIG" ] | ||||
| then | ||||
|     LIBVIRTD_CONFIG_ARGS="--config $LIBVIRTD_CONFIG" | ||||
| fi | ||||
|  | ||||
| RETVAL=0 | ||||
|  | ||||
| start() { | ||||
|     echo -n $"Starting $SERVICE daemon: " | ||||
|     mkdir -p @localstatedir@/cache/libvirt | ||||
|     rm -rf @localstatedir@/cache/libvirt/* | ||||
|     KRB5_KTNAME=$KRB5_KTNAME daemon --pidfile $PIDFILE --check $SERVICE $PROCESS --daemon $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS | ||||
|     RETVAL=$? | ||||
|     echo | ||||
|     [ $RETVAL -eq 0 ] && touch @localstatedir@/lock/subsys/$SERVICE | ||||
| } | ||||
|  | ||||
| stop() { | ||||
|     echo -n $"Stopping $SERVICE daemon: " | ||||
|  | ||||
|     killproc -p $PIDFILE $PROCESS | ||||
|     RETVAL=$? | ||||
|     echo | ||||
|     if [ $RETVAL -eq 0 ]; then | ||||
|         rm -f @localstatedir@/lock/subsys/$SERVICE | ||||
|         rm -f $PIDFILE | ||||
|         rm -rf @localstatedir@/cache/libvirt/* | ||||
|     else | ||||
|         exit $RETVAL | ||||
|     fi | ||||
| } | ||||
|  | ||||
| restart() { | ||||
|     stop | ||||
|     start | ||||
| } | ||||
|  | ||||
| reload() { | ||||
|     echo -n $"Reloading $SERVICE configuration: " | ||||
|  | ||||
|     killproc -p $PIDFILE $PROCESS -HUP | ||||
|     RETVAL=$? | ||||
|     echo | ||||
|     return $RETVAL | ||||
| } | ||||
|  | ||||
| # See how we were called. | ||||
| case "$1" in | ||||
|     start|stop|restart|reload) | ||||
|         $1 | ||||
|         ;; | ||||
|     status) | ||||
|         status -p $PIDFILE $PROCESS | ||||
|         RETVAL=$? | ||||
|         ;; | ||||
|     force-reload) | ||||
|         reload | ||||
|         ;; | ||||
|     condrestart|try-restart) | ||||
|         [ -f @localstatedir@/lock/subsys/$SERVICE ] && restart || : | ||||
|         ;; | ||||
|     *) | ||||
|         echo $"Usage: $0 {start|stop|status|restart|condrestart|reload|force-reload|try-restart}" | ||||
|         exit 2 | ||||
|         ;; | ||||
| esac | ||||
| exit $RETVAL | ||||
| @@ -1,9 +0,0 @@ | ||||
| @localstatedir@/log/libvirt/libvirtd.log { | ||||
|         weekly | ||||
|         missingok | ||||
|         rotate 4 | ||||
|         compress | ||||
|         delaycompress | ||||
|         copytruncate | ||||
|         minsize 100k | ||||
| } | ||||
| @@ -1,9 +0,0 @@ | ||||
| @localstatedir@/log/libvirt/lxc/*.log { | ||||
|         weekly | ||||
|         missingok | ||||
|         rotate 4 | ||||
|         compress | ||||
|         delaycompress | ||||
|         copytruncate | ||||
|         minsize 100k | ||||
| } | ||||
| @@ -1,168 +0,0 @@ | ||||
| =head1 NAME | ||||
|  | ||||
| libvirtd - libvirtd management daemon | ||||
|  | ||||
| =head1 SYNOPSIS | ||||
|  | ||||
| B<libvirtd> [ -dlv ] [ -f config_file ] [ -p pid_file ] [ -t timeout_seconds ] | ||||
|  | ||||
| B<libvirtd> --version | ||||
|  | ||||
| =head1 DESCRIPTION | ||||
|  | ||||
| The B<libvirtd> program is the server side daemon component of the libvirt | ||||
| virtualization management system. | ||||
|  | ||||
| This daemon runs on host servers and performs required management tasks for | ||||
| virtualized guests.  This includes activities such as starting, stopping | ||||
| and migrating guests between host servers, configuring and manipulating | ||||
| networking, and managing storage for use by guests. | ||||
|  | ||||
| The libvirt client libraries and utilities connect to this daemon to issue | ||||
| tasks and collect information about the configuration and resources of the host | ||||
| system and guests. | ||||
|  | ||||
| By default, the libvirtd daemon listens for requests on a local Unix domain | ||||
| socket.  Using the B<-l>|B<--listen> command line option, the libvirtd daemon | ||||
| can be instructed to additionally listen on a TCP/IP socket.  The TCP/IP socket | ||||
| to use is defined in the libvirtd configuration file. | ||||
|  | ||||
| Restarting libvirtd does not impact running guests.  Guests continue to operate | ||||
| and will be picked up automatically if their XML configuration has been | ||||
| defined.  Any guests whose XML configuration has not been defined will be lost | ||||
| from the configuration. | ||||
|  | ||||
| =head1 OPTIONS | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item B<-d, --daemon> | ||||
|  | ||||
| Run as a daemon & write PID file. | ||||
|  | ||||
| =item B<-f, --config> I<FILE> | ||||
|  | ||||
| Use this configuration file, overriding the default value. | ||||
|  | ||||
| =item B<-l, --listen> | ||||
|  | ||||
| Listen for TCP/IP connections. | ||||
|  | ||||
| =item B<-p, --pid-file> I<FILE> | ||||
|  | ||||
| Use this name for the PID file, overriding the default value. | ||||
|  | ||||
| =item B<-t, --timeout> I<SECONDS> | ||||
|  | ||||
| Exit after timeout period (in seconds) expires. | ||||
|  | ||||
| =item B<-v, --verbose> | ||||
|  | ||||
| Enable output of verbose messages. | ||||
|  | ||||
| =item B<    --version> | ||||
|  | ||||
| Display version information then exit. | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head1 SIGNALS | ||||
|  | ||||
| On receipt of B<SIGHUP> libvirtd will reload its configuration. | ||||
|  | ||||
| =head1 FILES | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item F<@sysconfdir@/libvirtd.conf> | ||||
|  | ||||
| The default configuration file used by libvirtd, unless overridden on the | ||||
| command line using the B<-f>|B<--config> option. | ||||
|  | ||||
| =item F<@localstatedir@/run/libvirt/libvirt-sock> | ||||
|  | ||||
| =item F<@localstatedir@/run/libvirt/libvirt-sock-ro> | ||||
|  | ||||
| The sockets libvirtd will use when B<run as root>. | ||||
|  | ||||
| =item F<$HOME/.libvirt/libvirt-sock> | ||||
|  | ||||
| The socket libvirtd will use when run as a B<non-root> user. | ||||
|  | ||||
| =item F<@sysconfdir@/pki/CA/cacert.pem> | ||||
|  | ||||
| The TLS B<Certificate Authority> certificate libvirtd will use. | ||||
|  | ||||
| =item F<@sysconfdir@/pki/libvirt/servercert.pem> | ||||
|  | ||||
| The TLS B<Server> certificate libvirtd will use. | ||||
|  | ||||
| =item F<@sysconfdir@/pki/libvirt/private/serverkey.pem> | ||||
|  | ||||
| The TLS B<Server> private key libvirtd will use. | ||||
|  | ||||
| =item F<@remote_pid_file@> | ||||
|  | ||||
| The PID file to use, unless overridden by the B<-p>|B<--pid-file> option. | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head1 EXAMPLES | ||||
|  | ||||
| To retrieve the version of libvirtd: | ||||
|  | ||||
|  # libvirtd --version | ||||
|  libvirtd (libvirt) 0.8.2 | ||||
|  # | ||||
|  | ||||
| To start libvirtd, instructing it to daemonize and create a PID file: | ||||
|  | ||||
|  # libvirtd -d | ||||
|  # ls -la @remote_pid_file@ | ||||
|  -rw-r--r-- 1 root root 6 Jul  9 02:40 @remote_pid_file@ | ||||
|  # | ||||
|  | ||||
| =head1 BUGS | ||||
|  | ||||
| Please report all bugs you discover.  This should be done via either: | ||||
|  | ||||
| =over | ||||
|  | ||||
| =item a) the mailing list | ||||
|  | ||||
| L<http://libvirt.org/contact.html> | ||||
|  | ||||
| =item or, | ||||
|  | ||||
| B<> | ||||
|  | ||||
| =item b) the bug tracker | ||||
|  | ||||
| L<http://libvirt.org/bugs.html> | ||||
|  | ||||
| =item Alternatively, you may report bugs to your software distributor / vendor. | ||||
|  | ||||
| =back | ||||
|  | ||||
| =head1 AUTHORS | ||||
|  | ||||
| Please refer to the AUTHORS file distributed with libvirt. | ||||
|  | ||||
| =head1 COPYRIGHT | ||||
|  | ||||
| Copyright (C) 2006-2010 Red Hat, Inc., and the authors listed in the | ||||
| libvirt AUTHORS file. | ||||
|  | ||||
| =head1 LICENSE | ||||
|  | ||||
| libvirtd is distributed under the terms of the GNU LGPL v2.1+. | ||||
| This is free software; see the source for copying conditions. There | ||||
| is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR | ||||
| PURPOSE | ||||
|  | ||||
| =head1 SEE ALSO | ||||
|  | ||||
| L<virsh(1)>, L<virt-install(1)>, L<virt-xml-validate(1)>, L<virt-top(1)>, | ||||
| L<virt-df(1)>, L<http://www.libvirt.org/> | ||||
|  | ||||
| =cut | ||||
| @@ -1,42 +0,0 @@ | ||||
| <!DOCTYPE policyconfig PUBLIC | ||||
|  "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" | ||||
|  "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> | ||||
|  | ||||
| <!-- | ||||
| Policy definitions for libvirt daemon | ||||
|  | ||||
| Copyright (c) 2007 Daniel P. Berrange <berrange redhat com> | ||||
|  | ||||
| libvirt is licensed to you under the GNU Lesser General Public License | ||||
| version 2. See COPYING for details. | ||||
|  | ||||
| NOTE: If you make changes to this file, make sure to validate the file | ||||
| using the polkit-policy-file-validate(1) tool. Changes made to this | ||||
| file are instantly applied. | ||||
| --> | ||||
|  | ||||
| <policyconfig> | ||||
|     <action id="org.libvirt.unix.monitor"> | ||||
|       <description>Monitor local virtualized systems</description> | ||||
|       <message>System policy prevents monitoring of local virtualized systems</message> | ||||
|       <defaults> | ||||
|         <!-- Any program can use libvirt in read-only mode for monitoring, | ||||
|              even if not part of a session --> | ||||
|         <allow_any>yes</allow_any> | ||||
|         <allow_inactive>yes</allow_inactive> | ||||
|         <allow_active>yes</allow_active> | ||||
|       </defaults> | ||||
|     </action> | ||||
|  | ||||
|     <action id="org.libvirt.unix.manage"> | ||||
|       <description>Manage local virtualized systems</description> | ||||
|       <message>System policy prevents management of local virtualized systems</message> | ||||
|       <defaults> | ||||
|         <!-- Only a program in the active host session can use libvirt in | ||||
|              read-write mode for management, and we require user password --> | ||||
|         <allow_any>no</allow_any> | ||||
|         <allow_inactive>no</allow_inactive> | ||||
|         <allow_active>auth_admin_keep_session</allow_active> | ||||
|       </defaults> | ||||
|     </action> | ||||
| </policyconfig> | ||||
| @@ -1,42 +0,0 @@ | ||||
| <!DOCTYPE policyconfig PUBLIC | ||||
|  "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" | ||||
|  "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> | ||||
|  | ||||
| <!-- | ||||
| Policy definitions for libvirt daemon | ||||
|  | ||||
| Copyright (c) 2007 Daniel P. Berrange <berrange redhat com> | ||||
|  | ||||
| libvirt is licensed to you under the GNU Lesser General Public License | ||||
| version 2. See COPYING for details. | ||||
|  | ||||
| NOTE: If you make changes to this file, make sure to validate the file | ||||
| using the polkit-policy-file-validate(1) tool. Changes made to this | ||||
| file are instantly applied. | ||||
| --> | ||||
|  | ||||
| <policyconfig> | ||||
|     <action id="org.libvirt.unix.monitor"> | ||||
|       <description>Monitor local virtualized systems</description> | ||||
|       <message>System policy prevents monitoring of local virtualized systems</message> | ||||
|       <defaults> | ||||
|         <!-- Any program can use libvirt in read-only mode for monitoring, | ||||
|              even if not part of a session --> | ||||
|         <allow_any>yes</allow_any> | ||||
|         <allow_inactive>yes</allow_inactive> | ||||
|         <allow_active>yes</allow_active> | ||||
|       </defaults> | ||||
|     </action> | ||||
|  | ||||
|     <action id="org.libvirt.unix.manage"> | ||||
|       <description>Manage local virtualized systems</description> | ||||
|       <message>System policy prevents management of local virtualized systems</message> | ||||
|       <defaults> | ||||
|         <!-- Only a program in the active host session can use libvirt in | ||||
|              read-write mode for management, and we require user password --> | ||||
|         <allow_any>no</allow_any> | ||||
|         <allow_inactive>no</allow_inactive> | ||||
|         <allow_active>auth_admin_keep</allow_active> | ||||
|       </defaults> | ||||
|     </action> | ||||
| </policyconfig> | ||||
| @@ -1,9 +0,0 @@ | ||||
| @localstatedir@/log/libvirt/qemu/*.log { | ||||
|         weekly | ||||
|         missingok | ||||
|         rotate 4 | ||||
|         compress | ||||
|         delaycompress | ||||
|         copytruncate | ||||
|         minsize 100k | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| # If you want to use the non-TLS socket, then you *must* include | ||||
| # the GSSAPI or DIGEST-MD5 mechanisms, because they are the only | ||||
| # ones that can offer session encryption as well as authentication. | ||||
| # | ||||
| # If you're only using TLS, then you can turn on any mechanisms | ||||
| # you like for authentication, because TLS provides the encryption | ||||
| # | ||||
| # Default to a simple username+password mechanism | ||||
| mech_list: digest-md5 | ||||
|  | ||||
| # Before you can use GSSAPI, you need a service principle on the | ||||
| # KDC server for libvirt, and that to be exported to the keytab | ||||
| # file listed below | ||||
| #mech_list: gssapi | ||||
| # | ||||
| # You can also list many mechanisms at once, then the user can choose | ||||
| # by adding  '?auth=sasl.gssapi' to their libvirt URI, eg | ||||
| #   qemu+tcp://hostname/system?auth=sasl.gssapi | ||||
| #mech_list: digest-md5 gssapi | ||||
|  | ||||
| # MIT kerberos ignores this option & needs KRB5_KTNAME env var. | ||||
| # May be useful for other non-Linux OS though.... | ||||
| keytab: /etc/libvirt/krb5.tab | ||||
|  | ||||
| # If using digest-md5 for username/passwds, then this is the file | ||||
| # containing the passwds. Use 'saslpasswd2 -a libvirt [username]' | ||||
| # to add entries, and 'sasldblistusers2 -a libvirt' to browse it | ||||
| sasldb_path: /etc/libvirt/passwd.db | ||||
| @@ -1,65 +0,0 @@ | ||||
| probe libvirt.daemon.client.connect = process("libvirtd").mark("client_connect") | ||||
| { | ||||
|   fd = $arg1; | ||||
|   readonly = $arg2; | ||||
|   localAddr = user_string($arg3); | ||||
|   remoteAddr = user_string($arg4); | ||||
| } | ||||
|  | ||||
| probe libvirt.daemon.client.disconnect = process("libvirtd").mark("client_disconnect") | ||||
| { | ||||
|   fd = $arg1; | ||||
| } | ||||
|  | ||||
|  | ||||
| probe libvirt.daemon.client.tls_allow = process("libvirtd").mark("client_tls_allow") | ||||
| { | ||||
|   fd = $arg1; | ||||
|   x509dname = user_string($arg2); | ||||
| } | ||||
|  | ||||
| probe libvirt.daemon.client.tls_deny = process("libvirtd").mark("client_tls_deny") | ||||
| { | ||||
|   fd = $arg1; | ||||
|   x509dname = user_string($arg2); | ||||
| } | ||||
|  | ||||
| probe libvirt.daemon.client.tls_fail = process("libvirtd").mark("client_tls_fail") | ||||
| { | ||||
|   fd = $arg1; | ||||
| } | ||||
|  | ||||
|  | ||||
| function authtype_to_string(authtype) { | ||||
|   if (authtype == 0) | ||||
|     return "none" | ||||
|   if (authtype == 1) | ||||
|     return "sasl" | ||||
|   if (authtype == 2) | ||||
|     return "polkit" | ||||
|   return "unknown" | ||||
| } | ||||
|  | ||||
|  | ||||
| probe libvirt.daemon.client.auth_allow = process("libvirtd").mark("client_auth_allow") | ||||
| { | ||||
|   fd = $arg1; | ||||
|   authtype = $arg2; | ||||
|   authname = authtype_to_string($arg2); | ||||
|   identity = user_string($arg3); | ||||
| } | ||||
|  | ||||
| probe libvirt.daemon.client.auth_deny = process("libvirtd").mark("client_auth_deny") | ||||
| { | ||||
|   fd = $arg1; | ||||
|   authtype = $arg2; | ||||
|   authname = authtype_to_string($arg2); | ||||
|   identity = user_string($arg3); | ||||
| } | ||||
|  | ||||
| probe libvirt.daemon.client.auth_fail = process("libvirtd").mark("client_auth_fail") | ||||
| { | ||||
|   fd = $arg1; | ||||
|   authtype = $arg2; | ||||
|   authname = authtype_to_string($arg2); | ||||
| } | ||||
| @@ -1,18 +0,0 @@ | ||||
| # Override the default config file | ||||
| #LIBVIRTD_CONFIG=/etc/libvirt/libvirtd.conf | ||||
|  | ||||
| # Listen for TCP/IP connections | ||||
| # NB. must setup TLS/SSL keys prior to using this | ||||
| #LIBVIRTD_ARGS="--listen" | ||||
|  | ||||
| # Override Kerberos service keytab for SASL/GSSAPI | ||||
| #KRB5_KTNAME=/etc/libvirt/krb5.tab | ||||
|  | ||||
| # Override the QEMU/SDL default audio driver probing when | ||||
| # starting virtual machines using SDL graphics | ||||
| # | ||||
| # NB these have no effect for VMs using VNC, unless vnc_allow_host_audio | ||||
| # is enabled in /etc/libvirt/qemu.conf | ||||
| #QEMU_AUDIO_DRV=sdl | ||||
| # | ||||
| #SDL_AUDIODRIVER=pulse | ||||
| @@ -1,9 +0,0 @@ | ||||
| @localstatedir@/log/libvirt/uml/*.log { | ||||
|         weekly | ||||
|         missingok | ||||
|         rotate 4 | ||||
|         compress | ||||
|         delaycompress | ||||
|         copytruncate | ||||
|         minsize 100k | ||||
| } | ||||
| @@ -1,46 +0,0 @@ | ||||
| # libvirtd upstart job | ||||
| # | ||||
| # XXX wait for rc to get all dependent initscripts started | ||||
| # from sysv libvirtd initscript: Required-Start: $network messagebus | ||||
| start on stopped rc RUNLEVEL=[345] | ||||
| stop on runlevel [!345] | ||||
|  | ||||
| respawn | ||||
|  | ||||
| script | ||||
|     LIBVIRTD_CONFIG= | ||||
|     LIBVIRTD_ARGS= | ||||
|     KRB5_KTNAME=/etc/libvirt/krb5.tab | ||||
|  | ||||
|     if [ -f /etc/sysconfig/libvirtd ]; then | ||||
|         . /etc/sysconfig/libvirtd | ||||
|     fi | ||||
|  | ||||
|     export QEMU_AUDIO_DRV | ||||
|     export SDL_AUDIODRIVER | ||||
|     export KRB5_KTNAME | ||||
|  | ||||
|     LIBVIRTD_CONFIG_ARGS= | ||||
|     if [ -n "$LIBVIRTD_CONFIG" ]; then | ||||
|         LIBVIRTD_CONFIG_ARGS="--config $LIBVIRTD_CONFIG" | ||||
|     fi | ||||
|  | ||||
|     # DAEMON_COREFILE_LIMIT from /etc/sysconfig/libvirtd is not handled | ||||
|     # automatically | ||||
|     if [ -n "$DAEMON_COREFILE_LIMIT" ]; then | ||||
|         ulimit -c "$DAEMON_COREFILE_LIMIT" | ||||
|     fi | ||||
|  | ||||
|     # Clean up a pidfile that might be left around | ||||
|     rm -f /var/run/libvirtd.pid | ||||
|  | ||||
|     mkdir -p /var/cache/libvirt | ||||
|     rm -rf /var/cache/libvirt/* | ||||
|  | ||||
|     exec /usr/sbin/libvirtd $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS | ||||
| end script | ||||
|  | ||||
| post-stop script | ||||
|     rm -f $PIDFILE | ||||
|     rm -rf /var/cache/libvirt/* | ||||
| end script | ||||
| @@ -1,12 +0,0 @@ | ||||
| provider libvirtd { | ||||
| 	 probe client_connect(int fd, int readonly, const char *localAddr, const char *remoteAddr); | ||||
| 	 probe client_disconnect(int fd); | ||||
|  | ||||
| 	 probe client_auth_allow(int fd, int authtype, const char *identity); | ||||
| 	 probe client_auth_deny(int fd, int authtype, const char *identity); | ||||
| 	 probe client_auth_fail(int fd, int authtype); | ||||
|  | ||||
| 	 probe client_tls_allow(int fd, const char *x509dname); | ||||
| 	 probe client_tls_deny(int fd, const char *x509dname); | ||||
| 	 probe client_tls_fail(int fd); | ||||
| }; | ||||
							
								
								
									
										3244
									
								
								daemon/remote.c
									
									
									
									
									
								
							
							
						
						
									
										3244
									
								
								daemon/remote.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,41 +0,0 @@ | ||||
| /* | ||||
|  * remote.h: handlers for RPC method calls | ||||
|  * | ||||
|  * Copyright (C) 2007, 2008, 2009 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, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA | ||||
|  * | ||||
|  * Author: Richard W.M. Jones <rjones@redhat.com> | ||||
|  * Author: Daniel P. Berrange <berrange@redhat.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef __LIBVIRTD_REMOTE_H__ | ||||
| # define __LIBVIRTD_REMOTE_H__ | ||||
|  | ||||
| # include "remote_protocol.h" | ||||
| # include "rpc/virnetserverprogram.h" | ||||
| # include "rpc/virnetserverclient.h" | ||||
|  | ||||
|  | ||||
| extern virNetServerProgramProc remoteProcs[]; | ||||
| extern size_t remoteNProcs; | ||||
|  | ||||
| extern virNetServerProgramProc qemuProcs[]; | ||||
| extern size_t qemuNProcs; | ||||
|  | ||||
| int remoteClientInitHook(virNetServerPtr srv, | ||||
|                          virNetServerClientPtr client); | ||||
|  | ||||
| #endif /* __LIBVIRTD_REMOTE_H__ */ | ||||
							
								
								
									
										750
									
								
								daemon/stream.c
									
									
									
									
									
								
							
							
						
						
									
										750
									
								
								daemon/stream.c
									
									
									
									
									
								
							| @@ -1,750 +0,0 @@ | ||||
| /* | ||||
|  * stream.c: APIs for managing client streams | ||||
|  * | ||||
|  * Copyright (C) 2009 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, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA | ||||
|  * | ||||
|  * Author: Daniel P. Berrange <berrange@redhat.com> | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #include <config.h> | ||||
|  | ||||
| #include "stream.h" | ||||
| #include "remote.h" | ||||
| #include "memory.h" | ||||
| #include "logging.h" | ||||
| #include "virnetserverclient.h" | ||||
| #include "virterror_internal.h" | ||||
|  | ||||
| #define VIR_FROM_THIS VIR_FROM_STREAMS | ||||
|  | ||||
| #define virNetError(code, ...)                                    \ | ||||
|     virReportErrorHelper(VIR_FROM_THIS, code, __FILE__,           \ | ||||
|                          __FUNCTION__, __LINE__, __VA_ARGS__) | ||||
|  | ||||
| struct daemonClientStream { | ||||
|     daemonClientPrivatePtr priv; | ||||
|     int refs; | ||||
|  | ||||
|     virNetServerProgramPtr prog; | ||||
|  | ||||
|     virStreamPtr st; | ||||
|     int procedure; | ||||
|     int serial; | ||||
|  | ||||
|     unsigned int recvEOF : 1; | ||||
|     unsigned int closed : 1; | ||||
|  | ||||
|     int filterID; | ||||
|  | ||||
|     virNetMessagePtr rx; | ||||
|     int tx; | ||||
|  | ||||
|     daemonClientStreamPtr next; | ||||
| }; | ||||
|  | ||||
| static int | ||||
| daemonStreamHandleWrite(virNetServerClientPtr client, | ||||
|                         daemonClientStream *stream); | ||||
| static int | ||||
| daemonStreamHandleRead(virNetServerClientPtr client, | ||||
|                        daemonClientStream *stream); | ||||
| static int | ||||
| daemonStreamHandleFinish(virNetServerClientPtr client, | ||||
|                          daemonClientStream *stream, | ||||
|                          virNetMessagePtr msg); | ||||
| static int | ||||
| daemonStreamHandleAbort(virNetServerClientPtr client, | ||||
|                         daemonClientStream *stream, | ||||
|                         virNetMessagePtr msg); | ||||
|  | ||||
|  | ||||
|  | ||||
| static void | ||||
| daemonStreamUpdateEvents(daemonClientStream *stream) | ||||
| { | ||||
|     int newEvents = 0; | ||||
|     if (stream->rx) | ||||
|         newEvents |= VIR_STREAM_EVENT_WRITABLE; | ||||
|     if (stream->tx && !stream->recvEOF) | ||||
|         newEvents |= VIR_STREAM_EVENT_READABLE; | ||||
|  | ||||
|     virStreamEventUpdateCallback(stream->st, newEvents); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Invoked when an outgoing data packet message has been fully sent. | ||||
|  * This simply re-enables TX of further data. | ||||
|  * | ||||
|  * The idea is to stop the daemon growing without bound due to | ||||
|  * fast stream, but slow client | ||||
|  */ | ||||
| static void | ||||
| daemonStreamMessageFinished(virNetMessagePtr msg, | ||||
|                             void *opaque) | ||||
| { | ||||
|     daemonClientStream *stream = opaque; | ||||
|     VIR_DEBUG("stream=%p proc=%d serial=%d", | ||||
|               stream, msg->header.proc, msg->header.serial); | ||||
|  | ||||
|     stream->tx = 1; | ||||
|     daemonStreamUpdateEvents(stream); | ||||
|  | ||||
|     daemonFreeClientStream(NULL, stream); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| daemonStreamEventFreeFunc(void *opaque) | ||||
| { | ||||
|     virNetServerClientPtr client = opaque; | ||||
|  | ||||
|     virNetServerClientFree(client); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Callback that gets invoked when a stream becomes writable/readable | ||||
|  */ | ||||
| static void | ||||
| daemonStreamEvent(virStreamPtr st, int events, void *opaque) | ||||
| { | ||||
|     virNetServerClientPtr client = opaque; | ||||
|     daemonClientStream *stream; | ||||
|     daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client); | ||||
|  | ||||
|     virMutexLock(&priv->lock); | ||||
|  | ||||
|     stream = priv->streams; | ||||
|     while (stream) { | ||||
|         if (stream->st == st) | ||||
|             break; | ||||
|         stream = stream->next; | ||||
|     } | ||||
|  | ||||
|     if (!stream) { | ||||
|         VIR_WARN("event for client=%p stream st=%p, but missing stream state", client, st); | ||||
|         virStreamEventRemoveCallback(st); | ||||
|         goto cleanup; | ||||
|     } | ||||
|  | ||||
|     VIR_DEBUG("st=%p events=%d EOF=%d closed=%d", st, events, stream->recvEOF, stream->closed); | ||||
|  | ||||
|     if (events & VIR_STREAM_EVENT_WRITABLE) { | ||||
|         if (daemonStreamHandleWrite(client, stream) < 0) { | ||||
|             daemonRemoveClientStream(client, stream); | ||||
|             virNetServerClientClose(client); | ||||
|             goto cleanup; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!stream->recvEOF && | ||||
|         (events & (VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP))) { | ||||
|         events = events & ~(VIR_STREAM_EVENT_READABLE | VIR_STREAM_EVENT_HANGUP); | ||||
|         if (daemonStreamHandleRead(client, stream) < 0) { | ||||
|             daemonRemoveClientStream(client, stream); | ||||
|             virNetServerClientClose(client); | ||||
|             goto cleanup; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* If we have a completion/abort message, always process it */ | ||||
|     if (stream->rx) { | ||||
|         virNetMessagePtr msg = stream->rx; | ||||
|         switch (msg->header.status) { | ||||
|         case VIR_NET_CONTINUE: | ||||
|             /* nada */ | ||||
|             break; | ||||
|         case VIR_NET_OK: | ||||
|             virNetMessageQueueServe(&stream->rx); | ||||
|             if (daemonStreamHandleFinish(client, stream, msg) < 0) { | ||||
|                 virNetMessageFree(msg); | ||||
|                 daemonRemoveClientStream(client, stream); | ||||
|                 virNetServerClientClose(client); | ||||
|                 goto cleanup; | ||||
|             } | ||||
|             break; | ||||
|         case VIR_NET_ERROR: | ||||
|         default: | ||||
|             virNetMessageQueueServe(&stream->rx); | ||||
|             if (daemonStreamHandleAbort(client, stream, msg) < 0) { | ||||
|                 virNetMessageFree(msg); | ||||
|                 daemonRemoveClientStream(client, stream); | ||||
|                 virNetServerClientClose(client); | ||||
|                 goto cleanup; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!stream->closed && | ||||
|         (events & (VIR_STREAM_EVENT_ERROR | VIR_STREAM_EVENT_HANGUP))) { | ||||
|         int ret; | ||||
|         virNetMessagePtr msg; | ||||
|         virNetMessageError rerr; | ||||
|  | ||||
|         memset(&rerr, 0, sizeof(rerr)); | ||||
|         stream->closed = 1; | ||||
|         virStreamEventRemoveCallback(stream->st); | ||||
|         virStreamAbort(stream->st); | ||||
|         if (events & VIR_STREAM_EVENT_HANGUP) | ||||
|             virNetError(VIR_ERR_RPC, | ||||
|                         "%s", _("stream had unexpected termination")); | ||||
|         else | ||||
|             virNetError(VIR_ERR_RPC, | ||||
|                         "%s", _("stream had I/O failure")); | ||||
|  | ||||
|         msg = virNetMessageNew(false); | ||||
|         if (!msg) { | ||||
|             ret = -1; | ||||
|         } else { | ||||
|             ret = virNetServerProgramSendStreamError(remoteProgram, | ||||
|                                                      client, | ||||
|                                                      msg, | ||||
|                                                      &rerr, | ||||
|                                                      stream->procedure, | ||||
|                                                      stream->serial); | ||||
|         } | ||||
|         daemonRemoveClientStream(client, stream); | ||||
|         if (ret < 0) | ||||
|             virNetServerClientClose(client); | ||||
|         goto cleanup; | ||||
|     } | ||||
|  | ||||
|     if (stream->closed) { | ||||
|         daemonRemoveClientStream(client, stream); | ||||
|     } else { | ||||
|         daemonStreamUpdateEvents(stream); | ||||
|     } | ||||
|  | ||||
| cleanup: | ||||
|     virMutexUnlock(&priv->lock); | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * @client: a locked client object | ||||
|  * | ||||
|  * Invoked by the main loop when filtering incoming messages. | ||||
|  * | ||||
|  * Returns 1 if the message was processed, 0 if skipped, | ||||
|  * -1 on fatal client error | ||||
|  */ | ||||
| static int | ||||
| daemonStreamFilter(virNetServerClientPtr client, | ||||
|                    virNetMessagePtr msg, | ||||
|                    void *opaque) | ||||
| { | ||||
|     daemonClientStream *stream = opaque; | ||||
|     int ret = 0; | ||||
|  | ||||
|     virMutexLock(&stream->priv->lock); | ||||
|  | ||||
|     if (msg->header.type != VIR_NET_STREAM) | ||||
|         goto cleanup; | ||||
|  | ||||
|     if (!virNetServerProgramMatches(stream->prog, msg)) | ||||
|         goto cleanup; | ||||
|  | ||||
|     if (msg->header.proc != stream->procedure || | ||||
|         msg->header.serial != stream->serial) | ||||
|         goto cleanup; | ||||
|  | ||||
|     VIR_DEBUG("Incoming client=%p, rx=%p, serial=%d, proc=%d, status=%d", | ||||
|               client, stream->rx, msg->header.proc, | ||||
|               msg->header.serial, msg->header.status); | ||||
|  | ||||
|     virNetMessageQueuePush(&stream->rx, msg); | ||||
|     daemonStreamUpdateEvents(stream); | ||||
|     ret = 1; | ||||
|  | ||||
| cleanup: | ||||
|     virMutexUnlock(&stream->priv->lock); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * @conn: a connection object to associate the stream with | ||||
|  * @header: the method call to associate with the stream | ||||
|  * | ||||
|  * Creates a new stream for this conn | ||||
|  * | ||||
|  * Returns a new stream object, or NULL upon OOM | ||||
|  */ | ||||
| daemonClientStream * | ||||
| daemonCreateClientStream(virNetServerClientPtr client, | ||||
|                          virStreamPtr st, | ||||
|                          virNetServerProgramPtr prog, | ||||
|                          virNetMessageHeaderPtr header) | ||||
| { | ||||
|     daemonClientStream *stream; | ||||
|     daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client); | ||||
|  | ||||
|     VIR_DEBUG("client=%p, proc=%d, serial=%d, st=%p", | ||||
|               client, header->proc, header->serial, st); | ||||
|  | ||||
|     if (VIR_ALLOC(stream) < 0) { | ||||
|         virReportOOMError(); | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     stream->refs = 1; | ||||
|     stream->priv = priv; | ||||
|     stream->prog = prog; | ||||
|     stream->procedure = header->proc; | ||||
|     stream->serial = header->serial; | ||||
|     stream->filterID = -1; | ||||
|     stream->st = st; | ||||
|  | ||||
|     virNetServerProgramRef(prog); | ||||
|  | ||||
|     return stream; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * @stream: an unused client stream | ||||
|  * | ||||
|  * Frees the memory associated with this inactive client | ||||
|  * stream | ||||
|  */ | ||||
| int daemonFreeClientStream(virNetServerClientPtr client, | ||||
|                            daemonClientStream *stream) | ||||
| { | ||||
|     virNetMessagePtr msg; | ||||
|     int ret = 0; | ||||
|  | ||||
|     if (!stream) | ||||
|         return 0; | ||||
|  | ||||
|     stream->refs--; | ||||
|     if (stream->refs) | ||||
|         return 0; | ||||
|  | ||||
|     VIR_DEBUG("client=%p, proc=%d, serial=%d", | ||||
|               client, stream->procedure, stream->serial); | ||||
|  | ||||
|     virNetServerProgramFree(stream->prog); | ||||
|  | ||||
|     msg = stream->rx; | ||||
|     while (msg) { | ||||
|         virNetMessagePtr tmp = msg->next; | ||||
|         if (client) { | ||||
|             /* Send a dummy reply to free up 'msg' & unblock client rx */ | ||||
|             virNetMessageClear(msg); | ||||
|             msg->header.type = VIR_NET_REPLY; | ||||
|             if (virNetServerClientSendMessage(client, msg) < 0) { | ||||
|                 virNetServerClientImmediateClose(client); | ||||
|                 virNetMessageFree(msg); | ||||
|                 ret = -1; | ||||
|             } | ||||
|         } else { | ||||
|             virNetMessageFree(msg); | ||||
|         } | ||||
|         msg = tmp; | ||||
|     } | ||||
|  | ||||
|     virStreamFree(stream->st); | ||||
|     VIR_FREE(stream); | ||||
|  | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * @client: a locked client to add the stream to | ||||
|  * @stream: a stream to add | ||||
|  */ | ||||
| int daemonAddClientStream(virNetServerClientPtr client, | ||||
|                           daemonClientStream *stream, | ||||
|                           bool transmit) | ||||
| { | ||||
|     VIR_DEBUG("client=%p, proc=%d, serial=%d, st=%p, transmit=%d", | ||||
|               client, stream->procedure, stream->serial, stream->st, transmit); | ||||
|     daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client); | ||||
|  | ||||
|     if (stream->filterID != -1) { | ||||
|         VIR_WARN("Filter already added to client %p", client); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (virStreamEventAddCallback(stream->st, 0, | ||||
|                                   daemonStreamEvent, client, | ||||
|                                   daemonStreamEventFreeFunc) < 0) | ||||
|         return -1; | ||||
|  | ||||
|     virNetServerClientRef(client); | ||||
|     if ((stream->filterID = virNetServerClientAddFilter(client, | ||||
|                                                         daemonStreamFilter, | ||||
|                                                         stream)) < 0) { | ||||
|         virStreamEventRemoveCallback(stream->st); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (transmit) | ||||
|         stream->tx = 1; | ||||
|  | ||||
|     virMutexLock(&priv->lock); | ||||
|     stream->next = priv->streams; | ||||
|     priv->streams = stream; | ||||
|  | ||||
|     daemonStreamUpdateEvents(stream); | ||||
|  | ||||
|     virMutexUnlock(&priv->lock); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * @client: a locked client object | ||||
|  * @stream: an inactive, closed stream object | ||||
|  * | ||||
|  * Removes a stream from the list of active streams for the client | ||||
|  * | ||||
|  * Returns 0 if the stream was removd, -1 if it doesn't exist | ||||
|  */ | ||||
| int | ||||
| daemonRemoveClientStream(virNetServerClientPtr client, | ||||
|                          daemonClientStream *stream) | ||||
| { | ||||
|     VIR_DEBUG("client=%p, proc=%d, serial=%d, st=%p", | ||||
|               client, stream->procedure, stream->serial, stream->st); | ||||
|     daemonClientPrivatePtr priv = virNetServerClientGetPrivateData(client); | ||||
|     daemonClientStream *curr = priv->streams; | ||||
|     daemonClientStream *prev = NULL; | ||||
|  | ||||
|     if (stream->filterID != -1) { | ||||
|         virNetServerClientRemoveFilter(client, | ||||
|                                        stream->filterID); | ||||
|         stream->filterID = -1; | ||||
|     } | ||||
|  | ||||
|     if (!stream->closed) { | ||||
|         virStreamEventRemoveCallback(stream->st); | ||||
|         virStreamAbort(stream->st); | ||||
|     } | ||||
|  | ||||
|     while (curr) { | ||||
|         if (curr == stream) { | ||||
|             if (prev) | ||||
|                 prev->next = curr->next; | ||||
|             else | ||||
|                 priv->streams = curr->next; | ||||
|             return daemonFreeClientStream(client, stream); | ||||
|         } | ||||
|         prev = curr; | ||||
|         curr = curr->next; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| daemonRemoveAllClientStreams(daemonClientStream *stream) | ||||
| { | ||||
|     daemonClientStream *tmp; | ||||
|  | ||||
|     VIR_DEBUG("stream=%p", stream); | ||||
|  | ||||
|     while (stream) { | ||||
|         tmp = stream->next; | ||||
|  | ||||
|         if (!stream->closed) { | ||||
|             virStreamEventRemoveCallback(stream->st); | ||||
|             virStreamAbort(stream->st); | ||||
|         } | ||||
|  | ||||
|         daemonFreeClientStream(NULL, stream); | ||||
|  | ||||
|         VIR_DEBUG("next stream=%p", tmp); | ||||
|         stream = tmp; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Returns: | ||||
|  *   -1  if fatal error occurred | ||||
|  *    0  if message was fully processed | ||||
|  *    1  if message is still being processed | ||||
|  */ | ||||
| static int | ||||
| daemonStreamHandleWriteData(virNetServerClientPtr client, | ||||
|                             daemonClientStream *stream, | ||||
|                             virNetMessagePtr msg) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d, len=%zu, offset=%zu", | ||||
|               client, stream, msg->header.proc, msg->header.serial, | ||||
|               msg->bufferLength, msg->bufferOffset); | ||||
|  | ||||
|     ret = virStreamSend(stream->st, | ||||
|                         msg->buffer + msg->bufferOffset, | ||||
|                         msg->bufferLength - msg->bufferOffset); | ||||
|  | ||||
|     if (ret > 0) { | ||||
|         msg->bufferOffset += ret; | ||||
|  | ||||
|         /* Partial write, so indicate we have more todo later */ | ||||
|         if (msg->bufferOffset < msg->bufferLength) | ||||
|             return 1; | ||||
|     } else if (ret == -2) { | ||||
|         /* Blocking, so indicate we have more todo later */ | ||||
|         return 1; | ||||
|     } else { | ||||
|         virNetMessageError rerr; | ||||
|  | ||||
|         memset(&rerr, 0, sizeof(rerr)); | ||||
|  | ||||
|         VIR_INFO("Stream send failed"); | ||||
|         stream->closed = 1; | ||||
|         return virNetServerProgramSendReplyError(stream->prog, | ||||
|                                                  client, | ||||
|                                                  msg, | ||||
|                                                  &rerr, | ||||
|                                                  &msg->header); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Process an finish handshake from the client. | ||||
|  * | ||||
|  * Returns a VIR_NET_OK confirmation if successful, or a VIR_NET_ERROR | ||||
|  * if there was a stream error | ||||
|  * | ||||
|  * Returns 0 if successfully sent RPC reply, -1 upon fatal error | ||||
|  */ | ||||
| static int | ||||
| daemonStreamHandleFinish(virNetServerClientPtr client, | ||||
|                          daemonClientStream *stream, | ||||
|                          virNetMessagePtr msg) | ||||
| { | ||||
|     int ret; | ||||
|  | ||||
|     VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d", | ||||
|               client, stream, msg->header.proc, msg->header.serial); | ||||
|  | ||||
|     stream->closed = 1; | ||||
|     virStreamEventRemoveCallback(stream->st); | ||||
|     ret = virStreamFinish(stream->st); | ||||
|  | ||||
|     if (ret < 0) { | ||||
|         virNetMessageError rerr; | ||||
|         memset(&rerr, 0, sizeof(rerr)); | ||||
|         return virNetServerProgramSendReplyError(stream->prog, | ||||
|                                                  client, | ||||
|                                                  msg, | ||||
|                                                  &rerr, | ||||
|                                                  &msg->header); | ||||
|     } else { | ||||
|         /* Send zero-length confirm */ | ||||
|         return virNetServerProgramSendStreamData(stream->prog, | ||||
|                                                  client, | ||||
|                                                  msg, | ||||
|                                                  stream->procedure, | ||||
|                                                  stream->serial, | ||||
|                                                  NULL, 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Process an abort request from the client. | ||||
|  * | ||||
|  * Returns 0 if successfully aborted, -1 upon error | ||||
|  */ | ||||
| static int | ||||
| daemonStreamHandleAbort(virNetServerClientPtr client, | ||||
|                         daemonClientStream *stream, | ||||
|                         virNetMessagePtr msg) | ||||
| { | ||||
|     VIR_DEBUG("client=%p, stream=%p, proc=%d, serial=%d", | ||||
|               client, stream, msg->header.proc, msg->header.serial); | ||||
|     virNetMessageError rerr; | ||||
|  | ||||
|     memset(&rerr, 0, sizeof(rerr)); | ||||
|  | ||||
|     stream->closed = 1; | ||||
|     virStreamEventRemoveCallback(stream->st); | ||||
|     virStreamAbort(stream->st); | ||||
|  | ||||
|     if (msg->header.status == VIR_NET_ERROR) | ||||
|         virNetError(VIR_ERR_RPC, | ||||
|                     "%s", _("stream aborted at client request")); | ||||
|     else { | ||||
|         VIR_WARN("unexpected stream status %d", msg->header.status); | ||||
|         virNetError(VIR_ERR_RPC, | ||||
|                     _("stream aborted with unexpected status %d"), | ||||
|                     msg->header.status); | ||||
|     } | ||||
|  | ||||
|     return virNetServerProgramSendReplyError(remoteProgram, | ||||
|                                              client, | ||||
|                                              msg, | ||||
|                                              &rerr, | ||||
|                                              &msg->header); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Called when the stream is signalled has being able to accept | ||||
|  * data writes. Will process all pending incoming messages | ||||
|  * until they're all gone, or I/O blocks | ||||
|  * | ||||
|  * Returns 0 on success, or -1 upon fatal error | ||||
|  */ | ||||
| static int | ||||
| daemonStreamHandleWrite(virNetServerClientPtr client, | ||||
|                         daemonClientStream *stream) | ||||
| { | ||||
|     VIR_DEBUG("client=%p, stream=%p", client, stream); | ||||
|  | ||||
|     while (stream->rx && !stream->closed) { | ||||
|         virNetMessagePtr msg = stream->rx; | ||||
|         int ret; | ||||
|  | ||||
|         switch (msg->header.status) { | ||||
|         case VIR_NET_OK: | ||||
|             ret = daemonStreamHandleFinish(client, stream, msg); | ||||
|             break; | ||||
|  | ||||
|         case VIR_NET_CONTINUE: | ||||
|             ret = daemonStreamHandleWriteData(client, stream, msg); | ||||
|             break; | ||||
|  | ||||
|         case VIR_NET_ERROR: | ||||
|         default: | ||||
|             ret = daemonStreamHandleAbort(client, stream, msg); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         if (ret > 0) | ||||
|             break;  /* still processing data from msg */ | ||||
|  | ||||
|         virNetMessageQueueServe(&stream->rx); | ||||
|         if (ret < 0) { | ||||
|             virNetMessageFree(msg); | ||||
|             virNetServerClientImmediateClose(client); | ||||
|             return -1; | ||||
|         } | ||||
|  | ||||
|         /* 'CONTINUE' messages don't send a reply (unless error | ||||
|          * occurred), so to release the 'msg' object we need to | ||||
|          * send a fake zero-length reply. Nothing actually gets | ||||
|          * onto the wire, but this causes the client to reset | ||||
|          * its active request count / throttling | ||||
|          */ | ||||
|         if (msg->header.status == VIR_NET_CONTINUE) { | ||||
|             virNetMessageClear(msg); | ||||
|             msg->header.type = VIR_NET_REPLY; | ||||
|             if (virNetServerClientSendMessage(client, msg) < 0) { | ||||
|                 virNetMessageFree(msg); | ||||
|                 virNetServerClientImmediateClose(client); | ||||
|                 return -1; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Invoked when a stream is signalled as having data | ||||
|  * available to read. This reads upto one message | ||||
|  * worth of data, and then queues that for transmission | ||||
|  * to the client. | ||||
|  * | ||||
|  * Returns 0 if data was queued for TX, or a error RPC | ||||
|  * was sent, or -1 on fatal error, indicating client should | ||||
|  * be killed | ||||
|  */ | ||||
| static int | ||||
| daemonStreamHandleRead(virNetServerClientPtr client, | ||||
|                        daemonClientStream *stream) | ||||
| { | ||||
|     char *buffer; | ||||
|     size_t bufferLen = VIR_NET_MESSAGE_PAYLOAD_MAX; | ||||
|     int ret; | ||||
|  | ||||
|     VIR_DEBUG("client=%p, stream=%p tx=%d closed=%d", | ||||
|               client, stream, stream->tx, stream->closed); | ||||
|  | ||||
|     /* We might have had an event pending before we shut | ||||
|      * down the stream, so if we're marked as closed, | ||||
|      * then do nothing | ||||
|      */ | ||||
|     if (stream->closed) | ||||
|         return 0; | ||||
|  | ||||
|     /* Shouldn't ever be called unless we're marked able to | ||||
|      * transmit, but doesn't hurt to check */ | ||||
|     if (!stream->tx) | ||||
|         return 0; | ||||
|  | ||||
|     if (VIR_ALLOC_N(buffer, bufferLen) < 0) | ||||
|         return -1; | ||||
|  | ||||
|     ret = virStreamRecv(stream->st, buffer, bufferLen); | ||||
|     if (ret == -2) { | ||||
|         /* Should never get this, since we're only called when we know | ||||
|          * we're readable, but hey things change... */ | ||||
|         ret = 0; | ||||
|     } else if (ret < 0) { | ||||
|         virNetMessagePtr msg; | ||||
|         virNetMessageError rerr; | ||||
|  | ||||
|         memset(&rerr, 0, sizeof(rerr)); | ||||
|  | ||||
|         if (!(msg = virNetMessageNew(false))) | ||||
|             ret = -1; | ||||
|         else | ||||
|             ret = virNetServerProgramSendStreamError(remoteProgram, | ||||
|                                                      client, | ||||
|                                                      msg, | ||||
|                                                      &rerr, | ||||
|                                                      stream->procedure, | ||||
|                                                      stream->serial); | ||||
|     } else { | ||||
|         virNetMessagePtr msg; | ||||
|         stream->tx = 0; | ||||
|         if (ret == 0) | ||||
|             stream->recvEOF = 1; | ||||
|         if (!(msg = virNetMessageNew(false))) | ||||
|             ret = -1; | ||||
|  | ||||
|         if (msg) { | ||||
|             msg->cb = daemonStreamMessageFinished; | ||||
|             msg->opaque = stream; | ||||
|             stream->refs++; | ||||
|             ret = virNetServerProgramSendStreamData(remoteProgram, | ||||
|                                                     client, | ||||
|                                                     msg, | ||||
|                                                     stream->procedure, | ||||
|                                                     stream->serial, | ||||
|                                                     buffer, ret); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     VIR_FREE(buffer); | ||||
|     return ret; | ||||
| } | ||||
| @@ -1,51 +0,0 @@ | ||||
| /* | ||||
|  * stream.h: APIs for managing client streams | ||||
|  * | ||||
|  * Copyright (C) 2009 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, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA | ||||
|  * | ||||
|  * Author: Daniel P. Berrange <berrange@redhat.com> | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef __LIBVIRTD_STREAM_H__ | ||||
| # define __LIBVIRTD_STREAM_H__ | ||||
|  | ||||
| # include "libvirtd.h" | ||||
|  | ||||
|  | ||||
|  | ||||
| daemonClientStream * | ||||
| daemonCreateClientStream(virNetServerClientPtr client, | ||||
|                          virStreamPtr st, | ||||
|                          virNetServerProgramPtr prog, | ||||
|                          virNetMessageHeaderPtr hdr); | ||||
|  | ||||
| int daemonFreeClientStream(virNetServerClientPtr client, | ||||
|                            daemonClientStream *stream); | ||||
|  | ||||
| int daemonAddClientStream(virNetServerClientPtr client, | ||||
|                           daemonClientStream *stream, | ||||
|                           bool transmit); | ||||
|  | ||||
| int | ||||
| daemonRemoveClientStream(virNetServerClientPtr client, | ||||
|                          daemonClientStream *stream); | ||||
|  | ||||
| void | ||||
| daemonRemoveAllClientStreams(daemonClientStream *stream); | ||||
|  | ||||
| #endif /* __LIBVIRTD_STREAM_H__ */ | ||||
| @@ -1,553 +0,0 @@ | ||||
| module Test_libvirtd = | ||||
|    let conf = "# Master libvirt daemon configuration file | ||||
| # | ||||
| # For further information consult http://libvirt.org/format.html | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Network connectivity controls | ||||
| # | ||||
|  | ||||
| # Flag listening for secure TLS connections on the public TCP/IP port. | ||||
| # NB, must pass the --listen flag to the libvirtd process for this to | ||||
| # have any effect. | ||||
| # | ||||
| # It is necessary to setup a CA and issue server certificates before | ||||
| # using this capability. | ||||
| # | ||||
| # This is enabled by default, uncomment this to disable it | ||||
| listen_tls = 0 | ||||
|  | ||||
| # Listen for unencrypted TCP connections on the public TCP/IP port. | ||||
| # NB, must pass the --listen flag to the libvirtd process for this to | ||||
| # have any effect. | ||||
| # | ||||
| # Using the TCP socket requires SASL authentication by default. Only | ||||
| # SASL mechanisms which support data encryption are allowed. This is | ||||
| # DIGEST_MD5 and GSSAPI (Kerberos5) | ||||
| # | ||||
| # This is disabled by default, uncomment this to enable it. | ||||
| listen_tcp = 1 | ||||
|  | ||||
|  | ||||
|  | ||||
| # Override the port for accepting secure TLS connections | ||||
| # This can be a port number, or service name | ||||
| # | ||||
| tls_port = \"16514\" | ||||
|  | ||||
| # Override the port for accepting insecure TCP connections | ||||
| # This can be a port number, or service name | ||||
| # | ||||
| tcp_port = \"16509\" | ||||
|  | ||||
|  | ||||
| # Override the default configuration which binds to all network | ||||
| # interfaces. This can be a numeric IPv4/6 address, or hostname | ||||
| # | ||||
| listen_addr = \"192.168.0.1\" | ||||
|  | ||||
|  | ||||
| # Flag toggling mDNS advertizement of the libvirt service. | ||||
| # | ||||
| # Alternatively can disable for all services on a host by | ||||
| # stopping the Avahi daemon | ||||
| # | ||||
| # This is enabled by default, uncomment this to disable it | ||||
| mdns_adv = 0 | ||||
|  | ||||
| # Override the default mDNS advertizement name. This must be | ||||
| # unique on the immediate broadcast network. | ||||
| # | ||||
| # The default is \"Virtualization Host HOSTNAME\", where HOSTNAME | ||||
| # is subsituted for the short hostname of the machine (without domain) | ||||
| # | ||||
| mdns_name = \"Virtualization Host Joe Demo\" | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # UNIX socket access controls | ||||
| # | ||||
|  | ||||
| # Set the UNIX domain socket group ownership. This can be used to | ||||
| # allow a 'trusted' set of users access to management capabilities | ||||
| # without becoming root. | ||||
| # | ||||
| # This is restricted to 'root' by default. | ||||
| unix_sock_group = \"libvirt\" | ||||
|  | ||||
| # Set the UNIX socket permissions for the R/O socket. This is used | ||||
| # for monitoring VM status only | ||||
| # | ||||
| # Default allows any user. If setting group ownership may want to | ||||
| # restrict this to: | ||||
| unix_sock_ro_perms = \"0777\" | ||||
|  | ||||
| # Set the UNIX socket permissions for the R/W socket. This is used | ||||
| # for full management of VMs | ||||
| # | ||||
| # Default allows only root. If PolicyKit is enabled on the socket, | ||||
| # the default will change to allow everyone (eg, 0777) | ||||
| # | ||||
| # If not using PolicyKit and setting group ownership for access | ||||
| # control then you may want to relax this to: | ||||
| unix_sock_rw_perms = \"0770\" | ||||
|  | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Authentication. | ||||
| # | ||||
| #  - none: do not perform auth checks. If you can connect to the | ||||
| #          socket you are allowed. This is suitable if there are | ||||
| #          restrictions on connecting to the socket (eg, UNIX | ||||
| #          socket permissions), or if there is a lower layer in | ||||
| #          the network providing auth (eg, TLS/x509 certificates) | ||||
| # | ||||
| #  - sasl: use SASL infrastructure. The actual auth scheme is then | ||||
| #          controlled from /etc/sasl2/libvirt.conf. For the TCP | ||||
| #          socket only GSSAPI & DIGEST-MD5 mechanisms will be used. | ||||
| #          For non-TCP or TLS sockets,  any scheme is allowed. | ||||
| # | ||||
| #  - polkit: use PolicyKit to authenticate. This is only suitable | ||||
| #            for use on the UNIX sockets. The default policy will | ||||
| #            require a user to supply their own password to gain | ||||
| #            full read/write access (aka sudo like), while anyone | ||||
| #            is allowed read/only access. | ||||
| # | ||||
| # Set an authentication scheme for UNIX read-only sockets | ||||
| # By default socket permissions allow anyone to connect | ||||
| # | ||||
| # To restrict monitoring of domains you may wish to enable | ||||
| # an authentication mechanism here | ||||
| auth_unix_ro = \"none\" | ||||
|  | ||||
| # Set an authentication scheme for UNIX read-write sockets | ||||
| # By default socket permissions only allow root. If PolicyKit | ||||
| # support was compiled into libvirt, the default will be to | ||||
| # use 'polkit' auth. | ||||
| # | ||||
| # If the unix_sock_rw_perms are changed you may wish to enable | ||||
| # an authentication mechanism here | ||||
| auth_unix_rw = \"none\" | ||||
|  | ||||
| # Change the authentication scheme for TCP sockets. | ||||
| # | ||||
| # If you don't enable SASL, then all TCP traffic is cleartext. | ||||
| # Don't do this outside of a dev/test scenario. For real world | ||||
| # use, always enable SASL and use the GSSAPI or DIGEST-MD5 | ||||
| # mechanism in /etc/sasl2/libvirt.conf | ||||
| auth_tcp = \"sasl\" | ||||
|  | ||||
| # Change the authentication scheme for TLS sockets. | ||||
| # | ||||
| # TLS sockets already have encryption provided by the TLS | ||||
| # layer, and limited authentication is done by certificates | ||||
| # | ||||
| # It is possible to make use of any SASL authentication | ||||
| # mechanism as well, by using 'sasl' for this option | ||||
| auth_tls = \"none\" | ||||
|  | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # TLS x509 certificate configuration | ||||
| # | ||||
|  | ||||
|  | ||||
| # Override the default server key file path | ||||
| # | ||||
| key_file = \"/etc/pki/libvirt/private/serverkey.pem\" | ||||
|  | ||||
| # Override the default server certificate file path | ||||
| # | ||||
| cert_file = \"/etc/pki/libvirt/servercert.pem\" | ||||
|  | ||||
| # Override the default CA certificate path | ||||
| # | ||||
| ca_file = \"/etc/pki/CA/cacert.pem\" | ||||
|  | ||||
| # Specify a certificate revocation list. | ||||
| # | ||||
| # Defaults to not using a CRL, uncomment to enable it | ||||
| crl_file = \"/etc/pki/CA/crl.pem\" | ||||
|  | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Authorization controls | ||||
| # | ||||
|  | ||||
|  | ||||
| # Flag to disable verification of client certificates | ||||
| # | ||||
| # Client certificate verification is the primary authentication mechanism. | ||||
| # Any client which does not present a certificate signed by the CA | ||||
| # will be rejected. | ||||
| # | ||||
| # Default is to always verify. Uncommenting this will disable | ||||
| # verification - make sure an IP whitelist is set | ||||
| tls_no_verify_certificate = 1 | ||||
| tls_no_sanity_certificate = 1 | ||||
|  | ||||
|  | ||||
| # A whitelist of allowed x509  Distinguished Names | ||||
| # This list may contain wildcards such as | ||||
| # | ||||
| #    \"C=GB,ST=London,L=London,O=Red Hat,CN=*\" | ||||
| # | ||||
| # See the POSIX fnmatch function for the format of the wildcards. | ||||
| # | ||||
| # NB If this is an empty list, no client can connect, so comment out | ||||
| # entirely rather than using empty list to disable these checks | ||||
| # | ||||
| # By default, no DN's are checked | ||||
|    tls_allowed_dn_list = [\"DN1\", \"DN2\"] | ||||
|  | ||||
|  | ||||
| # A whitelist of allowed SASL usernames. The format for usernames | ||||
| # depends on the SASL authentication mechanism. Kerberos usernames | ||||
| # look like username@REALM | ||||
| # | ||||
| # This list may contain wildcards such as | ||||
| # | ||||
| #    \"*@EXAMPLE.COM\" | ||||
| # | ||||
| # See the POSIX fnmatch function for the format of the wildcards. | ||||
| # | ||||
| # NB If this is an empty list, no client can connect, so comment out | ||||
| # entirely rather than using empty list to disable these checks | ||||
| # | ||||
| # By default, no Username's are checked | ||||
| sasl_allowed_username_list = [ | ||||
|   \"joe@EXAMPLE.COM\", | ||||
|   \"fred@EXAMPLE.COM\" | ||||
| ] | ||||
|  | ||||
|  | ||||
| ################################################################# | ||||
| # | ||||
| # Processing controls | ||||
| # | ||||
|  | ||||
| # The maximum number of concurrent client connections to allow | ||||
| # over all sockets combined. | ||||
| max_clients = 20 | ||||
|  | ||||
|  | ||||
| # The minimum limit sets the number of workers to start up | ||||
| # initially. If the number of active clients exceeds this, | ||||
| # then more threads are spawned, upto max_workers limit. | ||||
| # Typically you'd want max_workers to equal maximum number | ||||
| # of clients allowed | ||||
| min_workers = 5 | ||||
| max_workers = 20 | ||||
|  | ||||
| # Total global limit on concurrent RPC calls. Should be | ||||
| # at least as large as max_workers. Beyond this, RPC requests | ||||
| # will be read into memory and queued. This directly impact | ||||
| # memory usage, currently each request requires 256 KB of | ||||
| # memory. So by default upto 5 MB of memory is used | ||||
| max_requests = 20 | ||||
|  | ||||
| # Limit on concurrent requests from a single client | ||||
| # connection. To avoid one client monopolizing the server | ||||
| # this should be a small fraction of the global max_requests | ||||
| # and max_workers parameter | ||||
| max_client_requests = 5 | ||||
|  | ||||
| # Logging level: | ||||
| log_level = 4 | ||||
|  | ||||
| # Logging outputs: | ||||
| log_outputs=\"4:stderr\" | ||||
|  | ||||
| # Logging filters: | ||||
| log_filters=\"a\" | ||||
|  | ||||
| # Auditing: | ||||
| audit_level = 2 | ||||
| " | ||||
|  | ||||
|    test Libvirtd.lns get conf = | ||||
|         { "#comment" = "Master libvirt daemon configuration file" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "For further information consult http://libvirt.org/format.html" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "################################################################" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Network connectivity controls" } | ||||
|         { "#comment" = "" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Flag listening for secure TLS connections on the public TCP/IP port." } | ||||
|         { "#comment" = "NB, must pass the --listen flag to the libvirtd process for this to" } | ||||
|         { "#comment" = "have any effect." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "It is necessary to setup a CA and issue server certificates before" } | ||||
|         { "#comment" = "using this capability." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "This is enabled by default, uncomment this to disable it" } | ||||
|         { "listen_tls" = "0" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Listen for unencrypted TCP connections on the public TCP/IP port." } | ||||
|         { "#comment" = "NB, must pass the --listen flag to the libvirtd process for this to" } | ||||
|         { "#comment" = "have any effect." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Using the TCP socket requires SASL authentication by default. Only" } | ||||
|         { "#comment" = "SASL mechanisms which support data encryption are allowed. This is" } | ||||
|         { "#comment" = "DIGEST_MD5 and GSSAPI (Kerberos5)" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "This is disabled by default, uncomment this to enable it." } | ||||
|         { "listen_tcp" = "1" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Override the port for accepting secure TLS connections" } | ||||
|         { "#comment" = "This can be a port number, or service name" } | ||||
|         { "#comment" = "" } | ||||
|         { "tls_port" = "16514" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Override the port for accepting insecure TCP connections" } | ||||
|         { "#comment" = "This can be a port number, or service name" } | ||||
|         { "#comment" = "" } | ||||
|         { "tcp_port" = "16509" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Override the default configuration which binds to all network" } | ||||
|         { "#comment" = "interfaces. This can be a numeric IPv4/6 address, or hostname" } | ||||
|         { "#comment" = "" } | ||||
|         { "listen_addr" = "192.168.0.1" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Flag toggling mDNS advertizement of the libvirt service." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Alternatively can disable for all services on a host by" } | ||||
|         { "#comment" = "stopping the Avahi daemon" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "This is enabled by default, uncomment this to disable it" } | ||||
|         { "mdns_adv" = "0" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Override the default mDNS advertizement name. This must be" } | ||||
|         { "#comment" = "unique on the immediate broadcast network." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "The default is \"Virtualization Host HOSTNAME\", where HOSTNAME" } | ||||
|         { "#comment" = "is subsituted for the short hostname of the machine (without domain)" } | ||||
|         { "#comment" = "" } | ||||
|         { "mdns_name" = "Virtualization Host Joe Demo" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "################################################################" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "UNIX socket access controls" } | ||||
|         { "#comment" = "" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Set the UNIX domain socket group ownership. This can be used to" } | ||||
|         { "#comment" = "allow a 'trusted' set of users access to management capabilities" } | ||||
|         { "#comment" = "without becoming root." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "This is restricted to 'root' by default." } | ||||
|         { "unix_sock_group" = "libvirt" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Set the UNIX socket permissions for the R/O socket. This is used" } | ||||
|         { "#comment" = "for monitoring VM status only" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Default allows any user. If setting group ownership may want to" } | ||||
|         { "#comment" = "restrict this to:" } | ||||
|         { "unix_sock_ro_perms" = "0777" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Set the UNIX socket permissions for the R/W socket. This is used" } | ||||
|         { "#comment" = "for full management of VMs" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Default allows only root. If PolicyKit is enabled on the socket," } | ||||
|         { "#comment" = "the default will change to allow everyone (eg, 0777)" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "If not using PolicyKit and setting group ownership for access" } | ||||
|         { "#comment" = "control then you may want to relax this to:" } | ||||
|         { "unix_sock_rw_perms" = "0770" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "################################################################" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Authentication." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "- none: do not perform auth checks. If you can connect to the" } | ||||
|         { "#comment" = "socket you are allowed. This is suitable if there are" } | ||||
|         { "#comment" = "restrictions on connecting to the socket (eg, UNIX" } | ||||
|         { "#comment" = "socket permissions), or if there is a lower layer in" } | ||||
|         { "#comment" = "the network providing auth (eg, TLS/x509 certificates)" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "- sasl: use SASL infrastructure. The actual auth scheme is then" } | ||||
|         { "#comment" = "controlled from /etc/sasl2/libvirt.conf. For the TCP" } | ||||
|         { "#comment" = "socket only GSSAPI & DIGEST-MD5 mechanisms will be used." } | ||||
|         { "#comment" = "For non-TCP or TLS sockets,  any scheme is allowed." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "- polkit: use PolicyKit to authenticate. This is only suitable" } | ||||
|         { "#comment" = "for use on the UNIX sockets. The default policy will" } | ||||
|         { "#comment" = "require a user to supply their own password to gain" } | ||||
|         { "#comment" = "full read/write access (aka sudo like), while anyone" } | ||||
|         { "#comment" = "is allowed read/only access." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Set an authentication scheme for UNIX read-only sockets" } | ||||
|         { "#comment" = "By default socket permissions allow anyone to connect" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "To restrict monitoring of domains you may wish to enable" } | ||||
|         { "#comment" = "an authentication mechanism here" } | ||||
|         { "auth_unix_ro" = "none" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Set an authentication scheme for UNIX read-write sockets" } | ||||
|         { "#comment" = "By default socket permissions only allow root. If PolicyKit" } | ||||
|         { "#comment" = "support was compiled into libvirt, the default will be to" } | ||||
|         { "#comment" = "use 'polkit' auth." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "If the unix_sock_rw_perms are changed you may wish to enable" } | ||||
|         { "#comment" = "an authentication mechanism here" } | ||||
|         { "auth_unix_rw" = "none" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Change the authentication scheme for TCP sockets." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "If you don't enable SASL, then all TCP traffic is cleartext." } | ||||
|         { "#comment" = "Don't do this outside of a dev/test scenario. For real world" } | ||||
|         { "#comment" = "use, always enable SASL and use the GSSAPI or DIGEST-MD5" } | ||||
|         { "#comment" = "mechanism in /etc/sasl2/libvirt.conf" } | ||||
|         { "auth_tcp" = "sasl" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Change the authentication scheme for TLS sockets." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "TLS sockets already have encryption provided by the TLS" } | ||||
|         { "#comment" = "layer, and limited authentication is done by certificates" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "It is possible to make use of any SASL authentication" } | ||||
|         { "#comment" = "mechanism as well, by using 'sasl' for this option" } | ||||
|         { "auth_tls" = "none" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "################################################################" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "TLS x509 certificate configuration" } | ||||
|         { "#comment" = "" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Override the default server key file path" } | ||||
|         { "#comment" = "" } | ||||
|         { "key_file" = "/etc/pki/libvirt/private/serverkey.pem" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Override the default server certificate file path" } | ||||
|         { "#comment" = "" } | ||||
|         { "cert_file" = "/etc/pki/libvirt/servercert.pem" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Override the default CA certificate path" } | ||||
|         { "#comment" = "" } | ||||
|         { "ca_file" = "/etc/pki/CA/cacert.pem" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Specify a certificate revocation list." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Defaults to not using a CRL, uncomment to enable it" } | ||||
|         { "crl_file" = "/etc/pki/CA/crl.pem" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "################################################################" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Authorization controls" } | ||||
|         { "#comment" = "" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "Flag to disable verification of client certificates" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Client certificate verification is the primary authentication mechanism." } | ||||
|         { "#comment" = "Any client which does not present a certificate signed by the CA" } | ||||
|         { "#comment" = "will be rejected." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "Default is to always verify. Uncommenting this will disable" } | ||||
|         { "#comment" = "verification - make sure an IP whitelist is set" } | ||||
|         { "tls_no_verify_certificate" = "1" } | ||||
|         { "tls_no_sanity_certificate" = "1" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "A whitelist of allowed x509  Distinguished Names" } | ||||
|         { "#comment" = "This list may contain wildcards such as" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "\"C=GB,ST=London,L=London,O=Red Hat,CN=*\"" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "See the POSIX fnmatch function for the format of the wildcards." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "NB If this is an empty list, no client can connect, so comment out" } | ||||
|         { "#comment" = "entirely rather than using empty list to disable these checks" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "By default, no DN's are checked" } | ||||
|         { "tls_allowed_dn_list" | ||||
|              { "1" = "DN1"} | ||||
|              { "2" = "DN2"} | ||||
|         } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "A whitelist of allowed SASL usernames. The format for usernames" } | ||||
|         { "#comment" = "depends on the SASL authentication mechanism. Kerberos usernames" } | ||||
|         { "#comment" = "look like username@REALM" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "This list may contain wildcards such as" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "\"*@EXAMPLE.COM\"" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "See the POSIX fnmatch function for the format of the wildcards." } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "NB If this is an empty list, no client can connect, so comment out" } | ||||
|         { "#comment" = "entirely rather than using empty list to disable these checks" } | ||||
|         { "#comment" = "" } | ||||
|         { "#comment" = "By default, no Username's are checked" } | ||||
|         { "sasl_allowed_username_list" | ||||
|              { "1" = "joe@EXAMPLE.COM" } | ||||
|              { "2" = "fred@EXAMPLE.COM" } | ||||
|         } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "################################################################"} | ||||
|         { "#comment" = ""} | ||||
|         { "#comment" = "Processing controls"} | ||||
|         { "#comment" = ""} | ||||
|         { "#empty" } | ||||
|         { "#comment" = "The maximum number of concurrent client connections to allow"} | ||||
|         { "#comment" = "over all sockets combined."} | ||||
|         { "max_clients" = "20" } | ||||
|         { "#empty" } | ||||
|         { "#empty" } | ||||
|         { "#comment" = "The minimum limit sets the number of workers to start up"} | ||||
|         { "#comment" = "initially. If the number of active clients exceeds this,"} | ||||
|         { "#comment" = "then more threads are spawned, upto max_workers limit."} | ||||
|         { "#comment" = "Typically you'd want max_workers to equal maximum number"} | ||||
|         { "#comment" = "of clients allowed"} | ||||
|         { "min_workers" = "5" } | ||||
|         { "max_workers" = "20" } | ||||
| 	{ "#empty" } | ||||
|         { "#comment" = "Total global limit on concurrent RPC calls. Should be" } | ||||
|         { "#comment" = "at least as large as max_workers. Beyond this, RPC requests" } | ||||
|         { "#comment" = "will be read into memory and queued. This directly impact" } | ||||
|         { "#comment" = "memory usage, currently each request requires 256 KB of" } | ||||
|         { "#comment" = "memory. So by default upto 5 MB of memory is used" } | ||||
|         { "max_requests" = "20" } | ||||
| 	{ "#empty" } | ||||
|         { "#comment" = "Limit on concurrent requests from a single client" } | ||||
|         { "#comment" = "connection. To avoid one client monopolizing the server" } | ||||
|         { "#comment" = "this should be a small fraction of the global max_requests" } | ||||
|         { "#comment" = "and max_workers parameter" } | ||||
|         { "max_client_requests" = "5" } | ||||
| 	{ "#empty" } | ||||
|         { "#comment" = "Logging level:" } | ||||
|         { "log_level" = "4" } | ||||
| 	{ "#empty" } | ||||
|         { "#comment" = "Logging outputs:" } | ||||
|         { "log_outputs" = "4:stderr" } | ||||
| 	{ "#empty" } | ||||
|         { "#comment" = "Logging filters:" } | ||||
|         { "log_filters" = "a" } | ||||
| 	{ "#empty" } | ||||
|         { "#comment" = "Auditing:" } | ||||
|         { "audit_level" = "2" } | ||||
							
								
								
									
										8
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,8 +0,0 @@ | ||||
| Makefile | ||||
| Makefile.in | ||||
| .memdump | ||||
| apibuild.pyc | ||||
| *.html | ||||
| libvirt-api.xml | ||||
| libvirt-refs.xml | ||||
| todo.html.in | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 783 B | 
							
								
								
									
										227
									
								
								docs/Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										227
									
								
								docs/Makefile.am
									
									
									
									
									
								
							| @@ -1,227 +0,0 @@ | ||||
| ## Process this file with automake to produce Makefile.in | ||||
|  | ||||
| ## Copyright (C) 2005-2011 Red Hat, Inc. | ||||
| ## See COPYING.LIB for the License of this software | ||||
|  | ||||
| SUBDIRS= schemas | ||||
|  | ||||
| PERL = perl | ||||
|  | ||||
| # The directory containing the source code (if it contains documentation). | ||||
| DOC_SOURCE_DIR=../src | ||||
|  | ||||
| DEVHELP_DIR=$(datadir)/gtk-doc/html/libvirt | ||||
|  | ||||
| BUILT_SOURCES=hvsupport.html.in | ||||
|  | ||||
| apihtml =			\ | ||||
|   html/index.html		\ | ||||
|   html/libvirt-libvirt.html	\ | ||||
|   html/libvirt-virterror.html | ||||
|  | ||||
| apipng =	\ | ||||
|   html/left.png	\ | ||||
|   html/up.png	\ | ||||
|   html/home.png	\ | ||||
|   html/right.png | ||||
|  | ||||
| devhelphtml =			\ | ||||
|   devhelp/libvirt.devhelp	\ | ||||
|   devhelp/index.html		\ | ||||
|   devhelp/general.html		\ | ||||
|   devhelp/libvirt-libvirt.html	\ | ||||
|   devhelp/libvirt-virterror.html | ||||
|  | ||||
| css =         \ | ||||
|   generic.css \ | ||||
|   libvirt.css \ | ||||
|   main.css | ||||
|  | ||||
| devhelppng =		\ | ||||
|   devhelp/home.png	\ | ||||
|   devhelp/left.png	\ | ||||
|   devhelp/right.png	\ | ||||
|   devhelp/up.png | ||||
|  | ||||
| devhelpcss = devhelp/style.css | ||||
|  | ||||
| devhelpxsl = devhelp/devhelp.xsl devhelp/html.xsl | ||||
|  | ||||
| png = \ | ||||
|   32favicon.png \ | ||||
|   footer_corner.png \ | ||||
|   footer_pattern.png \ | ||||
|   libvirt-header-bg.png \ | ||||
|   libvirt-header-logo.png \ | ||||
|   libvirtLogo.png \ | ||||
|   libvirt-net-logical.png \ | ||||
|   libvirt-net-physical.png \ | ||||
|   libvirt-daemon-arch.png \ | ||||
|   libvirt-driver-arch.png \ | ||||
|   libvirt-object-model.png \ | ||||
|   madeWith.png \ | ||||
|   et.png | ||||
|  | ||||
| gif = \ | ||||
|   architecture.gif \ | ||||
|   node.gif | ||||
|  | ||||
| dot_html_in = $(notdir $(wildcard $(srcdir)/*.html.in)) todo.html.in hvsupport.html.in \ | ||||
|       $(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/internals/*.html.in)) | ||||
| dot_html = $(dot_html_in:%.html.in=%.html) | ||||
|  | ||||
| patches = $(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/api_extension/*.patch)) | ||||
|  | ||||
| xml = \ | ||||
|   libvirt-api.xml \ | ||||
|   libvirt-refs.xml | ||||
|  | ||||
| qemu_xml = \ | ||||
|   libvirt-qemu-api.xml \ | ||||
|   libvirt-qemu-refs.xml | ||||
|  | ||||
| fig = \ | ||||
|   libvirt-net-logical.fig \ | ||||
|   libvirt-net-physical.fig \ | ||||
|   libvirt-daemon-arch.fig \ | ||||
|   libvirt-driver-arch.fig \ | ||||
|   libvirt-object-model.fig | ||||
|  | ||||
| EXTRA_DIST=					\ | ||||
|   apibuild.py \ | ||||
|   site.xsl newapi.xsl news.xsl page.xsl \ | ||||
|   hacking1.xsl hacking2.xsl wrapstring.xsl \ | ||||
|   $(dot_html) $(dot_html_in) $(gif) $(apihtml) $(apipng) \ | ||||
|   $(devhelphtml) $(devhelppng) $(devhelpcss) $(devhelpxsl) \ | ||||
|   $(xml) $(qemu_xml) $(fig) $(png) $(css) \ | ||||
|   $(patches) \ | ||||
|   sitemap.html.in \ | ||||
|   todo.pl hvsupport.pl todo.cfg-example | ||||
|  | ||||
| MAINTAINERCLEANFILES = \ | ||||
|   $(addprefix $(srcdir)/,$(dot_html)) \ | ||||
|   $(addprefix $(srcdir)/,$(apihtml)) \ | ||||
|   $(addprefix $(srcdir)/,$(devhelphtml)) | ||||
|  | ||||
| all: web | ||||
|  | ||||
| api: $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml | ||||
| qemu_api: $(srcdir)/libvirt-qemu-api.xml $(srcdir)/libvirt-qemu-refs.xml | ||||
|  | ||||
| web: $(dot_html) html/index.html devhelp/index.html | ||||
|  | ||||
| todo.html.in: todo.pl | ||||
| 	if [ -f  todo.cfg ]; then \ | ||||
| 		echo "Generating $@"; \ | ||||
| 		$(PERL) $< > $@ \ | ||||
| 		|| { rm $@ && exit 1; }; \ | ||||
| 	else \ | ||||
| 		echo "Stubbing $@"; \ | ||||
| 		echo "<html><body><h1>Todo list</h1></body></html>" > $@ ; \ | ||||
| 	fi | ||||
|  | ||||
| todo: | ||||
| 	rm -f todo.html.in | ||||
| 	$(MAKE) todo.html | ||||
|  | ||||
| hvsupport.html.in: $(srcdir)/hvsupport.pl $(srcdir)/../src/libvirt_public.syms \ | ||||
| 	 $(srcdir)/../src/libvirt_qemu.syms $(srcdir)/../src/driver.h | ||||
| 	$(AM_V_GEN)$(PERL) $(srcdir)/hvsupport.pl $(srcdir)/../src > $@ || { rm $@ && exit 1; } | ||||
|  | ||||
| .PHONY: todo | ||||
|  | ||||
| %.png: %.fig | ||||
| 	convert -rotate 90 $< $@ | ||||
|  | ||||
| internals/%.html.tmp: internals/%.html.in subsite.xsl page.xsl sitemap.html.in | ||||
| 	@if [ -x $(XSLTPROC) ] ; then \ | ||||
| 	  echo "Generating $@"; \ | ||||
| 	  $(MKDIR_P) internals; \ | ||||
| 	  name=`echo $@ | sed -e 's/.tmp//'`; \ | ||||
| 	  $(XSLTPROC) --stringparam pagename $$name --nonet --html \ | ||||
| 	    $(top_srcdir)/docs/subsite.xsl $< > $@ \ | ||||
| 	    || { rm $@ && exit 1; }; fi | ||||
|  | ||||
| %.html.tmp: %.html.in site.xsl page.xsl sitemap.html.in | ||||
| 	@if [ -x $(XSLTPROC) ] ; then \ | ||||
| 	  echo "Generating $@"; \ | ||||
| 	  name=`echo $@ | sed -e 's/.tmp//'`; \ | ||||
| 	  $(XSLTPROC) --stringparam pagename $$name --nonet --html \ | ||||
| 	    $(top_srcdir)/docs/site.xsl $< > $@ \ | ||||
| 	    || { rm $@ && exit 1; }; fi | ||||
|  | ||||
| %.html: %.html.tmp | ||||
| 	@if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \ | ||||
| 	  if $(XMLCATALOG) '$(XML_CATALOG_FILE)' \ | ||||
| 	    "-//W3C//DTD XHTML 1.0 Strict//EN" > /dev/null ; then \ | ||||
| 	  echo "Validating $@" ; \ | ||||
| 	  SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \ | ||||
| 	  $(XMLLINT) --catalogs --nonet --format --valid $< > $(srcdir)/$@ \ | ||||
| 	  || { rm $(srcdir)/$@ && exit 1; }; \ | ||||
| 	  else echo "missing XHTML1 DTD" ; fi ; fi | ||||
|  | ||||
|  | ||||
| html/index.html: libvirt-api.xml newapi.xsl page.xsl sitemap.html.in | ||||
| 	$(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \ | ||||
| 	  $(XSLTPROC) --nonet -o $(srcdir)/ \ | ||||
| 	  $(srcdir)/newapi.xsl $(srcdir)/libvirt-api.xml ; fi && \ | ||||
| 	if test -x $(XMLLINT) && test -x $(XMLCATALOG) ; then \ | ||||
| 	  if $(XMLCATALOG) '$(XML_CATALOG_FILE)' "-//W3C//DTD XHTML 1.0 Strict//EN" \ | ||||
| 	    > /dev/null ; then \ | ||||
| 	  SGML_CATALOG_FILES='$(XML_CATALOG_FILE)' \ | ||||
| 	  $(XMLLINT) --catalogs --nonet --valid --noout $(srcdir)/html/*.html ; \ | ||||
| 	  else echo "missing XHTML1 DTD" ; fi ; fi | ||||
|  | ||||
| $(addprefix $(srcdir)/,$(devhelphtml)): $(srcdir)/libvirt-api.xml $(devhelpxsl) | ||||
| 	$(AM_V_GEN)if [ -x $(XSLTPROC) ] ; then \ | ||||
| 	  $(XSLTPROC) --nonet -o $(srcdir)/devhelp/ \ | ||||
| 	  $(top_srcdir)/docs/devhelp/devhelp.xsl $(srcdir)/libvirt-api.xml ; fi | ||||
|  | ||||
|  | ||||
| python_generated_files = \ | ||||
| 		$(srcdir)/html/libvirt-libvirt.html \ | ||||
| 		$(srcdir)/html/libvirt-libvirt-qemu.html \ | ||||
| 		$(srcdir)/html/libvirt-virterror.html \ | ||||
| 		$(srcdir)/libvirt-api.xml \ | ||||
| 		$(srcdir)/libvirt-refs.xml \ | ||||
| 		$(srcdir)/libvirt-qemu-api.xml \ | ||||
| 		$(srcdir)/libvirt-qemu-refs.xml | ||||
|  | ||||
| $(python_generated_files): $(srcdir)/apibuild.py \ | ||||
| 		$(srcdir)/../include/libvirt/*.h \ | ||||
| 		$(srcdir)/../src/libvirt.c \ | ||||
| 		$(srcdir)/../src/libvirt-qemu.c \ | ||||
| 		$(srcdir)/../src/util/virterror.c | ||||
| 	$(AM_V_GEN)srcdir=$(srcdir) $(PYTHON) $(srcdir)/apibuild.py | ||||
|  | ||||
| check-local: all | ||||
|  | ||||
| clean-local: | ||||
| 	rm -f *~ *.bak *.hierarchy *.signals *-unused.txt *.html | ||||
|  | ||||
| maintainer-clean-local: clean-local | ||||
| 	rm -rf $(srcdir)/libvirt-api.xml $(srcdir)/libvirt-refs.xml todo.html.in hvsupport.html.in | ||||
| 	rm -rf $(srcdir)/libvirt-qemu-api.xml $(srcdir)/libvirt-qemu-refs.xml | ||||
|  | ||||
| rebuild: api qemu_api all | ||||
|  | ||||
| install-data-local: | ||||
| 	$(mkinstalldirs) $(DESTDIR)$(HTML_DIR) | ||||
| 	for f in $(css) $(dot_html) $(gif) $(png); do \ | ||||
| 	  $(INSTALL) -m 0644 $(srcdir)/$$f $(DESTDIR)$(HTML_DIR); done | ||||
| 	$(mkinstalldirs) $(DESTDIR)$(HTML_DIR)/html | ||||
| 	for h in $(apihtml); do \ | ||||
| 	  $(INSTALL) -m 0644 $(srcdir)/$$h $(DESTDIR)$(HTML_DIR)/html; done | ||||
| 	for p in $(apipng); do \ | ||||
| 	  $(INSTALL) -m 0644 $(srcdir)/$$p $(DESTDIR)$(HTML_DIR)/html; done | ||||
| 	$(mkinstalldirs) $(DESTDIR)$(DEVHELP_DIR) | ||||
| 	for file in $(devhelphtml) $(devhelppng) $(devhelpcss); do \ | ||||
| 	    $(INSTALL) -m 0644 $(srcdir)/$${file} $(DESTDIR)$(DEVHELP_DIR) ; \ | ||||
| 	done | ||||
|  | ||||
| uninstall-local: | ||||
| 	for h in $(apihtml); do rm $(DESTDIR)$(HTML_DIR)/$$h; done | ||||
| 	for p in $(apipng); do rm $(DESTDIR)$(HTML_DIR)/$$p; done | ||||
| 	for f in $(devhelphtml) $(devhelppng) $(devhelpcss); do \ | ||||
| 	  rm $(DESTDIR)$(DEVHELP_DIR)/$$(basename $$f); \ | ||||
| 	done | ||||
							
								
								
									
										126
									
								
								docs/api.html.in
									
									
									
									
									
								
							
							
						
						
									
										126
									
								
								docs/api.html.in
									
									
									
									
									
								
							| @@ -1,126 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>The libvirt API concepts</h1> | ||||
|  | ||||
|     <p> This page describes the main principles and architecture choices | ||||
|     behind the definition of the libvirt API:</p> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="Objects">Objects exposed</a></h2> | ||||
|     <p> As defined in the <a href="goals.html">goals section</a>, libvirt | ||||
|     API need to expose all the resources needed to manage the virtualization | ||||
|     support of recent operating systems. The first object manipulated though | ||||
|     the API is <code>virConnectPtr</code> which represent a connection to | ||||
|     an hypervisor. Any application using libvirt is likely to start using the | ||||
|     API by calling one of <a href="html/libvirt-libvirt.html#virConnectOpen" | ||||
|     >the virConnectOpen functions</a>. You will note that those functions take | ||||
|     a name argument which is actually an URI to select the right hypervisor to | ||||
|     open, this is needed to allow remote connections and also select between | ||||
|     different possible hypervisors (for example on a Linux system it may be | ||||
|     possible to use both KVM and LinuxContainers on the same node). A NULL | ||||
|     name will default to a preselected hypervisor but it's probably not a | ||||
|     wise thing to do in most cases. See the <a href="uri.html">connection | ||||
|     URI</a> page for a full descriptions of the values allowed.</p> | ||||
|     <p> Once the application obtained a <code class='docref'>virConnectPtr</code> | ||||
|     connection to the | ||||
|     hypervisor it can then use it to manage domains and related resources | ||||
|     available for virtualization like storage and networking. All those are | ||||
|     exposed as first class objects, and connected to the hypervisor connection | ||||
|     (and the node or cluster where it is available).</p> | ||||
|     <p class="image"> | ||||
|       <img alt="first class objects exposed by the API" | ||||
|            src="libvirt-object-model.png"/> | ||||
|     </p> | ||||
|     <p> The figure above shows the five main objects exported by the API:</p> | ||||
|     <ul> | ||||
|       <li>virConnectPtr: represent a connection to an hypervisor.</li> | ||||
|       <li>virDomainPtr: represent one domain either active or defined (i.e. | ||||
|       existing as permanent config file and storage but not currently running | ||||
|       on that node). The function <code class='docref'>virConnectListDomains</code> | ||||
|       allows to list all the IDs for the domains active on this hypervisor.</li> | ||||
|       <li>virNetworkPtr: represent one network either active or defined (i.e. | ||||
|       existing as permanent config file and storage but not currently activated. | ||||
|       The function <code class='docref'>virConnectListNetworks</code> | ||||
|       allows to list all the virtualization networks actived on this node.</li> | ||||
|       <li>virStorageVolPtr: represent one storage volume, usually this is used | ||||
|       as a block device available to one of the domains. The function | ||||
|       <code class="docref">virStorageVolLookupByPath</code> allows to find | ||||
|       the object based on its path on the node.</li> | ||||
|       <li>virStoragePoolPtr: represent a storage pool, i.e. a logical area | ||||
|       which can be used to allocate and store storage volumes. The function | ||||
|       <code class="docref">virStoragePoolLookupByVolume</code> allows to find | ||||
|       the storage pool containing a given storage volume.</li> | ||||
|     </ul> | ||||
|     <p> Most object manipulated by the library can also be represented using | ||||
|       XML descriptions. This is used primarily to create those object, but is | ||||
|       also helpful to modify or save their description back.</p> | ||||
|     <p> Domains, network and storage pools can be either <code>active</code> | ||||
|       i.e. either running or available for immediate use, or | ||||
|       <code>defined</code> in which case they are inactive but there is | ||||
|       a permanent definition available in the system for them. Based on this | ||||
|       thay can be activated dynamically in order to be used.</p> | ||||
|     <p> Most kind of object can also be named in various ways:</p> | ||||
|     <ul> | ||||
|       <li>by their <code>name</code>, an user friendly identifier but | ||||
|       whose unicity cannot be garanteed between two nodes.</li> | ||||
|       <li>by their <code>ID</code>, which is a runtime unique identifier | ||||
|       provided by the hypervisor for one given activation of the object, | ||||
|       but it becomes invalid once the resource is deactivated.</li > | ||||
|       <li>by their <code>UUID</code>, a 16 bytes unique identifier | ||||
|       as defined in <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>, | ||||
|       which is garanteed to be unique for long term usage and across a | ||||
|       set of nodes.</li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="Functions">Functions and naming | ||||
|       conventions</a></h2> | ||||
|     <p> The naming of the functions present in the library is usually | ||||
|       made of a prefix describing the object associated to the function | ||||
|       and a verb describing the action on that object.</p> | ||||
|     <p> For each first class object you will find apis | ||||
|       for the following actions:</p> | ||||
|     <ul> | ||||
|       <li><b>Lookup</b>:...LookupByName,</li> | ||||
|       <li><b>Enumeration</b>:virConnectList... and virConnectNumOf...: | ||||
|         those are used to enumerate a set of object available to an given | ||||
|         hypervisor connection like: | ||||
|         <code class='docref'>virConnectListDomains</code>, | ||||
|         <code class='docref'>virConnectNumOfDomains</code>, | ||||
|         <code class='docref'>virConnectListNetworks</code>, | ||||
|         <code class='docref'>virConnectListStoragePools</code>, etc.</li> | ||||
|       <li><b>Description</b>: ...GetInfo: those are generic accessor providing | ||||
|         a set of informations about an object, they are | ||||
|         <code class='docref'>virNodeGetInfo</code>, | ||||
|         <code class='docref'>virDomainGetInfo</code>, | ||||
|         <code class='docref'>virStoragePoolGetInfo</code>, | ||||
|         <code class='docref'>virStorageVolGetInfo</code>.</li> | ||||
|       <li><b>Accessors</b>: ...Get... and ...Set...: those are more specific | ||||
|         accessors to query or modify the given object, like | ||||
|         <code class='docref'>virConnectGetType</code>, | ||||
|         <code class='docref'>virDomainGetMaxMemory</code>, | ||||
|         <code class='docref'>virDomainSetMemory</code>, | ||||
|         <code class='docref'>virDomainGetVcpus</code>, | ||||
|         <code class='docref'>virStoragePoolSetAutostart</code>, | ||||
|         <code class='docref'>virNetworkGetBridgeName</code>, etc.</li> | ||||
|       <li><b>Creation</b>: </li> | ||||
|       <li><b>Destruction</b>: ... </li> | ||||
|     </ul> | ||||
|     <p> For more in-depth details of the storage related APIs see | ||||
|       <a href="storage.html">the storage management page</a>. | ||||
|     </p> | ||||
|     <h2><a name="Driver">The libvirt drivers</a></h2> | ||||
|     <p></p> | ||||
|     <p class="image"> | ||||
|       <img alt="The libvirt driver architecture" | ||||
|            src="libvirt-driver-arch.png"/> | ||||
|     </p> | ||||
|     <h2><a name="Remote">Daemon and remote access</a></h2> | ||||
|     <p></p> | ||||
|     <p class="image"> | ||||
|       <img alt="The libvirt daemon and remote architecture" | ||||
|            src="libvirt-daemon-arch.png"/> | ||||
|     </p> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,433 +0,0 @@ | ||||
| <html> | ||||
|   <head> | ||||
|     <title>Implementing a new API in Libvirt</title> | ||||
|   </head> | ||||
|  | ||||
|   <body> | ||||
|     <h1>Implementing a new API in Libvirt</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <p> | ||||
|       This document walks you through the process of implementing a new | ||||
|       API in libvirt.  It uses as an example the addition of an API for | ||||
|       separating maximum from current vcpu usage of a domain, over | ||||
|       the course of a fifteen-patch series. | ||||
|       Remember that new API consists of any new public functions, as | ||||
|       well as the addition of flags or extensions of XML used by | ||||
|       existing functions.  The example in this document adds both new | ||||
|       functions and an XML extension.  Not all libvirt API additions | ||||
|       require quite as many patches. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Before you begin coding, it is critical that you propose your | ||||
|       changes on the libvirt mailing list and get feedback on your ideas to | ||||
|       make sure what you're proposing fits with the general direction of the | ||||
|       project.  Even before doing a proof of concept implementation, send an | ||||
|       email giving an overview of the functionality you think should be | ||||
|       added to libvirt.  Someone may already be working on the feature you | ||||
|       want.  Also, recognize that everything you write is likely to undergo | ||||
|       significant rework as you discuss it with the other developers, so | ||||
|       don't wait too long before getting feedback.  In the vcpu example | ||||
|       below, list feedback was first requested | ||||
|       <a href="https://www.redhat.com/archives/libvir-list/2010-September/msg00423.html">here</a> | ||||
|       and resulted in several rounds of improvements before coding | ||||
|       began.  In turn, this example is slightly rearranged from the actual | ||||
|       order of the commits. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Adding a new API to libvirt is not difficult, but there are quite a | ||||
|       few steps.  This document assumes that you are familiar with C | ||||
|       programming and have checked out the libvirt code from the source code | ||||
|       repository and successfully built the existing tree.  Instructions on | ||||
|       how to check out and build the code can be found at: | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       <a href="http://libvirt.org/downloads.html">http://libvirt.org/downloads.html</a> | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Once you have a working development environment, the steps to create a | ||||
|       new API are: | ||||
|     </p> | ||||
|     <ol> | ||||
|       <li>define the public API</li> | ||||
|       <li>define the internal driver API</li> | ||||
|       <li>implement the public API</li> | ||||
|       <li>implement the remote protocol: | ||||
|         <ol> | ||||
|           <li>define the wire protocol format</li> | ||||
|           <li>implement the RPC client</li> | ||||
|           <li>implement the server side dispatcher</li> | ||||
|         </ol> | ||||
|       </li> | ||||
|       <li>use new API where appropriate in drivers</li> | ||||
|       <li>add virsh support</li> | ||||
|       <li>add common handling for new API</li> | ||||
|       <li>for each driver that can support the new API: | ||||
|         <ol> | ||||
|           <li>add prerequisite support</li> | ||||
|           <li>fully implement new API</li> | ||||
|         </ol> | ||||
|       </li> | ||||
|     </ol> | ||||
|  | ||||
|     <p> | ||||
|       It is, of course, possible to implement the pieces in any order, but | ||||
|       if the development tasks are completed in the order listed, the code | ||||
|       will compile after each step.  Given the number of changes required, | ||||
|       verification after each step is highly recommended. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Submit new code in the form shown in the example code: one patch | ||||
|       per step.  That's not to say submit patches before you have working | ||||
|       functionality--get the whole thing working and make sure you're happy | ||||
|       with it.  Then use git or some other version control system that lets | ||||
|       you rewrite your commit history and break patches into pieces so you | ||||
|       don't drop a big blob of code on the mailing list in one go. | ||||
|       Also, you should follow the upstream tree, and rebase your | ||||
|       series to adapt your patches to work with any other changes | ||||
|       that were accepted upstream during your development. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Don't mix anything else into the patches you submit.  The patches | ||||
|       should be the minimal changes required to implement the functionality | ||||
|       you're adding.  If you notice a bug in unrelated code (i.e., code you | ||||
|       don't have to touch to implement your API change) during development, | ||||
|       create a patch that just addresses that bug and submit it | ||||
|       separately. | ||||
|     </p> | ||||
|  | ||||
|     <p>With that said, let's begin.</p> | ||||
|  | ||||
|     <h2><a name='publicapi'>Defining the public API</a></h2> | ||||
|  | ||||
|     <p>The first task is to define the public API.  If the new API | ||||
|       involves an XML extension, you have to enhance the RelaxNG | ||||
|       schema and document the new elements or attributes:</p> | ||||
|  | ||||
|     <p><code> | ||||
|         docs/schemas/domain.rng<br/> | ||||
|         docs/formatdomain.html.in | ||||
|     </code></p> | ||||
|  | ||||
|     <p>If the API extension involves a new function, you have to add a | ||||
|       declaration in the public header, and arrange to export the | ||||
|       function name (symbol) so other programs can link against the | ||||
|       libvirt library and call the new function:</p> | ||||
|  | ||||
|     <p><code> | ||||
|         include/libvirt/libvirt.h.in | ||||
|         src/libvirt_public.syms | ||||
|     </code></p> | ||||
|  | ||||
|     <p> | ||||
|       This task is in many ways the most important to get right, since once | ||||
|       the API has been committed to the repository, it's libvirt's policy | ||||
|       never to change it.  Mistakes in the implementation are bugs that you | ||||
|       can fix.  Make a mistake in the API definition and you're stuck with | ||||
|       it, so think carefully about the interface and don't be afraid to | ||||
|       rework it as you go through the process of implementing it. | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0001-add-to-xml.patch">0001-add-to-xml.patch</a> | ||||
|     and <a href="api_extension/0002-add-new-public-API.patch">0002-add-new-public-API.patch</a> | ||||
|     for example code.</p> | ||||
|  | ||||
|     <h2><a name='internalapi'>Defining the internal API</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Each public API call is associated with a driver, such as a host | ||||
|       virtualization driver, a network virtualization driver, a storage | ||||
|       virtualization driver, a state driver, or a device monitor.  Adding | ||||
|       the internal API is ordinarily a matter of adding a new member to the | ||||
|       struct representing one of these drivers. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Of course, it's possible that the new API will involve the creation of | ||||
|       an entirely new driver type, in which case the changes will include the | ||||
|       creation of a new struct type to represent the new driver type. | ||||
|     </p> | ||||
|  | ||||
|     <p>The driver structs are defined in:</p> | ||||
|  | ||||
|     <p><code>src/driver.h</code></p> | ||||
|  | ||||
|     <p> | ||||
|       To define the internal API, first typedef the driver function | ||||
|       prototype and then add a new field for it to the relevant driver | ||||
|       struct.  Then, update all existing instances of the driver to | ||||
|       provide a <code>NULL</code> stub for the new function. | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0003-define-internal-driver-API.patch">0003-define-internal-driver-API.patch</a></p> | ||||
|  | ||||
|     <h2><a name='implpublic'>Implementing the public API</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Implementing the public API is largely a formality in which we wire up | ||||
|       public API to the internal driver API.  The public API implementation | ||||
|       takes care of some basic validity checks before passing control to the | ||||
|       driver implementation.  In RFC 2119 vocabulary, this function: | ||||
|     </p> | ||||
|  | ||||
|     <ol class="ordinarylist"> | ||||
|       <li>SHOULD log a message with VIR_DEBUG() indicating that it is | ||||
|         being called and its parameters;</li> | ||||
|       <li>MUST call virResetLastError();</li> | ||||
|       <li>SHOULD confirm that the connection is valid with | ||||
|         VIR_IS_CONNECT(conn);</li> | ||||
|       <li><strong>SECURITY: If the API requires a connection with write | ||||
|           privileges, MUST confirm that the connection flags do not | ||||
|           indicate that the connection is read-only;</strong></li> | ||||
|       <li>SHOULD do basic validation of the parameters that are being | ||||
|         passed in;</li> | ||||
|       <li>MUST confirm that the driver for this connection exists and that | ||||
|         it implements this function;</li> | ||||
|       <li>MUST call the internal API;</li> | ||||
|       <li>SHOULD log a message with VIR_DEBUG() indicating that it is | ||||
|         returning, its return value, and status.</li> | ||||
|       <li>MUST return status to the caller.</li> | ||||
|     </ol> | ||||
|  | ||||
|     <p>The public API calls are implemented in:</p> | ||||
|  | ||||
|     <p><code>src/libvirt.c</code></p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0004-implement-the-public-APIs.patch">0004-implement-the-public-APIs.patch</a></p> | ||||
|  | ||||
|     <h2><a name='remoteproto'>Implementing the remote protocol</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Implementing the remote protocol is essentially a | ||||
|       straightforward exercise which is probably most easily | ||||
|       understood by referring to the existing code and the example | ||||
|       patch.  It involves several related changes, including the | ||||
|       regeneration of derived files, with further details below. | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0005-implement-the-remote-protocol.patch">0005-implement-the-remote-protocol.patch</a></p> | ||||
|  | ||||
|     <h3><a name='wireproto'>Defining the wire protocol format</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       Defining the wire protocol involves making additions to: | ||||
|     </p> | ||||
|  | ||||
|     <p><code>src/remote/remote_protocol.x</code></p> | ||||
|  | ||||
|     <p> | ||||
|       First, create two new structs for each new function that you're adding | ||||
|       to the API.  One struct describes the parameters to be passed to the | ||||
|       remote function, and a second struct describes the value returned by | ||||
|       the remote function.  The one exception to this rule is that functions | ||||
|       that return only 0 or -1 for status do not require a struct for returned | ||||
|       data. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Second, add values to the remote_procedure enum for each new function | ||||
|       added to the API. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Once these changes are in place, it's necessary to run 'make rpcgen' | ||||
|       in the src directory to create the .c and .h files required by the | ||||
|       remote protocol code. This must be done on a Linux host using the | ||||
|       GLibC rpcgen program. Other rpcgen versions may generate code which | ||||
|       results in bogus compile time warnings.  This regenerates the | ||||
|       following files: | ||||
|     </p> | ||||
|  | ||||
|     <p><code> | ||||
|         daemon/remote_dispatch_args.h | ||||
|         daemon/remote_dispatch_prototypes.h | ||||
|         daemon/remote_dispatch_table.h | ||||
|         src/remote/remote_protocol.c | ||||
|         src/remote/remote_protocol.h | ||||
|     </code></p> | ||||
|  | ||||
|     <h3><a name='rpcclient'>Implement the RPC client</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       Implementing the uses the rpcgen generated .h files.  The remote | ||||
|       method calls go in: | ||||
|     </p> | ||||
|  | ||||
|     <p><code>src/remote/remote_internal.c</code></p> | ||||
|  | ||||
|     <p>Each remote method invocation does the following:</p> | ||||
|  | ||||
|     <ol class="ordinarylist"> | ||||
|       <li>locks the remote driver;</li> | ||||
|       <li>sets up the method arguments;</li> | ||||
|       <li>invokes the remote function;</li> | ||||
|       <li>checks the return value, if necessary;</li> | ||||
|       <li>extracts any returned data;</li> | ||||
|       <li>frees any returned data;</li> | ||||
|       <li>unlocks the remote driver.</li> | ||||
|     </ol> | ||||
|  | ||||
|     <h3><a name="serverdispatch">Implement the server side dispatcher</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       Implementing the server side of the remote function call is simply a | ||||
|       matter of deserializing the parameters passed in from the remote | ||||
|       caller and passing them to the corresponding internal API function. | ||||
|       The server side dispatchers are implemented in: | ||||
|     </p> | ||||
|  | ||||
|     <p><code>daemon/remote.c</code></p> | ||||
|  | ||||
|     <p>Again, this step uses the .h files generated by make rpcgen.</p> | ||||
|  | ||||
|     <p> | ||||
|       After all three pieces of the remote protocol are complete, and | ||||
|       the generated files have been updated, it will be necessary to | ||||
|       update the file:</p> | ||||
|  | ||||
|     <p><code>src/remote_protocol-structs</code></p> | ||||
|  | ||||
|     <p> | ||||
|       This file should only have new lines added; modifications to | ||||
|       existing lines probably imply a backwards-incompatible API change. | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0005-implement-the-remote-protocol.patch">0005-implement-the-remote-protocol.patch</a></p> | ||||
|  | ||||
|     <h2><a name="internaluseapi">Use the new API internally</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Sometimes, a new API serves as a superset of existing API, by | ||||
|       adding more granularity in what can be managed.  When this is | ||||
|       the case, it makes sense to share a common implementation by | ||||
|       making the older API become a trivial wrapper around the new | ||||
|       API, rather than duplicating the common code.  This step should | ||||
|       not introduce any semantic differences for the old API, and is | ||||
|       not necessary if the new API has no relation to existing API. | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0006-make-old-API-trivially-wrap-to-new-API.patch">0006-make-old-API-trivially-wrap-to-new-API.patch</a></p> | ||||
|  | ||||
|     <h2><a name="virshuseapi">Expose the new API in virsh</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       All new API should be manageable from the virsh command line | ||||
|       shell.  This proves that the API is sufficient for the intended | ||||
|       purpose, and helps to identify whether the proposed API needs | ||||
|       slight changes for easier usage.  However, remember that virsh | ||||
|       is used to connect to hosts running older versions of libvirtd, | ||||
|       so new commands should have fallbacks to an older API if | ||||
|       possible; implementing the virsh hooks at this point makes it | ||||
|       very easy to test these fallbacks.  Also remember to document | ||||
|       virsh additions. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       A virsh command is composed of a few pieces of code.  You need to | ||||
|       define an array of vshCmdInfo structs for each new command that | ||||
|       contain the help text and the command description text.  You also need | ||||
|       an array of vshCmdOptDef structs to describe the command options. | ||||
|       Once you have those pieces in place you can write the function | ||||
|       implementing the virsh command.  Finally, you need to add the new | ||||
|       command to the commands[] array.  The following files need changes: | ||||
|     </p> | ||||
|  | ||||
|     <p><code> | ||||
|         tools/virsh.c<br/> | ||||
|         tools/virsh.pod | ||||
|     </code></p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0007-add-virsh-support.patch">0007-add-virsh-support.patch</a></p> | ||||
|  | ||||
|     <h2><a name="driverimpl">Implement the driver methods</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       So, after all that, we get to the fun part.  All functionality in | ||||
|       libvirt is implemented inside a driver.  Thus, here is where you | ||||
|       implement whatever functionality you're adding to libvirt.  You'll | ||||
|       either need to add additional files to the src directory or extend | ||||
|       files that are already there, depending on what functionality you're | ||||
|       adding. | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="commonimpl">Implement common handling</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       If the new API is applicable to more than one driver, it may | ||||
|       make sense to provide some utility routines, or to factor some | ||||
|       of the work into the dispatcher, to avoid reimplementing the | ||||
|       same code in every driver.  In the example code, this involved | ||||
|       adding a member to the virDomainDefPtr struct for mapping | ||||
|       between the XML API addition and the in-memory representation of | ||||
|       a domain, along with updating all clients to use the new member. | ||||
|       Up to this point, there have been no changes to existing | ||||
|       semantics, and the new APIs will fail unless they are used in | ||||
|       the same way as the older API wrappers. | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0008-support-new-xml.patch">0008-support-new-xml.patch</a></p> | ||||
|  | ||||
|     <h3><a name="drivercode">Implement driver handling</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       The remaining patches should only touch one driver at a time. | ||||
|       It is possible to implement all changes for a driver in one | ||||
|       patch, but for review purposes it may still make sense to break | ||||
|       things into simpler steps.  Here is where the new APIs finally | ||||
|       start working. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       In the example patches, three separate drivers are supported: | ||||
|       test, qemu, and xen.  It is always a good idea to patch the test | ||||
|       driver in addition to the target driver, to prove that the API | ||||
|       can be used for more than one driver.  The example updates the | ||||
|       test driver in one patch: | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0009-support-all-flags-in-test-driver.patch">0009-support-all-flags-in-test-driver.patch</a></p> | ||||
|  | ||||
|     <p> | ||||
|       The qemu changes were easier to split into two phases, one for | ||||
|       updating the mapping between the new XML and the hypervisor | ||||
|       command line arguments, and one for supporting all possible | ||||
|       flags of the new API: | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0010-improve-vcpu-support-in-qemu-command-line.patch">0010-improve-vcpu-support-in-qemu-command-line.patch</a> | ||||
|       and <a href="api_extension/0011-complete-vcpu-support-in-qemu-driver.patch">0011-complete-vcpu-support-in-qemu-driver.patch</a></p> | ||||
|  | ||||
|     <p> | ||||
|       Finally, the example breaks the xen driver changes across four | ||||
|       patches.  One maps the XML changes to the hypervisor command, | ||||
|       the next two are independently implementing the getter and | ||||
|       setter APIs, and the last one provides cleanup of code that was | ||||
|       rendered dead by the new API. | ||||
|     </p> | ||||
|  | ||||
|     <p class="example">See <a href="api_extension/0012-improve-vcpu-support-in-xen-command-line.patch">0012-improve-vcpu-support-in-xen-command-line.patch</a>, | ||||
|       <a href="api_extension/0013-improve-getting-xen-vcpu-counts.patch">0013-improve-getting-xen-vcpu-counts.patch</a>, | ||||
|       <a href="api_extension/0014-improve-setting-xen-vcpu-counts.patch">0014-improve-setting-xen-vcpu-counts.patch</a>, | ||||
|       and <a href="api_extension/0015-remove-dead-xen-code.patch">0015-remove-dead-xen-code.patch</a></p> | ||||
|  | ||||
|     <p> | ||||
|       The exact details of the example code are probably uninteresting | ||||
|       unless you're concerned with virtual cpu management. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Once you have working functionality, run make check and make | ||||
|       syntax-check on each patch of the series before submitting | ||||
|       patches.  It may also be worth writing tests for the libvirt-TCK | ||||
|       testsuite to exercise your new API, although those patches are | ||||
|       not kept in the libvirt repository. | ||||
|     </p> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,145 +0,0 @@ | ||||
| From a74f4e44649906dcd82151f7ef837f66d7fa2ab1 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Mon, 27 Sep 2010 17:36:06 -0600 | ||||
| Subject: [PATCH 01/15] vcpu: add current attribute to <vcpu> element | ||||
|  | ||||
| Syntax agreed on in | ||||
| https://www.redhat.com/archives/libvir-list/2010-September/msg00476.html | ||||
|  | ||||
| <domain ...> | ||||
|   <vcpu current='x'>y</vcpu> | ||||
| ... | ||||
|  | ||||
| can now be used to specify 1 <= x <= y current vcpus, in relation | ||||
| to the boot-time max of y vcpus.  If current is omitted, then | ||||
| current and max are assumed to be the same value. | ||||
|  | ||||
| * docs/schemas/domain.rng: Add new attribute. | ||||
| * docs/formatdomain.html.in: Document it. | ||||
| * tests/qemuxml2argvdata/qemuxml2argv-smp.xml: Add to | ||||
| domainschematest. | ||||
| * tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml: Likewise. | ||||
| --- | ||||
|  docs/formatdomain.html.in                   |    9 +++++-- | ||||
|  docs/schemas/domain.rng                     |    5 ++++ | ||||
|  tests/qemuxml2argvdata/qemuxml2argv-smp.xml |   28 +++++++++++++++++++++++++++ | ||||
|  tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml  |   22 +++++++++++++++++++++ | ||||
|  4 files changed, 61 insertions(+), 3 deletions(-) | ||||
|  create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smp.xml | ||||
|  create mode 100644 tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml | ||||
|  | ||||
| diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in | ||||
| index a8a1fac..96de121 100644 | ||||
| --- a/docs/formatdomain.html.in | ||||
| +++ b/docs/formatdomain.html.in | ||||
| @@ -200,7 +200,7 @@ | ||||
|      <swap_hard_limit>2097152</swap_hard_limit> | ||||
|      <min_guarantee>65536</min_guarantee> | ||||
|    </memtune> | ||||
| -  <vcpu cpuset="1-4,^3,6">2</vcpu> | ||||
| +  <vcpu cpuset="1-4,^3,6" current="1">2</vcpu> | ||||
|    ...</pre> | ||||
|  | ||||
|      <dl> | ||||
| @@ -238,7 +238,7 @@ | ||||
|  	minimum memory allocation for the guest. The units for this value are | ||||
|  	kilobytes (i.e. blocks of 1024 bytes)</dd> | ||||
|        <dt><code>vcpu</code></dt> | ||||
| -      <dd>The content of this element defines the number of virtual | ||||
| +      <dd>The content of this element defines the maximum number of virtual | ||||
|          CPUs allocated for the guest OS, which must be between 1 and | ||||
|          the maximum supported by the hypervisor.  <span class="since">Since | ||||
|          0.4.4</span>, this element can contain an optional | ||||
| @@ -246,7 +246,10 @@ | ||||
|          list of physical CPU numbers that virtual CPUs can be pinned | ||||
|          to.  Each element in that list is either a single CPU number, | ||||
|          a range of CPU numbers, or a caret followed by a CPU number to | ||||
| -        be excluded from a previous range. | ||||
| +        be excluded from a previous range.  <span class="since">Since | ||||
| +        0.8.5</span>, the optional attribute <code>current</code> can | ||||
| +        be used to specify whether fewer than the maximum number of | ||||
| +        virtual CPUs should be enabled. | ||||
|        </dd> | ||||
|      </dl> | ||||
|  | ||||
| diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng | ||||
| index f230263..a934a77 100644 | ||||
| --- a/docs/schemas/domain.rng | ||||
| +++ b/docs/schemas/domain.rng | ||||
| @@ -337,6 +337,11 @@ | ||||
|                <ref name="cpuset"/> | ||||
|              </attribute> | ||||
|            </optional> | ||||
| +          <optional> | ||||
| +            <attribute name="current"> | ||||
| +              <ref name="countCPU"/> | ||||
| +            </attribute> | ||||
| +          </optional> | ||||
|            <ref name="countCPU"/> | ||||
|          </element> | ||||
|        </optional> | ||||
| diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smp.xml b/tests/qemuxml2argvdata/qemuxml2argv-smp.xml | ||||
| new file mode 100644 | ||||
| index 0000000..975f873 | ||||
| --- /dev/null | ||||
| +++ b/tests/qemuxml2argvdata/qemuxml2argv-smp.xml | ||||
| @@ -0,0 +1,28 @@ | ||||
| +<domain type='qemu'> | ||||
| +  <name>QEMUGuest1</name> | ||||
| +  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> | ||||
| +  <memory>219200</memory> | ||||
| +  <currentMemory>219200</currentMemory> | ||||
| +  <vcpu current='1'>2</vcpu> | ||||
| +  <os> | ||||
| +    <type arch='i686' machine='pc'>hvm</type> | ||||
| +    <boot dev='hd'/> | ||||
| +  </os> | ||||
| +  <cpu> | ||||
| +    <topology sockets='2' cores='1' threads='1'/> | ||||
| +  </cpu> | ||||
| +  <clock offset='utc'/> | ||||
| +  <on_poweroff>destroy</on_poweroff> | ||||
| +  <on_reboot>restart</on_reboot> | ||||
| +  <on_crash>destroy</on_crash> | ||||
| +  <devices> | ||||
| +    <emulator>/usr/bin/qemu</emulator> | ||||
| +    <disk type='block' device='disk'> | ||||
| +      <source dev='/dev/HostVG/QEMUGuest1'/> | ||||
| +      <target dev='hda' bus='ide'/> | ||||
| +      <address type='drive' controller='0' bus='0' unit='0'/> | ||||
| +    </disk> | ||||
| +    <controller type='ide' index='0'/> | ||||
| +    <memballoon model='virtio'/> | ||||
| +  </devices> | ||||
| +</domain> | ||||
| diff --git a/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml | ||||
| new file mode 100644 | ||||
| index 0000000..d061e11 | ||||
| --- /dev/null | ||||
| +++ b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.xml | ||||
| @@ -0,0 +1,22 @@ | ||||
| +<domain type='xen' id='15'> | ||||
| +  <name>pvtest</name> | ||||
| +  <uuid>596a5d2171f48fb2e068e2386a5c413e</uuid> | ||||
| +  <os> | ||||
| +    <type>linux</type> | ||||
| +    <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> | ||||
| +    <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> | ||||
| +    <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os  </cmdline> | ||||
| +  </os> | ||||
| +  <memory>430080</memory> | ||||
| +  <vcpu current='2'>4</vcpu> | ||||
| +  <on_poweroff>destroy</on_poweroff> | ||||
| +  <on_reboot>destroy</on_reboot> | ||||
| +  <on_crash>destroy</on_crash> | ||||
| +  <devices> | ||||
| +    <disk type='file' device='disk'> | ||||
| +      <source file='/root/some.img'/> | ||||
| +      <target dev='xvda'/> | ||||
| +    </disk> | ||||
| +    <console tty='/dev/pts/4'/> | ||||
| +  </devices> | ||||
| +</domain> | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,62 +0,0 @@ | ||||
| From ea3f5c68093429c6ad507b45689cdf209c2c257b Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Fri, 24 Sep 2010 16:48:45 -0600 | ||||
| Subject: [PATCH 02/15] vcpu: add new public API | ||||
|  | ||||
| API agreed on in | ||||
| https://www.redhat.com/archives/libvir-list/2010-September/msg00456.html, | ||||
| but modified for enum names to be consistent with virDomainDeviceModifyFlags. | ||||
|  | ||||
| * include/libvirt/libvirt.h.in (virDomainVcpuFlags) | ||||
| (virDomainSetVcpusFlags, virDomainGetVcpusFlags): New | ||||
| declarations. | ||||
| * src/libvirt_public.syms: Export new symbols. | ||||
| --- | ||||
|  include/libvirt/libvirt.h.in |   15 +++++++++++++++ | ||||
|  src/libvirt_public.syms      |    2 ++ | ||||
|  2 files changed, 17 insertions(+), 0 deletions(-) | ||||
|  | ||||
| diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in | ||||
| index 2eba61e..d0cc4c0 100644 | ||||
| --- a/include/libvirt/libvirt.h.in | ||||
| +++ b/include/libvirt/libvirt.h.in | ||||
| @@ -915,8 +915,23 @@ struct _virVcpuInfo { | ||||
|  }; | ||||
|  typedef virVcpuInfo *virVcpuInfoPtr; | ||||
|  | ||||
| +/* Flags for controlling virtual CPU hot-plugging.  */ | ||||
| +typedef enum { | ||||
| +    /* Must choose at least one of these two bits; SetVcpus can choose both */ | ||||
| +    VIR_DOMAIN_VCPU_LIVE    = (1 << 0), /* Affect active domain */ | ||||
| +    VIR_DOMAIN_VCPU_CONFIG  = (1 << 1), /* Affect next boot */ | ||||
| + | ||||
| +    /* Additional flags to be bit-wise OR'd in */ | ||||
| +    VIR_DOMAIN_VCPU_MAXIMUM = (1 << 2), /* Max rather than current count */ | ||||
| +} virDomainVcpuFlags; | ||||
| + | ||||
|  int                     virDomainSetVcpus       (virDomainPtr domain, | ||||
|                                                   unsigned int nvcpus); | ||||
| +int                     virDomainSetVcpusFlags  (virDomainPtr domain, | ||||
| +                                                 unsigned int nvcpus, | ||||
| +                                                 unsigned int flags); | ||||
| +int                     virDomainGetVcpusFlags  (virDomainPtr domain, | ||||
| +                                                 unsigned int flags); | ||||
|  | ||||
|  int                     virDomainPinVcpu        (virDomainPtr domain, | ||||
|                                                   unsigned int vcpu, | ||||
| diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms | ||||
| index fceb516..a8091b1 100644 | ||||
| --- a/src/libvirt_public.syms | ||||
| +++ b/src/libvirt_public.syms | ||||
| @@ -409,6 +409,8 @@ LIBVIRT_0.8.5 { | ||||
|      global: | ||||
|          virDomainSetMemoryParameters; | ||||
|          virDomainGetMemoryParameters; | ||||
| +        virDomainGetVcpusFlags; | ||||
| +        virDomainSetVcpusFlags; | ||||
|  } LIBVIRT_0.8.2; | ||||
|  | ||||
|  # .... define new API here using predicted next version number .... | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,222 +0,0 @@ | ||||
| From dd255d64053e9960cd375994ce8f056522e12acc Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Mon, 27 Sep 2010 09:18:22 -0600 | ||||
| Subject: [PATCH 03/15] vcpu: define internal driver API | ||||
|  | ||||
| * src/driver.h (virDrvDomainSetVcpusFlags) | ||||
| (virDrvDomainGetVcpusFlags): New typedefs. | ||||
| (_virDriver): New callback members. | ||||
| * src/esx/esx_driver.c (esxDriver): Add stub for driver. | ||||
| * src/lxc/lxc_driver.c (lxcDriver): Likewise. | ||||
| * src/opennebula/one_driver.c (oneDriver): Likewise. | ||||
| * src/openvz/openvz_driver.c (openvzDriver): Likewise. | ||||
| * src/phyp/phyp_driver.c (phypDriver): Likewise. | ||||
| * src/qemu/qemu_driver.c (qemuDriver): Likewise. | ||||
| * src/remote/remote_driver.c (remote_driver): Likewise. | ||||
| * src/test/test_driver.c (testDriver): Likewise. | ||||
| * src/uml/uml_driver.c (umlDriver): Likewise. | ||||
| * src/vbox/vbox_tmpl.c (Driver): Likewise. | ||||
| * src/xen/xen_driver.c (xenUnifiedDriver): Likewise. | ||||
| * src/xenapi/xenapi_driver.c (xenapiDriver): Likewise. | ||||
| --- | ||||
|  src/driver.h                |    9 +++++++++ | ||||
|  src/esx/esx_driver.c        |    2 ++ | ||||
|  src/lxc/lxc_driver.c        |    2 ++ | ||||
|  src/opennebula/one_driver.c |    2 ++ | ||||
|  src/openvz/openvz_driver.c  |    2 ++ | ||||
|  src/phyp/phyp_driver.c      |    2 ++ | ||||
|  src/qemu/qemu_driver.c      |    2 ++ | ||||
|  src/remote/remote_driver.c  |    2 ++ | ||||
|  src/test/test_driver.c      |    2 ++ | ||||
|  src/uml/uml_driver.c        |    2 ++ | ||||
|  src/vbox/vbox_tmpl.c        |    2 ++ | ||||
|  src/xen/xen_driver.c        |    2 ++ | ||||
|  src/xenapi/xenapi_driver.c  |    2 ++ | ||||
|  13 files changed, 33 insertions(+), 0 deletions(-) | ||||
|  | ||||
| diff --git a/src/driver.h b/src/driver.h | ||||
| index 32aeb04..79a96c1 100644 | ||||
| --- a/src/driver.h | ||||
| +++ b/src/driver.h | ||||
| @@ -185,6 +185,13 @@ typedef int | ||||
|          (*virDrvDomainSetVcpus)		(virDomainPtr domain, | ||||
|                                           unsigned int nvcpus); | ||||
|  typedef int | ||||
| +        (*virDrvDomainSetVcpusFlags)	(virDomainPtr domain, | ||||
| +                                         unsigned int nvcpus, | ||||
| +                                         unsigned int flags); | ||||
| +typedef int | ||||
| +        (*virDrvDomainGetVcpusFlags)	(virDomainPtr domain, | ||||
| +                                         unsigned int flags); | ||||
| +typedef int | ||||
|          (*virDrvDomainPinVcpu)		(virDomainPtr domain, | ||||
|                                           unsigned int vcpu, | ||||
|                                           unsigned char *cpumap, | ||||
| @@ -520,6 +527,8 @@ struct _virDriver { | ||||
|      virDrvDomainRestore		domainRestore; | ||||
|      virDrvDomainCoreDump		domainCoreDump; | ||||
|      virDrvDomainSetVcpus		domainSetVcpus; | ||||
| +    virDrvDomainSetVcpusFlags		domainSetVcpusFlags; | ||||
| +    virDrvDomainGetVcpusFlags		domainGetVcpusFlags; | ||||
|      virDrvDomainPinVcpu		domainPinVcpu; | ||||
|      virDrvDomainGetVcpus		domainGetVcpus; | ||||
|      virDrvDomainGetMaxVcpus		domainGetMaxVcpus; | ||||
| diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c | ||||
| index 1b4ee29..2a32374 100644 | ||||
| --- a/src/esx/esx_driver.c | ||||
| +++ b/src/esx/esx_driver.c | ||||
| @@ -4160,6 +4160,8 @@ static virDriver esxDriver = { | ||||
|      NULL,                            /* domainRestore */ | ||||
|      NULL,                            /* domainCoreDump */ | ||||
|      esxDomainSetVcpus,               /* domainSetVcpus */ | ||||
| +    NULL,                            /* domainSetVcpusFlags */ | ||||
| +    NULL,                            /* domainGetVcpusFlags */ | ||||
|      NULL,                            /* domainPinVcpu */ | ||||
|      NULL,                            /* domainGetVcpus */ | ||||
|      esxDomainGetMaxVcpus,            /* domainGetMaxVcpus */ | ||||
| diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c | ||||
| index df814da..7563a8c 100644 | ||||
| --- a/src/lxc/lxc_driver.c | ||||
| +++ b/src/lxc/lxc_driver.c | ||||
| @@ -2768,6 +2768,8 @@ static virDriver lxcDriver = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      NULL, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
|      NULL, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/opennebula/one_driver.c b/src/opennebula/one_driver.c | ||||
| index ced9a38..199fca3 100644 | ||||
| --- a/src/opennebula/one_driver.c | ||||
| +++ b/src/opennebula/one_driver.c | ||||
| @@ -751,6 +751,8 @@ static virDriver oneDriver = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      NULL, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
|      NULL, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c | ||||
| index 92cf4a1..9d19aeb 100644 | ||||
| --- a/src/openvz/openvz_driver.c | ||||
| +++ b/src/openvz/openvz_driver.c | ||||
| @@ -1590,6 +1590,8 @@ static virDriver openvzDriver = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      openvzDomainSetVcpus, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
|      openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c | ||||
| index e63d8d9..6e0a5e9 100644 | ||||
| --- a/src/phyp/phyp_driver.c | ||||
| +++ b/src/phyp/phyp_driver.c | ||||
| @@ -3941,6 +3941,8 @@ static virDriver phypDriver = { | ||||
|      NULL,                       /* domainRestore */ | ||||
|      NULL,                       /* domainCoreDump */ | ||||
|      phypDomainSetCPU,           /* domainSetVcpus */ | ||||
| +    NULL,                       /* domainSetVcpusFlags */ | ||||
| +    NULL,                       /* domainGetVcpusFlags */ | ||||
|      NULL,                       /* domainPinVcpu */ | ||||
|      NULL,                       /* domainGetVcpus */ | ||||
|      phypGetLparCPUMAX,          /* domainGetMaxVcpus */ | ||||
| diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c | ||||
| index abd8e9d..3d17e04 100644 | ||||
| --- a/src/qemu/qemu_driver.c | ||||
| +++ b/src/qemu/qemu_driver.c | ||||
| @@ -12938,6 +12938,8 @@ static virDriver qemuDriver = { | ||||
|      qemudDomainRestore, /* domainRestore */ | ||||
|      qemudDomainCoreDump, /* domainCoreDump */ | ||||
|      qemudDomainSetVcpus, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      qemudDomainPinVcpu, /* domainPinVcpu */ | ||||
|      qemudDomainGetVcpus, /* domainGetVcpus */ | ||||
|      qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c | ||||
| index 0b10406..1a687ad 100644 | ||||
| --- a/src/remote/remote_driver.c | ||||
| +++ b/src/remote/remote_driver.c | ||||
| @@ -10468,6 +10468,8 @@ static virDriver remote_driver = { | ||||
|      remoteDomainRestore, /* domainRestore */ | ||||
|      remoteDomainCoreDump, /* domainCoreDump */ | ||||
|      remoteDomainSetVcpus, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      remoteDomainPinVcpu, /* domainPinVcpu */ | ||||
|      remoteDomainGetVcpus, /* domainGetVcpus */ | ||||
|      remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/test/test_driver.c b/src/test/test_driver.c | ||||
| index 7d4d119..6a00558 100644 | ||||
| --- a/src/test/test_driver.c | ||||
| +++ b/src/test/test_driver.c | ||||
| @@ -5260,6 +5260,8 @@ static virDriver testDriver = { | ||||
|      testDomainRestore, /* domainRestore */ | ||||
|      testDomainCoreDump, /* domainCoreDump */ | ||||
|      testSetVcpus, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      testDomainPinVcpu, /* domainPinVcpu */ | ||||
|      testDomainGetVcpus, /* domainGetVcpus */ | ||||
|      testDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c | ||||
| index 3dcd321..5161012 100644 | ||||
| --- a/src/uml/uml_driver.c | ||||
| +++ b/src/uml/uml_driver.c | ||||
| @@ -2129,6 +2129,8 @@ static virDriver umlDriver = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      NULL, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
|      NULL, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c | ||||
| index 7e7d8e4..cb9193a 100644 | ||||
| --- a/src/vbox/vbox_tmpl.c | ||||
| +++ b/src/vbox/vbox_tmpl.c | ||||
| @@ -8267,6 +8267,8 @@ virDriver NAME(Driver) = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      vboxDomainSetVcpus, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
|      vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c | ||||
| index c2a4de3..7d67ced 100644 | ||||
| --- a/src/xen/xen_driver.c | ||||
| +++ b/src/xen/xen_driver.c | ||||
| @@ -1951,6 +1951,8 @@ static virDriver xenUnifiedDriver = { | ||||
|      xenUnifiedDomainRestore, /* domainRestore */ | ||||
|      xenUnifiedDomainCoreDump, /* domainCoreDump */ | ||||
|      xenUnifiedDomainSetVcpus, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      xenUnifiedDomainPinVcpu, /* domainPinVcpu */ | ||||
|      xenUnifiedDomainGetVcpus, /* domainGetVcpus */ | ||||
|      xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c | ||||
| index e62a139..753169c 100644 | ||||
| --- a/src/xenapi/xenapi_driver.c | ||||
| +++ b/src/xenapi/xenapi_driver.c | ||||
| @@ -1754,6 +1754,8 @@ static virDriver xenapiDriver = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      xenapiDomainSetVcpus, /* domainSetVcpus */ | ||||
| +    NULL, /* domainSetVcpusFlags */ | ||||
| +    NULL, /* domainGetVcpusFlags */ | ||||
|      xenapiDomainPinVcpu, /* domainPinVcpu */ | ||||
|      xenapiDomainGetVcpus, /* domainGetVcpus */ | ||||
|      xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,188 +0,0 @@ | ||||
| From 9d2c60799271d605f82dfd4bfa6ed7d14ad87e26 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Mon, 27 Sep 2010 09:37:22 -0600 | ||||
| Subject: [PATCH 04/15] vcpu: implement the public APIs | ||||
|  | ||||
| Factors common checks (such as nonzero vcpu count) up front, but | ||||
| drivers will still need to do additional flag checks. | ||||
|  | ||||
| * src/libvirt.c (virDomainSetVcpusFlags, virDomainGetVcpusFlags): | ||||
| New functions. | ||||
| (virDomainSetVcpus, virDomainGetMaxVcpus): Refer to new API. | ||||
| --- | ||||
|  src/libvirt.c |  140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- | ||||
|  1 files changed, 134 insertions(+), 6 deletions(-) | ||||
|  | ||||
| diff --git a/src/libvirt.c b/src/libvirt.c | ||||
| index 629d97b..1b39210 100644 | ||||
| --- a/src/libvirt.c | ||||
| +++ b/src/libvirt.c | ||||
| @@ -5192,7 +5192,9 @@ error: | ||||
|   * This function requires privileged access to the hypervisor. | ||||
|   * | ||||
|   * This command only changes the runtime configuration of the domain, | ||||
| - * so can only be called on an active domain. | ||||
| + * so can only be called on an active domain.  It is hypervisor-dependent | ||||
| + * whether it also affects persistent configuration; for more control, | ||||
| + * use virDomainSetVcpusFlags(). | ||||
|   * | ||||
|   * Returns 0 in case of success, -1 in case of failure. | ||||
|   */ | ||||
| @@ -5237,13 +5239,139 @@ error: | ||||
|  } | ||||
|  | ||||
|  /** | ||||
| + * virDomainSetVcpusFlags: | ||||
| + * @domain: pointer to domain object, or NULL for Domain0 | ||||
| + * @nvcpus: the new number of virtual CPUs for this domain, must be at least 1 | ||||
| + * @flags: an OR'ed set of virDomainVcpuFlags | ||||
| + * | ||||
| + * Dynamically change the number of virtual CPUs used by the domain. | ||||
| + * Note that this call may fail if the underlying virtualization hypervisor | ||||
| + * does not support it or if growing the number is arbitrary limited. | ||||
| + * This function requires privileged access to the hypervisor. | ||||
| + * | ||||
| + * @flags must include VIR_DOMAIN_VCPU_LIVE to affect a running | ||||
| + * domain (which may fail if domain is not active), or | ||||
| + * VIR_DOMAIN_VCPU_CONFIG to affect the next boot via the XML | ||||
| + * description of the domain.  Both flags may be set. | ||||
| + * | ||||
| + * If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then | ||||
| + * VIR_DOMAIN_VCPU_LIVE must be clear, and only the maximum virtual | ||||
| + * CPU limit is altered; generally, this value must be less than or | ||||
| + * equal to virConnectGetMaxVcpus().  Otherwise, this call affects the | ||||
| + * current virtual CPU limit, which must be less than or equal to the | ||||
| + * maximum limit. | ||||
| + * | ||||
| + * Returns 0 in case of success, -1 in case of failure. | ||||
| + */ | ||||
| + | ||||
| +int | ||||
| +virDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, | ||||
| +                       unsigned int flags) | ||||
| +{ | ||||
| +    virConnectPtr conn; | ||||
| +    VIR_DEBUG("domain=%p, nvcpus=%u, flags=%u", domain, nvcpus, flags); | ||||
| + | ||||
| +    virResetLastError(); | ||||
| + | ||||
| +    if (!VIR_IS_CONNECTED_DOMAIN(domain)) { | ||||
| +        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); | ||||
| +        virDispatchError(NULL); | ||||
| +        return (-1); | ||||
| +    } | ||||
| +    if (domain->conn->flags & VIR_CONNECT_RO) { | ||||
| +        virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__); | ||||
| +        goto error; | ||||
| +    } | ||||
| + | ||||
| +    /* Perform some argument validation common to all implementations.  */ | ||||
| +    if (nvcpus < 1 || (unsigned short) nvcpus != nvcpus || | ||||
| +        (flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0) { | ||||
| +        virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| +        goto error; | ||||
| +    } | ||||
| +    conn = domain->conn; | ||||
| + | ||||
| +    if (conn->driver->domainSetVcpusFlags) { | ||||
| +        int ret; | ||||
| +        ret = conn->driver->domainSetVcpusFlags (domain, nvcpus, flags); | ||||
| +        if (ret < 0) | ||||
| +            goto error; | ||||
| +        return ret; | ||||
| +    } | ||||
| + | ||||
| +    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); | ||||
| + | ||||
| +error: | ||||
| +    virDispatchError(domain->conn); | ||||
| +    return -1; | ||||
| +} | ||||
| + | ||||
| +/** | ||||
| + * virDomainGetVcpusFlags: | ||||
| + * @domain: pointer to domain object, or NULL for Domain0 | ||||
| + * @flags: an OR'ed set of virDomainVcpuFlags | ||||
| + * | ||||
| + * Query the number of virtual CPUs used by the domain.  Note that | ||||
| + * this call may fail if the underlying virtualization hypervisor does | ||||
| + * not support it.  This function requires privileged access to the | ||||
| + * hypervisor. | ||||
| + * | ||||
| + * @flags must include either VIR_DOMAIN_VCPU_ACTIVE to query a | ||||
| + * running domain (which will fail if domain is not active), or | ||||
| + * VIR_DOMAIN_VCPU_PERSISTENT to query the XML description of the | ||||
| + * domain.  It is an error to set both flags. | ||||
| + * | ||||
| + * If @flags includes VIR_DOMAIN_VCPU_MAXIMUM, then the maximum | ||||
| + * virtual CPU limit is queried.  Otherwise, this call queries the | ||||
| + * current virtual CPU limit. | ||||
| + * | ||||
| + * Returns 0 in case of success, -1 in case of failure. | ||||
| + */ | ||||
| + | ||||
| +int | ||||
| +virDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) | ||||
| +{ | ||||
| +    virConnectPtr conn; | ||||
| +    VIR_DEBUG("domain=%p, flags=%u", domain, flags); | ||||
| + | ||||
| +    virResetLastError(); | ||||
| + | ||||
| +    if (!VIR_IS_CONNECTED_DOMAIN(domain)) { | ||||
| +        virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__); | ||||
| +        virDispatchError(NULL); | ||||
| +        return (-1); | ||||
| +    } | ||||
| + | ||||
| +    /* Exactly one of these two flags should be set.  */ | ||||
| +    if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) { | ||||
| +        virLibDomainError(domain, VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| +        goto error; | ||||
| +    } | ||||
| +    conn = domain->conn; | ||||
| + | ||||
| +    if (conn->driver->domainGetVcpusFlags) { | ||||
| +        int ret; | ||||
| +        ret = conn->driver->domainGetVcpusFlags (domain, flags); | ||||
| +        if (ret < 0) | ||||
| +            goto error; | ||||
| +        return ret; | ||||
| +    } | ||||
| + | ||||
| +    virLibConnError (conn, VIR_ERR_NO_SUPPORT, __FUNCTION__); | ||||
| + | ||||
| +error: | ||||
| +    virDispatchError(domain->conn); | ||||
| +    return -1; | ||||
| +} | ||||
| + | ||||
| +/** | ||||
|   * virDomainPinVcpu: | ||||
|   * @domain: pointer to domain object, or NULL for Domain0 | ||||
|   * @vcpu: virtual CPU number | ||||
|   * @cpumap: pointer to a bit map of real CPUs (in 8-bit bytes) (IN) | ||||
| - * 	Each bit set to 1 means that corresponding CPU is usable. | ||||
| - * 	Bytes are stored in little-endian order: CPU0-7, 8-15... | ||||
| - * 	In each byte, lowest CPU number is least significant bit. | ||||
| + *      Each bit set to 1 means that corresponding CPU is usable. | ||||
| + *      Bytes are stored in little-endian order: CPU0-7, 8-15... | ||||
| + *      In each byte, lowest CPU number is least significant bit. | ||||
|   * @maplen: number of bytes in cpumap, from 1 up to size of CPU map in | ||||
|   *	underlying virtualization system (Xen...). | ||||
|   *	If maplen < size, missing bytes are set to zero. | ||||
| @@ -5371,9 +5499,9 @@ error: | ||||
|   * | ||||
|   * Provides the maximum number of virtual CPUs supported for | ||||
|   * the guest VM. If the guest is inactive, this is basically | ||||
| - * the same as virConnectGetMaxVcpus. If the guest is running | ||||
| + * the same as virConnectGetMaxVcpus(). If the guest is running | ||||
|   * this will reflect the maximum number of virtual CPUs the | ||||
| - * guest was booted with. | ||||
| + * guest was booted with.  For more details, see virDomainGetVcpusFlags(). | ||||
|   * | ||||
|   * Returns the maximum of virtual CPU or -1 in case of error. | ||||
|   */ | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,421 +0,0 @@ | ||||
| From eb826444f90c2563dadf148630b0cd6a9b41ba1e Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Mon, 27 Sep 2010 10:10:06 -0600 | ||||
| Subject: [PATCH 05/15] vcpu: implement the remote protocol | ||||
|  | ||||
| Done by editing the first three files, then running | ||||
| 'make -C src rpcgen', then editing src/remote_protocol-structs | ||||
| to match. | ||||
|  | ||||
| * daemon/remote.c (remoteDispatchDomainSetVcpusFlags) | ||||
| (remoteDispatchDomainGetVcpusFlags): New functions. | ||||
| * src/remote/remote_driver.c (remoteDomainSetVcpusFlags) | ||||
| (remoteDomainGetVcpusFlags, remote_driver): Client side | ||||
| serialization. | ||||
| * src/remote/remote_protocol.x | ||||
| (remote_domain_set_vcpus_flags_args) | ||||
| (remote_domain_get_vcpus_flags_args) | ||||
| (remote_domain_get_vcpus_flags_ret) | ||||
| (REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS) | ||||
| (REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS): Define wire format. | ||||
| * daemon/remote_dispatch_args.h: Regenerate. | ||||
| * daemon/remote_dispatch_prototypes.h: Likewise. | ||||
| * daemon/remote_dispatch_table.h: Likewise. | ||||
| * src/remote/remote_protocol.c: Likewise. | ||||
| * src/remote/remote_protocol.h: Likewise. | ||||
| * src/remote_protocol-structs: Likewise. | ||||
| --- | ||||
|  daemon/remote.c                     |   53 ++++++++++++++++++++++++++++++++ | ||||
|  daemon/remote_dispatch_args.h       |    2 + | ||||
|  daemon/remote_dispatch_prototypes.h |   16 ++++++++++ | ||||
|  daemon/remote_dispatch_ret.h        |    1 + | ||||
|  daemon/remote_dispatch_table.h      |   10 ++++++ | ||||
|  src/remote/remote_driver.c          |   57 +++++++++++++++++++++++++++++++++- | ||||
|  src/remote/remote_protocol.c        |   33 ++++++++++++++++++++ | ||||
|  src/remote/remote_protocol.h        |   26 ++++++++++++++++ | ||||
|  src/remote/remote_protocol.x        |   19 +++++++++++- | ||||
|  src/remote_protocol-structs         |   12 +++++++ | ||||
|  10 files changed, 226 insertions(+), 3 deletions(-) | ||||
|  | ||||
| diff --git a/daemon/remote.c b/daemon/remote.c | ||||
| index 7a96e29..323f00c 100644 | ||||
| --- a/daemon/remote.c | ||||
| +++ b/daemon/remote.c | ||||
| @@ -1751,6 +1751,33 @@ oom: | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| +remoteDispatchDomainGetVcpusFlags (struct qemud_server *server ATTRIBUTE_UNUSED, | ||||
| +                                   struct qemud_client *client ATTRIBUTE_UNUSED, | ||||
| +                                   virConnectPtr conn, | ||||
| +                                   remote_message_header *hdr ATTRIBUTE_UNUSED, | ||||
| +                                   remote_error *rerr, | ||||
| +                                   remote_domain_get_vcpus_flags_args *args, | ||||
| +                                   remote_domain_get_vcpus_flags_ret *ret) | ||||
| +{ | ||||
| +    virDomainPtr dom; | ||||
| + | ||||
| +    dom = get_nonnull_domain (conn, args->dom); | ||||
| +    if (dom == NULL) { | ||||
| +        remoteDispatchConnError(rerr, conn); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    ret->num = virDomainGetVcpusFlags (dom, args->flags); | ||||
| +    if (ret->num == -1) { | ||||
| +        virDomainFree(dom); | ||||
| +        remoteDispatchConnError(rerr, conn); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    virDomainFree(dom); | ||||
| +    return 0; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
|  remoteDispatchDomainMigratePrepare (struct qemud_server *server ATTRIBUTE_UNUSED, | ||||
|                                      struct qemud_client *client ATTRIBUTE_UNUSED, | ||||
|                                      virConnectPtr conn, | ||||
| @@ -2568,6 +2595,32 @@ remoteDispatchDomainSetVcpus (struct qemud_server *server ATTRIBUTE_UNUSED, | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| +remoteDispatchDomainSetVcpusFlags (struct qemud_server *server ATTRIBUTE_UNUSED, | ||||
| +                                   struct qemud_client *client ATTRIBUTE_UNUSED, | ||||
| +                                   virConnectPtr conn, | ||||
| +                                   remote_message_header *hdr ATTRIBUTE_UNUSED, | ||||
| +                                   remote_error *rerr, | ||||
| +                                   remote_domain_set_vcpus_flags_args *args, | ||||
| +                                   void *ret ATTRIBUTE_UNUSED) | ||||
| +{ | ||||
| +    virDomainPtr dom; | ||||
| + | ||||
| +    dom = get_nonnull_domain (conn, args->dom); | ||||
| +    if (dom == NULL) { | ||||
| +        remoteDispatchConnError(rerr, conn); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    if (virDomainSetVcpusFlags (dom, args->nvcpus, args->flags) == -1) { | ||||
| +        virDomainFree(dom); | ||||
| +        remoteDispatchConnError(rerr, conn); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    virDomainFree(dom); | ||||
| +    return 0; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
|  remoteDispatchDomainShutdown (struct qemud_server *server ATTRIBUTE_UNUSED, | ||||
|                                struct qemud_client *client ATTRIBUTE_UNUSED, | ||||
|                                virConnectPtr conn, | ||||
| diff --git a/daemon/remote_dispatch_args.h b/daemon/remote_dispatch_args.h | ||||
| index d8528b6..9583e9c 100644 | ||||
| --- a/daemon/remote_dispatch_args.h | ||||
| +++ b/daemon/remote_dispatch_args.h | ||||
| @@ -167,3 +167,5 @@ | ||||
|      remote_domain_create_with_flags_args val_remote_domain_create_with_flags_args; | ||||
|      remote_domain_set_memory_parameters_args val_remote_domain_set_memory_parameters_args; | ||||
|      remote_domain_get_memory_parameters_args val_remote_domain_get_memory_parameters_args; | ||||
| +    remote_domain_set_vcpus_flags_args val_remote_domain_set_vcpus_flags_args; | ||||
| +    remote_domain_get_vcpus_flags_args val_remote_domain_get_vcpus_flags_args; | ||||
| diff --git a/daemon/remote_dispatch_prototypes.h b/daemon/remote_dispatch_prototypes.h | ||||
| index b674bb4..6b35851 100644 | ||||
| --- a/daemon/remote_dispatch_prototypes.h | ||||
| +++ b/daemon/remote_dispatch_prototypes.h | ||||
| @@ -306,6 +306,14 @@ static int remoteDispatchDomainGetVcpus( | ||||
|      remote_error *err, | ||||
|      remote_domain_get_vcpus_args *args, | ||||
|      remote_domain_get_vcpus_ret *ret); | ||||
| +static int remoteDispatchDomainGetVcpusFlags( | ||||
| +    struct qemud_server *server, | ||||
| +    struct qemud_client *client, | ||||
| +    virConnectPtr conn, | ||||
| +    remote_message_header *hdr, | ||||
| +    remote_error *err, | ||||
| +    remote_domain_get_vcpus_flags_args *args, | ||||
| +    remote_domain_get_vcpus_flags_ret *ret); | ||||
|  static int remoteDispatchDomainHasCurrentSnapshot( | ||||
|      struct qemud_server *server, | ||||
|      struct qemud_client *client, | ||||
| @@ -554,6 +562,14 @@ static int remoteDispatchDomainSetVcpus( | ||||
|      remote_error *err, | ||||
|      remote_domain_set_vcpus_args *args, | ||||
|      void *ret); | ||||
| +static int remoteDispatchDomainSetVcpusFlags( | ||||
| +    struct qemud_server *server, | ||||
| +    struct qemud_client *client, | ||||
| +    virConnectPtr conn, | ||||
| +    remote_message_header *hdr, | ||||
| +    remote_error *err, | ||||
| +    remote_domain_set_vcpus_flags_args *args, | ||||
| +    void *ret); | ||||
|  static int remoteDispatchDomainShutdown( | ||||
|      struct qemud_server *server, | ||||
|      struct qemud_client *client, | ||||
| diff --git a/daemon/remote_dispatch_ret.h b/daemon/remote_dispatch_ret.h | ||||
| index 17c9bca..3723b00 100644 | ||||
| --- a/daemon/remote_dispatch_ret.h | ||||
| +++ b/daemon/remote_dispatch_ret.h | ||||
| @@ -136,3 +136,4 @@ | ||||
|      remote_domain_get_block_info_ret val_remote_domain_get_block_info_ret; | ||||
|      remote_domain_create_with_flags_ret val_remote_domain_create_with_flags_ret; | ||||
|      remote_domain_get_memory_parameters_ret val_remote_domain_get_memory_parameters_ret; | ||||
| +    remote_domain_get_vcpus_flags_ret val_remote_domain_get_vcpus_flags_ret; | ||||
| diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h | ||||
| index 47d95eb..dd2adc7 100644 | ||||
| --- a/daemon/remote_dispatch_table.h | ||||
| +++ b/daemon/remote_dispatch_table.h | ||||
| @@ -997,3 +997,13 @@ | ||||
|      .args_filter = (xdrproc_t) xdr_remote_domain_get_memory_parameters_args, | ||||
|      .ret_filter = (xdrproc_t) xdr_remote_domain_get_memory_parameters_ret, | ||||
|  }, | ||||
| +{   /* DomainSetVcpusFlags => 199 */ | ||||
| +    .fn = (dispatch_fn) remoteDispatchDomainSetVcpusFlags, | ||||
| +    .args_filter = (xdrproc_t) xdr_remote_domain_set_vcpus_flags_args, | ||||
| +    .ret_filter = (xdrproc_t) xdr_void, | ||||
| +}, | ||||
| +{   /* DomainGetVcpusFlags => 200 */ | ||||
| +    .fn = (dispatch_fn) remoteDispatchDomainGetVcpusFlags, | ||||
| +    .args_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_flags_args, | ||||
| +    .ret_filter = (xdrproc_t) xdr_remote_domain_get_vcpus_flags_ret, | ||||
| +}, | ||||
| diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c | ||||
| index 1a687ad..37c37ef 100644 | ||||
| --- a/src/remote/remote_driver.c | ||||
| +++ b/src/remote/remote_driver.c | ||||
| @@ -2580,6 +2580,59 @@ done: | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| +remoteDomainSetVcpusFlags (virDomainPtr domain, unsigned int nvcpus, | ||||
| +                           unsigned int flags) | ||||
| +{ | ||||
| +    int rv = -1; | ||||
| +    remote_domain_set_vcpus_flags_args args; | ||||
| +    struct private_data *priv = domain->conn->privateData; | ||||
| + | ||||
| +    remoteDriverLock(priv); | ||||
| + | ||||
| +    make_nonnull_domain (&args.dom, domain); | ||||
| +    args.nvcpus = nvcpus; | ||||
| +    args.flags = flags; | ||||
| + | ||||
| +    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS, | ||||
| +              (xdrproc_t) xdr_remote_domain_set_vcpus_flags_args, | ||||
| +              (char *) &args, | ||||
| +              (xdrproc_t) xdr_void, (char *) NULL) == -1) | ||||
| +        goto done; | ||||
| + | ||||
| +    rv = 0; | ||||
| + | ||||
| +done: | ||||
| +    remoteDriverUnlock(priv); | ||||
| +    return rv; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +remoteDomainGetVcpusFlags (virDomainPtr domain, unsigned int flags) | ||||
| +{ | ||||
| +    int rv = -1; | ||||
| +    remote_domain_get_vcpus_flags_args args; | ||||
| +    remote_domain_get_vcpus_flags_ret ret; | ||||
| +    struct private_data *priv = domain->conn->privateData; | ||||
| + | ||||
| +    remoteDriverLock(priv); | ||||
| + | ||||
| +    make_nonnull_domain (&args.dom, domain); | ||||
| +    args.flags = flags; | ||||
| + | ||||
| +    memset (&ret, 0, sizeof ret); | ||||
| +    if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS, | ||||
| +              (xdrproc_t) xdr_remote_domain_get_vcpus_flags_args, (char *) &args, | ||||
| +              (xdrproc_t) xdr_remote_domain_get_vcpus_flags_ret, (char *) &ret) == -1) | ||||
| +        goto done; | ||||
| + | ||||
| +    rv = ret.num; | ||||
| + | ||||
| +done: | ||||
| +    remoteDriverUnlock(priv); | ||||
| +    return rv; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
|  remoteDomainPinVcpu (virDomainPtr domain, | ||||
|                       unsigned int vcpu, | ||||
|                       unsigned char *cpumap, | ||||
| @@ -10468,8 +10521,8 @@ static virDriver remote_driver = { | ||||
|      remoteDomainRestore, /* domainRestore */ | ||||
|      remoteDomainCoreDump, /* domainCoreDump */ | ||||
|      remoteDomainSetVcpus, /* domainSetVcpus */ | ||||
| -    NULL, /* domainSetVcpusFlags */ | ||||
| -    NULL, /* domainGetVcpusFlags */ | ||||
| +    remoteDomainSetVcpusFlags, /* domainSetVcpusFlags */ | ||||
| +    remoteDomainGetVcpusFlags, /* domainGetVcpusFlags */ | ||||
|      remoteDomainPinVcpu, /* domainPinVcpu */ | ||||
|      remoteDomainGetVcpus, /* domainGetVcpus */ | ||||
|      remoteDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c | ||||
| index 5c55713..38ea050 100644 | ||||
| --- a/src/remote/remote_protocol.c | ||||
| +++ b/src/remote/remote_protocol.c | ||||
| @@ -1355,6 +1355,39 @@ xdr_remote_domain_set_vcpus_args (XDR *xdrs, remote_domain_set_vcpus_args *objp) | ||||
|  } | ||||
|  | ||||
|  bool_t | ||||
| +xdr_remote_domain_set_vcpus_flags_args (XDR *xdrs, remote_domain_set_vcpus_flags_args *objp) | ||||
| +{ | ||||
| + | ||||
| +         if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) | ||||
| +                 return FALSE; | ||||
| +         if (!xdr_u_int (xdrs, &objp->nvcpus)) | ||||
| +                 return FALSE; | ||||
| +         if (!xdr_u_int (xdrs, &objp->flags)) | ||||
| +                 return FALSE; | ||||
| +        return TRUE; | ||||
| +} | ||||
| + | ||||
| +bool_t | ||||
| +xdr_remote_domain_get_vcpus_flags_args (XDR *xdrs, remote_domain_get_vcpus_flags_args *objp) | ||||
| +{ | ||||
| + | ||||
| +         if (!xdr_remote_nonnull_domain (xdrs, &objp->dom)) | ||||
| +                 return FALSE; | ||||
| +         if (!xdr_u_int (xdrs, &objp->flags)) | ||||
| +                 return FALSE; | ||||
| +        return TRUE; | ||||
| +} | ||||
| + | ||||
| +bool_t | ||||
| +xdr_remote_domain_get_vcpus_flags_ret (XDR *xdrs, remote_domain_get_vcpus_flags_ret *objp) | ||||
| +{ | ||||
| + | ||||
| +         if (!xdr_int (xdrs, &objp->num)) | ||||
| +                 return FALSE; | ||||
| +        return TRUE; | ||||
| +} | ||||
| + | ||||
| +bool_t | ||||
|  xdr_remote_domain_pin_vcpu_args (XDR *xdrs, remote_domain_pin_vcpu_args *objp) | ||||
|  { | ||||
|          char **objp_cpp0 = (char **) (void *) &objp->cpumap.cpumap_val; | ||||
| diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h | ||||
| index 756da11..d75e76c 100644 | ||||
| --- a/src/remote/remote_protocol.h | ||||
| +++ b/src/remote/remote_protocol.h | ||||
| @@ -750,6 +750,24 @@ struct remote_domain_set_vcpus_args { | ||||
|  }; | ||||
|  typedef struct remote_domain_set_vcpus_args remote_domain_set_vcpus_args; | ||||
|  | ||||
| +struct remote_domain_set_vcpus_flags_args { | ||||
| +        remote_nonnull_domain dom; | ||||
| +        u_int nvcpus; | ||||
| +        u_int flags; | ||||
| +}; | ||||
| +typedef struct remote_domain_set_vcpus_flags_args remote_domain_set_vcpus_flags_args; | ||||
| + | ||||
| +struct remote_domain_get_vcpus_flags_args { | ||||
| +        remote_nonnull_domain dom; | ||||
| +        u_int flags; | ||||
| +}; | ||||
| +typedef struct remote_domain_get_vcpus_flags_args remote_domain_get_vcpus_flags_args; | ||||
| + | ||||
| +struct remote_domain_get_vcpus_flags_ret { | ||||
| +        int num; | ||||
| +}; | ||||
| +typedef struct remote_domain_get_vcpus_flags_ret remote_domain_get_vcpus_flags_ret; | ||||
| + | ||||
|  struct remote_domain_pin_vcpu_args { | ||||
|          remote_nonnull_domain dom; | ||||
|          int vcpu; | ||||
| @@ -2281,6 +2299,8 @@ enum remote_procedure { | ||||
|          REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196, | ||||
|          REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS = 197, | ||||
|          REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198, | ||||
| +        REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199, | ||||
| +        REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200, | ||||
|  }; | ||||
|  typedef enum remote_procedure remote_procedure; | ||||
|  | ||||
| @@ -2422,6 +2442,9 @@ extern  bool_t xdr_remote_domain_define_xml_args (XDR *, remote_domain_define_xm | ||||
|  extern  bool_t xdr_remote_domain_define_xml_ret (XDR *, remote_domain_define_xml_ret*); | ||||
|  extern  bool_t xdr_remote_domain_undefine_args (XDR *, remote_domain_undefine_args*); | ||||
|  extern  bool_t xdr_remote_domain_set_vcpus_args (XDR *, remote_domain_set_vcpus_args*); | ||||
| +extern  bool_t xdr_remote_domain_set_vcpus_flags_args (XDR *, remote_domain_set_vcpus_flags_args*); | ||||
| +extern  bool_t xdr_remote_domain_get_vcpus_flags_args (XDR *, remote_domain_get_vcpus_flags_args*); | ||||
| +extern  bool_t xdr_remote_domain_get_vcpus_flags_ret (XDR *, remote_domain_get_vcpus_flags_ret*); | ||||
|  extern  bool_t xdr_remote_domain_pin_vcpu_args (XDR *, remote_domain_pin_vcpu_args*); | ||||
|  extern  bool_t xdr_remote_domain_get_vcpus_args (XDR *, remote_domain_get_vcpus_args*); | ||||
|  extern  bool_t xdr_remote_domain_get_vcpus_ret (XDR *, remote_domain_get_vcpus_ret*); | ||||
| @@ -2762,6 +2785,9 @@ extern bool_t xdr_remote_domain_define_xml_args (); | ||||
|  extern bool_t xdr_remote_domain_define_xml_ret (); | ||||
|  extern bool_t xdr_remote_domain_undefine_args (); | ||||
|  extern bool_t xdr_remote_domain_set_vcpus_args (); | ||||
| +extern bool_t xdr_remote_domain_set_vcpus_flags_args (); | ||||
| +extern bool_t xdr_remote_domain_get_vcpus_flags_args (); | ||||
| +extern bool_t xdr_remote_domain_get_vcpus_flags_ret (); | ||||
|  extern bool_t xdr_remote_domain_pin_vcpu_args (); | ||||
|  extern bool_t xdr_remote_domain_get_vcpus_args (); | ||||
|  extern bool_t xdr_remote_domain_get_vcpus_ret (); | ||||
| diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x | ||||
| index e80fb5f..d57e6d0 100644 | ||||
| --- a/src/remote/remote_protocol.x | ||||
| +++ b/src/remote/remote_protocol.x | ||||
| @@ -768,6 +768,21 @@ struct remote_domain_set_vcpus_args { | ||||
|      int nvcpus; | ||||
|  }; | ||||
|  | ||||
| +struct remote_domain_set_vcpus_flags_args { | ||||
| +    remote_nonnull_domain dom; | ||||
| +    unsigned int nvcpus; | ||||
| +    unsigned int flags; | ||||
| +}; | ||||
| + | ||||
| +struct remote_domain_get_vcpus_flags_args { | ||||
| +    remote_nonnull_domain dom; | ||||
| +    unsigned int flags; | ||||
| +}; | ||||
| + | ||||
| +struct remote_domain_get_vcpus_flags_ret { | ||||
| +    int num; | ||||
| +}; | ||||
| + | ||||
|  struct remote_domain_pin_vcpu_args { | ||||
|      remote_nonnull_domain dom; | ||||
|      int vcpu; | ||||
| @@ -2062,7 +2077,9 @@ enum remote_procedure { | ||||
|      REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195, | ||||
|      REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196, | ||||
|      REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS = 197, | ||||
| -    REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198 | ||||
| +    REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198, | ||||
| +    REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199, | ||||
| +    REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200 | ||||
|  | ||||
|      /* | ||||
|       * Notice how the entries are grouped in sets of 10 ? | ||||
| diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs | ||||
| index 838423e..d505886 100644 | ||||
| --- a/src/remote_protocol-structs | ||||
| +++ b/src/remote_protocol-structs | ||||
| @@ -461,6 +461,18 @@ struct remote_domain_set_vcpus_args { | ||||
|  	remote_nonnull_domain      dom; | ||||
|  	int                        nvcpus; | ||||
|  }; | ||||
| +struct remote_domain_set_vcpus_flags_args { | ||||
| +	remote_nonnull_domain      dom; | ||||
| +	u_int                      nvcpus; | ||||
| +	u_int                      flags; | ||||
| +}; | ||||
| +struct remote_domain_get_vcpus_flags_args { | ||||
| +	remote_nonnull_domain      dom; | ||||
| +	u_int                      flags; | ||||
| +}; | ||||
| +struct remote_domain_get_vcpus_flags_ret { | ||||
| +	int                        num; | ||||
| +}; | ||||
|  struct remote_domain_pin_vcpu_args { | ||||
|  	remote_nonnull_domain      dom; | ||||
|  	int                        vcpu; | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,735 +0,0 @@ | ||||
| From 50c51f13e2af04afac46e181c4ed62581545a488 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Mon, 27 Sep 2010 16:37:53 -0600 | ||||
| Subject: [PATCH 06/15] vcpu: make old API trivially wrap to new API | ||||
|  | ||||
| Note - this wrapping is completely mechanical; the old API will | ||||
| function identically, since the new API validates that the exact | ||||
| same flags are provided by the old API.  On a per-driver basis, | ||||
| it may make sense to have the old API pass a different set of flags, | ||||
| but that should be done in the per-driver patch that implements | ||||
| the full range of flag support in the new API. | ||||
|  | ||||
| * src/esx/esx_driver.c (esxDomainSetVcpus, escDomainGetMaxVpcus): | ||||
| Move guts... | ||||
| (esxDomainSetVcpusFlags, esxDomainGetVcpusFlags): ...to new | ||||
| functions. | ||||
| (esxDriver): Trivially support the new API. | ||||
| * src/openvz/openvz_driver.c (openvzDomainSetVcpus) | ||||
| (openvzDomainSetVcpusFlags, openvzDomainGetMaxVcpus) | ||||
| (openvzDomainGetVcpusFlags, openvzDriver): Likewise. | ||||
| * src/phyp/phyp_driver.c (phypDomainSetCPU) | ||||
| (phypDomainSetVcpusFlags, phypGetLparCPUMAX) | ||||
| (phypDomainGetVcpusFlags, phypDriver): Likewise. | ||||
| * src/qemu/qemu_driver.c (qemudDomainSetVcpus) | ||||
| (qemudDomainSetVcpusFlags, qemudDomainGetMaxVcpus) | ||||
| (qemudDomainGetVcpusFlags, qemuDriver): Likewise. | ||||
| * src/test/test_driver.c (testSetVcpus, testDomainSetVcpusFlags) | ||||
| (testDomainGetMaxVcpus, testDomainGetVcpusFlags, testDriver): | ||||
| Likewise. | ||||
| * src/vbox/vbox_tmpl.c (vboxDomainSetVcpus) | ||||
| (vboxDomainSetVcpusFlags, virDomainGetMaxVcpus) | ||||
| (virDomainGetVcpusFlags, virDriver): Likewise. | ||||
| * src/xen/xen_driver.c (xenUnifiedDomainSetVcpus) | ||||
| (xenUnifiedDomainSetVcpusFlags, xenUnifiedDomainGetMaxVcpus) | ||||
| (xenUnifiedDomainGetVcpusFlags, xenUnifiedDriver): Likewise. | ||||
| * src/xenapi/xenapi_driver.c (xenapiDomainSetVcpus) | ||||
| (xenapiDomainSetVcpusFlags, xenapiDomainGetMaxVcpus) | ||||
| (xenapiDomainGetVcpusFlags, xenapiDriver): Likewise. | ||||
| (xenapiError): New helper macro. | ||||
| --- | ||||
|  src/esx/esx_driver.c       |   32 +++++++++++++++++++--- | ||||
|  src/openvz/openvz_driver.c |   34 +++++++++++++++++++++--- | ||||
|  src/phyp/phyp_driver.c     |   32 ++++++++++++++++++++--- | ||||
|  src/qemu/qemu_driver.c     |   38 +++++++++++++++++++++++++--- | ||||
|  src/test/test_driver.c     |   36 ++++++++++++++++++++++--- | ||||
|  src/vbox/vbox_tmpl.c       |   36 +++++++++++++++++++++++--- | ||||
|  src/xen/xen_driver.c       |   34 ++++++++++++++++++++++--- | ||||
|  src/xenapi/xenapi_driver.c |   60 ++++++++++++++++++++++++++++++++++++++------ | ||||
|  8 files changed, 263 insertions(+), 39 deletions(-) | ||||
|  | ||||
| diff --git a/src/esx/esx_driver.c b/src/esx/esx_driver.c | ||||
| index 2a32374..b3e1284 100644 | ||||
| --- a/src/esx/esx_driver.c | ||||
| +++ b/src/esx/esx_driver.c | ||||
| @@ -2384,7 +2384,8 @@ esxDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info) | ||||
|  | ||||
|  | ||||
|  static int | ||||
| -esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) | ||||
| +esxDomainSetVcpusFlags(virDomainPtr domain, unsigned int nvcpus, | ||||
| +                       unsigned int flags) | ||||
|  { | ||||
|      int result = -1; | ||||
|      esxPrivate *priv = domain->conn->privateData; | ||||
| @@ -2394,6 +2395,11 @@ esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) | ||||
|      esxVI_ManagedObjectReference *task = NULL; | ||||
|      esxVI_TaskInfoState taskInfoState; | ||||
|  | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        ESX_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      if (nvcpus < 1) { | ||||
|          ESX_ERROR(VIR_ERR_INVALID_ARG, "%s", | ||||
|                    _("Requested number of virtual CPUs must at least be 1")); | ||||
| @@ -2453,15 +2459,26 @@ esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) | ||||
|  } | ||||
|  | ||||
|  | ||||
| +static int | ||||
| +esxDomainSetVcpus(virDomainPtr domain, unsigned int nvcpus) | ||||
| +{ | ||||
| +    return esxDomainSetVcpusFlags(domain, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
|  | ||||
|  static int | ||||
| -esxDomainGetMaxVcpus(virDomainPtr domain) | ||||
| +esxDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) | ||||
|  { | ||||
|      esxPrivate *priv = domain->conn->privateData; | ||||
|      esxVI_String *propertyNameList = NULL; | ||||
|      esxVI_ObjectContent *hostSystem = NULL; | ||||
|      esxVI_DynamicProperty *dynamicProperty = NULL; | ||||
|  | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        ESX_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      if (priv->maxVcpus > 0) { | ||||
|          return priv->maxVcpus; | ||||
|      } | ||||
| @@ -2507,7 +2524,12 @@ esxDomainGetMaxVcpus(virDomainPtr domain) | ||||
|      return priv->maxVcpus; | ||||
|  } | ||||
|  | ||||
| - | ||||
| +static int | ||||
| +esxDomainGetMaxVcpus(virDomainPtr domain) | ||||
| +{ | ||||
| +    return esxDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                           VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
|  | ||||
|  static char * | ||||
|  esxDomainDumpXML(virDomainPtr domain, int flags) | ||||
| @@ -4160,8 +4182,8 @@ static virDriver esxDriver = { | ||||
|      NULL,                            /* domainRestore */ | ||||
|      NULL,                            /* domainCoreDump */ | ||||
|      esxDomainSetVcpus,               /* domainSetVcpus */ | ||||
| -    NULL,                            /* domainSetVcpusFlags */ | ||||
| -    NULL,                            /* domainGetVcpusFlags */ | ||||
| +    esxDomainSetVcpusFlags,          /* domainSetVcpusFlags */ | ||||
| +    esxDomainGetVcpusFlags,          /* domainGetVcpusFlags */ | ||||
|      NULL,                            /* domainPinVcpu */ | ||||
|      NULL,                            /* domainGetVcpus */ | ||||
|      esxDomainGetMaxVcpus,            /* domainGetMaxVcpus */ | ||||
| diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c | ||||
| index 9d19aeb..0f3cfdf 100644 | ||||
| --- a/src/openvz/openvz_driver.c | ||||
| +++ b/src/openvz/openvz_driver.c | ||||
| @@ -67,7 +67,6 @@ | ||||
|  static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid); | ||||
|  static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type); | ||||
|  static int openvzDomainGetMaxVcpus(virDomainPtr dom); | ||||
| -static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus); | ||||
|  static int openvzDomainSetVcpusInternal(virDomainObjPtr vm, | ||||
|                                          unsigned int nvcpus); | ||||
|  static int openvzDomainSetMemoryInternal(virDomainObjPtr vm, | ||||
| @@ -1211,11 +1210,24 @@ static int openvzGetMaxVCPUs(virConnectPtr conn ATTRIBUTE_UNUSED, | ||||
|      return -1; | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +openvzDomainGetVcpusFlags(virDomainPtr dom ATTRIBUTE_UNUSED, | ||||
| +                          unsigned int flags) | ||||
| +{ | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        openvzError(VIR_ERR_INVALID_ARG, _("unsupported flags (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
|  | ||||
| -static int openvzDomainGetMaxVcpus(virDomainPtr dom ATTRIBUTE_UNUSED) { | ||||
|      return openvzGetMaxVCPUs(NULL, "openvz"); | ||||
|  } | ||||
|  | ||||
| +static int openvzDomainGetMaxVcpus(virDomainPtr dom) | ||||
| +{ | ||||
| +    return openvzDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                           VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
| + | ||||
|  static int openvzDomainSetVcpusInternal(virDomainObjPtr vm, | ||||
|                                          unsigned int nvcpus) | ||||
|  { | ||||
| @@ -1241,12 +1253,18 @@ static int openvzDomainSetVcpusInternal(virDomainObjPtr vm, | ||||
|      return 0; | ||||
|  } | ||||
|  | ||||
| -static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) | ||||
| +static int openvzDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
| +                                     unsigned int flags) | ||||
|  { | ||||
|      virDomainObjPtr         vm; | ||||
|      struct openvz_driver   *driver = dom->conn->privateData; | ||||
|      int                     ret = -1; | ||||
|  | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        openvzError(VIR_ERR_INVALID_ARG, _("unsupported flags (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      openvzDriverLock(driver); | ||||
|      vm = virDomainFindByUUID(&driver->domains, dom->uuid); | ||||
|      openvzDriverUnlock(driver); | ||||
| @@ -1272,6 +1290,12 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) | ||||
| +{ | ||||
| +    return openvzDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
|  static virDrvOpenStatus openvzOpen(virConnectPtr conn, | ||||
|                                     virConnectAuthPtr auth ATTRIBUTE_UNUSED, | ||||
|                                     int flags ATTRIBUTE_UNUSED) | ||||
| @@ -1590,8 +1614,8 @@ static virDriver openvzDriver = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      openvzDomainSetVcpus, /* domainSetVcpus */ | ||||
| -    NULL, /* domainSetVcpusFlags */ | ||||
| -    NULL, /* domainGetVcpusFlags */ | ||||
| +    openvzDomainSetVcpusFlags, /* domainSetVcpusFlags */ | ||||
| +    openvzDomainGetVcpusFlags, /* domainGetVcpusFlags */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
|      openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c | ||||
| index 6e0a5e9..e284ae0 100644 | ||||
| --- a/src/phyp/phyp_driver.c | ||||
| +++ b/src/phyp/phyp_driver.c | ||||
| @@ -1497,15 +1497,27 @@ phypGetLparCPU(virConnectPtr conn, const char *managed_system, int lpar_id) | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| -phypGetLparCPUMAX(virDomainPtr dom) | ||||
| +phypDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) | ||||
|  { | ||||
|      phyp_driverPtr phyp_driver = dom->conn->privateData; | ||||
|      char *managed_system = phyp_driver->managed_system; | ||||
|  | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        PHYP_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      return phypGetLparCPUGeneric(dom->conn, managed_system, dom->id, 1); | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| +phypGetLparCPUMAX(virDomainPtr dom) | ||||
| +{ | ||||
| +    return phypDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                         VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
|  phypGetRemoteSlot(virConnectPtr conn, const char *managed_system, | ||||
|                    const char *lpar_name) | ||||
|  { | ||||
| @@ -3831,7 +3843,8 @@ phypConnectGetCapabilities(virConnectPtr conn) | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| -phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) | ||||
| +phypDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
| +                        unsigned int flags) | ||||
|  { | ||||
|      ConnectionData *connection_data = dom->conn->networkPrivateData; | ||||
|      phyp_driverPtr phyp_driver = dom->conn->privateData; | ||||
| @@ -3846,6 +3859,11 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) | ||||
|      unsigned int amount = 0; | ||||
|      virBuffer buf = VIR_BUFFER_INITIALIZER; | ||||
|  | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        PHYP_ERROR(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      if ((ncpus = phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) | ||||
|          return 0; | ||||
|  | ||||
| @@ -3891,6 +3909,12 @@ phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) | ||||
|  | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +phypDomainSetCPU(virDomainPtr dom, unsigned int nvcpus) | ||||
| +{ | ||||
| +    return phypDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
|  static virDrvOpenStatus | ||||
|  phypVIOSDriverOpen(virConnectPtr conn, | ||||
|                     virConnectAuthPtr auth ATTRIBUTE_UNUSED, | ||||
| @@ -3941,8 +3965,8 @@ static virDriver phypDriver = { | ||||
|      NULL,                       /* domainRestore */ | ||||
|      NULL,                       /* domainCoreDump */ | ||||
|      phypDomainSetCPU,           /* domainSetVcpus */ | ||||
| -    NULL,                       /* domainSetVcpusFlags */ | ||||
| -    NULL,                       /* domainGetVcpusFlags */ | ||||
| +    phypDomainSetVcpusFlags,    /* domainSetVcpusFlags */ | ||||
| +    phypDomainGetVcpusFlags,    /* domainGetVcpusFlags */ | ||||
|      NULL,                       /* domainPinVcpu */ | ||||
|      NULL,                       /* domainGetVcpus */ | ||||
|      phypGetLparCPUMAX,          /* domainGetMaxVcpus */ | ||||
| diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c | ||||
| index 3d17e04..7a2ea8f 100644 | ||||
| --- a/src/qemu/qemu_driver.c | ||||
| +++ b/src/qemu/qemu_driver.c | ||||
| @@ -5934,13 +5934,22 @@ unsupported: | ||||
|  } | ||||
|  | ||||
|  | ||||
| -static int qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { | ||||
| +static int | ||||
| +qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
| +                         unsigned int flags) | ||||
| +{ | ||||
|      struct qemud_driver *driver = dom->conn->privateData; | ||||
|      virDomainObjPtr vm; | ||||
|      const char * type; | ||||
|      int max; | ||||
|      int ret = -1; | ||||
|  | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| +                        flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      qemuDriverLock(driver); | ||||
|      vm = virDomainFindByUUID(&driver->domains, dom->uuid); | ||||
|      qemuDriverUnlock(driver); | ||||
| @@ -5994,6 +6003,12 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +qemudDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) | ||||
| +{ | ||||
| +    return qemudDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
|  | ||||
|  static int | ||||
|  qemudDomainPinVcpu(virDomainPtr dom, | ||||
| @@ -6150,12 +6165,20 @@ cleanup: | ||||
|  } | ||||
|  | ||||
|  | ||||
| -static int qemudDomainGetMaxVcpus(virDomainPtr dom) { | ||||
| +static int | ||||
| +qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) | ||||
| +{ | ||||
|      struct qemud_driver *driver = dom->conn->privateData; | ||||
|      virDomainObjPtr vm; | ||||
|      const char *type; | ||||
|      int ret = -1; | ||||
|  | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| +                        flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      qemuDriverLock(driver); | ||||
|      vm = virDomainFindByUUID(&driver->domains, dom->uuid); | ||||
|      qemuDriverUnlock(driver); | ||||
| @@ -6183,6 +6206,13 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +qemudDomainGetMaxVcpus(virDomainPtr dom) | ||||
| +{ | ||||
| +    return qemudDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                          VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
| + | ||||
|  static int qemudDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel) | ||||
|  { | ||||
|      struct qemud_driver *driver = (struct qemud_driver *)dom->conn->privateData; | ||||
| @@ -12938,8 +12968,8 @@ static virDriver qemuDriver = { | ||||
|      qemudDomainRestore, /* domainRestore */ | ||||
|      qemudDomainCoreDump, /* domainCoreDump */ | ||||
|      qemudDomainSetVcpus, /* domainSetVcpus */ | ||||
| -    NULL, /* domainSetVcpusFlags */ | ||||
| -    NULL, /* domainGetVcpusFlags */ | ||||
| +    qemudDomainSetVcpusFlags, /* domainSetVcpusFlags */ | ||||
| +    qemudDomainGetVcpusFlags, /* domainGetVcpusFlags */ | ||||
|      qemudDomainPinVcpu, /* domainPinVcpu */ | ||||
|      qemudDomainGetVcpus, /* domainGetVcpus */ | ||||
|      qemudDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/test/test_driver.c b/src/test/test_driver.c | ||||
| index 6a00558..b70c80d 100644 | ||||
| --- a/src/test/test_driver.c | ||||
| +++ b/src/test/test_driver.c | ||||
| @@ -2029,17 +2029,37 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| -static int testDomainGetMaxVcpus(virDomainPtr domain) | ||||
| +static int | ||||
| +testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) | ||||
|  { | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      return testGetMaxVCPUs(domain->conn, "test"); | ||||
|  } | ||||
|  | ||||
| -static int testSetVcpus(virDomainPtr domain, | ||||
| -                        unsigned int nrCpus) { | ||||
| +static int | ||||
| +testDomainGetMaxVcpus(virDomainPtr domain) | ||||
| +{ | ||||
| +    return testDomainGetVcpusFlags(domain, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                            VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus, | ||||
| +                        unsigned int flags) | ||||
| +{ | ||||
|      testConnPtr privconn = domain->conn->privateData; | ||||
|      virDomainObjPtr privdom = NULL; | ||||
|      int ret = -1, maxvcpus; | ||||
|  | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      /* Do this first before locking */ | ||||
|      maxvcpus = testDomainGetMaxVcpus(domain); | ||||
|      if (maxvcpus < 0) | ||||
| @@ -2082,6 +2102,12 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +testSetVcpus(virDomainPtr domain, unsigned int nrCpus) | ||||
| +{ | ||||
| +    return testDomainSetVcpusFlags(domain, nrCpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
|  static int testDomainGetVcpus(virDomainPtr domain, | ||||
|                                virVcpuInfoPtr info, | ||||
|                                int maxinfo, | ||||
| @@ -5260,8 +5286,8 @@ static virDriver testDriver = { | ||||
|      testDomainRestore, /* domainRestore */ | ||||
|      testDomainCoreDump, /* domainCoreDump */ | ||||
|      testSetVcpus, /* domainSetVcpus */ | ||||
| -    NULL, /* domainSetVcpusFlags */ | ||||
| -    NULL, /* domainGetVcpusFlags */ | ||||
| +    testDomainSetVcpusFlags, /* domainSetVcpusFlags */ | ||||
| +    testDomainGetVcpusFlags, /* domainGetVcpusFlags */ | ||||
|      testDomainPinVcpu, /* domainPinVcpu */ | ||||
|      testDomainGetVcpus, /* domainGetVcpus */ | ||||
|      testDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c | ||||
| index cb9193a..0cbe8b3 100644 | ||||
| --- a/src/vbox/vbox_tmpl.c | ||||
| +++ b/src/vbox/vbox_tmpl.c | ||||
| @@ -1839,13 +1839,21 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| -static int vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) { | ||||
| +static int | ||||
| +vboxDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
| +                        unsigned int flags) | ||||
| +{ | ||||
|      VBOX_OBJECT_CHECK(dom->conn, int, -1); | ||||
|      IMachine *machine    = NULL; | ||||
|      vboxIID  *iid        = NULL; | ||||
|      PRUint32  CPUCount   = nvcpus; | ||||
|      nsresult rc; | ||||
|  | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        vboxError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|  #if VBOX_API_VERSION == 2002 | ||||
|      if (VIR_ALLOC(iid) < 0) { | ||||
|          virReportOOMError(); | ||||
| @@ -1887,11 +1895,24 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| -static int vboxDomainGetMaxVcpus(virDomainPtr dom) { | ||||
| +static int | ||||
| +vboxDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) | ||||
| +{ | ||||
| +    return vboxDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +vboxDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) | ||||
| +{ | ||||
|      VBOX_OBJECT_CHECK(dom->conn, int, -1); | ||||
|      ISystemProperties *systemProperties = NULL; | ||||
|      PRUint32 maxCPUCount = 0; | ||||
|  | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        vboxError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      /* Currently every domain supports the same number of max cpus | ||||
|       * as that supported by vbox and thus take it directly from | ||||
|       * the systemproperties. | ||||
| @@ -1909,6 +1930,13 @@ static int vboxDomainGetMaxVcpus(virDomainPtr dom) { | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +vboxDomainGetMaxVcpus(virDomainPtr dom) | ||||
| +{ | ||||
| +    return vboxDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                         VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
| + | ||||
|  static char *vboxDomainDumpXML(virDomainPtr dom, int flags) { | ||||
|      VBOX_OBJECT_CHECK(dom->conn, char *, NULL); | ||||
|      virDomainDefPtr def  = NULL; | ||||
| @@ -8267,8 +8295,8 @@ virDriver NAME(Driver) = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      vboxDomainSetVcpus, /* domainSetVcpus */ | ||||
| -    NULL, /* domainSetVcpusFlags */ | ||||
| -    NULL, /* domainGetVcpusFlags */ | ||||
| +    vboxDomainSetVcpusFlags, /* domainSetVcpusFlags */ | ||||
| +    vboxDomainGetVcpusFlags, /* domainGetVcpusFlags */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
|      vboxDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c | ||||
| index 7d67ced..d6c9c57 100644 | ||||
| --- a/src/xen/xen_driver.c | ||||
| +++ b/src/xen/xen_driver.c | ||||
| @@ -1069,11 +1069,18 @@ xenUnifiedDomainCoreDump (virDomainPtr dom, const char *to, int flags) | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| -xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) | ||||
| +xenUnifiedDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus, | ||||
| +                               unsigned int flags) | ||||
|  { | ||||
|      GET_PRIVATE(dom->conn); | ||||
|      int i; | ||||
|  | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| +                        flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      /* Try non-hypervisor methods first, then hypervisor direct method | ||||
|       * as a last resort. | ||||
|       */ | ||||
| @@ -1093,6 +1100,12 @@ xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| +xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) | ||||
| +{ | ||||
| +    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
|  xenUnifiedDomainPinVcpu (virDomainPtr dom, unsigned int vcpu, | ||||
|                           unsigned char *cpumap, int maplen) | ||||
|  { | ||||
| @@ -1126,11 +1139,17 @@ xenUnifiedDomainGetVcpus (virDomainPtr dom, | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| -xenUnifiedDomainGetMaxVcpus (virDomainPtr dom) | ||||
| +xenUnifiedDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags) | ||||
|  { | ||||
|      GET_PRIVATE(dom->conn); | ||||
|      int i, ret; | ||||
|  | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| +                        flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) | ||||
|          if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) { | ||||
|              ret = drivers[i]->domainGetMaxVcpus (dom); | ||||
| @@ -1140,6 +1159,13 @@ xenUnifiedDomainGetMaxVcpus (virDomainPtr dom) | ||||
|      return -1; | ||||
|  } | ||||
|  | ||||
| +static int | ||||
| +xenUnifiedDomainGetMaxVcpus (virDomainPtr dom) | ||||
| +{ | ||||
| +    return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                               VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
| + | ||||
|  static char * | ||||
|  xenUnifiedDomainDumpXML (virDomainPtr dom, int flags) | ||||
|  { | ||||
| @@ -1951,8 +1977,8 @@ static virDriver xenUnifiedDriver = { | ||||
|      xenUnifiedDomainRestore, /* domainRestore */ | ||||
|      xenUnifiedDomainCoreDump, /* domainCoreDump */ | ||||
|      xenUnifiedDomainSetVcpus, /* domainSetVcpus */ | ||||
| -    NULL, /* domainSetVcpusFlags */ | ||||
| -    NULL, /* domainGetVcpusFlags */ | ||||
| +    xenUnifiedDomainSetVcpusFlags, /* domainSetVcpusFlags */ | ||||
| +    xenUnifiedDomainGetVcpusFlags, /* domainGetVcpusFlags */ | ||||
|      xenUnifiedDomainPinVcpu, /* domainPinVcpu */ | ||||
|      xenUnifiedDomainGetVcpus, /* domainGetVcpus */ | ||||
|      xenUnifiedDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c | ||||
| index 753169c..7d4ab8d 100644 | ||||
| --- a/src/xenapi/xenapi_driver.c | ||||
| +++ b/src/xenapi/xenapi_driver.c | ||||
| @@ -40,6 +40,11 @@ | ||||
|  #include "xenapi_driver_private.h" | ||||
|  #include "xenapi_utils.h" | ||||
|  | ||||
| +#define VIR_FROM_THIS VIR_FROM_XENAPI | ||||
| + | ||||
| +#define xenapiError(code, ...)                                    \ | ||||
| +        virReportErrorHelper(NULL, VIR_FROM_THIS, code, __FILE__, \ | ||||
| +                             __FUNCTION__, __LINE__, __VA_ARGS__) | ||||
|  | ||||
|  /* | ||||
|   * getCapsObject | ||||
| @@ -987,19 +992,26 @@ xenapiDomainGetInfo (virDomainPtr dom, virDomainInfoPtr info) | ||||
|  | ||||
|  | ||||
|  /* | ||||
| - * xenapiDomainSetVcpus | ||||
| + * xenapiDomainSetVcpusFlags | ||||
|   * | ||||
|   * Sets the VCPUs on the domain | ||||
|   * Return 0 on success or -1 in case of error | ||||
|   */ | ||||
|  static int | ||||
| -xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) | ||||
| +xenapiDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus, | ||||
| +                           unsigned int flags) | ||||
|  { | ||||
| - | ||||
|      /* vm.set_vcpus_max */ | ||||
|      xen_vm vm; | ||||
|      xen_vm_set *vms; | ||||
|      xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; | ||||
| + | ||||
| +    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        xenapiError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| +                    flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) { | ||||
|          if (vms->size != 1) { | ||||
|              xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, | ||||
| @@ -1019,6 +1031,18 @@ xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) | ||||
|  } | ||||
|  | ||||
|  /* | ||||
| + * xenapiDomainSetVcpus | ||||
| + * | ||||
| + * Sets the VCPUs on the domain | ||||
| + * Return 0 on success or -1 in case of error | ||||
| + */ | ||||
| +static int | ||||
| +xenapiDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) | ||||
| +{ | ||||
| +    return xenapiDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +} | ||||
| + | ||||
| +/* | ||||
|   * xenapiDomainPinVcpu | ||||
|   * | ||||
|   * Dynamically change the real CPUs which can be allocated to a virtual CPU | ||||
| @@ -1140,19 +1164,26 @@ xenapiDomainGetVcpus (virDomainPtr dom, | ||||
|  } | ||||
|  | ||||
|  /* | ||||
| - * xenapiDomainGetMaxVcpus | ||||
| + * xenapiDomainGetVcpusFlags | ||||
|   * | ||||
|   * | ||||
| - * Returns maximum number of Vcpus on success or -1 in case of error | ||||
| + * Returns Vcpus count on success or -1 in case of error | ||||
|   */ | ||||
|  static int | ||||
| -xenapiDomainGetMaxVcpus (virDomainPtr dom) | ||||
| +xenapiDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags) | ||||
|  { | ||||
|      xen_vm vm; | ||||
|      xen_vm_set *vms; | ||||
|      int64_t maxvcpu = 0; | ||||
|      enum xen_vm_power_state state; | ||||
|      xen_session *session = ((struct _xenapiPrivate *)(dom->conn->privateData))->session; | ||||
| + | ||||
| +    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        xenapiError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| +                    flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
|      if (xen_vm_get_by_name_label(session, &vms, dom->name) && vms->size > 0) { | ||||
|          if (vms->size != 1) { | ||||
|              xenapiSessionErrorHandler(dom->conn, VIR_ERR_INTERNAL_ERROR, | ||||
| @@ -1176,6 +1207,19 @@ xenapiDomainGetMaxVcpus (virDomainPtr dom) | ||||
|  } | ||||
|  | ||||
|  /* | ||||
| + * xenapiDomainGetMaxVcpus | ||||
| + * | ||||
| + * | ||||
| + * Returns maximum number of Vcpus on success or -1 in case of error | ||||
| + */ | ||||
| +static int | ||||
| +xenapiDomainGetMaxVcpus (virDomainPtr dom) | ||||
| +{ | ||||
| +    return xenapiDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE | | ||||
| +                                           VIR_DOMAIN_VCPU_MAXIMUM)); | ||||
| +} | ||||
| + | ||||
| +/* | ||||
|   * xenapiDomainDumpXML | ||||
|   * | ||||
|   * | ||||
| @@ -1754,8 +1798,8 @@ static virDriver xenapiDriver = { | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
|      xenapiDomainSetVcpus, /* domainSetVcpus */ | ||||
| -    NULL, /* domainSetVcpusFlags */ | ||||
| -    NULL, /* domainGetVcpusFlags */ | ||||
| +    xenapiDomainSetVcpusFlags, /* domainSetVcpusFlags */ | ||||
| +    xenapiDomainGetVcpusFlags, /* domainGetVcpusFlags */ | ||||
|      xenapiDomainPinVcpu, /* domainPinVcpu */ | ||||
|      xenapiDomainGetVcpus, /* domainGetVcpus */ | ||||
|      xenapiDomainGetMaxVcpus, /* domainGetMaxVcpus */ | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,388 +0,0 @@ | ||||
| From bf945ee97b72d3b0c4fc2da04530f5294f529d66 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Wed, 29 Sep 2010 15:20:23 -0600 | ||||
| Subject: [PATCH 08/15] vcpu: add virsh support | ||||
|  | ||||
| * tools/virsh.c (cmdSetvcpus): Add new flags.  Let invalid | ||||
| commands through to driver, to ease testing of hypervisor argument | ||||
| validation. | ||||
| (cmdMaxvcpus, cmdVcpucount): New commands. | ||||
| (commands): Add new commands. | ||||
| * tools/virsh.pod (setvcpus, vcpucount, maxvcpus): Document new | ||||
| behavior. | ||||
| --- | ||||
|  tools/virsh.c   |  247 ++++++++++++++++++++++++++++++++++++++++++++++++++----- | ||||
|  tools/virsh.pod |   38 ++++++++- | ||||
|  2 files changed, 262 insertions(+), 23 deletions(-) | ||||
|  | ||||
| diff --git a/tools/virsh.c b/tools/virsh.c | ||||
| index 4f8c495..7fb7fbd 100644 | ||||
| --- a/tools/virsh.c | ||||
| +++ b/tools/virsh.c | ||||
| @@ -2281,10 +2281,216 @@ cmdFreecell(vshControl *ctl, const vshCmd *cmd) | ||||
|  } | ||||
|  | ||||
|  /* | ||||
| + * "maxvcpus" command | ||||
| + */ | ||||
| +static const vshCmdInfo info_maxvcpus[] = { | ||||
| +    {"help", N_("connection vcpu maximum")}, | ||||
| +    {"desc", N_("Show maximum number of virtual CPUs for guests on this connection.")}, | ||||
| +    {NULL, NULL} | ||||
| +}; | ||||
| + | ||||
| +static const vshCmdOptDef opts_maxvcpus[] = { | ||||
| +    {"type", VSH_OT_STRING, 0, N_("domain type")}, | ||||
| +    {NULL, 0, 0, NULL} | ||||
| +}; | ||||
| + | ||||
| +static int | ||||
| +cmdMaxvcpus(vshControl *ctl, const vshCmd *cmd) | ||||
| +{ | ||||
| +    char *type; | ||||
| +    int vcpus; | ||||
| + | ||||
| +    type = vshCommandOptString(cmd, "type", NULL); | ||||
| + | ||||
| +    if (!vshConnectionUsability(ctl, ctl->conn)) | ||||
| +        return FALSE; | ||||
| + | ||||
| +    vcpus = virConnectGetMaxVcpus(ctl->conn, type); | ||||
| +    if (vcpus < 0) | ||||
| +        return FALSE; | ||||
| +    vshPrint(ctl, "%d\n", vcpus); | ||||
| + | ||||
| +    return TRUE; | ||||
| +} | ||||
| + | ||||
| +/* | ||||
| + * "vcpucount" command | ||||
| + */ | ||||
| +static const vshCmdInfo info_vcpucount[] = { | ||||
| +    {"help", N_("domain vcpu counts")}, | ||||
| +    {"desc", N_("Returns the number of virtual CPUs used by the domain.")}, | ||||
| +    {NULL, NULL} | ||||
| +}; | ||||
| + | ||||
| +static const vshCmdOptDef opts_vcpucount[] = { | ||||
| +    {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, | ||||
| +    {"maximum", VSH_OT_BOOL, 0, N_("get maximum cap on vcpus")}, | ||||
| +    {"current", VSH_OT_BOOL, 0, N_("get current vcpu usage")}, | ||||
| +    {"config", VSH_OT_BOOL, 0, N_("get value to be used on next boot")}, | ||||
| +    {"live", VSH_OT_BOOL, 0, N_("get value from running domain")}, | ||||
| +    {NULL, 0, 0, NULL} | ||||
| +}; | ||||
| + | ||||
| +static int | ||||
| +cmdVcpucount(vshControl *ctl, const vshCmd *cmd) | ||||
| +{ | ||||
| +    virDomainPtr dom; | ||||
| +    int ret = TRUE; | ||||
| +    int maximum = vshCommandOptBool(cmd, "maximum"); | ||||
| +    int current = vshCommandOptBool(cmd, "current"); | ||||
| +    int config = vshCommandOptBool(cmd, "config"); | ||||
| +    int live = vshCommandOptBool(cmd, "live"); | ||||
| +    bool all = maximum + current + config + live == 0; | ||||
| +    int count; | ||||
| + | ||||
| +    if (maximum && current) { | ||||
| +        vshError(ctl, "%s", | ||||
| +                 _("--maximum and --current cannot both be specified")); | ||||
| +        return FALSE; | ||||
| +    } | ||||
| +    if (config && live) { | ||||
| +        vshError(ctl, "%s", | ||||
| +                 _("--config and --live cannot both be specified")); | ||||
| +        return FALSE; | ||||
| +    } | ||||
| +    /* We want one of each pair of mutually exclusive options; that | ||||
| +     * is, use of flags requires exactly two options.  */ | ||||
| +    if (maximum + current + config + live == 1) { | ||||
| +        vshError(ctl, | ||||
| +                 _("when using --%s, either --%s or --%s must be specified"), | ||||
| +                 (maximum ? "maximum" : current ? "current" | ||||
| +                  : config ? "config" : "live"), | ||||
| +                 maximum + current ? "config" : "maximum", | ||||
| +                 maximum + current ? "live" : "current"); | ||||
| +        return FALSE; | ||||
| +    } | ||||
| + | ||||
| +    if (!vshConnectionUsability(ctl, ctl->conn)) | ||||
| +        return FALSE; | ||||
| + | ||||
| +    if (!(dom = vshCommandOptDomain(ctl, cmd, NULL))) | ||||
| +        return FALSE; | ||||
| + | ||||
| +    /* In all cases, try the new API first; if it fails because we are | ||||
| +     * talking to an older client, try a fallback API before giving | ||||
| +     * up.  */ | ||||
| +    if (all || (maximum && config)) { | ||||
| +        count = virDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_MAXIMUM | | ||||
| +                                             VIR_DOMAIN_VCPU_CONFIG)); | ||||
| +        if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT | ||||
| +                          || last_error->code == VIR_ERR_INVALID_ARG)) { | ||||
| +            char *tmp; | ||||
| +            char *xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_INACTIVE); | ||||
| +            if (xml && (tmp = strstr(xml, "<vcpu"))) { | ||||
| +                tmp = strchr(tmp, '>'); | ||||
| +                if (!tmp || virStrToLong_i(tmp + 1, &tmp, 10, &count) < 0) | ||||
| +                    count = -1; | ||||
| +            } | ||||
| +            VIR_FREE(xml); | ||||
| +        } | ||||
| + | ||||
| +        if (count < 0) { | ||||
| +            virshReportError(ctl); | ||||
| +            ret = FALSE; | ||||
| +        } else if (all) { | ||||
| +            vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("config"), | ||||
| +                     count); | ||||
| +        } else { | ||||
| +            vshPrint(ctl, "%d\n", count); | ||||
| +        } | ||||
| +        virFreeError(last_error); | ||||
| +        last_error = NULL; | ||||
| +    } | ||||
| + | ||||
| +    if (all || (maximum && live)) { | ||||
| +        count = virDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_MAXIMUM | | ||||
| +                                             VIR_DOMAIN_VCPU_LIVE)); | ||||
| +        if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT | ||||
| +                          || last_error->code == VIR_ERR_INVALID_ARG)) { | ||||
| +            count = virDomainGetMaxVcpus(dom); | ||||
| +        } | ||||
| + | ||||
| +        if (count < 0) { | ||||
| +            virshReportError(ctl); | ||||
| +            ret = FALSE; | ||||
| +        } else if (all) { | ||||
| +            vshPrint(ctl, "%-12s %-12s %3d\n", _("maximum"), _("live"), | ||||
| +                     count); | ||||
| +        } else { | ||||
| +            vshPrint(ctl, "%d\n", count); | ||||
| +        } | ||||
| +        virFreeError(last_error); | ||||
| +        last_error = NULL; | ||||
| +    } | ||||
| + | ||||
| +    if (all || (current && config)) { | ||||
| +        count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_CONFIG); | ||||
| +        if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT | ||||
| +                          || last_error->code == VIR_ERR_INVALID_ARG)) { | ||||
| +            char *tmp, *end; | ||||
| +            char *xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_INACTIVE); | ||||
| +            if (xml && (tmp = strstr(xml, "<vcpu"))) { | ||||
| +                end = strchr(tmp, '>'); | ||||
| +                if (end) { | ||||
| +                    *end = '\0'; | ||||
| +                    tmp = strstr(tmp, "current="); | ||||
| +                    if (!tmp) | ||||
| +                        tmp = end + 1; | ||||
| +                    else { | ||||
| +                        tmp += strlen("current="); | ||||
| +                        tmp += *tmp == '\'' || *tmp == '"'; | ||||
| +                    } | ||||
| +                } | ||||
| +                if (!tmp || virStrToLong_i(tmp, &tmp, 10, &count) < 0) | ||||
| +                    count = -1; | ||||
| +            } | ||||
| +            VIR_FREE(xml); | ||||
| +        } | ||||
| + | ||||
| +        if (count < 0) { | ||||
| +            virshReportError(ctl); | ||||
| +            ret = FALSE; | ||||
| +        } else if (all) { | ||||
| +            vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("config"), | ||||
| +                     count); | ||||
| +        } else { | ||||
| +            vshPrint(ctl, "%d\n", count); | ||||
| +        } | ||||
| +        virFreeError(last_error); | ||||
| +        last_error = NULL; | ||||
| +    } | ||||
| + | ||||
| +    if (all || (current && live)) { | ||||
| +        count = virDomainGetVcpusFlags(dom, VIR_DOMAIN_VCPU_LIVE); | ||||
| +        if (count < 0 && (last_error->code == VIR_ERR_NO_SUPPORT | ||||
| +                          || last_error->code == VIR_ERR_INVALID_ARG)) { | ||||
| +            virDomainInfo info; | ||||
| +            if (virDomainGetInfo(dom, &info) == 0) | ||||
| +                count = info.nrVirtCpu; | ||||
| +        } | ||||
| + | ||||
| +        if (count < 0) { | ||||
| +            virshReportError(ctl); | ||||
| +            ret = FALSE; | ||||
| +        } else if (all) { | ||||
| +            vshPrint(ctl, "%-12s %-12s %3d\n", _("current"), _("live"), | ||||
| +                     count); | ||||
| +        } else { | ||||
| +            vshPrint(ctl, "%d\n", count); | ||||
| +        } | ||||
| +        virFreeError(last_error); | ||||
| +        last_error = NULL; | ||||
| +    } | ||||
| + | ||||
| +    virDomainFree(dom); | ||||
| +    return ret; | ||||
| +} | ||||
| + | ||||
| +/* | ||||
|   * "vcpuinfo" command | ||||
|   */ | ||||
|  static const vshCmdInfo info_vcpuinfo[] = { | ||||
| -    {"help", N_("domain vcpu information")}, | ||||
| +    {"help", N_("detailed domain vcpu information")}, | ||||
|      {"desc", N_("Returns basic information about the domain virtual CPUs.")}, | ||||
|      {NULL, NULL} | ||||
|  }; | ||||
| @@ -2514,6 +2720,9 @@ static const vshCmdInfo info_setvcpus[] = { | ||||
|  static const vshCmdOptDef opts_setvcpus[] = { | ||||
|      {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")}, | ||||
|      {"count", VSH_OT_DATA, VSH_OFLAG_REQ, N_("number of virtual CPUs")}, | ||||
| +    {"maximum", VSH_OT_BOOL, 0, N_("set maximum limit on next boot")}, | ||||
| +    {"config", VSH_OT_BOOL, 0, N_("affect next boot")}, | ||||
| +    {"live", VSH_OT_BOOL, 0, N_("affect running domain")}, | ||||
|      {NULL, 0, 0, NULL} | ||||
|  }; | ||||
|  | ||||
| @@ -2522,8 +2731,13 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) | ||||
|  { | ||||
|      virDomainPtr dom; | ||||
|      int count; | ||||
| -    int maxcpu; | ||||
|      int ret = TRUE; | ||||
| +    int maximum = vshCommandOptBool(cmd, "maximum"); | ||||
| +    int config = vshCommandOptBool(cmd, "config"); | ||||
| +    int live = vshCommandOptBool(cmd, "live"); | ||||
| +    int flags = ((maximum ? VIR_DOMAIN_VCPU_MAXIMUM : 0) | | ||||
| +                 (config ? VIR_DOMAIN_VCPU_CONFIG : 0) | | ||||
| +                 (live ? VIR_DOMAIN_VCPU_LIVE : 0)); | ||||
|  | ||||
|      if (!vshConnectionUsability(ctl, ctl->conn)) | ||||
|          return FALSE; | ||||
| @@ -2532,26 +2746,15 @@ cmdSetvcpus(vshControl *ctl, const vshCmd *cmd) | ||||
|          return FALSE; | ||||
|  | ||||
|      count = vshCommandOptInt(cmd, "count", &count); | ||||
| -    if (count <= 0) { | ||||
| -        vshError(ctl, "%s", _("Invalid number of virtual CPUs.")); | ||||
| -        virDomainFree(dom); | ||||
| -        return FALSE; | ||||
| -    } | ||||
| - | ||||
| -    maxcpu = virDomainGetMaxVcpus(dom); | ||||
| -    if (maxcpu <= 0) { | ||||
| -        virDomainFree(dom); | ||||
| -        return FALSE; | ||||
| -    } | ||||
| - | ||||
| -    if (count > maxcpu) { | ||||
| -        vshError(ctl, "%s", _("Too many virtual CPUs.")); | ||||
| -        virDomainFree(dom); | ||||
| -        return FALSE; | ||||
| -    } | ||||
|  | ||||
| -    if (virDomainSetVcpus(dom, count) != 0) { | ||||
| -        ret = FALSE; | ||||
| +    if (!flags) { | ||||
| +        if (virDomainSetVcpus(dom, count) != 0) { | ||||
| +            ret = FALSE; | ||||
| +        } | ||||
| +    } else { | ||||
| +        if (virDomainSetVcpusFlags(dom, count, flags) < 0) { | ||||
| +            ret = FALSE; | ||||
| +        } | ||||
|      } | ||||
|  | ||||
|      virDomainFree(dom); | ||||
| @@ -9642,6 +9845,7 @@ static const vshCmdDef commands[] = { | ||||
|      {"freecell", cmdFreecell, opts_freecell, info_freecell}, | ||||
|      {"hostname", cmdHostname, NULL, info_hostname}, | ||||
|      {"list", cmdList, opts_list, info_list}, | ||||
| +    {"maxvcpus", cmdMaxvcpus, opts_maxvcpus, info_maxvcpus}, | ||||
|      {"migrate", cmdMigrate, opts_migrate, info_migrate}, | ||||
|      {"migrate-setmaxdowntime", cmdMigrateSetMaxDowntime, opts_migrate_setmaxdowntime, info_migrate_setmaxdowntime}, | ||||
|  | ||||
| @@ -9748,6 +9952,7 @@ static const vshCmdDef commands[] = { | ||||
|      {"vol-name", cmdVolName, opts_vol_name, info_vol_name}, | ||||
|      {"vol-key", cmdVolKey, opts_vol_key, info_vol_key}, | ||||
|  | ||||
| +    {"vcpucount", cmdVcpucount, opts_vcpucount, info_vcpucount}, | ||||
|      {"vcpuinfo", cmdVcpuinfo, opts_vcpuinfo, info_vcpuinfo}, | ||||
|      {"vcpupin", cmdVcpupin, opts_vcpupin, info_vcpupin}, | ||||
|      {"version", cmdVersion, NULL, info_version}, | ||||
| diff --git a/tools/virsh.pod b/tools/virsh.pod | ||||
| index 943a563..dbcc680 100644 | ||||
| --- a/tools/virsh.pod | ||||
| +++ b/tools/virsh.pod | ||||
| @@ -443,7 +443,14 @@ Remove the managed save file for a domain if it exists.  The next time the | ||||
|  domain is started it will not restore to its previous state but instead will | ||||
|  do a full boot. | ||||
|  | ||||
| -=item B<migrate> optional I<--live> I<--suspend> I<domain-id> I<desturi> I<migrateuri> | ||||
| +=item B<maxvcpus> optional I<type> | ||||
| + | ||||
| +Provide the maximum number of virtual CPUs supported for a guest VM on | ||||
| +this connection.  If provided, the I<type> parameter must be a valid | ||||
| +type attribute for the <domain> element of XML. | ||||
| + | ||||
| +=item B<migrate> optional I<--live> I<--suspend> I<domain-id> I<desturi> | ||||
| +I<migrateuri> | ||||
|  | ||||
|  Migrate domain to another host.  Add --live for live migration; --suspend | ||||
|  leaves the domain paused on the destination host. The I<desturi> is the | ||||
| @@ -521,7 +528,8 @@ Displays the domain memory parameters. | ||||
|  | ||||
|  Allows you to set the domain memory parameters. LXC and QEMU/KVM supports these parameters. | ||||
|  | ||||
| -=item B<setvcpus> I<domain-id> I<count> | ||||
| +=item B<setvcpus> I<domain-id> I<count> optional I<--maximum> I<--config> | ||||
| +I<--live> | ||||
|  | ||||
|  Change the number of virtual CPUs active in the guest domain. Note that | ||||
|  I<count> may be limited by host, hypervisor or limit coming from the | ||||
| @@ -530,6 +538,17 @@ original description of domain. | ||||
|  For Xen, you can only adjust the virtual CPUs of a running domain if | ||||
|  the domain is paravirtualized. | ||||
|  | ||||
| +If I<--config> is specified, the change will only affect the next | ||||
| +boot of a domain.  If I<--live> is specified, the domain must be | ||||
| +running, and the change takes place immediately.  Both flags may be | ||||
| +specified, if supported by the hypervisor.  If neither flag is given, | ||||
| +then I<--live> is implied and it is up to the hypervisor whether | ||||
| +I<--config> is also implied. | ||||
| + | ||||
| +If I<--maximum> is specified, then you must use I<--config> and | ||||
| +avoid I<--live>; this flag controls the maximum limit of vcpus that | ||||
| +can be hot-plugged the next time the domain is booted. | ||||
| + | ||||
|  =item B<shutdown> I<domain-id> | ||||
|  | ||||
|  Gracefully shuts down a domain.  This coordinates with the domain OS | ||||
| @@ -568,6 +587,21 @@ is not available the processes will provide an exit code of 1. | ||||
|  Undefine the configuration for an inactive domain. Since it's not running | ||||
|  the domain name or UUID must be used as the I<domain-id>. | ||||
|  | ||||
| +=item B<vcpucount> I<domain-id>  optional I<--maximum> I<--current> | ||||
| +I<--config> I<--live> | ||||
| + | ||||
| +Print information about the virtual cpu counts of the given | ||||
| +I<domain-id>.  If no flags are specified, all possible counts are | ||||
| +listed in a table; otherwise, the output is limited to just the | ||||
| +numeric value requested. | ||||
| + | ||||
| +I<--maximum> requests information on the maximum cap of vcpus that a | ||||
| +domain can add via B<setvcpus>, while I<--current> shows the current | ||||
| +usage; these two flags cannot both be specified.  I<--config> | ||||
| +requests information regarding the next time the domain will be | ||||
| +booted, while I<--live> requires a running domain and lists current | ||||
| +values; these two flags cannot both be specified. | ||||
| + | ||||
|  =item B<vcpuinfo> I<domain-id> | ||||
|  | ||||
|  Returns basic information about the domain virtual CPUs, like the number of | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,519 +0,0 @@ | ||||
| From 4617eedfaeee2b187a1f14691d25746ba3ff31b6 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Wed, 29 Sep 2010 10:20:07 -0600 | ||||
| Subject: [PATCH 07/15] vcpu: support maxvcpu in domain_conf | ||||
|  | ||||
| Although this patch adds a distinction between maximum vcpus and | ||||
| current vcpus in the XML, the values should be identical for all | ||||
| drivers at this point.  Only in subsequent per-driver patches will | ||||
| a distinction be made. | ||||
|  | ||||
| In general, virDomainGetInfo should prefer the current vcpus. | ||||
|  | ||||
| * src/conf/domain_conf.h (_virDomainDef): Adjust vcpus to unsigned | ||||
| short, to match virDomainGetInfo limit.  Add maxvcpus member. | ||||
| * src/conf/domain_conf.c (virDomainDefParseXML) | ||||
| (virDomainDefFormat): parse and print out vcpu details. | ||||
| * src/xen/xend_internal.c (xenDaemonParseSxpr) | ||||
| (xenDaemonFormatSxpr): Manage both vcpu numbers, and require them | ||||
| to be equal for now. | ||||
| * src/xen/xm_internal.c (xenXMDomainConfigParse) | ||||
| (xenXMDomainConfigFormat): Likewise. | ||||
| * src/phyp/phyp_driver.c (phypDomainDumpXML): Likewise. | ||||
| * src/openvz/openvz_conf.c (openvzLoadDomains): Likewise. | ||||
| * src/openvz/openvz_driver.c (openvzDomainDefineXML) | ||||
| (openvzDomainCreateXML, openvzDomainSetVcpusInternal): Likewise. | ||||
| * src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxDomainDefineXML): | ||||
| Likewise. | ||||
| * src/xenapi/xenapi_driver.c (xenapiDomainDumpXML): Likewise. | ||||
| * src/xenapi/xenapi_utils.c (createVMRecordFromXml): Likewise. | ||||
| * src/esx/esx_vmx.c (esxVMX_ParseConfig, esxVMX_FormatConfig): | ||||
| Likewise. | ||||
| * src/qemu/qemu_conf.c (qemuBuildSmpArgStr) | ||||
| (qemuParseCommandLineSmp, qemuParseCommandLine): Likewise. | ||||
| * src/qemu/qemu_driver.c (qemudDomainHotplugVcpus): Likewise. | ||||
| * src/opennebula/one_conf.c (xmlOneTemplate): Likewise. | ||||
| --- | ||||
|  src/conf/domain_conf.c     |   45 +++++++++++++++++++++++++++++++++++++------ | ||||
|  src/conf/domain_conf.h     |    3 +- | ||||
|  src/esx/esx_vmx.c          |   24 ++++++++++++++-------- | ||||
|  src/opennebula/one_conf.c  |    9 +++++-- | ||||
|  src/openvz/openvz_conf.c   |    7 +++-- | ||||
|  src/openvz/openvz_driver.c |   15 +++++++++---- | ||||
|  src/phyp/phyp_driver.c     |    2 +- | ||||
|  src/qemu/qemu_conf.c       |   14 +++++++++++- | ||||
|  src/qemu/qemu_driver.c     |    5 ++- | ||||
|  src/vbox/vbox_tmpl.c       |   12 +++++++--- | ||||
|  src/xen/xend_internal.c    |    9 ++++--- | ||||
|  src/xen/xm_internal.c      |   11 ++++++--- | ||||
|  src/xenapi/xenapi_driver.c |    2 +- | ||||
|  src/xenapi/xenapi_utils.c  |    4 +- | ||||
|  14 files changed, 114 insertions(+), 48 deletions(-) | ||||
|  | ||||
| diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c | ||||
| index 78d7a6a..a997e06 100644 | ||||
| --- a/src/conf/domain_conf.c | ||||
| +++ b/src/conf/domain_conf.c | ||||
| @@ -4203,6 +4203,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, | ||||
|      int i, n; | ||||
|      long id = -1; | ||||
|      virDomainDefPtr def; | ||||
| +    unsigned long count; | ||||
|  | ||||
|      if (VIR_ALLOC(def) < 0) { | ||||
|          virReportOOMError(); | ||||
| @@ -4287,8 +4288,37 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, | ||||
|                        &def->mem.swap_hard_limit) < 0) | ||||
|          def->mem.swap_hard_limit = 0; | ||||
|  | ||||
| -    if (virXPathULong("string(./vcpu[1])", ctxt, &def->vcpus) < 0) | ||||
| -        def->vcpus = 1; | ||||
| +    n = virXPathULong("string(./vcpu[1])", ctxt, &count); | ||||
| +    if (n == -2) { | ||||
| +        virDomainReportError(VIR_ERR_XML_ERROR, "%s", | ||||
| +                             _("maximum vcpus must be an integer")); | ||||
| +        goto error; | ||||
| +    } else if (n < 0) { | ||||
| +        def->maxvcpus = 1; | ||||
| +    } else { | ||||
| +        def->maxvcpus = count; | ||||
| +        if (def->maxvcpus != count || count == 0) { | ||||
| +            virDomainReportError(VIR_ERR_XML_ERROR, | ||||
| +                                 _("invalid maxvcpus %lu"), count); | ||||
| +            goto error; | ||||
| +        } | ||||
| +    } | ||||
| + | ||||
| +    n = virXPathULong("string(./vcpu[1]/@current)", ctxt, &count); | ||||
| +    if (n == -2) { | ||||
| +        virDomainReportError(VIR_ERR_XML_ERROR, "%s", | ||||
| +                             _("current vcpus must be an integer")); | ||||
| +        goto error; | ||||
| +    } else if (n < 0) { | ||||
| +        def->vcpus = def->maxvcpus; | ||||
| +    } else { | ||||
| +        def->vcpus = count; | ||||
| +        if (def->vcpus != count || count == 0 || def->maxvcpus < count) { | ||||
| +            virDomainReportError(VIR_ERR_XML_ERROR, | ||||
| +                                 _("invalid current vcpus %lu"), count); | ||||
| +            goto error; | ||||
| +        } | ||||
| +    } | ||||
|  | ||||
|      tmp = virXPathString("string(./vcpu[1]/@cpuset)", ctxt); | ||||
|      if (tmp) { | ||||
| @@ -6462,17 +6492,18 @@ char *virDomainDefFormat(virDomainDefPtr def, | ||||
|          if (def->cpumask[n] != 1) | ||||
|              allones = 0; | ||||
|  | ||||
| -    if (allones) { | ||||
| -        virBufferAsprintf(&buf, "  <vcpu>%lu</vcpu>\n", def->vcpus); | ||||
| -    } else { | ||||
| +    virBufferAddLit(&buf, "  <vcpu"); | ||||
| +    if (!allones) { | ||||
|          char *cpumask = NULL; | ||||
|          if ((cpumask = | ||||
|               virDomainCpuSetFormat(def->cpumask, def->cpumasklen)) == NULL) | ||||
|              goto cleanup; | ||||
| -        virBufferAsprintf(&buf, "  <vcpu cpuset='%s'>%lu</vcpu>\n", | ||||
| -                          cpumask, def->vcpus); | ||||
| +        virBufferAsprintf(&buf, " cpuset='%s'", cpumask); | ||||
|          VIR_FREE(cpumask); | ||||
|      } | ||||
| +    if (def->vcpus != def->maxvcpus) | ||||
| +        virBufferAsprintf(&buf, " current='%u'", def->vcpus); | ||||
| +    virBufferAsprintf(&buf, ">%u</vcpu>\n", def->maxvcpus); | ||||
|  | ||||
|      if (def->os.bootloader) { | ||||
|          virBufferEscapeString(&buf, "  <bootloader>%s</bootloader>\n", | ||||
| diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h | ||||
| index db09c23..5499f28 100644 | ||||
| --- a/src/conf/domain_conf.h | ||||
| +++ b/src/conf/domain_conf.h | ||||
| @@ -885,7 +885,8 @@ struct _virDomainDef { | ||||
|          unsigned long min_guarantee; | ||||
|          unsigned long swap_hard_limit; | ||||
|      } mem; | ||||
| -    unsigned long vcpus; | ||||
| +    unsigned short vcpus; | ||||
| +    unsigned short maxvcpus; | ||||
|      int cpumasklen; | ||||
|      char *cpumask; | ||||
|  | ||||
| diff --git a/src/esx/esx_vmx.c b/src/esx/esx_vmx.c | ||||
| index 7ec8c0e..0a26614 100644 | ||||
| --- a/src/esx/esx_vmx.c | ||||
| +++ b/src/esx/esx_vmx.c | ||||
| @@ -50,7 +50,7 @@ def->uuid = <value>               <=>   uuid.bios = "<value>" | ||||
|  def->name = <value>               <=>   displayName = "<value>" | ||||
|  def->mem.max_balloon = <value kilobyte>    <=>   memsize = "<value megabyte>"            # must be a multiple of 4, defaults to 32 | ||||
|  def->mem.cur_balloon = <value kilobyte>    <=>   sched.mem.max = "<value megabyte>"      # defaults to "unlimited" -> def->mem.cur_balloon = def->mem.max_balloon | ||||
| -def->vcpus = <value>              <=>   numvcpus = "<value>"                    # must be 1 or a multiple of 2, defaults to 1 | ||||
| +def->maxvcpus = <value>           <=>   numvcpus = "<value>"                    # must be 1 or a multiple of 2, defaults to 1 | ||||
|  def->cpumask = <uint list>        <=>   sched.cpu.affinity = "<uint list>" | ||||
|  | ||||
|  | ||||
| @@ -1075,7 +1075,7 @@ esxVMX_ParseConfig(esxVMX_Context *ctx, virCapsPtr caps, const char *vmx, | ||||
|          goto cleanup; | ||||
|      } | ||||
|  | ||||
| -    def->vcpus = numvcpus; | ||||
| +    def->maxvcpus = def->vcpus = numvcpus; | ||||
|  | ||||
|      /* vmx:sched.cpu.affinity -> def:cpumask */ | ||||
|      // VirtualMachine:config.cpuAffinity.affinitySet | ||||
| @@ -2609,16 +2609,22 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def, | ||||
|                            (int)(def->mem.cur_balloon / 1024)); | ||||
|      } | ||||
|  | ||||
| -    /* def:vcpus -> vmx:numvcpus */ | ||||
| -    if (def->vcpus <= 0 || (def->vcpus % 2 != 0 && def->vcpus != 1)) { | ||||
| +    /* def:maxvcpus -> vmx:numvcpus */ | ||||
| +    if (def->vcpus != def->maxvcpus) { | ||||
| +        ESX_ERROR(VIR_ERR_CONFIG_UNSUPPORTED, | ||||
| +                  _("No support for domain XML entry 'vcpu' attribute " | ||||
| +                    "'current'")); | ||||
| +        goto cleanup; | ||||
| +    } | ||||
| +    if (def->maxvcpus <= 0 || (def->maxvcpus % 2 != 0 && def->maxvcpus != 1)) { | ||||
|          ESX_ERROR(VIR_ERR_INTERNAL_ERROR, | ||||
|                    _("Expecting domain XML entry 'vcpu' to be an unsigned " | ||||
|                      "integer (1 or a multiple of 2) but found %d"), | ||||
| -                  (int)def->vcpus); | ||||
| +                  def->maxvcpus); | ||||
|          goto cleanup; | ||||
|      } | ||||
|  | ||||
| -    virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", (int)def->vcpus); | ||||
| +    virBufferAsprintf(&buffer, "numvcpus = \"%d\"\n", def->maxvcpus); | ||||
|  | ||||
|      /* def:cpumask -> vmx:sched.cpu.affinity */ | ||||
|      if (def->cpumasklen > 0) { | ||||
| @@ -2632,11 +2638,11 @@ esxVMX_FormatConfig(esxVMX_Context *ctx, virCapsPtr caps, virDomainDefPtr def, | ||||
|              } | ||||
|          } | ||||
|  | ||||
| -        if (sched_cpu_affinity_length < def->vcpus) { | ||||
| +        if (sched_cpu_affinity_length < def->maxvcpus) { | ||||
|              ESX_ERROR(VIR_ERR_INTERNAL_ERROR, | ||||
|                        _("Expecting domain XML attribute 'cpuset' of entry " | ||||
| -                        "'vcpu' to contains at least %d CPU(s)"), | ||||
| -                      (int)def->vcpus); | ||||
| +                        "'vcpu' to contain at least %d CPU(s)"), | ||||
| +                      def->maxvcpus); | ||||
|              goto cleanup; | ||||
|          } | ||||
|  | ||||
| diff --git a/src/opennebula/one_conf.c b/src/opennebula/one_conf.c | ||||
| index 44e28dc..2079c51 100644 | ||||
| --- a/src/opennebula/one_conf.c | ||||
| +++ b/src/opennebula/one_conf.c | ||||
| @@ -1,5 +1,7 @@ | ||||
|  /*----------------------------------------------------------------------------------*/ | ||||
| -/* Copyright 2002-2009, Distributed Systems Architecture Group, Universidad | ||||
| +/* | ||||
| + * Copyright (C) 2010 Red Hat, Inc. | ||||
| + * Copyright 2002-2009, Distributed Systems Architecture Group, Universidad | ||||
|   * Complutense de Madrid (dsa-research.org) | ||||
|   * | ||||
|   * This library is free software; you can redistribute it and/or | ||||
| @@ -169,9 +171,10 @@ char* xmlOneTemplate(virDomainDefPtr def) | ||||
|  { | ||||
|      int i; | ||||
|      virBuffer buf= VIR_BUFFER_INITIALIZER; | ||||
| -    virBufferAsprintf(&buf,"#OpenNebula Template automatically generated by libvirt\nNAME = %s\nCPU = %ld\nMEMORY = %ld\n", | ||||
| +    virBufferAsprintf(&buf,"#OpenNebula Template automatically generated " | ||||
| +                      "by libvirt\nNAME = %s\nCPU = %d\nMEMORY = %ld\n", | ||||
|                        def->name, | ||||
| -                      def->vcpus, | ||||
| +                      def->maxvcpus, | ||||
|                        (def->mem.max_balloon)/1024); | ||||
|  | ||||
|      /*Optional Booting OpenNebula Information:*/ | ||||
| diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c | ||||
| index ec11bbc..c84a6f3 100644 | ||||
| --- a/src/openvz/openvz_conf.c | ||||
| +++ b/src/openvz/openvz_conf.c | ||||
| @@ -507,11 +507,12 @@ int openvzLoadDomains(struct openvz_driver *driver) { | ||||
|                          veid); | ||||
|              goto cleanup; | ||||
|          } else if (ret > 0) { | ||||
| -            dom->def->vcpus = strtoI(temp); | ||||
| +            dom->def->maxvcpus = strtoI(temp); | ||||
|          } | ||||
|  | ||||
| -        if (ret == 0 || dom->def->vcpus == 0) | ||||
| -            dom->def->vcpus = openvzGetNodeCPUs(); | ||||
| +        if (ret == 0 || dom->def->maxvcpus == 0) | ||||
| +            dom->def->maxvcpus = openvzGetNodeCPUs(); | ||||
| +        dom->def->vcpus = dom->def->maxvcpus; | ||||
|  | ||||
|          /* XXX load rest of VM config data .... */ | ||||
|  | ||||
| diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c | ||||
| index 0f3cfdf..b7c2754 100644 | ||||
| --- a/src/openvz/openvz_driver.c | ||||
| +++ b/src/openvz/openvz_driver.c | ||||
| @@ -925,8 +925,13 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml) | ||||
|      if (openvzDomainSetNetworkConfig(conn, vm->def) < 0) | ||||
|          goto cleanup; | ||||
|  | ||||
| -    if (vm->def->vcpus > 0) { | ||||
| -        if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) { | ||||
| +    if (vm->def->vcpus != vm->def->maxvcpus) { | ||||
| +        openvzError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", | ||||
| +                    _("current vcpu count must equal maximum")); | ||||
| +        goto cleanup; | ||||
| +    } | ||||
| +    if (vm->def->maxvcpus > 0) { | ||||
| +        if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) { | ||||
|              openvzError(VIR_ERR_INTERNAL_ERROR, "%s", | ||||
|                          _("Could not set number of virtual cpu")); | ||||
|               goto cleanup; | ||||
| @@ -1019,8 +1024,8 @@ openvzDomainCreateXML(virConnectPtr conn, const char *xml, | ||||
|      vm->def->id = vm->pid; | ||||
|      vm->state = VIR_DOMAIN_RUNNING; | ||||
|  | ||||
| -    if (vm->def->vcpus > 0) { | ||||
| -        if (openvzDomainSetVcpusInternal(vm, vm->def->vcpus) < 0) { | ||||
| +    if (vm->def->maxvcpus > 0) { | ||||
| +        if (openvzDomainSetVcpusInternal(vm, vm->def->maxvcpus) < 0) { | ||||
|              openvzError(VIR_ERR_INTERNAL_ERROR, "%s", | ||||
|                          _("Could not set number of virtual cpu")); | ||||
|              goto cleanup; | ||||
| @@ -1249,7 +1254,7 @@ static int openvzDomainSetVcpusInternal(virDomainObjPtr vm, | ||||
|          return -1; | ||||
|      } | ||||
|  | ||||
| -    vm->def->vcpus = nvcpus; | ||||
| +    vm->def->maxvcpus = vm->def->vcpus = nvcpus; | ||||
|      return 0; | ||||
|  } | ||||
|  | ||||
| diff --git a/src/phyp/phyp_driver.c b/src/phyp/phyp_driver.c | ||||
| index e284ae0..3d0ed11 100644 | ||||
| --- a/src/phyp/phyp_driver.c | ||||
| +++ b/src/phyp/phyp_driver.c | ||||
| @@ -3540,7 +3540,7 @@ phypDomainDumpXML(virDomainPtr dom, int flags) | ||||
|          goto err; | ||||
|      } | ||||
|  | ||||
| -    if ((def.vcpus = | ||||
| +    if ((def.maxvcpus = def.vcpus = | ||||
|           phypGetLparCPU(dom->conn, managed_system, dom->id)) == 0) { | ||||
|          VIR_ERROR0(_("Unable to determine domain's CPU.")); | ||||
|          goto err; | ||||
| diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c | ||||
| index 83c0f83..38c8351 100644 | ||||
| --- a/src/qemu/qemu_conf.c | ||||
| +++ b/src/qemu/qemu_conf.c | ||||
| @@ -3711,7 +3711,7 @@ qemuBuildSmpArgStr(const virDomainDefPtr def, | ||||
|  { | ||||
|      virBuffer buf = VIR_BUFFER_INITIALIZER; | ||||
|  | ||||
| -    virBufferAsprintf(&buf, "%lu", def->vcpus); | ||||
| +    virBufferAsprintf(&buf, "%u", def->vcpus); | ||||
|  | ||||
|      if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) { | ||||
|          /* sockets, cores, and threads are either all zero | ||||
| @@ -3722,11 +3722,18 @@ qemuBuildSmpArgStr(const virDomainDefPtr def, | ||||
|              virBufferAsprintf(&buf, ",threads=%u", def->cpu->threads); | ||||
|          } | ||||
|          else { | ||||
| -            virBufferAsprintf(&buf, ",sockets=%lu", def->vcpus); | ||||
| +            virBufferAsprintf(&buf, ",sockets=%u", def->maxvcpus); | ||||
|              virBufferAsprintf(&buf, ",cores=%u", 1); | ||||
|              virBufferAsprintf(&buf, ",threads=%u", 1); | ||||
|          } | ||||
|      } | ||||
| +    if (def->vcpus != def->maxvcpus) { | ||||
| +        virBufferFreeAndReset(&buf); | ||||
| +        qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", | ||||
| +                        _("setting current vcpu count less than maximum is " | ||||
| +                          "not supported yet")); | ||||
| +        return NULL; | ||||
| +    } | ||||
|  | ||||
|      if (virBufferError(&buf)) { | ||||
|          virBufferFreeAndReset(&buf); | ||||
| @@ -6178,6 +6185,8 @@ qemuParseCommandLineSmp(virDomainDefPtr dom, | ||||
|          } | ||||
|      } | ||||
|  | ||||
| +    dom->maxvcpus = dom->vcpus; | ||||
| + | ||||
|      if (sockets && cores && threads) { | ||||
|          virCPUDefPtr cpu; | ||||
|  | ||||
| @@ -6247,6 +6256,7 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, | ||||
|  | ||||
|      def->id = -1; | ||||
|      def->mem.cur_balloon = def->mem.max_balloon = 64 * 1024; | ||||
| +    def->maxvcpus = 1; | ||||
|      def->vcpus = 1; | ||||
|      def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; | ||||
|      def->features = (1 << VIR_DOMAIN_FEATURE_ACPI) | ||||
| diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c | ||||
| index 7a2ea8f..c66dc04 100644 | ||||
| --- a/src/qemu/qemu_driver.c | ||||
| +++ b/src/qemu/qemu_driver.c | ||||
| @@ -2425,8 +2425,9 @@ qemuDetectVcpuPIDs(struct qemud_driver *driver, | ||||
|  | ||||
|      if (ncpupids != vm->def->vcpus) { | ||||
|          qemuReportError(VIR_ERR_INTERNAL_ERROR, | ||||
| -                        _("got wrong number of vCPU pids from QEMU monitor. got %d, wanted %d"), | ||||
| -                        ncpupids, (int)vm->def->vcpus); | ||||
| +                        _("got wrong number of vCPU pids from QEMU monitor. " | ||||
| +                          "got %d, wanted %d"), | ||||
| +                        ncpupids, vm->def->vcpus); | ||||
|          VIR_FREE(cpupids); | ||||
|          return -1; | ||||
|      } | ||||
| diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c | ||||
| index 0cbe8b3..5a859a4 100644 | ||||
| --- a/src/vbox/vbox_tmpl.c | ||||
| +++ b/src/vbox/vbox_tmpl.c | ||||
| @@ -2028,7 +2028,7 @@ static char *vboxDomainDumpXML(virDomainPtr dom, int flags) { | ||||
|              def->mem.max_balloon = memorySize * 1024; | ||||
|  | ||||
|              machine->vtbl->GetCPUCount(machine, &CPUCount); | ||||
| -            def->vcpus = CPUCount; | ||||
| +            def->maxvcpus = def->vcpus = CPUCount; | ||||
|  | ||||
|              /* Skip cpumasklen, cpumask, onReboot, onPoweroff, onCrash */ | ||||
|  | ||||
| @@ -4598,11 +4598,15 @@ static virDomainPtr vboxDomainDefineXML(virConnectPtr conn, const char *xml) { | ||||
|                    def->mem.cur_balloon, (unsigned)rc); | ||||
|      } | ||||
|  | ||||
| -    rc = machine->vtbl->SetCPUCount(machine, def->vcpus); | ||||
| +    if (def->vcpus != def->maxvcpus) { | ||||
| +        vboxError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", | ||||
| +                    _("current vcpu count must equal maximum")); | ||||
| +    } | ||||
| +    rc = machine->vtbl->SetCPUCount(machine, def->maxvcpus); | ||||
|      if (NS_FAILED(rc)) { | ||||
|          vboxError(VIR_ERR_INTERNAL_ERROR, | ||||
| -                  _("could not set the number of virtual CPUs to: %lu, rc=%08x"), | ||||
| -                  def->vcpus, (unsigned)rc); | ||||
| +                  _("could not set the number of virtual CPUs to: %u, rc=%08x"), | ||||
| +                  def->maxvcpus, (unsigned)rc); | ||||
|      } | ||||
|  | ||||
|  #if VBOX_API_VERSION < 3001 | ||||
| diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c | ||||
| index 5ffc3c8..456b477 100644 | ||||
| --- a/src/xen/xend_internal.c | ||||
| +++ b/src/xen/xend_internal.c | ||||
| @@ -2190,7 +2190,8 @@ xenDaemonParseSxpr(virConnectPtr conn, | ||||
|          } | ||||
|      } | ||||
|  | ||||
| -    def->vcpus = sexpr_int(root, "domain/vcpus"); | ||||
| +    def->maxvcpus = sexpr_int(root, "domain/vcpus"); | ||||
| +    def->vcpus = def->maxvcpus; | ||||
|  | ||||
|      tmp = sexpr_node(root, "domain/on_poweroff"); | ||||
|      if (tmp != NULL) { | ||||
| @@ -5649,7 +5650,7 @@ xenDaemonFormatSxprInput(virDomainInputDefPtr input, | ||||
|   * | ||||
|   * Generate an SEXPR representing the domain configuration. | ||||
|   * | ||||
| - * Returns the 0 terminatedi S-Expr string or NULL in case of error. | ||||
| + * Returns the 0 terminated S-Expr string or NULL in case of error. | ||||
|   *         the caller must free() the returned value. | ||||
|   */ | ||||
|  char * | ||||
| @@ -5666,7 +5667,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, | ||||
|      virBufferAsprintf(&buf, "(name '%s')", def->name); | ||||
|      virBufferAsprintf(&buf, "(memory %lu)(maxmem %lu)", | ||||
|                        def->mem.cur_balloon/1024, def->mem.max_balloon/1024); | ||||
| -    virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus); | ||||
| +    virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); | ||||
|  | ||||
|      if (def->cpumask) { | ||||
|          char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen); | ||||
| @@ -5761,7 +5762,7 @@ xenDaemonFormatSxpr(virConnectPtr conn, | ||||
|              else | ||||
|                  virBufferAsprintf(&buf, "(kernel '%s')", def->os.loader); | ||||
|  | ||||
| -            virBufferAsprintf(&buf, "(vcpus %lu)", def->vcpus); | ||||
| +            virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); | ||||
|  | ||||
|              for (i = 0 ; i < def->os.nBootDevs ; i++) { | ||||
|                  switch (def->os.bootDevs[i]) { | ||||
| diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c | ||||
| index 8e42a1c..bf20a64 100644 | ||||
| --- a/src/xen/xm_internal.c | ||||
| +++ b/src/xen/xm_internal.c | ||||
| @@ -678,6 +678,7 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { | ||||
|      int i; | ||||
|      const char *defaultArch, *defaultMachine; | ||||
|      int vmlocaltime = 0; | ||||
| +    unsigned long count; | ||||
|  | ||||
|      if (VIR_ALLOC(def) < 0) { | ||||
|          virReportOOMError(); | ||||
| @@ -770,9 +771,11 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { | ||||
|      def->mem.cur_balloon *= 1024; | ||||
|      def->mem.max_balloon *= 1024; | ||||
|  | ||||
| - | ||||
| -    if (xenXMConfigGetULong(conf, "vcpus", &def->vcpus, 1) < 0) | ||||
| +    if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 || | ||||
| +        (unsigned short) count != count) | ||||
|          goto cleanup; | ||||
| +    def->maxvcpus = count; | ||||
| +    def->vcpus = def->maxvcpus; | ||||
|  | ||||
|      if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0) | ||||
|          goto cleanup; | ||||
| @@ -1650,7 +1653,7 @@ int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) { | ||||
|      if (!(entry = virHashLookup(priv->configCache, filename))) | ||||
|          goto cleanup; | ||||
|  | ||||
| -    entry->def->vcpus = vcpus; | ||||
| +    entry->def->maxvcpus = entry->def->vcpus = vcpus; | ||||
|  | ||||
|      /* If this fails, should we try to undo our changes to the | ||||
|       * in-memory representation of the config file. I say not! | ||||
| @@ -2241,7 +2244,7 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, | ||||
|      if (xenXMConfigSetInt(conf, "memory", def->mem.cur_balloon / 1024) < 0) | ||||
|          goto no_memory; | ||||
|  | ||||
| -    if (xenXMConfigSetInt(conf, "vcpus", def->vcpus) < 0) | ||||
| +    if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0) | ||||
|          goto no_memory; | ||||
|  | ||||
|      if ((def->cpumask != NULL) && | ||||
| diff --git a/src/xenapi/xenapi_driver.c b/src/xenapi/xenapi_driver.c | ||||
| index 7d4ab8d..5ccdede 100644 | ||||
| --- a/src/xenapi/xenapi_driver.c | ||||
| +++ b/src/xenapi/xenapi_driver.c | ||||
| @@ -1335,7 +1335,7 @@ xenapiDomainDumpXML (virDomainPtr dom, int flags ATTRIBUTE_UNUSED) | ||||
|      } else { | ||||
|          defPtr->mem.cur_balloon = memory; | ||||
|      } | ||||
| -    defPtr->vcpus = xenapiDomainGetMaxVcpus(dom); | ||||
| +    defPtr->maxvcpus = defPtr->vcpus = xenapiDomainGetMaxVcpus(dom); | ||||
|      enum xen_on_normal_exit action; | ||||
|      if (xen_vm_get_actions_after_shutdown(session, &action, vm)) { | ||||
|          defPtr->onPoweroff = xenapiNormalExitEnum2virDomainLifecycle(action); | ||||
| diff --git a/src/xenapi/xenapi_utils.c b/src/xenapi/xenapi_utils.c | ||||
| index be55491..a7e2a4b 100644 | ||||
| --- a/src/xenapi/xenapi_utils.c | ||||
| +++ b/src/xenapi/xenapi_utils.c | ||||
| @@ -510,8 +510,8 @@ createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def, | ||||
|      else | ||||
|          (*record)->memory_dynamic_max = (*record)->memory_static_max; | ||||
|  | ||||
| -    if (def->vcpus) { | ||||
| -        (*record)->vcpus_max = (int64_t) def->vcpus; | ||||
| +    if (def->maxvcpus) { | ||||
| +        (*record)->vcpus_max = (int64_t) def->maxvcpus; | ||||
|          (*record)->vcpus_at_startup = (int64_t) def->vcpus; | ||||
|      } | ||||
|      if (def->onPoweroff) | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,197 +0,0 @@ | ||||
| From 6c9e6b956453d0f0c4ff542ef8a184d663a39266 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Mon, 4 Oct 2010 17:01:12 -0600 | ||||
| Subject: [PATCH 09/15] vcpu: support all flags in test driver | ||||
|  | ||||
| * src/test/test_driver.c (testDomainGetVcpusFlags) | ||||
| (testDomainSetVcpusFlags): Support all flags. | ||||
| (testDomainUpdateVCPUs): Update cpu count here. | ||||
| --- | ||||
|  src/test/test_driver.c |  128 ++++++++++++++++++++++++++++++++++++++++------- | ||||
|  1 files changed, 109 insertions(+), 19 deletions(-) | ||||
|  | ||||
| diff --git a/src/test/test_driver.c b/src/test/test_driver.c | ||||
| index b70c80d..a9d3d89 100644 | ||||
| --- a/src/test/test_driver.c | ||||
| +++ b/src/test/test_driver.c | ||||
| @@ -450,6 +450,7 @@ testDomainUpdateVCPUs(virConnectPtr conn, | ||||
|                  goto cleanup; | ||||
|      } | ||||
|  | ||||
| +    dom->def->vcpus = nvcpus; | ||||
|      ret = 0; | ||||
|  cleanup: | ||||
|      return ret; | ||||
| @@ -2032,12 +2033,51 @@ cleanup: | ||||
|  static int | ||||
|  testDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) | ||||
|  { | ||||
| -    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| -        testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +    testConnPtr privconn = domain->conn->privateData; | ||||
| +    virDomainObjPtr vm; | ||||
| +    virDomainDefPtr def; | ||||
| +    int ret = -1; | ||||
| + | ||||
| +    virCheckFlags(VIR_DOMAIN_VCPU_LIVE | | ||||
| +                  VIR_DOMAIN_VCPU_CONFIG | | ||||
| +                  VIR_DOMAIN_VCPU_MAXIMUM, -1); | ||||
| + | ||||
| +    /* Exactly one of LIVE or CONFIG must be set.  */ | ||||
| +    if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) { | ||||
| +        testError(VIR_ERR_INVALID_ARG, | ||||
| +                  _("invalid flag combination: (0x%x)"), flags); | ||||
|          return -1; | ||||
|      } | ||||
|  | ||||
| -    return testGetMaxVCPUs(domain->conn, "test"); | ||||
| +    testDriverLock(privconn); | ||||
| +    vm = virDomainFindByUUID(&privconn->domains, domain->uuid); | ||||
| +    testDriverUnlock(privconn); | ||||
| + | ||||
| +    if (!vm) { | ||||
| +        char uuidstr[VIR_UUID_STRING_BUFLEN]; | ||||
| +        virUUIDFormat(domain->uuid, uuidstr); | ||||
| +        testError(VIR_ERR_NO_DOMAIN, | ||||
| +                  _("no domain with matching uuid '%s'"), uuidstr); | ||||
| +        goto cleanup; | ||||
| +    } | ||||
| + | ||||
| +    if (flags & VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        if (!virDomainObjIsActive(vm)) { | ||||
| +            testError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                      _("domain not active")); | ||||
| +            goto cleanup; | ||||
| +        } | ||||
| +        def = vm->def; | ||||
| +    } else { | ||||
| +        def = vm->newDef ? vm->newDef : vm->def; | ||||
| +    } | ||||
| + | ||||
| +    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus; | ||||
| + | ||||
| +cleanup: | ||||
| +    if (vm) | ||||
| +        virDomainObjUnlock(vm); | ||||
| +    return ret; | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| @@ -2053,21 +2093,30 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus, | ||||
|  { | ||||
|      testConnPtr privconn = domain->conn->privateData; | ||||
|      virDomainObjPtr privdom = NULL; | ||||
| +    virDomainDefPtr def; | ||||
|      int ret = -1, maxvcpus; | ||||
|  | ||||
| -    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| -        testError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), flags); | ||||
| +    virCheckFlags(VIR_DOMAIN_VCPU_LIVE | | ||||
| +                  VIR_DOMAIN_VCPU_CONFIG | | ||||
| +                  VIR_DOMAIN_VCPU_MAXIMUM, -1); | ||||
| + | ||||
| +    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be | ||||
| +     * mixed with LIVE.  */ | ||||
| +    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 || | ||||
| +        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) == | ||||
| +         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) { | ||||
| +        testError(VIR_ERR_INVALID_ARG, | ||||
| +                  _("invalid flag combination: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    if (!nrCpus || (maxvcpus = testGetMaxVCPUs(domain->conn, NULL)) < nrCpus) { | ||||
| +        testError(VIR_ERR_INVALID_ARG, | ||||
| +                  _("argument out of range: %d"), nrCpus); | ||||
|          return -1; | ||||
|      } | ||||
| - | ||||
| -    /* Do this first before locking */ | ||||
| -    maxvcpus = testDomainGetMaxVcpus(domain); | ||||
| -    if (maxvcpus < 0) | ||||
| -        goto cleanup; | ||||
|  | ||||
|      testDriverLock(privconn); | ||||
| -    privdom = virDomainFindByName(&privconn->domains, | ||||
| -                                  domain->name); | ||||
| +    privdom = virDomainFindByUUID(&privconn->domains, domain->uuid); | ||||
|      testDriverUnlock(privconn); | ||||
|  | ||||
|      if (privdom == NULL) { | ||||
| @@ -2075,13 +2124,17 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus, | ||||
|          goto cleanup; | ||||
|      } | ||||
|  | ||||
| -    if (!virDomainObjIsActive(privdom)) { | ||||
| +    if (!virDomainObjIsActive(privdom) && (flags & VIR_DOMAIN_VCPU_LIVE)) { | ||||
|          testError(VIR_ERR_OPERATION_INVALID, | ||||
|                    "%s", _("cannot hotplug vcpus for an inactive domain")); | ||||
|          goto cleanup; | ||||
|      } | ||||
|  | ||||
| -    /* We allow more cpus in guest than host */ | ||||
| +    /* We allow more cpus in guest than host, but not more than the | ||||
| +     * domain's starting limit.  */ | ||||
| +    if ((flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) == | ||||
| +        VIR_DOMAIN_VCPU_LIVE && privdom->def->maxvcpus < maxvcpus) | ||||
| +        maxvcpus = privdom->def->maxvcpus; | ||||
|      if (nrCpus > maxvcpus) { | ||||
|          testError(VIR_ERR_INVALID_ARG, | ||||
|                    "requested cpu amount exceeds maximum (%d > %d)", | ||||
| @@ -2089,12 +2142,49 @@ testDomainSetVcpusFlags(virDomainPtr domain, unsigned int nrCpus, | ||||
|          goto cleanup; | ||||
|      } | ||||
|  | ||||
| -    /* Update VCPU state for the running domain */ | ||||
| -    if (testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0) < 0) | ||||
| -        goto cleanup; | ||||
| +    switch (flags) { | ||||
| +    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG: | ||||
| +        def = privdom->def; | ||||
| +        if (virDomainObjIsActive(privdom)) { | ||||
| +            if (privdom->newDef) | ||||
| +                def = privdom->newDef; | ||||
| +            else { | ||||
| +                testError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                          _("no persistent state")); | ||||
| +                goto cleanup; | ||||
| +            } | ||||
| +        } | ||||
| +        def->maxvcpus = nrCpus; | ||||
| +        if (nrCpus < def->vcpus) | ||||
| +            def->vcpus = nrCpus; | ||||
| +        ret = 0; | ||||
| +        break; | ||||
|  | ||||
| -    privdom->def->vcpus = nrCpus; | ||||
| -    ret = 0; | ||||
| +    case VIR_DOMAIN_VCPU_CONFIG: | ||||
| +        def = privdom->def; | ||||
| +        if (virDomainObjIsActive(privdom)) { | ||||
| +            if (privdom->newDef) | ||||
| +                def = privdom->newDef; | ||||
| +            else { | ||||
| +                testError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                          _("no persistent state")); | ||||
| +                goto cleanup; | ||||
| +            } | ||||
| +        } | ||||
| +        def->vcpus = nrCpus; | ||||
| +        ret = 0; | ||||
| +        break; | ||||
| + | ||||
| +    case VIR_DOMAIN_VCPU_LIVE: | ||||
| +        ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0); | ||||
| +        break; | ||||
| + | ||||
| +    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG: | ||||
| +        ret = testDomainUpdateVCPUs(domain->conn, privdom, nrCpus, 0); | ||||
| +        if (ret == 0 && privdom->newDef) | ||||
| +            privdom->newDef->vcpus = nrCpus; | ||||
| +        break; | ||||
| +    } | ||||
|  | ||||
|  cleanup: | ||||
|      if (privdom) | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,122 +0,0 @@ | ||||
| From d67c189e80e6aef7adf13e5763365555cfc1a02a Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Wed, 29 Sep 2010 15:58:47 -0600 | ||||
| Subject: [PATCH 10/15] vcpu: improve vcpu support in qemu command line | ||||
|  | ||||
| * src/qemu/qemu_conf.c (qemuParseCommandLineSmp): Distinguish | ||||
| between vcpus and maxvcpus, for new enough qemu. | ||||
| * tests/qemuargv2xmltest.c (mymain): Add new test. | ||||
| * tests/qemuxml2argvtest.c (mymain): Likewise. | ||||
| * tests/qemuxml2xmltest.c (mymain): Likewise. | ||||
| * tests/qemuxml2argvdata/qemuxml2argv-smp.args: New file. | ||||
| --- | ||||
|  src/qemu/qemu_conf.c                         |   13 +++++++++---- | ||||
|  tests/qemuargv2xmltest.c                     |    2 ++ | ||||
|  tests/qemuxml2argvdata/qemuxml2argv-smp.args |    1 + | ||||
|  tests/qemuxml2argvtest.c                     |    2 ++ | ||||
|  tests/qemuxml2xmltest.c                      |    2 ++ | ||||
|  5 files changed, 16 insertions(+), 4 deletions(-) | ||||
|  create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-smp.args | ||||
|  | ||||
| diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c | ||||
| index 38c8351..ffe184b 100644 | ||||
| --- a/src/qemu/qemu_conf.c | ||||
| +++ b/src/qemu/qemu_conf.c | ||||
| @@ -3714,6 +3714,8 @@ qemuBuildSmpArgStr(const virDomainDefPtr def, | ||||
|      virBufferAsprintf(&buf, "%u", def->vcpus); | ||||
|  | ||||
|      if ((qemuCmdFlags & QEMUD_CMD_FLAG_SMP_TOPOLOGY)) { | ||||
| +        if (def->vcpus != def->maxvcpus) | ||||
| +            virBufferAsprintf(&buf, ",maxcpus=%u", def->maxvcpus); | ||||
|          /* sockets, cores, and threads are either all zero | ||||
|           * or all non-zero, thus checking one of them is enough */ | ||||
|          if (def->cpu && def->cpu->sockets) { | ||||
| @@ -3726,12 +3728,12 @@ qemuBuildSmpArgStr(const virDomainDefPtr def, | ||||
|              virBufferAsprintf(&buf, ",cores=%u", 1); | ||||
|              virBufferAsprintf(&buf, ",threads=%u", 1); | ||||
|          } | ||||
| -    } | ||||
| -    if (def->vcpus != def->maxvcpus) { | ||||
| +    } else if (def->vcpus != def->maxvcpus) { | ||||
|          virBufferFreeAndReset(&buf); | ||||
| +        /* FIXME - consider hot-unplugging cpus after boot for older qemu */ | ||||
|          qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", | ||||
|                          _("setting current vcpu count less than maximum is " | ||||
| -                          "not supported yet")); | ||||
| +                          "not supported with this QEMU binary")); | ||||
|          return NULL; | ||||
|      } | ||||
|  | ||||
| @@ -6153,6 +6155,7 @@ qemuParseCommandLineSmp(virDomainDefPtr dom, | ||||
|      unsigned int sockets = 0; | ||||
|      unsigned int cores = 0; | ||||
|      unsigned int threads = 0; | ||||
| +    unsigned int maxcpus = 0; | ||||
|      int i; | ||||
|      int nkws; | ||||
|      char **kws; | ||||
| @@ -6180,12 +6183,14 @@ qemuParseCommandLineSmp(virDomainDefPtr dom, | ||||
|                  cores = n; | ||||
|              else if (STREQ(kws[i], "threads")) | ||||
|                  threads = n; | ||||
| +            else if (STREQ(kws[i], "maxcpus")) | ||||
| +                maxcpus = n; | ||||
|              else | ||||
|                  goto syntax; | ||||
|          } | ||||
|      } | ||||
|  | ||||
| -    dom->maxvcpus = dom->vcpus; | ||||
| +    dom->maxvcpus = maxcpus ? maxcpus : dom->vcpus; | ||||
|  | ||||
|      if (sockets && cores && threads) { | ||||
|          virCPUDefPtr cpu; | ||||
| diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c | ||||
| index 4f9ec84..d941b0b 100644 | ||||
| --- a/tests/qemuargv2xmltest.c | ||||
| +++ b/tests/qemuargv2xmltest.c | ||||
| @@ -221,6 +221,8 @@ mymain(int argc, char **argv) | ||||
|  | ||||
|      DO_TEST("hostdev-pci-address"); | ||||
|  | ||||
| +    DO_TEST("smp"); | ||||
| + | ||||
|      DO_TEST_FULL("restore-v1", 0, "stdio"); | ||||
|      DO_TEST_FULL("restore-v2", 0, "stdio"); | ||||
|      DO_TEST_FULL("restore-v2", 0, "exec:cat"); | ||||
| diff --git a/tests/qemuxml2argvdata/qemuxml2argv-smp.args b/tests/qemuxml2argvdata/qemuxml2argv-smp.args | ||||
| new file mode 100644 | ||||
| index 0000000..3ec8f15 | ||||
| --- /dev/null | ||||
| +++ b/tests/qemuxml2argvdata/qemuxml2argv-smp.args | ||||
| @@ -0,0 +1 @@ | ||||
| +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1,maxcpus=2,sockets=2,cores=1,threads=1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb | ||||
| diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c | ||||
| index 92d5b18..551d6c4 100644 | ||||
| --- a/tests/qemuxml2argvtest.c | ||||
| +++ b/tests/qemuxml2argvtest.c | ||||
| @@ -385,6 +385,8 @@ mymain(int argc, char **argv) | ||||
|  | ||||
|      DO_TEST("qemu-ns", 0); | ||||
|  | ||||
| +    DO_TEST("smp", QEMUD_CMD_FLAG_SMP_TOPOLOGY); | ||||
| + | ||||
|      free(driver.stateDir); | ||||
|      virCapabilitiesFree(driver.caps); | ||||
|  | ||||
| diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c | ||||
| index a33d435..cdc4390 100644 | ||||
| --- a/tests/qemuxml2xmltest.c | ||||
| +++ b/tests/qemuxml2xmltest.c | ||||
| @@ -180,6 +180,8 @@ mymain(int argc, char **argv) | ||||
|      DO_TEST("encrypted-disk"); | ||||
|      DO_TEST("memtune"); | ||||
|  | ||||
| +    DO_TEST("smp"); | ||||
| + | ||||
|      /* These tests generate different XML */ | ||||
|      DO_TEST_DIFFERENT("balloon-device-auto"); | ||||
|      DO_TEST_DIFFERENT("channel-virtio-auto"); | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,169 +0,0 @@ | ||||
| From 28a3605906385cba43df77051dc26e865f237b09 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Wed, 29 Sep 2010 17:40:45 -0600 | ||||
| Subject: [PATCH 11/15] vcpu: complete vcpu support in qemu driver | ||||
|  | ||||
| * src/qemu/qemu_driver.c (qemudDomainSetVcpusFlags) | ||||
| (qemudDomainGetVcpusFlags): Support all feasible flag | ||||
| combinations. | ||||
| --- | ||||
|  src/qemu/qemu_driver.c |  100 ++++++++++++++++++++++++++++++++++++++++------- | ||||
|  1 files changed, 85 insertions(+), 15 deletions(-) | ||||
|  | ||||
| diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c | ||||
| index c66dc04..a9e057f 100644 | ||||
| --- a/src/qemu/qemu_driver.c | ||||
| +++ b/src/qemu/qemu_driver.c | ||||
| @@ -5941,13 +5941,27 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
|  { | ||||
|      struct qemud_driver *driver = dom->conn->privateData; | ||||
|      virDomainObjPtr vm; | ||||
| +    virDomainDefPtr def; | ||||
|      const char * type; | ||||
|      int max; | ||||
|      int ret = -1; | ||||
|  | ||||
| -    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| -        qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| -                        flags); | ||||
| +    virCheckFlags(VIR_DOMAIN_VCPU_LIVE | | ||||
| +                  VIR_DOMAIN_VCPU_CONFIG | | ||||
| +                  VIR_DOMAIN_VCPU_MAXIMUM, -1); | ||||
| + | ||||
| +    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be | ||||
| +     * mixed with LIVE.  */ | ||||
| +    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 || | ||||
| +        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) == | ||||
| +         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) { | ||||
| +        qemuReportError(VIR_ERR_INVALID_ARG, | ||||
| +                        _("invalid flag combination: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    if (!nvcpus || (unsigned short) nvcpus != nvcpus) { | ||||
| +        qemuReportError(VIR_ERR_INVALID_ARG, | ||||
| +                        _("argument out of range: %d"), nvcpus); | ||||
|          return -1; | ||||
|      } | ||||
|  | ||||
| @@ -5966,7 +5980,7 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
|      if (qemuDomainObjBeginJob(vm) < 0) | ||||
|          goto cleanup; | ||||
|  | ||||
| -    if (!virDomainObjIsActive(vm)) { | ||||
| +    if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) { | ||||
|          qemuReportError(VIR_ERR_OPERATION_INVALID, | ||||
|                           "%s", _("domain is not running")); | ||||
|          goto endjob; | ||||
| @@ -5985,6 +5999,11 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
|          goto endjob; | ||||
|      } | ||||
|  | ||||
| +    if ((flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) == | ||||
| +        VIR_DOMAIN_VCPU_LIVE && vm->def->maxvcpus < max) { | ||||
| +        max = vm->def->maxvcpus; | ||||
| +    } | ||||
| + | ||||
|      if (nvcpus > max) { | ||||
|          qemuReportError(VIR_ERR_INVALID_ARG, | ||||
|                          _("requested vcpus is greater than max allowable" | ||||
| @@ -5992,7 +6011,49 @@ qemudDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, | ||||
|          goto endjob; | ||||
|      } | ||||
|  | ||||
| -    ret = qemudDomainHotplugVcpus(vm, nvcpus); | ||||
| +    switch (flags) { | ||||
| +    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG: | ||||
| +        def = vm->def; | ||||
| +        if (virDomainObjIsActive(vm)) { | ||||
| +            if (vm->newDef) | ||||
| +                def = vm->newDef; | ||||
| +            else{ | ||||
| +                qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                                _("no persistent state")); | ||||
| +                goto endjob; | ||||
| +            } | ||||
| +        } | ||||
| +        def->maxvcpus = nvcpus; | ||||
| +        if (nvcpus < vm->newDef->vcpus) | ||||
| +            def->vcpus = nvcpus; | ||||
| +        ret = 0; | ||||
| +        break; | ||||
| + | ||||
| +    case VIR_DOMAIN_VCPU_CONFIG: | ||||
| +        def = vm->def; | ||||
| +        if (virDomainObjIsActive(vm)) { | ||||
| +            if (vm->newDef) | ||||
| +                def = vm->newDef; | ||||
| +            else { | ||||
| +                qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                                _("no persistent state")); | ||||
| +                goto endjob; | ||||
| +            } | ||||
| +        } | ||||
| +        def->vcpus = nvcpus; | ||||
| +        ret = 0; | ||||
| +        break; | ||||
| + | ||||
| +    case VIR_DOMAIN_VCPU_LIVE: | ||||
| +        ret = qemudDomainHotplugVcpus(vm, nvcpus); | ||||
| +        break; | ||||
| + | ||||
| +    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG: | ||||
| +        ret = qemudDomainHotplugVcpus(vm, nvcpus); | ||||
| +        if (ret == 0 && vm->newDef) | ||||
| +            vm->newDef->vcpus = nvcpus; | ||||
| +        break; | ||||
| +    } | ||||
|  | ||||
|  endjob: | ||||
|      if (qemuDomainObjEndJob(vm) == 0) | ||||
| @@ -6171,12 +6232,17 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) | ||||
|  { | ||||
|      struct qemud_driver *driver = dom->conn->privateData; | ||||
|      virDomainObjPtr vm; | ||||
| -    const char *type; | ||||
| +    virDomainDefPtr def; | ||||
|      int ret = -1; | ||||
|  | ||||
| -    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| -        qemuReportError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| -                        flags); | ||||
| +    virCheckFlags(VIR_DOMAIN_VCPU_LIVE | | ||||
| +                  VIR_DOMAIN_VCPU_CONFIG | | ||||
| +                  VIR_DOMAIN_VCPU_MAXIMUM, -1); | ||||
| + | ||||
| +    /* Exactly one of LIVE or CONFIG must be set.  */ | ||||
| +    if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) { | ||||
| +        qemuReportError(VIR_ERR_INVALID_ARG, | ||||
| +                        _("invalid flag combination: (0x%x)"), flags); | ||||
|          return -1; | ||||
|      } | ||||
|  | ||||
| @@ -6192,14 +6258,18 @@ qemudDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) | ||||
|          goto cleanup; | ||||
|      } | ||||
|  | ||||
| -    if (!(type = virDomainVirtTypeToString(vm->def->virtType))) { | ||||
| -        qemuReportError(VIR_ERR_INTERNAL_ERROR, | ||||
| -                        _("unknown virt type in domain definition '%d'"), | ||||
| -                        vm->def->virtType); | ||||
| -        goto cleanup; | ||||
| +    if (flags & VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        if (!virDomainObjIsActive(vm)) { | ||||
| +            qemuReportError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                            _("domain not active")); | ||||
| +            goto cleanup; | ||||
| +        } | ||||
| +        def = vm->def; | ||||
| +    } else { | ||||
| +        def = vm->newDef ? vm->newDef : vm->def; | ||||
|      } | ||||
|  | ||||
| -    ret = qemudGetMaxVCPUs(NULL, type); | ||||
| +    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus; | ||||
|  | ||||
|  cleanup: | ||||
|      if (vm) | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,294 +0,0 @@ | ||||
| From 0fab10e5ed971ab4f960a53e9640b0672f4b8ac3 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Tue, 5 Oct 2010 08:18:52 -0600 | ||||
| Subject: [PATCH 12/15] vcpu: improve vcpu support in xen command line | ||||
|  | ||||
| This patch series focuses on xendConfigVersion 2 (xm_internal) and 3 | ||||
| (xend_internal), but leaves out changes for xenapi drivers. | ||||
|  | ||||
| See this link for more details about vcpu_avail for xm usage. | ||||
| http://lists.xensource.com/archives/html/xen-devel/2009-11/msg01061.html | ||||
|  | ||||
| This relies on the fact that def->maxvcpus can be at most 32 with xen. | ||||
|  | ||||
| * src/xen/xend_internal.c (xenDaemonParseSxpr) | ||||
| (sexpr_to_xend_domain_info, xenDaemonFormatSxpr): Use vcpu_avail | ||||
| when current vcpus is less than maximum. | ||||
| * src/xen/xm_internal.c (xenXMDomainConfigParse) | ||||
| (xenXMDomainConfigFormat): Likewise. | ||||
| * tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr: New file. | ||||
| * tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr: Likewise. | ||||
| * tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml: Likewise. | ||||
| * tests/xmconfigdata/test-paravirt-vcpu.cfg: Likewise. | ||||
| * tests/xmconfigdata/test-paravirt-vcpu.xml: Likewise. | ||||
| * tests/xml2sexprtest.c (mymain): New test. | ||||
| * tests/sexpr2xmltest.c (mymain): Likewise. | ||||
| * tests/xmconfigtest.c (mymain): Likewise. | ||||
| --- | ||||
|  src/xen/xend_internal.c                      |   19 +++++++++++++-- | ||||
|  src/xen/xm_internal.c                        |   10 ++++++- | ||||
|  tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr |    1 + | ||||
|  tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml   |   27 +++++++++++++++++++++ | ||||
|  tests/sexpr2xmltest.c                        |    1 + | ||||
|  tests/xmconfigdata/test-paravirt-vcpu.cfg    |   17 +++++++++++++ | ||||
|  tests/xmconfigdata/test-paravirt-vcpu.xml    |   32 ++++++++++++++++++++++++++ | ||||
|  tests/xmconfigtest.c                         |    1 + | ||||
|  tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr |    1 + | ||||
|  tests/xml2sexprtest.c                        |    1 + | ||||
|  10 files changed, 105 insertions(+), 5 deletions(-) | ||||
|  create mode 100644 tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr | ||||
|  create mode 100644 tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml | ||||
|  create mode 100644 tests/xmconfigdata/test-paravirt-vcpu.cfg | ||||
|  create mode 100644 tests/xmconfigdata/test-paravirt-vcpu.xml | ||||
|  create mode 100644 tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr | ||||
|  | ||||
| diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c | ||||
| index 456b477..dfc6415 100644 | ||||
| --- a/src/xen/xend_internal.c | ||||
| +++ b/src/xen/xend_internal.c | ||||
| @@ -44,6 +44,7 @@ | ||||
|  #include "xen_hypervisor.h" | ||||
|  #include "xs_internal.h" /* To extract VNC port & Serial console TTY */ | ||||
|  #include "memory.h" | ||||
| +#include "count-one-bits.h" | ||||
|  | ||||
|  /* required for cpumap_t */ | ||||
|  #include <xen/dom0_ops.h> | ||||
| @@ -2191,7 +2192,9 @@ xenDaemonParseSxpr(virConnectPtr conn, | ||||
|      } | ||||
|  | ||||
|      def->maxvcpus = sexpr_int(root, "domain/vcpus"); | ||||
| -    def->vcpus = def->maxvcpus; | ||||
| +    def->vcpus = count_one_bits(sexpr_int(root, "domain/vcpu_avail")); | ||||
| +    if (!def->vcpus || def->maxvcpus < def->vcpus) | ||||
| +        def->vcpus = def->maxvcpus; | ||||
|  | ||||
|      tmp = sexpr_node(root, "domain/on_poweroff"); | ||||
|      if (tmp != NULL) { | ||||
| @@ -2433,7 +2436,7 @@ sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root, | ||||
|                            virDomainInfoPtr info) | ||||
|  { | ||||
|      const char *flags; | ||||
| - | ||||
| +    int vcpus; | ||||
|  | ||||
|      if ((root == NULL) || (info == NULL)) | ||||
|          return (-1); | ||||
| @@ -2464,7 +2467,11 @@ sexpr_to_xend_domain_info(virDomainPtr domain, const struct sexpr *root, | ||||
|              info->state = VIR_DOMAIN_NOSTATE; | ||||
|      } | ||||
|      info->cpuTime = sexpr_float(root, "domain/cpu_time") * 1000000000; | ||||
| -    info->nrVirtCpu = sexpr_int(root, "domain/vcpus"); | ||||
| +    vcpus = sexpr_int(root, "domain/vcpus"); | ||||
| +    info->nrVirtCpu = count_one_bits(sexpr_int(root, "domain/vcpu_avail")); | ||||
| +    if (!info->nrVirtCpu || vcpus < info->nrVirtCpu) | ||||
| +        info->nrVirtCpu = vcpus; | ||||
| + | ||||
|      return (0); | ||||
|  } | ||||
|  | ||||
| @@ -5668,6 +5675,9 @@ xenDaemonFormatSxpr(virConnectPtr conn, | ||||
|      virBufferAsprintf(&buf, "(memory %lu)(maxmem %lu)", | ||||
|                        def->mem.cur_balloon/1024, def->mem.max_balloon/1024); | ||||
|      virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); | ||||
| +    /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is 32.  */ | ||||
| +    if (def->vcpus < def->maxvcpus) | ||||
| +        virBufferAsprintf(&buf, "(vcpu_avail %u)", (1U << def->vcpus) - 1); | ||||
|  | ||||
|      if (def->cpumask) { | ||||
|          char *ranges = virDomainCpuSetFormat(def->cpumask, def->cpumasklen); | ||||
| @@ -5763,6 +5773,9 @@ xenDaemonFormatSxpr(virConnectPtr conn, | ||||
|                  virBufferAsprintf(&buf, "(kernel '%s')", def->os.loader); | ||||
|  | ||||
|              virBufferAsprintf(&buf, "(vcpus %u)", def->maxvcpus); | ||||
| +            if (def->vcpus < def->maxvcpus) | ||||
| +                virBufferAsprintf(&buf, "(vcpu_avail %u)", | ||||
| +                                  (1U << def->vcpus) - 1); | ||||
|  | ||||
|              for (i = 0 ; i < def->os.nBootDevs ; i++) { | ||||
|                  switch (def->os.bootDevs[i]) { | ||||
| diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c | ||||
| index bf20a64..f7121ab 100644 | ||||
| --- a/src/xen/xm_internal.c | ||||
| +++ b/src/xen/xm_internal.c | ||||
| @@ -46,6 +46,7 @@ | ||||
|  #include "util.h" | ||||
|  #include "memory.h" | ||||
|  #include "logging.h" | ||||
| +#include "count-one-bits.h" | ||||
|  | ||||
|  #define VIR_FROM_THIS VIR_FROM_XENXM | ||||
|  | ||||
| @@ -772,10 +773,12 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { | ||||
|      def->mem.max_balloon *= 1024; | ||||
|  | ||||
|      if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 || | ||||
| -        (unsigned short) count != count) | ||||
| +        MAX_VIRT_CPUS < count) | ||||
|          goto cleanup; | ||||
|      def->maxvcpus = count; | ||||
| -    def->vcpus = def->maxvcpus; | ||||
| +    if (xenXMConfigGetULong(conf, "vcpu_avail", &count, -1) < 0) | ||||
| +        goto cleanup; | ||||
| +    def->vcpus = MIN(count_one_bits(count), def->maxvcpus); | ||||
|  | ||||
|      if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0) | ||||
|          goto cleanup; | ||||
| @@ -2246,6 +2249,9 @@ virConfPtr xenXMDomainConfigFormat(virConnectPtr conn, | ||||
|  | ||||
|      if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0) | ||||
|          goto no_memory; | ||||
| +    if (def->vcpus < def->maxvcpus && | ||||
| +        xenXMConfigSetInt(conf, "vcpu_avail", (1U << def->vcpus) - 1) < 0) | ||||
| +        goto no_memory; | ||||
|  | ||||
|      if ((def->cpumask != NULL) && | ||||
|          ((cpus = virDomainCpuSetFormat(def->cpumask, | ||||
| diff --git a/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr | ||||
| new file mode 100644 | ||||
| index 0000000..2be6822 | ||||
| --- /dev/null | ||||
| +++ b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.sexpr | ||||
| @@ -0,0 +1 @@ | ||||
| +(domain (domid 6)(name 'pvtest')(memory 420)(maxmem 420)(vcpus 4)(vcpu_avail 3)(uuid '596a5d2171f48fb2e068e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os  ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) | ||||
| diff --git a/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml | ||||
| new file mode 100644 | ||||
| index 0000000..0d6bf11 | ||||
| --- /dev/null | ||||
| +++ b/tests/sexpr2xmldata/sexpr2xml-pv-vcpus.xml | ||||
| @@ -0,0 +1,27 @@ | ||||
| +<domain type='xen' id='6'> | ||||
| +  <name>pvtest</name> | ||||
| +  <uuid>596a5d21-71f4-8fb2-e068-e2386a5c413e</uuid> | ||||
| +  <memory>430080</memory> | ||||
| +  <currentMemory>430080</currentMemory> | ||||
| +  <vcpu current='2'>4</vcpu> | ||||
| +  <os> | ||||
| +    <type>linux</type> | ||||
| +    <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> | ||||
| +    <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> | ||||
| +    <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os  </cmdline> | ||||
| +  </os> | ||||
| +  <clock offset='utc'/> | ||||
| +  <on_poweroff>destroy</on_poweroff> | ||||
| +  <on_reboot>destroy</on_reboot> | ||||
| +  <on_crash>destroy</on_crash> | ||||
| +  <devices> | ||||
| +    <disk type='file' device='disk'> | ||||
| +      <driver name='file'/> | ||||
| +      <source file='/root/some.img'/> | ||||
| +      <target dev='xvda' bus='xen'/> | ||||
| +    </disk> | ||||
| +    <console type='pty'> | ||||
| +      <target type='xen' port='0'/> | ||||
| +    </console> | ||||
| +  </devices> | ||||
| +</domain> | ||||
| diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c | ||||
| index d62b44f..f100dd8 100644 | ||||
| --- a/tests/sexpr2xmltest.c | ||||
| +++ b/tests/sexpr2xmltest.c | ||||
| @@ -132,6 +132,7 @@ mymain(int argc, char **argv) | ||||
|      DO_TEST("pv-vfb-type-crash", "pv-vfb-type-crash", 3); | ||||
|      DO_TEST("fv-autoport", "fv-autoport", 3); | ||||
|      DO_TEST("pv-bootloader", "pv-bootloader", 1); | ||||
| +    DO_TEST("pv-vcpus", "pv-vcpus", 1); | ||||
|  | ||||
|      DO_TEST("disk-file", "disk-file", 2); | ||||
|      DO_TEST("disk-block", "disk-block", 2); | ||||
| diff --git a/tests/xmconfigdata/test-paravirt-vcpu.cfg b/tests/xmconfigdata/test-paravirt-vcpu.cfg | ||||
| new file mode 100644 | ||||
| index 0000000..24c78f4 | ||||
| --- /dev/null | ||||
| +++ b/tests/xmconfigdata/test-paravirt-vcpu.cfg | ||||
| @@ -0,0 +1,17 @@ | ||||
| +name = "XenGuest1" | ||||
| +uuid = "c7a5fdb0-cdaf-9455-926a-d65c16db1809" | ||||
| +maxmem = 579 | ||||
| +memory = 394 | ||||
| +vcpus = 4 | ||||
| +vcpu_avail = 3 | ||||
| +bootloader = "/usr/bin/pygrub" | ||||
| +on_poweroff = "destroy" | ||||
| +on_reboot = "restart" | ||||
| +on_crash = "restart" | ||||
| +sdl = 0 | ||||
| +vnc = 1 | ||||
| +vncunused = 1 | ||||
| +vnclisten = "127.0.0.1" | ||||
| +vncpasswd = "123poi" | ||||
| +disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ] | ||||
| +vif = [ "mac=00:16:3e:66:94:9c,bridge=br0,script=vif-bridge" ] | ||||
| diff --git a/tests/xmconfigdata/test-paravirt-vcpu.xml b/tests/xmconfigdata/test-paravirt-vcpu.xml | ||||
| new file mode 100644 | ||||
| index 0000000..0be9456 | ||||
| --- /dev/null | ||||
| +++ b/tests/xmconfigdata/test-paravirt-vcpu.xml | ||||
| @@ -0,0 +1,32 @@ | ||||
| +<domain type='xen'> | ||||
| +  <name>XenGuest1</name> | ||||
| +  <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid> | ||||
| +  <memory>592896</memory> | ||||
| +  <currentMemory>403456</currentMemory> | ||||
| +  <vcpu current='2'>4</vcpu> | ||||
| +  <bootloader>/usr/bin/pygrub</bootloader> | ||||
| +  <os> | ||||
| +    <type arch='i686' machine='xenpv'>linux</type> | ||||
| +  </os> | ||||
| +  <clock offset='utc'/> | ||||
| +  <on_poweroff>destroy</on_poweroff> | ||||
| +  <on_reboot>restart</on_reboot> | ||||
| +  <on_crash>restart</on_crash> | ||||
| +  <devices> | ||||
| +    <disk type='block' device='disk'> | ||||
| +      <driver name='phy'/> | ||||
| +      <source dev='/dev/HostVG/XenGuest1'/> | ||||
| +      <target dev='xvda' bus='xen'/> | ||||
| +    </disk> | ||||
| +    <interface type='bridge'> | ||||
| +      <mac address='00:16:3e:66:94:9c'/> | ||||
| +      <source bridge='br0'/> | ||||
| +      <script path='vif-bridge'/> | ||||
| +    </interface> | ||||
| +    <console type='pty'> | ||||
| +      <target type='xen' port='0'/> | ||||
| +    </console> | ||||
| +    <input type='mouse' bus='xen'/> | ||||
| +    <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1' passwd='123poi'/> | ||||
| +  </devices> | ||||
| +</domain> | ||||
| diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c | ||||
| index 221b322..ea00747 100644 | ||||
| --- a/tests/xmconfigtest.c | ||||
| +++ b/tests/xmconfigtest.c | ||||
| @@ -210,6 +210,7 @@ mymain(int argc, char **argv) | ||||
|      DO_TEST("paravirt-new-pvfb-vncdisplay", 3); | ||||
|      DO_TEST("paravirt-net-e1000", 3); | ||||
|      DO_TEST("paravirt-net-vifname", 3); | ||||
| +    DO_TEST("paravirt-vcpu", 2); | ||||
|      DO_TEST("fullvirt-old-cdrom", 1); | ||||
|      DO_TEST("fullvirt-new-cdrom", 2); | ||||
|      DO_TEST("fullvirt-utc", 2); | ||||
| diff --git a/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr | ||||
| new file mode 100644 | ||||
| index 0000000..e886545 | ||||
| --- /dev/null | ||||
| +++ b/tests/xml2sexprdata/xml2sexpr-pv-vcpus.sexpr | ||||
| @@ -0,0 +1 @@ | ||||
| +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 4)(vcpu_avail 3)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os  ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) | ||||
| \ No newline at end of file | ||||
| diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c | ||||
| index 77cf760..9cf8d39 100644 | ||||
| --- a/tests/xml2sexprtest.c | ||||
| +++ b/tests/xml2sexprtest.c | ||||
| @@ -118,6 +118,7 @@ mymain(int argc, char **argv) | ||||
|      DO_TEST("pv-vfb-new", "pv-vfb-new", "pvtest", 3); | ||||
|      DO_TEST("pv-vfb-new-auto", "pv-vfb-new-auto", "pvtest", 3); | ||||
|      DO_TEST("pv-bootloader", "pv-bootloader", "pvtest", 1); | ||||
| +    DO_TEST("pv-vcpus", "pv-vcpus", "pvtest", 1); | ||||
|  | ||||
|      DO_TEST("disk-file", "disk-file", "pvtest", 2); | ||||
|      DO_TEST("disk-block", "disk-block", "pvtest", 2); | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,216 +0,0 @@ | ||||
| From 290ea33111be7bdf1f1381b90de33eb0e67c1a15 Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Wed, 6 Oct 2010 17:54:41 -0600 | ||||
| Subject: [PATCH 13/15] vcpu: improve support for getting xen vcpu counts | ||||
|  | ||||
| * src/xen/xen_driver.c (xenUnifiedDomainGetVcpusFlags): Support | ||||
| more flags. | ||||
| * src/xen/xend_internal.h (xenDaemonDomainGetVcpusFlags): New | ||||
| prototype. | ||||
| * src/xen/xm_internal.h (xenXMDomainGetVcpusFlags): Likewise. | ||||
| * src/xen/xend_internal.c (virDomainGetVcpusFlags): New function. | ||||
| * src/xen/xm_internal.c (xenXMDomainGetVcpusFlags): Likewise. | ||||
| --- | ||||
|  src/xen/xen_driver.c    |   31 +++++++++++++++++++-------- | ||||
|  src/xen/xend_internal.c |   52 +++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  src/xen/xend_internal.h |    2 + | ||||
|  src/xen/xm_internal.c   |   47 ++++++++++++++++++++++++++++++++++++++++++ | ||||
|  src/xen/xm_internal.h   |    1 + | ||||
|  5 files changed, 124 insertions(+), 9 deletions(-) | ||||
|  | ||||
| diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c | ||||
| index d6c9c57..fe2ff86 100644 | ||||
| --- a/src/xen/xen_driver.c | ||||
| +++ b/src/xen/xen_driver.c | ||||
| @@ -1142,20 +1142,33 @@ static int | ||||
|  xenUnifiedDomainGetVcpusFlags (virDomainPtr dom, unsigned int flags) | ||||
|  { | ||||
|      GET_PRIVATE(dom->conn); | ||||
| -    int i, ret; | ||||
| +    int ret; | ||||
|  | ||||
| -    if (flags != (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| -        xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| -                        flags); | ||||
| +    virCheckFlags(VIR_DOMAIN_VCPU_LIVE | | ||||
| +                  VIR_DOMAIN_VCPU_CONFIG | | ||||
| +                  VIR_DOMAIN_VCPU_MAXIMUM, -1); | ||||
| + | ||||
| +    /* Exactly one of LIVE or CONFIG must be set.  */ | ||||
| +    if (!(flags & VIR_DOMAIN_VCPU_LIVE) == !(flags & VIR_DOMAIN_VCPU_CONFIG)) { | ||||
| +        xenUnifiedError(VIR_ERR_INVALID_ARG, | ||||
| +                        _("invalid flag combination: (0x%x)"), flags); | ||||
|          return -1; | ||||
|      } | ||||
|  | ||||
| -    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) | ||||
| -        if (priv->opened[i] && drivers[i]->domainGetMaxVcpus) { | ||||
| -            ret = drivers[i]->domainGetMaxVcpus (dom); | ||||
| -            if (ret != 0) return ret; | ||||
| -        } | ||||
| +    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) { | ||||
| +        ret = xenDaemonDomainGetVcpusFlags(dom, flags); | ||||
| +        if (ret != -2) | ||||
| +            return ret; | ||||
| +    } | ||||
| +    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) { | ||||
| +        ret = xenXMDomainGetVcpusFlags(dom, flags); | ||||
| +        if (ret != -2) | ||||
| +            return ret; | ||||
| +    } | ||||
| +    if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM)) | ||||
| +        return xenHypervisorGetVcpuMax(dom); | ||||
|  | ||||
| +    xenUnifiedError(VIR_ERR_NO_SUPPORT, __FUNCTION__); | ||||
|      return -1; | ||||
|  } | ||||
|  | ||||
| diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c | ||||
| index dfc6415..3642296 100644 | ||||
| --- a/src/xen/xend_internal.c | ||||
| +++ b/src/xen/xend_internal.c | ||||
| @@ -3620,6 +3620,58 @@ xenDaemonDomainPinVcpu(virDomainPtr domain, unsigned int vcpu, | ||||
|  } | ||||
|  | ||||
|  /** | ||||
| + * xenDaemonDomainGetVcpusFlags: | ||||
| + * @domain: pointer to domain object | ||||
| + * @flags: bitwise-ORd from virDomainVcpuFlags | ||||
| + * | ||||
| + * Extract information about virtual CPUs of domain according to flags. | ||||
| + * | ||||
| + * Returns the number of vcpus on success, -1 if an error message was | ||||
| + * issued, and -2 if the unified driver should keep trying. | ||||
| + | ||||
| + */ | ||||
| +int | ||||
| +xenDaemonDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) | ||||
| +{ | ||||
| +    struct sexpr *root; | ||||
| +    int ret; | ||||
| +    xenUnifiedPrivatePtr priv; | ||||
| + | ||||
| +    if (domain == NULL || domain->conn == NULL || domain->name == NULL) { | ||||
| +        virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    priv = (xenUnifiedPrivatePtr) domain->conn->privateData; | ||||
| + | ||||
| +    /* If xendConfigVersion is 2, then we can only report _LIVE (and | ||||
| +     * xm_internal reports _CONFIG).  If it is 3, then _LIVE and | ||||
| +     * _CONFIG are always in sync for a running system.  */ | ||||
| +    if (domain->id < 0 && priv->xendConfigVersion < 3) | ||||
| +        return -2; | ||||
| +    if (domain->id < 0 && (flags & VIR_DOMAIN_VCPU_LIVE)) { | ||||
| +        virXendError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                     _("domain not active")); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    root = sexpr_get(domain->conn, "/xend/domain/%s?detail=1", domain->name); | ||||
| +    if (root == NULL) | ||||
| +        return -1; | ||||
| + | ||||
| +    ret = sexpr_int(root, "domain/vcpus"); | ||||
| +    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM)) { | ||||
| +        int vcpus = count_one_bits(sexpr_int(root, "domain/vcpu_avail")); | ||||
| +        if (vcpus) | ||||
| +            ret = MIN(vcpus, ret); | ||||
| +    } | ||||
| +    if (!ret) | ||||
| +        ret = -2; | ||||
| +    sexpr_free(root); | ||||
| +    return ret; | ||||
| +} | ||||
| + | ||||
| +/** | ||||
|   * virDomainGetVcpus: | ||||
|   * @domain: pointer to domain object, or NULL for Domain0 | ||||
|   * @info: pointer to an array of virVcpuInfo structures (OUT) | ||||
| diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h | ||||
| index c757716..923cebd 100644 | ||||
| --- a/src/xen/xend_internal.h | ||||
| +++ b/src/xen/xend_internal.h | ||||
| @@ -155,6 +155,8 @@ int	xenDaemonDomainPinVcpu		(virDomainPtr domain, | ||||
|                                           unsigned int vcpu, | ||||
|                                           unsigned char *cpumap, | ||||
|                                           int maplen); | ||||
| +int     xenDaemonDomainGetVcpusFlags    (virDomainPtr domain, | ||||
| +                                         unsigned int flags); | ||||
|  int	xenDaemonDomainGetVcpus		(virDomainPtr domain, | ||||
|                                           virVcpuInfoPtr info, | ||||
|                                           int maxinfo, | ||||
| diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c | ||||
| index f7121ab..4ea4245 100644 | ||||
| --- a/src/xen/xm_internal.c | ||||
| +++ b/src/xen/xm_internal.c | ||||
| @@ -1671,6 +1671,53 @@ cleanup: | ||||
|  } | ||||
|  | ||||
|  /** | ||||
| + * xenXMDomainGetVcpusFlags: | ||||
| + * @domain: pointer to domain object | ||||
| + * @flags: bitwise-ORd from virDomainVcpuFlags | ||||
| + * | ||||
| + * Extract information about virtual CPUs of domain according to flags. | ||||
| + * | ||||
| + * Returns the number of vcpus on success, -1 if an error message was | ||||
| + * issued, and -2 if the unified driver should keep trying. | ||||
| + */ | ||||
| +int | ||||
| +xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags) | ||||
| +{ | ||||
| +    xenUnifiedPrivatePtr priv; | ||||
| +    const char *filename; | ||||
| +    xenXMConfCachePtr entry; | ||||
| +    int ret = -2; | ||||
| + | ||||
| +    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { | ||||
| +        xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    if (domain->id != -1) | ||||
| +        return -2; | ||||
| +    if (flags & VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        xenXMError(VIR_ERR_OPERATION_FAILED, "%s", _("domain not active")); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    priv = domain->conn->privateData; | ||||
| +    xenUnifiedLock(priv); | ||||
| + | ||||
| +    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) | ||||
| +        goto cleanup; | ||||
| + | ||||
| +    if (!(entry = virHashLookup(priv->configCache, filename))) | ||||
| +        goto cleanup; | ||||
| + | ||||
| +    ret = ((flags & VIR_DOMAIN_VCPU_MAXIMUM) ? entry->def->maxvcpus | ||||
| +           : entry->def->vcpus); | ||||
| + | ||||
| +cleanup: | ||||
| +    xenUnifiedUnlock(priv); | ||||
| +    return ret; | ||||
| +} | ||||
| + | ||||
| +/** | ||||
|   * xenXMDomainPinVcpu: | ||||
|   * @domain: pointer to domain object | ||||
|   * @vcpu: virtual CPU number (reserved) | ||||
| diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h | ||||
| index 3ad3456..3295fbd 100644 | ||||
| --- a/src/xen/xm_internal.h | ||||
| +++ b/src/xen/xm_internal.h | ||||
| @@ -45,6 +45,7 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory); | ||||
|  int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory); | ||||
|  unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain); | ||||
|  int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus); | ||||
| +int xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags); | ||||
|  int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu, | ||||
|                         unsigned char *cpumap, int maplen); | ||||
|  virDomainPtr xenXMDomainLookupByName(virConnectPtr conn, const char *domname); | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,342 +0,0 @@ | ||||
| From e443a003129a172a7332f3cb6e40b3c39363ed5e Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Thu, 14 Oct 2010 16:17:18 -0600 | ||||
| Subject: [PATCH 14/15] vcpu: improve support for setting xen vcpu counts | ||||
|  | ||||
| Tested with RHEL 5.6 (xendConfigVersion 2, where xend_internal | ||||
| controls live domains and xm_internal controls inactive domains). | ||||
| Hopefully this works with xendConfigVersion 3 (where xend_internal | ||||
| controls everything). | ||||
|  | ||||
| * src/xen/xen_driver.c (xenUnifiedDomainSetVcpusFlags): Support | ||||
| more flags. | ||||
| (xenUnifiedGetMaxVcpus): Export. | ||||
| * src/xen/xm_internal.h (xenXMDomainSetVcpusFlags): New prototype. | ||||
| * src/xen/xend_internal.h (xenDaemonDomainSetVcpusFlags): Likewise. | ||||
| * src/xen/xen_driver.h (xenUnifiedGetMaxVcpus): Likewise. | ||||
| * src/xen/xm_internal.c (xenXMDomainSetVcpusFlags): New function. | ||||
| * src/xen/xend_internal.c (xenDaemonDomainSetVcpusFlags): Likewise. | ||||
| --- | ||||
|  src/xen/xen_driver.c    |   60 ++++++++++++++++++++++++--------- | ||||
|  src/xen/xen_driver.h    |    1 + | ||||
|  src/xen/xend_internal.c |   76 +++++++++++++++++++++++++++++++++++++++++++ | ||||
|  src/xen/xend_internal.h |    3 ++ | ||||
|  src/xen/xm_internal.c   |   83 +++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  src/xen/xm_internal.h   |    2 + | ||||
|  6 files changed, 208 insertions(+), 17 deletions(-) | ||||
|  | ||||
| diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c | ||||
| index fe2ff86..66e8518 100644 | ||||
| --- a/src/xen/xen_driver.c | ||||
| +++ b/src/xen/xen_driver.c | ||||
| @@ -508,7 +508,7 @@ xenUnifiedIsSecure(virConnectPtr conn) | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| -static int | ||||
| +int | ||||
|  xenUnifiedGetMaxVcpus (virConnectPtr conn, const char *type) | ||||
|  { | ||||
|      GET_PRIVATE(conn); | ||||
| @@ -1073,36 +1073,62 @@ xenUnifiedDomainSetVcpusFlags (virDomainPtr dom, unsigned int nvcpus, | ||||
|                                 unsigned int flags) | ||||
|  { | ||||
|      GET_PRIVATE(dom->conn); | ||||
| -    int i; | ||||
| +    int ret; | ||||
| + | ||||
| +    virCheckFlags(VIR_DOMAIN_VCPU_LIVE | | ||||
| +                  VIR_DOMAIN_VCPU_CONFIG | | ||||
| +                  VIR_DOMAIN_VCPU_MAXIMUM, -1); | ||||
|  | ||||
| -    if (flags != VIR_DOMAIN_VCPU_LIVE) { | ||||
| -        xenUnifiedError(VIR_ERR_INVALID_ARG, _("unsupported flags: (0x%x)"), | ||||
| -                        flags); | ||||
| +    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be | ||||
| +     * mixed with LIVE.  */ | ||||
| +    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 || | ||||
| +        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) == | ||||
| +         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) { | ||||
| +        xenUnifiedError(VIR_ERR_INVALID_ARG, | ||||
| +                        _("invalid flag combination: (0x%x)"), flags); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    if (!nvcpus || (unsigned short) nvcpus != nvcpus) { | ||||
| +        xenUnifiedError(VIR_ERR_INVALID_ARG, | ||||
| +                        _("argument out of range: %d"), nvcpus); | ||||
|          return -1; | ||||
|      } | ||||
|  | ||||
|      /* Try non-hypervisor methods first, then hypervisor direct method | ||||
|       * as a last resort. | ||||
|       */ | ||||
| -    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) | ||||
| -        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET && | ||||
| -            priv->opened[i] && | ||||
| -            drivers[i]->domainSetVcpus && | ||||
| -            drivers[i]->domainSetVcpus (dom, nvcpus) == 0) | ||||
| -            return 0; | ||||
| - | ||||
| -    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] && | ||||
| -        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus && | ||||
| -        drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->domainSetVcpus (dom, nvcpus) == 0) | ||||
| -        return 0; | ||||
| +    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) { | ||||
| +        ret = xenDaemonDomainSetVcpusFlags(dom, nvcpus, flags); | ||||
| +        if (ret != -2) | ||||
| +            return ret; | ||||
| +    } | ||||
| +    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) { | ||||
| +        ret = xenXMDomainSetVcpusFlags(dom, nvcpus, flags); | ||||
| +        if (ret != -2) | ||||
| +            return ret; | ||||
| +    } | ||||
| +    if (flags == VIR_DOMAIN_VCPU_LIVE) | ||||
| +        return xenHypervisorSetVcpus(dom, nvcpus); | ||||
|  | ||||
| +    xenUnifiedError(VIR_ERR_NO_SUPPORT, __FUNCTION__); | ||||
|      return -1; | ||||
|  } | ||||
|  | ||||
|  static int | ||||
|  xenUnifiedDomainSetVcpus (virDomainPtr dom, unsigned int nvcpus) | ||||
|  { | ||||
| -    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE); | ||||
| +    unsigned int flags = VIR_DOMAIN_VCPU_LIVE; | ||||
| +    xenUnifiedPrivatePtr priv; | ||||
| + | ||||
| +    /* Per the documented API, it is hypervisor-dependent whether this | ||||
| +     * affects just _LIVE or _LIVE|_CONFIG; in xen's case, that | ||||
| +     * depends on xendConfigVersion.  */ | ||||
| +    if (dom) { | ||||
| +        priv = dom->conn->privateData; | ||||
| +        if (priv->xendConfigVersion >= 3) | ||||
| +            flags |= VIR_DOMAIN_VCPU_CONFIG; | ||||
| +    } | ||||
| +    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags); | ||||
|  } | ||||
|  | ||||
|  static int | ||||
| diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h | ||||
| index 3e7c1d0..115a26a 100644 | ||||
| --- a/src/xen/xen_driver.h | ||||
| +++ b/src/xen/xen_driver.h | ||||
| @@ -220,6 +220,7 @@ int  xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr info, | ||||
|  void xenUnifiedDomainEventDispatch (xenUnifiedPrivatePtr priv, | ||||
|                                      virDomainEventPtr event); | ||||
|  unsigned long xenUnifiedVersion(void); | ||||
| +int xenUnifiedGetMaxVcpus(virConnectPtr conn, const char *type); | ||||
|  | ||||
|  # ifndef PROXY | ||||
|  void xenUnifiedLock(xenUnifiedPrivatePtr priv); | ||||
| diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c | ||||
| index 3642296..55c2cc4 100644 | ||||
| --- a/src/xen/xend_internal.c | ||||
| +++ b/src/xen/xend_internal.c | ||||
| @@ -3535,6 +3535,82 @@ xenDaemonLookupByID(virConnectPtr conn, int id) { | ||||
|  } | ||||
|  | ||||
|  /** | ||||
| + * xenDaemonDomainSetVcpusFlags: | ||||
| + * @domain: pointer to domain object | ||||
| + * @nvcpus: the new number of virtual CPUs for this domain | ||||
| + * @flags: bitwise-ORd from virDomainVcpuFlags | ||||
| + * | ||||
| + * Change virtual CPUs allocation of domain according to flags. | ||||
| + * | ||||
| + * Returns 0 on success, -1 if an error message was issued, and -2 if | ||||
| + * the unified driver should keep trying. | ||||
| + */ | ||||
| +int | ||||
| +xenDaemonDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus, | ||||
| +                             unsigned int flags) | ||||
| +{ | ||||
| +    char buf[VIR_UUID_BUFLEN]; | ||||
| +    xenUnifiedPrivatePtr priv; | ||||
| +    int max; | ||||
| + | ||||
| +    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) | ||||
| +        || (vcpus < 1)) { | ||||
| +        virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| +        return (-1); | ||||
| +    } | ||||
| + | ||||
| +    priv = (xenUnifiedPrivatePtr) domain->conn->privateData; | ||||
| + | ||||
| +    if ((domain->id < 0 && priv->xendConfigVersion < 3) || | ||||
| +        (flags & VIR_DOMAIN_VCPU_MAXIMUM)) | ||||
| +        return -2; | ||||
| + | ||||
| +    /* With xendConfigVersion 2, only _LIVE is supported.  With | ||||
| +     * xendConfigVersion 3, only _LIVE|_CONFIG is supported for | ||||
| +     * running domains, or _CONFIG for inactive domains.  */ | ||||
| +    if (priv->xendConfigVersion < 3) { | ||||
| +        if (flags & VIR_DOMAIN_VCPU_CONFIG) { | ||||
| +            virXendError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                         _("Xend version does not support modifying " | ||||
| +                           "persistent config")); | ||||
| +            return -1; | ||||
| +        } | ||||
| +    } else if (domain->id < 0) { | ||||
| +        if (flags & VIR_DOMAIN_VCPU_LIVE) { | ||||
| +            virXendError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                         _("domain not running")); | ||||
| +            return -1; | ||||
| +        } | ||||
| +    } else { | ||||
| +        if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) != | ||||
| +            (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) { | ||||
| +            virXendError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                         _("Xend only supports modifying both live and " | ||||
| +                           "persistent config")); | ||||
| +        } | ||||
| +    } | ||||
| + | ||||
| +    /* Unfortunately, xend_op does not validate whether this exceeds | ||||
| +     * the maximum.  */ | ||||
| +    flags |= VIR_DOMAIN_VCPU_MAXIMUM; | ||||
| +    if ((max = xenDaemonDomainGetVcpusFlags(domain, flags)) < 0) { | ||||
| +        virXendError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                     _("could not determin max vcpus for the domain")); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    if (vcpus > max) { | ||||
| +        virXendError(VIR_ERR_INVALID_ARG, | ||||
| +                     _("requested vcpus is greater than max allowable" | ||||
| +                       " vcpus for the domain: %d > %d"), vcpus, max); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    snprintf(buf, sizeof(buf), "%d", vcpus); | ||||
| +    return xend_op(domain->conn, domain->name, "op", "set_vcpus", "vcpus", | ||||
| +                   buf, NULL); | ||||
| +} | ||||
| + | ||||
| +/** | ||||
|   * xenDaemonDomainSetVcpus: | ||||
|   * @domain: pointer to domain object | ||||
|   * @nvcpus: the new number of virtual CPUs for this domain | ||||
| diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h | ||||
| index 923cebd..53f5d2c 100644 | ||||
| --- a/src/xen/xend_internal.h | ||||
| +++ b/src/xen/xend_internal.h | ||||
| @@ -151,6 +151,9 @@ int xenDaemonDomainUndefine(virDomainPtr domain); | ||||
|  | ||||
|  int	xenDaemonDomainSetVcpus		(virDomainPtr domain, | ||||
|                                           unsigned int vcpus); | ||||
| +int	xenDaemonDomainSetVcpusFlags	(virDomainPtr domain, | ||||
| +                                         unsigned int vcpus, | ||||
| +                                         unsigned int flags); | ||||
|  int	xenDaemonDomainPinVcpu		(virDomainPtr domain, | ||||
|                                           unsigned int vcpu, | ||||
|                                           unsigned char *cpumap, | ||||
| diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c | ||||
| index 4ea4245..2b8e51e 100644 | ||||
| --- a/src/xen/xm_internal.c | ||||
| +++ b/src/xen/xm_internal.c | ||||
| @@ -1670,6 +1670,89 @@ cleanup: | ||||
|      return ret; | ||||
|  } | ||||
|  | ||||
| +/* | ||||
| + * xenXMDomainSetVcpusFlags: | ||||
| + * @domain: pointer to domain object | ||||
| + * @nvcpus: number of vcpus | ||||
| + * @flags: bitwise-ORd from virDomainVcpuFlags | ||||
| + * | ||||
| + * Change virtual CPUs allocation of domain according to flags. | ||||
| + * | ||||
| + * Returns 0 on success, -1 if an error message was issued, and -2 if | ||||
| + * the unified driver should keep trying. | ||||
| + */ | ||||
| +int | ||||
| +xenXMDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus, | ||||
| +                         unsigned int flags) | ||||
| +{ | ||||
| +    xenUnifiedPrivatePtr priv; | ||||
| +    const char *filename; | ||||
| +    xenXMConfCachePtr entry; | ||||
| +    int ret = -1; | ||||
| +    int max; | ||||
| + | ||||
| +    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { | ||||
| +        xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    if (domain->conn->flags & VIR_CONNECT_RO) { | ||||
| +        xenXMError(VIR_ERR_OPERATION_DENIED, __FUNCTION__); | ||||
| +        return -1; | ||||
| +    } | ||||
| +    if (domain->id != -1) | ||||
| +        return -2; | ||||
| +    if (flags & VIR_DOMAIN_VCPU_LIVE) { | ||||
| +        xenXMError(VIR_ERR_OPERATION_INVALID, "%s", | ||||
| +                   _("domain is not running")); | ||||
| +        return -1; | ||||
| +    } | ||||
| + | ||||
| +    priv = domain->conn->privateData; | ||||
| +    xenUnifiedLock(priv); | ||||
| + | ||||
| +    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) | ||||
| +        goto cleanup; | ||||
| + | ||||
| +    if (!(entry = virHashLookup(priv->configCache, filename))) | ||||
| +        goto cleanup; | ||||
| + | ||||
| +    /* Hypervisor maximum. */ | ||||
| +    if ((max = xenUnifiedGetMaxVcpus(domain->conn, NULL)) < 0) { | ||||
| +        xenXMError(VIR_ERR_INTERNAL_ERROR, "%s", | ||||
| +                   _("could not determin max vcpus for the domain")); | ||||
| +        goto cleanup; | ||||
| +    } | ||||
| +    /* Can't specify a current larger than stored maximum; but | ||||
| +     * reducing maximum can silently reduce current.  */ | ||||
| +    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM)) | ||||
| +        max = entry->def->maxvcpus; | ||||
| +    if (vcpus > max) { | ||||
| +        xenXMError(VIR_ERR_INVALID_ARG, | ||||
| +                   _("requested vcpus is greater than max allowable" | ||||
| +                     " vcpus for the domain: %d > %d"), vcpus, max); | ||||
| +        goto cleanup; | ||||
| +    } | ||||
| + | ||||
| +    if (flags & VIR_DOMAIN_VCPU_MAXIMUM) { | ||||
| +        entry->def->maxvcpus = vcpus; | ||||
| +        if (entry->def->vcpus > vcpus) | ||||
| +            entry->def->vcpus = vcpus; | ||||
| +    } else { | ||||
| +        entry->def->vcpus = vcpus; | ||||
| +    } | ||||
| + | ||||
| +    /* If this fails, should we try to undo our changes to the | ||||
| +     * in-memory representation of the config file. I say not! | ||||
| +     */ | ||||
| +    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) | ||||
| +        goto cleanup; | ||||
| +    ret = 0; | ||||
| + | ||||
| +cleanup: | ||||
| +    xenUnifiedUnlock(priv); | ||||
| +    return ret; | ||||
| +} | ||||
| + | ||||
|  /** | ||||
|   * xenXMDomainGetVcpusFlags: | ||||
|   * @domain: pointer to domain object | ||||
| diff --git a/src/xen/xm_internal.h b/src/xen/xm_internal.h | ||||
| index 3295fbd..a46e1a2 100644 | ||||
| --- a/src/xen/xm_internal.h | ||||
| +++ b/src/xen/xm_internal.h | ||||
| @@ -45,6 +45,8 @@ int xenXMDomainSetMemory(virDomainPtr domain, unsigned long memory); | ||||
|  int xenXMDomainSetMaxMemory(virDomainPtr domain, unsigned long memory); | ||||
|  unsigned long xenXMDomainGetMaxMemory(virDomainPtr domain); | ||||
|  int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus); | ||||
| +int xenXMDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus, | ||||
| +                             unsigned int flags); | ||||
|  int xenXMDomainGetVcpusFlags(virDomainPtr domain, unsigned int flags); | ||||
|  int xenXMDomainPinVcpu(virDomainPtr domain, unsigned int vcpu, | ||||
|                         unsigned char *cpumap, int maplen); | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
| @@ -1,228 +0,0 @@ | ||||
| From b013788742183afec9aa5068d3cfd185a3b5c62e Mon Sep 17 00:00:00 2001 | ||||
| From: Eric Blake <eblake@redhat.com> | ||||
| Date: Thu, 7 Oct 2010 08:59:27 -0600 | ||||
| Subject: [PATCH 15/15] vcpu: remove dead xen code | ||||
|  | ||||
| * src/xen/xen_driver.h (xenUnifiedDriver): Remove now-unused | ||||
| domainGetMaxVcpus, domainSetVcpus. | ||||
| * src/xen/proxy_internal.c (xenProxyDriver): Likewise. | ||||
| * src/xen/xen_hypervisor.c (xenHypervisorDriver): Likewise. | ||||
| * src/xen/xen_inotify.c (xenInotifyDriver): Likewise. | ||||
| * src/xen/xend_internal.c (xenDaemonDriver) | ||||
| (xenDaemonDomainSetVcpus): Likewise. | ||||
| * src/xen/xm_internal.c (xenXMDriver, xenXMDomainSetVcpus): | ||||
| Likewise. | ||||
| * src/xen/xs_internal.c (xenStoreDriver): Likewise. | ||||
| --- | ||||
|  src/xen/proxy_internal.c |    2 -- | ||||
|  src/xen/xen_driver.h     |    4 +--- | ||||
|  src/xen/xen_hypervisor.c |    2 -- | ||||
|  src/xen/xen_inotify.c    |    2 -- | ||||
|  src/xen/xend_internal.c  |   33 --------------------------------- | ||||
|  src/xen/xm_internal.c    |   43 ------------------------------------------- | ||||
|  src/xen/xs_internal.c    |    2 -- | ||||
|  7 files changed, 1 insertions(+), 87 deletions(-) | ||||
|  | ||||
| diff --git a/src/xen/proxy_internal.c b/src/xen/proxy_internal.c | ||||
| index 335dfc4..4033727 100644 | ||||
| --- a/src/xen/proxy_internal.c | ||||
| +++ b/src/xen/proxy_internal.c | ||||
| @@ -67,10 +67,8 @@ struct xenUnifiedDriver xenProxyDriver = { | ||||
|      NULL, /* domainSave */ | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
| -    NULL, /* domainSetVcpus */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
| -    NULL, /* domainGetMaxVcpus */ | ||||
|      NULL, /* listDefinedDomains */ | ||||
|      NULL, /* numOfDefinedDomains */ | ||||
|      NULL, /* domainCreate */ | ||||
| diff --git a/src/xen/xen_driver.h b/src/xen/xen_driver.h | ||||
| index 115a26a..53f97d4 100644 | ||||
| --- a/src/xen/xen_driver.h | ||||
| +++ b/src/xen/xen_driver.h | ||||
| @@ -1,7 +1,7 @@ | ||||
|  /* | ||||
|   * xen_unified.c: Unified Xen driver. | ||||
|   * | ||||
| - * Copyright (C) 2007 Red Hat, Inc. | ||||
| + * Copyright (C) 2007, 2010 Red Hat, Inc. | ||||
|   * | ||||
|   * See COPYING.LIB for the License of this software | ||||
|   * | ||||
| @@ -84,10 +84,8 @@ struct xenUnifiedDriver { | ||||
|          virDrvDomainSave		domainSave; | ||||
|          virDrvDomainRestore		domainRestore; | ||||
|          virDrvDomainCoreDump		domainCoreDump; | ||||
| -        virDrvDomainSetVcpus		domainSetVcpus; | ||||
|          virDrvDomainPinVcpu		domainPinVcpu; | ||||
|          virDrvDomainGetVcpus		domainGetVcpus; | ||||
| -        virDrvDomainGetMaxVcpus		domainGetMaxVcpus; | ||||
|          virDrvListDefinedDomains	listDefinedDomains; | ||||
|          virDrvNumOfDefinedDomains	numOfDefinedDomains; | ||||
|          virDrvDomainCreate		domainCreate; | ||||
| diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c | ||||
| index 6246513..3797865 100644 | ||||
| --- a/src/xen/xen_hypervisor.c | ||||
| +++ b/src/xen/xen_hypervisor.c | ||||
| @@ -784,10 +784,8 @@ struct xenUnifiedDriver xenHypervisorDriver = { | ||||
|      NULL, /* domainSave */ | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
| -    xenHypervisorSetVcpus, /* domainSetVcpus */ | ||||
|      xenHypervisorPinVcpu, /* domainPinVcpu */ | ||||
|      xenHypervisorGetVcpus, /* domainGetVcpus */ | ||||
| -    xenHypervisorGetVcpuMax, /* domainGetMaxVcpus */ | ||||
|      NULL, /* listDefinedDomains */ | ||||
|      NULL, /* numOfDefinedDomains */ | ||||
|      NULL, /* domainCreate */ | ||||
| diff --git a/src/xen/xen_inotify.c b/src/xen/xen_inotify.c | ||||
| index d24b20f..9507061 100644 | ||||
| --- a/src/xen/xen_inotify.c | ||||
| +++ b/src/xen/xen_inotify.c | ||||
| @@ -71,10 +71,8 @@ struct xenUnifiedDriver xenInotifyDriver = { | ||||
|      NULL, /* domainSave */ | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
| -    NULL, /* domainSetVcpus */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
| -    NULL, /* domainGetMaxVcpus */ | ||||
|      NULL, /* listDefinedDomains */ | ||||
|      NULL, /* numOfDefinedDomains */ | ||||
|      NULL, /* domainCreate */ | ||||
| diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c | ||||
| index 55c2cc4..b90c331 100644 | ||||
| --- a/src/xen/xend_internal.c | ||||
| +++ b/src/xen/xend_internal.c | ||||
| @@ -3611,37 +3611,6 @@ xenDaemonDomainSetVcpusFlags(virDomainPtr domain, unsigned int vcpus, | ||||
|  } | ||||
|  | ||||
|  /** | ||||
| - * xenDaemonDomainSetVcpus: | ||||
| - * @domain: pointer to domain object | ||||
| - * @nvcpus: the new number of virtual CPUs for this domain | ||||
| - * | ||||
| - * Dynamically change the number of virtual CPUs used by the domain. | ||||
| - * | ||||
| - * Returns 0 for success; -1 (with errno) on error | ||||
| - */ | ||||
| -int | ||||
| -xenDaemonDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) | ||||
| -{ | ||||
| -    char buf[VIR_UUID_BUFLEN]; | ||||
| -    xenUnifiedPrivatePtr priv; | ||||
| - | ||||
| -    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL) | ||||
| -     || (vcpus < 1)) { | ||||
| -        virXendError(VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| -        return (-1); | ||||
| -    } | ||||
| - | ||||
| -    priv = (xenUnifiedPrivatePtr) domain->conn->privateData; | ||||
| - | ||||
| -    if (domain->id < 0 && priv->xendConfigVersion < 3) | ||||
| -        return(-1); | ||||
| - | ||||
| -    snprintf(buf, sizeof(buf), "%d", vcpus); | ||||
| -    return(xend_op(domain->conn, domain->name, "op", "set_vcpus", "vcpus", | ||||
| -                   buf, NULL)); | ||||
| -} | ||||
| - | ||||
| -/** | ||||
|   * xenDaemonDomainPinCpu: | ||||
|   * @domain: pointer to domain object | ||||
|   * @vcpu: virtual CPU number | ||||
| @@ -5213,10 +5182,8 @@ struct xenUnifiedDriver xenDaemonDriver = { | ||||
|      xenDaemonDomainSave,         /* domainSave */ | ||||
|      xenDaemonDomainRestore,      /* domainRestore */ | ||||
|      xenDaemonDomainCoreDump,     /* domainCoreDump */ | ||||
| -    xenDaemonDomainSetVcpus,     /* domainSetVcpus */ | ||||
|      xenDaemonDomainPinVcpu,      /* domainPinVcpu */ | ||||
|      xenDaemonDomainGetVcpus,     /* domainGetVcpus */ | ||||
| -    NULL,                        /* domainGetMaxVcpus */ | ||||
|      xenDaemonListDefinedDomains, /* listDefinedDomains */ | ||||
|      xenDaemonNumOfDefinedDomains,/* numOfDefinedDomains */ | ||||
|      xenDaemonDomainCreate,       /* domainCreate */ | ||||
| diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c | ||||
| index 2b8e51e..430d40b 100644 | ||||
| --- a/src/xen/xm_internal.c | ||||
| +++ b/src/xen/xm_internal.c | ||||
| @@ -103,10 +103,8 @@ struct xenUnifiedDriver xenXMDriver = { | ||||
|      NULL, /* domainSave */ | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
| -    xenXMDomainSetVcpus, /* domainSetVcpus */ | ||||
|      xenXMDomainPinVcpu, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
| -    NULL, /* domainGetMaxVcpus */ | ||||
|      xenXMListDefinedDomains, /* listDefinedDomains */ | ||||
|      xenXMNumOfDefinedDomains, /* numOfDefinedDomains */ | ||||
|      xenXMDomainCreate, /* domainCreate */ | ||||
| @@ -1630,47 +1628,6 @@ cleanup: | ||||
|  } | ||||
|  | ||||
|  /* | ||||
| - * Set the VCPU count in config | ||||
| - */ | ||||
| -int xenXMDomainSetVcpus(virDomainPtr domain, unsigned int vcpus) { | ||||
| -    xenUnifiedPrivatePtr priv; | ||||
| -    const char *filename; | ||||
| -    xenXMConfCachePtr entry; | ||||
| -    int ret = -1; | ||||
| - | ||||
| -    if ((domain == NULL) || (domain->conn == NULL) || (domain->name == NULL)) { | ||||
| -        xenXMError(VIR_ERR_INVALID_ARG, __FUNCTION__); | ||||
| -        return (-1); | ||||
| -    } | ||||
| -    if (domain->conn->flags & VIR_CONNECT_RO) | ||||
| -        return (-1); | ||||
| -    if (domain->id != -1) | ||||
| -        return (-1); | ||||
| - | ||||
| -    priv = domain->conn->privateData; | ||||
| -    xenUnifiedLock(priv); | ||||
| - | ||||
| -    if (!(filename = virHashLookup(priv->nameConfigMap, domain->name))) | ||||
| -        goto cleanup; | ||||
| - | ||||
| -    if (!(entry = virHashLookup(priv->configCache, filename))) | ||||
| -        goto cleanup; | ||||
| - | ||||
| -    entry->def->maxvcpus = entry->def->vcpus = vcpus; | ||||
| - | ||||
| -    /* If this fails, should we try to undo our changes to the | ||||
| -     * in-memory representation of the config file. I say not! | ||||
| -     */ | ||||
| -    if (xenXMConfigSaveFile(domain->conn, entry->filename, entry->def) < 0) | ||||
| -        goto cleanup; | ||||
| -    ret = 0; | ||||
| - | ||||
| -cleanup: | ||||
| -    xenUnifiedUnlock(priv); | ||||
| -    return ret; | ||||
| -} | ||||
| - | ||||
| -/* | ||||
|   * xenXMDomainSetVcpusFlags: | ||||
|   * @domain: pointer to domain object | ||||
|   * @nvcpus: number of vcpus | ||||
| diff --git a/src/xen/xs_internal.c b/src/xen/xs_internal.c | ||||
| index 9296f25..a9817b1 100644 | ||||
| --- a/src/xen/xs_internal.c | ||||
| +++ b/src/xen/xs_internal.c | ||||
| @@ -67,10 +67,8 @@ struct xenUnifiedDriver xenStoreDriver = { | ||||
|      NULL, /* domainSave */ | ||||
|      NULL, /* domainRestore */ | ||||
|      NULL, /* domainCoreDump */ | ||||
| -    NULL, /* domainSetVcpus */ | ||||
|      NULL, /* domainPinVcpu */ | ||||
|      NULL, /* domainGetVcpus */ | ||||
| -    NULL, /* domainGetMaxVcpus */ | ||||
|      NULL, /* listDefinedDomains */ | ||||
|      NULL, /* numOfDefinedDomains */ | ||||
|      NULL, /* domainCreate */ | ||||
| --  | ||||
| 1.7.2.3 | ||||
|  | ||||
							
								
								
									
										2403
									
								
								docs/apibuild.py
									
									
									
									
									
								
							
							
						
						
									
										2403
									
								
								docs/apibuild.py
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,352 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Applications using <strong>libvirt</strong></h1> | ||||
|  | ||||
|     <p> | ||||
|       This page provides an illustration of the wide variety of | ||||
|       applications using the libvirt management API. | ||||
|     </p> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="add">Add an application</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       To add an application not listed on this page, send a message | ||||
|       to the <a href="contact.html">mailing list</a>, requesting it | ||||
|       be added here, or simply send a patch against the documentation | ||||
|       in the libvirt.git docs subdirectory. | ||||
|       If your application uses libvirt as its API, | ||||
|       the following graphic is available for your website to advertise | ||||
|       support for libvirt: | ||||
|     </p> | ||||
|  | ||||
|     <p class="image"> | ||||
|       <img src="madeWith.png" alt="Made with libvirt"/> | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="clientserver">Client/Server applications</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://archipelproject.org">Archipel</a></dt> | ||||
|       <dd> | ||||
|         Archipel is a libvirt-based solution to manage and supervise virtual | ||||
|         machines.  It uses XMPP for all communication. There is no web | ||||
|         service or custom protocol.  You just need at least one XMPP server, | ||||
|         like eJabberd, to start playing with it.  This allows Archipel to | ||||
|         work completely real time.  You never have to refresh the user | ||||
|         interface, you'll be notified as soon as something happens. You can | ||||
|         even use your favorite chat clients to command your infrastructure. | ||||
|       </dd> | ||||
|       <dd> | ||||
|         Isn't it great to be able to open a chat conversation with your | ||||
|         virtual machine and say things like "How are you today?" or "Hey, | ||||
|         please reboot"? | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="command">Command line tools</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://libguestfs.org">guestfish</a></dt> | ||||
|       <dd> | ||||
|         Guestfish is an interactive shell and command-line tool for examining | ||||
|         and modifying virtual machine filesystems.  It uses libvirt to find | ||||
|         guests and their associated disks. | ||||
|       </dd> | ||||
|       <dt>virsh</dt> | ||||
|       <dd> | ||||
|         An interactive shell, and batch scriptable tool for performing | ||||
|         management tasks on all libvirt managed domains, networks and | ||||
|         storage. This is part of the libvirt core distribution. | ||||
|       </dd> | ||||
|       <dt><a href="http://virt-manager.org/">virt-clone</a></dt> | ||||
|       <dd> | ||||
|         Allows the disk image(s) and configuration for an existing | ||||
|         virtual machine to be cloned to form a new virtual machine. | ||||
|         It automates copying of data across to new disk images, and | ||||
|         updates the UUID, MAC address, and name in the configuration. | ||||
|       </dd> | ||||
|       <dt><a href="http://et.redhat.com/~rjones/virt-df/">virt-df</a></dt> | ||||
|       <dd> | ||||
|         Examine the utilization of each filesystem in a virtual machine | ||||
|         from the comfort of the host machine. This tool peeks into the | ||||
|         guest disks and determines how much space is used. It can cope | ||||
|         with common Linux filesystems and LVM volumes. | ||||
|       </dd> | ||||
|       <dt><a href="http://virt-manager.org/">virt-image</a></dt> | ||||
|       <dd> | ||||
|         Provides a way to deploy virtual appliances. It defines a | ||||
|         simplified portable XML format describing the pre-requisites | ||||
|         of a virtual machine. At time of deployment this is translated | ||||
|         into the domain XML format for execution under any libvirt | ||||
|         hypervisor meeting the pre-requisites. | ||||
|       </dd> | ||||
|       <dt><a href="http://virt-manager.org/">virt-install</a></dt> | ||||
|       <dd> | ||||
|         Provides a way to provision new virtual machines from a | ||||
|         OS distribution install tree. It supports provisioning from | ||||
|         local CD images, and the network over NFS, HTTP and FTP. | ||||
|       </dd> | ||||
|       <dt><a href="http://et.redhat.com/~rjones/virt-top/">virt-top</a></dt> | ||||
|       <dd> | ||||
|         Watch the CPU, memory, network and disk utilization of all | ||||
|         virtual machines running on a host. | ||||
|       </dd> | ||||
|       <dt> | ||||
|         <a href="http://people.redhat.com/~rjones/virt-what/">virt-what</a> | ||||
|       </dt> | ||||
|       <dd> | ||||
|         virt-what is a shell script for detecting if the program is running | ||||
|         in a virtual machine.  It prints out a list of facts about the | ||||
|         virtual machine, derived from heuristics. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="configmgmt">Configuration Management</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="https://wiki.lcfg.org/bin/view/LCFG/LcfgLibvirt">LCFG</a></dt> | ||||
|       <dd> | ||||
|         LCFG is a system for automatically installing and managing the | ||||
|         configuration of large numbers of Unix systems.  It is particularly | ||||
|         suitable for sites with very diverse and rapidly changing | ||||
|         configurations. | ||||
|       </dd> | ||||
|       <dd> | ||||
|         The lcfg-libvirt package adds support for virtualized systems to | ||||
|         LCFG, with both Xen and KVM known to work.  Cloning guests is | ||||
|         supported, as are the bridged, routed, and isolated modes for | ||||
|         Virtual Networking. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="continuousintegration">Continuous Integration</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://buildbot.net/buildbot/docs/current/Libvirt.html">BuildBot</a></dt> | ||||
|       <dd> | ||||
|         BuildBot is a system to automate the compile/test cycle required | ||||
|         by most software projects.  CVS commits trigger new builds, run on | ||||
|         a variety of client machines.  Build status (pass/fail/etc) are | ||||
|         displayed on a web page or through other protocols. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://wiki.jenkins-ci.org/display/JENKINS/Libvirt+Slaves+Plugin">Jenkins</a></dt> | ||||
|       <dd> | ||||
|         This plugin for Jenkins adds a way to control guest domains hosted | ||||
|         on Xen or QEMU/KVM.  You configure a Jenkins Slave, | ||||
|         selecting the guest domain and hypervisor.  When you need to build a | ||||
|         job on a specific Slave, its guest domain is started, then the job is | ||||
|         run.  When the build process is finished, the guest domain is shut | ||||
|         down, ready to be used again as required. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="conversion">Conversion</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="https://rwmj.wordpress.com/2009/10/13/poor-mans-p2v/">Poor mans p2v</a></dt> | ||||
|       <dd> | ||||
|         A simple approach for converting a physical machine to a virtual | ||||
|         machine, using a rescue CD. | ||||
|       </dd> | ||||
|       <dt><a href="http://et.redhat.com/~rjones/virt-p2v/">virt-p2v</a></dt> | ||||
|       <dd> | ||||
|         An older tool for converting a physical machine into a virtual | ||||
|         machine.  It is a LiveCD which is booted on the machine to be | ||||
|         converted.  It collects a little information from the user, then | ||||
|         copies the disks over to a remote machine and defines the XML for a | ||||
|         domain to run the guest. | ||||
|       </dd> | ||||
|       <dt><a href="http://git.fedorahosted.org/git/?p=virt-v2v.git;a=summary">virt-v2v</a></dt> | ||||
|       <dd> | ||||
|         virt-v2v converts guests from a foreign hypervisor to run on KVM, | ||||
|         managed by libvirt.  It can currently convert Red Hat Enterprise | ||||
|         Linux (RHEL) and Fedora guests running on Xen and VMware ESX.  It | ||||
|         will enable VirtIO drivers in the converted guest if possible. | ||||
|       </dd> | ||||
|       <dd> | ||||
|         For RHEL customers of Red Hat, conversion of Windows guests is also | ||||
|         possible.  This conversion requires some Microsoft signed pieces, | ||||
|         that Red Hat can provide. | ||||
|       </dd> | ||||
|       <dt><a href="https://launchpad.net/virt-goodies">vmware2libvirt</a></dt> | ||||
|       <dd> | ||||
|         Part of the <i>virt-goodies</i> package, vmware2libvirt is a python | ||||
|         script for migrating a vmware image to libvirt. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="desktop">Desktop applications</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://virt-manager.org/">virt-manager</a></dt> | ||||
|       <dd> | ||||
|         A general purpose desktop management tool, able to manage | ||||
|         virtual machines across both local and remotely accessed | ||||
|         hypervisors. It is targeted at home and small office usage | ||||
|         upto managing 10-20 hosts and their VMs. | ||||
|       </dd> | ||||
|       <dt><a href="http://virt-manager.org/">virt-viewer</a></dt> | ||||
|       <dd> | ||||
|         A lightweight tool for accessing the graphical console | ||||
|         associated with a virtual machine. It can securely connect | ||||
|         to remote consoles supporting the VNC protocol. Also provides | ||||
|         an optional mozilla browser plugin. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="iaas">Infrastructure as a Service (IaaS)</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://www.emotivecloud.net">EMOTIVE Cloud</a></dt> | ||||
|       <dd>The EMOTIVE (Elastic Management Of Tasks In Virtualized | ||||
|         Environments) middleware allows executing tasks and providing | ||||
|         virtualized environments to the users with Xen, KVM or | ||||
|         VirtualBox hypervisor. EMOTIVE's main feature is VM management | ||||
|         with different scheduling policies. It can be also used as a | ||||
|         cloud provider and is very easy to extend thanks to its | ||||
|         modular Web Services architecture. | ||||
|       </dd> | ||||
|  | ||||
|       <dt><a href="http://www.nimbusproject.org">Nimbus</a></dt> | ||||
|       <dd> | ||||
|         Nimbus is an open-source toolkit focused on providing | ||||
|         Infrastructure-as-a-Service (IaaS) capabilities to the scientific | ||||
|         community.  It uses libvirt for communication with all KVM and Xen | ||||
|         virtual machines. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="libraries">Libraries</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://libguestfs.org">libguestfs</a></dt> | ||||
|       <dd> | ||||
|         A library and set of tools for accessing and modifying virtual | ||||
|         machine disk images.  It can be linked with C and C++ management | ||||
|         programs, and has bindings for Perl, Python, Ruby, Java, OCaml, | ||||
|         PHP, Haskell, and C#. | ||||
|       </dd> | ||||
|       <dd> | ||||
|         Using its FUSE module, you can also mount guest filesystems on the | ||||
|         host, and there is a subproject to allow merging changes into the | ||||
|         Windows Registry in Windows guests. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|         <dl> | ||||
|             <dt><a href="https://github.com/ohadlevy/virt#readme">Ruby | ||||
|             Libvirt Object bindings</a></dt> | ||||
|             <dd> | ||||
|                 Allows using simple ruby objects to manipulate | ||||
|                 hypervisors, guests, storage, network etc.  It is | ||||
|                 based on top of | ||||
|                 the <a href="http://libvirt.org/ruby">native ruby | ||||
|                 bindings</a>. | ||||
|             </dd> | ||||
|         </dl> | ||||
|     <h2><a name="livecd">LiveCD / Appliances</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://et.redhat.com/~rjones/virt-p2v/">virt-p2v</a></dt> | ||||
|       <dd> | ||||
|         An older tool for converting a physical machine into a virtual | ||||
|         machine.  It is a LiveCD which is booted on the machine to be | ||||
|         converted.  It collects a little information from the user, then | ||||
|         copies the disks over to a remote machine and defines the XML for a | ||||
|         domain to run the guest. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="monitoring">Monitoring</a></h2> | ||||
|     <dl> | ||||
|       <dt><a href="http://collectd.org/plugins/libvirt.shtml">collectd</a></dt> | ||||
|       <dd> | ||||
|         The libvirt-plugin is part of <a href="http://collectd.org/">collectd</a> | ||||
|         and gathers statistics about virtualized guests on a system. This | ||||
|         way, you can collect CPU, network interface and block device usage | ||||
|         for each guest without installing collectd on the guest systems. | ||||
|         For a full description, please refer to the libvirt section in the | ||||
|         collectd.conf(5) manual page. | ||||
|       </dd> | ||||
|       <dt><a href="http://honk.sigxcpu.org/projects/libvirt/#munin">Munin</a></dt> | ||||
|       <dd> | ||||
|         The plugins provided by Guido Günther allow to monitor various things | ||||
|         like network and block I/O with | ||||
|         <a href="http://munin.projects.linpro.no/">Munin</a>. | ||||
|       </dd> | ||||
|       <dt><a href="http://et.redhat.com/~rjones/nagios-virt/">Nagios-virt</a></dt> | ||||
|       <dd> | ||||
|         Nagios-virt is a configuration tool to add monitoring of your | ||||
|         virtualised domains to <a href="http://www.nagios.org/">Nagios</a>. | ||||
|         You can use this tool to either set up a new Nagios installation for | ||||
|         your Xen or QEMU/KVM guests, or to integrate with your existing Nagios | ||||
|         installation. | ||||
|       </dd> | ||||
|       <dt><a href="http://community.zenoss.org/docs/DOC-4687">Zenoss</a></dt> | ||||
|       <dd> | ||||
|         The Zenoss libvirt Zenpack adds support for monitoring virtualization | ||||
|         servers.  It has been tested with KVM, QEMU, VMware ESX, and VMware | ||||
|         GSX. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <h2><a name="provisioning">Provisioning</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://www.ibm.com/software/tivoli/products/prov-mgr/">Tivoli Provisioning Manager</a></dt> | ||||
|       <dd> | ||||
|         Part of the IBM Tivoli family, Tivoli Provisioning Manager (TPM) is | ||||
|         an IT lifecycle automation product.  It | ||||
|         <a href="http://publib.boulder.ibm.com/infocenter/tivihelp/v38r1/index.jsp?topic=/com.ibm.tivoli.tpm.apk.doc/libvirt_package.html">uses libvirt</a> | ||||
|         for communication with virtualization hosts and guest domains. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://theforeman.org">Foreman</a></dt> | ||||
|       <dd> | ||||
|       Foreman is an open source web based application aimed to be a | ||||
|       Single Address For All Machines Life Cycle Management. Foreman: | ||||
|  | ||||
|       <ul> | ||||
|           <li>Creates everything you need when adding a new machine to | ||||
|           your network, its goal being automatically managing | ||||
|           everything you would normally manage manually (DNS, DHCP, | ||||
|           TFTP, Virtual Machines,CA, CMDB...)</li> | ||||
|           <li>Integrates with Puppet (and acts as web front end to it).</li> | ||||
|           <li>Takes care of provisioning until the point puppet is | ||||
|           running, allowing Puppet to do what it does best.</li> | ||||
|           <li>Shows you Systems Inventory (based on Facter) and | ||||
|           provides real time information about hosts status based on | ||||
|           Puppet reports.</li> | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|  | ||||
|     <h2><a name="web">Web applications</a></h2> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="http://community.abiquo.com/display/AbiCloud">AbiCloud</a></dt> | ||||
|       <dd> | ||||
|         AbiCloud is an open source cloud platform manager which allows to | ||||
|         easily deploy a private cloud in your datacenter. One of the key | ||||
|         differences of AbiCloud is the web rich interface for managing the | ||||
|         infrastructure. You can deploy a new service just dragging and | ||||
|         dropping a VM. | ||||
|       </dd> | ||||
|       <dt><a href="http://ovirt.org/">oVirt</a></dt> | ||||
|       <dd> | ||||
|         oVirt provides the ability to manage large numbers of virtual | ||||
|         machines across an entire data center of hosts. It integrates | ||||
|         with FreeIPA for Kerberos authentication, and in the future, | ||||
|         certificate management. | ||||
|       </dd> | ||||
|     </dl> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,5 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Domain management architecture</h1> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,87 +0,0 @@ | ||||
| #FIG 3.2 | ||||
| Landscape | ||||
| Center | ||||
| Inches | ||||
| Letter   | ||||
| 100.00 | ||||
| Single | ||||
| -2 | ||||
| 1200 2 | ||||
| 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 | ||||
| 	 1050 7500 9375 7500 9375 8700 1050 8700 1050 7500 | ||||
| 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 | ||||
| 	 3525 7275 3525 4125 1050 4125 1050 7275 3525 7275 | ||||
| 2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2 | ||||
| 	 1050 6540 3540 6525 | ||||
| 2 4 0 1 0 7 50 -1 -1 4.000 0 0 7 0 0 5 | ||||
| 	 1590 6900 1590 6645 1140 6645 1140 6900 1590 6900 | ||||
| 2 4 0 1 0 7 50 -1 -1 4.000 0 0 7 0 0 5 | ||||
| 	 1590 7185 1590 6930 1140 6930 1140 7185 1590 7185 | ||||
| 2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 1875 7725 8625 7725 | ||||
| 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 | ||||
| 	 1650 5625 3000 5625 3000 6375 1650 6375 1650 5625 | ||||
| 2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 2850 7725 2850 6375 | ||||
| 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 | ||||
| 	 6450 7275 6450 4125 3975 4125 3975 7275 6450 7275 | ||||
| 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 | ||||
| 	 9300 7275 9300 4125 6825 4125 6825 7275 9300 7275 | ||||
| 2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2 | ||||
| 	 3975 6540 6465 6525 | ||||
| 2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2 | ||||
| 	 6825 6540 9315 6525 | ||||
| 2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 5400 7725 5400 7050 | ||||
| 2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 8025 7725 8025 7050 | ||||
| 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 | ||||
| 	 1050 8925 9375 8925 9375 9900 1050 9900 1050 8925 | ||||
| 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 | ||||
| 	 2100 4575 3450 4575 3450 5325 2100 5325 2100 4575 | ||||
| 2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 3225 5325 3225 8325 | ||||
| 2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 6225 6900 6225 8250 | ||||
| 2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 8925 6900 8925 8250 | ||||
| 2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 1725 7125 1725 8325 | ||||
| 2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 2850 5850 2850 5025 | ||||
| 2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 5175 8475 5175 9375 | ||||
| 2 1 1 3 0 7 50 -1 -1 2.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 1350 7125 1350 9450 | ||||
| 2 1 0 4 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 | ||||
| 	1 1 2.00 120.00 240.00 | ||||
| 	 2325 7725 2325 7200 | ||||
| 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 1 | ||||
| 	 900 3975 | ||||
| 2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 1 | ||||
| 	 9525 9975 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 870 4350 7980 XenBus\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 780 1680 6870 drivers\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 1050 1800 6075 XenStore\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 900 1875 7125 Kernel0\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 960 4875 6975 KernelU\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 960 7650 6975 KernelU\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 255 1740 4050 8400 Xen Hypervisor\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 585 2325 4950 Xend\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 690 1200 4725 Dom0\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 750 4875 5325 DomU\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 750 7650 5325 DomU\001 | ||||
| 4 0 0 50 -1 0 18 0.0000 4 195 1080 3750 9450 Hardware\001 | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 5.4 KiB | 
| @@ -1,97 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1 >libvirt architecture</h1> | ||||
|  | ||||
|     <p> | ||||
|       Currently libvirt supports 2 kind of virtualization, and its | ||||
|       internal structure is based on a driver model which simplifies | ||||
|       adding new | ||||
|       engines: | ||||
|     </p> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="Xen">Xen support</a></h2> | ||||
|  | ||||
|     <p>When running in a Xen environment, programs using libvirt have to execute | ||||
| in "Domain 0", which is the primary Linux OS loaded on the machine. That OS | ||||
| kernel provides most if not all of the actual drivers used by the set of | ||||
| domains. It also runs the Xen Store, a database of information shared by the | ||||
| hypervisor, the kernels, the drivers and the xen daemon. Xend. The xen daemon | ||||
| supervise the control and execution of the sets of domains. The hypervisor, | ||||
| drivers, kernels and daemons communicate though a shared system bus | ||||
| implemented in the hypervisor. The figure below tries to provide a view of | ||||
| this environment:</p> | ||||
|     <img src="architecture.gif" alt="The Xen architecture" /> | ||||
|     <p>The library can be initialized in 2 ways depending on the level of | ||||
| privilege of the embedding program. If it runs with root access, | ||||
| virConnectOpen() can be used, it will use three different ways to connect to | ||||
| the Xen infrastructure:</p> | ||||
|     <ul> | ||||
|       <li>a connection to the Xen Daemon though an HTTP RPC layer</li> | ||||
|       <li>a read/write connection to the Xen Store</li> | ||||
|       <li>use Xen Hypervisor calls</li> | ||||
|       <li>when used as non-root libvirt connect to a proxy daemon running | ||||
|       as root and providing read-only support</li> | ||||
|     </ul> | ||||
|     <p>The library will usually interact with the Xen daemon for any operation | ||||
| changing the state of the system, but for performance and accuracy reasons | ||||
| may talk directly to the hypervisor when gathering state information at | ||||
| least when possible (i.e. when the running program using libvirt has root | ||||
| privilege access).</p> | ||||
|     <p>If it runs without root access virConnectOpenReadOnly() should be used to | ||||
| connect to initialize the library. It will then fork a libvirt_proxy | ||||
| program running as root and providing read_only access to the API, this is | ||||
| then only useful for reporting and monitoring.</p> | ||||
|  | ||||
|     <h2><a name="QEmu">QEmu and KVM support</a></h2> | ||||
|  | ||||
|     <p>The model for QEmu and KVM is completely similar, basically KVM is based | ||||
| on QEmu for the process controlling a new domain, only small details differs | ||||
| between the two. In both case the libvirt API is provided by a controlling | ||||
| process forked by libvirt in the background and which launch and control the | ||||
| QEmu or KVM process. That program called libvirt_qemud talks though a specific | ||||
| protocol to the library, and connects to the console of the QEmu process in | ||||
| order to control and report on its status. Libvirt tries to expose all the | ||||
| emulations models of QEmu, the selection is done when creating the new | ||||
| domain, by specifying the architecture and machine type targeted.</p> | ||||
|     <p>The code controlling the QEmu process is available in the | ||||
| <code>qemud/</code> directory.</p> | ||||
|  | ||||
|     <h2><a name="drivers">Driver based architecture</a></h2> | ||||
|  | ||||
|     <p>As the previous section explains, libvirt can communicate using different | ||||
| channels with the current hypervisor, and should also be able to use | ||||
| different kind of hypervisor. To simplify the internal design, code, ease | ||||
| maintenance and simplify the support of other virtualization engine the | ||||
| internals have been structured as one core component, the libvirt.c module | ||||
| acting as a front-end for the library API and a set of hypervisor drivers | ||||
| defining a common set of routines. That way the Xen Daemon access, the Xen | ||||
| Store one, the Hypervisor hypercall are all isolated in separate C modules | ||||
| implementing at least a subset of the common operations defined by the | ||||
| drivers present in driver.h:</p> | ||||
|     <ul> | ||||
|       <li>xend_internal: implements the driver functions though the Xen | ||||
|   Daemon</li> | ||||
|       <li>xs_internal: implements the subset of the driver available though the | ||||
|     Xen Store</li> | ||||
|       <li>xen_internal: provide the implementation of the functions possible via | ||||
|     direct hypervisor access</li> | ||||
|       <li>proxy_internal: provide read-only Xen access via a proxy, the proxy code | ||||
|     is in the <code>proxy/</code> directory.</li> | ||||
|       <li>xm_internal: provide support for Xen defined but not running | ||||
|     domains.</li> | ||||
|       <li>qemu_internal: implement the driver functions for QEmu and | ||||
|     KVM virtualization engines. It also uses a qemud/ specific daemon | ||||
|     which interacts with the QEmu process to implement libvirt API.</li> | ||||
|       <li>test: this is a test driver useful for regression tests of the | ||||
|     front-end part of libvirt.</li> | ||||
|     </ul> | ||||
|     <p>Note that a given driver may only implement a subset of those functions, | ||||
| (for example saving a Xen domain state to disk and restoring it is only | ||||
| possible though the Xen Daemon), in that case the driver entry points for | ||||
| unsupported functions are initialized to NULL.</p> | ||||
|     <p></p> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,53 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Network management architecture</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="architecture">Architecture illustration</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The diagrams below illustrate some of the network configurations | ||||
|       enabled by the libvirt networking APIs | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li><strong>VLAN 1</strong>. This virtual network has connectivity | ||||
|         to <code>LAN 2</code> with traffic forwarded and NATed. | ||||
|       </li> | ||||
|       <li><strong>VLAN 2</strong>. This virtual network is completely | ||||
|         isolated from any physical LAN. | ||||
|       </li> | ||||
|       <li><strong>Guest A</strong>. The first network interface is bridged | ||||
|         to the physical <code>LAN 1</code>. The second interface is connected | ||||
|         to a virtual network <code>VLAN 1</code>. | ||||
|       </li> | ||||
|       <li><strong>Guest B</strong>. The first network interface is connected | ||||
|         to a virtual network <code>VLAN 1</code>, giving it limited NAT | ||||
|         based connectivity to LAN2. It has a second network interface | ||||
|         connected to <code>VLAN 2</code>. It acts a router allowing limited | ||||
|         traffic between the two VLANs, thus giving <code>Guest C</code> | ||||
|         connectivity to the physical <code>LAN 2</code>. | ||||
|         </li> | ||||
|       <li><strong>Guest C</strong>. The only network interface is connected | ||||
|         to a virtual network <code>VLAN 2</code>. It has no direct connectivity | ||||
|         to a physical LAN, relying on <code>Guest B</code> to route traffic | ||||
|         on its behalf. | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <h3><a name="logical">Logical diagram</a></h3> | ||||
|  | ||||
|     <p class="image"> | ||||
|       <img src="libvirt-net-logical.png" alt="Logical network architecture"/> | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="physical">Physical diagram</a></h3> | ||||
|  | ||||
|     <p class="image"> | ||||
|       <img src="libvirt-net-physical.png" alt="Physical network architecture"/> | ||||
|     </p> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,5 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Node device management architecture</h1> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,30 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Storage management architecture</h1> | ||||
|  | ||||
|     <p> | ||||
|       The storage management APIs are based around 2 core concepts | ||||
|     </p> | ||||
|     <ol> | ||||
|       <li> | ||||
|         <strong>Volume</strong> - a single storage volume which can | ||||
|         be assigned to a guest, or used for creating further pools. A | ||||
|         volume is either a block device, a raw file, or a special format | ||||
|         file. | ||||
|       </li> | ||||
|       <li> | ||||
|         <strong>Pool</strong> - provides a means for taking a chunk | ||||
|         of storage and carving it up into volumes. A pool can be used to | ||||
|         manage things such as a physical disk, a NFS server, a iSCSI target, | ||||
|         a host adapter, an LVM group. | ||||
|       </li> | ||||
|     </ol> | ||||
|  | ||||
|     <p> | ||||
|       These two concepts are mapped through to two libvirt objects, a | ||||
|       <code>virStorageVolPtr</code> and a <code>virStoragePoolPtr</code>, | ||||
|       each with a collection of APIs for their management. | ||||
|     </p> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,172 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1 >Access control</h1> | ||||
|     <p> | ||||
|       When connecting to libvirt, some connections may require client | ||||
|       authentication before allowing use of the APIs. The set of possible | ||||
|       authentication mechanisms is administrator controlled, independent | ||||
|       of applications using libvirt. | ||||
|     </p> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="ACL_server_config">Server configuration</a></h2> | ||||
|     <p> | ||||
| The libvirt daemon allows the administrator to choose the authentication | ||||
| mechanisms used for client connections on each network socket independently. | ||||
| This is primarily controlled via the libvirt daemon master config file in | ||||
| <code>/etc/libvirt/libvirtd.conf</code>. Each of the libvirt sockets can | ||||
| have its authentication mechanism configured independently. There is | ||||
| currently a choice of <code>none</code>, <code>polkit</code>, and <code>sasl</code>. | ||||
| The SASL scheme can be further configured to choose between a large | ||||
| number of different mechanisms. | ||||
| </p> | ||||
|     <h2><a name="ACL_server_unix_perms">UNIX socket permissions/group</a></h2> | ||||
|     <p> | ||||
| If libvirt does not contain support for PolicyKit, then access control for | ||||
| the UNIX domain socket is done using traditional file user/group ownership | ||||
| and permissions. There are 2 sockets, one for full read-write access, the | ||||
| other for read-only access. The RW socket will be restricted (mode 0700) to | ||||
| only allow the <code>root</code> user to connect. The read-only socket will | ||||
| be open access (mode 0777) to allow any user to connect. | ||||
| </p> | ||||
|     <p> | ||||
| To allow non-root users greater access, the <code>libvirtd.conf</code> file | ||||
| can be edited to change the permissions via the <code>unix_sock_rw_perms</code>, | ||||
| config parameter and to set a user group via the <code>unix_sock_group</code> | ||||
| parameter. For example, setting the former to mode <code>0770</code> and the | ||||
| latter <code>wheel</code> would let any user in the wheel group connect to | ||||
| the libvirt daemon. | ||||
| </p> | ||||
|     <h2><a name="ACL_server_polkit">UNIX socket PolicyKit auth</a></h2> | ||||
|     <p> | ||||
| If libvirt contains support for PolicyKit, then access control options are | ||||
| more advanced. The <code>unix_sock_auth</code> parameter will default to | ||||
| <code>polkit</code>, and the file permissions will default to <code>0777</code> | ||||
| even on the RW socket. Upon connecting to the socket, the client application | ||||
| will be required to identify itself with PolicyKit. The default policy for the | ||||
| RW daemon socket will require any application running in the current desktop | ||||
| session to authenticate using the user's password. This is akin to <code>sudo</code> | ||||
| auth, but does not require that the client application ultimately run as root. | ||||
| Default policy will still allow any application to connect to the RO socket. | ||||
| </p> | ||||
|     <p> | ||||
| The default policy can be overridden by creating a new policy file in the | ||||
| local override directory <code>/etc/polkit-1/localauthority/50-local.d/</code>. | ||||
| Policy files should have a unique name ending with .pkla.  Using reverse DNS | ||||
| naming works well. Information on the options available can be found by | ||||
| reading the pklocalauthority man page. The two libvirt daemon actions | ||||
| available are named <code>org.libvirt.unix.manage</code> for full management | ||||
| access, and <code>org.libvirt.unix.monitor</code> for read-only access. | ||||
|     </p> | ||||
|     <p> | ||||
| As an example, this gives the user <code>fred</code> full management access: | ||||
|     </p> | ||||
| <pre>[Allow fred libvirt management permissions] | ||||
| Identity=unix-user:fred | ||||
| Action=org.libvirt.unix.manage | ||||
| ResultAny=yes | ||||
| ResultInactive=yes | ||||
| ResultActive=yes</pre> | ||||
|     <p> | ||||
| Further examples of PolicyKit setup can be found on the | ||||
| <a href="http://wiki.libvirt.org/page/SSHPolicyKitSetup">wiki page</a>. | ||||
|     </p> | ||||
|     <h2><a name="ACL_server_username">Username/password auth</a></h2> | ||||
|     <p> | ||||
| The plain TCP socket of the libvirt daemon defaults to using SASL for authentication. | ||||
| The SASL mechanism configured by default is DIGEST-MD5, which provides a basic | ||||
| username+password style authentication. It also provides for encryption of the data | ||||
| stream, so the security of the plain TCP socket is on a par with that of the TLS | ||||
| socket. If desired the UNIX socket and TLS socket can also have SASL enabled by | ||||
| setting the <code>auth_unix_ro</code>, <code>auth_unix_rw</code>, <code>auth_tls</code> | ||||
| config params in <code>libvirt.conf</code>. | ||||
| </p> | ||||
|     <p> | ||||
| Out of the box, no user accounts are defined, so no clients will be able to authenticate | ||||
| on the TCP socket. Adding users and setting their passwords is done with the <code>saslpasswd2</code> | ||||
| command. When running this command it is important to tell it that the appname is <code>libvirt</code>. | ||||
| As an example, to add a user <code>fred</code>, run | ||||
| </p> | ||||
|     <pre> | ||||
| # saslpasswd2 -a libvirt fred | ||||
| Password: xxxxxx | ||||
| Again (for verification): xxxxxx | ||||
| </pre> | ||||
|     <p> | ||||
| To see a list of all accounts the <code>sasldblistusers2</code> command can be used. | ||||
| This command expects to be given the path to the libvirt user database, which is kept | ||||
| in <code>/etc/libvirt/passwd.db</code> | ||||
| </p> | ||||
|     <pre> | ||||
| # sasldblistusers2 -f /etc/libvirt/passwd.db | ||||
| fred@t60wlan.home.berrange.com: userPassword | ||||
| </pre> | ||||
|     <p> | ||||
| Finally, to disable a user's access, the <code>saslpasswd2</code> command can be used | ||||
| again: | ||||
| </p> | ||||
|     <pre> | ||||
| # saslpasswd2 -a libvirt -d fred | ||||
| </pre> | ||||
|     <h2><a name="ACL_server_kerberos">Kerberos auth</a></h2> | ||||
|     <p> | ||||
| The plain TCP socket of the libvirt daemon defaults to using SASL for authentication. | ||||
| The SASL mechanism configured by default is DIGEST-MD5, which provides a basic | ||||
| username+password style authentication. To enable Kerberos single-sign-on instead, | ||||
| the libvirt SASL configuration file must be changed. This is <code>/etc/sasl2/libvirt.conf</code>. | ||||
| The <code>mech_list</code> parameter must first be changed to <code>gssapi</code> | ||||
| instead of the default <code>digest-md5</code>. If SASL is enabled on the UNIX | ||||
| and/or TLS sockets, Kerberos will also be used for them. Like DIGEST-MD5, the Kerberos | ||||
| mechanism provides data encryption of the session. | ||||
| </p> | ||||
|     <p> | ||||
| Some operating systems do not install the SASL kerberos plugin by default. It | ||||
| may be necessary to install a sub-package such as <code>cyrus-sasl-gssapi</code>. | ||||
| To check whether the Kerberos plugin is installed run the <code>pluginviewer</code> | ||||
| program and verify that <code>gssapi</code> is listed,eg: | ||||
| </p> | ||||
|     <pre> | ||||
| # pluginviewer | ||||
| ...snip... | ||||
| Plugin "gssapiv2" [loaded],     API version: 4 | ||||
|         SASL mechanism: GSSAPI, best SSF: 56 | ||||
|         security flags: NO_ANONYMOUS|NO_PLAINTEXT|NO_ACTIVE|PASS_CREDENTIALS|MUTUAL_AUTH | ||||
|         features: WANT_CLIENT_FIRST|PROXY_AUTHENTICATION|NEED_SERVER_FQDN | ||||
| </pre> | ||||
|     <p> | ||||
| Next it is necessary for the administrator of the Kerberos realm to issue a principle | ||||
| for the libvirt server. There needs to be one principle per host running the libvirt | ||||
| daemon. The principle should be named <code>libvirt/full.hostname@KERBEROS.REALM</code>. | ||||
| This is typically done by running the <code>kadmin.local</code> command on the Kerberos | ||||
| server, though some Kerberos servers have alternate ways of setting up service principles. | ||||
| Once created, the principle should be exported to a keytab, copied to the host running | ||||
| the libvirt daemon and placed in <code>/etc/libvirt/krb5.tab</code> | ||||
| </p> | ||||
|     <pre> | ||||
| # kadmin.local | ||||
| kadmin.local: add_principal libvirt/foo.example.com | ||||
| Enter password for principal "libvirt/foo.example.com@EXAMPLE.COM": | ||||
| Re-enter password for principal "libvirt/foo.example.com@EXAMPLE.COM": | ||||
| Principal "libvirt/foo.example.com@EXAMPLE.COM" created. | ||||
|  | ||||
| kadmin.local:  ktadd -k /root/libvirt-foo-example.tab libvirt/foo.example.com@EXAMPLE.COM | ||||
| Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/root/libvirt-foo-example.tab. | ||||
| Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type ArcFour with HMAC/md5 added to keytab WRFILE:/root/libvirt-foo-example.tab. | ||||
| Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES with HMAC/sha1 added to keytab WRFILE:/root/libvirt-foo-example.tab. | ||||
| Entry for principal libvirt/foo.example.com@EXAMPLE.COM with kvno 4, encryption type DES cbc mode with RSA-MD5 added to keytab WRFILE:/root/libvirt-foo-example.tab. | ||||
|  | ||||
| kadmin.local: quit | ||||
|  | ||||
| # scp /root/libvirt-foo-example.tab root@foo.example.com:/etc/libvirt/krb5.tab | ||||
| # rm /root/libvirt-foo-example.tab | ||||
| </pre> | ||||
|     <p> | ||||
| Any client application wishing to connect to a Kerberos enabled libvirt server | ||||
| merely needs to run <code>kinit</code> to gain a user principle. This may well | ||||
| be done automatically when a user logs into a desktop session, if PAM is setup | ||||
| to authenticate against Kerberos. | ||||
| </p> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,83 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1 >Bindings for other languages</h1> | ||||
|  | ||||
|     <p> | ||||
|       Libvirt supports C and C++ directly, and has bindings available | ||||
|       for other languages: | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         <strong>C#</strong>: Arnaud Champion develops | ||||
|         <a href="csharp.html">C# bindings</a>. | ||||
|       </li> | ||||
|       <li> | ||||
|         <strong>Java</strong>: Daniel Veillard develops | ||||
|         <a href="java.html">Java bindings</a>. | ||||
|       </li> | ||||
|       <li> | ||||
|         <strong>OCaml</strong>: Richard Jones develops | ||||
|         <a href="http://libvirt.org/ocaml/">OCaml bindings</a>. | ||||
|       </li> | ||||
|       <li> | ||||
|         <strong>Perl</strong>: Daniel Berrange develops | ||||
|         <a href="http://search.cpan.org/dist/Sys-Virt/">Perl bindings</a>. | ||||
|       </li> | ||||
|       <li> | ||||
|         <p> | ||||
|           <strong>PHP</strong>: Radek Hladik started developing | ||||
|           <a href="http://libvirt.org/php">PHP bindings</a> in 2010. | ||||
|         </p> | ||||
|         <p> | ||||
|           In February 2011 the binding development has been moved to the libvirt.org website as | ||||
|           libvirt-php project. | ||||
|         </p> | ||||
|         <p> | ||||
|           The project is now maintained by Michal Novotny and it's heavily based | ||||
|           on Radek's version. For more information, including | ||||
|           information on posting patches to libvirt-php, please refer | ||||
|           to the <a href="http://libvirt.org/php">PHP bindings</a> site. | ||||
|         </p> | ||||
|       </li> | ||||
|       <li> | ||||
|         <p> | ||||
|           <strong>Python</strong>: Libvirt comes with direct support for | ||||
|           the Python language. | ||||
|         </p> | ||||
|         <p> | ||||
|           If your libvirt is installed as packages, rather than compiled | ||||
|           by you from source code, ensure you have the appropriate | ||||
|           package installed. | ||||
|         </p> | ||||
|         <p> | ||||
|           This is named <b>libvirt-python</b> on RHEL/Fedora, | ||||
|           <a href="http://packages.ubuntu.com/search?keywords=python-libvirt"><b>python-libvirt</b></a> | ||||
|           on Ubuntu, and may be named differently on others. | ||||
|         </p> | ||||
|         <p> | ||||
|           For usage information, see the | ||||
|           <a href="python.html">Python API bindings</a> page. | ||||
|         </p> | ||||
|       </li> | ||||
|       <li> | ||||
|         <strong>Ruby</strong>: Chris Lalancette develops | ||||
|         <a href="http://libvirt.org/ruby/">Ruby bindings</a>. | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <p> | ||||
|       For information on using libvirt on <strong>Windows</strong> | ||||
|       <a href="windows.html">please see the Windows support page</a>. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Support, requests or help for libvirt bindings are welcome on the | ||||
|       <a href="https://www.redhat.com/mailman/listinfo/libvir-list/">mailing list</a>, | ||||
|       as usual try to provide enough background information and make sure | ||||
|       you use recent version, see the <a href="bugs.html">help page</a>. | ||||
|     </p> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,115 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|  | ||||
|     <h1>Bug reporting</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="bugzilla">Bug Tracking</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The <a href="http://bugzilla.redhat.com">Red Hat Bugzilla Server</a> | ||||
|       should be used to report bugs and request features in libvirt. | ||||
|       Before submitting a ticket, check the existing tickets to see if | ||||
|       the bug/feature is already tracked. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="general">General libvirt bug reports</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       If you are using official libvirt binaries from a Linux distribution | ||||
|       check below for distribution specific bug reporting policies first. | ||||
|       For general libvirt bug reports, from self-built releases, GIT snapshots | ||||
|       and any other non-distribution supported builds, enter tickets under | ||||
|       the <code>Virtualization Tools</code> product and the <code>libvirt</code> | ||||
|       component. | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li><a href="http://bugzilla.redhat.com/buglist.cgi?component=libvirt&product=Virtualization%20Tools">View libvirt tickets</a></li> | ||||
|       <li><a href="http://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Virtualization%20Tools&component=libvirt">New libvirt ticket</a></li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="distribution">Linux Distribution specific bug reports</a></h2> | ||||
|     <ul> | ||||
|       <li> | ||||
|         If you are using official binaries from a <strong>Fedora distribution</strong>, enter | ||||
|         tickets against the <code>Fedora</code> product and the <code>libvirt</code> | ||||
|         component. | ||||
|         <ul> | ||||
|           <li><a href="http://bugzilla.redhat.com/buglist.cgi?component=libvirt&product=Fedora">View Fedora libvirt tickets</a></li> | ||||
|           <li><a href="http://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Fedora&component=libvirt">New Fedora libvirt ticket</a></li> | ||||
|         </ul> | ||||
|       </li> | ||||
|       <li> | ||||
|         If you are using official binaries from <strong>Red Hat Enterprise Linux distribution</strong>, | ||||
|         tickets against the <code>Red Hat Enterprise Linux 5</code> product and | ||||
|         the <code>libvirt</code> component. | ||||
|         <ul> | ||||
|           <li><a href="http://bugzilla.redhat.com/buglist.cgi?component=libvirt&product=Red%20Hat%20Enterprise%20Linux%205">View Red Hat Enterprise Linux libvirt tickets</a></li> | ||||
|           <li><a href="http://bugzilla.redhat.com/bugzilla/enter_bug.cgi?product=Red%20Hat%20Enterprise%20Linux%205&component=libvirt">New Red Hat Enterprise Linux libvirt ticket</a></li> | ||||
|         </ul> | ||||
|       </li> | ||||
|       <li> | ||||
|         If you are using official binaries from another Linux distribution first | ||||
|         follow their own bug reporting guidelines. | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|  | ||||
|     <h2><a name="quality">How to file high quality bug reports</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       To increase the likelihood of your bug report being addressed it is | ||||
|       important to provide as much information as possible. When filing | ||||
|       libvirt bugs use this checklist to see if you are providing enough | ||||
|       information: | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li>The version number of the libvirt build, or SHA1 of the GIT | ||||
|         commit</li> | ||||
|       <li>The hardware architecture being used</li> | ||||
|       <li>The name of the hypervisor (Xen, QEMU, KVM)</li> | ||||
|       <li>The XML config of the guest domain if relevant</li> | ||||
|       <li>For Xen hypervisor, the XenD logfile from /var/log/xen</li> | ||||
|       <li>For QEMU/KVM, the domain logfile from /var/log/libvirt/qemu</li> | ||||
|     </ul> | ||||
|  | ||||
|     <p> | ||||
|       If the bug leads to a tool linked to libvirt crash, then the best | ||||
|       is to provide a backtrace along with the scenario used to get the | ||||
|       crash, the simplest is to run the program under gdb, reproduce the | ||||
|       steps leading to the crash and then issue a gdb "bt" command to | ||||
|       get the stack trace, attach it to the bug. Note that for the | ||||
|       data to be really useful libvirt debug informations must be present | ||||
|       for example by installing libvirt debuginfo package on Fedora or | ||||
|       Red Hat Enterprise Linux (with debuginfo-install libvirt) prior | ||||
|       to running gdb.</p> | ||||
|     <p> | ||||
|       It may also happen that the libvirt daemon itself crashes or get stuck, | ||||
|       in the first case run it (as root) under gdb, and reproduce the sequence | ||||
|       leading to the crash, similary to a normal program provide the | ||||
|       "bt" backtrace information to where gdb will have stopped.<br/> | ||||
|       But if libvirtd get stuck, for example seems to stop processing | ||||
|       commands, try to attach to the faulty daemon and issue a gdb command | ||||
|       "thread apply all bt" to show all the threads backtraces, as in:</p> | ||||
|       <pre> #  ps -o etime,pid `pgrep libvirt` | ||||
| ... note the process id from the output | ||||
| # gdb /usr/sbin/libvirtd | ||||
| .... some informations about gdb and loading debug data | ||||
| (gdb) attach $the_damon_process_id | ||||
| .... | ||||
| (gdb) thread apply all bt | ||||
| .... informations to attach to the bug | ||||
| (gdb) | ||||
| </pre> | ||||
|  | ||||
|     <p> | ||||
|       If requesting a new feature attach any available patch to the ticket | ||||
|       and also email the patch to the libvirt mailing list for discussion | ||||
|     </p> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,75 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1><a name="installation">libvirt Installation</a></h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="compiling">Compiling a release tarball</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       libvirt uses the standard configure/make/install steps: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       $ gunzip -c libvirt-x.x.x.tar.gz | tar xvf - | ||||
|       $ cd libvirt-x.x.x | ||||
|       $ ./configure</pre> | ||||
|  | ||||
|     <p> | ||||
|       The <i>configure</i> script can be given options to change its default | ||||
|       behaviour. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       To get the complete list of the options it can take, pass it the | ||||
|       <i>--help</i> option like this: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       $ ./configure <i>--help</i></pre> | ||||
|  | ||||
|     <p> | ||||
|       When you have determined which options you want to use (if any), | ||||
|       continue the process. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Note the use of <b>sudo</b> with the <i>make install</i> command | ||||
|       below.  Using sudo is only required when installing to a location your | ||||
|       user does not have write access to.  Installing to a system location | ||||
|       is a good example of this. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       If you are installing to a location that your user <i>does</i> have write | ||||
|       access to, then you can instead run the <i>make install</i> command | ||||
|       without putting <b>sudo</b> before it. | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       $ ./configure <i>[possible options]</i> | ||||
|       $ make | ||||
|       $ <b>sudo</b> <i>make install</i></pre> | ||||
|  | ||||
|     <p> | ||||
|       At this point you <b>may</b> have to run ldconfig or a similar utility | ||||
|       to update your list of installed shared libs. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="building">Building from a GIT checkout</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The libvirt build process uses GNU autotools, so after obtaining a | ||||
|       checkout it is necessary to generate the configure script and Makefile.in | ||||
|       templates using the <code>autogen.sh</code> command, passing the extra | ||||
|       arguments as for configure. As an example, to do a complete build and | ||||
|       install it into your home directory run: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       $ ./autogen.sh --prefix=$HOME/usr --enable-compile-warnings=error | ||||
|       $ make | ||||
|       $ <b>sudo</b> make install</pre> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,103 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Contacting the development team</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="email">Mailing lists</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       There are three mailing-lists: | ||||
|     </p> | ||||
|  | ||||
|     <dl> | ||||
|       <dt><a href="https://www.redhat.com/mailman/listinfo/libvir-list">libvir-list@redhat.com</a> (for development)</dt> | ||||
|       <dd> | ||||
|         Archives at <a href="https://www.redhat.com/archives/libvir-list">https://www.redhat.com/archives/libvir-list</a> | ||||
|       </dd> | ||||
|       <dd> | ||||
|         This is a high volume mailing list.  It is a place for discussions | ||||
|         about the <strong>development</strong> of libvirt. | ||||
|       </dd> | ||||
|       <dd> | ||||
|         Topics for discussion include: | ||||
|         <ul> | ||||
|           <li>New features for libvirt</li> | ||||
|           <li>Bug fixing of libvirt</li> | ||||
|           <li>New hypervisor drivers</li> | ||||
|           <li>Development of language bindings for libvirt API</li> | ||||
|           <li>Testing and documentation of libvirt</li> | ||||
|         </ul> | ||||
|       </dd> | ||||
|  | ||||
|       <dt><a href="https://www.redhat.com/mailman/listinfo/libvirt-users">libvirt-users@redhat.com</a> (for users)</dt> | ||||
|       <dd> | ||||
|         Archives at <a href="https://www.redhat.com/archives/libvirt-users">https://www.redhat.com/archives/libvirt-users</a> | ||||
|       </dd> | ||||
|       <dd> | ||||
|         This is a moderate volume mailing list.  It is a place for discussions | ||||
|         involving libvirt <strong>users</strong>. | ||||
|       </dd> | ||||
|       <dd> | ||||
|         Topics for discussion include: | ||||
|         <ul> | ||||
|           <li>Usage of libvirt / virsh</li> | ||||
|           <li>Administration of libvirt</li> | ||||
|           <li>Deployment of libvirt with hypervisors</li> | ||||
|           <li>Development of applications on top of / using the libvirt API(s)</li> | ||||
|           <li>Any other topics along these lines</li> | ||||
|         </ul> | ||||
|       </dd> | ||||
|  | ||||
|       <dt><a href="https://www.redhat.com/mailman/listinfo/libvirt-announce">libvirt-announce@redhat.com</a> (for release notices)</dt> | ||||
|       <dd> | ||||
|         Archives at <a href="https://www.redhat.com/archives/libvirt-announce">https://www.redhat.com/archives/libvirt-announce</a> | ||||
|       </dd> | ||||
|       <dd> | ||||
|         This is a low volume mailing list, with restricted posting, for | ||||
|         announcements of new libvirt releases. | ||||
|       </dd> | ||||
|       <dd> | ||||
|         Subscribe to just this if you want to be notified of new releases, | ||||
|         without subscribing to either of the other mailing lists. | ||||
|       </dd> | ||||
|  | ||||
|     </dl> | ||||
|  | ||||
|     <p> | ||||
|       It is recommended but not required that you subscribe before posting | ||||
|       to the user and development lists.  Posts from non-subscribers will be | ||||
|       subject to manual moderation delays.  You can subscribe at the linked | ||||
|       web pages above. | ||||
|     </p> | ||||
|     <p> | ||||
|       Patches with explanations and provided as attachments are really | ||||
|       appreciated, and should be directed to the development mailing list | ||||
|       for review and discussion. | ||||
|       Wherever possible, please generate the patches by using | ||||
|       <code>git format-patch</code> in a git repository clone.  Further | ||||
|       useful information regarding developing libvirt and/or contributing is | ||||
|       available on our <a href="hacking.html">Contributor Guidelines</a> | ||||
|       page. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="irc">IRC discussion</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Some of the libvirt developers may be found on IRC on the <a href="http://oftc.net">OFTC IRC</a> | ||||
|       network. Use the settings: | ||||
|     </p> | ||||
|     <ul> | ||||
|       <li>server: irc.oftc.net</li> | ||||
|       <li>port: 6667 (the usual IRC port)</li> | ||||
|       <li>channel: #virt</li> | ||||
|     </ul> | ||||
|     <p> | ||||
|       NB There is no guarantee that someone will be watching or able to reply | ||||
|       promptly, so use the mailing-list if you don't get an answer on the IRC | ||||
|       channel. | ||||
|     </p> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,502 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>C# API bindings</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="description">Description</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The C# libvirt bindings are a class library.  They use a Microsoft | ||||
|       Visual Studio project architecture, and have been tested with Windows | ||||
|       .NET, and Mono, on both Linux and Windows. | ||||
|     </p> | ||||
|     <p> | ||||
|       Compiling them produces <b>LibvirtBindings.dll</b>, which can | ||||
|       be added as a .NET reference to any .NET project needing access | ||||
|       to libvirt. | ||||
|     </p> | ||||
|  | ||||
|     <p> </p> | ||||
|  | ||||
|     <h2><a name="requirements">Requirements</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       These bindings depend upon the libvirt libraries being installed. | ||||
|     </p> | ||||
|     <p> | ||||
|       In the .NET case, this is <b>libvirt-0.dll</b>, produced from | ||||
|       compiling libvirt for windows. | ||||
|     </p> | ||||
|  | ||||
|     <p> </p> | ||||
|  | ||||
| <!-- 2010-10-19 JC: Commented out until we have C# tarballs to download | ||||
|     <h2><a name="getting">Getting them</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The latest versions of the libvirt C# bindings can be downloaded from: | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li><a href="ftp://libvirt.org/libvirt/csharp/">libvirt.org FTP server</a></li> | ||||
|       <li><a href="http://libvirt.org/sources/csharp/">libvirt.org HTTP server</a></li> | ||||
|     </ul> | ||||
| --> | ||||
|  | ||||
|     <h2><a name="git">GIT source repository</a></h2> | ||||
|     <p> | ||||
|       The C# bindings source code is maintained in a <a | ||||
|       href="http://git-scm.com/">git</a> repository available on | ||||
|       <a href="http://libvirt.org/git/">libvirt.org</a>: | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| git clone git://libvirt.org/libvirt-csharp.git | ||||
| </pre> | ||||
|  | ||||
|     <p> | ||||
|       They can also be browsed online: | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| <a href="http://libvirt.org/git/?p=libvirt-csharp.git;a=summary">http://libvirt.org/git/?p=libvirt-csharp.git;a=summary</a> | ||||
| </pre> | ||||
|  | ||||
|     <p> </p> | ||||
|  | ||||
|     <h2><a name="usage">Usage</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The libvirt C# bindings class library exposes the <b>Libvirt</b> | ||||
|       namespace.  This namespace exposes all of the needed types (enum, | ||||
|       struct), plus many classes exposing the libvirt API methods. | ||||
|     </p> | ||||
|     <p> | ||||
|       These classes are grouped into functional areas, with each class | ||||
|       exposing libvirt methods related to that area. | ||||
|     </p> | ||||
|     <p> | ||||
|       For example, the libvirt methods related to connections, such as | ||||
|       <b>virConnectOpenAuth</b> and <b>virConnectNumOfDomains</b>, are in | ||||
|       the <b>Connect</b> class. | ||||
|       <br /> | ||||
|       They are accessed as <b>Connect.OpenAuth</b>, and | ||||
|       <b>Connect.NumOfDomains</b> respectively. | ||||
|     </p> | ||||
|     <p> | ||||
|       In the same manner, the other class name mappings are: | ||||
|     </p> | ||||
|     <table class="top_table"> | ||||
|       <tr><th>Name of libvirt function</th><th>C# class name</th></tr> | ||||
|       <tr><td>virDomain...</td><td>Domain</td></tr> | ||||
|       <tr><td>virEvent...</td><td>Event</td></tr> | ||||
|       <tr><td>virInterface...</td><td>Interface</td></tr> | ||||
|       <tr><td>virNetwork...</td><td>Network</td></tr> | ||||
|       <tr><td>virNode...</td><td>Node</td></tr> | ||||
|       <tr><td>virSecret...</td><td>Secret</td></tr> | ||||
|       <tr><td>virStoragePool...</td><td>StoragePool</td></tr> | ||||
|       <tr><td>virStorageVolume...</td><td>StorageVolume</td></tr> | ||||
|       <tr><td>virStream...</td><td>Stream</td></tr> | ||||
|     </table> | ||||
|     <p> | ||||
|       There are some additions as well: | ||||
|     </p> | ||||
|     <ul> | ||||
|       <li> | ||||
|         There is a class named <b>Library</b>, exposing the | ||||
|         <b>virGetVersion</b> and <b>virInitialize</b> methods | ||||
|       </li> | ||||
|       <li> | ||||
|         There is a class named <b>Errors</b>, exposing the error | ||||
|         related methods.  For example, <b>virSetErrorFunc</b> and | ||||
|         <b>virConnResetLastError</b>. | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <p> </p> | ||||
|  | ||||
|     <h2><a name="authors">Authors</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The C# bindings are the work of Arnaud Champion | ||||
|       <<a href="mailto:arnaud.champion AT devatom.fr">arnaud.champion AT devatom.fr</a>>, | ||||
|       based upon the previous work of Jaromír Červenka. | ||||
|     </p> | ||||
|  | ||||
|     <p> </p> | ||||
|  | ||||
|     <h2><a name="notes">Test Configuration</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Testing is performed using the following configurations: | ||||
|     </p> | ||||
|     <ul> | ||||
|       <li>Windows 7 (64 bits) / .Net 4</li> | ||||
|       <li>Windows 7 (64 bits) / Mono 2.6.7 (compiled in 32 bits)</li> | ||||
|       <li>Ubuntu 10.10 amd64 / Mono 2.6.7 (compiled in 64 bits)</li> | ||||
|     </ul> | ||||
|  | ||||
|     <p> </p> | ||||
|  | ||||
|     <h2><a name="type">Type Coverage</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Coverage of the libvirt types is: | ||||
|     </p> | ||||
|     <table class="top_table"> | ||||
|       <tr><th>Type</th><th>Name</th><th>Binding?</th><th>Tested?</th><th>Sample Code?</th><th>Works?</th><th>Tested .Net/Windows Works?</th><th>Tested Mono (32-bit)/Windows Works?</th><th>Tested Mono (64-bit)/Linux Works?</th></tr> | ||||
|       <tr><td>enum</td><td>virCPUCompareResult</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virConnect</td><td>Yes, an IntPtr as the struct is not public</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virConnectAuth</td><td>Yes</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>struct</td><td>virConnectCredential</td><td>Yes</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virConnectCredentialType</td><td>Yes</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virConnectFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomain</td><td>Yes, an IntPtr as the struct is not public</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomainBlockInfo</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomainBlockStatsInfo</td><td>Yes</td><td>Yes</td><td>virDomainStats</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virDomainCoreDumpFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainCreateFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainDeviceModifyFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventDefinedDetailType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>struct</td><td>virDomainEventGraphicsAddress</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventGraphicsAddressType</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventGraphicsPhase</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomainEventGraphicsSubject</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomainEventGraphicsSubjectIdentity</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventID</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventIOErrorAction</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventResumedDetailType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventStartedDetailType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventStoppedDetailType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventSuspendedDetailType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventUndefinedDetailType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>enum</td><td>virDomainEventWatchdogAction</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomainInfo</td><td>Yes</td><td>Yes</td><td>virConnectSetErrorFunc, virDomainStats</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>struct</td><td>virDomainInterfaceStatsStruct</td><td>Yes</td><td>Yes</td><td>virDomainStats</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>struct</td><td>virDomainJobInfo</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainJobType</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainMemoryFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomainMemoryStatStruct</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainMemoryStatTags</td><td>Yes</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainMigrateFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virDomainSnapshot</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainSnapshotDeleteFlags</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainState</td><td>Yes</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virDomainXMLFlags</td><td>Yes</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virEventHandleType</td><td>Yes</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>struct</td><td>virInterface</td><td>Yes, an IntPtr as the struct is not public</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virInterfaceXMLFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virNWFilter</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virNetwork</td><td>Yes, an IntPtr as the struct is not public</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virNodeDevice</td><td>Yes, an IntPtr as the struct is not public</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virNodeInfo</td><td>Yes</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virSchedParameter</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virSchedParameterType</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virSecret</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virSecretUsageType</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virSecurityLabel</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virSecurityModel</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virStoragePoolBuildFlags</td><td>Yes</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virStoragePoolDeleteFlags</td><td>Yes</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virStoragePoolInfo</td><td>Yes</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virStoragePool</td><td>Yes, an IntPtr as the struct is not public</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virStoragePoolState</td><td>Yes</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virStorageVol</td><td>Yes, an IntPtr as the struct is not public</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virStorageVolDeleteFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virStorageVolInfo</td><td>Yes</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virStorageVolType</td><td>Yes</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virStream</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virStreamEventType</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virStreamFlags</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virVcpuInfo</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>enum</td><td>virVcpuState</td><td>No</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>struct</td><td>virError</td><td>Yes</td><td>Yes</td><td>virConnectSetErrorFunc, virDomainStats</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|     </table> | ||||
|  | ||||
|     <p> </p> | ||||
|  | ||||
|     <h2><a name="funccover">Function Coverage</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Coverage of the libvirt functions is: | ||||
|     </p> | ||||
|     <table class="top_table"> | ||||
|       <tr><th>Name</th><th>Binding?</th><th>Type?</th><th>Tested?</th><th>Sample Code?</th><th>Working?</th><th>Tested .Net/Windows Works?</th><th>Tested Mono (32-bit)/Windows Works?</th><th>Tested Mono (64-bit)/Linux Works?</th></tr> | ||||
|       <tr><td>virConnectAuthCallback</td><td>Yes</td><td>delegate</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectBaselineCPU</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectClose</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectCompareCPU</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventCallback</td><td>Yes</td><td>delegate</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventDeregister</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventDeregisterAny</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventGenericCallback</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventGraphicsCallback</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventIOErrorCallback</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventIOErrorReasonCallback</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventRTCChangeCallback</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventRegister</td><td>Yes</td><td>function</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectDomainEventRegisterAny</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainEventWatchdogCallback</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainXMLFromNative</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectDomainXMLToNative</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectFindStoragePoolSources</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectGetCapabilities</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectGetHostname</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectGetLibVersion</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectGetMaxVcpus</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectGetType</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectGetURI</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectGetVersion</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectIsEncrypted</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectIsSecure</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListDefinedDomains</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectListDefinedInterfaces </td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListDefinedNetworks</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListDefinedStoragePools</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListDomains</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth, virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectListInterfaces</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes, if the host handle the method</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListNWFilters </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListNetworks</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListSecrets</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectListStoragePools</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpen</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectNumOfDefinedDomains</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectNumOfDefinedInterfaces</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectNumOfDefinedNetworks</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectNumOfDefinedStoragePools</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectNumOfDomains</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth, virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectNumOfInterfaces</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectNumOfNWFilters</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectNumOfNetworks </td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectNumOfSecrets</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectNumOfStoragePools</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpen</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectOpen</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpen, virEventRegisterImpl, virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectOpenAuth</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnectOpenReadOnly</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virConnectRef</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainAbortJob</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainAttachDevice</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainAttachDeviceFlags</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainBlockPeek</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainBlockStats</td><td>Yes</td><td>function</td><td>Yes</td><td>virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virDomainCoreDump</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainCreate</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainCreateLinux</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainCreateWithFlags</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainCreateXML</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainDefineXML</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainDestroy</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainDetachDevice</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainDetachDeviceFlags</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainFree</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetAutostart</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetBlockInfo</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetConnect</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetID</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetInfo</td><td>Yes</td><td>function</td><td>Yes</td><td>virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virDomainGetJobInfo</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetMaxMemory</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetMaxVcpus</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetName</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth, virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virDomainGetOSType</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetSchedulerParameters</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetSchedulerType</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetSecurityLabel</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetUUID</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetUUIDString</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetVcpus</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainGetXMLDesc</td><td>Yes</td><td>function</td><td>Yes</td><td>virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virDomainHasCurrentSnapshot</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainHasManagedSaveImage</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainInterfaceStats </td><td>No</td><td>function</td><td>Yes</td><td>virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virDomainIsActive</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainIsPersistent</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainLookupByID</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectOpenAuth, virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virDomainLookupByName</td><td>Yes</td><td>function</td><td>Yes</td><td>virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virDomainLookupByUUID</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainLookupByUUIDString</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainManagedSave    </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainManagedSaveRemove</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainMemoryPeek</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainMemoryStats</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainMigrate</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainMigrateSetMaxDowntime</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainMigrateToURI   </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainPinVcpu</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainReboot</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainRef    </td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainRestore</td><td>Yes </td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainResume </td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainRevertToSnapshot</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSave</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSetAutostart</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSetMaxMemory   </td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSetMemory</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSetSchedulerParameters</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSetVcpus</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainShutdown</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotCreateXML</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotCurrent</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotDelete</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotFree</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotGetXMLDesc</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotListNames</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotLookupByName</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSnapshotNum</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainSuspend</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainUndefine</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virDomainUpdateDeviceFlags</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virEventAddHandleFunc</td><td>Yes</td><td>delegate</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virEventAddTimeoutFunc</td><td>Yes</td><td>delegate</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virEventHandleCallback</td><td>Yes</td><td>delegate</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virEventRegisterImpl</td><td>Yes</td><td>function</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virEventRemoveHandleFunc</td><td>Yes</td><td>delegate</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virEventRemoveTimeoutFunc</td><td>Yes</td><td>delegate</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virEventTimeoutCallback</td><td>Yes</td><td>delegate</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virEventUpdateHandleFunc</td><td>Yes</td><td>delegate</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virEventUpdateTimeoutFunc</td><td>Yes</td><td>delegate</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virFreeCallback</td><td>Yes</td><td>function</td><td>Yes</td><td>virEventRegisterImpl</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virGetVersion</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInitialize</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceCreate</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceDefineXML</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceDestroy</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceFree</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceGetConnect</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceGetMACString</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceGetName</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceGetXMLDesc</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceIsActive</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceLookupByMACString</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceLookupByName</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceRef </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virInterfaceUndefine</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterDefineXML</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterFree</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterGetName</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterGetUUID</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterGetUUIDString</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterGetXMLDesc</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterLookupByName </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterLookupByUUID</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterLookupByUUIDString</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterRef  </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNWFilterUndefine</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkCreate</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkCreateXML</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkDefineXML</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkDestroy</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkFree</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkGetAutostart</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkGetBridgeName</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkGetConnect</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkGetName</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkGetUUID</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkGetUUIDString </td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkGetXMLDesc</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkIsActive</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkIsPersistent</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkLookupByName</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkLookupByUUID</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkLookupByUUIDString</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkRef</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkSetAutostart</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNetworkUndefine</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceCreateXML</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceDestroy</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceDettach</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceFree</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceGetName</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceGetParent</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceGetXMLDesc</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceListCaps</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceLookupByName</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceNumOfCaps</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceReAttach</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceRef</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeDeviceReset</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeGetCellsFreeMemory</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeGetFreeMemory</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeGetInfo</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeGetSecurityModel </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeListDevices</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virNodeNumOfDevices</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretDefineXML</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretFree   </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretGetConnect</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretGetUUID</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretGetUUIDString  </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretGetUsageID</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretGetUsageType</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretGetValue</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretGetXMLDesc</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretLookupByUUID</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretLookupByUUIDString</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretLookupByUsage</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretRef</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretSetValue</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virSecretUndefine</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolBuild</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolCreate</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolCreateXML </td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolDefineXML</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolDelete</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolDestroy</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolFree</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolGetAutostart</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolGetConnect</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolGetInfo</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolGetName</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolGetUUID</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolGetUUIDString</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolGetXMLDesc</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolIsActive</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolIsPersistent</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolListVolumes</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolLookupByName</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolLookupByUUID</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolLookupByUUIDString</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolLookupByVolume</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolNumOfVolumes</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolRef</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolRefresh</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolSetAutostart</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStoragePoolUndefine</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolCreateXML</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolCreateXMLFrom</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolDelete</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolFree</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolGetConnect  </td><td>Yes</td><td>function</td><td>No</td><td> </td><td>Maybe</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolGetInfo</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolGetKey</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolGetName</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolGetPath</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolGetXMLDesc </td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolLookupByKey</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolLookupByName</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolLookupByPath</td><td>Yes</td><td>function</td><td>Yes</td><td> </td><td>Yes</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolRef</td><td>Yes</td><td>function</td><td>No</td><td> </td><td>No</td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStorageVolWipe</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamAbort  </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamEventAddCallback</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamEventCallback</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamEventRemoveCallback</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamEventUpdateCallback</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamFinish </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamFree   </td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamNew</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamRecv</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamRecvAll</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamRef</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamSend</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamSendAll</td><td>No</td><td>function</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamSinkFunc</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virStreamSourceFunc</td><td>No</td><td>delegate</td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td></tr> | ||||
|       <tr><td>virGetLastError</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectSetErrorFunc</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virConnSetErrorFunc</td><td>Yes</td><td>function</td><td>Yes</td><td>virConnectSetErrorFunc</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|       <tr><td>virErrorFunc</td><td>Yes</td><td>delegate</td><td>Yes</td><td>virConnectSetErrorFunc, virDomainInfos</td><td>Yes</td><td>Yes</td><td>Yes</td><td>Yes</td></tr> | ||||
|     </table> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,48 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Deployment</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="packages">Pre-packaged releases</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The libvirt API is now available in all major Linux distributions, | ||||
|       so the simplest deployment approach is to use your distributions' | ||||
|       package management software to install the <code>libvirt</code> | ||||
|       module. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="tarball">Self-built releases</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       libvirt uses GNU autotools for its build system, so deployment | ||||
|       follows the usual process of <code>configure; make ; make install</code> | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|  | ||||
|       # ./configure --prefix=$HOME/usr | ||||
|       # make | ||||
|       # make install | ||||
|     </pre> | ||||
|  | ||||
|     <h2><a name="git">Built from GIT</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       When building from GIT it is necessary to generate the autotools | ||||
|       support files. This requires having <code>autoconf</code>, | ||||
|       <code>automake</code>, <code>libtool</code> and <code>intltool</code> | ||||
|       installed. The process can be automated with the <code>autogen.sh</code> | ||||
|       script. | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|  | ||||
|       # ./autogen.sh --prefix=$HOME/usr | ||||
|       # make | ||||
|       # make install | ||||
|     </pre> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,55 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>libvirt Application Development Guide</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <p> | ||||
|       The guide is both a learning tool for developing with libvirt and an | ||||
|       API reference document. It is a work in progress, composed by a | ||||
|       professional author from contributions written by members of the | ||||
|       libvirt team. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Contributions to the guide are <b>VERY</b> welcome. If you'd like to get | ||||
|       your name on this and demonstrate your virtualisation prowess, a solid | ||||
|       contribution to the content here will do it. :) | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="online">Browsable online</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li><a href="http://libvirt.org/guide/html/"> | ||||
|         HTML format using multiple pages</a></li> | ||||
|       <li><a href="http://libvirt.org/guide/html-single/"> | ||||
|         HTML format using one big page</a></li> | ||||
|       <li><a href="http://libvirt.org/guide/pdf/Application_Development_Guide.pdf"> | ||||
|         PDF format</a></li> | ||||
|       <li><a href="http://libvirt.org/guide/libvirt-0.7.5-Application_Development_Guide-en-US.epub"> | ||||
|         ePub format</a></li> | ||||
|       <li><a href="http://libvirt.org/guide/txt/Application_Development_Guide.txt"> | ||||
|         Plain text format</a></li> | ||||
|       <li><a href="http://libvirt.org/guide/libvirt-Application_Development_Guide-0.7.5-web-en-US-1-9.el5.src.rpm"> | ||||
|         Source RPM format</a></li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="git">GIT source repository</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The source is in a git repository: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       git clone git://libvirt.org/libvirt-appdev-guide.git</pre> | ||||
|  | ||||
|     <p> | ||||
|       Browsable here: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       <a href="http://libvirt.org/git/?p=libvirt-appdev-guide.git;a=summary">http://libvirt.org/git/?p=libvirt-appdev-guide.git;a=summary</a></pre> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
							
								
								
									
										4
									
								
								docs/devhelp/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								docs/devhelp/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +0,0 @@ | ||||
| Makefile | ||||
| Makefile.in | ||||
| libvirt.devhelp | ||||
| *.html | ||||
| @@ -1,132 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" | ||||
| 		xmlns="http://www.devhelp.net/book" | ||||
| 		xmlns:exsl="http://exslt.org/common" | ||||
| 		xmlns:str="http://exslt.org/strings" | ||||
| 		extension-element-prefixes="exsl str" | ||||
| 		exclude-result-prefixes="exsl str"> | ||||
|   <!-- The stylesheet for the html pages --> | ||||
|   <xsl:import href="html.xsl"/> | ||||
|  | ||||
|   <xsl:output method="xml" encoding="UTF-8" indent="yes"/> | ||||
|  | ||||
|   <!-- Build keys for all symbols --> | ||||
|   <xsl:key name="symbols" match="/api/symbols/*" use="@name"/> | ||||
|  | ||||
|   <xsl:template match="/"> | ||||
|     <xsl:document xmlns="http://www.devhelp.net/book" href="libvirt.devhelp" | ||||
|                   method="xml" encoding="UTF-8" indent="yes"> | ||||
|       <xsl:apply-templates/> | ||||
|     </xsl:document> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template match="/api"> | ||||
|     <book title="{@name} Reference Manual" link="index.html" author="" name="{@name}"> | ||||
|       <xsl:apply-templates select="files"/> | ||||
|       <xsl:apply-templates select="symbols"/> | ||||
|     </book> | ||||
|     <xsl:call-template name="generate_index"/> | ||||
|     <xsl:call-template name="generate_general"/> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/files"> | ||||
|     <chapters> | ||||
|       <sub name="API" link="general.html"> | ||||
|         <xsl:apply-templates select="file"/> | ||||
|       </sub> | ||||
|     </chapters> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/files/file"> | ||||
|     <xsl:variable name="module" select="@name"/> | ||||
|     <xsl:variable name="prev" select="string(preceding-sibling::file[position()=1]/@name)"/> | ||||
|     <xsl:variable name="next" select="string(following-sibling::file[position()=1]/@name)"/> | ||||
|     <sub name="{@name}" link="libvirt-{@name}.html"/> | ||||
|     <xsl:document xmlns="" href="libvirt-{@name}.html" method="xml" indent="yes" encoding="UTF-8"> | ||||
|       <html> | ||||
|         <head> | ||||
| 	  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||||
| 	  <title><xsl:value-of select="concat(@name, ': ', summary)"/></title> | ||||
| 	  <meta name="generator" content="Libvirt devhelp stylesheet"/> | ||||
| 	  <link rel="start" href="index.html" title="libvirt Reference Manual"/> | ||||
| 	  <link rel="up" href="general.html" title="API"/> | ||||
| 	  <link rel="stylesheet" href="style.css" type="text/css"/> | ||||
| 	  <link rel="chapter" href="general.html" title="API"/> | ||||
|         </head> | ||||
| 	<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||||
|  | ||||
|           <table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"> | ||||
| 	    <tr valign="middle"> | ||||
| 	      <xsl:if test="$prev != ''"> | ||||
| 		<td><a accesskey="p" href="libvirt-{$prev}.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"/></a></td> | ||||
| 	      </xsl:if> | ||||
|               <td><a accesskey="u" href="general.html"><img src="up.png" width="24" height="24" border="0" alt="Up"/></a></td> | ||||
|               <td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"/></a></td> | ||||
| 	      <xsl:if test="$next != ''"> | ||||
| 		<td><a accesskey="n" href="libvirt-{$next}.html"><img src="right.png" width="24" height="24" border="0" alt="Next"/></a></td> | ||||
| 	      </xsl:if> | ||||
|               <th width="100%" align="center">libvirt Reference Manual</th> | ||||
|             </tr> | ||||
| 	  </table> | ||||
| 	  <h2><span class="refentrytitle"><xsl:value-of select="@name"/></span></h2> | ||||
| 	  <p><xsl:value-of select="@name"/> - <xsl:value-of select="summary"/></p> | ||||
| 	  <p><xsl:value-of select="description"/></p> | ||||
| 	  <xsl:if test="deprecated"> | ||||
| 	    <p> WARNING: this module is deprecated !</p> | ||||
| 	  </xsl:if> | ||||
| 	  <p>Author(s): <xsl:value-of select="author"/></p> | ||||
| 	  <div class="refsynopsisdiv"> | ||||
| 	  <h2>Synopsis</h2> | ||||
| 	  <pre class="synopsis"> | ||||
| 	    <xsl:apply-templates mode="synopsis" select="exports"/> | ||||
| 	  </pre> | ||||
| 	  </div> | ||||
| 	  <div class="refsect1" lang="en"> | ||||
| 	  <h2>Description</h2> | ||||
| 	  </div> | ||||
| 	  <div class="refsect1" lang="en"> | ||||
| 	  <h2>Details</h2> | ||||
| 	  <div class="refsect2" lang="en"> | ||||
| 	    <xsl:apply-templates mode="details" select="/api/symbols/macro[@file=$module]"/> | ||||
| 	    <xsl:apply-templates mode="details" select="/api/symbols/typedef[@file=$module] | /api/symbols/struct[@file=$module]"/> | ||||
| 	    <xsl:apply-templates mode="details" select="/api/symbols/functype[@file=$module]"/> | ||||
| 	    <xsl:apply-templates mode="details" select="/api/symbols/variable[@file=$module]"/> | ||||
| 	    <xsl:apply-templates mode="details" select="/api/symbols/function[@file=$module]"/> | ||||
| 	  </div> | ||||
| 	  </div> | ||||
| 	</body> | ||||
|       </html> | ||||
|     </xsl:document> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols"> | ||||
|     <functions> | ||||
|       <xsl:apply-templates select="macro"/> | ||||
|       <xsl:apply-templates select="enum"/> | ||||
|       <xsl:apply-templates select="typedef"/> | ||||
|       <xsl:apply-templates select="struct"/> | ||||
|       <xsl:apply-templates select="functype"/> | ||||
|       <xsl:apply-templates select="variable"/> | ||||
|       <xsl:apply-templates select="function"/> | ||||
|     </functions> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols/functype"> | ||||
|     <function name="{@name}" link="libvirt-{@file}.html#{@name}"/> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols/function"> | ||||
|     <function name="{@name} ()" link="libvirt-{@file}.html#{@name}"/> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols/typedef"> | ||||
|     <function name="{@name}" link="libvirt-{@file}.html#{@name}"/> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols/enum"> | ||||
|     <function name="{@name}" link="libvirt-{@file}.html#{@name}"/> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols/struct"> | ||||
|     <function name="{@name}" link="libvirt-{@file}.html#{@name}"/> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols/macro"> | ||||
|     <function name="{@name}" link="libvirt-{@file}.html#{@name}"/> | ||||
|   </xsl:template> | ||||
|   <xsl:template match="/api/symbols/variable"> | ||||
|     <function name="{@name}" link="libvirt-{@file}.html#{@name}"/> | ||||
|   </xsl:template> | ||||
|  | ||||
| </xsl:stylesheet> | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 654 B | 
| @@ -1,577 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" | ||||
| 		xmlns:exsl="http://exslt.org/common" | ||||
| 		xmlns:str="http://exslt.org/strings" | ||||
| 		extension-element-prefixes="exsl str" | ||||
| 		exclude-result-prefixes="exsl str"> | ||||
|   <xsl:output method="xml" encoding="UTF-8" indent="yes"/> | ||||
|  | ||||
|   <!-- This is convoluted but needed to force the current document to | ||||
|        be the API one and not the result tree from the tokenize() result, | ||||
|        because the keys are only defined on the main document --> | ||||
|   <xsl:template mode="dumptoken" match='*'> | ||||
|     <xsl:param name="token"/> | ||||
|     <xsl:variable name="ref" select="key('symbols', $token)"/> | ||||
|     <xsl:choose> | ||||
|       <xsl:when test="$ref"> | ||||
|         <a href="libvirt-{$ref/@file}.html#{$ref/@name}"><xsl:value-of select="$token"/></a> | ||||
|       </xsl:when> | ||||
|       <xsl:otherwise> | ||||
|         <xsl:value-of select="$token"/> | ||||
|       </xsl:otherwise> | ||||
|     </xsl:choose> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <!-- dumps a string, making cross-reference links --> | ||||
|   <xsl:template name="dumptext"> | ||||
|     <xsl:param name="text"/> | ||||
|     <xsl:variable name="ctxt" select='.'/> | ||||
|     <!-- <xsl:value-of select="$text"/> --> | ||||
|     <xsl:for-each select="str:tokenize($text, ' 	')"> | ||||
|       <xsl:apply-templates select="$ctxt" mode='dumptoken'> | ||||
|         <xsl:with-param name="token" select="string(.)"/> | ||||
|       </xsl:apply-templates> | ||||
|       <xsl:if test="position() != last()"> | ||||
|         <xsl:text> </xsl:text> | ||||
|       </xsl:if> | ||||
|     </xsl:for-each> | ||||
|   </xsl:template> | ||||
|  | ||||
| <!-- | ||||
|  | ||||
|              The following builds the Synopsis section | ||||
|  | ||||
| --> | ||||
|   <xsl:template mode="synopsis" match="function"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <xsl:variable name="nlen" select="string-length($name)"/> | ||||
|     <xsl:variable name="tlen" select="string-length(return/@type)"/> | ||||
|     <xsl:variable name="blen" select="(($nlen + 8) - (($nlen + 8) mod 8)) + (($tlen + 8) - (($tlen + 8) mod 8))"/> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="return/@type"/> | ||||
|     </xsl:call-template> | ||||
|     <xsl:text>	</xsl:text> | ||||
|     <a href="#{@name}"><xsl:value-of select="@name"/></a> | ||||
|     <xsl:if test="$blen - 40 < -8"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:if test="$blen - 40 < 0"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:text>	(</xsl:text> | ||||
|     <xsl:if test="not(arg)"> | ||||
|       <xsl:text>void</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:for-each select="arg"> | ||||
|       <xsl:call-template name="dumptext"> | ||||
|         <xsl:with-param name="text" select="@type"/> | ||||
|       </xsl:call-template> | ||||
|       <xsl:text> </xsl:text> | ||||
|       <xsl:value-of select="@name"/> | ||||
|       <xsl:if test="position() != last()"> | ||||
|         <xsl:text>, </xsl:text><br/> | ||||
| 	<xsl:if test="$blen - 40 > 8"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:if test="$blen - 40 > 0"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:text>					 </xsl:text> | ||||
|       </xsl:if> | ||||
|     </xsl:for-each> | ||||
|     <xsl:text>);</xsl:text> | ||||
|     <xsl:text> | ||||
| </xsl:text> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="synopsis" match="functype"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <xsl:variable name="nlen" select="string-length($name)"/> | ||||
|     <xsl:variable name="tlen" select="string-length(return/@type)"/> | ||||
|     <xsl:variable name="blen" select="(($nlen + 8) - (($nlen + 8) mod 8)) + (($tlen + 8) - (($tlen + 8) mod 8))"/> | ||||
|     <xsl:text>typedef </xsl:text> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="return/@type"/> | ||||
|     </xsl:call-template> | ||||
|     <xsl:text> </xsl:text> | ||||
|     <a href="#{@name}"><xsl:value-of select="@name"/></a> | ||||
|     <xsl:if test="$blen - 40 < -8"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:if test="$blen - 40 < 0"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:text>	(</xsl:text> | ||||
|     <xsl:if test="not(arg)"> | ||||
|       <xsl:text>void</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:for-each select="arg"> | ||||
|       <xsl:call-template name="dumptext"> | ||||
|         <xsl:with-param name="text" select="@type"/> | ||||
|       </xsl:call-template> | ||||
|       <xsl:text> </xsl:text> | ||||
|       <xsl:value-of select="@name"/> | ||||
|       <xsl:if test="position() != last()"> | ||||
|         <xsl:text>, </xsl:text><br/> | ||||
| 	<xsl:if test="$blen - 40 > 8"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:if test="$blen - 40 > 0"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:text>					 </xsl:text> | ||||
|       </xsl:if> | ||||
|     </xsl:for-each> | ||||
|     <xsl:text>);</xsl:text> | ||||
|     <xsl:text> | ||||
| </xsl:text> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="synopsis" match="exports[@type='function']"> | ||||
|     <xsl:variable name="def" select="key('symbols',@symbol)"/> | ||||
|     <xsl:apply-templates mode="synopsis" select="$def"/> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="synopsis" match="exports[@type='typedef']"> | ||||
|     <xsl:text>typedef </xsl:text> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="string(key('symbols',@symbol)/@type)"/> | ||||
|     </xsl:call-template> | ||||
|     <xsl:text> </xsl:text> | ||||
|     <a href="#{@symbol}"><xsl:value-of select="@symbol"/></a> | ||||
|     <xsl:text>; | ||||
| </xsl:text> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="synopsis" match="exports[@type='macro']"> | ||||
|     <xsl:variable name="def" select="key('symbols',@symbol)"/> | ||||
|     <xsl:text>#define </xsl:text> | ||||
|     <a href="#{@symbol}"><xsl:value-of select="@symbol"/></a> | ||||
|     <xsl:if test="$def/arg"> | ||||
|       <xsl:text>(</xsl:text> | ||||
|       <xsl:for-each select="$def/arg"> | ||||
|         <xsl:value-of select="@name"/> | ||||
| 	<xsl:if test="position() != last()"> | ||||
| 	  <xsl:text>, </xsl:text> | ||||
| 	</xsl:if> | ||||
|       </xsl:for-each> | ||||
|       <xsl:text>)</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:text>; | ||||
| </xsl:text> | ||||
|   </xsl:template> | ||||
|   <xsl:template mode="synopsis" match="exports[@type='enum']"> | ||||
|   </xsl:template> | ||||
|   <xsl:template mode="synopsis" match="exports[@type='struct']"> | ||||
|   </xsl:template> | ||||
|  | ||||
| <!-- | ||||
|  | ||||
|              The following builds the Details section | ||||
|  | ||||
| --> | ||||
|   <xsl:template mode="details" match="struct"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <div class="refsect2" lang="en"> | ||||
|     <h3><a name="{$name}">Structure </a><xsl:value-of select="$name"/></h3> | ||||
|     <pre class="programlisting"> | ||||
|     <xsl:value-of select="@type"/><xsl:text> { | ||||
| </xsl:text> | ||||
|     <xsl:if test="not(field)"> | ||||
|       <xsl:text>The content of this structure is not made public by the API. | ||||
| </xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:for-each select="field"> | ||||
|         <xsl:text>    </xsl:text> | ||||
| 	<xsl:call-template name="dumptext"> | ||||
| 	  <xsl:with-param name="text" select="@type"/> | ||||
| 	</xsl:call-template> | ||||
| 	<xsl:text>	</xsl:text> | ||||
| 	<xsl:value-of select="@name"/> | ||||
| 	<xsl:if test="@info != ''"> | ||||
| 	  <xsl:text>	: </xsl:text> | ||||
| 	  <xsl:call-template name="dumptext"> | ||||
| 	    <xsl:with-param name="text" select="substring(@info, 1, 70)"/> | ||||
| 	  </xsl:call-template> | ||||
| 	</xsl:if> | ||||
| 	<xsl:text> | ||||
| </xsl:text> | ||||
|     </xsl:for-each> | ||||
|     <xsl:text>} </xsl:text> | ||||
|     <xsl:value-of select="$name"/> | ||||
|     <xsl:text>; | ||||
| </xsl:text> | ||||
|     </pre> | ||||
|     <p> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="info"/> | ||||
|     </xsl:call-template> | ||||
|     </p><xsl:text> | ||||
| </xsl:text> | ||||
|     </div><hr/> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="details" match="typedef[@type != 'enum']"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <div class="refsect2" lang="en"> | ||||
|     <h3><a name="{$name}">Typedef </a><xsl:value-of select="$name"/></h3> | ||||
|     <pre class="programlisting"> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="string(@type)"/> | ||||
|     </xsl:call-template> | ||||
|     <xsl:text> </xsl:text> | ||||
|     <xsl:value-of select="$name"/> | ||||
|     <xsl:text>; | ||||
| </xsl:text> | ||||
|     </pre> | ||||
|     <p> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="info"/> | ||||
|     </xsl:call-template> | ||||
|     </p><xsl:text> | ||||
| </xsl:text> | ||||
|     </div><hr/> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="details" match="variable"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <div class="refsect2" lang="en"> | ||||
|     <h3><a name="{$name}">Variable </a><xsl:value-of select="$name"/></h3> | ||||
|     <pre class="programlisting"> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="string(@type)"/> | ||||
|     </xsl:call-template> | ||||
|     <xsl:text> </xsl:text> | ||||
|     <xsl:value-of select="$name"/> | ||||
|     <xsl:text>; | ||||
| </xsl:text> | ||||
|     </pre> | ||||
|     <p> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="info"/> | ||||
|     </xsl:call-template> | ||||
|     </p><xsl:text> | ||||
| </xsl:text> | ||||
|     </div><hr/> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="details" match="typedef[@type = 'enum']"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <div class="refsect2" lang="en"> | ||||
|     <h3><a name="{$name}">Enum </a><xsl:value-of select="$name"/></h3> | ||||
|     <pre class="programlisting"> | ||||
|     <xsl:text>enum </xsl:text> | ||||
|     <a href="#{$name}"><xsl:value-of select="$name"/></a> | ||||
|     <xsl:text> { | ||||
| </xsl:text> | ||||
|     <xsl:for-each select="/api/symbols/enum[@type=$name]"> | ||||
|       <xsl:sort select="@value" data-type="number" order="ascending"/> | ||||
|       <xsl:text>    </xsl:text> | ||||
|       <a name="{@name}"><xsl:value-of select="@name"/></a> | ||||
|       <xsl:if test="@value"> | ||||
|         <xsl:text> = </xsl:text> | ||||
| 	<xsl:value-of select="@value"/> | ||||
|       </xsl:if> | ||||
|       <xsl:if test="@info"> | ||||
|         <xsl:text> /* </xsl:text> | ||||
| 	<xsl:value-of select="@info"/> | ||||
|         <xsl:text> */</xsl:text> | ||||
|       </xsl:if> | ||||
|       <xsl:text> | ||||
| </xsl:text> | ||||
|     </xsl:for-each> | ||||
|     <xsl:text>}; | ||||
| </xsl:text> | ||||
|     </pre> | ||||
|     <p> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="info"/> | ||||
|     </xsl:call-template> | ||||
|     </p><xsl:text> | ||||
| </xsl:text> | ||||
|     </div><hr/> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="details" match="macro"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <div class="refsect2" lang="en"> | ||||
|     <h3><a name="{$name}">Macro </a><xsl:value-of select="$name"/></h3> | ||||
|     <pre class="programlisting"> | ||||
|     <xsl:text>#define </xsl:text> | ||||
|     <a href="#{$name}"><xsl:value-of select="$name"/></a> | ||||
|     <xsl:if test="arg"> | ||||
|       <xsl:text>(</xsl:text> | ||||
|       <xsl:for-each select="arg"> | ||||
|         <xsl:value-of select="@name"/> | ||||
| 	<xsl:if test="position() != last()"> | ||||
| 	  <xsl:text>, </xsl:text> | ||||
| 	</xsl:if> | ||||
|       </xsl:for-each> | ||||
|       <xsl:text>)</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:text>; | ||||
| </xsl:text> | ||||
|     </pre> | ||||
|     <p> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="info"/> | ||||
|     </xsl:call-template> | ||||
|     </p> | ||||
|     <xsl:if test="arg"> | ||||
|       <div class="variablelist"><table border="0"><col align="left"/><tbody> | ||||
|       <xsl:for-each select="arg"> | ||||
|         <tr> | ||||
|           <td><span class="term"><i><tt><xsl:value-of select="@name"/></tt></i>:</span></td> | ||||
| 	  <td> | ||||
| 	    <xsl:call-template name="dumptext"> | ||||
| 	      <xsl:with-param name="text" select="@info"/> | ||||
| 	    </xsl:call-template> | ||||
| 	  </td> | ||||
|         </tr> | ||||
|       </xsl:for-each> | ||||
|       </tbody></table></div> | ||||
|     </xsl:if> | ||||
|     <xsl:text> | ||||
| </xsl:text> | ||||
|     </div><hr/> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="details" match="function"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <xsl:variable name="nlen" select="string-length($name)"/> | ||||
|     <xsl:variable name="tlen" select="string-length(return/@type)"/> | ||||
|     <xsl:variable name="blen" select="(($nlen + 8) - (($nlen + 8) mod 8)) + (($tlen + 8) - (($tlen + 8) mod 8))"/> | ||||
|     <div class="refsect2" lang="en"> | ||||
|     <h3><a name="{$name}"></a><xsl:value-of select="$name"/> ()</h3> | ||||
|     <pre class="programlisting"> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="return/@type"/> | ||||
|     </xsl:call-template> | ||||
|     <xsl:text>	</xsl:text> | ||||
|     <xsl:value-of select="@name"/> | ||||
|     <xsl:if test="$blen - 40 < -8"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:if test="$blen - 40 < 0"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:text>	(</xsl:text> | ||||
|     <xsl:if test="not(arg)"> | ||||
|       <xsl:text>void</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:for-each select="arg"> | ||||
|       <xsl:call-template name="dumptext"> | ||||
|         <xsl:with-param name="text" select="@type"/> | ||||
|       </xsl:call-template> | ||||
|       <xsl:text> </xsl:text> | ||||
|       <xsl:value-of select="@name"/> | ||||
|       <xsl:if test="position() != last()"> | ||||
|         <xsl:text>, </xsl:text><br/> | ||||
| 	<xsl:if test="$blen - 40 > 8"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:if test="$blen - 40 > 0"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:text>					 </xsl:text> | ||||
|       </xsl:if> | ||||
|     </xsl:for-each> | ||||
|     <xsl:text>)</xsl:text><br/> | ||||
|     <xsl:text> | ||||
| </xsl:text> | ||||
|     </pre> | ||||
|     <p> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="info"/> | ||||
|     </xsl:call-template> | ||||
|     </p><xsl:text> | ||||
| </xsl:text> | ||||
|     <xsl:if test="arg | return/@info"> | ||||
|       <div class="variablelist"><table border="0"><col align="left"/><tbody> | ||||
|       <xsl:for-each select="arg"> | ||||
|         <tr> | ||||
|           <td><span class="term"><i><tt><xsl:value-of select="@name"/></tt></i>:</span></td> | ||||
| 	  <td> | ||||
| 	    <xsl:call-template name="dumptext"> | ||||
| 	      <xsl:with-param name="text" select="@info"/> | ||||
| 	    </xsl:call-template> | ||||
| 	  </td> | ||||
|         </tr> | ||||
|       </xsl:for-each> | ||||
|       <xsl:if test="return/@info"> | ||||
|         <tr> | ||||
|           <td><span class="term"><i><tt>Returns</tt></i>:</span></td> | ||||
| 	  <td> | ||||
| 	    <xsl:call-template name="dumptext"> | ||||
| 	      <xsl:with-param name="text" select="return/@info"/> | ||||
| 	    </xsl:call-template> | ||||
| 	  </td> | ||||
|         </tr> | ||||
|       </xsl:if> | ||||
|       </tbody></table></div> | ||||
|     </xsl:if> | ||||
|     </div><hr/> | ||||
|   </xsl:template> | ||||
|  | ||||
|   <xsl:template mode="details" match="functype"> | ||||
|     <xsl:variable name="name" select="string(@name)"/> | ||||
|     <xsl:variable name="nlen" select="string-length($name)"/> | ||||
|     <xsl:variable name="tlen" select="string-length(return/@type)"/> | ||||
|     <xsl:variable name="blen" select="(($nlen + 8) - (($nlen + 8) mod 8)) + (($tlen + 8) - (($tlen + 8) mod 8))"/> | ||||
|     <div class="refsect2" lang="en"> | ||||
|     <h3><a name="{$name}"></a>Function type <xsl:value-of select="$name"/> </h3> | ||||
|     <pre class="programlisting"> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="return/@type"/> | ||||
|     </xsl:call-template> | ||||
|     <xsl:text>	</xsl:text> | ||||
|     <xsl:value-of select="@name"/> | ||||
|     <xsl:if test="$blen - 40 < -8"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:if test="$blen - 40 < 0"> | ||||
|       <xsl:text>	</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:text>	(</xsl:text> | ||||
|     <xsl:if test="not(arg)"> | ||||
|       <xsl:text>void</xsl:text> | ||||
|     </xsl:if> | ||||
|     <xsl:for-each select="arg"> | ||||
|       <xsl:call-template name="dumptext"> | ||||
|         <xsl:with-param name="text" select="@type"/> | ||||
|       </xsl:call-template> | ||||
|       <xsl:text> </xsl:text> | ||||
|       <xsl:value-of select="@name"/> | ||||
|       <xsl:if test="position() != last()"> | ||||
|         <xsl:text>, </xsl:text><br/> | ||||
| 	<xsl:if test="$blen - 40 > 8"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:if test="$blen - 40 > 0"> | ||||
| 	  <xsl:text>	</xsl:text> | ||||
| 	</xsl:if> | ||||
| 	<xsl:text>					 </xsl:text> | ||||
|       </xsl:if> | ||||
|     </xsl:for-each> | ||||
|     <xsl:text>)</xsl:text><br/> | ||||
|     <xsl:text> | ||||
| </xsl:text> | ||||
|     </pre> | ||||
|     <p> | ||||
|     <xsl:call-template name="dumptext"> | ||||
|       <xsl:with-param name="text" select="info"/> | ||||
|     </xsl:call-template> | ||||
|     </p><xsl:text> | ||||
| </xsl:text> | ||||
|     <xsl:if test="arg | return/@info"> | ||||
|       <div class="variablelist"><table border="0"><col align="left"/><tbody> | ||||
|       <xsl:for-each select="arg"> | ||||
|         <tr> | ||||
|           <td><span class="term"><i><tt><xsl:value-of select="@name"/></tt></i>:</span></td> | ||||
| 	  <td> | ||||
| 	    <xsl:call-template name="dumptext"> | ||||
| 	      <xsl:with-param name="text" select="@info"/> | ||||
| 	    </xsl:call-template> | ||||
| 	  </td> | ||||
|         </tr> | ||||
|       </xsl:for-each> | ||||
|       <xsl:if test="return/@info"> | ||||
|         <tr> | ||||
|           <td><span class="term"><i><tt>Returns</tt></i>:</span></td> | ||||
| 	  <td> | ||||
| 	    <xsl:call-template name="dumptext"> | ||||
| 	      <xsl:with-param name="text" select="return/@info"/> | ||||
| 	    </xsl:call-template> | ||||
| 	  </td> | ||||
|         </tr> | ||||
|       </xsl:if> | ||||
|       </tbody></table></div> | ||||
|     </xsl:if> | ||||
|     </div><hr/> | ||||
|   </xsl:template> | ||||
|  | ||||
| <!-- | ||||
|  | ||||
|              The following builds the general.html page | ||||
|  | ||||
| --> | ||||
|   <xsl:template name="generate_general"> | ||||
|     <xsl:variable name="next" select="string(/api/files/file[position()=1]/@name)"/> | ||||
|     <xsl:document xmlns="" href="general.html" method="xml" indent="yes" encoding="UTF-8"> | ||||
|       <html> | ||||
|         <head> | ||||
| 	  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||||
| 	  <title><xsl:value-of select="concat(@name, ': ', summary)"/></title> | ||||
| 	  <meta name="generator" content="Libvirt devhelp stylesheet"/> | ||||
| 	  <link rel="start" href="index.html" title="libvirt Reference Manual"/> | ||||
| 	  <link rel="up" href="index.html" title="libvirt Reference Manual"/> | ||||
| 	  <link rel="stylesheet" href="style.css" type="text/css"/> | ||||
| 	  <link rel="chapter" href="index.html" title="libvirt Reference Manual"/> | ||||
|         </head> | ||||
| 	<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||||
|  | ||||
|           <table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"> | ||||
| 	    <tr valign="middle"> | ||||
|               <td><a accesskey="u" href="index.html"><img src="up.png" width="24" height="24" border="0" alt="Up"/></a></td> | ||||
|               <td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"/></a></td> | ||||
| 	      <xsl:if test="$next != ''"> | ||||
| 		<td><a accesskey="n" href="libvirt-{$next}.html"><img src="right.png" width="24" height="24" border="0" alt="Next"/></a></td> | ||||
| 	      </xsl:if> | ||||
|               <th width="100%" align="center">libvirt Reference Manual</th> | ||||
|             </tr> | ||||
| 	  </table> | ||||
| 	  <h2><span class="refentrytitle">libvirt API Modules</span></h2> | ||||
| 	  <p> | ||||
| 	  <xsl:for-each select="/api/files/file"> | ||||
| 	    <a href="libvirt-{@name}.html"><xsl:value-of select="@name"/></a> - <xsl:value-of select="summary"/><br/> | ||||
| 	  </xsl:for-each> | ||||
| 	  </p> | ||||
| 	</body> | ||||
|       </html> | ||||
|     </xsl:document> | ||||
|   </xsl:template> | ||||
|  | ||||
| <!-- | ||||
|  | ||||
|              The following builds the index.html page | ||||
|  | ||||
| --> | ||||
|   <xsl:template name="generate_index"> | ||||
|     <xsl:document xmlns="" href="index.html" method="xml" indent="yes" encoding="UTF-8"> | ||||
|       <html> | ||||
|         <head> | ||||
| 	  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||||
| 	  <title>libvirt Reference Manual</title> | ||||
| 	  <meta name="generator" content="Libvirt devhelp stylesheet"/> | ||||
| 	  <link rel="stylesheet" href="style.css" type="text/css"/> | ||||
|         </head> | ||||
| 	<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | ||||
|  | ||||
|           <table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"> | ||||
| 	    <tr valign="middle"> | ||||
|               <td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"/></a></td> | ||||
| 	      <td><a accesskey="n" href="general.html"><img src="right.png" width="24" height="24" border="0" alt="Next"/></a></td> | ||||
|               <th width="100%" align="center">libvirt Reference Manual</th> | ||||
|             </tr> | ||||
| 	  </table> | ||||
| 	  <h2><span class="refentrytitle">libvirt Reference Manual</span></h2> | ||||
| <p>Libvir is a C toolkit to interact with the virtualization capabilities of | ||||
| recent versions of Linux (and other OSes). It is free software available | ||||
| under the <a href="http://www.opensource.org/licenses/lgpl-license.html">GNU | ||||
| Lesser General Public License</a>. Virtualization of the Linux Operating | ||||
| System means the ability to run multiple instances of Operating Systems | ||||
| concurrently on a single hardware system where the basic resources are driven | ||||
| by a Linux instance. The library aim at providing long term stable C API | ||||
| initially for the <a href="http://www.cl.cam.ac.uk/Research/SRG/netos/xen/index.html">Xen | ||||
| paravirtualization</a> but should be able to integrate other virtualization | ||||
| mechanisms if needed.</p> | ||||
| <p> If you get lost searching for some specific API use, try | ||||
| <a href="http://libvirt.org/search.php">the online search | ||||
| engine</a> hosted on <a href="http://libvirt.org/">libvirt.org</a> | ||||
| it indexes the project page, the APIs as well as the mailing-list archives. </p> | ||||
| 	</body> | ||||
|       </html> | ||||
|     </xsl:document> | ||||
|   </xsl:template> | ||||
|  | ||||
| </xsl:stylesheet> | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 459 B | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 472 B | 
| @@ -1,66 +0,0 @@ | ||||
| .synopsis, .classsynopsis | ||||
| { | ||||
|   background: #eeeeee; | ||||
|   border: solid 1px #aaaaaa; | ||||
|   padding: 0.5em; | ||||
| } | ||||
| .programlisting | ||||
| { | ||||
|   background: #eeeeff; | ||||
|   border: solid 1px #aaaaff; | ||||
|   padding: 0.5em; | ||||
| } | ||||
| .variablelist | ||||
| { | ||||
|   padding: 4px; | ||||
|   margin-left: 3em; | ||||
| } | ||||
| .variablelist td:first-child | ||||
| { | ||||
|   vertical-align: top; | ||||
| } | ||||
| table.navigation | ||||
| { | ||||
|   background: #ffeeee; | ||||
|   border: solid 1px #ffaaaa; | ||||
|   margin-top: 0.5em; | ||||
|   margin-bottom: 0.5em; | ||||
| } | ||||
| .navigation a | ||||
| { | ||||
|   color: #770000; | ||||
| } | ||||
| .navigation a:visited | ||||
| { | ||||
|   color: #550000; | ||||
| } | ||||
| .navigation .title | ||||
| { | ||||
|   font-size: 200%; | ||||
| } | ||||
| div.refnamediv | ||||
| { | ||||
|   margin-top: 2em; | ||||
| } | ||||
| div.gallery-float | ||||
| { | ||||
|   float: left; | ||||
|   padding: 10px; | ||||
| } | ||||
| div.gallery-float img | ||||
| { | ||||
|   border-style: none; | ||||
| } | ||||
| div.gallery-spacer | ||||
| { | ||||
|   clear: both; | ||||
| } | ||||
| a | ||||
| { | ||||
|   text-decoration: none; | ||||
| } | ||||
| a:hover | ||||
| { | ||||
|   text-decoration: underline; | ||||
|   color: #FF0000; | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 406 B | 
| @@ -1,5 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Documentation</h1> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,99 +0,0 @@ | ||||
| <?xml version="1.0"?> | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Downloads</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <h2><a name="releases">Official Releases</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The latest versions of the libvirt C library can be downloaded from: | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li><a href="ftp://libvirt.org/libvirt/">libvirt.org FTP server</a></li> | ||||
|       <li><a href="http://libvirt.org/sources/">libvirt.org HTTP server</a></li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="hourly">Hourly development snapshots</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Once an hour, an automated snapshot is made from the git server | ||||
|       source tree. These snapshots should be usable, but we make no guarantees | ||||
|       about their stability: | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li><a href="ftp://libvirt.org/libvirt/libvirt-git-snapshot.tar.gz">libvirt.org FTP server</a></li> | ||||
|       <li><a href="http://libvirt.org/sources/libvirt-git-snapshot.tar.gz">libvirt.org HTTP server</a></li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="git">GIT source repository</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       Libvirt code source is now maintained in a <a href="http://git-scm.com/">git</a> | ||||
|       repository available on <a href="http://libvirt.org/git/">libvirt.org</a>: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       git clone git://libvirt.org/libvirt.git</pre> | ||||
|  | ||||
|     <p> | ||||
|       It can also be browsed at: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       <a href="http://libvirt.org/git/?p=libvirt.git;a=summary">http://libvirt.org/git/?p=libvirt.git;a=summary</a></pre> | ||||
|  | ||||
|     <br /> | ||||
|  | ||||
|     <h1>libvirt Application Development Guide</h1> | ||||
|  | ||||
|     <p> | ||||
|       The guide is both a learning tool for developing with libvirt and an | ||||
|       API reference document. It is a work in progress, composed by a | ||||
|       professional author from contributions written by members of the | ||||
|       libvirt team. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Contributions to the guide are <b>VERY</b> welcome. If you'd like to get | ||||
|       your name on this and demonstrate your virtualisation prowess, a solid | ||||
|       contribution to the content here will do it. :) | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="appdevpdf">Application Development Guide PDF</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       PDF download is available here: | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li><a href="http://libvirt.org/guide/pdf/Application_Development_Guide.pdf">libvirt App Dev Guide</a> (PDF)</li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="appdevgit">Application Development Guide source GIT repository</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The source is also in a git repository: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       git clone git://libvirt.org/libvirt-appdev-guide.git</pre> | ||||
|  | ||||
|     <p> | ||||
|       Browsable at: | ||||
|     </p> | ||||
|  | ||||
|     <pre> | ||||
|       <a href="http://libvirt.org/git/?p=libvirt-appdev-guide.git;a=summary">http://libvirt.org/git/?p=libvirt-appdev-guide.git;a=summary</a></pre> | ||||
|  | ||||
|     <br /> | ||||
|  | ||||
|     <p> | ||||
|       Once you've have obtained the libvirt source code, you can compile it | ||||
|       using the <a href="compiling.html">instructions here</a>. | ||||
|     </p> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,47 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Internal drivers</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <p> | ||||
|       The libvirt public API delegates its implementation to one or | ||||
|       more internal drivers, depending on the <a href="uri.html">connection URI</a> | ||||
|       passed when initializing the library. There is always a hypervisor driver | ||||
|       active, and if the libvirt daemon is available there will usually be a | ||||
|       network and storage driver active. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="hypervisor">Hypervisor drivers</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       The hypervisor drivers currently supported by libvirt are: | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li><strong><a href="drvlxc.html">LXC</a></strong> - Linux Containers</li> | ||||
|       <li><strong><a href="drvopenvz.html">OpenVZ</a></strong></li> | ||||
|       <li><strong><a href="drvqemu.html">QEMU</a></strong></li> | ||||
|       <li><strong><a href="drvtest.html">Test</a></strong> - Used for testing</li> | ||||
|       <li><strong><a href="drvuml.html">UML</a></strong> - User Mode Linux</li> | ||||
|       <li><strong><a href="drvvbox.html">VirtualBox</a></strong></li> | ||||
|       <li><strong><a href="drvesx.html">VMware ESX</a></strong></li> | ||||
|       <li><strong><a href="drvvmware.html">VMware Workstation/Player</a></strong></li> | ||||
|       <li><strong><a href="drvxen.html">Xen</a></strong></li> | ||||
|       <li><strong><a href="drvhyperv.html">Microsoft Hyper-V</a></strong></li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="stroage">Storage drivers</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li><strong><a href="storage.html#StorageBackendDir">Directory backend</a></strong></li> | ||||
|       <li><strong><a href="storage.html#StorageBackendFS">Local filesystem backend</a></strong></li> | ||||
|       <li><strong><a href="storage.html#StorageBackendNetFS">Network filesystem backend</a></strong></li> | ||||
|       <li><strong><a href="storage.html#StorageBackendLogical">Logical Volume Manager (LVM) backend</a></strong></li> | ||||
|       <li><strong><a href="storage.html#StorageBackendDisk">Disk backend</a></strong></li> | ||||
|       <li><strong><a href="storage.html#StorageBackendISCSI">iSCSI backend</a></strong></li> | ||||
|       <li><strong><a href="storage.html#StorageBackendSCSI">SCSI backend</a></strong></li> | ||||
|       <li><strong><a href="storage.html#StorageBackendMultipath">Multipath backend</a></strong></li> | ||||
|     </ul> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,811 +0,0 @@ | ||||
| <html><body> | ||||
|     <h1>VMware ESX hypervisor driver</h1> | ||||
|     <ul id="toc"></ul> | ||||
|     <p> | ||||
|         The libvirt VMware ESX driver can manage VMware ESX/ESXi 3.5/4.x and | ||||
|         VMware GSX 2.0, also called VMware Server 2.0, and possibly later | ||||
|         versions. <span class="since">Since 0.8.3</span> the driver can also | ||||
|         connect to a VMware vCenter 2.5/4.x (VPX). | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="project">Project Links</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         The <a href="http://www.vmware.com/">VMware ESX and GSX</a> | ||||
|         hypervisors | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="prereq">Deployment pre-requisites</a></h2> | ||||
|     <p> | ||||
|         None. Any out-of-the-box installation of VPX/ESX(i)/GSX should work. No | ||||
|         preparations are required on the server side, no libvirtd must be | ||||
|         installed on the ESX server. The driver uses version 2.5 of the remote, | ||||
|         SOAP based | ||||
|         <a href="http://www.vmware.com/support/developer/vc-sdk/visdk25pubs/ReferenceGuide/"> | ||||
|         VMware Virtual Infrastructure API</a> (VI API) to communicate with the | ||||
|         ESX server, like the VMware Virtual Infrastructure Client (VI client) | ||||
|         does. Since version 4.0 this API is called | ||||
|         <a href="http://www.vmware.com/support/developer/vc-sdk/visdk400pubs/ReferenceGuide/"> | ||||
|         VMware vSphere API</a>. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="uri">Connections to the VMware ESX driver</a></h2> | ||||
|     <p> | ||||
|         Some example remote connection URIs for the driver are: | ||||
|     </p> | ||||
| <pre> | ||||
| vpx://example-vcenter.com/dc1/srv1     (VPX over HTTPS, select ESX server 'srv1' in datacenter 'dc1') | ||||
| esx://example-esx.com                  (ESX over HTTPS) | ||||
| gsx://example-gsx.com                  (GSX over HTTPS) | ||||
| esx://example-esx.com/?transport=http  (ESX over HTTP) | ||||
| esx://example-esx.com/?no_verify=1     (ESX over HTTPS, but doesn't verify the server's SSL certificate) | ||||
| </pre> | ||||
|     <p> | ||||
|         <strong>Note</strong>: In contrast to other drivers, the ESX driver is | ||||
|         a client-side-only driver. It connects to the ESX server using HTTP(S). | ||||
|         Therefore, the <a href="remote.html">remote transport mechanism</a> | ||||
|         provided by the remote driver and libvirtd will not work, and you | ||||
|         cannot use URIs like <code>esx+ssh://example.com</code>. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h3><a name="uriformat">URI Format</a></h3> | ||||
|     <p> | ||||
|         URIs have this general form (<code>[...]</code> marks an optional part). | ||||
|     </p> | ||||
| <pre> | ||||
| type://[username@]hostname[:port]/[datacenter[/cluster]/server][?extraparameters] | ||||
| </pre> | ||||
|     <p> | ||||
|         The <code>type://</code> is either <code>esx://</code> or | ||||
|         <code>gsx://</code> or <code>vpx://</code> <span class="since">since 0.8.3</span>. | ||||
|         The driver selects the default port depending on the <code>type://</code>. | ||||
|         For <code>esx://</code> and <code>vpx://</code> the default HTTPS port | ||||
|         is 443, for <code>gsx://</code> it is 8333. | ||||
|         If the port parameter is given, it overrides the default port. | ||||
|     </p> | ||||
|     <p> | ||||
|         A <code>vpx://</code> connection is currently restricted to a single | ||||
|         ESX server. This might be relaxed in the future. The path part of the | ||||
|         URI is used to specify the datacenter and the ESX server in it. If the | ||||
|         ESX server is part of a cluster then the cluster has to be specified too. | ||||
|     </p> | ||||
|     <p> | ||||
|         An example: ESX server <code>example-esx.com</code> is managed by | ||||
|         vCenter <code>example-vcenter.com</code> and part of cluster | ||||
|         <code>cluster1</code>. This cluster is part of datacenter <code>dc1</code>. | ||||
|     </p> | ||||
| <pre> | ||||
| vpx://example-vcenter.com/dc1/cluster1/example-esx.com | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h4><a name="extraparams">Extra parameters</a></h4> | ||||
|     <p> | ||||
|         Extra parameters can be added to a URI as part of the query string | ||||
|         (the part following <code>?</code>). A single parameter is formed by a | ||||
|         <code>name=value</code> pair. Multiple parameters are separated by | ||||
|         <code>&</code>. | ||||
|     </p> | ||||
| <pre> | ||||
| ?<span style="color: #E50000">no_verify=1</span>&<span style="color: #00B200">auto_answer=1</span>&<span style="color: #0000E5">proxy=socks://example-proxy.com:23456</span> | ||||
| </pre> | ||||
|     <p> | ||||
|         The driver understands the extra parameters shown below. | ||||
|     </p> | ||||
|     <table class="top_table"> | ||||
|         <tr> | ||||
|             <th>Name</th> | ||||
|             <th>Values</th> | ||||
|             <th>Meaning</th> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>transport</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <code>http</code> or <code>https</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 Overrides the default HTTPS transport. For <code>esx://</code> | ||||
|                 and <code>vpx://</code> the default HTTP port is 80, for | ||||
|                 <code>gsx://</code> it is 8222. | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>vcenter</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 Hostname of a VMware vCenter or <code>*</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 In order to perform a migration the driver needs to know the | ||||
|                 VMware vCenter for the ESX server. If set to <code>*</code>, | ||||
|                 the driver connects to the vCenter known to the ESX server. | ||||
|                 This parameter in useful when connecting to an ESX server only. | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>no_verify</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <code>0</code> or <code>1</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 If set to 1, this disables libcurl client checks of the server's | ||||
|                 SSL certificate. The default value it 0. See the | ||||
|                 <a href="#certificates">Certificates for HTTPS</a> section for | ||||
|                 details. | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>auto_answer</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <code>0</code> or <code>1</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 If set to 1, the driver answers all | ||||
|                 <a href="#questions">questions</a> with the default answer. | ||||
|                 If set to 0, questions are reported as errors. The default | ||||
|                 value it 0. <span class="since">Since 0.7.5</span>. | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>proxy</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <code>[type://]hostname[:port]</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 Allows to specify a proxy for HTTP and HTTPS communication. | ||||
|                 <span class="since">Since 0.8.2</span>. | ||||
|                 The optional <code>type</code> part may be one of: | ||||
|                 <code>http</code>, <code>socks</code>, <code>socks4</code>, | ||||
|                 <code>socks4a</code> or <code>socks5</code>. The default is | ||||
|                 <code>http</code> and <code>socks</code> is synonymous for | ||||
|                 <code>socks5</code>. The optional <code>port</code> allows to | ||||
|                 override the default port 1080. | ||||
|             </td> | ||||
|         </tr> | ||||
|     </table> | ||||
|  | ||||
|  | ||||
|     <h3><a name="auth">Authentication</a></h3> | ||||
|     <p> | ||||
|         In order to perform any useful operation the driver needs to log into | ||||
|         the ESX server. Therefore, only <code>virConnectOpenAuth</code> can be | ||||
|         used to connect to an ESX server, <code>virConnectOpen</code> and | ||||
|         <code>virConnectOpenReadOnly</code> don't work. | ||||
|         To log into an ESX server or vCenter the driver will request | ||||
|         credentials using the callback passed to the | ||||
|         <code>virConnectOpenAuth</code> function. The driver passes the | ||||
|         hostname as challenge parameter to the callback. This enables the | ||||
|         callback to distinguish between requests for ESX server and vCenter. | ||||
|     </p> | ||||
|     <p> | ||||
|         <strong>Note</strong>: During the ongoing driver development, testing | ||||
|         is done using an unrestricted <code>root</code> account. Problems may | ||||
|         occur if you use a restricted account. Detailed testing with restricted | ||||
|         accounts has not been done yet. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h3><a name="certificates">Certificates for HTTPS</a></h3> | ||||
|     <p> | ||||
|         By default the ESX driver uses HTTPS to communicate with an ESX server. | ||||
|         Proper HTTPS communication requires correctly configured SSL | ||||
|         certificates. This certificates are different from the ones libvirt | ||||
|         uses for <a href="remote.html">secure communication over TLS</a> to a | ||||
|         libvirtd one a remote server. | ||||
|     </p> | ||||
|     <p> | ||||
|         By default the driver tries to verify the server's SSL certificate | ||||
|         using the CA certificate pool installed on your client computer. With | ||||
|         an out-of-the-box installed ESX server this won't work, because a newly | ||||
|         installed ESX server uses auto-generated self-signed certificates. | ||||
|         Those are singed by a CA certificate that is typically not known to your | ||||
|         client computer and libvirt will report an error like this one: | ||||
|     </p> | ||||
| <pre> | ||||
| error: internal error curl_easy_perform() returned an error: Peer certificate cannot be authenticated with known CA certificates (60) | ||||
| </pre> | ||||
|     <p> | ||||
|         Where are two ways to solve this problem: | ||||
|     </p> | ||||
|     <ul> | ||||
|         <li> | ||||
|             Use the <code>no_verify=1</code> <a href="#extraparams">extra parameter</a> | ||||
|             to disable server certificate verification. | ||||
|         </li> | ||||
|         <li> | ||||
|             Generate new SSL certificates signed by a CA known to your client | ||||
|             computer and replace the original ones on your ESX server. See the | ||||
|             section <i>Replace a Default Certificate with a CA-Signed Certificate</i> | ||||
|             in the <a href="http://www.vmware.com/pdf/vsphere4/r40/vsp_40_esx_server_config.pdf">ESX Configuration Guide</a> | ||||
|         </li> | ||||
|     </ul> | ||||
|  | ||||
|  | ||||
|     <h3><a name="connproblems">Connection problems</a></h3> | ||||
|     <p> | ||||
|         There are also other causes for connection problems than the | ||||
|         <a href="#certificates">HTTPS certificate</a> related ones. | ||||
|     </p> | ||||
|     <ul> | ||||
|         <li> | ||||
|             As stated before the ESX driver doesn't need the | ||||
|             <a href="remote.html">remote transport mechanism</a> | ||||
|             provided by the remote driver and libvirtd, nor does the ESX driver | ||||
|             support it. Therefore, using an URI including a transport in the | ||||
|             scheme won't work. Only <a href="#uriformat">URIs as described</a> | ||||
|             are supported by the ESX driver. Here's a collection of possible | ||||
|             error messages: | ||||
| <pre> | ||||
| $ virsh -c esx+tcp://example.com/ | ||||
| error: unable to connect to libvirtd at 'example.com': Connection refused | ||||
| </pre> | ||||
| <pre> | ||||
| $ virsh -c esx+tls://example.com/ | ||||
| error: Cannot access CA certificate '/etc/pki/CA/cacert.pem': No such file or directory | ||||
| </pre> | ||||
| <pre> | ||||
| $ virsh -c esx+ssh://example.com/ | ||||
| error: cannot recv data: ssh: connect to host example.com port 22: Connection refused | ||||
| </pre> | ||||
| <pre> | ||||
| $ virsh -c esx+ssh://example.com/ | ||||
| error: cannot recv data: Resource temporarily unavailable | ||||
| </pre> | ||||
|         </li> | ||||
|         <li> | ||||
|             <span class="since">Since 0.7.0</span> libvirt contains the ESX | ||||
|             driver. Earlier versions of libvirt will report a misleading error | ||||
|             about missing certificates when you try to connect to an ESX server. | ||||
| <pre> | ||||
| $ virsh -c esx://example.com/ | ||||
| error: Cannot access CA certificate '/etc/pki/CA/cacert.pem': No such file or directory | ||||
| </pre> | ||||
|             <p> | ||||
|                 Don't let this error message confuse you. Setting up certificates | ||||
|                 as described on the <a href="remote.html#Remote_certificates">remote transport mechanism</a> page | ||||
|                 does not help, as this is not a certificate related problem. | ||||
|             </p> | ||||
|             <p> | ||||
|                 To fix this problem you need to update your libvirt to 0.7.0 or newer. | ||||
|                 You may also see this error when you use a libvirt version that | ||||
|                 contains the ESX driver but you or your distro disabled the ESX | ||||
|                 driver during compilation. <span class="since">Since 0.8.3</span> | ||||
|                 the error message has been improved in this case: | ||||
|             </p> | ||||
| <pre> | ||||
| $ virsh -c esx://example.com/ | ||||
| error: invalid argument in libvirt was built without the 'esx' driver | ||||
| </pre> | ||||
|         </li> | ||||
|     </ul> | ||||
|  | ||||
|  | ||||
|     <h2><a name="questions">Questions blocking tasks</a></h2> | ||||
|     <p> | ||||
|         Some methods of the VI API start tasks, for example | ||||
|         <code>PowerOnVM_Task()</code>. Such tasks may be blocked by questions | ||||
|         if the ESX server detects an issue with the domain that requires user | ||||
|         interaction. The ESX driver cannot prompt the user to answer a | ||||
|         question, libvirt doesn't have an API for something like this. | ||||
|     </p> | ||||
|     <p> | ||||
|         The VI API provides the <code>AnswerVM()</code> method to | ||||
|         programmatically answer a questions. So the driver has two options | ||||
|         how to handle such a situation: either answer the questions with the | ||||
|         default answer or report the question as an error and cancel the | ||||
|         blocked task if possible. The | ||||
|         <a href="#uriformat"><code>auto_answer</code></a> query parameter | ||||
|         controls the answering behavior. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h2><a name="xmlspecial">Specialties in the domain XML config</a></h2> | ||||
|     <p> | ||||
|         There are several specialties in the domain XML config for ESX domains. | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="restrictions">Restrictions</a></h3> | ||||
|     <p> | ||||
|         There are some restrictions for some values of the domain XML config. | ||||
|         The driver will complain if this restrictions are violated. | ||||
|     </p> | ||||
|     <ul> | ||||
|         <li> | ||||
|             Memory size has to be a multiple of 4096 | ||||
|         </li> | ||||
|         <li> | ||||
|             Number of virtual CPU has to be 1 or a multiple of 2 | ||||
|         </li> | ||||
|         <li> | ||||
|             Valid MAC address prefixes are <code>00:0c:29</code> and | ||||
|             <code>00:50:56</code>. <span class="since">Since 0.7.6</span> | ||||
|             arbitrary <a href="#macaddresses">MAC addresses</a> are supported. | ||||
|         </li> | ||||
|     </ul> | ||||
|  | ||||
|  | ||||
|     <h3><a name="datastore">Datastore references</a></h3> | ||||
|     <p> | ||||
|         Storage is managed in datastores. VMware uses a special path format to | ||||
|         reference files in a datastore. Basically, the datastore name is put | ||||
|         into squared braces in front of the path. | ||||
|     </p> | ||||
| <pre> | ||||
| [datastore] directory/filename | ||||
| </pre> | ||||
|     <p> | ||||
|         To define a new domain the driver converts the domain XML into a | ||||
|         VMware VMX file and uploads it to a datastore known to the ESX server. | ||||
|         Because multiple datastores may be known to an ESX server the driver | ||||
|         needs to decide to which datastore the VMX file should be uploaded. | ||||
|         The driver deduces this information from the path of the source of the | ||||
|         first file-based harddisk listed in the domain XML. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h3><a name="macaddresses">MAC addresses</a></h3> | ||||
|     <p> | ||||
|         VMware has registered two MAC address prefixes for domains: | ||||
|         <code>00:0c:29</code> and <code>00:50:56</code>. These prefixes are | ||||
|         split into ranges for different purposes. | ||||
|     </p> | ||||
|     <table class="top_table"> | ||||
|         <tr> | ||||
|             <th>Range</th> | ||||
|             <th>Purpose</th> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>00:0c:29:00:00:00</code> - <code>00:0c:29:ff:ff:ff</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 An ESX server autogenerates MAC addresses from this range if | ||||
|                 the VMX file doesn't contain a MAC address when trying to start | ||||
|                 a domain. | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>00:50:56:00:00:00</code> - <code>00:50:56:3f:ff:ff</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 MAC addresses from this range can by manually assigned by the | ||||
|                 user in the VI client. | ||||
|             </td> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>00:50:56:80:00:00</code> - <code>00:50:56:bf:ff:ff</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 A VI client autogenerates MAC addresses from this range for | ||||
|                 newly defined domains. | ||||
|             </td> | ||||
|         </tr> | ||||
|     </table> | ||||
|     <p> | ||||
|         The VMX files generated by the ESX driver always contain a MAC address, | ||||
|         because libvirt generates a random one if an interface element in the | ||||
|         domain XML file lacks a MAC address. | ||||
|         <span class="since">Since 0.7.6</span> the ESX driver sets the prefix | ||||
|         for generated MAC addresses to <code>00:0c:29</code>. Before 0.7.6 | ||||
|         the <code>00:50:56</code> prefix was used. Sometimes this resulted in | ||||
|         the generation of out-of-range MAC address that were rejected by the | ||||
|         ESX server. | ||||
|     </p> | ||||
|     <p> | ||||
|         Also <span class="since">since 0.7.6</span> every MAC address outside | ||||
|         this ranges can be used. For such MAC addresses the ESX server-side | ||||
|         check is disabled in the VMX file to stop the ESX server from rejecting | ||||
|         out-of-predefined-range MAC addresses. | ||||
|     </p> | ||||
| <pre> | ||||
| ethernet0.checkMACAddress = "false" | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h3><a name="hardware">Available hardware</a></h3> | ||||
|     <p> | ||||
|         VMware ESX supports different models of SCSI controllers and network | ||||
|         cards. | ||||
|     </p> | ||||
|  | ||||
|     <h4>SCSI controller models</h4> | ||||
|     <dl> | ||||
|         <dt><code>auto</code></dt> | ||||
|         <dd> | ||||
|             This isn't a actual controller model. If specified the ESX driver | ||||
|             tries to detect the SCSI controller model referenced in the | ||||
|             <code>.vmdk</code> file and use it. Autodetection fails when a | ||||
|             SCSI controller has multiple disks attached and the SCSI controller | ||||
|             models referenced in the <code>.vmdk</code> files are inconsistent. | ||||
|             <span class="since">Since 0.8.3</span> | ||||
|         </dd> | ||||
|         <dt><code>buslogic</code></dt> | ||||
|         <dd> | ||||
|             BusLogic SCSI controller for older guests. | ||||
|         </dd> | ||||
|         <dt><code>lsilogic</code></dt> | ||||
|         <dd> | ||||
|             LSI Logic SCSI controller for recent guests. | ||||
|         </dd> | ||||
|         <dt><code>lsisas1068</code></dt> | ||||
|         <dd> | ||||
|             LSI Logic SAS 1068 controller. <span class="since">Since 0.8.0</span> | ||||
|         </dd> | ||||
|         <dt><code>vmpvscsi</code></dt> | ||||
|         <dd> | ||||
|             Special VMware Paravirtual SCSI controller, requires VMware tools inside | ||||
|             the guest. See <a href="http://kb.vmware.com/kb/1010398">VMware KB1010398</a> | ||||
|             for details. <span class="since">Since 0.8.3</span> | ||||
|         </dd> | ||||
|     </dl> | ||||
|     <p> | ||||
|         Here a domain XML snippet: | ||||
|     </p> | ||||
| <pre> | ||||
|     ... | ||||
|     <disk type='file' device='disk'> | ||||
|       <source file='[local-storage] Fedora11/Fedora11.vmdk'/> | ||||
|       <target dev='sda' bus='scsi'/> | ||||
|       <address type='drive' controller='0' bus='0' unit='0'/> | ||||
|     </disk> | ||||
|     <controller type='scsi' index='0' model='<strong>lsilogic</strong>'/> | ||||
|     ... | ||||
| </pre> | ||||
|     <p> | ||||
|         The controller element is supported <span class="since">since 0.8.2</span>. | ||||
|         Prior to this <code><driver name='lsilogic'/></code> was abused to | ||||
|         specify the SCSI controller model. This attribute usage is deprecated now. | ||||
|     </p> | ||||
| <pre> | ||||
|     ... | ||||
|     <disk type='file' device='disk'> | ||||
|       <driver name='<strong>lsilogic</strong>'/> | ||||
|       <source file='[local-storage] Fedora11/Fedora11.vmdk'/> | ||||
|       <target dev='sda' bus='scsi'/> | ||||
|     </disk> | ||||
|     ... | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h4>Network card models</h4> | ||||
|     <dl> | ||||
|         <dt><code>vlance</code></dt> | ||||
|         <dd> | ||||
|             AMD PCnet32 network card for older guests. | ||||
|         </dd> | ||||
|         <dt><code>vmxnet</code>, <code>vmxnet2</code>, <code>vmxnet3</code></dt> | ||||
|         <dd> | ||||
|             Special VMware VMXnet network card, requires VMware tools inside | ||||
|             the guest. See <a href="http://kb.vmware.com/kb/1001805">VMware KB1001805</a> | ||||
|             for details. | ||||
|         </dd> | ||||
|         <dt><code>e1000</code></dt> | ||||
|         <dd> | ||||
|             Intel E1000 network card for recent guests. | ||||
|         </dd> | ||||
|     </dl> | ||||
|     <p> | ||||
|         Here a domain XML snippet: | ||||
|     </p> | ||||
| <pre> | ||||
|     ... | ||||
|     <interface type='bridge'> | ||||
|       <mac address='00:50:56:25:48:c7'/> | ||||
|       <source bridge='VM Network'/> | ||||
|       <model type='<strong>e1000</strong>'/> | ||||
|     </interface> | ||||
|     ... | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h2><a name="importexport">Import and export of domain XML configs</a></h2> | ||||
|     <p> | ||||
|         The ESX driver currently supports a native config format known as | ||||
|         <code>vmware-vmx</code> to handle VMware VMX configs. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h3><a name="xmlimport">Converting from VMware VMX config to domain XML config</a></h3> | ||||
|     <p> | ||||
|         The <code>virsh domxml-from-native</code> provides a way to convert an | ||||
|         existing VMware VMX config into a domain XML config that can then be | ||||
|         used by libvirt. | ||||
|     </p> | ||||
| <pre> | ||||
| $ cat > demo.vmx << EOF | ||||
| #!/usr/bin/vmware | ||||
| config.version = "8" | ||||
| virtualHW.version = "4" | ||||
| floppy0.present = "false" | ||||
| nvram = "Fedora11.nvram" | ||||
| deploymentPlatform = "windows" | ||||
| virtualHW.productCompatibility = "hosted" | ||||
| tools.upgrade.policy = "useGlobal" | ||||
| powerType.powerOff = "default" | ||||
| powerType.powerOn = "default" | ||||
| powerType.suspend = "default" | ||||
| powerType.reset = "default" | ||||
| displayName = "Fedora11" | ||||
| extendedConfigFile = "Fedora11.vmxf" | ||||
| scsi0.present = "true" | ||||
| scsi0.sharedBus = "none" | ||||
| scsi0.virtualDev = "lsilogic" | ||||
| memsize = "1024" | ||||
| scsi0:0.present = "true" | ||||
| scsi0:0.fileName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Fedora11/Fedora11.vmdk" | ||||
| scsi0:0.deviceType = "scsi-hardDisk" | ||||
| ide0:0.present = "true" | ||||
| ide0:0.clientDevice = "true" | ||||
| ide0:0.deviceType = "cdrom-raw" | ||||
| ide0:0.startConnected = "false" | ||||
| ethernet0.present = "true" | ||||
| ethernet0.networkName = "VM Network" | ||||
| ethernet0.addressType = "vpx" | ||||
| ethernet0.generatedAddress = "00:50:56:91:48:c7" | ||||
| chipset.onlineStandby = "false" | ||||
| guestOSAltName = "Red Hat Enterprise Linux 5 (32-Bit)" | ||||
| guestOS = "rhel5" | ||||
| uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10" | ||||
| snapshot.action = "keep" | ||||
| sched.cpu.min = "0" | ||||
| sched.cpu.units = "mhz" | ||||
| sched.cpu.shares = "normal" | ||||
| sched.mem.minsize = "0" | ||||
| sched.mem.shares = "normal" | ||||
| toolScripts.afterPowerOn = "true" | ||||
| toolScripts.afterResume = "true" | ||||
| toolScripts.beforeSuspend = "true" | ||||
| toolScripts.beforePowerOff = "true" | ||||
| scsi0:0.redo = "" | ||||
| tools.syncTime = "false" | ||||
| uuid.location = "56 4d b5 06 a2 bd fb eb-ae 86 f7 d8 49 27 d0 c4" | ||||
| sched.cpu.max = "unlimited" | ||||
| sched.swap.derivedName = "/vmfs/volumes/498076b2-02796c1a-ef5b-000ae484a6a3/Fedora11/Fedora11-7de040d8.vswp" | ||||
| tools.remindInstall = "TRUE" | ||||
| EOF | ||||
|  | ||||
| $ virsh -c esx://example.com domxml-from-native vmware-vmx demo.vmx | ||||
| Enter username for example.com [root]: | ||||
| Enter root password for example.com: | ||||
| <domain type='vmware'> | ||||
|   <name>Fedora11</name> | ||||
|   <uuid>50115e16-9bdc-49d7-f171-53c4d7f91710</uuid> | ||||
|   <memory>1048576</memory> | ||||
|   <currentMemory>1048576</currentMemory> | ||||
|   <vcpu>1</vcpu> | ||||
|   <os> | ||||
|     <type arch='i686'>hvm</type> | ||||
|   </os> | ||||
|   <clock offset='utc'/> | ||||
|   <on_poweroff>destroy</on_poweroff> | ||||
|   <on_reboot>restart</on_reboot> | ||||
|   <on_crash>destroy</on_crash> | ||||
|   <devices> | ||||
|     <disk type='file' device='disk'> | ||||
|       <source file='[local-storage] Fedora11/Fedora11.vmdk'/> | ||||
|       <target dev='sda' bus='scsi'/> | ||||
|       <address type='drive' controller='0' bus='0' unit='0'/> | ||||
|     </disk> | ||||
|     <controller type='scsi' index='0' model='lsilogic'/> | ||||
|     <interface type='bridge'> | ||||
|       <mac address='00:50:56:91:48:c7'/> | ||||
|       <source bridge='VM Network'/> | ||||
|     </interface> | ||||
|   </devices> | ||||
| </domain> | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h3><a name="xmlexport">Converting from domain XML config to VMware VMX config</a></h3> | ||||
|     <p> | ||||
|       The <code>virsh domxml-to-native</code> provides a way to convert a | ||||
|       domain XML config into a VMware VMX config. | ||||
|     </p> | ||||
| <pre> | ||||
| $ cat > demo.xml << EOF | ||||
| <domain type='vmware'> | ||||
|   <name>Fedora11</name> | ||||
|   <uuid>50115e16-9bdc-49d7-f171-53c4d7f91710</uuid> | ||||
|   <memory>1048576</memory> | ||||
|   <currentMemory>1048576</currentMemory> | ||||
|   <vcpu>1</vcpu> | ||||
|   <os> | ||||
|     <type arch='x86_64'>hvm</type> | ||||
|   </os> | ||||
|   <devices> | ||||
|     <disk type='file' device='disk'> | ||||
|       <source file='[local-storage] Fedora11/Fedora11.vmdk'/> | ||||
|       <target dev='sda' bus='scsi'/> | ||||
|       <address type='drive' controller='0' bus='0' unit='0'/> | ||||
|     </disk> | ||||
|     <controller type='scsi' index='0' model='lsilogic'/> | ||||
|     <interface type='bridge'> | ||||
|       <mac address='00:50:56:25:48:c7'/> | ||||
|       <source bridge='VM Network'/> | ||||
|     </interface> | ||||
|   </devices> | ||||
| </domain> | ||||
| EOF | ||||
|  | ||||
| $ virsh -c esx://example.com domxml-to-native vmware-vmx demo.xml | ||||
| Enter username for example.com [root]: | ||||
| Enter root password for example.com: | ||||
| config.version = "8" | ||||
| virtualHW.version = "4" | ||||
| guestOS = "other-64" | ||||
| uuid.bios = "50 11 5e 16 9b dc 49 d7-f1 71 53 c4 d7 f9 17 10" | ||||
| displayName = "Fedora11" | ||||
| memsize = "1024" | ||||
| numvcpus = "1" | ||||
| scsi0.present = "true" | ||||
| scsi0.virtualDev = "lsilogic" | ||||
| scsi0:0.present = "true" | ||||
| scsi0:0.deviceType = "scsi-hardDisk" | ||||
| scsi0:0.fileName = "/vmfs/volumes/local-storage/Fedora11/Fedora11.vmdk" | ||||
| ethernet0.present = "true" | ||||
| ethernet0.networkName = "VM Network" | ||||
| ethernet0.connectionType = "bridged" | ||||
| ethernet0.addressType = "static" | ||||
| ethernet0.address = "00:50:56:25:48:C7" | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h2><a name="xmlconfig">Example domain XML configs</a></h2> | ||||
|  | ||||
|     <h3>Fedora11 on x86_64</h3> | ||||
| <pre> | ||||
| <domain type='vmware'> | ||||
|   <name>Fedora11</name> | ||||
|   <uuid>50115e16-9bdc-49d7-f171-53c4d7f91710</uuid> | ||||
|   <memory>1048576</memory> | ||||
|   <currentMemory>1048576</currentMemory> | ||||
|   <vcpu>1</vcpu> | ||||
|   <os> | ||||
|     <type arch='x86_64'>hvm</type> | ||||
|   </os> | ||||
|   <devices> | ||||
|     <disk type='file' device='disk'> | ||||
|       <source file='[local-storage] Fedora11/Fedora11.vmdk'/> | ||||
|       <target dev='sda' bus='scsi'/> | ||||
|       <address type='drive' controller='0' bus='0' unit='0'/> | ||||
|     </disk> | ||||
|     <controller type='scsi' index='0'/> | ||||
|     <interface type='bridge'> | ||||
|       <mac address='00:50:56:25:48:c7'/> | ||||
|       <source bridge='VM Network'/> | ||||
|     </interface> | ||||
|   </devices> | ||||
| </domain> | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h2><a name="migration">Migration</a></h2> | ||||
|     <p> | ||||
|         A migration cannot be initiated on an ESX server directly, a VMware | ||||
|         vCenter is necessary for this. The <code>vcenter</code> query | ||||
|         parameter must be set either to the hostname or IP address of the | ||||
|         vCenter managing the ESX server or to <code>*</code>. Setting it | ||||
|         to <code>*</code> causes the driver to connect to the vCenter known to | ||||
|         the ESX server. If the ESX server is not managed by a vCenter an error | ||||
|         is reported. | ||||
|     </p> | ||||
| <pre> | ||||
| esx://example.com/?vcenter=example-vcenter.com | ||||
| </pre> | ||||
|     <p> | ||||
|         Here's an example how to migrate the domain <code>Fedora11</code> from | ||||
|         ESX server <code>example-src.com</code> to ESX server | ||||
|         <code>example-dst.com</code> implicitly involving vCenter | ||||
|         <code>example-vcenter.com</code> using <code>virsh</code>. | ||||
|     </p> | ||||
| <pre> | ||||
| $ virsh -c esx://example-src.com/?vcenter=* migrate Fedora11 esx://example-dst.com/?vcenter=* | ||||
| Enter username for example-src.com [root]: | ||||
| Enter root password for example-src.com: | ||||
| Enter username for example-vcenter.com [administrator]: | ||||
| Enter administrator password for example-vcenter.com: | ||||
| Enter username for example-dst.com [root]: | ||||
| Enter root password for example-dst.com: | ||||
| Enter username for example-vcenter.com [administrator]: | ||||
| Enter administrator password for example-vcenter.com: | ||||
| </pre> | ||||
|     <p> | ||||
|         <span class="since">Since 0.8.3</span> you can directly connect to a vCenter. | ||||
|         This simplifies migration a bit. Here's the same migration as above but | ||||
|         using <code>vpx://</code> connections and assuming both ESX server are in | ||||
|         datacenter <code>dc1</code> and aren't part of a cluster. | ||||
|     </p> | ||||
| <pre> | ||||
| $ virsh -c vpx://example-vcenter.com/dc1/example-src.com migrate Fedora11 vpx://example-vcenter.com/dc1/example-dst.com | ||||
| Enter username for example-vcenter.com [administrator]: | ||||
| Enter administrator password for example-vcenter.com: | ||||
| Enter username for example-vcenter.com [administrator]: | ||||
| Enter administrator password for example-vcenter.com: | ||||
| </pre> | ||||
|  | ||||
|  | ||||
|     <h2><a name="scheduler">Scheduler configuration</a></h2> | ||||
|     <p> | ||||
|         The driver exposes the ESX CPU scheduler. The parameters listed below | ||||
|         are available to control the scheduler. | ||||
|     </p> | ||||
|     <dl> | ||||
|         <dt><code>reservation</code></dt> | ||||
|         <dd> | ||||
|             The amount of CPU resource in MHz that is guaranteed to be | ||||
|             available to the domain. Valid values are 0 and greater. | ||||
|         </dd> | ||||
|         <dt><code>limit</code></dt> | ||||
|         <dd> | ||||
|             The CPU utilization of the domain will be | ||||
|             limited to this value in MHz, even if more CPU resources are | ||||
|             available. If the limit is set to -1, the CPU utilization of the | ||||
|             domain is unlimited. If the limit is not set to -1, it must be | ||||
|             greater than or equal to the reservation. | ||||
|         </dd> | ||||
|         <dt><code>shares</code></dt> | ||||
|         <dd> | ||||
|             Shares are used to determine relative CPU | ||||
|             allocation between domains. In general, a domain with more shares | ||||
|             gets proportionally more of the CPU resource. Valid values are 0 | ||||
|             and greater. The special values -1, -2 and -3 represent the | ||||
|             predefined shares level <code>low</code>, <code>normal</code> and | ||||
|             <code>high</code>. | ||||
|         </dd> | ||||
|     </dl> | ||||
|  | ||||
|  | ||||
|     <h2><a name="tools">VMware tools</a></h2> | ||||
|     <p> | ||||
|         Some actions require installed VMware tools. If the VMware tools are | ||||
|         not installed in the guest and one of the actions below is to be | ||||
|         performed the ESX server raises an error and the driver reports it. | ||||
|     </p> | ||||
|     <ul> | ||||
|         <li> | ||||
|             <code>virDomainReboot</code> | ||||
|         </li> | ||||
|         <li> | ||||
|             <code>virDomainShutdown</code> | ||||
|         </li> | ||||
|     </ul> | ||||
|  | ||||
|  | ||||
|     <h2><a name="links">Links</a></h2> | ||||
|     <ul> | ||||
|         <li> | ||||
|             <a href="http://www.vmware.com/support/developer/vc-sdk/"> | ||||
|                 VMware vSphere Web Services SDK Documentation | ||||
|             </a> | ||||
|         </li> | ||||
|         <li> | ||||
|             <a href="http://www.vmware.com/pdf/esx3_memory.pdf"> | ||||
|                 The Role of Memory in VMware ESX Server 3 | ||||
|             </a> | ||||
|         </li> | ||||
|         <li> | ||||
|             <a href="http://www.sanbarrow.com/vmx.html"> | ||||
|                 VMware VMX config parameters | ||||
|             </a> | ||||
|         </li> | ||||
|         <li> | ||||
|             <a href="http://www.vmware.com/pdf/vsp_4_pvscsi_perf.pdf"> | ||||
|                 VMware ESX 4.0 PVSCSI Storage Performance | ||||
|             </a> | ||||
|         </li> | ||||
|     </ul> | ||||
| </body></html> | ||||
| @@ -1,112 +0,0 @@ | ||||
| <html><body> | ||||
|     <h1>Microsoft Hyper-V hypervisor driver</h1> | ||||
|     <ul id="toc"></ul> | ||||
|     <p> | ||||
|         The libvirt Microsoft Hyper-V driver can manage Hyper-V 2008 R2. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h2><a name="project">Project Links</a></h2> | ||||
|     <ul> | ||||
|       <li> | ||||
|         The <a href="http://www.microsoft.com/hyper-v-server/">Microsoft Hyper-V</a> | ||||
|         hypervisor | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|  | ||||
|     <h2><a name="uri">Connections to the Microsoft Hyper-V driver</a></h2> | ||||
|     <p> | ||||
|         Some example remote connection URIs for the driver are: | ||||
|     </p> | ||||
| <pre> | ||||
| hyperv://example-hyperv.com                  (over HTTPS) | ||||
| hyperv://example-hyperv.com/?transport=http  (over HTTP) | ||||
| </pre> | ||||
|     <p> | ||||
|         <strong>Note</strong>: In contrast to other drivers, the Hyper-V driver | ||||
|         is a client-side-only driver. It connects to the Hyper-V server using | ||||
|         WS-Management over HTTP(S). Therefore, the | ||||
|         <a href="remote.html">remote transport mechanism</a> provided by the | ||||
|         remote driver and libvirtd will not work, and you cannot use URIs like | ||||
|         <code>hyperv+ssh://example.com</code>. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h3><a name="uriformat">URI Format</a></h3> | ||||
|     <p> | ||||
|         URIs have this general form (<code>[...]</code> marks an optional part). | ||||
|     </p> | ||||
| <pre> | ||||
| hyperv://[username@]hostname[:port]/[?extraparameters] | ||||
| </pre> | ||||
|     <p> | ||||
|         The default HTTPS ports is 5986. If the port parameter is given, it | ||||
|         overrides the default port. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h4><a name="extraparams">Extra parameters</a></h4> | ||||
|     <p> | ||||
|         Extra parameters can be added to a URI as part of the query string | ||||
|         (the part following <code>?</code>). A single parameter is formed by a | ||||
|         <code>name=value</code> pair. Multiple parameters are separated by | ||||
|         <code>&</code>. | ||||
|     </p> | ||||
| <pre> | ||||
| ?transport=http | ||||
| </pre> | ||||
|     <p> | ||||
|         The driver understands the extra parameters shown below. | ||||
|     </p> | ||||
|     <table class="top_table"> | ||||
|         <tr> | ||||
|             <th>Name</th> | ||||
|             <th>Values</th> | ||||
|             <th>Meaning</th> | ||||
|         </tr> | ||||
|         <tr> | ||||
|             <td> | ||||
|                 <code>transport</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 <code>http</code> or <code>https</code> | ||||
|             </td> | ||||
|             <td> | ||||
|                 Overrides the default HTTPS transport. The default HTTP port | ||||
|                 is 5985. | ||||
|             </td> | ||||
|         </tr> | ||||
|     </table> | ||||
|  | ||||
|  | ||||
|     <h3><a name="auth">Authentication</a></h3> | ||||
|     <p> | ||||
|         In order to perform any useful operation the driver needs to log into | ||||
|         the Hyper-V server. Therefore, only <code>virConnectOpenAuth</code> can | ||||
|         be used to connect to an Hyper-V server, <code>virConnectOpen</code> and | ||||
|         <code>virConnectOpenReadOnly</code> don't work. | ||||
|         To log into an Hyper-V server the driver will request credentials using | ||||
|         the callback passed to the <code>virConnectOpenAuth</code> function. | ||||
|         The driver passes the hostname as challenge parameter to the callback. | ||||
|     </p> | ||||
|     <p> | ||||
|         <strong>Note</strong>: Currently only <code>Basic</code> authentication | ||||
|         is supported by libvirt. This method is disabled by default on the | ||||
|         Hyper-V server and can be enabled via the WinRM commandline tool. | ||||
|     </p> | ||||
| <pre> | ||||
| winrm set winrm/config/service/auth @{Basic="true"} | ||||
| </pre> | ||||
|     <p> | ||||
|         To allow <code>Basic</code> authentication with HTTP transport WinRM | ||||
|         needs to allow unencrypted communication. This can be enabled via the | ||||
|         WinRM commandline tool. However, this is not the recommended | ||||
|         communication mode. | ||||
|     </p> | ||||
| <pre> | ||||
| winrm set winrm/config/service @{AllowUnencrypted="true"} | ||||
| </pre> | ||||
|  | ||||
|  | ||||
| </body></html> | ||||
| @@ -1,122 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>LXC container driver</h1> | ||||
| <p> | ||||
| The libvirt LXC driver manages "Linux Containers".  Containers are sets of processes | ||||
| with private namespaces which can (but don't always) look like separate machines, but | ||||
| do not have their own OS.  Here are two example configurations.  The first is a very | ||||
| light-weight "application container" which does not have its own root image. | ||||
| </p> | ||||
|  | ||||
|     <h2><a name="project">Project Links</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         The <a href="http://lxc.sourceforge.net/">LXC</a> Linux | ||||
|         container system | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
| <h2>Cgroups Requirements</h2> | ||||
|  | ||||
| <p> | ||||
| The libvirt LXC driver requires that certain cgroups controllers are | ||||
| mounted on the host OS. The minimum required controllers are 'cpuacct', | ||||
| 'memory' and 'devices', while recommended extra controllers are | ||||
| 'cpu', 'freezer' and 'blkio'. The /etc/cgconfig.conf & cgconfig | ||||
| init service used to mount cgroups at host boot time. To manually | ||||
| mount them use: | ||||
| </p> | ||||
|  | ||||
| <pre> | ||||
|  # mount -t cgroup cgroup /dev/cgroup -o cpuacct,memory,devices,cpu,freezer,blkio | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| NB, the blkio controller in some kernels will not allow creation of nested | ||||
| sub-directories which will prevent correct operation of the libvirt LXC | ||||
| driver. On such kernels, it may be neccessary to unmount the blkio controller. | ||||
| </p> | ||||
|  | ||||
|  | ||||
| <h3>Example config version 1</h3> | ||||
| <p></p> | ||||
| <pre> | ||||
| <domain type='lxc'> | ||||
|   <name>vm1</name> | ||||
|   <memory>500000</memory> | ||||
|   <os> | ||||
|     <type>exe</type> | ||||
|     <init>/bin/sh</init> | ||||
|   </os> | ||||
|   <vcpu>1</vcpu> | ||||
|   <clock offset='utc'/> | ||||
|   <on_poweroff>destroy</on_poweroff> | ||||
|   <on_reboot>restart</on_reboot> | ||||
|   <on_crash>destroy</on_crash> | ||||
|   <devices> | ||||
|     <emulator>/usr/libexec/libvirt_lxc</emulator> | ||||
|     <interface type='network'> | ||||
|       <source network='default'/> | ||||
|     </interface> | ||||
|     <console type='pty' /> | ||||
|   </devices> | ||||
| </domain> | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| In the <emulator> element, be sure you specify the correct path | ||||
| to libvirt_lxc, if it does not live in /usr/libexec on your system. | ||||
| </p> | ||||
|  | ||||
| <p> | ||||
| The next example assumes there is a private root filesystem | ||||
| (perhaps hand-crafted using busybox, or installed from media, | ||||
| debootstrap, whatever) under /opt/vm-1-root: | ||||
| </p> | ||||
| <p></p> | ||||
| <pre> | ||||
| <domain type='lxc'> | ||||
|   <name>vm1</name> | ||||
|   <memory>32768</memory> | ||||
|   <os> | ||||
|     <type>exe</type> | ||||
|     <init>/init</init> | ||||
|   </os> | ||||
|   <vcpu>1</vcpu> | ||||
|   <clock offset='utc'/> | ||||
|   <on_poweroff>destroy</on_poweroff> | ||||
|   <on_reboot>restart</on_reboot> | ||||
|   <on_crash>destroy</on_crash> | ||||
|   <devices> | ||||
|     <emulator>/usr/libexec/libvirt_lxc</emulator> | ||||
|     <filesystem type='mount'> | ||||
|       <source dir='/opt/vm-1-root'/> | ||||
|       <target dir='/'/> | ||||
|     </filesystem> | ||||
|     <interface type='network'> | ||||
|       <source network='default'/> | ||||
|     </interface> | ||||
|     <console type='pty' /> | ||||
|   </devices> | ||||
| </domain> | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| In both cases, you can define and start a container using:</p> | ||||
| <pre> | ||||
| virsh --connect lxc:/// define v1.xml | ||||
| virsh --connect lxc:/// start vm1 | ||||
| </pre> | ||||
| and then get a console  using: | ||||
| <pre> | ||||
| virsh --connect lxc:/// console vm1 | ||||
| </pre> | ||||
| <p>Now doing 'ps -ef' will only show processes in the container, for | ||||
| instance.  You can undefine it using | ||||
| </p> | ||||
| <pre> | ||||
| virsh --connect lxc:/// undefine vm1 | ||||
| </pre> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,121 +0,0 @@ | ||||
| <html> <!-- -*- html -*- --> | ||||
|   <body> | ||||
|     <h1>OpenVZ container driver</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <p> | ||||
|     The OpenVZ driver for libvirt allows use and management of container | ||||
|     based virtualization on a Linux host OS. Prior to using the OpenVZ | ||||
|     driver, the OpenVZ enabled kernel must be installed & booted, and the | ||||
|     OpenVZ userspace tools installed. The libvirt driver has been tested | ||||
|     with OpenVZ 3.0.22, but other 3.0.x versions should also work without | ||||
|     undue trouble. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="project">Project Links</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         The <a href="http://openvz.org/">OpenVZ</a> Linux container | ||||
|         system | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="connections">Connections to OpenVZ driver</a></h2> | ||||
|  | ||||
|     <p> | ||||
|     The libvirt OpenVZ driver is a single-instance privileged driver, | ||||
|     with a driver name of 'openvz'. Some example connection URIs for | ||||
|     the libvirt driver are: | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| openvz:///system                     (local access) | ||||
| openvz+unix:///system                (local access) | ||||
| openvz://example.com/system          (remote access, TLS/x509) | ||||
| openvz+tcp://example.com/system      (remote access, SASl/Kerberos) | ||||
| openvz+ssh://root@example.com/system (remote access, SSH tunnelled) | ||||
| </pre> | ||||
|  | ||||
|     <h2><a name="notes">Notes on bridged networking</a></h2> | ||||
|  | ||||
|     <p> | ||||
|     Bridged networking enables a guest domain (ie container) to have its | ||||
|     network interface connected directly to the host's physical LAN. Before | ||||
|     this can be used there are a couple of configuration pre-requisites for | ||||
|     the host OS. | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="host">Host network devices</a></h3> | ||||
|  | ||||
|     <p> | ||||
|     One or more of the physical devices must be attached to a bridge. The | ||||
|     process for this varies according to the operating system in use, so | ||||
|     for up to date notes consult the <a href="http://wiki.libvirt.org">Wiki</a> | ||||
|     or your operating system's networking documentation. The basic idea is | ||||
|     that the host OS should end up with a bridge device "br0" containing a | ||||
|     physical device "eth0", or a bonding device "bond0". | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="tools">OpenVZ tools configuration</a></h3> | ||||
|  | ||||
|     <p> | ||||
|     OpenVZ releases later than 3.0.23 ship with a standard network device | ||||
|     setup script that is able to setup bridging, named | ||||
|     <code>/usr/sbin/vznetaddbr</code>. For releases prior to 3.0.23, this | ||||
|     script must be created manually by the host OS administrator. The | ||||
|     simplest way is to just download the latest version of this script | ||||
|     from a newer OpenVZ release, or upstream source repository. Then | ||||
|     a generic configuration file <code>/etc/vz/vznetctl.conf</code> | ||||
|     must be created containing | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| #!/bin/bash | ||||
| EXTERNAL_SCRIPT="/usr/sbin/vznetaddbr" | ||||
| </pre> | ||||
|  | ||||
|     <p> | ||||
|     The host OS is now ready to allow bridging of guest containers, which | ||||
|     will work whether the container is started with libvirt, or OpenVZ | ||||
|     tools. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h2><a name="example">Example guest domain XML configuration</a></h2> | ||||
|  | ||||
|     <p> | ||||
|     The current libvirt OpenVZ driver has a restriction that the | ||||
|     domain names must match the OpenVZ container VEID, which by | ||||
|     convention start at 100, and are incremented from there. The | ||||
|     choice of OS template to use inside the container is determined | ||||
|     by the <code>filesystem</code> tag, and the template source name | ||||
|     matches the templates known to OpenVZ tools. | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| <domain type='openvz' id='104'> | ||||
|   <name>104</name> | ||||
|   <uuid>86c12009-e591-a159-6e9f-91d18b85ef78</uuid> | ||||
|   <vcpu>3</vcpu> | ||||
|   <os> | ||||
|     <type>exe</type> | ||||
|     <init>/sbin/init</init> | ||||
|   </os> | ||||
|   <devices> | ||||
|     <filesystem type='template'> | ||||
|       <source name='fedora-9-i386-minimal'/> | ||||
|       <target dir='/'/> | ||||
|     </filesystem> | ||||
|     <interface type='bridge'> | ||||
|       <mac address='00:18:51:5b:ea:bf'/> | ||||
|       <source bridge='br0'/> | ||||
|       <target dev='veth101.0'/> | ||||
|     </interface> | ||||
|   </devices> | ||||
| </domain> | ||||
| </pre> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,578 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>KVM/QEMU hypervisor driver</h1> | ||||
|  | ||||
|     <ul id="toc"></ul> | ||||
|  | ||||
|     <p> | ||||
|       The libvirt KVM/QEMU driver can manage any QEMU emulator from | ||||
|       version 0.8.1 or later. It can also manage Xenner, which | ||||
|       provides the same QEMU command line syntax and monitor | ||||
|       interaction. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="project">Project Links</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         The <a href="http://www.linux-kvm.org/">KVM</a> Linux | ||||
|         hypervisor | ||||
|       <li> | ||||
|         The <a href="http://wiki.qemu.org/Index.html">QEMU</a> emulator | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="prereq">Deployment pre-requisites</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         <strong>QEMU emulators</strong>: The driver will probe <code>/usr/bin</code> | ||||
|         for the presence of <code>qemu</code>, <code>qemu-system-x86_64</code>, | ||||
|         <code>qemu-system-microblaze</code>, | ||||
|         <code>qemu-system-microblazeel</code>, | ||||
|         <code>qemu-system-mips</code>,<code>qemu-system-mipsel</code>, | ||||
|         <code>qemu-system-sparc</code>,<code>qemu-system-ppc</code>. The results | ||||
|         of this can be seen from the capabilities XML output. | ||||
|       </li> | ||||
|       <li> | ||||
|         <strong>KVM hypervisor</strong>: The driver will probe <code>/usr/bin</code> | ||||
|         for the presence of <code>qemu-kvm</code> and <code>/dev/kvm</code> device | ||||
|         node. If both are found, then KVM fullyvirtualized, hardware accelerated | ||||
|         guests will be available. | ||||
|       </li> | ||||
|       <li> | ||||
|         <strong>Xenner hypervisor</strong>: The driver will probe <code>/usr/bin</code> | ||||
|         for the presence of <code>xenner</code> and <code>/dev/kvm</code> device | ||||
|         node. If both are found, then Xen paravirtualized guests can be run using | ||||
|         the KVM hardware acceleration. | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2><a name="uris">Connections to QEMU driver</a></h2> | ||||
|  | ||||
|     <p> | ||||
|     The libvirt QEMU driver is a multi-instance driver, providing a single | ||||
|     system wide privileged driver (the "system" instance), and per-user | ||||
|     unprivileged drivers (the "session" instance). The URI driver protocol | ||||
|     is "qemu". Some example conection URIs for the libvirt driver are: | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| qemu:///session                      (local access to per-user instance) | ||||
| qemu+unix:///session                 (local access to per-user instance) | ||||
|  | ||||
| qemu:///system                       (local access to system instance) | ||||
| qemu+unix:///system                  (local access to system instance) | ||||
| qemu://example.com/system            (remote access, TLS/x509) | ||||
| qemu+tcp://example.com/system        (remote access, SASl/Kerberos) | ||||
| qemu+ssh://root@example.com/system   (remote access, SSH tunnelled) | ||||
| </pre> | ||||
|  | ||||
|     <h2><a name="security">Driver security architecture</a></h2> | ||||
|  | ||||
|     <p> | ||||
|       There are multiple layers to security in the QEMU driver, allowing for | ||||
|       flexibility in the use of QEMU based virtual machines. | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="securitydriver">Driver instances</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       As explained above there are two ways to access the QEMU driver | ||||
|       in libvirt. The "qemu:///session" family of URIs connect to a | ||||
|       libvirtd instance running as the same user/group ID as the client | ||||
|       application. Thus the QEMU instances spawned from this driver will | ||||
|       share the same privileges as the client application. The intended | ||||
|       use case for this driver is desktop virtualization, with virtual | ||||
|       machines storing their disk images in the user's home directory and | ||||
|       being managed from the local desktop login session. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       The "qemu:///system" family of URIs connect to a | ||||
|       libvirtd instance running as the privileged system account 'root'. | ||||
|       Thus the QEMU instances spawned from this driver may have much | ||||
|       higher privileges than the client application managing them. | ||||
|       The intended use case for this driver is server virtualization, | ||||
|       where the virtual machines may need to be connected to host | ||||
|       resources (block, PCI, USB, network devices) whose access requires | ||||
|       elevated privileges. | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="securitydac">POSIX users/groups</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       In the "session" instance, the POSIX users/groups model restricts QEMU | ||||
|       virtual machines (and libvirtd in general) to only have access to resources | ||||
|       with the same user/group ID as the client application. There is no | ||||
|       finer level of configuration possible for the "session" instances. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       In the "system" instance, libvirt releases from 0.7.0 onwards allow | ||||
|       control over the user/group that the QEMU virtual machines are run | ||||
|       as. A build of libvirt with no configuration parameters set will | ||||
|       still run QEMU processes as root:root. It is possible to change | ||||
|       this default by using the --with-qemu-user=$USERNAME and | ||||
|       --with-qemu-group=$GROUPNAME arguments to 'configure' during | ||||
|       build. It is strongly recommended that vendors build with both | ||||
|       of these arguments set to 'qemu'. Regardless of this build time | ||||
|       default, administrators can set a per-host default setting in | ||||
|       the <code>/etc/libvirt/qemu.conf</code> configuration file via | ||||
|       the <code>user=$USERNAME</code> and <code>group=$GROUPNAME</code> | ||||
|       parameters. When a non-root user or group is configured, the | ||||
|       libvirt QEMU driver will change uid/gid to match immediately | ||||
|       before executing the QEMU binary for a virtual machine. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       If QEMU virtual machines from the "system" instance are being | ||||
|       run as non-root, there will be greater restrictions on what | ||||
|       host resources the QEMU process will be able to access. The | ||||
|       libvirtd daemon will attempt to manage permissions on resources | ||||
|       to minimise the likelihood of unintentional security denials, | ||||
|       but the administrator / application developer must be aware of | ||||
|       some of the consequences / restrictions. | ||||
|     </p> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         <p> | ||||
|           The directories <code>/var/run/libvirt/qemu/</code>, | ||||
|           <code>/var/lib/libvirt/qemu/</code> and | ||||
|           <code>/var/cache/libvirt/qemu/</code> must all have their | ||||
|           ownership set to match the user / group ID that QEMU | ||||
|           guests will be run as. If the vendor has set a non-root | ||||
|           user/group for the QEMU driver at build time, the | ||||
|           permissions should be set automatically at install time. | ||||
|           If a host administrator customizes user/group in | ||||
|           <code>/etc/libvirt/qemu.conf</code>, they will need to | ||||
|           manually set the ownership on these directories. | ||||
|         </p> | ||||
|       </li> | ||||
|       <li> | ||||
|         <p> | ||||
|           When attaching USB and PCI devices to a QEMU guest, | ||||
|           QEMU will need to access files in <code>/dev/bus/usb</code> | ||||
|           and <code>/sys/bus/pci/devices</code> respectively. The libvirtd daemon | ||||
|           will automatically set the ownership on specific devices | ||||
|           that are assigned to a guest at start time. There should | ||||
|           not be any need for administrator changes in this respect. | ||||
|         </p> | ||||
|       </li> | ||||
|       <li> | ||||
|         <p> | ||||
|           Any files/devices used as guest disk images must be | ||||
|           accessible to the user/group ID that QEMU guests are | ||||
|           configured to run as. The libvirtd daemon will automatically | ||||
|           set the ownership of the file/device path to the correct | ||||
|           user/group ID. Applications / administrators must be aware | ||||
|           though that the parent directory permissions may still | ||||
|           deny access. The directories containing disk images | ||||
|           must either have their ownership set to match the user/group | ||||
|           configured for QEMU, or their UNIX file permissions must | ||||
|           have the 'execute/search' bit enabled for 'others'. | ||||
|         </p> | ||||
|         <p> | ||||
|           The simplest option is the latter one, of just enabling | ||||
|           the 'execute/search' bit. For any directory to be used | ||||
|           for storing disk images, this can be achieved by running | ||||
|           the following command on the directory itself, and any | ||||
|           parent directories | ||||
|         </p> | ||||
| <pre> | ||||
| chmod o+x /path/to/directory | ||||
| </pre> | ||||
|         <p> | ||||
|           In particular note that if using the "system" instance | ||||
|           and attempting to store disk images in a user home | ||||
|           directory, the default permissions on $HOME are typically | ||||
|           too restrictive to allow access. | ||||
|         </p> | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <h3><a name="securitycap">Linux process capabilities</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       The libvirt QEMU driver has a build time option allowing it to use | ||||
|       the <a href="http://people.redhat.com/sgrubb/libcap-ng/index.html">libcap-ng</a> | ||||
|       library to manage process capabilities. If this build option is | ||||
|       enabled, then the QEMU driver will use this to ensure that all | ||||
|       process capabilities are dropped before executing a QEMU virtual | ||||
|       machine. Process capabilities are what gives the 'root' account | ||||
|       its high power, in particular the CAP_DAC_OVERRIDE capability | ||||
|       is what allows a process running as 'root' to access files owned | ||||
|       by any user. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       If the QEMU driver is configured to run virtual machines as non-root, | ||||
|       then they will already lose all their process capabilities at time | ||||
|       of startup. The Linux capability feature is thus aimed primarily at | ||||
|       the scenario where the QEMU processes are running as root. In this | ||||
|       case, before launching a QEMU virtual machine, libvirtd will use | ||||
|       libcap-ng APIs to drop all process capabilities. It is important | ||||
|       for administrators to note that this implies the QEMU process will | ||||
|       <strong>only</strong> be able to access files owned by root, and | ||||
|       not files owned by any other user. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Thus, if a vendor / distributor has configured their libvirt package | ||||
|       to run as 'qemu' by default, a number of changes will be required | ||||
|       before an administrator can change a host to run guests as root. | ||||
|       In particular it will be necessary to change ownership on the | ||||
|       directories <code>/var/run/libvirt/qemu/</code>, | ||||
|       <code>/var/lib/libvirt/qemu/</code> and | ||||
|       <code>/var/cache/libvirt/qemu/</code> back to root, in addition | ||||
|       to changing the <code>/etc/libvirt/qemu.conf</code> settings. | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="securityselinux">SELinux basic confinement</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       The basic SELinux protection for QEMU virtual machines is intended to | ||||
|       protect the host OS from a compromised virtual machine process. There | ||||
|       is no protection between guests. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       In the basic model, all QEMU virtual machines run under the confined | ||||
|       domain <code>root:system_r:qemu_t</code>. It is required that any | ||||
|       disk image assigned to a QEMU virtual machine is labelled with | ||||
|       <code>system_u:object_r:virt_image_t</code>. In a default deployment, | ||||
|       package vendors/distributor will typically ensure that the directory | ||||
|       <code>/var/lib/libvirt/images</code> has this label, such that any | ||||
|       disk images created in this directory will automatically inherit the | ||||
|       correct labelling. If attempting to use disk images in another | ||||
|       location, the user/administrator must ensure the directory has be | ||||
|       given this requisite label. Likewise physical block devices must | ||||
|       be labelled <code>system_u:object_r:virt_image_t</code>. | ||||
|     </p> | ||||
|     <p> | ||||
|       Not all filesystems allow for labelling of individual files. In | ||||
|       particular NFS, VFat and NTFS have no support for labelling. In | ||||
|       these cases administrators must use the 'context' option when | ||||
|       mounting the filesystem to set the default label to | ||||
|       <code>system_u:object_r:virt_image_t</code>. In the case of | ||||
|       NFS, there is an alternative option, of enabling the <code>virt_use_nfs</code> | ||||
|       SELinux boolean. | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="securitysvirt">SELinux sVirt confinement</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       The SELinux sVirt protection for QEMU virtual machines builds to the | ||||
|       basic level of protection, to also allow individual guests to be | ||||
|       protected from each other. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       In the sVirt model, each QEMU virtual machine runs under its own | ||||
|       confined domain, which is based on <code>system_u:system_r:svirt_t:s0</code> | ||||
|       with a unique category appended, eg, <code>system_u:system_r:svirt_t:s0:c34,c44</code>. | ||||
|       The rules are setup such that a domain can only access files which are | ||||
|       labelled with the matching category level, eg | ||||
|       <code>system_u:object_r:svirt_image_t:s0:c34,c44</code>. This prevents one | ||||
|       QEMU process accessing any file resources that are prevent to another QEMU | ||||
|       process. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       There are two ways of assigning labels to virtual machines under sVirt. | ||||
|       In the default setup, if sVirt is enabled, guests will get an automatically | ||||
|       assigned unique label each time they are booted. The libvirtd daemon will | ||||
|       also automatically relabel exclusive access disk images to match this | ||||
|       label.  Disks that are marked as <shared> will get a generic | ||||
|       label <code>system_u:system_r:svirt_image_t:s0</code> allowing all guests | ||||
|       read/write access them, while disks marked as <readonly> will | ||||
|       get a generic label <code>system_u:system_r:svirt_content_t:s0</code> | ||||
|       which allows all guests read-only access. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       With statically assigned labels, the application should include the | ||||
|       desired guest and file labels in the XML at time of creating the | ||||
|       guest with libvirt. In this scenario the application is responsible | ||||
|       for ensuring the disk images & similar resources are suitably | ||||
|       labelled to match, libvirtd will not attempt any relabelling. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       If the sVirt security model is active, then the node capabilities | ||||
|       XML will include its details. If a virtual machine is currently | ||||
|       protected by the security model, then the guest XML will include | ||||
|       its assigned labels. If enabled at compile time, the sVirt security | ||||
|       model will always be activated if SELinux is available on the host | ||||
|       OS. To disable sVirt, and revert to the basic level of SELinux | ||||
|       protection (host protection only), the <code>/etc/libvirt/qemu.conf</code> | ||||
|       file can be used to change the setting to <code>security_driver="none"</code> | ||||
|     </p> | ||||
|  | ||||
|     <h3><a name="securitysvirtaa">AppArmor sVirt confinement</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       When using basic AppArmor protection for the libvirtd daemon and | ||||
|       QEMU virtual machines, the intention is to protect the host OS | ||||
|       from a compromised virtual machine process. There is no protection | ||||
|       between guests. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       The AppArmor sVirt protection for QEMU virtual machines builds on | ||||
|       this basic level of protection, to also allow individual guests to | ||||
|       be protected from each other. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       In the sVirt model, if a profile is loaded for the libvirtd daemon, | ||||
|       then each <code>qemu:///system</code> QEMU virtual machine will have | ||||
|       a profile created for it when the virtual machine is started if one | ||||
|       does not already exist. This generated profile uses a profile name | ||||
|       based on the UUID of the QEMU virtual machine and contains rules | ||||
|       allowing access to only the files it needs to run, such as its disks, | ||||
|       pid file and log files. Just before the QEMU virtual machine is | ||||
|       started, the libvirtd daemon will change into this unique profile, | ||||
|       preventing the QEMU process from accessing any file resources that | ||||
|       are present in another QEMU process or the host machine. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       The AppArmor sVirt implementation is flexible in that it allows an | ||||
|       administrator to customize the template file in | ||||
|       <code>/etc/apparmor.d/libvirt/TEMPLATE</code> for site-specific | ||||
|       access for all newly created QEMU virtual machines. Also, when a new | ||||
|       profile is generated, two files are created: | ||||
|       <code>/etc/apparmor.d/libvirt/libvirt-<uuid></code> and | ||||
|       <code>/etc/apparmor.d/libvirt/libvirt-<uuid>.files</code>. The | ||||
|       former can be fine-tuned by the administrator to allow custom access | ||||
|       for this particular QEMU virtual machine, and the latter will be | ||||
|       updated appropriately when required file access changes, such as when | ||||
|       a disk is added. This flexibility allows for situations such as | ||||
|       having one virtual machine in complain mode with all others in | ||||
|       enforce mode. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       While users can define their own AppArmor profile scheme, a typical | ||||
|       configuration will include a profile for <code>/usr/sbin/libvirtd</code>, | ||||
|       <code>/usr/lib/libvirt/virt-aa-helper</code> (a helper program which the | ||||
|       libvirtd daemon uses instead of manipulating AppArmor directly), and | ||||
|       an abstraction to be included by <code>/etc/apparmor.d/libvirt/TEMPLATE</code> | ||||
|       (typically <code>/etc/apparmor.d/abstractions/libvirt-qemu</code>). | ||||
|       An example profile scheme can be found in the examples/apparmor | ||||
|       directory of the source distribution. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       If the sVirt security model is active, then the node capabilities | ||||
|       XML will include its details. If a virtual machine is currently | ||||
|       protected by the security model, then the guest XML will include | ||||
|       its assigned profile name. If enabled at compile time, the sVirt | ||||
|       security model will be activated if AppArmor is available on the host | ||||
|       OS and a profile for the libvirtd daemon is loaded when libvirtd is | ||||
|       started. To disable sVirt, and revert to the basic level of AppArmor | ||||
|       protection (host protection only), the <code>/etc/libvirt/qemu.conf</code> | ||||
|       file can be used to change the setting to <code>security_driver="none"</code>. | ||||
|     </p> | ||||
|  | ||||
|  | ||||
|     <h3><a name="securityacl">Cgroups device ACLs</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       Recent Linux kernels have a capability known as "cgroups" which is used | ||||
|       for resource management. It is implemented via a number of "controllers", | ||||
|       each controller covering a specific task/functional area. One of the | ||||
|       available controllers is the "devices" controller, which is able to | ||||
|       setup whitelists of block/character devices that a cgroup should be | ||||
|       allowed to access. If the "devices" controller is mounted on a host, | ||||
|       then libvirt will automatically create a dedicated cgroup for each | ||||
|       QEMU virtual machine and setup the device whitelist so that the QEMU | ||||
|       process can only access shared devices, and explicitly disks images | ||||
|       backed by block devices. | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       The list of shared devices a guest is allowed access to is | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| /dev/null, /dev/full, /dev/zero, | ||||
| /dev/random, /dev/urandom, | ||||
| /dev/ptmx, /dev/kvm, /dev/kqemu, | ||||
| /dev/rtc, /dev/hpet, /dev/net/tun | ||||
| </pre> | ||||
|  | ||||
|     <p> | ||||
|       In the event of unanticipated needs arising, this can be customized | ||||
|       via the <code>/etc/libvirt/qemu.conf</code> file. | ||||
|       To mount the cgroups device controller, the following command | ||||
|       should be run as root, prior to starting libvirtd | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| mkdir /dev/cgroup | ||||
| mount -t cgroup none /dev/cgroup -o devices | ||||
| </pre> | ||||
|  | ||||
|     <p> | ||||
|       libvirt will then place each virtual machine in a cgroup at | ||||
|       <code>/dev/cgroup/libvirt/qemu/$VMNAME/</code> | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="imex">Import and export of libvirt domain XML configs</a></h2> | ||||
|  | ||||
|     <p>The QEMU driver currently supports a single native | ||||
|       config format known as <code>qemu-argv</code>. The data for this format | ||||
|       is expected to be a single line first a list of environment variables, | ||||
|       then the QEMu binary name, finally followed by the QEMU command line | ||||
|       arguments</p> | ||||
|  | ||||
|     <h3><a name="xmlimport">Converting from QEMU args to domain XML</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       The <code>virsh domxml-from-native</code> provides a way to convert an | ||||
|       existing set of QEMU args into a guest description using libvirt Domain XML | ||||
|       that can then be used by libvirt. | ||||
|     </p> | ||||
|  | ||||
|     <pre>$ cat > demo.args <<EOF | ||||
| LC_ALL=C PATH=/bin HOME=/home/test USER=test \ | ||||
| LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 \ | ||||
| -nographic -monitor pty -no-acpi -boot c -hda \ | ||||
| /dev/HostVG/QEMUGuest1 -net none -serial none \ | ||||
| -parallel none -usb | ||||
| EOF | ||||
|  | ||||
| $ virsh domxml-from-native qemu-argv demo.args | ||||
| <domain type='qemu'> | ||||
|   <uuid>00000000-0000-0000-0000-000000000000</uuid> | ||||
|   <memory>219136</memory> | ||||
|   <currentMemory>219136</currentMemory> | ||||
|   <vcpu>1</vcpu> | ||||
|   <os> | ||||
|     <type arch='i686' machine='pc'>hvm</type> | ||||
|     <boot dev='hd'/> | ||||
|   </os> | ||||
|   <clock offset='utc'/> | ||||
|   <on_poweroff>destroy</on_poweroff> | ||||
|   <on_reboot>restart</on_reboot> | ||||
|   <on_crash>destroy</on_crash> | ||||
|   <devices> | ||||
|     <emulator>/usr/bin/qemu</emulator> | ||||
|     <disk type='block' device='disk'> | ||||
|       <source dev='/dev/HostVG/QEMUGuest1'/> | ||||
|       <target dev='hda' bus='ide'/> | ||||
|     </disk> | ||||
|   </devices> | ||||
| </domain> | ||||
| </pre> | ||||
|  | ||||
|     <p>NB, don't include the literral \ in the args, put everything on one line</p> | ||||
|  | ||||
|     <h3><a name="xmlexport">Converting from domain XML to QEMU args</a></h3> | ||||
|  | ||||
|     <p> | ||||
|       The <code>virsh domxml-to-native</code> provides a way to convert a | ||||
|       guest description using libvirt Domain XML, into a set of QEMU args | ||||
|       that can be run manually. | ||||
|     </p> | ||||
|  | ||||
|     <pre>$ cat > demo.xml <<EOF | ||||
| <domain type='qemu'> | ||||
|   <name>QEMUGuest1</name> | ||||
|   <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> | ||||
|   <memory>219200</memory> | ||||
|   <currentMemory>219200</currentMemory> | ||||
|   <vcpu>1</vcpu> | ||||
|   <os> | ||||
|     <type arch='i686' machine='pc'>hvm</type> | ||||
|     <boot dev='hd'/> | ||||
|   </os> | ||||
|   <clock offset='utc'/> | ||||
|   <on_poweroff>destroy</on_poweroff> | ||||
|   <on_reboot>restart</on_reboot> | ||||
|   <on_crash>destroy</on_crash> | ||||
|   <devices> | ||||
|     <emulator>/usr/bin/qemu</emulator> | ||||
|     <disk type='block' device='disk'> | ||||
|       <source dev='/dev/HostVG/QEMUGuest1'/> | ||||
|       <target dev='hda' bus='ide'/> | ||||
|     </disk> | ||||
|   </devices> | ||||
| </domain> | ||||
| EOF | ||||
|  | ||||
| $ virsh domxml-to-native qemu-argv demo.xml | ||||
|   LC_ALL=C PATH=/usr/bin:/bin HOME=/home/test \ | ||||
|   USER=test LOGNAME=test /usr/bin/qemu -S -M pc \ | ||||
|   -no-kqemu -m 214 -smp 1 -name QEMUGuest1 -nographic \ | ||||
|   -monitor pty -no-acpi -boot c -drive \ | ||||
|   file=/dev/HostVG/QEMUGuest1,if=ide,index=0 -net none \ | ||||
|   -serial none -parallel none -usb | ||||
| </pre> | ||||
|  | ||||
|     <h2><a name="xmlconfig">Example domain XML config</a></h2> | ||||
|  | ||||
|     <h3>QEMU emulated guest on x86_64</h3> | ||||
|  | ||||
|         <pre><domain type='qemu'> | ||||
|   <name>QEmu-fedora-i686</name> | ||||
|   <uuid>c7a5fdbd-cdaf-9455-926a-d65c16db1809</uuid> | ||||
|   <memory>219200</memory> | ||||
|   <currentMemory>219200</currentMemory> | ||||
|   <vcpu>2</vcpu> | ||||
|   <os> | ||||
|     <type arch='i686' machine='pc'>hvm</type> | ||||
|     <boot dev='cdrom'/> | ||||
|   </os> | ||||
|   <devices> | ||||
|     <emulator>/usr/bin/qemu-system-x86_64</emulator> | ||||
|     <disk type='file' device='cdrom'> | ||||
|       <source file='/home/user/boot.iso'/> | ||||
|       <target dev='hdc'/> | ||||
|       <readonly/> | ||||
|     </disk> | ||||
|     <disk type='file' device='disk'> | ||||
|       <source file='/home/user/fedora.img'/> | ||||
|       <target dev='hda'/> | ||||
|     </disk> | ||||
|     <interface type='network'> | ||||
|       <source network='default'/> | ||||
|     </interface> | ||||
|     <graphics type='vnc' port='-1'/> | ||||
|   </devices> | ||||
| </domain></pre> | ||||
|  | ||||
|     <h3>KVM hardware accelerated guest on i686</h3> | ||||
|  | ||||
|         <pre><domain type='kvm'> | ||||
|   <name>demo2</name> | ||||
|   <uuid>4dea24b3-1d52-d8f3-2516-782e98a23fa0</uuid> | ||||
|   <memory>131072</memory> | ||||
|   <vcpu>1</vcpu> | ||||
|   <os> | ||||
|     <type arch="i686">hvm</type> | ||||
|   </os> | ||||
|   <clock sync="localtime"/> | ||||
|   <devices> | ||||
|     <emulator>/usr/bin/qemu-kvm</emulator> | ||||
|     <disk type='file' device='disk'> | ||||
|       <source file='/var/lib/libvirt/images/demo2.img'/> | ||||
|       <target dev='hda'/> | ||||
|     </disk> | ||||
|     <interface type='network'> | ||||
|       <source network='default'/> | ||||
|       <mac address='24:42:53:21:52:45'/> | ||||
|     </interface> | ||||
|     <graphics type='vnc' port='-1' keymap='de'/> | ||||
|   </devices> | ||||
| </domain></pre> | ||||
|  | ||||
|     <h3>Xen paravirtualized guests with hardware acceleration</h3> | ||||
|  | ||||
|  | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,5 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Remote management driver</h1> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,25 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>Test "mock" driver</h1> | ||||
|  | ||||
|     <h2>Connections to Test driver</h2> | ||||
|  | ||||
|     <p> | ||||
|     The libvirt Test driver is a per-process fake hypervisor driver, | ||||
|     with a driver name of 'test'. The driver maintains all its state | ||||
|     in memory. It can start with a pre-configured default config, or | ||||
|     be given a path to a alternate config. Some example conection URIs | ||||
|     for the libvirt driver are: | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| test:///default                     (local access, default config) | ||||
| test:///path/to/driver/config.xml   (local access, custom config) | ||||
| test+unix:///default                (local access, default config, via daemon) | ||||
| test://example.com/default          (remote access, TLS/x509) | ||||
| test+tcp://example.com/default      (remote access, SASl/Kerberos) | ||||
| test+ssh://root@example.com/default (remote access, SSH tunnelled) | ||||
| </pre> | ||||
|  | ||||
|   </body> | ||||
| </html> | ||||
| @@ -1,91 +0,0 @@ | ||||
| <html> | ||||
|   <body> | ||||
|     <h1>User Mode Linux driver</h1> | ||||
|  | ||||
|     <p> | ||||
|     The UML driver for libvirt allows use and management of paravirtualized | ||||
|     guests built for User Mode Linux. UML requires no special support in | ||||
|     the host kernel, so can be used by any user of any linux system, provided | ||||
|     they have enough free RAM for their guest's needs, though there are | ||||
|     certain restrictions on network connectivity unless the administrator | ||||
|     has pre-created TAP devices. | ||||
|     </p> | ||||
|  | ||||
|     <h2><a name="project">Project Links</a></h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         The <a href="http://user-mode-linux.sourceforge.net/">User | ||||
|         Mode Linux</a> paravirtualized kernel | ||||
|       </li> | ||||
|     </ul> | ||||
|  | ||||
|     <h2>Connections to UML driver</h2> | ||||
|  | ||||
|     <p> | ||||
|     The libvirt UML driver follows the QEMU driver in providing two | ||||
|     types of connection. There is one privileged instance per host, | ||||
|     which runs as root. This is called the "system" instance, and allows | ||||
|     full use of all host resources. Then, there is a per-user unprivileged | ||||
|     "session", instance. This has more restricted capabilities, and may | ||||
|     require the host administrator to setup certain resources ahead of | ||||
|     time to allow full integration with the network. Example connection | ||||
|     URIs are | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| uml:///session                       (local access to per-user instance) | ||||
| uml+unix:///session                  (local access to per-user instance) | ||||
|  | ||||
| uml:///system                        (local access to system instance) | ||||
| uml+unix:///system                   (local access to system instance) | ||||
| uml://example.com/system             (remote access, TLS/x509) | ||||
| uml+tcp://example.com/system         (remote access, SASl/Kerberos) | ||||
| uml+ssh://root@example.com/system    (remote access, SSH tunnelled) | ||||
| </pre> | ||||
|  | ||||
|     <h2>Example XML configuration</h2> | ||||
|  | ||||
|     <p> | ||||
|       User mode Linux driver only supports directly kernel boot at | ||||
|       this time. A future driver enhancement may allow a paravirt | ||||
|       bootloader in a similar style to Xen's pygrub. For now though, | ||||
|       the UML kernel must be stored on the host and referenced | ||||
|       explicitly in the "os" element. Since UML is a paravirtualized | ||||
|       technology, the kernel "type" is set to "uml" | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       There is not yet support for networking in the driver, but | ||||
|       disks can be specified in the usual libvirt manner. The main | ||||
|       variation is the target device naming scheme "ubd0", and | ||||
|       bus type of "uml". | ||||
|     </p> | ||||
|  | ||||
|     <p> | ||||
|       Once booted the primary console is connected toa PTY, and | ||||
|       thus accessible with "virsh console" or equivalent tools | ||||
|     </p> | ||||
|  | ||||
| <pre> | ||||
| <domain type='uml'> | ||||
|   <name>demo</name> | ||||
|   <uuid>b4433fc2-a22e-ffb3-0a3d-9c173b395800</uuid> | ||||
|   <memory>500000</memory> | ||||
|   <currentMemory>500000</currentMemory> | ||||
|   <vcpu>1</vcpu> | ||||
|   <os> | ||||
|     <type arch='x86_64'>uml</type> | ||||
|     <kernel>/home/berrange/linux-uml-2.6.26-x86_64</kernel> | ||||
|   </os> | ||||
|   <devices> | ||||
|     <disk type='file' device='disk'> | ||||
|       <source file='/home/berrange/FedoraCore6-AMD64-root_fs'/> | ||||
|       <target dev='ubd0' bus='uml'/> | ||||
|     </disk> | ||||
|     <console type='pty'/> | ||||
|   </devices> | ||||
| </domain> | ||||
| </pre> | ||||
|   </body> | ||||
| </html> | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user