diff --git a/api/src/com/cloud/agent/api/storage/ListTemplateCommand.java b/api/src/com/cloud/agent/api/storage/ListTemplateCommand.java index 959e4ae5494..a04bc9a6617 100644 --- a/api/src/com/cloud/agent/api/storage/ListTemplateCommand.java +++ b/api/src/com/cloud/agent/api/storage/ListTemplateCommand.java @@ -17,16 +17,25 @@ */ package com.cloud.agent.api.storage; +import com.cloud.agent.api.to.SwiftTO; + public class ListTemplateCommand extends StorageCommand { private String secUrl; + private SwiftTO swift; public ListTemplateCommand() { } public ListTemplateCommand(String secUrl) { this.secUrl = secUrl; + this.swift = null; } + public ListTemplateCommand(SwiftTO swift) { + this.secUrl = null; + this.swift = swift; + } + @Override public boolean executeInSequence() { return true; @@ -36,8 +45,8 @@ public class ListTemplateCommand extends StorageCommand { return secUrl; } - public void setSecUrl(String secUrl) { - this.secUrl = secUrl; + public SwiftTO getSwift() { + return swift; } } diff --git a/core/src/com/cloud/storage/Swift.java b/core/src/com/cloud/storage/Swift.java index 56b890af666..f058fe270fb 100644 --- a/core/src/com/cloud/storage/Swift.java +++ b/core/src/com/cloud/storage/Swift.java @@ -17,9 +17,12 @@ */ package com.cloud.storage; +import com.cloud.agent.api.to.SwiftTO; + public interface Swift { public String getUrl(); public String getAccount(); public String getUserName(); public String getKey(); + public SwiftTO toSwiftTO(); } diff --git a/core/src/com/cloud/storage/SwiftVO.java b/core/src/com/cloud/storage/SwiftVO.java index 9967e955f3d..9d3e7f93255 100644 --- a/core/src/com/cloud/storage/SwiftVO.java +++ b/core/src/com/cloud/storage/SwiftVO.java @@ -24,6 +24,8 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; + +import com.cloud.agent.api.to.SwiftTO; @Entity @Table(name="swift") @@ -75,4 +77,8 @@ public class SwiftVO implements Swift { return key; } + @Override + public SwiftTO toSwiftTO() { + return new SwiftTO(getId(), getUrl(), getAccount(), getUserName(), getKey()); + } } diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index 41fabe7c130..ffc2da18e4b 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -78,12 +78,14 @@ import com.cloud.storage.template.DownloadManager; import com.cloud.storage.template.DownloadManagerImpl; import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser; import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateLocation; import com.cloud.storage.template.UploadManager; import com.cloud.storage.template.UploadManagerImpl; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; +import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; import com.cloud.vm.SecondaryStorageVm; @@ -112,6 +114,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S private String _eth1mask; private String _eth1ip; final private String _parent = "/mnt/SecStorage"; + final private String _tmpltDir = "/var/cloudstack/template"; + final private String _tmpltpp = "template.properties"; @Override public void disconnected() { } @@ -235,6 +239,28 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return null; } + String[] swiftList(SwiftTO swift, String container, String rFilename) { + Script command = new Script("/bin/bash", s_logger); + command.add("-c"); + command.add("/usr/bin/python /usr/local/cloud/systemvm/scripts/storage/secondary/swift -A " + swift.getUrl() + " -U " + swift.getAccount() + ":" + swift.getUserName() + " -K " + + swift.getKey() + " list " + container + " " + rFilename); + OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); + String result = command.execute(parser); + if (result == null && parser.getLines() != null) { + String[] lines = parser.getLines().split("\\n"); + return lines; + } else { + if (result != null) { + String errMsg = "swiftList failed , err=" + result; + s_logger.warn(errMsg); + } else { + String errMsg = "swiftList, no lines returns"; + s_logger.warn(errMsg); + } + } + return null; + } + String swiftDelete(SwiftTO swift, String container, String rFilename) { Script command = new Script("/bin/bash", s_logger); command.add("-c"); @@ -374,7 +400,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } return new Answer(cmd, false, checksum); } - } + } return new Answer(cmd, true, checksum); } @@ -451,14 +477,51 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } } - + Map swiftListTemplate(SwiftTO swift) { + String[] containers = swiftList(swift, "", ""); + if (containers == null) { + return null; + } + Map tmpltInfos = new HashMap(); + for( String container : containers) { + if ( container.startsWith("T-")) { + String ldir = _tmpltDir + "/" + UUID.randomUUID().toString(); + createLocalDir(ldir); + String lFullPath = ldir + "/" + _tmpltpp; + swiftDownload(swift, container, _tmpltpp, lFullPath); + TemplateLocation loc = new TemplateLocation(_storage, ldir); + try { + if (!loc.load()) { + s_logger.warn("Can not parse template.properties file for template " + container); + continue; + } + } catch (IOException e) { + s_logger.warn("Unable to load template location " + ldir + " due to " + e.toString(), e); + continue; + } + TemplateInfo tInfo = loc.getTemplateInfo(); + tInfo.setInstallPath(container); + tmpltInfos.put(tInfo.getTemplateName(), tInfo); + loc.purge(); + deleteLocalDir(ldir); + } + } + return tmpltInfos; + + } + private Answer execute(ListTemplateCommand cmd) { if (!_inSystemVM){ return new Answer(cmd, true, null); } - String root = getRootDir(cmd.getSecUrl()); - Map templateInfos = _dlMgr.gatherTemplateInfo(root); - return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); + if (cmd.getSwift() != null) { + Map templateInfos = swiftListTemplate(cmd.getSwift()); + return new ListTemplateAnswer(cmd.getSwift().toString(), templateInfos); + } else { + String root = getRootDir(cmd.getSecUrl()); + Map templateInfos = _dlMgr.gatherTemplateInfo(root); + return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); + } } private Answer execute(SecStorageVMSetupCommand cmd) { @@ -513,6 +576,19 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return null; } + private String deleteLocalDir(String folder) { + Script command = new Script("/bin/bash", s_logger); + command.add("-c"); + command.add("rmdir " + folder); + String result = command.execute(); + if (result != null) { + String errMsg = "Delete local path " + folder + " failed , err=" + result; + s_logger.warn(errMsg); + return errMsg; + } + return null; + } + private String deleteLocalFile(String fullPath) { Script command = new Script("/bin/bash", s_logger); command.add("-c"); diff --git a/core/src/com/cloud/storage/template/DownloadManagerImpl.java b/core/src/com/cloud/storage/template/DownloadManagerImpl.java index 10bfe0c668f..8bf37b2ee68 100755 --- a/core/src/com/cloud/storage/template/DownloadManagerImpl.java +++ b/core/src/com/cloud/storage/template/DownloadManagerImpl.java @@ -640,12 +640,6 @@ public class DownloadManagerImpl implements DownloadManager { } } catch (IOException e) { s_logger.warn("Unable to load template location " + path, e); - //loc.purge(); - try { - _storage.cleanup(path, templateDir); - } catch (IOException e1) { - s_logger.warn("Unable to cleanup " + path, e1); - } continue; } diff --git a/core/src/com/cloud/storage/template/TemplateLocation.java b/core/src/com/cloud/storage/template/TemplateLocation.java index 0e4d9223979..1b34759014e 100644 --- a/core/src/com/cloud/storage/template/TemplateLocation.java +++ b/core/src/com/cloud/storage/template/TemplateLocation.java @@ -27,8 +27,8 @@ import java.util.Properties; import org.apache.log4j.Logger; -import com.cloud.storage.StorageLayer; import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.StorageLayer; import com.cloud.storage.template.Processor.FormatInfo; import com.cloud.utils.NumbersUtil; @@ -192,7 +192,7 @@ public class TemplateLocation { } protected boolean checkFormatValidity(FormatInfo info) { - return (info.format != null && info.size > 0 && info.virtualSize > 0 && info.filename != null && _storage.exists(_templatePath + info.filename) && _storage.getSize(_templatePath + info.filename) == info.size); + return (info.format != null && info.size > 0 && info.virtualSize > 0 && info.filename != null); } protected FormatInfo deleteFormat(ImageFormat format) { diff --git a/server/src/com/cloud/agent/AgentManager.java b/server/src/com/cloud/agent/AgentManager.java index 96dab1d435a..fac8e783236 100755 --- a/server/src/com/cloud/agent/AgentManager.java +++ b/server/src/com/cloud/agent/AgentManager.java @@ -258,7 +258,7 @@ public interface AgentManager extends Manager { Answer sendToSecStorage(HostVO ssHost, Command cmd); - Answer sendToSSVM(final long dcId, final Command cmd); + Answer sendToSSVM(Long dcId, final Command cmd); HostVO getSSAgent(HostVO ssHost); diff --git a/server/src/com/cloud/agent/manager/AgentManagerImpl.java b/server/src/com/cloud/agent/manager/AgentManagerImpl.java index 4f95daa6443..187c2e09efe 100755 --- a/server/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/server/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -550,14 +550,12 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory, Manager { } @Override - public Answer sendToSSVM(final long dcId, final Command cmd) { - List ssAHosts = _hostDao.listSecondaryStorageVM(dcId); - if (ssAHosts == null || ssAHosts.isEmpty() ) { + public Answer sendToSSVM(final Long dcId, final Command cmd) { + HostVO ssAHost = _hostDao.findSecondaryStorageVM(dcId); + if (ssAHost == null) { return new Answer(cmd, false, "can not find secondary storage VM agent for data center " + dcId); } - Collections.shuffle(ssAHosts); - HostVO ssAhost = ssAHosts.get(0); - return easySend(ssAhost.getId(), cmd); + return easySend(ssAHost.getId(), cmd); } @Override diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index a3669125f71..8cccf11d2d3 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -130,6 +130,8 @@ public enum Config { // Advanced JobExpireMinutes("Advanced", ManagementServer.class, String.class, "job.expire.minutes", "1440", "Time (in minutes) for async-jobs to be kept in system", null), JobCancelThresholdMinutes("Advanced", ManagementServer.class, String.class, "job.cancel.threshold.minutes", "60", "Time (in minutes) for async-jobs to be forcely cancelled if it has been in process for long", null), + SwiftEnable( + "Advanced", ManagementServer.class, Boolean.class, "swift.enable", "false", "enable swift ", null), AccountCleanupInterval("Advanced", ManagementServer.class, Integer.class, "account.cleanup.interval", "86400", "The interval (in seconds) between cleanup for removed accounts", null), AllowPublicUserTemplates("Advanced", ManagementServer.class, Integer.class, "allow.public.user.templates", "true", "If false, users will not be able to create public templates.", null), diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 226054359e2..0487ba6fbe7 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -93,6 +93,8 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network; @@ -115,7 +117,9 @@ import com.cloud.projects.ProjectManager; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.SwiftVO; import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.SwiftDao; import com.cloud.test.IPRangeConfig; import com.cloud.user.Account; import com.cloud.user.AccountManager; @@ -163,6 +167,10 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura @Inject DomainDao _domainDao; @Inject + HostDao _hostDao; + @Inject + SwiftDao _swiftDao; + @Inject ServiceOfferingDao _serviceOfferingDao; @Inject DiskOfferingDao _diskOfferingDao; @@ -441,6 +449,16 @@ public class ConfigurationManagerImpl implements ConfigurationManager, Configura s_logger.error("Configuration variable " + name + " is expecting true or false in stead of " + value); return "Please enter either 'true' or 'false'."; } + if (Config.SwiftEnable.key().equals(name)) { + HostVO host = _hostDao.findSecondaryStorageHost(null); + if (host != null) { + return " can not change " + Config.SwiftEnable.key() + " after you have added secondary storage"; + } + SwiftVO swift = _swiftDao.findById(1L); + if (swift != null) { + return " can not change " + Config.SwiftEnable.key() + " after you have added Swift"; + } + } return null; } diff --git a/server/src/com/cloud/host/dao/HostDao.java b/server/src/com/cloud/host/dao/HostDao.java index 6dba59a2904..9348991bc60 100755 --- a/server/src/com/cloud/host/dao/HostDao.java +++ b/server/src/com/cloud/host/dao/HostDao.java @@ -43,7 +43,8 @@ public interface HostDao extends GenericDao { List listByStatus(Status... status); List listBy(Host.Type type, long dcId); List listAllBy(Host.Type type, long dcId); - HostVO findSecondaryStorageHost(long dcId); + + HostVO findSecondaryStorageHost(Long dcId); List listByCluster(long clusterId); /** * Lists all secondary storage hosts, across all zones @@ -178,5 +179,7 @@ public interface HostDao extends GenericDao { List listByInAllStatus(Type type, Long clusterId, Long podId, long dcId); - List listByClusterStatus(long clusterId, Status status); + List listByClusterStatus(long clusterId, Status status); + + HostVO findSecondaryStorageVM(Long dcId); } diff --git a/server/src/com/cloud/host/dao/HostDaoImpl.java b/server/src/com/cloud/host/dao/HostDaoImpl.java index 5d16677f1d1..adc7ce8ad03 100755 --- a/server/src/com/cloud/host/dao/HostDaoImpl.java +++ b/server/src/com/cloud/host/dao/HostDaoImpl.java @@ -311,10 +311,29 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao } @Override - public HostVO findSecondaryStorageHost(long dcId) { + public HostVO findSecondaryStorageHost(Long dcId) { SearchCriteria sc = TypeDcSearch.create(); sc.setParameters("type", Host.Type.SecondaryStorage); - sc.setParameters("dc", dcId); + if (dcId != null) { + sc.setParameters("dc", dcId); + } + List storageHosts = listBy(sc); + if (storageHosts == null || storageHosts.size() < 1) { + return null; + } else { + Collections.shuffle(storageHosts); + return storageHosts.get(0); + } + } + + @Override + public HostVO findSecondaryStorageVM(Long dcId) { + SearchCriteria sc = SecondaryStorageVMSearch.create(); + sc.setParameters("type", Host.Type.SecondaryStorageVM); + sc.setParameters("status", Status.Up); + if (dcId != null) { + sc.setParameters("dc", dcId); + } List storageHosts = listBy(sc); if (storageHosts == null || storageHosts.size() < 1) { return null; diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index ea46d0770f3..741f3e32778 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -197,6 +197,7 @@ import com.cloud.storage.dao.UploadDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; +import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.storage.upload.UploadMonitor; import com.cloud.template.TemplateManager; import com.cloud.template.VirtualMachineTemplate; @@ -310,6 +311,8 @@ public class ManagementServerImpl implements ManagementServer { private final HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; private final Adapters _hostAllocators; @Inject ProjectManager _projectMgr; + @Inject + SnapshotManager _snapshotMgr; private final KeystoreManager _ksMgr; @@ -1382,7 +1385,14 @@ public class ManagementServerImpl implements ManagementServer { Set> templateZonePairSet = new HashSet>(); if (template == null) { - templateZonePairSet = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr, permittedAccounts, caller); + Boolean swiftEnable = Boolean.valueOf(_configDao.getValue(Config.SwiftEnable.key())); + if (swiftEnable) { + templateZonePairSet = _templateDao.searchSwiftTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr, + permittedAccounts, caller); + } else { + templateZonePairSet = _templateDao.searchTemplates(name, keyword, templateFilter, isIso, hypers, bootable, domain, pageSize, startIndex, zoneId, hyperType, onlyReady, showDomr, + permittedAccounts, caller); + } } else { // if template is not public, perform permission check here if (!template.isPublicTemplate() && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { diff --git a/server/src/com/cloud/storage/dao/VMTemplateDao.java b/server/src/com/cloud/storage/dao/VMTemplateDao.java index da83391131e..4f707555e7c 100644 --- a/server/src/com/cloud/storage/dao/VMTemplateDao.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDao.java @@ -61,6 +61,9 @@ public interface VMTemplateDao extends GenericDao { public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller); + public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, + Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller); + public long addTemplateToZone(VMTemplateVO tmplt, long zoneId); public List listAllInZone(long dataCenterId); diff --git a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index 4a46c9fc3b2..75b54127a87 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -81,7 +81,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem private final String SELECT_TEMPLATE_ZONE_REF = "SELECT t.id, tzr.zone_id, t.unique_name, t.name, t.public, t.featured, t.type, t.hvm, t.bits, t.url, t.format, t.created, t.account_id, " + "t.checksum, t.display_text, t.enable_password, t.guest_os_id, t.bootable, t.prepopulate, t.cross_zones, t.hypervisor_type FROM vm_template t INNER JOIN template_zone_ref tzr on (t.id = tzr.template_id) "; - + protected SearchBuilder TemplateNameSearch; protected SearchBuilder UniqueNameSearch; protected SearchBuilder tmpltTypeSearch; @@ -302,6 +302,149 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem public String getRoutingTemplateUniqueName() { return routerTmpltName; } + + @Override + public Set> searchSwiftTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, + Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr, List permittedAccounts, Account caller) { + + StringBuilder builder = new StringBuilder(); + if (!permittedAccounts.isEmpty()) { + for (Account permittedAccount : permittedAccounts) { + builder.append(permittedAccount.getAccountId() + ","); + } + } + + String permittedAccountsStr = builder.toString(); + + if (permittedAccountsStr.length() > 0) { + // chop the "," off + permittedAccountsStr = permittedAccountsStr.substring(0, permittedAccountsStr.length() - 1); + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + Set> templateZonePairList = new HashSet>(); + PreparedStatement pstmt = null; + ResultSet rs = null; + String sql = SELECT_TEMPLATE_HOST_REF; + String groupByClause = ""; + try { + // short accountType; + // String accountId = null; + String guestOSJoin = ""; + StringBuilder templateHostRefJoin = new StringBuilder(); + String dataCenterJoin = ""; + + if (isIso && !hyperType.equals(HypervisorType.None)) { + guestOSJoin = " INNER JOIN guest_os guestOS on (guestOS.id = t.guest_os_id) INNER JOIN guest_os_hypervisor goh on ( goh.guest_os_id = guestOS.id) "; + } + if (onlyReady) { + templateHostRefJoin.append(" INNER JOIN template_swift_ref tsr on (t.id = tsr.template_id)"); + } + + sql += guestOSJoin + templateHostRefJoin + dataCenterJoin; + String whereClause = ""; + + if (!isIso) { + if (hypers.isEmpty()) { + return templateZonePairList; + } else { + StringBuilder relatedHypers = new StringBuilder(); + for (HypervisorType hyper : hypers) { + relatedHypers.append("'"); + relatedHypers.append(hyper.toString()); + relatedHypers.append("'"); + relatedHypers.append(","); + } + relatedHypers.setLength(relatedHypers.length() - 1); + whereClause += " AND t.hypervisor_type IN (" + relatedHypers + ")"; + } + } + + + if (templateFilter == TemplateFilter.featured) { + whereClause += " WHERE t.public = 1 AND t.featured = 1"; + } else if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { + whereClause += " INNER JOIN account a on (t.account_id = a.id) INNER JOIN domain d on (a.domain_id = d.id) WHERE d.path LIKE '" + domain.getPath() + "%'"; + } else { + whereClause += " WHERE t.account_id IN (" + permittedAccountsStr + ")"; + } + } else if (templateFilter == TemplateFilter.sharedexecutable && caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { + whereClause += " LEFT JOIN launch_permission lp ON t.id = lp.template_id WHERE" + " (t.account_id IN (" + permittedAccountsStr + ") OR" + " lp.account_id IN (" + + permittedAccountsStr + "))"; + } else { + whereClause += " INNER JOIN account a on (t.account_id = a.id) "; + } + } else if (templateFilter == TemplateFilter.executable && !permittedAccounts.isEmpty()) { + whereClause += " WHERE (t.public = 1 OR t.account_id IN (" + permittedAccountsStr + "))"; + } else if (templateFilter == TemplateFilter.community) { + whereClause += " WHERE t.public = 1 AND t.featured = 0"; + } else if (templateFilter == TemplateFilter.all && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { + whereClause += " WHERE "; + } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + return templateZonePairList; + } + + if (whereClause.equals("")) { + whereClause += " WHERE "; + } else if (!whereClause.equals(" WHERE ")) { + whereClause += " AND "; + } + + sql += whereClause + getExtrasWhere(templateFilter, name, keyword, isIso, bootable, hyperType, zoneId, onlyReady, showDomr) + groupByClause + getOrderByLimit(pageSize, startIndex); + + pstmt = txn.prepareStatement(sql); + rs = pstmt.executeQuery(); + while (rs.next()) { + Pair templateZonePair = new Pair(rs.getLong(1), rs.getLong(2)); + templateZonePairList.add(templateZonePair); + } + + // for now, defaulting pageSize to a large val if null; may need to + // revisit post 2.2RC2 + if (isIso && templateZonePairList.size() < (pageSize != null ? pageSize : 500) && templateFilter != TemplateFilter.community + && !(templateFilter == TemplateFilter.self && !BaseCmd.isRootAdmin(caller.getType()))) { // evaluates + // to + // true + // If + // root + // admin + // and + // filter=self + List publicIsos = publicIsoSearch(bootable); + for (int i = 0; i < publicIsos.size(); i++) { + if (keyword != null && publicIsos.get(i).getName().contains(keyword)) { + templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); + continue; + } else if (name != null && publicIsos.get(i).getName().contains(name)) { + templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); + continue; + } else if (keyword == null && name == null) { + templateZonePairList.add(new Pair(publicIsos.get(i).getId(), null)); + } + } + } + } catch (Exception e) { + s_logger.warn("Error listing templates", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + txn.commit(); + } catch (SQLException sqle) { + s_logger.warn("Error in cleaning up", sqle); + } + } + + return templateZonePairList; + } @Override public Set> searchTemplates(String name, String keyword, TemplateFilter templateFilter, boolean isIso, List hypers, Boolean bootable, DomainVO domain, Long pageSize, Long startIndex, Long zoneId, HypervisorType hyperType, boolean onlyReady, boolean showDomr,List permittedAccounts, Account caller) { diff --git a/server/src/com/cloud/storage/download/DownloadMonitor.java b/server/src/com/cloud/storage/download/DownloadMonitor.java index 48eb5a3461a..e42799a80a9 100644 --- a/server/src/com/cloud/storage/download/DownloadMonitor.java +++ b/server/src/com/cloud/storage/download/DownloadMonitor.java @@ -18,7 +18,6 @@ package com.cloud.storage.download; -import java.util.List; import java.util.Map; import com.cloud.exception.StorageUnavailableException; @@ -46,7 +45,7 @@ public interface DownloadMonitor extends Manager{ /*When new host added, take a look at if there are templates needed to be downloaded for the same hypervisor as the host*/ void handleSysTemplateDownload(HostVO hostId); - void handleTemplateSync(long dcId); + void handleTemplateSync(Long dcId); void addSystemVMTemplatesToHost(HostVO host, Map templateInfos); diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 4b411c840c7..7ac706c1b12 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -41,6 +41,7 @@ import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; import com.cloud.agent.api.storage.ListTemplateAnswer; import com.cloud.agent.api.storage.ListTemplateCommand; import com.cloud.alert.AlertManager; +import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; @@ -55,15 +56,19 @@ 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.SwiftVO; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.VMTemplateSwiftVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.storage.dao.SwiftDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.storage.dao.VMTemplateSwiftDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.template.TemplateConstants; @@ -99,6 +104,8 @@ public class DownloadMonitorImpl implements DownloadMonitor { @Inject VMTemplatePoolDao _vmTemplatePoolDao; @Inject + VMTemplateSwiftDao _vmTemplateSwiftlDao; + @Inject StoragePoolHostDao _poolHostDao; @Inject SecondaryStorageVmDao _secStorageVmDao; @@ -125,6 +132,8 @@ public class DownloadMonitorImpl implements DownloadMonitor { private ClusterDao _clusterDao; @Inject private HostDao _hostDao; + @Inject + private SwiftDao _swiftDao; private String _name; private Boolean _sslCopy = new Boolean(false); @@ -480,10 +489,19 @@ public class DownloadMonitorImpl implements DownloadMonitor { } @Override - public void handleTemplateSync(long dcId) { - List ssHosts = _hostDao.listSecondaryStorageHosts(dcId); - for ( HostVO ssHost : ssHosts ) { - handleTemplateSync(ssHost); + public void handleTemplateSync(Long dcId) { + if ( dcId != null ) { + List ssHosts = _hostDao.listSecondaryStorageHosts(dcId); + for ( HostVO ssHost : ssHosts ) { + handleTemplateSync(ssHost); + } + } + Boolean swiftEnable = Boolean.getBoolean(_configDao.getValue(Config.SwiftEnable.key())); + if (swiftEnable) { + List swifts = _swiftDao.listAll(); + for (SwiftVO swift : swifts) { + handleTemplateSync(swift); + } } } @@ -502,6 +520,53 @@ public class DownloadMonitorImpl implements DownloadMonitor { return null; } + private Map listTemplate(SwiftVO swift) { + if (swift == null) { + return null; + } + ListTemplateCommand cmd = new ListTemplateCommand(swift.toSwiftTO()); + Answer answer = _agentMgr.sendToSSVM(null, 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 swift " + swift); + } + } + return null; + } + + public void handleTemplateSync(SwiftVO swift) { + if (swift == null) { + s_logger.warn("Huh? swift is null"); + return; + } + Map templateInfos = listTemplate(swift); + if (templateInfos == null) { + return; + } + List allTemplates = _templateDao.listAll(); + for (VMTemplateVO tmplt : allTemplates) { + String uniqueName = tmplt.getUniqueName(); + VMTemplateSwiftVO tmpltSwift = _vmTemplateSwiftlDao.findBySwiftTemplate(swift.getId(), tmplt.getId()); + if (templateInfos.containsKey(uniqueName)) { + TemplateInfo tmpltInfo = templateInfos.remove(uniqueName); + if (tmpltSwift != null) { + s_logger.info("Template Sync found " + uniqueName + " already in the template swift table"); + continue; + } else { + tmpltSwift = new VMTemplateSwiftVO(swift.getId(), tmplt.getId(), new Date(), tmpltInfo.getSize(), tmpltInfo.getPhysicalSize()); + _vmTemplateSwiftlDao.persist(tmpltSwift); + s_logger.info("Template Sync added " + uniqueName + " to the template swift table"); + } + } + } + + for (TemplateInfo tmpltInfo : templateInfos.values()) { + s_logger.warn("Template Sync found template " + tmpltInfo.getInstallPath() + " in Swift description, but not in template table, please"); + } + } @Override public void handleTemplateSync(HostVO ssHost) { diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index d18aecf8c28..95cc65c6a23 100644 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -296,9 +296,12 @@ public class SecondaryStorageManagerImpl implements SecondaryStorageVmManager, V if( snapshots != null && !snapshots.isEmpty()) { throw new CloudRuntimeException("Can not delete this secondary storage due to there are still snapshots on it "); } - List list = _templateDao.listPrivateTemplatesByHost(hostId); - if( list != null && !list.isEmpty()) { - throw new CloudRuntimeException("Can not delete this secondary storage due to there are still private template on it "); + Boolean swiftEnable = Boolean.getBoolean(_configDao.getValue(Config.SwiftEnable.key())); + if (!swiftEnable) { + List list = _templateDao.listPrivateTemplatesByHost(hostId); + if (list != null && !list.isEmpty()) { + throw new CloudRuntimeException("Can not delete this secondary storage due to there are still private template on it "); + } } _vmTemplateHostDao.deleteByHost(hostId); HostVO host = _hostDao.findById(hostId);