[libvirt] [PATCH 0/7] parallels: bridge network support enhancement and other network fixes

Maxim Nestratov (7): parallels: introduce and use string constants for network types and names parallels: fix parallelsLoadNetworks parallels: better bridge network interface support parallels: set network adapter device status to connected parallels: make E1000 network adapter type default parallels: switch off offline management feature parallels: don't prevent domain start if VIR_DOMAIN_NET_TYPE_BRIDGE

Signed-off-by: Maxim Nestratov <mnestratov@parallels.com> --- src/parallels/parallels_network.c | 6 +++--- src/parallels/parallels_sdk.c | 6 +++--- src/parallels/parallels_utils.h | 8 +++++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/parallels/parallels_network.c b/src/parallels/parallels_network.c index 62ed268..26767c0 100644 --- a/src/parallels/parallels_network.c +++ b/src/parallels/parallels_network.c @@ -211,12 +211,12 @@ parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj) goto cleanup; } - if (STREQ(tmp, "bridged")) { + if (STREQ(tmp, PARALLELS_BRIDGED_NETWORK_TYPE)) { def->forward.type = VIR_NETWORK_FORWARD_BRIDGE; if (parallelsGetBridgedNetInfo(def, jobj) < 0) goto cleanup; - } else if (STREQ(tmp, "host-only")) { + } else if (STREQ(tmp, PARALLELS_HOSTONLY_NETWORK_TYPE)) { def->forward.type = VIR_NETWORK_FORWARD_NONE; if (parallelsGetHostOnlyNetInfo(def, def->name) < 0) @@ -249,7 +249,7 @@ parallelsAddRoutedNetwork(parallelsConnPtr privconn) def->forward.type = VIR_NETWORK_FORWARD_ROUTE; - if (VIR_STRDUP(def->name, PARALLELS_ROUTED_NETWORK_NAME) < 0) + if (VIR_STRDUP(def->name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME) < 0) goto cleanup; if (virUUIDParse(PARALLELS_ROUTED_NETWORK_UUID, def->uuid) < 0) { diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index fec145d..c31439f 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -709,7 +709,7 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt) * always up */ net->linkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_UP; if (VIR_STRDUP(net->data.network.name, - PARALLELS_ROUTED_NETWORK_NAME) < 0) + PARALLELS_DOMAIN_ROUTED_NETWORK_NAME) < 0) goto cleanup; return 0; } @@ -728,7 +728,7 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt) if (emulatedType == PNA_ROUTED) { if (VIR_STRDUP(net->data.network.name, - PARALLELS_ROUTED_NETWORK_NAME) < 0) + PARALLELS_DOMAIN_ROUTED_NETWORK_NAME) < 0) goto cleanup; } else { pret = PrlVmDevNet_GetVirtualNetworkId(netAdapter, NULL, &buflen); @@ -2644,8 +2644,8 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net) pret = PrlVmDevNet_SetMacAddress(sdknet, macstr); prlsdkCheckRetGoto(pret, cleanup); - if (STREQ(net->data.network.name, PARALLELS_ROUTED_NETWORK_NAME)) { pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED); + if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) { prlsdkCheckRetGoto(pret, cleanup); } else { pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name); diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h index ead5586..a1c7c60 100644 --- a/src/parallels/parallels_utils.h +++ b/src/parallels/parallels_utils.h @@ -47,7 +47,13 @@ _("no domain with matching uuid '%s'"), uuidstr); \ } while (0) -# define PARALLELS_ROUTED_NETWORK_NAME "Routed" +# define PARALLELS_DOMAIN_ROUTED_NETWORK_NAME "Routed" +# define PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME "Bridged" + +# define PARALLELS_REQUIRED_HOSTONLY_NETWORK "Host-Only" +# define PARALLELS_HOSTONLY_NETWORK_TYPE "host-only" +# define PARALLELS_REQUIRED_BRIDGED_NETWORK "Bridged" +# define PARALLELS_BRIDGED_NETWORK_TYPE "bridged" struct _parallelsConn { virMutex lock; -- 1.7.1

Don't fail initialization of parallels driver if parallelsLoadNetwork fails for optional networks. This can happen when some of them are added manually and configured incompletely. PCS requires only two networks created automatically (named Host-Only and Bridged), others are optional and their incompletenes can be ignored. Signed-off-by: Maxim Nestratov <mnestratov@parallels.com> --- src/parallels/parallels_network.c | 29 +++++++++++++++++++++-------- 1 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/parallels/parallels_network.c b/src/parallels/parallels_network.c index 26767c0..24fdb70 100644 --- a/src/parallels/parallels_network.c +++ b/src/parallels/parallels_network.c @@ -180,9 +180,10 @@ static int parallelsGetHostOnlyNetInfo(virNetworkDefPtr def, const char *name) return ret; } -static virNetworkObjPtr +static int parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj) { + int ret = -1; virNetworkObjPtr net; virNetworkDefPtr def; const char *tmp; @@ -214,13 +215,25 @@ parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj) if (STREQ(tmp, PARALLELS_BRIDGED_NETWORK_TYPE)) { def->forward.type = VIR_NETWORK_FORWARD_BRIDGE; - if (parallelsGetBridgedNetInfo(def, jobj) < 0) + if (parallelsGetBridgedNetInfo(def, jobj) < 0) { + + /* Only mandatory networks required to be configured completely */ + if (!STREQ(def->name, PARALLELS_REQUIRED_BRIDGED_NETWORK)) + ret = 0; + goto cleanup; + } } else if (STREQ(tmp, PARALLELS_HOSTONLY_NETWORK_TYPE)) { def->forward.type = VIR_NETWORK_FORWARD_NONE; - if (parallelsGetHostOnlyNetInfo(def, def->name) < 0) + if (parallelsGetHostOnlyNetInfo(def, def->name) < 0) { + + /* Only mandatory networks required to be configured completely */ + if (!STREQ(def->name, PARALLELS_REQUIRED_HOSTONLY_NETWORK)) + ret = 0; + goto cleanup; + } } else { parallelsParseError(); goto cleanup; @@ -231,11 +244,12 @@ parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj) net->active = 1; net->autostart = 1; virNetworkObjUnlock(net); - return net; + ret = 0; + return ret; cleanup: virNetworkDefFree(def); - return NULL; + return ret; } static virNetworkObjPtr @@ -277,7 +291,6 @@ parallelsAddRoutedNetwork(parallelsConnPtr privconn) static int parallelsLoadNetworks(parallelsConnPtr privconn) { virJSONValuePtr jobj, jobj2; - virNetworkObjPtr net; int ret = -1; int count; size_t i; @@ -302,8 +315,8 @@ static int parallelsLoadNetworks(parallelsConnPtr privconn) goto cleanup; } - net = parallelsLoadNetwork(privconn, jobj2); - if (!net) + ret = parallelsLoadNetwork(privconn, jobj2); + if (!ret) goto cleanup; } -- 1.7.1

In order to support 'bridge' network adapters in parallels driver we need to plug our veth devices into corresponding linux bridges. We are going to do this by reusing our abstraction of Virtual Networks in terms of PCS. On a domain creation, we create a new Virtual Network naming it with the same name as a source bridge for each network interface. Having done this, we plug PCS veth interfaces created with names of target dev into specified bridges using our standard PCS procedures Signed-off-by: Maxim Nestratov <mnestratov@parallels.com> --- src/parallels/parallels_sdk.c | 101 +++++++++++++++++++++++++++++++++++------ 1 files changed, 87 insertions(+), 14 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index c31439f..71a64a1 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -692,9 +692,6 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt) /* use device name, shown by prlctl as target device * for identifying network adapter in virDomainDefineXML */ - pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex); - prlsdkCheckRetGoto(pret, cleanup); - pret = PrlVmDevNet_GetHostInterfaceName(netAdapter, NULL, &buflen); prlsdkCheckRetGoto(pret, cleanup); @@ -704,6 +701,9 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt) pret = PrlVmDevNet_GetHostInterfaceName(netAdapter, net->ifname, &buflen); prlsdkCheckRetGoto(pret, cleanup); + pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex); + prlsdkCheckRetGoto(pret, cleanup); + if (isCt && netAdapterIndex == (PRL_UINT32) -1) { /* venet devices don't have mac address and * always up */ @@ -741,6 +741,16 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt) net->data.network.name, &buflen); prlsdkCheckRetGoto(pret, cleanup); + + /* + * We use VIR_DOMAIN_NET_TYPE_NETWORK for all network adapters + * except those whose Virtual Network Id differ from Parallels + * predefined ones such as PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME + * and PARALLELS_DONAIN_ROUTED_NETWORK_NAME + */ + if (!STREQ(net->data.network.name, PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME)) + net->type = VIR_DOMAIN_NET_TYPE_BRIDGE; + } pret = PrlVmDev_IsConnected(netAdapter, &isConnected); @@ -2616,10 +2626,12 @@ static const char * prlsdkFormatMac(virMacAddrPtr mac, char *macstr) return macstr; } -static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net) +static int prlsdkAddNet(PRL_HANDLE sdkdom, parallelsConnPtr privconn, virDomainNetDefPtr net) { PRL_RESULT pret; PRL_HANDLE sdknet = PRL_INVALID_HANDLE; + PRL_HANDLE vnet = PRL_INVALID_HANDLE; + PRL_HANDLE job = PRL_INVALID_HANDLE; int ret = -1; char macstr[PRL_MAC_STRING_BUFNAME]; @@ -2644,10 +2656,39 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net) pret = PrlVmDevNet_SetMacAddress(sdknet, macstr); prlsdkCheckRetGoto(pret, cleanup); - pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED); - if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) { + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { + if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) { + pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED); + prlsdkCheckRetGoto(pret, cleanup); + } else if (STREQ(net->data.network.name, PARALLELS_DOMAIN_BRIDGED_NETWORK_NAME)) { + pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name); + prlsdkCheckRetGoto(pret, cleanup); + } + } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) { + /* + * For this type of adapter we create a new + * Virtual Network assuming that bridge with given name exists + * Failing creating this means domain creation failure + */ + pret = PrlVirtNet_Create(&vnet); prlsdkCheckRetGoto(pret, cleanup); - } else { + + pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVirtNet_SetNetworkType(vnet, PVN_BRIDGED_ETHERNET); + prlsdkCheckRetGoto(pret, cleanup); + + job = PrlSrv_AddVirtualNetwork(privconn->server, vnet, 0); + if (PRL_FAILED(pret = waitJob(job, privconn->jobTimeout))) + goto cleanup; + + pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET); + prlsdkCheckRetGoto(pret, cleanup); + pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name); prlsdkCheckRetGoto(pret, cleanup); } @@ -2660,10 +2701,34 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net) ret = 0; cleanup: + PrlHandle_Free(vnet); PrlHandle_Free(sdknet); return ret; } +static void prlsdkDelNet(parallelsConnPtr privconn, virDomainNetDefPtr net) +{ + PRL_RESULT pret; + PRL_HANDLE vnet = PRL_INVALID_HANDLE; + PRL_HANDLE job = PRL_INVALID_HANDLE; + + if (net->type != VIR_DOMAIN_NET_TYPE_BRIDGE) + return; + + pret = PrlVirtNet_Create(&vnet); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name); + prlsdkCheckRetGoto(pret, cleanup); + + PrlSrv_DeleteVirtualNetwork(privconn->server, vnet, 0); + if (PRL_FAILED(pret = waitJob(job, privconn->jobTimeout))) + goto cleanup; + + cleanup: + PrlHandle_Free(vnet); +} + static int prlsdkAddDisk(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk, bool bootDisk) { PRL_RESULT pret; @@ -2835,7 +2900,8 @@ prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDefPtr fs) return ret; } static int -prlsdkDoApplyConfig(PRL_HANDLE sdkdom, +prlsdkDoApplyConfig(virConnectPtr conn, + PRL_HANDLE sdkdom, virDomainDefPtr def) { PRL_RESULT pret; @@ -2887,8 +2953,8 @@ prlsdkDoApplyConfig(PRL_HANDLE sdkdom, } for (i = 0; i < def->nnets; i++) { - if (prlsdkAddNet(sdkdom, def->nets[i]) < 0) - goto error; + if (prlsdkAddNet(sdkdom, conn->privateData, def->nets[i]) < 0) + goto error; } for (i = 0; i < def->ndisks; i++) { @@ -2912,7 +2978,10 @@ prlsdkDoApplyConfig(PRL_HANDLE sdkdom, return 0; error: - return -1; + for (i = 0; i < def->nnets; i++) + prlsdkDelNet(conn->privateData, def->nets[i]); + + return -1; } int @@ -2933,7 +3002,7 @@ prlsdkApplyConfig(virConnectPtr conn, if (PRL_FAILED(waitJob(job, privconn->jobTimeout))) return -1; - ret = prlsdkDoApplyConfig(sdkdom, new); + ret = prlsdkDoApplyConfig(conn, sdkdom, new); if (ret == 0) { job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE); @@ -2970,7 +3039,7 @@ prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def) pret = PrlVmCfg_SetDefaultConfig(sdkdom, srvconf, PVS_GUEST_VER_LIN_REDHAT, 0); prlsdkCheckRetGoto(pret, cleanup); - ret = prlsdkDoApplyConfig(sdkdom, def); + ret = prlsdkDoApplyConfig(conn, sdkdom, def); if (ret) goto cleanup; @@ -3032,7 +3101,7 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def) } - ret = prlsdkDoApplyConfig(sdkdom, def); + ret = prlsdkDoApplyConfig(conn, sdkdom, def); if (ret) goto cleanup; @@ -3051,6 +3120,10 @@ prlsdkUnregisterDomain(parallelsConnPtr privconn, virDomainObjPtr dom) { parallelsDomObjPtr privdom = dom->privateData; PRL_HANDLE job; + size_t i; + + for (i = 0; i < dom->def->nnets; i++) + prlsdkDelNet(privconn, dom->def->nets[i]); job = PrlVm_Unreg(privdom->sdkdom); if (PRL_FAILED(waitJob(job, privconn->jobTimeout))) -- 1.7.1

when a new network adapter device is added Signed-off-by: Maxim Nestratov <mnestratov@parallels.com> --- src/parallels/parallels_sdk.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index 71a64a1..f0777bd 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -2644,7 +2644,7 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, parallelsConnPtr privconn, virDomainN pret = PrlVmDev_SetEnabled(sdknet, 1); prlsdkCheckRetGoto(pret, cleanup); - pret = PrlVmDev_SetConnected(sdknet, net->linkstate); + pret = PrlVmDev_SetConnected(sdknet, 1); prlsdkCheckRetGoto(pret, cleanup); if (net->ifname) { -- 1.7.1

Signed-off-by: Maxim Nestratov <mnestratov@parallels.com> --- src/parallels/parallels_sdk.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index f0777bd..e17a941 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -2656,6 +2656,10 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, parallelsConnPtr privconn, virDomainN pret = PrlVmDevNet_SetMacAddress(sdknet, macstr); prlsdkCheckRetGoto(pret, cleanup); + /* Other alternatives: PNT_VIRTIO, PNT_RTL */ + pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_E1000); + prlsdkCheckRetGoto(pret, cleanup); + if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) { if (STREQ(net->data.network.name, PARALLELS_DOMAIN_ROUTED_NETWORK_NAME)) { pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED); -- 1.7.1

which is on by default when a new VM/CT is created. We should do this because this feature can't be controlled by libvirt now and it sets up some iptables rules. So it's better to do this to avoid potential conflict of different set of rules or to avoid unexpected behavior. Signed-off-by: Maxim Nestratov <mnestratov@parallels.com> --- src/parallels/parallels_sdk.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index e17a941..fb65ff9 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -3043,6 +3043,9 @@ prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def) pret = PrlVmCfg_SetDefaultConfig(sdkdom, srvconf, PVS_GUEST_VER_LIN_REDHAT, 0); prlsdkCheckRetGoto(pret, cleanup); + pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0); + prlsdkCheckRetGoto(pret, cleanup); + ret = prlsdkDoApplyConfig(conn, sdkdom, def); if (ret) goto cleanup; -- 1.7.1

network adapter is used Signed-off-by: Maxim Nestratov <mnestratov@parallels.com> --- src/parallels/parallels_sdk.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c index fb65ff9..c94e70a 100644 --- a/src/parallels/parallels_sdk.c +++ b/src/parallels/parallels_sdk.c @@ -2237,7 +2237,8 @@ static int prlsdkCheckSerialUnsupportedParams(virDomainChrDefPtr chr) static int prlsdkCheckNetUnsupportedParams(virDomainNetDefPtr net) { - if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK) { + if (net->type != VIR_DOMAIN_NET_TYPE_NETWORK && + net->type != VIR_DOMAIN_NET_TYPE_BRIDGE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Specified network adapter type is not " "supported by Parallels Cloud Server.")); -- 1.7.1
participants (1)
-
Maxim Nestratov