This is an automated email from the ASF dual-hosted git repository.
weizhou pushed a commit to branch 4.18
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.18 by this push:
new e4117e68d2f engine/schema: fix duplicated guest OSes in 4.18.0.0
(#7799)
e4117e68d2f is described below
commit e4117e68d2f04e307aba8b3d9b98cc248de384e1
Author: Wei Zhou <[email protected]>
AuthorDate: Wed Aug 23 09:44:34 2023 +0200
engine/schema: fix duplicated guest OSes in 4.18.0.0 (#7799)
Co-authored-by: Daan Hoogland <[email protected]>
---
api/src/main/java/com/cloud/storage/GuestOS.java | 2 +
.../api/command/admin/guest/AddGuestOsCmd.java | 8 +-
.../api/command/admin/guest/UpdateGuestOsCmd.java | 11 ++-
.../api/command/user/guest/ListGuestOsCmd.java | 14 ++-
.../cloudstack/api/response/GuestOSResponse.java | 12 +++
.../src/main/java/com/cloud/storage/GuestOSVO.java | 14 +++
.../java/com/cloud/storage/dao/GuestOSDao.java | 13 ++-
.../java/com/cloud/storage/dao/GuestOSDaoImpl.java | 78 ++++++++++++++-
.../cloud/storage/dao/GuestOSHypervisorDao.java | 8 +-
.../storage/dao/GuestOSHypervisorDaoImpl.java | 8 +-
.../main/java/com/cloud/upgrade/GuestOsMapper.java | 110 +++++++++++++++++++--
.../com/cloud/upgrade/dao/Upgrade41800to41810.java | 12 +++
.../resources/META-INF/db/schema-41720to41800.sql | 4 +-
.../resources/META-INF/db/schema-41800to41810.sql | 4 +
.../java/com/cloud/hypervisor/guru/VMwareGuru.java | 4 +-
server/src/main/java/com/cloud/api/ApiDBUtils.java | 2 +-
.../main/java/com/cloud/api/ApiResponseHelper.java | 1 +
.../com/cloud/server/ManagementServerImpl.java | 49 +++------
.../cloudstack/vm/UnmanagedVMsManagerImpl.java | 2 +-
19 files changed, 295 insertions(+), 61 deletions(-)
diff --git a/api/src/main/java/com/cloud/storage/GuestOS.java
b/api/src/main/java/com/cloud/storage/GuestOS.java
index 371260bec64..90b904758a9 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 2b95c209bb8..b0d59d49362 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.Parameter;
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 class AddGuestOsCmd extends BaseAsyncCreateCmd {
}
public Map getDetails() {
- Map<String, String> detailsMap = new HashMap<String, String>();
+ Map<String, String> detailsMap = new HashMap<>();
if (!details.isEmpty()) {
Collection<?> servicesCollection = details.values();
Iterator<?> iter = servicesCollection.iterator();
@@ -92,6 +95,9 @@ public class AddGuestOsCmd extends BaseAsyncCreateCmd {
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 1168bf00ffc..502b1f8faae 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.BaseAsyncCmd;
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 class UpdateGuestOsCmd extends BaseAsyncCmd {
}
public Map getDetails() {
- Map<String, String> detailsMap = new HashMap<String, String>();;
+ Map<String, String> detailsMap = new HashMap<>();;
if (!details.isEmpty()) {
Collection<?> servicesCollection = details.values();
Iterator<?> iter = servicesCollection.iterator();
@@ -84,6 +87,10 @@ public class UpdateGuestOsCmd extends BaseAsyncCmd {
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 7419cd8f759..9d6cd438561 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 @@ package org.apache.cloudstack.api.command.user.guest;
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 class ListGuestOsCmd extends BaseListCmd {
return description;
}
+ public Boolean getDisplay() {
+ return BooleanUtils.toBooleanDefaultIfNull(display, true);
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -74,8 +84,8 @@ public class ListGuestOsCmd extends BaseListCmd {
@Override
public void execute() {
Pair<List<? extends GuestOS>, Integer> result =
_mgr.listGuestOSByCriteria(this);
- ListResponse<GuestOSResponse> response = new
ListResponse<GuestOSResponse>();
- List<GuestOSResponse> osResponses = new ArrayList<GuestOSResponse>();
+ ListResponse<GuestOSResponse> response = new ListResponse<>();
+ List<GuestOSResponse> 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 c1a57c3e0e1..7ec2677ca32 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 class GuestOSResponse extends BaseResponse {
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 f04f9a4208c..03955f17667 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 class GuestOSVO implements GuestOS {
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 83e19b17e25..eeae0bdae00 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, Long> {
- GuestOSVO listByDisplayName(String displayName);
+ GuestOSVO findOneByDisplayName(String displayName);
GuestOSVO findByCategoryIdAndDisplayNameOrderByCreatedDesc(long
categoryId, String displayName);
+
+ Set<String> findDoubleNames();
+
+ List<GuestOSVO> listByDisplayName(String displayName);
+
+ Pair<List<? extends GuestOS>, 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 68da2b92acb..19c4e902188 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 class GuestOSDaoImpl extends GenericDaoBase<GuestOSVO,
Long> implements G
}
@Override
- public GuestOSVO listByDisplayName(String displayName) {
+ public GuestOSVO findOneByDisplayName(String displayName) {
SearchCriteria<GuestOSVO> sc = Search.create();
sc.setParameters("display_name", displayName);
return findOneBy(sc);
@@ -62,4 +73,69 @@ public class GuestOSDaoImpl extends
GenericDaoBase<GuestOSVO, Long> implements G
}
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<String> 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<String> 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<GuestOSVO> listByDisplayName(String displayName) {
+ SearchCriteria<GuestOSVO> sc = Search.create();
+ sc.setParameters("display_name", displayName);
+ return listBy(sc);
+ }
+
+ public Pair<List<? extends GuestOS>, 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<GuestOSVO> 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<List<GuestOSVO>, 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 47a71433a32..f9a91c7d210 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 @@ import java.util.List;
public interface GuestOSHypervisorDao extends GenericDao<GuestOSHypervisorVO,
Long> {
- 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<GuestOSHypervisorVO> 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 65f17c29fbc..e03e3f7ce64 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.ArrayList;
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 class GuestOSHypervisorDaoImpl extends
GenericDaoBase<GuestOSHypervisorVO
}
@Override
- public HypervisorType findHypervisorTypeByGuestOsId(long guestOsId) {
+ public List<GuestOSHypervisorVO> listByGuestOsId(long guestOsId) {
SearchCriteria<GuestOSHypervisorVO> 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 739eb32261c..20f9d851c3b 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 org.apache.log4j.Logger;
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 class GuestOsMapper {
guestOSDao = new GuestOSDaoImpl();
}
+ public void mergeDuplicates() {
+ LOG.info("merging duplicate guest osses");
+ Set<Set<GuestOSVO>> duplicates = findDuplicates();
+ LOG.debug(String.format("merging %d sets of duplicates",
duplicates.size()));
+ for (Set<GuestOSVO> 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<GuestOSVO>
setOfGuestOSes) {
+ for (GuestOSVO oldGuestOs : setOfGuestOSes) {
+ if (guestOSVO.getId() != oldGuestOs.getId()) {
+ List<GuestOSHypervisorVO> 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<GuestOSHypervisorVO>
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<GuestOSVO> 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<Set<GuestOSVO>> findDuplicates() {
+ Set<Set<GuestOSVO>> rc = new HashSet<>();
+ Set<String> names = guestOSDao.findDoubleNames();
+ for (String name : names) {
+ List<GuestOSVO> guestOsses = guestOSDao.listByDisplayName(name);
+ if (CollectionUtils.isNotEmpty(guestOsses)) {
+ rc.add(new HashSet<>(guestOsses));
+ }
+ }
+ return rc;
+ }
+
+ public List<GuestOSVO> 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 @@ public class GuestOsMapper {
}
public void addGuestOsAndHypervisorMappings(long categoryId, String
displayName, List<GuestOSHypervisorMapping> 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 class GuestOsMapper {
}
}
+ 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 53bd497ca22..8eb50666ec8 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 @@ package com.cloud.upgrade.dao;
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 org.apache.log4j.Logger;
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 class Upgrade41800to41810 implements DbUpgrade,
DbUpgradeSystemVmTemplate
updateGuestOsMappings(conn);
copyGuestOsMappingsToVMware80u1();
addForeignKeyToAutoscaleVmprofiles(conn);
+ mergeDuplicateGuestOSes();
+ }
+
+ private void mergeDuplicateGuestOSes() {
+ guestOsMapper.mergeDuplicates();
+ List<GuestOSVO> 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 2af6723c134..7941424a43f 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 495c184918c..4ea2bf57292 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 f148a16473e..db41ab19d56 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 @@ public class VMwareGuru extends HypervisorGuruBase
implements HypervisorGuru, Co
*/
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 162b1f38add..c4d7f3cc717 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 class ApiDBUtils {
}
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 55f00a609e9..05aee6b6ccb 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 class ApiResponseHelper implements
ResponseGenerator {
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 85e86b5b21b..c6ace852bd3 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 @@ public class ManagementServerImpl extends ManagerBase
implements ManagementServe
@Override
public Pair<List<? extends GuestOS>, 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<GuestOSVO> 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<List<GuestOSVO>, Integer> result =
_guestOSDao.searchAndCount(sc, searchFilter);
- return new Pair<List<? extends GuestOS>, Integer>(result.first(),
result.second());
+ return _guestOSDao.listGuestOSByCriteria(startIndex, pageSize, id,
osCategoryId, description, keyword, forDisplay);
}
@Override
@@ -2796,18 +2779,20 @@ public class ManagementServerImpl extends ManagerBase
implements ManagementServe
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<String, String> 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<String, String> 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 class ManagementServerImpl extends ManagerBase
implements ManagementServe
throw new InvalidParameterValueException("Unable to modify system
defined guest OS");
}
- if (cmd.getDetails() != null && !cmd.getDetails().isEmpty()) {
- Map<String, String> 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 class ManagementServerImpl extends ManagerBase
implements ManagementServe
}
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 72ccf621e3a..eab1e98c800 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 class UnmanagedVMsManagerImpl implements
UnmanagedVMsManager {
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) {