[libvirt] [PATCH 06/10] interface: allow opening with interface:///system and interface:///session URIs

Daniel P. Berrangé berrange at redhat.com
Fri Jan 26 13:35:33 UTC 2018


Allow the possibility of opening a connection to only the interface
driver, by defining interface:///system and interface:///session URIs
and registering a fake hypervisor driver that supports them.

The hypervisor drivers can now directly open a interface driver
connection at time of need, instead of having to pass around a
virConnectPtr through many functions. This will facilitate the later
change to support separate daemons for each driver.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 src/interface/interface_backend_netcf.c | 98 ++++++++++++++++++++++++++++++++-
 src/interface/interface_backend_udev.c  | 97 +++++++++++++++++++++++++++++++-
 2 files changed, 193 insertions(+), 2 deletions(-)

diff --git a/src/interface/interface_backend_netcf.c b/src/interface/interface_backend_netcf.c
index c7cc07122a..9b04271647 100644
--- a/src/interface/interface_backend_netcf.c
+++ b/src/interface/interface_backend_netcf.c
@@ -46,6 +46,7 @@ typedef struct
 {
     virObjectLockable parent;
     struct netcf *netcf;
+    bool privileged;
 } virNetcfDriverState, *virNetcfDriverStatePtr;
 
 static virClassPtr virNetcfDriverStateClass;
@@ -78,7 +79,7 @@ virNetcfDriverStateDispose(void *obj)
 
 
 static int
-netcfStateInitialize(bool privileged ATTRIBUTE_UNUSED,
+netcfStateInitialize(bool privileged,
                      virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                      void *opaque ATTRIBUTE_UNUSED)
 {
@@ -88,6 +89,8 @@ netcfStateInitialize(bool privileged ATTRIBUTE_UNUSED,
     if (!(driver = virObjectLockableNew(virNetcfDriverStateClass)))
         return -1;
 
+    driver->privileged = privileged;
+
     /* open netcf */
     if (ncf_init(&driver->netcf, NULL) != 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -148,6 +151,80 @@ netcfStateReload(void)
 }
 
 
+static virDrvOpenStatus netcfConnectOpen(virConnectPtr conn,
+                                         virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                                         virConfPtr conf ATTRIBUTE_UNUSED,
+                                         unsigned int flags)
+{
+    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+    /* Verify uri was specified */
+    if (conn->uri == NULL) {
+        /* Only hypervisor drivers are permitted to auto-open on NULL uri */
+        return VIR_DRV_OPEN_DECLINED;
+    } else {
+        if (STRNEQ_NULLABLE(conn->uri->scheme, "interface"))
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* Leave for remote driver */
+        if (conn->uri->server != NULL)
+            return VIR_DRV_OPEN_DECLINED;
+
+        if (driver == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("interface state driver is not active"));
+            return VIR_DRV_OPEN_ERROR;
+        }
+
+        if (driver->privileged) {
+            if (STRNEQ(conn->uri->path, "/system")) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected interface URI path '%s', try interface:///system"),
+                               conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+        } else {
+            if (STRNEQ(conn->uri->path, "/session")) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected interface URI path '%s', try interface:///session"),
+                               conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+        }
+    }
+
+    if (virConnectOpenEnsureACL(conn) < 0)
+        return VIR_DRV_OPEN_ERROR;
+
+    return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int netcfConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
+static int netcfConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    /* Trivially secure, since always inside the daemon */
+    return 1;
+}
+
+
+static int netcfConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    /* Not encrypted, but remote driver takes care of that */
+    return 0;
+}
+
+
+static int netcfConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return 1;
+}
+
+
 /*
  * Get a minimal virInterfaceDef containing enough metadata
  * for access control checks to be performed. Currently
@@ -1134,6 +1211,23 @@ static virInterfaceDriver interfaceDriver = {
 #endif /* HAVE_NETCF_TRANSACTIONS */
 };
 
+
+static virHypervisorDriver interfaceHypervisorDriver = {
+    .name = "interface",
+    .connectOpen = netcfConnectOpen, /* 4.1.0 */
+    .connectClose = netcfConnectClose, /* 4.1.0 */
+    .connectIsEncrypted = netcfConnectIsEncrypted, /* 4.1.0 */
+    .connectIsSecure = netcfConnectIsSecure, /* 4.1.0 */
+    .connectIsAlive = netcfConnectIsAlive, /* 4.1.0 */
+};
+
+
+static virConnectDriver interfaceConnectDriver = {
+    .hypervisorDriver = &interfaceHypervisorDriver,
+    .interfaceDriver = &interfaceDriver,
+};
+
+
 static virStateDriver interfaceStateDriver = {
     .name = INTERFACE_DRIVER_NAME,
     .stateInitialize = netcfStateInitialize,
@@ -1143,6 +1237,8 @@ static virStateDriver interfaceStateDriver = {
 
 int netcfIfaceRegister(void)
 {
+    if (virRegisterConnectDriver(&interfaceConnectDriver, false) < 0)
+        return -1;
     if (virSetSharedInterfaceDriver(&interfaceDriver) < 0)
         return -1;
     if (virRegisterStateDriver(&interfaceStateDriver) < 0)
diff --git a/src/interface/interface_backend_udev.c b/src/interface/interface_backend_udev.c
index 1cd84060a8..2e8e105ffc 100644
--- a/src/interface/interface_backend_udev.c
+++ b/src/interface/interface_backend_udev.c
@@ -41,6 +41,7 @@
 
 struct udev_iface_driver {
     struct udev *udev;
+    bool privileged;
 };
 
 typedef enum {
@@ -1158,7 +1159,7 @@ udevInterfaceIsActive(virInterfacePtr ifinfo)
 
 
 static int
-udevStateInitialize(bool privileged ATTRIBUTE_UNUSED,
+udevStateInitialize(bool privileged,
                     virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                     void *opaque ATTRIBUTE_UNUSED)
 {
@@ -1173,6 +1174,7 @@ udevStateInitialize(bool privileged ATTRIBUTE_UNUSED,
                        _("failed to create udev context"));
         goto cleanup;
     }
+    driver->privileged = privileged;
 
     ret = 0;
 
@@ -1193,6 +1195,80 @@ udevStateCleanup(void)
 }
 
 
+static virDrvOpenStatus udevConnectOpen(virConnectPtr conn,
+                                        virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                                        virConfPtr conf ATTRIBUTE_UNUSED,
+                                        unsigned int flags)
+{
+    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+    /* Verify uri was specified */
+    if (conn->uri == NULL) {
+        /* Only hypervisor drivers are permitted to auto-open on NULL uri */
+        return VIR_DRV_OPEN_DECLINED;
+    } else {
+        if (STRNEQ_NULLABLE(conn->uri->scheme, "interface"))
+            return VIR_DRV_OPEN_DECLINED;
+
+        /* Leave for remote driver */
+        if (conn->uri->server != NULL)
+            return VIR_DRV_OPEN_DECLINED;
+
+        if (driver == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("interface state driver is not active"));
+            return VIR_DRV_OPEN_ERROR;
+        }
+
+        if (driver->privileged) {
+            if (STRNEQ(conn->uri->path, "/system")) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected interface URI path '%s', try interface:///system"),
+                               conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+        } else {
+            if (STRNEQ(conn->uri->path, "/session")) {
+                virReportError(VIR_ERR_INTERNAL_ERROR,
+                               _("unexpected interface URI path '%s', try interface:///session"),
+                               conn->uri->path);
+                return VIR_DRV_OPEN_ERROR;
+            }
+        }
+    }
+
+    if (virConnectOpenEnsureACL(conn) < 0)
+        return VIR_DRV_OPEN_ERROR;
+
+    return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int udevConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return 0;
+}
+
+
+static int udevConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    /* Trivially secure, since always inside the daemon */
+    return 1;
+}
+
+
+static int udevConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    /* Not encrypted, but remote driver takes care of that */
+    return 0;
+}
+
+
+static int udevConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
+{
+    return 1;
+}
+
+
 static virInterfaceDriver udevIfaceDriver = {
     .name = "udev",
     .connectNumOfInterfaces = udevConnectNumOfInterfaces, /* 1.0.0 */
@@ -1206,6 +1282,23 @@ static virInterfaceDriver udevIfaceDriver = {
     .interfaceGetXMLDesc = udevInterfaceGetXMLDesc, /* 1.0.0 */
 };
 
+
+static virHypervisorDriver udevHypervisorDriver = {
+    .name = "interface",
+    .connectOpen = udevConnectOpen, /* 4.1.0 */
+    .connectClose = udevConnectClose, /* 4.1.0 */
+    .connectIsEncrypted = udevConnectIsEncrypted, /* 4.1.0 */
+    .connectIsSecure = udevConnectIsSecure, /* 4.1.0 */
+    .connectIsAlive = udevConnectIsAlive, /* 4.1.0 */
+};
+
+
+static virConnectDriver udevConnectDriver = {
+    .hypervisorDriver = &udevHypervisorDriver,
+    .interfaceDriver = &udevIfaceDriver,
+};
+
+
 static virStateDriver interfaceStateDriver = {
     .name = "udev",
     .stateInitialize = udevStateInitialize,
@@ -1215,6 +1308,8 @@ static virStateDriver interfaceStateDriver = {
 int
 udevIfaceRegister(void)
 {
+    if (virRegisterConnectDriver(&udevConnectDriver, false) < 0)
+        return -1;
     if (virSetSharedInterfaceDriver(&udevIfaceDriver) < 0) {
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("failed to register udev interface driver"));
-- 
2.14.3




More information about the libvir-list mailing list