mirror of https://github.com/apache/cloudstack.git
Merge branch '4.22'
This commit is contained in:
commit
e929f2024a
|
|
@ -153,8 +153,8 @@ public abstract class BaseUpdateTemplateOrIsoCmd extends BaseCmd {
|
|||
return (Map) (paramsCollection.toArray())[0];
|
||||
}
|
||||
|
||||
public boolean isCleanupDetails(){
|
||||
return cleanupDetails == null ? false : cleanupDetails.booleanValue();
|
||||
public boolean isCleanupDetails() {
|
||||
return cleanupDetails != null && cleanupDetails;
|
||||
}
|
||||
|
||||
public CPU.CPUArch getCPUArch() {
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ public abstract class BaseDeployVMCmd extends BaseAsyncCreateCustomIdCmd impleme
|
|||
@Parameter(name = ApiConstants.MAC_ADDRESS, type = CommandType.STRING, description = "the mac address for default vm's network")
|
||||
private String macAddress;
|
||||
|
||||
@Parameter(name = ApiConstants.KEYBOARD, type = CommandType.STRING, description = "an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us")
|
||||
@Parameter(name = ApiConstants.KEYBOARD, type = CommandType.STRING, description = "an optional keyboard device type for the virtual machine. valid value can be one of de,de-ch,es,es-latam,fi,fr,fr-be,fr-ch,is,it,jp,nl-be,no,pt,uk,us")
|
||||
private String keyboard;
|
||||
|
||||
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "Deploy vm for the project")
|
||||
|
|
|
|||
|
|
@ -340,6 +340,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
|
|||
@Param(description = "List of read-only Instance details as comma separated string.", since = "4.16.0")
|
||||
private String readOnlyDetails;
|
||||
|
||||
@SerializedName("alloweddetails")
|
||||
@Param(description = "List of allowed Vm details as comma separated string if VM instance settings are read from OVA.", since = "4.22.1")
|
||||
private String allowedDetails;
|
||||
|
||||
@SerializedName(ApiConstants.SSH_KEYPAIRS)
|
||||
@Param(description = "SSH key-pairs")
|
||||
private String keyPairNames;
|
||||
|
|
@ -1091,6 +1095,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
|
|||
this.readOnlyDetails = readOnlyDetails;
|
||||
}
|
||||
|
||||
public void setAllowedDetails(String allowedDetails) {
|
||||
this.allowedDetails = allowedDetails;
|
||||
}
|
||||
|
||||
public void setOsTypeId(String osTypeId) {
|
||||
this.osTypeId = osTypeId;
|
||||
}
|
||||
|
|
@ -1115,6 +1123,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
|
|||
return readOnlyDetails;
|
||||
}
|
||||
|
||||
public String getAllowedDetails() {
|
||||
return allowedDetails;
|
||||
}
|
||||
|
||||
public Boolean getDynamicallyScalable() {
|
||||
return isDynamicallyScalable;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
if (detailsStr == null) {
|
||||
return;
|
||||
}
|
||||
List<VMTemplateDetailVO> details = new ArrayList<VMTemplateDetailVO>();
|
||||
List<VMTemplateDetailVO> details = new ArrayList<>();
|
||||
for (String key : detailsStr.keySet()) {
|
||||
VMTemplateDetailVO detail = new VMTemplateDetailVO(tmpl.getId(), key, detailsStr.get(key), true);
|
||||
details.add(detail);
|
||||
|
|
@ -479,7 +479,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||
}
|
||||
|
||||
if (tmplt.getDetails() != null) {
|
||||
List<VMTemplateDetailVO> details = new ArrayList<VMTemplateDetailVO>();
|
||||
List<VMTemplateDetailVO> details = new ArrayList<>();
|
||||
for (String key : tmplt.getDetails().keySet()) {
|
||||
details.add(new VMTemplateDetailVO(tmplt.getId(), key, tmplt.getDetails().get(key), true));
|
||||
}
|
||||
|
|
|
|||
8
pom.xml
8
pom.xml
|
|
@ -65,20 +65,20 @@
|
|||
<!-- Plugins versions -->
|
||||
<cs.antrun-plugin.version>1.8</cs.antrun-plugin.version>
|
||||
<cs.builder-helper-plugin.version>3.0.0</cs.builder-helper-plugin.version>
|
||||
<cs.checkstyle-plugin.version>3.1.0</cs.checkstyle-plugin.version>
|
||||
<cs.checkstyle-plugin.version>3.6.0</cs.checkstyle-plugin.version>
|
||||
<cs.jacoco-plugin.version>0.8.11</cs.jacoco-plugin.version>
|
||||
<cs.compiler-plugin.version>3.8.1</cs.compiler-plugin.version>
|
||||
<cs.dependency-plugin.version>3.1.1</cs.dependency-plugin.version>
|
||||
<cs.dependency-plugin.version>3.9.0</cs.dependency-plugin.version>
|
||||
<cs.failsafe-plugin.version>2.22.2</cs.failsafe-plugin.version>
|
||||
<cs.spotbugs.version>3.1.12</cs.spotbugs.version>
|
||||
<cs.spotbugs-maven-plugin.version>3.1.12.2</cs.spotbugs-maven-plugin.version>
|
||||
<cs.jar-plugin.version>3.2.0</cs.jar-plugin.version>
|
||||
<cs.pmd-plugin.version>3.12.0</cs.pmd-plugin.version>
|
||||
<cs.pmd-plugin.version>3.28.0</cs.pmd-plugin.version>
|
||||
<cs.project-info-plugin.version>3.0.0</cs.project-info-plugin.version>
|
||||
<cs.owasp.dependency-checker-plugin.version>7.4.4</cs.owasp.dependency-checker-plugin.version>
|
||||
<cs.release-plugin.version>2.5.3</cs.release-plugin.version>
|
||||
<cs.resources-plugin.version>3.1.0</cs.resources-plugin.version>
|
||||
<cs.site-plugin.version>3.8.2</cs.site-plugin.version>
|
||||
<cs.site-plugin.version>3.21.0</cs.site-plugin.version>
|
||||
<cs.surefire-plugin.version>2.22.2</cs.surefire-plugin.version>
|
||||
<cs.clover-maven-plugin.version>4.4.1</cs.clover-maven-plugin.version>
|
||||
<cs.exec-maven-plugin.version>3.2.0</cs.exec-maven-plugin.version>
|
||||
|
|
|
|||
|
|
@ -5408,7 +5408,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||
|
||||
options.put(ApiConstants.BootType.UEFI.toString(), Arrays.asList(ApiConstants.BootMode.LEGACY.toString(),
|
||||
ApiConstants.BootMode.SECURE.toString()));
|
||||
options.put(VmDetailConstants.KEYBOARD, Arrays.asList("uk", "us", "jp", "fr"));
|
||||
options.put(VmDetailConstants.KEYBOARD, Arrays.asList("uk", "us", "jp", "fr", "es-latam"));
|
||||
options.put(VmDetailConstants.CPU_CORE_PER_SOCKET, Collections.emptyList());
|
||||
options.put(VmDetailConstants.ROOT_DISK_SIZE, Collections.emptyList());
|
||||
|
||||
|
|
|
|||
|
|
@ -69,9 +69,11 @@ import com.cloud.service.ServiceOfferingDetailsVO;
|
|||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.GuestOS;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.VnfTemplateDetailVO;
|
||||
import com.cloud.storage.VnfTemplateNicVO;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VnfTemplateDetailsDao;
|
||||
import com.cloud.storage.dao.VnfTemplateNicDao;
|
||||
import com.cloud.user.Account;
|
||||
|
|
@ -124,6 +126,8 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
private ServiceOfferingDao serviceOfferingDao;
|
||||
@Inject
|
||||
private VgpuProfileDao vgpuProfileDao;
|
||||
@Inject
|
||||
VMTemplateDao vmTemplateDao;
|
||||
|
||||
private final SearchBuilder<UserVmJoinVO> VmDetailSearch;
|
||||
private final SearchBuilder<UserVmJoinVO> activeVmByIsoSearch;
|
||||
|
|
@ -465,6 +469,10 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||
if (caller.getType() != Account.Type.ADMIN) {
|
||||
userVmResponse.setReadOnlyDetails(QueryService.UserVMReadOnlyDetails.value());
|
||||
}
|
||||
VMTemplateVO template = vmTemplateDao.findByIdIncludingRemoved(userVm.getTemplateId());
|
||||
if (template != null && template.isDeployAsIs() && UserVmManager.VmwareAdditionalDetailsFromOvaEnabled.valueIn(userVm.getDataCenterId())) {
|
||||
userVmResponse.setAllowedDetails(UserVmManager.VmwareAllowedAdditionalDetailsFromOva.valueIn(userVm.getDataCenterId()));
|
||||
}
|
||||
}
|
||||
|
||||
userVmResponse.setObjectName(objectName);
|
||||
|
|
|
|||
|
|
@ -2256,7 +2256,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
templateTag == null &&
|
||||
forCks == null &&
|
||||
arch == null &&
|
||||
(! cleanupDetails && details == null) //update details in every case except this one
|
||||
(!cleanupDetails && details == null) //update details in every case except this one
|
||||
);
|
||||
if (!updateNeeded) {
|
||||
return template;
|
||||
|
|
@ -2360,8 +2360,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
|||
if (cleanupDetails) {
|
||||
template.setDetails(null);
|
||||
_tmpltDetailsDao.removeDetails(id);
|
||||
}
|
||||
else if (details != null && !details.isEmpty()) {
|
||||
} else if (details != null && !details.isEmpty()) {
|
||||
template.setDetails(details);
|
||||
_tmpltDao.saveDetails(template);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,15 @@ public interface UserVmManager extends UserVmService {
|
|||
ConfigKey.Scope.Account);
|
||||
|
||||
|
||||
ConfigKey<Boolean> VmwareAdditionalDetailsFromOvaEnabled = new ConfigKey<Boolean>("Advanced", Boolean.class,
|
||||
"vmware.additional.details.from.ova.enabled", "false",
|
||||
"If true, allow users to add additional VM settings if VM instance settings are read from OVA.", true, ConfigKey.Scope.Zone);
|
||||
|
||||
ConfigKey<String> VmwareAllowedAdditionalDetailsFromOva = new ConfigKey<>(String.class,
|
||||
"vmware.allowed.additional.details.from.ova", "Advanced", "",
|
||||
"Comma separated list of allowed additional VM settings if VM instance settings are read from OVA.",
|
||||
true, ConfigKey.Scope.Zone, null, null, null, null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
static final int MAX_USER_DATA_LENGTH_BYTES = 2048;
|
||||
|
||||
public static final String CKS_NODE = "cksnode";
|
||||
|
|
|
|||
|
|
@ -150,7 +150,6 @@ import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
|
|||
import org.apache.cloudstack.utils.security.ParserUtils;
|
||||
import org.apache.cloudstack.vm.UnmanagedVMsManager;
|
||||
import org.apache.cloudstack.vm.lease.VMLeaseManager;
|
||||
import org.apache.cloudstack.vm.schedule.VMScheduleManager;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
|
|
@ -315,7 +314,6 @@ import com.cloud.resource.ResourceState;
|
|||
import com.cloud.resourcelimit.CheckedReservation;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.server.ResourceTag;
|
||||
import com.cloud.server.StatsCollector;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDao;
|
||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||
|
|
@ -615,28 +613,28 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
SnapshotPolicyDao snapshotPolicyDao;
|
||||
@Inject
|
||||
BackupScheduleDao backupScheduleDao;
|
||||
|
||||
@Inject
|
||||
private StatsCollector statsCollector;
|
||||
@Inject
|
||||
private UserDataDao userDataDao;
|
||||
|
||||
@Inject
|
||||
protected SnapshotHelper snapshotHelper;
|
||||
|
||||
@Inject
|
||||
private AutoScaleManager autoScaleManager;
|
||||
|
||||
@Inject
|
||||
VMScheduleManager vmScheduleManager;
|
||||
@Inject
|
||||
NsxProviderDao nsxProviderDao;
|
||||
|
||||
@Inject
|
||||
NetworkService networkService;
|
||||
|
||||
@Inject
|
||||
SnapshotDataFactory snapshotDataFactory;
|
||||
@Inject
|
||||
private OrchestrationService _orchSrvc;
|
||||
@Inject
|
||||
private VolumeOrchestrationService volumeMgr;
|
||||
@Inject
|
||||
private ManagementService _mgr;
|
||||
@Inject
|
||||
private UserDataManager userDataManager;
|
||||
@Inject
|
||||
VnfTemplateManager vnfTemplateManager;
|
||||
|
||||
private ScheduledExecutorService _executor = null;
|
||||
private ScheduledExecutorService _vmIpFetchExecutor = null;
|
||||
|
|
@ -646,8 +644,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
private int capacityReleaseInterval;
|
||||
private ExecutorService _vmIpFetchThreadExecutor;
|
||||
private List<KubernetesServiceHelper> kubernetesServiceHelpers;
|
||||
|
||||
|
||||
private String _instance;
|
||||
private boolean _instanceNameFlag;
|
||||
private int _scaleRetry;
|
||||
|
|
@ -655,10 +651,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
protected static long ROOT_DEVICE_ID = 0;
|
||||
|
||||
private static final int MAX_HTTP_GET_LENGTH = 2 * MAX_USER_DATA_LENGTH_BYTES;
|
||||
private static final int NUM_OF_2K_BLOCKS = 512;
|
||||
private static final int MAX_HTTP_POST_LENGTH = NUM_OF_2K_BLOCKS * MAX_USER_DATA_LENGTH_BYTES;
|
||||
|
||||
public List<KubernetesServiceHelper> getKubernetesServiceHelpers() {
|
||||
return kubernetesServiceHelpers;
|
||||
}
|
||||
|
|
@ -667,34 +659,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
this.kubernetesServiceHelpers = kubernetesServiceHelpers;
|
||||
}
|
||||
|
||||
@Inject
|
||||
private OrchestrationService _orchSrvc;
|
||||
|
||||
@Inject
|
||||
private VolumeOrchestrationService volumeMgr;
|
||||
|
||||
@Inject
|
||||
private ManagementService _mgr;
|
||||
|
||||
@Inject
|
||||
private UserDataManager userDataManager;
|
||||
|
||||
@Inject
|
||||
VnfTemplateManager vnfTemplateManager;
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchWaitInterval = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmip.retrieval.interval", "180",
|
||||
private static final ConfigKey<Integer> VmIpFetchWaitInterval = new ConfigKey<>("Advanced", Integer.class, "externaldhcp.vmip.retrieval.interval", "180",
|
||||
"Wait Interval (in seconds) for shared network vm dhcp ip addr fetch for next iteration ", true);
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchTrialMax = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmip.max.retry", "10",
|
||||
private static final ConfigKey<Integer> VmIpFetchTrialMax = new ConfigKey<>("Advanced", Integer.class, "externaldhcp.vmip.max.retry", "10",
|
||||
"The max number of retrieval times for shared network vm dhcp ip fetch, in case of failures", true);
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchThreadPoolMax = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10",
|
||||
private static final ConfigKey<Integer> VmIpFetchThreadPoolMax = new ConfigKey<>("Advanced", Integer.class, "externaldhcp.vmipFetch.threadPool.max", "10",
|
||||
"number of threads for fetching vms ip address", true);
|
||||
|
||||
private static final ConfigKey<Integer> VmIpFetchTaskWorkers = new ConfigKey<Integer>("Advanced", Integer.class, "externaldhcp.vmipfetchtask.workers", "10",
|
||||
private static final ConfigKey<Integer> VmIpFetchTaskWorkers = new ConfigKey<>("Advanced", Integer.class, "externaldhcp.vmipfetchtask.workers", "10",
|
||||
"number of worker threads for vm ip fetch task ", true);
|
||||
|
||||
private static final ConfigKey<Boolean> AllowDeployVmIfGivenHostFails = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.deploy.vm.if.deploy.on.given.host.fails", "false",
|
||||
private static final ConfigKey<Boolean> AllowDeployVmIfGivenHostFails = new ConfigKey<>("Advanced", Boolean.class, "allow.deploy.vm.if.deploy.on.given.host.fails", "false",
|
||||
"allow vm to deploy on different host if vm fails to deploy on the given host ", true);
|
||||
|
||||
private static final ConfigKey<String> KvmAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||
|
|
@ -706,7 +683,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
private static final ConfigKey<String> VmwareAdditionalConfigAllowList = new ConfigKey<>(String.class,
|
||||
"allow.additional.vm.configuration.list.vmware", "Advanced", "", "Comma separated list of allowed additional configuration options.", true, ConfigKey.Scope.Global, null, null, EnableAdditionalVmConfig.key(), null, null, ConfigKey.Kind.CSV, null);
|
||||
|
||||
private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<Boolean>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
|
||||
private static final ConfigKey<Boolean> VmDestroyForcestop = new ConfigKey<>("Advanced", Boolean.class, "vm.destroy.forcestop", "false",
|
||||
"On destroy, force-stop takes this value ", true);
|
||||
|
||||
@Override
|
||||
|
|
@ -735,7 +712,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
long vmId;
|
||||
int retrievalCount = VmIpFetchTrialMax.value();
|
||||
|
||||
|
||||
public VmAndCountDetails() {
|
||||
}
|
||||
|
||||
|
|
@ -1192,7 +1168,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
|
||||
//List all networks of vm
|
||||
List<Long> vmNetworks = _vmNetworkMapDao.getNetworks(vmId);
|
||||
List<DomainRouterVO> routers = new ArrayList<DomainRouterVO>();
|
||||
List<DomainRouterVO> routers = new ArrayList<>();
|
||||
//List the stopped routers
|
||||
for(long vmNetworkId : vmNetworks) {
|
||||
List<DomainRouterVO> router = _routerDao.listStopped(vmNetworkId);
|
||||
|
|
@ -2903,11 +2879,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
UserVmVO vmInstance = _vmDao.findById(cmd.getId());
|
||||
VMTemplateVO template = _templateDao.findById(vmInstance.getTemplateId());
|
||||
if (MapUtils.isNotEmpty(details) || cmd.isCleanupDetails()) {
|
||||
if (template != null && template.isDeployAsIs()) {
|
||||
throw new CloudRuntimeException("Detail settings are read from OVA, it cannot be changed by API call.");
|
||||
}
|
||||
}
|
||||
|
||||
UserVmVO userVm = _vmDao.findById(cmd.getId());
|
||||
if (userVm != null && UserVmManager.SHAREDFSVM.equals(userVm.getUserVmType())) {
|
||||
throw new InvalidParameterValueException("Operation not supported on Shared FileSystem Instance");
|
||||
|
|
@ -2937,6 +2909,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
.collect(Collectors.toList());
|
||||
List<VMInstanceDetailVO> existingDetails = vmInstanceDetailsDao.listDetails(id);
|
||||
if (cleanupDetails) {
|
||||
if (template != null && template.isDeployAsIs()) {
|
||||
throw new InvalidParameterValueException("Detail settings are read from OVA, it cannot be cleaned up by API call.");
|
||||
}
|
||||
if (caller != null && caller.getType() == Account.Type.ADMIN) {
|
||||
for (final VMInstanceDetailVO detail : existingDetails) {
|
||||
if (detail != null && detail.isDisplay() && !isExtraConfig(detail.getName())) {
|
||||
|
|
@ -2965,6 +2940,23 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
throw new InvalidParameterValueException("'extraconfig' should not be included in details as key");
|
||||
}
|
||||
|
||||
if (template != null && template.isDeployAsIs()) {
|
||||
final List<String> vmwareAllowedDetailsFromOva = VmwareAdditionalDetailsFromOvaEnabled.valueIn(vmInstance.getDataCenterId()) ?
|
||||
Stream.of(VmwareAllowedAdditionalDetailsFromOva.valueIn(vmInstance.getDataCenterId()).split(","))
|
||||
.map(String::trim)
|
||||
.collect(Collectors.toList()) : List.of();
|
||||
for (String detailKey : details.keySet()) {
|
||||
if (vmwareAllowedDetailsFromOva.contains(detailKey)) {
|
||||
continue;
|
||||
}
|
||||
VMInstanceDetailVO detailVO = existingDetails.stream().filter(d -> Objects.equals(d.getName(), detailKey)).findFirst().orElse(null);
|
||||
if (detailVO != null && ObjectUtils.allNotNull(detailVO.getValue(), details.get(detailKey)) && detailVO.getValue().equals(details.get(detailKey))) {
|
||||
continue;
|
||||
}
|
||||
throw new InvalidParameterValueException("Detail settings are read from OVA, it cannot be changed by API call.");
|
||||
}
|
||||
}
|
||||
|
||||
details.entrySet().removeIf(detail -> isExtraConfig(detail.getKey()));
|
||||
|
||||
if (caller != null && caller.getType() != Account.Type.ADMIN) {
|
||||
|
|
@ -3214,7 +3206,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
// Verify that vm's hostName is unique
|
||||
|
||||
List<NetworkVO> vmNtwks = new ArrayList<NetworkVO>(nics.size());
|
||||
List<NetworkVO> vmNtwks = new ArrayList<>(nics.size());
|
||||
for (Nic nic : nics) {
|
||||
vmNtwks.add(_networkDao.findById(nic.getNetworkId()));
|
||||
}
|
||||
|
|
@ -3784,7 +3776,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
StorageUnavailableException, ResourceAllocationException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
|
||||
List<NetworkVO> networkList = new ArrayList<>();
|
||||
|
||||
// Verify that caller can perform actions in behalf of vm owner
|
||||
_accountMgr.checkAccess(caller, null, true, owner);
|
||||
|
|
@ -3810,7 +3802,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
//add the default securityGroup only if no security group is specified
|
||||
if (securityGroupIdList == null || securityGroupIdList.isEmpty()) {
|
||||
if (securityGroupIdList == null) {
|
||||
securityGroupIdList = new ArrayList<Long>();
|
||||
securityGroupIdList = new ArrayList<>();
|
||||
}
|
||||
SecurityGroup defaultGroup = _securityGroupMgr.getDefaultSecurityGroup(owner.getId());
|
||||
if (defaultGroup != null) {
|
||||
|
|
@ -3842,7 +3834,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, Map<String, String> userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType, Volume volume, Snapshot snapshot) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
|
||||
List<NetworkVO> networkList = new ArrayList<>();
|
||||
boolean isSecurityGroupEnabledNetworkUsed = false;
|
||||
boolean isVmWare = (template.getHypervisorType() == HypervisorType.VMware || (hypervisor != null && hypervisor == HypervisorType.VMware));
|
||||
|
||||
|
|
@ -3920,7 +3912,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
//add the default securityGroup only if no security group is specified
|
||||
if (securityGroupIdList == null || securityGroupIdList.isEmpty()) {
|
||||
if (securityGroupIdList == null) {
|
||||
securityGroupIdList = new ArrayList<Long>();
|
||||
securityGroupIdList = new ArrayList<>();
|
||||
}
|
||||
|
||||
SecurityGroup defaultGroup = _securityGroupMgr.getDefaultSecurityGroup(owner.getId());
|
||||
|
|
@ -3955,7 +3947,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
StorageUnavailableException, ResourceAllocationException {
|
||||
|
||||
Account caller = CallContext.current().getCallingAccount();
|
||||
List<NetworkVO> networkList = new ArrayList<NetworkVO>();
|
||||
List<NetworkVO> networkList = new ArrayList<>();
|
||||
|
||||
// Verify that caller can perform actions in behalf of vm owner
|
||||
_accountMgr.checkAccess(caller, null, true, owner);
|
||||
|
|
@ -4910,10 +4902,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
logger.debug("Allocating in the DB for vm");
|
||||
DataCenterDeployment plan = new DataCenterDeployment(zone.getId());
|
||||
|
||||
List<String> computeTags = new ArrayList<String>();
|
||||
List<String> computeTags = new ArrayList<>();
|
||||
computeTags.add(offering.getHostTag());
|
||||
|
||||
List<String> rootDiskTags = new ArrayList<String>();
|
||||
List<String> rootDiskTags = new ArrayList<>();
|
||||
DiskOfferingVO rootDiskOfferingVO = _diskOfferingDao.findById(rootDiskOfferingId);
|
||||
rootDiskTags.add(rootDiskOfferingVO.getTags());
|
||||
|
||||
|
|
@ -5127,7 +5119,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
VirtualMachine.class.getName(), vm.getUuid(), isDisplay);
|
||||
}
|
||||
else {
|
||||
Map<String, String> customParameters = new HashMap<String, String>();
|
||||
Map<String, String> customParameters = new HashMap<>();
|
||||
customParameters.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString());
|
||||
customParameters.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString());
|
||||
customParameters.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString());
|
||||
|
|
@ -5144,7 +5136,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
logger.debug("Collect vm network statistics from host before stopping Vm");
|
||||
long hostId = userVm.getHostId();
|
||||
List<String> vmNames = new ArrayList<String>();
|
||||
List<String> vmNames = new ArrayList<>();
|
||||
vmNames.add(userVm.getInstanceName());
|
||||
final HostVO host = _hostDao.findById(hostId);
|
||||
Account account = _accountMgr.getAccount(userVm.getAccountId());
|
||||
|
|
@ -5736,7 +5728,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
SecurityGroup defaultSecurityGroup = _securityGroupMgr.getDefaultSecurityGroup(vm.getAccountId());
|
||||
if (defaultSecurityGroup != null) {
|
||||
List<Long> groupList = new ArrayList<Long>();
|
||||
List<Long> groupList = new ArrayList<>();
|
||||
groupList.add(defaultSecurityGroup.getId());
|
||||
_securityGroupMgr.addInstanceToGroups(vm, groupList);
|
||||
}
|
||||
|
|
@ -6025,7 +6017,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return;
|
||||
}
|
||||
long hostId = userVm.getHostId();
|
||||
List<String> vmNames = new ArrayList<String>();
|
||||
List<String> vmNames = new ArrayList<>();
|
||||
vmNames.add(userVm.getInstanceName());
|
||||
final HostVO host = _hostDao.findById(hostId);
|
||||
Account account = _accountMgr.getAccount(userVm.getAccountId());
|
||||
|
|
@ -6433,7 +6425,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
String userData = null;
|
||||
Long userDataId = null;
|
||||
String userDataDetails = null;
|
||||
List<String> sshKeyPairNames = new ArrayList<String>();
|
||||
List<String> sshKeyPairNames = new ArrayList<>();
|
||||
if (cmd instanceof CreateVMFromBackupCmd) {
|
||||
if (cmd.getUserData() != null) {
|
||||
throw new InvalidParameterValueException("User data not supported for instance created from backup");
|
||||
|
|
@ -6890,7 +6882,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
//transform group names to ids here
|
||||
if (cmd.getSecurityGroupNameList() != null) {
|
||||
List<Long> securityGroupIds = new ArrayList<Long>();
|
||||
List<Long> securityGroupIds = new ArrayList<>();
|
||||
for (String groupName : cmd.getSecurityGroupNameList()) {
|
||||
SecurityGroup sg = _securityGroupMgr.getSecurityGroup(groupName, cmd.getEntityOwnerId());
|
||||
if (sg == null) {
|
||||
|
|
@ -7675,7 +7667,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
}
|
||||
|
||||
private Map<Long, Long> getVolumePoolMappingForMigrateVmWithStorage(VMInstanceVO vm, Map<String, String> volumeToPool) {
|
||||
Map<Long, Long> volToPoolObjectMap = new HashMap<Long, Long>();
|
||||
Map<Long, Long> volToPoolObjectMap = new HashMap<>();
|
||||
|
||||
List<VolumeVO> vmVolumes = getVmVolumesForMigrateVmWithStorage(vm);
|
||||
|
||||
|
|
@ -9352,7 +9344,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return new ConfigKey<?>[] {EnableDynamicallyScaleVm, AllowDiskOfferingChangeDuringScaleVm, AllowUserExpungeRecoverVm, VmIpFetchWaitInterval, VmIpFetchTrialMax,
|
||||
VmIpFetchThreadPoolMax, VmIpFetchTaskWorkers, AllowDeployVmIfGivenHostFails, EnableAdditionalVmConfig, DisplayVMOVFProperties,
|
||||
KvmAdditionalConfigAllowList, XenServerAdditionalConfigAllowList, VmwareAdditionalConfigAllowList, DestroyRootVolumeOnVmDestruction,
|
||||
EnforceStrictResourceLimitHostTagCheck, StrictHostTags, AllowUserForceStopVm, VmDistinctHostNameScope};
|
||||
EnforceStrictResourceLimitHostTagCheck, StrictHostTags, AllowUserForceStopVm, VmDistinctHostNameScope,
|
||||
VmwareAdditionalDetailsFromOvaEnabled, VmwareAllowedAdditionalDetailsFromOva};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -9712,7 +9705,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
|
||||
Map<Long, IpAddresses> ipToNetworkMap = cmd.getIpToNetworkMap();
|
||||
if (networkIds == null && ipToNetworkMap == null) {
|
||||
networkIds = new ArrayList<Long>();
|
||||
networkIds = new ArrayList<>();
|
||||
ipToNetworkMap = backupManager.getIpToNetworkMapFromBackup(backup, cmd.getPreserveIp(), networkIds);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import java.util.Date;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
|
@ -182,6 +183,11 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
Long.class, "vm.job.check.interval", "3000",
|
||||
"Interval in milliseconds to check if the job is complete", false);
|
||||
|
||||
private static final Set<String> VM_SNAPSHOT_CUSTOM_SERVICE_OFFERING_DETAILS = Set.of(
|
||||
VmDetailConstants.CPU_NUMBER.toLowerCase(),
|
||||
VmDetailConstants.CPU_SPEED.toLowerCase(),
|
||||
VmDetailConstants.MEMORY.toLowerCase());
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
_name = name;
|
||||
|
|
@ -472,7 +478,8 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
}
|
||||
|
||||
/**
|
||||
* Add entries on vm_snapshot_details if service offering is dynamic. This will allow setting details when revert to vm snapshot
|
||||
* Add entries about cpu, cpu_speed and memory in vm_snapshot_details if service offering is dynamic.
|
||||
* This will allow setting details when revert to vm snapshot.
|
||||
* @param vmId vm id
|
||||
* @param serviceOfferingId service offering id
|
||||
* @param vmSnapshotId vm snapshot id
|
||||
|
|
@ -483,7 +490,7 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
List<VMInstanceDetailVO> vmDetails = _vmInstanceDetailsDao.listDetails(vmId);
|
||||
List<VMSnapshotDetailsVO> vmSnapshotDetails = new ArrayList<VMSnapshotDetailsVO>();
|
||||
for (VMInstanceDetailVO detail : vmDetails) {
|
||||
if(detail.getName().equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || detail.getName().equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || detail.getName().equalsIgnoreCase(VmDetailConstants.MEMORY)) {
|
||||
if (VM_SNAPSHOT_CUSTOM_SERVICE_OFFERING_DETAILS.contains(detail.getName().toLowerCase())) {
|
||||
vmSnapshotDetails.add(new VMSnapshotDetailsVO(vmSnapshotId, detail.getName(), detail.getValue(), detail.isDisplay()));
|
||||
}
|
||||
}
|
||||
|
|
@ -936,7 +943,7 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
Transaction.execute(new TransactionCallbackWithExceptionNoReturn<CloudRuntimeException>() {
|
||||
@Override
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) throws CloudRuntimeException {
|
||||
revertUserVmDetailsFromVmSnapshot(userVm, vmSnapshotVo);
|
||||
revertCustomServiceOfferingDetailsFromVmSnapshot(userVm, vmSnapshotVo);
|
||||
updateUserVmServiceOffering(userVm, vmSnapshotVo);
|
||||
}
|
||||
});
|
||||
|
|
@ -948,19 +955,19 @@ public class VMSnapshotManagerImpl extends MutualExclusiveIdsManagerBase impleme
|
|||
}
|
||||
|
||||
/**
|
||||
* Update or add user vm details from vm snapshot for vms with custom service offerings
|
||||
* Update or add user vm details (cpu, cpu_speed and memory) from vm snapshot for vms with custom service offerings
|
||||
* @param userVm user vm
|
||||
* @param vmSnapshotVo vm snapshot
|
||||
*/
|
||||
protected void revertUserVmDetailsFromVmSnapshot(UserVmVO userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
protected void revertCustomServiceOfferingDetailsFromVmSnapshot(UserVmVO userVm, VMSnapshotVO vmSnapshotVo) {
|
||||
ServiceOfferingVO serviceOfferingVO = _serviceOfferingDao.findById(vmSnapshotVo.getServiceOfferingId());
|
||||
if (serviceOfferingVO.isDynamic()) {
|
||||
List<VMSnapshotDetailsVO> vmSnapshotDetails = _vmSnapshotDetailsDao.listDetails(vmSnapshotVo.getId());
|
||||
List<VMInstanceDetailVO> userVmDetails = new ArrayList<VMInstanceDetailVO>();
|
||||
for (VMSnapshotDetailsVO detail : vmSnapshotDetails) {
|
||||
userVmDetails.add(new VMInstanceDetailVO(userVm.getId(), detail.getName(), detail.getValue(), detail.isDisplay()));
|
||||
if (VM_SNAPSHOT_CUSTOM_SERVICE_OFFERING_DETAILS.contains(detail.getName().toLowerCase())) {
|
||||
_vmInstanceDetailsDao.addDetail(userVm.getId(), detail.getName(), detail.getValue(), detail.isDisplay());
|
||||
}
|
||||
}
|
||||
_vmInstanceDetailsDao.saveDetails(userVmDetails);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import static org.mockito.MockitoAnnotations.openMocks;
|
|||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import com.cloud.storage.dao.VMTemplateDao;
|
||||
import org.apache.cloudstack.annotation.dao.AnnotationDao;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.ResponseObject;
|
||||
|
|
@ -78,6 +79,9 @@ public class UserVmJoinDaoImplTest extends GenericDaoBaseWithTagInformationBaseT
|
|||
@Mock
|
||||
private VnfTemplateDetailsDao vnfTemplateDetailsDao;
|
||||
|
||||
@Mock
|
||||
private VMTemplateDao vmTemplateDao;
|
||||
|
||||
private UserVmJoinVO userVm = new UserVmJoinVO();
|
||||
private UserVmResponse userVmResponse = new UserVmResponse();
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ import com.cloud.vm.UserVmManager;
|
|||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VirtualMachine.State;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
import com.cloud.vm.VmDetailConstants;
|
||||
import com.cloud.vm.dao.UserVmDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
|
@ -68,7 +69,6 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.Spy;
|
||||
|
|
@ -80,13 +80,18 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
|
@ -228,13 +233,13 @@ public class VMSnapshotManagerTest {
|
|||
when(_serviceOfferingDao.findById(SERVICE_OFFERING_ID)).thenReturn(serviceOffering);
|
||||
|
||||
for (ResourceDetail detail : Arrays.asList(userVmDetailCpuNumber, vmSnapshotDetailCpuNumber)) {
|
||||
when(detail.getName()).thenReturn("cpuNumber");
|
||||
when(detail.getName()).thenReturn(VmDetailConstants.CPU_NUMBER);
|
||||
when(detail.getValue()).thenReturn("2");
|
||||
when(detail.isDisplay()).thenReturn(true);
|
||||
}
|
||||
|
||||
for (ResourceDetail detail : Arrays.asList(userVmDetailMemory, vmSnapshotDetailMemory)) {
|
||||
when(detail.getName()).thenReturn("memory");
|
||||
when(detail.getName()).thenReturn(VmDetailConstants.MEMORY);
|
||||
when(detail.getValue()).thenReturn("2048");
|
||||
when(detail.isDisplay()).thenReturn(true);
|
||||
}
|
||||
|
|
@ -363,12 +368,12 @@ public class VMSnapshotManagerTest {
|
|||
@Test
|
||||
public void testUpdateUserVmServiceOfferingDifferentServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(userVm.getServiceOfferingId()).thenReturn(SERVICE_OFFERING_DIFFERENT_ID);
|
||||
when(_userVmManager.upgradeVirtualMachine(ArgumentMatchers.eq(TEST_VM_ID), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
_vmSnapshotMgr.updateUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
|
||||
verify(_vmSnapshotMgr).changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(ArgumentMatchers.eq(userVm), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -383,18 +388,18 @@ public class VMSnapshotManagerTest {
|
|||
|
||||
@Test
|
||||
public void testChangeUserVmServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(ArgumentMatchers.eq(TEST_VM_ID), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(true);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(ArgumentMatchers.eq(userVm), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test(expected=CloudRuntimeException.class)
|
||||
public void testChangeUserVmServiceOfferingFailOnUpgradeVMServiceOffering() throws ConcurrentOperationException, ResourceUnavailableException, ManagementServerException, VirtualMachineMigrationException {
|
||||
when(_userVmManager.upgradeVirtualMachine(ArgumentMatchers.eq(TEST_VM_ID), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(false);
|
||||
when(_userVmManager.upgradeVirtualMachine(eq(TEST_VM_ID), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture())).thenReturn(false);
|
||||
_vmSnapshotMgr.changeUserVmServiceOffering(userVm, vmSnapshotVO);
|
||||
verify(_vmSnapshotMgr).getVmMapDetails(userVm);
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(ArgumentMatchers.eq(userVm), ArgumentMatchers.eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
verify(_vmSnapshotMgr).upgradeUserVmServiceOffering(eq(userVm), eq(SERVICE_OFFERING_ID), mapDetailsCaptor.capture());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -411,16 +416,27 @@ public class VMSnapshotManagerTest {
|
|||
|
||||
@Test
|
||||
public void testRevertUserVmDetailsFromVmSnapshotNotDynamicServiceOffering() {
|
||||
_vmSnapshotMgr.revertUserVmDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
_vmSnapshotMgr.revertCustomServiceOfferingDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
verify(_vmSnapshotDetailsDao, never()).listDetails(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevertUserVmDetailsFromVmSnapshotDynamicServiceOffering() {
|
||||
when(serviceOffering.isDynamic()).thenReturn(true);
|
||||
_vmSnapshotMgr.revertUserVmDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
verify(_vmSnapshotDetailsDao).listDetails(VM_SNAPSHOT_ID);
|
||||
verify(_vmInstanceDetailsDao).saveDetails(listUserVmDetailsCaptor.capture());
|
||||
}
|
||||
VMSnapshotDetailsVO uefiSnapshotDetail = new VMSnapshotDetailsVO(VM_SNAPSHOT_ID, "UEFI", "SECURE", true);
|
||||
List<VMSnapshotDetailsVO> snapshotDetailsWithUefi = Arrays.asList(
|
||||
vmSnapshotDetailCpuNumber, vmSnapshotDetailMemory, uefiSnapshotDetail);
|
||||
when(_vmSnapshotDetailsDao.listDetails(VM_SNAPSHOT_ID)).thenReturn(snapshotDetailsWithUefi);
|
||||
|
||||
_vmSnapshotMgr.revertCustomServiceOfferingDetailsFromVmSnapshot(vmMock, vmSnapshotVO);
|
||||
|
||||
verify(_vmSnapshotDetailsDao).listDetails(VM_SNAPSHOT_ID);
|
||||
verify(_vmInstanceDetailsDao, never()).saveDetails(any());
|
||||
ArgumentCaptor<String> detailNameCaptor = ArgumentCaptor.forClass(String.class);
|
||||
verify(_vmInstanceDetailsDao, times(2)).addDetail(eq(TEST_VM_ID), detailNameCaptor.capture(), anyString(), anyBoolean());
|
||||
List<String> appliedNames = detailNameCaptor.getAllValues();
|
||||
assertTrue(appliedNames.contains(VmDetailConstants.CPU_NUMBER));
|
||||
assertTrue(appliedNames.contains(VmDetailConstants.MEMORY));
|
||||
assertFalse("UEFI must not be applied from snapshot so that existing UEFI setting is preserved", appliedNames.contains("UEFI"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import ZRLEDecoder from "./decoders/zrle.js";
|
|||
import JPEGDecoder from "./decoders/jpeg.js";
|
||||
import H264Decoder from "./decoders/h264.js";
|
||||
import SCANCODES_JP from "../keymaps/keymap-ja-atset1.js"
|
||||
import SCANCODES_ES_LATAM from "../keymaps/keymap-es-latam-atset1.js"
|
||||
|
||||
// How many seconds to wait for a disconnect to finish
|
||||
const DISCONNECT_TIMEOUT = 3;
|
||||
|
|
@ -127,6 +128,8 @@ export default class RFB extends EventTargetMixin {
|
|||
this._scancodes = {};
|
||||
if (this._language === "jp") {
|
||||
this._scancodes = SCANCODES_JP;
|
||||
} else if (this._language === "es-latam") {
|
||||
this._scancodes = SCANCODES_ES_LATAM;
|
||||
}
|
||||
|
||||
// Internal state
|
||||
|
|
@ -197,6 +200,7 @@ export default class RFB extends EventTargetMixin {
|
|||
// Keys
|
||||
this._shiftPressed = false;
|
||||
this._shiftKey = KeyTable.XK_Shift_L;
|
||||
this._altgrPressed = false;
|
||||
|
||||
// Mouse state
|
||||
this._mousePos = {};
|
||||
|
|
@ -531,6 +535,10 @@ export default class RFB extends EventTargetMixin {
|
|||
this._shiftKey = down ? keysym : KeyTable.XK_Shift_L;
|
||||
}
|
||||
|
||||
if (keysym === KeyTable.XK_Alt_R) {
|
||||
this._altgrPressed = down;
|
||||
}
|
||||
|
||||
if (this._qemuExtKeyEventSupported && scancode) {
|
||||
// 0 is NoSymbol
|
||||
keysym = keysym || 0;
|
||||
|
|
@ -538,31 +546,10 @@ export default class RFB extends EventTargetMixin {
|
|||
Log.Info("Sending key (" + (down ? "down" : "up") + "): keysym " + keysym + ", scancode " + scancode);
|
||||
|
||||
RFB.messages.QEMUExtendedKeyEvent(this._sock, keysym, down, scancode);
|
||||
} else if (Object.keys(this._scancodes).length > 0) {
|
||||
let vscancode = this._scancodes[keysym]
|
||||
if (vscancode) {
|
||||
let shifted = vscancode.includes("shift");
|
||||
let vscancode_int = parseInt(vscancode);
|
||||
let isLetter = (keysym >= 65 && keysym <=90) || (keysym >=97 && keysym <=122);
|
||||
if (shifted && ! this._shiftPressed && ! isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
}
|
||||
if (! shifted && this._shiftPressed && ! isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
RFB.messages.VMwareExtendedKeyEvent(this._sock, keysym, down, vscancode_int);
|
||||
if (shifted && ! this._shiftPressed && ! isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
if (! shifted && this._shiftPressed && ! isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
}
|
||||
} else {
|
||||
if (this._language === "jp" && keysym === 65328) {
|
||||
keysym = 65509; // Caps lock
|
||||
}
|
||||
RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0);
|
||||
}
|
||||
} else if (Object.keys(this._scancodes).length > 0 && this._language === "jp") {
|
||||
this.sendKeyWithJapaneseKeyboard(keysym, down)
|
||||
} else if (Object.keys(this._scancodes).length > 0 && this._language === "es-latam") {
|
||||
this.sendKeyWithSpanishLatamKeyboard(keysym, down)
|
||||
} else {
|
||||
if (!keysym) {
|
||||
return;
|
||||
|
|
@ -572,6 +559,93 @@ export default class RFB extends EventTargetMixin {
|
|||
}
|
||||
}
|
||||
|
||||
sendKeyWithJapaneseKeyboard(keysym, down) {
|
||||
let vscancode = this._scancodes[keysym]
|
||||
if (vscancode) {
|
||||
let shifted = vscancode.includes("shift");
|
||||
let vscancode_int = parseInt(vscancode);
|
||||
let isLetter = (keysym >= 65 && keysym <= 90) || (keysym >= 97 && keysym <= 122);
|
||||
if (shifted && !this._shiftPressed && !isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
}
|
||||
if (!shifted && this._shiftPressed && !isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
RFB.messages.VMwareExtendedKeyEvent(this._sock, keysym, down, vscancode_int);
|
||||
if (shifted && !this._shiftPressed && !isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
if (!shifted && this._shiftPressed && !isLetter) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
}
|
||||
} else {
|
||||
if (keysym === 65328) {
|
||||
keysym = 65509; // Caps lock
|
||||
}
|
||||
RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
sendKeyWithSpanishLatamKeyboard(keysym, down) {
|
||||
const VSCODE_ACUTE_LATAM = 26; // The ASCII code of acute is 180
|
||||
let vscancode = this._scancodes[keysym]
|
||||
if (vscancode) {
|
||||
let shifted = vscancode.includes("shift");
|
||||
let altgr = vscancode.includes("altgr");
|
||||
let acute = vscancode.includes("acute");
|
||||
let vscancode_int = parseInt(vscancode);
|
||||
if (acute) {
|
||||
let shifted_1 = vscancode.includes("shift1"); // Shift with Acute accent
|
||||
let shifted_2 = vscancode.includes("shift2"); // Shift with a/e/i/o/u
|
||||
if (down) {
|
||||
if (shifted_1 && ! this._shiftPressed) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
} else if (! shifted_1 && this._shiftPressed) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
RFB.messages.VMwareExtendedKeyEvent(this._sock, keysym, 1, VSCODE_ACUTE_LATAM);
|
||||
RFB.messages.VMwareExtendedKeyEvent(this._sock, keysym, 0, VSCODE_ACUTE_LATAM);
|
||||
if (shifted_2) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
} else {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
} else {
|
||||
RFB.messages.VMwareExtendedKeyEvent(this._sock, keysym, 0, VSCODE_ACUTE_LATAM);
|
||||
if (shifted_2 && ! this._shiftPressed) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
} else if (! shifted_2 && this._shiftPressed) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
}
|
||||
}
|
||||
RFB.messages.VMwareExtendedKeyEvent(this._sock, keysym, down, vscancode_int);
|
||||
return;
|
||||
}
|
||||
let isLetter = (keysym >= 65 && keysym <= 90) || (keysym >= 97 && keysym <= 122);
|
||||
if (shifted && !this._shiftPressed && !isLetter && down) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
}
|
||||
if (!shifted && this._shiftPressed && !isLetter && down) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
if (altgr && !this._altgrPressed && down) {
|
||||
RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_R, 1);
|
||||
}
|
||||
RFB.messages.VMwareExtendedKeyEvent(this._sock, keysym, down, vscancode_int);
|
||||
if (altgr && !this._altgrPressed && !down) {
|
||||
RFB.messages.keyEvent(this._sock, KeyTable.XK_Alt_R, 0);
|
||||
}
|
||||
if (shifted && !this._shiftPressed && !isLetter && !down) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 0);
|
||||
}
|
||||
if (!shifted && this._shiftPressed && !isLetter && !down) {
|
||||
RFB.messages.keyEvent(this._sock, this._shiftKey, 1);
|
||||
}
|
||||
} else {
|
||||
RFB.messages.keyEvent(this._sock, keysym, down ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
focus(options) {
|
||||
this._canvas.focus(options);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# This script
|
||||
# (1) loads keysym name and keycode mappings from noVNC/core/input/keysym.js and
|
||||
# (2) loads keysyn name to atset1 code mappings from keymap files which can be downloadeded from https://github.com/qemu/qemu/blob/master/pc-bios/keymaps
|
||||
# (2) loads keysym name to atset1 code mappings from keymap files which can be downloadeded from https://github.com/qemu/qemu/blob/master/pc-bios/keymaps
|
||||
# (3) generates the mappings of keycode and atset1 code
|
||||
#
|
||||
# Note: please add language specific mappings if needed.
|
||||
|
|
@ -96,7 +96,10 @@ def generate_js_file(keymap_file):
|
|||
js_config.append(" */\n")
|
||||
js_config.append("export default {\n")
|
||||
for keycode in dict(sorted(list(result_mappings.items()), key=lambda item: int(item[0]))):
|
||||
js_config.append("%10s : \"%s\",\n" % ("\"" + str(keycode) + "\"", result_mappings[keycode].strip()))
|
||||
if keycode not in list(keycode_to_x11name.keys()):
|
||||
js_config.append("%10s : \"%s\",\n" % ("\"" + str(keycode) + "\"", result_mappings[keycode].strip()))
|
||||
else:
|
||||
js_config.append("%10s : \"%s\", // %s\n" % ("\"" + str(keycode) + "\"", result_mappings[keycode].strip(), keycode_to_x11name[keycode]))
|
||||
js_config.append("}\n")
|
||||
for line in js_config:
|
||||
handle.write(line)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
/* This file is auto-generated by generate-language-keymaps.py
|
||||
* command : generate-language-keymaps.py keymap-es
|
||||
* layout : es-latam
|
||||
*/
|
||||
export default {
|
||||
"32" : "57", // XK_space
|
||||
"33" : "2 shift", // XK_exclam
|
||||
"34" : "3 shift", // XK_quotedbl
|
||||
"35" : "4 shift", // XK_numbersign
|
||||
"36" : "5 shift", // XK_dollar
|
||||
"37" : "6 shift", // XK_percent
|
||||
"38" : "7 shift", // XK_ampersand
|
||||
"39" : "12", // XK_apostrophe
|
||||
"40" : "9 shift", // XK_parenleft
|
||||
"41" : "10 shift", // XK_parenright
|
||||
"42" : "27 shift", // XK_asterisk
|
||||
"43" : "27", // XK_plus
|
||||
"44" : "51", // XK_comma
|
||||
"45" : "53", // XK_minus
|
||||
"46" : "52", // XK_period
|
||||
"47" : "8 shift", // XK_slash
|
||||
"48" : "11", // XK_0
|
||||
"49" : "2", // XK_1
|
||||
"50" : "3", // XK_2
|
||||
"51" : "4", // XK_3
|
||||
"52" : "5", // XK_4
|
||||
"53" : "6", // XK_5
|
||||
"54" : "7", // XK_6
|
||||
"55" : "8", // XK_7
|
||||
"56" : "9", // XK_8
|
||||
"57" : "10", // XK_9
|
||||
"58" : "52 shift", // XK_colon
|
||||
"59" : "51 shift", // XK_semicolon
|
||||
"60" : "86", // XK_less
|
||||
"61" : "11 shift", // XK_equal
|
||||
"62" : "86 shift", // XK_greater
|
||||
"63" : "12 shift", // XK_question
|
||||
"64" : "16 altgr", // XK_at
|
||||
"65" : "30 shift", // XK_A
|
||||
"66" : "48 shift", // XK_B
|
||||
"67" : "46 shift", // XK_C
|
||||
"68" : "32 shift", // XK_D
|
||||
"69" : "18 shift", // XK_E
|
||||
"70" : "33 shift", // XK_F
|
||||
"71" : "34 shift", // XK_G
|
||||
"72" : "35 shift", // XK_H
|
||||
"73" : "23 shift", // XK_I
|
||||
"74" : "36 shift", // XK_J
|
||||
"75" : "37 shift", // XK_K
|
||||
"76" : "38 shift", // XK_L
|
||||
"77" : "50 shift", // XK_M
|
||||
"78" : "49 shift", // XK_N
|
||||
"79" : "24 shift", // XK_O
|
||||
"80" : "25 shift", // XK_P
|
||||
"81" : "16 shift", // XK_Q
|
||||
"82" : "19 shift", // XK_R
|
||||
"83" : "31 shift", // XK_S
|
||||
"84" : "20 shift", // XK_T
|
||||
"85" : "22 shift", // XK_U
|
||||
"86" : "47 shift", // XK_V
|
||||
"87" : "17 shift", // XK_W
|
||||
"88" : "45 shift", // XK_X
|
||||
"89" : "21 shift", // XK_Y
|
||||
"90" : "44 shift", // XK_Z
|
||||
"91" : "40 shift", // XK_bracketleft
|
||||
"92" : "12 altgr", // XK_backslash
|
||||
"93" : "43 shift", // XK_bracketright
|
||||
"94": "40 altgr", // ^
|
||||
"95" : "53 shift", // XK_underscore
|
||||
"96": "43 altgr", // `
|
||||
"97" : "30", // XK_a
|
||||
"98" : "48", // XK_b
|
||||
"99" : "46", // XK_c
|
||||
"100" : "32", // XK_d
|
||||
"101" : "18", // XK_e
|
||||
"102" : "33", // XK_f
|
||||
"103" : "34", // XK_g
|
||||
"104" : "35", // XK_h
|
||||
"105" : "23", // XK_i
|
||||
"106" : "36", // XK_j
|
||||
"107" : "37", // XK_k
|
||||
"108" : "38", // XK_l
|
||||
"109" : "50", // XK_m
|
||||
"110" : "49", // XK_n
|
||||
"111" : "24", // XK_o
|
||||
"112" : "25", // XK_p
|
||||
"113" : "16", // XK_q
|
||||
"114" : "19", // XK_r
|
||||
"115" : "31", // XK_s
|
||||
"116" : "20", // XK_t
|
||||
"117" : "22", // XK_u
|
||||
"118" : "47", // XK_v
|
||||
"119" : "17", // XK_w
|
||||
"120" : "45", // XK_x
|
||||
"121" : "21", // XK_y
|
||||
"122" : "44", // XK_z
|
||||
"123" : "40", // XK_braceleft
|
||||
"124" : "41", // XK_bar
|
||||
"125" : "43", // XK_braceright
|
||||
"126" : "27 altgr", // XK_asciitilde
|
||||
"161" : "13 shift", // XK_exclamdown
|
||||
"168" : "26 shift", // ¨
|
||||
"171" : "44 altgr", // XK_guillemotleft
|
||||
"172" : "41 altgr", // XK_notsign
|
||||
"176" : "41 shift", // XK_degree
|
||||
"180" : "26", // ´
|
||||
"186" : "41", // XK_masculine
|
||||
"191" : "13", // XK_questiondown
|
||||
"193" : "30 acute shift2", // Á
|
||||
"196" : "30 shift1 acute shift2", // Ä
|
||||
"201" : "18 acute shift2", // É
|
||||
"203" : "18 shift1 acute shift2", // Ë
|
||||
"205" : "23 acute shift2", // Í
|
||||
"207" : "23 shift1 acute shift2", // Ï
|
||||
"209" : "39 shift", // XK_Ntilde
|
||||
"211" : "24 acute shift2", // Ó
|
||||
"214" : "24 shift1 acute shift2", // Ö
|
||||
"218" : "22 acute shift2", // Ú
|
||||
"220" : "22 shift1 acute shift2", // Ü
|
||||
"225" : "30 acute", // á
|
||||
"228" : "30 shift1 acute", // ä
|
||||
"233" : "18 acute", // é
|
||||
"235" : "18 shift1 acute", // ë
|
||||
"237" : "23 acute", // í
|
||||
"239" : "23 shift1 acute", // ï
|
||||
"241" : "39", // XK_ntilde
|
||||
"243" : "24 acute", // ó
|
||||
"246" : "24 shift1 acute", // ö
|
||||
"250" : "22 acute", // ú
|
||||
"252" : "22 shift1 acute", // ü
|
||||
}
|
||||
|
|
@ -19,11 +19,8 @@
|
|||
under the License.
|
||||
|
||||
-->
|
||||
<ruleset name="Maven Ruleset"
|
||||
xmlns="http://pmd.sf.net/ruleset/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
|
||||
<ruleset name="CloudStack PMD Ruleset"
|
||||
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0">
|
||||
|
||||
<description>
|
||||
Ruleset that brings all the rulesets we want from the pmd jar, because
|
||||
|
|
@ -31,16 +28,16 @@
|
|||
to add our own future rulesets, if any.
|
||||
</description>
|
||||
|
||||
<rule ref="rulesets/java/basic.xml"/>
|
||||
<rule ref="rulesets/java/braces.xml"/>
|
||||
<rule ref="rulesets/java/clone.xml"/>
|
||||
<rule ref="rulesets/java/codesize.xml"/>
|
||||
<rule ref="rulesets/java/comments.xml">
|
||||
<rule ref="category/java/basic.xml"/>
|
||||
<rule ref="category/java/braces.xml"/>
|
||||
<rule ref="category/java/clone.xml"/>
|
||||
<rule ref="category/java/codesize.xml"/>
|
||||
<rule ref="category/java/comments.xml">
|
||||
<!-- We shouldn't limit the number of lines in the header of a class -->
|
||||
<exclude name="CommentSize"/>
|
||||
<exclude name="CommentRequired" />
|
||||
</rule>
|
||||
<rule ref="rulesets/java/controversial.xml">
|
||||
<rule ref="category/java/controversial.xml">
|
||||
<!-- The rule is good, but is not properly applied. It forces you to statically declare it as ConcurrentHashMap -->
|
||||
<exclude name="UseConcurrentHashMap"/>
|
||||
<exclude name="CallSuperInConstructor"/>
|
||||
|
|
@ -50,35 +47,35 @@
|
|||
<exclude name="DataflowAnomalyAnalysis" />
|
||||
<exclude name="UseObjectForClearerAPI" />
|
||||
</rule>
|
||||
<rule ref="rulesets/java/coupling.xml">
|
||||
<rule ref="category/java/coupling.xml">
|
||||
<exclude name="ExcessiveImports" />
|
||||
<exclude name="LawOfDemeter"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/design.xml">
|
||||
<rule ref="category/java/design.xml">
|
||||
<exclude name="ConstructorCallsOverridableMethod"/>
|
||||
<exclude name="AbstractClassWithoutAbstractMethod"/>
|
||||
<exclude name="AvoidSynchronizedAtMethodLevel"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/empty.xml"/>
|
||||
<rule ref="rulesets/java/finalizers.xml"/>
|
||||
<rule ref="rulesets/java/imports.xml"/>
|
||||
<rule ref="rulesets/java/j2ee.xml"/>
|
||||
<rule ref="rulesets/java/junit.xml"/>
|
||||
<rule ref="rulesets/java/logging-java.xml"/>
|
||||
<rule ref="rulesets/java/naming.xml">
|
||||
<rule ref="category/java/empty.xml"/>
|
||||
<rule ref="category/java/finalizers.xml"/>
|
||||
<rule ref="category/java/imports.xml"/>
|
||||
<rule ref="category/java/j2ee.xml"/>
|
||||
<rule ref="category/java/junit.xml"/>
|
||||
<rule ref="category/java/logging-java.xml"/>
|
||||
<rule ref="category/java/naming.xml">
|
||||
<exclude name="ShortVariable"/>
|
||||
<exclude name="AbstractNaming"/>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/naming.xml/LongVariable">
|
||||
<rule ref="category/java/naming.xml/LongVariable">
|
||||
<properties>
|
||||
<property name="minimum" value="32"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="rulesets/java/optimizations.xml"/>
|
||||
<rule ref="rulesets/java/strictexception.xml"/>
|
||||
<rule ref="rulesets/java/strings.xml"/>
|
||||
<rule ref="rulesets/java/sunsecure.xml"/>
|
||||
<rule ref="rulesets/java/typeresolution.xml"/>
|
||||
<rule ref="rulesets/java/unnecessary.xml"/>
|
||||
<rule ref="rulesets/java/unusedcode.xml"/>
|
||||
<rule ref="category/java/optimizations.xml"/>
|
||||
<rule ref="category/java/strictexception.xml"/>
|
||||
<rule ref="category/java/strings.xml"/>
|
||||
<rule ref="category/java/sunsecure.xml"/>
|
||||
<rule ref="category/java/typeresolution.xml"/>
|
||||
<rule ref="category/java/unnecessary.xml"/>
|
||||
<rule ref="category/java/unusedcode.xml"/>
|
||||
</ruleset>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,8 @@
|
|||
"uk": "label.uk.keyboard",
|
||||
"fr": "label.french.azerty.keyboard",
|
||||
"jp": "label.japanese.keyboard",
|
||||
"sc": "label.simplified.chinese.keyboard"
|
||||
"sc": "label.simplified.chinese.keyboard",
|
||||
"es-latam": "Spanish Latin American Keyboard"
|
||||
},
|
||||
"userCard": {
|
||||
"enabled": true,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
"error.release.dedicate.pod": "Failed to release dedicated Pod.",
|
||||
"error.release.dedicate.zone": "Failed to release dedicated Zone.",
|
||||
"error.unable.to.add.setting.extraconfig": "It is not allowed to add setting for extraconfig. Please update VirtualMachine with extraconfig parameter.",
|
||||
"error.unable.to.add.setting": "Unable to add or edit setting",
|
||||
"error.unable.to.proceed": "Unable to proceed. Please contact your administrator.",
|
||||
"firewall.close": "Firewall",
|
||||
"icmp.code.desc": "Please specify -1 if you want to allow all ICMP codes (except NSX zones).",
|
||||
|
|
@ -1023,6 +1024,7 @@
|
|||
"label.endpoint": "Endpoint",
|
||||
"label.endport": "End port",
|
||||
"label.enter.account.name": "Enter the account name",
|
||||
"label.enter.domain.name": "Enter the domain name",
|
||||
"label.enter.code": "Enter 2FA code to verify",
|
||||
"label.enter.static.pin": "Enter static PIN to verify",
|
||||
"label.enter.token": "Enter token",
|
||||
|
|
@ -3299,6 +3301,9 @@
|
|||
"message.delete.account.processing": "Deleting account",
|
||||
"message.delete.account.success": "Successfully deleted account",
|
||||
"message.delete.account.warning": "Deleting this account will delete all of the instances, volumes and snapshots associated with the account.",
|
||||
"message.delete.domain.confirm": "Please confirm that you want to delete this domain by entering the name of the domain below.",
|
||||
"message.delete.domain.warning": "All associated accounts, users, VMs, and sub-domains will be permanently deleted. This action cannot be undone.",
|
||||
"message.delete.domain.failed": "Delete domain failed",
|
||||
"message.delete.acl.processing": "Removing ACL rule...",
|
||||
"message.delete.acl.rule": "Remove ACL rule",
|
||||
"message.delete.acl.rule.failed": "Failed to remove ACL rule.",
|
||||
|
|
@ -3432,6 +3437,7 @@
|
|||
"message.error.delete.tungsten.tag": "Removing Tag failed",
|
||||
"message.error.description": "Please enter description.",
|
||||
"message.error.discovering.feature": "Exception caught while discovering features.",
|
||||
"message.error.setting.deployasistemplate": "Settings are read directly from the template",
|
||||
"message.error.setup.2fa": "2FA setup failed while verifying the code, please retry.",
|
||||
"message.error.verifying.2fa": "Unable to verify 2FA, please retry.",
|
||||
"message.error.display.text": "Please enter display text.",
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@
|
|||
<tooltip-button
|
||||
:tooltip="$t('label.edit')"
|
||||
icon="edit-outlined"
|
||||
:disabled="deployasistemplate === true || item.name.startsWith('extraconfig')"
|
||||
:disabled="item.name.startsWith('extraconfig')"
|
||||
v-if="!item.edit"
|
||||
@onClick="showEditDetail(index)" />
|
||||
</div>
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
>
|
||||
<tooltip-button
|
||||
:tooltip="$t('label.delete')"
|
||||
:disabled="deployasistemplate === true || item.name.startsWith('extraconfig')"
|
||||
:disabled="item.name.startsWith('extraconfig')"
|
||||
type="primary"
|
||||
:danger="true"
|
||||
icon="delete-outlined" />
|
||||
|
|
@ -213,11 +213,16 @@ export default {
|
|||
this.detailOptions = json.listdetailoptionsresponse.detailoptions.details
|
||||
})
|
||||
this.disableSettings = (this.$route.meta.name === 'vm' && resource.state !== 'Stopped')
|
||||
getAPI('listTemplates', { templatefilter: 'all', id: resource.templateid }).then(json => {
|
||||
this.deployasistemplate = json.listtemplatesresponse.template[0].deployasis
|
||||
})
|
||||
if (this.$route.meta.name === 'vm') {
|
||||
getAPI('listTemplates', { templatefilter: 'all', id: resource.templateid }).then(json => {
|
||||
this.deployasistemplate = json.listtemplatesresponse.template[0].deployasis
|
||||
})
|
||||
}
|
||||
},
|
||||
allowEditOfDetail (name) {
|
||||
if (this.deployasistemplate) {
|
||||
return this.resource.alloweddetails && this.resource.alloweddetails.split(',').map(item => item.trim()).includes(name)
|
||||
}
|
||||
if (this.resource.readonlydetails) {
|
||||
if (this.resource.readonlydetails.split(',').map(item => item.trim()).includes(name)) {
|
||||
return false
|
||||
|
|
@ -320,7 +325,11 @@ export default {
|
|||
return
|
||||
}
|
||||
if (!this.allowEditOfDetail(this.newKey)) {
|
||||
this.error = this.$t('error.unable.to.proceed')
|
||||
if (this.deployasistemplate) {
|
||||
this.error = this.$t('error.unable.to.add.setting') + ' : ' + this.newKey + '. ' + this.$t('message.error.setting.deployasistemplate')
|
||||
} else {
|
||||
this.error = this.$t('error.unable.to.add.setting') + ' : ' + this.newKey
|
||||
}
|
||||
return
|
||||
}
|
||||
this.error = false
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
// 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.
|
||||
<template>
|
||||
<a-modal
|
||||
:visible="true"
|
||||
:title="$t('label.action.delete.domain') + ': ' + domain.name"
|
||||
:okText="$t('label.delete.domain')"
|
||||
okType="danger"
|
||||
:confirmLoading="loading"
|
||||
:ok-button-props="{ disabled: !canDelete }"
|
||||
@cancel="emitClose"
|
||||
@ok="emitConfirm">
|
||||
|
||||
<a-alert
|
||||
type="warning"
|
||||
show-icon
|
||||
style="margin-bottom: 16px">
|
||||
<template #message>
|
||||
<div v-html="$t('message.delete.domain.warning')"></div>
|
||||
</template>
|
||||
</a-alert>
|
||||
|
||||
<a-spin v-if="loading" />
|
||||
|
||||
<a-table
|
||||
v-else
|
||||
size="small"
|
||||
:columns="columns"
|
||||
:dataSource="accountVmSummary"
|
||||
:pagination="false"
|
||||
rowKey="account" />
|
||||
|
||||
<div style="margin-top: 16px">
|
||||
<a-alert style="margin-bottom: 10px">
|
||||
<template #message>
|
||||
<div v-html="$t('message.delete.domain.confirm')"></div>
|
||||
</template>
|
||||
</a-alert>
|
||||
<a-input
|
||||
v-model:value="confirmText"
|
||||
:placeholder="$t('label.enter.domain.name')" />
|
||||
</div>
|
||||
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api } from '@/api'
|
||||
|
||||
export default {
|
||||
name: 'DomainDeleteConfirm',
|
||||
props: {
|
||||
domain: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
confirmText: '',
|
||||
accountVmSummary: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
canDelete () {
|
||||
return this.confirmText.trim() === this.domain.name.trim()
|
||||
},
|
||||
columns () {
|
||||
return [
|
||||
{ title: this.$t('label.account'), dataIndex: 'account' },
|
||||
{ title: this.$t('label.total') + ' VMs', dataIndex: 'total' },
|
||||
{ title: this.$t('label.running') + ' VMs', dataIndex: 'running' },
|
||||
{ title: this.$t('label.stopped') + ' VMs', dataIndex: 'stopped' }
|
||||
]
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.fetchDomainImpact()
|
||||
},
|
||||
methods: {
|
||||
emitClose () {
|
||||
this.$emit('close')
|
||||
},
|
||||
emitConfirm () {
|
||||
if (this.canDelete) {
|
||||
this.$emit('confirm')
|
||||
}
|
||||
},
|
||||
async fetchDomainImpact () {
|
||||
this.loading = true
|
||||
try {
|
||||
const accResp = await api('listAccounts', {
|
||||
domainid: this.domain.id,
|
||||
listall: true
|
||||
})
|
||||
|
||||
const accounts =
|
||||
accResp.listaccountsresponse &&
|
||||
accResp.listaccountsresponse.account
|
||||
? accResp.listaccountsresponse.account
|
||||
: []
|
||||
|
||||
const vmResp = await api('listVirtualMachines', {
|
||||
domainid: this.domain.id,
|
||||
listall: true
|
||||
})
|
||||
|
||||
const vms =
|
||||
vmResp.listvirtualmachinesresponse &&
|
||||
vmResp.listvirtualmachinesresponse.virtualmachine
|
||||
? vmResp.listvirtualmachinesresponse.virtualmachine
|
||||
: []
|
||||
|
||||
this.accountVmSummary = accounts.map(account => {
|
||||
const accountVms = vms.filter(vm => vm.account === account.name)
|
||||
const running = accountVms.filter(vm => vm.state === 'Running').length
|
||||
const stopped = accountVms.length - running
|
||||
|
||||
return {
|
||||
account: account.name,
|
||||
total: accountVms.length,
|
||||
running,
|
||||
stopped
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: e.response?.headers['x-description'] || this.$t('message.request.failed')
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
|
|
@ -74,6 +74,11 @@
|
|||
:resource="resource"
|
||||
:action="action"/>
|
||||
</div>
|
||||
<domain-delete-confirm
|
||||
v-if="showDeleteConfirm"
|
||||
:domain="deleteDomainResource"
|
||||
@close="showDeleteConfirm = false"
|
||||
@confirm="confirmDeleteDomain" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -87,6 +92,7 @@ import ActionButton from '@/components/view/ActionButton'
|
|||
import TreeView from '@/components/view/TreeView'
|
||||
import DomainActionForm from '@/views/iam/DomainActionForm'
|
||||
import ResourceView from '@/components/view/ResourceView'
|
||||
import DomainDeleteConfirm from '@/components/view/DomainDeleteConfirm'
|
||||
import eventBus from '@/config/eventBus'
|
||||
|
||||
export default {
|
||||
|
|
@ -96,7 +102,8 @@ export default {
|
|||
ActionButton,
|
||||
TreeView,
|
||||
DomainActionForm,
|
||||
ResourceView
|
||||
ResourceView,
|
||||
DomainDeleteConfirm
|
||||
},
|
||||
mixins: [mixinDevice],
|
||||
data () {
|
||||
|
|
@ -111,7 +118,9 @@ export default {
|
|||
action: {},
|
||||
dataView: false,
|
||||
domainStore: {},
|
||||
treeDeletedKey: null
|
||||
treeDeletedKey: null,
|
||||
showDeleteConfirm: false,
|
||||
deleteDomainResource: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -205,7 +214,12 @@ export default {
|
|||
})
|
||||
},
|
||||
execAction (action) {
|
||||
this.treeDeletedKey = action.api === 'deleteDomain' ? this.resource.key : null
|
||||
if (action.api === 'deleteDomain') {
|
||||
this.deleteDomainResource = this.resource
|
||||
this.showDeleteConfirm = true
|
||||
return
|
||||
}
|
||||
this.treeDeletedKey = null
|
||||
this.actionData = []
|
||||
this.action = action
|
||||
this.action.params = store.getters.apis[this.action.api].params
|
||||
|
|
@ -316,6 +330,42 @@ export default {
|
|||
closeAction () {
|
||||
this.showAction = false
|
||||
},
|
||||
confirmDeleteDomain () {
|
||||
const domain = this.deleteDomainResource
|
||||
const params = { id: domain.id, cleanup: true }
|
||||
|
||||
api('deleteDomain', params).then(json => {
|
||||
const jobId = json.deletedomainresponse.jobid
|
||||
|
||||
this.$pollJob({
|
||||
jobId,
|
||||
title: this.$t('label.action.delete.domain'),
|
||||
description: domain.name,
|
||||
loadingMessage: `${this.$t('label.action.delete.domain')} ${domain.name}`,
|
||||
successMessage: `${this.$t('label.action.delete.domain')} ${domain.name}`,
|
||||
catchMessage: this.$t('error.fetching.async.job.result'),
|
||||
successMethod: () => {
|
||||
this.$router.replace({ path: '/domain' })
|
||||
this.resource = {}
|
||||
this.treeSelected = {}
|
||||
this.treeDeletedKey = null
|
||||
this.treeViewKey += 1
|
||||
this.$nextTick(() => {
|
||||
this.fetchData()
|
||||
})
|
||||
}
|
||||
})
|
||||
}).catch(error => {
|
||||
this.$notification.error({
|
||||
message: this.$t('message.request.failed'),
|
||||
description: error.response?.headers['x-description'] || this.$t('message.request.failed')
|
||||
})
|
||||
}).finally(() => {
|
||||
this.showDeleteConfirm = false
|
||||
this.deleteDomainResource = null
|
||||
this.treeDeletedKey = null
|
||||
})
|
||||
},
|
||||
forceRerender () {
|
||||
this.treeViewKey += 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -261,6 +261,8 @@ export default {
|
|||
userdatapolicylist: {},
|
||||
architectureTypes: {},
|
||||
originalOstypeid: null
|
||||
detailsFields: [],
|
||||
details: {}
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
|
|
@ -315,17 +317,10 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
const resourceDetailsFields = []
|
||||
if (this.resource.hypervisor === 'KVM') {
|
||||
resourceDetailsFields.push('rootDiskController')
|
||||
this.detailsFields.push('rootDiskController')
|
||||
} else if (this.resource.hypervisor === 'VMware' && !this.resource.deployasis) {
|
||||
resourceDetailsFields.push(...['rootDiskController', 'nicAdapter', 'keyboard'])
|
||||
}
|
||||
for (var detailsField of resourceDetailsFields) {
|
||||
var detailValue = this.resource?.details?.[detailsField] || null
|
||||
if (detailValue) {
|
||||
this.form[detailValue] = fieldValue
|
||||
}
|
||||
this.detailsFields.push(...['rootDiskController', 'nicAdapter', 'keyboard'])
|
||||
}
|
||||
},
|
||||
fetchData () {
|
||||
|
|
@ -336,6 +331,7 @@ export default {
|
|||
this.fetchKeyboardTypes()
|
||||
this.fetchUserdata()
|
||||
this.fetchUserdataPolicy()
|
||||
this.fetchDetails()
|
||||
},
|
||||
isValidValueForKey (obj, key) {
|
||||
if (this.emptyAllowedFields.includes(key) && obj[key] === '') {
|
||||
|
|
@ -380,6 +376,10 @@ export default {
|
|||
id: 'virtio',
|
||||
description: 'virtio'
|
||||
})
|
||||
controller.push({
|
||||
id: 'virtio-blk',
|
||||
description: 'virtio-blk'
|
||||
})
|
||||
} else if (hyperVisor === 'VMware') {
|
||||
controller.push({
|
||||
id: '',
|
||||
|
|
@ -506,6 +506,25 @@ export default {
|
|||
this.userdata.loading = false
|
||||
})
|
||||
},
|
||||
fetchDetails () {
|
||||
const params = {}
|
||||
params.id = this.resource.id
|
||||
params.templatefilter = 'all'
|
||||
|
||||
api('listTemplates', params).then(response => {
|
||||
if (response?.listtemplatesresponse?.template?.length > 0) {
|
||||
this.details = response.listtemplatesresponse.template[0].details
|
||||
if (this.details) {
|
||||
for (var detailsField of this.detailsFields) {
|
||||
var detailValue = this.details?.[detailsField] || null
|
||||
if (detailValue) {
|
||||
this.form[detailsField] = detailValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
if (this.loading) return
|
||||
|
|
@ -515,10 +534,14 @@ export default {
|
|||
const params = {
|
||||
id: this.resource.id
|
||||
}
|
||||
const detailsField = ['rootDiskController', 'nicAdapter', 'keyboard']
|
||||
if (this.details) {
|
||||
Object.keys(this.details).forEach((detail, index) => {
|
||||
params['details[0].' + detail] = this.details[detail]
|
||||
})
|
||||
}
|
||||
for (const key in values) {
|
||||
if (!this.isValidValueForKey(values, key)) continue
|
||||
if (detailsField.includes(key)) {
|
||||
if (this.detailsFields.includes(key)) {
|
||||
params['details[0].' + key] = values[key]
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue