On Fri, Feb 22, 2008 at 08:23:43AM -0500, Daniel Veillard wrote: > On Thu, Feb 21, 2008 at 02:36:10PM +0000, Daniel P. Berrange wrote: > > - Else probe each registered driver in order until one succeeds > > > > For the latter I think we could add a 'probe' method to the internal driver > > API table. Then we can just call 'probe' on each driver in turn until we > > find one which is available on the system. > > > > At the same time it could be worth having a public API to 'detect drivers' > > which will call probe for each driver and return a list of all drivers > > which are available. This allows an app to easily ask libvirt what it > > supports > > I actually started to look at that and while it sounds good 'on paper' > it's a bit messy in practice, for example: > - test driver: if compiled in, you would think the probe should return > true, but as a result if trying an operation whyle no hypervisor > is available you would end up doing it on the test driver instead of > returning a failure, annoying > - qemu driver: well QEmu is actually a driver for a potentially large > set, KVM, QEmu for the current architecture, QEmu for emulated > architectures. Would the probe return true if it finds > /usr/bin/qemu-mips ? Or the KVM package may be present but would not be > usable because the current kernel doesn't have a kvm module > > Trying to be a bit systematic purely based on the driver model proves harder > than expected, still worth trying but I prefer early feedback :-) Okay, first patch enclosed, it seems to work for me: - grow the internal driver adding a const char *probe(void) entry point, it returns the URI to use to access the driver I did a bit of reformating of driver.h to maintain alignment of fields - define the entry point for OpenVZ, test, Xen (probe is arch specific as suggested for Solaris), and QEmu. In the last case I just checked /usr/bin/qemu and /usr/bin/qemu-kvm presence, and if non root return the session URI instead of the system one. - in do_open check first for LIBVIRT_DEFAULT_URI, if still empty, then go though the probes, ignore the test driver to avoid surprises and if Xen is found give it priority compared to others to maintain compatibility with previous behaviour - added a virFileExists to util.[ch] keeping code clean Daniel -- Red Hat Virtualization group http://redhat.com/virtualization/ Daniel Veillard | virtualization library http://libvirt.org/ veillard@xxxxxxxxxx | libxml GNOME XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | Rpmfind RPM search engine http://rpmfind.net/
Index: src/libvirt.c =================================================================== RCS file: /data/cvs/libxen/src/libvirt.c,v retrieving revision 1.123 diff -u -p -r1.123 libvirt.c --- src/libvirt.c 20 Feb 2008 16:54:36 -0000 1.123 +++ src/libvirt.c 22 Feb 2008 15:42:27 -0000 @@ -632,9 +632,47 @@ do_open (const char *name, virConnectPtr ret = NULL; xmlURIPtr uri; - /* Convert NULL or "" to xen:/// for back compat */ - if (!name || name[0] == '\0') - name = "xen:///"; + /* + * If no URI is passed, then check for an environment string if not + * available probe the compiled in drivers to find a default hypervisor + * if detectable. + */ + if (!name || name[0] == '\0') { + char *defname = getenv("LIBVIRT_DEFAULT_URI"); + if (defname && *defname) { + DEBUG("Using LIBVIRT_DEFAULT_URI %s", defname); + name = defname; + } else { + const char *use = NULL; + const char *latest; + int probes = 0; + for (i = 0; i < virNetworkDriverTabCount; i++) { + if ((virDriverTab[i]->probe != NULL) && + ((latest = virDriverTab[i]->probe()) != NULL)) { + probes++; + + DEBUG("Probed %s", latest); + /* + * if running a xen kernel, give it priority over + * QEmu emultation + */ + if (STREQ(latest, "xen:///")) + use = latest; + else if ((use == NULL) && (!STREQ(latest, "test:///"))) + use = latest; + } + } + if (use == NULL) { + name = "xen:///"; + DEBUG("Could not probe any hypervisor defaulting to %s", + name); + } else { + name = use; + DEBUG("Using %s as default URI, %d hypervisor found", + use, probes); + } + } + } /* Convert xen -> xen:/// for back compat */ if (!strcasecmp(name, "xen")) Index: src/openvz_driver.c =================================================================== RCS file: /data/cvs/libxen/src/openvz_driver.c,v retrieving revision 1.15 diff -u -p -r1.15 openvz_driver.c --- src/openvz_driver.c 5 Feb 2008 19:27:37 -0000 1.15 +++ src/openvz_driver.c 22 Feb 2008 15:42:27 -0000 @@ -546,6 +546,15 @@ bail_out5: return ret; } +static const char *openvzProbe(void) +{ +#ifdef __linux__ + if ((getuid() == 0) && (virFileExists("/proc/vz"))) + return("openvz:///"); +#endif + return(NULL); +} + static virDrvOpenStatus openvzOpen(virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth ATTRIBUTE_UNUSED, @@ -694,6 +703,7 @@ static virDriver openvzDriver = { VIR_DRV_OPENVZ, "OPENVZ", LIBVIR_VERSION_NUMBER, + openvzProbe, /* probe */ openvzOpen, /* open */ openvzClose, /* close */ NULL, /* supports_feature */ Index: src/qemu_driver.c =================================================================== RCS file: /data/cvs/libxen/src/qemu_driver.c,v retrieving revision 1.52 diff -u -p -r1.52 qemu_driver.c --- src/qemu_driver.c 7 Feb 2008 16:50:17 -0000 1.52 +++ src/qemu_driver.c 22 Feb 2008 15:42:27 -0000 @@ -1386,6 +1386,24 @@ static int qemudMonitorCommand(struct qe return -1; } +/** + * qemudProbe: + * + * Probe for the availability of the qemu driver, assume the + * presence of QEmu emulation if the binaries are installed + */ +static const char *qemudProbe(void) +{ + if ((virFileExists("/usr/bin/qemu")) || + (virFileExists("/usr/bin/qemu-kvm"))) { + if (getuid() == 0) { + return("qemu:///system"); + } else { + return("qemu:///session"); + } + } + return(NULL); +} static virDrvOpenStatus qemudOpen(virConnectPtr conn, xmlURIPtr uri, @@ -2857,6 +2875,7 @@ static virDriver qemuDriver = { VIR_DRV_QEMU, "QEMU", LIBVIR_VERSION_NUMBER, + qemudProbe, /* probe */ qemudOpen, /* open */ qemudClose, /* close */ NULL, /* supports_feature */ Index: src/remote_internal.c =================================================================== RCS file: /data/cvs/libxen/src/remote_internal.c,v retrieving revision 1.60 diff -u -p -r1.60 remote_internal.c --- src/remote_internal.c 20 Feb 2008 15:23:36 -0000 1.60 +++ src/remote_internal.c 22 Feb 2008 15:42:27 -0000 @@ -4599,6 +4599,7 @@ static virDriver driver = { .no = VIR_DRV_REMOTE, .name = "remote", .ver = REMOTE_PROTOCOL_VERSION, + .probe = NULL, .open = remoteOpen, .close = remoteClose, .supports_feature = remoteSupportsFeature, Index: src/test.c =================================================================== RCS file: /data/cvs/libxen/src/test.c,v retrieving revision 1.65 diff -u -p -r1.65 test.c --- src/test.c 20 Feb 2008 15:53:34 -0000 1.65 +++ src/test.c 22 Feb 2008 15:42:27 -0000 @@ -180,6 +180,17 @@ testError(virConnectPtr con, errmsg, info, NULL, 0, 0, errmsg, info, 0); } +/** + * testProbe: + * + * Probe for the availability of the test driver + */ +static const char * +testProbe(void) +{ + return("test:///"); +} + static int testRestartStringToFlag(const char *str) { if (!strcmp(str, "restart")) { return VIR_DOMAIN_RESTART; @@ -1938,6 +1949,7 @@ static virDriver testDriver = { VIR_DRV_TEST, "Test", LIBVIR_VERSION_NUMBER, + testProbe, /* probe */ testOpen, /* open */ testClose, /* close */ NULL, /* supports_feature */ Index: src/xen_unified.c =================================================================== RCS file: /data/cvs/libxen/src/xen_unified.c,v retrieving revision 1.36 diff -u -p -r1.36 xen_unified.c --- src/xen_unified.c 7 Feb 2008 09:37:10 -0000 1.36 +++ src/xen_unified.c 22 Feb 2008 15:42:27 -0000 @@ -39,6 +39,7 @@ #include "xs_internal.h" #include "xm_internal.h" #include "xml.h" +#include "util.h" #define DEBUG(fmt,...) VIR_DEBUG(__FILE__, fmt,__VA_ARGS__) @@ -217,6 +218,24 @@ done: * in the low level drivers directly. */ +static const char * +xenUnifiedProbe (void) +{ +#ifdef __linux__ + if (virFileExists("/proc/xen")) + return("xen:///"); +#endif +#ifdef __sun__ + FILE *fh; + + if (fh = fopen(path, "r")) { + fclose(fh); + return("xen:///"); + } +#endif + return(NULL); +} + static int xenUnifiedOpen (virConnectPtr conn, xmlURIPtr uri, virConnectAuthPtr auth, int flags) { @@ -1198,6 +1217,7 @@ static virDriver xenUnifiedDriver = { .no = VIR_DRV_XEN_UNIFIED, .name = "Xen", .ver = HV_VERSION, + .probe = xenUnifiedProbe, .open = xenUnifiedOpen, .close = xenUnifiedClose, .supports_feature = xenUnifiedSupportsFeature, Index: src/driver.h =================================================================== RCS file: /data/cvs/libxen/src/driver.h,v retrieving revision 1.42 diff -u -p -r1.42 driver.h --- src/driver.h 20 Feb 2008 15:06:53 -0000 1.42 +++ src/driver.h 22 Feb 2008 15:42:26 -0000 @@ -69,6 +69,8 @@ typedef enum { #define VIR_DRV_SUPPORTS_FEATURE(drv,conn,feature) \ ((drv)->supports_feature ? (drv)->supports_feature((conn),(feature)) : 0) +typedef const char * + (*virDrvProbe) (void); typedef virDrvOpenStatus (*virDrvOpen) (virConnectPtr conn, xmlURIPtr uri, @@ -277,62 +279,63 @@ typedef unsigned long long * - close */ struct _virDriver { - int no; /* the number virDrvNo */ - const char * name; /* the name of the driver */ - unsigned long ver; /* the version of the backend */ - virDrvOpen open; - virDrvClose close; + int no; /* the number virDrvNo */ + const char * name; /* the name of the driver */ + unsigned long ver; /* the version of the backend */ + virDrvProbe probe; + virDrvOpen open; + virDrvClose close; virDrvSupportsFeature supports_feature; - virDrvGetType type; - virDrvGetVersion version; + virDrvGetType type; + virDrvGetVersion version; virDrvGetHostname getHostname; virDrvGetURI getURI; - virDrvGetMaxVcpus getMaxVcpus; - virDrvNodeGetInfo nodeGetInfo; - virDrvGetCapabilities getCapabilities; - virDrvListDomains listDomains; - virDrvNumOfDomains numOfDomains; - virDrvDomainCreateLinux domainCreateLinux; - virDrvDomainLookupByID domainLookupByID; - virDrvDomainLookupByUUID domainLookupByUUID; - virDrvDomainLookupByName domainLookupByName; - virDrvDomainSuspend domainSuspend; - virDrvDomainResume domainResume; - virDrvDomainShutdown domainShutdown; - virDrvDomainReboot domainReboot; - virDrvDomainDestroy domainDestroy; - virDrvDomainGetOSType domainGetOSType; - virDrvDomainGetMaxMemory domainGetMaxMemory; - virDrvDomainSetMaxMemory domainSetMaxMemory; - virDrvDomainSetMemory domainSetMemory; - virDrvDomainGetInfo domainGetInfo; - virDrvDomainSave domainSave; - virDrvDomainRestore domainRestore; - virDrvDomainCoreDump domainCoreDump; - virDrvDomainSetVcpus domainSetVcpus; - virDrvDomainPinVcpu domainPinVcpu; - virDrvDomainGetVcpus domainGetVcpus; - virDrvDomainGetMaxVcpus domainGetMaxVcpus; - virDrvDomainDumpXML domainDumpXML; - virDrvListDefinedDomains listDefinedDomains; - virDrvNumOfDefinedDomains numOfDefinedDomains; - virDrvDomainCreate domainCreate; - virDrvDomainDefineXML domainDefineXML; - virDrvDomainUndefine domainUndefine; - virDrvDomainAttachDevice domainAttachDevice; - virDrvDomainDetachDevice domainDetachDevice; - virDrvDomainGetAutostart domainGetAutostart; - virDrvDomainSetAutostart domainSetAutostart; - virDrvDomainGetSchedulerType domainGetSchedulerType; - virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; - virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; + virDrvGetMaxVcpus getMaxVcpus; + virDrvNodeGetInfo nodeGetInfo; + virDrvGetCapabilities getCapabilities; + virDrvListDomains listDomains; + virDrvNumOfDomains numOfDomains; + virDrvDomainCreateLinux domainCreateLinux; + virDrvDomainLookupByID domainLookupByID; + virDrvDomainLookupByUUID domainLookupByUUID; + virDrvDomainLookupByName domainLookupByName; + virDrvDomainSuspend domainSuspend; + virDrvDomainResume domainResume; + virDrvDomainShutdown domainShutdown; + virDrvDomainReboot domainReboot; + virDrvDomainDestroy domainDestroy; + virDrvDomainGetOSType domainGetOSType; + virDrvDomainGetMaxMemory domainGetMaxMemory; + virDrvDomainSetMaxMemory domainSetMaxMemory; + virDrvDomainSetMemory domainSetMemory; + virDrvDomainGetInfo domainGetInfo; + virDrvDomainSave domainSave; + virDrvDomainRestore domainRestore; + virDrvDomainCoreDump domainCoreDump; + virDrvDomainSetVcpus domainSetVcpus; + virDrvDomainPinVcpu domainPinVcpu; + virDrvDomainGetVcpus domainGetVcpus; + virDrvDomainGetMaxVcpus domainGetMaxVcpus; + virDrvDomainDumpXML domainDumpXML; + virDrvListDefinedDomains listDefinedDomains; + virDrvNumOfDefinedDomains numOfDefinedDomains; + virDrvDomainCreate domainCreate; + virDrvDomainDefineXML domainDefineXML; + virDrvDomainUndefine domainUndefine; + virDrvDomainAttachDevice domainAttachDevice; + virDrvDomainDetachDevice domainDetachDevice; + virDrvDomainGetAutostart domainGetAutostart; + virDrvDomainSetAutostart domainSetAutostart; + virDrvDomainGetSchedulerType domainGetSchedulerType; + virDrvDomainGetSchedulerParameters domainGetSchedulerParameters; + virDrvDomainSetSchedulerParameters domainSetSchedulerParameters; virDrvDomainMigratePrepare domainMigratePrepare; virDrvDomainMigratePerform domainMigratePerform; virDrvDomainMigrateFinish domainMigrateFinish; virDrvDomainBlockStats domainBlockStats; virDrvDomainInterfaceStats domainInterfaceStats; - virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; - virDrvNodeGetFreeMemory getFreeMemory; + virDrvNodeGetCellsFreeMemory nodeGetCellsFreeMemory; + virDrvNodeGetFreeMemory getFreeMemory; }; typedef int Index: src/util.c =================================================================== RCS file: /data/cvs/libxen/src/util.c,v retrieving revision 1.20 diff -u -p -r1.20 util.c --- src/util.c 20 Feb 2008 15:29:13 -0000 1.20 +++ src/util.c 22 Feb 2008 15:42:27 -0000 @@ -500,6 +500,15 @@ virFileLinkPointsTo (const char *checkLi #endif /*! __MINGW32__ */ +int virFileExists(const char *path) +{ + struct stat st; + + if (stat(path, &st) >= 0) + return(1); + return(0); +} + int virFileMakePath(const char *path) { struct stat st; Index: src/util.h =================================================================== RCS file: /data/cvs/libxen/src/util.h,v retrieving revision 1.9 diff -u -p -r1.9 util.h --- src/util.h 20 Feb 2008 15:29:13 -0000 1.9 +++ src/util.h 22 Feb 2008 15:42:27 -0000 @@ -47,6 +47,9 @@ int virFileHasSuffix(const char *str, int virFileLinkPointsTo(const char *checkLink, const char *checkDest); + +int virFileExists(const char *path); + int virFileMakePath(const char *path); int virFileBuildPath(const char *dir,
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list