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 ;
@@ -1635,39 +1636,24 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
16351636 final DataStoreTO imageStore = srcData .getDataStore ();
16361637 final VolumeObjectTO volume = snapshot .getVolume ();
16371638
1638- if (!(imageStore instanceof NfsTO )) {
1639+ if (!(imageStore instanceof NfsTO || imageStore instanceof PrimaryDataStoreTO )) {
16391640 return new CopyCmdAnswer ("unsupported protocol" );
16401641 }
16411642
1642- final NfsTO nfsImageStore = (NfsTO )imageStore ;
1643-
16441643 final String snapshotFullPath = snapshot .getPath ();
16451644 final int index = snapshotFullPath .lastIndexOf ("/" );
16461645 final String snapshotPath = snapshotFullPath .substring (0 , index );
16471646 final String snapshotName = snapshotFullPath .substring (index + 1 );
1648- final KVMStoragePool secondaryPool = storagePoolMgr .getStoragePoolByURI (nfsImageStore .getUrl () + File .separator + snapshotPath );
1649- final KVMPhysicalDisk snapshotDisk = secondaryPool .getPhysicalDisk (snapshotName );
1650-
1651- if (volume .getFormat () == ImageFormat .RAW ) {
1652- snapshotDisk .setFormat (PhysicalDiskFormat .RAW );
1653- } else if (volume .getFormat () == ImageFormat .QCOW2 ) {
1654- snapshotDisk .setFormat (PhysicalDiskFormat .QCOW2 );
1647+ KVMPhysicalDisk disk = null ;
1648+ if (imageStore instanceof NfsTO ) {
1649+ disk = createVolumeFromSnapshotOnNFS (cmd , pool , imageStore , volume , snapshotPath , snapshotName );
1650+ } else {
1651+ disk = createVolumeFromRBDSnapshot (cmd , destData , pool , imageStore , volume , snapshotName , disk );
16551652 }
16561653
1657- final String primaryUuid = pool .getUuid ();
1658- final KVMStoragePool primaryPool = storagePoolMgr .getStoragePool (pool .getPoolType (), primaryUuid );
1659- final String volUuid = UUID .randomUUID ().toString ();
1660-
1661- Map <String , String > details = cmd .getOptions2 ();
1662-
1663- String path = details != null ? details .get (DiskTO .IQN ) : null ;
1664-
1665- storagePoolMgr .connectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path , details );
1666-
1667- KVMPhysicalDisk disk = storagePoolMgr .copyPhysicalDisk (snapshotDisk , path != null ? path : volUuid , primaryPool , cmd .getWaitInMillSeconds ());
1668-
1669- storagePoolMgr .disconnectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path );
1670-
1654+ if (disk == null ) {
1655+ return new CopyCmdAnswer ("Could not create volume from snapshot" );
1656+ }
16711657 final VolumeObjectTO newVol = new VolumeObjectTO ();
16721658 newVol .setPath (disk .getName ());
16731659 newVol .setSize (disk .getVirtualSize ());
@@ -1680,6 +1666,126 @@ public Answer createVolumeFromSnapshot(final CopyCommand cmd) {
16801666 }
16811667 }
16821668
1669+ private KVMPhysicalDisk createVolumeFromRBDSnapshot (CopyCommand cmd , DataTO destData ,
1670+ PrimaryDataStoreTO pool , DataStoreTO imageStore , VolumeObjectTO volume , String snapshotName , KVMPhysicalDisk disk ) {
1671+ PrimaryDataStoreTO primaryStore = (PrimaryDataStoreTO ) imageStore ;
1672+ KVMStoragePool srcPool = storagePoolMgr .getStoragePool (primaryStore .getPoolType (), primaryStore .getUuid ());
1673+ KVMPhysicalDisk snapshotDisk = srcPool .getPhysicalDisk (volume .getPath ());
1674+ KVMStoragePool destPool = storagePoolMgr .getStoragePool (pool .getPoolType (), pool .getUuid ());
1675+ VolumeObjectTO newVol = (VolumeObjectTO ) destData ;
1676+
1677+ if (StoragePoolType .RBD .equals (primaryStore .getPoolType ())) {
1678+ s_logger .debug (String .format ("Attempting to create volume from RBD snapshot %s" , snapshotName ));
1679+ if (StoragePoolType .RBD .equals (pool .getPoolType ())) {
1680+ disk = createRBDvolumeFromRBDSnapshot (snapshotDisk , snapshotName , newVol .getUuid (),
1681+ PhysicalDiskFormat .RAW , newVol .getSize (), destPool , cmd .getWaitInMillSeconds ());
1682+ s_logger .debug (String .format ("Created RBD volume %s from snapshot %s" , disk , snapshotDisk ));
1683+ } else {
1684+ Map <String , String > details = cmd .getOptions2 ();
1685+
1686+ String path = details != null ? details .get (DiskTO .IQN ) : null ;
1687+
1688+ storagePoolMgr .connectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path , details );
1689+
1690+ snapshotDisk .setPath (snapshotDisk .getPath () + "@" + snapshotName );
1691+ disk = storagePoolMgr .copyPhysicalDisk (snapshotDisk , path != null ? path : newVol .getUuid (),
1692+ destPool , cmd .getWaitInMillSeconds ());
1693+
1694+ storagePoolMgr .disconnectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path );
1695+ s_logger .debug (String .format ("Created RBD volume %s from snapshot %s" , disk , snapshotDisk ));
1696+
1697+ }
1698+ }
1699+ return disk ;
1700+ }
1701+
1702+ private KVMPhysicalDisk createVolumeFromSnapshotOnNFS (CopyCommand cmd , PrimaryDataStoreTO pool ,
1703+ DataStoreTO imageStore , VolumeObjectTO volume , String snapshotPath , String snapshotName ) {
1704+ NfsTO nfsImageStore = (NfsTO )imageStore ;
1705+ KVMStoragePool secondaryPool = storagePoolMgr .getStoragePoolByURI (nfsImageStore .getUrl () + File .separator + snapshotPath );
1706+ KVMPhysicalDisk snapshotDisk = secondaryPool .getPhysicalDisk (snapshotName );
1707+ if (volume .getFormat () == ImageFormat .RAW ) {
1708+ snapshotDisk .setFormat (PhysicalDiskFormat .RAW );
1709+ } else if (volume .getFormat () == ImageFormat .QCOW2 ) {
1710+ snapshotDisk .setFormat (PhysicalDiskFormat .QCOW2 );
1711+ }
1712+
1713+ final String primaryUuid = pool .getUuid ();
1714+ final KVMStoragePool primaryPool = storagePoolMgr .getStoragePool (pool .getPoolType (), primaryUuid );
1715+ final String volUuid = UUID .randomUUID ().toString ();
1716+
1717+ Map <String , String > details = cmd .getOptions2 ();
1718+
1719+ String path = details != null ? details .get (DiskTO .IQN ) : null ;
1720+
1721+ storagePoolMgr .connectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path , details );
1722+
1723+ KVMPhysicalDisk disk = storagePoolMgr .copyPhysicalDisk (snapshotDisk , path != null ? path : volUuid , primaryPool , cmd .getWaitInMillSeconds ());
1724+
1725+ storagePoolMgr .disconnectPhysicalDisk (pool .getPoolType (), pool .getUuid (), path );
1726+ return disk ;
1727+ }
1728+
1729+ private KVMPhysicalDisk createRBDvolumeFromRBDSnapshot (KVMPhysicalDisk volume , String snapshotName , String name ,
1730+ PhysicalDiskFormat format , long size , KVMStoragePool destPool , int timeout ) {
1731+
1732+ KVMStoragePool srcPool = volume .getPool ();
1733+ KVMPhysicalDisk disk = null ;
1734+ String newUuid = name ;
1735+
1736+ disk = new KVMPhysicalDisk (destPool .getSourceDir () + "/" + newUuid , newUuid , destPool );
1737+ disk .setFormat (format );
1738+ disk .setSize (size > volume .getVirtualSize () ? size : volume .getVirtualSize ());
1739+ disk .setVirtualSize (size > volume .getVirtualSize () ? size : disk .getSize ());
1740+
1741+ try {
1742+
1743+ Rados r = new Rados (srcPool .getAuthUserName ());
1744+ r .confSet ("mon_host" , srcPool .getSourceHost () + ":" + srcPool .getSourcePort ());
1745+ r .confSet ("key" , srcPool .getAuthSecret ());
1746+ r .confSet ("client_mount_timeout" , "30" );
1747+ r .connect ();
1748+
1749+ IoCTX io = r .ioCtxCreate (srcPool .getSourceDir ());
1750+ Rbd rbd = new Rbd (io );
1751+ RbdImage srcImage = rbd .open (volume .getName ());
1752+
1753+ List <RbdSnapInfo > snaps = srcImage .snapList ();
1754+ boolean snapFound = false ;
1755+ for (RbdSnapInfo snap : snaps ) {
1756+ if (snapshotName .equals (snap .name )) {
1757+ snapFound = true ;
1758+ break ;
1759+ }
1760+ }
1761+
1762+ if (!snapFound ) {
1763+ s_logger .debug (String .format ("Could not find snapshot %s on RBD" , snapshotName ));
1764+ return null ;
1765+ }
1766+ srcImage .snapProtect (snapshotName );
1767+
1768+ s_logger .debug (String .format ("Try to clone snapshot %s on RBD" , snapshotName ));
1769+ rbd .clone (volume .getName (), snapshotName , io , disk .getName (), LibvirtStorageAdaptor .RBD_FEATURES , 0 );
1770+ RbdImage diskImage = rbd .open (disk .getName ());
1771+ if (disk .getVirtualSize () > volume .getVirtualSize ()) {
1772+ diskImage .resize (disk .getVirtualSize ());
1773+ }
1774+
1775+ diskImage .flatten ();
1776+ rbd .close (diskImage );
1777+
1778+ srcImage .snapUnprotect (snapshotName );
1779+ rbd .close (srcImage );
1780+ r .ioCtxDestroy (io );
1781+ } catch (RadosException | RbdException e ) {
1782+ s_logger .error (String .format ("Failed due to %s" , e .getMessage ()), e );
1783+ disk = null ;
1784+ }
1785+
1786+ return disk ;
1787+ }
1788+
16831789 @ Override
16841790 public Answer deleteSnapshot (final DeleteCommand cmd ) {
16851791 String snap_full_name = "" ;
0 commit comments