mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Create a template from a SAN snapshot
This commit is contained in:
parent
b576e4d67e
commit
455ffc3342
@ -135,6 +135,10 @@ public class TemplateObjectTO implements DataTO {
|
|||||||
return this.imageDataStore;
|
return this.imageDataStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHypervisorType(Hypervisor.HypervisorType hypervisorType) {
|
||||||
|
this.hypervisorType = hypervisorType;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Hypervisor.HypervisorType getHypervisorType() {
|
public Hypervisor.HypervisorType getHypervisorType() {
|
||||||
return this.hypervisorType;
|
return this.hypervisorType;
|
||||||
|
|||||||
@ -32,4 +32,6 @@
|
|||||||
class="org.apache.cloudstack.storage.motion.XenServerStorageMotionStrategy" />
|
class="org.apache.cloudstack.storage.motion.XenServerStorageMotionStrategy" />
|
||||||
<bean id="hypervStorageMotionStrategy"
|
<bean id="hypervStorageMotionStrategy"
|
||||||
class="org.apache.cloudstack.storage.motion.HypervStorageMotionStrategy" />
|
class="org.apache.cloudstack.storage.motion.HypervStorageMotionStrategy" />
|
||||||
|
<bean id="storageSystemDataMotionStrategy"
|
||||||
|
class="org.apache.cloudstack.storage.motion.StorageSystemDataMotionStrategy" />
|
||||||
</beans>
|
</beans>
|
||||||
|
|||||||
@ -18,8 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.cloudstack.storage.motion;
|
package org.apache.cloudstack.storage.motion;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@ -27,20 +31,68 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
|
|||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
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.DataStore;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
|
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
|
||||||
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
|
||||||
|
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||||
|
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||||
|
import org.apache.cloudstack.storage.command.CopyCmdAnswer;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||||
|
|
||||||
|
import com.cloud.agent.AgentManager;
|
||||||
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
|
import com.cloud.configuration.Config;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.org.Cluster;
|
||||||
|
import com.cloud.org.Grouping.AllocationState;
|
||||||
|
import com.cloud.resource.ResourceState;
|
||||||
|
import com.cloud.server.ManagementService;
|
||||||
|
import com.cloud.storage.DataStoreRole;
|
||||||
|
import com.cloud.storage.dao.SnapshotDetailsDao;
|
||||||
|
import com.cloud.storage.dao.SnapshotDetailsVO;
|
||||||
|
import com.cloud.utils.NumbersUtil;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
import com.cloud.vm.VirtualMachineManager;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||||
private static final Logger s_logger = Logger.getLogger(StorageSystemDataMotionStrategy.class);
|
private static final Logger s_logger = Logger.getLogger(StorageSystemDataMotionStrategy.class);
|
||||||
|
|
||||||
|
@Inject private AgentManager _agentMgr;
|
||||||
|
@Inject private ConfigurationDao _configDao;
|
||||||
|
@Inject private HostDao _hostDao;
|
||||||
|
@Inject private ManagementService _mgr;
|
||||||
|
@Inject private PrimaryDataStoreDao _storagePoolDao;
|
||||||
|
@Inject private SnapshotDetailsDao _snapshotDetailsDao;
|
||||||
|
@Inject private VolumeService _volService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
|
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
|
||||||
return StrategyPriority.DEFAULT;
|
if (srcData instanceof SnapshotInfo && destData.getDataStore().getRole() == DataStoreRole.Image || destData.getDataStore().getRole() == DataStoreRole.ImageCache) {
|
||||||
|
DataStore dataStore = srcData.getDataStore();
|
||||||
|
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
|
||||||
|
|
||||||
|
if (mapCapabilities != null) {
|
||||||
|
String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString());
|
||||||
|
Boolean supportsStorageSystemSnapshots = new Boolean(value);
|
||||||
|
|
||||||
|
if (supportsStorageSystemSnapshots) {
|
||||||
|
s_logger.info("Using 'StorageSystemDataMotionStrategy'");
|
||||||
|
|
||||||
|
return StrategyPriority.HIGHEST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StrategyPriority.CANT_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -50,10 +102,114 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, Host destHost, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
|
if (srcData instanceof SnapshotInfo && destData.getDataStore().getRole() == DataStoreRole.Image || destData.getDataStore().getRole() == DataStoreRole.ImageCache) {
|
||||||
|
SnapshotInfo snapshotInfo = (SnapshotInfo)srcData;
|
||||||
|
HostVO hostVO = getHost(srcData);
|
||||||
|
DataStore srcDataStore = srcData.getDataStore();
|
||||||
|
|
||||||
|
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||||
|
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||||
|
CopyCommand copyCommand = new CopyCommand(srcData.getTO(), destData.getTO(), primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
|
||||||
|
|
||||||
|
CopyCmdAnswer copyCmdAnswer = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
_volService.grantAccess(snapshotInfo, hostVO, srcDataStore);
|
||||||
|
|
||||||
|
Map<String, String> srcDetails = getSourceDetails(_storagePoolDao.findById(srcDataStore.getId()), snapshotInfo);
|
||||||
|
|
||||||
|
copyCommand.setOptions(srcDetails);
|
||||||
|
|
||||||
|
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new CloudRuntimeException(ex.getMessage());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
_volService.revokeAccess(snapshotInfo, hostVO, srcDataStore);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
s_logger.debug(ex.getMessage(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String errMsg = null;
|
||||||
|
|
||||||
|
if (copyCmdAnswer == null || !copyCmdAnswer.getResult()) {
|
||||||
|
if (copyCmdAnswer != null && copyCmdAnswer.getDetails() != null && !copyCmdAnswer.getDetails().isEmpty()) {
|
||||||
|
errMsg = copyCmdAnswer.getDetails();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errMsg = "Unable to perform host-side operation";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyCommandResult result = new CopyCommandResult(null, copyCmdAnswer);
|
||||||
|
|
||||||
|
result.setResult(errMsg);
|
||||||
|
|
||||||
|
callback.complete(result);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, String> getSourceDetails(StoragePoolVO storagePoolVO, SnapshotInfo snapshotInfo) {
|
||||||
|
Map<String, String> srcDetails = new HashMap<String, String>();
|
||||||
|
|
||||||
|
srcDetails.put(DiskTO.STORAGE_HOST, storagePoolVO.getHostAddress());
|
||||||
|
srcDetails.put(DiskTO.STORAGE_PORT, String.valueOf(storagePoolVO.getPort()));
|
||||||
|
|
||||||
|
long snapshotId = snapshotInfo.getId();
|
||||||
|
|
||||||
|
srcDetails.put(DiskTO.IQN, getProperty(snapshotId, DiskTO.IQN));
|
||||||
|
|
||||||
|
srcDetails.put(DiskTO.CHAP_INITIATOR_USERNAME, getProperty(snapshotId, DiskTO.CHAP_INITIATOR_USERNAME));
|
||||||
|
srcDetails.put(DiskTO.CHAP_INITIATOR_SECRET, getProperty(snapshotId, DiskTO.CHAP_INITIATOR_SECRET));
|
||||||
|
srcDetails.put(DiskTO.CHAP_TARGET_USERNAME, getProperty(snapshotId, DiskTO.CHAP_TARGET_USERNAME));
|
||||||
|
srcDetails.put(DiskTO.CHAP_TARGET_SECRET, getProperty(snapshotId, DiskTO.CHAP_TARGET_SECRET));
|
||||||
|
|
||||||
|
return srcDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getProperty(long snapshotId, String property) {
|
||||||
|
SnapshotDetailsVO snapshotDetails = _snapshotDetailsDao.findDetail(snapshotId, property);
|
||||||
|
|
||||||
|
if (snapshotDetails != null) {
|
||||||
|
return snapshotDetails.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HostVO getHost(DataObject srcData) {
|
||||||
|
long dataStoreId = srcData.getDataStore().getId();
|
||||||
|
StoragePoolVO storagePoolVO = _storagePoolDao.findById(dataStoreId);
|
||||||
|
|
||||||
|
List<? extends Cluster> clusters = _mgr.searchForClusters(storagePoolVO.getDataCenterId(), new Long(0), Long.MAX_VALUE, HypervisorType.XenServer.toString());
|
||||||
|
|
||||||
|
if (clusters == null) {
|
||||||
|
throw new CloudRuntimeException("Unable to locate an applicable cluster");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Cluster cluster : clusters) {
|
||||||
|
if (cluster.getAllocationState() == AllocationState.Enabled) {
|
||||||
|
List<HostVO> hosts = _hostDao.findByClusterId(cluster.getId());
|
||||||
|
|
||||||
|
if (hosts != null) {
|
||||||
|
for (HostVO host : hosts) {
|
||||||
|
if (host.getResourceState() == ResourceState.Enabled) {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new CloudRuntimeException("Unable to locate an applicable cluster");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback) {
|
||||||
return copyAsync(srcData, destData, null, callback);
|
return copyAsync(srcData, destData, null, callback);
|
||||||
|
|||||||
@ -217,6 +217,9 @@ public class TemplateObject implements TemplateInfo {
|
|||||||
// For template created from snapshot, template name is determine by resource code.
|
// For template created from snapshot, template name is determine by resource code.
|
||||||
templateVO.setUniqueName(newTemplate.getName());
|
templateVO.setUniqueName(newTemplate.getName());
|
||||||
}
|
}
|
||||||
|
if (newTemplate.getHypervisorType() != null) {
|
||||||
|
templateVO.setHypervisorType(newTemplate.getHypervisorType());
|
||||||
|
}
|
||||||
templateVO.setSize(newTemplate.getSize());
|
templateVO.setSize(newTemplate.getSize());
|
||||||
imageDao.update(templateVO.getId(), templateVO);
|
imageDao.update(templateVO.getId(), templateVO);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -226,7 +226,7 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
sourceDetails = getSourceDetails(volumeInfo);
|
sourceDetails = getSourceDetails(volumeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
HostVO hostVO = getHostId(hostId, volumeVO);
|
HostVO hostVO = getHost(hostId, volumeVO);
|
||||||
|
|
||||||
long storagePoolId = volumeVO.getPoolId();
|
long storagePoolId = volumeVO.getPoolId();
|
||||||
StoragePoolVO storagePoolVO = _storagePoolDao.findById(storagePoolId);
|
StoragePoolVO storagePoolVO = _storagePoolDao.findById(storagePoolId);
|
||||||
@ -340,7 +340,7 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HostVO getHostId(Long hostId, VolumeVO volumeVO) {
|
private HostVO getHost(Long hostId, VolumeVO volumeVO) {
|
||||||
HostVO hostVO = _hostDao.findById(hostId);
|
HostVO hostVO = _hostDao.findById(hostId);
|
||||||
|
|
||||||
if (hostVO != null) {
|
if (hostVO != null) {
|
||||||
@ -404,7 +404,8 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
DataStore dataStore = _dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary);
|
DataStore dataStore = _dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary);
|
||||||
|
|
||||||
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
|
Map<String, String> mapCapabilities = dataStore.getDriver().getCapabilities();
|
||||||
if(mapCapabilities != null) {
|
|
||||||
|
if (mapCapabilities != null) {
|
||||||
String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString());
|
String value = mapCapabilities.get(DataStoreCapabilities.STORAGE_SYSTEM_SNAPSHOT.toString());
|
||||||
Boolean supportsStorageSystemSnapshots = new Boolean(value);
|
Boolean supportsStorageSystemSnapshots = new Boolean(value);
|
||||||
|
|
||||||
@ -412,6 +413,7 @@ public class StorageSystemSnapshotStrategy extends SnapshotStrategyBase {
|
|||||||
return StrategyPriority.HIGHEST;
|
return StrategyPriority.HIGHEST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return StrategyPriority.CANT_HANDLE;
|
return StrategyPriority.CANT_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,8 +64,10 @@ import com.cloud.agent.api.to.S3TO;
|
|||||||
import com.cloud.agent.api.to.StorageFilerTO;
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
import com.cloud.agent.api.to.SwiftTO;
|
import com.cloud.agent.api.to.SwiftTO;
|
||||||
import com.cloud.exception.InternalErrorException;
|
import com.cloud.exception.InternalErrorException;
|
||||||
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.SRType;
|
import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase.SRType;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.Storage.ImageFormat;
|
import com.cloud.storage.Storage.ImageFormat;
|
||||||
import com.cloud.storage.resource.StorageProcessor;
|
import com.cloud.storage.resource.StorageProcessor;
|
||||||
import com.cloud.utils.S3Utils;
|
import com.cloud.utils.S3Utils;
|
||||||
@ -1457,7 +1459,126 @@ public class XenServerStorageProcessor implements StorageProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Answer createTemplateFromSnapshot(CopyCommand cmd) {
|
public Answer createTemplateFromSnapshot(CopyCommand cmd) {
|
||||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
Connection conn = hypervisorResource.getConnection();
|
||||||
|
|
||||||
|
SnapshotObjectTO snapshotObjTO = (SnapshotObjectTO)cmd.getSrcTO();
|
||||||
|
TemplateObjectTO templateObjTO = (TemplateObjectTO)cmd.getDestTO();
|
||||||
|
|
||||||
|
if (!(snapshotObjTO.getDataStore() instanceof PrimaryDataStoreTO) || !(templateObjTO.getDataStore() instanceof NfsTO)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String userSpecifiedTemplateName = templateObjTO.getName();
|
||||||
|
|
||||||
|
NfsTO destStore = null;
|
||||||
|
URI destUri = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
destStore = (NfsTO)templateObjTO.getDataStore();
|
||||||
|
|
||||||
|
destUri = new URI(destStore.getUrl());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
s_logger.debug("Invalid URI", ex);
|
||||||
|
|
||||||
|
return new CopyCmdAnswer("Invalid URI: " + ex.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
SR srcSr = null;
|
||||||
|
SR destSr = null;
|
||||||
|
|
||||||
|
String destDir = templateObjTO.getPath();
|
||||||
|
VDI destVdi = null;
|
||||||
|
|
||||||
|
boolean result = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, String> srcDetails = cmd.getOptions();
|
||||||
|
|
||||||
|
String iScsiName = srcDetails.get(DiskTO.IQN);
|
||||||
|
String storageHost = srcDetails.get(DiskTO.STORAGE_HOST);
|
||||||
|
String chapInitiatorUsername = srcDetails.get(DiskTO.CHAP_INITIATOR_USERNAME);
|
||||||
|
String chapInitiatorSecret = srcDetails.get(DiskTO.CHAP_INITIATOR_SECRET);
|
||||||
|
|
||||||
|
srcSr = hypervisorResource.getIscsiSR(conn, iScsiName, storageHost, iScsiName, chapInitiatorUsername, chapInitiatorSecret, true);
|
||||||
|
|
||||||
|
String destNfsPath = destUri.getHost() + ":" + destUri.getPath();
|
||||||
|
|
||||||
|
if (!hypervisorResource.createSecondaryStorageFolder(conn, destNfsPath, destDir)) {
|
||||||
|
String details = " Failed to create folder " + destDir + " in secondary storage";
|
||||||
|
|
||||||
|
s_logger.warn(details);
|
||||||
|
|
||||||
|
return new CopyCmdAnswer(details);
|
||||||
|
}
|
||||||
|
|
||||||
|
URI templateUri = new URI(destStore.getUrl() + "/" + destDir);
|
||||||
|
|
||||||
|
destSr = hypervisorResource.createNfsSRbyURI(conn, templateUri, false);
|
||||||
|
|
||||||
|
// there should only be one VDI in this SR
|
||||||
|
VDI srcVdi = srcSr.getVDIs(conn).iterator().next();
|
||||||
|
|
||||||
|
destVdi = srcVdi.copy(conn, destSr);
|
||||||
|
|
||||||
|
// scan makes XenServer pick up VDI physicalSize
|
||||||
|
destSr.scan(conn);
|
||||||
|
|
||||||
|
if (userSpecifiedTemplateName != null) {
|
||||||
|
destVdi.setNameLabel(conn, userSpecifiedTemplateName);
|
||||||
|
}
|
||||||
|
|
||||||
|
String templateUuid = destVdi.getUuid(conn);
|
||||||
|
String templateFilename = templateUuid + ".vhd";
|
||||||
|
long virtualSize = destVdi.getVirtualSize(conn);
|
||||||
|
long physicalSize = destVdi.getPhysicalUtilisation(conn);
|
||||||
|
|
||||||
|
// create the template.properties file
|
||||||
|
String templatePath = destNfsPath + "/" + destDir;
|
||||||
|
|
||||||
|
templatePath = templatePath.replaceAll("//", "/");
|
||||||
|
|
||||||
|
result = hypervisorResource.postCreatePrivateTemplate(conn, templatePath, templateFilename, templateUuid, userSpecifiedTemplateName, null,
|
||||||
|
physicalSize, virtualSize, templateObjTO.getId());
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
throw new CloudRuntimeException("Could not create the template.properties file on secondary storage dir: " + templateUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateObjectTO newTemplate = new TemplateObjectTO();
|
||||||
|
|
||||||
|
newTemplate.setPath(destDir + "/" + templateFilename);
|
||||||
|
newTemplate.setFormat(Storage.ImageFormat.VHD);
|
||||||
|
newTemplate.setHypervisorType(HypervisorType.XenServer);
|
||||||
|
newTemplate.setSize(virtualSize);
|
||||||
|
newTemplate.setPhysicalSize(physicalSize);
|
||||||
|
newTemplate.setName(templateUuid);
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
return new CopyCmdAnswer(newTemplate);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
s_logger.error("Failed to create a template from a snapshot", ex);
|
||||||
|
|
||||||
|
return new CopyCmdAnswer("Failed to create a template from a snapshot: " + ex.toString());
|
||||||
|
} finally {
|
||||||
|
if (!result) {
|
||||||
|
if (destVdi != null) {
|
||||||
|
try {
|
||||||
|
destVdi.destroy(conn);
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.debug("Cleaned up leftover VDI on destination storage due to failure: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcSr != null) {
|
||||||
|
hypervisorResource.removeSR(conn, srcSr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destSr != null) {
|
||||||
|
hypervisorResource.removeSR(conn, destSr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -61,69 +61,94 @@ public class Xenserver625StorageProcessor extends XenServerStorageProcessor {
|
|||||||
public Xenserver625StorageProcessor(CitrixResourceBase resource) {
|
public Xenserver625StorageProcessor(CitrixResourceBase resource) {
|
||||||
super(resource);
|
super(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean mountNfs(Connection conn, String remoteDir, String localDir) {
|
protected boolean mountNfs(Connection conn, String remoteDir, String localDir) {
|
||||||
if (localDir == null) {
|
if (localDir == null) {
|
||||||
localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remoteDir.getBytes());
|
localDir = "/var/cloud_mount/" + UUID.nameUUIDFromBytes(remoteDir.getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000,
|
String results = hypervisorResource.callHostPluginAsync(conn, "cloud-plugin-storage", "mountNfsSecondaryStorage", 100 * 1000,
|
||||||
"localDir", localDir, "remoteDir", remoteDir);
|
"localDir", localDir, "remoteDir", remoteDir);
|
||||||
|
|
||||||
if (results == null || results.isEmpty()) {
|
if (results == null || results.isEmpty()) {
|
||||||
String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir;
|
String errMsg = "Could not mount secondary storage " + remoteDir + " on host " + localDir;
|
||||||
|
|
||||||
s_logger.warn(errMsg);
|
s_logger.warn(errMsg);
|
||||||
|
|
||||||
throw new CloudRuntimeException(errMsg);
|
throw new CloudRuntimeException(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean makeDirectory(Connection conn, String path) {
|
protected boolean makeDirectory(Connection conn, String path) {
|
||||||
String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path);
|
String result = hypervisorResource.callHostPlugin(conn, "cloud-plugin-storage", "makeDirectory", "path", path);
|
||||||
|
|
||||||
if (result == null || result.isEmpty()) {
|
if (result == null || result.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SR createFileSR(Connection conn, String path) {
|
protected SR createFileSR(Connection conn, String path) {
|
||||||
SR sr = null;
|
SR sr = null;
|
||||||
PBD pbd = null;
|
PBD pbd = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String srname = hypervisorResource.getHost().uuid + path.trim();
|
String srname = hypervisorResource.getHost().uuid + path.trim();
|
||||||
|
|
||||||
Set<SR> srs = SR.getByNameLabel(conn, srname);
|
Set<SR> srs = SR.getByNameLabel(conn, srname);
|
||||||
if ( srs != null && !srs.isEmpty()) {
|
|
||||||
|
if (srs != null && !srs.isEmpty()) {
|
||||||
return srs.iterator().next();
|
return srs.iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> smConfig = new HashMap<String, String>();
|
Map<String, String> smConfig = new HashMap<String, String>();
|
||||||
|
|
||||||
Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid);
|
Host host = Host.getByUuid(conn, hypervisorResource.getHost().uuid);
|
||||||
String uuid = UUID.randomUUID().toString();
|
String uuid = UUID.randomUUID().toString();
|
||||||
|
|
||||||
sr = SR.introduce(conn, uuid, srname, srname, "file", "file", false, smConfig);
|
sr = SR.introduce(conn, uuid, srname, srname, "file", "file", false, smConfig);
|
||||||
|
|
||||||
PBD.Record record = new PBD.Record();
|
PBD.Record record = new PBD.Record();
|
||||||
|
|
||||||
record.host = host;
|
record.host = host;
|
||||||
record.SR = sr;
|
record.SR = sr;
|
||||||
|
|
||||||
smConfig.put("location", path);
|
smConfig.put("location", path);
|
||||||
|
|
||||||
record.deviceConfig = smConfig;
|
record.deviceConfig = smConfig;
|
||||||
|
|
||||||
pbd = PBD.create(conn, record);
|
pbd = PBD.create(conn, record);
|
||||||
|
|
||||||
pbd.plug(conn);
|
pbd.plug(conn);
|
||||||
|
|
||||||
sr.scan(conn);
|
sr.scan(conn);
|
||||||
|
|
||||||
return sr;
|
return sr;
|
||||||
} catch (Exception e) {
|
} catch (Exception ex) {
|
||||||
try {
|
try {
|
||||||
if (pbd != null) {
|
if (pbd != null) {
|
||||||
pbd.destroy(conn);
|
pbd.destroy(conn);
|
||||||
}
|
}
|
||||||
} catch (Exception e1) {
|
} catch (Exception e1) {
|
||||||
s_logger.debug("Failed to destroy pbd", e);
|
s_logger.debug("Failed to destroy PBD", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (sr != null) {
|
if (sr != null) {
|
||||||
sr.forget(conn);
|
sr.forget(conn);
|
||||||
}
|
}
|
||||||
} catch (Exception e2) {
|
} catch (Exception e2) {
|
||||||
s_logger.error("Failed to forget sr", e);
|
s_logger.error("Failed to forget SR", ex);
|
||||||
}
|
}
|
||||||
String msg = "createFileSR failed! due to " + e.toString();
|
|
||||||
s_logger.warn(msg, e);
|
String msg = "createFileSR failed! due to the following: " + ex.toString();
|
||||||
throw new CloudRuntimeException(msg, e);
|
|
||||||
|
s_logger.warn(msg, ex);
|
||||||
|
|
||||||
|
throw new CloudRuntimeException(msg, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user