mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge branch '4.18' into main
This commit is contained in:
commit
05b9b6e2e7
@ -177,6 +177,9 @@ public class RegisterIsoCmd extends BaseCmd implements UserCmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Long getZoneId() {
|
public Long getZoneId() {
|
||||||
|
if (zoneId == null || zoneId == -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return zoneId;
|
return zoneId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +223,10 @@ public class RegisterIsoCmd extends BaseCmd implements UserCmd {
|
|||||||
return directDownload == null ? false : directDownload;
|
return directDownload == null ? false : directDownload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDirectDownload(Boolean directDownload) {
|
||||||
|
this.directDownload = directDownload;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPasswordEnabled() {
|
public boolean isPasswordEnabled() {
|
||||||
return passwordEnabled == null ? false : passwordEnabled;
|
return passwordEnabled == null ? false : passwordEnabled;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,11 +20,10 @@ package org.apache.cloudstack.storage.image;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
|
||||||
import org.apache.cloudstack.direct.download.DirectDownloadManager;
|
import org.apache.cloudstack.direct.download.DirectDownloadManager;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
@ -36,18 +35,21 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
|||||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
||||||
import org.apache.cloudstack.storage.image.store.TemplateObject;
|
import org.apache.cloudstack.storage.image.store.TemplateObject;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
import com.cloud.storage.VMTemplateStoragePoolVO;
|
import com.cloud.storage.VMTemplateStoragePoolVO;
|
||||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
import com.cloud.storage.dao.VMTemplateDao;
|
import com.cloud.storage.dao.VMTemplateDao;
|
||||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class TemplateDataFactoryImpl implements TemplateDataFactory {
|
public class TemplateDataFactoryImpl implements TemplateDataFactory {
|
||||||
@ -203,12 +205,7 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
|
|||||||
* Given existing spool refs, return one pool id existing on pools and refs
|
* Given existing spool refs, return one pool id existing on pools and refs
|
||||||
*/
|
*/
|
||||||
private Long getOneMatchingPoolIdFromRefs(List<VMTemplateStoragePoolVO> existingRefs, List<StoragePoolVO> pools) {
|
private Long getOneMatchingPoolIdFromRefs(List<VMTemplateStoragePoolVO> existingRefs, List<StoragePoolVO> pools) {
|
||||||
if (pools.isEmpty()) {
|
if (!existingRefs.isEmpty()) {
|
||||||
throw new CloudRuntimeException("No storage pools found");
|
|
||||||
}
|
|
||||||
if (existingRefs.isEmpty()) {
|
|
||||||
return pools.get(0).getId();
|
|
||||||
} else {
|
|
||||||
for (VMTemplateStoragePoolVO ref : existingRefs) {
|
for (VMTemplateStoragePoolVO ref : existingRefs) {
|
||||||
for (StoragePoolVO p : pools) {
|
for (StoragePoolVO p : pools) {
|
||||||
if (ref.getPoolId() == p.getId()) {
|
if (ref.getPoolId() == p.getId()) {
|
||||||
@ -217,45 +214,51 @@ public class TemplateDataFactoryImpl implements TemplateDataFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return pools.get(0).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve storage pools with scope = cluster or zone matching clusterId or dataCenterId depending on their scope
|
* Retrieve storage pools with scope = cluster or zone or local matching clusterId or dataCenterId or hostId depending on their scope
|
||||||
*/
|
*/
|
||||||
private List<StoragePoolVO> getStoragePoolsFromClusterOrZone(Long clusterId, long dataCenterId, Hypervisor.HypervisorType hypervisorType) {
|
private List<StoragePoolVO> getStoragePoolsForScope(long dataCenterId, Long clusterId, long hostId, Hypervisor.HypervisorType hypervisorType) {
|
||||||
List<StoragePoolVO> pools = new ArrayList<>();
|
List<StoragePoolVO> pools = new ArrayList<>();
|
||||||
if (clusterId != null) {
|
if (clusterId != null) {
|
||||||
List<StoragePoolVO> clusterPools = primaryDataStoreDao.listPoolsByCluster(clusterId);
|
List<StoragePoolVO> clusterPools = primaryDataStoreDao.listPoolsByCluster(clusterId);
|
||||||
|
clusterPools = clusterPools.stream().filter(p -> !p.isLocal()).collect(Collectors.toList());
|
||||||
pools.addAll(clusterPools);
|
pools.addAll(clusterPools);
|
||||||
}
|
}
|
||||||
List<StoragePoolVO> zonePools = primaryDataStoreDao.findZoneWideStoragePoolsByHypervisor(dataCenterId, hypervisorType);
|
List<StoragePoolVO> zonePools = primaryDataStoreDao.findZoneWideStoragePoolsByHypervisor(dataCenterId, hypervisorType);
|
||||||
pools.addAll(zonePools);
|
pools.addAll(zonePools);
|
||||||
|
List<StoragePoolVO> localPools = primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(hostId, null);
|
||||||
|
pools.addAll(localPools);
|
||||||
return pools;
|
return pools;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Long getBypassedTemplateExistingOrNewPoolId(VMTemplateVO templateVO, Long hostId) {
|
||||||
|
HostVO host = hostDao.findById(hostId);
|
||||||
|
List<StoragePoolVO> pools = getStoragePoolsForScope(host.getDataCenterId(), host.getClusterId(), hostId, host.getHypervisorType());
|
||||||
|
if (CollectionUtils.isEmpty(pools)) {
|
||||||
|
throw new CloudRuntimeException(String.format("No storage pool found to download template: %s", templateVO.getName()));
|
||||||
|
}
|
||||||
|
List<VMTemplateStoragePoolVO> existingRefs = templatePoolDao.listByTemplateId(templateVO.getId());
|
||||||
|
return getOneMatchingPoolIdFromRefs(existingRefs, pools);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TemplateInfo getReadyBypassedTemplateOnPrimaryStore(long templateId, Long poolId, Long hostId) {
|
public TemplateInfo getReadyBypassedTemplateOnPrimaryStore(long templateId, Long poolId, Long hostId) {
|
||||||
VMTemplateVO templateVO = imageDataDao.findById(templateId);
|
VMTemplateVO templateVO = imageDataDao.findById(templateId);
|
||||||
if (templateVO == null || !templateVO.isDirectDownload()) {
|
if (templateVO == null || !templateVO.isDirectDownload()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Long pool = poolId;
|
Long templatePoolId = poolId;
|
||||||
if (poolId == null) {
|
if (poolId == null) {
|
||||||
//Get ISO from existing pool ref
|
templatePoolId = getBypassedTemplateExistingOrNewPoolId(templateVO, hostId);
|
||||||
HostVO host = hostDao.findById(hostId);
|
|
||||||
List<StoragePoolVO> pools = getStoragePoolsFromClusterOrZone(host.getClusterId(), host.getDataCenterId(), host.getHypervisorType());
|
|
||||||
List<VMTemplateStoragePoolVO> existingRefs = templatePoolDao.listByTemplateId(templateId);
|
|
||||||
pool = getOneMatchingPoolIdFromRefs(existingRefs, pools);
|
|
||||||
}
|
}
|
||||||
if (pool == null) {
|
VMTemplateStoragePoolVO spoolRef = templatePoolDao.findByPoolTemplate(templatePoolId, templateId, null);
|
||||||
throw new CloudRuntimeException("No storage pool found where to download template: " + templateId);
|
|
||||||
}
|
|
||||||
VMTemplateStoragePoolVO spoolRef = templatePoolDao.findByPoolTemplate(pool, templateId, null);
|
|
||||||
if (spoolRef == null) {
|
if (spoolRef == null) {
|
||||||
directDownloadManager.downloadTemplate(templateId, pool, hostId);
|
directDownloadManager.downloadTemplate(templateId, templatePoolId, hostId);
|
||||||
}
|
}
|
||||||
DataStore store = storeMgr.getDataStore(pool, DataStoreRole.Primary);
|
DataStore store = storeMgr.getDataStore(templatePoolId, DataStoreRole.Primary);
|
||||||
return this.getTemplate(templateId, store);
|
return this.getTemplate(templateId, store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -294,12 +294,14 @@ public class KVMStoragePoolManager {
|
|||||||
String uuid = null;
|
String uuid = null;
|
||||||
String sourceHost = "";
|
String sourceHost = "";
|
||||||
StoragePoolType protocol = null;
|
StoragePoolType protocol = null;
|
||||||
if (storageUri.getScheme().equalsIgnoreCase("nfs") || storageUri.getScheme().equalsIgnoreCase("NetworkFilesystem")) {
|
final String scheme = storageUri.getScheme().toLowerCase();
|
||||||
|
List<String> acceptedSchemes = List.of("nfs", "networkfilesystem", "filesystem");
|
||||||
|
if (acceptedSchemes.contains(scheme)) {
|
||||||
sourcePath = storageUri.getPath();
|
sourcePath = storageUri.getPath();
|
||||||
sourcePath = sourcePath.replace("//", "/");
|
sourcePath = sourcePath.replace("//", "/");
|
||||||
sourceHost = storageUri.getHost();
|
sourceHost = storageUri.getHost();
|
||||||
uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString();
|
uuid = UUID.nameUUIDFromBytes(new String(sourceHost + sourcePath).getBytes()).toString();
|
||||||
protocol = StoragePoolType.NetworkFilesystem;
|
protocol = scheme.equals("filesystem") ? StoragePoolType.Filesystem: StoragePoolType.NetworkFilesystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// secondary storage registers itself through here
|
// secondary storage registers itself through here
|
||||||
|
|||||||
@ -25,23 +25,26 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import org.apache.cloudstack.direct.download.DirectDownloadHelper;
|
|
||||||
import org.apache.cloudstack.direct.download.DirectTemplateDownloader;
|
|
||||||
import com.cloud.storage.ScopeType;
|
|
||||||
import com.cloud.storage.Volume;
|
|
||||||
import org.apache.cloudstack.agent.directdownload.DirectDownloadAnswer;
|
import org.apache.cloudstack.agent.directdownload.DirectDownloadAnswer;
|
||||||
import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand;
|
import org.apache.cloudstack.agent.directdownload.DirectDownloadCommand;
|
||||||
|
import org.apache.cloudstack.direct.download.DirectDownloadHelper;
|
||||||
|
import org.apache.cloudstack.direct.download.DirectTemplateDownloader;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
|
||||||
import org.apache.cloudstack.storage.command.AttachAnswer;
|
import org.apache.cloudstack.storage.command.AttachAnswer;
|
||||||
import org.apache.cloudstack.storage.command.AttachCommand;
|
import org.apache.cloudstack.storage.command.AttachCommand;
|
||||||
@ -71,7 +74,10 @@ import org.apache.cloudstack.utils.qemu.QemuImgFile;
|
|||||||
import org.apache.cloudstack.utils.qemu.QemuObject;
|
import org.apache.cloudstack.utils.qemu.QemuObject;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
import org.libvirt.Connect;
|
import org.libvirt.Connect;
|
||||||
import org.libvirt.Domain;
|
import org.libvirt.Domain;
|
||||||
@ -110,9 +116,11 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.DiskDef.DiskProtocol;
|
|||||||
import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper;
|
import com.cloud.hypervisor.kvm.resource.wrapper.LibvirtUtilitiesHelper;
|
||||||
import com.cloud.storage.JavaStorageLayer;
|
import com.cloud.storage.JavaStorageLayer;
|
||||||
import com.cloud.storage.MigrationOptions;
|
import com.cloud.storage.MigrationOptions;
|
||||||
|
import com.cloud.storage.ScopeType;
|
||||||
import com.cloud.storage.Storage.ImageFormat;
|
import com.cloud.storage.Storage.ImageFormat;
|
||||||
import com.cloud.storage.Storage.StoragePoolType;
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
import com.cloud.storage.StorageLayer;
|
import com.cloud.storage.StorageLayer;
|
||||||
|
import com.cloud.storage.Volume;
|
||||||
import com.cloud.storage.resource.StorageProcessor;
|
import com.cloud.storage.resource.StorageProcessor;
|
||||||
import com.cloud.storage.template.Processor;
|
import com.cloud.storage.template.Processor;
|
||||||
import com.cloud.storage.template.Processor.FormatInfo;
|
import com.cloud.storage.template.Processor.FormatInfo;
|
||||||
@ -126,16 +134,6 @@ import com.cloud.utils.script.Script;
|
|||||||
import com.cloud.utils.storage.S3.S3Utils;
|
import com.cloud.utils.storage.S3.S3Utils;
|
||||||
import com.cloud.vm.VmDetailConstants;
|
import com.cloud.vm.VmDetailConstants;
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
|
||||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
|
||||||
|
|
||||||
public class KVMStorageProcessor implements StorageProcessor {
|
public class KVMStorageProcessor implements StorageProcessor {
|
||||||
private static final Logger s_logger = Logger.getLogger(KVMStorageProcessor.class);
|
private static final Logger s_logger = Logger.getLogger(KVMStorageProcessor.class);
|
||||||
private final KVMStoragePoolManager storagePoolMgr;
|
private final KVMStoragePoolManager storagePoolMgr;
|
||||||
@ -1074,7 +1072,8 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
s_logger.debug(String.format("This backup is temporary, not deleting snapshot [%s] on primary storage [%s]", snapshotPath, primaryPool.getUuid()));
|
s_logger.debug(String.format("This backup is temporary, not deleting snapshot [%s] on primary storage [%s]", snapshotPath, primaryPool.getUuid()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected synchronized void attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach, Map<String, String> params) throws
|
|
||||||
|
protected synchronized void attachOrDetachISO(final Connect conn, final String vmName, String isoPath, final boolean isAttach, Map<String, String> params, DataStoreTO store) throws
|
||||||
LibvirtException, InternalErrorException {
|
LibvirtException, InternalErrorException {
|
||||||
DiskDef iso = new DiskDef();
|
DiskDef iso = new DiskDef();
|
||||||
boolean isUefiEnabled = MapUtils.isNotEmpty(params) && params.containsKey("UEFI");
|
boolean isUefiEnabled = MapUtils.isNotEmpty(params) && params.containsKey("UEFI");
|
||||||
@ -1082,8 +1081,14 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
final int index = isoPath.lastIndexOf("/");
|
final int index = isoPath.lastIndexOf("/");
|
||||||
final String path = isoPath.substring(0, index);
|
final String path = isoPath.substring(0, index);
|
||||||
final String name = isoPath.substring(index + 1);
|
final String name = isoPath.substring(index + 1);
|
||||||
final KVMStoragePool secondaryPool = storagePoolMgr.getStoragePoolByURI(path);
|
KVMStoragePool storagePool;
|
||||||
final KVMPhysicalDisk isoVol = secondaryPool.getPhysicalDisk(name);
|
if (store instanceof PrimaryDataStoreTO) {
|
||||||
|
PrimaryDataStoreTO primaryDataStoreTO = (PrimaryDataStoreTO)store;
|
||||||
|
storagePool = storagePoolMgr.getStoragePool(primaryDataStoreTO.getPoolType(), store.getUuid());
|
||||||
|
} else {
|
||||||
|
storagePool = storagePoolMgr.getStoragePoolByURI(path);
|
||||||
|
}
|
||||||
|
final KVMPhysicalDisk isoVol = storagePool.getPhysicalDisk(name);
|
||||||
isoPath = isoVol.getPath();
|
isoPath = isoVol.getPath();
|
||||||
|
|
||||||
iso.defISODisk(isoPath, isUefiEnabled);
|
iso.defISODisk(isoPath, isUefiEnabled);
|
||||||
@ -1112,7 +1117,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
try {
|
try {
|
||||||
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
||||||
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||||
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), true, cmd.getControllerInfo());
|
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), true, cmd.getControllerInfo(), store);
|
||||||
} catch (final LibvirtException e) {
|
} catch (final LibvirtException e) {
|
||||||
return new Answer(cmd, false, e.toString());
|
return new Answer(cmd, false, e.toString());
|
||||||
} catch (final InternalErrorException e) {
|
} catch (final InternalErrorException e) {
|
||||||
@ -1133,7 +1138,7 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
try {
|
try {
|
||||||
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
String dataStoreUrl = getDataStoreUrlFromStore(store);
|
||||||
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
final Connect conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName());
|
||||||
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), false, cmd.getParams());
|
attachOrDetachISO(conn, cmd.getVmName(), dataStoreUrl + File.separator + isoTO.getPath(), false, cmd.getParams(), store);
|
||||||
} catch (final LibvirtException e) {
|
} catch (final LibvirtException e) {
|
||||||
return new Answer(cmd, false, e.toString());
|
return new Answer(cmd, false, e.toString());
|
||||||
} catch (final InternalErrorException e) {
|
} catch (final InternalErrorException e) {
|
||||||
@ -1149,19 +1154,25 @@ public class KVMStorageProcessor implements StorageProcessor {
|
|||||||
* Return data store URL from store
|
* Return data store URL from store
|
||||||
*/
|
*/
|
||||||
private String getDataStoreUrlFromStore(DataStoreTO store) {
|
private String getDataStoreUrlFromStore(DataStoreTO store) {
|
||||||
if (!(store instanceof NfsTO) && (!(store instanceof PrimaryDataStoreTO) ||
|
List<StoragePoolType> supportedPoolType = List.of(StoragePoolType.NetworkFilesystem, StoragePoolType.Filesystem);
|
||||||
store instanceof PrimaryDataStoreTO && !((PrimaryDataStoreTO) store).getPoolType().equals(StoragePoolType.NetworkFilesystem))) {
|
if (!(store instanceof NfsTO) && (!(store instanceof PrimaryDataStoreTO) || !supportedPoolType.contains(((PrimaryDataStoreTO) store).getPoolType()))) {
|
||||||
|
s_logger.error(String.format("Unsupported protocol, store: %s", store.getUuid()));
|
||||||
throw new InvalidParameterValueException("unsupported protocol");
|
throw new InvalidParameterValueException("unsupported protocol");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (store instanceof NfsTO) {
|
if (store instanceof NfsTO) {
|
||||||
NfsTO nfsStore = (NfsTO)store;
|
NfsTO nfsStore = (NfsTO)store;
|
||||||
return nfsStore.getUrl();
|
return nfsStore.getUrl();
|
||||||
} else if (store instanceof PrimaryDataStoreTO && ((PrimaryDataStoreTO) store).getPoolType().equals(StoragePoolType.NetworkFilesystem)) {
|
} else if (store instanceof PrimaryDataStoreTO) {
|
||||||
//In order to support directly downloaded ISOs
|
//In order to support directly downloaded ISOs
|
||||||
|
StoragePoolType poolType = ((PrimaryDataStoreTO)store).getPoolType();
|
||||||
String psHost = ((PrimaryDataStoreTO) store).getHost();
|
String psHost = ((PrimaryDataStoreTO) store).getHost();
|
||||||
String psPath = ((PrimaryDataStoreTO) store).getPath();
|
String psPath = ((PrimaryDataStoreTO) store).getPath();
|
||||||
return "nfs://" + psHost + File.separator + psPath;
|
if (StoragePoolType.NetworkFilesystem.equals(poolType)) {
|
||||||
|
return "nfs://" + psHost + File.separator + psPath;
|
||||||
|
} else if (StoragePoolType.Filesystem.equals(poolType)) {
|
||||||
|
return StoragePoolType.Filesystem.toString().toLowerCase() + "://" + psHost + File.separator + psPath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return store.getUrl();
|
return store.getUrl();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,6 +128,7 @@ import com.cloud.network.dao.IPAddressVO;
|
|||||||
import com.cloud.network.dao.NetworkDao;
|
import com.cloud.network.dao.NetworkDao;
|
||||||
import com.cloud.network.dao.NetworkVO;
|
import com.cloud.network.dao.NetworkVO;
|
||||||
import com.cloud.network.dao.PhysicalNetworkDao;
|
import com.cloud.network.dao.PhysicalNetworkDao;
|
||||||
|
import com.cloud.network.router.NetworkHelper;
|
||||||
import com.cloud.network.rules.FirewallRule;
|
import com.cloud.network.rules.FirewallRule;
|
||||||
import com.cloud.network.rules.FirewallRuleVO;
|
import com.cloud.network.rules.FirewallRuleVO;
|
||||||
import com.cloud.network.security.SecurityGroupManager;
|
import com.cloud.network.security.SecurityGroupManager;
|
||||||
@ -253,6 +254,8 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||||||
private SecurityGroupManager securityGroupManager;
|
private SecurityGroupManager securityGroupManager;
|
||||||
@Inject
|
@Inject
|
||||||
public SecurityGroupService securityGroupService;
|
public SecurityGroupService securityGroupService;
|
||||||
|
@Inject
|
||||||
|
public NetworkHelper networkHelper;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private UserVmService userVmService;
|
private UserVmService userVmService;
|
||||||
@ -360,8 +363,12 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||||||
|
|
||||||
public VMTemplateVO getKubernetesServiceTemplate(DataCenter dataCenter, Hypervisor.HypervisorType hypervisorType) {
|
public VMTemplateVO getKubernetesServiceTemplate(DataCenter dataCenter, Hypervisor.HypervisorType hypervisorType) {
|
||||||
VMTemplateVO template = templateDao.findSystemVMReadyTemplate(dataCenter.getId(), hypervisorType);
|
VMTemplateVO template = templateDao.findSystemVMReadyTemplate(dataCenter.getId(), hypervisorType);
|
||||||
|
if (DataCenter.Type.Edge.equals(dataCenter.getType()) && template != null && !template.isDirectDownload()) {
|
||||||
|
LOGGER.debug(String.format("Template %s can not be used for edge zone %s", template, dataCenter));
|
||||||
|
template = templateDao.findRoutingTemplate(hypervisorType, networkHelper.getHypervisorRouterTemplateConfigMap().get(hypervisorType).valueIn(dataCenter.getId()));
|
||||||
|
}
|
||||||
if (template == null) {
|
if (template == null) {
|
||||||
throw new CloudRuntimeException("Not able to find the System templates or not downloaded in zone " + dataCenter.getId());
|
throw new CloudRuntimeException("Not able to find the System or Routing template in ready state for the zone " + dataCenter.getUuid());
|
||||||
}
|
}
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
@ -628,7 +635,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataCenter validateAndGetZoneForKubernetesCreateParameters(Long zoneId) {
|
private DataCenter validateAndGetZoneForKubernetesCreateParameters(Long zoneId, Long networkId) {
|
||||||
DataCenter zone = dataCenterDao.findById(zoneId);
|
DataCenter zone = dataCenterDao.findById(zoneId);
|
||||||
if (zone == null) {
|
if (zone == null) {
|
||||||
throw new InvalidParameterValueException("Unable to find zone by ID: " + zoneId);
|
throw new InvalidParameterValueException("Unable to find zone by ID: " + zoneId);
|
||||||
@ -636,6 +643,9 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||||||
if (zone.getAllocationState() == Grouping.AllocationState.Disabled) {
|
if (zone.getAllocationState() == Grouping.AllocationState.Disabled) {
|
||||||
throw new PermissionDeniedException(String.format("Cannot perform this operation, zone ID: %s is currently disabled", zone.getUuid()));
|
throw new PermissionDeniedException(String.format("Cannot perform this operation, zone ID: %s is currently disabled", zone.getUuid()));
|
||||||
}
|
}
|
||||||
|
if (DataCenter.Type.Edge.equals(zone.getType()) && networkId == null) {
|
||||||
|
throw new PermissionDeniedException("Kubernetes clusters cannot be created on an edge zone without an existing network");
|
||||||
|
}
|
||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,7 +685,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||||||
throw new InvalidParameterValueException("Invalid name for the Kubernetes cluster name: " + name);
|
throw new InvalidParameterValueException("Invalid name for the Kubernetes cluster name: " + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
validateAndGetZoneForKubernetesCreateParameters(zoneId);
|
validateAndGetZoneForKubernetesCreateParameters(zoneId, networkId);
|
||||||
validateSshKeyPairForKubernetesCreateParameters(sshKeyPair, owner);
|
validateSshKeyPairForKubernetesCreateParameters(sshKeyPair, owner);
|
||||||
|
|
||||||
if (nodeRootDiskSize != null && nodeRootDiskSize <= 0) {
|
if (nodeRootDiskSize != null && nodeRootDiskSize <= 0) {
|
||||||
@ -751,7 +761,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne
|
|||||||
String.format("Maximum cluster size can not exceed %d. Please contact your administrator", maxClusterSize));
|
String.format("Maximum cluster size can not exceed %d. Please contact your administrator", maxClusterSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
DataCenter zone = validateAndGetZoneForKubernetesCreateParameters(zoneId);
|
DataCenter zone = validateAndGetZoneForKubernetesCreateParameters(zoneId, networkId);
|
||||||
|
|
||||||
if (!isKubernetesServiceConfigured(zone)) {
|
if (!isKubernetesServiceConfigured(zone)) {
|
||||||
throw new CloudRuntimeException("Kubernetes service has not been configured properly to provision Kubernetes clusters");
|
throw new CloudRuntimeException("Kubernetes service has not been configured properly to provision Kubernetes clusters");
|
||||||
|
|||||||
@ -31,10 +31,12 @@ import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
|
|||||||
import org.apache.cloudstack.api.command.user.kubernetes.version.ListKubernetesSupportedVersionsCmd;
|
import org.apache.cloudstack.api.command.user.kubernetes.version.ListKubernetesSupportedVersionsCmd;
|
||||||
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
|
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
|
||||||
import org.apache.cloudstack.api.response.ListResponse;
|
import org.apache.cloudstack.api.response.ListResponse;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.api.query.dao.TemplateJoinDao;
|
import com.cloud.api.query.dao.TemplateJoinDao;
|
||||||
import com.cloud.api.query.vo.TemplateJoinVO;
|
import com.cloud.api.query.vo.TemplateJoinVO;
|
||||||
|
import com.cloud.dc.DataCenter;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
import com.cloud.event.ActionEvent;
|
import com.cloud.event.ActionEvent;
|
||||||
@ -56,7 +58,6 @@ import com.cloud.utils.db.Filter;
|
|||||||
import com.cloud.utils.db.SearchBuilder;
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
import com.cloud.utils.db.SearchCriteria;
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
public class KubernetesVersionManagerImpl extends ManagerBase implements KubernetesVersionService {
|
public class KubernetesVersionManagerImpl extends ManagerBase implements KubernetesVersionService {
|
||||||
public static final Logger LOGGER = Logger.getLogger(KubernetesVersionManagerImpl.class.getName());
|
public static final Logger LOGGER = Logger.getLogger(KubernetesVersionManagerImpl.class.getName());
|
||||||
@ -104,6 +105,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
response.setIsoId(template.getUuid());
|
response.setIsoId(template.getUuid());
|
||||||
response.setIsoName(template.getName());
|
response.setIsoName(template.getName());
|
||||||
response.setIsoState(template.getState().toString());
|
response.setIsoState(template.getState().toString());
|
||||||
|
response.setDirectDownload(template.isDirectDownload());
|
||||||
}
|
}
|
||||||
response.setCreated(kubernetesSupportedVersion.getCreated());
|
response.setCreated(kubernetesSupportedVersion.getCreated());
|
||||||
return response;
|
return response;
|
||||||
@ -147,7 +149,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
return versions;
|
return versions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private VirtualMachineTemplate registerKubernetesVersionIso(final Long zoneId, final String versionName, final String isoUrl, final String isoChecksum)throws IllegalAccessException, NoSuchFieldException,
|
private VirtualMachineTemplate registerKubernetesVersionIso(final Long zoneId, final String versionName, final String isoUrl, final String isoChecksum, final boolean directDownload) throws IllegalAccessException, NoSuchFieldException,
|
||||||
IllegalArgumentException, ResourceAllocationException {
|
IllegalArgumentException, ResourceAllocationException {
|
||||||
String isoName = String.format("%s-Kubernetes-Binaries-ISO", versionName);
|
String isoName = String.format("%s-Kubernetes-Binaries-ISO", versionName);
|
||||||
RegisterIsoCmd registerIsoCmd = new RegisterIsoCmd();
|
RegisterIsoCmd registerIsoCmd = new RegisterIsoCmd();
|
||||||
@ -163,6 +165,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
if (StringUtils.isNotEmpty(isoChecksum)) {
|
if (StringUtils.isNotEmpty(isoChecksum)) {
|
||||||
registerIsoCmd.setChecksum(isoChecksum);
|
registerIsoCmd.setChecksum(isoChecksum);
|
||||||
}
|
}
|
||||||
|
registerIsoCmd.setDirectDownload(directDownload);
|
||||||
registerIsoCmd.setAccountName(accountManager.getSystemAccount().getAccountName());
|
registerIsoCmd.setAccountName(accountManager.getSystemAccount().getAccountName());
|
||||||
registerIsoCmd.setDomainId(accountManager.getSystemAccount().getDomainId());
|
registerIsoCmd.setDomainId(accountManager.getSystemAccount().getDomainId());
|
||||||
return templateService.registerIso(registerIsoCmd);
|
return templateService.registerIso(registerIsoCmd);
|
||||||
@ -288,6 +291,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
final String isoChecksum = cmd.getChecksum();
|
final String isoChecksum = cmd.getChecksum();
|
||||||
final Integer minimumCpu = cmd.getMinimumCpu();
|
final Integer minimumCpu = cmd.getMinimumCpu();
|
||||||
final Integer minimumRamSize = cmd.getMinimumRamSize();
|
final Integer minimumRamSize = cmd.getMinimumRamSize();
|
||||||
|
final boolean isDirectDownload = cmd.isDirectDownload();
|
||||||
if (minimumCpu == null || minimumCpu < KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU) {
|
if (minimumCpu == null || minimumCpu < KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU) {
|
||||||
throw new InvalidParameterValueException(String.format("Invalid value for %s parameter. Minimum %d vCPUs required.", ApiConstants.MIN_CPU_NUMBER, KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU));
|
throw new InvalidParameterValueException(String.format("Invalid value for %s parameter. Minimum %d vCPUs required.", ApiConstants.MIN_CPU_NUMBER, KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_CPU));
|
||||||
}
|
}
|
||||||
@ -297,8 +301,14 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
if (compareSemanticVersions(semanticVersion, MIN_KUBERNETES_VERSION) < 0) {
|
if (compareSemanticVersions(semanticVersion, MIN_KUBERNETES_VERSION) < 0) {
|
||||||
throw new InvalidParameterValueException(String.format("New supported Kubernetes version cannot be added as %s is minimum version supported by Kubernetes Service", MIN_KUBERNETES_VERSION));
|
throw new InvalidParameterValueException(String.format("New supported Kubernetes version cannot be added as %s is minimum version supported by Kubernetes Service", MIN_KUBERNETES_VERSION));
|
||||||
}
|
}
|
||||||
if (zoneId != null && dataCenterDao.findById(zoneId) == null) {
|
if (zoneId != null) {
|
||||||
throw new InvalidParameterValueException("Invalid zone specified");
|
DataCenter zone = dataCenterDao.findById(zoneId);
|
||||||
|
if (zone == null) {
|
||||||
|
throw new InvalidParameterValueException("Invalid zone specified");
|
||||||
|
}
|
||||||
|
if (DataCenter.Type.Edge.equals(zone.getType()) && !isDirectDownload) {
|
||||||
|
throw new InvalidParameterValueException(String.format("Zone: %s supports only direct download Kubernetes versions", zone.getName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.isEmpty(isoUrl)) {
|
if (StringUtils.isEmpty(isoUrl)) {
|
||||||
throw new InvalidParameterValueException(String.format("Invalid URL for ISO specified, %s", isoUrl));
|
throw new InvalidParameterValueException(String.format("Invalid URL for ISO specified, %s", isoUrl));
|
||||||
@ -312,7 +322,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
|
|
||||||
VMTemplateVO template = null;
|
VMTemplateVO template = null;
|
||||||
try {
|
try {
|
||||||
VirtualMachineTemplate vmTemplate = registerKubernetesVersionIso(zoneId, name, isoUrl, isoChecksum);
|
VirtualMachineTemplate vmTemplate = registerKubernetesVersionIso(zoneId, name, isoUrl, isoChecksum, isDirectDownload);
|
||||||
template = templateDao.findById(vmTemplate.getId());
|
template = templateDao.findById(vmTemplate.getId());
|
||||||
} catch (IllegalAccessException | NoSuchFieldException | IllegalArgumentException | ResourceAllocationException ex) {
|
} catch (IllegalAccessException | NoSuchFieldException | IllegalArgumentException | ResourceAllocationException ex) {
|
||||||
LOGGER.error(String.format("Unable to register binaries ISO for supported kubernetes version, %s, with url: %s", name, isoUrl), ex);
|
LOGGER.error(String.format("Unable to register binaries ISO for supported kubernetes version, %s, with url: %s", name, isoUrl), ex);
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import org.apache.cloudstack.api.command.admin.AdminCmd;
|
|||||||
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
|
import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse;
|
||||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.exception.ConcurrentOperationException;
|
import com.cloud.exception.ConcurrentOperationException;
|
||||||
@ -38,7 +39,6 @@ import com.cloud.exception.InvalidParameterValueException;
|
|||||||
import com.cloud.kubernetes.version.KubernetesSupportedVersion;
|
import com.cloud.kubernetes.version.KubernetesSupportedVersion;
|
||||||
import com.cloud.kubernetes.version.KubernetesVersionService;
|
import com.cloud.kubernetes.version.KubernetesVersionService;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
@APICommand(name = "addKubernetesSupportedVersion",
|
@APICommand(name = "addKubernetesSupportedVersion",
|
||||||
description = "Add a supported Kubernetes version",
|
description = "Add a supported Kubernetes version",
|
||||||
@ -84,6 +84,10 @@ public class AddKubernetesSupportedVersionCmd extends BaseCmd implements AdminCm
|
|||||||
description = "the minimum RAM size in MB to be set with the Kubernetes version")
|
description = "the minimum RAM size in MB to be set with the Kubernetes version")
|
||||||
private Integer minimumRamSize;
|
private Integer minimumRamSize;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.DIRECT_DOWNLOAD, type = CommandType.BOOLEAN, since="4.18.2",
|
||||||
|
description = "If set to true the Kubernetes supported version ISO will bypass Secondary Storage and be downloaded to Primary Storage on deployment. Default is false")
|
||||||
|
private Boolean directDownload;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -123,6 +127,10 @@ public class AddKubernetesSupportedVersionCmd extends BaseCmd implements AdminCm
|
|||||||
return minimumRamSize;
|
return minimumRamSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDirectDownload() {
|
||||||
|
return (directDownload != null) ? directDownload : false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getEntityOwnerId() {
|
public long getEntityOwnerId() {
|
||||||
return CallContext.current().getCallingAccountId();
|
return CallContext.current().getCallingAccountId();
|
||||||
|
|||||||
@ -86,6 +86,10 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
|
|||||||
@Param(description = "the date when this Kubernetes supported version was created")
|
@Param(description = "the date when this Kubernetes supported version was created")
|
||||||
private Date created;
|
private Date created;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.DIRECT_DOWNLOAD)
|
||||||
|
@Param(description = "KVM Only: true if the ISO for the Kubernetes supported version is directly downloaded to Primary Storage bypassing Secondary Storage", since = "4.18.2")
|
||||||
|
private Boolean directDownload;
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -193,4 +197,8 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
|
|||||||
public void setCreated(Date created) {
|
public void setCreated(Date created) {
|
||||||
this.created = created;
|
this.created = created;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDirectDownload(Boolean directDownload) {
|
||||||
|
this.directDownload = directDownload;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
|
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.NicTO;
|
import com.cloud.agent.api.to.NicTO;
|
||||||
@ -93,4 +94,6 @@ public interface NetworkHelper {
|
|||||||
throws ConcurrentOperationException, InsufficientAddressCapacityException;
|
throws ConcurrentOperationException, InsufficientAddressCapacityException;
|
||||||
|
|
||||||
public boolean validateHAProxyLBRule(final LoadBalancingRule rule);
|
public boolean validateHAProxyLBRule(final LoadBalancingRule rule);
|
||||||
|
|
||||||
|
public Map<HypervisorType, ConfigKey<String>> getHypervisorRouterTemplateConfigMap();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,6 @@ import java.util.Map;
|
|||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import com.cloud.utils.validation.ChecksumUtil;
|
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||||
@ -102,6 +101,7 @@ import com.cloud.user.dao.UserDao;
|
|||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.utils.net.NetUtils;
|
import com.cloud.utils.net.NetUtils;
|
||||||
|
import com.cloud.utils.validation.ChecksumUtil;
|
||||||
import com.cloud.vm.DomainRouterVO;
|
import com.cloud.vm.DomainRouterVO;
|
||||||
import com.cloud.vm.Nic;
|
import com.cloud.vm.Nic;
|
||||||
import com.cloud.vm.NicProfile;
|
import com.cloud.vm.NicProfile;
|
||||||
@ -969,4 +969,9 @@ public class NetworkHelperImpl implements NetworkHelper {
|
|||||||
public String acquireGuestIpAddressForVrouterRedundant(Network network) {
|
public String acquireGuestIpAddressForVrouterRedundant(Network network) {
|
||||||
return _ipAddrMgr.acquireGuestIpAddressByPlacement(network, null);
|
return _ipAddrMgr.acquireGuestIpAddressByPlacement(network, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<HypervisorType, ConfigKey<String>> getHypervisorRouterTemplateConfigMap() {
|
||||||
|
return hypervisorsMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -342,7 +342,6 @@ export default {
|
|||||||
const listZones = json.listzonesresponse.zone
|
const listZones = json.listzonesresponse.zone
|
||||||
if (listZones) {
|
if (listZones) {
|
||||||
this.zones = this.zones.concat(listZones)
|
this.zones = this.zones.concat(listZones)
|
||||||
this.zones = this.zones.filter(zone => zone.type !== 'Edge')
|
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.zoneLoading = false
|
this.zoneLoading = false
|
||||||
@ -355,6 +354,7 @@ export default {
|
|||||||
handleZoneChange (zone) {
|
handleZoneChange (zone) {
|
||||||
this.selectedZone = zone
|
this.selectedZone = zone
|
||||||
this.fetchKubernetesVersionData()
|
this.fetchKubernetesVersionData()
|
||||||
|
this.fetchNetworkData()
|
||||||
},
|
},
|
||||||
fetchKubernetesVersionData () {
|
fetchKubernetesVersionData () {
|
||||||
this.kubernetesVersions = []
|
this.kubernetesVersions = []
|
||||||
@ -413,10 +413,14 @@ export default {
|
|||||||
},
|
},
|
||||||
fetchNetworkData () {
|
fetchNetworkData () {
|
||||||
const params = {}
|
const params = {}
|
||||||
|
if (!this.isObjectEmpty(this.selectedZone)) {
|
||||||
|
params.zoneid = this.selectedZone.id
|
||||||
|
}
|
||||||
this.networkLoading = true
|
this.networkLoading = true
|
||||||
api('listNetworks', params).then(json => {
|
api('listNetworks', params).then(json => {
|
||||||
const listNetworks = json.listnetworksresponse.network
|
var listNetworks = json.listnetworksresponse.network
|
||||||
if (this.arrayHasItems(listNetworks)) {
|
if (this.arrayHasItems(listNetworks)) {
|
||||||
|
listNetworks = listNetworks.filter(n => n.type !== 'L2')
|
||||||
this.networks = this.networks.concat(listNetworks)
|
this.networks = this.networks.concat(listNetworks)
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
|||||||
@ -221,16 +221,19 @@ export default {
|
|||||||
|
|
||||||
this.params.serviceofferingid = id
|
this.params.serviceofferingid = id
|
||||||
this.selectedOffering = this.offeringsMap[id]
|
this.selectedOffering = this.offeringsMap[id]
|
||||||
api('listDiskOfferings', {
|
this.selectedDiskOffering = null
|
||||||
id: this.selectedOffering.diskofferingid
|
if (this.selectedOffering.diskofferingid) {
|
||||||
}).then(response => {
|
api('listDiskOfferings', {
|
||||||
const diskOfferings = response.listdiskofferingsresponse.diskoffering || []
|
id: this.selectedOffering.diskofferingid
|
||||||
if (this.offerings) {
|
}).then(response => {
|
||||||
this.selectedDiskOffering = diskOfferings[0]
|
const diskOfferings = response.listdiskofferingsresponse.diskoffering || []
|
||||||
}
|
if (this.diskOfferings) {
|
||||||
}).catch(error => {
|
this.selectedDiskOffering = diskOfferings[0]
|
||||||
this.$notifyError(error)
|
}
|
||||||
})
|
}).catch(error => {
|
||||||
|
this.$notifyError(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
this.params.automigrate = this.autoMigrate
|
this.params.automigrate = this.autoMigrate
|
||||||
},
|
},
|
||||||
updateFieldValue (name, value) {
|
updateFieldValue (name, value) {
|
||||||
|
|||||||
@ -54,7 +54,8 @@
|
|||||||
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||||
}"
|
}"
|
||||||
:loading="zoneLoading"
|
:loading="zoneLoading"
|
||||||
:placeholder="apiParams.zoneid.description">
|
:placeholder="apiParams.zoneid.description"
|
||||||
|
@change="handleZoneChange">
|
||||||
<a-select-option v-for="(opt, optIndex) in this.zones" :key="optIndex" :label="opt.name || opt.description">
|
<a-select-option v-for="(opt, optIndex) in this.zones" :key="optIndex" :label="opt.name || opt.description">
|
||||||
<span>
|
<span>
|
||||||
<resource-icon v-if="opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
|
<resource-icon v-if="opt.icon" :image="opt.icon.base64image" size="1x" style="margin-right: 5px"/>
|
||||||
@ -96,6 +97,15 @@
|
|||||||
v-model:value="form.minmemory"
|
v-model:value="form.minmemory"
|
||||||
:placeholder="apiParams.minmemory.description"/>
|
:placeholder="apiParams.minmemory.description"/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item ref="directdownload" name="directdownload">
|
||||||
|
<template #label>
|
||||||
|
<tooltip-label :title="$t('label.directdownload')" :tooltip="apiParams.directdownload.description"/>
|
||||||
|
</template>
|
||||||
|
<a-switch
|
||||||
|
:disabled="directDownloadDisabled"
|
||||||
|
v-model:checked="form.directdownload"
|
||||||
|
:placeholder="apiParams.directdownload.description"/>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
<div :span="24" class="action-button">
|
<div :span="24" class="action-button">
|
||||||
<a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
|
<a-button @click="closeAction">{{ $t('label.cancel') }}</a-button>
|
||||||
@ -122,7 +132,10 @@ export default {
|
|||||||
return {
|
return {
|
||||||
zones: [],
|
zones: [],
|
||||||
zoneLoading: false,
|
zoneLoading: false,
|
||||||
loading: false
|
loading: false,
|
||||||
|
selectedZone: {},
|
||||||
|
directDownloadDisabled: false,
|
||||||
|
lastNonEdgeDirectDownloadUserSelection: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeCreate () {
|
beforeCreate () {
|
||||||
@ -143,7 +156,8 @@ export default {
|
|||||||
this.formRef = ref()
|
this.formRef = ref()
|
||||||
this.form = reactive({
|
this.form = reactive({
|
||||||
mincpunumber: 2,
|
mincpunumber: 2,
|
||||||
minmemory: 2048
|
minmemory: 2048,
|
||||||
|
directdownload: false
|
||||||
})
|
})
|
||||||
this.rules = reactive({
|
this.rules = reactive({
|
||||||
semanticversion: [{ required: true, message: this.$t('message.error.kuberversion') }],
|
semanticversion: [{ required: true, message: this.$t('message.error.kuberversion') }],
|
||||||
@ -198,7 +212,6 @@ export default {
|
|||||||
const listZones = json.listzonesresponse.zone
|
const listZones = json.listzonesresponse.zone
|
||||||
if (listZones) {
|
if (listZones) {
|
||||||
this.zones = this.zones.concat(listZones)
|
this.zones = this.zones.concat(listZones)
|
||||||
this.zones = this.zones.filter(zone => zone.type !== 'Edge')
|
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.zoneLoading = false
|
this.zoneLoading = false
|
||||||
@ -207,23 +220,38 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleZoneChange (zoneIdx) {
|
||||||
|
const zone = this.zones[zoneIdx]
|
||||||
|
if (this.selectedZone.type === zone.type) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var lastZoneType = this.selectedZone?.type || ''
|
||||||
|
if (lastZoneType !== 'Edge') {
|
||||||
|
this.nonEdgeDirectDownloadUserSelection = this.form.directdownload
|
||||||
|
}
|
||||||
|
this.selectedZone = zone
|
||||||
|
if (zone.type && zone.type === 'Edge') {
|
||||||
|
this.form.directdownload = true
|
||||||
|
this.directDownloadDisabled = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.directDownloadDisabled = false
|
||||||
|
this.form.directdownload = this.nonEdgeDirectDownloadUserSelection
|
||||||
|
},
|
||||||
handleSubmit (e) {
|
handleSubmit (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (this.loading) return
|
if (this.loading) return
|
||||||
this.formRef.value.validate().then(() => {
|
this.formRef.value.validate().then(() => {
|
||||||
const values = toRaw(this.form)
|
const values = toRaw(this.form)
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const params = {
|
const params = {}
|
||||||
semanticversion: values.semanticversion,
|
const customCheckParams = ['mincpunumber', 'minmemory', 'zoneid']
|
||||||
url: values.url
|
for (const key in values) {
|
||||||
|
if (!customCheckParams.includes(key) && values[key]) {
|
||||||
|
params[key] = values[key]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.isValidValueForKey(values, 'name')) {
|
if (this.isValidValueForKey(values, 'zoneid') && values.zoneid > 0) {
|
||||||
params.name = values.name
|
|
||||||
}
|
|
||||||
if (this.isValidValueForKey(values, 'checksum')) {
|
|
||||||
params.checksum = values.checksum
|
|
||||||
}
|
|
||||||
if (this.isValidValueForKey(values, 'zoneid')) {
|
|
||||||
params.zoneid = this.zones[values.zoneid].id
|
params.zoneid = this.zones[values.zoneid].id
|
||||||
}
|
}
|
||||||
if (this.isValidValueForKey(values, 'mincpunumber') && values.mincpunumber > 0) {
|
if (this.isValidValueForKey(values, 'mincpunumber') && values.mincpunumber > 0) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user