libvirt connections

来源:互联网 发布:淘宝美即面膜牛奶白滑 编辑:程序博客网 时间:2024/05/16 09:45
3.1. Overview
3.1.1. virConnectOpen
3.1.2. virConnectOpenReadOnly
3.1.3. virConnectOpenAuth
3.1.4. virConnectClose
3.2. URI formats
3.2.1. Local URIs
3.2.2. Remote URIs
3.3. Capability information
3.4. Host information
3.4.1. virConnectGetHostname
3.4.2. virConnectGetMaxVcpus
3.4.3. virNodeGetFreeMemory
3.4.4. virNodeGetInfo
3.4.5. virNodeGetCellsFreeMemory
3.4.6. virConnectGetType
3.4.7. virConnectGetVersion
3.4.8. virConnectGetLibVersion
3.4.9. virConnectGetURI
3.4.10. virConnectIsEncrypted
3.4.11. virConnectIsSecure
3.5. Event loop integration
3.6. Security model
3.7. Error handling
3.7.1. virSetErrorFunc
3.7.2. virConnSetErrorFunc
3.7.3. virCopyLastError
3.7.4. virGetLastError
3.7.5. virSaveLastError
3.7.6. virResetError
3.7.7. virFreeError
3.7.8. virConnResetError
3.7.9. virConnCopyLastError
3.7.10. virConnGetLastError
3.8. Debugging / logging
3.8.1. Environment Variables
3.9. Integrated example
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.

3.1. Overview

The very first thing a libvirt agent must do is call one of the libvirt connection functions to obtain avirConnectPtr handle. This handle will be used in subsequent operations. The libvirt library provides 3 different functions for connecting to a resource:
   virConnectPtr virConnectOpen(const char *name)   virConnectPtr virConnectOpenReadOnly(const char *name)   virConnectPtr virConnectOpenAuth(const char *name, virConnectAuthPtr auth, int flags)
In all three cases there is a name parameter which in fact refers to the URI of the hypervisor to connect to. The previous sectionsSection 2.2, “Driver model” and Section 3.2.2, “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.
The difference between the three methods outlined above is the way in which they authenticate and the resulting authorization level they provide.

3.1.1. virConnectOpen

The virConnectOpen 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.
/* 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;}
Example 3.1. Using virConnectOpen

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 URI's, see the libvirt URI section.

3.1.2. virConnectOpenReadOnly

The virConnectOpenReadOnly 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 virConnectOpen, this API has no scope for authentication callbacks, so relies on credentials.
/* 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;}
Example 3.2. Using virConnectOpenReadOnly

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 URI's, see the libvirt URI section.

3.1.3. virConnectOpenAuth

The virConnectOpenAuth API is the most flexible, and effectively obsoletes the previous two APIs. It takes an extra parameter providing an instance of thevirConnectAuthPtr 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 symbolvirConnectAuthPtrDefault 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 VIR_CONNECT_RO flag if desired. A simple example C program that usesvirConnectOpenAuth with the defaultvirConnectAuthPtrDefault is
/* 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;    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;}
Example 3.3. Using virConnectOpenAuth

To test the above program, the following configuration must be present:
  1. /etc/libvirt/libvirtd.conf
    listen_tls = 0listen_tcp = 1auth_tcp = "sasl"
  2. /etc/sasl2/libvirt.conf
    mech_list: digest-md5
  3. A virt user has been added to the SASL database:
    # saslpasswd2 -a libvirt virt # this will prompt for a password
  4. libvirtd has been started with --listen
Once the above is configured, Example 3.3, “Using virConnectOpenAuth” should prompt for a username and password and allow read-write access to libvirtd.
If additional functionality is needed, a custom credential callback can also be provided as in the following program:
/* 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;}
Example 3.4. Using a custom credential callback with virConnectOpenAuth

The same configuration as Example 3.3, “Using virConnectOpenAuth” must be present in order to test Example 3.4, “Using a custom credential callback with virConnectOpenAuth”. The first thing to note here is the use of avirConnectAuth structure, which looks like the following:
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;
The credtype member points to an array of integers that represent the type of credentials this callback is willing to support. InExample 3.4, “Using a custom credential callback with virConnectOpenAuth” 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:
typedef int (*virConnectAuthCallbackPtr)(virConnectCredentialPtr cred,                                         unsigned int ncred,                                         void *cbdata);
Finally, the cbdata member is a pointer that can point to additional data needed by the callback; inExample 3.4, “Using a custom credential callback with virConnectOpenAuth”, this is not used so it is set to NULL.
After setting up the auth structure, Example 3.4, “Using a custom credential callback with virConnectOpenAuth” goes on to use this structure in thevirConnectOpenAuth 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 ofvirConnectCredential 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.
It is the responsibility of the auth.cb callback to examine each of thevirConnectCredential structures and collect the necessary credentials. ThevirConnectCredential structure looks like:
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;
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.

3.1.4. virConnectClose

A connection must be released by calling virConnectClose 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 callvirConnectRef to ensure the connection is not freed while still in use. Every extra call tovirConnectRef must be accompanied by a corresponding call tovirConnectClose to release the reference when no longer required. An example program that uses additional references:
/* 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;}
Example 3.5. Using virConnectClose with additional references

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.

原创粉丝点击