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/
[EMAIL PROTECTED]  | 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@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to