mirror of
https://github.com/apache/cloudstack.git
synced 2025-12-16 02:22:52 +01:00
Merge remote-tracking branch 'origin/4.15'
This commit is contained in:
commit
1abd10199c
@ -72,7 +72,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
|
|||||||
private String format;
|
private String format;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, required = true, description = "the target hypervisor for the template")
|
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, required = true, description = "the target hypervisor for the template")
|
||||||
private String hypervisor;
|
protected String hypervisor;
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN, description = "true if this template is a featured template, false otherwise")
|
@Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN, description = "true if this template is a featured template, false otherwise")
|
||||||
private Boolean featured;
|
private Boolean featured;
|
||||||
@ -162,6 +162,11 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
|
|||||||
description = "true if template should bypass Secondary Storage and be downloaded to Primary Storage on deployment")
|
description = "true if template should bypass Secondary Storage and be downloaded to Primary Storage on deployment")
|
||||||
private Boolean directDownload;
|
private Boolean directDownload;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.DEPLOY_AS_IS,
|
||||||
|
type = CommandType.BOOLEAN,
|
||||||
|
description = "(VMware only) true if VM deployments should preserve all the configurations defined for this template", since = "4.15.1")
|
||||||
|
protected Boolean deployAsIs;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -274,8 +279,9 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
|
|||||||
return directDownload == null ? false : directDownload;
|
return directDownload == null ? false : directDownload;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean isDeployAsIs() {
|
public boolean isDeployAsIs() {
|
||||||
return hypervisor != null && hypervisor.equalsIgnoreCase(Hypervisor.HypervisorType.VMware.toString());
|
return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor) &&
|
||||||
|
Boolean.TRUE.equals(deployAsIs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -341,7 +347,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
|
|||||||
"Parameter directdownload is only allowed for KVM templates");
|
"Parameter directdownload is only allowed for KVM templates");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.VMware.toString()) && osTypeId == null) {
|
if (!isDeployAsIs() && osTypeId == null) {
|
||||||
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide a guest OS type");
|
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide a guest OS type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
package org.apache.cloudstack.api.command.user.template;
|
package org.apache.cloudstack.api.command.user.template;
|
||||||
|
|
||||||
import com.cloud.exception.ResourceAllocationException;
|
import com.cloud.exception.ResourceAllocationException;
|
||||||
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
import com.cloud.template.TemplateApiService;
|
import com.cloud.template.TemplateApiService;
|
||||||
import org.apache.cloudstack.api.ApiErrorCode;
|
import org.apache.cloudstack.api.ApiErrorCode;
|
||||||
import org.apache.cloudstack.api.ServerApiException;
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
@ -32,7 +33,7 @@ import org.mockito.runners.MockitoJUnitRunner;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class RegisterTemplateCmdTest{
|
public class RegisterTemplateCmdTest {
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private RegisterTemplateCmd registerTemplateCmd;
|
private RegisterTemplateCmd registerTemplateCmd;
|
||||||
@ -108,4 +109,34 @@ public class RegisterTemplateCmdTest{
|
|||||||
registerTemplateCmd.zoneId = 1L;
|
registerTemplateCmd.zoneId = 1L;
|
||||||
Assert.assertEquals((Long)1L,registerTemplateCmd.getZoneIds().get(0));
|
Assert.assertEquals((Long)1L,registerTemplateCmd.getZoneIds().get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testIsDeployAsIsBase(Hypervisor.HypervisorType hypervisorType, Boolean deployAsIsParameter, boolean expectedResult) {
|
||||||
|
registerTemplateCmd = new RegisterTemplateCmd();
|
||||||
|
registerTemplateCmd.hypervisor = hypervisorType.name();
|
||||||
|
registerTemplateCmd.deployAsIs = deployAsIsParameter;
|
||||||
|
boolean isDeployAsIs = registerTemplateCmd.isDeployAsIs();
|
||||||
|
Assert.assertEquals(expectedResult, isDeployAsIs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsDeployAsIsVmwareNullAsIs() {
|
||||||
|
testIsDeployAsIsBase(Hypervisor.HypervisorType.VMware, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsDeployAsIsVmwareNotAsIs() {
|
||||||
|
testIsDeployAsIsBase(Hypervisor.HypervisorType.VMware, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsDeployAsIsVmwareAsIs() {
|
||||||
|
testIsDeployAsIsBase(Hypervisor.HypervisorType.VMware, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsDeployAsIsNonVmware() {
|
||||||
|
testIsDeployAsIsBase(Hypervisor.HypervisorType.KVM, true, false);
|
||||||
|
testIsDeployAsIsBase(Hypervisor.HypervisorType.XenServer, true, false);
|
||||||
|
testIsDeployAsIsBase(Hypervisor.HypervisorType.Any, true, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -262,5 +262,11 @@ public interface VirtualMachineManager extends Manager {
|
|||||||
|
|
||||||
UserVm restoreVirtualMachine(long vmId, Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException;
|
UserVm restoreVirtualMachine(long vmId, Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the VM's Root volume is allocated at a local storage pool
|
||||||
|
*/
|
||||||
|
boolean isRootVolumeOnLocalStorage(long vmId);
|
||||||
|
|
||||||
Pair<Long, Long> findClusterAndHostIdForVm(long vmId);
|
Pair<Long, Long> findClusterAndHostIdForVm(long vmId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3828,22 +3828,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
|
|
||||||
final ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
|
final ServiceOfferingVO currentServiceOffering = _offeringDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId());
|
||||||
|
|
||||||
// Check that the service offering being upgraded to has the same Guest IP type as the VM's current service offering
|
checkIfNewOfferingStorageScopeMatchesStoragePool(vmInstance, newServiceOffering);
|
||||||
// NOTE: With the new network refactoring in 2.2, we shouldn't need the check for same guest IP type anymore.
|
|
||||||
/*
|
|
||||||
* if (!currentServiceOffering.getGuestIpType().equals(newServiceOffering.getGuestIpType())) { String errorMsg =
|
|
||||||
* "The service offering being upgraded to has a guest IP type: " + newServiceOffering.getGuestIpType(); errorMsg +=
|
|
||||||
* ". Please select a service offering with the same guest IP type as the VM's current service offering (" +
|
|
||||||
* currentServiceOffering.getGuestIpType() + ")."; throw new InvalidParameterValueException(errorMsg); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Check that the service offering being upgraded to has the same storage pool preference as the VM's current service
|
|
||||||
// offering
|
|
||||||
if (currentServiceOffering.isUseLocalStorage() != newServiceOffering.isUseLocalStorage()) {
|
|
||||||
throw new InvalidParameterValueException("Unable to upgrade virtual machine " + vmInstance.toString() +
|
|
||||||
", cannot switch between local storage and shared storage service offerings. Current offering " + "useLocalStorage=" +
|
|
||||||
currentServiceOffering.isUseLocalStorage() + ", target offering useLocalStorage=" + newServiceOffering.isUseLocalStorage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// if vm is a system vm, check if it is a system service offering, if yes return with error as it cannot be used for user vms
|
// if vm is a system vm, check if it is a system service offering, if yes return with error as it cannot be used for user vms
|
||||||
if (currentServiceOffering.isSystemUse() != newServiceOffering.isSystemUse()) {
|
if (currentServiceOffering.isSystemUse() != newServiceOffering.isSystemUse()) {
|
||||||
@ -3865,6 +3850,39 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Throws an InvalidParameterValueException in case the new service offerings does not match the storage scope (e.g. local or shared).
|
||||||
|
*/
|
||||||
|
protected void checkIfNewOfferingStorageScopeMatchesStoragePool(VirtualMachine vmInstance, ServiceOffering newServiceOffering) {
|
||||||
|
boolean isRootVolumeOnLocalStorage = isRootVolumeOnLocalStorage(vmInstance.getId());
|
||||||
|
|
||||||
|
if (newServiceOffering.isUseLocalStorage() && !isRootVolumeOnLocalStorage) {
|
||||||
|
String message = String .format("Unable to upgrade virtual machine %s, target offering use local storage but the storage pool where "
|
||||||
|
+ "the volume is allocated is a shared storage.", vmInstance.toString());
|
||||||
|
throw new InvalidParameterValueException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newServiceOffering.isUseLocalStorage() && isRootVolumeOnLocalStorage) {
|
||||||
|
String message = String.format("Unable to upgrade virtual machine %s, target offering use shared storage but the storage pool where "
|
||||||
|
+ "the volume is allocated is a local storage.", vmInstance.toString());
|
||||||
|
throw new InvalidParameterValueException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRootVolumeOnLocalStorage(long vmId) {
|
||||||
|
ScopeType poolScope = ScopeType.ZONE;
|
||||||
|
List<VolumeVO> volumes = _volsDao.findByInstanceAndType(vmId, Type.ROOT);
|
||||||
|
if(CollectionUtils.isNotEmpty(volumes)) {
|
||||||
|
VolumeVO rootDisk = volumes.get(0);
|
||||||
|
Long poolId = rootDisk.getPoolId();
|
||||||
|
if (poolId != null) {
|
||||||
|
StoragePoolVO storagePoolVO = _storagePoolDao.findById(poolId);
|
||||||
|
poolScope = storagePoolVO.getScope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ScopeType.HOST == poolScope;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean upgradeVmDb(final long vmId, final ServiceOffering newServiceOffering, ServiceOffering currentServiceOffering) {
|
public boolean upgradeVmDb(final long vmId, final ServiceOffering newServiceOffering, ServiceOffering currentServiceOffering) {
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
|
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
|
||||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||||
@ -624,4 +625,59 @@ public class VirtualMachineManagerImplTest {
|
|||||||
assertTrue(VirtualMachineManagerImpl.matches(tags,three));
|
assertTrue(VirtualMachineManagerImpl.matches(tags,three));
|
||||||
assertTrue(VirtualMachineManagerImpl.matches(others,three));
|
assertTrue(VirtualMachineManagerImpl.matches(others,three));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isRootVolumeOnLocalStorageTestOnLocal() {
|
||||||
|
prepareAndTestIsRootVolumeOnLocalStorage(ScopeType.HOST, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isRootVolumeOnLocalStorageTestCluster() {
|
||||||
|
prepareAndTestIsRootVolumeOnLocalStorage(ScopeType.CLUSTER, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isRootVolumeOnLocalStorageTestZone() {
|
||||||
|
prepareAndTestIsRootVolumeOnLocalStorage(ScopeType.ZONE, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareAndTestIsRootVolumeOnLocalStorage(ScopeType scope, boolean expected) {
|
||||||
|
StoragePoolVO storagePoolVoMock = Mockito.mock(StoragePoolVO.class);
|
||||||
|
Mockito.doReturn(storagePoolVoMock).when(storagePoolDaoMock).findById(Mockito.anyLong());
|
||||||
|
Mockito.doReturn(scope).when(storagePoolVoMock).getScope();
|
||||||
|
List<VolumeVO> mockedVolumes = new ArrayList<>();
|
||||||
|
mockedVolumes.add(volumeVoMock);
|
||||||
|
Mockito.doReturn(mockedVolumes).when(volumeDaoMock).findByInstanceAndType(Mockito.anyLong(), Mockito.any());
|
||||||
|
|
||||||
|
boolean result = virtualMachineManagerImpl.isRootVolumeOnLocalStorage(0l);
|
||||||
|
|
||||||
|
Assert.assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkIfNewOfferingStorageScopeMatchesStoragePoolTestLocalLocal() {
|
||||||
|
prepareAndRunCheckIfNewOfferingStorageScopeMatchesStoragePool(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkIfNewOfferingStorageScopeMatchesStoragePoolTestSharedShared() {
|
||||||
|
prepareAndRunCheckIfNewOfferingStorageScopeMatchesStoragePool(false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test (expected = InvalidParameterValueException.class)
|
||||||
|
public void checkIfNewOfferingStorageScopeMatchesStoragePoolTestLocalShared() {
|
||||||
|
prepareAndRunCheckIfNewOfferingStorageScopeMatchesStoragePool(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test (expected = InvalidParameterValueException.class)
|
||||||
|
public void checkIfNewOfferingStorageScopeMatchesStoragePoolTestSharedLocal() {
|
||||||
|
prepareAndRunCheckIfNewOfferingStorageScopeMatchesStoragePool(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareAndRunCheckIfNewOfferingStorageScopeMatchesStoragePool(boolean isRootOnLocal, boolean isOfferingUsingLocal) {
|
||||||
|
Mockito.doReturn(isRootOnLocal).when(virtualMachineManagerImpl).isRootVolumeOnLocalStorage(Mockito.anyLong());
|
||||||
|
Mockito.doReturn("vmInstanceMockedToString").when(vmInstanceMock).toString();
|
||||||
|
Mockito.doReturn(isOfferingUsingLocal).when(serviceOfferingMock).isUseLocalStorage();
|
||||||
|
virtualMachineManagerImpl.checkIfNewOfferingStorageScopeMatchesStoragePool(vmInstanceMock, serviceOfferingMock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -200,7 +200,7 @@ public class VMInstanceVO implements VirtualMachine, FiniteStateObject<State, Vi
|
|||||||
@Column(name = "backup_external_id")
|
@Column(name = "backup_external_id")
|
||||||
protected String backupExternalId;
|
protected String backupExternalId;
|
||||||
|
|
||||||
@Column(name = "backup_volumes")
|
@Column(name = "backup_volumes", length = 65535)
|
||||||
protected String backupVolumes;
|
protected String backupVolumes;
|
||||||
|
|
||||||
public VMInstanceVO(long id, long serviceOfferingId, String name, String instanceName, Type type, Long vmTemplateId, HypervisorType hypervisorType, long guestOSId,
|
public VMInstanceVO(long id, long serviceOfferingId, String name, String instanceName, Type type, Long vmTemplateId, HypervisorType hypervisorType, long guestOSId,
|
||||||
|
|||||||
@ -80,6 +80,7 @@ Requires: iptables-services
|
|||||||
Requires: qemu-img
|
Requires: qemu-img
|
||||||
Requires: python3-pip
|
Requires: python3-pip
|
||||||
Requires: python3-setuptools
|
Requires: python3-setuptools
|
||||||
|
Requires: libgcrypt > 1.8.3
|
||||||
Group: System Environment/Libraries
|
Group: System Environment/Libraries
|
||||||
%description management
|
%description management
|
||||||
The CloudStack management server is the central point of coordination,
|
The CloudStack management server is the central point of coordination,
|
||||||
@ -109,6 +110,7 @@ Requires: perl
|
|||||||
Requires: python3-libvirt
|
Requires: python3-libvirt
|
||||||
Requires: qemu-img
|
Requires: qemu-img
|
||||||
Requires: qemu-kvm
|
Requires: qemu-kvm
|
||||||
|
Requires: libgcrypt > 1.8.3
|
||||||
Provides: cloud-agent
|
Provides: cloud-agent
|
||||||
Group: System Environment/Libraries
|
Group: System Environment/Libraries
|
||||||
%description agent
|
%description agent
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import java.util.stream.Stream;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import com.cloud.storage.dao.VMTemplateDetailsDao;
|
import com.cloud.storage.dao.VMTemplateDetailsDao;
|
||||||
|
import com.cloud.vm.VirtualMachineManager;
|
||||||
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
|
||||||
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
|
import org.apache.cloudstack.affinity.AffinityGroupDomainMapVO;
|
||||||
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
||||||
@ -424,6 +425,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
@Inject
|
@Inject
|
||||||
private UserDao userDao;
|
private UserDao userDao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VirtualMachineManager virtualMachineManager;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
@ -2962,8 +2966,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
sc.addAnd("id", SearchCriteria.Op.NEQ, currentVmOffering.getId());
|
sc.addAnd("id", SearchCriteria.Op.NEQ, currentVmOffering.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Only return offerings with the same storage type
|
boolean isRootVolumeUsingLocalStorage = virtualMachineManager.isRootVolumeOnLocalStorage(vmId);
|
||||||
sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, currentVmOffering.isUseLocalStorage());
|
|
||||||
|
// 1. Only return offerings with the same storage type than the storage pool where the VM's root volume is allocated
|
||||||
|
sc.addAnd("useLocalStorage", SearchCriteria.Op.EQ, isRootVolumeUsingLocalStorage);
|
||||||
|
|
||||||
// 2.In case vm is running return only offerings greater than equal to current offering compute.
|
// 2.In case vm is running return only offerings greater than equal to current offering compute.
|
||||||
if (vmInstance.getState() == VirtualMachine.State.Running) {
|
if (vmInstance.getState() == VirtualMachine.State.Running) {
|
||||||
|
|||||||
@ -291,7 +291,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map details = cmd.getDetails();
|
Map details = cmd.getDetails();
|
||||||
if (hypervisorType == HypervisorType.VMware) {
|
if (cmd.isDeployAsIs()) {
|
||||||
if (MapUtils.isNotEmpty(details)) {
|
if (MapUtils.isNotEmpty(details)) {
|
||||||
if (details.containsKey(VmDetailConstants.ROOT_DISK_CONTROLLER)) {
|
if (details.containsKey(VmDetailConstants.ROOT_DISK_CONTROLLER)) {
|
||||||
s_logger.info("Ignoring the rootDiskController detail provided, as we honour what is defined in the template");
|
s_logger.info("Ignoring the rootDiskController detail provided, as we honour what is defined in the template");
|
||||||
|
|||||||
@ -260,8 +260,8 @@ class TestKubernetesCluster(cloudstackTestCase):
|
|||||||
|
|
||||||
if validateList(templates)[0] != PASS:
|
if validateList(templates)[0] != PASS:
|
||||||
details = None
|
details = None
|
||||||
if hypervisor in ["vmware"]:
|
if hypervisor in ["vmware"] and "details" in cks_template:
|
||||||
details = [{"keyboard": "us"}]
|
details = cks_template["details"]
|
||||||
template = Template.register(cls.apiclient, cks_template, zoneid=cls.zone.id, hypervisor=hypervisor.lower(), randomize_name=False, details=details)
|
template = Template.register(cls.apiclient, cks_template, zoneid=cls.zone.id, hypervisor=hypervisor.lower(), randomize_name=False, details=details)
|
||||||
template.download(cls.apiclient)
|
template.download(cls.apiclient)
|
||||||
return template, False
|
return template, False
|
||||||
|
|||||||
@ -59,6 +59,7 @@ class TestVMWareStoragePolicies(cloudstackTestCase):
|
|||||||
cls.apiclient,
|
cls.apiclient,
|
||||||
cls.zone.id,
|
cls.zone.id,
|
||||||
cls.hypervisor,
|
cls.hypervisor,
|
||||||
|
deploy_as_is=cls.hypervisor.lower() == "vmware"
|
||||||
)
|
)
|
||||||
cls._cleanup.append(cls.network_offering)
|
cls._cleanup.append(cls.network_offering)
|
||||||
return
|
return
|
||||||
|
|||||||
@ -84,6 +84,7 @@ class TestCreateTemplateWithChecksum(cloudstackTestCase):
|
|||||||
self.test_template.displaytext = 'test sha-1'
|
self.test_template.displaytext = 'test sha-1'
|
||||||
self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-vmware.ova"
|
self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-vmware.ova"
|
||||||
self.test_template.format = "OVA"
|
self.test_template.format = "OVA"
|
||||||
|
self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)")
|
||||||
self.md5 = "27f3c56a8c7ec7b2f3ff2199f7078006"
|
self.md5 = "27f3c56a8c7ec7b2f3ff2199f7078006"
|
||||||
self.sha256 = "a7b04c1eb507f3f5de844bda352df1ea5e20335b465409493ca6ae07dfd0a158"
|
self.sha256 = "a7b04c1eb507f3f5de844bda352df1ea5e20335b465409493ca6ae07dfd0a158"
|
||||||
|
|
||||||
|
|||||||
@ -308,7 +308,8 @@ class TestVolumes(cloudstackTestCase):
|
|||||||
cls.apiclient,
|
cls.apiclient,
|
||||||
cls.zone.id,
|
cls.zone.id,
|
||||||
cls.services["ostype"],
|
cls.services["ostype"],
|
||||||
cls.hypervisor
|
cls.hypervisor,
|
||||||
|
deploy_as_is=cls.hypervisor.lower() == "vmware"
|
||||||
)
|
)
|
||||||
if cls.template == FAILED:
|
if cls.template == FAILED:
|
||||||
assert False, "get_suitable_test_template() failed to return template with description %s" % cls.services["ostype"]
|
assert False, "get_suitable_test_template() failed to return template with description %s" % cls.services["ostype"]
|
||||||
|
|||||||
@ -1405,24 +1405,22 @@ class Template:
|
|||||||
elif "hypervisor" in services:
|
elif "hypervisor" in services:
|
||||||
cmd.hypervisor = services["hypervisor"]
|
cmd.hypervisor = services["hypervisor"]
|
||||||
|
|
||||||
if cmd.hypervisor.lower() not in ["vmware"]:
|
if "ostypeid" in services:
|
||||||
# Since version 4.15 VMware templates honour the guest OS defined in the template
|
cmd.ostypeid = services["ostypeid"]
|
||||||
if "ostypeid" in services:
|
elif "ostype" in services:
|
||||||
cmd.ostypeid = services["ostypeid"]
|
# Find OSTypeId from Os type
|
||||||
elif "ostype" in services:
|
sub_cmd = listOsTypes.listOsTypesCmd()
|
||||||
# Find OSTypeId from Os type
|
sub_cmd.description = services["ostype"]
|
||||||
sub_cmd = listOsTypes.listOsTypesCmd()
|
ostypes = apiclient.listOsTypes(sub_cmd)
|
||||||
sub_cmd.description = services["ostype"]
|
|
||||||
ostypes = apiclient.listOsTypes(sub_cmd)
|
|
||||||
|
|
||||||
if not isinstance(ostypes, list):
|
if not isinstance(ostypes, list):
|
||||||
raise Exception(
|
|
||||||
"Unable to find Ostype id with desc: %s" %
|
|
||||||
services["ostype"])
|
|
||||||
cmd.ostypeid = ostypes[0].id
|
|
||||||
else:
|
|
||||||
raise Exception(
|
raise Exception(
|
||||||
"Unable to find Ostype is required for registering template")
|
"Unable to find Ostype id with desc: %s" %
|
||||||
|
services["ostype"])
|
||||||
|
cmd.ostypeid = ostypes[0].id
|
||||||
|
else:
|
||||||
|
raise Exception(
|
||||||
|
"Unable to find Ostype is required for registering template")
|
||||||
|
|
||||||
cmd.url = services["url"]
|
cmd.url = services["url"]
|
||||||
|
|
||||||
@ -1440,6 +1438,7 @@ class Template:
|
|||||||
cmd.isdynamicallyscalable = services["isdynamicallyscalable"] if "isdynamicallyscalable" in services else False
|
cmd.isdynamicallyscalable = services["isdynamicallyscalable"] if "isdynamicallyscalable" in services else False
|
||||||
cmd.passwordenabled = services[
|
cmd.passwordenabled = services[
|
||||||
"passwordenabled"] if "passwordenabled" in services else False
|
"passwordenabled"] if "passwordenabled" in services else False
|
||||||
|
cmd.deployasis = services["deployasis"] if "deployasis" in services else False
|
||||||
|
|
||||||
if account:
|
if account:
|
||||||
cmd.account = account
|
cmd.account = account
|
||||||
|
|||||||
@ -348,7 +348,7 @@ def get_template(
|
|||||||
return list_templatesout[0]
|
return list_templatesout[0]
|
||||||
|
|
||||||
|
|
||||||
def get_test_template(apiclient, zone_id=None, hypervisor=None, test_templates=None):
|
def get_test_template(apiclient, zone_id=None, hypervisor=None, test_templates=None, deploy_as_is=False):
|
||||||
"""
|
"""
|
||||||
@Name : get_test_template
|
@Name : get_test_template
|
||||||
@Desc : Retrieves the test template used to running tests. When the template
|
@Desc : Retrieves the test template used to running tests. When the template
|
||||||
@ -373,6 +373,8 @@ def get_test_template(apiclient, zone_id=None, hypervisor=None, test_templates=N
|
|||||||
return FAILED
|
return FAILED
|
||||||
|
|
||||||
test_template = test_templates[hypervisor]
|
test_template = test_templates[hypervisor]
|
||||||
|
if deploy_as_is:
|
||||||
|
test_template['deployasis'] = True
|
||||||
|
|
||||||
cmd = listTemplates.listTemplatesCmd()
|
cmd = listTemplates.listTemplatesCmd()
|
||||||
cmd.name = test_template['name']
|
cmd.name = test_template['name']
|
||||||
@ -513,7 +515,7 @@ def get_windows_template(
|
|||||||
|
|
||||||
return FAILED
|
return FAILED
|
||||||
|
|
||||||
def get_suitable_test_template(apiclient, zoneid, ostypeid, hypervisor):
|
def get_suitable_test_template(apiclient, zoneid, ostypeid, hypervisor, deploy_as_is=False):
|
||||||
'''
|
'''
|
||||||
@Name : get_suitable_test_template
|
@Name : get_suitable_test_template
|
||||||
@Desc : Retrieves the test template information based upon inputs provided
|
@Desc : Retrieves the test template information based upon inputs provided
|
||||||
@ -525,11 +527,12 @@ def get_suitable_test_template(apiclient, zoneid, ostypeid, hypervisor):
|
|||||||
template Information matching the inputs
|
template Information matching the inputs
|
||||||
'''
|
'''
|
||||||
template = FAILED
|
template = FAILED
|
||||||
if hypervisor.lower() in ["xenserver"]:
|
if hypervisor.lower() in ["xenserver"] or (hypervisor.lower() in ["vmware"] and deploy_as_is):
|
||||||
template = get_test_template(
|
template = get_test_template(
|
||||||
apiclient,
|
apiclient,
|
||||||
zoneid,
|
zoneid,
|
||||||
hypervisor)
|
hypervisor,
|
||||||
|
deploy_as_is=deploy_as_is)
|
||||||
if template == FAILED:
|
if template == FAILED:
|
||||||
template = get_template(
|
template = get_template(
|
||||||
apiclient,
|
apiclient,
|
||||||
|
|||||||
@ -718,7 +718,7 @@
|
|||||||
"label.demote.project.owner": "Demote account to Regular role",
|
"label.demote.project.owner": "Demote account to Regular role",
|
||||||
"label.demote.project.owner.user": "Demote user to Regular role",
|
"label.demote.project.owner.user": "Demote user to Regular role",
|
||||||
"label.deny": "Deny",
|
"label.deny": "Deny",
|
||||||
"label.deployasis":"Deploy As-Is",
|
"label.deployasis":"Read VM settings from OVA",
|
||||||
"label.deploymentplanner": "Deployment planner",
|
"label.deploymentplanner": "Deployment planner",
|
||||||
"label.description": "Description",
|
"label.description": "Description",
|
||||||
"label.destcidr": "Destination CIDR",
|
"label.destcidr": "Destination CIDR",
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
<a-form-item class="pair-select-container" :label="selectLabel" v-if="this.checked">
|
<a-form-item class="pair-select-container" :label="selectLabel" v-if="this.checked">
|
||||||
<a-select
|
<a-select
|
||||||
v-decorator="[selectDecorator, {
|
v-decorator="[selectDecorator, {
|
||||||
initialValue: this.getSelectInitialValue()
|
initialValue: selectedOption ? selectedOption : this.getSelectInitialValue()
|
||||||
}]"
|
}]"
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="children"
|
optionFilterProp="children"
|
||||||
@ -80,23 +80,16 @@ export default {
|
|||||||
return array !== null && array !== undefined && Array.isArray(array) && array.length > 0
|
return array !== null && array !== undefined && Array.isArray(array) && array.length > 0
|
||||||
},
|
},
|
||||||
getSelectInitialValue () {
|
getSelectInitialValue () {
|
||||||
if (this.arrayHasItems(this.selectOptions)) {
|
const provider = this.selectOptions?.filter(x => x.enabled)?.[0]?.name || ''
|
||||||
for (var i = 0; i < this.selectOptions.length; i++) {
|
this.handleSelectChange(provider)
|
||||||
if (this.selectOptions[i].enabled !== false) {
|
return provider
|
||||||
return this.selectOptions[i].name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
},
|
},
|
||||||
handleCheckChange (e) {
|
handleCheckChange (e) {
|
||||||
this.checked = e.target.checked
|
this.checked = e.target.checked
|
||||||
if (this.checked && this.arrayHasItems(this.selectOptions)) {
|
|
||||||
this.selectedOption = this.selectOptions[0].name
|
|
||||||
}
|
|
||||||
this.$emit('handle-checkpair-change', this.resourceKey, this.checked, '')
|
this.$emit('handle-checkpair-change', this.resourceKey, this.checked, '')
|
||||||
},
|
},
|
||||||
handleSelectChange (val) {
|
handleSelectChange (val) {
|
||||||
|
this.selectedOption = val
|
||||||
this.$emit('handle-checkpair-change', this.resourceKey, this.checked, val)
|
this.$emit('handle-checkpair-change', this.resourceKey, this.checked, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export default {
|
|||||||
filter: ''
|
filter: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeMount () {
|
created () {
|
||||||
switch (this.$route.meta.name) {
|
switch (this.$route.meta.name) {
|
||||||
case 'account':
|
case 'account':
|
||||||
this.scopeKey = 'accountid'
|
this.scopeKey = 'accountid'
|
||||||
@ -119,8 +119,6 @@ export default {
|
|||||||
default:
|
default:
|
||||||
this.scopeKey = ''
|
this.scopeKey = ''
|
||||||
}
|
}
|
||||||
},
|
|
||||||
created () {
|
|
||||||
this.fetchData()
|
this.fetchData()
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|||||||
@ -317,7 +317,7 @@ export default {
|
|||||||
label: 'label.action.reset.password',
|
label: 'label.action.reset.password',
|
||||||
message: 'message.action.instance.reset.password',
|
message: 'message.action.instance.reset.password',
|
||||||
dataView: true,
|
dataView: true,
|
||||||
show: (record) => { return ['Running', 'Stopped'].includes(record.state) && record.passwordenabled },
|
show: (record) => { return ['Stopped'].includes(record.state) && record.passwordenabled },
|
||||||
response: (result) => { return result.virtualmachine && result.virtualmachine.password ? `The password of VM <b>${result.virtualmachine.displayname}</b> is <b>${result.virtualmachine.password}</b>` : null }
|
response: (result) => { return result.virtualmachine && result.virtualmachine.password ? `The password of VM <b>${result.virtualmachine.displayname}</b> is <b>${result.virtualmachine.password}</b>` : null }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -249,6 +249,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resourceName = params.displayname || params.displaytext || params.name || this.resource.name
|
||||||
let hasJobId = false
|
let hasJobId = false
|
||||||
api(this.action.api, params).then(json => {
|
api(this.action.api, params).then(json => {
|
||||||
for (const obj in json) {
|
for (const obj in json) {
|
||||||
@ -270,6 +271,18 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasJobId) {
|
if (!hasJobId) {
|
||||||
|
var message = this.action.successMessage ? this.$t(this.action.successMessage) : this.$t(this.action.label) +
|
||||||
|
(resourceName ? ' - ' + resourceName : '')
|
||||||
|
var duration = 2
|
||||||
|
if (this.action.additionalMessage) {
|
||||||
|
message = message + ' - ' + this.$t(this.action.successMessage)
|
||||||
|
duration = 5
|
||||||
|
}
|
||||||
|
this.$message.success({
|
||||||
|
content: message,
|
||||||
|
key: this.action.label + resourceName,
|
||||||
|
duration: duration
|
||||||
|
})
|
||||||
this.parentUpdActionData(json)
|
this.parentUpdActionData(json)
|
||||||
this.parentFetchData()
|
this.parentFetchData()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -208,8 +208,18 @@
|
|||||||
:default-checked="xenServerProvider" />
|
:default-checked="xenServerProvider" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-row>
|
</a-row>
|
||||||
|
|
||||||
|
<a-form-item :label="$t('label.deployasis')" v-if="hyperVMWShow">
|
||||||
|
<a-switch
|
||||||
|
v-decorator="['deployasis', {
|
||||||
|
initialValue: false,
|
||||||
|
}]"
|
||||||
|
:checked="deployasis"
|
||||||
|
@change="val => deployasis = val"/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
<a-row :gutter="12" v-if="hyperKVMShow || hyperVMWShow">
|
<a-row :gutter="12" v-if="hyperKVMShow || hyperVMWShow">
|
||||||
<a-col :md="24" :lg="24" v-if="hyperKVMShow">
|
<a-col :md="24" :lg="24" v-if="hyperKVMShow || (hyperVMWShow && !deployasis)">
|
||||||
<a-form-item :label="$t('label.rootdiskcontrollertype')">
|
<a-form-item :label="$t('label.rootdiskcontrollertype')">
|
||||||
<a-select
|
<a-select
|
||||||
v-decorator="['rootDiskControllerType', {
|
v-decorator="['rootDiskControllerType', {
|
||||||
@ -230,7 +240,7 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :md="24" :lg="24">
|
<a-col :md="24" :lg="24">
|
||||||
<a-form-item v-if="hyperVMWShow" :label="$t('label.keyboardtype')">
|
<a-form-item v-if="hyperVMWShow && !deployasis" :label="$t('label.keyboardtype')">
|
||||||
<a-select
|
<a-select
|
||||||
v-decorator="['keyboardType', {
|
v-decorator="['keyboardType', {
|
||||||
rules: [
|
rules: [
|
||||||
@ -248,7 +258,7 @@
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-row :gutter="12" v-if="!hyperVMWShow">
|
<a-row :gutter="12" v-if="!hyperVMWShow || (hyperVMWShow && !deployasis)">
|
||||||
<a-col :md="24" :lg="24">
|
<a-col :md="24" :lg="24">
|
||||||
<a-form-item :label="$t('label.ostypeid')">
|
<a-form-item :label="$t('label.ostypeid')">
|
||||||
<a-select
|
<a-select
|
||||||
@ -378,6 +388,7 @@ export default {
|
|||||||
hyperKVMShow: false,
|
hyperKVMShow: false,
|
||||||
hyperXenServerShow: false,
|
hyperXenServerShow: false,
|
||||||
hyperVMWShow: false,
|
hyperVMWShow: false,
|
||||||
|
deployasis: false,
|
||||||
zoneError: '',
|
zoneError: '',
|
||||||
zoneErrorMessage: '',
|
zoneErrorMessage: '',
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -763,6 +774,7 @@ export default {
|
|||||||
this.hyperXenServerShow = false
|
this.hyperXenServerShow = false
|
||||||
this.hyperVMWShow = false
|
this.hyperVMWShow = false
|
||||||
this.hyperKVMShow = false
|
this.hyperKVMShow = false
|
||||||
|
this.deployasis = false
|
||||||
this.allowDirectDownload = false
|
this.allowDirectDownload = false
|
||||||
|
|
||||||
this.resetSelect()
|
this.resetSelect()
|
||||||
@ -794,10 +806,6 @@ export default {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
params[key] = input.join()
|
params[key] = input.join()
|
||||||
} else if (key === 'zoneid') {
|
|
||||||
params[key] = input
|
|
||||||
} else if (key === 'ostypeid') {
|
|
||||||
params[key] = input
|
|
||||||
} else if (key === 'hypervisor') {
|
} else if (key === 'hypervisor') {
|
||||||
params[key] = this.hyperVisor.opts[input].name
|
params[key] = this.hyperVisor.opts[input].name
|
||||||
} else if (key === 'groupenabled') {
|
} else if (key === 'groupenabled') {
|
||||||
|
|||||||
@ -64,10 +64,10 @@
|
|||||||
:maskClosable="false"
|
:maskClosable="false"
|
||||||
:footer="null"
|
:footer="null"
|
||||||
:cancelText="$t('label.cancel')"
|
:cancelText="$t('label.cancel')"
|
||||||
@cancel="showCreateForm = false"
|
@cancel="closeAction"
|
||||||
centered
|
centered
|
||||||
width="auto">
|
width="auto">
|
||||||
<CreateNetwork :resource="{ zoneid: resource.zoneid }"/>
|
<CreateNetwork :resource="{ zoneid: resource.zoneid }" @close-action="closeAction"/>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
|
|
||||||
</a-spin>
|
</a-spin>
|
||||||
@ -161,6 +161,9 @@ export default {
|
|||||||
handleOpenShowCreateForm () {
|
handleOpenShowCreateForm () {
|
||||||
this.showCreateForm = true
|
this.showCreateForm = true
|
||||||
},
|
},
|
||||||
|
closeAction () {
|
||||||
|
this.showCreateForm = false
|
||||||
|
},
|
||||||
changePage (page, pageSize) {
|
changePage (page, pageSize) {
|
||||||
this.page = page
|
this.page = page
|
||||||
this.pageSize = pageSize
|
this.pageSize = pageSize
|
||||||
|
|||||||
@ -82,7 +82,7 @@
|
|||||||
<div>{{ acl.traffictype }}</div>
|
<div>{{ acl.traffictype }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="list__col">
|
<div class="list__col">
|
||||||
<div class="list__label">{{ $t('label.reason') }}</div>
|
<div class="list__label">{{ $t('label.description') }}</div>
|
||||||
<div>{{ acl.reason }}</div>
|
<div>{{ acl.reason }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -184,7 +184,7 @@
|
|||||||
<a-select-option value="egress">{{ $t('label.egress') }}</a-select-option>
|
<a-select-option value="egress">{{ $t('label.egress') }}</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item :label="$t('label.reason')">
|
<a-form-item :label="$t('label.description')">
|
||||||
<a-textarea
|
<a-textarea
|
||||||
v-decorator="['reason']"
|
v-decorator="['reason']"
|
||||||
:autosize="{ minRows: 2 }"
|
:autosize="{ minRows: 2 }"
|
||||||
|
|||||||
@ -554,7 +554,7 @@ export default {
|
|||||||
vpcid: this.resource.vpcid
|
vpcid: this.resource.vpcid
|
||||||
}).then(json => {
|
}).then(json => {
|
||||||
this.tiers.data = json.listnetworksresponse.network || []
|
this.tiers.data = json.listnetworksresponse.network || []
|
||||||
this.selectedTier = this.tiers.data && this.tiers.data[0].id ? this.tiers.data[0].id : null
|
this.selectedTier = this.tiers.data?.[0]?.id ? this.tiers.data[0].id : null
|
||||||
this.$forceUpdate()
|
this.$forceUpdate()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.$notifyError(error)
|
this.$notifyError(error)
|
||||||
|
|||||||
@ -503,7 +503,6 @@ export default {
|
|||||||
this.addVmModalNicLoading = false
|
this.addVmModalNicLoading = false
|
||||||
this.nics = []
|
this.nics = []
|
||||||
this.resetTagInputs()
|
this.resetTagInputs()
|
||||||
this.resetAllRules()
|
|
||||||
},
|
},
|
||||||
openTagsModal (id) {
|
openTagsModal (id) {
|
||||||
this.tagsModalLoading = true
|
this.tagsModalLoading = true
|
||||||
|
|||||||
@ -385,7 +385,13 @@ export default {
|
|||||||
publicIps: {},
|
publicIps: {},
|
||||||
snats: {},
|
snats: {},
|
||||||
vms: {}
|
vms: {}
|
||||||
}
|
},
|
||||||
|
lbProviderMap: {
|
||||||
|
publicLb: {
|
||||||
|
vpc: ['VpcVirtualRouter', 'Netscaler']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
publicLBExists: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
@ -417,6 +423,7 @@ export default {
|
|||||||
this.fetchLoadBalancers(network.id)
|
this.fetchLoadBalancers(network.id)
|
||||||
this.fetchVMs(network.id)
|
this.fetchVMs(network.id)
|
||||||
}
|
}
|
||||||
|
this.publicLBNetworkExists()
|
||||||
},
|
},
|
||||||
fetchNetworkAclList () {
|
fetchNetworkAclList () {
|
||||||
this.fetchLoading = true
|
this.fetchLoading = true
|
||||||
@ -435,6 +442,38 @@ export default {
|
|||||||
this.modalLoading = false
|
this.modalLoading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
getNetworkOffering (networkId) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
api('listNetworkOfferings', {
|
||||||
|
id: networkId
|
||||||
|
}).then(json => {
|
||||||
|
var networkOffering = json.listnetworkofferingsresponse.networkoffering[0]
|
||||||
|
resolve(networkOffering)
|
||||||
|
}).catch(e => {
|
||||||
|
reject(e)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
publicLBNetworkExists () {
|
||||||
|
api('listNetworks', {
|
||||||
|
vpcid: this.resource.id,
|
||||||
|
supportedservices: 'LB'
|
||||||
|
}).then(async json => {
|
||||||
|
var lbNetworks = json.listnetworksresponse.network || []
|
||||||
|
if (lbNetworks.length > 0) {
|
||||||
|
this.publicLBExists = true
|
||||||
|
for (var idx = 0; idx < lbNetworks.length; idx++) {
|
||||||
|
const lbNetworkOffering = await this.getNetworkOffering(lbNetworks[idx].networkofferingid)
|
||||||
|
const index = lbNetworkOffering.service.map(svc => { return svc.name }).indexOf('Lb')
|
||||||
|
if (index !== -1 &&
|
||||||
|
this.lbProviderMap.publicLb.vpc.indexOf(lbNetworkOffering.service.map(svc => { return svc.provider[0].name })[index]) !== -1) {
|
||||||
|
this.publicLBExists = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
fetchNetworkOfferings () {
|
fetchNetworkOfferings () {
|
||||||
this.fetchLoading = true
|
this.fetchLoading = true
|
||||||
this.modalLoading = true
|
this.modalLoading = true
|
||||||
@ -445,6 +484,17 @@ export default {
|
|||||||
state: 'Enabled'
|
state: 'Enabled'
|
||||||
}).then(json => {
|
}).then(json => {
|
||||||
this.networkOfferings = json.listnetworkofferingsresponse.networkoffering || []
|
this.networkOfferings = json.listnetworkofferingsresponse.networkoffering || []
|
||||||
|
var filteredOfferings = []
|
||||||
|
if (this.publicLBExists) {
|
||||||
|
for (var index in this.networkOfferings) {
|
||||||
|
const offering = this.networkOfferings[index]
|
||||||
|
const idx = offering.service.map(svc => { return svc.name }).indexOf('Lb')
|
||||||
|
if (idx === -1 || this.lbProviderMap.publicLb.vpc.indexOf(offering.service.map(svc => { return svc.provider[0].name })[idx]) === -1) {
|
||||||
|
filteredOfferings.push(offering)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.networkOfferings = filteredOfferings
|
||||||
|
}
|
||||||
this.$nextTick(function () {
|
this.$nextTick(function () {
|
||||||
this.form.setFieldsValue({
|
this.form.setFieldsValue({
|
||||||
networkOffering: this.networkOfferings[0].id
|
networkOffering: this.networkOfferings[0].id
|
||||||
|
|||||||
@ -680,7 +680,7 @@
|
|||||||
:loading="domainLoading"
|
:loading="domainLoading"
|
||||||
:placeholder="this.$t('label.domainid')">
|
:placeholder="this.$t('label.domainid')">
|
||||||
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
||||||
{{ opt.name || opt.description }}
|
{{ opt.path || opt.name || opt.description }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
@ -368,7 +368,7 @@
|
|||||||
:loading="domainLoading"
|
:loading="domainLoading"
|
||||||
:placeholder="this.$t('label.domainid')">
|
:placeholder="this.$t('label.domainid')">
|
||||||
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
||||||
{{ opt.name || opt.description }}
|
{{ opt.path || opt.name || opt.description }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
@ -228,7 +228,7 @@
|
|||||||
message: `${this.$t('message.error.select')}`
|
message: `${this.$t('message.error.select')}`
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
initialValue: 0
|
initialValue: this.serviceOfferings.length > 0 ? this.serviceOfferings[0].id : ''
|
||||||
}]"
|
}]"
|
||||||
showSearch
|
showSearch
|
||||||
optionFilterProp="children"
|
optionFilterProp="children"
|
||||||
@ -237,7 +237,7 @@
|
|||||||
}"
|
}"
|
||||||
:loading="serviceOfferingLoading"
|
:loading="serviceOfferingLoading"
|
||||||
:placeholder="this.$t('label.serviceofferingid')">
|
:placeholder="this.$t('label.serviceofferingid')">
|
||||||
<a-select-option v-for="(opt, optIndex) in this.serviceOfferings" :key="optIndex">
|
<a-select-option v-for="(opt) in this.serviceOfferings" :key="opt.id">
|
||||||
{{ opt.name || opt.description }}
|
{{ opt.name || opt.description }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
@ -410,7 +410,7 @@
|
|||||||
:loading="domainLoading"
|
:loading="domainLoading"
|
||||||
:placeholder="this.$t('label.domain')">
|
:placeholder="this.$t('label.domain')">
|
||||||
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
||||||
{{ opt.name || opt.description }}
|
{{ opt.path || opt.name || opt.description }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
@ -108,7 +108,7 @@
|
|||||||
:loading="domainLoading"
|
:loading="domainLoading"
|
||||||
:placeholder="this.$t('label.domain')">
|
:placeholder="this.$t('label.domain')">
|
||||||
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
||||||
{{ opt.name || opt.description }}
|
{{ opt.path || opt.name || opt.description }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
:loading="domainLoading"
|
:loading="domainLoading"
|
||||||
:placeholder="this.apiParams.domainid.description">
|
:placeholder="this.apiParams.domainid.description">
|
||||||
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
<a-select-option v-for="(opt, optIndex) in this.domains" :key="optIndex">
|
||||||
{{ opt.name || opt.description }}
|
{{ opt.path || opt.name || opt.description }}
|
||||||
</a-select-option>
|
</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user