]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
parallels: add network driver
authorDmitry Guryanov <dguryanov@parallels.com>
Tue, 11 Dec 2012 10:59:45 +0000 (14:59 +0400)
committerDaniel Veillard <veillard@redhat.com>
Tue, 11 Dec 2012 14:46:16 +0000 (22:46 +0800)
Parallels Cloud Server uses virtual networks model for network
configuration. It uses own tools for virtual network management.
So add network driver, which will be responsible for listing
virtual networks and performing different operations on them
(in consequent patched).

This patch only allows listing virtual network names, without
any parameters like DHCP server settings.

Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com>
po/POTFILES.in
src/Makefile.am
src/parallels/parallels_driver.c
src/parallels/parallels_network.c [new file with mode: 0644]
src/parallels/parallels_utils.h

index 50cdc4eaaaf8362622c00faeb5563ddc719e16d0..4789a97ef9edb993f6691ea582615bac1262bcaf 100644 (file)
@@ -76,6 +76,7 @@ src/openvz/openvz_conf.c
 src/openvz/openvz_driver.c
 src/openvz/openvz_util.c
 src/parallels/parallels_driver.c
+src/parallels/parallels_network.c
 src/parallels/parallels_utils.c
 src/parallels/parallels_utils.h
 src/parallels/parallels_storage.c
index 1a2f94f7901b7ac241da9aaf8c106004df6be02e..6d2816dc5111d1239c4e52951817106a374a4faa 100644 (file)
@@ -557,7 +557,8 @@ PARALLELS_DRIVER_SOURCES =                                  \
                parallels/parallels_driver.c                    \
                parallels/parallels_utils.c                     \
                parallels/parallels_utils.h                     \
-               parallels/parallels_storage.c
+               parallels/parallels_storage.c           \
+               parallels/parallels_network.c
 
 NETWORK_DRIVER_SOURCES =                                       \
                network/bridge_driver.h network/bridge_driver.c
index 389743fb511ce67bc6ff37b5cf2ae2a900b3ed9e..b288c952325cdc615c982a21d212c4666a114bdc 100644 (file)
@@ -2413,6 +2413,8 @@ parallelsRegister(void)
         return -1;
     if (parallelsStorageRegister())
         return -1;
+    if (parallelsNetworkRegister())
+        return -1;
 
     return 0;
 }
diff --git a/src/parallels/parallels_network.c b/src/parallels/parallels_network.c
new file mode 100644 (file)
index 0000000..d30c94d
--- /dev/null
@@ -0,0 +1,424 @@
+/*
+ * parallels_storage.c: core privconn functions for managing
+ * Parallels Cloud Server hosts
+ *
+ * Copyright (C) 2012 Parallels, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <config.h>
+
+#include "datatypes.h"
+#include "memory.h"
+#include "virterror_internal.h"
+#include "md5.h"
+
+#include "parallels_utils.h"
+
+#define VIR_FROM_THIS VIR_FROM_PARALLELS
+
+#define parallelsParseError()                                                  \
+    virReportErrorHelper(VIR_FROM_TEST, VIR_ERR_OPERATION_FAILED, __FILE__,    \
+                     __FUNCTION__, __LINE__, _("Can't parse prlctl output"))
+
+static virNetworkObjPtr
+parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj)
+{
+    virNetworkObjPtr net;
+    virNetworkDefPtr def;
+    const char *tmp;
+    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
+    unsigned char md5[MD5_DIGEST_SIZE];
+
+    if (VIR_ALLOC(def) < 0)
+        goto no_memory;
+
+    if (!(tmp = virJSONValueObjectGetString(jobj, "Network ID"))) {
+        parallelsParseError();
+        goto cleanup;
+    }
+
+    if (!(def->name = strdup(tmp)))
+        goto no_memory;
+
+    /* Network names are unique in Parallels Cloud Server, so we can make
+     * an UUID from it */
+    md5_buffer(tmp, strlen(tmp), md5);
+    memcpy(def->uuid, md5, VIR_UUID_BUFLEN);
+    def->uuid_specified = 1;
+
+    if (!(net = virNetworkAssignDef(&privconn->networks, def, false))) {
+        virNetworkDefFree(def);
+        goto cleanup;
+    }
+    net->active = 1;
+    net->persistent = 1;
+    net->autostart = 1;
+    virNetworkObjUnlock(net);
+    return net;
+
+no_memory:
+    virReportOOMError();
+cleanup:
+    virNetworkDefFree(def);
+    return NULL;
+}
+
+static int parallelsLoadNetworks(parallelsConnPtr privconn)
+{
+    virJSONValuePtr jobj, jobj2;
+    virNetworkObjPtr net;
+    int ret = -1;
+    int count, i;
+
+    jobj = parallelsParseOutput("prlsrvctl", "net", "list", "-j", NULL);
+
+    if (!jobj) {
+        parallelsParseError();
+        goto cleanup;
+    }
+
+    count = virJSONValueArraySize(jobj);
+    if (count < 0) {
+        parallelsParseError();
+        goto cleanup;
+    }
+
+    for (i = 0; i < count; i++) {
+        jobj2 = virJSONValueArrayGet(jobj, i);
+        if (!jobj2) {
+            parallelsParseError();
+            goto cleanup;
+        }
+
+        net = parallelsLoadNetwork(privconn, jobj2);
+        if (!net)
+            goto cleanup;
+
+    }
+
+    ret = 0;
+
+cleanup:
+    virJSONValueFree(jobj);
+    return ret;
+}
+
+static virDrvOpenStatus
+parallelsOpenNetwork(virConnectPtr conn,
+                     virConnectAuthPtr auth ATTRIBUTE_UNUSED,
+                     unsigned int flags)
+{
+    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
+
+    if (STRNEQ(conn->driver->name, "Parallels"))
+        return VIR_DRV_OPEN_DECLINED;
+
+    conn->networkPrivateData = conn->privateData;
+
+    if (parallelsLoadNetworks(conn->privateData) < 0)
+        return VIR_DRV_OPEN_DECLINED;
+
+    return VIR_DRV_OPEN_SUCCESS;
+}
+
+static int parallelsCloseNetwork(virConnectPtr conn)
+{
+    parallelsConnPtr privconn = conn->privateData;
+    parallelsDriverLock(privconn);
+    virNetworkObjListFree(&privconn->networks);
+    parallelsDriverUnlock(privconn);
+    return 0;
+}
+
+static int parallelsNumNetworks(virConnectPtr conn)
+{
+    int nactive = 0, i;
+    parallelsConnPtr privconn = conn->privateData;
+
+    parallelsDriverLock(privconn);
+    for (i = 0 ; i < privconn->networks.count ; i++) {
+        virNetworkObjLock(privconn->networks.objs[i]);
+        if (virNetworkObjIsActive(privconn->networks.objs[i]))
+            nactive++;
+        virNetworkObjUnlock(privconn->networks.objs[i]);
+    }
+    parallelsDriverUnlock(privconn);
+
+    return nactive;
+}
+
+static int parallelsListNetworks(virConnectPtr conn,
+                                 char **const names,
+                                 int nnames)
+{
+    parallelsConnPtr privconn = conn->privateData;
+    int got = 0, i;
+
+    parallelsDriverLock(privconn);
+    for (i = 0 ; i < privconn->networks.count && got < nnames ; i++) {
+        virNetworkObjLock(privconn->networks.objs[i]);
+        if (virNetworkObjIsActive(privconn->networks.objs[i])) {
+            if (!(names[got] = strdup(privconn->networks.objs[i]->def->name))) {
+                virNetworkObjUnlock(privconn->networks.objs[i]);
+                virReportOOMError();
+                goto cleanup;
+            }
+            got++;
+        }
+        virNetworkObjUnlock(privconn->networks.objs[i]);
+    }
+    parallelsDriverUnlock(privconn);
+
+    return got;
+
+ cleanup:
+    parallelsDriverUnlock(privconn);
+    for (i = 0 ; i < got ; i++)
+        VIR_FREE(names[i]);
+    return -1;
+}
+
+static int parallelsNumDefinedNetworks(virConnectPtr conn)
+{
+    int ninactive = 0, i;
+    parallelsConnPtr privconn = conn->privateData;
+
+    parallelsDriverLock(privconn);
+    for (i = 0 ; i < privconn->networks.count ; i++) {
+        virNetworkObjLock(privconn->networks.objs[i]);
+        if (!virNetworkObjIsActive(privconn->networks.objs[i]))
+            ninactive++;
+        virNetworkObjUnlock(privconn->networks.objs[i]);
+    }
+    parallelsDriverUnlock(privconn);
+
+    return ninactive;
+}
+
+static int parallelsListDefinedNetworks(virConnectPtr conn,
+                                        char **const names,
+                                        int nnames)
+{
+    parallelsConnPtr privconn = conn->privateData;
+    int got = 0, i;
+
+    parallelsDriverLock(privconn);
+    for (i = 0 ; i < privconn->networks.count && got < nnames ; i++) {
+        virNetworkObjLock(privconn->networks.objs[i]);
+        if (!virNetworkObjIsActive(privconn->networks.objs[i])) {
+            if (!(names[got] = strdup(privconn->networks.objs[i]->def->name))) {
+                virNetworkObjUnlock(privconn->networks.objs[i]);
+                virReportOOMError();
+                goto cleanup;
+            }
+            got++;
+        }
+        virNetworkObjUnlock(privconn->networks.objs[i]);
+    }
+    parallelsDriverUnlock(privconn);
+    return got;
+
+ cleanup:
+    parallelsDriverUnlock(privconn);
+    for (i = 0 ; i < got ; i++)
+        VIR_FREE(names[i]);
+    return -1;
+}
+
+static int parallelsListAllNetworks(virConnectPtr conn,
+                                    virNetworkPtr **nets,
+                                    unsigned int flags)
+{
+    parallelsConnPtr privconn = conn->privateData;
+    int ret = -1;
+
+    virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1);
+
+    parallelsDriverLock(privconn);
+    ret = virNetworkList(conn, privconn->networks, nets, flags);
+    parallelsDriverUnlock(privconn);
+
+    return ret;
+}
+
+static virNetworkPtr parallelsNetworkLookupByUUID(virConnectPtr conn,
+                                                  const unsigned char *uuid)
+{
+    parallelsConnPtr privconn = conn->privateData;
+    virNetworkObjPtr network;
+    virNetworkPtr ret = NULL;
+
+    parallelsDriverLock(privconn);
+    network = virNetworkFindByUUID(&privconn->networks, uuid);
+    parallelsDriverUnlock(privconn);
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+
+static virNetworkPtr parallelsNetworkLookupByName(virConnectPtr conn,
+                                                  const char *name)
+{
+    parallelsConnPtr privconn = conn->privateData;
+    virNetworkObjPtr network;
+    virNetworkPtr ret = NULL;
+
+    parallelsDriverLock(privconn);
+    network = virNetworkFindByName(&privconn->networks, name);
+    parallelsDriverUnlock(privconn);
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       _("no network with matching name '%s'"), name);
+        goto cleanup;
+    }
+
+    ret = virGetNetwork(conn, network->def->name, network->def->uuid);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+
+static char *parallelsNetworkGetXMLDesc(virNetworkPtr net,
+                                        unsigned int flags)
+{
+    parallelsConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr network;
+    char *ret = NULL;
+
+    virCheckFlags(VIR_NETWORK_XML_INACTIVE, NULL);
+
+    parallelsDriverLock(privconn);
+    network = virNetworkFindByUUID(&privconn->networks, net->uuid);
+    parallelsDriverUnlock(privconn);
+
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    ret = virNetworkDefFormat(network->def, flags);
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+
+static int parallelsNetworkIsActive(virNetworkPtr net)
+{
+    parallelsConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr obj;
+    int ret = -1;
+
+    parallelsDriverLock(privconn);
+    obj = virNetworkFindByUUID(&privconn->networks, net->uuid);
+    parallelsDriverUnlock(privconn);
+    if (!obj) {
+        virReportError(VIR_ERR_NO_NETWORK, NULL);
+        goto cleanup;
+    }
+    ret = virNetworkObjIsActive(obj);
+
+cleanup:
+    if (obj)
+        virNetworkObjUnlock(obj);
+    return ret;
+}
+
+static int parallelsNetworkIsPersistent(virNetworkPtr net)
+{
+    parallelsConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr obj;
+    int ret = -1;
+
+    parallelsDriverLock(privconn);
+    obj = virNetworkFindByUUID(&privconn->networks, net->uuid);
+    parallelsDriverUnlock(privconn);
+    if (!obj) {
+        virReportError(VIR_ERR_NO_NETWORK, NULL);
+        goto cleanup;
+    }
+    ret = obj->persistent;
+
+cleanup:
+    if (obj)
+        virNetworkObjUnlock(obj);
+    return ret;
+}
+
+static int parallelsNetworkGetAutostart(virNetworkPtr net,
+                                 int *autostart)
+{
+    parallelsConnPtr privconn = net->conn->privateData;
+    virNetworkObjPtr network;
+    int ret = -1;
+
+    parallelsDriverLock(privconn);
+    network = virNetworkFindByUUID(&privconn->networks, net->uuid);
+    parallelsDriverUnlock(privconn);
+    if (!network) {
+        virReportError(VIR_ERR_NO_NETWORK,
+                       "%s", _("no network with matching uuid"));
+        goto cleanup;
+    }
+
+    *autostart = network->autostart;
+    ret = 0;
+
+cleanup:
+    if (network)
+        virNetworkObjUnlock(network);
+    return ret;
+}
+static virNetworkDriver parallelsNetworkDriver = {
+    "Parallels",
+    .open = parallelsOpenNetwork, /* 1.0.1 */
+    .close = parallelsCloseNetwork, /* 1.0.1 */
+    .numOfNetworks = parallelsNumNetworks, /* 1.0.1 */
+    .listNetworks = parallelsListNetworks, /* 1.0.1 */
+    .numOfDefinedNetworks = parallelsNumDefinedNetworks, /* 1.0.1 */
+    .listDefinedNetworks = parallelsListDefinedNetworks, /* 1.0.1 */
+    .listAllNetworks = parallelsListAllNetworks, /* 1.0.1 */
+    .networkLookupByUUID = parallelsNetworkLookupByUUID, /* 1.0.1 */
+    .networkLookupByName = parallelsNetworkLookupByName, /* 1.0.1 */
+    .networkGetXMLDesc = parallelsNetworkGetXMLDesc, /* 1.0.1 */
+    .networkGetAutostart = parallelsNetworkGetAutostart, /* 1.0.1 */
+    .networkIsActive = parallelsNetworkIsActive, /* 1.0.1 */
+    .networkIsPersistent = parallelsNetworkIsPersistent, /* 1.0.1 */
+};
+
+int
+parallelsNetworkRegister(void)
+{
+    if (virRegisterNetworkDriver(&parallelsNetworkDriver) < 0)
+        return -1;
+
+    return 0;
+}
index 8b0bdf680ad8fe445aeb392f7cd2b3082baaacfb..aca3ee245c39998fd696f7d7814d9fb08a44236a 100644 (file)
@@ -28,6 +28,7 @@
 # include "conf/domain_conf.h"
 # include "conf/storage_conf.h"
 # include "conf/domain_event.h"
+# include "conf/network_conf.h"
 # include "json.h"
 
 # define parallelsParseError()                                                 \
@@ -38,6 +39,7 @@ struct _parallelsConn {
     virMutex lock;
     virDomainObjList domains;
     virStoragePoolObjList pools;
+    virNetworkObjList networks;
     virCapsPtr caps;
     virDomainEventStatePtr domainEventState;
 };
@@ -54,6 +56,7 @@ struct parallelsDomObj {
 typedef struct parallelsDomObj *parallelsDomObjPtr;
 
 int parallelsStorageRegister(void);
+int parallelsNetworkRegister(void);
 
 virJSONValuePtr parallelsParseOutput(const char *binary, ...)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;