Preliminary upload and attach changes work ..

This commit is contained in:
Nitin Mehta 2012-04-11 13:56:16 +05:30
parent 564cef8ddf
commit 54956280e6
16 changed files with 289 additions and 51 deletions

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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/";

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -7,4 +7,6 @@ public interface VolumeHostDao extends GenericDao<VolumeHostVO, Long> {
VolumeHostVO findByHostVolume(long id, long id2);
VolumeHostVO findByVolumeId(long volumeId);
}

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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());

View File

@ -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");