3131import org .apache .cloudstack .engine .subsystem .api .storage .DataStore ;
3232import org .apache .cloudstack .engine .subsystem .api .storage .DataStoreManager ;
3333import org .apache .cloudstack .engine .subsystem .api .storage .HostScope ;
34+ import org .apache .cloudstack .engine .subsystem .api .storage .ObjectInDataStoreStateMachine .Event ;
3435import org .apache .cloudstack .engine .subsystem .api .storage .Scope ;
3536import org .apache .cloudstack .engine .subsystem .api .storage .ZoneScope ;
3637import org .apache .cloudstack .engine .subsystem .api .storage .EndPoint ;
3940import org .apache .cloudstack .engine .subsystem .api .storage .StorageCacheManager ;
4041import org .apache .cloudstack .engine .subsystem .api .storage .VolumeInfo ;
4142import org .apache .cloudstack .framework .async .AsyncCompletionCallback ;
43+ import org .apache .cloudstack .storage .command .CopyCmdAnswer ;
4244import org .apache .cloudstack .storage .command .CopyCommand ;
4345import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
4446import org .apache .cloudstack .storage .datastore .db .SnapshotDataStoreDao ;
4547import org .apache .cloudstack .storage .datastore .db .TemplateDataStoreDao ;
4648import org .apache .cloudstack .storage .datastore .db .VolumeDataStoreDao ;
49+ import org .apache .cloudstack .storage .image .datastore .ImageStoreEntity ;
4750
4851import com .cloud .agent .api .Answer ;
4952import com .cloud .agent .api .to .DataObjectType ;
5760import com .cloud .host .Host ;
5861import com .cloud .host .dao .HostDao ;
5962import com .cloud .storage .DataStoreRole ;
63+ import com .cloud .storage .ImageStore ;
6064import com .cloud .storage .StorageManager ;
6165import com .cloud .storage .StoragePool ;
6266import com .cloud .storage .VolumeManager ;
@@ -136,6 +140,20 @@ protected boolean needCacheStorage(DataObject srcData, DataObject destData) {
136140 }
137141 return true ;
138142 }
143+
144+ private Scope getZoneScope (Scope destScope ) {
145+ ZoneScope zoneScope = null ;
146+ if (destScope instanceof ClusterScope ) {
147+ ClusterScope clusterScope = (ClusterScope ) destScope ;
148+ zoneScope = new ZoneScope (clusterScope .getZoneId ());
149+ } else if (destScope instanceof HostScope ) {
150+ HostScope hostScope = (HostScope ) destScope ;
151+ zoneScope = new ZoneScope (hostScope .getZoneId ());
152+ } else {
153+ zoneScope = (ZoneScope )destScope ;
154+ }
155+ return zoneScope ;
156+ }
139157
140158 protected Answer copyObject (DataObject srcData , DataObject destData ) {
141159 String value = configDao .getValue (Config .PrimaryStorageDownloadWait .toString ());
@@ -145,14 +163,7 @@ protected Answer copyObject(DataObject srcData, DataObject destData) {
145163 try {
146164 if (needCacheStorage (srcData , destData )) {
147165 // need to copy it to image cache store
148- Scope destScope = destData .getDataStore ().getScope ();
149- if (destScope instanceof ClusterScope ) {
150- ClusterScope clusterScope = (ClusterScope ) destScope ;
151- destScope = new ZoneScope (clusterScope .getZoneId ());
152- } else if (destScope instanceof HostScope ) {
153- HostScope hostScope = (HostScope ) destScope ;
154- destScope = new ZoneScope (hostScope .getZoneId ());
155- }
166+ Scope destScope = getZoneScope (destData .getDataStore ().getScope ());
156167 cacheData = cacheMgr .createCacheObject (srcData , destScope );
157168 CopyCommand cmd = new CopyCommand (cacheData .getTO (), destData .getTO (), _primaryStorageDownloadWait );
158169 EndPoint ep = selector .select (cacheData , destData );
@@ -248,11 +259,57 @@ protected Answer copyVolumeBetweenPools(DataObject srcData, DataObject destData)
248259 int _copyvolumewait = NumbersUtil .parseInt (value ,
249260 Integer .parseInt (Config .CopyVolumeWait .getDefaultValue ()));
250261
251- DataObject cacheData = cacheMgr .createCacheObject (srcData , destData .getDataStore ().getScope ());
252- CopyCommand cmd = new CopyCommand (cacheData .getTO (), destData .getTO (), _copyvolumewait );
253- EndPoint ep = selector .select (cacheData , destData );
254- Answer answer = ep .sendMessage (cmd );
255- return answer ;
262+ Scope destScope = getZoneScope (destData .getDataStore ().getScope ());
263+ DataStore cacheStore = cacheMgr .getCacheStorage (destScope );
264+ if (cacheStore == null ) {
265+ //need to find a nfs image store, assuming that can't copy volume directly to s3
266+ ImageStoreEntity imageStore = (ImageStoreEntity )this .dataStoreMgr .getImageStore (destScope .getScopeId ());
267+ if (!imageStore .getProtocol ().equalsIgnoreCase ("nfs" )) {
268+ s_logger .debug ("can't find a nfs image store" );
269+ return null ;
270+ }
271+
272+ DataObject objOnImageStore = imageStore .create (srcData );
273+ objOnImageStore .processEvent (Event .CreateOnlyRequested );
274+
275+ Answer answer = this .copyObject (srcData , objOnImageStore );
276+ if (answer == null || !answer .getResult ()) {
277+ if (answer != null ) {
278+ s_logger .debug ("copy to image store failed: " + answer .getDetails ());
279+ }
280+ objOnImageStore .processEvent (Event .OperationFailed );
281+ imageStore .delete (objOnImageStore );
282+ return answer ;
283+ }
284+
285+ objOnImageStore .processEvent (Event .OperationSuccessed , answer );
286+
287+ objOnImageStore .processEvent (Event .CopyingRequested );
288+
289+ CopyCommand cmd = new CopyCommand (objOnImageStore .getTO (), destData .getTO (), _copyvolumewait );
290+ EndPoint ep = selector .select (objOnImageStore , destData );
291+ answer = ep .sendMessage (cmd );
292+
293+ if (answer == null || !answer .getResult ()) {
294+ if (answer != null ) {
295+ s_logger .debug ("copy to primary store failed: " + answer .getDetails ());
296+ }
297+ objOnImageStore .processEvent (Event .OperationFailed );
298+ imageStore .delete (objOnImageStore );
299+ return answer ;
300+ }
301+
302+ objOnImageStore .processEvent (Event .OperationSuccessed );
303+ imageStore .delete (objOnImageStore );
304+ return answer ;
305+ } else {
306+ DataObject cacheData = cacheMgr .createCacheObject (srcData , destScope );
307+ CopyCommand cmd = new CopyCommand (cacheData .getTO (), destData .getTO (), _copyvolumewait );
308+ EndPoint ep = selector .select (cacheData , destData );
309+ Answer answer = ep .sendMessage (cmd );
310+ return answer ;
311+ }
312+
256313 }
257314
258315 @ Override
@@ -273,7 +330,7 @@ public Void copyAsync(DataObject srcData, DataObject destData,
273330 answer = cloneVolume (srcData , destData );
274331 } else if (destData .getType () == DataObjectType .VOLUME
275332 && srcData .getType () == DataObjectType .VOLUME && srcData .getDataStore ().getRole () == DataStoreRole .Primary && destData .getDataStore ().getRole () == DataStoreRole .Primary ) {
276- answer = copyVolumeBetweenPools (srcData , destData );
333+ answer = copyVolumeBetweenPools (srcData , destData );
277334 } else if (srcData .getType () == DataObjectType .SNAPSHOT &&
278335 destData .getType () == DataObjectType .SNAPSHOT ) {
279336 answer = copySnapshot (srcData , destData );
0 commit comments