From 3ed3acaea4346062879f019a6f7f46ab450f551a Mon Sep 17 00:00:00 2001 From: Kelven Yang Date: Mon, 14 Nov 2011 18:04:30 -0800 Subject: [PATCH] bug 11814: Allow template to have details info in key/value pairs. --- .../cloud/api/commands/CreateTemplateCmd.java | 20 ++++- .../api/commands/RegisterTemplateCmd.java | 19 ++++- .../com/cloud/storage/VMTemplateDetailVO.java | 83 +++++++++++++++++++ core/src/com/cloud/storage/VMTemplateVO.java | 25 ++++-- .../baremetal/BareMetalVmManagerImpl.java | 2 +- .../DefaultComponentLibrary.java | 2 + .../cloud/storage/dao/VMTemplateDaoImpl.java | 6 ++ .../storage/dao/VMTemplateDetailsDao.java | 33 ++++++++ .../storage/dao/VMTemplateDetailsDaoImpl.java | 80 ++++++++++++++++++ .../com/cloud/template/TemplateAdapter.java | 6 +- .../cloud/template/TemplateAdapterBase.java | 18 ++-- .../com/cloud/template/TemplateProfile.java | 17 +++- .../src/com/cloud/vm/UserVmManagerImpl.java | 8 +- setup/db/create-schema.sql | 9 ++ setup/db/db/schema-2213to2214.sql | 9 ++ 15 files changed, 313 insertions(+), 24 deletions(-) create mode 100644 core/src/com/cloud/storage/VMTemplateDetailVO.java create mode 100644 server/src/com/cloud/storage/dao/VMTemplateDetailsDao.java create mode 100644 server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java diff --git a/api/src/com/cloud/api/commands/CreateTemplateCmd.java b/api/src/com/cloud/api/commands/CreateTemplateCmd.java index 02d702fcf8d..6d7602f9406 100755 --- a/api/src/com/cloud/api/commands/CreateTemplateCmd.java +++ b/api/src/com/cloud/api/commands/CreateTemplateCmd.java @@ -18,7 +18,9 @@ package com.cloud.api.commands; +import java.util.Collection; import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; @@ -86,7 +88,10 @@ import com.cloud.user.UserContext; private String url; @Parameter(name=ApiConstants.TEMPLATE_TAG, type=CommandType.STRING, description="the tag for this template.") - private String templateTag; + private String templateTag; + + @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="Template details in key/value pairs.") + protected Map details; // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// @@ -142,7 +147,18 @@ import com.cloud.user.UserContext; public String getTemplateTag() { return templateTag; - } + } + + public Map getDetails() { + if (details == null || details.isEmpty()) { + return null; + } + + Collection paramsCollection = details.values(); + Map params = (Map) (paramsCollection.toArray())[0]; + return params; + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// diff --git a/api/src/com/cloud/api/commands/RegisterTemplateCmd.java b/api/src/com/cloud/api/commands/RegisterTemplateCmd.java index a150488f325..341d749aef1 100755 --- a/api/src/com/cloud/api/commands/RegisterTemplateCmd.java +++ b/api/src/com/cloud/api/commands/RegisterTemplateCmd.java @@ -18,7 +18,9 @@ package com.cloud.api.commands; import java.net.URISyntaxException; +import java.util.Collection; import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; @@ -27,6 +29,7 @@ import com.cloud.api.BaseCmd; import com.cloud.api.Implementation; import com.cloud.api.Parameter; import com.cloud.api.ServerApiException; +import com.cloud.api.BaseCmd.CommandType; import com.cloud.api.response.ListResponse; import com.cloud.api.response.TemplateResponse; import com.cloud.async.AsyncJob; @@ -96,6 +99,9 @@ public class RegisterTemplateCmd extends BaseCmd { @Parameter(name=ApiConstants.TEMPLATE_TAG, type=CommandType.STRING, description="the tag for this template.") private String templateTag; + + @Parameter(name=ApiConstants.DETAILS, type=CommandType.MAP, description="Template details in key/value pairs.") + protected Map details; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -167,7 +173,18 @@ public class RegisterTemplateCmd extends BaseCmd { public String getTemplateTag() { return templateTag; - } + } + + public Map getDetails() { + if (details == null || details.isEmpty()) { + return null; + } + + Collection paramsCollection = details.values(); + Map params = (Map) (paramsCollection.toArray())[0]; + return params; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/core/src/com/cloud/storage/VMTemplateDetailVO.java b/core/src/com/cloud/storage/VMTemplateDetailVO.java new file mode 100644 index 00000000000..89f4b821812 --- /dev/null +++ b/core/src/com/cloud/storage/VMTemplateDetailVO.java @@ -0,0 +1,83 @@ +/** + * 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 . + * + */ +package com.cloud.storage; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="vm_template_details") +public class VMTemplateDetailVO { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="template_id") + private long templateId; + + @Column(name="name") + private String name; + + @Column(name="value", length=1024) + private String value; + + public VMTemplateDetailVO() {} + + public VMTemplateDetailVO(long templateId, String name, String value) { + this.templateId = templateId; + this.name = name; + this.value = value; + } + + public long getId() { + return id; + } + + public long getTemplateId() { + return templateId; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + public void setId(long id) { + this.id = id; + } + + public void setTemplateId(long templateId) { + this.templateId = templateId; + } + + public void setName(String name) { + this.name = name; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/core/src/com/cloud/storage/VMTemplateVO.java b/core/src/com/cloud/storage/VMTemplateVO.java index df548dc34c7..d13bcadd94a 100755 --- a/core/src/com/cloud/storage/VMTemplateVO.java +++ b/core/src/com/cloud/storage/VMTemplateVO.java @@ -19,6 +19,7 @@ package com.cloud.storage; import java.util.Date; +import java.util.Map; import java.util.UUID; import javax.persistence.Column; @@ -117,6 +118,7 @@ public class VMTemplateVO implements VirtualMachineTemplate { @Column(name="template_tag") private String templateTag; + Map details; @Override public String getUniqueName() { @@ -133,12 +135,12 @@ public class VMTemplateVO implements VirtualMachineTemplate { /** * Proper constructor for a new vm template. */ - public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) { - this(id, generateUniqueName(id, accountId, name), name, format, isPublic, featured, isExtractable, type, url, null, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType); + public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, Map details) { + this(id, generateUniqueName(id, accountId, name), name, format, isPublic, featured, isExtractable, type, url, null, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType, details); } - public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, String templateTag) { - this(id, name, format, isPublic, featured, isExtractable, type, url, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType); + public VMTemplateVO(long id, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, String templateTag, Map details) { + this(id, name, format, isPublic, featured, isExtractable, type, url, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType, details); this.templateTag = templateTag; } @@ -164,13 +166,14 @@ public class VMTemplateVO implements VirtualMachineTemplate { } // Has an extra attribute - isExtractable - public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) { + public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, Map details) { this(id, uniqueName, name, format, isPublic, featured, type, url, created, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType); this.extractable = isExtractable; + this.details = details; } - public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, String templateTag) { - this(id, uniqueName, name, format, isPublic, featured, isExtractable, type, url, created, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType); + public VMTemplateVO(Long id, String uniqueName, String name, ImageFormat format, boolean isPublic, boolean featured, boolean isExtractable, TemplateType type, String url, Date created, boolean requiresHvm, int bits, long accountId, String cksum, String displayText, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType, String templateTag, Map details) { + this(id, uniqueName, name, format, isPublic, featured, isExtractable, type, url, created, requiresHvm, bits, accountId, cksum, displayText, enablePassword, guestOSId, bootable, hyperType, details); this.templateTag = templateTag; } @@ -382,6 +385,14 @@ public class VMTemplateVO implements VirtualMachineTemplate { return -1; } + public Map getDetails() { + return this.details; + } + + public void setDetails(Map details) { + this.details = details; + } + @Override public boolean equals(Object that) { if (this == that ) { diff --git a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java index ee0e18937d6..91b7620e78e 100755 --- a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java +++ b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java @@ -168,7 +168,7 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet try { TemplateProfile tmplProfile; tmplProfile = adapter.prepare(false, userId, cmd.getTemplateName(), cmd.getDisplayText(), cmd.getBits(), false, false, cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), false, - "BareMetal", cmd.getOsTypeId(), pxe.getDataCenterId(), HypervisorType.BareMetal, account.getAccountName(), account.getDomainId(), "0", true); + "BareMetal", cmd.getOsTypeId(), pxe.getDataCenterId(), HypervisorType.BareMetal, account.getAccountName(), account.getDomainId(), "0", true, cmd.getDetails()); if (!_pxeMgr.prepareCreateTemplate(_pxeMgr.getPxeServerType(pxe), pxe.getId(), vm, cmd.getUrl())) { throw new Exception("Prepare PXE boot file for host " + hostId + " failed"); diff --git a/server/src/com/cloud/configuration/DefaultComponentLibrary.java b/server/src/com/cloud/configuration/DefaultComponentLibrary.java index d490a5fa004..e70ee57a5b2 100755 --- a/server/src/com/cloud/configuration/DefaultComponentLibrary.java +++ b/server/src/com/cloud/configuration/DefaultComponentLibrary.java @@ -123,6 +123,7 @@ import com.cloud.storage.dao.StoragePoolWorkDaoImpl; import com.cloud.storage.dao.SwiftDaoImpl; import com.cloud.storage.dao.UploadDaoImpl; import com.cloud.storage.dao.VMTemplateDaoImpl; +import com.cloud.storage.dao.VMTemplateDetailsDaoImpl; import com.cloud.storage.dao.VMTemplateHostDaoImpl; import com.cloud.storage.dao.VMTemplatePoolDaoImpl; import com.cloud.storage.dao.VMTemplateZoneDaoImpl; @@ -165,6 +166,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com protected void populateDaos() { addDao("StackMaidDao", StackMaidDaoImpl.class); addDao("VMTemplateZoneDao", VMTemplateZoneDaoImpl.class); + addDao("VMTemplateDetailsDao", VMTemplateDetailsDaoImpl.class); addDao("DomainRouterDao", DomainRouterDaoImpl.class); addDao("HostDao", HostDaoImpl.class); addDao("VMInstanceDao", VMInstanceDaoImpl.class); diff --git a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java index d8fbaf021d1..7f1f1286a5c 100755 --- a/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VMTemplateDaoImpl.java @@ -67,6 +67,9 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem @Inject VMTemplateZoneDao _templateZoneDao; + @Inject + VMTemplateDetailsDao _templateDetailsDao; + @Inject ConfigurationDao _configDao; @Inject @@ -532,6 +535,9 @@ public class VMTemplateDaoImpl extends GenericDaoBase implem VMTemplateVO tmplt2 = findById(tmplt.getId()); if (tmplt2 == null){ persist(tmplt); + if(tmplt.getDetails() != null) { + _templateDetailsDao.persist(tmplt.getId(), tmplt.getDetails()); + } } VMTemplateZoneVO tmpltZoneVO = _templateZoneDao.findByZoneTemplate(zoneId, tmplt.getId()); if ( tmpltZoneVO == null ) { diff --git a/server/src/com/cloud/storage/dao/VMTemplateDetailsDao.java b/server/src/com/cloud/storage/dao/VMTemplateDetailsDao.java new file mode 100644 index 00000000000..9b742f90fa2 --- /dev/null +++ b/server/src/com/cloud/storage/dao/VMTemplateDetailsDao.java @@ -0,0 +1,33 @@ +/** + * 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 . + * + */ +package com.cloud.storage.dao; + +import java.util.Map; + +import com.cloud.storage.VMTemplateDetailVO; +import com.cloud.utils.db.GenericDao; + +public interface VMTemplateDetailsDao extends GenericDao { + Map findDetails(long templateId); + + void persist(long templateId, Map details); + + VMTemplateDetailVO findDetail(long templateId, String name); + + void deleteDetails(long vmId); +} diff --git a/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java new file mode 100644 index 00000000000..9550f4a15bb --- /dev/null +++ b/server/src/com/cloud/storage/dao/VMTemplateDetailsDaoImpl.java @@ -0,0 +1,80 @@ +package com.cloud.storage.dao; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ejb.Local; + +import com.cloud.storage.VMTemplateDetailVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; + +@Local(value=VMTemplateDetailsDao.class) +public class VMTemplateDetailsDaoImpl extends GenericDaoBase implements VMTemplateDetailsDao { + + protected final SearchBuilder TemplateSearch; + protected final SearchBuilder DetailSearch; + + protected VMTemplateDetailsDaoImpl() { + TemplateSearch = createSearchBuilder(); + TemplateSearch.and("templateId", TemplateSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + TemplateSearch.done(); + + DetailSearch = createSearchBuilder(); + DetailSearch.and("templateId", DetailSearch.entity().getTemplateId(), SearchCriteria.Op.EQ); + DetailSearch.and("name", DetailSearch.entity().getName(), SearchCriteria.Op.EQ); + DetailSearch.done(); + } + + @Override + public void deleteDetails(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("templateId", templateId); + + List results = search(sc, null); + for (VMTemplateDetailVO result : results) { + remove(result.getId()); + } + } + + @Override + public VMTemplateDetailVO findDetail(long templateId, String name) { + SearchCriteria sc = DetailSearch.create(); + sc.setParameters("templateId", templateId); + sc.setParameters("name", name); + + return findOneBy(sc); + } + + @Override + public Map findDetails(long templateId) { + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("templateId", templateId); + + List results = search(sc, null); + Map details = new HashMap(results.size()); + for (VMTemplateDetailVO result : results) { + details.put(result.getName(), result.getValue()); + } + + return details; + } + + @Override + public void persist(long templateId, Map details) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + SearchCriteria sc = TemplateSearch.create(); + sc.setParameters("templateId", templateId); + expunge(sc); + + for (Map.Entry detail : details.entrySet()) { + VMTemplateDetailVO vo = new VMTemplateDetailVO(templateId, detail.getKey(), detail.getValue()); + persist(vo); + } + txn.commit(); + } +} diff --git a/server/src/com/cloud/template/TemplateAdapter.java b/server/src/com/cloud/template/TemplateAdapter.java index dada14ff4b9..2e513d5bd42 100644 --- a/server/src/com/cloud/template/TemplateAdapter.java +++ b/server/src/com/cloud/template/TemplateAdapter.java @@ -1,5 +1,7 @@ package com.cloud.template; +import java.util.Map; + import com.cloud.api.commands.DeleteIsoCmd; import com.cloud.api.commands.DeleteTemplateCmd; import com.cloud.api.commands.RegisterIsoCmd; @@ -40,10 +42,10 @@ public interface TemplateAdapter extends Adapter { 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) throws ResourceAllocationException; + String accountName, Long domainId, String chksum, Boolean bootable, Map details) throws ResourceAllocationException; 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, String templateTag) throws ResourceAllocationException; + String accountName, Long domainId, String chksum, Boolean bootable, String templateTag, Map details) throws ResourceAllocationException; } diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index 45542d8eae9..b114dc05017 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -86,14 +86,17 @@ public abstract class TemplateAdapterBase implements TemplateAdapter { 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) throws ResourceAllocationException { + String accountName, Long domainId, String chksum, Boolean bootable, Map details) throws ResourceAllocationException { return prepare(isIso, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic, featured, isExtractable, format, guestOSId, zoneId, hypervisorType, - accountName, domainId, chksum, bootable, null); + accountName, domainId, chksum, bootable, null, details); } + 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, String templateTag) throws ResourceAllocationException { + String accountName, Long domainId, String chksum, Boolean bootable, String templateTag, Map details) + throws ResourceAllocationException { + Account ctxAccount = UserContext.current().getCaller(); Account resourceAccount = null; Long accountId = null; @@ -235,7 +238,7 @@ public abstract class TemplateAdapterBase implements TemplateAdapter { Long id = _tmpltDao.getNextInSequence(Long.class, "id"); UserContext.current().setEventDetails("Id: " +id+ " name: " + name); return new TemplateProfile(id, userId, name, displayText, bits, passwordEnabled, requiresHVM, url, isPublic, - featured, isExtractable, imgfmt, guestOSId, zoneId, hypervisorType, accountName, domainId, accountId, chksum, bootable, templateTag); + featured, isExtractable, imgfmt, guestOSId, zoneId, hypervisorType, accountName, domainId, accountId, chksum, bootable, templateTag, details); } @Override @@ -243,13 +246,13 @@ public abstract class TemplateAdapterBase implements TemplateAdapter { return prepare(false, UserContext.current().getCallerUserId(), cmd.getTemplateName(), cmd.getDisplayText(), cmd.getBits(), cmd.isPasswordEnabled(), cmd.getRequiresHvm(), cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), cmd.isExtractable(), cmd.getFormat(), cmd.getOsTypeId(), cmd.getZoneId(), HypervisorType.getType(cmd.getHypervisor()), - cmd.getAccountName(), cmd.getDomainId(), cmd.getChecksum(), true, cmd.getTemplateTag()); + cmd.getAccountName(), cmd.getDomainId(), cmd.getChecksum(), true, cmd.getTemplateTag(), cmd.getDetails()); } public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationException { return prepare(true, UserContext.current().getCallerUserId(), cmd.getIsoName(), cmd.getDisplayText(), 64, false, true, cmd.getUrl(), cmd.isPublic(), cmd.isFeatured(), cmd.isExtractable(), ImageFormat.ISO.toString(), cmd.getOsTypeId(), - cmd.getZoneId(), HypervisorType.None, cmd.getAccountName(), cmd.getDomainId(), null, cmd.isBootable(), null); + cmd.getZoneId(), HypervisorType.None, cmd.getAccountName(), cmd.getDomainId(), null, cmd.isBootable(), null, null); } protected VMTemplateVO persistTemplate(TemplateProfile profile) { @@ -257,7 +260,8 @@ public abstract class TemplateAdapterBase implements TemplateAdapter { VMTemplateVO template = new VMTemplateVO(profile.getTemplateId(), profile.getName(), profile.getFormat(), profile.getIsPublic(), profile.getFeatured(), profile.getIsExtractable(), TemplateType.USER, profile.getUrl(), profile.getRequiresHVM(), profile.getBits(), profile.getAccountId(), profile.getCheckSum(), profile.getDisplayText(), - profile.getPasswordEnabled(), profile.getGuestOsId(), profile.getBootable(), profile.getHypervisorType(), profile.getTemplateTag()); + profile.getPasswordEnabled(), profile.getGuestOsId(), profile.getBootable(), profile.getHypervisorType(), profile.getTemplateTag(), + profile.getDetails()); if (zoneId == null || zoneId == -1) { List dcs = _dcDao.listAllIncludingRemoved(); diff --git a/server/src/com/cloud/template/TemplateProfile.java b/server/src/com/cloud/template/TemplateProfile.java index f5e7ee39285..6e9bb223d9c 100644 --- a/server/src/com/cloud/template/TemplateProfile.java +++ b/server/src/com/cloud/template/TemplateProfile.java @@ -1,5 +1,7 @@ package com.cloud.template; +import java.util.Map; + import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateVO; @@ -27,10 +29,11 @@ public class TemplateProfile { Long templateId; VMTemplateVO template; String templateTag; + Map details; public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId, - HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable) { + HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, Map details) { this.templateId = templateId; this.userId = userId; this.name = name; @@ -51,6 +54,7 @@ public class TemplateProfile { this.accountId = accountId; this.chksum = chksum; this.bootable = bootable; + this.details = details; } public TemplateProfile(Long userId, VMTemplateVO template, Long zoneId) { @@ -61,9 +65,9 @@ public class TemplateProfile { public TemplateProfile(Long templateId, Long userId, String name, String displayText, Integer bits, Boolean passwordEnabled, Boolean requiresHvm, String url, Boolean isPublic, Boolean featured, Boolean isExtractable, ImageFormat format, Long guestOsId, Long zoneId, - HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, String templateTag) { + HypervisorType hypervisorType, String accountName, Long domainId, Long accountId, String chksum, Boolean bootable, String templateTag, Map details) { this(templateId, userId, name, displayText, bits, passwordEnabled, requiresHvm, url, isPublic, featured, isExtractable, format, guestOsId, zoneId, - hypervisorType, accountName, domainId, accountId, chksum, bootable); + hypervisorType, accountName, domainId, accountId, chksum, bootable, details); this.templateTag = templateTag; } @@ -215,4 +219,11 @@ public class TemplateProfile { this.templateTag = templateTag; } + public Map getDetails() { + return this.details; + } + + public void setDetails(Map details) { + this.details = details; + } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 8b175d0191a..1cd111e34ff 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -167,6 +167,7 @@ import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.StoragePoolDao; import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; @@ -235,6 +236,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager @Inject protected VMTemplateDao _templateDao = null; @Inject + protected VMTemplateDetailsDao _templateDetailsDao = null; + @Inject protected VMTemplateHostDao _templateHostDao = null; @Inject protected VMTemplateZoneDao _templateZoneDao = null; @@ -1469,7 +1472,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager } } privateTemplate = new VMTemplateVO(nextTemplateId, uniqueName, name, ImageFormat.RAW, isPublic, featured, isExtractable, TemplateType.USER, null, null, requiresHvmValue, bitsValue, accountId, - null, description, passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag); + null, description, passwordEnabledValue, guestOS.getId(), true, hyperType, templateTag, cmd.getDetails()); if(sourceTemplateId != null){ if(s_logger.isDebugEnabled()){ s_logger.debug("This template is getting created from other template, setting source template Id to: "+sourceTemplateId); @@ -1481,6 +1484,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager // Increment the number of templates if (template != null) { _accountMgr.incrementResourceCount(accountId, ResourceType.template); + if(cmd.getDetails() != null) { + _templateDetailsDao.persist(template.getId(), cmd.getDetails()); + } } return template; diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index 067dbb2582b..f99c949b118 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -873,6 +873,15 @@ CREATE TABLE `cloud`.`vm_template` ( INDEX `i_vm_template__removed`(`removed`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`vm_template_details` ( + `id` bigint unsigned NOT NULL auto_increment, + `template_id` bigint unsigned NOT NULL COMMENT 'template id', + `name` varchar(255) NOT NULL, + `value` varchar(1024) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_vm_template_details__template_id` FOREIGN KEY `fk_vm_template_details__template_id`(`template_id`) REFERENCES `vm_template`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE TABLE `cloud`.`vm_instance` ( `id` bigint unsigned UNIQUE NOT NULL, `name` varchar(255) NOT NULL, diff --git a/setup/db/db/schema-2213to2214.sql b/setup/db/db/schema-2213to2214.sql index 597b454c923..beaf0625f49 100644 --- a/setup/db/db/schema-2213to2214.sql +++ b/setup/db/db/schema-2213to2214.sql @@ -37,3 +37,12 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Premium', 'DEFAULT', 'manage INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Premium', 'DEFAULT', 'management-server', 'usage.sanity.check.interval', null, 'Interval (in days) to check sanity of usage data'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Premium', 'DEFAULT', 'management-server', 'usage.aggregation.timezone', 'GMT', 'The timezone to use for usage stats aggregation'); INSERT IGNORE INTO `cloud`.`guest_os` (category_id, name, display_name) VALUES (6, NULL, "Windows PV"); + +CREATE TABLE `cloud`.`vm_template_details` ( + `id` bigint unsigned NOT NULL auto_increment, + `template_id` bigint unsigned NOT NULL COMMENT 'template id', + `name` varchar(255) NOT NULL, + `value` varchar(1024) NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_vm_template_details__template_id` FOREIGN KEY `fk_vm_template_details__template_id`(`template_id`) REFERENCES `vm_template`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8;