[libvirt] [PATCH 4/8] parallels: add network driver

Daniel Veillard veillard at redhat.com
Tue Dec 11 14:40:36 UTC 2012


On Tue, Dec 11, 2012 at 02:59:45PM +0400, Dmitry Guryanov wrote:
> 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 at parallels.com>
> ---
>  po/POTFILES.in                    |    1 +
>  src/Makefile.am                   |    3 +-
>  src/parallels/parallels_driver.c  |    2 +
>  src/parallels/parallels_network.c |  424 +++++++++++++++++++++++++++++++++++++
>  src/parallels/parallels_utils.h   |    3 +
>  5 files changed, 432 insertions(+), 1 deletions(-)
>  create mode 100644 src/parallels/parallels_network.c
> 
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index 50cdc4e..4789a97 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -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
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 1a2f94f..6d2816d 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -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
> diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
> index 5d89503..21279c0 100644
> --- a/src/parallels/parallels_driver.c
> +++ b/src/parallels/parallels_driver.c
> @@ -2410,6 +2410,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
> index 0000000..d30c94d
> --- /dev/null
> +++ b/src/parallels/parallels_network.c
> @@ -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;
> +}
> diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h
> index 8b0bdf6..aca3ee2 100644
> --- a/src/parallels/parallels_utils.h
> +++ b/src/parallels/parallels_utils.h
> @@ -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;

  ACK, big chunk, but looks fine to me,

Daniel

-- 
Daniel Veillard      | Open Source and Standards, Red Hat
veillard at redhat.com  | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list