commit 920dbf83288bbd27414382a92b41438e37f914b2
Author: W. David Ashley <w.david.ashley(a)gmail.com>
Date: Fri Jun 26 15:33:03 2015 -0500
Mass changes to Connections.xml and added two extra chapters.
en-US/Connections.xml | 4225 +++++++-------------
en-US/Error_Handling.xml | 306 ++
en-US/Event_Handling.xml | 11 +
..._Application_Development_Guide_Using_Python.xml | 2 +
en-US/extras/Connections-Example-1.py | 11 +
en-US/extras/Connections-Example-10.py | 15 +
en-US/extras/Connections-Example-11.py | 15 +
en-US/extras/Connections-Example-12.py | 23 +
en-US/extras/Connections-Example-13.py | 21 +
en-US/extras/Connections-Example-14.py | 14 +
en-US/extras/Connections-Example-15.py | 15 +
en-US/extras/Connections-Example-16.py | 15 +
en-US/extras/Connections-Example-17.py | 15 +
en-US/extras/Connections-Example-18.py | 14 +
en-US/extras/Connections-Example-19.py | 14 +
en-US/extras/Connections-Example-2.py | 11 +
en-US/extras/Connections-Example-20.py | 17 +
en-US/extras/Connections-Example-3.py | 24 +
en-US/extras/Connections-Example-5.py | 16 +
en-US/extras/Connections-Example-6.py | 11 +
en-US/extras/Connections-Example-7.py | 11 +
en-US/extras/Connections-Example-8.py | 15 +
en-US/extras/Connections-Example-8.xml | 64 +
en-US/extras/Connections-Example-9.py | 15 +
en-US/extras/Error-Example-24.py | 16 +
25 files changed, 2156 insertions(+), 2760 deletions(-)
---
diff --git a/en-US/Connections.xml b/en-US/Connections.xml
index a2b3c08..a6c2fb3 100644
--- a/en-US/Connections.xml
+++ b/en-US/Connections.xml
@@ -4,2833 +4,1538 @@
%BOOK_ENTITIES;
]>
<chapter
id="libvirt_application_development_guide_using_python-Connections">
- <title>Connections</title>
- <para>
- In libvirt, a connection is the underpinning of every action and
- object in the system. Every entity that wants to interact with
- libvirt, be it virsh, virt-manager, or a program using the libvirt
- library, needs to first obtain a connection to the libvirt daemon on
- the host it is interested in interacting with. A connection describes
- not only the type of virtualization technology that the agent wants to
- interact with (qemu, xen, uml, etc), but also describes any
- authentication methods necessary to connect to that resource.
- </para>
- <section
id="libvirt_application_development_guide_using_python-Connections-Overview">
- <title>Overview</title>
+ <title>Connections</title>
<para>
- The very first thing a libvirt agent must do is call one of the
- libvirt connection functions to obtain a
<literal>virConnectPtr</literal> handle. This
- handle will be used in subsequent operations. The libvirt library
- provides 3 different functions for connecting to a resource:
+ In libvirt, a connection is the underpinning of every action and
+ object in the system. Every entity that wants to interact with
+ libvirt, be it virsh, virt-manager, or a program using the libvirt
+ library, needs to first obtain a connection to the libvirt daemon on
+ the host it is interested in interacting with. A connection describes
+ not only the type of virtualization technology that the agent wants to
+ interact with (qemu, xen, uml, etc), but also describes any
+ authentication methods necessary to connect to that resource.
</para>
- <programlisting>
-<![CDATA[ virConnectPtr virConnectOpen(const char *name)
- virConnectPtr virConnectOpenReadOnly(const char *name)
- virConnectPtr virConnectOpenAuth(const char *name, virConnectAuthPtr auth, int flags)
-]]>
- </programlisting>
- <para>
- In all three cases there is a <literal>name</literal> parameter
- which in fact refers to the URI of the hypervisor to connect
- to. The previous sections <xref
linkend="libvirt_application_development_guide_using_python-Architecture-Driver_Model"/>
- and <xref
linkend="libvirt_application_development_guide_using_python-Connections-Remote_URIs"/>
provide
- full details on the various URI formats that are acceptable.
- If the URI is NULL
- then libvirt will apply some heuristics and probe for a suitable
- hypervisor driver. While this may be convenient for developers doing
- adhoc testing, it is strongly recommended that applications do not
- rely on probing logic since it may change at any time. Applications
- should always explicitly request which hypervisor connection is
- desired by providing a URI.
- </para>
- <para>
- The difference between the three methods outlined above is the way in
- which they authenticate and the resulting authorization level they
- provide.
- </para>
- <section>
- <title>virConnectOpen</title>
- <para>
- The <literal>virConnectOpen</literal> API will attempt to open a
- connection for full read-write access. It does not have any scope for
- authentication callbacks to be provided, so it will only succeed for
- connections where authentication can be done based on the credentials
- of the application.
- </para>
- <example>
- <title>Using virConnectOpen</title>
- <programlisting><![CDATA[/* example ex1.c */
-/* compile with: gcc -g -Wall ex1.c -o ex -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- <para>
-The above example opens up a read-write connection to the system qemu hypervisor driver,
checks to make sure it was successful, and if so closes the connection. For more
information on libvirt URIs, refer to <xref
linkend="libvirt_application_development_guide_using_python-Connections-URI_Formats"
/>.
- </para>
- </section>
- <section>
- <title>virConnectOpenReadOnly</title>
- <para>
- The <literal>virConnectOpenReadOnly</literal> API will attempt to
open a connection
- for read-only access. Such a connection has a restricted set of API
- calls that are allowed, and is typically useful for monitoring
- applications that should not be allowed to make changes. As with
- <literal>virConnectOpen</literal>, this API has no scope for
authentication callbacks, so
- relies on credentials.
- </para>
- <example>
- <title>Using virConnectOpenReadOnly</title>
- <programlisting><![CDATA[/* example ex2.c */
-/* compile with: gcc -g -Wall ex2.c -o ex2 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- conn = virConnectOpenReadOnly("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- <para>
- The above example opens up a read-only connection to the system qemu hypervisor
driver, checks to make sure it was successful, and if so closes the connection. For more
information on libvirt URIs, refer to <xref
linkend="libvirt_application_development_guide_using_python-Connections-URI_Formats"
/>.
- </para>
- </section>
- <section>
- <title>virConnectOpenAuth</title>
- <para>
- The <literal>virConnectOpenAuth</literal> API is the most flexible,
and effectively
- obsoletes the previous two APIs. It takes an extra parameter providing
- an instance of the <literal>virConnectAuthPtr</literal> struct which
contains the
- callbacks for collecting authentication credentials from the client
- app. This allows libvirt to prompt for usernames, passwords, and
- more. The libvirt API provides an instance of this struct via the
- symbol <literal>virConnectAuthPtrDefault</literal> that implements
callbacks suitable for
- a command line based application. Graphical applications will need to
- provide their own callback implementations. The flags parameter allows
- the application to request a read-only connection with the
- <parameter>VIR_CONNECT_RO</parameter> flag if desired. A simple
example C program that uses
- <literal>virConnectOpenAuth</literal> with the default
<literal>virConnectAuthPtrDefault</literal> is
- </para>
- <example id="virtConnectOpenAuth-Example1">
- <title>Using virConnectOpenAuth</title>
- <programlisting><![CDATA[/* example ex3.c */
-/* compile with: gcc -g -Wall ex3.c -o ex3 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
+ <section
id="libvirt_application_development_guide_using_python-Connections-Overview">
+ <title>Overview</title>
+ <para>
+ The very first thing a libvirt agent must do is call one of the
+ Python libvirt connection functions to obtain an instance of the
<literal>virConnect</literal>
+ class. This instance will be used in subsequent operations. The Python
libvirt module
+ provides 3 different functions for connecting to a resource:
+ </para>
+ <programlisting language="Python">conn = libvirt.open(name)
+conn = libvirt.openAuth(uri, auth, flags)
+conn = libvirt.openReadOnly(name)</programlisting>
+ <para>
+ In all three cases there is a <literal>name</literal> parameter
+ which in fact refers to the URI of the hypervisor to connect
+ to. The previous sections <xref
linkend="libvirt_application_development_guide_using_python-Architecture-Driver_Model"/>
+ and <xref
linkend="libvirt_application_development_guide_using_python-Connections-Remote_URIs"/>
provide
+ full details on the various URI formats that are acceptable.
+ If the URI is <code language="Python">None</code>
+ then libvirt will apply some heuristics and probe for a suitable
+ hypervisor driver. While this may be convenient for developers doing
+ adhoc testing, it is strongly recommended that applications do not
+ rely on probing logic since it may change at any time. Applications
+ should always explicitly request which hypervisor connection is
+ desired by providing a URI.
+ </para>
+ <para>
+ The difference between the three methods outlined above is the way in
+ which they authenticate and the resulting authorization level they
+ provide.
+ </para>
- conn = virConnectOpenAuth("qemu+tcp://localhost/system",
virConnectAuthPtrDefault, 0);
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to
qemu+tcp://localhost/system\n");
- return 1;
- }
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- <para>
- To test the above program, the following configuration must be present:
- </para>
- <orderedlist>
- <listitem>
-
<para><filename>/etc/libvirt/libvirtd.conf</filename></para>
- <screen>listen_tls = 0
+ <section>
+ <title>open</title>
+ <para>
+ The <literal>open</literal> function will attempt to open a
+ connection for full read-write access. It does not have any scope for
+ authentication callbacks to be provided, so it will only succeed for
+ connections where authentication can be done based on the credentials
+ of the application.
+ </para>
+ <example>
+ <title>Using open</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-1.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ The above example opens up a read-write connection to the system qemu
hypervisor driver,
+ checks to make sure it was successful, and if so closes the connection.
For more information
+ on libvirt URIs, refer to
+ <xref
linkend="libvirt_application_development_guide_using_python-Connections-URI_Formats"
/>.
+ </para>
+ </section>
+
+ <section>
+ <title>openReadOnly</title>
+ <para>
+ The <literal>openReadOnly</literal> function will attempt to
open a connection
+ for read-only access. Such a connection has a restricted set of method
+ calls that are allowed, and is typically useful for monitoring
+ applications that should not be allowed to make changes. As with
+ <literal>open</literal>, this API has no scope for
authentication callbacks, so
+ relies on credentials.
+ </para>
+ <example>
+ <title>Using ppenReadOnly</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-2.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ The above example opens up a read-only connection to the system qemu
hypervisor driver, checks
+ to make sure it was successful, and if so closes the connection. For more
information on libvirt
+ URIs, refer to
+ <xref
linkend="libvirt_application_development_guide_using_python-Connections-URI_Formats"
/>.
+ </para>
+ </section>
+
+ <section>
+ <title>openAuth</title>
+ <para>
+ The <literal>openAuth</literal> function is the most
flexible, and effectively
+ obsoletes the previous two cunctions. It takes an extra parameter
providing
+ an Python <literal>List</literal> which contains the
authentication credentials from the
+ client app. The flags parameter allows
+ the application to request a read-only connection with the
+ <parameter>VIR_CONNECT_RO</parameter> flag if desired. A
simple example Python program that uses
+ <literal>openAuth</literal> with username and password
credentials follows. As with
+ <literal>open</literal>, this API has no scope for
authentication callbacks, so
+ relies on credentials.
+ </para>
+ <example id="openAuth-Example1">
+ <title>Using openAuth</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-3.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ To test the above program, the following configuration must be present:
+ </para>
+ <orderedlist>
+ <listitem>
+
<para><filename>/etc/libvirt/libvirtd.conf</filename></para>
+ <screen>listen_tls = 0
listen_tcp = 1
auth_tcp = "sasl"</screen>
- </listitem>
- <listitem>
-
<para><filename>/etc/sasl2/libvirt.conf</filename></para>
- <screen>mech_list: digest-md5</screen>
- </listitem>
- <listitem>
- <para>A virt user has been added to the SASL database:</para>
- <screen><command># saslpasswd2 -a libvirt virt # this will prompt
for a password</command></screen>
- </listitem>
- <listitem>
- <para>libvirtd has been started with
<parameter>--listen</parameter></para>
- </listitem>
- </orderedlist>
- <para>
- Once the above is configured, <xref
linkend="virtConnectOpenAuth-Example1" /> should prompt for a username
- and password and allow read-write access to libvirtd.
- </para>
- <para>
- If additional functionality is needed, a custom credential callback can also be
- provided as in the following program:
- </para>
- <example id="virtConnectOpenAuth-Example2">
- <title>Using a custom credential callback with
virConnectOpenAuth</title>
- <programlisting><![CDATA[/* example ex4.c */
-/* compile with: gcc -g -Wall ex4.c -o ex4 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <string.h>
-
-static int authCreds[] = {
- VIR_CRED_AUTHNAME,
- VIR_CRED_PASSPHRASE,
-};
-
-static int authCb(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata)
-{
- int i;
- char buf[1024];
-
- for (i = 0; i < ncred; i++) {
- if (cred[i].type == VIR_CRED_AUTHNAME) {
- printf("%s: ", cred[i].prompt);
- fflush(stdout);
- fgets(buf, sizeof(buf), stdin);
- buf[strlen(buf) - 1] = '\0';
- cred[i].result = strdup(buf);
- if (cred[i].result == NULL)
- return -1;
- cred[i].resultlen = strlen(cred[i].result);
- }
- else if (cred[i].type == VIR_CRED_PASSPHRASE) {
- printf("%s: ", cred[i].prompt);
- fflush(stdout);
- fgets(buf, sizeof(buf), stdin);
- buf[strlen(buf) - 1] = '\0';
- cred[i].result = strdup(buf);
- if (cred[i].result == NULL)
- return -1;
- cred[i].resultlen = strlen(cred[i].result);
- }
- }
-
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virConnectAuth auth;
-
- auth.credtype = authCreds;
- auth.ncredtype = sizeof(authCreds)/sizeof(int);
- auth.cb = authCb;
- auth.cbdata = NULL;
-
- conn = virConnectOpenAuth("qemu+tcp://localhost/system", &auth, 0);
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to
qemu+tcp://localhost/system\n");
- return 1;
- }
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- <para>
- The same configuration as <xref
linkend="virtConnectOpenAuth-Example1" /> must be present in order to test
- <xref linkend="virtConnectOpenAuth-Example2" />. The first thing
to note here is the use of a
- <literal>virConnectAuth</literal> structure, which looks like the
following:
- </para>
- <programlisting><![CDATA[struct _virConnectAuth {
- int *credtype; /* List of supported virConnectCredentialType values */
- unsigned int ncredtype;
-
- virConnectAuthCallbackPtr cb; /* Callback used to collect credentials */
- void *cbdata;
-};
-typedef struct _virConnectAuth virConnectAuth;]]></programlisting>
- <para>
- The credtype member points to an array of integers that represent the
- type of credentials this callback is willing to support. In <xref
linkend="virtConnectOpenAuth-Example2" />
- the authCreds array specifies all of the types that authCb supports;
- the full list of credential types is available in libvirt.h. The
- ncredtype member specifies the size of the credtype array. The cb
- member is a function pointer which specifies the callback that will be
- used when necessary; its signature must be:
- </para>
- <programlisting><![CDATA[typedef int
(*virConnectAuthCallbackPtr)(virConnectCredentialPtr cred,
- unsigned int ncred,
- void *cbdata);]]></programlisting>
- <para>
- Finally, the cbdata member is a pointer that can point to additional
- data needed by the callback; in <xref
linkend="virtConnectOpenAuth-Example2" />, this is not used so it is
- set to NULL.
- </para>
- <para>
- After setting up the auth structure, <xref
linkend="virtConnectOpenAuth-Example2" /> goes on to use this
- structure in the <literal>virConnectOpenAuth</literal> function.
When the libvirt
- internals require credentials, the callback in auth.cb (authCb) will
- be called. The cred parameter to this function is an array of
- <literal>virConnectCredential</literal> structures (described below)
that libvirt needs
- to finish the authentication. The ncred parameter specifies
- the size of the cred array. Finally, the cbdata parameter is a
- pointer that contains the value passed in from auth.cbdata.
- </para>
- <para>
- It is the responsibility of the auth.cb callback to examine each of
- the <literal>virConnectCredential</literal> structures and collect
the necessary
- credentials. The <literal>virConnectCredential</literal> structure
looks like:
- </para>
- <programlisting><![CDATA[struct _virConnectCredential {
- int type; /* One of virConnectCredentialType constants */
- const char *prompt; /* Prompt to show to user */
- const char *challenge; /* Additional challenge to show */
- const char *defresult; /* Optional default result */
- char *result; /* Result to be filled with user response (or defresult) */
- unsigned int resultlen; /* Length of the result */
-};
-typedef struct _virConnectCredential virConnectCredential;]]></programlisting>
- <para>
- In the case of example 4, authCb only handles VIR_CRED_AUTHNAME and
- VIR_CRED_PASSPHRASE, so for each of these credential types it prints
- out a prompt from the credential structure, collects the information
- into a temporary buffer, and then copies that buffer into the result
- and resultlen of that particular credential. Handling a credential
- but leaving result or resultlen as 0 is a programming error. If
- collection of all credentials is successful, auth.cb should return 0;
- otherwise, it should return -1 and libvirt will fail the connection.
- </para>
+ </listitem>
+ <listitem>
+
<para><filename>/etc/sasl2/libvirt.conf</filename></para>
+ <screen>mech_list: digest-md5</screen>
+ </listitem>
+ <listitem>
+ <para>A virt user has been added to the SASL
database:</para>
+ </listitem>
+ <listitem>
+ <para>libvirtd has been started with
<parameter>--listen</parameter></para>
+ </listitem>
+ </orderedlist>
+ <para>
+ Once the above is configured, <xref
linkend="openAuth-Example1" /> can utilize the configured
+ username and password and allow read-write access to libvirtd.
+ </para>
+ <para>
+ Unlike the libvirt C interface, Python does not provide for custom
callbacks to gather
+ credentials.
+ </para>
+ </section>
+
+ <section>
+ <title>close</title>
+ <para>
+ A connection must be released by calling the
<literal>close</literal> method
+ of the <literal>virConnection</literal> class when no
+ longer required. Connections are reference counted objects, so there
should be a
+ cooresponding call to the <literal>close</literal> method for
each
+ <literal>open</literal> function call.
+ </para>
+ <example id="close-Example">
+ <title>Using close with additional references</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-5.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ Also note that every other class instance associated with a connection
+ (virDomain, virNetwork, etc) will also hold a reference on the
+ connection.
+ </para>
+ </section>
</section>
- <section>
- <title>virConnectClose</title>
- <para>
- A connection must be released by calling
<literal>virConnectClose</literal> when no
- longer required. Connections are reference counted objects, so if it
- is intended for a connection to be used from multiple threads at
- once, each additional thread should call
<literal>virConnectRef</literal> to ensure the
- connection is not freed while still in use. Every extra call to
- <literal>virConnectRef</literal> must be accompanied by a
corresponding call to
- <literal>virConnectClose</literal> to release the reference when no
longer required. An
- example program that uses additional references:
- </para>
- <example id="virtConnectClose-Example">
- <title>Using virConnectClose with additional references</title>
- <programlisting><![CDATA[/* example ex5.c */
-/* compile with: gcc -g -Wall ex5.c -o ex5 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
- /* now the connection has a single reference to it */
-
- virConnectRef(conn);
-
- /* now the connection has two references to it */
-
- virConnectClose(conn);
-
- /* now the connection has one reference */
-
- virConnectClose(conn);
-
- /* now the connection has no references, and has been garbage
- * collected - it should no longer be used */
-
- return 0;
-}]]></programlisting>
- </example>
- <para>
- Also note that every other object associated with a connection
- (virDomainPtr, virNetworkPtr, etc) will also hold a reference on the
- connection. To avoid leaking a connection object, applications must
- ensure all associated objects are also freed.
- </para>
- </section>
- </section>
-
- <section
id="libvirt_application_development_guide_using_python-Connections-URI_Formats">
- <title>URI formats</title>
- <para>
- Libvirt uses Uniform Resource Identifiers (URIs) to identify hypervisor
connections.
- Both local and remote hypervisors are addressed by libvirt using URIs.
- The URI scheme and path defines the hypervisor to
- connect to, while the host part of the URI determines where it is located.
- </para>
- <section
id="libvirt_application_development_guide_using_python-Connections-Local_URIs">
- <title>Local URIs</title>
- <para>
- Libvirt local URIs have one of the following forms:
- </para>
+ <section
id="libvirt_application_development_guide_using_python-Connections-URI_Formats">
+ <title>URI formats</title>
+ <para>
+ Libvirt uses Uniform Resource Identifiers (URIs) to identify hypervisor
connections.
+ Both local and remote hypervisors are addressed by libvirt using URIs.
+ The URI scheme and path defines the hypervisor to
+ connect to, while the host part of the URI determines where it is located.
+ </para>
+ <section
id="libvirt_application_development_guide_using_python-Connections-Local_URIs">
+ <title>Local URIs</title>
+ <para>
+ Libvirt local URIs have one of the following forms:
+ </para>
<screen>driver:///system
driver:///session
driver+unix:///system
driver+unix:///session</screen>
- <para>
- All other uses of the libvirt URIs are considered remote, and
- behave as such, even if connecting to localhost. See <xref
linkend="libvirt_application_development_guide_using_python-Connections-Remote_URIs"
/> for details on remote URIs.
- </para>
- <para>
- The following drivers are currently supported:
- </para>
- <table id='supporteddrivers' frame='all'>
- <title>Supported Drivers</title>
- <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' />
- <colspec colname='c2' />
- <thead>
- <row>
- <entry><para>Driver</para></entry>
- <entry><para>Description</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>qemu</para>
- </entry>
- <entry>
+ <para>
+ All other uses of the libvirt URIs are considered remote, and
+ behave as such, even if connecting to localhost. See <xref
linkend="libvirt_application_development_guide_using_python-Connections-Remote_URIs"
/> for details on remote URIs.
+ </para>
+ <para>
+ The following drivers are currently supported:
+ </para>
+ <table id='supporteddrivers' frame='all'>
+ <title>Supported Drivers</title>
+ <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' />
+ <colspec colname='c2' />
+ <thead>
+ <row>
+ <entry><para>Driver</para></entry>
+
<entry><para>Description</para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>qemu</para>
+ </entry>
+ <entry>
+ <para>
+ For managing qemu and KVM guests
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>xen</para>
+ </entry>
+ <entry>
+ <para>
+ For managing old-style (Xen 3.1 and older) Xen
guests
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>xenapi</para>
+ </entry>
+ <entry>
+ <para>
+ For managing new-style Xen guests
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>uml</para>
+ </entry>
+ <entry>
+ <para>
+ For for managing UML guests
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>lxc</para>
+ </entry>
+ <entry>
+ <para>
+ For managing Linux Containers
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>vbox</para>
+ </entry>
+ <entry>
+ <para>
+ For managing VirtualBox guests
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>openvz</para>
+ </entry>
+ <entry>
+ <para>
+ For managing OpenVZ containers
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>esx</para>
+ </entry>
+ <entry>
+ <para>
+ For managing VMware ESX guests
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>one</para>
+ </entry>
+ <entry>
+ <para>
+ For mmanaging OpenNebula guests
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>phyp</para>
+ </entry>
+ <entry>
+ <para>
+ For managing Power Hypervisor guests
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ The following example shows how to local to a QEMU hypervisor using a
local URI.
+ </para>
+ <example id="Example-Connect_Local">
+ <title>Connecting to a local QEMU hypervisor</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-6.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section
id="libvirt_application_development_guide_using_python-Connections-Remote_URIs">
+ <title>Remote URIs</title>
+
+ <para>
+ Remote URIs have the general form ("[...]" meaning an optional
part):
+ </para>
+
+
<screen>driver[+transport]://[username@][hostname][:port]/[path][?extraparameters]</screen>
+
+ <para>
+ Each component of the URI is described below.
+ </para>
+
+ <table id='uricomponents' frame='all'>
+ <title>URI components</title>
+ <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' />
+ <colspec colname='c2' />
+ <thead>
+ <row>
+
<entry><para>Component</para></entry>
+
<entry><para>Description</para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>driver</para>
+ </entry>
+ <entry>
+ <para>
+ The name of the libvirt hypervisor driver to connect
+ to. This is the same as that used in a local URI. Some
+ examples are <literal>xen</literal>,
<literal>qemu</literal>,
+ <literal>lxc</literal>,
<literal>openvz</literal>, and
+ <literal>test</literal>. As a special case,
the psuedo
+ driver name <literal>remote</literal> can
be used, which
+ will cause the remote daemon to probe for an active
+ hypervisor and pick one to use. As a general rule if
the
+ application knows what hypervisor it wants, it should
+ always specify the explicit driver name and not rely
+ on automatic probing.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>transport</para>
+ </entry>
+ <entry>
+ <para>
+ The name of one of the data transports described
earlier
+ in this section. Possible values include
+ <literal>tls</literal>,
<literal>tcp</literal>,
+ <literal>unix</literal>,
<literal>ssh</literal> and
+ <literal>ext</literal>. If omitted, it
will default to
+ <literal>tls</literal> if a hostname is
provided, or
+ <literal>unix</literal> if no hostname is
provided.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>username</para>
+ </entry>
+ <entry>
+ <para>
+ When using the SSH data transport this allows choice
of
+ a username that differs from the client's current
login
+ name.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>hostname</para>
+ </entry>
+ <entry>
+ <para>
+ The fully qualified hostname of the remote machine.
+ If using TLS with x509 certificates, or SASL with
+ the GSSAPI/Keberos plug-in, it is critical that this
+ hostname match the hostname used in the server's
+ x509 certificates / Kerberos principle. Mis-matched
+ hostnames will guarantee authentication failures.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>port</para>
+ </entry>
+ <entry>
+ <para>
+ Rarely needed, unless SSH or libvirtd has been
configured
+ to run on a non-standard TCP port. Defaults to
<literal>22</literal>
+ for the SSH data transport,
<literal>16509</literal> for the
+ TCP data transport and
<literal>16514</literal> for the TLS
+ data transport.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>path</para>
+ </entry>
+ <entry>
+ <para>
+ The path should be the same path used for the
hypervisor
+ driver's local URIs. For Xen, this is always
just
+ <literal>/</literal>, while for QEMU this
would be
+ <literal>/system</literal>.
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>extraparameters</para>
+ </entry>
+ <entry>
+ <para>
+ The URI query parameters provide the mean to fine
tune
+ some aspects of the remote connection, and are
discussed
+ in depth in the next section.
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+
+ <para>
+ Based on the information described here and with reference to the
+ hypervisor specific URIs earlier in this document, it is now possible
+ to illustrate some example remote access URIs.
+ </para>
+
+ <blockquote>
<para>
- For managing qemu and KVM guests
+ Connect to a remote Xen hypervisor on host
<replaceable>node.example.com</replaceable>
+ using ssh tunneled data transport and ssh username
<replaceable>root</replaceable>:
+ <literal>xen+ssh://root@node.example.com/</literal>
</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>xen</para>
- </entry>
- <entry>
<para>
- For managing old-style (Xen 3.1 and older) Xen guests
+ Connect to a remote QEMU hypervisor on host
<replaceable>node.example.com</replaceable>
+ using TLS with x509 certificates:
<
literal>qemu://node.example.com/system</literal>
</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>xenapi</para>
- </entry>
- <entry>
<para>
- For managing new-style Xen guests
+ Connect to a remote Xen hypervisor on host
<replaceable>node.example.com</replaceable>
+ using TLS, skipping verification of the server's x509 certificate
(NB: this is compromising
+ your security):
<
literal>xen://node.example.com/?no_verify=1</literal>
</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>uml</para>
- </entry>
- <entry>
<para>
- For for managing UML guests
+ Connect to the local QEMU instances over a non-standard Unix socket
(the full path to
+ the Unix socket is supplied explicitly in this case):
+
<literal>qemu+unix:///system?socket=/opt/libvirt/run/libvirt/libvirt-sock</literal>
</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>lxc</para>
- </entry>
- <entry>
<para>
- For managing Linux Containers
+ Connect to a libvirtd daemon offering unencrypted TCP/IP connections
on an alternative
+ TCP port 5000 and use the test driver with default configuration:
+
<literal>test+tcp://node.example.com:5000/default</literal>
</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>vbox</para>
- </entry>
- <entry>
- <para>
- For managing VirtualBox guests
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>openvz</para>
- </entry>
- <entry>
- <para>
- For managing OpenVZ containers
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>esx</para>
- </entry>
- <entry>
- <para>
- For managing VMware ESX guests
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>one</para>
- </entry>
- <entry>
- <para>
- For mmanaging OpenNebula guests
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>phyp</para>
- </entry>
- <entry>
- <para>
- For managing Power Hypervisor guests
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- The following example shows how to local to a QEMU hypervisor using a local URI.
- </para>
- <example id="Example-Connect_Local">
- <title>Connecting to a local QEMU hypervisor</title>
- <programlisting><![CDATA[/* example ex6.c */
-/* compile with: gcc -g -Wall ex6.c -o ex6 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
-
- <section
id="libvirt_application_development_guide_using_python-Connections-Remote_URIs">
- <title>Remote URIs</title>
+ </blockquote>
- <para>
- Remote URIs have the general form ("[...]" meaning an optional part):
- </para>
-
-
<screen>driver[+transport]://[username@][hostname][:port]/[path][?extraparameters]</screen>
-
- <para>
- Each component of the URI is described below.
- </para>
-
- <table id='uricomponents' frame='all'>
- <title>URI components</title>
- <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' />
- <colspec colname='c2' />
- <thead>
- <row>
- <entry><para>Component</para></entry>
- <entry><para>Description</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>driver</para>
- </entry>
- <entry>
- <para>
- The name of the libvirt hypervisor driver to connect
- to. This is the same as that used in a local URI. Some
- examples are <literal>xen</literal>,
<literal>qemu</literal>,
- <literal>lxc</literal>,
<literal>openvz</literal>, and
- <literal>test</literal>. As a special case, the psuedo
- driver name <literal>remote</literal> can be used, which
- will cause the remote daemon to probe for an active
- hypervisor and pick one to use. As a general rule if the
- application knows what hypervisor it wants, it should
- always specify the explicit driver name and not rely
- on automatic probing.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>transport</para>
- </entry>
- <entry>
- <para>
- The name of one of the data transports described earlier
- in this section. Possible values include
- <literal>tls</literal>,
<literal>tcp</literal>,
- <literal>unix</literal>, <literal>ssh</literal>
and
- <literal>ext</literal>. If omitted, it will default to
- <literal>tls</literal> if a hostname is provided, or
- <literal>unix</literal> if no hostname is provided.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>username</para>
- </entry>
- <entry>
+ <formalpara>
+ <title>Extra parameters</title>
+
<para>
- When using the SSH data transport this allows choice of
- a username that differs from the client's current login
- name.
+ Extra parameters can be added to remote URIs as part of the query
string (the part
+ following "?"). Remote URIs understand the extra parameters
shown below. Any others
+ are passed unmodified through to the backend. Note that parameter
values must be
+ URI-escaped. Refer to <ulink
url="http://xmlsoft.org/html/libxml-uri.html#xmlURIEscapeStr"/>
+ for more information.
</para>
- </entry>
- </row>
- <row>
- <entry>
- <para>hostname</para>
- </entry>
- <entry>
- <para>
- The fully qualified hostname of the remote machine.
- If using TLS with x509 certificates, or SASL with
- the GSSAPI/Keberos plug-in, it is critical that this
- hostname match the hostname used in the server's
- x509 certificates / Kerberos principle. Mis-matched
- hostnames will guarantee authentication failures.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>port</para>
- </entry>
- <entry>
- <para>
- Rarely needed, unless SSH or libvirtd has been configured
- to run on a non-standard TCP port. Defaults to
<literal>22</literal>
- for the SSH data transport, <literal>16509</literal> for
the
- TCP data transport and <literal>16514</literal> for the
TLS
- data transport.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>path</para>
- </entry>
- <entry>
- <para>
- The path should be the same path used for the hypervisor
- driver's local URIs. For Xen, this is always just
- <literal>/</literal>, while for QEMU this would be
- <literal>/system</literal>.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>extraparameters</para>
- </entry>
- <entry>
- <para>
- The URI query parameters provide the mean to fine tune
- some aspects of the remote connection, and are discussed
- in depth in the next section.
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
+ </formalpara>
+
+ <table id='remote_URI' frame='none'><title>Extra
parameters for remote URIs</title>
+ <tgroup cols='3' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' colwidth="20%"/>
+ <colspec colname='c2' colwidth="20%"/>
+ <colspec colname='c3' colwidth="60%"/>
+ <thead>
+ <row>
+ <entry><para><emphasis
role="bold">Name</emphasis></para></entry>
+ <entry><para><emphasis
role="bold">Transports</emphasis></para></entry>
+ <entry><para><emphasis
role="bold">Description</emphasis></para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><para><literal>name</literal></para></entry>
+ <entry><para><replaceable>any
transport</replaceable></para></entry>
+ <entry>
+ <para>
+ The local hypervisor URI passed to the remote
virConnectOpen function. This URI is
+ normally formed by removing transport, hostname, port
number, username and extra
+ parameters from the remote URI, but in certain very
complex cases it may be necessary
+ to supply the name explicitly. Example:
<literal>name=qemu:///system</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+
<entry><para><literal>command</literal></para></entry>
+ <entry><para>ssh, ext</para></entry>
+ <entry>
+ <para>
+ The external command. For ext transport this is
required. For ssh the default
+ is ssh. The PATH is searched for the command.
Example: <literal>command=/opt/openssh/bin/ssh</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+
<entry><para><application>socket</application></para></entry>
+ <entry>
+ <para>unix, ssh</para>
+ </entry>
+ <entry>
+ <para>
+ The external command. For ext transport this is
required. For ssh
+ the default is <literal>ssh</literal>. The
PATH is searched for
+ the command. Example:
<literal>socket=/opt/libvirt/run/libvirt/libvirt-sock</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+
<entry><para><application>netcat</application></para></entry>
+ <entry>
+ <para>ssh</para>
+ </entry>
+ <entry>
+ <para>
+ The name of the netcat command on the remote machine.
The default
+ is nc. For ssh transport, libvirt constructs an ssh
command which looks like:
+ <screen>
+command -p port [-l username] hostname netcat -U socket
+ </screen>
+ Where port, username, hostname can be specified as
part of the remote URI,
+ and command, netcat and socket come from extra
parameters (or sensible
+ defaults). Example:
<literal>netcat=/opt/netcat/bin/nc</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+
<entry><para><application>no_verify</application></para></entry>
+ <entry>
+ <para>tls</para>
+ </entry>
+ <entry>
+ <para>
+ Client checks of the server's certificate are
disable if a non-zero value
+ is set. Note that to disable server checks of the
client's certificate or
+ IP address you must change the libvirtd
configuration.
+ Example: <literal>no_verify=1</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+
<entry><para><application>no_tty</application></para></entry>
+ <entry>
+ <para>ssh</para>
+ </entry>
+ <entry>
+ <para>
+ If set to a non-zero value, this stops ssh from
asking for a password if
+ it cannot log in to the remote machine automatically
(For example, when
+ using a ssh-agent). Use this when you don't have
access to a terminal -
+ for example in graphical programs which use libvirt.
Example:
+ <literal>no_tty=1</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ The following example shows how to local to a QEMU hypervisor using a
remote URI.
+ </para>
+ <example id="Example-Connect_Remote">
+ <title>Connecting to a remote QEMU hypervisor</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-7.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+ </section>
- <para>
- Based on the information described here and with reference to the
- hypervisor specific URIs earlier in this document, it is now possible
- to illustrate some example remote access URIs.
- </para>
+ <section
id="libvirt_application_development_guide_using_python-Connections-Capability_Info">
+ <title>Capability information</title>
+ <para>
+ The <literal>getCapabilities</literal> method call can be used to
obtain
+ information about the capabilities of the virtualization host. If
+ successful, it returns a Python string
+ containing the capabilities XML (described below). If an error
+ occurred, <literal>None</literal> will be returned instead.
+ The following
+ code demonstrates the use of the
<literal>getCapabilities</literal> method:
+ </para>
+ <example id="Example-ConnectGetCapabilities">
+ <title>Using virConnectGetCapabilities</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-8.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ The capabilities XML format provides information about the host
+ virtualization technology. In particular, it describes the
+ capabilities of the virtualization host, the virtualization driver,
+ and the kinds of guests that the virtualization technology can
+ launch. Note that the capabilities XML can (and does) vary based on
+ the libvirt driver in use. An example capabilities XML looks like:
+ </para>
+ <example>
+ <title>Example QEMU driver capabilities</title>
+ <programlisting language="XML"><xi:include
href="extras/Connections-Example-8.xml" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ <para>
+ (the rest of the discussion will refer back to this XML using XPath
notation).
+ In the capabilities XML, there is always the
<literal>/host</literal> sub-document, and zero or
+ more <literal>/guest</literal> sub-documents (while zero guest
sub-documents are allowed,
+ this means that no guests of this particular driver can be started on this
+ particular host).
+ </para>
- <blockquote>
<para>
- Connect to a remote Xen hypervisor on host
<replaceable>node.example.com</replaceable>
- using ssh tunneled data transport and ssh username
<replaceable>root</replaceable>:
- <literal>xen+ssh://root@node.example.com/</literal>
+ The <literal>/host</literal> sub-document describes the
capabilities of the host.
</para>
<para>
- Connect to a remote QEMU hypervisor on host
<replaceable>node.example.com</replaceable>
- using TLS with x509 certificates:
<
literal>qemu://node.example.com/system</literal>
+ <literal>/host/uuid</literal> shows the UUID of the host. This
is derived from the
+ SMBIOS UUID if it is available and valid, or can be overridden in
+ libvirtd.conf with a custom value. If neither of the above are
+ properly set, a temporary UUID will be generated each time that
+ libvirtd is restarted.
</para>
<para>
- Connect to a remote Xen hypervisor on host
<replaceable>node.example.com</replaceable>
- using TLS, skipping verification of the server's x509 certificate (NB: this
is compromising
- your security):
<
literal>xen://node.example.com/?no_verify=1</literal>
+ The <literal>/host/cpu</literal> sub-document describes the
capabilities of the host's
+ CPUs. It is used by libvirt when deciding whether a guest can be
+ properly started on this particular machine, and is also consulted
+ during live migration to determine if the destination machine supplies
+ the necessary flags to continue to run the guest.
</para>
<para>
- Connect to the local QEMU instances over a non-standard Unix socket (the full
path to
- the Unix socket is supplied explicitly in this case):
-
<literal>qemu+unix:///system?socket=/opt/libvirt/run/libvirt/libvirt-sock</literal>
+ <literal>/host/cpu/arch</literal> is a required XML node that
describes the underlying host
+ CPU architecture. As of this writing, all libvirt drivers initialize this
+ from the output of uname(2).
</para>
<para>
- Connect to a libvirtd daemon offering unencrypted TCP/IP connections on an
alternative
- TCP port 5000 and use the test driver with default configuration:
- <literal>test+tcp://node.example.com:5000/default</literal>
+ <literal>/host/cpu/features</literal> is an optional sub-document
that describes additional cpu
+ features present on the host. As of this writing, it is only used by the
+ xen driver to report on the presence or lack of the svm or vmx flag, and to
+ report on the presence or lack of the pae flag.
</para>
- </blockquote>
-
- <formalpara>
- <title>Extra parameters</title>
-
- <para>Extra parameters can be added to remote URIs as part of the query
string (the part following "?"). Remote URIs understand the extra parameters
shown below. Any others are passed unmodified through to the backend. Note that parameter
values must be URI-escaped. Refer to <ulink
url="http://xmlsoft.org/html/libxml-uri.html#xmlURIEscapeStr"/> for more
information.
+ <para>
+ <literal>/host/cpu/arch</literal> is a required XML node that
describes the underlying
+ host CPU architecture. As of this writing, all libvirt drivers
+ initialize this from the output of uname(2).
</para>
- </formalpara>
-
- <table id='remote_URI' frame='none'><title>Extra
parameters for remote URIs</title>
- <tgroup cols='3' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' colwidth="20%"/>
- <colspec colname='c2' colwidth="20%"/>
- <colspec colname='c3' colwidth="60%"/>
- <thead>
- <row>
- <entry><para><emphasis
role="bold">Name</emphasis></para></entry>
- <entry><para><emphasis
role="bold">Transports</emphasis></para></entry>
- <entry><para><emphasis
role="bold">Description</emphasis></para></entry>
- </row>
- </thead>
- <tbody>
- <row>
-
<entry><para><literal>name</literal></para></entry>
- <entry><para><replaceable>any
transport</replaceable></para></entry>
- <entry>
- <para>The local hypervisor URI passed to the remote virConnectOpen
function. This URI is
- normally formed by removing transport, hostname, port number, username
and extra
- parameters from the remote URI, but in certain very complex cases it
may be necessary
- to supply the name explicitly. Example:
<literal>name=qemu:///system</literal>
- </para>
- </entry>
- </row>
- <row>
-
<entry><para><literal>command</literal></para></entry>
- <entry><para>ssh, ext</para></entry>
- <entry>
- <para>
- The external command. For ext transport this is required. For ssh the
default
- is ssh. The PATH is searched for the command. Example:
<literal>command=/opt/openssh/bin/ssh</literal>
- </para>
- </entry>
- </row>
- <row>
-
<entry><para><application>socket</application></para></entry>
- <entry>
- <para>unix, ssh</para>
- </entry>
- <entry>
- <para>
- The external command. For ext transport this is required. For ssh
- the default is <literal>ssh</literal>. The PATH is searched
for
- the command. Example:
<literal>socket=/opt/libvirt/run/libvirt/libvirt-sock</literal></para>
- </entry>
- </row>
- <row>
-
<entry><para><application>netcat</application></para></entry>
- <entry>
- <para>ssh</para>
- </entry>
- <entry>
- <para>The name of the netcat command on the remote machine. The
default
- is nc. For ssh transport, libvirt constructs an ssh command which looks
like:
- <screen>
-command -p port [-l username] hostname netcat -U socket</screen>
- Where port, username, hostname can be specified as part of the remote
URI,
- and command, netcat and socket come from extra parameters (or sensible
- defaults). Example:
<literal>netcat=/opt/netcat/bin/nc</literal>
- </para>
- </entry>
- </row>
- <row>
-
<entry><para><application>no_verify</application></para></entry>
- <entry>
- <para>tls</para>
- </entry>
- <entry>
- <para>Client checks of the server's certificate are disable if
a non-zero value is set. Note that to disable server checks of the client's
certificate or IP address you must change the libvirtd configuration <!--(refer to
<xref linkend=""/>)-->. Example:
<literal>no_verify=1</literal>
- </para>
- </entry>
- </row>
- <row>
-
<entry><para><application>no_tty</application></para></entry>
- <entry>
- <para>ssh</para>
- </entry>
- <entry>
- <para>If set to a non-zero value, this stops ssh from asking for a
password if it cannot log in to the remote machine automatically (For example, when using
a ssh-agent). Use this when you don't have access to a terminal - for example in
graphical programs which use libvirt. Example: <literal>no_tty=1</literal>
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- The following example shows how to local to a QEMU hypervisor using a remote
URI.
- </para>
- <example id="Example-Connect_Remote">
- <title>Connecting to a remote QEMU hypervisor</title>
- <programlisting><![CDATA[/* example ex7.c */
-/* compile with: gcc -g -Wall ex7.c -o ex7 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- conn = virConnectOpen("qemu+tls://host2/system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to
qemu+tls://host2/system\n");
- return 1;
- }
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- </section>
-
- <section
id="libvirt_application_development_guide_using_python-Connections-Capability_Info">
- <title>Capability information</title>
- <para>
- The <literal>virConnectGetCapabilities</literal> API call can be used
to obtain
- information about the capabilities of the virtualization host. It
- takes a connection pointer in and, if successful, returns a string
- containing the capabilities XML (described below). If an error
- occurred, NULL will be returned instead. It is the responsibility of the
- caller to free the memory returned from this API call. The following
- code demonstrates the use of
<literal>virConnectGetCapabilities</literal>:
- </para>
- <example id="Example-ConnectGetCapabilities">
- <title>Using virConnectGetCapabilities</title>
- <programlisting><![CDATA[/* example ex8.c */
-/* compile with: gcc -g -Wall ex8.c -o ex8 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- char *caps;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- caps = virConnectGetCapabilities(conn);
- fprintf(stdout, "Capabilities:\n%s\n", caps);
- free(caps);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- <para>
- The capabilities XML format provides information about the host
- virtualization technology. In particular, it describes the
- capabilities of the virtualization host, the virtualization driver,
- and the kinds of guests that the virtualization technology can
- launch. Note that the capabilities XML can (and does) vary based on
- the libvirt driver in use. An example capabilities XML looks like:
- </para>
- <example>
- <title>Example QEMU driver capabilities</title>
- <programlisting><![CDATA[
- <capabilities>
- <host>
- <cpu>
- <arch>x86_64</arch>
- </cpu>
- <migration_features>
- <live/>
- <uri_transports>
- <uri_transport>tcp</uri_transport>
- </uri_transports>
- </migration_features>
- <topology>
- <cells num='1'>
- <cell id='0'>
- <cpus num='2'>
- <cpu id='0'/>
- <cpu id='1'/>
- </cpus>
- </cell>
- </cells>
- </topology>
- </host>
-
- <guest>
- <os_type>hvm</os_type>
- <arch name='i686'>
- <wordsize>32</wordsize>
- <emulator>/usr/bin/qemu</emulator>
- <machine>pc</machine>
- <machine>isapc</machine>
- <domain type='qemu'>
- </domain>
- <domain type='kvm'>
- <emulator>/usr/bin/qemu-kvm</emulator>
- </domain>
- </arch>
- <features>
- <pae/>
- <nonpae/>
- <acpi default='on' toggle='yes'/>
- <apic default='on' toggle='no'/>
- </features>
- </guest>
-
- <guest>
- <os_type>hvm</os_type>
- <arch name='x86_64'>
- <wordsize>64</wordsize>
- <emulator>/usr/bin/qemu-system-x86_64</emulator>
- <machine>pc</machine>
- <machine>isapc</machine>
- <domain type='qemu'>
- </domain>
- <domain type='kvm'>
- <emulator>/usr/bin/qemu-kvm</emulator>
- </domain>
- </arch>
- <features>
- <acpi default='on' toggle='yes'/>
- <apic default='on' toggle='no'/>
- </features>
- </guest>
-
- </capabilities>
- ]]>
- </programlisting>
- </example>
- <para>
- (the rest of the discussion will refer back to this XML using XPath notation).
- In the capabilities XML, there is always the <literal>/host</literal>
sub-document, and zero or
- more <literal>/guest</literal> sub-documents (while zero guest
sub-documents are allowed,
- this means that no guests of this particular driver can be started on this
- particular host).
- </para>
-
- <para>
- The <literal>/host</literal> sub-document describes the capabilities of
the host.
- </para>
- <para>
- <literal>/host/uuid</literal> shows the UUID of the host. This is
derived from the
- SMBIOS UUID if it is available and valid, or can be overridden in
- libvirtd.conf with a custom value. If neither of the above are
- properly set, a temporary UUID will be generated each time that
- libvirtd is restarted.
- </para>
- <para>
- The <literal>/host/cpu</literal> sub-document describes the
capabilities of the host's
- CPUs. It is used by libvirt when deciding whether a guest can be
- properly started on this particular machine, and is also consulted
- during live migration to determine if the destination machine supplies
- the necessary flags to continue to run the guest.
- </para>
- <para>
- <literal>/host/cpu/arch</literal> is a required XML node that describes
the underlying host
- CPU architecture. As of this writing, all libvirt drivers initialize this
- from the output of uname(2).
- </para>
- <para>
- <literal>/host/cpu/features</literal> is an optional sub-document that
describes additional cpu
- features present on the host. As of this writing, it is only used by the
- xen driver to report on the presence or lack of the svm or vmx flag, and to
- report on the presence or lack of the pae flag.
- </para>
- <para>
- <literal>/host/cpu/arch</literal> is a required XML node that describes
the underlying
- host CPU architecture. As of this writing, all libvirt drivers
- initialize this from the output of uname(2).
- </para>
- <para>
- <literal>/host/cpu/model</literal> is an optional element that
describes the CPU model
- that the host CPUs most closely resemble. The list of CPU models
- that libvirt currently know about are in the cpu_map.xml file.
- </para>
- <para>
- <literal>/host/cpu/feature</literal> are zero or more elements that
describe
- additional CPU features that the host CPUs have that are not covered in
- <literal>/host/cpu/model</literal>
- </para>
- <para>
- <literal>/host/cpu/features</literal> is an optional sub-document that
describes
- additional cpu features present on the host. As of this writing, it
- is only used by the xen driver to report on the presence or lack of
- the svm or vmx flag, and to report on the presence or lack of the pae flag.
- </para>
- <para>
- The <literal>/host/migration_features</literal> is an optional
sub-document that
- describes the migration features that this driver supports on this
- host (if any). If this sub-document does not exist, then migration is
- not supported. As of this writing, the xen, qemu, and esx drivers
- support migration.
- </para>
- <para>
- <literal>/host/migration_features/live</literal> XML node exists if the
driver
- supports live migration
- </para>
- <para>
- <literal>/host/migration_features/uri_transports</literal> is an
optional sub-document
- that describes alternate migration connection mechanisms. These
- alternate connection mechanisms can be useful on multi-homed
- virtualization systems. For instance, the virsh migrate command might
- connect to the source of the migration via 10.0.0.1, and the
- destination of the migration via 10.0.0.2. However, due to security
- policy, the source of the migration might only be allowed to talk
- directly to the destination of the migration via 192.168.0.0/24. In
- this case, using the alternate migration connection mechanism would
- allow this migration to succeed. As of this writing, the xen driver
- supports the alternate migration mechanism "xenmigr", while the qemu
- driver supports the alternate migration mechanism "tcp". Please see
- the documentation on migration for more information.
- </para>
- <para>
- The <literal>/host/topology</literal> sub-document describes the NUMA
topology of the
- host machine; each NUMA node is represented by a
- <literal>/host/topology/cells/cell</literal>, and describes which CPUs
are in that NUMA
- node. If the host machine is a UMA (non-NUMA) machine, then there will
- be only one cell and all CPUs will be in this cell. This is very
- hardware-specific, so will necessarily vary between different machines.
- </para>
- <para>
- <literal>/host/secmodel</literal> is an optional sub-document that
describes the security
- model in use on the host. <literal>/host/secmodel/model</literal> shows
the name of the
- security model while <literal>/host/secmodel/doi</literal> shows the
Domain Of
- Interpretation. For more information about security, please see the
- Security section.
- </para>
- <para>
- Each <literal>/guest</literal> sub-document describes a kind of guest
that this host driver can
- start. This description includes the architecture of the guest (i.e. i686)
- along with the ABI provided to the guest (i.e. hvm, xen, or uml).
- </para>
- <para>
- <literal>/guest/os_type</literal> is a required element that describes
the type of guest.
- </para>
- <table id='guesttypes' frame='all'>
- <title>Guest Types</title>
- <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' />
- <colspec colname='c2' />
- <thead>
- <row>
- <entry><para>Driver</para></entry>
- <entry><para>Guest Type</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>qemu</para>
- </entry>
- <entry>
- <para>
- Always "hvm"
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>xen</para>
- </entry>
- <entry>
- <para>
- Either "xen" for a paravirtualized guest or "hvm"
for a fully virtualized guest
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>uml</para>
- </entry>
- <entry>
- <para>
- Always "uml"
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>lxc</para>
- </entry>
- <entry>
- <para>
- Always "exe"
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>vbox</para>
- </entry>
- <entry>
- <para>
- Always "hvm"
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>openvz</para>
- </entry>
- <entry>
- <para>
- Always "exe"
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>one</para>
- </entry>
- <entry>
- <para>
- Always "hvm"
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>ex</para>
- </entry>
- <entry>
- <para>
- Not supported at this time
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- <literal>/guest/arch</literal> is the root of an XML sub-document
describing various virtual
- hardware aspects of this guest type. It has a single attribute called
- "name", which can be used to refer back to this sub-document.
- </para>
- <para>
- <literal>/guest/arch/wordsize</literal> is a required element that
describes how many bits per
- word this guest type uses. This is typically 32 or 64.
- </para>
- <para>
- <literal>/guest/arch/emulator</literal> is an optional element that
describes the
- default path to the emulator for this guest type. Note that the
- emulator can be overridden by the
<literal>/guest/arch/domain/emulator</literal>
- element (described below) for guest types that need alternate binaries.
- </para>
- <para>
- <literal>/guest/arch/loader</literal> is an optional element that
describes the default path to
- the firmware loader for this guest type. Note that the default loader
- path can be overridden by the
<literal>/guest/arch/domain/loader</literal> element (described
- below) for guest types that use alternate loaders. At present, this is
- only used by the xen driver for HVM guests.
- </para>
- <para>
- There can be zero or more <literal>/guest/arch/machine</literal>
elements that describe
- the default types of machines that this guest emulator can
- emulate. These "machines" typically represent the ABI or hardware
- interface that a guest can be started with. Note that these
- machine types can be overridden by the
<literal>/guest/arch/domain/machine</literal>
- elements (described below) for virtualization technologies that
- provide alternate machine types. Typical values for this are "pc",
- and "isapc", meaning a regular PCI based PC, and an older, ISA based
- PC, respectively.
- </para>
- <para>
- There can be zero or more <literal>/guest/arch/domain</literal> XML
sub-trees (although with
- zero /guest/arch/domain XML sub-trees, no guests of this driver can be
- started). Each <literal>/guest/arch/domain</literal> XML sub-tree has
optional <emulator>,
- <loader>, and <machine> elements that override the
respective defaults
- specified above. For any of the elements that are missing, the
- default values are used.
- </para>
- <para>
- The <literal>/guest/features</literal> optional sub-document describes
various additional
- guest features that can be enabled or disabled, along with their
- default state and whether they can be toggled on or off.
- </para>
-
- </section>
-
- <section
id="libvirt_application_development_guide_using_python-Connections-Host_Info">
- <title>Host information</title>
- <para>
- There are various APIs that can be used to get information about the
- virtualization host, including the hostname, maximum support guest
- CPUs, etc.
- </para>
- <section>
- <title>virConnectGetHostname</title>
- <para>
- The <command>virConnectGetHostname</command> API call can be used to
obtain the hostname
- of the virtualization host as returned by gethostname(2). It takes a
- connection pointer in and, if successful, returns a string
- containing the hostname. If an error occurred, NULL will be returned
- instead. It is the responsibility of the caller to free the memory
- returned from this API call. The following code demonstrates the use of
- <command>virConnectGetHostname</command>:
- </para>
- <example id="Example-ConnectGetHostname">
- <title>Using virConnectGetHostname</title>
- <programlisting><![CDATA[/* example ex9.c */
-/* compile with: gcc -g -Wall ex9.c -o ex9 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- char *host;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- host = virConnectGetHostname(conn);
- fprintf(stdout, "Hostname:%s\n", host);
- free(host);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virConnectGetMaxVcpus</title>
- <para>
- The <command>virConnectGetMaxVcpus</command> API call can be used to
obtain the maximum
- number of virtual CPUs per-guest the underlying virtualization
- technology supports. It takes a connection pointer and a
- virtualization "type" as input (which can be NULL), and if successful,
- returns the number of virtual CPUs supported. If an error occurred,
- -1 is returned instead. The following code demonstrates the use of
- <command>virConnectGetMaxVcpus</command>:
- </para>
- <example id="Example-ConnectGetMaxVcpus">
- <title>Using virConnectGetMaxVcpus</title>
- <programlisting><![CDATA[/* example ex10.c */
-/* compile with: gcc -g -Wall ex10.c -o ex10 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- int vcpus;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- vcpus = virConnectGetMaxVcpus(conn, NULL);
- fprintf(stdout, "Maximum support virtual CPUs: %d\n", vcpus);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virNodeGetFreeMemory</title>
- <para>
- The <command>virNodeGetFreeMemory</command> API call can be used to
obtain the total
- amount of free memory on the virtualization host. It takes a
- connection pointer as input, and if successful returns the amount of
- free memory as an unsigned long long. If an error occurred, 0 is
- returned instead. The following code demonstrates the use of
<command>virNodeGetFreeMemory</command>:
- </para>
- <example id="Example-NodeGetFreeMemory">
- <title>Using virNodeGetFreeMemory</title>
- <programlisting><![CDATA[/* example ex11.c */
-/* compile with: gcc -g -Wall ex11.c -o ex11 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- unsigned long long node_free_memory;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- node_free_memory = virNodeGetFreeMemory(conn);
- fprintf(stdout, "Node free memory: %llu\n", node_free_memory);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virNodeGetInfo</title>
- <para>
- The <command>virNodeGetInfo</command> API call can be used to obtain
various information
- about the virtualization host. It takes a connection pointer and a
- virNodeInfo pointer (allocated by the caller) as input, and if
- successful returns 0 and fills in the virNodeInfo structure. If an
- error occurred, -1 is returned instead. The virNodeInfo structure
- contains the following members:
- </para>
- <table id='virNodeInfo-structure-mem' frame='all'>
- <title>virNodeInfo structure members</title>
- <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
- <colspec colname='c1' />
- <colspec colname='c2' />
- <thead>
- <row>
- <entry><para>Member</para></entry>
- <entry><para>Description</para></entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>
- <para>char model[32]</para>
- </entry>
- <entry>
- <para>
- string indicating the CPU model
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>unsigned long memory</para>
- </entry>
- <entry>
- <para>
- memory size in kilobytes
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>unsigned int cpus</para>
- </entry>
- <entry>
- <para>
- the number of active CPUs
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>unsigned int mhz</para>
- </entry>
- <entry>
- <para>
- expected CPU frequency
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>unsigned int nodes</para>
- </entry>
- <entry>
- <para>
- the number of NUMA nodes, 1 for uniform memory access
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>unsigned int sockets</para>
- </entry>
- <entry>
- <para>
- number of CPU sockets per node
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>unsigned int cores</para>
- </entry>
- <entry>
- <para>
- number of cores per socket
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <para>unsigned int threads</para>
- </entry>
- <entry>
- <para>
- number of threads per core
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>
- The following code demonstrates the use of
<command>virNodeGetInfo</command>:
- </para>
- <example id="Example-NodeGetInfo">
- <title>Using virNodeGetInfo</title>
- <programlisting><![CDATA[/* example ex12.c */
-/* compile with: gcc -g -Wall ex12.c -o ex12 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virNodeInfo nodeinfo;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- virNodeGetInfo(conn, &nodeinfo);
-
- fprintf(stdout, "Model: %s\n", nodeinfo.model);
- fprintf(stdout, "Memory size: %lukb\n", nodeinfo.memory);
- fprintf(stdout, "Number of CPUs: %u\n", nodeinfo.cpus);
- fprintf(stdout, "MHz of CPUs: %u\n", nodeinfo.mhz);
- fprintf(stdout, "Number of NUMA nodes: %u\n", nodeinfo.nodes);
- fprintf(stdout, "Number of CPU sockets: %u\n", nodeinfo.sockets);
- fprintf(stdout, "Number of CPU cores per socket: %u\n", nodeinfo.cores);
- fprintf(stdout, "Number of CPU threads per core: %u\n", nodeinfo.threads);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virNodeGetCellsFreeMemory</title>
- <para>
- The <command>virNodeGetCellsFreeMemory</command> API call can be used
to obtain the
- amount of free memory (in kilobytes) in some or all of the NUMA
- nodes in the system. It takes as input a connection pointer, a
- pre-allocated array of unsigned long longs, and a maximum number of
- cells to retrieve data from (usually the size of the unsigned long
- long array). If successful, the array elements are filled in with the
- amount of free memory in each node, and the number of filled nodes
- is returned. On failure -1 is returned. The following code
- demonstrates the use of
<command>virNodeGetCellsFreeMemory</command>:
- </para>
- <example id="Example-NodeGetCellsFreeMemory">
- <title>Using virNodeGetCellsFreeMemory</title>
- <programlisting><![CDATA[/* example ex13.c */
-/* compile with: gcc -g -Wall ex13.c -o ex13 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virNodeInfo nodeinfo;
- unsigned long long *freemem;
- int i;
- int numnodes;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- /* first, get the node info. This includes the number of nodes
- * in the host in nodeinfo.nodes
- */
- virNodeGetInfo(conn, &nodeinfo);
-
- /* allocate an array to hold all of the node free memory information */
- freemem = malloc(nodeinfo.nodes * sizeof(unsigned long long));
-
- /* fetch all the numa node free memory information from libvirt */
- numnodes = virNodeGetCellsFreeMemory(conn, freemem, 0, nodeinfo.nodes);
-
- for (i = 0; i < numnodes; i++)
- fprintf(stdout, "Node %d: %llukb free memory\n", i, freemem[i]);
-
- free(freemem);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virConnectGetType</title>
- <para>
- The <command>virConnectGetType</command> API call can be used to
obtain the type of
- virtualization in use on this connection. It takes a connection
- pointer as input, and if successful returns a string representing
- the type of virtualization in use. This string should
<emphasis>not</emphasis> be
- freed by the caller. If an error occurred, NULL will be returned
- instead. The following code demonstrates the use of
<command>virConnectGetType</command>:
- </para>
- <example id="Example-ConnectGetType">
- <title>Using virConnectGetType</title>
- <programlisting><![CDATA[/* example ex14.c */
-/* compile with: gcc -g -Wall ex14.c -o ex14 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- fprintf(stdout, "Virtualization type: %s\n", virConnectGetType(conn));
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virConnectGetVersion</title>
- <para>
- The <command>virConnectGetVersion</command> API call can be used to
obtain the version of
- the host virtualization software in use. It takes a connection
- pointer and unsigned long pointer as input, and if successful fills in
- the unsigned long with the version. On success it returns 0 and
- if a failure occured returns -1. The following code demonstrates the
- use of <command>virConnectGetVersion</command>:
- </para>
- <example id="Example-ConnectGetVersion">
- <title>Using virConnectGetVersion</title>
- <programlisting><![CDATA[/* example ex15.c */
-/* compile with: gcc -g -Wall ex15.c -o ex15 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- unsigned long ver;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- virConnectGetVersion(conn, &ver);
-
- fprintf(stdout, "Version: %lu\n", ver);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virConnectGetLibVersion</title>
- <para>
- The <command>virConnectGetLibVersion</command> API call can be used
to obtain the version of
- the libvirt software in use on the host. It takes a connection
- pointer and unsigned long pointer as input, and if successful fills in
- the unsigned long with the libvirt version. On success it returns 0 and
- if a failure occured returns -1. The following code demonstrates the
- use of <command>virConnectGetLibVersion</command>:
- </para>
- <example id="Example-ConnectGetLibVersion">
- <title>Using virConnectGetLibVersion</title>
- <programlisting><![CDATA[/* example ex16.c */
-/* compile with: gcc -g -Wall ex16.c -o ex16 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- unsigned long ver;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- virConnectGetLibVersion(conn, &ver);
-
- fprintf(stdout, "Libvirt Version: %lu\n", ver);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virConnectGetURI</title>
- <para>
- The <command>virConnectGetURI</command> API call can be used to
obtain the URI for the
- current connection. While this is typically the same string that
- was passed into the <command>virConnectOpen</command> call, the
underlying driver can
- sometimes canonicalize the string. This API call will return the
- canonical version. It takes a connection pointer as input and if
- successful, returns a URI string that must be freed by the caller. If
- an error occurred, NULL will be returned instead. The following code demonstrates
the use of <command>virConnectGetURI</command>:
- </para>
- <example id="Example-ConnectGetURI">
- <title>Using virConnectGetURI</title>
- <programlisting><![CDATA[/* example ex17.c */
-/* compile with: gcc -g -Wall ex17.c -o ex17 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- char *uri;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- uri = virConnectGetURI(conn);
-
- fprintf(stdout, "Canonical URI: %s\n", uri);
-
- free(uri);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virConnectIsEncrypted</title>
- <para>
- The <command>virConnectIsEncrypted</command> API call can be used to
find out if a given
- connection is encrypted. It takes a connection pointer as input, and
- if successful returns 1 for an encrypted connection and 0 for an
- unencrypted connection. If an error occurred, -1 will be returned.
- The following code demonstrates the use of
<command>virConnectIsEncrypted</command>:
- </para>
- <example id="Example-ConnectIsEncrypted">
- <title>Using virConnectIsEncrypted</title>
- <programlisting><![CDATA[/* example ex18.c */
-/* compile with: gcc -g -Wall ex18.c -o ex18 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- fprintf(stdout, "Connection is encrypted: %d\n",
virConnectIsEncrypted(conn));
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- <section>
- <title>virConnectIsSecure</title>
- <para>
- The <command>virConnectIsSecure</command> API call can be used to
find out if a given
- connection is encrypted. A connection will be classified secure if
- it is either encrypted or it is running on a channel which is not
- vulnerable to eavsdropping (like a UNIX domain socket). It takes a
- connection pointer as input, and if successful returns 1 for a
- secure connection and 0 for an insecure connection. If an error
- occurred, -1 will be returned. The following code demonstrates the use
- of <command>virConnectIsSecure</command>:
- </para>
- <example id="Example-ConnectIsSecure">
- <title>Using virConnectIsSecure</title>
- <programlisting><![CDATA[/* example ex19.c */
-/* compile with: gcc -g -Wall ex19.c -o ex19 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- fprintf(stdout, "Connection is secure: %d\n", virConnectIsSecure(conn));
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
- </section>
-
- <section
id="libvirt_application_development_guide_using_python-Connections-Event_Loop">
- <title>Event loop integration</title>
- <para>
- The libvirt APIs use a basic request/response architecture that is
- generally synchronous. That is, a libvirt application calls a libvirt
- API (the request) which doesn't return until the action is complete
- (the response). However, a libvirtd server can also generate
- asynchronous messages and send them to the libvirt application; a
- typical usage of these messages is to inform the libvirt client when a
- domain has undergone a lifecycle change (like shutdown or restart).
- </para>
- <para>
- The libvirt event loop APIs allow an application to register for these
- asynchrounous events and properly handle them.
- </para>
- <para>
- The <literal>virEventRegisterImpl</literal> API registers a set of
callbacks that libvirt
- will call when adding, updating, or removing a handle to watch.
- </para>
- </section>
-
- <section
id="libvirt_application_development_guide_using_python-Connections-Security">
- <title>Security model</title>
- <para>
- The libvirt security model is known as svirt, and is designed to protect
- the host from guest domains, and guest domains from other guest
- domains. It works by putting each guest and guest disk into its own
- security domain, using whatever facilities are available to do so on
- the virtualization host. For the most part, svirt is invisible to application
- developers and need not be explored. There is a single libvirt API
- that provides information about the security model in use.
- </para>
- <para>
- The <command>virNodeGetSecurityModel</command> API call can be used
to find out the
- security model and DOI (Domain of Interpretation) in use on the
- virtualization host. It takes a connection pointer and a
- virSecurityModel pointer as input, and if successful fills in the
- virSecurityModel structure with the appropriate information. On
- success it returns 0; if an error occurred, -1 is returned.
- The following code demonstrates the use of
<command>virNodeGetSecurityModel</command>:
- </para>
- <example id="Example-NodeGetSecurityModel">
- <title>Using virNodeGetSecurityModel</title>
- <programlisting><![CDATA[/* example ex20.c */
-/* compile with: gcc -g -Wall ex20.c -o ex20 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virSecurityModel secmodel;
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- virNodeGetSecurityModel(conn, &secmodel);
-
- fprintf(stdout, "Security Model: %s\n", secmodel.model);
- fprintf(stdout, "Security DOI: %s\n", secmodel.doi);
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </example>
- </section>
-
- <section
id="libvirt_application_development_guide_using_python-Connections-Error_Handling">
- <title>Error handling</title>
- <para>
- The libvirt error APIs are designed to give more detailed information
- about what caused a failure in the case that a normal libvirt API
- returned an error. An important thing to note about libvirt error
- reporting is that errors are stored per-connection
<emphasis>and</emphasis> globally.
- This means that if multiple errors happen on a connection without
- checking for the error, intermediate errors may be lost. For this
- reason, it is strongly recommended to always check for and collect
- errors immediately after the libvirt API failed. Alternatively,
- libvirt provides a way to set a custom error handling function that
- will be called synchronously at the time the error occurred.
- </para>
- <para>
- All of the error functions deal with getting or clearing a
<literal>virError</literal>
- structure. The <literal>virError</literal> structure looks like:
- </para>
- <programlisting><![CDATA[typedef struct _virError virError;
-typedef virError *virErrorPtr;
-struct _virError {
- int code; /* The error code, a virErrorNumber */
- int domain; /* What part of the library raised this error */
- char *message;/* human-readable informative error message */
- virErrorLevel level;/* how consequent is the error */
- virConnectPtr conn VIR_DEPRECATED; /* connection if available, deprecated
- see note above */
- virDomainPtr dom VIR_DEPRECATED; /* domain if available, deprecated
- see note above */
- char *str1; /* extra string information */
- char *str2; /* extra string information */
- char *str3; /* extra string information */
- int int1; /* extra number information */
- int int2; /* extra number information */
- virNetworkPtr net VIR_DEPRECATED; /* network if available, deprecated
- see note above */
-};]]></programlisting>
- <para>
- (Note that conn, dom, and net are deprecated members and should not be
- used in new code, since they are not thread-safe)
- </para>
- <para>
- The first member of the structure, "code", is the error code that was
- returned from the error. This is one of the members of the
- <literal>virErrorNumber</literal> enum in
<filename>virterror.h</filename>; the full list of errors is:
- </para>
- <programlisting><![CDATA[typedef enum {
- VIR_ERR_OK = 0,
- VIR_ERR_INTERNAL_ERROR, /* internal error */
- VIR_ERR_NO_MEMORY, /* memory allocation failure */
- VIR_ERR_NO_SUPPORT, /* no support for this function */
- VIR_ERR_UNKNOWN_HOST,/* could not resolve hostname */
- VIR_ERR_NO_CONNECT, /* can't connect to hypervisor */
- VIR_ERR_INVALID_CONN,/* invalid connection object */
- VIR_ERR_INVALID_DOMAIN,/* invalid domain object */
- VIR_ERR_INVALID_ARG,/* invalid function argument */
- VIR_ERR_OPERATION_FAILED,/* a command to hypervisor failed */
- VIR_ERR_GET_FAILED,/* a HTTP GET command to failed */
- VIR_ERR_POST_FAILED,/* a HTTP POST command to failed */
- VIR_ERR_HTTP_ERROR,/* unexpected HTTP error code */
- VIR_ERR_SEXPR_SERIAL,/* failure to serialize an S-Expr */
- VIR_ERR_NO_XEN,/* could not open Xen hypervisor control */
- VIR_ERR_XEN_CALL,/* failure doing an hypervisor call */
- VIR_ERR_OS_TYPE, /* unknown OS type */
- VIR_ERR_NO_KERNEL, /* missing kernel information */
- VIR_ERR_NO_ROOT, /* missing root device information */
- VIR_ERR_NO_SOURCE, /* missing source device information */
- VIR_ERR_NO_TARGET, /* missing target device information */
- VIR_ERR_NO_NAME, /* missing domain name information */
- VIR_ERR_NO_OS, /* missing domain OS information */
- VIR_ERR_NO_DEVICE, /* missing domain devices information */
- VIR_ERR_NO_XENSTORE,/* could not open Xen Store control */
- VIR_ERR_DRIVER_FULL, /* too many drivers registered */
- VIR_ERR_CALL_FAILED, /* not supported by the drivers (DEPRECATED) */
- VIR_ERR_XML_ERROR, /* an XML description is not well formed or broken */
- VIR_ERR_DOM_EXIST,/* the domain already exist */
- VIR_ERR_OPERATION_DENIED, /* operation forbidden on read-only connections */
- VIR_ERR_OPEN_FAILED, /* failed to open a conf file */
- VIR_ERR_READ_FAILED, /* failed to read a conf file */
- VIR_ERR_PARSE_FAILED, /* failed to parse a conf file */
- VIR_ERR_CONF_SYNTAX, /* failed to parse the syntax of a conf file */
- VIR_ERR_WRITE_FAILED, /* failed to write a conf file */
- VIR_ERR_XML_DETAIL, /* detail of an XML error */
- VIR_ERR_INVALID_NETWORK, /* invalid network object */
- VIR_ERR_NETWORK_EXIST, /* the network already exist */
- VIR_ERR_SYSTEM_ERROR, /* general system call failure */
- VIR_ERR_RPC, /* some sort of RPC error */
- VIR_ERR_GNUTLS_ERROR, /* error from a GNUTLS call */
- VIR_WAR_NO_NETWORK, /* failed to start network */
- VIR_ERR_NO_DOMAIN, /* domain not found or unexpectedly disappeared */
- VIR_ERR_NO_NETWORK, /* network not found */
- VIR_ERR_INVALID_MAC, /* invalid MAC address */
- VIR_ERR_AUTH_FAILED, /* authentication failed */
- VIR_ERR_INVALID_STORAGE_POOL, /* invalid storage pool object */
- VIR_ERR_INVALID_STORAGE_VOL, /* invalid storage vol object */
- VIR_WAR_NO_STORAGE, /* failed to start storage */
- VIR_ERR_NO_STORAGE_POOL, /* storage pool not found */
- VIR_ERR_NO_STORAGE_VOL, /* storage pool not found */
- VIR_WAR_NO_NODE, /* failed to start node driver */
- VIR_ERR_INVALID_NODE_DEVICE,/* invalid node device object */
- VIR_ERR_NO_NODE_DEVICE,/* node device not found */
- VIR_ERR_NO_SECURITY_MODEL, /* security model not found */
- VIR_ERR_OPERATION_INVALID, /* operation is not applicable at this time */
- VIR_WAR_NO_INTERFACE, /* failed to start interface driver */
- VIR_ERR_NO_INTERFACE, /* interface driver not running */
- VIR_ERR_INVALID_INTERFACE, /* invalid interface object */
- VIR_ERR_MULTIPLE_INTERFACES, /* more than one matching interface found */
- VIR_WAR_NO_NWFILTER, /* failed to start nwfilter driver */
- VIR_ERR_INVALID_NWFILTER, /* invalid nwfilter object */
- VIR_ERR_NO_NWFILTER, /* nw filter pool not found */
- VIR_ERR_BUILD_FIREWALL, /* nw filter pool not found */
- VIR_WAR_NO_SECRET, /* failed to start secret storage */
- VIR_ERR_INVALID_SECRET, /* invalid secret */
- VIR_ERR_NO_SECRET, /* secret not found */
- VIR_ERR_CONFIG_UNSUPPORTED, /* unsupported configuration construct */
- VIR_ERR_OPERATION_TIMEOUT, /* timeout occurred during operation */
- VIR_ERR_MIGRATE_PERSIST_FAILED, /* a migration worked, but making the
- VM persist on the dest host failed */
- VIR_ERR_HOOK_SCRIPT_FAILED, /* a synchronous hook script failed */
- VIR_ERR_INVALID_DOMAIN_SNAPSHOT, /* invalid domain snapshot */
- VIR_ERR_NO_DOMAIN_SNAPSHOT, /* domain snapshot not found */
-} virErrorNumber;]]></programlisting>
- <para>
- The second member of the structure, "domain", is named that for legacy
- reasons, but really represents which part of libvirt generated the
- error. This is one of the members of the
<literal>virErrorDomain</literal> enum in
<filename>virterror.h</filename>;
- the full list is:
- </para>
- <programlisting><![CDATA[typedef enum {
- VIR_FROM_NONE = 0,
- VIR_FROM_XEN, /* Error at Xen hypervisor layer */
- VIR_FROM_XEND, /* Error at connection with xend daemon */
- VIR_FROM_XENSTORE, /* Error at connection with xen store */
- VIR_FROM_SEXPR, /* Error in the S-Expression code */
- VIR_FROM_XML, /* Error in the XML code */
- VIR_FROM_DOM, /* Error when operating on a domain */
- VIR_FROM_RPC, /* Error in the XML-RPC code */
- VIR_FROM_PROXY, /* Error in the proxy code */
- VIR_FROM_CONF, /* Error in the configuration file handling */
- VIR_FROM_QEMU, /* Error at the QEMU daemon */
- VIR_FROM_NET, /* Error when operating on a network */
- VIR_FROM_TEST, /* Error from test driver */
- VIR_FROM_REMOTE, /* Error from remote driver */
- VIR_FROM_OPENVZ, /* Error from OpenVZ driver */
- VIR_FROM_XENXM, /* Error at Xen XM layer */
- VIR_FROM_STATS_LINUX,/* Error in the Linux Stats code */
- VIR_FROM_LXC, /* Error from Linux Container driver */
- VIR_FROM_STORAGE, /* Error from storage driver */
- VIR_FROM_NETWORK, /* Error from network config */
- VIR_FROM_DOMAIN, /* Error from domain config */
- VIR_FROM_UML, /* Error at the UML driver */
- VIR_FROM_NODEDEV, /* Error from node device monitor */
- VIR_FROM_XEN_INOTIFY,/* Error from xen inotify layer */
- VIR_FROM_SECURITY, /* Error from security framework */
- VIR_FROM_VBOX, /* Error from VirtualBox driver */
- VIR_FROM_INTERFACE, /* Error when operating on an interface */
- VIR_FROM_ONE, /* Error from OpenNebula driver */
- VIR_FROM_ESX, /* Error from ESX driver */
- VIR_FROM_PHYP, /* Error from IBM power hypervisor */
- VIR_FROM_SECRET, /* Error from secret storage */
- VIR_FROM_CPU, /* Error from CPU driver */
- VIR_FROM_XENAPI, /* Error from XenAPI */
- VIR_FROM_NWFILTER, /* Error from network filter driver */
- VIR_FROM_HOOK, /* Error from Synchronous hooks */
- VIR_FROM_DOMAIN_SNAPSHOT, /* Error from domain snapshot */
-} virErrorDomain;]]></programlisting>
- <para>
- The third member of the structure, "message", is a human-readable string
- describing the error.
- </para>
- <para>
- The fourth member of the structure, "level", describes the severity of
the
- error. This is one of the members of the virErrorLevel enum in virterror.h;
-the full list of levels is:
- </para>
- <programlisting><![CDATA[typedef enum {
- VIR_ERR_NONE = 0,
- VIR_ERR_WARNING = 1, /* A simple warning */
- VIR_ERR_ERROR = 2 /* An error */
-} virErrorLevel;]]></programlisting>
- <para>
- The fifth member of the structure, "conn", is deprecated because it is
not
- thread-safe.
- </para>
- <para>
- The sixth member of the structure, "dom", is deprecated because it is
not
- thread-safe.
- </para>
- <para>
- The seventh member of the structure, "str1", gives extra human readable
- information.
- </para>
- <para>
- The eighth member of the structure, "str2", gives extra human readable
- information.
- </para>
- <para>
- The ninth member of the structure, "str3", gives extra human readable
- information.
- </para>
- <para>
- The tenth member of the structure, "int1", gives extra numeric
information that
- may be useful for further classifying the error.
- </para>
- <para>
- The eleventh member of the structure, "int2", gives extra numeric
- information that may be useful for further classifying the error.
- </para>
- <para>
- The twelfth member of the structure, "net", is deprecated because it is
not
- thread-safe.
- </para>
- <para>
- Example code that uses various parts of this structure will be
- presented in API call sub-sections.
- </para>
- <section>
- <title>virSetErrorFunc</title>
- <para>
- By default when an error occurs, libvirt will call the
- <literal>virDefaultErrorFunc</literal> function which will print the
error information to
- stderr. The <literal>virSetErrorFunc</literal> API call can be used
to set a custom global
- error function that libvirt will call instead. It takes a void *
- pointer for userData and a virErrorFunc function pointer as input, and
- returns nothing. The custom error function should have a function signature of:
- </para>
- <programlisting>typedef void (*virErrorFunc) (void *userData, virErrorPtr
error);</programlisting>
- <para>
- The following code demonstrates the use of
<literal>virSetErrorFunc</literal>:
- </para>
-<programlisting><![CDATA[/* example ex21.c */
-/* compile with: gcc -g -Wall ex21.c -o ex21 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-static void customErrorFunc(void *userdata, virErrorPtr err)
-{
- fprintf(stderr, "Failure of libvirt library call:\n");
- fprintf(stderr, " Code: %d\n", err->code);
- fprintf(stderr, " Domain: %d\n", err->domain);
- fprintf(stderr, " Message: %s\n", err->message);
- fprintf(stderr, " Level: %d\n", err->level);
- fprintf(stderr, " str1: %s\n", err->str1);
- fprintf(stderr, " str2: %s\n", err->str2);
- fprintf(stderr, " str3: %s\n", err->str3);
- fprintf(stderr, " int1: %d\n", err->int1);
- fprintf(stderr, " int2: %d\n", err->int2);
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
-
- virSetErrorFunc(NULL, customErrorFunc);
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- if (virConnectGetVersion(conn, NULL) < 0)
- fprintf(stderr, "virConnectGetVersion failed\n");
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </section>
- <section>
- <title>virConnSetErrorFunc</title>
- <para>
- The <literal>virConnSetErrorFunc</literal> API call can be used to
set a per-connection
- custom error handling function. If present, this per-connection error
- handling function will take precendence over the global error handling
- function. The internal libvirt logic for deciding which error
- handling function to call is (in pseudo-code):
- </para>
-<programlisting>if (conn->handler)
- conn->handler;
-else if (global_handler)
- global_handler;
-else
- virDefaultErrorFunc;
-</programlisting>
- <para>
- <literal>virConnSetErrorFunc</literal> takes a virConnectPtr, a void
* pointer for
- userData, and a virErrorFunc function pointer as input, and
- returns nothing. As with <literal>virSetErrorFunc</literal>, the
custom connection error
- function should have a function signature of:
- </para>
-
-<programlisting>typedef void (*virErrorFunc) (void *userData, virErrorPtr
error);</programlisting>
- <para>
- The following code demonstrates the use of
<literal>virConnSetErrorFunc</literal>:
- </para>
-<programlisting><![CDATA[/* example ex22.c */
-/* compile with: gcc -g -Wall ex22.c -o ex22 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-static void customConnErrorFunc(void *userdata, virErrorPtr err)
-{
- fprintf(stderr, "Connection handler, failure of libvirt library call:\n");
- fprintf(stderr, " Code: %d\n", err->code);
- fprintf(stderr, " Domain: %d\n", err->domain);
- fprintf(stderr, " Message: %s\n", err->message);
- fprintf(stderr, " Level: %d\n", err->level);
- fprintf(stderr, " str1: %s\n", err->str1);
- fprintf(stderr, " str2: %s\n", err->str2);
- fprintf(stderr, " str3: %s\n", err->str3);
- fprintf(stderr, " int1: %d\n", err->int1);
- fprintf(stderr, " int2: %d\n", err->int2);
-}
-
-static void customGlobalErrorFunc(void *userdata, virErrorPtr err)
-{
- fprintf(stderr, "Global handler, failure of libvirt library call:\n");
- fprintf(stderr, " Code: %d\n", err->code);
- fprintf(stderr, " Domain: %d\n", err->domain);
- fprintf(stderr, " Message: %s\n", err->message);
- fprintf(stderr, " Level: %d\n", err->level);
- fprintf(stderr, " str1: %s\n", err->str1);
- fprintf(stderr, " str2: %s\n", err->str2);
- fprintf(stderr, " str3: %s\n", err->str3);
- fprintf(stderr, " int1: %d\n", err->int1);
- fprintf(stderr, " int2: %d\n", err->int2);
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn1;
- virConnectPtr conn2;
-
- /* set a global error function for all connections */
- virSetErrorFunc(NULL, customGlobalErrorFunc);
-
- conn1 = virConnectOpen("qemu:///system");
- if (conn1 == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- conn2 = virConnectOpen("qemu:///system");
- if (conn2 == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- virConnectClose(conn1);
- return 2;
- }
-
- /* conn1 will use a different error function */
- virConnSetErrorFunc(conn1, NULL, customConnErrorFunc);
-
- /* this failure will use customConnErrorFunc */
- if (virConnectGetVersion(conn1, NULL) < 0)
- fprintf(stderr, "virConnectGetVersion failed\n");
-
- /* this failure will use customGlobalErrorFunc */
- if (virConnectGetVersion(conn2, NULL) < 0)
- fprintf(stderr, "virConnectGetVersion failed\n");
-
- virConnectClose(conn2);
- virConnectClose(conn1);
- return 0;
-}]]></programlisting>
- </section>
- <section>
- <title>virCopyLastError</title>
- <para>
- The <literal>virCopyLastError</literal> API call can be used to
obtain a copy of the last
- error reported from libvirt. The error object is kept in thread local
- storage so separate threads can safely use this function
- concurrently. It takes a virErrorPtr as input, and if successful
- makes a deep copy of the error. If there were no errors pending, 0 is
- returned. If there was an error pending, the error code is returned.
- If an error occurred, -1 is returned. The following code demonstrates
- the use of <literal>virCopyLastError</literal>:
- </para>
-<programlisting><![CDATA[/* example ex23.c */
-/* compile with: gcc -g -Wall ex23.c -o ex23 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-/* dummy error function to suppress virDefaultErrorFunc */
-static void customErrorFunc(void *userdata, virErrorPtr err)
-{
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virError err;
-
- virSetErrorFunc(NULL, customErrorFunc);
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- if (virConnectGetVersion(conn, NULL) < 0) {
- virCopyLastError(&err);
- fprintf(stderr, "virConnectGetVersion failed: %s\n", err.message);
- virResetError(&err);
- }
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </section>
- <section>
- <title>virGetLastError</title>
- <para>
- The <literal>virGetLastError</literal> API call can be used to obtain
a pointer to the last
- error reported from libvirt. The error object is kept in thread local
- storage so separate threads can safely use this function
- concurrently. Note that it does not take a copy, so error information
- can be lost if the current thread obtains this pointer, calls another
- libvirt function, and then tries to access this pointer. If that
- behavior is desired, use <literal>virCopyLastError</literal> or
<literal>virSaveLastError</literal>
- instead. It takes no input, and returns a pointer to the last error
- object if one exists. If there was no last error, or the last error
- was VIR_ERR_OK, NULL is returned instead. The following code demonstrates
- the use of <literal>virGetLastError</literal>:
- </para>
-<programlisting><![CDATA[/* example ex24.c */
-/* compile with: gcc -g -Wall ex24.c -o ex24 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-static void customErrorFunc(void *userdata, virErrorPtr err)
-{
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virErrorPtr err;
-
- virSetErrorFunc(NULL, customErrorFunc);
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- if (virConnectGetVersion(conn, NULL) < 0) {
- /* this is a valid way to use virGetLastError */
- err = virGetLastError();
- fprintf(stderr, "virConnectGetVersion failed: %s\n", err->message);
- }
-
- if (virConnectGetVersion(conn, NULL) < 0) {
- /* this is an invalid way to use virGetLastError; the error message will
- * not represent the error from virConnectGetVersion
- */
- err = virGetLastError();
- virNodeGetFreeMemory(NULL);
- fprintf(stderr, "virConnectGetVersion failed: %s\n", err->message);
- }
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </section>
- <section>
- <title>virSaveLastError</title>
- <para>
- The <literal>virSaveLastError</literal> API call can be used to
allocate and obtain a
- copy of the last error reported from libvirt. The error object is
- kept in thread local storage so separate threads can safely use this function
- concurrently. It takes nothing as input and if successful returns a
- newly allocated virError object. It is the responsibility of the
- caller to free the error with <literal>virFreeError</literal>. If an
error occurred, NULL is
- returned instead. The following code demonstrates the use of
<literal>virSaveLastError</literal>:
- </para>
-<programlisting><![CDATA[/* example ex25.c */
-/* compile with: gcc -g -Wall ex25.c -o ex25 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-/* dummy error function to suppress virDefaultErrorFunc */
-static void customErrorFunc(void *userdata, virErrorPtr err)
-{
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virErrorPtr err;
-
- virSetErrorFunc(NULL, customErrorFunc);
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- if (virConnectGetVersion(conn, NULL) < 0) {
- err = virSaveLastError();
- fprintf(stderr, "virConnectGetVersion failed: %s\n", err->message);
- virFreeError(err);
- }
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </section>
- <section>
- <title>virResetError</title>
- <para>
- The <literal>virResetError</literal> API call can be used to clear
and free any memory
- associated with an virError object (though it does not free the object
- itself). It is typically used after a program is finished using an
- virError object obtained through <literal>virCopyLastError</literal>,
though it can also
- be used after a <literal>virSaveLastError</literal> in special
circumstances. It takes
- the virErrorPtr as input, and returns nothing. The following code
- demonstrates the use of <literal>virResetError</literal>:
- </para>
-<programlisting><![CDATA[/* example ex26.c */
-/* compile with: gcc -g -Wall ex26.c -o ex26 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-/* dummy error function to suppress virDefaultErrorFunc */
-static void customErrorFunc(void *userdata, virErrorPtr err)
-{
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virError err;
-
- virSetErrorFunc(NULL, customErrorFunc);
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- if (virConnectGetVersion(conn, NULL) < 0) {
- virCopyLastError(&err);
- fprintf(stderr, "virConnectGetVersion failed: %s\n", err.message);
- virResetError(&err);
- }
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </section>
- <section>
- <title>virFreeError</title>
- <para>
- The <literal>virFreeError</literal> API call can be used to clear and
free any memory
- associated with an virError object, including the object itself. It
- is typically used after a program is finished using an virError object
- obtained through <literal>virSaveLastError</literal>, though it can
also be used after a
- <literal>virCopyLastError</literal> in special circumstances. It
takes the virErrorPtr
- as input, and returns nothing. The following code demonstrates the
- use of <literal>virFreeError</literal>:
- </para>
-<programlisting><![CDATA[/* example ex27.c */
-/* compile with: gcc -g -Wall ex27.c -o ex27 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-/* dummy error function to suppress virDefaultErrorFunc */
-static void customErrorFunc(void *userdata, virErrorPtr err)
-{
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn;
- virErrorPtr err;
-
- virSetErrorFunc(NULL, customErrorFunc);
-
- conn = virConnectOpen("qemu:///system");
- if (conn == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- if (virConnectGetVersion(conn, NULL) < 0) {
- err = virSaveLastError();
- fprintf(stderr, "virConnectGetVersion failed: %s\n", err->message);
- virFreeError(err);
- }
-
- virConnectClose(conn);
- return 0;
-}]]></programlisting>
- </section>
- <section>
- <title>virConnResetError</title>
- <para>
- The <literal>virConnResetError</literal> API call can be used to
clear and free any memory
- associated with an virError object on a particular connection (though
- it does not free the object itself). It is typically used after a
- program is finished using an virError object obtained through
- <literal>virConnCopyLastError</literal>, though it can also be used
after a <literal>virConnSaveLastError</literal>
- in special circumstances. However, both
<literal>virConnCopyLastError</literal> and
- <literal>virConnSaveLastError</literal> are deprecated, and since
libvirt 0.6.0 all
- per-connection errors are also propagated to the global error
- storage. Therefore, this API should not be used in new code;
- <literal>virResetError</literal> should be used instead. The function
remains for
- backwards compatibility.
- </para>
- </section>
- <section>
- <title>virConnCopyLastError</title>
- <para>
- The <literal>virConnCopyLastError</literal> API call can be used to
obtain a copy of the last
- error reported from libvirt on a particular connection. This function
- has been deprecated because it is not thread-safe, and since libvirt
- 0.6.0 all connection errors are also propagated to the global error
- object. New code should use <literal>virCopyLastError</literal>
instead. This
- function remains for backwards compatilibity.
- </para>
- </section>
- <section>
- <title>virConnGetLastError</title>
- <para>
- The <literal>virConnGetLastError</literal> API call can be used to
obtain a pointer to the last
- error reported from libvirt on a particular connection. This function
- has been deprecated because it is not thread-safe, and since libvirt
- 0.6.0 all connection errors are also propagated to the global error
- object. New code should use <literal>virGetLastError</literal>
instead. This
- function remains for backwards compatilibity.
- </para>
- </section>
- </section>
- <section
id="libvirt_application_development_guide_using_python-Connections-Debug">
- <title>Debugging / logging</title>
- <para>
- Libvirt includes logging facilities to facilitate the tracing of library
- execution. These logs will frequently be requested when trying to
- obtain support for libvirt, so familiarity with them is essential.
- </para>
- <para>
- The logging facilities in libvirt are based on 3 key concepts:
- </para>
- <orderedlist>
- <listitem>
<para>
- Log messages - generated at runtime by the libvirt code, they include
- a timestamp, a priority level (DEBUG = 1, INFO = 2, WARNING = 3, ERROR = 4),
- a category, function name and line number indicating where the
- message originated from, and a formatted message.
+ <literal>/host/cpu/model</literal> is an optional element that
describes the CPU model
+ that the host CPUs most closely resemble. The list of CPU models
+ that libvirt currently know about are in the cpu_map.xml file.
</para>
- </listitem>
- <listitem>
<para>
- Log filters - patterns and priorities which control whether or
- not a particular message is displayed. The format for a filter is:
+ <literal>/host/cpu/feature</literal> are zero or more elements
that describe
+ additional CPU features that the host CPUs have that are not covered in
+ <literal>/host/cpu/model</literal>
</para>
- <para><screen>x:name</screen></para>
<para>
- where "x" is the minimal priority level where the match should apply,
and
- "name" is a string to match against. The priority levels are:
+ <literal>/host/cpu/features</literal> is an optional sub-document
that describes
+ additional cpu features present on the host. As of this writing, it
+ is only used by the xen driver to report on the presence or lack of
+ the svm or vmx flag, and to report on the presence or lack of the pae flag.
</para>
- <itemizedlist>
- <listitem><para>1 (or debug) - log all
messages</para></listitem>
- <listitem><para>2 (or info) - log all non-debugging
information</para></listitem>
- <listitem><para>3 (or warn) - log only warnings and errors - this
is the default</para></listitem>
- <listitem><para>4 (or error) - log only
errors</para></listitem>
- </itemizedlist>
<para>
- For instance, to log all debug messages to the qemu driver, the
- following filter can be used:
+ The <literal>/host/migration_features</literal> is an optional
sub-document that
+ describes the migration features that this driver supports on this
+ host (if any). If this sub-document does not exist, then migration is
+ not supported. As of this writing, the xen, qemu, and esx drivers
+ support migration.
</para>
- <para><screen>1:qemu</screen></para>
<para>
- Multiple filters can be specified together by space separating them;
- the following example logs all debug messages from qemu, and logs
- all error messages from the remote driver:
+ <literal>/host/migration_features/live</literal> XML node exists
if the driver
+ supports live migration
</para>
- <para><screen>1:qemu 4:remote</screen></para>
- </listitem>
- <listitem>
<para>
- Log outputs - where to send the message once it has passed
- through filters. The format for a log output is one of the forms:
+ <literal>/host/migration_features/uri_transports</literal> is an
optional sub-document
+ that describes alternate migration connection mechanisms. These
+ alternate connection mechanisms can be useful on multi-homed
+ virtualization systems. For instance, the virsh migrate command might
+ connect to the source of the migration via 10.0.0.1, and the
+ destination of the migration via 10.0.0.2. However, due to security
+ policy, the source of the migration might only be allowed to talk
+ directly to the destination of the migration via 192.168.0.0/24. In
+ this case, using the alternate migration connection mechanism would
+ allow this migration to succeed. As of this writing, the xen driver
+ supports the alternate migration mechanism "xenmigr", while the
qemu
+ driver supports the alternate migration mechanism "tcp". Please
see
+ the documentation on migration for more information.
</para>
<para>
-<screen>x:stderr - log to stderr
-x:syslog:name - log to syslog with a prefix of "name"
-x:file:file_path - log to a file specified by "file_path"</screen>
+ The <literal>/host/topology</literal> sub-document describes the
NUMA topology of the
+ host machine; each NUMA node is represented by a
+ <literal>/host/topology/cells/cell</literal>, and describes which
CPUs are in that NUMA
+ node. If the host machine is a UMA (non-NUMA) machine, then there will
+ be only one cell and all CPUs will be in this cell. This is very
+ hardware-specific, so will necessarily vary between different machines.
</para>
<para>
- where "x" is the minimal priority level. For instance, to log all
- warnings and errors to syslog with a prefix of "libvirtd", the
- following output can be used:
+ <literal>/host/secmodel</literal> is an optional sub-document
that describes the security
+ model in use on the host. <literal>/host/secmodel/model</literal>
shows the name of the
+ security model while <literal>/host/secmodel/doi</literal> shows
the Domain Of
+ Interpretation. For more information about security, please see the
+ Security section.
</para>
- <para><screen>3:syslog:libvirtd</screen></para>
<para>
- Multiple outputs can be specified by space separating them; the
- following example logs all error and warning messages to syslog, and
- logs all debug, information, warning, and error messages to
- <filename>/tmp/libvirt.log</filename>:
+ Each <literal>/guest</literal> sub-document describes a kind of
guest that this host driver can
+ start. This description includes the architecture of the guest (i.e. i686)
+ along with the ABI provided to the guest (i.e. hvm, xen, or uml).
</para>
- <para><screen>3:syslog:libvirtd
1:file:/tmp/libvirt.log</screen></para>
- </listitem>
- </orderedlist>
- <section>
- <title>Environment Variables</title>
- <para>
- The desired log priority level, filters, and outputs are specified to
- the libvirt library through the use of environment variables:
- </para>
- <orderedlist>
- <listitem>
- <para>
- <literal>LIBVIRT_DEBUG</literal> specifies the minimum priority
level messages that
- will be logged. This can be thought of as a "global" priority
level;
- if a particular log message does not match a specific filter in
- <literal>LIBVIRT_LOG_FILTERS</literal>, it will be compared to
this global priority and
- logged as appropriate.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>LIBVIRT_LOG_FILTERS</literal> specifies the filters to
apply.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>LIBVIRT_LOG_OUTPUTS</literal> specifies the outputs to
send the message to.
- </para>
- </listitem>
- </orderedlist>
- <example>
- <title>Running virsh with environment variables</title>
<para>
- To see more detailed information about what is going on with virsh,
- we may run it like the following:
+ <literal>/guest/os_type</literal> is a required element that
describes the type of guest.
</para>
-
-<screen><command>LIBVIRT_DEBUG=error LIBVIRT_LOG_FILTERS="1:remote"
virsh list</command></screen>
-
+ <table id='guesttypes' frame='all'>
+ <title>Guest Types</title>
+ <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' />
+ <colspec colname='c2' />
+ <thead>
+ <row>
+ <entry><para>Driver</para></entry>
+ <entry><para>Guest Type</para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>qemu</para>
+ </entry>
+ <entry>
+ <para>
+ Always "hvm"
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>xen</para>
+ </entry>
+ <entry>
+ <para>
+ Either "xen" for a paravirtualized guest or
"hvm" for a fully virtualized guest
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>uml</para>
+ </entry>
+ <entry>
+ <para>
+ Always "uml"
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>lxc</para>
+ </entry>
+ <entry>
+ <para>
+ Always "exe"
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>vbox</para>
+ </entry>
+ <entry>
+ <para>
+ Always "hvm"
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>openvz</para>
+ </entry>
+ <entry>
+ <para>
+ Always "exe"
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>one</para>
+ </entry>
+ <entry>
+ <para>
+ Always "hvm"
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>ex</para>
+ </entry>
+ <entry>
+ <para>
+ Not supported at this time
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
<para>
- This example will only print error messages from virsh,
<emphasis>except</emphasis> that
- the remote driver will print all debug, information, warning, and
- error messages.
+ <literal>/guest/arch</literal> is the root of an XML sub-document
describing various virtual
+ hardware aspects of this guest type. It has a single attribute called
+ "name", which can be used to refer back to this sub-document.
+ </para>
+ <para>
+ <literal>/guest/arch/wordsize</literal> is a required element
that describes how many bits per
+ word this guest type uses. This is typically 32 or 64.
+ </para>
+ <para>
+ <literal>/guest/arch/emulator</literal> is an optional element
that describes the
+ default path to the emulator for this guest type. Note that the
+ emulator can be overridden by the
<literal>/guest/arch/domain/emulator</literal>
+ element (described below) for guest types that need alternate binaries.
+ </para>
+ <para>
+ <literal>/guest/arch/loader</literal> is an optional element that
describes the default path to
+ the firmware loader for this guest type. Note that the default loader
+ path can be overridden by the
<literal>/guest/arch/domain/loader</literal> element (described
+ below) for guest types that use alternate loaders. At present, this is
+ only used by the xen driver for HVM guests.
+ </para>
+ <para>
+ There can be zero or more <literal>/guest/arch/machine</literal>
elements that describe
+ the default types of machines that this guest emulator can
+ emulate. These "machines" typically represent the ABI or hardware
+ interface that a guest can be started with. Note that these
+ machine types can be overridden by the
<literal>/guest/arch/domain/machine</literal>
+ elements (described below) for virtualization technologies that
+ provide alternate machine types. Typical values for this are "pc",
+ and "isapc", meaning a regular PCI based PC, and an older, ISA
based
+ PC, respectively.
+ </para>
+ <para>
+ There can be zero or more <literal>/guest/arch/domain</literal>
XML sub-trees (although with
+ zero /guest/arch/domain XML sub-trees, no guests of this driver can be
+ started). Each <literal>/guest/arch/domain</literal> XML
sub-tree has optional <emulator>,
+ <loader>, and <machine> elements that override
the respective defaults
+ specified above. For any of the elements that are missing, the
+ default values are used.
+ </para>
+ <para>
+ The <literal>/guest/features</literal> optional sub-document
describes various additional
+ guest features that can be enabled or disabled, along with their
+ default state and whether they can be toggled on or off.
</para>
- </example>
- </section>
- </section>
- <section
id="libvirt_application_development_guide_using_python-Connections-Integrated-Example">
- <title>Integrated example</title>
- <para>
- This example demonstrates many of the concepts from the chapter
- together, including error checking. While still not a "real" program
- (which would likely be multi-threaded), it's a good example of how to
- write a libvirt program from end to end.
- </para>
-<programlisting><![CDATA[/* example ex28.c */
-/* compile with: gcc -g -Wall ex28.c -o ex28 -lvirt */
-#include <stdio.h>
-#include <stdlib.h>
-#include <libvirt/libvirt.h>
-#include <libvirt/virterror.h>
-
-static void customConnErrorFunc(void *userdata, virErrorPtr err)
-{
- fprintf(stderr, "Connection handler, failure of libvirt library call:\n");
- fprintf(stderr, " Code: %d\n", err->code);
- fprintf(stderr, " Domain: %d\n", err->domain);
- fprintf(stderr, " Message: %s\n", err->message);
- fprintf(stderr, " Level: %d\n", err->level);
- fprintf(stderr, " str1: %s\n", err->str1);
- fprintf(stderr, " str2: %s\n", err->str2);
- fprintf(stderr, " str3: %s\n", err->str3);
- fprintf(stderr, " int1: %d\n", err->int1);
- fprintf(stderr, " int2: %d\n", err->int2);
-}
-
-static void customGlobalErrorFunc(void *userdata, virErrorPtr err)
-{
- fprintf(stderr, "Global handler, failure of libvirt library call:\n");
- fprintf(stderr, " Code: %d\n", err->code);
- fprintf(stderr, " Domain: %d\n", err->domain);
- fprintf(stderr, " Message: %s\n", err->message);
- fprintf(stderr, " Level: %d\n", err->level);
- fprintf(stderr, " str1: %s\n", err->str1);
- fprintf(stderr, " str2: %s\n", err->str2);
- fprintf(stderr, " str3: %s\n", err->str3);
- fprintf(stderr, " int1: %d\n", err->int1);
- fprintf(stderr, " int2: %d\n", err->int2);
-}
-
-int main(int argc, char *argv[])
-{
- virConnectPtr conn1;
- virConnectPtr conn2;
- virConnectPtr conn3;
- virConnectPtr conn4;
- char *caps;
- virError err;
- char *hostname;
- virErrorPtr err2;
- int vcpus;
- unsigned long long node_free_memory;
- virNodeInfo nodeinfo;
- unsigned long long *node_cells_freemem;
- int numnodes;
- int i;
- const char *type;
- unsigned long virtVersion;
- unsigned long libvirtVersion;
- char *uri;
- int is_encrypted;
- int is_secure;
- virSecurityModel secmodel;
-
- /* set a global error function for all connections */
- virSetErrorFunc(NULL, customGlobalErrorFunc);
-
- /* open a connection using the old-style virConnectOpen */
- conn1 = virConnectOpen("qemu:///system");
- if (conn1 == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- return 1;
- }
-
- /* open a read-only connection using the old-style virConnectOpenReadOnly */
- conn2 = virConnectOpenReadOnly("qemu:///system");
- if (conn2 == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- virConnectClose(conn1);
- return 2;
- }
-
- /* open a connection using the new-style virConnectOpenAuth */
- conn3 = virConnectOpenAuth("qemu:///system", virConnectAuthPtrDefault, 0);
- if (conn3 == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- virConnectClose(conn2);
- virConnectClose(conn1);
- return 3;
- }
-
- /* open a read-only connection using the new-style virConnectOpenAuth */
- conn4 = virConnectOpenAuth("qemu:///system", virConnectAuthPtrDefault,
- VIR_CONNECT_RO);
- if (conn4 == NULL) {
- fprintf(stderr, "Failed to open connection to qemu:///system\n");
- virConnectClose(conn3);
- virConnectClose(conn2);
- virConnectClose(conn1);
- return 3;
- }
-
- /* conn1 will use a different error function */
- virConnSetErrorFunc(conn1, NULL, customConnErrorFunc);
-
- /* test out error handling */
- /* this failure will use customConnErrorFunc */
- if (virConnectGetVersion(conn1, NULL) < 0)
- fprintf(stderr, "virConnectGetVersion failed\n");
- /* this failure will use customGlobalErrorFunc */
- if (virConnectGetVersion(conn2, NULL) < 0)
- fprintf(stderr, "virConnectGetVersion failed\n");
-
- /* clear out the per-connection error function; we will report errors with
- * the vir*Error() functions below*/
- virConnSetErrorFunc(conn1, NULL, NULL);
-
- /* clear out the global error function; we will report errors with
- * the vir*Error() functions below*/
- virSetErrorFunc(NULL, NULL);
-
- /* get the capabilities of conn1 */
- caps = virConnectGetCapabilities(conn1);
- if (caps == NULL) {
- virCopyLastError(&err);
- fprintf(stderr, "virConnectGetCapabilities failed: %s\n",
err.message);
- virResetError(&err);
- }
- fprintf(stdout, "Capabilities of connection 1:\n%s\n", caps);
- free(caps);
-
- /* get the hostname reported from conn2 */
- hostname = virConnectGetHostname(conn2);
- if (hostname == NULL) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectGetVersion failed: %s\n",
err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Connection 2 hostname: %s\n", hostname);
- free(hostname);
-
- /* get the maximum number of vcpus supported by conn3 */
- vcpus = virConnectGetMaxVcpus(conn3, NULL);
- if (vcpus < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectGetMaxVcpus failed: %s\n",
err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Maximum number of cpus supported on connection 3: %d\n",
- vcpus);
-
- /* get the amount of free memory available on the node from conn4 */
- node_free_memory = virNodeGetFreeMemory(conn4);
- if (node_free_memory == 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virNodeGetFreeMemory failed: %s\n",
err2->message);
- virFreeError(err2);
- }
- /* get the node information from conn1 */
- if (virNodeGetInfo(conn1, &nodeinfo) < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virNodeGetInfo failed: %s\n", err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Node information from connection 1:\n");
- fprintf(stdout, " Model: %s\n", nodeinfo.model);
- fprintf(stdout, " Memory size: %lukb\n", nodeinfo.memory);
- fprintf(stdout, " Number of CPUs: %u\n", nodeinfo.cpus);
- fprintf(stdout, " MHz of CPUs: %u\n", nodeinfo.mhz);
- fprintf(stdout, " Number of NUMA nodes: %u\n", nodeinfo.nodes);
- fprintf(stdout, " Number of CPU sockets: %u\n", nodeinfo.sockets);
- fprintf(stdout, " Number of CPU cores per socket: %u\n", nodeinfo.cores);
- fprintf(stdout, " Number of CPU threads per core: %u\n",
nodeinfo.threads);
+ </section>
- /* get the amount of memory in each of the NUMA nodes from connection 1 */
- /* we already know the number of nodes from virNodeGetInfo above */
- node_cells_freemem = malloc(nodeinfo.nodes * sizeof(unsigned long long));
- numnodes = virNodeGetCellsFreeMemory(conn1, node_cells_freemem, 0,
- nodeinfo.nodes);
- if (numnodes < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virNodeGetCellsFreeMemory failed: %s\n",
- err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Node Cells Free Memory from connection 1:\n");
- for (i = 0; i < numnodes; i++)
- fprintf(stdout, " Cell %d: %llukb free memory\n", i,
- node_cells_freemem[i]);
- free(node_cells_freemem);
+ <section
id="libvirt_application_development_guide_using_python-Connections-Host_Info">
+ <title>Host information</title>
+ <para>
+ There are various Python <literal>virConnection</literal> methods
that can be used to get
+ information about the virtualization host, including the hostname, maximum
support guest
+ CPUs, etc.
+ </para>
- /* get the virtualization type from conn2 */
- type = virConnectGetType(conn2);
- if (type == NULL) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectGetType failed: %s\n", err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Virtualization type from connection 2: %s\n", type);
+ <section>
+ <title>getHostname</title>
+ <para>
+ The <command>getHostname</command> method can be used to
obtain the hostname
+ of the virtualization host as returned by gethostname(2). It takes a
+ connection pointer in and, if successful, returns a string
+ containing the hostname. If an error occurred, NULL will be returned
+ instead. It is the responsibility of the caller to free the memory
+ returned from this API call. The following code demonstrates the use of
+ <command>getHostname</command>:
+ </para>
+ <example id="Example-ConnectGetHostname">
+ <title>Using virConnectGetHostname</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-9.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>virConnectGetMaxVcpus</title>
+ <para>
+ The <command>virConnectGetMaxVcpus</command> API call can be
used to obtain the maximum
+ number of virtual CPUs per-guest the underlying virtualization
+ technology supports. It takes a
+ virtualization "type" as input (which can be
<literal>None</literal>), and if successful,
+ returns the number of virtual CPUs supported. If an error occurred,
+ -1 is returned instead. The following code demonstrates the use of
+ <command>getMaxVcpus</command>:
+ </para>
+ <example id="Example-ConnectGetMaxVcpus">
+ <title>Using virConnectGetMaxVcpus</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-10.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>getInfo</title>
+ <para>
+ The <command>getInfo</command> method can be used to obtain
various information
+ about the virtualization host. The method returns a Python
<literal>List</literal> if
+ successful and <literal>None</literal> if and error occurred.
The Python <literal>List</literal>
+ contains the following members:
+ </para>
+ <table id='virNodeInfo-structure-mem' frame='all'>
+ <title>virNodeInfo structure members</title>
+ <tgroup cols='2' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' />
+ <colspec colname='c2' />
+ <thead>
+ <row>
+ <entry><para>Member</para></entry>
+
<entry><para>Description</para></entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <para>listl0]</para>
+ </entry>
+ <entry>
+ <para>
+ string indicating the CPU model
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>list[1]</para>
+ </entry>
+ <entry>
+ <para>
+ memory size in kilobytes
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>list[2]</para>
+ </entry>
+ <entry>
+ <para>
+ the number of active CPUs
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>list[3]</para>
+ </entry>
+ <entry>
+ <para>
+ expected CPU frequency (mhz)
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>list[4]</para>
+ </entry>
+ <entry>
+ <para>
+ the number of NUMA nodes, 1 for uniform memory
access
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>list[5]</para>
+ </entry>
+ <entry>
+ <para>
+ number of CPU sockets per node
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>list[6]</para>
+ </entry>
+ <entry>
+ <para>
+ number of cores per socket
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <para>list[7]</para>
+ </entry>
+ <entry>
+ <para>
+ number of threads per core
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ The following code demonstrates the use of
<command>virNodeGetInfo</command>:
+ </para>
+ <example id="Example-NodeGetInfo">
+ <title>Using virNodeGetInfo</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-12.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>getCellsFreeMemory</title>
+ <para>
+ The <command>getCellsFreeMemory</command> method can be used
to obtain the
+ amount of free memory (in kilobytes) in some or all of the NUMA
+ nodes in the system. It takes as input thet starting cell
+ and the maximum number of cells to retrieve data from.
+ If successful, aPython <literal>List</literal> is returned
with the
+ amount of free memory in each node
+ On failure <literal>None</literal> is returned. The
following code
+ demonstrates the use of
<command>getCellsFreeMemory</command>:
+ </para>
+ <example id="Example-NodeGetCellsFreeMemory">
+ <title>Using virNodeGetCellsFreeMemory</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-13.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>getType</title>
+ <para>
+ The <command>getType</command> method can be used to obtain
the type of
+ virtualization in use on this connection.
+ If successful it returns a string representing
+ the type of virtualization in use.
+ If an error occurred, <literal>None</literal> will be
returned
+ instead. The following code demonstrates the use of
<command>getType</command>:
+ </para>
+ <example id="Example-ConnectGetType">
+ <title>Using virConnectGetType</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-14.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>getVersion</title>
+ <para>
+ The <command>getVersion</command> method can be used to
obtain the version of
+ the host virtualization software in use. If successful it returns a
Python string
+ with the version, otherwise it returns
<literal>None</literal>.
+ The following code demonstrates the use of
<command>getVersion</command>:
+ </para>
+ <example id="Example-ConnectGetVersion">
+ <title>Using virConnectGetVersion</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-15.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>getLibVersion</title>
+ <para>
+ The <command>getLibVersion</command> method can be used to
obtain the version of
+ the libvirt software in use on the host.
+ If successful it retirns a Python string with the version, otherwise it
returns
+ <literal>None</literal>. The following code demonstrates the
+ use of <command>getLibVersion</command>:
+ </para>
+ <example id="Example-ConnectGetLibVersion">
+ <title>Using virConnectGetLibVersion</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-16.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>getURI</title>
+ <para>
+ The <command>getURI</command> method can be used to obtain
the URI for the
+ current connection. While this is typically the same string that
+ was passed into the <command>open</command> call, the
underlying driver can
+ sometimes canonicalize the string. This method will return the
+ canonical version. If successful, it returns a URI string. If
+ an error occurred, <literal>None</literal> will be returned
instead.
+ The following code demonstrates the use of
<command>getURI</command>:
+ </para>
+ <example id="Example-ConnectGetURI">
+ <title>Using virConnectGetURI</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-17.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>isEncrypted</title>
+ <para>
+ The <command>isEncrypted</command> method can be used to find
out if a given
+ connection is encrypted.
+ If successful it returns 1 for an encrypted connection and 0 for an
+ unencrypted connection. If an error occurred, -1 will be returned.
+ The following code demonstrates the use of
<command>isEncrypted</command>:
+ </para>
+ <example id="Example-ConnectIsEncrypted">
+ <title>Using virConnectIsEncrypted</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-18.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+
+ <section>
+ <title>isSecure</title>
+ <para>
+ The <command>isSecure</command> method can be used to find
out if a given
+ connection is encrypted. A connection will be classified secure if
+ it is either encrypted or it is running on a channel which is not
+ vulnerable to eavsdropping (like a UNIX domain socket).
+ If successful it returns 1 for a
+ secure connection and 0 for an insecure connection. If an error
+ occurred, -1 will be returned. The following code demonstrates the use
+ of <command>isSecure</command>:
+ </para>
+ <example id="Example-ConnectIsSecure">
+ <title>Using virConnectIsSecure</title>
+ <programlisting language="Python"><xi:include
href="extras/Connections-Example-19.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
- /* get the virtualization version from conn3 */
- if (virConnectGetVersion(conn3, &virtVersion) < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectGetVersion failed: %s\n",
err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Virtualization version from connection 3: %lu\n",
- virtVersion);
+ </section>
- /* get the libvirt version from conn4 */
- if (virConnectGetLibVersion(conn4, &libvirtVersion) < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectGetLibVersion failed: %s\n",
err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Libvirt version from connection 4: %lu\n",
libvirtVersion);
+ <section
id="libvirt_application_development_guide_using_python-Connections-Event_Loop">
+ <title>Event loop integration</title>
+ <para>
+ Unlike the libvirt C interface, the Python libvirt module does not provide a
+ mechanism for event loop integration. This is a known problem and may be
addressed
+ in a future version of the libvirt module.
+ </para>
+ </section>
- /* get the URI from conn1 */
- uri = virConnectGetURI(conn1);
- if (uri == NULL) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectGetURI failed: %s\n", err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Canonical URI from connection 1: %s\n", uri);
- free(uri);
+ <section
id="libvirt_application_development_guide_using_python-Connections-Security">
+ <title>Security model</title>
+ <para>
+ Unlike the libvirt C interface, the Python libvirt module does not provide a
+ mechanism for accessing the security model. This is a known problem and may
be addressed
+ in a future version of the libvirt module.
+ </para>
+ </section>
- /* is the connection encrypted? from conn2 */
- is_encrypted = virConnectIsEncrypted(conn2);
- if (is_encrypted < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectIsEncrypted failed: %s\n",
err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Connection 2 %s encrypted\n",
- (is_encrypted == 0) ? "is not" : "is");
+ <section
id="libvirt_application_development_guide_using_python-Connections-Debug">
+ <title>Debugging / logging</title>
+ <para>
+ Libvirt includes logging facilities to facilitate the tracing of library
+ execution. These logs will frequently be requested when trying to
+ obtain support for libvirt, so familiarity with them is essential.
+ </para>
+ <para>
+ The logging facilities in libvirt are based on 3 key concepts:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ Log messages - generated at runtime by the libvirt code, they
include
+ a timestamp, a priority level (DEBUG = 1, INFO = 2, WARNING = 3,
ERROR = 4),
+ a category, function name and line number indicating where the
+ message originated from, and a formatted message.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Log filters - patterns and priorities which control whether or
+ not a particular message is displayed. The format for a filter is:
+ </para>
+ <para><screen>x:name</screen></para>
+ <para>
+ where "x" is the minimal priority level where the match
should apply, and
+ "name" is a string to match against. The priority levels
are:
+ </para>
+ <itemizedlist>
+ <listitem><para>1 (or debug) - log all
messages</para></listitem>
+ <listitem><para>2 (or info) - log all non-debugging
information</para></listitem>
+ <listitem><para>3 (or warn) - log only warnings and
errors - this is the default</para></listitem>
+ <listitem><para>4 (or error) - log only
errors</para></listitem>
+ </itemizedlist>
+ <para>
+ For instance, to log all debug messages to the qemu driver, the
+ following filter can be used:
+ </para>
+ <para><screen>1:qemu</screen></para>
+ <para>
+ Multiple filters can be specified together by space separating them;
+ the following example logs all debug messages from qemu, and logs
+ all error messages from the remote driver:
+ </para>
+ <para><screen>1:qemu 4:remote</screen></para>
+ </listitem>
+ <listitem>
+ <para>
+ Log outputs - where to send the message once it has passed
+ through filters. The format for a log output is one of the forms:
+ </para>
+ <para>
+<screen>x:stderr - log to stderr
+x:syslog:name - log to syslog with a prefix of "name"
+x:file:file_path - log to a file specified by "file_path"</screen>
+ </para>
+ <para>
+ where "x" is the minimal priority level. For instance, to
log all
+ warnings and errors to syslog with a prefix of "libvirtd",
the
+ following output can be used:
+ </para>
+ <para><screen>3:syslog:libvirtd</screen></para>
+ <para>
+ Multiple outputs can be specified by space separating them; the
+ following example logs all error and warning messages to syslog, and
+ logs all debug, information, warning, and error messages to
+ <filename>/tmp/libvirt.log</filename>:
+ </para>
+ <para><screen>3:syslog:libvirtd
1:file:/tmp/libvirt.log</screen></para>
+ </listitem>
+ </orderedlist>
+
+ <section>
+ <title>Environment Variables</title>
+ <para>
+ The desired log priority level, filters, and outputs are specified to
+ the libvirt library through the use of environment variables:
+ </para>
+ <orderedlist>
+ <listitem>
+ <para>
+ <literal>LIBVIRT_DEBUG</literal> specifies the
minimum priority level messages that
+ will be logged. This can be thought of as a "global"
priority level;
+ if a particular log message does not match a specific filter in
+ <literal>LIBVIRT_LOG_FILTERS</literal>, it will be
compared to this global priority and
+ logged as appropriate.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LIBVIRT_LOG_FILTERS</literal> specifies the
filters to apply.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LIBVIRT_LOG_OUTPUTS</literal> specifies the
outputs to send the message to.
+ </para>
+ </listitem>
+ </orderedlist>
+ <example>
+ <title>Running virsh with environment variables</title>
+ <para>
+ To see more detailed information about what is going on with virsh,
+ we may run it like the following:
+ </para>
+<screen><command>LIBVIRT_DEBUG=error LIBVIRT_LOG_FILTERS="1:remote"
virsh list</command></screen>
+ <para>
+ This example will only print error messages from virsh,
<emphasis>except</emphasis> that
+ the remote driver will print all debug, information, warning, and
+ error messages.
+ </para>
+ </example>
+ </section>
+ </section>
- /* is the connection secure? from conn3 */
- is_secure = virConnectIsSecure(conn3);
- if (is_secure < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virConnectIsSecure failed: %s\n", err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Connection 3 %s secure\n",
- (is_secure == 0) ? "is not" : "is");
+ <section
id="libvirt_application_development_guide_using_python-Connections-Integrated-Example">
+ <title>Integrated example</title>
+ <para>
+ This example demonstrates many of the concepts from the chapter
+ together, including error checking. While still not a "real"
program
+ (which would likely be multi-threaded), it's a good example of how to
+ write a libvirt program from end to end.
+ </para>
+ <programlisting><![CDATA[/* example ex28.c */
+ /* compile with: gcc -g -Wall ex28.c -o ex28 -lvirt */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <libvirt/libvirt.h>
+ #include <libvirt/virterror.h>
+
+ static void customConnErrorFunc(void *userdata, virErrorPtr err)
+ {
+ fprintf(stderr, "Connection handler, failure of libvirt library
call:\n");
+ fprintf(stderr, " Code: %d\n", err->code);
+ fprintf(stderr, " Domain: %d\n", err->domain);
+ fprintf(stderr, " Message: %s\n", err->message);
+ fprintf(stderr, " Level: %d\n", err->level);
+ fprintf(stderr, " str1: %s\n", err->str1);
+ fprintf(stderr, " str2: %s\n", err->str2);
+ fprintf(stderr, " str3: %s\n", err->str3);
+ fprintf(stderr, " int1: %d\n", err->int1);
+ fprintf(stderr, " int2: %d\n", err->int2);
+ }
- /* get the security model from conn4 */
- if (virNodeGetSecurityModel(conn4, &secmodel) < 0) {
- err2 = virSaveLastError();
- fprintf(stderr, "virNodeGetSecurityModel failed: %s\n",
err2->message);
- virFreeError(err2);
- }
- fprintf(stdout, "Connection 4 Security Model = %s, DOI = %s\n",
- secmodel.model, secmodel.doi);
+ static void customGlobalErrorFunc(void *userdata, virErrorPtr err)
+ {
+ fprintf(stderr, "Global handler, failure of libvirt library
call:\n");
+ fprintf(stderr, " Code: %d\n", err->code);
+ fprintf(stderr, " Domain: %d\n", err->domain);
+ fprintf(stderr, " Message: %s\n", err->message);
+ fprintf(stderr, " Level: %d\n", err->level);
+ fprintf(stderr, " str1: %s\n", err->str1);
+ fprintf(stderr, " str2: %s\n", err->str2);
+ fprintf(stderr, " str3: %s\n", err->str3);
+ fprintf(stderr, " int1: %d\n", err->int1);
+ fprintf(stderr, " int2: %d\n", err->int2);
+ }
- virConnectClose(conn4);
- virConnectClose(conn3);
- virConnectClose(conn2);
- virConnectClose(conn1);
- return 0;
-}]]></programlisting>
- </section>
+ int main(int argc, char *argv[])
+ {
+ virConnectPtr conn1;
+ virConnectPtr conn2;
+ virConnectPtr conn3;
+ virConnectPtr conn4;
+ char *caps;
+ virError err;
+ char *hostname;
+ virErrorPtr err2;
+ int vcpus;
+ unsigned long long node_free_memory;
+ virNodeInfo nodeinfo;
+ unsigned long long *node_cells_freemem;
+ int numnodes;
+ int i;
+ const char *type;
+ unsigned long virtVersion;
+ unsigned long libvirtVersion;
+ char *uri;
+ int is_encrypted;
+ int is_secure;
+ virSecurityModel secmodel;
+
+ /* set a global error function for all connections */
+ virSetErrorFunc(NULL, customGlobalErrorFunc);
+
+ /* open a connection using the old-style virConnectOpen */
+ conn1 = virConnectOpen("qemu:///system");
+ if (conn1 == NULL) {
+ fprintf(stderr, "Failed to open connection to
qemu:///system\n");
+ return 1;
+ }
+
+ /* open a read-only connection using the old-style virConnectOpenReadOnly */
+ conn2 = virConnectOpenReadOnly("qemu:///system");
+ if (conn2 == NULL) {
+ fprintf(stderr, "Failed to open connection to
qemu:///system\n");
+ virConnectClose(conn1);
+ return 2;
+ }
+
+ /* open a connection using the new-style virConnectOpenAuth */
+ conn3 = virConnectOpenAuth("qemu:///system",
virConnectAuthPtrDefault, 0);
+ if (conn3 == NULL) {
+ fprintf(stderr, "Failed to open connection to
qemu:///system\n");
+ virConnectClose(conn2);
+ virConnectClose(conn1);
+ return 3;
+ }
+
+ /* open a read-only connection using the new-style virConnectOpenAuth */
+ conn4 = virConnectOpenAuth("qemu:///system",
virConnectAuthPtrDefault,
+ VIR_CONNECT_RO);
+ if (conn4 == NULL) {
+ fprintf(stderr, "Failed to open connection to
qemu:///system\n");
+ virConnectClose(conn3);
+ virConnectClose(conn2);
+ virConnectClose(conn1);
+ return 3;
+ }
+
+ /* conn1 will use a different error function */
+ virConnSetErrorFunc(conn1, NULL, customConnErrorFunc);
+
+ /* test out error handling */
+ /* this failure will use customConnErrorFunc */
+ if (virConnectGetVersion(conn1, NULL) < 0)
+ fprintf(stderr, "virConnectGetVersion failed\n");
+ /* this failure will use customGlobalErrorFunc */
+ if (virConnectGetVersion(conn2, NULL) < 0)
+ fprintf(stderr, "virConnectGetVersion failed\n");
+
+ /* clear out the per-connection error function; we will report errors with
+ * the vir*Error() functions below*/
+ virConnSetErrorFunc(conn1, NULL, NULL);
+
+ /* clear out the global error function; we will report errors with
+ * the vir*Error() functions below*/
+ virSetErrorFunc(NULL, NULL);
+
+ /* get the capabilities of conn1 */
+ caps = virConnectGetCapabilities(conn1);
+ if (caps == NULL) {
+ virCopyLastError(&err);
+ fprintf(stderr, "virConnectGetCapabilities failed: %s\n",
err.message);
+ virResetError(&err);
+ }
+ fprintf(stdout, "Capabilities of connection 1:\n%s\n", caps);
+ free(caps);
+
+ /* get the hostname reported from conn2 */
+ hostname = virConnectGetHostname(conn2);
+ if (hostname == NULL) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectGetVersion failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Connection 2 hostname: %s\n", hostname);
+ free(hostname);
+
+ /* get the maximum number of vcpus supported by conn3 */
+ vcpus = virConnectGetMaxVcpus(conn3, NULL);
+ if (vcpus < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectGetMaxVcpus failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Maximum number of cpus supported on connection 3:
%d\n",
+ vcpus);
+
+ /* get the amount of free memory available on the node from conn4 */
+ node_free_memory = virNodeGetFreeMemory(conn4);
+ if (node_free_memory == 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virNodeGetFreeMemory failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+
+ /* get the node information from conn1 */
+ if (virNodeGetInfo(conn1, &nodeinfo) < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virNodeGetInfo failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Node information from connection 1:\n");
+ fprintf(stdout, " Model: %s\n", nodeinfo.model);
+ fprintf(stdout, " Memory size: %lukb\n", nodeinfo.memory);
+ fprintf(stdout, " Number of CPUs: %u\n", nodeinfo.cpus);
+ fprintf(stdout, " MHz of CPUs: %u\n", nodeinfo.mhz);
+ fprintf(stdout, " Number of NUMA nodes: %u\n", nodeinfo.nodes);
+ fprintf(stdout, " Number of CPU sockets: %u\n", nodeinfo.sockets);
+ fprintf(stdout, " Number of CPU cores per socket: %u\n",
nodeinfo.cores);
+ fprintf(stdout, " Number of CPU threads per core: %u\n",
nodeinfo.threads);
+
+ /* get the amount of memory in each of the NUMA nodes from connection 1 */
+ /* we already know the number of nodes from virNodeGetInfo above */
+ node_cells_freemem = malloc(nodeinfo.nodes * sizeof(unsigned long long));
+ numnodes = virNodeGetCellsFreeMemory(conn1, node_cells_freemem, 0,
+ nodeinfo.nodes);
+ if (numnodes < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virNodeGetCellsFreeMemory failed: %s\n",
+ err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Node Cells Free Memory from connection 1:\n");
+ for (i = 0; i < numnodes; i++)
+ fprintf(stdout, " Cell %d: %llukb free memory\n", i,
+ node_cells_freemem[i]);
+ free(node_cells_freemem);
+
+ /* get the virtualization type from conn2 */
+ type = virConnectGetType(conn2);
+ if (type == NULL) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectGetType failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Virtualization type from connection 2: %s\n",
type);
+
+ /* get the virtualization version from conn3 */
+ if (virConnectGetVersion(conn3, &virtVersion) < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectGetVersion failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Virtualization version from connection 3: %lu\n",
+ virtVersion);
+
+ /* get the libvirt version from conn4 */
+ if (virConnectGetLibVersion(conn4, &libvirtVersion) < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectGetLibVersion failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Libvirt version from connection 4: %lu\n",
libvirtVersion);
+
+ /* get the URI from conn1 */
+ uri = virConnectGetURI(conn1);
+ if (uri == NULL) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectGetURI failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Canonical URI from connection 1: %s\n", uri);
+ free(uri);
+
+ /* is the connection encrypted? from conn2 */
+ is_encrypted = virConnectIsEncrypted(conn2);
+ if (is_encrypted < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectIsEncrypted failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Connection 2 %s encrypted\n",
+ (is_encrypted == 0) ? "is not" : "is");
+
+ /* is the connection secure? from conn3 */
+ is_secure = virConnectIsSecure(conn3);
+ if (is_secure < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virConnectIsSecure failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Connection 3 %s secure\n",
+ (is_secure == 0) ? "is not" : "is");
+
+ /* get the security model from conn4 */
+ if (virNodeGetSecurityModel(conn4, &secmodel) < 0) {
+ err2 = virSaveLastError();
+ fprintf(stderr, "virNodeGetSecurityModel failed: %s\n",
err2->message);
+ virFreeError(err2);
+ }
+ fprintf(stdout, "Connection 4 Security Model = %s, DOI = %s\n",
+ secmodel.model, secmodel.doi);
+
+ virConnectClose(conn4);
+ virConnectClose(conn3);
+ virConnectClose(conn2);
+ virConnectClose(conn1);
+ return 0;
+ }]]></programlisting>
+ </section>
</chapter>
diff --git a/en-US/Error_Handling.xml b/en-US/Error_Handling.xml
new file mode 100644
index 0000000..5984f1b
--- /dev/null
+++ b/en-US/Error_Handling.xml
@@ -0,0 +1,306 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM
"Libvirt_Application_Development_Guide_Using_Python.ent">
+%BOOK_ENTITIES;
+]>
+<chapter
id="libvirt_application_development_guide_using_python-Error_Handling">
+ <title>Error Handling</title>
+ <para>
+ The libvirt error functions are designed to give more detailed information
+ about what caused a failure in the case that a normal libvirt function or method
+ returned an error. An important thing to note about Python libvirt error
+ reporting is that errors are stored on a per thread basis and not per
connection.
+ </para>
+ <para>
+ The libvirt Python module defines a standard exception class
<literal>libvirtError</literal>
+ that can be overloaded to add additional functionality when raising a libvirt
exception.
+ The <literal>libvirtError</literal> class definition looks like:
+ </para>
+ <programlisting language="Python"><![CDATA[class
libvirtError(Exception):
+ def __init__(self, defmsg, conn=None, dom=None, net=None, pool=None, vol=None):
+
+ # Never call virConnGetLastError().
+ # virGetLastError() is now thread local
+ err = virGetLastError()
+ if err is None:
+ msg = defmsg
+ else:
+ msg = err[2]
+
+ Exception.__init__(self, msg)
+
+ self.err = err
+
+ def get_error_code(self):
+ if self.err is None:
+ return None
+ return self.err[0]
+
+ def get_error_domain(self):
+ if self.err is None:
+ return None
+ return self.err[1]
+
+ def get_error_message(self):
+ if self.err is None:
+ return None
+ return self.err[2]
+
+ def get_error_level(self):
+ if self.err is None:
+ return None
+ return self.err[3]
+
+ def get_str1(self):
+ if self.err is None:
+ return None
+ return self.err[4]
+
+ def get_str2(self):
+ if self.err is None:
+ return None
+ return self.err[5]
+
+ def get_str3(self):
+ if self.err is None:
+ return None
+ return self.err[6]
+
+ def get_int1(self):
+ if self.err is None:
+ return None
+ return self.err[7]
+
+ def get_int2(self):
+ if self.err is None:
+ return None
+ return self.err[8]]]></programlisting>
+ <para>
+ There are a few things to note about this definition. The first is that you can
instantiate this class
+ by using the Python <literal>raise</literal> statement. Actually this
is not of much use unless
+ you overload the class with your own class which would contain
+ the needed behaviour. You should also make note of the methods which can obtain
the error
+ information. A description of these methods follows:
+ </para>
+ <para>
+ The method <literal>get_error_code</literal> returns the error code
that was
+ returned from the error. This is one of the data definition from the Python
libvirt module.
+ Some of the higher numbered entries from this list my not be available in your
Python
+ libvirt module.
+ </para>
+ <programlisting language="Python"><![CDATA[VIR_ERR_OK = 0
+VIR_ERR_INTERNAL_ERROR = 1 # internal error
+VIR_ERR_NO_MEMORY = 2 # memory allocation failure
+VIR_ERR_NO_SUPPORT = 3 # no support for this function
+VIR_ERR_UNKNOWN_HOST = 4 # could not resolve hostname
+VIR_ERR_NO_CONNECT = 5 # can not connect to hypervisor
+VIR_ERR_INVALID_CONN = 6 # invalid connection object
+VIR_ERR_INVALID_DOMAIN = 7 # invalid domain object
+VIR_ERR_INVALID_ARG = 8 # invalid function argument
+VIR_ERR_OPERATION_FAILED = 9 # a command to hypervisor failed
+VIR_ERR_GET_FAILED = 10 # a HTTP GET command to failed
+VIR_ERR_POST_FAILED = 11 # a HTTP POST command to failed
+VIR_ERR_HTTP_ERROR = 12 # unexpected HTTP error code
+VIR_ERR_SEXPR_SERIAL = 13 # failure to serialize an S-Expr
+VIR_ERR_NO_XEN = 14 # could not open Xen hypervisor control
+VIR_ERR_XEN_CALL = 15 # failure doing an hypervisor call
+VIR_ERR_OS_TYPE = 16 # unknown OS type
+VIR_ERR_NO_KERNEL = 17 # missing kernel information
+VIR_ERR_NO_ROOT = 18 # missing root device information
+VIR_ERR_NO_SOURCE = 19 # missing source device information
+VIR_ERR_NO_TARGET = 20 # missing target device information
+VIR_ERR_NO_NAME = 21 # missing domain name information
+VIR_ERR_NO_OS = 22 # missing domain OS information
+VIR_ERR_NO_DEVICE = 23 # missing domain devices information
+VIR_ERR_NO_XENSTORE = 24 # could not open Xen Store control
+VIR_ERR_DRIVER_FULL = 25 # too many drivers registered
+VIR_ERR_CALL_FAILED = 26 # not supported by the drivers (DEPRECATED)
+VIR_ERR_XML_ERROR = 27 # an XML description is not well formed or broken
+VIR_ERR_DOM_EXIST = 28 # the domain already exist
+VIR_ERR_OPERATION_DENIED = 29 # operation forbidden on read-only connections
+VIR_ERR_OPEN_FAILED = 30 # failed to open a conf file
+VIR_ERR_READ_FAILED = 31 # failed to read a conf file
+VIR_ERR_PARSE_FAILED = 32 # failed to parse a conf file
+VIR_ERR_CONF_SYNTAX = 33 # failed to parse the syntax of a conf file
+VIR_ERR_WRITE_FAILED = 34 # failed to write a conf file
+VIR_ERR_XML_DETAIL = 35 # detail of an XML error
+VIR_ERR_INVALID_NETWORK = 36 # invalid network object
+VIR_ERR_NETWORK_EXIST = 37 # the network already exist
+VIR_ERR_SYSTEM_ERROR = 38 # general system call failure
+VIR_ERR_RPC = 39 # some sort of RPC error
+VIR_ERR_GNUTLS_ERROR = 40 # error from a GNUTLS call
+VIR_WAR_NO_NETWORK = 41 # failed to start network
+VIR_ERR_NO_DOMAIN = 42 # domain not found or unexpectedly disappeared
+VIR_ERR_NO_NETWORK = 43 # network not found
+VIR_ERR_INVALID_MAC = 44 # invalid MAC address
+VIR_ERR_AUTH_FAILED = 45 # authentication failed
+VIR_ERR_INVALID_STORAGE_POOL = 46 # invalid storage pool object
+VIR_ERR_INVALID_STORAGE_VOL = 47 # invalid storage vol object
+VIR_WAR_NO_STORAGE = 48 # failed to start storage
+VIR_ERR_NO_STORAGE_POOL = 49 # storage pool not found
+VIR_ERR_NO_STORAGE_VOL = 50 # storage pool not found
+VIR_WAR_NO_NODE = 51 # failed to start node driver
+VIR_ERR_INVALID_NODE_DEVICE = 52 # invalid node device object
+VIR_ERR_NO_NODE_DEVICE = 53 # node device not found
+VIR_ERR_NO_SECURITY_MODEL = 54 # security model not found
+VIR_ERR_OPERATION_INVALID = 55 # operation is not applicable at this time
+VIR_WAR_NO_INTERFACE = 56 # failed to start interface driver
+VIR_ERR_NO_INTERFACE = 57 # interface driver not running
+VIR_ERR_INVALID_INTERFACE = 58 # invalid interface object
+VIR_ERR_MULTIPLE_INTERFACES = 59 # more than one matching interface found
+VIR_WAR_NO_NWFILTER = 60 # failed to start nwfilter driver
+VIR_ERR_INVALID_NWFILTER = 61 # invalid nwfilter object
+VIR_ERR_NO_NWFILTER = 62 # nw filter pool not found
+VIR_ERR_BUILD_FIREWALL = 63 # nw filter pool not found
+VIR_WAR_NO_SECRET = 64 # failed to start secret storage
+VIR_ERR_INVALID_SECRET = 65 # invalid secret
+VIR_ERR_NO_SECRET = 66 # secret not found
+VIR_ERR_CONFIG_UNSUPPORTED = 67 # unsupported configuration construct
+VIR_ERR_OPERATION_TIMEOUT = 68 # timeout occurred during operation
+VIR_ERR_MIGRATE_PERSIST_FAILED = 69 # a migration worked, but making the VM persist on
the dest host failed
+VIR_ERR_HOOK_SCRIPT_FAILED = 70 # a synchronous hook script failed
+VIR_ERR_INVALID_DOMAIN_SNAPSHOT = 71 # invalid domain snapshot
+VIR_ERR_NO_DOMAIN_SNAPSHOT = 72 # domain snapshot was not found
+VIR_ERR_INVALID_STREAM = 73 # invalid i/o stream
+VIR_ERR_ARGUMENT_UNSUPPORTED = 74 # an argument was unsupported
+VIR_ERR_STORAGE_PROBE_FAILED = 75 # a storage probe failed
+VIR_ERR_STORAGE_POOL_BUILT = 76
+VIR_ERR_SNAPSHOT_REVERT_RISKY = 77
+VIR_ERR_OPERATION_ABORTED = 78 # the operation was aborted
+VIR_ERR_AUTH_CANCELLED = 79
+VIR_ERR_NO_DOMAIN_METADATA = 80 # no domain metadata was found
+VIR_ERR_MIGRATE_UNSAFE = 81
+VIR_ERR_OVERFLOW = 82 # an overflow situation was detected
+VIR_ERR_BLOCK_COPY_ACTIVE = 83
+VIR_ERR_OPERATION_UNSUPPORTED = 84 # the operation was unsupported
+VIR_ERR_SSH = 85 # an ssh error was detected
+VIR_ERR_AGENT_UNRESPONSIVE = 86 # an agent timeout was detected
+VIR_ERR_RESOURCE_BUSY = 87
+VIR_ERR_ACCESS_DENIED = 88
+VIR_ERR_DBUS_SERVICE = 89
+VIR_ERR_STORAGE_VOL_EXIST = 90
+VIR_ERR_CPU_INCOMPATIBLE = 91
+VIR_ERR_XML_INVALID_SCHEMA = 92]]></programlisting>
+ <para>
+ The method <literal>get_error_domain</literal> is named that for
legacy
+ reasons, but really represents which part of libvirt generated the
+ error. This is one of the data definition from the Python libvirt module.
+ Some of the higher numbered entries from this list my not be available in your
Python
+ libvirt module. The full list is:
+ </para>
+ <programlisting language="Python"><![CDATA[VIR_FROM_NONE = 0
+VIR_FROM_XEN = 1 # Error at Xen hypervisor layer
+VIR_FROM_XEND = 2 # Error at connection with xend daemon
+VIR_FROM_XENSTORE = 3 # Error at connection with xen store
+VIR_FROM_SEXPR = 4 # Error in the S-Expression code
+VIR_FROM_XML = 5 # Error in the XML code
+VIR_FROM_DOM = 6 # Error when operating on a domain
+VIR_FROM_RPC = 7 # Error in the XML-RPC code
+VIR_FROM_PROXY = 8 # Error in the proxy code
+VIR_FROM_CONF = 9 # Error in the configuration file handling
+VIR_FROM_QEMU = 10 # Error at the QEMU daemon
+VIR_FROM_NET = 11 # Error when operating on a network
+VIR_FROM_TEST = 12 # Error from test driver
+VIR_FROM_REMOTE = 13 # Error from remote driver
+VIR_FROM_OPENVZ = 14 # Error from OpenVZ driver
+VIR_FROM_XENXM = 15 # Error at Xen XM layer
+VIR_FROM_STATS_LINUX = 16 # Error in the Linux Stats code
+VIR_FROM_LXC = 17 # Error from Linux Container driver
+VIR_FROM_STORAGE = 18 # Error from storage driver
+VIR_FROM_NETWORK = 19 # Error from network config
+VIR_FROM_DOMAIN = 20 # Error from domain config
+VIR_FROM_UML = 21 # Error at the UML driver
+VIR_FROM_NODEDEV = 22 # Error from node device monitor
+VIR_FROM_XEN_INOTIFY = 23 # Error from xen inotify layer
+VIR_FROM_SECURITY = 24 # Error from security framework
+VIR_FROM_VBOX = 25 # Error from VirtualBox driver
+VIR_FROM_INTERFACE = 26 # Error when operating on an interface
+VIR_FROM_ONE = 27 # Error from OpenNebula driver
+VIR_FROM_ESX = 28 # Error from ESX driver
+VIR_FROM_PHYP = 29 # Error from IBM power hypervisor
+VIR_FROM_SECRET = 30 # Error from secret storage
+VIR_FROM_CPU = 31 # Error from CPU driver
+VIR_FROM_XENAPI = 32 # Error from XenAPI
+VIR_FROM_NWFILTER = 33 # Error from network filter driver
+VIR_FROM_HOOK = 34 # Error from Synchronous hooks
+VIR_FROM_DOMAIN_SNAPSHOT = 35 # Error from domain snapshot
+VIR_FROM_AUDIT = 36
+VIR_FROM_SYSINFO = 37
+VIR_FROM_STREAMS = 38
+VIR_FROM_VMWARE = 39
+VIR_FROM_EVENT = 40
+VIR_FROM_LIBXL = 41
+VIR_FROM_LOCKING = 42
+VIR_FROM_HYPERV = 43
+VIR_FROM_CAPABILITIES = 44
+VIR_FROM_URI = 45
+VIR_FROM_AUTH = 46
+VIR_FROM_DBUS = 47
+VIR_FROM_PARALLELS = 48
+VIR_FROM_DEVICE = 49
+VIR_FROM_SSH = 50
+VIR_FROM_LOCKSPACE = 51
+VIR_FROM_INITCTL = 52
+VIR_FROM_IDENTITY = 53
+VIR_FROM_CGROUP = 54
+VIR_FROM_ACCESS = 55
+VIR_FROM_SYSTEMD = 56
+VIR_FROM_BHYVE = 57
+VIR_FROM_CRYPTO = 58
+VIR_FROM_FIREWALL = 59
+VIR_FROM_POLKIT = 60]]></programlisting>
+ <para>
+ The method <literal>get_error_message</literal> is a human-readable
string
+ describing the error.
+ </para>
+ <para>
+ The method <literal>get_error_level</literal> describes the severity
of the
+ error. This is one of the data definition from the Python libvirt module.
+ The full list of levels is:
+ </para>
+ <programlisting language="Python"><![CDATA[VIR_ERR_NONE = 0
+VIR_ERR_WARNING = 1 # A simple warning
+VIR_ERR_ERROR = 2 # An error]]></programlisting>
+ <para>
+ The method <literal>get_error_str1</literal> gives extra human
readable
+ information.
+ </para>
+ <para>
+ The method <literal>get_error_str2</literal> gives extra human
readable
+ information.
+ </para>
+ <para>
+ The method <literal>get_error_str3</literal> gives extra human
readable
+ information.
+ </para>
+ <para>
+ The method <literal>get_error_int1</literal> gives extra numeric
information that
+ may be useful for further classifying the error.
+ </para>
+ <para>
+ The method <literal>get_error_int2</literal> gives extra numeric
information that
+ may be useful for further classifying the error.
+ </para>
+ <para>
+ Example code that uses various parts of this structure will be
+ presented in subsequent sub-sections.
+ </para>
+
+ <section
id="libvirt_application_development_guide_using_python-Error_Handling-virGetLastError">
+ <title>virGetLastError</title>
+ <para>
+ The <literal>virGetLastError</literal> function can be used to
obtain a
+ Python <literal>List</literal> that contains all the information
+ from the error reported from libvirt. This information is kept in thread
local
+ storage so separate threads can safely use this function
+ concurrently. Note that it does not make a copy, so error information
+ can be lost if the current thread calls this function subsequently.
+ The following code demonstrates
+ the use of <literal>virGetLastError</literal>:
+ </para>
+ <example>
+ <title>Using virGetLastError</title>
+ <programlisting language="Python"><xi:include
href="extras/Error-Example-24.py" parse="text"
xmlns:xi="http://www.w3.org/2001/XInclude" /></programlisting>
+ </example>
+ </section>
+</chapter>
diff --git a/en-US/Event_Handling.xml b/en-US/Event_Handling.xml
new file mode 100644
index 0000000..52a2085
--- /dev/null
+++ b/en-US/Event_Handling.xml
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % BOOK_ENTITIES SYSTEM
"Libvirt_Application_Development_Guide_Using_Python.ent">
+%BOOK_ENTITIES;
+]>
+<chapter
id="libvirt_application_development_guide_using_python-Event_Handling">
+ <title>Event Handling</title>
+ <para>
+ TBD
+ </para>
+</chapter>
diff --git a/en-US/Libvirt_Application_Development_Guide_Using_Python.xml
b/en-US/Libvirt_Application_Development_Guide_Using_Python.xml
index cd81aed..39d4cbb 100644
--- a/en-US/Libvirt_Application_Development_Guide_Using_Python.xml
+++ b/en-US/Libvirt_Application_Development_Guide_Using_Python.xml
@@ -14,5 +14,7 @@
<xi:include href="Virtual_Networks.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Network_Interfaces.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Host_Devices.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Error_Handling.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Event_Handling.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Revision_History.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</book>
diff --git a/en-US/extras/Connections-Example-1.py
b/en-US/extras/Connections-Example-1.py
new file mode 100644
index 0000000..cca785e
--- /dev/null
+++ b/en-US/extras/Connections-Example-1.py
@@ -0,0 +1,11 @@
+# Example-1.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-10.py
b/en-US/extras/Connections-Example-10.py
new file mode 100644
index 0000000..b6c7a3c
--- /dev/null
+++ b/en-US/extras/Connections-Example-10.py
@@ -0,0 +1,15 @@
+# Example-10.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+vcpus = conn.getMaxVcpus(None)
+print('Maximum support virtual CPUs: '+str(vcpus))
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-11.py
b/en-US/extras/Connections-Example-11.py
new file mode 100644
index 0000000..57376f8
--- /dev/null
+++ b/en-US/extras/Connections-Example-11.py
@@ -0,0 +1,15 @@
+# Example-11.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+node_free_memory = conn.getFreeMemory()
+print('Node free memory: '+str(node_free_memory))
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-12.py
b/en-US/extras/Connections-Example-12.py
new file mode 100644
index 0000000..bb5ac07
--- /dev/null
+++ b/en-US/extras/Connections-Example-12.py
@@ -0,0 +1,23 @@
+# Example-12.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+nodeinfo = conn.getInfo()
+
+print('Model: '+str(nodeinfo[0]))
+print('Memory size: '+str(nodeinfo[1])+'MB')
+print('Number of CPUs: '+str(nodeinfo[2]))
+print('MHz of CPUs: '+str(nodeinfo[3]))
+print('Number of NUMA nodes: '+str(nodeinfo[4]))
+print('Number of CPU sockets: '+str(nodeinfo[5]))
+print('Number of CPU cores per socket: '+str(nodeinfo[6]))
+print('Number of CPU threads per core: '+str(nodeinfo[7]))
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-13.py
b/en-US/extras/Connections-Example-13.py
new file mode 100644
index 0000000..a8692d0
--- /dev/null
+++ b/en-US/extras/Connections-Example-13.py
@@ -0,0 +1,21 @@
+# Example-13.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+nodeinfo = conn.getInfo()
+numnodes = nodeinfo[4]
+
+memlist = conn.getCellsFreeMemory(0, numnodes)
+cell = 0
+for cellfreemem in memlist:
+ print('Node '+str(cell)+': '+str(cellfreemem)+' bytes free
memory')
+ cell += 1
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-14.py
b/en-US/extras/Connections-Example-14.py
new file mode 100644
index 0000000..054c5d0
--- /dev/null
+++ b/en-US/extras/Connections-Example-14.py
@@ -0,0 +1,14 @@
+# Example-14.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+print('Virtualization type: '+conn.getType())
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-15.py
b/en-US/extras/Connections-Example-15.py
new file mode 100644
index 0000000..bf4277f
--- /dev/null
+++ b/en-US/extras/Connections-Example-15.py
@@ -0,0 +1,15 @@
+# Example-15.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+ver = conn.getVersion()
+print('Version: '+str(ver))
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-16.py
b/en-US/extras/Connections-Example-16.py
new file mode 100644
index 0000000..5f965fa
--- /dev/null
+++ b/en-US/extras/Connections-Example-16.py
@@ -0,0 +1,15 @@
+# Example-16.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+ver = conn.getLibVersion();
+print('Libvirt Version: '+str(ver));
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-17.py
b/en-US/extras/Connections-Example-17.py
new file mode 100644
index 0000000..990c9cb
--- /dev/null
+++ b/en-US/extras/Connections-Example-17.py
@@ -0,0 +1,15 @@
+# Example-17.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+uri = conn.getURI()
+print('Canonical URI: '+uri)
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-18.py
b/en-US/extras/Connections-Example-18.py
new file mode 100644
index 0000000..53d62e3
--- /dev/null
+++ b/en-US/extras/Connections-Example-18.py
@@ -0,0 +1,14 @@
+# Example-15.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+print('Connection is encrypted: '+str(conn.isEncrypted()))
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-19.py
b/en-US/extras/Connections-Example-19.py
new file mode 100644
index 0000000..d05e305
--- /dev/null
+++ b/en-US/extras/Connections-Example-19.py
@@ -0,0 +1,14 @@
+# Example-19.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+print('Connection is secure: '+str(conn.isSecure()))
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-2.py
b/en-US/extras/Connections-Example-2.py
new file mode 100644
index 0000000..1b83b8e
--- /dev/null
+++ b/en-US/extras/Connections-Example-2.py
@@ -0,0 +1,11 @@
+# Example-2.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.openReadOnly('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-20.py
b/en-US/extras/Connections-Example-20.py
new file mode 100644
index 0000000..80464dd
--- /dev/null
+++ b/en-US/extras/Connections-Example-20.py
@@ -0,0 +1,17 @@
+# Example-20.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+secmodel = conn.getSecurityModel()
+
+print('Security Model: '+secmodel[0])
+print('Security DOI: '+secmodel[1])
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-3.py
b/en-US/extras/Connections-Example-3.py
new file mode 100644
index 0000000..472086c
--- /dev/null
+++ b/en-US/extras/Connections-Example-3.py
@@ -0,0 +1,24 @@
+# Example-3.py
+from __future__ import print_function
+import sys
+import libvirt
+
+SASL_USER = "my-super-user"
+SASL_PASS = "my-super-pass"
+
+def request_cred(credentials, user_data):
+ for credential in credentials:
+ if credential[0] == libvirt.VIR_CRED_AUTHNAME:
+ credential[4] = SASL_USER
+ elif credential[0] == libvirt.VIR_CRED_PASSPHRASE:
+ credential[4] = SASL_PASS
+ return 0
+
+auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE], request_cred, None]
+
+conn = libvirt.openAuth('qemu+tcp://localhost/system', auth, 0)
+if conn == None:
+ print('Failed to open connection to qemu+tcp://localhost/system',
file=sys.stderr)
+ exit(1)
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-5.py
b/en-US/extras/Connections-Example-5.py
new file mode 100644
index 0000000..910b62c
--- /dev/null
+++ b/en-US/extras/Connections-Example-5.py
@@ -0,0 +1,16 @@
+# Example-5.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn1 = libvirt.open('qemu:///system')
+if conn1 == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+conn2 = libvirt.open('qemu:///system')
+if conn2 == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+conn1.close()
+conn2.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-6.py
b/en-US/extras/Connections-Example-6.py
new file mode 100644
index 0000000..c312aeb
--- /dev/null
+++ b/en-US/extras/Connections-Example-6.py
@@ -0,0 +1,11 @@
+# Example-6.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-7.py
b/en-US/extras/Connections-Example-7.py
new file mode 100644
index 0000000..0df3c60
--- /dev/null
+++ b/en-US/extras/Connections-Example-7.py
@@ -0,0 +1,11 @@
+# Example-7.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu+tls://host2/system')
+if conn == None:
+ print('Failed to open connection to qemu+tls://host2/system',
file=sys.stderr)
+ exit(1)
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-8.py
b/en-US/extras/Connections-Example-8.py
new file mode 100644
index 0000000..dbb0a0d
--- /dev/null
+++ b/en-US/extras/Connections-Example-8.py
@@ -0,0 +1,15 @@
+# Example-8.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+caps = conn.getCapabilities() # caps will be a string of XML
+print('Capabilities:\n'+caps)
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Connections-Example-8.xml
b/en-US/extras/Connections-Example-8.xml
new file mode 100644
index 0000000..be47c32
--- /dev/null
+++ b/en-US/extras/Connections-Example-8.xml
@@ -0,0 +1,64 @@
+<capabilities>
+ <host>
+ <cpu>
+ <arch>x86_64</arch>
+ </cpu>
+ <migration_features>
+ <live/>
+ <uri_transports>
+ <uri_transport>tcp</uri_transport>
+ </uri_transports>
+ </migration_features>
+ <topology>
+ <cells num='1'>
+ <cell id='0'>
+ <cpus num='2'>
+ <cpu id='0'/>
+ <cpu id='1'/>
+ </cpus>
+ </cell>
+ </cells>
+ </topology>
+ </host>
+
+ <guest>
+ <os_type>hvm</os_type>
+ <arch name='i686'>
+ <wordsize>32</wordsize>
+ <emulator>/usr/bin/qemu</emulator>
+ <machine>pc</machine>
+ <machine>isapc</machine>
+ <domain type='qemu'>
+ </domain>
+ <domain type='kvm'>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ </domain>
+ </arch>
+ <features>
+ <pae/>
+ <nonpae/>
+ <acpi default='on' toggle='yes'/>
+ <apic default='on' toggle='no'/>
+ </features>
+ </guest>
+
+ <guest>
+ <os_type>hvm</os_type>
+ <arch name='x86_64'>
+ <wordsize>64</wordsize>
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
+ <machine>pc</machine>
+ <machine>isapc</machine>
+ <domain type='qemu'>
+ </domain>
+ <domain type='kvm'>
+ <emulator>/usr/bin/qemu-kvm</emulator>
+ </domain>
+ </arch>
+ <features>
+ <acpi default='on' toggle='yes'/>
+ <apic default='on' toggle='no'/>
+ </features>
+ </guest>
+
+</capabilities>
diff --git a/en-US/extras/Connections-Example-9.py
b/en-US/extras/Connections-Example-9.py
new file mode 100644
index 0000000..7a29a0b
--- /dev/null
+++ b/en-US/extras/Connections-Example-9.py
@@ -0,0 +1,15 @@
+# Example-9.py
+from __future__ import print_function
+import sys
+import libvirt
+
+conn = libvirt.open('qemu:///system')
+if conn == None:
+ print('Failed to open connection to qemu:///system', file=sys.stderr)
+ exit(1)
+
+host = conn.getHostname()
+print('Hostname:'+host)
+
+conn.close()
+exit(0)
diff --git a/en-US/extras/Error-Example-24.py b/en-US/extras/Error-Example-24.py
new file mode 100644
index 0000000..387f9f0
--- /dev/null
+++ b/en-US/extras/Error-Example-24.py
@@ -0,0 +1,16 @@
+from __future__ import print_function
+import sys
+import libvirt
+
+def report_libvirt_error():
+ """Call virGetLastError function to get the last error
information."""
+ err = libvirt.virGetLastError()
+ print('Error code: '+str(err[0]), file=sys.stderr)
+ print('Error domain: '+str(err[1]), file=sys.stderr)
+ print('Error message: '+err[2], file=sys.stderr)
+ print('Error level: '+str(err[3]), file=sys.stderr)
+ print('Error string1: '+err[4], file=sys.stderr)
+ print('Error string2: '+err[5], file=sys.stderr)
+ print('Error string3: '+err[6], file=sys.stderr)
+ print('Error int1: '+str(err[7]), file=sys.stderr)
+ print('Error int2: '+str(err[8]), file=sys.stderr)