Merge branch '4.16' into main

This commit is contained in:
Suresh Kumar Anaparti 2022-02-08 19:01:34 +05:30
commit 208ae84dd7
No known key found for this signature in database
GPG Key ID: D7CEAE3A9E71D0AA
32 changed files with 583 additions and 151 deletions

View File

@ -154,5 +154,7 @@ public interface VolumeApiService {
Volume recoverVolume(long volumeId);
boolean validateVolumeSizeInBytes(long size);
Volume changeDiskOfferingForVolume(ChangeOfferingForVolumeCmd cmd) throws ResourceAllocationException;
}

View File

@ -355,7 +355,7 @@ public abstract class BaseCmd {
if (roleIsAllowed) {
validFields.add(field);
} else {
s_logger.debug("Ignoring paremeter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in");
s_logger.debug("Ignoring parameter " + parameterAnnotation.name() + " as the caller is not authorized to pass it in");
}
}

View File

@ -75,6 +75,13 @@ public interface VolumeOrchestrationService {
true
);
ConfigKey<Long> MaxVolumeSize = new ConfigKey<Long>("Storage",
Long.class,
"storage.max.volume.size",
"2000",
"The maximum size for a volume (in GB).",
true);
VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType)
throws ConcurrentOperationException, StorageUnavailableException;

View File

@ -221,7 +221,7 @@ public class VMEntityManagerImpl implements VMEntityManager {
// call retry it.
return UUID.randomUUID().toString();
} else {
throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId(),
throw new InsufficientServerCapacityException("No destination found for a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId(),
areAffinityGroupsAssociated(vmProfile));
}
}

View File

@ -18,10 +18,12 @@
*/
package org.apache.cloudstack.engine.orchestration;
import static com.cloud.storage.resource.StorageProcessor.REQUEST_TEMPLATE_RELOAD;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -35,13 +37,6 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd;
import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin;
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
@ -83,12 +78,13 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.allocator.PodAllocator;
@ -150,21 +146,24 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmCloneSettingVO;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfileImpl;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.VmWorkAttachVolume;
import com.cloud.vm.VmWorkMigrateVolume;
import com.cloud.vm.VmWorkSerializer;
import com.cloud.vm.VmWorkTakeVolumeSnapshot;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmCloneSettingDao;
import com.cloud.vm.dao.UserVmDao;
import static com.cloud.storage.resource.StorageProcessor.REQUEST_TEMPLATE_RELOAD;
import java.util.Date;
import com.cloud.vm.dao.UserVmDetailsDao;
public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrationService, Configurable {
@ -1779,8 +1778,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
return true;
}
public static final ConfigKey<Long> MaxVolumeSize = new ConfigKey<Long>(Long.class, "storage.max.volume.size", "Storage", "2000", "The maximum size for a volume (in GB).", true);
public static final ConfigKey<Boolean> RecreatableSystemVmEnabled = new ConfigKey<Boolean>(Boolean.class, "recreate.systemvm.enabled", "Advanced", "false",
"If true, will recreate system vm root disk whenever starting system vm", true);

View File

@ -29,9 +29,9 @@
</parent>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${cs.log4j.version}</version>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
<version>${cs.reload4j.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -139,16 +139,15 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
}
s_logger.info("Getting pending quota records for account=" + account.getAccountName());
for (UsageVO usageRecord : usageRecords.first()) {
BigDecimal aggregationRatio = new BigDecimal(_aggregationDuration).divide(s_minutesInMonth, 8, RoundingMode.HALF_EVEN);
switch (usageRecord.getUsageType()) {
case QuotaTypes.RUNNING_VM:
List<QuotaUsageVO> lq = updateQuotaRunningVMUsage(usageRecord, aggregationRatio);
List<QuotaUsageVO> lq = updateQuotaRunningVMUsage(usageRecord);
if (!lq.isEmpty()) {
quotaListForAccount.addAll(lq);
}
break;
case QuotaTypes.ALLOCATED_VM:
QuotaUsageVO qu = updateQuotaAllocatedVMUsage(usageRecord, aggregationRatio);
QuotaUsageVO qu = updateQuotaAllocatedVMUsage(usageRecord);
if (qu != null) {
quotaListForAccount.add(qu);
}
@ -159,7 +158,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
case QuotaTypes.VOLUME:
case QuotaTypes.VM_SNAPSHOT:
case QuotaTypes.BACKUP:
qu = updateQuotaDiskUsage(usageRecord, aggregationRatio, usageRecord.getUsageType());
qu = updateQuotaDiskUsage(usageRecord, usageRecord.getUsageType());
if (qu != null) {
quotaListForAccount.add(qu);
}
@ -170,7 +169,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
case QuotaTypes.NETWORK_OFFERING:
case QuotaTypes.SECURITY_GROUP:
case QuotaTypes.VPN_USERS:
qu = updateQuotaRaw(usageRecord, aggregationRatio, usageRecord.getUsageType());
qu = updateQuotaRaw(usageRecord, usageRecord.getUsageType());
if (qu != null) {
quotaListForAccount.add(qu);
}
@ -333,14 +332,14 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
return true;
}
public QuotaUsageVO updateQuotaDiskUsage(UsageVO usageRecord, final BigDecimal aggregationRatio, final int quotaType) {
public QuotaUsageVO updateQuotaDiskUsage(UsageVO usageRecord, final int quotaType) {
QuotaUsageVO quota_usage = null;
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(quotaType, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
BigDecimal quotaUsgage;
BigDecimal onehourcostpergb;
BigDecimal noofgbinuse;
onehourcostpergb = tariff.getCurrencyValue().multiply(aggregationRatio);
onehourcostpergb = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
noofgbinuse = new BigDecimal(usageRecord.getSize()).divide(s_gb, 8, RoundingMode.HALF_EVEN);
quotaUsgage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcostpergb).multiply(noofgbinuse);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), usageRecord.getUsageType(),
@ -352,7 +351,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
return quota_usage;
}
public List<QuotaUsageVO> updateQuotaRunningVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
public List<QuotaUsageVO> updateQuotaRunningVMUsage(UsageVO usageRecord) {
List<QuotaUsageVO> quotalist = new ArrayList<QuotaUsageVO>();
QuotaUsageVO quota_usage;
BigDecimal cpuquotausgage, speedquotausage, memoryquotausage, vmusage;
@ -368,7 +367,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_NUMBER, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getCpu() != null) {
BigDecimal cpu = new BigDecimal(serviceoffering.getCpu());
onehourcostpercpu = tariff.getCurrencyValue().multiply(aggregationRatio);
onehourcostpercpu = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
cpuquotausgage = rawusage.multiply(onehourcostpercpu).multiply(cpu);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.CPU_NUMBER,
cpuquotausgage, usageRecord.getStartDate(), usageRecord.getEndDate());
@ -377,8 +376,8 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
}
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.CPU_CLOCK_RATE, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getSpeed() != null) {
BigDecimal speed = new BigDecimal(serviceoffering.getSpeed() / 100.00);
onehourcostper100mhz = tariff.getCurrencyValue().multiply(aggregationRatio);
BigDecimal speed = new BigDecimal(serviceoffering.getSpeed()*serviceoffering.getCpu() / 100.00);
onehourcostper100mhz = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
speedquotausage = rawusage.multiply(onehourcostper100mhz).multiply(speed);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.CPU_CLOCK_RATE,
speedquotausage, usageRecord.getStartDate(), usageRecord.getEndDate());
@ -388,7 +387,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.MEMORY, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0 && serviceoffering.getRamSize() != null) {
BigDecimal memory = new BigDecimal(serviceoffering.getRamSize());
onehourcostper1mb = tariff.getCurrencyValue().multiply(aggregationRatio);
onehourcostper1mb = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
memoryquotausage = rawusage.multiply(onehourcostper1mb).multiply(memory);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.MEMORY, memoryquotausage,
usageRecord.getStartDate(), usageRecord.getEndDate());
@ -397,7 +396,7 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
}
tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.RUNNING_VM, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
onehourcostforvmusage = tariff.getCurrencyValue().multiply(aggregationRatio);
onehourcostforvmusage = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
vmusage = rawusage.multiply(onehourcostforvmusage);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.RUNNING_VM, vmusage,
usageRecord.getStartDate(), usageRecord.getEndDate());
@ -410,13 +409,13 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
return quotalist;
}
public QuotaUsageVO updateQuotaAllocatedVMUsage(UsageVO usageRecord, final BigDecimal aggregationRatio) {
public QuotaUsageVO updateQuotaAllocatedVMUsage(UsageVO usageRecord) {
QuotaUsageVO quota_usage = null;
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(QuotaTypes.ALLOCATED_VM, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
BigDecimal vmusage;
BigDecimal onehourcostforvmusage;
onehourcostforvmusage = tariff.getCurrencyValue().multiply(aggregationRatio);
onehourcostforvmusage = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
vmusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcostforvmusage);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), QuotaTypes.ALLOCATED_VM, vmusage,
usageRecord.getStartDate(), usageRecord.getEndDate());
@ -428,13 +427,13 @@ public class QuotaManagerImpl extends ManagerBase implements QuotaManager {
return quota_usage;
}
public QuotaUsageVO updateQuotaRaw(UsageVO usageRecord, final BigDecimal aggregationRatio, final int ruleType) {
public QuotaUsageVO updateQuotaRaw(UsageVO usageRecord, final int ruleType) {
QuotaUsageVO quota_usage = null;
QuotaTariffVO tariff = _quotaTariffDao.findTariffPlanByUsageType(ruleType, usageRecord.getEndDate());
if (tariff != null && tariff.getCurrencyValue().compareTo(BigDecimal.ZERO) != 0) {
BigDecimal ruleusage;
BigDecimal onehourcost;
onehourcost = tariff.getCurrencyValue().multiply(aggregationRatio);
onehourcost = tariff.getCurrencyValue().divide(s_hoursInMonth, 8, RoundingMode.HALF_DOWN);
ruleusage = new BigDecimal(usageRecord.getRawUsage()).multiply(onehourcost);
quota_usage = new QuotaUsageVO(usageRecord.getId(), usageRecord.getZoneId(), usageRecord.getAccountId(), usageRecord.getDomainId(), ruleType, ruleusage,
usageRecord.getStartDate(), usageRecord.getEndDate());

View File

@ -151,7 +151,7 @@ public class QuotaManagerImplTest extends TestCase {
QuotaUsageVO quotaUsageVO = new QuotaUsageVO();
quotaUsageVO.setAccountId(2L);
Mockito.doReturn(quotaUsageVO).when(quotaManager).updateQuotaAllocatedVMUsage(Mockito.eq(usageVO), Mockito.any(BigDecimal.class));
Mockito.doReturn(quotaUsageVO).when(quotaManager).updateQuotaAllocatedVMUsage(Mockito.eq(usageVO));
assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, new Pair<List<? extends UsageVO>, Integer>(null, 0)).size() == 0);
assertTrue(quotaManager.aggregatePendingQuotaRecordsForAccount(accountVO, usageRecords).size() == 1);
@ -172,11 +172,11 @@ public class QuotaManagerImplTest extends TestCase {
QuotaUsageVO qu = quotaManager.updateQuotaNetwork(usageVO, UsageTypes.NETWORK_BYTES_SENT);
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
qu = quotaManager.updateQuotaAllocatedVMUsage(usageVO, new BigDecimal(0.5));
qu = quotaManager.updateQuotaAllocatedVMUsage(usageVO);
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
qu = quotaManager.updateQuotaDiskUsage(usageVO, new BigDecimal(0.5), UsageTypes.VOLUME);
qu = quotaManager.updateQuotaDiskUsage(usageVO, UsageTypes.VOLUME);
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
qu = quotaManager.updateQuotaRaw(usageVO, new BigDecimal(0.5), UsageTypes.VPN_USERS);
qu = quotaManager.updateQuotaRaw(usageVO, UsageTypes.VPN_USERS);
assertTrue(qu.getQuotaUsed().compareTo(BigDecimal.ZERO) > 0);
Mockito.verify(quotaUsageDao, Mockito.times(4)).persistQuotaUsage(Mockito.any(QuotaUsageVO.class));

View File

@ -305,6 +305,9 @@ public class ExplicitDedicationProcessor extends AffinityProcessorBase implement
for (HostPodVO pod : podList) {
DedicatedResourceVO dPod = _dedicatedDao.findByPodId(pod.getId());
if (dPod != null && !dedicatedResources.contains(dPod)) {
if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("Avoiding POD %s [%s] because it is not dedicated.", pod.getName(), pod.getUuid()));
}
avoidList.addPod(pod.getId());
} else {
includeList.addPod(pod.getId());
@ -343,6 +346,9 @@ public class ExplicitDedicationProcessor extends AffinityProcessorBase implement
for (HostPodVO pod : pods) {
if (podsInIncludeList != null && !podsInIncludeList.contains(pod.getId())) {
if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("Avoiding POD %s [%s], as it is not in include list.", pod.getName(), pod.getUuid()));
}
avoidList.addPod(pod.getId());
}
}

View File

@ -33,8 +33,8 @@
<artifactId>org.apache.servicemix.bundles.snmp4j</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -29,8 +29,8 @@
</parent>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -107,7 +107,7 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy
}
}
// Hosts running vms of other accounts created by ab implicit planner in strict mode should always be avoided.
// Hosts running vms of other accounts created by an implicit planner in strict mode should always be avoided.
avoid.addHostList(hostRunningStrictImplicitVmsOfOtherAccounts);
if (!hostRunningVmsOfAccount.isEmpty() && (hostsToAvoid == null || !hostsToAvoid.containsAll(hostRunningVmsOfAccount))) {

View File

@ -44,8 +44,8 @@
<version>${cs.commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -86,9 +86,9 @@
<version>${cs.guava.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${cs.log4j.version}</version>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
<version>${cs.reload4j.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>

View File

@ -112,6 +112,12 @@
<groupId>net.juniper.contrail</groupId>
<artifactId>juniper-contrail-api</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>

View File

@ -175,6 +175,10 @@
<version>${ads.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<!--
shared-ldap-schema module needs to be excluded to avoid multiple schema resources on the classpath
-->

20
pom.xml
View File

@ -76,14 +76,14 @@
<cs.clover-maven-plugin.version>4.4.1</cs.clover-maven-plugin.version>
<!-- Logging versions -->
<cs.log4j.version>1.2.17</cs.log4j.version>
<cs.reload4j.version>1.2.18.4</cs.reload4j.version>
<cs.log4j.extras.version>1.2.17</cs.log4j.extras.version>
<cs.logging.version>1.1.1</cs.logging.version>
<!-- Apache Commons versions -->
<cs.codec.version>1.15</cs.codec.version>
<cs.commons-collections.version>4.4</cs.commons-collections.version>
<cs.commons-compress.version>1.20</cs.commons-compress.version>
<cs.commons-compress.version>1.21</cs.commons-compress.version>
<cs.commons-exec.version>1.3</cs.commons-exec.version>
<cs.commons-fileupload.version>1.4</cs.commons-fileupload.version>
<cs.commons-httpclient.version>3.1</cs.commons-httpclient.version>
@ -113,7 +113,7 @@
<cs.selenium-java-client-driver.version>1.0.1</cs.selenium-java-client-driver.version>
<cs.testng.version>7.1.0</cs.testng.version>
<cs.wiremock.version>2.27.2</cs.wiremock.version>
<cs.xercesImpl.version>2.12.0</cs.xercesImpl.version>
<cs.xercesImpl.version>2.12.2</cs.xercesImpl.version>
<!-- Dependencies versions -->
<cs.amqp-client.version>5.10.0</cs.amqp-client.version>
@ -171,7 +171,7 @@
<cs.winrm4j.version>0.5.0</cs.winrm4j.version>
<cs.xapi.version>6.2.0-3.1</cs.xapi.version>
<cs.xmlrpc.version>3.1.3</cs.xmlrpc.version>
<cs.xstream.version>1.4.15</cs.xstream.version>
<cs.xstream.version>1.4.19</cs.xstream.version>
<org.springframework.version>5.3.3</org.springframework.version>
<cs.ini.version>0.5.4</cs.ini.version>
<cs.gmaven.version>1.12.0</cs.gmaven.version>
@ -439,9 +439,9 @@
</exclusions>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${cs.log4j.version}</version>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
<version>${cs.reload4j.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
@ -618,6 +618,12 @@
<groupId>org.owasp.esapi</groupId>
<artifactId>esapi</artifactId>
<version>2.1.0.1</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Test dependency in mysql for db tests -->
<dependency>

View File

@ -16,6 +16,15 @@
// under the License.
package com.cloud.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.agent.AgentManager;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.ha.HighAvailabilityManager;
@ -29,14 +38,6 @@ import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.template.TemplateManager;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.snapshot.VMSnapshotManager;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.ConfigKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
/**
* @deprecated use the more dynamic ConfigKey
@ -144,7 +145,6 @@ public enum Config {
"60000",
"The interval (in milliseconds) when storage stats (per host) are retrieved from agents.",
null),
MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.size", "2000", "The maximum size for a volume (in GB).", null),
StorageCacheReplacementLRUTimeInterval(
"Storage",
ManagementServer.class,

View File

@ -43,7 +43,6 @@ import java.util.Vector;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.googlecode.ipv6.IPv6Address;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupService;
@ -85,6 +84,7 @@ import org.apache.cloudstack.config.ApiServiceConfiguration;
import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.config.ConfigDepot;
@ -270,6 +270,7 @@ import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Sets;
import com.googlecode.ipv6.IPv6Address;
public class ConfigurationManagerImpl extends ManagerBase implements ConfigurationManager, ConfigurationService, Configurable {
public static final Logger s_logger = Logger.getLogger(ConfigurationManagerImpl.class);
@ -421,7 +422,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Inject
protected DataCenterLinkLocalIpAddressDao _linkLocalIpAllocDao;
private int _maxVolumeSizeInGb = Integer.parseInt(Config.MaxVolumeSize.getDefaultValue());
private long _defaultPageSize = Long.parseLong(Config.DefaultPageSize.getDefaultValue());
private static final String DOMAIN_NAME_PATTERN = "^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{1,63}$";
protected Set<String> configValuesForValidation;
@ -477,9 +477,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
final String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.key());
_maxVolumeSizeInGb = NumbersUtil.parseInt(maxVolumeSizeInGbString, Integer.parseInt(Config.MaxVolumeSize.getDefaultValue()));
final String defaultPageSizeString = _configDao.getValue(Config.DefaultPageSize.key());
_defaultPageSize = NumbersUtil.parseLong(defaultPageSizeString, Long.parseLong(Config.DefaultPageSize.getDefaultValue()));
@ -3048,6 +3045,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (rootDiskSizeInGiB != null && rootDiskSizeInGiB <= 0L) {
throw new InvalidParameterValueException(String.format("The Root disk size is of %s GB but it must be greater than 0.", rootDiskSizeInGiB));
} else if (rootDiskSizeInGiB != null) {
long maxVolumeSizeInGb = VolumeOrchestrationService.MaxVolumeSize.value();
if (rootDiskSizeInGiB > maxVolumeSizeInGb) {
throw new InvalidParameterValueException(String.format("The maximum size for a disk is %d GB.", maxVolumeSizeInGb));
}
long rootDiskSizeInBytes = rootDiskSizeInGiB * GiB_TO_BYTES;
diskOffering.setDiskSize(rootDiskSizeInBytes);
}
@ -3313,10 +3314,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
Long iopsWriteRate, Long iopsWriteRateMax, Long iopsWriteRateMaxLength,
final Integer hypervisorSnapshotReserve, String cacheMode, final Map<String, String> details, final Long storagePolicyID, final boolean diskSizeStrictness) {
long diskSize = 0;// special case for custom disk offerings
long maxVolumeSizeInGb = VolumeOrchestrationService.MaxVolumeSize.value();
if (numGibibytes != null && numGibibytes <= 0) {
throw new InvalidParameterValueException("Please specify a disk size of at least 1 Gb.");
} else if (numGibibytes != null && numGibibytes > _maxVolumeSizeInGb) {
throw new InvalidParameterValueException("The maximum size for a disk is " + _maxVolumeSizeInGb + " Gb.");
throw new InvalidParameterValueException("Please specify a disk size of at least 1 GB.");
} else if (numGibibytes != null && numGibibytes > maxVolumeSizeInGb) {
throw new InvalidParameterValueException(String.format("The maximum size for a disk is %d GB.", maxVolumeSizeInGb));
}
final ProvisioningType typedProvisioningType = ProvisioningType.getProvisioningType(provisioningType);

View File

@ -752,9 +752,17 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
//Only when the type is instance VM and not explicitly dedicated.
if (vm.getType() == VirtualMachine.Type.User && !isExplicit) {
//add explicitly dedicated resources in avoidList
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding pods to avoid lists for non-explicit VM deployment: " + allPodsInDc);
}
avoids.addPodList(allPodsInDc);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding clusters to avoid lists for non-explicit VM deployment: " + allClustersInDc);
}
avoids.addClusterList(allClustersInDc);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding hosts to avoid lists for non-explicit VM deployment: " + allHostsInDc);
}
avoids.addHostList(allHostsInDc);
}
@ -833,8 +841,17 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
}
//Add in avoid list or no addition if no dedication
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding pods to avoid lists: " + allPodsInDc);
}
avoids.addPodList(allPodsInDc);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding clusters to avoid lists: " + allClustersInDc);
}
avoids.addClusterList(allClustersInDc);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Adding hosts to avoid lists: " + allHostsInDc);
}
avoids.addHostList(allHostsInDc);
}
}

View File

@ -325,7 +325,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
public static final ConfigKey<Boolean> MatchStoragePoolTagsWithDiskOffering = new ConfigKey<Boolean>("Advanced", Boolean.class, "match.storage.pool.tags.with.disk.offering", "true",
"If true, volume's disk offering can be changed only with the matched storage tags", true, ConfigKey.Scope.Zone);
private long _maxVolumeSizeInGb;
private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
private static final Set<Volume.State> STATES_VOLUME_CANNOT_BE_DESTROYED = new HashSet<>(Arrays.asList(Volume.State.Destroy, Volume.State.Expunging, Volume.State.Expunged, Volume.State.Allocated));
@ -745,9 +744,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
maxIops = diskOffering.getMaxIops();
}
if (!validateVolumeSizeRange(size)) {// convert size from mb to gb
// for validation
throw new InvalidParameterValueException("Invalid size for custom volume creation: " + size + " ,max volume size is:" + _maxVolumeSizeInGb);
if (!validateVolumeSizeInBytes(size)) {
throw new InvalidParameterValueException(String.format("Invalid size for custom volume creation: %s, max volume size is: %s GB", NumbersUtil.toReadableSize(size), VolumeOrchestrationService.MaxVolumeSize.value()));
}
}
@ -901,11 +899,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
});
}
public boolean validateVolumeSizeRange(long size) {
@Override
public boolean validateVolumeSizeInBytes(long size) {
long maxVolumeSize = VolumeOrchestrationService.MaxVolumeSize.value();
if (size < 0 || (size > 0 && size < (1024 * 1024 * 1024))) {
throw new InvalidParameterValueException("Please specify a size of at least 1 GB.");
} else if (size > (_maxVolumeSizeInGb * 1024 * 1024 * 1024)) {
throw new InvalidParameterValueException("Requested volume size is " + size + ", but the maximum size allowed is " + _maxVolumeSizeInGb + " GB.");
} else if (size > (maxVolumeSize * 1024 * 1024 * 1024)) {
throw new InvalidParameterValueException(String.format("Requested volume size is %s, but the maximum size allowed is %d GB.", NumbersUtil.toReadableSize(size), maxVolumeSize));
}
return true;
@ -1144,7 +1144,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
if (!validateVolumeSizeRange(newSize)) {
if (!validateVolumeSizeInBytes(newSize)) {
throw new InvalidParameterValueException("Requested size out of range");
}
@ -1962,7 +1962,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
if (!validateVolumeSizeRange(newSize)) {
if (!validateVolumeSizeInBytes(newSize)) {
throw new InvalidParameterValueException("Requested size out of range");
}
@ -3943,8 +3943,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
@Override
public boolean configure(String name, Map<String, Object> params) {
String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.toString());
_maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000);
supportingDefaultHV = _hypervisorCapabilitiesDao.getHypervisorsWithDefaultEntries();
return true;
}

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.vm;
import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.io.IOException;
@ -26,6 +27,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@ -50,8 +52,6 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import com.cloud.network.router.CommandSetupHelper;
import com.cloud.network.router.NetworkHelper;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -118,6 +118,7 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
@ -248,6 +249,8 @@ import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.router.CommandSetupHelper;
import com.cloud.network.router.NetworkHelper;
import com.cloud.network.router.VpcVirtualNetworkApplianceManager;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRuleVO;
@ -357,10 +360,6 @@ import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshotManager;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
import java.util.HashSet;
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH;
public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable {
private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class);
@ -3819,18 +3818,18 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
}
DiskOfferingVO rootdiskOffering = _diskOfferingDao.findById(rootDiskOfferingId);
long size = configureCustomRootDiskSize(customParameters, template, hypervisorType, rootdiskOffering);
long volumesSize = configureCustomRootDiskSize(customParameters, template, hypervisorType, rootdiskOffering);
if (!isIso && diskOfferingId != null) {
DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
size += verifyAndGetDiskSize(diskOffering, diskSize);
volumesSize += verifyAndGetDiskSize(diskOffering, diskSize);
}
if (! VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
resourceLimitCheck(owner, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize()));
}
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, (isIso || diskOfferingId == null ? 1 : 2));
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, size);
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumesSize);
// verify security group ids
if (securityGroupIdList != null) {
@ -4136,7 +4135,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
private long verifyAndGetDiskSize(DiskOfferingVO diskOffering, Long diskSize) {
long size = 0l;
if (diskOffering != null && diskOffering.isCustomized() && !diskOffering.isComputeOnly()) {
if (diskOffering == null) {
throw new InvalidParameterValueException("Specified disk offering cannot be found");
}
if (diskOffering.isCustomized() && !diskOffering.isComputeOnly()) {
if (diskSize == null) {
throw new InvalidParameterValueException("This disk offering requires a custom size specified");
}
@ -4146,9 +4148,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("VM Creation failed. Volume size: " + diskSize + "GB is out of allowed range. Max: " + customDiskOfferingMaxSize
+ " Min:" + customDiskOfferingMinSize);
}
size += diskSize * GiB_TO_BYTES;
size = diskSize * GiB_TO_BYTES;
} else {
size = diskOffering.getDiskSize();
}
size += diskOffering.getDiskSize();
_volumeService.validateVolumeSizeInBytes(size);
return size;
}
@ -4170,6 +4174,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
verifyIfHypervisorSupportsRootdiskSizeOverride(hypervisorType);
long rootDiskSizeInBytes = verifyAndGetDiskSize(rootDiskOffering, NumbersUtil.parseLong(customParameters.get(VmDetailConstants.ROOT_DISK_SIZE), -1));
if (rootDiskSizeInBytes > 0) { //if the size at DiskOffering is not zero then the Service Offering had it configured, it holds priority over the User custom size
_volumeService.validateVolumeSizeInBytes(rootDiskSizeInBytes);
long rootDiskSizeInGiB = rootDiskSizeInBytes / GiB_TO_BYTES;
customParameters.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(rootDiskSizeInGiB));
return rootDiskSizeInBytes;
@ -4180,7 +4185,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (rootDiskSize <= 0) {
throw new InvalidParameterValueException("Root disk size should be a positive number.");
}
return rootDiskSize * GiB_TO_BYTES;
rootDiskSize *= GiB_TO_BYTES;
_volumeService.validateVolumeSizeInBytes(rootDiskSize);
return rootDiskSize;
} else {
// For baremetal, size can be 0 (zero)
Long templateSize = _templateDao.findById(template.getId()).getSize();

View File

@ -33,15 +33,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.configuration.Resource;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.dao.AccountDao;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
@ -59,24 +50,34 @@ import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.powermock.core.classloader.annotations.PrepareForTest;
import com.cloud.configuration.Resource;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.NetworkModel;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.uservm.UserVm;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@ -151,6 +152,9 @@ public class UserVmManagerImplTest {
@Mock
ResourceLimitService resourceLimitMgr;
@Mock
VolumeApiService volumeApiService;
private long vmId = 1l;
private static final long GiB_TO_BYTES = 1024 * 1024 * 1024;
@ -474,6 +478,7 @@ public class UserVmManagerImplTest {
Mockito.when(diskfferingVo.getDiskSize()).thenReturn(offeringRootDiskSize);
Mockito.when(volumeApiService.validateVolumeSizeInBytes(Mockito.anyLong())).thenReturn(true);
long rootDiskSize = userVmManagerImpl.configureCustomRootDiskSize(customParameters, template, Hypervisor.HypervisorType.KVM, diskfferingVo);
Assert.assertEquals(expectedRootDiskSize, rootDiskSize);

View File

@ -29,8 +29,8 @@
</parent>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>

View File

@ -29,8 +29,8 @@
</parent>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>

View File

@ -33,8 +33,8 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>

View File

@ -1688,7 +1688,7 @@
"label.powerflex.gateway.username": "Gateway Username",
"label.powerflex.storage.pool": "Storage Pool",
"label.powerstate": "Power State",
"label.preferred": "Prefered",
"label.preferred": "Preferred",
"label.presetup": "PreSetup",
"label.prev": "Prev",
"label.previous": "Previous",
@ -1992,6 +1992,7 @@
"label.select.instance": "Select instance",
"label.select.instance.to.attach.volume.to": "Select instance to attach volume to",
"label.select.iso.or.template": "Select ISO or template",
"label.select.network": "Select Network",
"label.select.offering": "Select offering",
"label.select.project": "Select Project",
"label.select.projects": "Select Projects",

View File

@ -0,0 +1,149 @@
// 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>
<div>
<a-table
class="top-spaced"
size="small"
style="max-height: 250px; overflow-y: auto"
:columns="nicColumns"
:dataSource="nics"
:pagination="false"
:rowKey="record => record.InstanceID">
<template slot="displaytext" slot-scope="record">
<span>{{ record.elementName + ' - ' + record.name }}
<a-tooltip :title="record.nicDescription" placement="top">
<a-icon type="info-circle" class="table-tooltip-icon" />
</a-tooltip>
</span>
</template>
<div slot="size" slot-scope="record">
<span v-if="record.size">
{{ $bytesToHumanReadableSize(record.size) }}
</span>
</div>
<template slot="selectednetwork" slot-scope="record">
<span>{{ record.selectednetworkname || '' }}</span>
</template>
<template slot="select" slot-scope="record">
<div style="display: flex; justify-content: flex-end;"><a-button @click="openNicNetworkSelector(record)">{{ record.selectednetworkid ? $t('label.change') : $t('label.select') }}</a-button></div>
</template>
</a-table>
<a-modal
:visible="!(!selectedNicForNetworkSelection.id)"
:title="$t('label.select.network')"
:closable="true"
:maskClosable="false"
:footer="null"
:cancelText="$t('label.cancel')"
@cancel="closeNicNetworkSelector()"
centered
width="auto">
<nic-network-select-form
:resource="selectedNicForNetworkSelection"
:zoneid="zoneid"
:isOpen="!(!selectedNicForNetworkSelection.id)"
@close-action="closeNicNetworkSelector()"
@select="handleNicNetworkSelection" />
</a-modal>
</div>
</template>
<script>
import NicNetworkSelectForm from '@/components/view/NicNetworkSelectForm'
export default {
name: 'InstanceNicsNetworkSelectListView',
components: {
NicNetworkSelectForm
},
props: {
nics: {
type: Array,
required: true
},
zoneid: {
type: String,
required: true
}
},
data () {
return {
nicColumns: [
{
title: this.$t('label.nic'),
scopedSlots: { customRender: 'displaytext' }
},
{
title: this.$t('label.network'),
scopedSlots: { customRender: 'selectednetwork' }
},
{
title: '',
scopedSlots: { customRender: 'select' }
}
],
selectedNicForNetworkSelection: {}
}
},
methods: {
resetSelection () {
var nics = this.nics
this.nics = []
for (var nic of nics) {
nic.selectednetworkid = null
nic.selectednetworkname = ''
}
this.nics = nics
this.updateNicToNetworkSelection()
},
openNicNetworkSelector (nic) {
this.selectedNicForNetworkSelection = nic
},
closeNicNetworkSelector () {
this.selectedNicForNetworkSelection = {}
},
handleNicNetworkSelection (nicId, network) {
for (const nic of this.nics) {
if (nic.id === nicId) {
nic.selectednetworkid = network.id
nic.selectednetworkname = network.name
break
}
}
this.updateNicToNetworkSelection()
},
updateNicToNetworkSelection () {
var nicToNetworkSelection = []
for (const nic of this.nics) {
if (nic.selectednetworkid && nic.selectednetworkid !== -1) {
nicToNetworkSelection.push({ nic: nic.id, network: nic.selectednetworkid })
}
}
this.$emit('select', nicToNetworkSelection)
}
}
}
</script>
<style scoped lang="less">
.top-spaced {
margin-top: 20px;
}
</style>

View File

@ -0,0 +1,228 @@
// 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>
<div class="form" v-ctrl-enter="handleKeyboardSubmit">
<div>
<a-input-search
class="top-spaced"
:placeholder="$t('label.search')"
v-model="searchQuery"
style="margin-bottom: 10px;"
@search="fetchNetworks"
autoFocus />
<a-table
size="small"
style="overflow-y: auto"
:loading="loading"
:columns="columns"
:dataSource="networks"
:pagination="false"
:rowKey="record => record.id">
<template slot="select" slot-scope="record">
<a-radio
@click="updateSelection(record)"
:checked="selectedNetwork != null && record.id === selectedNetwork.id">
</a-radio>
</template>
</a-table>
<a-pagination
class="top-spaced"
size="small"
:current="page"
:pageSize="pageSize"
:total="totalCount"
:showTotal="total => `${$t('label.total')} ${total} ${$t('label.items')}`"
:pageSizeOptions="['10', '20', '40', '80', '100']"
@change="handleChangePage"
@showSizeChange="handleChangePageSize"
showSizeChanger>
<template slot="buildOptionText" slot-scope="props">
<span>{{ props.value }} / {{ $t('label.page') }}</span>
</template>
</a-pagination>
</div>
<a-divider />
<div class="actions">
<a-button @click="closeModal">{{ $t('label.cancel') }}</a-button>
<a-button type="primary" ref="submit" :disabled="!selectedNetwork" @click="submitForm">{{ $t('label.ok') }}</a-button>
</div>
</div>
</template>
<script>
import { api } from '@/api'
export default {
name: 'NicNetworkSelectForm',
props: {
resource: {
type: Object,
required: true
},
zoneid: {
type: String,
required: true
},
isOpen: {
type: Boolean,
required: false
}
},
data () {
return {
loading: false,
networks: [],
searchQuery: '',
totalCount: 0,
page: 1,
pageSize: 10,
selectedNetwork: null,
columns: [
{
title: this.$t('label.networkid'),
dataIndex: 'name'
},
{
title: this.$t('label.guestiptype'),
dataIndex: 'type'
},
{
title: this.$t('label.vpc'),
dataIndex: 'vpcName'
},
{
title: this.$t('label.cidr'),
dataIndex: 'cidr'
},
{
title: this.$t('label.select'),
scopedSlots: { customRender: 'select' }
}
]
}
},
created () {
this.fetchNetworks()
this.preselectNetwork()
},
watch: {
isOpen (newValue) {
if (newValue) {
setTimeout(() => {
this.reset()
}, 50)
}
}
},
methods: {
fetchNetworks () {
this.loading = true
var params = {
zoneid: this.zoneid,
keyword: this.searchQuery,
page: this.page,
pagesize: this.pageSize,
canusefordeploy: true,
projectid: this.$store.getters.project ? this.$store.getters.project.id : null,
domainid: this.$store.getters.project && this.$store.getters.project.id ? null : this.$store.getters.userInfo.domainid,
account: this.$store.getters.project && this.$store.getters.project.id ? null : this.$store.getters.userInfo.account
}
api('listNetworks', params).then(response => {
this.networks = response.listnetworksresponse.network || []
this.totalCount = response.listnetworksresponse.count
}).catch(error => {
this.$notifyError(error)
}).finally(() => {
this.loading = false
})
},
handleChangePage (page, pageSize) {
this.page = page
this.pageSize = pageSize
this.fetchNetworks()
},
handleChangePageSize (currentPage, pageSize) {
this.page = currentPage
this.pageSize = pageSize
this.fetchNetworks()
},
preselectNetwork () {
if (this.resource && 'selectednetworkid' in this.resource) {
this.selectedNetwork = { id: this.resource.selectednetworkid }
}
},
clearView () {
this.networks = []
this.searchQuery = ''
this.totalCount = 0
this.page = 1
this.pageSize = 10
this.selectedNetwork = null
},
reset () {
this.clearView()
this.preselectNetwork()
this.fetchNetworks()
},
updateSelection (network) {
this.selectedNetwork = network
},
closeModal () {
this.$emit('close-action')
},
handleKeyboardSubmit () {
if (this.selectedNetwork != null) {
this.submitForm()
}
},
submitForm () {
this.$emit('select', this.resource.id, this.selectedNetwork)
this.closeModal()
}
}
}
</script>
<style scoped lang="scss">
.form {
width: 80vw;
@media (min-width: 900px) {
width: 850px;
}
}
.top-spaced {
margin-top: 20px;
}
.actions {
display: flex;
justify-content: flex-end;
margin-top: 20px;
button {
&:not(:last-child) {
margin-right: 10px;
}
}
}
</style>

View File

@ -390,31 +390,10 @@
<template slot="description">
<div v-if="zoneSelected">
<div v-if="vm.templateid && templateNics && templateNics.length > 0">
<a-form-item
v-for="(nic, nicIndex) in templateNics"
:key="nicIndex"
:v-bind="nic.name" >
<tooltip-label slot="label" :title="nic.elementName + ' - ' + nic.name" :tooltip="nic.networkDescription"/>
<a-select
showSearch
optionFilterProp="children"
v-decorator="[
'networkMap.nic-' + nic.InstanceID.toString(),
{ initialValue: options.networks && options.networks.length > 0 ? options.networks[Math.min(nicIndex, options.networks.length - 1)].id : null }
]"
:placeholder="nic.networkDescription"
:filterOption="(input, option) => {
return option.componentOptions.children[0].children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
>
<a-select-option v-for="opt in options.networks" :key="opt.id">
<span v-if="opt.type!=='L2'">
{{ opt.name || opt.description }} ({{ `${$t('label.cidr')}: ${opt.cidr}` }})
</span>
<span v-else>{{ opt.name || opt.description }}</span>
</a-select-option>
</a-select>
</a-form-item>
<instance-nics-network-select-list-view
:nics="templateNics"
:zoneid="selectedZone"
@select="handleNicsNetworkSelection" />
</div>
<div v-show="!(vm.templateid && templateNics && templateNics.length > 0)" >
<network-selection
@ -771,6 +750,7 @@ import NetworkConfiguration from '@views/compute/wizard/NetworkConfiguration'
import SshKeyPairSelection from '@views/compute/wizard/SshKeyPairSelection'
import SecurityGroupSelection from '@views/compute/wizard/SecurityGroupSelection'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import InstanceNicsNetworkSelectListView from '@/components/view/InstanceNicsNetworkSelectListView.vue'
export default {
name: 'Wizard',
@ -788,7 +768,8 @@ export default {
ComputeSelection,
SecurityGroupSelection,
ResourceIcon,
TooltipLabel
TooltipLabel,
InstanceNicsNetworkSelectListView
},
props: {
visible: {
@ -911,7 +892,8 @@ export default {
minIops: 0,
maxIops: 0,
zones: [],
selectedZone: ''
selectedZone: '',
nicToNetworkSelection: []
}
},
computed: {
@ -1796,13 +1778,11 @@ export default {
deployVmData.affinitygroupids = (values.affinitygroupids || []).join(',')
// step 6: select network
if (this.zone.networktype !== 'Basic') {
if ('networkMap' in values) {
const keys = Object.keys(values.networkMap)
for (var j = 0; j < keys.length; ++j) {
if (values.networkMap[keys[j]] && values.networkMap[keys[j]].length > 0) {
deployVmData['nicnetworklist[' + j + '].nic'] = keys[j].replace('nic-', '')
deployVmData['nicnetworklist[' + j + '].network'] = values.networkMap[keys[j]]
}
if (this.nicToNetworkSelection && this.nicToNetworkSelection.length > 0) {
for (var j in this.nicToNetworkSelection) {
var nicNetwork = this.nicToNetworkSelection[j]
deployVmData['nicnetworklist[' + j + '].nic'] = nicNetwork.nic
deployVmData['nicnetworklist[' + j + '].network'] = nicNetwork.network
}
} else {
const arrNetwork = []
@ -2172,6 +2152,17 @@ export default {
nics.sort(function (a, b) {
return a.InstanceID - b.InstanceID
})
if (this.options.networks && this.options.networks.length > 0) {
this.nicToNetworkSelection = []
for (var i = 0; i < nics.length; ++i) {
var nic = nics[i]
nic.id = nic.InstanceID
var network = this.options.networks[Math.min(i, this.options.networks.length - 1)]
nic.selectednetworkid = network.id
nic.selectednetworkname = network.name
this.nicToNetworkSelection.push({ nic: nic.id, network: network.id })
}
}
}
return nics
},
@ -2336,6 +2327,9 @@ export default {
onBootTypeChange (value) {
this.fetchBootModes(value)
this.updateFieldValue('bootmode', this.options.bootModes?.[0]?.id || undefined)
},
handleNicsNetworkSelection (nicToNetworkSelection) {
this.nicToNetworkSelection = nicToNetworkSelection
}
}
}

View File

@ -228,7 +228,7 @@
<a-radio-button value="strict">
{{ $t('label.strict') }}
</a-radio-button>
<a-radio-button value="preferred">
<a-radio-button value="Preferred">
{{ $t('label.preferred') }}
</a-radio-button>
</a-radio-group>

View File

@ -47,8 +47,8 @@
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<groupId>ch.qos.reload4j</groupId>
<artifactId>reload4j</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
@ -143,6 +143,10 @@
<groupId>org.owasp.esapi</groupId>
<artifactId>esapi</artifactId>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>