mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
plugins: Add Custom hypervisor minimal changes (#7692)
### Description Design document: https://cwiki.apache.org/confluence/display/CLOUDSTACK/%5BDRAFT%5D+Minimal+changes+to+allow+new+dynamic+hypervisor+type%3A+Custom+Hypervisor This PR introduces the minimal changes to add a new hypervisor type (internally named Custom in the codebase, and configurable display name), allowing to write an external hypervisor plugin as a Custom Hypervisor to CloudStack The custom hypervisor name is set by the setting: 'hypervisor.custom.display.name'. The new hypervisor type does not affect the behaviour of any CloudStack operation, it simply introduces a new hypervisor type into the system. CloudStack does not have any means to dynamically add new hypervisor types. The hypervisor types are internally preset by an enum defined within the CloudStack codebase and unless a new version supports a new hypervisor it is not possible to add a host of a hypervisor that is not in part of the enum. It is possible to implement minimal changes in CloudStack to support a new hypervisor plugin that may be developed privately This PR is an initial work on allowing new dynamic hypervisor types (adds a new element to the HypervisorType enum, but allows variable display name for the hypervisor) ##### Proposed Future work: Replace the HypervisorType from a fixed enum to an extensible registry mechanism, registered from the hypervisor plugin #### Feature Specifications - The new hypervisor type is internally named 'Custom' to the CloudStack services (management server and agent services, database records). - A new global setting ‘hypervisor.custom.display.name’ allows administrators to set the display name of the hypervisor type. The display name will be shown in the CloudStack UI and API. - In case the ‘hypervisor.list’ setting contains the display name of the new hypervisor type, the setting value is automatically updated after the ‘hypervisor.custom.display.name’ setting is updated. - The new Custom hypervisor type supports: - Direct downloads (the ability to download templates into primary storage from the hypervisor hosts without using secondary storage) - Local storage (use hypervisor hosts local storage as primary storage) - Template format: RAW format (the templates to be registered on the new hypervisor type must be in RAW format) - The UI is also extended to display the new hypervisor type and the supported features listed above. - The above are the minimal changes for CloudStack to support the new hypervisor type, which can be tested by integrating the plugin codebase with this feature. #### Use cases This PR allows the cloud administrators to test custom hypervisor plugins implementations in CloudStack and easily integrate it into CloudStack as a new hypervisor type ("Custom"), reducing the implementation to only the hypervisor supported specific storage/networking and the hypervisor resource to communicate with the management server. - CloudStack admin should be able to create a zone for the new custom hypervisor and add clusters, hosts into the zone with normal operations - CloudStack users should be able to execute normal VMs/volumes/network/storage operations on VMs/volumes running on the custom hypervisor hosts
This commit is contained in:
parent
fe70f4d801
commit
8b5ba13b81
@ -27,7 +27,7 @@ public class Hypervisor {
|
||||
static Map<String, HypervisorType> hypervisorTypeMap;
|
||||
static Map<HypervisorType, ImageFormat> supportedImageFormatMap;
|
||||
|
||||
public static enum HypervisorType {
|
||||
public enum HypervisorType {
|
||||
None, //for storage hosts
|
||||
XenServer,
|
||||
KVM,
|
||||
@ -40,6 +40,7 @@ public class Hypervisor {
|
||||
Ovm,
|
||||
Ovm3,
|
||||
LXC,
|
||||
Custom,
|
||||
|
||||
Any; /*If you don't care about the hypervisor type*/
|
||||
|
||||
@ -57,6 +58,7 @@ public class Hypervisor {
|
||||
hypervisorTypeMap.put("lxc", HypervisorType.LXC);
|
||||
hypervisorTypeMap.put("any", HypervisorType.Any);
|
||||
hypervisorTypeMap.put("ovm3", HypervisorType.Ovm3);
|
||||
hypervisorTypeMap.put("custom", HypervisorType.Custom);
|
||||
|
||||
supportedImageFormatMap = new HashMap<>();
|
||||
supportedImageFormatMap.put(HypervisorType.XenServer, ImageFormat.VHD);
|
||||
@ -68,7 +70,19 @@ public class Hypervisor {
|
||||
|
||||
public static HypervisorType getType(String hypervisor) {
|
||||
return hypervisor == null ? HypervisorType.None :
|
||||
hypervisorTypeMap.getOrDefault(hypervisor.toLowerCase(Locale.ROOT), HypervisorType.None);
|
||||
(hypervisor.toLowerCase(Locale.ROOT).equalsIgnoreCase(
|
||||
HypervisorGuru.HypervisorCustomDisplayName.value()) ? Custom :
|
||||
hypervisorTypeMap.getOrDefault(hypervisor.toLowerCase(Locale.ROOT), HypervisorType.None));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name of a hypervisor type in case the custom hypervisor is used,
|
||||
* using the 'hypervisor.custom.display.name' setting. Otherwise, returns hypervisor name
|
||||
*/
|
||||
public String getHypervisorDisplayName() {
|
||||
return !Hypervisor.HypervisorType.Custom.equals(this) ?
|
||||
this.toString() :
|
||||
HypervisorGuru.HypervisorCustomDisplayName.value();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -20,6 +20,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.cloudstack.backup.Backup;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
import com.cloud.agent.api.to.NicTO;
|
||||
@ -35,6 +36,10 @@ import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
public interface HypervisorGuru extends Adapter {
|
||||
|
||||
ConfigKey<String> HypervisorCustomDisplayName = new ConfigKey<>(String.class,
|
||||
"hypervisor.custom.display.name", ConfigKey.CATEGORY_ADVANCED, "Custom",
|
||||
"Display name for custom hypervisor", true, ConfigKey.Scope.Global, null);
|
||||
|
||||
HypervisorType getHypervisorType();
|
||||
|
||||
/**
|
||||
|
||||
@ -23,6 +23,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.cloud.hypervisor.HypervisorGuru;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
@ -342,9 +343,11 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
|
||||
"Parameter zoneids cannot combine all zones (-1) option with other zones");
|
||||
|
||||
if (isDirectDownload() && !getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.KVM.toString())) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
|
||||
"Parameter directdownload is only allowed for KVM templates");
|
||||
String customHypervisor = HypervisorGuru.HypervisorCustomDisplayName.value();
|
||||
if (isDirectDownload() && !(getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.KVM.toString())
|
||||
|| getHypervisor().equalsIgnoreCase(customHypervisor))) {
|
||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, String.format("Parameter directdownload " +
|
||||
"is only allowed for KVM or %s templates", customHypervisor));
|
||||
}
|
||||
|
||||
if (!isDeployAsIs() && osTypeId == null) {
|
||||
|
||||
@ -24,7 +24,6 @@ import org.apache.cloudstack.api.EntityReference;
|
||||
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@ -84,7 +83,7 @@ public class HostForMigrationResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.HYPERVISOR)
|
||||
@Param(description = "the host hypervisor")
|
||||
private HypervisorType hypervisor;
|
||||
private String hypervisor;
|
||||
|
||||
@SerializedName("cpunumber")
|
||||
@Param(description = "the CPU number of the host")
|
||||
@ -295,7 +294,7 @@ public class HostForMigrationResponse extends BaseResponse {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public void setHypervisor(HypervisorType hypervisor) {
|
||||
public void setHypervisor(String hypervisor) {
|
||||
this.hypervisor = hypervisor;
|
||||
}
|
||||
|
||||
|
||||
@ -29,7 +29,6 @@ import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
|
||||
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Status;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
@ -89,7 +88,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
|
||||
|
||||
@SerializedName(ApiConstants.HYPERVISOR)
|
||||
@Param(description = "the host hypervisor")
|
||||
private HypervisorType hypervisor;
|
||||
private String hypervisor;
|
||||
|
||||
@SerializedName("cpusockets")
|
||||
@Param(description = "the number of CPU sockets on the host")
|
||||
@ -335,7 +334,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public void setHypervisor(HypervisorType hypervisor) {
|
||||
public void setHypervisor(String hypervisor) {
|
||||
this.hypervisor = hypervisor;
|
||||
}
|
||||
|
||||
@ -602,7 +601,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
|
||||
return version;
|
||||
}
|
||||
|
||||
public HypervisorType getHypervisor() {
|
||||
public String getHypervisor() {
|
||||
return hypervisor;
|
||||
}
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.hypervisor.HypervisorCapabilities;
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
@ -37,7 +36,7 @@ public class HypervisorCapabilitiesResponse extends BaseResponse {
|
||||
|
||||
@SerializedName(ApiConstants.HYPERVISOR)
|
||||
@Param(description = "the hypervisor type")
|
||||
private HypervisorType hypervisor;
|
||||
private String hypervisor;
|
||||
|
||||
@SerializedName(ApiConstants.MAX_GUESTS_LIMIT)
|
||||
@Param(description = "the maximum number of guest vms recommended for this hypervisor")
|
||||
@ -83,11 +82,11 @@ public class HypervisorCapabilitiesResponse extends BaseResponse {
|
||||
this.hypervisorVersion = hypervisorVersion;
|
||||
}
|
||||
|
||||
public HypervisorType getHypervisor() {
|
||||
public String getHypervisor() {
|
||||
return hypervisor;
|
||||
}
|
||||
|
||||
public void setHypervisor(HypervisorType hypervisor) {
|
||||
public void setHypervisor(String hypervisor) {
|
||||
this.hypervisor = hypervisor;
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,6 @@ import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
|
||||
import org.apache.cloudstack.api.EntityReference;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.serializer.Param;
|
||||
import com.cloud.vm.snapshot.VMSnapshot;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
@ -111,7 +110,7 @@ public class VMSnapshotResponse extends BaseResponseWithTagInformation implement
|
||||
|
||||
@SerializedName(ApiConstants.HYPERVISOR)
|
||||
@Param(description = "the type of hypervisor on which snapshot is stored")
|
||||
private Hypervisor.HypervisorType hypervisor;
|
||||
private String hypervisor;
|
||||
|
||||
public VMSnapshotResponse() {
|
||||
tags = new LinkedHashSet<ResourceTagResponse>();
|
||||
@ -266,11 +265,11 @@ public class VMSnapshotResponse extends BaseResponseWithTagInformation implement
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
public Hypervisor.HypervisorType getHypervisor() {
|
||||
public String getHypervisor() {
|
||||
return hypervisor;
|
||||
}
|
||||
|
||||
public void setHypervisor(Hypervisor.HypervisorType hypervisor) {
|
||||
public void setHypervisor(String hypervisor) {
|
||||
this.hypervisor = hypervisor;
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
|
||||
@Entity
|
||||
@ -72,7 +73,7 @@ public class GuestOSHypervisorVO implements GuestOSHypervisor {
|
||||
|
||||
@Override
|
||||
public String getHypervisorType() {
|
||||
return hypervisorType;
|
||||
return Hypervisor.HypervisorType.getType(hypervisorType).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -121,6 +121,11 @@
|
||||
<property name="name" value="KVM Agent"/>
|
||||
</bean>
|
||||
|
||||
<bean id="CustomServerDiscoverer"
|
||||
class="com.cloud.hypervisor.discoverer.CustomServerDiscoverer">
|
||||
<property name="name" value="CustomHW Agent" />
|
||||
</bean>
|
||||
|
||||
<bean id="BareMetalDiscoverer" class="com.cloud.baremetal.BareMetalDiscoverer">
|
||||
<property name="name" value="Bare Metal Agent"/>
|
||||
</bean>
|
||||
|
||||
@ -111,6 +111,7 @@ under the License.
|
||||
<adapter name="XCP Agent" class="com.cloud.hypervisor.xenserver.discoverer.XcpServerDiscoverer"/>
|
||||
<adapter name="SecondaryStorage" class="com.cloud.storage.secondary.SecondaryStorageDiscoverer"/>
|
||||
<adapter name="KVM Agent" class="com.cloud.hypervisor.kvm.discoverer.KvmServerDiscoverer"/>
|
||||
<adapter name="CustomHW Agent" class="com.cloud.hypervisor.discoverer.CustomServerDiscoverer"/>
|
||||
<adapter name="Bare Metal Agent" class="com.cloud.baremetal.BareMetalDiscoverer"/>
|
||||
<adapter name="Ovm Discover" class="com.cloud.ovm.hypervisor.OvmDiscoverer" />
|
||||
</adapters>
|
||||
|
||||
@ -1283,6 +1283,9 @@ public class ApiDBUtils {
|
||||
// If this check is not passed, the hypervisor type will remain OVM.
|
||||
type = HypervisorType.KVM;
|
||||
break;
|
||||
} else if (pool.getHypervisor() == HypervisorType.Custom) {
|
||||
type = HypervisorType.Custom;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import org.apache.cloudstack.acl.ControlledEntity;
|
||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
@ -735,7 +736,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
if (vm != null) {
|
||||
vmSnapshotResponse.setVirtualMachineId(vm.getUuid());
|
||||
vmSnapshotResponse.setVirtualMachineName(StringUtils.isEmpty(vm.getDisplayName()) ? vm.getHostName() : vm.getDisplayName());
|
||||
vmSnapshotResponse.setHypervisor(vm.getHypervisorType());
|
||||
vmSnapshotResponse.setHypervisor(vm.getHypervisorType().getHypervisorDisplayName());
|
||||
DataCenterVO datacenter = ApiDBUtils.findZoneById(vm.getDataCenterId());
|
||||
if (datacenter != null) {
|
||||
vmSnapshotResponse.setZoneId(datacenter.getUuid());
|
||||
@ -1437,7 +1438,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
clusterResponse.setZoneId(dc.getUuid());
|
||||
clusterResponse.setZoneName(dc.getName());
|
||||
}
|
||||
clusterResponse.setHypervisorType(cluster.getHypervisorType().toString());
|
||||
clusterResponse.setHypervisorType(cluster.getHypervisorType().getHypervisorDisplayName());
|
||||
clusterResponse.setClusterType(cluster.getClusterType().toString());
|
||||
clusterResponse.setAllocationState(cluster.getAllocationState().toString());
|
||||
clusterResponse.setManagedState(cluster.getManagedState().toString());
|
||||
@ -1633,7 +1634,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
vmResponse.setTemplateName(template.getName());
|
||||
}
|
||||
vmResponse.setCreated(vm.getCreated());
|
||||
vmResponse.setHypervisor(vm.getHypervisorType().toString());
|
||||
vmResponse.setHypervisor(vm.getHypervisorType().getHypervisorDisplayName());
|
||||
|
||||
if (vm.getHostId() != null) {
|
||||
Host host = ApiDBUtils.findHostById(vm.getHostId());
|
||||
@ -2792,7 +2793,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
public HypervisorCapabilitiesResponse createHypervisorCapabilitiesResponse(HypervisorCapabilities hpvCapabilities) {
|
||||
HypervisorCapabilitiesResponse hpvCapabilitiesResponse = new HypervisorCapabilitiesResponse();
|
||||
hpvCapabilitiesResponse.setId(hpvCapabilities.getUuid());
|
||||
hpvCapabilitiesResponse.setHypervisor(hpvCapabilities.getHypervisorType());
|
||||
hpvCapabilitiesResponse.setHypervisor(hpvCapabilities.getHypervisorType().getHypervisorDisplayName());
|
||||
hpvCapabilitiesResponse.setHypervisorVersion(hpvCapabilities.getHypervisorVersion());
|
||||
hpvCapabilitiesResponse.setIsSecurityGroupEnabled(hpvCapabilities.isSecurityGroupEnabled());
|
||||
hpvCapabilitiesResponse.setMaxGuestsLimit(hpvCapabilities.getMaxGuestsLimit());
|
||||
@ -3690,7 +3691,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
public GuestOsMappingResponse createGuestOSMappingResponse(GuestOSHypervisor guestOSHypervisor) {
|
||||
GuestOsMappingResponse response = new GuestOsMappingResponse();
|
||||
response.setId(guestOSHypervisor.getUuid());
|
||||
response.setHypervisor(guestOSHypervisor.getHypervisorType());
|
||||
response.setHypervisor(Hypervisor.HypervisorType.getType(guestOSHypervisor.getHypervisorType()).getHypervisorDisplayName());
|
||||
response.setHypervisorVersion(guestOSHypervisor.getHypervisorVersion());
|
||||
response.setOsNameForHypervisor((guestOSHypervisor.getGuestOsName()));
|
||||
response.setIsUserDefined(Boolean.valueOf(guestOSHypervisor.getIsUserDefined()).toString());
|
||||
@ -4940,7 +4941,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
||||
response.setId(certificate.getUuid());
|
||||
response.setAlias(certificate.getAlias());
|
||||
handleCertificateResponse(certificate.getCertificate(), response);
|
||||
response.setHypervisor(certificate.getHypervisorType().name());
|
||||
response.setHypervisor(certificate.getHypervisorType().getHypervisorDisplayName());
|
||||
response.setObjectName("directdownloadcertificate");
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -126,7 +126,7 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
|
||||
}
|
||||
|
||||
if (router.getHypervisorType() != null) {
|
||||
routerResponse.setHypervisor(router.getHypervisorType().toString());
|
||||
routerResponse.setHypervisor(router.getHypervisorType().getHypervisorDisplayName());
|
||||
}
|
||||
routerResponse.setHasAnnotation(annotationDao.hasAnnotations(router.getUuid(), AnnotationService.EntityType.VR.name(),
|
||||
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));
|
||||
|
||||
@ -125,7 +125,10 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
|
||||
hostResponse.setCpuNumber(host.getCpus());
|
||||
hostResponse.setZoneId(host.getZoneUuid());
|
||||
hostResponse.setDisconnectedOn(host.getDisconnectedOn());
|
||||
hostResponse.setHypervisor(host.getHypervisorType());
|
||||
if (host.getHypervisorType() != null) {
|
||||
String hypervisorType = host.getHypervisorType().getHypervisorDisplayName();
|
||||
hostResponse.setHypervisor(hypervisorType);
|
||||
}
|
||||
hostResponse.setHostType(host.getType());
|
||||
hostResponse.setLastPinged(new Date(host.getLastPinged()));
|
||||
Long mshostId = host.getManagementServerId();
|
||||
@ -239,7 +242,8 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
|
||||
hostResponse.setUefiCapabilty(new Boolean(false));
|
||||
}
|
||||
}
|
||||
if (details.contains(HostDetails.all) && host.getHypervisorType() == Hypervisor.HypervisorType.KVM) {
|
||||
if (details.contains(HostDetails.all) && (host.getHypervisorType() == Hypervisor.HypervisorType.KVM ||
|
||||
host.getHypervisorType() == Hypervisor.HypervisorType.Custom)) {
|
||||
//only kvm has the requirement to return host details
|
||||
try {
|
||||
hostResponse.setDetails(hostDetails);
|
||||
@ -303,7 +307,7 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
|
||||
hostResponse.setCpuNumber(host.getCpus());
|
||||
hostResponse.setZoneId(host.getZoneUuid());
|
||||
hostResponse.setDisconnectedOn(host.getDisconnectedOn());
|
||||
hostResponse.setHypervisor(host.getHypervisorType());
|
||||
hostResponse.setHypervisor(host.getHypervisorType().getHypervisorDisplayName());
|
||||
hostResponse.setHostType(host.getType());
|
||||
hostResponse.setLastPinged(new Date(host.getLastPinged()));
|
||||
hostResponse.setManagementServerId(host.getManagementServerId());
|
||||
|
||||
@ -110,7 +110,7 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Lo
|
||||
poolResponse.setScope(pool.getScope().toString());
|
||||
}
|
||||
if (pool.getHypervisor() != null) {
|
||||
poolResponse.setHypervisor(pool.getHypervisor().toString());
|
||||
poolResponse.setHypervisor(pool.getHypervisor().getHypervisorDisplayName());
|
||||
}
|
||||
|
||||
StoragePoolDetailVO poolType = storagePoolDetailsDao.findDetail(pool.getId(), "pool_type");
|
||||
@ -201,7 +201,7 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase<StoragePoolJoinVO, Lo
|
||||
poolResponse.setCreated(pool.getCreated());
|
||||
poolResponse.setScope(pool.getScope().toString());
|
||||
if (pool.getHypervisor() != null) {
|
||||
poolResponse.setHypervisor(pool.getHypervisor().toString());
|
||||
poolResponse.setHypervisor(pool.getHypervisor().getHypervisorDisplayName());
|
||||
}
|
||||
|
||||
long allocatedSize = pool.getUsedCapacity();
|
||||
|
||||
@ -208,7 +208,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
|
||||
templateResponse.setTemplateType(template.getTemplateType().toString());
|
||||
}
|
||||
|
||||
templateResponse.setHypervisor(template.getHypervisorType().toString());
|
||||
templateResponse.setHypervisor(template.getHypervisorType().getHypervisorDisplayName());
|
||||
|
||||
templateResponse.setOsTypeId(template.getGuestOSUuid());
|
||||
templateResponse.setOsTypeName(template.getGuestOSName());
|
||||
@ -330,7 +330,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
|
||||
response.setOsTypeId(result.getGuestOSUuid());
|
||||
response.setOsTypeName(result.getGuestOSName());
|
||||
response.setBootable(result.isBootable());
|
||||
response.setHypervisor(result.getHypervisorType().toString());
|
||||
response.setHypervisor(result.getHypervisorType().getHypervisorDisplayName());
|
||||
response.setDynamicallyScalable(result.isDynamicallyScalable());
|
||||
|
||||
// populate owner.
|
||||
|
||||
@ -128,7 +128,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
||||
UserVmResponse userVmResponse = new UserVmResponse();
|
||||
|
||||
if (userVm.getHypervisorType() != null) {
|
||||
userVmResponse.setHypervisor(userVm.getHypervisorType().toString());
|
||||
userVmResponse.setHypervisor(userVm.getHypervisorType().getHypervisorDisplayName());
|
||||
}
|
||||
userVmResponse.setId(userVm.getUuid());
|
||||
userVmResponse.setName(userVm.getName());
|
||||
|
||||
@ -21,6 +21,7 @@ import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.offering.DiskOffering;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
@ -147,8 +148,10 @@ public class VolumeJoinDaoImpl extends GenericDaoBaseWithTagInformation<VolumeJo
|
||||
volResponse.setSize(volume.getVolumeStoreSize());
|
||||
volResponse.setCreated(volume.getCreatedOnStore());
|
||||
|
||||
if (view == ResponseView.Full)
|
||||
volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volume.getDataCenterId(), volume.getFormat()).toString());
|
||||
if (view == ResponseView.Full) {
|
||||
Hypervisor.HypervisorType hypervisorTypeFromFormat = ApiDBUtils.getHypervisorTypeFromFormat(volume.getDataCenterId(), volume.getFormat());
|
||||
volResponse.setHypervisor(hypervisorTypeFromFormat.getHypervisorDisplayName());
|
||||
}
|
||||
if (volume.getDownloadState() != Status.DOWNLOADED) {
|
||||
String volumeStatus = "Processing";
|
||||
if (volume.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) {
|
||||
@ -209,9 +212,10 @@ public class VolumeJoinDaoImpl extends GenericDaoBaseWithTagInformation<VolumeJo
|
||||
if (view == ResponseView.Full) {
|
||||
if (volume.getState() != Volume.State.UploadOp) {
|
||||
if (volume.getHypervisorType() != null) {
|
||||
volResponse.setHypervisor(volume.getHypervisorType().toString());
|
||||
volResponse.setHypervisor(volume.getHypervisorType().getHypervisorDisplayName());
|
||||
} else {
|
||||
volResponse.setHypervisor(ApiDBUtils.getHypervisorTypeFromFormat(volume.getDataCenterId(), volume.getFormat()).toString());
|
||||
Hypervisor.HypervisorType hypervisorTypeFromFormat = ApiDBUtils.getHypervisorTypeFromFormat(volume.getDataCenterId(), volume.getFormat());
|
||||
volResponse.setHypervisor(hypervisorTypeFromFormat.getHypervisorDisplayName());
|
||||
}
|
||||
}
|
||||
Long poolId = volume.getPoolId();
|
||||
|
||||
@ -46,6 +46,7 @@ import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
|
||||
import com.cloud.hypervisor.HypervisorGuru;
|
||||
import org.apache.cloudstack.acl.SecurityChecker;
|
||||
import org.apache.cloudstack.affinity.AffinityGroup;
|
||||
import org.apache.cloudstack.affinity.AffinityGroupService;
|
||||
@ -773,6 +774,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
final TransactionLegacy txn = TransactionLegacy.currentTxn();
|
||||
txn.start();
|
||||
|
||||
String previousValue = _configDao.getValue(name);
|
||||
if (!_configDao.update(name, category, value)) {
|
||||
s_logger.error("Failed to update configuration option, name: " + name + ", value:" + value);
|
||||
throw new CloudRuntimeException("Failed to update configuration value. Please contact Cloud Support.");
|
||||
@ -853,6 +855,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
} catch (final Throwable e) {
|
||||
throw new CloudRuntimeException("Failed to clean up download URLs in template_store_ref or volume_store_ref due to exception ", e);
|
||||
}
|
||||
} else if (HypervisorGuru.HypervisorCustomDisplayName.key().equals(name)) {
|
||||
updateCustomDisplayNameOnHypervisorsList(previousValue, value);
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
@ -860,6 +864,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
|
||||
return _configDao.getValue(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the 'hypervisor.list' value to match the new custom hypervisor name set as newValue if the previous value was set
|
||||
*/
|
||||
private void updateCustomDisplayNameOnHypervisorsList(String previousValue, String newValue) {
|
||||
String hypervisorListConfigName = Config.HypervisorList.key();
|
||||
String hypervisors = _configDao.getValue(hypervisorListConfigName);
|
||||
if (Arrays.asList(hypervisors.split(",")).contains(previousValue)) {
|
||||
hypervisors = hypervisors.replace(previousValue, newValue);
|
||||
s_logger.info(String.format("Updating the hypervisor list configuration '%s' " +
|
||||
"to match the new custom hypervisor display name", hypervisorListConfigName));
|
||||
_configDao.update(hypervisorListConfigName, hypervisors);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_CONFIGURATION_VALUE_EDIT, eventDescription = "updating configuration")
|
||||
public Configuration updateConfiguration(final UpdateCfgCmd cmd) throws InvalidParameterValueException {
|
||||
|
||||
@ -360,7 +360,10 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
|
||||
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {VmMinMemoryEqualsMemoryDividedByMemOverprovisioningFactor, VmMinCpuSpeedEqualsCpuSpeedDividedByCpuOverprovisioningFactor };
|
||||
return new ConfigKey<?>[] {VmMinMemoryEqualsMemoryDividedByMemOverprovisioningFactor,
|
||||
VmMinCpuSpeedEqualsCpuSpeedDividedByCpuOverprovisioningFactor,
|
||||
HypervisorCustomDisplayName
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
// 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.discoverer;
|
||||
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.hypervisor.kvm.discoverer.LibvirtServerDiscoverer;
|
||||
|
||||
public class CustomServerDiscoverer extends LibvirtServerDiscoverer {
|
||||
@Override
|
||||
public Hypervisor.HypervisorType getHypervisorType() {
|
||||
return Hypervisor.HypervisorType.Custom;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPatchPath() {
|
||||
return "scripts/vm/hypervisor/kvm/";
|
||||
}
|
||||
}
|
||||
@ -42,6 +42,7 @@ import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.hypervisor.HypervisorGuru;
|
||||
import org.apache.cloudstack.alert.AlertService;
|
||||
import org.apache.cloudstack.annotation.AnnotationService;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
@ -652,7 +653,9 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
|
||||
}
|
||||
}
|
||||
|
||||
return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), false);
|
||||
String hypervisorType = cmd.getHypervisor().equalsIgnoreCase(HypervisorGuru.HypervisorCustomDisplayName.value()) ?
|
||||
"Custom" : cmd.getHypervisor();
|
||||
return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, hypervisorType, hostTags, cmd.getFullUrlParams(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1264,7 +1264,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
}
|
||||
|
||||
if (hypervisorType != null) {
|
||||
sc.setParameters("hypervisorType", hypervisorType);
|
||||
String hypervisorStr = (String) hypervisorType;
|
||||
String hypervisorSearch = HypervisorType.getType(hypervisorStr).toString();
|
||||
sc.setParameters("hypervisorType", hypervisorSearch);
|
||||
}
|
||||
|
||||
if (clusterType != null) {
|
||||
@ -4470,7 +4472,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
||||
} else {
|
||||
final List<ClusterVO> clustersForZone = _clusterDao.listByZoneId(zoneId);
|
||||
for (final ClusterVO cluster : clustersForZone) {
|
||||
result.add(cluster.getHypervisorType().toString());
|
||||
result.add(cluster.getHypervisorType().getHypervisorDisplayName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -148,20 +148,21 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate on random running KVM host that URL is reachable
|
||||
* Validate on random running host that URL is reachable
|
||||
* @param url url
|
||||
*/
|
||||
private Long performDirectDownloadUrlValidation(final String format, final String url, final List<Long> zoneIds) {
|
||||
private Long performDirectDownloadUrlValidation(final String format, final Hypervisor.HypervisorType hypervisor,
|
||||
final String url, final List<Long> zoneIds) {
|
||||
HostVO host = null;
|
||||
if (zoneIds != null && !zoneIds.isEmpty()) {
|
||||
for (Long zoneId : zoneIds) {
|
||||
host = resourceManager.findOneRandomRunningHostByHypervisor(Hypervisor.HypervisorType.KVM, zoneId);
|
||||
host = resourceManager.findOneRandomRunningHostByHypervisor(hypervisor, zoneId);
|
||||
if (host != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
host = resourceManager.findOneRandomRunningHostByHypervisor(Hypervisor.HypervisorType.KVM, null);
|
||||
host = resourceManager.findOneRandomRunningHostByHypervisor(hypervisor, null);
|
||||
}
|
||||
|
||||
if (host == null) {
|
||||
@ -198,7 +199,8 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
||||
zoneIds = new ArrayList<>();
|
||||
zoneIds.add(cmd.getZoneId());
|
||||
}
|
||||
Long templateSize = performDirectDownloadUrlValidation(ImageFormat.ISO.getFileExtension(), url, zoneIds);
|
||||
Long templateSize = performDirectDownloadUrlValidation(ImageFormat.ISO.getFileExtension(),
|
||||
Hypervisor.HypervisorType.KVM, url, zoneIds);
|
||||
profile.setSize(templateSize);
|
||||
}
|
||||
profile.setUrl(url);
|
||||
@ -221,9 +223,11 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
|
||||
TemplateProfile profile = super.prepare(cmd);
|
||||
String url = profile.getUrl();
|
||||
UriUtils.validateUrl(cmd.getFormat(), url, cmd.isDirectDownload());
|
||||
Hypervisor.HypervisorType hypervisor = Hypervisor.HypervisorType.getType(cmd.getHypervisor());
|
||||
if (cmd.isDirectDownload()) {
|
||||
DigestHelper.validateChecksumString(cmd.getChecksum());
|
||||
Long templateSize = performDirectDownloadUrlValidation(cmd.getFormat(), url, cmd.getZoneIds());
|
||||
Long templateSize = performDirectDownloadUrlValidation(cmd.getFormat(),
|
||||
hypervisor, url, cmd.getZoneIds());
|
||||
profile.setSize(templateSize);
|
||||
}
|
||||
profile.setUrl(url);
|
||||
|
||||
@ -309,8 +309,12 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
||||
if (type == HypervisorType.BareMetal) {
|
||||
adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName());
|
||||
} else {
|
||||
// see HypervisorTemplateAdapter
|
||||
adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.Hypervisor.getName());
|
||||
// Get template adapter according to hypervisor
|
||||
adapter = AdapterBase.getAdapterByName(_adapters, type.name());
|
||||
// Otherwise, default to generic hypervisor template adapter
|
||||
if (adapter == null) {
|
||||
adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.Hypervisor.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (adapter == null) {
|
||||
|
||||
@ -650,6 +650,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
HypervisorType.Simulator
|
||||
));
|
||||
|
||||
protected static final List<HypervisorType> ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS = Arrays.asList(
|
||||
HypervisorType.KVM,
|
||||
HypervisorType.XenServer,
|
||||
HypervisorType.VMware,
|
||||
HypervisorType.Simulator,
|
||||
HypervisorType.Custom
|
||||
);
|
||||
|
||||
private static final List<HypervisorType> HYPERVISORS_THAT_CAN_DO_STORAGE_MIGRATION_ON_NON_USER_VMS = Arrays.asList(HypervisorType.KVM, HypervisorType.VMware);
|
||||
|
||||
@Override
|
||||
@ -4338,7 +4346,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
* @throws InvalidParameterValueException if the hypervisor does not support rootdisksize override
|
||||
*/
|
||||
protected void verifyIfHypervisorSupportsRootdiskSizeOverride(HypervisorType hypervisorType) {
|
||||
if (!(hypervisorType == HypervisorType.KVM || hypervisorType == HypervisorType.XenServer || hypervisorType == HypervisorType.VMware || hypervisorType == HypervisorType.Simulator)) {
|
||||
if (!ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS.contains(hypervisorType)) {
|
||||
throw new InvalidParameterValueException("Hypervisor " + hypervisorType + " does not support rootdisksize override");
|
||||
}
|
||||
}
|
||||
@ -5004,6 +5012,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
Answer startAnswer = cmds.getAnswer(StartAnswer.class);
|
||||
String returnedIp = null;
|
||||
String originalIp = null;
|
||||
String originalVncPassword = profile.getVirtualMachine().getVncPassword();
|
||||
String returnedVncPassword = null;
|
||||
if (startAnswer != null) {
|
||||
StartAnswer startAns = (StartAnswer)startAnswer;
|
||||
VirtualMachineTO vmTO = startAns.getVirtualMachine();
|
||||
@ -5012,6 +5022,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
returnedIp = nicTO.getIp();
|
||||
}
|
||||
}
|
||||
returnedVncPassword = vmTO.getVncPassword();
|
||||
}
|
||||
|
||||
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
|
||||
@ -5063,6 +5074,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
}
|
||||
}
|
||||
|
||||
updateVncPasswordIfItHasChanged(originalVncPassword, returnedVncPassword, profile);
|
||||
|
||||
// get system ip and create static nat rule for the vm
|
||||
try {
|
||||
_rulesMgr.getSystemIpAndEnableStaticNatForVm(profile.getVirtualMachine(), false);
|
||||
@ -5097,6 +5110,14 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void updateVncPasswordIfItHasChanged(String originalVncPassword, String returnedVncPassword, VirtualMachineProfile profile) {
|
||||
if (returnedVncPassword != null && !originalVncPassword.equals(returnedVncPassword)) {
|
||||
UserVmVO userVm = _vmDao.findById(profile.getId());
|
||||
userVm.setVncPassword(returnedVncPassword);
|
||||
_vmDao.update(userVm.getId(), userVm);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalizeExpunge(VirtualMachine vm) {
|
||||
}
|
||||
|
||||
@ -38,6 +38,11 @@
|
||||
<property name="name" value="Lxc Discover" />
|
||||
</bean>
|
||||
|
||||
<bean id="CustomServerDiscoverer"
|
||||
class="com.cloud.hypervisor.discoverer.CustomServerDiscoverer">
|
||||
<property name="name" value="CustomHW Agent" />
|
||||
</bean>
|
||||
|
||||
<bean id="dummyHostDiscoverer" class="com.cloud.resource.DummyHostDiscoverer">
|
||||
<property name="name" value="dummyHostDiscoverer" />
|
||||
</bean>
|
||||
|
||||
@ -221,6 +221,9 @@ public class UserVmManagerImplTest {
|
||||
@Mock
|
||||
UserDataManager userDataManager;
|
||||
|
||||
@Mock
|
||||
VirtualMachineProfile virtualMachineProfile;
|
||||
|
||||
private static final long vmId = 1l;
|
||||
private static final long zoneId = 2L;
|
||||
private static final long accountId = 3L;
|
||||
@ -248,6 +251,8 @@ public class UserVmManagerImplTest {
|
||||
customParameters.put(VmDetailConstants.ROOT_DISK_SIZE, "123");
|
||||
lenient().doNothing().when(resourceLimitMgr).incrementResourceCount(anyLong(), any(Resource.ResourceType.class));
|
||||
lenient().doNothing().when(resourceLimitMgr).decrementResourceCount(anyLong(), any(Resource.ResourceType.class), anyLong());
|
||||
|
||||
Mockito.when(virtualMachineProfile.getId()).thenReturn(vmId);
|
||||
}
|
||||
|
||||
@After
|
||||
@ -561,13 +566,10 @@ public class UserVmManagerImplTest {
|
||||
public void verifyIfHypervisorSupportRootdiskSizeOverrideTest() {
|
||||
Hypervisor.HypervisorType[] hypervisorTypeArray = Hypervisor.HypervisorType.values();
|
||||
int exceptionCounter = 0;
|
||||
int expectedExceptionCounter = hypervisorTypeArray.length - 4;
|
||||
int expectedExceptionCounter = hypervisorTypeArray.length - 5;
|
||||
|
||||
for(int i = 0; i < hypervisorTypeArray.length; i++) {
|
||||
if (Hypervisor.HypervisorType.KVM == hypervisorTypeArray[i]
|
||||
|| Hypervisor.HypervisorType.XenServer == hypervisorTypeArray[i]
|
||||
|| Hypervisor.HypervisorType.VMware == hypervisorTypeArray[i]
|
||||
|| Hypervisor.HypervisorType.Simulator == hypervisorTypeArray[i]) {
|
||||
if (UserVmManagerImpl.ROOT_DISK_SIZE_OVERRIDE_SUPPORTING_HYPERVISORS.contains(hypervisorTypeArray[i])) {
|
||||
userVmManagerImpl.verifyIfHypervisorSupportsRootdiskSizeOverride(hypervisorTypeArray[i]);
|
||||
} else {
|
||||
try {
|
||||
@ -1041,4 +1043,21 @@ public class UserVmManagerImplTest {
|
||||
Pair<VMInstanceVO, Host> pair = mockObjectsForChooseVmMigrationDestinationUsingVolumePoolMapTest(false, destinationHost);
|
||||
Assert.assertEquals(destinationHost, userVmManagerImpl.chooseVmMigrationDestinationUsingVolumePoolMap(pair.first(), pair.second(), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateVncPasswordIfItHasChanged() {
|
||||
String vncPassword = "12345678";
|
||||
userVmManagerImpl.updateVncPasswordIfItHasChanged(vncPassword, vncPassword, virtualMachineProfile);
|
||||
Mockito.verify(userVmDao, Mockito.never()).update(vmId, userVmVoMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateVncPasswordIfItHasChangedNewPassword() {
|
||||
String vncPassword = "12345678";
|
||||
String newPassword = "87654321";
|
||||
Mockito.when(userVmVoMock.getId()).thenReturn(vmId);
|
||||
userVmManagerImpl.updateVncPasswordIfItHasChanged(vncPassword, newPassword, virtualMachineProfile);
|
||||
Mockito.verify(userVmDao).findById(vmId);
|
||||
Mockito.verify(userVmDao).update(vmId, userVmVoMock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +81,9 @@ export default {
|
||||
label: 'label.action.secure.host',
|
||||
message: 'message.action.secure.host',
|
||||
dataView: true,
|
||||
show: (record) => { return record.hypervisor === 'KVM' },
|
||||
show: (record) => {
|
||||
return record.hypervisor === 'KVM' || record.hypervisor === store.getters.customHypervisorName
|
||||
},
|
||||
args: ['hostid'],
|
||||
mapping: {
|
||||
hostid: {
|
||||
|
||||
@ -48,7 +48,8 @@ const getters = {
|
||||
twoFaEnabled: state => state.user.twoFaEnabled,
|
||||
twoFaProvider: state => state.user.twoFaProvider,
|
||||
twoFaIssuer: state => state.user.twoFaIssuer,
|
||||
loginFlag: state => state.user.loginFlag
|
||||
loginFlag: state => state.user.loginFlag,
|
||||
customHypervisorName: state => state.user.customHypervisorName
|
||||
}
|
||||
|
||||
export default getters
|
||||
|
||||
@ -64,7 +64,8 @@ const user = {
|
||||
shutdownTriggered: false,
|
||||
twoFaEnabled: false,
|
||||
twoFaProvider: '',
|
||||
twoFaIssuer: ''
|
||||
twoFaIssuer: '',
|
||||
customHypervisorName: 'Custom'
|
||||
},
|
||||
|
||||
mutations: {
|
||||
@ -151,6 +152,9 @@ const user = {
|
||||
},
|
||||
SET_LOGIN_FLAG: (state, flag) => {
|
||||
state.loginFlag = flag
|
||||
},
|
||||
SET_CUSTOM_HYPERVISOR_NAME (state, name) {
|
||||
state.customHypervisorName = name
|
||||
}
|
||||
},
|
||||
|
||||
@ -298,6 +302,15 @@ const user = {
|
||||
commit('SET_CLOUDIAN', cloudian)
|
||||
}).catch(ignored => {
|
||||
})
|
||||
|
||||
api('listConfigurations', { name: 'hypervisor.custom.display.name' }).then(json => {
|
||||
if (json.listconfigurationsresponse.configuration !== null) {
|
||||
const config = json.listconfigurationsresponse.configuration[0]
|
||||
commit('SET_CUSTOM_HYPERVISOR_NAME', config.value)
|
||||
}
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
@ -391,6 +404,15 @@ const user = {
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
|
||||
api('listConfigurations', { name: 'hypervisor.custom.display.name' }).then(json => {
|
||||
if (json.listconfigurationsresponse.configuration !== null) {
|
||||
const config = json.listconfigurationsresponse.configuration[0]
|
||||
commit('SET_CUSTOM_HYPERVISOR_NAME', config.value)
|
||||
}
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
UpdateConfiguration ({ commit }) {
|
||||
@ -411,6 +433,9 @@ const user = {
|
||||
},
|
||||
SetLoginFlag ({ commit }, loggedIn) {
|
||||
commit('SET_LOGIN_FLAG', loggedIn)
|
||||
},
|
||||
SetCustomHypervisorName ({ commit }, name) {
|
||||
commit('SET_CUSTOM_HYPERVISOR_NAME', name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="12" v-if="allowed && hyperKVMShow && currentForm !== 'Upload'">
|
||||
<a-row :gutter="12" v-if="allowed && (hyperKVMShow || hyperCustomShow) && currentForm !== 'Upload'">
|
||||
<a-col :md="24" :lg="12">
|
||||
<a-form-item ref="directdownload" name="directdownload" :label="$t('label.directdownload')">
|
||||
<a-switch v-model:checked="form.directdownload" @change="handleChangeDirect" />
|
||||
@ -398,6 +398,7 @@ export default {
|
||||
userdatapolicylist: {},
|
||||
defaultOsId: null,
|
||||
hyperKVMShow: false,
|
||||
hyperCustomShow: false,
|
||||
hyperXenServerShow: false,
|
||||
hyperVMWShow: false,
|
||||
selectedFormat: '',
|
||||
@ -408,7 +409,8 @@ export default {
|
||||
allowed: false,
|
||||
allowDirectDownload: false,
|
||||
uploadParams: null,
|
||||
currentForm: ['plus-outlined', 'PlusOutlined'].includes(this.action.currentAction.icon) ? 'Create' : 'Upload'
|
||||
currentForm: ['plus-outlined', 'PlusOutlined'].includes(this.action.currentAction.icon) ? 'Create' : 'Upload',
|
||||
customHypervisorName: 'Custom'
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
@ -456,6 +458,7 @@ export default {
|
||||
})
|
||||
},
|
||||
fetchData () {
|
||||
this.fetchCustomHypervisorName()
|
||||
this.fetchZone()
|
||||
this.fetchOsTypes()
|
||||
this.fetchUserData()
|
||||
@ -516,6 +519,23 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
fetchCustomHypervisorName () {
|
||||
const params = {
|
||||
name: 'hypervisor.custom.display.name'
|
||||
}
|
||||
this.loading = true
|
||||
api('listConfigurations', params).then(json => {
|
||||
if (json.listconfigurationsresponse.configuration !== null) {
|
||||
const config = json.listconfigurationsresponse.configuration[0]
|
||||
if (config && config.name === params.name) {
|
||||
this.customHypervisorName = config.value
|
||||
store.dispatch('SetCustomHypervisorName', this.customHypervisorName)
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
fetchZone () {
|
||||
const params = {}
|
||||
let listZones = []
|
||||
@ -781,6 +801,13 @@ export default {
|
||||
description: 'TAR'
|
||||
})
|
||||
break
|
||||
case this.customHypervisorName:
|
||||
this.hyperCustomShow = true
|
||||
format.push({
|
||||
id: 'RAW',
|
||||
description: 'RAW'
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -839,6 +866,7 @@ export default {
|
||||
this.hyperXenServerShow = false
|
||||
this.hyperVMWShow = false
|
||||
this.hyperKVMShow = false
|
||||
this.hyperCustomShow = false
|
||||
this.deployasis = false
|
||||
this.allowDirectDownload = false
|
||||
this.selectedFormat = null
|
||||
|
||||
@ -108,6 +108,7 @@ import { nextTick } from 'vue'
|
||||
import { api } from '@/api'
|
||||
import { mixinDevice } from '@/utils/mixin.js'
|
||||
import StaticInputsForm from '@views/infra/zone/StaticInputsForm'
|
||||
import store from '@/store'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -283,7 +284,7 @@ export default {
|
||||
placeHolder: 'message.error.host.name',
|
||||
required: true,
|
||||
display: {
|
||||
hypervisor: ['VMware', 'BareMetal', 'Ovm', 'Hyperv', 'KVM', 'XenServer', 'LXC', 'Simulator']
|
||||
hypervisor: ['VMware', 'BareMetal', 'Ovm', 'Hyperv', 'KVM', 'XenServer', 'LXC', 'Simulator', store.getters.customHypervisorName]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -292,7 +293,7 @@ export default {
|
||||
placeHolder: 'message.error.host.username',
|
||||
required: true,
|
||||
display: {
|
||||
hypervisor: ['VMware', 'BareMetal', 'Ovm', 'Hyperv', 'KVM', 'XenServer', 'LXC', 'Simulator']
|
||||
hypervisor: ['VMware', 'BareMetal', 'Ovm', 'Hyperv', 'KVM', 'XenServer', 'LXC', 'Simulator', store.getters.customHypervisorName]
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -329,7 +330,7 @@ export default {
|
||||
required: true,
|
||||
password: true,
|
||||
display: {
|
||||
hypervisor: ['VMware', 'BareMetal', 'Ovm', 'Hyperv', 'KVM', 'XenServer', 'LXC', 'Simulator'],
|
||||
hypervisor: ['VMware', 'BareMetal', 'Ovm', 'Hyperv', 'KVM', 'XenServer', 'LXC', 'Simulator', store.getters.customHypervisorName],
|
||||
authmethod: 'password'
|
||||
}
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user