|
23 | 23 | import java.util.List; |
24 | 24 | import java.util.Map; |
25 | 25 | import java.util.Optional; |
| 26 | +import java.util.UUID; |
26 | 27 |
|
27 | 28 | import javax.annotation.Nonnull; |
28 | 29 |
|
29 | 30 | import com.cloud.storage.Storage; |
30 | 31 | import com.cloud.utils.exception.CloudRuntimeException; |
| 32 | +import com.cloud.utils.script.Script; |
| 33 | + |
31 | 34 | import org.apache.cloudstack.storage.datastore.util.LinstorUtil; |
32 | 35 | import org.apache.cloudstack.utils.qemu.QemuImg; |
33 | 36 | import org.apache.cloudstack.utils.qemu.QemuImgException; |
|
55 | 58 | import com.linbit.linstor.api.model.Volume; |
56 | 59 | import com.linbit.linstor.api.model.VolumeDefinition; |
57 | 60 |
|
| 61 | +import java.io.File; |
| 62 | + |
58 | 63 | @StorageAdaptorInfo(storagePoolType=Storage.StoragePoolType.Linstor) |
59 | 64 | public class LinstorStorageAdaptor implements StorageAdaptor { |
60 | 65 | private static final Logger s_logger = Logger.getLogger(LinstorStorageAdaptor.class); |
@@ -562,19 +567,14 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMSt |
562 | 567 | name, QemuImg.PhysicalDiskFormat.RAW, provisioningType, disk.getVirtualSize(), null); |
563 | 568 |
|
564 | 569 | final DevelopersApi api = getLinstorAPI(destPools); |
565 | | - final String rscName = LinstorUtil.RSC_PREFIX + name; |
566 | | - try { |
567 | | - LinstorUtil.applyAuxProps(api, rscName, disk.getDispName(), disk.getVmName()); |
568 | | - } catch (ApiException apiExc) { |
569 | | - s_logger.error(String.format("Error setting aux properties for %s", rscName)); |
570 | | - logLinstorAnswers(apiExc.getApiCallRcList()); |
571 | | - } |
| 570 | + applyAuxProps(api, name, disk.getDispName(), disk.getVmName()); |
572 | 571 |
|
573 | 572 | s_logger.debug(String.format("Linstor.copyPhysicalDisk: dstPath: %s", dstDisk.getPath())); |
574 | 573 | final QemuImgFile destFile = new QemuImgFile(dstDisk.getPath()); |
575 | 574 | destFile.setFormat(dstDisk.getFormat()); |
576 | 575 | destFile.setSize(disk.getVirtualSize()); |
577 | 576 |
|
| 577 | + final String rscName = getLinstorRscName(name); |
578 | 578 | boolean zeroedDevice = resourceSupportZeroBlocks(destPools, rscName); |
579 | 579 |
|
580 | 580 | try { |
@@ -619,13 +619,57 @@ public KVMPhysicalDisk createDiskFromTemplateBacking( |
619 | 619 | return null; |
620 | 620 | } |
621 | 621 |
|
| 622 | + private void fileExistsOrThrow(String templateFilePath) { |
| 623 | + File sourceFile = new File(templateFilePath); |
| 624 | + if (!sourceFile.exists()) { |
| 625 | + throw new CloudRuntimeException("Direct download template file " + sourceFile + |
| 626 | + " does not exist on this host"); |
| 627 | + } |
| 628 | + } |
| 629 | + |
| 630 | + private String getFinalDirectDownloadPath(String templateFilePath, KVMStoragePool destPool) { |
| 631 | + String finalSourcePath = templateFilePath; |
| 632 | + if (LibvirtStorageAdaptor.isTemplateExtractable(templateFilePath)) { |
| 633 | + finalSourcePath = templateFilePath.substring(0, templateFilePath.lastIndexOf('.')); |
| 634 | + LibvirtStorageAdaptor.extractDownloadedTemplate(templateFilePath, destPool, finalSourcePath); |
| 635 | + } |
| 636 | + return finalSourcePath; |
| 637 | + } |
| 638 | + |
| 639 | + private void applyAuxProps(DevelopersApi api, String csPath, String csName, String csVMName) { |
| 640 | + final String rscName = getLinstorRscName(csPath); |
| 641 | + try { |
| 642 | + LinstorUtil.applyAuxProps(api, rscName, csName, csVMName); |
| 643 | + } catch (ApiException apiExc) { |
| 644 | + s_logger.error(String.format("Error setting aux properties for %s", rscName)); |
| 645 | + logLinstorAnswers(apiExc.getApiCallRcList()); |
| 646 | + } |
| 647 | + } |
| 648 | + |
622 | 649 | @Override |
623 | 650 | public KVMPhysicalDisk createTemplateFromDirectDownloadFile(String templateFilePath, String destTemplatePath, |
624 | 651 | KVMStoragePool destPool, Storage.ImageFormat format, |
625 | 652 | int timeout) |
626 | 653 | { |
627 | | - s_logger.debug("Linstor: createTemplateFromDirectDownloadFile"); |
628 | | - return null; |
| 654 | + s_logger.debug(String.format("Linstor: createTemplateFromDirectDownloadFile: %s/%s", templateFilePath, format)); |
| 655 | + fileExistsOrThrow(templateFilePath); |
| 656 | + String name = UUID.randomUUID().toString(); |
| 657 | + |
| 658 | + String finalSourcePath = getFinalDirectDownloadPath(templateFilePath, destPool); |
| 659 | + |
| 660 | + File finalSourceFile = new File(finalSourcePath); |
| 661 | + final KVMPhysicalDisk dstDisk = destPool.createPhysicalDisk( |
| 662 | + name, QemuImg.PhysicalDiskFormat.RAW, Storage.ProvisioningType.THIN, finalSourceFile.length(), null); |
| 663 | + |
| 664 | + final DevelopersApi api = getLinstorAPI(destPool); |
| 665 | + applyAuxProps(api, name, finalSourceFile.getName(), null); |
| 666 | + |
| 667 | + Script.runSimpleBashScript( |
| 668 | + String.format("dd if=\"%s\" of=\"%s\" bs=64k conv=nocreat,sparse oflag=direct", |
| 669 | + finalSourcePath, dstDisk.getPath())); |
| 670 | + |
| 671 | + Script.runSimpleBashScript("rm " + finalSourcePath); |
| 672 | + return dstDisk; |
629 | 673 | } |
630 | 674 |
|
631 | 675 | public long getCapacity(LinstorStoragePool pool) { |
|
0 commit comments