8585import com .ceph .rbd .Rbd ;
8686import com .ceph .rbd .RbdException ;
8787import com .ceph .rbd .RbdImage ;
88+ import com .ceph .rbd .jna .RbdSnapInfo ;
8889import com .cloud .agent .api .Answer ;
8990import com .cloud .agent .api .storage .PrimaryStorageDownloadAnswer ;
9091import com .cloud .agent .api .to .DataObjectType ;
@@ -1594,39 +1595,24 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
15941595 final DataStoreTO imageStore = srcData .getDataStore ();
15951596 final VolumeObjectTO volume = snapshot .getVolume ();
15961597
1597- if (!(imageStore instanceof NfsTO )) {
1598+ if (!(imageStore instanceof NfsTO || imageStore instanceof PrimaryDataStoreTO )) {
15981599 return new CopyCmdAnswer ("unsupported protocol" );
15991600 }
16001601
1601- final NfsTO nfsImageStore = (NfsTO )imageStore ;
1602-
16031602 final String snapshotFullPath = snapshot .getPath ();
16041603 final int index = snapshotFullPath .lastIndexOf ("/" );
16051604 final String snapshotPath = snapshotFullPath .substring (0 , index );
16061605 final String snapshotName = snapshotFullPath .substring (index + 1 );
1607- final KVMStoragePool secondaryPool = storagePoolMgr .getStoragePoolByURI (nfsImageStore .getUrl () + File .separator + snapshotPath );
1608- final KVMPhysicalDisk snapshotDisk = secondaryPool .getPhysicalDisk (snapshotName );
1609-
1610- if (volume .getFormat () == ImageFormat .RAW ) {
1611- snapshotDisk .setFormat (PhysicalDiskFormat .RAW );
1612- } else if (volume .getFormat () == ImageFormat .QCOW2 ) {
1613- snapshotDisk .setFormat (PhysicalDiskFormat .QCOW2 );
1606+ KVMPhysicalDisk disk = null ;
1607+ if (imageStore instanceof NfsTO ) {
1608+ disk = createVolumeFromSnapshotOnNFS (cmd , pool , imageStore , volume , snapshotPath , snapshotName );
1609+ } else {
1610+ disk = createVolumeFromRBDSnapshot (cmd , destData , pool , imageStore , volume , snapshotName , disk );
16141611 }
16151612
1616- final String primaryUuid = pool .getUuid ();
1617- final KVMStoragePool primaryPool = storagePoolMgr .getStoragePool (pool .getPoolType (), primaryUuid );
1618- final String volUuid = UUID .randomUUID ().toString ();
1619-
1620- Map <String , String > details = cmd .getOptions2 ();
1621-
1622- String path = details != null ? details .get (DiskTO .IQN ) : null ;
1623-
1624- storagePoolMgr .connectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path , details );
1625-
1626- KVMPhysicalDisk disk = storagePoolMgr .copyPhysicalDisk (snapshotDisk , path != null ? path : volUuid , primaryPool , cmd .getWaitInMillSeconds ());
1627-
1628- storagePoolMgr .disconnectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path );
1629-
1613+ if (disk == null ) {
1614+ return new CopyCmdAnswer ("Could not create volume from snapshot" );
1615+ }
16301616 final VolumeObjectTO newVol = new VolumeObjectTO ();
16311617 newVol .setPath (disk .getName ());
16321618 newVol .setSize (disk .getVirtualSize ());
@@ -1639,6 +1625,126 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
16391625 }
16401626 }
16411627
1628+ private KVMPhysicalDisk createVolumeFromRBDSnapshot (CopyCommand cmd , DataTO destData ,
1629+ PrimaryDataStoreTO pool , DataStoreTO imageStore , VolumeObjectTO volume , String snapshotName , KVMPhysicalDisk disk ) {
1630+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO ) imageStore ;
1631+ KVMStoragePool srcPool = storagePoolMgr .getStoragePool (primaryStore .getPoolType (), primaryStore .getUuid ());
1632+ KVMPhysicalDisk snapshotDisk = srcPool .getPhysicalDisk (volume .getPath ());
1633+ KVMStoragePool destPool = storagePoolMgr .getStoragePool (pool .getPoolType (), pool .getUuid ());
1634+ VolumeObjectTO newVol = (VolumeObjectTO ) destData ;
1635+
1636+ if (StoragePoolType .RBD .equals (primaryStore .getPoolType ())) {
1637+ s_logger .debug (String .format ("Attempting to create volume from RBD snapshot %s" , snapshotName ));
1638+ if (StoragePoolType .RBD .equals (pool .getPoolType ())) {
1639+ disk = createRBDvolumeFromRBDSnapshot (snapshotDisk , snapshotName , newVol .getUuid (),
1640+ PhysicalDiskFormat .RAW , newVol .getSize (), destPool , cmd .getWaitInMillSeconds ());
1641+ s_logger .debug (String .format ("Created RBD volume %s from snapshot %s" , disk , snapshotDisk ));
1642+ } else {
1643+ Map <String , String > details = cmd .getOptions2 ();
1644+
1645+ String path = details != null ? details .get (DiskTO .IQN ) : null ;
1646+
1647+ storagePoolMgr .connectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path , details );
1648+
1649+ snapshotDisk .setPath (snapshotDisk .getPath () + "@" + snapshotName );
1650+ disk = storagePoolMgr .copyPhysicalDisk (snapshotDisk , path != null ? path : newVol .getUuid (),
1651+ destPool , cmd .getWaitInMillSeconds ());
1652+
1653+ storagePoolMgr .disconnectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path );
1654+ s_logger .debug (String .format ("Created RBD volume %s from snapshot %s" , disk , snapshotDisk ));
1655+
1656+ }
1657+ }
1658+ return disk ;
1659+ }
1660+
1661+ private KVMPhysicalDisk createVolumeFromSnapshotOnNFS (CopyCommand cmd , PrimaryDataStoreTO pool ,
1662+ DataStoreTO imageStore , VolumeObjectTO volume , String snapshotPath , String snapshotName ) {
1663+ NfsTO nfsImageStore = (NfsTO )imageStore ;
1664+ KVMStoragePool secondaryPool = storagePoolMgr .getStoragePoolByURI (nfsImageStore .getUrl () + File .separator + snapshotPath );
1665+ KVMPhysicalDisk snapshotDisk = secondaryPool .getPhysicalDisk (snapshotName );
1666+ if (volume .getFormat () == ImageFormat .RAW ) {
1667+ snapshotDisk .setFormat (PhysicalDiskFormat .RAW );
1668+ } else if (volume .getFormat () == ImageFormat .QCOW2 ) {
1669+ snapshotDisk .setFormat (PhysicalDiskFormat .QCOW2 );
1670+ }
1671+
1672+ final String primaryUuid = pool .getUuid ();
1673+ final KVMStoragePool primaryPool = storagePoolMgr .getStoragePool (pool .getPoolType (), primaryUuid );
1674+ final String volUuid = UUID .randomUUID ().toString ();
1675+
1676+ Map <String , String > details = cmd .getOptions2 ();
1677+
1678+ String path = details != null ? details .get (DiskTO .IQN ) : null ;
1679+
1680+ storagePoolMgr .connectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path , details );
1681+
1682+ KVMPhysicalDisk disk = storagePoolMgr .copyPhysicalDisk (snapshotDisk , path != null ? path : volUuid , primaryPool , cmd .getWaitInMillSeconds ());
1683+
1684+ storagePoolMgr .disconnectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path );
1685+ return disk ;
1686+ }
1687+
1688+ private KVMPhysicalDisk createRBDvolumeFromRBDSnapshot (KVMPhysicalDisk volume , String snapshotName , String name ,
1689+ PhysicalDiskFormat format , long size , KVMStoragePool destPool , int timeout ) {
1690+
1691+ KVMStoragePool srcPool = volume .getPool ();
1692+ KVMPhysicalDisk disk = null ;
1693+ String newUuid = name ;
1694+
1695+ disk = new KVMPhysicalDisk (destPool .getSourceDir () + "/" + newUuid , newUuid , destPool );
1696+ disk .setFormat (format );
1697+ disk .setSize (size > volume .getVirtualSize () ? size : volume .getVirtualSize ());
1698+ disk .setVirtualSize (size > volume .getVirtualSize () ? size : disk .getSize ());
1699+
1700+ try {
1701+
1702+ Rados r = new Rados (srcPool .getAuthUserName ());
1703+ r .confSet ("mon_host" , srcPool .getSourceHost () + ":" + srcPool .getSourcePort ());
1704+ r .confSet ("key" , srcPool .getAuthSecret ());
1705+ r .confSet ("client_mount_timeout" , "30" );
1706+ r .connect ();
1707+
1708+ IoCTX io = r .ioCtxCreate (srcPool .getSourceDir ());
1709+ Rbd rbd = new Rbd (io );
1710+ RbdImage srcImage = rbd .open (volume .getName ());
1711+
1712+ List <RbdSnapInfo > snaps = srcImage .snapList ();
1713+ boolean snapFound = false ;
1714+ for (RbdSnapInfo snap : snaps ) {
1715+ if (snapshotName .equals (snap .name )) {
1716+ snapFound = true ;
1717+ break ;
1718+ }
1719+ }
1720+
1721+ if (!snapFound ) {
1722+ s_logger .debug (String .format ("Could not find snapshot %s on RBD" , snapshotName ));
1723+ return null ;
1724+ }
1725+ srcImage .snapProtect (snapshotName );
1726+
1727+ s_logger .debug (String .format ("Try to clone snapshot %s on RBD" , snapshotName ));
1728+ rbd .clone (volume .getName (), snapshotName , io , disk .getName (), LibvirtStorageAdaptor .RBD_FEATURES , 0 );
1729+ RbdImage diskImage = rbd .open (disk .getName ());
1730+ if (disk .getVirtualSize () > volume .getVirtualSize ()) {
1731+ diskImage .resize (disk .getVirtualSize ());
1732+ }
1733+
1734+ diskImage .flatten ();
1735+ rbd .close (diskImage );
1736+
1737+ srcImage .snapUnprotect (snapshotName );
1738+ rbd .close (srcImage );
1739+ r .ioCtxDestroy (io );
1740+ } catch (RadosException | RbdException e ) {
1741+ s_logger .error (String .format ("Failed due to %s" , e .getMessage ()), e );
1742+ disk = null ;
1743+ }
1744+
1745+ return disk ;
1746+ }
1747+
16421748 @ Override
16431749 public Answer deleteSnapshot (final DeleteCommand cmd ) {
16441750 String snap_full_name = "" ;
0 commit comments