mirror of https://github.com/apache/cloudstack.git
Preliminary upload and attach changes work ..
This commit is contained in:
parent
564cef8ddf
commit
54956280e6
|
|
@ -117,6 +117,7 @@ public class DownloadCommand extends AbstractDownloadCommand {
|
|||
this.auth = that.getAuth();
|
||||
this.setSecUrl(that.getSecUrl());
|
||||
this.maxDownloadSizeInBytes = that.getMaxDownloadSizeInBytes();
|
||||
this.resourceType = that.resourceType;
|
||||
}
|
||||
|
||||
public DownloadCommand(String secUrl, VirtualMachineTemplate template, Long maxDownloadSizeInBytes) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package com.cloud.agent.api.storage;
|
||||
|
||||
import com.cloud.agent.api.LogLevel;
|
||||
import com.cloud.agent.api.LogLevel.Log4jLevel;
|
||||
import com.cloud.agent.api.to.SwiftTO;
|
||||
|
||||
public class ListVolumeCommand extends StorageCommand {
|
||||
|
||||
private String secUrl;
|
||||
|
||||
public ListVolumeCommand() {
|
||||
}
|
||||
|
||||
public ListVolumeCommand(String secUrl) {
|
||||
this.secUrl = secUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getSecUrl() {
|
||||
return secUrl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -31,7 +31,10 @@ public interface Volume extends ControlledEntity, BasedOn, StateObject<Volume.St
|
|||
Migrating("The volume is migrating to other storage pool"),
|
||||
Snapshotting("There is a snapshot created on this volume, not backed up to secondary storage yet"),
|
||||
Expunging("The volume is being expunging"),
|
||||
Destroy("The volume is destroyed, and can't be recovered.");
|
||||
Destroy("The volume is destroyed, and can't be recovered."),
|
||||
Uploading ("The volume upload is in progress"),
|
||||
Uploaded ("The volume is uploaded"),
|
||||
UploadError ("The volume couldnt be uploaded");
|
||||
|
||||
String _description;
|
||||
|
||||
|
|
@ -55,7 +58,13 @@ public interface Volume extends ControlledEntity, BasedOn, StateObject<Volume.St
|
|||
s_fsm.addTransition(Creating, Event.OperationFailed, Allocated);
|
||||
s_fsm.addTransition(Creating, Event.OperationSucceeded, Ready);
|
||||
s_fsm.addTransition(Creating, Event.DestroyRequested, Destroy);
|
||||
s_fsm.addTransition(Creating, Event.CreateRequested, Creating);
|
||||
s_fsm.addTransition(Creating, Event.CreateRequested, Creating);
|
||||
s_fsm.addTransition(Allocated, Event.UploadRequested, Uploading);
|
||||
s_fsm.addTransition(Uploading, Event.UploadSucceeded, Uploaded);
|
||||
s_fsm.addTransition(Uploading, Event.OperationFailed, UploadError);
|
||||
s_fsm.addTransition(Uploaded, Event.CopyRequested, Creating);
|
||||
s_fsm.addTransition(Creating, Event.CopySucceeded, Ready);
|
||||
s_fsm.addTransition(Creating, Event.CopyFailed, Uploaded);
|
||||
s_fsm.addTransition(Ready, Event.DestroyRequested, Destroy);
|
||||
s_fsm.addTransition(Destroy, Event.ExpungingRequested, Expunging);
|
||||
s_fsm.addTransition(Ready, Event.SnapshotRequested, Snapshotting);
|
||||
|
|
@ -70,9 +79,14 @@ public interface Volume extends ControlledEntity, BasedOn, StateObject<Volume.St
|
|||
|
||||
enum Event {
|
||||
CreateRequested,
|
||||
CopyRequested,
|
||||
CopySucceeded,
|
||||
CopyFailed,
|
||||
OperationFailed,
|
||||
OperationSucceeded,
|
||||
OperationRetry,
|
||||
UploadRequested,
|
||||
UploadSucceeded,
|
||||
MigrationRequested,
|
||||
SnapshotRequested,
|
||||
DestroyRequested,
|
||||
|
|
|
|||
|
|
@ -72,9 +72,6 @@ public class VolumeHostVO {
|
|||
|
||||
@Column (name="url")
|
||||
private String downloadUrl;
|
||||
|
||||
@Column(name="is_copy")
|
||||
private boolean isCopy = false;
|
||||
|
||||
@Column(name="destroyed")
|
||||
boolean destroyed = false;
|
||||
|
|
@ -260,16 +257,7 @@ public class VolumeHostVO {
|
|||
|
||||
public String getDownloadUrl() {
|
||||
return downloadUrl;
|
||||
}
|
||||
|
||||
public void setCopy(boolean isCopy) {
|
||||
this.isCopy = isCopy;
|
||||
}
|
||||
|
||||
public boolean isCopy() {
|
||||
return isCopy;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public long getVolumeSize() {
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import com.cloud.agent.api.storage.DownloadCommand;
|
|||
import com.cloud.agent.api.storage.DownloadProgressCommand;
|
||||
import com.cloud.agent.api.storage.ListTemplateAnswer;
|
||||
import com.cloud.agent.api.storage.ListTemplateCommand;
|
||||
import com.cloud.agent.api.storage.ListVolumeCommand;
|
||||
import com.cloud.agent.api.storage.UploadCommand;
|
||||
import com.cloud.agent.api.storage.ssCommand;
|
||||
import com.cloud.agent.api.to.SwiftTO;
|
||||
|
|
@ -702,6 +703,17 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S
|
|||
}
|
||||
}
|
||||
|
||||
private Answer execute(ListVolumeCommand cmd) {
|
||||
if (!_inSystemVM){
|
||||
return new Answer(cmd, true, null);
|
||||
}
|
||||
|
||||
String root = getRootDir(cmd.getSecUrl());
|
||||
Map<String, TemplateInfo> templateInfos = _dlMgr.gatherTemplateInfo(root);
|
||||
return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos);
|
||||
|
||||
}
|
||||
|
||||
private Answer execute(SecStorageVMSetupCommand cmd) {
|
||||
if (!_inSystemVM){
|
||||
return new Answer(cmd, true, null);
|
||||
|
|
|
|||
|
|
@ -92,5 +92,11 @@ public interface DownloadManager extends Manager {
|
|||
* @return list of template info for installed templates
|
||||
*/
|
||||
public Map<String, TemplateInfo> gatherTemplateInfo(String templateDir);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @return list of volume info for installed volumes
|
||||
*/
|
||||
public Map<String, TemplateInfo> gatherVolumeInfo(String volumeDir);
|
||||
|
||||
}
|
||||
|
|
@ -222,6 +222,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
|
||||
private final Map<String, DownloadJob> jobs = new ConcurrentHashMap<String, DownloadJob>();
|
||||
private String listTmpltScr;
|
||||
private String listVolScr;
|
||||
private int installTimeoutPerGig = 180 * 60 * 1000;
|
||||
private boolean _sslCopy;
|
||||
|
||||
|
|
@ -317,23 +318,28 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
private String postDownload(String jobId) {
|
||||
DownloadJob dnld = jobs.get(jobId);
|
||||
TemplateDownloader td = dnld.getTemplateDownloader();
|
||||
String templatePath = null;
|
||||
templatePath = dnld.getInstallPathPrefix() + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;// dnld.getTmpltName();
|
||||
String resourcePath = null;
|
||||
ResourceType resourceType = dnld.getResourceType();
|
||||
|
||||
_storage.mkdirs(templatePath);
|
||||
|
||||
|
||||
// once template path is set, remove the parent dir so that the template is installed with a relative path
|
||||
String finalTemplatePath = resourceType == ResourceType.TEMPLATE ? _templateDir : _volumeDir
|
||||
+ File.separator + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;
|
||||
dnld.setTmpltPath(finalTemplatePath);
|
||||
String finalResourcePath = "";
|
||||
if (resourceType == ResourceType.TEMPLATE){
|
||||
finalResourcePath += _templateDir + File.separator + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;
|
||||
resourcePath = dnld.getInstallPathPrefix() + dnld.getAccountId() + File.separator + dnld.getId() + File.separator;// dnld.getTmpltName();
|
||||
}else {
|
||||
finalResourcePath += _volumeDir + File.separator + dnld.getId() + File.separator;
|
||||
resourcePath = dnld.getInstallPathPrefix() + dnld.getId() + File.separator;// dnld.getTmpltName();
|
||||
}
|
||||
|
||||
_storage.mkdirs(resourcePath);
|
||||
dnld.setTmpltPath(finalResourcePath);
|
||||
|
||||
int imgSizeGigs = (int) Math.ceil(_storage.getSize(td.getDownloadLocalPath()) * 1.0d / (1024 * 1024 * 1024));
|
||||
imgSizeGigs++; // add one just in case
|
||||
long timeout = imgSizeGigs * installTimeoutPerGig;
|
||||
Script scr = null;
|
||||
String script = resourceType == ResourceType.TEMPLATE ? createTmpltScr : createVolScr;
|
||||
scr = new Script(createTmpltScr, timeout, s_logger);
|
||||
scr = new Script(script, timeout, s_logger);
|
||||
scr.add("-s", Integer.toString(imgSizeGigs));
|
||||
scr.add("-S", Long.toString(td.getMaxTemplateSizeInBytes()));
|
||||
if (dnld.getDescription() != null && dnld.getDescription().length() > 1) {
|
||||
|
|
@ -353,10 +359,10 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
}
|
||||
|
||||
String templateFilename = templateName + "." + extension;
|
||||
dnld.setTmpltPath(finalTemplatePath + "/" + templateFilename);
|
||||
dnld.setTmpltPath(finalResourcePath + "/" + templateFilename);
|
||||
scr.add("-n", templateFilename);
|
||||
|
||||
scr.add("-t", templatePath);
|
||||
scr.add("-t", resourcePath);
|
||||
scr.add("-f", td.getDownloadLocalPath());
|
||||
if (dnld.getChecksum() != null && dnld.getChecksum().length() > 1) {
|
||||
scr.add("-c", dnld.getChecksum());
|
||||
|
|
@ -370,18 +376,24 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
}
|
||||
|
||||
// Set permissions for the downloaded template
|
||||
File downloadedTemplate = new File(templatePath + "/" + templateFilename);
|
||||
File downloadedTemplate = new File(resourcePath + "/" + templateFilename);
|
||||
_storage.setWorldReadableAndWriteable(downloadedTemplate);
|
||||
|
||||
// Set permissions for template.properties
|
||||
File templateProperties = new File(templatePath + "/template.properties");
|
||||
// Set permissions for template/volume.properties
|
||||
String propertiesFile = resourcePath;
|
||||
if (resourceType == ResourceType.TEMPLATE){
|
||||
propertiesFile += "/template.properties";
|
||||
}else{
|
||||
propertiesFile += "/volume.properties";
|
||||
}
|
||||
File templateProperties = new File(propertiesFile);
|
||||
_storage.setWorldReadableAndWriteable(templateProperties);
|
||||
|
||||
TemplateLocation loc = new TemplateLocation(_storage, templatePath);
|
||||
TemplateLocation loc = new TemplateLocation(_storage, resourcePath);
|
||||
try {
|
||||
loc.create(dnld.getId(), true, dnld.getTmpltName());
|
||||
} catch (IOException e) {
|
||||
s_logger.warn("Something is wrong with template location " + templatePath, e);
|
||||
s_logger.warn("Something is wrong with template location " + resourcePath, e);
|
||||
loc.purge();
|
||||
return "Unable to download due to " + e.getMessage();
|
||||
}
|
||||
|
|
@ -392,7 +404,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
|
||||
FormatInfo info = null;
|
||||
try {
|
||||
info = processor.process(templatePath, null, templateName);
|
||||
info = processor.process(resourcePath, null, templateName);
|
||||
} catch (InternalErrorException e) {
|
||||
s_logger.error("Template process exception ", e);
|
||||
return e.toString();
|
||||
|
|
@ -432,7 +444,12 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
public String downloadPublicTemplate(long id, String url, String name, ImageFormat format, boolean hvm, Long accountId, String descr, String cksum, String installPathPrefix, String user, String password, long maxTemplateSizeInBytes, Proxy proxy, ResourceType resourceType) {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
String jobId = uuid.toString();
|
||||
String tmpDir = installPathPrefix + File.separator + accountId + File.separator + id;
|
||||
String tmpDir = "";
|
||||
if(resourceType == ResourceType.TEMPLATE){
|
||||
tmpDir = installPathPrefix + File.separator + accountId + File.separator + id;
|
||||
}else {
|
||||
tmpDir = installPathPrefix + File.separator + id;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
|
|
@ -672,6 +689,19 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private List<String> listVolumes(String rootdir) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
|
||||
Script script = new Script(listVolScr, s_logger);
|
||||
script.add("-r", rootdir);
|
||||
ZfsPathParser zpp = new ZfsPathParser(rootdir);
|
||||
script.execute(zpp);
|
||||
result.addAll(zpp.getPaths());
|
||||
s_logger.info("found " + zpp.getPaths().size() + " volumes" + zpp.getPaths());
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<String> listTemplates(String rootdir) {
|
||||
List<String> result = new ArrayList<String>();
|
||||
|
||||
|
|
@ -849,6 +879,12 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
}
|
||||
s_logger.info("createtmplt.sh found in " + createTmpltScr);
|
||||
|
||||
/*listVolScr = Script.findScript(scriptsDir, "listvolume.sh");
|
||||
if (listVolScr == null) {
|
||||
throw new ConfigurationException("Unable to find the listvolume.sh");
|
||||
}
|
||||
s_logger.info("listvolume.sh found in " + listVolScr);*/
|
||||
|
||||
createVolScr = Script.findScript(scriptsDir, "createvolume.sh");
|
||||
if (createVolScr == null) {
|
||||
throw new ConfigurationException("Unable to find createvolume.sh");
|
||||
|
|
@ -884,7 +920,7 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
_templateDir = TemplateConstants.DEFAULT_TMPLT_ROOT_DIR;
|
||||
}
|
||||
_templateDir += File.separator + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR;
|
||||
_volumeDir = TemplateConstants.DEFAULT_VOLUME_ROOT_DIR;
|
||||
_volumeDir = TemplateConstants.DEFAULT_VOLUME_ROOT_DIR + File.separator;
|
||||
// Add more processors here.
|
||||
threadPool = Executors.newFixedThreadPool(numInstallThreads);
|
||||
return true;
|
||||
|
|
@ -959,4 +995,10 @@ public class DownloadManagerImpl implements DownloadManager {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, TemplateInfo> gatherVolumeInfo(String volumeDir) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package com.cloud.storage.template;
|
|||
*/
|
||||
public final class TemplateConstants {
|
||||
public static final String DEFAULT_TMPLT_ROOT_DIR = "template";
|
||||
public static final String DEFAULT_VOLUME_ROOT_DIR = "volume";
|
||||
public static final String DEFAULT_VOLUME_ROOT_DIR = "volumes";
|
||||
public static final String DEFAULT_TMPLT_FIRST_LEVEL_DIR = "tmpl/";
|
||||
|
||||
public static final String DEFAULT_SYSTEM_VM_TEMPLATE_PATH = "template/tmpl/1/";
|
||||
|
|
|
|||
|
|
@ -48,7 +48,12 @@ public class TemplateLocation {
|
|||
}
|
||||
_formats = new ArrayList<FormatInfo>(5);
|
||||
_props = new Properties();
|
||||
_file = _storage.getFile(_templatePath + Filename);
|
||||
//TO DO remove this hack
|
||||
if (_templatePath.matches(".*"+"volumes"+".*")){
|
||||
_file = _storage.getFile(_templatePath + "volume.properties");
|
||||
}else {
|
||||
_file = _storage.getFile(_templatePath + Filename);
|
||||
}
|
||||
_isCorrupted = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -220,4 +220,10 @@ public interface StorageManager extends StorageService, Manager {
|
|||
List<Long> getUpHostsInPool(long poolId);
|
||||
|
||||
void cleanupSecondaryStorage(boolean recurring);
|
||||
}
|
||||
|
||||
VolumeVO copyVolumeFromSecToPrimary(VolumeVO volume, VMInstanceVO vm,
|
||||
VMTemplateVO template, DataCenterVO dc, HostPodVO pod,
|
||||
Long clusterId, ServiceOfferingVO offering,
|
||||
DiskOfferingVO diskOffering, List<StoragePoolVO> avoids, long size,
|
||||
HypervisorType hyperType) throws NoTransitionException;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ import com.cloud.service.ServiceOfferingVO;
|
|||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Volume.Event;
|
||||
import com.cloud.storage.Volume.Type;
|
||||
import com.cloud.storage.allocator.StoragePoolAllocator;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
|
|
@ -144,6 +145,7 @@ import com.cloud.storage.dao.VMTemplateHostDao;
|
|||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
import com.cloud.storage.dao.VMTemplateSwiftDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.dao.VolumeHostDao;
|
||||
import com.cloud.storage.download.DownloadMonitor;
|
||||
import com.cloud.storage.listener.StoragePoolMonitor;
|
||||
import com.cloud.storage.secondary.SecondaryStorageVmManager;
|
||||
|
|
@ -255,6 +257,8 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||
@Inject
|
||||
protected UserVmDao _userVmDao;
|
||||
@Inject
|
||||
VolumeHostDao _volumeHostDao;
|
||||
@Inject
|
||||
protected VMInstanceDao _vmInstanceDao;
|
||||
@Inject
|
||||
protected StoragePoolDao _storagePoolDao = null;
|
||||
|
|
@ -706,6 +710,53 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||
return new Pair<String, String>(vdiUUID, basicErrMsg);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public VolumeVO copyVolumeFromSecToPrimary(VolumeVO volume, VMInstanceVO vm, VMTemplateVO template, DataCenterVO dc, HostPodVO pod, Long clusterId, ServiceOfferingVO offering, DiskOfferingVO diskOffering,
|
||||
List<StoragePoolVO> avoids, long size, HypervisorType hyperType) throws NoTransitionException {
|
||||
|
||||
final HashSet<StoragePool> avoidPools = new HashSet<StoragePool>(avoids);
|
||||
DiskProfile dskCh = createDiskCharacteristics(volume, template, dc, diskOffering);
|
||||
dskCh.setHyperType(vm.getHypervisorType());
|
||||
// Find a suitable storage to create volume on
|
||||
StoragePoolVO destPool = findStoragePool(dskCh, dc, pod, clusterId, vm, avoidPools);
|
||||
|
||||
// Copy the volume from secondary storage to the destination storage pool
|
||||
stateTransitTo(volume, Event.CopyRequested);
|
||||
VolumeHostVO volumeHostVO = _volumeHostDao.findByVolumeId(volume.getId());
|
||||
HostVO secStorage = _hostDao.findById(volumeHostVO.getHostId());
|
||||
String secondaryStorageURL = secStorage.getStorageUrl();
|
||||
String[] volumePath = volumeHostVO.getInstallPath().split("/");
|
||||
String volumeUUID = volumePath[volumePath.length - 1].split("\\.")[0];
|
||||
|
||||
CopyVolumeCommand cvCmd = new CopyVolumeCommand(volume.getId(), volumeUUID, destPool, secondaryStorageURL, false, _copyvolumewait);
|
||||
CopyVolumeAnswer cvAnswer;
|
||||
try {
|
||||
cvAnswer = (CopyVolumeAnswer) sendToPool(destPool, cvCmd);
|
||||
} catch (StorageUnavailableException e1) {
|
||||
stateTransitTo(volume, Event.CopyFailed);
|
||||
throw new CloudRuntimeException("Failed to copy the volume from secondary storage to the destination primary storage pool.");
|
||||
}
|
||||
|
||||
if (cvAnswer == null || !cvAnswer.getResult()) {
|
||||
stateTransitTo(volume, Event.CopyFailed);
|
||||
throw new CloudRuntimeException("Failed to copy the volume from secondary storage to the destination primary storage pool.");
|
||||
}
|
||||
Transaction txn = Transaction.currentTxn();
|
||||
txn.start();
|
||||
volume.setPath(cvAnswer.getVolumePath());
|
||||
volume.setFolder(destPool.getPath());
|
||||
volume.setPodId(destPool.getPodId());
|
||||
volume.setPoolId(destPool.getId());
|
||||
volume.setPodId(destPool.getPodId());
|
||||
stateTransitTo(volume, Event.CopySucceeded);
|
||||
_volumeHostDao.remove(volumeHostVO.getId());
|
||||
txn.commit();
|
||||
return volume;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public VolumeVO createVolume(VolumeVO volume, VMInstanceVO vm, VMTemplateVO template, DataCenterVO dc, HostPodVO pod, Long clusterId, ServiceOfferingVO offering, DiskOfferingVO diskOffering,
|
||||
|
|
@ -1748,7 +1799,7 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||
volume.setAccountId(ownerId);
|
||||
volume.setDomainId(((caller == null) ? Domain.ROOT_DOMAIN : caller.getDomainId()));
|
||||
long diskOfferingId = _diskOfferingDao.findByUniqueName("Cloud.com-Custom").getId();
|
||||
volume.setDiskOfferingId(diskOfferingId);
|
||||
volume.setDiskOfferingId(diskOfferingId);
|
||||
//volume.setSize(size);
|
||||
volume.setInstanceId(null);
|
||||
volume.setUpdated(new Date());
|
||||
|
|
@ -1757,7 +1808,12 @@ public class StorageManagerImpl implements StorageManager, Manager, ClusterManag
|
|||
volume = _volsDao.persist(volume);
|
||||
UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), diskOfferingId, null, 0l);
|
||||
_usageEventDao.persist(usageEvent);
|
||||
|
||||
try {
|
||||
stateTransitTo(volume, Event.UploadRequested);
|
||||
} catch (NoTransitionException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
UserContext.current().setEventDetails("Volume Id: " + volume.getId());
|
||||
|
||||
// Increment resource count during allocation; if actual creation fails, decrement it
|
||||
|
|
|
|||
|
|
@ -7,4 +7,6 @@ public interface VolumeHostDao extends GenericDao<VolumeHostVO, Long> {
|
|||
|
||||
VolumeHostVO findByHostVolume(long id, long id2);
|
||||
|
||||
VolumeHostVO findByVolumeId(long volumeId);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
package com.cloud.storage.dao;
|
||||
|
||||
|
||||
import javax.ejb.Local;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import com.cloud.storage.VolumeHostVO;
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
|
|
@ -11,6 +12,7 @@ import com.cloud.utils.db.SearchCriteria;
|
|||
public class VolumeHostDaoImpl extends GenericDaoBase<VolumeHostVO, Long> implements VolumeHostDao {
|
||||
|
||||
protected final SearchBuilder<VolumeHostVO> HostVolumeSearch;
|
||||
protected final SearchBuilder<VolumeHostVO> VolumeSearch;
|
||||
|
||||
VolumeHostDaoImpl(){
|
||||
HostVolumeSearch = createSearchBuilder();
|
||||
|
|
@ -18,6 +20,11 @@ public class VolumeHostDaoImpl extends GenericDaoBase<VolumeHostVO, Long> implem
|
|||
HostVolumeSearch.and("volume_id", HostVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
|
||||
HostVolumeSearch.and("destroyed", HostVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
HostVolumeSearch.done();
|
||||
|
||||
VolumeSearch = createSearchBuilder();
|
||||
VolumeSearch.and("volume_id", VolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
|
||||
VolumeSearch.and("destroyed", VolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
|
||||
VolumeSearch.done();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -30,5 +37,13 @@ public class VolumeHostDaoImpl extends GenericDaoBase<VolumeHostVO, Long> implem
|
|||
sc.setParameters("destroyed", false);
|
||||
return findOneIncludingRemovedBy(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VolumeHostVO findByVolumeId(long volumeId) {
|
||||
SearchCriteria<VolumeHostVO> sc = VolumeSearch.create();
|
||||
sc.setParameters("volume_id", volumeId);
|
||||
sc.setParameters("destroyed", false);
|
||||
return findOneBy(sc);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,16 +33,19 @@ import com.cloud.agent.api.StartupStorageCommand;
|
|||
import com.cloud.agent.api.storage.DownloadAnswer;
|
||||
import com.cloud.agent.api.storage.DownloadCommand;
|
||||
import com.cloud.agent.api.storage.DownloadProgressCommand;
|
||||
import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
|
||||
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.ConnectionException;
|
||||
import com.cloud.host.HostVO;
|
||||
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.VMTemplateHostVO;
|
||||
import com.cloud.storage.VolumeHostVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
import com.cloud.storage.Volume.Event;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VMTemplateHostDao;
|
||||
|
|
@ -50,6 +53,7 @@ import com.cloud.storage.dao.VolumeDao;
|
|||
import com.cloud.storage.dao.VolumeHostDao;
|
||||
import com.cloud.storage.download.DownloadState.DownloadEvent;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
|
||||
/**
|
||||
* Monitor progress of template download to a single storage server
|
||||
|
|
@ -108,7 +112,8 @@ public class DownloadListener implements Listener {
|
|||
private boolean downloadActive = true;
|
||||
|
||||
private VolumeHostDao volumeHostDao;
|
||||
private VolumeDao _volumeDao;
|
||||
private VolumeDao _volumeDao;
|
||||
private StorageManager _storageMgr;
|
||||
private VMTemplateHostDao vmTemplateHostDao;
|
||||
private VMTemplateDao _vmTemplateDao;
|
||||
|
||||
|
|
@ -146,7 +151,7 @@ public class DownloadListener implements Listener {
|
|||
updateDatabase(Status.NOT_DOWNLOADED, "");
|
||||
}
|
||||
|
||||
public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao) {
|
||||
public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr) {
|
||||
this.ssAgent = ssAgent;
|
||||
this.sserver = host;
|
||||
this.volume = volume;
|
||||
|
|
@ -160,6 +165,7 @@ public class DownloadListener implements Listener {
|
|||
this.timeoutTask = new TimeoutTask(this);
|
||||
this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL);
|
||||
this._volumeDao = volumeDao;
|
||||
this._storageMgr = storageMgr;
|
||||
updateDatabase(Status.NOT_DOWNLOADED, "");
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +192,11 @@ public class DownloadListener implements Listener {
|
|||
log("Sending progress command ", Level.TRACE);
|
||||
}
|
||||
try {
|
||||
downloadMonitor.send(ssAgent.getId(), new DownloadProgressCommand(getCommand(), getJobId(), reqType), this);
|
||||
DownloadProgressCommand dcmd = new DownloadProgressCommand(getCommand(), getJobId(), reqType);
|
||||
if (template == null){
|
||||
dcmd.setResourceType(ResourceType.VOLUME);
|
||||
}
|
||||
downloadMonitor.send(ssAgent.getId(), dcmd, this);
|
||||
} catch (AgentUnavailableException e) {
|
||||
s_logger.debug("Send command failed", e);
|
||||
setDisconnected();
|
||||
|
|
@ -328,6 +338,12 @@ public class DownloadListener implements Listener {
|
|||
updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize());
|
||||
|
||||
volumeHostDao.update(getVolumeHostId(), updateBuilder);
|
||||
try {
|
||||
_storageMgr.stateTransitTo(volume, Event.UploadSucceeded);
|
||||
} catch (NoTransitionException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
/*if (answer.getCheckSum() != null) {
|
||||
VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate();
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import com.cloud.agent.api.Command;
|
|||
import com.cloud.agent.api.storage.DeleteTemplateCommand;
|
||||
import com.cloud.agent.api.storage.DownloadCommand;
|
||||
import com.cloud.agent.api.storage.DownloadCommand.Proxy;
|
||||
import com.cloud.agent.api.storage.DownloadCommand.ResourceType;
|
||||
import com.cloud.agent.api.storage.DownloadProgressCommand;
|
||||
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
|
||||
import com.cloud.agent.api.storage.ListTemplateAnswer;
|
||||
|
|
@ -57,12 +58,14 @@ import com.cloud.host.dao.HostDao;
|
|||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.SwiftVO;
|
||||
import com.cloud.storage.VMTemplateHostVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||
import com.cloud.storage.VolumeHostVO;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
||||
import com.cloud.storage.Volume.Event;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.VMTemplateZoneVO;
|
||||
import com.cloud.storage.dao.StoragePoolHostDao;
|
||||
|
|
@ -86,6 +89,7 @@ import com.cloud.utils.db.SearchBuilder;
|
|||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.fsm.NoTransitionException;
|
||||
import com.cloud.vm.SecondaryStorageVm;
|
||||
import com.cloud.vm.SecondaryStorageVmVO;
|
||||
import com.cloud.vm.UserVmManager;
|
||||
|
|
@ -126,6 +130,8 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||
protected SwiftManager _swiftMgr;
|
||||
@Inject
|
||||
SecondaryStorageVmManager _ssvmMgr;
|
||||
@Inject
|
||||
StorageManager _storageMgr ;
|
||||
|
||||
@Inject
|
||||
private final DataCenterDao _dcDao = null;
|
||||
|
|
@ -423,12 +429,19 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||
|
||||
volumeHost = _volumeHostDao.findByHostVolume(sserver.getId(), volume.getId());
|
||||
if (volumeHost == null) {
|
||||
volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, url, checkSum);
|
||||
volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null,
|
||||
"jobid0000", null, url, checkSum);
|
||||
_volumeHostDao.persist(volumeHost);
|
||||
} else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) {
|
||||
downloadJobExists = true;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
_storageMgr.stateTransitTo(volume, Event.UploadRequested);
|
||||
} catch (NoTransitionException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes();
|
||||
String secUrl = sserver.getStorageUrl();
|
||||
if(volumeHost != null) {
|
||||
|
|
@ -437,6 +450,7 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||
dcmd.setProxy(getHttpProxy());
|
||||
if (downloadJobExists) {
|
||||
dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART);
|
||||
dcmd.setResourceType(ResourceType.VOLUME);
|
||||
}
|
||||
|
||||
HostVO ssvm = _ssvmMgr.pickSsvmHost(sserver);
|
||||
|
|
@ -444,7 +458,8 @@ public class DownloadMonitorImpl implements DownloadMonitor {
|
|||
s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName());
|
||||
return;
|
||||
}
|
||||
DownloadListener dl = new DownloadListener(ssvm, sserver, volume, _timer, _volumeHostDao, volumeHost.getId(), this, dcmd, _volumeDao);
|
||||
DownloadListener dl = new DownloadListener(ssvm, sserver, volume, _timer, _volumeHostDao, volumeHost.getId(),
|
||||
this, dcmd, _volumeDao, _storageMgr);
|
||||
|
||||
if (downloadJobExists) {
|
||||
dl.setCurrState(volumeHost.getDownloadState());
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ import com.cloud.storage.GuestOSVO;
|
|||
import com.cloud.storage.Snapshot;
|
||||
import com.cloud.storage.SnapshotVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.VolumeHostVO;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
|
|
@ -175,6 +176,7 @@ import com.cloud.storage.dao.VMTemplateDetailsDao;
|
|||
import com.cloud.storage.dao.VMTemplateHostDao;
|
||||
import com.cloud.storage.dao.VMTemplateZoneDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.dao.VolumeHostDao;
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import com.cloud.template.VirtualMachineTemplate;
|
||||
import com.cloud.template.VirtualMachineTemplate.BootloaderType;
|
||||
|
|
@ -335,6 +337,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||
SecurityGroupVMMapDao _securityGroupVMMapDao;
|
||||
@Inject
|
||||
protected ItWorkDao _workDao;
|
||||
VolumeHostDao _volumeHostDao;
|
||||
|
||||
|
||||
protected ScheduledExecutorService _executor = null;
|
||||
protected int _expungeInterval;
|
||||
|
|
@ -548,14 +552,20 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||
//permission check
|
||||
_accountMgr.checkAccess(caller, null, true, volume, vm);
|
||||
|
||||
//Check if volume is stored on secondary Storage.
|
||||
boolean volumeOnSec = false;
|
||||
VolumeHostVO volHostVO = _volumeHostDao.findByVolumeId(volume.getId());
|
||||
if (volHostVO != null){
|
||||
volumeOnSec = true;
|
||||
}
|
||||
|
||||
// Check that the volume is stored on shared storage
|
||||
if (!(Volume.State.Allocated.equals(volume.getState())) && !_storageMgr.volumeOnSharedStoragePool(volume)) {
|
||||
if (!(Volume.State.Allocated.equals(volume.getState()) || Volume.State.Uploaded.equals(volume.getState())) && !_storageMgr.volumeOnSharedStoragePool(volume)) {
|
||||
throw new InvalidParameterValueException("Please specify a volume that has been created on a shared storage pool.");
|
||||
}
|
||||
|
||||
if (!(Volume.State.Allocated.equals(volume.getState()) || Volume.State.Ready.equals(volume.getState()))) {
|
||||
throw new InvalidParameterValueException("Volume state must be in Allocated or Ready state");
|
||||
if ( !(Volume.State.Allocated.equals(volume.getState()) || Volume.State.Ready.equals(volume.getState()) || Volume.State.Uploaded.equals(volume.getState())) ) {
|
||||
throw new InvalidParameterValueException("Volume state must be in Allocated, Ready or Uploaded state");
|
||||
}
|
||||
|
||||
VolumeVO rootVolumeOfVm = null;
|
||||
|
|
@ -566,8 +576,31 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||
rootVolumeOfVm = rootVolumesOfVm.get(0);
|
||||
}
|
||||
|
||||
HypervisorType rootDiskHyperType = vm.getHypervisorType();
|
||||
|
||||
HypervisorType rootDiskHyperType = _volsDao.getHypervisorType(rootVolumeOfVm.getId());
|
||||
|
||||
if (volume.getState().equals(Volume.State.Allocated) || volume.getState().equals(Volume.State.Uploaded)) {
|
||||
/* Need to create the volume */
|
||||
VMTemplateVO rootDiskTmplt = _templateDao.findById(vm.getTemplateId());
|
||||
DataCenterVO dcVO = _dcDao.findById(vm.getDataCenterIdToDeployIn());
|
||||
HostPodVO pod = _podDao.findById(vm.getPodIdToDeployIn());
|
||||
StoragePoolVO rootDiskPool = _storagePoolDao.findById(rootVolumeOfVm.getPoolId());
|
||||
ServiceOfferingVO svo = _serviceOfferingDao.findById(vm.getServiceOfferingId());
|
||||
DiskOfferingVO diskVO = _diskOfferingDao.findById(volume.getDiskOfferingId());
|
||||
if (!volumeOnSec){
|
||||
volume = _storageMgr.createVolume(volume, vm, rootDiskTmplt, dcVO, pod, rootDiskPool.getClusterId(), svo, diskVO, new ArrayList<StoragePoolVO>(), volume.getSize(), rootDiskHyperType);
|
||||
}else {
|
||||
try {
|
||||
volume = _storageMgr.copyVolumeFromSecToPrimary(volume, vm, rootDiskTmplt, dcVO, pod, rootDiskPool.getClusterId(), svo, diskVO, new ArrayList<StoragePoolVO>(), volume.getSize(), rootDiskHyperType);
|
||||
} catch (NoTransitionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (volume == null) {
|
||||
throw new CloudRuntimeException("Failed to create volume when attaching it to VM: " + vm.getHostName());
|
||||
}
|
||||
}
|
||||
|
||||
HypervisorType dataDiskHyperType = _volsDao.getHypervisorType(volume.getId());
|
||||
if (dataDiskHyperType != HypervisorType.None && rootDiskHyperType != dataDiskHyperType) {
|
||||
throw new InvalidParameterValueException("Can't attach a volume created by: " + dataDiskHyperType + " to a " + rootDiskHyperType + " vm");
|
||||
|
|
|
|||
Loading…
Reference in New Issue