diff --git a/api/src/main/java/com/cloud/storage/GuestOS.java b/api/src/main/java/com/cloud/storage/GuestOS.java index 371260bec64e..90b904758a9e 100644 --- a/api/src/main/java/com/cloud/storage/GuestOS.java +++ b/api/src/main/java/com/cloud/storage/GuestOS.java @@ -34,4 +34,6 @@ public interface GuestOS extends InternalIdentity, Identity { Date getRemoved(); boolean getIsUserDefined(); + + boolean getForDisplay(); } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java index 2b95c209bb86..b0d59d493623 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsCmd.java @@ -27,6 +27,7 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.GuestOSCategoryResponse; import org.apache.cloudstack.api.response.GuestOSResponse; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.context.CallContext; import com.cloud.event.EventTypes; @@ -60,6 +61,8 @@ public class AddGuestOsCmd extends BaseAsyncCreateCmd { @Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, required = false, description = "Map of (key/value pairs)") private Map details; + @Parameter(name="forDisplay", type=CommandType.BOOLEAN, description="whether this guest OS is available for end users", authorized = {RoleType.Admin}) + private Boolean display; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -78,7 +81,7 @@ public String getOsName() { } public Map getDetails() { - Map detailsMap = new HashMap(); + Map detailsMap = new HashMap<>(); if (!details.isEmpty()) { Collection servicesCollection = details.values(); Iterator iter = servicesCollection.iterator(); @@ -92,6 +95,9 @@ public Map getDetails() { return detailsMap; } + public Boolean getForDisplay() { + return display; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java index 1168bf00ffc6..502b1f8faae1 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsCmd.java @@ -26,6 +26,7 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.GuestOSResponse; +import org.apache.cloudstack.acl.RoleType; import com.cloud.event.EventTypes; import com.cloud.storage.GuestOS; @@ -56,8 +57,10 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.DETAILS, type = CommandType.MAP, required = true, description = "Map of (key/value pairs)") private Map details; + @Parameter(name="forDisplay", type=CommandType.BOOLEAN, description="whether this guest OS is available for end users", authorized = {RoleType.Admin}) + private Boolean display; -///////////////////////////////////////////////////// + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -70,7 +73,7 @@ public String getOsDisplayName() { } public Map getDetails() { - Map detailsMap = new HashMap();; + Map detailsMap = new HashMap<>();; if (!details.isEmpty()) { Collection servicesCollection = details.values(); Iterator iter = servicesCollection.iterator(); @@ -84,6 +87,10 @@ public Map getDetails() { return detailsMap; } + public Boolean getForDisplay() { + return display; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java index 7419cd8f7595..9d6cd4385610 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/guest/ListGuestOsCmd.java @@ -19,8 +19,10 @@ import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.BooleanUtils; import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; @@ -51,6 +53,10 @@ public class ListGuestOsCmd extends BaseListCmd { @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "list os by description", since = "3.0.1") private String description; + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "list resources by display flag; only ROOT admin is eligible to pass this parameter", + since = "4.18.1", authorized = {RoleType.Admin}) + private Boolean display; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -67,6 +73,10 @@ public String getDescription() { return description; } + public Boolean getDisplay() { + return BooleanUtils.toBooleanDefaultIfNull(display, true); + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -74,8 +84,8 @@ public String getDescription() { @Override public void execute() { Pair, Integer> result = _mgr.listGuestOSByCriteria(this); - ListResponse response = new ListResponse(); - List osResponses = new ArrayList(); + ListResponse response = new ListResponse<>(); + List osResponses = new ArrayList<>(); for (GuestOS guestOS : result.first()) { GuestOSResponse guestOSResponse = _responseGenerator.createGuestOSResponse(guestOS); osResponses.add(guestOSResponse); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java index c1a57c3e0e14..7ec2677ca326 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/GuestOSResponse.java @@ -43,6 +43,10 @@ public class GuestOSResponse extends BaseResponse { @Param(description = "is the guest OS user defined") private Boolean isUserDefined; + @SerializedName(ApiConstants.FOR_DISPLAY) + @Param(description = "is the guest OS visible for the users") + private Boolean forDisplay; + public String getId() { return id; } @@ -75,4 +79,12 @@ public void setIsUserDefined(Boolean isUserDefined) { this.isUserDefined = isUserDefined; } + public Boolean getForDisplay() { + return this.forDisplay; + } + + public void setForDisplay(final Boolean forDisplay) { + this.forDisplay = forDisplay; + } + } diff --git a/engine/schema/src/main/java/com/cloud/storage/GuestOSVO.java b/engine/schema/src/main/java/com/cloud/storage/GuestOSVO.java index f04f9a4208c7..03955f17667d 100644 --- a/engine/schema/src/main/java/com/cloud/storage/GuestOSVO.java +++ b/engine/schema/src/main/java/com/cloud/storage/GuestOSVO.java @@ -57,6 +57,9 @@ public class GuestOSVO implements GuestOS { @Column(name = "is_user_defined") private boolean isUserDefined; + @Column(name = "display", updatable = true, nullable = false) + protected boolean display = true; + @Override public long getId() { return id; @@ -120,4 +123,15 @@ public boolean getIsUserDefined() { public void setIsUserDefined(boolean isUserDefined) { this.isUserDefined = isUserDefined; } + + public boolean getForDisplay() { + return isDisplay(); + } + public boolean isDisplay() { + return display; + } + + public void setDisplay(boolean display) { + this.display = display; + } } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDao.java index 83e19b17e258..eeae0bdae006 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDao.java @@ -16,12 +16,23 @@ // under the License. package com.cloud.storage.dao; +import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOSVO; +import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; +import java.util.List; +import java.util.Set; + public interface GuestOSDao extends GenericDao { - GuestOSVO listByDisplayName(String displayName); + GuestOSVO findOneByDisplayName(String displayName); GuestOSVO findByCategoryIdAndDisplayNameOrderByCreatedDesc(long categoryId, String displayName); + + Set findDoubleNames(); + + List listByDisplayName(String displayName); + + Pair, Integer> listGuestOSByCriteria(Long startIndex, Long pageSize, Long id, Long osCategoryId, String description, String keyword, Boolean forDisplay); } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDaoImpl.java index 68da2b92acb5..19c4e9021882 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSDaoImpl.java @@ -17,8 +17,19 @@ package com.cloud.storage.dao; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import com.cloud.storage.GuestOS; +import com.cloud.utils.Pair; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.TransactionLegacy; +import com.cloud.utils.exception.CloudRuntimeException; import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Component; @@ -42,7 +53,7 @@ public GuestOSDaoImpl() { } @Override - public GuestOSVO listByDisplayName(String displayName) { + public GuestOSVO findOneByDisplayName(String displayName) { SearchCriteria sc = Search.create(); sc.setParameters("display_name", displayName); return findOneBy(sc); @@ -62,4 +73,69 @@ public GuestOSVO findByCategoryIdAndDisplayNameOrderByCreatedDesc(long categoryI } return null; } + + /** + + "select display_name from" + + "(select display_name, count(1) as count from guest_os go1 where removed is null group by display_name having count > 1) tab0"; + * + * @return + */ + @Override + @DB + public Set findDoubleNames() { + String selectSql = "SELECT display_name FROM (SELECT display_name, count(1) AS count FROM guest_os go1 WHERE removed IS NULL GROUP BY display_name HAVING count > 1) tab0"; + Set names = new HashSet<>(); + Connection conn = TransactionLegacy.getStandaloneConnection(); + try { + PreparedStatement stmt = conn.prepareStatement(selectSql); + ResultSet rs = stmt.executeQuery(); + while (rs != null && rs.next()) { + names.add(rs.getString(1)); + } + } catch (SQLException ex) { + throw new CloudRuntimeException("Error while trying to find duplicate guest OSses", ex); + } + return names; + } + + /** + * get all with a certain display name + * @param displayName + * @return a list with GuestOS objects + */ + @Override + public List listByDisplayName(String displayName) { + SearchCriteria sc = Search.create(); + sc.setParameters("display_name", displayName); + return listBy(sc); + } + + public Pair, Integer> listGuestOSByCriteria(Long startIndex, Long pageSize, Long id, Long osCategoryId, String description, String keyword, Boolean forDisplay) { + final Filter searchFilter = new Filter(GuestOSVO.class, "displayName", true, startIndex, pageSize); + final SearchCriteria sc = createSearchCriteria(); + + if (id != null) { + sc.addAnd("id", SearchCriteria.Op.EQ, id); + } + + if (osCategoryId != null) { + sc.addAnd("categoryId", SearchCriteria.Op.EQ, osCategoryId); + } + + if (description != null) { + sc.addAnd("displayName", SearchCriteria.Op.LIKE, "%" + description + "%"); + } + + if (keyword != null) { + sc.addAnd("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%"); + } + + if (forDisplay != null) { + sc.addAnd("display", SearchCriteria.Op.EQ, forDisplay); + } + + final Pair, Integer> result = searchAndCount(sc, searchFilter); + return new Pair<>(result.first(), result.second()); + } + } diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java index 47a71433a327..f9a91c7d2109 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDao.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.storage.dao; -import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.utils.db.GenericDao; @@ -24,7 +23,12 @@ public interface GuestOSHypervisorDao extends GenericDao { - HypervisorType findHypervisorTypeByGuestOsId(long guestOsId); + /** + * list all the mappings for a guesos id + * @param guestOsId the guestos to look for + * @return a list of mappings + */ + List listByGuestOsId(long guestOsId); GuestOSHypervisorVO findByOsIdAndHypervisor(long guestOsId, String hypervisorType, String hypervisorVersion); diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java index 65f17c29fbc4..e03e3f7ce640 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/GuestOSHypervisorDaoImpl.java @@ -20,13 +20,12 @@ import java.util.Date; import java.util.List; -import com.cloud.utils.db.QueryBuilder; import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Component; -import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSHypervisorVO; import com.cloud.utils.db.Filter; +import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -82,11 +81,10 @@ public GuestOSHypervisorDaoImpl() { } @Override - public HypervisorType findHypervisorTypeByGuestOsId(long guestOsId) { + public List listByGuestOsId(long guestOsId) { SearchCriteria sc = guestOsSearch.create(); sc.setParameters("guest_os_id", guestOsId); - GuestOSHypervisorVO goh = findOneBy(sc); - return HypervisorType.getType(goh.getHypervisorType()); + return listBy(sc); } @Override diff --git a/engine/schema/src/main/java/com/cloud/upgrade/GuestOsMapper.java b/engine/schema/src/main/java/com/cloud/upgrade/GuestOsMapper.java index 739eb32261c0..20f9d851c3b3 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/GuestOsMapper.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/GuestOsMapper.java @@ -23,7 +23,9 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.inject.Inject; @@ -53,6 +55,89 @@ public GuestOsMapper() { guestOSDao = new GuestOSDaoImpl(); } + public void mergeDuplicates() { + LOG.info("merging duplicate guest osses"); + Set> duplicates = findDuplicates(); + LOG.debug(String.format("merging %d sets of duplicates", duplicates.size())); + for (Set setOfGuestOSes : duplicates) { + // decide which to (mark as) remove(d) + // # highest/lowest id + // # or is user_defined == false + GuestOSVO guestOSVO = highestIdFrom(setOfGuestOSes); + LOG.info(String.format("merging %d duplicates for %s ", setOfGuestOSes.size(), guestOSVO.getDisplayName())); + makeNormative(guestOSVO, setOfGuestOSes); + + } + } + + public void makeNormative(GuestOSVO guestOSVO, Set setOfGuestOSes) { + for (GuestOSVO oldGuestOs : setOfGuestOSes) { + if (guestOSVO.getId() != oldGuestOs.getId()) { + List mappings = guestOSHypervisorDao.listByGuestOsId(oldGuestOs.getId()); + copyMappings(guestOSVO, mappings); + makeHidden(oldGuestOs); + } + } + } + + private void makeHidden(GuestOSVO guestOSVO) { + guestOSVO.setDisplay(false); + guestOSDao.update(guestOSVO.getId(),guestOSVO); + } + + private void copyMappings(GuestOSVO guestOSVO, List mappings) { + for (GuestOSHypervisorVO mapping : mappings) { + if (null == guestOSHypervisorDao.findByOsIdAndHypervisor(guestOSVO.getId(), mapping.getHypervisorType(), mapping.getHypervisorVersion())) { + GuestOSHypervisorVO newMap = new GuestOSHypervisorVO(); + newMap.setGuestOsId(guestOSVO.getId()); + newMap.setGuestOsName(mapping.getGuestOsName()); + newMap.setHypervisorType(mapping.getHypervisorType()); + newMap.setHypervisorVersion(mapping.getHypervisorVersion()); + guestOSHypervisorDao.persist(newMap); + } + } + } + + private GuestOSVO highestIdFrom(Set setOfGuestOSes) { + GuestOSVO rc = null; + for (GuestOSVO guestOSVO: setOfGuestOSes) { + if (rc == null || (guestOSVO.getId() > rc.getId() && !guestOSVO.getIsUserDefined())) { + rc = guestOSVO; + break; + } + } + return rc; + } + + /** + * + ¨¨¨ + select * from guest_os go2 + where display_name + in (select display_name from + (select display_name, count(1) as count from guest_os go1 group by display_name having count > 1) tab0); + ¨¨¨ + * and group them by display_name + * + * + * @return a list of sets of duplicate + */ + private Set> findDuplicates() { + Set> rc = new HashSet<>(); + Set names = guestOSDao.findDoubleNames(); + for (String name : names) { + List guestOsses = guestOSDao.listByDisplayName(name); + if (CollectionUtils.isNotEmpty(guestOsses)) { + rc.add(new HashSet<>(guestOsses)); + } + } + return rc; + } + + public List listByDisplayName(String displayName) { + return guestOSDao.listByDisplayName(displayName); + } + private long getGuestOsId(long categoryId, String displayName) { GuestOSVO guestOS = guestOSDao.findByCategoryIdAndDisplayNameOrderByCreatedDesc(categoryId, displayName); long id = 0l; @@ -76,18 +161,19 @@ private long getGuestOsIdFromHypervisorMapping(GuestOSHypervisorMapping mapping) } public void addGuestOsAndHypervisorMappings(long categoryId, String displayName, List mappings) { - if (!addGuestOs(categoryId, displayName)) { - LOG.warn("Couldn't add the guest OS with category id: " + categoryId + " and display name: " + displayName); - return; - } - - if (CollectionUtils.isEmpty(mappings)) { - return; - } - long guestOsId = getGuestOsId(categoryId, displayName); if (guestOsId == 0) { LOG.debug("No guest OS found with category id: " + categoryId + " and display name: " + displayName); + if (!addGuestOs(categoryId, displayName)) { + LOG.warn("Couldn't add the guest OS with category id: " + categoryId + " and display name: " + displayName); + return; + } + guestOsId = getGuestOsId(categoryId, displayName); + } else { + updateToSystemDefined(guestOsId); + } + + if (CollectionUtils.isEmpty(mappings)) { return; } @@ -96,6 +182,12 @@ public void addGuestOsAndHypervisorMappings(long categoryId, String displayName, } } + private void updateToSystemDefined(long guestOsId) { + GuestOSVO guestOsVo = guestOSDao.findById(guestOsId); + guestOsVo.setIsUserDefined(false); + guestOSDao.update(guestOsId, guestOsVo);// TODO: update is_user_defined to false + } + public boolean addGuestOs(long categoryId, String displayName) { LOG.debug("Adding guest OS with category id: " + categoryId + " and display name: " + displayName); GuestOSVO guestOS = new GuestOSVO(); diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41800to41810.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41800to41810.java index 53bd497ca22b..8eb50666ec84 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41800to41810.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41800to41810.java @@ -19,6 +19,7 @@ import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.GuestOSHypervisorMapping; import com.cloud.upgrade.GuestOsMapper; +import com.cloud.storage.GuestOSVO; import com.cloud.upgrade.SystemVmTemplateRegistration; import com.cloud.utils.exception.CloudRuntimeException; import org.apache.log4j.Logger; @@ -26,10 +27,13 @@ import java.io.InputStream; import java.sql.Connection; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; public class Upgrade41800to41810 implements DbUpgrade, DbUpgradeSystemVmTemplate { final static Logger LOG = Logger.getLogger(Upgrade41800to41810.class); + private GuestOsMapper guestOsMapper = new GuestOsMapper(); + private SystemVmTemplateRegistration systemVmTemplateRegistration; @Override @@ -64,6 +68,14 @@ public void performDataMigration(Connection conn) { updateGuestOsMappings(conn); copyGuestOsMappingsToVMware80u1(); addForeignKeyToAutoscaleVmprofiles(conn); + mergeDuplicateGuestOSes(); + } + + private void mergeDuplicateGuestOSes() { + guestOsMapper.mergeDuplicates(); + List nines = guestOsMapper.listByDisplayName("Red Hat Enterprise Linux 9"); + GuestOSVO nineDotZero = guestOsMapper.listByDisplayName("Red Hat Enterprise Linux 9.0").get(0); + guestOsMapper.makeNormative(nineDotZero, new HashSet<>(nines)); } @Override diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41720to41800.sql b/engine/schema/src/main/resources/META-INF/db/schema-41720to41800.sql index 2af6723c134b..7941424a43f1 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41720to41800.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41720to41800.sql @@ -1568,4 +1568,6 @@ UPDATE SET usage_type = 22 WHERE - usage_type = 24 AND usage_display like '% io write'; \ No newline at end of file + usage_type = 24 AND usage_display like '% io write'; + +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.guest_os', 'display', 'tinyint(1) DEFAULT ''1'' COMMENT ''should this guest_os be shown to the end user'' '); \ No newline at end of file diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41800to41810.sql b/engine/schema/src/main/resources/META-INF/db/schema-41800to41810.sql index 495c184918c5..4ea2bf572920 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41800to41810.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41800to41810.sql @@ -43,3 +43,7 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.autoscale_vmprofiles', 'user_data_de UPDATE `cloud`.`service_offering` so SET so.limit_cpu_use = 0 WHERE so.default_use = 1 AND so.vm_type IN ('domainrouter', 'secondarystoragevm', 'consoleproxy', 'internalloadbalancervm', 'elasticloadbalancervm'); + +-- fix erronous commas in guest_os names +UPDATE `cloud`.`guest_os_hypervisor` SET guest_os_name = 'rhel9_64Guest' WHERE guest_os_name = 'rhel9_64Guest,'; +CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.guest_os', 'display', 'tinyint(1) DEFAULT ''1'' COMMENT ''should this guest_os be shown to the end user'' '); diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java index f148a16473e4..db41ab19d566 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/guru/VMwareGuru.java @@ -456,8 +456,8 @@ private DatacenterMO getDatacenterMO(long zoneId) throws Exception { */ private Long getImportingVMGuestOs(VirtualMachineConfigSummary configSummary) { String guestFullName = configSummary.getGuestFullName(); - GuestOSVO os = _guestOsDao.listByDisplayName(guestFullName); - return os != null ? os.getId() : _guestOsDao.listByDisplayName("Other (64-bit)").getId(); + GuestOSVO os = _guestOsDao.findOneByDisplayName(guestFullName); + return os != null ? os.getId() : _guestOsDao.findOneByDisplayName("Other (64-bit)").getId(); } /** diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java index 162b1f38addd..c4d7f3cc717e 100644 --- a/server/src/main/java/com/cloud/api/ApiDBUtils.java +++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java @@ -1104,7 +1104,7 @@ public static GuestOS findGuestOSById(Long id) { } public static GuestOS findGuestOSByDisplayName(String displayName) { - return s_guestOSDao.listByDisplayName(displayName); + return s_guestOSDao.findOneByDisplayName(displayName); } public static HostVO findHostById(Long hostId) { diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 55f00a609e9c..05aee6b6ccb6 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -3646,6 +3646,7 @@ public GuestOSResponse createGuestOSResponse(GuestOS guestOS) { response.setDescription(guestOS.getDisplayName()); response.setId(guestOS.getUuid()); response.setIsUserDefined(guestOS.getIsUserDefined()); + response.setForDisplay(guestOS.getForDisplay()); GuestOSCategoryVO category = ApiDBUtils.findGuestOsCategoryById(guestOS.getCategoryId()); if (category != null) { response.setOsCategoryId(category.getUuid()); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 85e86b5b21be..c6ace852bd36 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -2625,32 +2625,15 @@ protected void setParameters(SearchCriteria sc, final ListPublicIpA @Override public Pair, Integer> listGuestOSByCriteria(final ListGuestOsCmd cmd) { - final Filter searchFilter = new Filter(GuestOSVO.class, "displayName", true, cmd.getStartIndex(), cmd.getPageSizeVal()); final Long id = cmd.getId(); final Long osCategoryId = cmd.getOsCategoryId(); final String description = cmd.getDescription(); final String keyword = cmd.getKeyword(); + final Long startIndex = cmd.getStartIndex(); + final Long pageSize = cmd.getPageSizeVal(); + Boolean forDisplay = cmd.getDisplay(); - final SearchCriteria sc = _guestOSDao.createSearchCriteria(); - - if (id != null) { - sc.addAnd("id", SearchCriteria.Op.EQ, id); - } - - if (osCategoryId != null) { - sc.addAnd("categoryId", SearchCriteria.Op.EQ, osCategoryId); - } - - if (description != null) { - sc.addAnd("displayName", SearchCriteria.Op.LIKE, "%" + description + "%"); - } - - if (keyword != null) { - sc.addAnd("displayName", SearchCriteria.Op.LIKE, "%" + keyword + "%"); - } - - final Pair, Integer> result = _guestOSDao.searchAndCount(sc, searchFilter); - return new Pair, Integer>(result.first(), result.second()); + return _guestOSDao.listGuestOSByCriteria(startIndex, pageSize, id, osCategoryId, description, keyword, forDisplay); } @Override @@ -2796,18 +2779,20 @@ public GuestOS addGuestOs(final AddGuestOsCmd cmd) { guestOsVo.setDisplayName(displayName); guestOsVo.setName(name); guestOsVo.setIsUserDefined(true); + guestOsVo.setDisplay(cmd.getForDisplay() == null ? true : cmd.getForDisplay()); final GuestOS guestOsPersisted = _guestOSDao.persist(guestOsVo); - if (cmd.getDetails() != null && !cmd.getDetails().isEmpty()) { - Map detailsMap = cmd.getDetails(); - for (Object key : detailsMap.keySet()) { - _guestOsDetailsDao.addDetail(guestOsPersisted.getId(), (String)key, detailsMap.get(key), false); - } - } + persistGuestOsDetails(cmd.getDetails(), guestOsPersisted.getId()); return guestOsPersisted; } + private void persistGuestOsDetails(Map details, long guestOsPersistedId) { + for (Object key : details.keySet()) { + _guestOsDetailsDao.addDetail(guestOsPersistedId, (String)key, details.get(key), false); + } + } + @Override @ActionEvent(eventType = EventTypes.EVENT_GUEST_OS_ADD, eventDescription = "Adding a new guest OS type", async = true) public GuestOS getAddedGuestOs(final Long guestOsId) { @@ -2831,12 +2816,7 @@ public GuestOS updateGuestOs(final UpdateGuestOsCmd cmd) { throw new InvalidParameterValueException("Unable to modify system defined guest OS"); } - if (cmd.getDetails() != null && !cmd.getDetails().isEmpty()) { - Map detailsMap = cmd.getDetails(); - for (Object key : detailsMap.keySet()) { - _guestOsDetailsDao.addDetail(id, (String)key, detailsMap.get(key), false); - } - } + persistGuestOsDetails(cmd.getDetails(), id); //Check if update is needed if (displayName.equals(guestOsHandle.getDisplayName())) { @@ -2850,6 +2830,9 @@ public GuestOS updateGuestOs(final UpdateGuestOsCmd cmd) { } final GuestOSVO guestOs = _guestOSDao.createForUpdate(id); guestOs.setDisplayName(displayName); + if (cmd.getForDisplay() != null) { + guestOs.setDisplay(cmd.getForDisplay()); + } if (_guestOSDao.update(id, guestOs)) { return _guestOSDao.findById(id); } else { diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 72ccf621e3a3..eab1e98c8001 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -1214,7 +1214,7 @@ public UserVmResponse importUnmanagedInstance(ImportUnmanagedInstanceCmd cmd) { String osName = unmanagedInstance.getOperatingSystem(); GuestOS guestOS = null; if (StringUtils.isNotEmpty(osName)) { - guestOS = guestOSDao.listByDisplayName(osName); + guestOS = guestOSDao.findOneByDisplayName(osName); } GuestOSHypervisor guestOSHypervisor = null; if (guestOS != null) {