[libvirt] [PATCH 6/9] admin: Add URI support and introduce virAdmGetDefaultURI

Erik Skultety eskultet at redhat.com
Tue Oct 13 13:38:19 UTC 2015


Since virt-admin should be able to connect to various admin servers
on hosted different daemons, we need to provide URI support to
libvirt-admin.
---
 include/libvirt/libvirt-admin.h |   2 +
 src/datatypes.c                 |   2 +
 src/datatypes.h                 |   1 +
 src/libvirt-admin.c             | 132 +++++++++++++++++++++++++++++++---------
 src/libvirt_admin_public.syms   |   1 +
 tools/virt-admin.c              |  38 ++++++++++++
 6 files changed, 146 insertions(+), 30 deletions(-)

diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h
index 2358173..4b6b719 100644
--- a/include/libvirt/libvirt-admin.h
+++ b/include/libvirt/libvirt-admin.h
@@ -76,6 +76,8 @@ int virAdmConnectUnregisterCloseCallback(virAdmConnectPtr conn,
 int virAdmConnectGetLibVersion(virAdmConnectPtr conn,
                                unsigned long long *libVer);
 
+char * virAdmConnectGetURI(virAdmConnectPtr conn);
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/src/datatypes.c b/src/datatypes.c
index 9e374e4..1d2329c 100644
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -839,6 +839,8 @@ virAdmConnectDispose(void *obj)
     if (conn->privateDataFreeFunc)
         conn->privateDataFreeFunc(conn);
 
+    virURIFree(conn->uri);
+
     virObjectUnref(conn->closeCallback);
 }
 
diff --git a/src/datatypes.h b/src/datatypes.h
index 33df476..aa160a8 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -408,6 +408,7 @@ struct _virConnect {
  */
 struct _virAdmConnect {
     virObjectLockable object;
+    virURIPtr  uri;
 
     void *privateData;
     virFreeCallback privateDataFreeFunc;
diff --git a/src/libvirt-admin.c b/src/libvirt-admin.c
index 2da3d43..252fdbe 100644
--- a/src/libvirt-admin.c
+++ b/src/libvirt-admin.c
@@ -29,6 +29,7 @@
 #include "configmake.h"
 
 #include "viralloc.h"
+#include "virconf.h"
 #include "virlog.h"
 #include "virnetclient.h"
 #include "virobject.h"
@@ -283,60 +284,54 @@ virAdmInitialize(void)
 }
 
 static char *
-getSocketPath(const char *name)
+getSocketPath(virURIPtr uri)
 {
     char *rundir = virGetUserRuntimeDirectory();
     char *sock_path = NULL;
     size_t i = 0;
-    virURIPtr uri = NULL;
 
-    if (name) {
-        if (!(uri = virURIParse(name)))
-            goto error;
+    if (!uri)
+        goto cleanup;
 
-        if (STRNEQ(uri->scheme, "admin") ||
-            uri->server || uri->user || uri->fragment) {
-            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Invalid connection name '%s'"), name);
-            goto error;
-        }
 
-        for (i = 0; i < uri->paramsCount; i++) {
-            virURIParamPtr param = &uri->params[i];
+    for (i = 0; i < uri->paramsCount; i++) {
+        virURIParamPtr param = &uri->params[i];
 
-            if (STREQ(param->name, "socket")) {
-                VIR_FREE(sock_path);
-                if (VIR_STRDUP(sock_path, param->value) < 0)
-                    goto error;
-            } else {
-                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                               _("Unknown URI parameter '%s'"), param->name);
+        if (STREQ(param->name, "socket")) {
+            VIR_FREE(sock_path);
+            if (VIR_STRDUP(sock_path, param->value) < 0)
                 goto error;
-            }
+        } else {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Unknown URI parameter '%s'"), param->name);
+            goto error;
         }
     }
 
     if (!sock_path) {
-        if (!uri || !uri->path || STREQ(uri->path, "/system")) {
+        if (STRNEQ(uri->scheme, "libvirtd")) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("Unsupported URI scheme '%s'"),
+                           uri->scheme);
+            goto error;
+        }
+        if (STREQ_NULLABLE(uri->path, "/system")) {
             if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0)
                 goto error;
         } else if (STREQ_NULLABLE(uri->path, "/session")) {
-            if (!rundir)
-                goto error;
-
-            if (virAsprintf(&sock_path,
-                            "%s%s", rundir, LIBVIRTD_ADMIN_SOCK_NAME) < 0)
+            if (!rundir && virAsprintf(&sock_path, "%s%s", rundir,
+                                       LIBVIRTD_ADMIN_SOCK_NAME) < 0)
                 goto error;
         } else {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                           _("Invalid URI path '%s'"), uri->path);
+                           _("Invalid URI path '%s', try '/system'"),
+                           uri->path ? uri->path : "");
             goto error;
         }
     }
 
  cleanup:
     VIR_FREE(rundir);
-    virURIFree(uri);
     return sock_path;
 
  error:
@@ -344,6 +339,40 @@ getSocketPath(const char *name)
     goto cleanup;
 }
 
+static int
+virAdmGetDefaultURI(virConfPtr conf, virURIPtr *uri)
+{
+    virConfValuePtr value = NULL;
+    const char *uristr = NULL;
+
+    uristr = virGetEnvBlockSUID("LIBVIRT_ADMIN_DEFAULT_URI");
+    if (uristr && *uristr) {
+        VIR_DEBUG("Using LIBVIRT_ADMIN_DEFAULT_URI '%s'", uristr);
+    } else if ((value = virConfGetValue(conf, "uri_default_admin"))) {
+        if (value->type != VIR_CONF_STRING) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("Expected a string for 'uri_default_admin' config "
+                             "parameter"));
+            return -1;
+        }
+
+        VIR_DEBUG("Using config file uri '%s'", value->str);
+        uristr = value->str;
+    } else {
+        /* Since we can't probe connecting via any hypervisor driver as libvirt
+         * does, if no explicit URI was given and neither the environment
+         * variable, nor the configuration parameter had previously been set,
+         * we set the default admin server URI to 'libvirtd://system'.
+         */
+        uristr = "libvirtd:///system";
+    }
+
+    if (!(*uri = virURIParse(uristr)))
+        return -1;
+
+    return 0;
+}
+
 /**
  * virAdmConnectOpen:
  * @name: uri of the daemon to connect to, NULL for default
@@ -358,6 +387,7 @@ virAdmConnectOpen(const char *name, unsigned int flags)
 {
     char *sock_path = NULL;
     virAdmConnectPtr conn = NULL;
+    virConfPtr conf = NULL;
 
     if (virAdmInitialize() < 0)
         goto error;
@@ -368,7 +398,18 @@ virAdmConnectOpen(const char *name, unsigned int flags)
     if (!(conn = virAdmConnectNew()))
         goto error;
 
-    if (!(sock_path = getSocketPath(name)))
+    if (virGetLibvirtConfigFile(&conf) < 0)
+        goto error;
+
+    if (!name) {
+        if (virAdmGetDefaultURI(conf, &conn->uri) < 0)
+            goto error;
+    } else {
+        if (!(conn->uri = virURIParse(name)))
+            goto error;
+    }
+
+    if (!(sock_path = getSocketPath(conn->uri)))
         goto error;
 
     if (!(conn->privateData = remoteAdminPrivNew(sock_path)))
@@ -635,3 +676,34 @@ int virAdmConnectGetLibVersion(virAdmConnectPtr conn,
     virDispatchError(NULL);
     return -1;
 }
+
+/**
+ * virAdmConnectGetURI:
+ * @conn: pointer to an admin connection
+ *
+ * String returned by this method is normally the same as the string passed
+ * to the virAdmConnectOpen. Even if NULL was passed to virAdmConnectOpen,
+ * this method returns a non-null URI string.
+ *
+ * Returns an URI string related to the connection or NULL in case of an error.
+ * Caller is responsible for freeing the string.
+ */
+char *
+virAdmConnectGetURI(virAdmConnectPtr conn)
+{
+    char *uri = NULL;
+    VIR_DEBUG("conn=%p", conn);
+
+    virResetLastError();
+
+    virCheckAdmConnectReturn(conn, NULL);
+
+    if (!(uri = virURIFormat(conn->uri)))
+        goto error;
+
+    return uri;
+
+ error:
+    virDispatchError(NULL);
+    return uri;
+}
diff --git a/src/libvirt_admin_public.syms b/src/libvirt_admin_public.syms
index 273af4d..4467c88 100644
--- a/src/libvirt_admin_public.syms
+++ b/src/libvirt_admin_public.syms
@@ -19,4 +19,5 @@ LIBVIRT_ADMIN_1.3.0 {
         virAdmConnectRegisterCloseCallback;
         virAdmConnectUnregisterCloseCallback;
         virAdmConnectGetLibVersion;
+        virAdmConnectGetURI;
 };
diff --git a/tools/virt-admin.c b/tools/virt-admin.c
index 0c807f2..a202ce2 100644
--- a/tools/virt-admin.c
+++ b/tools/virt-admin.c
@@ -203,6 +203,38 @@ cmdVersion(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
     return true;
 }
 
+/*
+ * 'uri' command
+ */
+
+static const vshCmdInfo info_uri[] = {
+    {.name = "help",
+     .data = N_("print the admin server URI")
+    },
+    {.name = "desc",
+     .data = ""
+    },
+    {.name = NULL}
+};
+
+static bool
+cmdURI(vshControl *ctl, const vshCmd *cmd ATTRIBUTE_UNUSED)
+{
+    char *uri;
+    vshAdmControlPtr priv = ctl->privData;
+
+    uri = virAdmConnectGetURI(priv->conn);
+    if (!uri) {
+        vshError(ctl, "%s", _("failed to get URI"));
+        return false;
+    }
+
+    vshPrint(ctl, "%s\n", uri);
+    VIR_FREE(uri);
+
+    return true;
+}
+
 
 /* ---------------
  * Command Connect
@@ -547,6 +579,12 @@ static const vshCmdDef vshAdmCmds[] = {
      .info = info_version,
      .flags = 0
     },
+    {.name = "uri",
+     .handler = cmdURI,
+     .opts = NULL,
+     .info = info_uri,
+     .flags = 0
+    },
     {.name = "connect",
      .handler = cmdConnect,
      .opts = opts_connect,
-- 
2.4.3




More information about the libvir-list mailing list