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@xxxxxxxxxxxxx> > --- > 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(¶llelsNetworkDriver) < 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@xxxxxxxxxx | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list