diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java index f1ca62b626a..62b5c8771e7 100755 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java @@ -49,7 +49,7 @@ public class TemplateDataStoreVO implements StateObject dcs = _dcDao.listAllIncludingRemoved(); for (DataCenterVO dc : dcs) { @@ -90,53 +91,39 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem return profile; } - + @Override public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { throw new CloudRuntimeException("Baremetal doesn't support ISO template"); } - - private void templateCreateUsage(VMTemplateVO template, HostVO host) { + + private void templateCreateUsage(VMTemplateVO template, long dcId) { if (template.getAccountId() != Account.ACCOUNT_ID_SYSTEM) { - UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), host.getDataCenterId(), + UsageEventVO usageEvent = new UsageEventVO(EventTypes.EVENT_TEMPLATE_CREATE, template.getAccountId(), dcId, template.getId(), template.getName(), null, template.getSourceTemplateId(), 0L); _usageEventDao.persist(usageEvent); } } - + @Override public VMTemplateVO create(TemplateProfile profile) { VMTemplateVO template = persistTemplate(profile); Long zoneId = profile.getZoneId(); - - /* There is no secondary storage vm for baremetal, we use pxe server id. - * Tempalte is not bound to pxeserver right now, and we assume the pxeserver - * cannot be removed once it was added. so we use host id of first found pxe - * server as reference in template_host_ref. - * This maybe a FIXME in future. - */ - VMTemplateHostVO vmTemplateHost = null; + + // create an entry at template_store_ref with store_id = null to represent that this template is ready for use. + TemplateDataStoreVO vmTemplateHost = new TemplateDataStoreVO(null, template.getId(), new Date(), 100, + Status.DOWNLOADED, null, null, null, null, template.getUrl()); + this._tmpltStoreDao.persist(vmTemplateHost); + if (zoneId == null || zoneId == -1) { List dcs = _dcDao.listAllIncludingRemoved(); - for (DataCenterVO dc : dcs) { - HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, dc.getId()).get(0); - - vmTemplateHost = _tmpltHostDao.findByHostTemplate(dc.getId(), template.getId()); - if (vmTemplateHost == null) { - vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100, - Status.DOWNLOADED, null, null, null, null, template.getUrl()); - _tmpltHostDao.persist(vmTemplateHost); - templateCreateUsage(template, pxe); - } + if ( dcs != null && dcs.size() > 0 ){ + templateCreateUsage(template, dcs.get(0).getId()); } } else { - HostVO pxe = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId).get(0); - vmTemplateHost = new VMTemplateHostVO(pxe.getId(), template.getId(), new Date(), 100, - Status.DOWNLOADED, null, null, null, null, template.getUrl()); - _tmpltHostDao.persist(vmTemplateHost); - templateCreateUsage(template, pxe); + templateCreateUsage(template, zoneId); } - + _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.template); _resourceLimitMgr.incrementResourceCount(profile.getAccountId(), ResourceType.secondary_storage, UriUtils.getRemoteSize(profile.getUrl())); @@ -146,65 +133,70 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { throw new CloudRuntimeException("Baremetal doesn't support ISO, how the delete get here???"); } - + @Override @DB public boolean delete(TemplateProfile profile) { VMTemplateVO template = profile.getTemplate(); Long templateId = template.getId(); boolean success = true; String zoneName; - boolean isAllZone; - + if (!template.isCrossZones() && profile.getZoneId() != null) { - isAllZone = false; zoneName = profile.getZoneId().toString(); } else { zoneName = "all zones"; - isAllZone = true; } - + s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); Account account = _accountDao.findByIdIncludingRemoved(template.getAccountId()); String eventType = EventTypes.EVENT_TEMPLATE_DELETE; - List templateHostVOs = _tmpltHostDao.listByTemplateId(templateId); - - for (VMTemplateHostVO vo : templateHostVOs) { - VMTemplateHostVO lock = null; - try { - HostVO pxeServer = _hostDao.findById(vo.getHostId()); - if (!isAllZone && pxeServer.getDataCenterId() != profile.getZoneId()) { - continue; - } + List templateHostVOs = this._tmpltStoreDao.listByTemplate(templateId); - lock = _tmpltHostDao.acquireInLockTable(vo.getId()); + for (TemplateDataStoreVO vo : templateHostVOs) { + TemplateDataStoreVO lock = null; + try { + lock = _tmpltStoreDao.acquireInLockTable(vo.getId()); if (lock == null) { - s_logger.debug("Failed to acquire lock when deleting templateHostVO with ID: " + vo.getId()); + s_logger.debug("Failed to acquire lock when deleting templateDataStoreVO with ID: " + vo.getId()); success = false; break; } vo.setDestroyed(true); - _tmpltHostDao.update(vo.getId(), vo); - VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(pxeServer.getDataCenterId(), templateId); - if (templateZone != null) { - _tmpltZoneDao.remove(templateZone.getId()); - } + _tmpltStoreDao.update(vo.getId(), vo); + - UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), pxeServer.getDataCenterId(), templateId, null); - _usageEventDao.persist(usageEvent); } finally { if (lock != null) { - _tmpltHostDao.releaseFromLockTable(lock.getId()); + _tmpltStoreDao.releaseFromLockTable(lock.getId()); } } } - + + if ( profile.getZoneId() != null ){ + UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), profile.getZoneId(), templateId, null); + _usageEventDao.persist(usageEvent); + } + else{ + List dcs = _dcDao.listAllIncludingRemoved(); + for ( DataCenterVO dc : dcs){ + UsageEventVO usageEvent = new UsageEventVO(eventType, account.getId(), dc.getId(), templateId, null); + _usageEventDao.persist(usageEvent); + } + } + + VMTemplateZoneVO templateZone = _tmpltZoneDao.findByZoneTemplate(profile.getZoneId(), templateId); + + if (templateZone != null) { + _tmpltZoneDao.remove(templateZone.getId()); + } + s_logger.debug("Successfully marked template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName); - + // If there are no more non-destroyed template host entries for this template, delete it - if (success && (_tmpltHostDao.listByTemplateId(templateId).size() == 0)) { + if (success && (_tmpltStoreDao.listByTemplate(templateId).size() == 0)) { long accountId = template.getAccountId(); - + VMTemplateVO lock = _tmpltDao.acquireInLockTable(templateId); try { @@ -225,7 +217,7 @@ public class BareMetalTemplateAdapter extends TemplateAdapterBase implements Tem } s_logger.debug("Removed template: " + template.getName() + " because all of its template host refs were marked as destroyed."); } - + return success; } } diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index 9826298d50b..f65b3641493 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -26,7 +26,6 @@ import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd; -import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.log4j.Logger; @@ -47,12 +46,10 @@ import com.cloud.org.Grouping; import com.cloud.storage.GuestOS; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; -import com.cloud.storage.DataStoreRole; import com.cloud.storage.TemplateProfile; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.GuestOSHypervisorDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; @@ -76,7 +73,6 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat protected @Inject AccountManager _accountMgr; protected @Inject DataCenterDao _dcDao; protected @Inject VMTemplateDao _tmpltDao; - protected @Inject VMTemplateHostDao _tmpltHostDao; protected @Inject TemplateDataStoreDao _tmpltStoreDao; protected @Inject VMTemplateZoneDao _tmpltZoneDao; protected @Inject UsageEventDao _usageEventDao; @@ -99,7 +95,8 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); } - public TemplateProfile prepare(boolean isIso, Long userId, String name, String displayText, Integer bits, + @Override + public TemplateProfile prepare(boolean isIso, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHVM, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType, String accountName, Long domainId, String chksum, Boolean bootable, Map details) throws ResourceAllocationException { @@ -107,7 +104,8 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat chksum, bootable, null, null, details, false); } - public TemplateProfile prepare(boolean isIso, long userId, String name, String displayText, Integer bits, + @Override + public TemplateProfile prepare(boolean isIso, long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHVM, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, String format, Long guestOSId, Long zoneId, HypervisorType hypervisorType, String chksum, Boolean bootable, String templateTag, Account templateOwner, Map details, Boolean sshkeyEnabled) throws ResourceAllocationException { @@ -228,7 +226,8 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat cmd.getChecksum(), true, cmd.getTemplateTag(), owner, cmd.getDetails(), cmd.isSshKeyEnabled()); } - public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { + @Override + public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { //check if the caller can operate with the template owner Account caller = UserContext.current().getCaller(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); @@ -304,7 +303,8 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat return userId; } - public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { + @Override + public TemplateProfile prepareDelete(DeleteTemplateCmd cmd) { Long templateId = cmd.getId(); Long userId = UserContext.current().getCallerUserId(); Account account = UserContext.current().getCaller(); @@ -329,7 +329,8 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat return new TemplateProfile(userId, template, zoneId); } - public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { + @Override + public TemplateProfile prepareDelete(DeleteIsoCmd cmd) { Long templateId = cmd.getId(); Long userId = UserContext.current().getCallerUserId(); Account account = UserContext.current().getCaller(); @@ -354,6 +355,8 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat return new TemplateProfile(userId, template, zoneId); } - abstract public VMTemplateVO create(TemplateProfile profile); - abstract public boolean delete(TemplateProfile profile); + @Override + abstract public VMTemplateVO create(TemplateProfile profile); + @Override + abstract public boolean delete(TemplateProfile profile); } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 6a7365f9054..9519266e7f5 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -115,10 +115,11 @@ CREATE VIEW `cloud`.`image_store_view` AS left join `cloud`.`image_store_details` ON image_store_details.store_id = image_store.id; - +-- here we have to allow null for store_id to accomodate baremetal case to search for ready templates since template state is only stored in this table +-- FK also commented out due to this CREATE TABLE `cloud`.`template_store_ref` ( `id` bigint unsigned NOT NULL auto_increment, - `store_id` bigint unsigned NOT NULL, + `store_id` bigint unsigned, `template_id` bigint unsigned NOT NULL, `created` DATETIME NOT NULL, `last_updated` DATETIME, @@ -135,7 +136,7 @@ CREATE TABLE `cloud`.`template_store_ref` ( `destroyed` tinyint(1) COMMENT 'indicates whether the template_store entry was destroyed by the user or not', `is_copy` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'indicates whether this was copied ', PRIMARY KEY (`id`), - CONSTRAINT `fk_template_store_ref__store_id` FOREIGN KEY `fk_template_store_ref__store_id` (`store_id`) REFERENCES `image_data_store` (`id`) ON DELETE CASCADE, +-- CONSTRAINT `fk_template_store_ref__store_id` FOREIGN KEY `fk_template_store_ref__store_id` (`store_id`) REFERENCES `image_data_store` (`id`) ON DELETE CASCADE, INDEX `i_template_store_ref__store_id`(`store_id`), CONSTRAINT `fk_template_store_ref__template_id` FOREIGN KEY `fk_template_store_ref__template_id` (`template_id`) REFERENCES `vm_template` (`id`), INDEX `i_template_store_ref__template_id`(`template_id`)