[libvirt] [PATCH] parallels: implement attach/detach network.

Mikhail Feoktistov mfeoktistov at odin.com
Thu Jun 11 12:36:10 UTC 2015


Support nova commands interface-attach and interface-detach.
For containers only.

I use memcmp() to compare MAC addresses,
because PrlVmDevNet_GetMacAddress() returns MAC as a UTF-8 encoded,
null-terminated string.
---
 src/parallels/parallels_driver.c |   16 ++++
 src/parallels/parallels_sdk.c    |  144 +++++++++++++++++++++++++++++++++++++-
 src/parallels/parallels_sdk.h    |    4 +
 3 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/src/parallels/parallels_driver.c b/src/parallels/parallels_driver.c
index 706229d..0009127 100644
--- a/src/parallels/parallels_driver.c
+++ b/src/parallels/parallels_driver.c
@@ -1117,6 +1117,14 @@ static int parallelsDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
             goto cleanup;
         }
         break;
+    case VIR_DOMAIN_DEVICE_NET:
+        ret = prlsdkAttachNet(privdom, privconn, dev->data.net);
+        if (ret) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("network attach failed"));
+            goto cleanup;
+        }
+        break;
     default:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("device type '%s' cannot be attached"),
@@ -1186,6 +1194,14 @@ static int parallelsDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
             goto cleanup;
         }
         break;
+    case VIR_DOMAIN_DEVICE_NET:
+        ret = prlsdkDetachNet(privdom, privconn, dev->data.net);
+        if (ret) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("network detach failed"));
+            goto cleanup;
+        }
+        break;
     default:
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                        _("device type '%s' cannot be detached"),
diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
index 104c905..306f5e3 100644
--- a/src/parallels/parallels_sdk.c
+++ b/src/parallels/parallels_sdk.c
@@ -2815,6 +2815,12 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom,
     pret = PrlVmDevNet_SetMacAddress(sdknet, macstr);
     prlsdkCheckRetGoto(pret, cleanup);
 
+    pret = PrlVmDevNet_SetConfigureWithDhcp(sdknet, true);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDevNet_SetAutoApply(sdknet, true);
+    prlsdkCheckRetGoto(pret, cleanup);
+
     if (isCt) {
         if (net->model)
              VIR_WARN("Setting network adapter for containers is not "
@@ -2885,14 +2891,15 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom,
     return ret;
 }
 
-static void prlsdkDelNet(parallelsConnPtr privconn, virDomainNetDefPtr net)
+static int prlsdkDelNet(parallelsConnPtr privconn, virDomainNetDefPtr net)
 {
+    int ret = -1;
     PRL_RESULT pret;
     PRL_HANDLE vnet = PRL_INVALID_HANDLE;
     PRL_HANDLE job = PRL_INVALID_HANDLE;
 
     if (net->type != VIR_DOMAIN_NET_TYPE_BRIDGE)
-        return;
+        return 0;
 
     pret = PrlVirtNet_Create(&vnet);
     prlsdkCheckRetGoto(pret, cleanup);
@@ -2900,12 +2907,142 @@ static void prlsdkDelNet(parallelsConnPtr privconn, virDomainNetDefPtr net)
     pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name);
     prlsdkCheckRetGoto(pret, cleanup);
 
-    PrlSrv_DeleteVirtualNetwork(privconn->server, vnet, 0);
+    job = PrlSrv_DeleteVirtualNetwork(privconn->server, vnet, 0);
     if (PRL_FAILED(pret = waitJob(job)))
         goto cleanup;
 
+    ret = 0;
+
  cleanup:
     PrlHandle_Free(vnet);
+    return ret;
+}
+
+int prlsdkAttachNet(virDomainObjPtr dom, parallelsConnPtr privconn, virDomainNetDefPtr net)
+{
+    int ret = -1;
+    parallelsDomObjPtr privdom = dom->privateData;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    if (!IS_CT(dom->def)) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("network device cannot be attached"));
+        goto cleanup;
+    }
+
+    job = PrlVm_BeginEdit(privdom->sdkdom);
+    if (PRL_FAILED(waitJob(job)))
+        goto cleanup;
+
+    ret = prlsdkAddNet(privdom->sdkdom, privconn, net, IS_CT(dom->def));
+    if (ret == 0) {
+        job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
+        if (PRL_FAILED(waitJob(job))) {
+            ret = -1;
+            goto cleanup;
+        }
+    }
+
+ cleanup:
+    return ret;
+}
+
+static int
+prlsdkGetNetIndex(PRL_HANDLE sdkdom, virDomainNetDefPtr net)
+{
+    int idx = -1;
+    PRL_RESULT pret;
+    PRL_UINT32 netCount;
+    PRL_UINT32 i;
+    PRL_HANDLE adapter = PRL_INVALID_HANDLE;
+    PRL_UINT32 len;
+    char adapterMac[PRL_MAC_STRING_BUFNAME];
+    char netMac[PRL_MAC_STRING_BUFNAME];
+
+    prlsdkFormatMac(&net->mac, netMac);
+    pret = PrlVmCfg_GetNetAdaptersCount(sdkdom, &netCount);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    for (i = 0; i < netCount; ++i) {
+
+        pret = PrlVmCfg_GetNetAdapter(sdkdom, i, &adapter);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        len = sizeof(adapterMac);
+        memset(adapterMac, 0, sizeof(adapterMac));
+        pret = PrlVmDevNet_GetMacAddress(adapter, adapterMac, &len);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        if (memcmp(adapterMac, netMac, PRL_MAC_STRING_BUFNAME)) {
+
+            PrlHandle_Free(adapter);
+            adapter = PRL_INVALID_HANDLE;
+            continue;
+        }
+
+        idx = i;
+        break;
+    }
+
+ cleanup:
+    PrlHandle_Free(adapter);
+    return idx;
+}
+
+static int prlsdkDelNetAdapter(PRL_HANDLE sdkdom, int idx)
+{
+    int ret = -1;
+    PRL_RESULT pret;
+    PRL_HANDLE sdknet = PRL_INVALID_HANDLE;
+
+    pret = PrlVmCfg_GetNetAdapter(sdkdom, idx, &sdknet);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_Remove(sdknet);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = 0;
+
+ cleanup:
+    PrlHandle_Free(sdknet);
+    return ret;
+}
+
+int prlsdkDetachNet(virDomainObjPtr dom, parallelsConnPtr privconn, virDomainNetDefPtr net)
+{
+    int ret = -1, idx = -1;
+    parallelsDomObjPtr privdom = dom->privateData;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    if (!IS_CT(dom->def)) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                       _("network device cannot be detached"));
+        goto cleanup;
+    }
+
+    idx = prlsdkGetNetIndex(privdom->sdkdom, net);
+    if (idx < 0)
+        goto cleanup;
+
+    job = PrlVm_BeginEdit(privdom->sdkdom);
+    if (PRL_FAILED(waitJob(job)))
+        goto cleanup;
+
+    ret = prlsdkDelNet(privconn, net);
+    if (ret != 0)
+        goto cleanup;
+
+    ret = prlsdkDelNetAdapter(privdom->sdkdom, idx);
+    if (ret == 0) {
+        job = PrlVm_CommitEx(privdom->sdkdom, PVCF_DETACH_HDD_BUNDLE);
+        if (PRL_FAILED(waitJob(job))) {
+            ret = -1;
+            goto cleanup;
+        }
+    }
+
+ cleanup:
+    return ret;
 }
 
 static int prlsdkDelDisk(PRL_HANDLE sdkdom, int idx)
@@ -3150,6 +3287,7 @@ prlsdkGetDiskIndex(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk)
         pret = PrlVmCfg_GetHardDisk(sdkdom, i, &hdd);
         prlsdkCheckRetGoto(pret, cleanup);
 
+        buflen = 0;
         pret = PrlVmDev_GetFriendlyName(hdd, 0, &buflen);
         prlsdkCheckRetGoto(pret, cleanup);
 
diff --git a/src/parallels/parallels_sdk.h b/src/parallels/parallels_sdk.h
index afa6745..6708fd4 100644
--- a/src/parallels/parallels_sdk.h
+++ b/src/parallels/parallels_sdk.h
@@ -66,3 +66,7 @@ int
 prlsdkDetachVolume(virDomainObjPtr dom, virDomainDiskDefPtr disk);
 int
 prlsdkGetBlockStats(virDomainObjPtr dom, virDomainDiskDefPtr disk, virDomainBlockStatsPtr stats);
+int
+prlsdkAttachNet(virDomainObjPtr dom, parallelsConnPtr privconn, virDomainNetDefPtr net);
+int
+prlsdkDetachNet(virDomainObjPtr dom, parallelsConnPtr privconn, virDomainNetDefPtr net);
-- 
1.7.1




More information about the libvir-list mailing list