diff --git a/api/src/com/cloud/agent/api/storage/DeleteVolumeCommand.java b/api/src/com/cloud/agent/api/storage/DeleteVolumeCommand.java new file mode 100755 index 00000000000..77ad27c6ce2 --- /dev/null +++ b/api/src/com/cloud/agent/api/storage/DeleteVolumeCommand.java @@ -0,0 +1,22 @@ +package com.cloud.agent.api.storage; + +public class DeleteVolumeCommand extends ssCommand { + private String volumePath; + + public DeleteVolumeCommand() { + } + + public DeleteVolumeCommand(String secUrl, String volumePath) { + this.setSecUrl(secUrl); + this.volumePath = volumePath; + } + + @Override + public boolean executeInSequence() { + return true; + } + + public String getVolumePath() { + return volumePath; + } +} diff --git a/api/src/com/cloud/agent/api/storage/ListVolumeAnswer.java b/api/src/com/cloud/agent/api/storage/ListVolumeAnswer.java new file mode 100755 index 00000000000..1daa0f27041 --- /dev/null +++ b/api/src/com/cloud/agent/api/storage/ListVolumeAnswer.java @@ -0,0 +1,37 @@ +package com.cloud.agent.api.storage; + +import java.util.Map; + +import com.cloud.agent.api.Answer; +import com.cloud.storage.template.TemplateInfo; + +public class ListVolumeAnswer extends Answer { + private String secUrl; + private Map templateInfos; + + public ListVolumeAnswer() { + + } + + public ListVolumeAnswer(String secUrl, Map templateInfos) { + super(null, true, "success"); + this.setSecUrl(secUrl); + this.templateInfos = templateInfos; + } + + public Map getTemplateInfo() { + return templateInfos; + } + + public void setTemplateInfo(Map templateInfos) { + this.templateInfos = templateInfos; + } + + public void setSecUrl(String secUrl) { + this.secUrl = secUrl; + } + + public String getSecUrl() { + return secUrl; + } +} diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index fadaa386f13..3108067abd6 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -54,20 +54,20 @@ import com.cloud.agent.api.SecStorageSetupAnswer; import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.SecStorageSetupCommand.Certificates; import com.cloud.agent.api.StartupSecondaryStorageCommand; -import com.cloud.agent.api.SecStorageFirewallCfgCommand.PortConfig; import com.cloud.agent.api.SecStorageVMSetupCommand; import com.cloud.agent.api.StartupCommand; -import com.cloud.agent.api.StartupSecondaryStorageCommand; import com.cloud.agent.api.downloadSnapshotFromSwiftCommand; import com.cloud.agent.api.downloadTemplateFromSwiftToSecondaryStorageCommand; import com.cloud.agent.api.uploadTemplateToSwiftFromSecondaryStorageCommand; import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand; import com.cloud.agent.api.storage.DeleteEntityDownloadURLCommand; import com.cloud.agent.api.storage.DeleteTemplateCommand; +import com.cloud.agent.api.storage.DeleteVolumeCommand; 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.ListVolumeAnswer; import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.storage.UploadCommand; import com.cloud.agent.api.storage.ssCommand; @@ -156,7 +156,9 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return execute((ComputeChecksumCommand)cmd); } else if (cmd instanceof ListTemplateCommand){ return execute((ListTemplateCommand)cmd); - } else if (cmd instanceof downloadSnapshotFromSwiftCommand){ + } else if (cmd instanceof ListVolumeCommand){ + return execute((ListVolumeCommand)cmd); + }else if (cmd instanceof downloadSnapshotFromSwiftCommand){ return execute((downloadSnapshotFromSwiftCommand)cmd); } else if (cmd instanceof DeleteSnapshotBackupCommand){ return execute((DeleteSnapshotBackupCommand)cmd); @@ -709,8 +711,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } String root = getRootDir(cmd.getSecUrl()); - Map templateInfos = _dlMgr.gatherTemplateInfo(root); - return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); + Map templateInfos = _dlMgr.gatherVolumeInfo(root); + return new ListVolumeAnswer(cmd.getSecUrl(), templateInfos); } @@ -893,6 +895,54 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return new Answer(cmd, true, null); } + protected Answer execute(final DeleteVolumeCommand cmd) { + String relativeVolumePath = cmd.getVolumePath(); + String parent = getRootDir(cmd); + + if (relativeVolumePath.startsWith(File.separator)) { + relativeVolumePath = relativeVolumePath.substring(1); + } + + if (!parent.endsWith(File.separator)) { + parent += File.separator; + } + String absoluteVolumePath = parent + relativeVolumePath; + File tmpltParent = new File(absoluteVolumePath).getParentFile(); + String details = null; + if (!tmpltParent.exists()) { + details = "volume parent directory " + tmpltParent.getName() + " doesn't exist"; + s_logger.debug(details); + return new Answer(cmd, true, details); + } + File[] tmpltFiles = tmpltParent.listFiles(); + if (tmpltFiles == null || tmpltFiles.length == 0) { + details = "No files under volume parent directory " + tmpltParent.getName(); + s_logger.debug(details); + } else { + boolean found = false; + for (File f : tmpltFiles) { + if (!found && f.getName().equals("volume.properties")) { + found = true; + } + if (!f.delete()) { + return new Answer(cmd, false, "Unable to delete file " + f.getName() + " under Volume path " + + relativeVolumePath); + } + } + if (!found) { + details = "Can not find volume.properties under " + tmpltParent.getName(); + s_logger.debug(details); + } + } + if (!tmpltParent.delete()) { + details = "Unable to delete directory " + tmpltParent.getName() + " under Volume path " + + relativeVolumePath; + s_logger.debug(details); + return new Answer(cmd, false, details); + } + return new Answer(cmd, true, null); + } + Answer execute(CleanupSnapshotBackupCommand cmd) { String parent = getRootDir(cmd.getSecondaryStoragePoolURL()); if (!parent.endsWith(File.separator)) { diff --git a/core/src/com/cloud/storage/template/DownloadManager.java b/core/src/com/cloud/storage/template/DownloadManager.java index 306836e87da..fe841f81b9d 100644 --- a/core/src/com/cloud/storage/template/DownloadManager.java +++ b/core/src/com/cloud/storage/template/DownloadManager.java @@ -97,6 +97,7 @@ public interface DownloadManager extends Manager { /** * @return list of volume info for installed volumes */ - public Map gatherVolumeInfo(String volumeDir); + public Map gatherVolumeInfo(String volumeDir); + } \ No newline at end of file diff --git a/core/src/com/cloud/storage/template/DownloadManagerImpl.java b/core/src/com/cloud/storage/template/DownloadManagerImpl.java index 5867ac63eda..b1f09069622 100755 --- a/core/src/com/cloud/storage/template/DownloadManagerImpl.java +++ b/core/src/com/cloud/storage/template/DownloadManagerImpl.java @@ -702,6 +702,8 @@ public class DownloadManagerImpl implements DownloadManager { return result; } + + private List listTemplates(String rootdir) { List result = new ArrayList(); @@ -771,6 +773,52 @@ public class DownloadManagerImpl implements DownloadManager { return result; } + @Override + public Map gatherVolumeInfo(String rootDir) { + Map result = new HashMap(); + String volumeDir = rootDir + File.separator + _volumeDir; + + if (! _storage.exists(volumeDir)) { + _storage.mkdirs(volumeDir); + } + + List vols = listVolumes(volumeDir); + for (String vol : vols) { + String path = vol.substring(0, vol.lastIndexOf(File.separator)); + TemplateLocation loc = new TemplateLocation(_storage, path); + try { + if (!loc.load()) { + s_logger.warn("Post download installation was not completed for " + path); + //loc.purge(); + _storage.cleanup(path, volumeDir); + continue; + } + } catch (IOException e) { + s_logger.warn("Unable to load volume location " + path, e); + continue; + } + + TemplateInfo vInfo = loc.getTemplateInfo(); + + if ((vInfo.size == vInfo.physicalSize) && (vInfo.installPath.endsWith(ImageFormat.OVA.getFileExtension()))) { + try { + Processor processor = _processors.get("VMDK Processor"); + VmdkProcessor vmdkProcessor = (VmdkProcessor)processor; + long vSize = vmdkProcessor.getTemplateVirtualSize(path, vInfo.installPath.substring(vInfo.installPath.lastIndexOf(File.separator) + 1)); + vInfo.size = vSize; + loc.updateVirtualSize(vSize); + loc.save(); + } catch (Exception e) { + s_logger.error("Unable to get the virtual size of the volume: " + vInfo.installPath + " due to " + e.getMessage()); + } + } + + result.put(vInfo.getId(), vInfo); + s_logger.debug("Added volume name: " + vInfo.templateName + ", path: " + vol); + } + return result; + } + private int deleteDownloadDirectories(File downloadPath, int deleted) { try { if (downloadPath.exists()) { @@ -879,11 +927,11 @@ public class DownloadManagerImpl implements DownloadManager { } s_logger.info("createtmplt.sh found in " + createTmpltScr); - /*listVolScr = Script.findScript(scriptsDir, "listvolume.sh"); + 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);*/ + s_logger.info("listvolume.sh found in " + listVolScr); createVolScr = Script.findScript(scriptsDir, "createvolume.sh"); if (createVolScr == null) { @@ -995,10 +1043,5 @@ public class DownloadManagerImpl implements DownloadManager { return; } } - - @Override - public Map gatherVolumeInfo(String volumeDir) { - // TODO Auto-generated method stub - return null; - } + } diff --git a/core/src/com/cloud/storage/template/TemplateLocation.java b/core/src/com/cloud/storage/template/TemplateLocation.java index 42d591342ab..1071574bb2b 100644 --- a/core/src/com/cloud/storage/template/TemplateLocation.java +++ b/core/src/com/cloud/storage/template/TemplateLocation.java @@ -22,6 +22,7 @@ import java.util.Properties; import org.apache.log4j.Logger; +import com.cloud.agent.api.storage.DownloadCommand.ResourceType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; import com.cloud.storage.template.Processor.FormatInfo; @@ -34,6 +35,7 @@ public class TemplateLocation { StorageLayer _storage; String _templatePath; boolean _isCorrupted; + ResourceType _resourceType = ResourceType.TEMPLATE; File _file; Properties _props; @@ -48,9 +50,10 @@ public class TemplateLocation { } _formats = new ArrayList(5); _props = new Properties(); - //TO DO remove this hack + //TO DO - remove this hack if (_templatePath.matches(".*"+"volumes"+".*")){ _file = _storage.getFile(_templatePath + "volume.properties"); + _resourceType = ResourceType.VOLUME; }else { _file = _storage.getFile(_templatePath + Filename); } @@ -153,7 +156,11 @@ public class TemplateLocation { TemplateInfo tmplInfo = new TemplateInfo(); tmplInfo.id = Long.parseLong(_props.getProperty("id")); tmplInfo.installPath = _templatePath + File.separator + _props.getProperty("filename"); - tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("template")); + if (_resourceType == ResourceType.VOLUME){ + tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("volumes")); + }else { + tmplInfo.installPath = tmplInfo.installPath.substring(tmplInfo.installPath.indexOf("template")); + } tmplInfo.isCorrupted = _isCorrupted; tmplInfo.isPublic = Boolean.parseBoolean(_props.getProperty("public")); tmplInfo.templateName = _props.getProperty("uniquename"); diff --git a/scripts/storage/secondary/listvolume.sh b/scripts/storage/secondary/listvolume.sh new file mode 100755 index 00000000000..546813937fd --- /dev/null +++ b/scripts/storage/secondary/listvolume.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Copyright (C) 2011 Citrix Systems, 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 . +# + + + + + +# $Id: listvmvolume.sh 9132 2010-06-04 20:17:43Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/storage/secondary/listvmvolume.sh $ +# listvolume.sh -- list volumes under a directory + +usage() { + printf "Usage: %s: -r \n" $(basename $0) >&2 +} + + +#set -x + +rflag= +rootdir= + +while getopts 'r:' OPTION +do + case $OPTION in + r) rflag=1 + rootdir="$OPTARG" + ;; + ?) usage + exit 2 + ;; + esac +done + +if [ "$rflag" != "1" ] +then + usage + exit 2 +fi + + +for i in $(find /$rootdir -name volume.properties ); +do + d=$(dirname $i) + filename=$(grep "^filename" $i | awk -F"=" '{print $NF}') +# size=$(grep "virtualsize" $i | awk -F"=" '{print $NF}') +# if [ -n "$filename" ] && [ -n "$size" ] +# then +# d=$d/$filename/$size +# fi + echo ${d#/}/$filename #remove leading slash +done + +exit 0 diff --git a/server/src/com/cloud/storage/dao/VolumeHostDao.java b/server/src/com/cloud/storage/dao/VolumeHostDao.java index 33d46410897..96efd126595 100755 --- a/server/src/com/cloud/storage/dao/VolumeHostDao.java +++ b/server/src/com/cloud/storage/dao/VolumeHostDao.java @@ -1,12 +1,17 @@ package com.cloud.storage.dao; +import java.util.List; + +import com.cloud.host.HostVO; import com.cloud.storage.VolumeHostVO; import com.cloud.utils.db.GenericDao; public interface VolumeHostDao extends GenericDao { - VolumeHostVO findByHostVolume(long id, long id2); + VolumeHostVO findByHostVolume(long hostId, long volumeId); VolumeHostVO findByVolumeId(long volumeId); + List listBySecStorage(long sserverId); + } diff --git a/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java b/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java index 8f4b5e20729..fb1ad0afbad 100755 --- a/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java @@ -4,6 +4,8 @@ package com.cloud.storage.dao; import java.util.List; import javax.ejb.Local; + +import com.cloud.host.HostVO; import com.cloud.storage.VolumeHostVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -13,6 +15,7 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem protected final SearchBuilder HostVolumeSearch; protected final SearchBuilder VolumeSearch; + protected final SearchBuilder HostSearch; VolumeHostDaoImpl(){ HostVolumeSearch = createSearchBuilder(); @@ -21,6 +24,11 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem HostVolumeSearch.and("destroyed", HostVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); HostVolumeSearch.done(); + HostSearch = createSearchBuilder(); + HostSearch.and("host_id", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostSearch.and("destroyed", HostSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + HostSearch.done(); + VolumeSearch = createSearchBuilder(); VolumeSearch.and("volume_id", VolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); VolumeSearch.and("destroyed", VolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); @@ -46,4 +54,14 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem return findOneBy(sc); } + + + @Override + public List listBySecStorage(long ssHostId) { + SearchCriteria sc = HostSearch.create(); + sc.setParameters("host_id", ssHostId); + sc.setParameters("destroyed", false); + return listAll(); + } + } diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java index 62e3f3eeee4..970a70fda84 100755 --- a/server/src/com/cloud/storage/download/DownloadListener.java +++ b/server/src/com/cloud/storage/download/DownloadListener.java @@ -338,13 +338,14 @@ 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.getDownloadStatus() == Status.DOWNLOADED){ + try { + _storageMgr.stateTransitTo(volume, Event.UploadSucceeded); + } catch (NoTransitionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } } - /*if (answer.getCheckSum() != null) { VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate(); templateDaoBuilder.setChecksum(answer.getCheckSum()); @@ -379,9 +380,10 @@ public class DownloadListener implements Listener { storage.getResourceType() == Storage.StorageResourceType.LOCAL_SECONDARY_STORAGE ) { downloadMonitor.addSystemVMTemplatesToHost(agent, storage.getTemplateInfo()); downloadMonitor.handleTemplateSync(agent); + downloadMonitor.handleVolumeSync(agent); } } else if ( cmd instanceof StartupSecondaryStorageCommand ) { - downloadMonitor.handleTemplateSync(agent.getDataCenterId()); + downloadMonitor.handleSync(agent.getDataCenterId()); } } diff --git a/server/src/com/cloud/storage/download/DownloadMonitor.java b/server/src/com/cloud/storage/download/DownloadMonitor.java index 982776b2d20..c7dc600cebe 100644 --- a/server/src/com/cloud/storage/download/DownloadMonitor.java +++ b/server/src/com/cloud/storage/download/DownloadMonitor.java @@ -39,10 +39,12 @@ public interface DownloadMonitor extends Manager{ void handleSysTemplateDownload(HostVO hostId); - void handleTemplateSync(Long dcId); + void handleSync(Long dcId); void addSystemVMTemplatesToHost(HostVO host, Map templateInfos); boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum); + void handleVolumeSync(HostVO ssHost); + } \ No newline at end of file diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 34139798ba1..c880f8f5392 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -32,7 +32,10 @@ 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.DeleteVolumeCommand; import com.cloud.agent.api.storage.DownloadCommand; +import com.cloud.agent.api.storage.ListVolumeAnswer; +import com.cloud.agent.api.storage.ListVolumeCommand; import com.cloud.agent.api.storage.DownloadCommand.Proxy; import com.cloud.agent.api.storage.DownloadCommand.ResourceType; import com.cloud.agent.api.storage.DownloadProgressCommand; @@ -620,11 +623,12 @@ public class DownloadMonitorImpl implements DownloadMonitor { } @Override - public void handleTemplateSync(Long dcId) { + public void handleSync(Long dcId) { if (dcId != null) { List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); for (HostVO ssHost : ssHosts) { handleTemplateSync(ssHost); + handleVolumeSync(ssHost); } } } @@ -644,6 +648,21 @@ public class DownloadMonitorImpl implements DownloadMonitor { return null; } + private Map listVolume(HostVO ssHost) { + ListVolumeCommand cmd = new ListVolumeCommand(ssHost.getStorageUrl()); + Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd); + if (answer != null && answer.getResult()) { + ListVolumeAnswer tanswer = (ListVolumeAnswer)answer; + return tanswer.getTemplateInfo(); + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Can not list volumes for secondary storage host " + ssHost.getId()); + } + } + + return null; + } + private Map listTemplate(SwiftVO swift) { if (swift == null) { return null; @@ -660,7 +679,88 @@ public class DownloadMonitorImpl implements DownloadMonitor { } return null; } + + @Override + public void handleVolumeSync(HostVO ssHost) { + if (ssHost == null) { + s_logger.warn("Huh? ssHost is null"); + return; + } + long sserverId = ssHost.getId(); + 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 volumeInfos = listVolume(ssHost); + if (volumeInfos == null) { + return; + } + + List dbVolumes = _volumeHostDao.listBySecStorage(sserverId); + List toBeDownloaded = new ArrayList(dbVolumes); + for (VolumeHostVO volumeHost : dbVolumes){ + VolumeVO volume = _volumeDao.findById(volumeHost.getVolumeId()); + //Exists then don't download + if (volumeInfos.containsKey(volume.getId())){ + TemplateInfo volInfo = volumeInfos.remove(volume.getId()); + toBeDownloaded.remove(volumeHost); + s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume host table"); + if (volumeHost.getDownloadState() != Status.DOWNLOADED) { + volumeHost.setErrorString(""); + } + if (volInfo.isCorrupted()) { + volumeHost.setDownloadState(Status.DOWNLOAD_ERROR); + String msg = "Volume " + volume.getUuid() + " is corrupted on secondary storage "; + volumeHost.setErrorString(msg); + s_logger.info("msg"); + if (volumeHost.getDownloadUrl() == null) { + msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + "is corrupted, please check in secondary storage: " + volumeHost.getHostId(); + s_logger.warn(msg); + } else { + toBeDownloaded.add(volumeHost); + } + + } else { + volumeHost.setDownloadPercent(100); + volumeHost.setDownloadState(Status.DOWNLOADED); + volumeHost.setInstallPath(volInfo.getInstallPath()); + volumeHost.setSize(volInfo.getSize()); + volumeHost.setPhysicalSize(volInfo.getPhysicalSize()); + volumeHost.setLastUpdated(new Date()); + } + _volumeHostDao.update(volumeHost.getId(), volumeHost); + } + } + + //Download volumes which havent been downloaded yet. + if (toBeDownloaded.size() > 0) { + for (VolumeHostVO volumeHost : toBeDownloaded) { + if (volumeHost.getDownloadUrl() == null) { // If url is null we can't initiate the download + continue; + } + s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + ssHost.getName()); + downloadVolumeToStorage(_volumeDao.findById(volumeHost.getVolumeId()), ssHost, volumeHost.getDownloadUrl(), volumeHost.getChecksum()); + } + } + + //Delete volumes which are not present on DB. + for (Long uniqueName : volumeInfos.keySet()) { + TemplateInfo vInfo = volumeInfos.get(uniqueName); + DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), vInfo.getInstallPath()); + try { + _agentMgr.sendToSecStorage(ssHost, dtCommand, null); + } catch (AgentUnavailableException e) { + String err = "Failed to delete " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database"; + s_logger.error(err); + return; + } + + String description = "Deleted volume " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database"; + s_logger.info(description); + } + } + @Override public void handleTemplateSync(HostVO ssHost) { if (ssHost == null) {