http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index f3da368..8cfbae4 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -22,7 +22,8 @@ import javax.inject.Inject; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; -import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -31,6 +32,7 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.DataObjectManager; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; import org.apache.cloudstack.storage.datastore.PrimaryDataStore; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; @@ -55,6 +57,8 @@ public class VolumeServiceImpl implements VolumeService { @Inject ObjectInDataStoreManager objectInDataStoreMgr; @Inject + DataObjectManager dataObjectMgr; + @Inject ImageMotionService imageMotion; @Inject TemplateInstallStrategy templateInstallStrategy; @@ -85,6 +89,8 @@ public class VolumeServiceImpl implements VolumeService { } + + @Override public AsyncCallFuture<VolumeApiResult> createVolumeAsync(VolumeInfo volume, long dataStoreId) { PrimaryDataStore dataStore = dataStoreMgr.getPrimaryDataStore(dataStoreId); @@ -107,16 +113,16 @@ public class VolumeServiceImpl implements VolumeService { vo.stateTransit(Volume.Event.CreateRequested); CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(null, vo, future); - AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this); + AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().createVolumeCallback(null, null)) .setContext(context); - //dataStore.createVolumeAsync(vo, null, caller); + dataObjectMgr.createAsync(volume, dataStore, caller, true); return future; } - protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> callback, CreateVolumeContext<VolumeApiResult> context) { - CommandResult result = callback.getResult(); + protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeContext<VolumeApiResult> context) { + CreateCmdResult result = callback.getResult(); VolumeObject vo = context.getVolume(); VolumeApiResult volResult = new VolumeApiResult(vo); if (result.isSuccess()) { @@ -172,7 +178,7 @@ public class VolumeServiceImpl implements VolumeService { caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null)) .setContext(context); - dataStore.getDriver().deleteAsync(volume, caller); + dataObjectMgr.deleteAsync(volume, caller); return future; } @@ -279,21 +285,23 @@ public class VolumeServiceImpl implements VolumeService { @DB protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture<VolumeApiResult> future) { - CreateBaseImageContext<VolumeApiResult> context = new CreateBaseImageContext<VolumeApiResult>(null, volume, + CreateBaseImageContext<CreateCmdResult> context = new CreateBaseImageContext<CreateCmdResult>(null, volume, dataStore, template, future); - AsyncCallbackDispatcher<VolumeServiceImpl, CreateBaseImageResult> caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().createBaseImageCallback(null, null)) + AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null)) .setContext(context); - - templateInstallStrategy.installAsync(template, dataStore, caller); + DataObject templateOnPrimaryStoreObj = dataObjectMgr.createInternalStateOnly(template, dataStore); + + dataObjectMgr.copyAsync(context.srcTemplate, templateOnPrimaryStoreObj, caller); + return; } - + @DB - protected Void createBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateBaseImageResult> callback, CreateBaseImageContext<VolumeApiResult> context) { - CreateBaseImageResult result = callback.getResult(); + protected Void copyBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateBaseImageContext<VolumeApiResult> context) { + CreateCmdResult result = callback.getResult(); VolumeApiResult res = new VolumeApiResult(context.getVolume()); AsyncCallFuture<VolumeApiResult> future = context.getFuture(); @@ -302,23 +310,26 @@ public class VolumeServiceImpl implements VolumeService { future.complete(res); return null; } - - //now create volume on base image - TemplateInfo templateOnPrimaryStoreObj = result.template; - VolumeInfo volume = context.getVolume(); - PrimaryDataStore pd = context.getDataStore(); + DataObject templateOnPrimaryStoreObj = objectInDataStoreMgr.get(context.srcTemplate, context.dataStore); - createVolumeFromBaseImageAsync(volume, templateOnPrimaryStoreObj, pd, future); + createVolumeFromBaseImageAsync(context.volume, templateOnPrimaryStoreObj, context.dataStore, future); return null; } private class CreateVolumeFromBaseImageContext<T> extends AsyncRpcConext<T> { private final VolumeObject vo; private final AsyncCallFuture<VolumeApiResult> future; - public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo, AsyncCallFuture<VolumeApiResult> future) { + private final DataStore primaryStore; + private final DataObject templateOnStore; + public CreateVolumeFromBaseImageContext(AsyncCompletionCallback<T> callback, VolumeObject vo, + DataStore primaryStore, + DataObject templateOnStore, + AsyncCallFuture<VolumeApiResult> future) { super(callback); this.vo = vo; this.future = future; + this.primaryStore = primaryStore; + this.templateOnStore = templateOnStore; } public VolumeObject getVolumeObject() { @@ -331,7 +342,7 @@ public class VolumeServiceImpl implements VolumeService { } @DB - protected void createVolumeFromBaseImageAsync(VolumeInfo volume, TemplateInfo templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture<VolumeApiResult> future) { + protected void createVolumeFromBaseImageAsync(VolumeInfo volume, DataObject templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture<VolumeApiResult> future) { VolumeObject vo = (VolumeObject) volume; try { vo.stateTransit(Volume.Event.CreateRequested); @@ -342,19 +353,22 @@ public class VolumeServiceImpl implements VolumeService { return; } - CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, vo, future); - AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().createVolumeFromBaseImageCallback(null, null)) + CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, vo, pd, templateOnPrimaryStore, future); + AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyBaseImageCallBack(null, null)) .setContext(context); - pd.getDriver().copyAsync(volume, templateOnPrimaryStore, caller); + DataObject volumeOnPrimaryStorage = dataObjectMgr.createInternalStateOnly(volume, pd); + dataObjectMgr.copyAsync(context.templateOnStore, volumeOnPrimaryStorage, caller); + return; } @DB - public Object createVolumeFromBaseImageCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) { + public Void copyBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CreateCmdResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) { VolumeObject vo = context.getVolumeObject(); - CopyCommandResult result = callback.getResult(); + CreateCmdResult result = callback.getResult(); VolumeApiResult volResult = new VolumeApiResult(vo); + if (result.isSuccess()) { if (result.getPath() != null) { vo.setPath(result.getPath());
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java ---------------------------------------------------------------------- diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java index 1aa96c3..06367af 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java @@ -28,22 +28,18 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.UUID; import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer; import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd; import org.apache.cloudstack.storage.command.CopyCmd; import org.apache.cloudstack.storage.command.CopyCmdAnswer; +import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.command.CreateObjectCommand; import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd; -import org.apache.cloudstack.storage.command.CreateObjectAnswer; import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol; import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; -import org.apache.cloudstack.storage.to.NfsPrimaryDataStoreTO; -import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; -import org.apache.cloudstack.storage.to.TemplateTO; import org.apache.cloudstack.storage.to.VolumeTO; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -57,8 +53,10 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.storage.DeleteVolumeCommand; import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType; -import com.cloud.storage.Storage.StoragePoolType; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.storage.encoding.DataStore; +import com.cloud.utils.storage.encoding.DecodedDataObject; +import com.cloud.utils.storage.encoding.Decoder; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.PBD; @@ -137,28 +135,23 @@ public class XenServerStorageResource { } protected CreateObjectAnswer execute(CreateObjectCommand cmd) { String uriString = cmd.getObjectUri(); - Map<String, String> params = null; - - try { - URI uri = new URI(uriString); - params = getParameters(uri); - } catch (URISyntaxException e1) { - s_logger.debug("uri exception", e1); - return new CreateObjectAnswer(cmd, false, e1.toString()); - } - - if (params.get("objType").equalsIgnoreCase("template")) { - return getTemplateSize(cmd, params.get("path")); - } - - long size = Long.parseLong(params.get("size")); - String name = params.get("name"); - String storeUuid = params.get("storagePath"); + DecodedDataObject obj = null; + Connection conn = hypervisorResource.getConnection(); VDI vdi = null; boolean result = false; String errorMsg = null; + try { + obj = Decoder.decode(uriString); + DataStore store = obj.getStore(); + if (obj.getObjType().equalsIgnoreCase("template") && store.getRole().equalsIgnoreCase("image")) { + return getTemplateSize(cmd, obj.getPath()); + } + + long size = obj.getSize(); + String name = obj.getName(); + String storeUuid = store.getUuid(); SR primaryDataStoreSR = getSRByNameLabel(conn, storeUuid); vdi = createVdi(conn, name, primaryDataStoreSR, size); VDI.Record record = vdi.getRecord(conn); @@ -173,6 +166,9 @@ public class XenServerStorageResource { } catch (XmlRpcException e) { s_logger.debug("Failed to create volume", e); errorMsg = e.toString(); + } catch (URISyntaxException e) { + s_logger.debug("Failed to create volume", e); + errorMsg = e.toString(); } finally { if (!result && vdi != null) { try { @@ -227,13 +223,13 @@ public class XenServerStorageResource { } } - protected SR getNfsSR(Connection conn, URI uri) { + protected SR getNfsSR(Connection conn, DataStore store) { Map<String, String> deviceConfig = new HashMap<String, String>(); - Map<String, String> params = getParameters(uri); - String uuid = params.get("storeUuid"); + + String uuid = store.getUuid(); try { - String server = uri.getHost(); - String serverpath = uri.getPath(); + String server = store.getServer(); + String serverpath = store.getPath(); serverpath = serverpath.replace("//", "/"); Set<SR> srs = SR.getAll(conn); @@ -410,25 +406,17 @@ public class XenServerStorageResource { protected Answer execute(CreatePrimaryDataStoreCmd cmd) { Connection conn = hypervisorResource.getConnection(); String storeUrl = cmd.getDataStore(); - String scheme = null; - String type = null; - URI storeUri = null; - try { - storeUri = new URI(storeUrl); - } catch(URISyntaxException e) { - return new Answer(cmd, false, e.toString()); - } - - scheme = storeUri.getScheme(); - + try { - if (scheme.equalsIgnoreCase("nfs")) { - SR sr = getNfsSR(conn, storeUri); - } else if (scheme.equalsIgnoreCase("iscsi")) { + DecodedDataObject obj = Decoder.decode(storeUrl); + DataStore store = obj.getStore(); + if (store.getScheme().equalsIgnoreCase("nfs")) { + SR sr = getNfsSR(conn, store); + } else if (store.getScheme().equalsIgnoreCase("iscsi")) { //getIscsiSR(conn, dataStore); - } else if (scheme.equalsIgnoreCase("presetup")) { + } else if (store.getScheme().equalsIgnoreCase("presetup")) { } else { - return new Answer(cmd, false, "The pool type: " + scheme + " is not supported."); + return new Answer(cmd, false, "The pool type: " + store.getScheme() + " is not supported."); } return new Answer(cmd, true, "success"); } catch (Exception e) { @@ -509,31 +497,30 @@ public class XenServerStorageResource { } - protected Answer directDownloadHttpTemplate(CopyCmd cmd, TemplateTO template, PrimaryDataStoreTO primarDataStore) { - String primaryStoreUuid = primarDataStore.getUuid(); + protected Answer directDownloadHttpTemplate(CopyCmd cmd, DecodedDataObject srcObj, DecodedDataObject destObj) { Connection conn = hypervisorResource.getConnection(); SR poolsr = null; VDI vdi = null; boolean result = false; try { - - Set<SR> srs = SR.getByNameLabel(conn, primaryStoreUuid); + if (destObj.getPath() == null) { + //need to create volume at first + + } + vdi = VDI.getByUuid(conn, destObj.getPath()); + if (vdi == null) { + throw new CloudRuntimeException("can't find volume: " + destObj.getPath()); + } + String destStoreUuid = destObj.getStore().getUuid(); + Set<SR> srs = SR.getByNameLabel(conn, destStoreUuid); if (srs.size() != 1) { - throw new CloudRuntimeException("storage uuid: " + primaryStoreUuid + " is not unique"); + throw new CloudRuntimeException("storage uuid: " + destStoreUuid + " is not unique"); } poolsr = srs.iterator().next(); - VDI.Record vdir = new VDI.Record(); - vdir.nameLabel = "Base-Image-" + UUID.randomUUID().toString(); - vdir.SR = poolsr; - vdir.type = Types.VdiType.USER; - - vdir.virtualSize = getTemplateSize(conn, template.getPath()); - vdi = VDI.create(conn, vdir); - - vdir = vdi.getRecord(conn); + VDI.Record vdir = vdi.getRecord(conn); String vdiLocation = vdir.location; String pbdLocation = null; - if (primarDataStore.getType().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) { + if (destObj.getStore().getScheme().equalsIgnoreCase(DataStoreProtocol.NFS.toString())) { pbdLocation = "/run/sr-mount/" + poolsr.getUuid(conn); } else { Set<PBD> pbds = poolsr.getPBDs(conn); @@ -551,7 +538,7 @@ public class XenServerStorageResource { String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd"; //download a url into vdipath //downloadHttpToLocalFile(vdiPath, template.getPath()); - hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", template.getPath()); + hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", srcObj.getPath()); result = true; return new CopyCmdAnswer(cmd, vdi.getUuid(conn)); } catch (BadServerResponse e) { @@ -581,16 +568,10 @@ public class XenServerStorageResource { protected Answer execute(AttachPrimaryDataStoreCmd cmd) { String dataStoreUri = cmd.getDataStore(); Connection conn = hypervisorResource.getConnection(); - Map<String, String> params = null; try { - try { - URI uri = new URI(dataStoreUri); - params = getParameters(uri); - } catch (URISyntaxException e1) { - s_logger.debug("uri exception", e1); - return new CreateObjectAnswer(cmd, false, e1.toString()); - } - SR sr = hypervisorResource.getStorageRepository(conn, params.get("storeUuid")); + DecodedDataObject obj = Decoder.decode(dataStoreUri); + DataStore store = obj.getStore(); + SR sr = hypervisorResource.getStorageRepository(conn, store.getUuid()); hypervisorResource.setupHeartbeatSr(conn, sr, false); long capacity = sr.getPhysicalSize(conn); long available = capacity - sr.getPhysicalUtilisation(conn); @@ -616,10 +597,18 @@ public class XenServerStorageResource { } protected Answer execute(CopyCmd cmd) { - ImageOnPrimayDataStoreTO imageTO = cmd.getImage(); - TemplateTO template = imageTO.getTemplate(); - if (template.getPath().startsWith("http")) { - return directDownloadHttpTemplate(cmd, template, imageTO.getPrimaryDataStore()); + DecodedDataObject srcObj = null; + DecodedDataObject destObj = null; + try { + srcObj = Decoder.decode(cmd.getSrcUri()); + destObj = Decoder.decode(cmd.getDestUri()); + } catch (URISyntaxException e) { + return new Answer(cmd, false, e.toString()); + } + + + if (srcObj.getPath().startsWith("http")) { + return directDownloadHttpTemplate(cmd, srcObj, destObj); } else { return new Answer(cmd, false, "not implemented yet"); /* http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java index e066dff..04b553c 100644 --- a/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java @@ -37,7 +37,7 @@ public class VMTemplateDetailsDaoImpl extends GenericDaoBase<VMTemplateDetailVO, protected final SearchBuilder<VMTemplateDetailVO> TemplateSearch; protected final SearchBuilder<VMTemplateDetailVO> DetailSearch; - protected VMTemplateDetailsDaoImpl() { + public VMTemplateDetailsDaoImpl() { TemplateSearch = createSearchBuilder(); TemplateSearch.and("templateId", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); TemplateSearch.done(); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/6f5655cb/setup/db/4.1-new-db-schema.sql ---------------------------------------------------------------------- diff --git a/setup/db/4.1-new-db-schema.sql b/setup/db/4.1-new-db-schema.sql index d541537..e8bafa2 100644 --- a/setup/db/4.1-new-db-schema.sql +++ b/setup/db/4.1-new-db-schema.sql @@ -18,6 +18,8 @@ alter table vm_template add image_data_store_id bigint unsigned; alter table vm_template add size bigint unsigned; alter table vm_template add state varchar(255); +alter table vm_template add update_count bigint unsigned; +alter table vm_template add updated datetime; alter table storage_pool add storage_provider_id bigint unsigned; alter table storage_pool add scope varchar(255); alter table storage_pool modify id bigint unsigned AUTO_INCREMENT UNIQUE NOT NULL; @@ -67,7 +69,7 @@ CREATE TABLE `cloud`.`object_datastore_ref` ( `size` bigint unsigned COMMENT 'the size of the template on the pool', `state` varchar(255) NOT NULL, `update_count` bigint unsigned NOT NULL, - `updated` DATETIME NOT NULL, + `updated` DATETIME, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
