[Libvir] [PATCH] default hypervisor selection

Daniel Veillard veillard at redhat.com
Fri Feb 22 15:59:43 UTC 2008


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 at redhat.com  | libxml GNOME XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | Rpmfind RPM search engine  http://rpmfind.net/
-------------- next part --------------
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,


More information about the libvir-list mailing list