|
65 | 65 | import com.cloud.exception.ConcurrentOperationException; |
66 | 66 | import com.cloud.exception.ResourceAllocationException; |
67 | 67 | import com.cloud.host.Host; |
| 68 | +import com.cloud.storage.DataStoreRole; |
68 | 69 | import com.cloud.storage.StoragePool; |
69 | 70 | import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; |
70 | 71 | import com.cloud.storage.Volume; |
@@ -635,13 +636,73 @@ protected Void copyVolumeFromImageToPrimaryCallback( |
635 | 636 | return null; |
636 | 637 | } |
637 | 638 |
|
| 639 | + |
| 640 | + protected AsyncCallFuture<VolumeApiResult> copyVolumeFromPrimaryToImage(VolumeInfo srcVolume, DataStore destStore) { |
| 641 | + AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>(); |
| 642 | + VolumeApiResult res = new VolumeApiResult(srcVolume); |
| 643 | + VolumeInfo destVolume = null; |
| 644 | + try { |
| 645 | + destVolume = (VolumeInfo)destStore.create(srcVolume); |
| 646 | + destVolume.processEvent(Event.CreateOnlyRequested); |
| 647 | + srcVolume.processEvent(Event.CopyingRequested); // this is just used for locking that src volume record in DB to avoid using lock |
| 648 | + |
| 649 | + CopyVolumeContext<VolumeApiResult> context = new CopyVolumeContext<VolumeApiResult>(null, future, srcVolume, |
| 650 | + destVolume, |
| 651 | + destStore); |
| 652 | + AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); |
| 653 | + caller.setCallback(caller.getTarget().copyVolumeFromPrimaryToImageCallback(null, null)) |
| 654 | + .setContext(context); |
| 655 | + |
| 656 | + motionSrv.copyAsync(srcVolume, destVolume, caller); |
| 657 | + return future; |
| 658 | + } catch (Exception e) { |
| 659 | + s_logger.error("failed to copy volume to image store", e); |
| 660 | + if (destVolume != null) { |
| 661 | + destVolume.processEvent(Event.OperationFailed); |
| 662 | + } |
| 663 | + srcVolume.processEvent(Event.OperationFailed); // unlock source volume record |
| 664 | + res.setResult(e.toString()); |
| 665 | + future.complete(res); |
| 666 | + return future; |
| 667 | + } |
| 668 | + } |
| 669 | + |
| 670 | + protected Void copyVolumeFromPrimaryToImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CopyVolumeContext<VolumeApiResult> context) { |
| 671 | + VolumeInfo srcVolume = context.srcVolume; |
| 672 | + VolumeInfo destVolume = context.destVolume; |
| 673 | + CopyCommandResult result = callback.getResult(); |
| 674 | + AsyncCallFuture<VolumeApiResult> future = context.future; |
| 675 | + VolumeApiResult res = new VolumeApiResult(destVolume); |
| 676 | + try { |
| 677 | + if (res.isFailed()) { |
| 678 | + destVolume.processEvent(Event.OperationFailed); |
| 679 | + srcVolume.processEvent(Event.OperationFailed); |
| 680 | + res.setResult(result.getResult()); |
| 681 | + future.complete(res); |
| 682 | + }else{ |
| 683 | + srcVolume.processEvent(Event.OperationSuccessed); |
| 684 | + destVolume.processEvent(Event.OperationSuccessed, result.getAnswer()); |
| 685 | + future.complete(res); |
| 686 | + } |
| 687 | + } catch (Exception e) { |
| 688 | + res.setResult(e.toString()); |
| 689 | + future.complete(res); |
| 690 | + } |
| 691 | + return null; |
| 692 | + } |
| 693 | + |
| 694 | + |
638 | 695 | @Override |
639 | 696 | public AsyncCallFuture<VolumeApiResult> copyVolume(VolumeInfo srcVolume, DataStore destStore) { |
640 | 697 |
|
641 | 698 | if (srcVolume.getState() == Volume.State.Uploaded) { |
642 | 699 | return copyVolumeFromImageToPrimary(srcVolume, destStore); |
643 | 700 | } |
644 | 701 |
|
| 702 | + if (destStore.getRole() == DataStoreRole.Image) { |
| 703 | + return copyVolumeFromPrimaryToImage(srcVolume, destStore); |
| 704 | + } |
| 705 | + |
645 | 706 | AsyncCallFuture<VolumeApiResult> future = new AsyncCallFuture<VolumeApiResult>(); |
646 | 707 | VolumeApiResult res = new VolumeApiResult(srcVolume); |
647 | 708 | try { |
@@ -1056,7 +1117,7 @@ public void handleVolumeSync(DataStore store) { |
1056 | 1117 | * for (Long uniqueName : volumeInfos.keySet()) { TemplateProp vInfo = |
1057 | 1118 | * volumeInfos.get(uniqueName); |
1058 | 1119 | * expungeVolumeAsync(volFactory.getVolume(vInfo.getId(), store)); |
1059 | | - * |
| 1120 | + * |
1060 | 1121 | * String description = "Deleted volume " + vInfo.getTemplateName() + |
1061 | 1122 | * " on image store " + storeId; s_logger.info(description); } |
1062 | 1123 | */ |
|
0 commit comments