On Tue, Jul 06, 2010 at 03:28:54PM +0200, Matthias Bolte wrote: > --- > Makefile.am | 2 +- > configure.ac | 1 + > examples/openauth/.gitignore | 5 + > examples/openauth/Makefile.am | 5 + > examples/openauth/openauth.c | 287 +++++++++++++++++++++++++++++++++++++++++ > libvirt.spec.in | 3 +- > 6 files changed, 301 insertions(+), 2 deletions(-) > create mode 100644 examples/openauth/.gitignore > create mode 100644 examples/openauth/Makefile.am > create mode 100644 examples/openauth/openauth.c > > diff --git a/Makefile.am b/Makefile.am > index 286b13b..a6af20f 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -6,7 +6,7 @@ GENHTML = genhtml > SUBDIRS = gnulib/lib include src daemon tools proxy docs gnulib/tests \ > python tests po examples/domain-events/events-c examples/hellolibvirt \ > examples/dominfo examples/domsuspend examples/python examples/apparmor \ > - examples/xml/nwfilter > + examples/xml/nwfilter examples/openauth > > ACLOCAL_AMFLAGS = -I m4 -I gnulib/m4 > > diff --git a/configure.ac b/configure.ac > index c9c5b53..eece723 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -2129,6 +2129,7 @@ AC_OUTPUT(Makefile src/Makefile include/Makefile docs/Makefile \ > examples/domain-events/events-c/Makefile \ > examples/domsuspend/Makefile \ > examples/dominfo/Makefile \ > + examples/openauth/Makefile \ > examples/python/Makefile \ > examples/hellolibvirt/Makefile \ > examples/xml/nwfilter/Makefile) > diff --git a/examples/openauth/.gitignore b/examples/openauth/.gitignore > new file mode 100644 > index 0000000..1431557 > --- /dev/null > +++ b/examples/openauth/.gitignore > @@ -0,0 +1,5 @@ > +Makefile > +Makefile.in > +openauth > +.deps > +.libs > diff --git a/examples/openauth/Makefile.am b/examples/openauth/Makefile.am > new file mode 100644 > index 0000000..279a032 > --- /dev/null > +++ b/examples/openauth/Makefile.am > @@ -0,0 +1,5 @@ > +INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include > +noinst_PROGRAMS = openauth > +openauth_CFLAGS = $(WARN_CFLAGS) > +openauth_SOURCES = openauth.c > +openauth_LDADD = @top_builddir@/src/libvirt.la > diff --git a/examples/openauth/openauth.c b/examples/openauth/openauth.c > new file mode 100644 > index 0000000..ff830cb > --- /dev/null > +++ b/examples/openauth/openauth.c > @@ -0,0 +1,287 @@ > +/* This is a copy of the hellolibvirt example demonstaring how to use > + * virConnectOpenAuth with a custom auth callback */ > + > +#include <config.h> > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <libvirt/libvirt.h> > +#include <libvirt/virterror.h> > + > +static void > +showError(virConnectPtr conn) > +{ > + int ret; > + virErrorPtr err; > + > + err = malloc(sizeof(*err)); > + if (NULL == err) { > + printf("Could not allocate memory for error data\n"); > + goto out; > + } > + > + ret = virConnCopyLastError(conn, err); > + > + switch (ret) { > + case 0: > + printf("No error found\n"); > + break; > + > + case -1: > + printf("Parameter error when attempting to get last error\n"); > + break; > + > + default: > + printf("libvirt reported: \"%s\"\n", err->message); > + break; > + } > + > + virResetError(err); > + free(err); > + > +out: > + return; > +} > + > + > +static int > +showHypervisorInfo(virConnectPtr conn) > +{ > + int ret = 0; > + unsigned long hvVer, major, minor, release; > + const char *hvType; > + > + /* virConnectGetType returns a pointer to a static string, so no > + * allocation or freeing is necessary; it is possible for the call > + * to fail if, for example, there is no connection to a > + * hypervisor, so check what it returns. */ > + hvType = virConnectGetType(conn); > + if (NULL == hvType) { > + ret = 1; > + printf("Failed to get hypervisor type\n"); > + showError(conn); > + goto out; > + } > + > + if (0 != virConnectGetVersion(conn, &hvVer)) { > + ret = 1; > + printf("Failed to get hypervisor version\n"); > + showError(conn); > + goto out; > + } > + > + major = hvVer / 1000000; > + hvVer %= 1000000; > + minor = hvVer / 1000; > + release = hvVer % 1000; > + > + printf("Hypervisor: \"%s\" version: %lu.%lu.%lu\n", > + hvType, > + major, > + minor, > + release); > + > +out: > + return ret; > +} > + > + > +static int > +showDomains(virConnectPtr conn) > +{ > + int ret = 0, i, numNames, numInactiveDomains, numActiveDomains; > + char **nameList = NULL; > + > + numActiveDomains = virConnectNumOfDomains(conn); > + if (-1 == numActiveDomains) { > + ret = 1; > + printf("Failed to get number of active domains\n"); > + showError(conn); > + goto out; > + } > + > + numInactiveDomains = virConnectNumOfDefinedDomains(conn); > + if (-1 == numInactiveDomains) { > + ret = 1; > + printf("Failed to get number of inactive domains\n"); > + showError(conn); > + goto out; > + } > + > + printf("There are %d active and %d inactive domains\n", > + numActiveDomains, numInactiveDomains); > + > + nameList = malloc(sizeof(*nameList) * numInactiveDomains); > + > + if (NULL == nameList) { > + ret = 1; > + printf("Could not allocate memory for list of inactive domains\n"); > + goto out; > + } > + > + numNames = virConnectListDefinedDomains(conn, > + nameList, > + numInactiveDomains); > + > + if (-1 == numNames) { > + ret = 1; > + printf("Could not get list of defined domains from hypervisor\n"); > + showError(conn); > + goto out; > + } > + > + if (numNames > 0) { > + printf("Inactive domains:\n"); > + } > + > + for (i = 0 ; i < numNames ; i++) { > + printf(" %s\n", *(nameList + i)); > + /* The API documentation doesn't say so, but the names > + * returned by virConnectListDefinedDomains are strdup'd and > + * must be freed here. */ > + free(*(nameList + i)); > + } > + > +out: > + free(nameList); > + return ret; > +} > + > +/* Struct to pass the credentials to the auth callback via the cbdata pointer */ > +struct _AuthData { > + char *username; > + char *password; > +}; > + > +typedef struct _AuthData AuthData; > + > +/* This function will be called by libvirt to obtain credentials in order to > + * authenticate to the hypervisor */ > +static int > +authCallback(virConnectCredentialPtr cred, unsigned int ncred, void *cbdata) > +{ > + int i; > + AuthData *authData = cbdata; > + > + /* libvirt might request multiple credentials in a single call. > + * This example supports VIR_CRED_AUTHNAME and VIR_CRED_PASSPHRASE > + * credentials only, but there are several other types. > + * > + * A request may also contain a prompt message that can be displayed > + * to the user and a challenge. The challenge is specific to the > + * credential type and hypervisor type. > + * > + * For example the ESX driver passes the hostname of the ESX or vCenter > + * server as challenge. This allows a auth callback to return the > + * proper credentials. */ > + for (i = 0; i < ncred ; ++i) { > + switch (cred[i].type) { > + case VIR_CRED_AUTHNAME: > + cred[i].result = strdup(authData->username); > + > + if (cred[i].result == NULL) { > + return -1; > + } > + > + cred[i].resultlen = strlen(cred[i].result); > + break; > + > + case VIR_CRED_PASSPHRASE: > + cred[i].result = strdup(authData->password); > + > + if (cred[i].result == NULL) { > + return -1; > + } > + > + cred[i].resultlen = strlen(cred[i].result); > + break; > + > + default: > + return -1; > + } > + } > + > + return 0; > +} > + > + > +/* The list of credential types supported by our auth callback */ > +static int credTypes[] = { > + VIR_CRED_AUTHNAME, > + VIR_CRED_PASSPHRASE > +}; > + > + > +/* The auth struct that will be passed to virConnectOpenAuth */ > +static virConnectAuth auth = { > + credTypes, > + sizeof(credTypes) / sizeof(int), > + authCallback, > + NULL, // cbdata will be initialized in main > +}; > + > + > +int > +main(int argc, char *argv[]) > +{ > + int ret = 0; > + virConnectPtr conn; > + char *uri; > + AuthData authData; > + > + if (argc != 4) { > + ret = 1; > + printf("Usage: %s <uri> <username> <password>\n", argv[0]); > + goto out; > + } > + > + uri = argv[1]; > + authData.username = argv[2]; > + authData.password = argv[3]; > + auth.cbdata = &authData; > + > + printf("Attempting to connect to hypervisor\n"); > + > + conn = virConnectOpenAuth(uri, &auth, 0); > + > + if (NULL == conn) { > + ret = 1; > + printf("No connection to hypervisor\n"); > + showError(conn); > + goto out; > + } > + > + uri = virConnectGetURI(conn); > + if (NULL == uri) { > + ret = 1; > + printf("Failed to get URI for hypervisor connection\n"); > + showError(conn); > + goto disconnect; > + } > + > + printf("Connected to hypervisor at \"%s\"\n", uri); > + free(uri); > + > + if (0 != showHypervisorInfo(conn)) { > + ret = 1; > + goto disconnect; > + } > + > + if (0 != showDomains(conn)) { > + ret = 1; > + goto disconnect; > + } > + > +disconnect: > + if (0 != virConnectClose(conn)) { > + printf("Failed to disconnect from hypervisor\n"); > + showError(conn); > + ret = 1; > + } else { > + printf("Disconnected from hypervisor\n"); > + } > + > +out: > + return ret; > +} > diff --git a/libvirt.spec.in b/libvirt.spec.in > index 33e757c..ce58f2a 100644 > --- a/libvirt.spec.in > +++ b/libvirt.spec.in > @@ -585,7 +585,7 @@ gzip -9 ChangeLog > rm -fr %{buildroot} > > %makeinstall > -for i in domain-events/events-c dominfo domsuspend hellolibvirt python xml/nwfilter > +for i in domain-events/events-c dominfo domsuspend hellolibvirt openauth python xml/nwfilter > do > (cd examples/$i ; make clean ; rm -rf .deps .libs Makefile Makefile.in) > done > @@ -887,6 +887,7 @@ fi > %doc examples/domain-events/events-c > %doc examples/dominfo > %doc examples/domsuspend > +%doc examples/openauth > %doc examples/xml > > %if %{with_python} Looks fine to me, good idea :-) ACK Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list