You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ha...@apache.org on 2022/12/30 07:46:31 UTC
[cloudstack] 01/07: Guest OS mapping improvements - Checks the OS mapping name in hypervisor (VMware, XenServer) - Displays guest OS mappings in UI
This is an automated email from the ASF dual-hosted git repository.
harikrishna pushed a commit to branch guest-os-mappings-improvements
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit fad7a8fcdf4a0fcef6d526d4a485f656b6936317
Author: Suresh Kumar Anaparti <su...@gmail.com>
AuthorDate: Fri Jul 15 17:39:43 2022 +0530
Guest OS mapping improvements
- Checks the OS mapping name in hypervisor (VMware, XenServer)
- Displays guest OS mappings in UI
---
.../org/apache/cloudstack/api/ApiConstants.java | 1 +
.../command/admin/guest/AddGuestOsMappingCmd.java | 17 ++++++
.../admin/guest/UpdateGuestOsMappingCmd.java | 10 ++++
.../cloud/agent/api/CheckGuestOsMappingAnswer.java | 38 +++++++++++++
.../agent/api/CheckGuestOsMappingCommand.java | 54 +++++++++++++++++++
.../src/main/java/com/cloud/host/dao/HostDao.java | 2 +
.../main/java/com/cloud/host/dao/HostDaoImpl.java | 18 +++++++
.../hypervisor/vmware/resource/VmwareResource.java | 28 ++++++++++
.../CitrixCheckGuestOsMappingCommandWrapper.java | 63 ++++++++++++++++++++++
.../com/cloud/server/ManagementServerImpl.java | 53 +++++++++++++++++-
ui/public/locales/en.json | 9 ++++
ui/src/components/view/ListView.vue | 9 ++++
ui/src/config/section/config.js | 19 +++++++
ui/src/views/AutogenView.vue | 10 +++-
.../com/cloud/hypervisor/vmware/mo/ClusterMO.java | 12 +++++
.../com/cloud/hypervisor/vmware/mo/HostMO.java | 11 ++++
.../hypervisor/vmware/mo/VmwareHypervisorHost.java | 4 ++
17 files changed, 355 insertions(+), 3 deletions(-)
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index e43572ae489..a52eba6e555 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -301,6 +301,7 @@ public class ApiConstants {
public static final String OS_TYPE_ID = "ostypeid";
public static final String OS_DISPLAY_NAME = "osdisplayname";
public static final String OS_NAME_FOR_HYPERVISOR = "osnameforhypervisor";
+ public static final String OS_MAPPING_CHECK_ENABLED = "osmappingcheckenabled";
public static final String OUTOFBANDMANAGEMENT_POWERSTATE = "outofbandmanagementpowerstate";
public static final String OUTOFBANDMANAGEMENT_ENABLED = "outofbandmanagementenabled";
public static final String OUTPUT = "output";
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java
index 79e82d6f5d4..829668b134f 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/AddGuestOsMappingCmd.java
@@ -58,6 +58,12 @@ public class AddGuestOsMappingCmd extends BaseAsyncCreateCmd {
@Parameter(name = ApiConstants.OS_NAME_FOR_HYPERVISOR, type = CommandType.STRING, required = true, description = "OS name specific to the hypervisor")
private String osNameForHypervisor;
+ @Parameter(name = ApiConstants.OS_MAPPING_CHECK_ENABLED, type = CommandType.BOOLEAN, required = false, description = "When set to true, checks the guest os mapping name in the hypervisor (supports VMware and XenServer only)", since = "4.18.0")
+ private Boolean osMappingCheckEnabled;
+
+ @Parameter(name = ApiConstants.FORCED, type = CommandType.BOOLEAN, required = false, description = "Forces add guest os mapping, overrides any existing user defined mapping", since = "4.18.0")
+ private Boolean forced;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -82,6 +88,17 @@ public class AddGuestOsMappingCmd extends BaseAsyncCreateCmd {
return osNameForHypervisor;
}
+ public Boolean getOsMappingCheckEnabled() {
+ if (osMappingCheckEnabled == null) {
+ return false;
+ }
+ return osMappingCheckEnabled;
+ }
+
+ public boolean isForced() {
+ return (forced != null) ? forced : false;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java
index 2683a21dfcf..5080775500d 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/guest/UpdateGuestOsMappingCmd.java
@@ -48,6 +48,9 @@ public class UpdateGuestOsMappingCmd extends BaseAsyncCmd {
@Parameter(name = ApiConstants.OS_NAME_FOR_HYPERVISOR, type = CommandType.STRING, required = true, description = "Hypervisor specific name for this Guest OS")
private String osNameForHypervisor;
+ @Parameter(name = ApiConstants.OS_MAPPING_CHECK_ENABLED, type = CommandType.BOOLEAN, required = false, description = "When set to true, checks the guest os mapping name in the hypervisor (supports VMware and XenServer only)", since = "4.18.0")
+ private Boolean osMappingCheckEnabled;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -60,6 +63,13 @@ public class UpdateGuestOsMappingCmd extends BaseAsyncCmd {
return osNameForHypervisor;
}
+ public Boolean getOsMappingCheckEnabled() {
+ if (osMappingCheckEnabled == null) {
+ return false;
+ }
+ return osMappingCheckEnabled;
+ }
+
@Override
public void execute() {
GuestOSHypervisor guestOsMapping = _mgr.updateGuestOsMapping(this);
diff --git a/core/src/main/java/com/cloud/agent/api/CheckGuestOsMappingAnswer.java b/core/src/main/java/com/cloud/agent/api/CheckGuestOsMappingAnswer.java
new file mode 100644
index 00000000000..53cfded2335
--- /dev/null
+++ b/core/src/main/java/com/cloud/agent/api/CheckGuestOsMappingAnswer.java
@@ -0,0 +1,38 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api;
+
+public class CheckGuestOsMappingAnswer extends Answer {
+
+ protected CheckGuestOsMappingAnswer() {
+ }
+
+ public CheckGuestOsMappingAnswer(CheckGuestOsMappingCommand cmd) {
+ super(cmd, true, null);
+ }
+
+ public CheckGuestOsMappingAnswer(CheckGuestOsMappingCommand cmd, String details) {
+ super(cmd, false, details);
+ }
+
+ public CheckGuestOsMappingAnswer(CheckGuestOsMappingCommand cmd, Throwable th) {
+ super(cmd, false, th.getMessage());
+ }
+}
diff --git a/core/src/main/java/com/cloud/agent/api/CheckGuestOsMappingCommand.java b/core/src/main/java/com/cloud/agent/api/CheckGuestOsMappingCommand.java
new file mode 100644
index 00000000000..f58f3e2cefd
--- /dev/null
+++ b/core/src/main/java/com/cloud/agent/api/CheckGuestOsMappingCommand.java
@@ -0,0 +1,54 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.agent.api;
+
+public class CheckGuestOsMappingCommand extends Command {
+ String guestOsName;
+ String guestOsHypervisorMappingName;
+ String hypervisorVersion;
+
+ public CheckGuestOsMappingCommand() {
+ super();
+ }
+
+ public CheckGuestOsMappingCommand(String guestOsName, String guestOsHypervisorMappingName, String hypervisorVersion) {
+ super();
+ this.guestOsName = guestOsName;
+ this.guestOsHypervisorMappingName = guestOsHypervisorMappingName;
+ this.hypervisorVersion = hypervisorVersion;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ return false;
+ }
+
+ public String getGuestOsName() {
+ return guestOsName;
+ }
+
+ public String getGuestOsHypervisorMappingName() {
+ return guestOsHypervisorMappingName;
+ }
+
+ public String getHypervisorVersion() {
+ return hypervisorVersion;
+ }
+}
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
index 54d4a5e9ca3..2055891bcaf 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDao.java
@@ -141,6 +141,8 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
HostVO findByName(String name);
+ HostVO findHostByHypervisorTypeAndVersion(HypervisorType hypervisorType, String hypervisorVersion);
+
List<HostVO> listHostsWithActiveVMs(long offeringId);
/**
diff --git a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
index 8e1f8f470dd..49b977e6cd0 100644
--- a/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/host/dao/HostDaoImpl.java
@@ -113,6 +113,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
protected SearchBuilder<HostVO> ResourceStateSearch;
protected SearchBuilder<HostVO> NameLikeSearch;
protected SearchBuilder<HostVO> NameSearch;
+ protected SearchBuilder<HostVO> HostHypervisorTypeAndVersionSearch;
protected SearchBuilder<HostVO> SequenceSearch;
protected SearchBuilder<HostVO> DirectlyConnectedSearch;
protected SearchBuilder<HostVO> UnmanagedDirectConnectSearch;
@@ -308,6 +309,13 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ);
NameSearch.done();
+ HostHypervisorTypeAndVersionSearch = createSearchBuilder();
+ HostHypervisorTypeAndVersionSearch.and("hypervisorType", HostHypervisorTypeAndVersionSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ);
+ HostHypervisorTypeAndVersionSearch.and("hypervisorVersion", HostHypervisorTypeAndVersionSearch.entity().getHypervisorVersion(), SearchCriteria.Op.EQ);
+ HostHypervisorTypeAndVersionSearch.and("type", HostHypervisorTypeAndVersionSearch.entity().getType(), SearchCriteria.Op.EQ);
+ HostHypervisorTypeAndVersionSearch.and("status", HostHypervisorTypeAndVersionSearch.entity().getStatus(), SearchCriteria.Op.EQ);
+ HostHypervisorTypeAndVersionSearch.done();
+
SequenceSearch = createSearchBuilder();
SequenceSearch.and("id", SequenceSearch.entity().getId(), SearchCriteria.Op.EQ);
// SequenceSearch.addRetrieve("sequence", SequenceSearch.entity().getSequence());
@@ -1398,6 +1406,16 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
return findOneBy(sc);
}
+ @Override
+ public HostVO findHostByHypervisorTypeAndVersion(HypervisorType hypervisorType, String hypervisorVersion) {
+ SearchCriteria<HostVO> sc = HostHypervisorTypeAndVersionSearch.create();
+ sc.setParameters("hypervisorType", hypervisorType);
+ sc.setParameters("hypervisorVersion", hypervisorVersion);
+ sc.setParameters("type", Host.Type.Routing);
+ sc.setParameters("status", Status.Up);
+ return findOneBy(sc);
+ }
+
private ResultSet executeSqlGetResultsetForMethodFindHostInZoneToExecuteCommand(HypervisorType hypervisorType, long zoneId, TransactionLegacy tx, String sql) throws SQLException {
PreparedStatement pstmt = tx.prepareAutoCloseStatement(sql);
pstmt.setString(1, Objects.toString(hypervisorType));
diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
index aabebf56bd1..d1ccba3baff 100644
--- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
+++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java
@@ -47,6 +47,8 @@ import java.util.stream.Collectors;
import javax.naming.ConfigurationException;
import javax.xml.datatype.XMLGregorianCalendar;
+import com.cloud.agent.api.CheckGuestOsMappingAnswer;
+import com.cloud.agent.api.CheckGuestOsMappingCommand;
import com.cloud.agent.api.PatchSystemVmAnswer;
import com.cloud.agent.api.PatchSystemVmCommand;
import com.cloud.resource.ServerResourceBase;
@@ -306,6 +308,7 @@ import com.vmware.vim25.DistributedVirtualSwitchPortCriteria;
import com.vmware.vim25.DynamicProperty;
import com.vmware.vim25.GuestInfo;
import com.vmware.vim25.GuestNicInfo;
+import com.vmware.vim25.GuestOsDescriptor;
import com.vmware.vim25.HostCapability;
import com.vmware.vim25.HostConfigInfo;
import com.vmware.vim25.HostFileSystemMountInfo;
@@ -604,6 +607,8 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
answer = execute((GetVmVncTicketCommand) cmd);
} else if (clz == GetAutoScaleMetricsCommand.class) {
answer = execute((GetAutoScaleMetricsCommand) cmd);
+ } else if (clz == CheckGuestOsMappingCommand.class) {
+ answer = execute((CheckGuestOsMappingCommand) cmd);
} else {
answer = Answer.createUnsupportedCommandAnswer(cmd);
}
@@ -7715,6 +7720,29 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
}
}
+ private CheckGuestOsMappingAnswer execute(CheckGuestOsMappingCommand cmd) {
+ String guestOsName = cmd.getGuestOsName();
+ String guestOsMappingName = cmd.getGuestOsHypervisorMappingName();
+ s_logger.info("Checking guest os mapping name: " + guestOsMappingName + " for the guest os: " + guestOsName + " in the hypervisor");
+ try {
+ VmwareContext context = getServiceContext();
+ VmwareHypervisorHost hyperHost = getHyperHost(context);
+ GuestOsDescriptor guestOsDescriptor = hyperHost.getGuestOsDescriptor(guestOsMappingName);
+ if (guestOsDescriptor == null) {
+ return new CheckGuestOsMappingAnswer(cmd, "Guest os mapping name not found in the hypervisor");
+ }
+ s_logger.debug("Matching hypervisor guest os - id: " + guestOsDescriptor.getId() + ", full name: " + guestOsDescriptor.getFullName() + ", family: " + guestOsDescriptor.getFamily());
+ if (guestOsDescriptor.getFullName().equalsIgnoreCase(guestOsName)) {
+ // Extact matching may fail, try with regex?
+ s_logger.debug("Hypervisor guest os name matches with os name: " + guestOsName + " from user");
+ }
+ return new CheckGuestOsMappingAnswer(cmd);
+ } catch (Exception e) {
+ s_logger.error("Failed to check the hypervisor guest os mapping name: " + guestOsMappingName, e);
+ return new CheckGuestOsMappingAnswer(cmd, e.getLocalizedMessage());
+ }
+ }
+
private Integer getVmwareWindowTimeInterval() {
Integer windowInterval = VmwareManager.VMWARE_STATS_TIME_WINDOW.value();
if (windowInterval == null || windowInterval < 20) {
diff --git a/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckGuestOsMappingCommandWrapper.java b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckGuestOsMappingCommandWrapper.java
new file mode 100644
index 00000000000..ed16d5bfed3
--- /dev/null
+++ b/plugins/hypervisors/xenserver/src/main/java/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixCheckGuestOsMappingCommandWrapper.java
@@ -0,0 +1,63 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package com.cloud.hypervisor.xenserver.resource.wrapper.xenbase;
+
+import java.util.Set;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CheckGuestOsMappingAnswer;
+import com.cloud.agent.api.CheckGuestOsMappingCommand;
+import com.cloud.hypervisor.xenserver.resource.CitrixResourceBase;
+import com.cloud.resource.CommandWrapper;
+import com.cloud.resource.ResourceWrapper;
+import com.xensource.xenapi.Connection;
+import com.xensource.xenapi.VM;
+
+@ResourceWrapper(handles = CheckGuestOsMappingCommand.class)
+public final class CitrixCheckGuestOsMappingCommandWrapper extends CommandWrapper<CheckGuestOsMappingCommand, Answer, CitrixResourceBase> {
+
+ private static final Logger s_logger = Logger.getLogger(CitrixCheckGuestOsMappingCommandWrapper.class);
+
+ @Override
+ public Answer execute(final CheckGuestOsMappingCommand command, final CitrixResourceBase citrixResourceBase) {
+ final Connection conn = citrixResourceBase.getConnection();
+ String guestOsName = command.getGuestOsName();
+ String guestOsMappingName = command.getGuestOsHypervisorMappingName();
+ try {
+ s_logger.info("Checking guest os mapping name: " + guestOsMappingName + " for the guest os: " + guestOsName + " in the hypervisor");
+ final Set<VM> vms = VM.getAll(conn);
+ if (vms.size() == 0) {
+ return new CheckGuestOsMappingAnswer(command, "Guest os mapping name not found in the hypervisor");
+ }
+ for (VM vm : vms) {
+ if (guestOsMappingName.equalsIgnoreCase(vm.getNameLabel(conn))) {
+ // Extact matching may fail, try with regex?
+ s_logger.debug("Hypervisor guest os name matches with os name: " + guestOsName + " from user");
+ }
+ }
+ return new CheckGuestOsMappingAnswer(command);
+ } catch (final Exception e) {
+ s_logger.error("Failed to find the hypervisor guest os mapping name: " + guestOsMappingName, e);
+ return new CheckGuestOsMappingAnswer(command, e.getLocalizedMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index aa362b2dc63..29c66bfed6f 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -51,6 +51,8 @@ import com.cloud.user.UserData;
import com.cloud.user.UserDataVO;
import com.cloud.user.dao.UserDataDao;
import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.CheckGuestOsMappingAnswer;
+import com.cloud.agent.api.CheckGuestOsMappingCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.PatchSystemVmAnswer;
import com.cloud.agent.api.PatchSystemVmCommand;
@@ -2599,6 +2601,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
@Override
public Pair<List<? extends GuestOSHypervisor>, Integer> listGuestOSMappingByCriteria(final ListGuestOsMappingCmd cmd) {
final Filter searchFilter = new Filter(GuestOSHypervisorVO.class, "hypervisorType", true, cmd.getStartIndex(), cmd.getPageSizeVal());
+ searchFilter.addOrderBy(GuestOSHypervisorVO.class, "hypervisorVersion", false);
+ searchFilter.addOrderBy(GuestOSHypervisorVO.class, "guestOsId", true);
+ searchFilter.addOrderBy(GuestOSHypervisorVO.class, "created", false);
final Long id = cmd.getId();
final Long osTypeId = cmd.getOsTypeId();
final String hypervisor = cmd.getHypervisor();
@@ -2671,9 +2676,28 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
final GuestOSHypervisorVO duplicate = _guestOSHypervisorDao.findByOsIdAndHypervisorAndUserDefined(guestOs.getId(), hypervisorType.toString(), hypervisorVersion, true);
if (duplicate != null) {
- throw new InvalidParameterValueException(
- "Mapping from hypervisor : " + hypervisorType.toString() + ", version : " + hypervisorVersion + " and guest OS : " + guestOs.getDisplayName() + " already exists!");
+ if (!cmd.isForced()) {
+ throw new InvalidParameterValueException(
+ "Mapping from hypervisor : " + hypervisorType.toString() + ", version : " + hypervisorVersion + " and guest OS : " + guestOs.getDisplayName() + " already exists!");
+ }
+
+ if (cmd.getOsMappingCheckEnabled()) {
+ checkGuestOSHypervisorMapping(hypervisorType, hypervisorVersion, guestOs.getDisplayName(), osNameForHypervisor);
+ }
+
+ final long guestOsId = duplicate.getId();
+ final GuestOSHypervisorVO guestOsHypervisor = _guestOSHypervisorDao.createForUpdate(guestOsId);
+ guestOsHypervisor.setGuestOsName(osNameForHypervisor);
+ if (_guestOSHypervisorDao.update(guestOsId, guestOsHypervisor)) {
+ return _guestOSHypervisorDao.findById(guestOsId);
+ }
+ return null;
+ }
+
+ if (cmd.getOsMappingCheckEnabled()) {
+ checkGuestOSHypervisorMapping(hypervisorType, hypervisorVersion, guestOs.getDisplayName(), osNameForHypervisor);
}
+
final GuestOSHypervisorVO guestOsMapping = new GuestOSHypervisorVO();
guestOsMapping.setGuestOsId(guestOs.getId());
guestOsMapping.setGuestOsName(osNameForHypervisor);
@@ -2681,7 +2705,24 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
guestOsMapping.setHypervisorVersion(hypervisorVersion);
guestOsMapping.setIsUserDefined(true);
return _guestOSHypervisorDao.persist(guestOsMapping);
+ }
+ private void checkGuestOSHypervisorMapping(HypervisorType hypervisorType, String hypervisorVersion, String guestOsName, String guestOsNameForHypervisor) {
+ if (!isGuestOSMappingCheckSupported(hypervisorType)) {
+ throw new InvalidParameterValueException(String.format("Guest OS mapping check is not supported for hypervisor: %s", hypervisorType.toString()));
+ }
+ final HostVO host = _hostDao.findHostByHypervisorTypeAndVersion(hypervisorType, hypervisorVersion);
+ if (host == null) {
+ throw new CloudRuntimeException(String.format("No host available with hypervisor: %s and version: %s, unable to check the guest os mapping", hypervisorType.toString(), hypervisorVersion));
+ }
+ CheckGuestOsMappingAnswer answer = (CheckGuestOsMappingAnswer) _agentMgr.easySend(host.getId(), new CheckGuestOsMappingCommand(guestOsName, guestOsNameForHypervisor, hypervisorVersion));
+ if (answer == null || !answer.getResult()) {
+ throw new CloudRuntimeException(String.format("Invalid hypervisor os mapping: %s for guest os: %s, hypervisor: %s and version: %s", guestOsNameForHypervisor, guestOsName, hypervisorType.toString(), hypervisorVersion));
+ }
+ }
+
+ private boolean isGuestOSMappingCheckSupported(HypervisorType hypervisorType) {
+ return (hypervisorType == HypervisorType.VMware || hypervisorType == HypervisorType.XenServer);
}
@Override
@@ -2811,6 +2852,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
throw new InvalidParameterValueException("Unable to modify system defined Guest OS mapping");
}
+ if (cmd.getOsMappingCheckEnabled()) {
+ GuestOS guestOs = ApiDBUtils.findGuestOSById(guestOsHypervisorHandle.getGuestOsId());
+ if (guestOs == null) {
+ throw new InvalidParameterValueException("Unable to find the guest OS for the mapping");
+ }
+ checkGuestOSHypervisorMapping(HypervisorType.getType(guestOsHypervisorHandle.getHypervisorType()), guestOsHypervisorHandle.getHypervisorVersion(), guestOs.getDisplayName(), osNameForHypervisor);
+ }
+
final GuestOSHypervisorVO guestOsHypervisor = _guestOSHypervisorDao.createForUpdate(id);
guestOsHypervisor.setGuestOsName(osNameForHypervisor);
if (_guestOSHypervisorDao.update(id, guestOsHypervisor)) {
diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index 571f5f96faa..cf9661ad174 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -785,6 +785,7 @@
"label.guest.ip.range": "Guest IP range",
"label.guest.netmask": "Guest netmask",
"label.guest.networks": "Guest networks",
+"label.guest.os.mappings": "Guest OS mappings",
"label.guest.start.ip": "Guest start IP",
"label.guest.traffic": "Guest traffic",
"label.guestcidraddress": "Guest CIDR",
@@ -954,6 +955,7 @@
"label.issourcenat": "Source NAT",
"label.isstaticnat": "Static NAT",
"label.issystem": "Is system",
+"label.isuserdefined": "User defined",
"label.isvolatile": "Volatile",
"label.items": "items",
"label.items.selected": "item(s) selected",
@@ -984,6 +986,7 @@
"label.kubernetes.version.update": "Manage Kubernetes version",
"label.kubernetesversionid": "Kubernetes version",
"label.kubernetesversionname": "Kubernetes version",
+"label.kvm": "KVM",
"label.kvmnetworklabel": "KVM traffic label",
"label.l2": "L2",
"label.l2gatewayserviceuuid": "L2 Gateway Service UUID",
@@ -1046,6 +1049,7 @@
"label.logout": "Logout",
"label.lun": "LUN",
"label.lun.number": "LUN #",
+"label.lxc": "LXC",
"label.lxcnetworklabel": "LXC traffic label",
"label.macaddress": "MAC address",
"label.macaddress.example": "The MAC address. Example: 01:23:45:67:89:ab",
@@ -1242,6 +1246,8 @@
"label.optional": "Optional",
"label.order": "Order",
"label.oscategoryid": "OS preference",
+"label.osdisplayname": "OS name",
+"label.osnameforhypervisor": "Hypervisor mapping name",
"label.ostypeid": "OS type",
"label.osdistribution": "OS distribution",
"label.ostypename": "OS type",
@@ -1260,6 +1266,7 @@
"label.overridepublictraffic": "Override public-traffic",
"label.override.root.diskoffering": "Override root disk offering",
"label.ovf.properties": "vApp properties",
+"label.ovm3": "OVM3",
"label.ovm3cluster": "Native Clustering",
"label.ovm3networklabel": "OVM3 traffic label",
"label.ovm3pool": "Native pooling",
@@ -1905,6 +1912,7 @@
"label.vms": "VMs",
"label.vmstate": "VM state",
"label.vmtotal": "Total of VMs",
+"label.vmware": "VMWare",
"label.vmware.storage.policy": "VMWare storage policy",
"label.vmwaredcid": "VMware datacenter ID",
"label.vmwaredcname": "VMware datacenter name",
@@ -1967,6 +1975,7 @@
"label.writeio": "Write (IO)",
"label.writethrough": "Write-through",
"label.xennetworklabel": "XenServer Traffic Label",
+"label.xenserver": "XenServer",
"label.xenservertoolsversion61plus": "Original XS Version is 6.1+",
"label.yes": "Yes",
"label.yourinstance": "Your instance",
diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue
index 6111300881c..e322b1b28f3 100644
--- a/ui/src/components/view/ListView.vue
+++ b/ui/src/components/view/ListView.vue
@@ -178,8 +178,17 @@
<span v-if="$route.name === 'hypervisorcapability'">
<router-link :to="{ path: $route.path + '/' + record.id }">{{ text }}</router-link>
</span>
+ <span v-else-if="$route.name === 'guestoshypervisormapping'">
+ <router-link :to="{ path: $route.path + '/' + record.id }">{{ text }}</router-link>
+ </span>
<span v-else>{{ text }}</span>
</template>
+ <!-- <template #guestosmapping="{ text, record }">
+ <span v-if="$route.name === 'guestoshypervisormapping'">
+ <router-link :to="{ path: $route.path + '/' + record.id }">{{ text }}</router-link>
+ </span>
+ <span v-else>{{ text }}</span>
+ </template> -->
<template #state="{ text, record }">
<status v-if="$route.path.startsWith('/host')" :text="getHostState(record)" displayText />
<status v-else :text="text ? text : ''" displayText :styles="{ 'min-width': '80px' }" />
diff --git a/ui/src/config/section/config.js b/ui/src/config/section/config.js
index 5dc3a76e88a..da9a1ea3f10 100644
--- a/ui/src/config/section/config.js
+++ b/ui/src/config/section/config.js
@@ -82,6 +82,25 @@ export default {
args: ['maxguestslimit']
}
]
+ },
+ {
+ name: 'guestoshypervisormapping',
+ title: 'label.guest.os.mappings',
+ icon: 'database-outlined',
+ permission: ['listGuestOsMapping'],
+ columns: ['hypervisor', 'hypervisorversion', 'osdisplayname', 'osnameforhypervisor'],
+ details: ['hypervisor', 'hypervisorversion', 'osdisplayname', 'osnameforhypervisor', 'isuserdefined'],
+ filters: ['all', 'kvm', 'vmware', 'xenserver', 'lxc', 'ovm3'],
+ searchFilters: ['hypervisor', 'hypervisorversion'],
+ actions: [
+ {
+ api: 'updateGuestOsMapping',
+ icon: 'edit-outlined',
+ label: 'label.edit',
+ dataView: true,
+ args: ['osnameforhypervisor']
+ }
+ ]
}
]
}
diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue
index 8ce9c5d7dbc..c707cabae6b 100644
--- a/ui/src/views/AutogenView.vue
+++ b/ui/src/views/AutogenView.vue
@@ -56,7 +56,7 @@
:value="$route.query.filter || (projectView && $route.name === 'vm' ||
['Admin', 'DomainAdmin'].includes($store.getters.userInfo.roletype) && ['vm', 'iso', 'template'].includes($route.name)
? 'all' : ['publicip'].includes($route.name)
- ? 'allocated' : ['guestnetwork', 'guestvlans'].includes($route.name) ? 'all' : 'self')"
+ ? 'allocated' : ['guestnetwork', 'guestvlans', 'guestoshypervisormapping'].includes($route.name) ? 'all' : 'self')"
style="min-width: 120px; margin-left: 10px"
@change="changeFilter"
showSearch
@@ -1560,6 +1560,12 @@ export default {
} else if (filter === 'allocatedonly') {
query.allocatedonly = 'true'
}
+ } else if (this.$route.name === 'guestoshypervisormapping') {
+ if (filter === 'all') {
+ delete query.hypervisor
+ } else {
+ query.hypervisor = filter
+ }
}
query.filter = filter
query.page = '1'
@@ -1587,6 +1593,8 @@ export default {
query.templatetype = value
} else if (this.$route.name === 'globalsetting') {
query.name = value
+ } else if (this.$route.name === 'guestoshypervisormapping') {
+ query.hypervisor = value
} else {
query.keyword = value
}
diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java
index 095b20c5b67..318cdb87e61 100644
--- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java
+++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/ClusterMO.java
@@ -740,4 +740,16 @@ public class ClusterMO extends BaseMO implements VmwareHypervisorHost {
throw new CloudRuntimeException(msg);
}
}
+
+ @Override
+ public GuestOsDescriptor getGuestOsDescriptor(String guestOsId) throws Exception {
+ VirtualMachineConfigOption vmConfigOption = _context.getService().queryConfigOption(getEnvironmentBrowser(), null, null);
+ List<GuestOsDescriptor> guestDescriptors = vmConfigOption.getGuestOSDescriptor();
+ for (GuestOsDescriptor descriptor : guestDescriptors) {
+ if (guestOsId != null && guestOsId.equalsIgnoreCase(descriptor.getId())) {
+ return descriptor;
+ }
+ }
+ return null;
+ }
}
diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
index 07bead77c1f..7240f0972ba 100644
--- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
+++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java
@@ -36,6 +36,7 @@ import com.vmware.vim25.ComputeResourceSummary;
import com.vmware.vim25.CustomFieldStringValue;
import com.vmware.vim25.DatastoreSummary;
import com.vmware.vim25.DynamicProperty;
+import com.vmware.vim25.GuestOsDescriptor;
import com.vmware.vim25.HostConfigManager;
import com.vmware.vim25.HostConnectInfo;
import com.vmware.vim25.HostFirewallInfo;
@@ -1163,6 +1164,16 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost {
return null;
}
+ @Override
+ public GuestOsDescriptor getGuestOsDescriptor(String guestOsId) throws Exception {
+ ManagedObjectReference morParent = getParentMor();
+ if (morParent.getType().equals("ClusterComputeResource")) {
+ ClusterMO clusterMo = new ClusterMO(_context, morParent);
+ return clusterMo.getGuestOsDescriptor(guestOsId);
+ }
+ return null;
+ }
+
public String getHostManagementIp(String managementPortGroup) throws Exception {
HostNetworkInfo netInfo = getHostNetworkInfo();
diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
index ce2f178ef3f..3e6182b5666 100644
--- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
+++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VmwareHypervisorHost.java
@@ -20,6 +20,7 @@ import java.util.List;
import com.vmware.vim25.ClusterDasConfigInfo;
import com.vmware.vim25.ComputeResourceSummary;
+import com.vmware.vim25.GuestOsDescriptor;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.ObjectContent;
import com.vmware.vim25.VirtualMachineConfigSpec;
@@ -91,5 +92,8 @@ public interface VmwareHypervisorHost {
ComputeResourceSummary getHyperHostHardwareSummary() throws Exception;
LicenseAssignmentManagerMO getLicenseAssignmentManager() throws Exception;
+
String getRecommendedDiskController(String guestOsId) throws Exception;
+
+ GuestOsDescriptor getGuestOsDescriptor(String guestOsId) throws Exception;
}