mirror of https://github.com/apache/cloudstack.git
Merge branch '4.20' into 4.22
This commit is contained in:
commit
cd6a8f61ca
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -460,7 +460,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);
|
||||
|
|
@ -482,7 +482,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
|
|
@ -63,20 +63,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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -471,7 +477,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
|
||||
|
|
@ -482,7 +489,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()));
|
||||
}
|
||||
}
|
||||
|
|
@ -935,7 +942,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);
|
||||
}
|
||||
});
|
||||
|
|
@ -947,19 +954,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,6 +51,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;
|
||||
|
|
@ -67,7 +68,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;
|
||||
|
|
@ -79,13 +79,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;
|
||||
|
||||
|
|
@ -225,13 +230,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);
|
||||
}
|
||||
|
|
@ -348,12 +353,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
|
||||
|
|
@ -368,18 +373,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
|
||||
|
|
@ -396,16 +401,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"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -1017,6 +1017,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",
|
||||
|
|
@ -3270,6 +3271,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.",
|
||||
|
|
|
|||
|
|
@ -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