1919package org .apache .cloudstack .storage .motion ;
2020
2121import com .cloud .agent .AgentManager ;
22- import com .cloud .agent .api .Answer ;
2322import com .cloud .agent .api .to .DataStoreTO ;
2423import com .cloud .agent .api .to .DataTO ;
2524import com .cloud .agent .api .to .DiskTO ;
3736import com .cloud .server .ManagementService ;
3837import com .cloud .storage .DataStoreRole ;
3938import com .cloud .storage .DiskOfferingVO ;
39+ import com .cloud .storage .Snapshot ;
4040import com .cloud .storage .SnapshotVO ;
4141import com .cloud .storage .Storage .ImageFormat ;
42- import com .cloud .storage .Volume ;
4342import com .cloud .storage .VolumeDetailVO ;
4443import com .cloud .storage .VolumeVO ;
4544import com .cloud .storage .dao .DiskOfferingDao ;
7978import org .apache .cloudstack .framework .config .dao .ConfigurationDao ;
8079import org .apache .cloudstack .storage .command .CopyCmdAnswer ;
8180import org .apache .cloudstack .storage .command .CopyCommand ;
82- import org .apache .cloudstack .storage .command .DeleteCommand ;
83- import org .apache .cloudstack .storage .command .DettachAnswer ;
84- import org .apache .cloudstack .storage .command .DettachCommand ;
8581import org .apache .cloudstack .storage .command .ResignatureAnswer ;
8682import org .apache .cloudstack .storage .command .ResignatureCommand ;
8783import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
8884import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
8985import org .apache .cloudstack .storage .to .PrimaryDataStoreTO ;
90- import org .apache .cloudstack .storage .to .SnapshotObjectTO ;
9186import org .apache .cloudstack .storage .to .VolumeObjectTO ;
9287import org .apache .commons .lang .StringUtils ;
9388import org .apache .log4j .Logger ;
@@ -225,6 +220,7 @@ public void copyAsync(DataObject srcData, DataObject destData, Host destHost, As
225220
226221 if (canHandleDest ) {
227222 handleCreateVolumeFromSnapshotOnSecondaryStorage (snapshotInfo , volumeInfo , callback );
223+
228224 return ;
229225 }
230226
@@ -415,8 +411,14 @@ private void handleCopyDataToSecondaryStorage(SnapshotInfo snapshotInfo, DataObj
415411
416412 copyCmdAnswer = (CopyCmdAnswer )_agentMgr .send (hostVO .getId (), copyCommand );
417413
418- if (needCache ) {
414+ if (!copyCmdAnswer .getResult ()) {
415+ // We were not able to copy. Handle it.
416+ errMsg = copyCmdAnswer .getDetails ();
419417
418+ throw new CloudRuntimeException (errMsg );
419+ }
420+
421+ if (needCache ) {
420422 // If cached storage was needed (in case of object store as secondary
421423 // storage), at this point, the data has been copied from the primary
422424 // to the NFS cache by the hypervisor. We now invoke another copy
@@ -430,34 +432,34 @@ private void handleCopyDataToSecondaryStorage(SnapshotInfo snapshotInfo, DataObj
430432
431433 if (ep == null ) {
432434 errMsg = "No remote endpoint to send command, check if host or ssvm is down?" ;
435+
433436 LOGGER .error (errMsg );
437+
434438 copyCmdAnswer = new CopyCmdAnswer (errMsg );
435439 } else {
436- copyCmdAnswer = (CopyCmdAnswer ) ep .sendMessage (cmd );
440+ copyCmdAnswer = (CopyCmdAnswer )ep .sendMessage (cmd );
437441 }
438442
439443 // clean up snapshot copied to staging
440- performCleanupCacheStorage (destOnStore );
444+ cacheMgr . deleteCacheObject (destOnStore );
441445 }
442446
443-
444447 } catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex ) {
445448 String msg = "Failed to create template from snapshot (Snapshot ID = " + snapshotInfo .getId () + ") : " ;
446449
447450 LOGGER .warn (msg , ex );
448451
449452 throw new CloudRuntimeException (msg + ex .getMessage ());
450-
451453 } finally {
452-
453- // detach and remove access after the volume is created
454- SnapshotObjectTO snapshotObjectTO = (SnapshotObjectTO ) snapshotInfo .getTO ();
455- DiskTO disk = new DiskTO (snapshotObjectTO , null , snapshotInfo .getPath (), Volume .Type .UNKNOWN );
456- detachManagedStoreVolume (snapshotInfo , hostVO , getProperty (snapshotInfo .getId (), DiskTO .IQN ), srcDataStore .getId (), disk );
454+ _volumeService .revokeAccess (snapshotInfo , hostVO , srcDataStore );
457455
458456 if (copyCmdAnswer == null || !copyCmdAnswer .getResult ()) {
459457 if (copyCmdAnswer != null && !StringUtils .isEmpty (copyCmdAnswer .getDetails ())) {
460458 errMsg = copyCmdAnswer .getDetails ();
459+
460+ if (needCache ) {
461+ cacheMgr .deleteCacheObject (destOnStore );
462+ }
461463 }
462464 else {
463465 errMsg = "Unable to create template from snapshot" ;
@@ -497,11 +499,9 @@ private void handleCopyDataToSecondaryStorage(SnapshotInfo snapshotInfo, DataObj
497499 * @param callback for async
498500 */
499501 private void handleCreateVolumeFromSnapshotOnSecondaryStorage (SnapshotInfo snapshotInfo , VolumeInfo volumeInfo , AsyncCompletionCallback <CopyCommandResult > callback ) {
500-
501502 // at this point, the snapshotInfo and volumeInfo should have the same disk offering ID (so either one should be OK to get a DiskOfferingVO instance)
502503 DiskOfferingVO diskOffering = _diskOfferingDao .findByIdIncludingRemoved (volumeInfo .getDiskOfferingId ());
503504 SnapshotVO snapshot = _snapshotDao .findById (snapshotInfo .getId ());
504- DataStore destDataStore = volumeInfo .getDataStore ();
505505
506506 // update the volume's hv_ss_reserve (hypervisor snapshot reserve) from a disk offering (used for managed storage)
507507 _volumeService .updateHypervisorSnapshotReserveForVolume (diskOffering , volumeInfo .getId (), snapshot .getHypervisorType ());
@@ -510,9 +510,9 @@ private void handleCreateVolumeFromSnapshotOnSecondaryStorage(SnapshotInfo snaps
510510 String errMsg = null ;
511511
512512 HostVO hostVO = null ;
513- try {
514513
515- //create a volume on the storage
514+ try {
515+ // create a volume on the storage
516516 AsyncCallFuture <VolumeApiResult > future = _volumeService .createVolumeAsync (volumeInfo , volumeInfo .getDataStore ());
517517 VolumeApiResult result = future .get ();
518518
@@ -529,7 +529,7 @@ private void handleCreateVolumeFromSnapshotOnSecondaryStorage(SnapshotInfo snaps
529529
530530 hostVO = getHost (snapshotInfo .getDataCenterId (), false );
531531
532- //copy the volume from secondary via the hypervisor
532+ // copy the volume from secondary via the hypervisor
533533 copyCmdAnswer = performCopyOfVdi (volumeInfo , snapshotInfo , hostVO );
534534
535535 if (copyCmdAnswer == null || !copyCmdAnswer .getResult ()) {
@@ -543,86 +543,13 @@ private void handleCreateVolumeFromSnapshotOnSecondaryStorage(SnapshotInfo snaps
543543 }
544544 catch (Exception ex ) {
545545 errMsg = ex .getMessage () != null ? ex .getMessage () : "Copy operation failed in 'StorageSystemDataMotionStrategy.handleCreateVolumeFromSnapshotBothOnStorageSystem'" ;
546- } finally {
547-
548-
549- DiskTO disk = new DiskTO (volumeInfo .getTO (), volumeInfo .getDeviceId (), volumeInfo .getPath (),volumeInfo .getVolumeType ());
550- long storagePoolId = volumeInfo .getPoolId ();
551- detachManagedStoreVolume (volumeInfo , hostVO , volumeInfo .get_iScsiName (), storagePoolId , disk );
552546 }
553547
554548 CopyCommandResult result = new CopyCommandResult (null , copyCmdAnswer );
555549
556550 result .setResult (errMsg );
557551
558552 callback .complete (result );
559-
560-
561- }
562-
563- /**
564- * Detaches a managed volume from a host
565- * @param dataObject Volume to be detached
566- * @param hostVO Host where the volume is currently attached
567- * @param storagePoolId Storage where volume resides
568- * @param disk Object which stores disk attributes to send to the agents
569- */
570- private void detachManagedStoreVolume (DataObject dataObject , HostVO hostVO , String iqn , long storagePoolId , DiskTO disk ) {
571-
572- DataStore destDataStore = dataObject .getDataStore ();
573- DettachCommand cmd = new DettachCommand (disk , null );
574- StoragePoolVO storagePool = _storagePoolDao .findById (storagePoolId );
575-
576- cmd .setManaged (true );
577- cmd .setStorageHost (storagePool .getHostAddress ());
578- cmd .setStoragePort (storagePool .getPort ());
579- cmd .set_iScsiName (iqn );
580-
581- try {
582- DettachAnswer dettachAnswer = (DettachAnswer ) _agentMgr .send (hostVO .getId (), cmd );
583-
584- if (!dettachAnswer .getResult ()) {
585- LOGGER .warn ("Error detaching DataObject:" + dettachAnswer .getDetails ());
586- }
587-
588- } catch (Exception e ) {
589- LOGGER .warn ("Error detaching DataObject " + dataObject .getId () + " Error: " + e .getMessage ());
590- }
591-
592-
593- try {
594- _volumeService .revokeAccess (dataObject , hostVO , destDataStore );
595- } catch (Exception e ) {
596- LOGGER .warn ("Error revoking access to DataObject (DataObject ID = " + dataObject .getId () + "): " + e .getMessage (), e );
597- }
598- }
599-
600- private void performCleanupCacheStorage (DataObject destOnStore ) {
601- destOnStore .processEvent (Event .DestroyRequested );
602-
603- DeleteCommand deleteCommand = new DeleteCommand (destOnStore .getTO ());
604- EndPoint ep = selector .select (destOnStore );
605- try {
606- if (ep == null ) {
607- LOGGER .warn ("Unable to cleanup staging NFS because no endpoint was found " +
608- "Object: " + destOnStore .getType () + " ID: " + destOnStore .getId ());
609-
610- destOnStore .processEvent (Event .OperationFailed );
611- } else {
612- Answer deleteAnswer = ep .sendMessage (deleteCommand );
613- if (deleteAnswer != null && deleteAnswer .getResult ()) {
614- LOGGER .warn ("Unable to cleanup staging NFS " + deleteAnswer .getDetails () +
615- "Object: " + destOnStore .getType () + " ID: " + destOnStore .getId ());
616- destOnStore .processEvent (Event .OperationFailed );
617- }
618- }
619-
620- destOnStore .processEvent (Event .OperationSuccessed );
621- } catch (Exception e ) {
622- destOnStore .processEvent (Event .OperationFailed );
623- LOGGER .warn ("Unable to clean up staging cache Exception " + e .getMessage () +
624- "Object: " + destOnStore .getType () + " ID: " + destOnStore .getId ());
625- }
626553 }
627554
628555 /**
@@ -899,7 +826,7 @@ private Map<String, String> getVolumeDetails(VolumeInfo volumeInfo) {
899826 }
900827
901828 private Map <String , String > getSnapshotDetails (SnapshotInfo snapshotInfo ) {
902- Map <String , String > snapshotDetails = new HashMap <String , String >();
829+ Map <String , String > snapshotDetails = new HashMap <>();
903830
904831 long storagePoolId = snapshotInfo .getDataStore ().getId ();
905832 StoragePoolVO storagePoolVO = _storagePoolDao .findById (storagePoolId );
@@ -1066,30 +993,34 @@ protected DataObject cacheSnapshotChain(SnapshotInfo snapshot, Scope scope) {
1066993 * @return result of the copy
1067994 */
1068995 private CopyCmdAnswer performCopyOfVdi (VolumeInfo volumeInfo , SnapshotInfo snapshotInfo , HostVO hostVO ) {
996+ Snapshot .LocationType locationType = snapshotInfo .getLocationType ();
997+
1069998 String value = _configDao .getValue (Config .PrimaryStorageDownloadWait .toString ());
1070999 int primaryStorageDownloadWait = NumbersUtil .parseInt (value , Integer .parseInt (Config .PrimaryStorageDownloadWait .getDefaultValue ()));
10711000
10721001 DataObject srcData = snapshotInfo ;
10731002 CopyCmdAnswer copyCmdAnswer = null ;
10741003 DataObject cacheData = null ;
1004+
10751005 boolean needCacheStorage = needCacheStorage (snapshotInfo , volumeInfo );
10761006
10771007 if (needCacheStorage ) {
10781008 cacheData = cacheSnapshotChain (snapshotInfo , new ZoneScope (volumeInfo .getDataCenterId ()));
10791009 srcData = cacheData ;
1080-
10811010 }
10821011
10831012 CopyCommand copyCommand = new CopyCommand (srcData .getTO (), volumeInfo .getTO (), primaryStorageDownloadWait , VirtualMachineManager .ExecuteInSequence .value ());
10841013
10851014 try {
1015+ if (Snapshot .LocationType .PRIMARY .equals (locationType )) {
1016+ _volumeService .grantAccess (snapshotInfo , hostVO , snapshotInfo .getDataStore ());
10861017
1087- _volumeService .grantAccess (snapshotInfo , hostVO , snapshotInfo .getDataStore ());
1088- _volumeService .grantAccess (volumeInfo , hostVO , volumeInfo .getDataStore ());
1018+ Map <String , String > srcDetails = getSnapshotDetails (snapshotInfo );
10891019
1090- Map <String , String > srcDetails = getSnapshotDetails (snapshotInfo );
1020+ copyCommand .setOptions (srcDetails );
1021+ }
10911022
1092- copyCommand . setOptions ( srcDetails );
1023+ _volumeService . grantAccess ( volumeInfo , hostVO , volumeInfo . getDataStore () );
10931024
10941025 Map <String , String > destDetails = getVolumeDetails (volumeInfo );
10951026
@@ -1105,11 +1036,14 @@ private CopyCmdAnswer performCopyOfVdi(VolumeInfo volumeInfo, SnapshotInfo snaps
11051036 throw new CloudRuntimeException (msg + ex .getMessage ());
11061037 }
11071038 finally {
1108- _volumeService .revokeAccess (snapshotInfo , hostVO , snapshotInfo .getDataStore ());
1039+ if (Snapshot .LocationType .PRIMARY .equals (locationType )) {
1040+ _volumeService .revokeAccess (snapshotInfo , hostVO , snapshotInfo .getDataStore ());
1041+ }
1042+
11091043 _volumeService .revokeAccess (volumeInfo , hostVO , volumeInfo .getDataStore ());
11101044
11111045 if (needCacheStorage && copyCmdAnswer != null && copyCmdAnswer .getResult ()) {
1112- performCleanupCacheStorage (cacheData );
1046+ cacheMgr . deleteCacheObject (cacheData );
11131047 }
11141048 }
11151049
0 commit comments