blob: 46f6fa7012d1f3af4dd8cc7915ec1d8111c7a6ef [file] [log] [blame]
/**
* Copyright (C) 2010 Cloud.com, Inc. All rights reserved.
*
* This software is licensed under the GNU General Public License v3 or later.
*
* It is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.cloud.storage.download;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.Listener;
import com.cloud.agent.api.Answer;
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.DownloadProgressCommand;
import com.cloud.agent.api.storage.ListTemplateAnswer;
import com.cloud.agent.api.storage.ListTemplateCommand;
import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType;
import com.cloud.alert.AlertManager;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventVO;
import com.cloud.event.dao.UsageEventDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.StorageUnavailableException;
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.storage.Storage.ImageFormat;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.VMTemplateHostVO;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplateHostDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VMTemplateZoneDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.storage.template.TemplateConstants;
import com.cloud.storage.template.TemplateInfo;
import com.cloud.user.Account;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.SecondaryStorageVmDao;
/**
* @author chiradeep
*
*/
@Local(value={DownloadMonitor.class})
public class DownloadMonitorImpl implements DownloadMonitor {
static final Logger s_logger = Logger.getLogger(DownloadMonitorImpl.class);
@Inject
VMTemplateHostDao _vmTemplateHostDao;
@Inject
VMTemplateZoneDao _vmTemplateZoneDao;
@Inject
VMTemplatePoolDao _vmTemplatePoolDao;
@Inject
StoragePoolHostDao _poolHostDao;
@Inject
SecondaryStorageVmDao _secStorageVmDao;
@Inject
AlertManager _alertMgr;
@Inject
private final DataCenterDao _dcDao = null;
@Inject
VMTemplateDao _templateDao = null;
@Inject
private AgentManager _agentMgr;
@Inject SecondaryStorageVmManager _secMgr;
@Inject
ConfigurationDao _configDao;
@Inject
UserVmManager _vmMgr;
@Inject
private UsageEventDao _usageEventDao;
@Inject
private ClusterDao _clusterDao;
@Inject
private HostDao _hostDao;
private String _name;
private Boolean _sslCopy = new Boolean(false);
private String _copyAuthPasswd;
protected SearchBuilder<VMTemplateHostVO> ReadyTemplateStatesSearch;
Timer _timer;
final Map<VMTemplateHostVO, DownloadListener> _listenerMap = new ConcurrentHashMap<VMTemplateHostVO, DownloadListener>();
public long send(Long hostId, Command cmd, Listener listener) {
return _agentMgr.gatherStats(hostId, cmd, listener);
}
@Override
public boolean configure(String name, Map<String, Object> params) {
_name = name;
final Map<String, String> configs = _configDao.getConfiguration("ManagementServer", params);
_sslCopy = Boolean.parseBoolean(configs.get("secstorage.encrypt.copy"));
String cert = configs.get("secstorage.ssl.cert.domain");
if (!"realhostip.com".equalsIgnoreCase(cert)) {
s_logger.warn("Only realhostip.com ssl cert is supported, ignoring self-signed and other certs");
}
_copyAuthPasswd = configs.get("secstorage.copy.password");
_agentMgr.registerForHostEvents(new DownloadListener(this), true, false, false);
ReadyTemplateStatesSearch = _vmTemplateHostDao.createSearchBuilder();
ReadyTemplateStatesSearch.and("download_state", ReadyTemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.EQ);
ReadyTemplateStatesSearch.and("destroyed", ReadyTemplateStatesSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
ReadyTemplateStatesSearch.and("host_id", ReadyTemplateStatesSearch.entity().getHostId(), SearchCriteria.Op.EQ);
SearchBuilder<VMTemplateVO> TemplatesWithNoChecksumSearch = _templateDao.createSearchBuilder();
TemplatesWithNoChecksumSearch.and("checksum", TemplatesWithNoChecksumSearch.entity().getChecksum(), SearchCriteria.Op.NULL);
ReadyTemplateStatesSearch.join("vm_template", TemplatesWithNoChecksumSearch, TemplatesWithNoChecksumSearch.entity().getId(),
ReadyTemplateStatesSearch.entity().getTemplateId(), JoinBuilder.JoinType.INNER);
TemplatesWithNoChecksumSearch.done();
ReadyTemplateStatesSearch.done();
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public boolean start() {
_timer = new Timer();
return true;
}
@Override
public boolean stop() {
return true;
}
public boolean isTemplateUpdateable(Long templateId) {
List<VMTemplateHostVO> downloadsInProgress =
_vmTemplateHostDao.listByTemplateStatus(templateId, VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS);
return (downloadsInProgress.size() == 0);
}
public boolean isTemplateUpdateable(Long templateId, Long datacenterId) {
List<VMTemplateHostVO> downloadsInProgress =
_vmTemplateHostDao.listByTemplateStatus(templateId, datacenterId, VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS);
return (downloadsInProgress.size() == 0);
}
@Override
public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) throws StorageUnavailableException{
boolean downloadJobExists = false;
VMTemplateHostVO destTmpltHost = null;
VMTemplateHostVO srcTmpltHost = null;
srcTmpltHost = _vmTemplateHostDao.findByHostTemplate(sourceServer.getId(), template.getId());
if (srcTmpltHost == null) {
throw new InvalidParameterValueException("Template " + template.getName() + " not associated with " + sourceServer.getName());
}
if( !_secMgr.generateSetupCommand(sourceServer.getId()) ){
return false;
}
String url = generateCopyUrl(sourceServer, srcTmpltHost);
if (url == null) {
s_logger.warn("Unable to start/resume copy of template " + template.getUniqueName() + " to " + destServer.getName() + ", no secondary storage vm in running state in source zone");
throw new StorageUnavailableException("No secondary VM in running state in zone " + sourceServer.getDataCenterId(), srcTmpltHost.getPoolId());
}
destTmpltHost = _vmTemplateHostDao.findByHostTemplate(destServer.getId(), template.getId());
if (destTmpltHost == null) {
destTmpltHost = new VMTemplateHostVO(destServer.getId(), template.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, url);
destTmpltHost.setCopy(true);
destTmpltHost.setPhysicalSize(srcTmpltHost.getPhysicalSize());
_vmTemplateHostDao.persist(destTmpltHost);
} else if ((destTmpltHost.getJobId() != null) && (destTmpltHost.getJobId().length() > 2)) {
downloadJobExists = true;
}
Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes();
if(destTmpltHost != null) {
start();
DownloadCommand dcmd =
new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes);
if (downloadJobExists) {
dcmd = new DownloadProgressCommand(dcmd, destTmpltHost.getJobId(), RequestType.GET_OR_RESTART);
}
HostVO ssAhost = _agentMgr.getSSAgent(destServer);
if( ssAhost == null ) {
s_logger.warn("There is no secondary storage VM for secondary storage host " + destServer.getName());
return false;
}
DownloadListener dl = new DownloadListener(ssAhost, destServer, template, _timer, _vmTemplateHostDao, destTmpltHost.getId(), this, dcmd);
if (downloadJobExists) {
dl.setCurrState(destTmpltHost.getDownloadState());
}
DownloadListener old = null;
synchronized (_listenerMap) {
old = _listenerMap.put(destTmpltHost, dl);
}
if( old != null ) {
old.abandon();
}
long result = send(ssAhost.getId(), dcmd, dl);
if (result == -1) {
s_logger.warn("Unable to start /resume COPY of template " + template.getUniqueName() + " to " + destServer.getName());
dl.setDisconnected();
dl.scheduleStatusCheck(RequestType.GET_OR_RESTART);
} else {
return true;
}
}
return false;
}
private String generateCopyUrl(String ipAddress, String dir, String path){
String hostname = ipAddress;
String scheme = "http";
if (_sslCopy) {
hostname = ipAddress.replace(".", "-");
hostname = hostname + ".realhostip.com";
scheme = "https";
}
return scheme + "://" + hostname + "/copy/SecStorage/" + dir + "/" + path;
}
private String generateCopyUrl(HostVO sourceServer, VMTemplateHostVO srcTmpltHost) {
List<SecondaryStorageVmVO> ssVms = _secStorageVmDao.getSecStorageVmListInStates(SecondaryStorageVm.Role.templateProcessor, sourceServer.getDataCenterId(), State.Running);
if (ssVms.size() > 0) {
SecondaryStorageVmVO ssVm = ssVms.get(0);
if (ssVm.getPublicIpAddress() == null) {
s_logger.warn("A running secondary storage vm has a null public ip?");
return null;
}
return generateCopyUrl(ssVm.getPublicIpAddress(), sourceServer.getParent(), srcTmpltHost.getInstallPath());
}
VMTemplateVO tmplt = _templateDao.findById(srcTmpltHost.getTemplateId());
HypervisorType hyperType = tmplt.getHypervisorType();
/*No secondary storage vm yet*/
if (hyperType != null && hyperType == HypervisorType.KVM) {
return "file://" + sourceServer.getParent() + "/" + srcTmpltHost.getInstallPath();
}
return null;
}
private void downloadTemplateToStorage(VMTemplateVO template, HostVO sserver) {
boolean downloadJobExists = false;
VMTemplateHostVO vmTemplateHost = null;
vmTemplateHost = _vmTemplateHostDao.findByHostTemplate(sserver.getId(), template.getId());
if (vmTemplateHost == null) {
vmTemplateHost = new VMTemplateHostVO(sserver.getId(), template.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, template.getUrl());
_vmTemplateHostDao.persist(vmTemplateHost);
} else if ((vmTemplateHost.getJobId() != null) && (vmTemplateHost.getJobId().length() > 2)) {
downloadJobExists = true;
}
Long maxTemplateSizeInBytes = getMaxTemplateSizeInBytes();
String secUrl = sserver.getStorageUrl();
if(vmTemplateHost != null) {
start();
DownloadCommand dcmd =
new DownloadCommand(secUrl, template, maxTemplateSizeInBytes);
if (downloadJobExists) {
dcmd = new DownloadProgressCommand(dcmd, vmTemplateHost.getJobId(), RequestType.GET_OR_RESTART);
}
if (vmTemplateHost.isCopy()) {
dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd);
}
HostVO ssAhost = _agentMgr.getSSAgent(sserver);
if( ssAhost == null ) {
s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName());
return;
}
DownloadListener dl = new DownloadListener(ssAhost, sserver, template, _timer, _vmTemplateHostDao, vmTemplateHost.getId(), this, dcmd);
if (downloadJobExists) {
dl.setCurrState(vmTemplateHost.getDownloadState());
}
DownloadListener old = null;
synchronized (_listenerMap) {
old = _listenerMap.put(vmTemplateHost, dl);
}
if( old != null ) {
old.abandon();
}
long result = send(ssAhost.getId(), dcmd, dl);
if (result == -1) {
s_logger.warn("Unable to start /resume download of template " + template.getUniqueName() + " to " + sserver.getName());
dl.setDisconnected();
dl.scheduleStatusCheck(RequestType.GET_OR_RESTART);
}
}
}
@Override
public boolean downloadTemplateToStorage(Long templateId, Long zoneId) {
List<DataCenterVO> dcs = new ArrayList<DataCenterVO>();
if (zoneId == null) {
dcs.addAll(_dcDao.listAll());
} else {
dcs.add(_dcDao.findById(zoneId));
}
for ( DataCenterVO dc : dcs ) {
List<HostVO> ssHosts = _hostDao.listAllSecondaryStorageHosts(dc.getId());
for ( HostVO ssHost : ssHosts ) {
if (isTemplateUpdateable(ssHost.getId(), templateId)) {
initiateTemplateDownload(templateId, ssHost);
}
}
}
return true;
}
private void initiateTemplateDownload(Long templateId, HostVO ssHost) {
VMTemplateVO template = _templateDao.findById(templateId);
if (template != null && (template.getUrl() != null)) {
//find all storage hosts and tell them to initiate download
downloadTemplateToStorage(template, ssHost);
}
}
public void handleDownloadEvent(HostVO host, VMTemplateVO template, Status dnldStatus) {
if ((dnldStatus == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) || (dnldStatus==Status.ABANDONED)){
VMTemplateHostVO vmTemplateHost = new VMTemplateHostVO(host.getId(), template.getId());
synchronized (_listenerMap) {
_listenerMap.remove(vmTemplateHost);
}
}
VMTemplateHostVO vmTemplateHost = _vmTemplateHostDao.findByHostTemplate(host.getId(), template.getId());
if (dnldStatus == Status.DOWNLOADED) {
long size = -1;
if(vmTemplateHost!=null){
size = vmTemplateHost.getPhysicalSize();
}
else{
s_logger.warn("Failed to get size for template" + template.getName());
}
String eventType = EventTypes.EVENT_TEMPLATE_CREATE;
if((template.getFormat()).equals(ImageFormat.ISO)){
eventType = EventTypes.EVENT_ISO_CREATE;
}
if(template.getAccountId() != Account.ACCOUNT_ID_SYSTEM){
UsageEventVO usageEvent = new UsageEventVO(eventType, template.getAccountId(), host.getDataCenterId(), template.getId(), template.getName(), null, template.getSourceTemplateId() , size);
_usageEventDao.persist(usageEvent);
}
}
if (vmTemplateHost != null) {
Long poolId = vmTemplateHost.getPoolId();
if (poolId != null) {
VMTemplateStoragePoolVO vmTemplatePool = _vmTemplatePoolDao.findByPoolTemplate(poolId, template.getId());
StoragePoolHostVO poolHost = _poolHostDao.findByPoolHost(poolId, host.getId());
if (vmTemplatePool != null && poolHost != null) {
vmTemplatePool.setDownloadPercent(vmTemplateHost.getDownloadPercent());
vmTemplatePool.setDownloadState(vmTemplateHost.getDownloadState());
vmTemplatePool.setErrorString(vmTemplateHost.getErrorString());
String localPath = poolHost.getLocalPath();
String installPath = vmTemplateHost.getInstallPath();
if (installPath != null) {
if (!installPath.startsWith("/")) {
installPath = "/" + installPath;
}
if (!(localPath == null) && !installPath.startsWith(localPath)) {
localPath = localPath.replaceAll("/\\p{Alnum}+/*$", ""); //remove instance if necessary
}
if (!(localPath == null) && installPath.startsWith(localPath)) {
installPath = installPath.substring(localPath.length());
}
}
vmTemplatePool.setInstallPath(installPath);
vmTemplatePool.setLastUpdated(vmTemplateHost.getLastUpdated());
vmTemplatePool.setJobId(vmTemplateHost.getJobId());
vmTemplatePool.setLocalDownloadPath(vmTemplateHost.getLocalDownloadPath());
_vmTemplatePoolDao.update(vmTemplatePool.getId(),vmTemplatePool);
}
}
}
}
@Override
public void handleSysTemplateDownload(HostVO host) {
List<HypervisorType> hypers = _hostDao.getAvailHypervisorInZone(host.getId(), host.getDataCenterId());
HypervisorType hostHyper = host.getHypervisorType();
if (hypers.contains(hostHyper)) {
return;
}
Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>();
List<HostVO> ssHosts = _hostDao.listBy(Host.Type.SecondaryStorage, host.getDataCenterId());
if (ssHosts == null || ssHosts.isEmpty()) {
return;
}
/*Download all the templates in zone with the same hypervisortype*/
for ( HostVO ssHost : ssHosts) {
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (rtngTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(rtngTmplt);
}
}
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (builtinTmplt.getHypervisorType() == hostHyper) {
toBeDownloaded.add(builtinTmplt);
}
}
for (VMTemplateVO template: toBeDownloaded) {
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(ssHost.getId(), template.getId());
if (tmpltHost == null || tmpltHost.getDownloadState() != Status.DOWNLOADED) {
downloadTemplateToStorage(template, ssHost);
}
}
}
}
@Override
public void addSystemVMTemplatesToHost(HostVO host, Map<String, TemplateInfo> templateInfos){
if ( templateInfos == null ) {
return;
}
Long hostId = host.getId();
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
for ( VMTemplateVO tmplt : rtngTmplts ) {
TemplateInfo tmpltInfo = templateInfos.get(tmplt.getUniqueName());
if ( tmpltInfo == null ) {
continue;
}
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(hostId, tmplt.getId());
if ( tmpltHost == null ) {
tmpltHost = new VMTemplateHostVO(hostId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl());
tmpltHost.setSize(tmpltInfo.getSize());
tmpltHost.setPhysicalSize(tmpltInfo.getPhysicalSize());
_vmTemplateHostDao.persist(tmpltHost);
}
}
}
@Override
public void handleTemplateSync(long dcId) {
List<HostVO> ssHosts = _hostDao.listSecondaryStorageHosts(dcId);
for ( HostVO ssHost : ssHosts ) {
handleTemplateSync(ssHost);
}
}
private Map<String, TemplateInfo> listTemplate(HostVO ssHost) {
ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getStorageUrl());
Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd);
if (answer != null && answer.getResult()) {
ListTemplateAnswer tanswer = (ListTemplateAnswer)answer;
return tanswer.getTemplateInfo();
} else {
if (s_logger.isDebugEnabled()) {
s_logger.debug("can not list template for secondary storage host " + ssHost.getId());
}
}
return null;
}
@Override
public void handleTemplateSync(HostVO ssHost) {
if (ssHost == null) {
s_logger.warn("Huh? ssHost is null");
return;
}
long sserverId = ssHost.getId();
long zoneId = ssHost.getDataCenterId();
if (!(ssHost.getType() == Host.Type.SecondaryStorage || ssHost.getType() == Host.Type.LocalSecondaryStorage)) {
s_logger.warn("Huh? Agent id " + sserverId + " is not secondary storage host");
return;
}
Map<String, TemplateInfo> templateInfos = listTemplate(ssHost);
if (templateInfos == null) {
return;
}
Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>();
List<VMTemplateVO> allTemplates = _templateDao.listAllInZone(zoneId);
List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates();
List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates();
if (rtngTmplts != null) {
for (VMTemplateVO rtngTmplt : rtngTmplts) {
if (!allTemplates.contains(rtngTmplt)) {
allTemplates.add(rtngTmplt);
}
}
}
if (defaultBuiltin != null) {
for (VMTemplateVO builtinTmplt : defaultBuiltin) {
if (!allTemplates.contains(builtinTmplt)) {
allTemplates.add(builtinTmplt);
}
}
}
toBeDownloaded.addAll(allTemplates);
for (VMTemplateVO tmplt : allTemplates) {
String uniqueName = tmplt.getUniqueName();
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(sserverId, tmplt.getId());
if (templateInfos.containsKey(uniqueName)) {
TemplateInfo tmpltInfo = templateInfos.remove(uniqueName);
toBeDownloaded.remove(tmplt);
if (tmpltHost != null) {
s_logger.info("Template Sync found " + uniqueName + " already in the template host table");
if (tmpltHost.getDownloadState() != Status.DOWNLOADED) {
tmpltHost.setErrorString("");
}
if (tmpltInfo.isCorrupted()) {
tmpltHost.setDownloadState(Status.DOWNLOAD_ERROR);
String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltHost.getId();
tmpltHost.setErrorString(msg);
s_logger.info("msg");
if (tmplt.getUrl() == null) {
msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in secondary storage: " + tmpltHost.getHostId();
s_logger.warn(msg);
} else {
toBeDownloaded.add(tmplt);
}
} else {
tmpltHost.setDownloadPercent(100);
tmpltHost.setDownloadState(Status.DOWNLOADED);
tmpltHost.setInstallPath(tmpltInfo.getInstallPath());
tmpltHost.setSize(tmpltInfo.getSize());
tmpltHost.setPhysicalSize(tmpltInfo.getPhysicalSize());
tmpltHost.setLastUpdated(new Date());
}
_vmTemplateHostDao.update(tmpltHost.getId(), tmpltHost);
} else {
tmpltHost = new VMTemplateHostVO(sserverId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl());
tmpltHost.setSize(tmpltInfo.getSize());
tmpltHost.setPhysicalSize(tmpltInfo.getPhysicalSize());
_vmTemplateHostDao.persist(tmpltHost);
VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(zoneId, tmplt.getId());
if (tmpltZoneVO == null) {
tmpltZoneVO = new VMTemplateZoneVO(zoneId, tmplt.getId(), new Date());
_vmTemplateZoneDao.persist(tmpltZoneVO);
} else {
tmpltZoneVO.setLastUpdated(new Date());
_vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO);
}
}
continue;
}
if (tmpltHost != null && tmpltHost.getDownloadState() != Status.DOWNLOADED) {
s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + sserverId + ", will request download to start/resume shortly");
} else if (tmpltHost == null) {
s_logger.info("Template Sync did not find " + uniqueName + " on the server " + sserverId + ", will request download shortly");
VMTemplateHostVO templtHost = new VMTemplateHostVO(sserverId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl());
_vmTemplateHostDao.persist(templtHost);
VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(zoneId, tmplt.getId());
if (tmpltZoneVO == null) {
tmpltZoneVO = new VMTemplateZoneVO(zoneId, tmplt.getId(), new Date());
_vmTemplateZoneDao.persist(tmpltZoneVO);
} else {
tmpltZoneVO.setLastUpdated(new Date());
_vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO);
}
}
}
if (toBeDownloaded.size() > 0) {
/* Only download templates whose hypervirsor type is in the zone */
List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId);
if (availHypers.isEmpty()) {
/*
* This is for cloudzone, local secondary storage resource
* started before cluster created
*/
availHypers.add(HypervisorType.KVM);
}
/* Baremetal need not to download any template */
availHypers.remove(HypervisorType.BareMetal);
availHypers.add(HypervisorType.None); // bug 9809: resume ISO
// download.
for (VMTemplateVO tmplt : toBeDownloaded) {
if (tmplt.getUrl() == null) { // If url is null we can't
// initiate the download
continue;
}
// if this is private template, and there is no record for this
// template in this sHost, skip
if (!tmplt.isPublicTemplate() && !tmplt.isFeatured()) {
VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(sserverId, tmplt.getId());
if (tmpltHost == null) {
continue;
}
}
if (availHypers.contains(tmplt.getHypervisorType())) {
s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssHost.getName());
downloadTemplateToStorage(tmplt, ssHost);
}
}
}
for (String uniqueName : templateInfos.keySet()) {
TemplateInfo tInfo = templateInfos.get(uniqueName);
DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(ssHost.getStorageUrl(), tInfo.getInstallPath());
long result = _agentMgr.sendToSecStorage(ssHost, dtCommand, null);
if (result == -1) {
String description = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database";
s_logger.error(description);
return;
}
String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database, result=" + result;
s_logger.info(description);
}
}
@Override
public void cancelAllDownloads(Long templateId) {
List<VMTemplateHostVO> downloadsInProgress =
_vmTemplateHostDao.listByTemplateStates(templateId, VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS, VMTemplateHostVO.Status.NOT_DOWNLOADED);
if (downloadsInProgress.size() > 0){
for (VMTemplateHostVO vmthvo: downloadsInProgress) {
DownloadListener dl = null;
synchronized (_listenerMap) {
dl = _listenerMap.remove(vmthvo);
}
if (dl != null) {
dl.abandon();
s_logger.info("Stopping download of template " + templateId + " to storage server " + vmthvo.getHostId());
}
}
}
}
private void checksumSync(long hostId){
SearchCriteria<VMTemplateHostVO> sc = ReadyTemplateStatesSearch.create();
sc.setParameters("download_state", com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
sc.setParameters("host_id", hostId);
List<VMTemplateHostVO> templateHostRefList = _vmTemplateHostDao.search(sc, null);
s_logger.debug("Found " +templateHostRefList.size()+ " templates with no checksum. Will ask for computation");
for(VMTemplateHostVO templateHostRef : templateHostRefList){
s_logger.debug("Getting checksum for template - " + templateHostRef.getTemplateId());
String checksum = _vmMgr.getChecksum(hostId, templateHostRef.getInstallPath());
VMTemplateVO template = _templateDao.findById(templateHostRef.getTemplateId());
s_logger.debug("Setting checksum " +checksum+ " for template - " + template.getName());
template.setChecksum(checksum);
_templateDao.update(template.getId(), template);
}
}
private Long getMaxTemplateSizeInBytes() {
try {
return Long.parseLong(_configDao.getValue("max.template.iso.size")) * 1024L * 1024L * 1024L;
} catch (NumberFormatException e) {
return null;
}
}
}