]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
parallels: add support of disks creation
authorDmitry Guryanov <dguryanov@parallels.com>
Tue, 4 Dec 2012 13:43:11 +0000 (17:43 +0400)
committerDaniel Veillard <veillard@redhat.com>
Tue, 11 Dec 2012 08:26:32 +0000 (16:26 +0800)
Implement creation of new disks - if a new disk found
in configuration, find a volume by disk path and
actually create a disk image by issuing prlctl command.
If it's successfully finished - remove the file with volume
definition.

Signed-off-by: Dmitry Guryanov <dguryanov@parallels.com>
src/parallels/parallels_driver.c

index 44af70ffac39c0eb26e6ee7de5de827cdf8106e5..d7e83998813f6c5178850a645a2abd9756e100cd 100644 (file)
@@ -1499,22 +1499,94 @@ parallelsApplyVideoParams(parallelsDomObjPtr pdom,
     return 0;
 }
 
+static int parallelsAddHddByVolume(parallelsDomObjPtr pdom,
+                                   virDomainDiskDefPtr disk,
+                                   virStoragePoolObjPtr pool,
+                                   virStorageVolDefPtr voldef)
+{
+    int ret = -1;
+    const char *strbus;
+
+    virCommandPtr cmd = virCommandNewArgList(PRLCTL, "set", pdom->uuid,
+                                             "--device-add", "hdd", NULL);
+    virCommandAddArgFormat(cmd, "--size=%lluM", voldef->capacity >> 20);
+
+    if (!(strbus = parallelsGetDiskBusName(disk->bus))) {
+        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
+                       _("Invalid disk bus: %d"), disk->bus);
+        goto cleanup;
+    }
+
+    virCommandAddArgFormat(cmd, "--iface=%s", strbus);
+
+    if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
+        virCommandAddArgFormat(cmd, "--position=%d",
+                               disk->info.addr.drive.target);
+
+    if (virCommandRun(cmd, NULL))
+        goto cleanup;
+
+    if (parallelsStorageVolumeDefRemove(pool, voldef))
+        goto cleanup;
+
+    ret = 0;
+cleanup:
+    virCommandFree(cmd);
+    return ret;
+}
+
+static int parallelsAddHdd(virConnectPtr conn,
+                           parallelsDomObjPtr pdom,
+                           virDomainDiskDefPtr disk)
+{
+    parallelsConnPtr privconn = conn->privateData;
+    virStorageVolDefPtr voldef = NULL;
+    virStoragePoolObjPtr pool = NULL;
+    virStorageVolPtr vol = NULL;
+    int ret = -1;
+
+    if (!(vol = parallelsStorageVolumeLookupByPathLocked(conn, disk->src))) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("Can't find volume with path '%s'"), disk->src);
+        return -1;
+    }
+
+    pool = virStoragePoolObjFindByName(&privconn->pools, vol->pool);
+    if (!pool) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("Can't find storage pool with name '%s'"),
+                       vol->pool);
+        goto cleanup;
+    }
+
+    voldef = virStorageVolDefFindByPath(pool, disk->src);
+    if (!voldef) {
+        virReportError(VIR_ERR_INVALID_ARG,
+                       _("Can't find storage volume definition for path '%s'"),
+                       disk->src);
+        goto cleanup;
+    }
+
+    ret = parallelsAddHddByVolume(pdom, disk, pool, voldef);
+
+cleanup:
+    if (pool)
+        virStoragePoolObjUnlock(pool);
+    virObjectUnref(vol);
+    return ret;
+}
+
 static int
-parallelsApplyDisksParams(parallelsDomObjPtr pdom,
+parallelsApplyDisksParams(virConnectPtr conn, parallelsDomObjPtr pdom,
                           virDomainDiskDefPtr *olddisks, int nold,
                           virDomainDiskDefPtr *newdisks, int nnew)
 {
-    /* TODO: allow creating and removing disks */
-    if (nold != nnew) {
-        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
-                       _("Adding and removing disks is not supported"));
-        return -1;
-    }
+    int i, j;
 
-    for (int i = 0; i < nold; i++) {
+    for (i = 0; i < nold; i++) {
         virDomainDiskDefPtr newdisk = NULL;
         virDomainDiskDefPtr olddisk = olddisks[i];
-        for (int j = 0; j < nnew; j++) {
+        for (j = 0; j < nnew; j++) {
             if (STREQ_NULLABLE(newdisks[j]->dst, olddisk->dst)) {
                 newdisk = newdisks[j];
                 break;
@@ -1544,7 +1616,7 @@ parallelsApplyDisksParams(parallelsDomObjPtr pdom,
 
             if (!(strbus = parallelsGetDiskBusName(newdisk->bus))) {
                 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
-                               _("Unsupported disk bus: %d", newdisk->bus));
+                               _("Unsupported disk bus: %d"), newdisk->bus);
                 return -1;
             }
 
@@ -1557,11 +1629,24 @@ parallelsApplyDisksParams(parallelsDomObjPtr pdom,
         }
     }
 
+    for (i = 0; i < nnew; i++) {
+        virDomainDiskDefPtr newdisk = newdisks[i];
+        bool found = false;
+        for (j = 0; j < nold; j++)
+            if (STREQ_NULLABLE(olddisks[j]->dst, newdisk->dst))
+                found = true;
+        if (found)
+            continue;
+
+        if (parallelsAddHdd(conn, pdom, newdisk))
+            return -1;
+    }
+
     return 0;
 }
 
 static int
-parallelsApplyChanges(virDomainObjPtr dom, virDomainDefPtr new)
+parallelsApplyChanges(virConnectPtr conn, virDomainObjPtr dom, virDomainDefPtr new)
 {
     char buf[32];
 
@@ -1794,7 +1879,7 @@ parallelsApplyChanges(virDomainObjPtr dom, virDomainDefPtr new)
     if (parallelsApplyVideoParams(pdom, old->videos, old->nvideos,
                                    new->videos, new->nvideos) < 0)
         return -1;
-    if (parallelsApplyDisksParams(pdom, old->disks, old->ndisks,
+    if (parallelsApplyDisksParams(conn, pdom, old->disks, old->ndisks,
                                   new->disks, new->ndisks) < 0)
         return -1;
 
@@ -1928,7 +2013,7 @@ parallelsDomainDefineXML(virConnectPtr conn, const char *xml)
 
     if (dupVM == 1) {
         olddom = virDomainFindByUUID(&privconn->domains, def->uuid);
-        if (parallelsApplyChanges(olddom, def) < 0) {
+        if (parallelsApplyChanges(conn, olddom, def) < 0) {
             virDomainObjUnlock(olddom);
             goto cleanup;
         }