Skip to content

Commit b30e39b

Browse files
committed
CLOUDSTACK-1392: add create template from snapshot and volume
1 parent 0978df9 commit b30e39b

3 files changed

Lines changed: 97 additions & 10 deletions

File tree

engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121
import javax.inject.Inject;
2222

2323
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
24+
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
2425
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult;
2526
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
2627
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
2728
import org.apache.cloudstack.engine.subsystem.api.storage.ImageService;
2829
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
30+
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
2931
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
3032
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
3133
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
@@ -37,6 +39,7 @@
3739
import org.apache.cloudstack.storage.datastore.DataObjectManager;
3840
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
3941
import org.apache.cloudstack.storage.image.store.TemplateObject;
42+
import org.apache.cloudstack.storage.motion.DataMotionService;
4043
import org.apache.log4j.Logger;
4144
import org.springframework.stereotype.Component;
4245

@@ -49,6 +52,8 @@ public class ImageServiceImpl implements ImageService {
4952
ObjectInDataStoreManager objectInDataStoreMgr;
5053
@Inject
5154
DataObjectManager dataObjectMgr;
55+
@Inject
56+
DataMotionService motionSrv;
5257

5358
class CreateTemplateContext<T> extends AsyncRpcConext<T> {
5459
final TemplateInfo srcTemplate;
@@ -140,17 +145,91 @@ public AsyncCallFuture<CommandResult> deleteTemplateAsync(
140145
return null;
141146
}
142147

148+
private class CopyTemplateContext<T> extends AsyncRpcConext<T> {
149+
final AsyncCallFuture<CommandResult> future;
150+
final DataObject object;
151+
/**
152+
* @param callback
153+
*/
154+
public CopyTemplateContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<CommandResult> future, DataObject object) {
155+
super(callback);
156+
this.future = future;
157+
this.object = object;
158+
}
159+
160+
}
143161
@Override
144162
public AsyncCallFuture<CommandResult> createTemplateFromSnapshotAsync(
145163
SnapshotInfo snapshot, TemplateInfo template, DataStore store) {
146-
// TODO Auto-generated method stub
164+
AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
165+
DataObject templateOnStore = null;
166+
try {
167+
templateOnStore = store.create(template);
168+
templateOnStore.processEvent(Event.CreateOnlyRequested);
169+
170+
CopyTemplateContext<CommandResult> context = new CopyTemplateContext<CommandResult>(null, future, templateOnStore);
171+
AsyncCallbackDispatcher<ImageServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
172+
caller.setCallback(caller.getTarget().copyTemplateAsyncCallback(null, null))
173+
.setContext(context);
174+
this.motionSrv.copyAsync(snapshot, templateOnStore, caller);
175+
} catch (Exception e) {
176+
s_logger.debug("Failed to create template: " + template.getId() + "from snapshot: " + snapshot.getId() + ", due to " + e.toString());
177+
if (templateOnStore != null) {
178+
try {
179+
templateOnStore.processEvent(Event.OperationFailed);
180+
} catch (Exception e1) {
181+
182+
}
183+
}
184+
CommandResult result = new CommandResult();
185+
result.setResult(e.toString());
186+
future.complete(result);
187+
}
188+
return future;
189+
}
190+
191+
protected Void copyTemplateAsyncCallback(AsyncCallbackDispatcher<ImageServiceImpl, CopyCommandResult> callback, CopyTemplateContext<CommandResult> context) {
192+
CopyCommandResult result = callback.getResult();
193+
AsyncCallFuture<CommandResult> future = context.future;
194+
DataObject object = context.object;
195+
CommandResult res = new CommandResult();
196+
if (result.isFailed()) {
197+
res.setResult(result.getResult());
198+
object.processEvent(Event.OperationFailed);
199+
} else {
200+
object.processEvent(Event.OperationSuccessed);
201+
}
202+
future.complete(res);
147203
return null;
148204
}
149205

150206
@Override
151207
public AsyncCallFuture<CommandResult> createTemplateFromVolumeAsync(
152208
VolumeInfo volume, TemplateInfo template, DataStore store) {
153-
// TODO Auto-generated method stub
154-
return null;
209+
AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
210+
DataObject templateOnStore = null;
211+
try {
212+
templateOnStore = store.create(template);
213+
templateOnStore.processEvent(Event.CreateOnlyRequested);
214+
215+
CopyTemplateContext<CommandResult> context = new CopyTemplateContext<CommandResult>(null, future, templateOnStore);
216+
AsyncCallbackDispatcher<ImageServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this);
217+
caller.setCallback(caller.getTarget().copyTemplateAsyncCallback(null, null))
218+
.setContext(context);
219+
this.motionSrv.copyAsync(volume, templateOnStore, caller);
220+
} catch (Exception e) {
221+
s_logger.debug("Failed to create template: " + template.getId() + "from volume: " + volume.getId() + ", due to " + e.toString());
222+
if (templateOnStore != null) {
223+
try {
224+
templateOnStore.processEvent(Event.OperationFailed);
225+
} catch (Exception e1) {
226+
227+
}
228+
}
229+
CommandResult result = new CommandResult();
230+
result.setResult(e.toString());
231+
future.complete(result);
232+
}
233+
return future;
155234
}
156235
}

engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -668,9 +668,7 @@ protected Answer sendCommand(Command cmd, StoragePool pool,
668668
String checkSum = this.templateMgr
669669
.getChecksum(hostId, answer.getPath());
670670

671-
Transaction txn = Transaction.currentTxn();
672671

673-
txn.start();
674672

675673
privateTemplate.setChecksum(checkSum);
676674
templateDao.update(privateTemplate.getId(), privateTemplate);
@@ -685,8 +683,9 @@ protected Answer sendCommand(Command cmd, StoragePool pool,
685683
templateHostVO.setLastUpdated(new Date());
686684
templateHostVO.setSize(answer.getVirtualSize());
687685
templateHostVO.setPhysicalSize(answer.getphysicalSize());
686+
688687
templateHostDao.persist(templateHostVO);
689-
txn.close();
688+
690689
return answer;
691690
}
692691

server/src/com/cloud/template/TemplateManagerImpl.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,8 +1716,17 @@ public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command)
17161716

17171717
try {
17181718
TemplateInfo tmplInfo = this.tmplFactory.getTemplate(templateId);
1719-
snapshot = _snapshotDao.findById(snapshotId);
1720-
ZoneScope scope = new ZoneScope(snapshot.getDataCenterId());
1719+
ZoneScope scope = null;
1720+
Long zoneId = null;
1721+
if (snapshotId != null) {
1722+
snapshot = _snapshotDao.findById(snapshotId);
1723+
zoneId = snapshot.getDataCenterId();
1724+
1725+
} else if (volumeId != null) {
1726+
volume = _volumeDao.findById(volumeId);
1727+
zoneId = volume.getDataCenterId();
1728+
}
1729+
scope = new ZoneScope(zoneId);
17211730
List<DataStore> store = this.dataStoreMgr.getImageStores(scope);
17221731
if (store.size() > 1) {
17231732
throw new CloudRuntimeException("muliple image data store, don't know which one to use");
@@ -1727,7 +1736,6 @@ public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command)
17271736
SnapshotInfo snapInfo = this.snapshotFactory.getSnapshot(snapshotId);
17281737
future = this.imageSvr.createTemplateFromSnapshotAsync(snapInfo, tmplInfo, store.get(0));
17291738
} else if (volumeId != null) {
1730-
volume = _volumeDao.findById(volumeId);
17311739
VolumeInfo volInfo = this.volFactory.getVolume(volumeId);
17321740
future = this.imageSvr.createTemplateFromVolumeAsync(volInfo, tmplInfo, store.get(0));
17331741
} else {
@@ -1748,7 +1756,7 @@ public VirtualMachineTemplate createPrivateTemplate(CreateTemplateCmd command)
17481756
UsageEventVO usageEvent = new UsageEventVO(
17491757
EventTypes.EVENT_TEMPLATE_CREATE,
17501758
privateTemplate.getAccountId(),
1751-
snapshot.getDataCenterId(),
1759+
zoneId,
17521760
privateTemplate.getId(), privateTemplate.getName(),
17531761
null, privateTemplate.getSourceTemplateId(),
17541762
privateTemplate.getSize());
@@ -1971,6 +1979,7 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd,
19711979
}
19721980
}
19731981
privateTemplate.setSourceTemplateId(sourceTemplateId);
1982+
privateTemplate.setImageDataStoreId(1);
19741983

19751984
VMTemplateVO template = this._tmpltDao.persist(privateTemplate);
19761985
// Increment the number of templates

0 commit comments

Comments
 (0)