Merge branch '4.20'

This commit is contained in:
Daan Hoogland 2025-07-25 23:38:12 +02:00
commit bcafbd1649
104 changed files with 1884 additions and 1493 deletions

View File

@ -87,6 +87,8 @@ public interface AccountService {
boolean isDomainAdmin(Long accountId);
boolean isResourceDomainAdmin(Long accountId);
boolean isNormalUser(long accountId);
User getActiveUserByRegistrationToken(String registrationToken);

View File

@ -145,19 +145,19 @@ public class ListClustersCmd extends BaseListCmd {
protected Pair<List<ClusterResponse>, Integer> getClusterResponses() {
Pair<List<? extends Cluster>, Integer> result = _mgr.searchForClusters(this);
List<ClusterResponse> clusterResponses = new ArrayList<ClusterResponse>();
List<ClusterResponse> clusterResponses = new ArrayList<>();
for (Cluster cluster : result.first()) {
ClusterResponse clusterResponse = _responseGenerator.createClusterResponse(cluster, showCapacities);
clusterResponse.setObjectName("cluster");
clusterResponses.add(clusterResponse);
}
return new Pair<List<ClusterResponse>, Integer>(clusterResponses, result.second());
return new Pair<>(clusterResponses, result.second());
}
@Override
public void execute() {
Pair<List<ClusterResponse>, Integer> clusterResponses = getClusterResponses();
ListResponse<ClusterResponse> response = new ListResponse<ClusterResponse>();
ListResponse<ClusterResponse> response = new ListResponse<>();
response.setResponses(clusterResponses.first(), clusterResponses.second());
response.setResponseName(getCommandName());
this.setResponseObject(response);

View File

@ -103,8 +103,8 @@ public class ListPodsByCmd extends BaseListCmd {
@Override
public void execute() {
Pair<List<? extends Pod>, Integer> result = _mgr.searchForPods(this);
ListResponse<PodResponse> response = new ListResponse<PodResponse>();
List<PodResponse> podResponses = new ArrayList<PodResponse>();
ListResponse<PodResponse> response = new ListResponse<>();
List<PodResponse> podResponses = new ArrayList<>();
for (Pod pod : result.first()) {
PodResponse podResponse = _responseGenerator.createPodResponse(pod, showCapacities);
podResponse.setObjectName("pod");

View File

@ -73,6 +73,7 @@ public class ListCapabilitiesCmd extends BaseCmd {
response.setSharedFsVmMinCpuCount((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_CPU_COUNT));
response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE));
response.setInstanceLeaseEnabled((Boolean) capabilities.get(ApiConstants.INSTANCE_LEASE_ENABLED));
response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED));
response.setObjectName("capability");
response.setResponseName(getCommandName());
this.setResponseObject(response);

View File

@ -33,7 +33,7 @@ import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.UserData;
@APICommand(name = "registerUserData",
description = "Register a new userdata.",
description = "Register a new User Data.",
since = "4.18",
responseObject = SuccessResponse.class,
requestHasSensitiveInfo = false,
@ -46,9 +46,55 @@ public class RegisterUserDataCmd extends BaseRegisterUserDataCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.STRING, required = true, description = "User data content", length = 1048576)
protected String userData;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of the User Data")
private String name;
//Owner information
@Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an optional account for the User Data. Must be used with domainId.")
private String accountName;
@Parameter(name = ApiConstants.DOMAIN_ID,
type = CommandType.UUID,
entityType = DomainResponse.class,
description = "an optional domainId for the User Data. If the account parameter is used, domainId must also be used.")
private Long domainId;
@Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "an optional project for the User Data")
private Long projectId;
@Parameter(name = ApiConstants.USER_DATA,
type = CommandType.STRING,
required = true,
description = "Base64 encoded User Data content. " +
"Using HTTP GET (via querystring), you can send up to 4KB of data after base64 encoding. " +
"Using HTTP POST (via POST body), you can send up to 32KB of data after base64 encoding, " +
"which can be increased upto 1MB using the vm.userdata.max.length setting",
length = 1048576)
private String userData;
@Parameter(name = ApiConstants.PARAMS, type = CommandType.STRING, description = "comma separated list of variables declared in the User Data content")
private String params;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
public String getName() {
return name;
}
public String getAccountName() {
return accountName;
}
public Long getDomainId() {
return domainId;
}
public Long getProjectId() {
return projectId;
}
public String getUserData() {
return userData;

View File

@ -34,8 +34,6 @@ import org.apache.cloudstack.api.response.ZoneResponse;
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListZonesCmd extends BaseListCmd implements UserCmd {
private static final String s_name = "listzonesresponse";
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ -130,11 +128,6 @@ public class ListZonesCmd extends BaseListCmd implements UserCmd {
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@Override
public String getCommandName() {
return s_name;
}
@Override
public void execute() {
ListResponse<ZoneResponse> response = _queryService.listDataCenters(this);

View File

@ -140,6 +140,10 @@ public class CapabilitiesResponse extends BaseResponse {
@Param(description = "true if instance lease feature is enabled", since = "4.21.0")
private Boolean instanceLeaseEnabled;
@SerializedName(ApiConstants.DYNAMIC_SCALING_ENABLED)
@Param(description = "true if dynamically scaling for instances is enabled", since = "4.21.0")
private Boolean dynamicScalingEnabled;
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
this.securityGroupsEnabled = securityGroupsEnabled;
}
@ -255,4 +259,8 @@ public class CapabilitiesResponse extends BaseResponse {
public void setInstanceLeaseEnabled(Boolean instanceLeaseEnabled) {
this.instanceLeaseEnabled = instanceLeaseEnabled;
}
public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) {
this.dynamicScalingEnabled = dynamicScalingEnabled;
}
}

View File

@ -27,41 +27,41 @@ import org.apache.cloudstack.api.EntityReference;
public class UserDataResponse extends BaseResponseWithAnnotations implements ControlledEntityResponse {
@SerializedName(ApiConstants.ID)
@Param(description = "ID of the ssh keypair")
@Param(description = "ID of the User Data")
private String id;
@SerializedName(ApiConstants.NAME)
@Param(description = "Name of the userdata")
@Param(description = "Name of the User Data")
private String name;
@SerializedName(ApiConstants.ACCOUNT_ID) @Param(description="the owner id of the userdata")
@SerializedName(ApiConstants.ACCOUNT_ID) @Param(description="the owner id of the User Data")
private String accountId;
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner of the userdata")
@SerializedName(ApiConstants.ACCOUNT) @Param(description="the owner of the User Data")
private String accountName;
@SerializedName(ApiConstants.PROJECT_ID)
@Param(description = "the project id of the userdata", since = "4.19.1")
@Param(description = "the project id of the User Data", since = "4.19.1")
private String projectId;
@SerializedName(ApiConstants.PROJECT)
@Param(description = "the project name of the userdata", since = "4.19.1")
@Param(description = "the project name of the User Data", since = "4.19.1")
private String projectName;
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain id of the userdata owner")
@SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain id of the User Data owner")
private String domainId;
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the userdata owner")
@SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the User Data owner")
private String domain;
@SerializedName(ApiConstants.DOMAIN_PATH)
@Param(description = "path of the domain to which the userdata owner belongs", since = "4.19.2.0")
@Param(description = "path of the domain to which the User Data owner belongs", since = "4.19.2.0")
private String domainPath;
@SerializedName(ApiConstants.USER_DATA) @Param(description="base64 encoded userdata content")
@SerializedName(ApiConstants.USER_DATA) @Param(description="base64 encoded User Data content")
private String userData;
@SerializedName(ApiConstants.PARAMS) @Param(description="list of parameters which contains the list of keys or string parameters that are needed to be passed for any variables declared in userdata")
@SerializedName(ApiConstants.PARAMS) @Param(description="list of parameters which contains the list of keys or string parameters that are needed to be passed for any variables declared in the User Data")
private String params;
public UserDataResponse() {

View File

@ -114,11 +114,11 @@ public interface QueryService {
ConfigKey<Boolean> AllowUserViewDestroyedVM = new ConfigKey<>("Advanced", Boolean.class, "allow.user.view.destroyed.vm", "false",
"Determines whether users can view their destroyed or expunging vm ", true, ConfigKey.Scope.Account);
static final ConfigKey<String> UserVMDeniedDetails = new ConfigKey<>(String.class,
ConfigKey<String> UserVMDeniedDetails = new ConfigKey<>(String.class,
"user.vm.denied.details", "Advanced", "rootdisksize, cpuOvercommitRatio, memoryOvercommitRatio, Message.ReservedCapacityFreed.Flag",
"Determines whether users can view certain VM settings. When set to empty, default value used is: rootdisksize, cpuOvercommitRatio, memoryOvercommitRatio, Message.ReservedCapacityFreed.Flag.", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
static final ConfigKey<String> UserVMReadOnlyDetails = new ConfigKey<>(String.class,
ConfigKey<String> UserVMReadOnlyDetails = new ConfigKey<>(String.class,
"user.vm.readonly.details", "Advanced", "dataDiskController, rootDiskController",
"List of read-only VM settings/details as comma separated string", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
@ -127,16 +127,20 @@ public interface QueryService {
"network offering, zones), we use the flag to determine if the entities should be sorted ascending (when flag is true) " +
"or descending (when flag is false). Within the scope of the config all users see the same result.", true, ConfigKey.Scope.Global);
public static final ConfigKey<Boolean> AllowUserViewAllDomainAccounts = new ConfigKey<>("Advanced", Boolean.class,
ConfigKey<Boolean> AllowUserViewAllDomainAccounts = new ConfigKey<>("Advanced", Boolean.class,
"allow.user.view.all.domain.accounts", "false",
"Determines whether users can view all user accounts within the same domain", true, ConfigKey.Scope.Domain);
static final ConfigKey<Boolean> SharePublicTemplatesWithOtherDomains = new ConfigKey<>("Advanced", Boolean.class, "share.public.templates.with.other.domains", "true",
ConfigKey<Boolean> AllowUserViewAllDataCenters = new ConfigKey<>("Advanced", Boolean.class, "allow.user.view.all.zones", "true",
"Determines whether for instance a Resource Admin can view zones that are not dedicated to them.", true, ConfigKey.Scope.Domain);
ConfigKey<Boolean> SharePublicTemplatesWithOtherDomains = new ConfigKey<>("Advanced", Boolean.class, "share.public.templates.with.other.domains", "true",
"If false, templates of this domain will not show up in the list templates of other domains.", true, ConfigKey.Scope.Domain);
ConfigKey<Boolean> ReturnVmStatsOnVmList = new ConfigKey<>("Advanced", Boolean.class, "list.vm.default.details.stats", "true",
"Determines whether VM stats should be returned when details are not explicitly specified in listVirtualMachines API request. When false, details default to [group, nics, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp]. When true, all details are returned including 'stats'.", true, ConfigKey.Scope.Global);
ListResponse<UserResponse> searchForUsers(ResponseObject.ResponseView responseView, ListUsersCmd cmd) throws PermissionDeniedException;
ListResponse<UserResponse> searchForUsers(Long domainId, boolean recursive) throws PermissionDeniedException;

View File

@ -17,22 +17,33 @@
package com.cloud.agent.api;
import org.apache.cloudstack.storage.volume.VolumeOnStorageTO;
import java.util.Map;
public class CheckVolumeAnswer extends Answer {
private long size;
private Map<VolumeOnStorageTO.Detail, String> volumeDetails;
CheckVolumeAnswer() {
}
public CheckVolumeAnswer(CheckVolumeCommand cmd, String details, long size) {
super(cmd, true, details);
public CheckVolumeAnswer(CheckVolumeCommand cmd, final boolean success, String details, long size,
Map<VolumeOnStorageTO.Detail, String> volumeDetails) {
super(cmd, success, details);
this.size = size;
this.volumeDetails = volumeDetails;
}
public long getSize() {
return size;
}
public Map<VolumeOnStorageTO.Detail, String> getVolumeDetails() {
return volumeDetails;
}
public String getString() {
return "CheckVolumeAnswer [size=" + size + "]";
}

View File

@ -17,21 +17,28 @@
package com.cloud.agent.api;
import org.apache.cloudstack.storage.volume.VolumeOnStorageTO;
import java.util.Map;
public class CopyRemoteVolumeAnswer extends Answer {
private String remoteIp;
private String filename;
private long size;
private Map<VolumeOnStorageTO.Detail, String> volumeDetails;
CopyRemoteVolumeAnswer() {
}
public CopyRemoteVolumeAnswer(CopyRemoteVolumeCommand cmd, String details, String filename, long size) {
super(cmd, true, details);
public CopyRemoteVolumeAnswer(CopyRemoteVolumeCommand cmd, final boolean success, String details, String filename, long size,
Map<VolumeOnStorageTO.Detail, String> volumeDetails) {
super(cmd, success, details);
this.remoteIp = cmd.getRemoteIp();
this.filename = filename;
this.size = size;
this.volumeDetails = volumeDetails;
}
public String getRemoteIp() {
@ -54,6 +61,10 @@ public class CopyRemoteVolumeAnswer extends Answer {
return size;
}
public Map<VolumeOnStorageTO.Detail, String> getVolumeDetails() {
return volumeDetails;
}
public String getString() {
return "CopyRemoteVolumeAnswer [remoteIp=" + remoteIp + "]";
}

View File

@ -24,6 +24,7 @@ import com.cloud.utils.PasswordGenerator;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.ca.CAManager;
import org.apache.cloudstack.framework.ca.Certificate;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.utils.security.CertUtils;
import org.apache.cloudstack.utils.security.KeyStoreUtils;
@ -37,6 +38,9 @@ import java.util.Base64;
*/
public interface VirtualMachineGuru {
static final ConfigKey<String> NTPServerConfig = new ConfigKey<String>(String.class, "ntp.server.list", "Advanced", null,
"Comma separated list of NTP servers to configure in System VMs", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context);
/**

View File

@ -58,6 +58,7 @@ import javax.inject.Inject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
@ -169,6 +170,7 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
if (VirtualMachine.State.Stopped.equals(vm.getState())) {
List<VolumeVO> vmVolumes = volumeDao.findByInstance(vm.getId());
vmVolumes.sort(Comparator.comparing(Volume::getDeviceId));
List<String> volumePaths = getVolumePaths(vmVolumes);
command.setVolumePaths(volumePaths);
}
@ -223,7 +225,10 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
@Override
public boolean restoreVMFromBackup(VirtualMachine vm, Backup backup) {
List<Backup.VolumeInfo> backedVolumes = backup.getBackedUpVolumes();
List<VolumeVO> volumes = backedVolumes.stream().map(volume -> volumeDao.findByUuid(volume.getUuid())).collect(Collectors.toList());
List<VolumeVO> volumes = backedVolumes.stream()
.map(volume -> volumeDao.findByUuid(volume.getUuid()))
.sorted((v1, v2) -> Long.compare(v1.getDeviceId(), v2.getDeviceId()))
.collect(Collectors.toList());
LOG.debug("Restoring vm {} from backup {} on the NAS Backup Provider", vm, backup);
BackupRepository backupRepository = getBackupRepository(vm, backup);
@ -257,9 +262,13 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
if (Objects.isNull(storagePool)) {
throw new CloudRuntimeException("Unable to find storage pool associated to the volume");
}
String volumePathPrefix = String.format("/mnt/%s", storagePool.getUuid());
String volumePathPrefix;
if (ScopeType.HOST.equals(storagePool.getScope())) {
volumePathPrefix = storagePool.getPath();
} else if (Storage.StoragePoolType.SharedMountPoint.equals(storagePool.getPoolType())) {
volumePathPrefix = storagePool.getPath();
} else {
volumePathPrefix = String.format("/mnt/%s", storagePool.getUuid());
}
volumePaths.add(String.format("%s/%s", volumePathPrefix, volume.getPath()));
}

View File

@ -3524,7 +3524,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
if (!meetRequirements) {
return false;
}
return isUbuntuHost() || isIoUringSupportedByQemu();
return isUbuntuOrDebianHost() || isIoUringSupportedByQemu();
}
/**
@ -3537,13 +3537,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return diskBus != DiskDef.DiskBus.IDE || getHypervisorQemuVersion() >= HYPERVISOR_QEMU_VERSION_IDE_DISCARD_FIXED;
}
public boolean isUbuntuHost() {
public boolean isUbuntuOrDebianHost() {
Map<String, String> versionString = getVersionStrings();
String hostKey = "Host.OS";
if (MapUtils.isEmpty(versionString) || !versionString.containsKey(hostKey) || versionString.get(hostKey) == null) {
return false;
}
return versionString.get(hostKey).equalsIgnoreCase("ubuntu");
return versionString.get(hostKey).equalsIgnoreCase("ubuntu")
|| versionString.get(hostKey).toLowerCase().startsWith("debian");
}
private KVMPhysicalDisk getPhysicalDiskFromNfsStore(String dataStoreUrl, DataTO data) {
@ -5629,14 +5630,14 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
public boolean hostSupportsInstanceConversion() {
int exitValue = Script.runSimpleBashScriptForExitValue(INSTANCE_CONVERSION_SUPPORTED_CHECK_CMD);
if (isUbuntuHost() && exitValue == 0) {
if (isUbuntuOrDebianHost() && exitValue == 0) {
exitValue = Script.runSimpleBashScriptForExitValue(UBUNTU_NBDKIT_PKG_CHECK_CMD);
}
return exitValue == 0;
}
public boolean hostSupportsWindowsGuestConversion() {
if (isUbuntuHost()) {
if (isUbuntuOrDebianHost()) {
int exitValue = Script.runSimpleBashScriptForExitValue(UBUNTU_WINDOWS_GUEST_CONVERSION_SUPPORTED_CHECK_CMD);
return exitValue == 0;
}

View File

@ -32,7 +32,7 @@ public class LibvirtCheckConvertInstanceCommandWrapper extends CommandWrapper<Ch
public Answer execute(CheckConvertInstanceCommand cmd, LibvirtComputingResource serverResource) {
if (!serverResource.hostSupportsInstanceConversion()) {
String msg = String.format("Cannot convert the instance from VMware as the virt-v2v binary is not found on host %s. " +
"Please install virt-v2v%s on the host before attempting the instance conversion.", serverResource.getPrivateIp(), serverResource.isUbuntuHost()? ", nbdkit" : "");
"Please install virt-v2v%s on the host before attempting the instance conversion.", serverResource.getPrivateIp(), serverResource.isUbuntuOrDebianHost()? ", nbdkit" : "");
logger.info(msg);
return new CheckConvertInstanceAnswer(cmd, false, msg);
}

View File

@ -31,16 +31,24 @@ import com.cloud.resource.CommandWrapper;
import com.cloud.resource.ResourceWrapper;
import com.cloud.storage.Storage;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.storage.volume.VolumeOnStorageTO;
import org.apache.cloudstack.utils.qemu.QemuImg;
import org.apache.cloudstack.utils.qemu.QemuImgException;
import org.apache.cloudstack.utils.qemu.QemuImgFile;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.libvirt.LibvirtException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ResourceWrapper(handles = CheckVolumeCommand.class)
public final class LibvirtCheckVolumeCommandWrapper extends CommandWrapper<CheckVolumeCommand, Answer, LibvirtComputingResource> {
private static final List<Storage.StoragePoolType> STORAGE_POOL_TYPES_SUPPORTED = Arrays.asList(Storage.StoragePoolType.Filesystem, Storage.StoragePoolType.NetworkFilesystem);
@Override
public Answer execute(final CheckVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
String result = null;
@ -50,34 +58,76 @@ public final class LibvirtCheckVolumeCommandWrapper extends CommandWrapper<Check
KVMStoragePool pool = poolMgr.getStoragePool(storageFilerTO.getType(), storageFilerTO.getUuid());
try {
if (storageFilerTO.getType() == Storage.StoragePoolType.Filesystem ||
storageFilerTO.getType() == Storage.StoragePoolType.NetworkFilesystem) {
if (STORAGE_POOL_TYPES_SUPPORTED.contains(storageFilerTO.getType())) {
final KVMPhysicalDisk vol = pool.getPhysicalDisk(srcFile);
final String path = vol.getPath();
long size = getVirtualSizeFromFile(path);
return new CheckVolumeAnswer(command, "", size);
try {
KVMPhysicalDisk.checkQcow2File(path);
} catch (final CloudRuntimeException e) {
return new CheckVolumeAnswer(command, false, "", 0, getVolumeDetails(pool, vol));
}
long size = KVMPhysicalDisk.getVirtualSizeFromFile(path);
return new CheckVolumeAnswer(command, true, "", size, getVolumeDetails(pool, vol));
} else {
return new Answer(command, false, "Unsupported Storage Pool");
}
} catch (final Exception e) {
logger.error("Error while locating disk: "+ e.getMessage());
logger.error("Error while checking the disk: {}", e.getMessage());
return new Answer(command, false, result);
}
}
private long getVirtualSizeFromFile(String path) {
private Map<VolumeOnStorageTO.Detail, String> getVolumeDetails(KVMStoragePool pool, KVMPhysicalDisk disk) {
Map<String, String> info = getDiskFileInfo(pool, disk, true);
if (MapUtils.isEmpty(info)) {
return null;
}
Map<VolumeOnStorageTO.Detail, String> volumeDetails = new HashMap<>();
String backingFilePath = info.get(QemuImg.BACKING_FILE);
if (StringUtils.isNotBlank(backingFilePath)) {
volumeDetails.put(VolumeOnStorageTO.Detail.BACKING_FILE, backingFilePath);
}
String backingFileFormat = info.get(QemuImg.BACKING_FILE_FORMAT);
if (StringUtils.isNotBlank(backingFileFormat)) {
volumeDetails.put(VolumeOnStorageTO.Detail.BACKING_FILE_FORMAT, backingFileFormat);
}
String clusterSize = info.get(QemuImg.CLUSTER_SIZE);
if (StringUtils.isNotBlank(clusterSize)) {
volumeDetails.put(VolumeOnStorageTO.Detail.CLUSTER_SIZE, clusterSize);
}
String fileFormat = info.get(QemuImg.FILE_FORMAT);
if (StringUtils.isNotBlank(fileFormat)) {
volumeDetails.put(VolumeOnStorageTO.Detail.FILE_FORMAT, fileFormat);
}
String encrypted = info.get(QemuImg.ENCRYPTED);
if (StringUtils.isNotBlank(encrypted) && encrypted.equalsIgnoreCase("yes")) {
volumeDetails.put(VolumeOnStorageTO.Detail.IS_ENCRYPTED, String.valueOf(Boolean.TRUE));
}
Boolean isLocked = isDiskFileLocked(pool, disk);
volumeDetails.put(VolumeOnStorageTO.Detail.IS_LOCKED, String.valueOf(isLocked));
return volumeDetails;
}
private Map<String, String> getDiskFileInfo(KVMStoragePool pool, KVMPhysicalDisk disk, boolean secure) {
if (!STORAGE_POOL_TYPES_SUPPORTED.contains(pool.getType())) {
return new HashMap<>(); // unknown
}
try {
QemuImg qemu = new QemuImg(0);
QemuImgFile qemuFile = new QemuImgFile(path);
Map<String, String> info = qemu.info(qemuFile);
if (info.containsKey(QemuImg.VIRTUAL_SIZE)) {
return Long.parseLong(info.get(QemuImg.VIRTUAL_SIZE));
} else {
throw new CloudRuntimeException("Unable to determine virtual size of volume at path " + path);
}
QemuImgFile qemuFile = new QemuImgFile(disk.getPath(), disk.getFormat());
return qemu.info(qemuFile, secure);
} catch (QemuImgException | LibvirtException ex) {
throw new CloudRuntimeException("Error when inspecting volume at path " + path, ex);
logger.error("Failed to get info of disk file: " + ex.getMessage());
return null;
}
}
private boolean isDiskFileLocked(KVMStoragePool pool, KVMPhysicalDisk disk) {
Map<String, String> info = getDiskFileInfo(pool, disk, false);
return info == null;
}
}

View File

@ -60,7 +60,7 @@ public class LibvirtConvertInstanceCommandWrapper extends CommandWrapper<Convert
if (cmd.getCheckConversionSupport() && !serverResource.hostSupportsInstanceConversion()) {
String msg = String.format("Cannot convert the instance %s from VMware as the virt-v2v binary is not found. " +
"Please install virt-v2v%s on the host before attempting the instance conversion.", sourceInstanceName, serverResource.isUbuntuHost()? ", nbdkit" : "");
"Please install virt-v2v%s on the host before attempting the instance conversion.", sourceInstanceName, serverResource.isUbuntuOrDebianHost()? ", nbdkit" : "");
logger.info(msg);
return new Answer(cmd, false, msg);
}

View File

@ -31,15 +31,22 @@ import com.cloud.resource.CommandWrapper;
import com.cloud.resource.ResourceWrapper;
import com.cloud.storage.Storage;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.storage.volume.VolumeOnStorageTO;
import org.apache.cloudstack.utils.qemu.QemuImg;
import org.apache.cloudstack.utils.qemu.QemuImgException;
import org.apache.cloudstack.utils.qemu.QemuImgFile;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.libvirt.LibvirtException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ResourceWrapper(handles = CopyRemoteVolumeCommand.class)
public final class LibvirtCopyRemoteVolumeCommandWrapper extends CommandWrapper<CopyRemoteVolumeCommand, Answer, LibvirtComputingResource> {
private static final List<Storage.StoragePoolType> STORAGE_POOL_TYPES_SUPPORTED = Arrays.asList(Storage.StoragePoolType.Filesystem, Storage.StoragePoolType.NetworkFilesystem);
@Override
public Answer execute(final CopyRemoteVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
@ -55,14 +62,19 @@ public final class LibvirtCopyRemoteVolumeCommandWrapper extends CommandWrapper<
int timeoutInSecs = command.getWait();
try {
if (storageFilerTO.getType() == Storage.StoragePoolType.Filesystem ||
storageFilerTO.getType() == Storage.StoragePoolType.NetworkFilesystem) {
if (STORAGE_POOL_TYPES_SUPPORTED.contains(storageFilerTO.getType())) {
String filename = libvirtComputingResource.copyVolume(srcIp, username, password, dstPath, srcFile, tmpPath, timeoutInSecs);
logger.debug("Volume " + srcFile + " copy successful, copied to file: " + filename);
final KVMPhysicalDisk vol = pool.getPhysicalDisk(filename);
final String path = vol.getPath();
long size = getVirtualSizeFromFile(path);
return new CopyRemoteVolumeAnswer(command, "", filename, size);
try {
KVMPhysicalDisk.checkQcow2File(path);
} catch (final CloudRuntimeException e) {
return new CopyRemoteVolumeAnswer(command, false, "", filename, 0, getVolumeDetails(pool, vol));
}
long size = KVMPhysicalDisk.getVirtualSizeFromFile(path);
return new CopyRemoteVolumeAnswer(command, true, "", filename, size, getVolumeDetails(pool, vol));
} else {
String msg = "Unsupported storage pool type: " + storageFilerTO.getType().toString() + ", only local and NFS pools are supported";
return new Answer(command, false, msg);
@ -74,18 +86,56 @@ public final class LibvirtCopyRemoteVolumeCommandWrapper extends CommandWrapper<
}
}
private long getVirtualSizeFromFile(String path) {
private Map<VolumeOnStorageTO.Detail, String> getVolumeDetails(KVMStoragePool pool, KVMPhysicalDisk disk) {
Map<String, String> info = getDiskFileInfo(pool, disk, true);
if (MapUtils.isEmpty(info)) {
return null;
}
Map<VolumeOnStorageTO.Detail, String> volumeDetails = new HashMap<>();
String backingFilePath = info.get(QemuImg.BACKING_FILE);
if (StringUtils.isNotBlank(backingFilePath)) {
volumeDetails.put(VolumeOnStorageTO.Detail.BACKING_FILE, backingFilePath);
}
String backingFileFormat = info.get(QemuImg.BACKING_FILE_FORMAT);
if (StringUtils.isNotBlank(backingFileFormat)) {
volumeDetails.put(VolumeOnStorageTO.Detail.BACKING_FILE_FORMAT, backingFileFormat);
}
String clusterSize = info.get(QemuImg.CLUSTER_SIZE);
if (StringUtils.isNotBlank(clusterSize)) {
volumeDetails.put(VolumeOnStorageTO.Detail.CLUSTER_SIZE, clusterSize);
}
String fileFormat = info.get(QemuImg.FILE_FORMAT);
if (StringUtils.isNotBlank(fileFormat)) {
volumeDetails.put(VolumeOnStorageTO.Detail.FILE_FORMAT, fileFormat);
}
String encrypted = info.get(QemuImg.ENCRYPTED);
if (StringUtils.isNotBlank(encrypted) && encrypted.equalsIgnoreCase("yes")) {
volumeDetails.put(VolumeOnStorageTO.Detail.IS_ENCRYPTED, String.valueOf(Boolean.TRUE));
}
Boolean isLocked = isDiskFileLocked(pool, disk);
volumeDetails.put(VolumeOnStorageTO.Detail.IS_LOCKED, String.valueOf(isLocked));
return volumeDetails;
}
private Map<String, String> getDiskFileInfo(KVMStoragePool pool, KVMPhysicalDisk disk, boolean secure) {
if (!STORAGE_POOL_TYPES_SUPPORTED.contains(pool.getType())) {
return new HashMap<>(); // unknown
}
try {
QemuImg qemu = new QemuImg(0);
QemuImgFile qemuFile = new QemuImgFile(path);
Map<String, String> info = qemu.info(qemuFile);
if (info.containsKey(QemuImg.VIRTUAL_SIZE)) {
return Long.parseLong(info.get(QemuImg.VIRTUAL_SIZE));
} else {
throw new CloudRuntimeException("Unable to determine virtual size of volume at path " + path);
}
QemuImgFile qemuFile = new QemuImgFile(disk.getPath(), disk.getFormat());
return qemu.info(qemuFile, secure);
} catch (QemuImgException | LibvirtException ex) {
throw new CloudRuntimeException("Error when inspecting volume at path " + path, ex);
logger.error("Failed to get info of disk file: " + ex.getMessage());
return null;
}
}
private boolean isDiskFileLocked(KVMStoragePool pool, KVMPhysicalDisk disk) {
Map<String, String> info = getDiskFileInfo(pool, disk, false);
return info == null;
}
}

View File

@ -36,6 +36,7 @@ import org.apache.cloudstack.utils.qemu.QemuImg;
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
import org.apache.cloudstack.utils.qemu.QemuImgException;
import org.apache.cloudstack.utils.qemu.QemuImgFile;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.libvirt.LibvirtException;
@ -91,37 +92,46 @@ public final class LibvirtGetVolumesOnStorageCommandWrapper extends CommandWrapp
if (disk.getQemuEncryptFormat() != null) {
volumeOnStorageTO.setQemuEncryptFormat(disk.getQemuEncryptFormat().toString());
}
String backingFilePath = info.get(QemuImg.BACKING_FILE);
if (StringUtils.isNotBlank(backingFilePath)) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.BACKING_FILE, backingFilePath);
}
String backingFileFormat = info.get(QemuImg.BACKING_FILE_FORMAT);
if (StringUtils.isNotBlank(backingFileFormat)) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.BACKING_FILE_FORMAT, backingFileFormat);
}
String clusterSize = info.get(QemuImg.CLUSTER_SIZE);
if (StringUtils.isNotBlank(clusterSize)) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.CLUSTER_SIZE, clusterSize);
}
String fileFormat = info.get(QemuImg.FILE_FORMAT);
if (StringUtils.isNotBlank(fileFormat)) {
if (!fileFormat.equalsIgnoreCase(disk.getFormat().toString())) {
return new GetVolumesOnStorageAnswer(command, false, String.format("The file format is %s, but expected to be %s", fileFormat, disk.getFormat()));
}
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.FILE_FORMAT, fileFormat);
if (StringUtils.isNotBlank(fileFormat) && !fileFormat.equalsIgnoreCase(disk.getFormat().toString())) {
return new GetVolumesOnStorageAnswer(command, false, String.format("The file format is %s, but expected to be %s", fileFormat, disk.getFormat()));
}
String encrypted = info.get(QemuImg.ENCRYPTED);
if (StringUtils.isNotBlank(encrypted) && encrypted.equalsIgnoreCase("yes")) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.IS_ENCRYPTED, String.valueOf(Boolean.TRUE));
}
Boolean isLocked = isDiskFileLocked(storagePool, disk);
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.IS_LOCKED, String.valueOf(isLocked));
addDetailsToVolumeOnStorageTO(volumeOnStorageTO, info, storagePool, disk);
volumes.add(volumeOnStorageTO);
}
return new GetVolumesOnStorageAnswer(command, volumes);
}
private void addDetailsToVolumeOnStorageTO(VolumeOnStorageTO volumeOnStorageTO, final Map<String, String> info, final KVMStoragePool storagePool, final KVMPhysicalDisk disk) {
if (MapUtils.isEmpty(info)) {
return;
}
String backingFilePath = info.get(QemuImg.BACKING_FILE);
if (StringUtils.isNotBlank(backingFilePath)) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.BACKING_FILE, backingFilePath);
}
String backingFileFormat = info.get(QemuImg.BACKING_FILE_FORMAT);
if (StringUtils.isNotBlank(backingFileFormat)) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.BACKING_FILE_FORMAT, backingFileFormat);
}
String clusterSize = info.get(QemuImg.CLUSTER_SIZE);
if (StringUtils.isNotBlank(clusterSize)) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.CLUSTER_SIZE, clusterSize);
}
String fileFormat = info.get(QemuImg.FILE_FORMAT);
if (StringUtils.isNotBlank(fileFormat)) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.FILE_FORMAT, fileFormat);
}
String encrypted = info.get(QemuImg.ENCRYPTED);
if (StringUtils.isNotBlank(encrypted) && encrypted.equalsIgnoreCase("yes")) {
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.IS_ENCRYPTED, String.valueOf(Boolean.TRUE));
}
Boolean isLocked = isDiskFileLocked(storagePool, disk);
volumeOnStorageTO.addDetail(VolumeOnStorageTO.Detail.IS_LOCKED, String.valueOf(isLocked));
}
private GetVolumesOnStorageAnswer addAllVolumes(final GetVolumesOnStorageCommand command, final KVMStoragePool storagePool, String keyword) {
List<VolumeOnStorageTO> volumes = new ArrayList<>();
@ -134,11 +144,21 @@ public final class LibvirtGetVolumesOnStorageCommandWrapper extends CommandWrapp
if (!isDiskFormatSupported(disk)) {
continue;
}
Map<String, String> info = getDiskFileInfo(storagePool, disk, true);
if (info == null) {
continue;
}
VolumeOnStorageTO volumeOnStorageTO = new VolumeOnStorageTO(Hypervisor.HypervisorType.KVM, disk.getName(), disk.getName(), disk.getPath(),
disk.getFormat().toString(), disk.getSize(), disk.getVirtualSize());
if (disk.getQemuEncryptFormat() != null) {
volumeOnStorageTO.setQemuEncryptFormat(disk.getQemuEncryptFormat().toString());
}
String fileFormat = info.get(QemuImg.FILE_FORMAT);
if (StringUtils.isNotBlank(fileFormat) && !fileFormat.equalsIgnoreCase(disk.getFormat().toString())) {
continue;
}
addDetailsToVolumeOnStorageTO(volumeOnStorageTO, info, storagePool, disk);
volumes.add(volumeOnStorageTO);
}
return new GetVolumesOnStorageAnswer(command, volumes);

View File

@ -43,7 +43,7 @@ public final class LibvirtReadyCommandWrapper extends CommandWrapper<ReadyComman
public Answer execute(final ReadyCommand command, final LibvirtComputingResource libvirtComputingResource) {
Map<String, String> hostDetails = new HashMap<String, String>();
if (hostSupportsUefi(libvirtComputingResource.isUbuntuHost()) && libvirtComputingResource.isUefiPropertiesFileLoaded()) {
if (hostSupportsUefi(libvirtComputingResource.isUbuntuOrDebianHost()) && libvirtComputingResource.isUefiPropertiesFileLoaded()) {
hostDetails.put(Host.HOST_UEFI_ENABLE, Boolean.TRUE.toString());
}
@ -58,10 +58,10 @@ public final class LibvirtReadyCommandWrapper extends CommandWrapper<ReadyComman
return new ReadyAnswer(command, hostDetails);
}
private boolean hostSupportsUefi(boolean isUbuntuHost) {
private boolean hostSupportsUefi(boolean isUbuntuOrDebianHost) {
int timeout = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.AGENT_SCRIPT_TIMEOUT) * 1000; // Get property value & convert to milliseconds
int result;
if (isUbuntuHost) {
if (isUbuntuOrDebianHost) {
logger.debug("Running command : [dpkg -l ovmf] with timeout : " + timeout + " ms");
result = Script.executeCommandForExitValue(timeout, Script.getExecutableAbsolutePath("dpkg"), "-l", "ovmf");
} else {

View File

@ -25,7 +25,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.cloud.hypervisor.kvm.storage.ScaleIOStorageAdaptor;
import org.apache.cloudstack.utils.cryptsetup.KeyFile;
@ -33,7 +32,6 @@ import org.apache.cloudstack.utils.qemu.QemuImageOptions;
import org.apache.cloudstack.utils.qemu.QemuImg;
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
import org.apache.cloudstack.utils.qemu.QemuImgException;
import org.apache.cloudstack.utils.qemu.QemuImgFile;
import org.apache.cloudstack.utils.qemu.QemuObject;
import org.libvirt.Connect;
import org.libvirt.Domain;
@ -100,7 +98,7 @@ public final class LibvirtResizeVolumeCommandWrapper extends CommandWrapper<Resi
newSize = ScaleIOStorageAdaptor.getUsableBytesFromRawBytes(newSize);
} else if (spool.getType().equals(StoragePoolType.PowerFlex)) {
// PowerFlex RAW/LUKS is already resized, we just notify the domain based on new size (considering LUKS overhead)
newSize = getVirtualSizeFromFile(path);
newSize = KVMPhysicalDisk.getVirtualSizeFromFile(path);
}
if (pool.getType() != StoragePoolType.RBD && pool.getType() != StoragePoolType.Linstor && pool.getType() != StoragePoolType.PowerFlex) {
@ -214,21 +212,6 @@ public final class LibvirtResizeVolumeCommandWrapper extends CommandWrapper<Resi
}
}
private long getVirtualSizeFromFile(String path) {
try {
QemuImg qemu = new QemuImg(0);
QemuImgFile qemuFile = new QemuImgFile(path);
Map<String, String> info = qemu.info(qemuFile);
if (info.containsKey(QemuImg.VIRTUAL_SIZE)) {
return Long.parseLong(info.get(QemuImg.VIRTUAL_SIZE));
} else {
throw new CloudRuntimeException("Unable to determine virtual size of volume at path " + path);
}
} catch (QemuImgException | LibvirtException ex) {
throw new CloudRuntimeException("Error when inspecting volume at path " + path, ex);
}
}
private Answer handleMultipathSCSIResize(ResizeVolumeCommand command, KVMStoragePool pool) {
((MultipathSCSIPool)pool).resize(command.getPath(), command.getInstanceName(), command.getNewSize());
return new ResizeVolumeAnswer(command, true, "");

View File

@ -62,16 +62,25 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
String restoreVolumeUuid = command.getRestoreVolumeUUID();
String newVolumeId = null;
if (Objects.isNull(vmExists)) {
String volumePath = volumePaths.get(0);
int lastIndex = volumePath.lastIndexOf("/");
newVolumeId = volumePath.substring(lastIndex + 1);
restoreVolume(backupPath, backupRepoType, backupRepoAddress, volumePath, diskType, restoreVolumeUuid,
new Pair<>(vmName, command.getVmState()), mountOptions);
} else if (Boolean.TRUE.equals(vmExists)) {
restoreVolumesOfExistingVM(volumePaths, backupPath, backupRepoType, backupRepoAddress, mountOptions);
} else {
restoreVolumesOfDestroyedVMs(volumePaths, vmName, backupPath, backupRepoType, backupRepoAddress, mountOptions);
try {
if (Objects.isNull(vmExists)) {
String volumePath = volumePaths.get(0);
int lastIndex = volumePath.lastIndexOf("/");
newVolumeId = volumePath.substring(lastIndex + 1);
restoreVolume(backupPath, backupRepoType, backupRepoAddress, volumePath, diskType, restoreVolumeUuid,
new Pair<>(vmName, command.getVmState()), mountOptions);
} else if (Boolean.TRUE.equals(vmExists)) {
restoreVolumesOfExistingVM(volumePaths, backupPath, backupRepoType, backupRepoAddress, mountOptions);
} else {
restoreVolumesOfDestroyedVMs(volumePaths, vmName, backupPath, backupRepoType, backupRepoAddress, mountOptions);
}
} catch (CloudRuntimeException e) {
String errorMessage = "Failed to restore backup for VM: " + vmName + ".";
if (e.getMessage() != null && !e.getMessage().isEmpty()) {
errorMessage += " Details: " + e.getMessage();
}
logger.error(errorMessage);
return new BackupAnswer(command, false, errorMessage);
}
return new BackupAnswer(command, true, newVolumeId);
@ -86,10 +95,8 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
String volumePath = volumePaths.get(idx);
Pair<String, String> bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, null);
diskType = "datadisk";
try {
replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first());
} catch (IOException e) {
throw new CloudRuntimeException(String.format("Unable to revert backup for volume [%s] due to [%s].", bkpPathAndVolUuid.second(), e.getMessage()), e);
if (!replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first())) {
throw new CloudRuntimeException(String.format("Unable to restore backup for volume [%s].", bkpPathAndVolUuid.second()));
}
}
} finally {
@ -108,10 +115,8 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
String volumePath = volumePaths.get(i);
Pair<String, String> bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, null);
diskType = "datadisk";
try {
replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first());
} catch (IOException e) {
throw new CloudRuntimeException(String.format("Unable to revert backup for volume [%s] due to [%s].", bkpPathAndVolUuid.second(), e.getMessage()), e);
if (!replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first())) {
throw new CloudRuntimeException(String.format("Unable to restore backup for volume [%s].", bkpPathAndVolUuid.second()));
}
}
} finally {
@ -126,15 +131,13 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
Pair<String, String> bkpPathAndVolUuid;
try {
bkpPathAndVolUuid = getBackupPath(mountDirectory, volumePath, backupPath, diskType, volumeUUID);
try {
replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first());
if (VirtualMachine.State.Running.equals(vmNameAndState.second())) {
if (!attachVolumeToVm(vmNameAndState.first(), volumePath)) {
throw new CloudRuntimeException(String.format("Failed to attach volume to VM: %s", vmNameAndState.first()));
}
if (!replaceVolumeWithBackup(volumePath, bkpPathAndVolUuid.first())) {
throw new CloudRuntimeException(String.format("Unable to restore backup for volume [%s].", bkpPathAndVolUuid.second()));
}
if (VirtualMachine.State.Running.equals(vmNameAndState.second())) {
if (!attachVolumeToVm(vmNameAndState.first(), volumePath)) {
throw new CloudRuntimeException(String.format("Failed to attach volume to VM: %s", vmNameAndState.first()));
}
} catch (IOException e) {
throw new CloudRuntimeException(String.format("Unable to revert backup for volume [%s] due to [%s].", bkpPathAndVolUuid.second(), e.getMessage()), e);
}
} catch (Exception e) {
throw new CloudRuntimeException("Failed to restore volume", e);
@ -194,8 +197,9 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper<RestoreBa
return new Pair<>(bkpPath, volUuid);
}
private void replaceVolumeWithBackup(String volumePath, String backupPath) throws IOException {
Script.runSimpleBashScript(String.format(RSYNC_COMMAND, backupPath, volumePath));
private boolean replaceVolumeWithBackup(String volumePath, String backupPath) {
int exitValue = Script.runSimpleBashScriptForExitValue(String.format(RSYNC_COMMAND, backupPath, volumePath));
return exitValue == 0;
}
private boolean attachVolumeToVm(String vmName, String volumePath) {

View File

@ -16,10 +16,17 @@
// under the License.
package com.cloud.hypervisor.kvm.storage;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.storage.formatinspector.Qcow2Inspector;
import org.apache.cloudstack.utils.imagestore.ImageStoreUtil;
import org.apache.cloudstack.utils.qemu.QemuImg;
import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat;
import org.apache.cloudstack.utils.qemu.QemuImgException;
import org.apache.cloudstack.utils.qemu.QemuImgFile;
import org.apache.cloudstack.utils.qemu.QemuObject;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang3.StringUtils;
import org.libvirt.LibvirtException;
import java.util.ArrayList;
import java.util.List;
@ -83,6 +90,31 @@ public class KVMPhysicalDisk {
return hostIp;
}
public static long getVirtualSizeFromFile(String path) {
try {
QemuImg qemu = new QemuImg(0);
QemuImgFile qemuFile = new QemuImgFile(path);
Map<String, String> info = qemu.info(qemuFile);
if (info.containsKey(QemuImg.VIRTUAL_SIZE)) {
return Long.parseLong(info.get(QemuImg.VIRTUAL_SIZE));
} else {
throw new CloudRuntimeException("Unable to determine virtual size of volume at path " + path);
}
} catch (QemuImgException | LibvirtException ex) {
throw new CloudRuntimeException("Error when inspecting volume at path " + path, ex);
}
}
public static void checkQcow2File(String path) {
if (ImageStoreUtil.isCorrectExtension(path, "qcow2")) {
try {
Qcow2Inspector.validateQcow2File(path);
} catch (RuntimeException e) {
throw new CloudRuntimeException("The volume file at path " + path + " is not a valid QCOW2. Error: " + e.getMessage());
}
}
}
private PhysicalDiskFormat format;
private long size;
private long virtualSize;

View File

@ -236,6 +236,12 @@ public class MockAccountManager extends ManagerBase implements AccountManager {
return false;
}
@Override
public boolean isResourceDomainAdmin(Long accountId) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isNormalUser(long accountId) {
// TODO Auto-generated method stub

View File

@ -136,13 +136,18 @@ public class StorageVmSharedFSLifeCycle implements SharedFSLifeCycle {
return fsVmConfig;
}
private String getStorageVmName(String fileShareName) {
private String getStorageVmPrefix(String fileShareName) {
String prefix = String.format("%s-%s", SharedFSVmNamePrefix, fileShareName);
String suffix = Long.toHexString(System.currentTimeMillis());
if (!NetUtils.verifyDomainNameLabel(prefix, true)) {
prefix = prefix.replaceAll("[^a-zA-Z0-9-]", "");
}
return prefix;
}
private String getStorageVmName(String fileShareName) {
String prefix = getStorageVmPrefix(fileShareName);
String suffix = Long.toHexString(System.currentTimeMillis());
int nameLength = prefix.length() + suffix.length() + SharedFSVmNamePrefix.length();
if (nameLength > 63) {
int prefixLength = prefix.length() - (nameLength - 63);
@ -232,8 +237,18 @@ public class StorageVmSharedFSLifeCycle implements SharedFSLifeCycle {
Account owner = accountMgr.getActiveAccountById(sharedFS.getAccountId());
UserVm vm = deploySharedFSVM(sharedFS.getDataCenterId(), owner, List.of(networkId), sharedFS.getName(), sharedFS.getServiceOfferingId(), diskOfferingId, sharedFS.getFsType(), size, minIops, maxIops);
List<VolumeVO> volumes = volumeDao.findByInstanceAndType(vm.getId(), Volume.Type.DATADISK);
return new Pair<>(volumes.get(0).getId(), vm.getId());
List<VolumeVO> volumes = volumeDao.findByInstance(vm.getId());
VolumeVO dataVol = null;
for (VolumeVO vol : volumes) {
String volumeName = vol.getName();
String updatedVolumeName = SharedFSVmNamePrefix + "-" + volumeName;
vol.setName(updatedVolumeName);
volumeDao.update(vol.getId(), vol);
if (vol.getVolumeType() == Volume.Type.DATADISK) {
dataVol = vol;
}
}
return new Pair<>(dataVol.getId(), vm.getId());
}
@Override

View File

@ -259,9 +259,14 @@ public class StorageVmSharedFSLifeCycleTest {
anyMap(), isNull(), isNull(), isNull(), isNull(),
anyBoolean(), anyString(), isNull(), isNull(), isNull())).thenReturn(vm);
VolumeVO volume = mock(VolumeVO.class);
when(volume.getId()).thenReturn(s_volumeId);
when(volumeDao.findByInstanceAndType(s_vmId, Volume.Type.DATADISK)).thenReturn(List.of(volume));
VolumeVO rootVol = mock(VolumeVO.class);
when(rootVol.getVolumeType()).thenReturn(Volume.Type.ROOT);
when(rootVol.getName()).thenReturn("ROOT-1");
VolumeVO dataVol = mock(VolumeVO.class);
when(dataVol.getId()).thenReturn(s_volumeId);
when(dataVol.getName()).thenReturn("DATA-1");
when(dataVol.getVolumeType()).thenReturn(Volume.Type.DATADISK);
when(volumeDao.findByInstance(s_vmId)).thenReturn(List.of(rootVol, dataVol));
Pair<Long, Long> result = lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops);
Assert.assertEquals(Optional.ofNullable(result.first()), Optional.ofNullable(s_volumeId));

View File

@ -5,6 +5,12 @@ All notable changes to Linstor CloudStack plugin will be documented in this file
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2025-07-01]
### Fixed
- Regression in 4.19.3 and 4.21.0 with templates from snapshots
## [2025-05-07]
### Added

View File

@ -622,7 +622,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor {
try {
templateProps.load(new FileInputStream(propFile.toFile()));
String desc = templateProps.getProperty("description");
if (desc.startsWith("SystemVM Template")) {
if (desc != null && desc.startsWith("SystemVM Template")) {
return true;
}
} catch (IOException e) {

View File

@ -74,12 +74,14 @@ import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool;
import com.cloud.storage.VMTemplateStoragePoolVO;
import com.cloud.storage.VMTemplateStorageResourceAssoc;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeDetailVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.SnapshotDetailsDao;
import com.cloud.storage.dao.SnapshotDetailsVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VMTemplatePoolDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.storage.dao.VolumeDetailsDao;
@ -133,6 +135,7 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
ConfigurationDao _configDao;
@Inject
private HostDao _hostDao;
@Inject private VMTemplateDao _vmTemplateDao;
private long volumeStatsLastUpdate = 0L;
private final Map<String, Pair<Long, Long>> volumeStats = new HashMap<>();
@ -670,8 +673,15 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
storagePoolVO.getId(), csCloneId, null);
if (tmplPoolRef != null) {
final String templateRscName = LinstorUtil.RSC_PREFIX + tmplPoolRef.getLocalDownloadPath();
final String templateRscName;
if (tmplPoolRef.getLocalDownloadPath() == null) {
VMTemplateVO vmTemplateVO = _vmTemplateDao.findById(tmplPoolRef.getTemplateId());
templateRscName = LinstorUtil.RSC_PREFIX + vmTemplateVO.getUuid();
} else {
templateRscName = LinstorUtil.RSC_PREFIX + tmplPoolRef.getLocalDownloadPath();
}
final String rscName = LinstorUtil.RSC_PREFIX + volumeInfo.getUuid();
final DevelopersApi linstorApi = LinstorUtil.getLinstorAPI(storagePoolVO.getHostAddress());
try {

View File

@ -1279,13 +1279,13 @@ public class ScaleIOPrimaryDataStoreDriver implements PrimaryDataStoreDriver {
}
org.apache.cloudstack.storage.datastore.api.Volume scaleIOVolume = client.getVolume(scaleIOVolumeId);
long newSizeInGB = newSizeInBytes / (1024 * 1024 * 1024);
long newSizeIn8gbBoundary = (long) (Math.ceil(newSizeInGB / 8.0) * 8.0);
double newSizeInGB = newSizeInBytes / (1024.0 * 1024 * 1024);
long newSizeIn8GBBoundary = (long) (Math.ceil(newSizeInGB / 8.0) * 8.0);
if (scaleIOVolume.getSizeInKb() == newSizeIn8gbBoundary << 20) {
if (scaleIOVolume.getSizeInKb() == newSizeIn8GBBoundary << 20) {
logger.debug("No resize necessary at API");
} else {
scaleIOVolume = client.resizeVolume(scaleIOVolumeId, (int) newSizeIn8gbBoundary);
scaleIOVolume = client.resizeVolume(scaleIOVolumeId, (int) newSizeIn8GBBoundary);
if (scaleIOVolume == null) {
throw new CloudRuntimeException("Failed to resize volume: " + volumeInfo.getName());
}
@ -1411,12 +1411,12 @@ public class ScaleIOPrimaryDataStoreDriver implements PrimaryDataStoreDriver {
@Override
public long getVolumeSizeRequiredOnPool(long volumeSize, Long templateSize, boolean isEncryptionRequired) {
long newSizeInGB = volumeSize / (1024 * 1024 * 1024);
double newSizeInGB = volumeSize / (1024.0 * 1024 * 1024);
if (templateSize != null && isEncryptionRequired && needsExpansionForEncryptionHeader(templateSize, volumeSize)) {
newSizeInGB = (volumeSize + (1<<30)) / (1024 * 1024 * 1024);
newSizeInGB = (volumeSize + (1<<30)) / (1024.0 * 1024 * 1024);
}
long newSizeIn8gbBoundary = (long) (Math.ceil(newSizeInGB / 8.0) * 8.0);
return newSizeIn8gbBoundary * (1024 * 1024 * 1024);
long newSizeIn8GBBoundary = (long) (Math.ceil(newSizeInGB / 8.0) * 8.0);
return newSizeIn8GBBoundary * (1024 * 1024 * 1024);
}
@Override

View File

@ -555,6 +555,18 @@ public class ScaleIOPrimaryDataStoreDriverTest {
@Test
public void testGetVolumeSizeRequiredOnPool() {
Assert.assertEquals(8L * (1024 * 1024 * 1024),
scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
52428800,
null,
false));
Assert.assertEquals(8L * (1024 * 1024 * 1024),
scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
52428800,
52428800L,
true));
Assert.assertEquals(16L * (1024 * 1024 * 1024),
scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool(
10L * (1024 * 1024 * 1024),

View File

@ -150,6 +150,9 @@ public class StorPoolStorageAdaptor implements StorageAdaptor {
}
public static String getVolumeNameFromPath(final String volumeUuid, boolean tildeNeeded) {
if (volumeUuid == null) {
return null;
}
if (volumeUuid.startsWith("/dev/storpool/")) {
return volumeUuid.split("/")[3];
} else if (volumeUuid.startsWith("/dev/storpool-byid/")) {

View File

@ -140,10 +140,11 @@ public class LdapListUsersCmd extends BaseListCmd {
try {
final List<LdapUser> users = _ldapManager.getUsers(domainId);
ldapResponses = createLdapUserResponse(users);
// now filter and annotate
// now filter and annotate
ldapResponses = applyUserFilter(ldapResponses);
} catch (final NoLdapUserMatchingQueryException ex) {
// ok, we'll make do with the empty list ldapResponses = new ArrayList<LdapUserResponse>();
logger.debug(ex.getMessage());
// ok, we'll make do with the empty list
} finally {
response.setResponses(ldapResponses);
response.setResponseName(getCommandName());

View File

@ -45,6 +45,8 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
@Inject
private AccountManager _accountManager;
private static final String LDAP_READ_TIMED_OUT_MESSAGE = "LDAP response read timed out";
public LdapAuthenticator() {
super();
}
@ -74,8 +76,8 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
return rc;
}
List<LdapTrustMapVO> ldapTrustMapVOs = getLdapTrustMapVOS(domainId);
if(ldapTrustMapVOs != null && ldapTrustMapVOs.size() > 0) {
if(ldapTrustMapVOs.size() == 1 && ldapTrustMapVOs.get(0).getAccountId() == 0) {
if (ldapTrustMapVOs != null && ldapTrustMapVOs.size() > 0) {
if (ldapTrustMapVOs.size() == 1 && ldapTrustMapVOs.get(0).getAccountId() == 0) {
if (logger.isTraceEnabled()) {
logger.trace("We have a single mapping of a domain to an ldap group or ou");
}
@ -125,11 +127,11 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
mappedGroups.retainAll(memberships);
tracelist("actual groups for " + username, mappedGroups);
// check membership, there must be only one match in this domain
if(ldapUser.isDisabled()) {
if (ldapUser.isDisabled()) {
logAndDisable(userAccount, "attempt to log on using disabled ldap user " + userAccount.getUsername(), false);
} else if(mappedGroups.size() > 1) {
} else if (mappedGroups.size() > 1) {
logAndDisable(userAccount, "user '" + username + "' is mapped to more then one account in domain and will be disabled.", false);
} else if(mappedGroups.size() < 1) {
} else if (mappedGroups.size() < 1) {
logAndDisable(userAccount, "user '" + username + "' is not mapped to an account in domain and will be removed.", true);
} else {
// a valid ldap configured user exists
@ -137,12 +139,12 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
// we could now assert that ldapTrustMapVOs.contains(mapping);
// createUser in Account can only be done by account name not by account id;
Account account = _accountManager.getAccount(mapping.getAccountId());
if(null == account) {
if (null == account) {
throw new CloudRuntimeException(String.format("account for user (%s) not found by id %d", username, mapping.getAccountId()));
}
String accountName = account.getAccountName();
rc.first(_ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId));
if (! rc.first()) {
if (!rc.first()) {
rc.second(ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
}
// for security reasons we keep processing on faulty login attempt to not give a way information on userid existence
@ -162,7 +164,7 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
userAccount = _accountManager.getUserAccountById(user.getId());
} else {
// not a new user, check if mapped group has changed
if(userAccount.getAccountId() != mapping.getAccountId()) {
if (userAccount.getAccountId() != mapping.getAccountId()) {
final Account mappedAccount = _accountManager.getAccount(mapping.getAccountId());
if (mappedAccount == null || mappedAccount.getRemoved() != null) {
throw new CloudRuntimeException("Mapped account for users does not exist. Please contact your administrator.");
@ -174,12 +176,21 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
}
} catch (NoLdapUserMatchingQueryException e) {
logger.debug(e.getMessage());
disableUserInCloudStack(userAccount);
processLdapUserErrorMessage(userAccount, e.getMessage(), rc);
}
return rc;
}
private void processLdapUserErrorMessage(UserAccount user, String errorMessage, Pair<Boolean, ActionOnFailedAuthentication> rc) {
if (StringUtils.isNotEmpty(errorMessage) && errorMessage.contains(LDAP_READ_TIMED_OUT_MESSAGE) && !rc.first()) {
rc.second(ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
} else {
// no user in ldap ==>> disable user in cloudstack
disableUserInCloudStack(user);
}
}
private void tracelist(String msg, List<String> listToTrace) {
if (logger.isTraceEnabled()) {
StringBuilder logMsg = new StringBuilder();
@ -197,7 +208,7 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
if (logger.isInfoEnabled()) {
logger.info(msg);
}
if(remove) {
if (remove) {
removeUserInCloudStack(userAccount);
} else {
disableUserInCloudStack(userAccount);
@ -229,23 +240,22 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
processLdapUser(password, domainId, user, rc, ldapUser, accountType);
} catch (NoLdapUserMatchingQueryException e) {
logger.debug(e.getMessage());
// no user in ldap ==>> disable user in cloudstack
disableUserInCloudStack(user);
processLdapUserErrorMessage(user, e.getMessage(), rc);
}
return rc;
}
private void processLdapUser(String password, Long domainId, UserAccount user, Pair<Boolean, ActionOnFailedAuthentication> rc, LdapUser ldapUser, Account.Type accountType) {
if(!ldapUser.isDisabled()) {
if (!ldapUser.isDisabled()) {
rc.first(_ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId));
if(rc.first()) {
if(user == null) {
if (rc.first()) {
if (user == null) {
// import user to cloudstack
createCloudStackUserAccount(ldapUser, domainId, accountType);
} else {
enableUserInCloudStack(user);
}
} else if(user != null) {
} else if (user != null) {
rc.second(ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT);
}
} else {
@ -264,30 +274,34 @@ public class LdapAuthenticator extends AdapterBase implements UserAuthenticator
*/
Pair<Boolean, ActionOnFailedAuthentication> authenticate(String username, String password, Long domainId, UserAccount user) {
boolean result = false;
boolean timedOut = false;
if(user != null ) {
if (user != null ) {
try {
LdapUser ldapUser = _ldapManager.getUser(username, domainId);
if(!ldapUser.isDisabled()) {
if (!ldapUser.isDisabled()) {
result = _ldapManager.canAuthenticate(ldapUser.getPrincipal(), password, domainId);
} else {
logger.debug("user with principal "+ ldapUser.getPrincipal() + " is disabled in ldap");
}
} catch (NoLdapUserMatchingQueryException e) {
logger.debug(e.getMessage());
if (e.getMessage().contains(LDAP_READ_TIMED_OUT_MESSAGE)) {
timedOut = true;
}
}
}
return processResultAndAction(user, result);
return processResultAndAction(user, result, timedOut);
}
private Pair<Boolean, ActionOnFailedAuthentication> processResultAndAction(UserAccount user, boolean result) {
return (!result && user != null) ?
private Pair<Boolean, ActionOnFailedAuthentication> processResultAndAction(UserAccount user, boolean result, boolean timedOut) {
return (!result && (user != null || timedOut)) ?
new Pair<Boolean, ActionOnFailedAuthentication>(result, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT):
new Pair<Boolean, ActionOnFailedAuthentication>(result, null);
}
private void enableUserInCloudStack(UserAccount user) {
if(user != null && (user.getState().equalsIgnoreCase(Account.State.DISABLED.toString()))) {
if (user != null && (user.getState().equalsIgnoreCase(Account.State.DISABLED.toString()))) {
_accountManager.enableUser(user.getId());
}
}

View File

@ -166,7 +166,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
private LdapConfigurationResponse addConfigurationInternal(final String hostname, int port, final Long domainId) throws InvalidParameterValueException {
// TODO evaluate what the right default should be
if(port <= 0) {
if (port <= 0) {
port = 389;
}
@ -210,7 +210,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
// TODO return the right account for this user
final LdapContext context = _ldapContextFactory.createUserContext(principal, password, domainId);
closeContext(context);
if(logger.isTraceEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace(String.format("User(%s) authenticated for domain(%s)", principal, domainId));
}
return true;
@ -234,7 +234,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
@Override
public LdapConfigurationResponse createLdapConfigurationResponse(final LdapConfigurationVO configuration) {
String domainUuid = null;
if(configuration.getDomainId() != null) {
if (configuration.getDomainId() != null) {
DomainVO domain = domainDao.findById(configuration.getDomainId());
if (domain != null) {
domainUuid = domain.getUuid();
@ -303,8 +303,8 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUser(escapedUsername, context, domainId);
} catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e);
throw new NoLdapUserMatchingQueryException("No Ldap User found for username: "+username);
logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("Unable to find LDAP User for username: " + username + ", due to " + e.getMessage());
} finally {
closeContext(context);
}
@ -324,8 +324,8 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
LdapUserManager userManagerFactory = _ldapUserManagerFactory.getInstance(ldapProvider);
return userManagerFactory.getUser(escapedUsername, type, name, context, domainId);
} catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e);
throw new NoLdapUserMatchingQueryException("No Ldap User found for username: "+username + " in group: " + name + " of type: " + type);
logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("Unable to find LDAP User for username: " + username + " in group: " + name + " of type: " + type + ", due to " + e.getMessage());
} finally {
closeContext(context);
}
@ -338,7 +338,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
context = _ldapContextFactory.createBindContext(domainId);
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsers(context, domainId);
} catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e);
logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("*");
} finally {
closeContext(context);
@ -352,7 +352,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
context = _ldapContextFactory.createBindContext(domainId);
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(domainId)).getUsersInGroup(groupName, context, domainId);
} catch (NamingException | IOException e) {
logger.debug("ldap NamingException: ",e);
logger.debug("LDAP Exception: ", e);
throw new NoLdapUserMatchingQueryException("groupName=" + groupName);
} finally {
closeContext(context);
@ -390,7 +390,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
final String escapedUsername = LdapUtils.escapeLDAPSearchFilter(username);
return _ldapUserManagerFactory.getInstance(_ldapConfiguration.getLdapProvider(null)).getUsers("*" + escapedUsername + "*", context, null);
} catch (NamingException | IOException e) {
logger.debug("ldap Exception: ",e);
logger.debug("LDAP Exception: ",e);
throw new NoLdapUserMatchingQueryException(username);
} finally {
closeContext(context);
@ -481,7 +481,7 @@ public class LdapManagerImpl extends ComponentLifecycleBase implements LdapManag
private void clearOldAccountMapping(LinkAccountToLdapCmd cmd) {
// first find if exists log warning and update
LdapTrustMapVO oldVo = _ldapTrustMapDao.findGroupInDomain(cmd.getDomainId(), cmd.getLdapDomain());
if(oldVo != null) {
if (oldVo != null) {
// deal with edge cases, i.e. check if the old account is indeed deleted etc.
if (oldVo.getAccountId() != 0l) {
AccountVO oldAcount = accountDao.findByIdIncludingRemoved(oldVo.getAccountId());

View File

@ -478,6 +478,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
isoResponse.setExtractable(iso.isExtractable() && !(iso.getTemplateType() == TemplateType.PERHOST));
isoResponse.setCreated(iso.getCreatedOnStore());
isoResponse.setDynamicallyScalable(iso.isDynamicallyScalable());
isoResponse.setFormat(iso.getFormat());
if (iso.getTemplateType() == TemplateType.PERHOST) {
// for TemplateManager.XS_TOOLS_ISO and TemplateManager.VMWARE_TOOLS_ISO, we didn't download, but is ready to use.
isoResponse.setReady(true);
@ -577,10 +578,14 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation<Templa
isoResponse.setZoneName(iso.getDataCenterName());
}
Long isoSize = iso.getSize();
long isoSize = iso.getSize();
if (isoSize > 0) {
isoResponse.setSize(isoSize);
}
long isoPhysicalSize = iso.getPhysicalSize();
if (isoPhysicalSize > 0) {
isoResponse.setPhysicalSize(isoPhysicalSize);
}
if (iso.getUserDataId() != null) {
isoResponse.setUserDataId(iso.getUserDataUUid());

View File

@ -1276,6 +1276,10 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
buf.append(" vmpassword=").append(configurationDao.getValue("system.vm.password"));
}
if (StringUtils.isNotEmpty(NTPServerConfig.value())) {
buf.append(" ntpserverlist=").append(NTPServerConfig.value().replaceAll("\\s+",""));
}
for (NicProfile nic : profile.getNics()) {
int deviceId = nic.getDeviceId();
if (nic.getIPv4Address() == null) {
@ -1506,7 +1510,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
public Long[] getScannablePools() {
List<Long> zoneIds = dataCenterDao.listEnabledNonEdgeZoneIds();
if (logger.isDebugEnabled()) {
logger.debug(String.format("Enabled non-edge zones available for scan: %s", org.apache.commons.lang3.StringUtils.join(zoneIds, ",")));
logger.debug(String.format("Enabled non-edge zones available for scan: %s", StringUtils.join(zoneIds, ",")));
}
return zoneIds.toArray(Long[]::new);
}

View File

@ -146,6 +146,7 @@ import com.cloud.vm.dao.VMInstanceDao;
@Component
public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLimitService, Configurable {
public static final String CHECKING_IF = "Checking if {}";
@Inject
private AccountManager _accountMgr;
@Inject
@ -171,8 +172,6 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
@Inject
private ResourceLimitDao _resourceLimitDao;
@Inject
private ResourceLimitService resourceLimitService;
@Inject
private ReservationDao reservationDao;
@Inject
protected SnapshotDao _snapshotDao;
@ -353,7 +352,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
return;
}
final long numToIncrement = (delta.length == 0) ? 1 : delta[0].longValue();
final long numToIncrement = (delta.length == 0) ? 1 : delta[0];
removeResourceReservationIfNeededAndIncrementResourceCount(accountId, type, tag, numToIncrement);
}
@ -369,7 +368,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
logger.trace("Not decrementing resource count for system accounts, returning");
return;
}
long numToDecrement = (delta.length == 0) ? 1 : delta[0].longValue();
long numToDecrement = (delta.length == 0) ? 1 : delta[0];
if (!updateResourceCountForAccount(accountId, type, tag, false, numToDecrement)) {
_alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, "Failed to decrement resource count of type " + type + " for account id=" + accountId,
@ -396,11 +395,11 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
// Check if limit is configured for account
if (limit != null) {
max = limit.getMax().longValue();
max = limit.getMax();
} else {
String resourceTypeName = type.name();
// If the account has an no limit set, then return global default account limits
Long value = null;
Long value;
if (account.getType() == Account.Type.PROJECT) {
value = projectResourceLimitMap.get(resourceTypeName);
} else {
@ -441,10 +440,10 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
// Check if limit is configured for account
if (limit != null) {
max = limit.longValue();
max = limit;
} else {
// If the account has an no limit set, then return global default account limits
Long value = null;
Long value;
if (account.getType() == Account.Type.PROJECT) {
value = projectResourceLimitMap.get(type.getName());
} else {
@ -476,7 +475,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
ResourceLimitVO limit = _resourceLimitDao.findByOwnerIdAndTypeAndTag(domain.getId(), ResourceOwnerType.Domain, type, tag);
if (limit != null) {
max = limit.getMax().longValue();
max = limit.getMax();
} else {
// check domain hierarchy
Long domainId = domain.getParent();
@ -490,12 +489,12 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
}
if (limit != null) {
max = limit.getMax().longValue();
max = limit.getMax();
} else {
if (StringUtils.isNotEmpty(tag)) {
return findCorrectResourceLimitForDomain(domain, type, null);
}
Long value = null;
Long value;
value = domainResourceLimitMap.get(type.name());
if (value != null) {
if (value < 0) { // return unlimit if value is set to negative
@ -514,7 +513,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
protected void checkDomainResourceLimit(final Account account, final Project project, final ResourceType type, String tag, long numResources) throws ResourceAllocationException {
// check all domains in the account's domain hierarchy
Long domainId = null;
Long domainId;
if (project != null) {
domainId = project.getDomainId();
} else {
@ -553,9 +552,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
convCurrentDomainResourceCount, convCurrentResourceReservation, convNumResources
);
if (logger.isDebugEnabled()) {
logger.debug("Checking if" + messageSuffix);
}
logger.debug(CHECKING_IF, messageSuffix);
if (domainResourceLimit != Resource.RESOURCE_UNLIMITED && requestedDomainResourceCount > domainResourceLimit) {
String message = "Maximum" + messageSuffix;
@ -594,9 +591,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
convertedAccountResourceLimit, convertedCurrentResourceCount, convertedCurrentResourceReservation, convertedNumResources
);
if (logger.isDebugEnabled()) {
logger.debug("Checking if" + messageSuffix);
}
logger.debug(CHECKING_IF, messageSuffix);
if (accountResourceLimit != Resource.RESOURCE_UNLIMITED && requestedResourceCount > accountResourceLimit) {
String message = "Maximum" + messageSuffix;
@ -615,14 +610,14 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
@Override
public long findDefaultResourceLimitForDomain(ResourceType resourceType) {
Long resourceLimit = null;
Long resourceLimit;
resourceLimit = domainResourceLimitMap.get(resourceType.getName());
if (resourceLimit != null && ResourceType.isStorageType(resourceType)) {
if (! Long.valueOf(Resource.RESOURCE_UNLIMITED).equals(resourceLimit)) {
resourceLimit = resourceLimit * ResourceType.bytesToGiB;
}
} else {
resourceLimit = Long.valueOf(Resource.RESOURCE_UNLIMITED);
resourceLimit = (long) Resource.RESOURCE_UNLIMITED;
}
return resourceLimit;
}
@ -700,8 +695,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
@Override
public List<ResourceLimitVO> searchForLimits(Long id, Long accountId, Long domainId, ResourceType resourceType, String tag, Long startIndex, Long pageSizeVal) {
Account caller = CallContext.current().getCallingAccount();
List<ResourceLimitVO> limits = new ArrayList<ResourceLimitVO>();
boolean isAccount = true;
List<ResourceLimitVO> limits = new ArrayList<>();
boolean isAccount;
if (!_accountMgr.isAdmin(caller.getId())) {
accountId = caller.getId();
@ -793,7 +788,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
if (foundLimits.isEmpty()) {
ResourceOwnerType ownerType = ResourceOwnerType.Domain;
Long ownerId = domainId;
long max = 0;
long max;
if (isAccount) {
ownerType = ResourceOwnerType.Account;
ownerId = accountId;
@ -811,8 +806,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
// see if any limits are missing from the table, and if yes - get it from the config table and add
ResourceType[] resourceTypes = ResourceCount.ResourceType.values();
if (foundLimits.size() != resourceTypes.length) {
List<String> accountLimitStr = new ArrayList<String>();
List<String> domainLimitStr = new ArrayList<String>();
List<String> accountLimitStr = new ArrayList<>();
List<String> domainLimitStr = new ArrayList<>();
for (ResourceLimitVO foundLimit : foundLimits) {
if (foundLimit.getAccountId() != null) {
accountLimitStr.add(foundLimit.getType().toString());
@ -906,8 +901,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
Account caller = CallContext.current().getCallingAccount();
if (max == null) {
max = new Long(Resource.RESOURCE_UNLIMITED);
} else if (max.longValue() < Resource.RESOURCE_UNLIMITED) {
max = (long)Resource.RESOURCE_UNLIMITED;
} else if (max < Resource.RESOURCE_UNLIMITED) {
throw new InvalidParameterValueException("Please specify either '-1' for an infinite limit, or a limit that is at least '0'.");
}
@ -915,7 +910,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
ResourceType resourceType = null;
if (typeId != null) {
for (ResourceType type : Resource.ResourceType.values()) {
if (type.getOrdinal() == typeId.intValue()) {
if (type.getOrdinal() == typeId) {
resourceType = type;
}
}
@ -954,7 +949,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
throw new InvalidParameterValueException("Only " + Resource.RESOURCE_UNLIMITED + " limit is supported for Root Admin accounts");
}
if ((caller.getAccountId() == accountId.longValue()) && (_accountMgr.isDomainAdmin(caller.getId()) || caller.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN)) {
if ((caller.getAccountId() == accountId) && (_accountMgr.isDomainAdmin(caller.getId()) || caller.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN)) {
// If the admin is trying to update their own account, disallow.
throw new PermissionDeniedException(String.format("Unable to update resource limit for their own account %s, permission denied", account));
}
@ -990,12 +985,12 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
_accountMgr.checkAccess(caller, domain);
if (Domain.ROOT_DOMAIN == domainId.longValue()) {
if (Domain.ROOT_DOMAIN == domainId) {
// no one can add limits on ROOT domain, disallow...
throw new PermissionDeniedException("Cannot update resource limit for ROOT domain " + domainId + ", permission denied");
}
if ((caller.getDomainId() == domainId.longValue()) && caller.getType() == Account.Type.DOMAIN_ADMIN || caller.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN) {
if ((caller.getDomainId() == domainId) && caller.getType() == Account.Type.DOMAIN_ADMIN || caller.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN) {
// if the admin is trying to update their own domain, disallow...
throw new PermissionDeniedException("Unable to update resource limit for domain " + domainId + ", permission denied");
}
@ -1010,7 +1005,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
if (parentDomainId != null) {
DomainVO parentDomain = _domainDao.findById(parentDomainId);
long parentMaximum = findCorrectResourceLimitForDomain(parentDomain, resourceType, tag);
if ((parentMaximum >= 0) && (max.longValue() > parentMaximum)) {
if ((parentMaximum >= 0) && (max > parentMaximum)) {
throw new InvalidParameterValueException(String.format("Domain %s has maximum allowed resource limit %d for %s, please specify a value less than or equal to %d", parentDomain, parentMaximum, resourceType, parentMaximum));
}
}
@ -1107,15 +1102,15 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
@Override
public List<? extends ResourceCount> recalculateResourceCount(Long accountId, Long domainId, Integer typeId, String tag) throws CloudRuntimeException {
Account callerAccount = CallContext.current().getCallingAccount();
long count = 0;
List<ResourceCountVO> counts = new ArrayList<ResourceCountVO>();
List<ResourceType> resourceTypes = new ArrayList<ResourceType>();
long count;
List<ResourceCountVO> counts = new ArrayList<>();
List<ResourceType> resourceTypes = new ArrayList<>();
ResourceType resourceType = null;
if (typeId != null) {
for (ResourceType type : Resource.ResourceType.values()) {
if (type.getOrdinal() == typeId.intValue()) {
if (type.getOrdinal() == typeId) {
resourceType = type;
}
}
@ -1134,12 +1129,13 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
throw new InvalidParameterValueException("Please specify a valid domain ID.");
}
_accountMgr.checkAccess(callerAccount, domain);
Account account = _entityMgr.findById(Account.class, accountId);
if (account == null) {
throw new InvalidParameterValueException("Unable to find account " + accountId);
if (accountId != null) {
Account account = _entityMgr.findById(Account.class, accountId);
if (account == null) {
throw new InvalidParameterValueException("Unable to find account " + accountId);
}
_accountMgr.verifyCallerPrivilegeForUserOrAccountOperations(account);
}
_accountMgr.verifyCallerPrivilegeForUserOrAccountOperations(account);
if (resourceType != null) {
resourceTypes.add(resourceType);
} else {
@ -1188,7 +1184,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
convertedDelta = toHumanReadableSize(delta);
}
String typeStr = StringUtils.isNotEmpty(tag) ? String.format("%s (tag: %s)", type, tag) : type.getName();
logger.debug("Updating resource Type = " + typeStr + " count for Account = " + accountId + " Operation = " + (increment ? "increasing" : "decreasing") + " Amount = " + convertedDelta);
logger.debug("Updating resource Type = {} count for Account with id = {} Operation = {} Amount = {}", typeStr, accountId, (increment ? "increasing" : "decreasing"), convertedDelta);
}
Set<Long> rowIdsToUpdate = _resourceCountDao.listAllRowsToUpdate(accountId, ResourceOwnerType.Account, type, tag);
return _resourceCountDao.updateCountByDeltaForIds(new ArrayList<>(rowIdsToUpdate), increment, delta);
@ -1243,6 +1239,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
newResourceCount += _projectDao.countProjectsForDomain(domainId);
}
// TODO make sure that the resource counts are not null
for (ResourceCountVO resourceCount : resourceCounts) {
if (resourceCount.getResourceOwnerType() == ResourceOwnerType.Domain && resourceCount.getDomainId() == domainId) {
oldResourceCount = resourceCount.getCount();
@ -1252,11 +1249,12 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
}
}
// TODO domainRC may be null if there are no resource counts for the domain found in the loop above
if (oldResourceCount != newResourceCount) {
domainRC.setCount(newResourceCount);
_resourceCountDao.update(domainRC.getId(), domainRC);
logger.warn("Discrepency in the resource count has been detected " + "(original count = " + oldResourceCount + " correct count = " + newResourceCount + ") for Type = " + type
+ " for Domain ID = " + domainId + " is fixed during resource count recalculation.");
logger.warn("Discrepency in the resource count has been detected (original count = {} correct count = {}) for Type = {} for Domain ID = {} is fixed during resource count recalculation.",
oldResourceCount, newResourceCount, type, domainId);
}
return newResourceCount;
});
@ -1329,9 +1327,10 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
// No need to log message for storage type resources because both are recalculating the
// resource count which will not lead to any discrepancy.
if (newCount != null && !newCount.equals(oldCount) && !ResourceType.isStorageType(type)) {
logger.warn("Discrepancy in the resource count " + "(original count=" + oldCount + " correct count = " + newCount + ") for type " + type +
" for account ID " + accountId + " is fixed during resource count recalculation.");
if (newCount != null && !newCount.equals(oldCount) &&
type != Resource.ResourceType.primary_storage && type != Resource.ResourceType.secondary_storage) {
logger.warn("Discrepancy in the resource count (original count={} correct count = {}) for type {} for account ID {} is fixed during resource count recalculation.",
oldCount, newCount, type, accountId);
}
return (newCount == null) ? 0 : newCount;
@ -1475,20 +1474,16 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
}
private long calculatePublicIpForAccount(long accountId) {
Long dedicatedCount = 0L;
Long allocatedCount = 0L;
long dedicatedCount = 0L;
long allocatedCount;
List<VlanVO> dedicatedVlans = _vlanDao.listDedicatedVlans(accountId);
for (VlanVO dedicatedVlan : dedicatedVlans) {
List<IPAddressVO> ips = _ipAddressDao.listByVlanId(dedicatedVlan.getId());
dedicatedCount += new Long(ips.size());
dedicatedCount += ips.size();
}
allocatedCount = _ipAddressDao.countAllocatedIPsForAccount(accountId);
if (dedicatedCount > allocatedCount) {
return dedicatedCount;
} else {
return allocatedCount;
}
return Math.max(dedicatedCount, allocatedCount);
}
protected long calculatePrimaryStorageForAccount(long accountId, String tag) {
@ -1576,10 +1571,10 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
protected TaggedResourceLimitAndCountResponse getTaggedResourceLimitAndCountResponse(Account account,
Domain domain, ResourceOwnerType ownerType, ResourceType type, String tag) {
Long limit = ResourceOwnerType.Account.equals(ownerType) ?
long limit = ResourceOwnerType.Account.equals(ownerType) ?
findCorrectResourceLimitForAccount(account, type, tag) :
findCorrectResourceLimitForDomain(domain, type, tag);
Long count = 0L;
long count = 0L;
ResourceCountVO countVO = _resourceCountDao.findByOwnerAndTypeAndTag(
ResourceOwnerType.Account.equals(ownerType) ? account.getId() : domain.getId(), ownerType, type, tag);
if (countVO != null) {
@ -1828,7 +1823,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
if (currentOfferingTags.isEmpty() && newOfferingTags.isEmpty()) {
return null;
}
Set<String> sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet());;
Set<String> sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet());
Set<String> newTags = newOfferingTags.stream().filter(tag -> !currentOfferingTags.contains(tag)).collect(Collectors.toSet());
Set<String> removedTags = currentOfferingTags.stream().filter(tag -> !newOfferingTags.contains(tag)).collect(Collectors.toSet());
return new Ternary<>(sameTags, newTags, removedTags);
@ -1899,7 +1894,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
if (currentOfferingTags.isEmpty() && newOfferingTags.isEmpty()) {
return null;
}
Set<String> sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet());;
Set<String> sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet());
Set<String> newTags = newOfferingTags.stream().filter(tag -> !currentOfferingTags.contains(tag)).collect(Collectors.toSet());
Set<String> removedTags = currentOfferingTags.stream().filter(tag -> !newOfferingTags.contains(tag)).collect(Collectors.toSet());
return new Ternary<>(sameTags, newTags, removedTags);

View File

@ -777,7 +777,6 @@ import com.cloud.org.Grouping.AllocationState;
import com.cloud.projects.Project;
import com.cloud.projects.Project.ListProjectResourcesCriteria;
import com.cloud.projects.ProjectManager;
import com.cloud.resource.ResourceManager;
import com.cloud.server.ResourceTag.ResourceObjectType;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
@ -879,8 +878,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
static final ConfigKey<Integer> sshKeyLength = new ConfigKey<>("Advanced", Integer.class, "ssh.key.length", "2048", "Specifies custom SSH key length (bit)", true, ConfigKey.Scope.Global);
static final ConfigKey<Boolean> humanReadableSizes = new ConfigKey<>("Advanced", Boolean.class, "display.human.readable.sizes", "true", "Enables outputting human readable byte sizes to logs and usage records.", false, ConfigKey.Scope.Global);
public static final ConfigKey<String> customCsIdentifier = new ConfigKey<>("Advanced", String.class, "custom.cs.identifier", UUID.randomUUID().toString().split("-")[0].substring(4), "Custom identifier for the cloudstack installation", true, ConfigKey.Scope.Global);
public static final ConfigKey<Boolean> exposeCloudStackVersionInApiXmlResponse = new ConfigKey<Boolean>("Advanced", Boolean.class, "expose.cloudstack.version.api.xml.response", "true", "Indicates whether ACS version should appear in the root element of an API XML response.", true, ConfigKey.Scope.Global);
public static final ConfigKey<Boolean> exposeCloudStackVersionInApiListCapabilities = new ConfigKey<Boolean>("Advanced", Boolean.class, "expose.cloudstack.version.api.list.capabilities", "true", "Indicates whether ACS version should show in the listCapabilities API.", true, ConfigKey.Scope.Global);
public static final ConfigKey<Boolean> exposeCloudStackVersionInApiXmlResponse = new ConfigKey<>("Advanced", Boolean.class, "expose.cloudstack.version.api.xml.response", "true", "Indicates whether ACS version should appear in the root element of an API XML response.", true, ConfigKey.Scope.Global);
public static final ConfigKey<Boolean> exposeCloudStackVersionInApiListCapabilities = new ConfigKey<>("Advanced", Boolean.class, "expose.cloudstack.version.api.list.capabilities", "true", "Indicates whether ACS version should show in the listCapabilities API.", true, ConfigKey.Scope.Global);
private static final VirtualMachine.Type []systemVmTypes = { VirtualMachine.Type.SecondaryStorageVm, VirtualMachine.Type.ConsoleProxy};
private static final List<HypervisorType> LIVE_MIGRATION_SUPPORTING_HYPERVISORS = List.of(HypervisorType.Hyperv, HypervisorType.KVM,
@ -985,8 +984,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
@Inject
private ProjectManager _projectMgr;
@Inject
private ResourceManager _resourceMgr;
@Inject
private HighAvailabilityManager _haMgr;
@Inject
private HostTagsDao _hostTagsDao;
@ -4729,6 +4726,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
capabilities.put(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_ENABLED, StatsCollector.vmDiskStatsRetentionEnabled.value());
capabilities.put(ApiConstants.INSTANCES_DISKS_STATS_RETENTION_TIME, StatsCollector.vmDiskStatsMaxRetentionTime.value());
capabilities.put(ApiConstants.INSTANCE_LEASE_ENABLED, VMLeaseManager.InstanceLeaseEnabled.value());
capabilities.put(ApiConstants.DYNAMIC_SCALING_ENABLED, UserVmManager.EnableDynamicallyScaleVm.value());
if (apiLimitEnabled) {
capabilities.put("apiLimitInterval", apiLimitInterval);
capabilities.put("apiLimitMax", apiLimitMax);

View File

@ -2637,7 +2637,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
excludeLocalStorageIfNeeded(volumeToAttach);
checkForDevicesInCopies(vmId, vm);
checkForVMSnapshots(vmId, vm);
checkForBackups(vm, true);
checkRightsToAttach(caller, volumeToAttach, vm);
@ -2739,18 +2741,12 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
private void checkForDevicesInCopies(Long vmId, UserVmVO vm) {
private void checkForVMSnapshots(Long vmId, UserVmVO vm) {
// if target VM has associated VM snapshots
List<VMSnapshotVO> vmSnapshots = _vmSnapshotDao.findByVm(vmId);
if (vmSnapshots.size() > 0) {
throw new InvalidParameterValueException(String.format("Unable to attach volume to VM %s/%s, please specify a VM that does not have VM snapshots", vm.getName(), vm.getUuid()));
}
// if target VM has backups
List<Backup> backups = backupDao.listByVmId(vm.getDataCenterId(), vm.getId());
if (vm.getBackupOfferingId() != null && !backups.isEmpty()) {
throw new InvalidParameterValueException(String.format("Unable to attach volume to VM %s/%s, please specify a VM that does not have any backups", vm.getName(), vm.getUuid()));
}
}
/**
@ -2850,7 +2846,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
return volumeToAttach;
}
protected void validateIfVmHasBackups(UserVmVO vm, boolean attach) {
protected void checkForBackups(UserVmVO vm, boolean attach) {
if ((vm.getBackupOfferingId() == null || CollectionUtils.isEmpty(vm.getBackupVolumeList())) || BooleanUtils.isTrue(BackupManager.BackupEnableAttachDetachVolumes.value())) {
return;
}
@ -3070,7 +3066,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
throw new InvalidParameterValueException("Unable to detach volume, please specify a VM that does not have VM snapshots");
}
validateIfVmHasBackups(vm, false);
checkForBackups(vm, false);
AsyncJobExecutionContext asyncExecutionContext = AsyncJobExecutionContext.getCurrentExecutionContext();
if (asyncExecutionContext != null) {

View File

@ -650,6 +650,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M
return false;
}
@Override
public boolean isResourceDomainAdmin(Long accountId) {
if (accountId != null) {
AccountVO acct = _accountDao.findById(accountId);

View File

@ -19,6 +19,7 @@ package org.apache.cloudstack.backup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -292,6 +293,7 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
public static String createVolumeInfoFromVolumes(List<VolumeVO> vmVolumes) {
List<Backup.VolumeInfo> list = new ArrayList<>();
vmVolumes.sort(Comparator.comparing(VolumeVO::getDeviceId));
for (VolumeVO vol : vmVolumes) {
list.add(new Backup.VolumeInfo(vol.getUuid(), vol.getPath(), vol.getVolumeType(), vol.getSize()));
}

View File

@ -170,6 +170,7 @@ import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.volume.VolumeOnStorageTO;
import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
@ -814,7 +815,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
throw new CloudRuntimeException("Error while copying volume of remote instance: " + answer.getDetails());
}
CopyRemoteVolumeAnswer copyRemoteVolumeAnswer = (CopyRemoteVolumeAnswer) answer;
if(!copyRemoteVolumeAnswer.getResult()) {
checkVolume(copyRemoteVolumeAnswer.getVolumeDetails());
if (!copyRemoteVolumeAnswer.getResult()) {
throw new CloudRuntimeException("Unable to copy volume of remote instance");
}
diskProfile.setSize(copyRemoteVolumeAnswer.getSize());
@ -1188,6 +1190,8 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
allDetails.put(VmDetailConstants.KVM_VNC_PASSWORD, unmanagedInstance.getVncPassword());
}
addImportingVMBootTypeAndModeDetails(unmanagedInstance.getBootType(), unmanagedInstance.getBootMode(), allDetails);
VirtualMachine.PowerState powerState = VirtualMachine.PowerState.PowerOff;
if (unmanagedInstance.getPowerState().equals(UnmanagedInstanceTO.PowerState.PowerOn)) {
powerState = VirtualMachine.PowerState.PowerOn;
@ -1259,6 +1263,12 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
return userVm;
}
private void addImportingVMBootTypeAndModeDetails(String bootType, String bootMode, Map<String, String> allDetails) {
if (StringUtils.isNotBlank(bootType) && bootType.equalsIgnoreCase("uefi") && StringUtils.isNotBlank(bootMode)) {
allDetails.put("UEFI", bootMode);
}
}
private HashMap<String, UnmanagedInstanceTO> getUnmanagedInstancesForHost(HostVO host, String instanceName, List<String> managedVms) {
HashMap<String, UnmanagedInstanceTO> unmanagedInstances = new HashMap<>();
if (host.isInMaintenanceStates()) {
@ -2692,7 +2702,13 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
throw new CloudRuntimeException("Disk not found or is invalid");
}
CheckVolumeAnswer checkVolumeAnswer = (CheckVolumeAnswer) answer;
if(!checkVolumeAnswer.getResult()) {
try {
checkVolume(checkVolumeAnswer.getVolumeDetails());
} catch (CloudRuntimeException e) {
cleanupFailedImportVM(userVm);
throw e;
}
if (!checkVolumeAnswer.getResult()) {
cleanupFailedImportVM(userVm);
throw new CloudRuntimeException("Disk not found or is invalid");
}
@ -2718,6 +2734,31 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager {
return userVm;
}
private void checkVolume(Map<VolumeOnStorageTO.Detail, String> volumeDetails) {
if (MapUtils.isEmpty(volumeDetails)) {
return;
}
if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_LOCKED)) {
String isLocked = volumeDetails.get(VolumeOnStorageTO.Detail.IS_LOCKED);
if (Boolean.parseBoolean(isLocked)) {
logFailureAndThrowException("Locked volume cannot be imported or unmanaged.");
}
}
if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.IS_ENCRYPTED)) {
String isEncrypted = volumeDetails.get(VolumeOnStorageTO.Detail.IS_ENCRYPTED);
if (Boolean.parseBoolean(isEncrypted)) {
logFailureAndThrowException("Encrypted volume cannot be imported or unmanaged.");
}
}
if (volumeDetails.containsKey(VolumeOnStorageTO.Detail.BACKING_FILE)) {
String backingFile = volumeDetails.get(VolumeOnStorageTO.Detail.BACKING_FILE);
if (StringUtils.isNotBlank(backingFile)) {
logFailureAndThrowException("Volume with backing file cannot be imported or unmanaged.");
}
}
}
private NetworkVO getDefaultNetwork(DataCenter zone, Account owner, boolean selectAny) throws InsufficientCapacityException, ResourceAllocationException {
NetworkVO defaultNetwork = null;

View File

@ -672,7 +672,6 @@ public class VolumeApiServiceImplTest {
when(vm.getState()).thenReturn(State.Running);
when(vm.getDataCenterId()).thenReturn(34L);
when(vm.getBackupOfferingId()).thenReturn(null);
when(backupDaoMock.listByVmId(anyLong(), anyLong())).thenReturn(Collections.emptyList());
when(volumeDaoMock.findByInstanceAndType(anyLong(), any(Volume.Type.class))).thenReturn(new ArrayList<>(10));
when(volumeDataFactoryMock.getVolume(9L)).thenReturn(volumeToAttach);
when(volumeToAttach.getState()).thenReturn(Volume.State.Uploaded);
@ -1311,7 +1310,7 @@ public class VolumeApiServiceImplTest {
try {
UserVmVO vm = Mockito.mock(UserVmVO.class);
when(vm.getBackupOfferingId()).thenReturn(1l);
volumeApiServiceImpl.validateIfVmHasBackups(vm, false);
volumeApiServiceImpl.checkForBackups(vm, false);
} catch (Exception e) {
Assert.assertEquals("Unable to detach volume, cannot detach volume from a VM that has backups. First remove the VM from the backup offering or set the global configuration 'backup.enable.attach.detach.of.volumes' to true.", e.getMessage());
}
@ -1322,7 +1321,7 @@ public class VolumeApiServiceImplTest {
try {
UserVmVO vm = Mockito.mock(UserVmVO.class);
when(vm.getBackupOfferingId()).thenReturn(1l);
volumeApiServiceImpl.validateIfVmHasBackups(vm, true);
volumeApiServiceImpl.checkForBackups(vm, true);
} catch (Exception e) {
Assert.assertEquals("Unable to attach volume, please specify a VM that does not have any backups or set the global configuration 'backup.enable.attach.detach.of.volumes' to true.", e.getMessage());
}
@ -1332,7 +1331,7 @@ public class VolumeApiServiceImplTest {
public void validateIfVmHaveBackupsTestSuccessWhenVMDontHaveBackupOffering() {
UserVmVO vm = Mockito.mock(UserVmVO.class);
when(vm.getBackupOfferingId()).thenReturn(null);
volumeApiServiceImpl.validateIfVmHasBackups(vm, true);
volumeApiServiceImpl.checkForBackups(vm, true);
}
@Test

View File

@ -422,6 +422,11 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco
return false;
}
@Override
public boolean isResourceDomainAdmin(Long accountId) {
return false;
}
@Override
public boolean isNormalUser(long accountId) {
// TODO Auto-generated method stub

View File

@ -76,6 +76,7 @@ public class ConsoleProxy {
static int httpCmdListenPort = 8001;
static int reconnectMaxRetry = 5;
static int readTimeoutSeconds = 90;
public static int defaultBufferSize = 64 * 1024;
static int keyboardType = KEYBOARD_RAW;
static String factoryClzName;
static boolean standaloneStart = false;
@ -160,6 +161,12 @@ public class ConsoleProxy {
readTimeoutSeconds = Integer.parseInt(s);
LOGGER.info("Setting readTimeoutSeconds=" + readTimeoutSeconds);
}
s = conf.getProperty("consoleproxy.defaultBufferSize");
if (s != null) {
defaultBufferSize = Integer.parseInt(s);
LOGGER.info("Setting defaultBufferSize=" + defaultBufferSize);
}
}
public static ConsoleProxyServerFactory getHttpServerFactory() {

View File

@ -52,6 +52,9 @@ public class ConsoleProxyNoVncClient implements ConsoleProxyClient {
private ConsoleProxyClientParam clientParam;
private String sessionUuid;
private ByteBuffer readBuffer = null;
private int flushThreshold = -1;
public ConsoleProxyNoVncClient(Session session) {
this.session = session;
}
@ -109,8 +112,9 @@ public class ConsoleProxyNoVncClient implements ConsoleProxyClient {
connectClientToVNCServer(tunnelUrl, tunnelSession, websocketUrl);
authenticateToVNCServer(clientSourceIp);
int readBytes;
byte[] b;
// Track consecutive iterations with no data and sleep accordingly. Only used for NIO socket connections.
int consecutiveZeroReads = 0;
int sleepTime = 1;
while (connectionAlive) {
logger.trace("Connection with client [{}] [IP: {}] is alive.", clientId, clientSourceIp);
if (client.isVncOverWebSocketConnection()) {
@ -118,30 +122,53 @@ public class ConsoleProxyNoVncClient implements ConsoleProxyClient {
updateFrontEndActivityTime();
}
connectionAlive = session.isOpen();
sleepTime = 1;
} else if (client.isVncOverNioSocket()) {
byte[] bytesArr;
int nextBytes = client.getNextBytes();
bytesArr = new byte[nextBytes];
client.readBytes(bytesArr, nextBytes);
logger.trace("Read [{}] bytes from client [{}].", nextBytes, clientId);
if (nextBytes > 0) {
session.getRemote().sendBytes(ByteBuffer.wrap(bytesArr));
ByteBuffer buffer = getOrCreateReadBuffer();
int bytesRead = client.readAvailableDataIntoBuffer(buffer, buffer.remaining());
if (bytesRead > 0) {
updateFrontEndActivityTime();
consecutiveZeroReads = 0; // Reset counter on successful read
sleepTime = 0; // Still no sleep to catch any remaining data quickly
} else {
connectionAlive = session.isOpen();
consecutiveZeroReads++;
// Use adaptive sleep time to prevent excessive busy waiting
sleepTime = Math.min(consecutiveZeroReads, 10); // Cap at 10ms max
}
final boolean bufferHasData = buffer.position() > 0;
if (bufferHasData && (bytesRead == 0 || buffer.remaining() <= flushThreshold)) {
buffer.flip();
logger.trace("Flushing buffer with [{}] bytes for client [{}]", buffer.remaining(), clientId);
session.getRemote().sendBytes(buffer);
buffer.compact();
}
} else {
b = new byte[100];
readBytes = client.read(b);
ByteBuffer buffer = getOrCreateReadBuffer();
buffer.clear();
int readBytes = client.read(buffer.array());
logger.trace("Read [{}] bytes from client [{}].", readBytes, clientId);
if (readBytes == -1 || (readBytes > 0 && !sendReadBytesToNoVNC(b, readBytes))) {
if (readBytes > 0) {
// Update buffer position to reflect bytes read and flip for reading
buffer.position(readBytes);
buffer.flip();
if (!sendReadBytesToNoVNC(buffer)) {
connectionAlive = false;
}
} else if (readBytes == -1) {
connectionAlive = false;
}
sleepTime = 1;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
logger.error("Error on sleep for vnc sessions", e);
if (sleepTime > 0 && connectionAlive) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
logger.error("Error on sleep for vnc sessions", e);
}
}
}
logger.info("Connection with client [{}] [IP: {}] is dead.", clientId, clientSourceIp);
@ -154,9 +181,10 @@ public class ConsoleProxyNoVncClient implements ConsoleProxyClient {
worker.start();
}
private boolean sendReadBytesToNoVNC(byte[] b, int readBytes) {
private boolean sendReadBytesToNoVNC(ByteBuffer buffer) {
try {
session.getRemote().sendBytes(ByteBuffer.wrap(b, 0, readBytes));
// Buffer is already prepared for reading by flip()
session.getRemote().sendBytes(buffer);
updateFrontEndActivityTime();
} catch (WebSocketException | IOException e) {
logger.error("VNC server connection exception.", e);
@ -316,9 +344,29 @@ public class ConsoleProxyNoVncClient implements ConsoleProxyClient {
this.clientParam = param;
}
private ByteBuffer getOrCreateReadBuffer() {
if (readBuffer == null) {
readBuffer = ByteBuffer.allocate(ConsoleProxy.defaultBufferSize);
logger.debug("Allocated {} KB read buffer for client [{}]", ConsoleProxy.defaultBufferSize / 1024 , clientId);
// Only apply batching logic for NIO TLS connections to work around 16KB record limitation
// For non-TLS or non-NIO connections, use immediate flush for better responsiveness
if (client != null && client.isVncOverNioSocket() && client.isTLSConnectionEstablished()) {
flushThreshold = Math.min(ConsoleProxy.defaultBufferSize / 4, 2048);
logger.debug("NIO TLS connection detected - using batching with threshold {} for client [{}]", flushThreshold, clientId);
} else {
flushThreshold = ConsoleProxy.defaultBufferSize + 1; // Always flush immediately
logger.debug("Non-TLS or non-NIO connection - using immediate flush for client [{}]", clientId);
}
}
return readBuffer;
}
@Override
public void closeClient() {
this.connectionAlive = false;
// Clear buffer reference to allow GC when client disconnects
this.readBuffer = null;
ConsoleProxy.removeViewer(this);
}

View File

@ -502,18 +502,14 @@ public class NoVncClient {
return nioSocketConnection.readServerInit();
}
public int getNextBytes() {
return nioSocketConnection.readNextBytes();
public int readAvailableDataIntoBuffer(ByteBuffer buffer, int maxSize) {
return nioSocketConnection.readAvailableDataIntoBuffer(buffer, maxSize);
}
public boolean isTLSConnectionEstablished() {
return nioSocketConnection.isTLSConnection();
}
public void readBytes(byte[] arr, int len) {
nioSocketConnection.readNextByteArray(arr, len);
}
public void processHandshakeSecurityType(int secType, String vmPassword, String host, int port) {
waitForNoVNCReply();

View File

@ -41,6 +41,8 @@ public class NioSocket {
socketChannel = SocketChannel.open();
socketChannel.configureBlocking(false);
socketChannel.socket().setSoTimeout(5000);
socketChannel.socket().setKeepAlive(true);
socketChannel.socket().setTcpNoDelay(true);
writeSelector = Selector.open();
readSelector = Selector.open();
socketChannel.register(writeSelector, SelectionKey.OP_WRITE);
@ -77,7 +79,6 @@ public class NioSocket {
socketChannel.register(selector, SelectionKey.OP_CONNECT);
waitForSocketSelectorConnected(selector);
socketChannel.socket().setTcpNoDelay(false);
} catch (IOException e) {
logger.error(String.format("Error creating NioSocket to %s:%s: %s", host, port, e.getMessage()), e);
}

View File

@ -29,8 +29,7 @@ public interface NioSocketHandler {
void readBytes(ByteBuffer data, int length);
String readString();
byte[] readServerInit();
int readNextBytes();
void readNextByteArray(byte[] arr, int len);
int readAvailableDataIntoBuffer(ByteBuffer buffer, int maxSize);
// Write operations
void writeUnsignedInteger(int sizeInBits, int value);

View File

@ -17,6 +17,7 @@
package com.cloud.consoleproxy.vnc.network;
import com.cloud.consoleproxy.ConsoleProxy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -28,13 +29,11 @@ public class NioSocketHandlerImpl implements NioSocketHandler {
private NioSocketOutputStream outputStream;
private boolean isTLS = false;
private static final int DEFAULT_BUF_SIZE = 16384;
protected Logger logger = LogManager.getLogger(getClass());
public NioSocketHandlerImpl(NioSocket socket) {
this.inputStream = new NioSocketInputStream(DEFAULT_BUF_SIZE, socket);
this.outputStream = new NioSocketOutputStream(DEFAULT_BUF_SIZE, socket);
this.inputStream = new NioSocketInputStream(ConsoleProxy.defaultBufferSize, socket);
this.outputStream = new NioSocketOutputStream(ConsoleProxy.defaultBufferSize, socket);
}
@Override
@ -97,13 +96,8 @@ public class NioSocketHandlerImpl implements NioSocketHandler {
}
@Override
public int readNextBytes() {
return inputStream.getNextBytes();
}
@Override
public void readNextByteArray(byte[] arr, int len) {
inputStream.readNextByteArrayFromReadBuffer(arr, len);
public int readAvailableDataIntoBuffer(ByteBuffer buffer, int maxSize) {
return inputStream.readAvailableDataIntoBuffer(buffer, maxSize);
}
@Override

View File

@ -175,28 +175,38 @@ public class NioSocketInputStream extends NioSocketStream {
return ArrayUtils.addAll(ret, (byte) 0, (byte) 0, (byte) 0);
}
protected int getNextBytes() {
int size = 200;
while (size > 0) {
if (checkForSizeWithoutWait(size)) {
break;
}
size--;
/**
* This method checks what data is immediately available and returns a reasonable amount.
*
* @param maxSize Maximum number of bytes to attempt to read
* @return Number of bytes available to read (0 if none available)
*/
protected int getAvailableBytes(int maxSize) {
// First check if we have data already in our buffer
int bufferedData = endPosition - currentPosition;
if (bufferedData > 0) {
return Math.min(bufferedData, maxSize);
}
return size;
// Try to read more data with non-blocking call
// This determines how much data is available
return getReadBytesAvailableToFitSize(1, maxSize, false);
}
protected void readNextByteArrayFromReadBuffer(byte[] arr, int len) {
copyBytesFromReadBuffer(len, arr);
}
protected void copyBytesFromReadBuffer(int length, byte[] arr) {
int ptr = 0;
while (length > 0) {
int n = getReadBytesAvailableToFitSize(1, length, true);
readBytes(ByteBuffer.wrap(arr, ptr, n), n);
ptr += n;
length -= n;
/**
* Read available data directly into a ByteBuffer.
*
* @param buffer ByteBuffer to read data into
* @param maxSize Maximum number of bytes to read
* @return Number of bytes actually read (0 if none available)
*/
protected int readAvailableDataIntoBuffer(ByteBuffer buffer, int maxSize) {
// Get the amount of data available to read
int available = getAvailableBytes(maxSize);
if (available > 0) {
// Read directly into the ByteBuffer
readBytes(buffer, available);
}
return available;
}
}

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.consoleproxy.vnc.network;
import com.cloud.consoleproxy.ConsoleProxy;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
@ -43,9 +45,9 @@ public class NioSocketSSLEngineManager {
executor = Executors.newSingleThreadExecutor();
int pktBufSize = engine.getSession().getPacketBufferSize();
myNetData = ByteBuffer.allocate(pktBufSize);
peerNetData = ByteBuffer.allocate(pktBufSize);
int networkBufSize = Math.max(engine.getSession().getPacketBufferSize(), ConsoleProxy.defaultBufferSize);
myNetData = ByteBuffer.allocate(networkBufSize);
peerNetData = ByteBuffer.allocate(networkBufSize);
}
private void handshakeNeedUnwrap(ByteBuffer peerAppData) throws SSLException {
@ -155,22 +157,25 @@ public class NioSocketSSLEngineManager {
}
public int write(ByteBuffer data) throws IOException {
int n = 0;
int totalBytesConsumed = 0;
int sessionAppBufSize = engine.getSession().getApplicationBufferSize();
boolean shouldBatch = ConsoleProxy.defaultBufferSize > sessionAppBufSize;
while (data.hasRemaining()) {
SSLEngineResult result = engine.wrap(data, myNetData);
n += result.bytesConsumed();
totalBytesConsumed += result.bytesConsumed();
switch (result.getStatus()) {
case OK:
myNetData.flip();
outputStream.writeBytes(myNetData, myNetData.remaining());
outputStream.flushWriteBuffer();
myNetData.compact();
// Flush immediately if: batching is disabled, small data, or last chunk
if (!shouldBatch || result.bytesConsumed() < sessionAppBufSize || !data.hasRemaining()) {
flush();
}
// Otherwise accumulate for batching (large chunk with more data coming)
break;
case BUFFER_OVERFLOW:
myNetData.flip();
outputStream.writeBytes(myNetData, myNetData.remaining());
myNetData.compact();
// Flush when buffer is full
flush();
break;
case CLOSED:
@ -181,7 +186,16 @@ public class NioSocketSSLEngineManager {
break;
}
}
return n;
return totalBytesConsumed;
}
public void flush() {
if (myNetData.position() > 0) {
myNetData.flip();
outputStream.writeBytes(myNetData, myNetData.remaining());
outputStream.flushWriteBuffer();
myNetData.compact();
}
}
public SSLSession getSession() {

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.consoleproxy.vnc.network;
import com.cloud.consoleproxy.ConsoleProxy;
import com.cloud.utils.exception.CloudRuntimeException;
import java.io.IOException;
@ -26,7 +27,7 @@ public class NioSocketTLSInputStream extends NioSocketInputStream {
private final NioSocketSSLEngineManager sslEngineManager;
public NioSocketTLSInputStream(NioSocketSSLEngineManager sslEngineManager, NioSocket socket) {
super(sslEngineManager.getSession().getApplicationBufferSize(), socket);
super(ConsoleProxy.defaultBufferSize, socket);
this.sslEngineManager = sslEngineManager;
}

View File

@ -16,6 +16,8 @@
// under the License.
package com.cloud.consoleproxy.vnc.network;
import com.cloud.consoleproxy.ConsoleProxy;
import java.io.IOException;
import java.nio.ByteBuffer;
@ -24,7 +26,7 @@ public class NioSocketTLSOutputStream extends NioSocketOutputStream {
private final NioSocketSSLEngineManager sslEngineManager;
public NioSocketTLSOutputStream(NioSocketSSLEngineManager sslEngineManager, NioSocket socket) {
super(sslEngineManager.getSession().getApplicationBufferSize(), socket);
super(ConsoleProxy.defaultBufferSize, socket);
this.sslEngineManager = sslEngineManager;
}
@ -38,6 +40,7 @@ public class NioSocketTLSOutputStream extends NioSocketOutputStream {
}
currentPosition = start;
sslEngineManager.flush();
}
protected int writeThroughSSLEngineManager(byte[] data, int startPos, int length) {

View File

@ -268,9 +268,6 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
private final GlobalLock _allocLock = GlobalLock.getInternLock(getAllocLockName());
static final ConfigKey<String> NTPServerConfig = new ConfigKey<String>(String.class, "ntp.server.list", "Advanced", null,
"Comma separated list of NTP servers to configure in Secondary storage VM", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null);
static final ConfigKey<Integer> MaxNumberOfSsvmsForMigration = new ConfigKey<Integer>("Advanced", Integer.class, "max.ssvm.count", "5",
"Number of additional SSVMs to handle migration of data objects concurrently", true, ConfigKey.Scope.Global);
@ -1178,7 +1175,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
buf.append(" vmpassword=").append(_configDao.getValue("system.vm.password"));
}
if (NTPServerConfig.value() != null) {
if (StringUtils.isNotEmpty(NTPServerConfig.value())) {
buf.append(" ntpserverlist=").append(NTPServerConfig.value().replaceAll("\\s+",""));
}

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import io.netty.util.IllegalReferenceCountException;
import org.apache.cloudstack.storage.template.UploadEntity;
import org.apache.cloudstack.utils.imagestore.ImageStoreUtil;
import org.apache.commons.lang3.StringUtils;
@ -230,8 +231,15 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler<HttpObj
private void reset() {
request = null;
// destroy the decoder to release all resources
decoder.destroy();
decoder = null;
if (decoder != null) {
try {
decoder.destroy();
} catch (IllegalReferenceCountException e) {
logger.warn("Decoder already destroyed", e);
}
decoder = null;
}
}
private HttpResponseStatus readFileUploadData() throws IOException {

View File

@ -21,3 +21,4 @@ consoleproxy.httpCmdListenPort=8001
consoleproxy.jarDir=./applet/
consoleproxy.viewerLinger=180
consoleproxy.reconnectMaxRetry=5
consoleproxy.defaultBufferSize=65536

View File

@ -683,7 +683,7 @@ getPublicIp() {
setup_ntp() {
log_it "Setting up NTP"
NTP_CONF_FILE="/etc/ntp.conf"
NTP_CONF_FILE="/etc/ntpsec/ntp.conf"
if [ -f $NTP_CONF_FILE ]
then
IFS=',' read -a server_list <<< "$NTP_SERVER_LIST"
@ -692,9 +692,9 @@ setup_ntp() {
do
server=$(echo ${server_list[iterator]} | tr -d '\r')
PATTERN="server $server"
sed -i "0,/^#server/s//$PATTERN\n#server/" $NTP_CONF_FILE
sed -i "0,/^# server/s//$PATTERN\n# server/" $NTP_CONF_FILE
done
systemctl enable ntp
systemctl enable --now --no-block ntp
else
log_it "NTP configuration file not found"
fi

View File

@ -40,6 +40,10 @@ setup_console_proxy() {
disable_rpfilter
enable_fwding 0
enable_irqbalance 0
if [[ -n "$NTP_SERVER_LIST" ]]; then
setup_ntp
systemctl restart ntp
fi
rm -f /etc/logrotate.d/cloud
}

View File

@ -82,6 +82,7 @@ HTTP
enable_fwding 0
enable_irqbalance 0
setup_ntp
systemctl restart ntp
rm -f /etc/logrotate.d/cloud
}

View File

@ -953,9 +953,72 @@ class TestLinstorVolumes(cloudstackTestCase):
snapshot.delete(self.apiClient)
@attr(tags=['basic'], required_hardware=False)
def test_10_create_template_from_snapshot(self):
"""
Create a template from a snapshot and start an instance from it
"""
self.virtual_machine.stop(self.apiClient)
volume = list_volumes(
self.apiClient,
virtualmachineid = self.virtual_machine.id,
type = "ROOT",
listall = True,
)
snapshot = Snapshot.create(
self.apiClient,
volume_id=volume[0].id,
account=self.account.name,
domainid=self.domain.id,
)
self.cleanup.append(snapshot)
self.assertIsNotNone(snapshot, "Could not create snapshot")
services = {
"displaytext": "IntegrationTestTemplate",
"name": "int-test-template",
"ostypeid": self.template.ostypeid,
"ispublic": "true"
}
custom_template = Template.create_from_snapshot(
self.apiClient,
snapshot,
services,
)
self.cleanup.append(custom_template)
# create VM from custom template
test_virtual_machine = VirtualMachine.create(
self.apiClient,
self.testdata[TestData.virtualMachine2],
accountid=self.account.name,
zoneid=self.zone.id,
serviceofferingid=self.compute_offering.id,
templateid=custom_template.id,
domainid=self.domain.id,
startvm=False,
mode='basic',
)
self.cleanup.append(test_virtual_machine)
TestLinstorVolumes._start_vm(test_virtual_machine)
test_virtual_machine.stop(self.apiClient)
test_virtual_machine.delete(self.apiClient, True)
self.cleanup.remove(test_virtual_machine)
custom_template.delete(self.apiClient)
self.cleanup.remove(custom_template)
snapshot.delete(self.apiClient)
self.cleanup.remove(snapshot)
@attr(tags=['advanced', 'migration'], required_hardware=False)
def test_10_migrate_volume_to_same_instance_pool(self):
def test_11_migrate_volume_to_same_instance_pool(self):
"""Migrate volume to the same instance pool"""
if not self.testdata[TestData.migrationTests]:
@ -1088,7 +1151,7 @@ class TestLinstorVolumes(cloudstackTestCase):
test_virtual_machine.delete(self.apiClient, True)
@attr(tags=['advanced', 'migration'], required_hardware=False)
def test_11_migrate_volume_to_distinct_instance_pool(self):
def test_12_migrate_volume_to_distinct_instance_pool(self):
"""Migrate volume to distinct instance pool"""
if not self.testdata[TestData.migrationTests]:
@ -1221,7 +1284,7 @@ class TestLinstorVolumes(cloudstackTestCase):
test_virtual_machine.delete(self.apiClient, True)
@attr(tags=["basic"], required_hardware=False)
def test_12_create_vm_snapshots(self):
def test_13_create_vm_snapshots(self):
"""Test to create VM snapshots
"""
vm = TestLinstorVolumes._start_vm(self.virtual_machine)
@ -1251,7 +1314,7 @@ class TestLinstorVolumes(cloudstackTestCase):
)
@attr(tags=["basic"], required_hardware=False)
def test_13_revert_vm_snapshots(self):
def test_14_revert_vm_snapshots(self):
"""Test to revert VM snapshots
"""
@ -1313,7 +1376,7 @@ class TestLinstorVolumes(cloudstackTestCase):
)
@attr(tags=["basic"], required_hardware=False)
def test_14_delete_vm_snapshots(self):
def test_15_delete_vm_snapshots(self):
"""Test to delete vm snapshots
"""

View File

@ -14,12 +14,12 @@
"label.account.specific": "Account-Specific",
"label.accounts": "Accounts",
"label.accounttype": "Account Type",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL List Rules",
"label.acl.rules": "ACL Rules",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL Name",
"label.acl.rule.name": "ACL Name",
"label.acquire.new.ip": "Acquire New IP",
"label.acquire.new.secondary.ip": "Acquire new secondary IP",
"label.action": "Action",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Active Sessions",
"label.add": "Add",
"label.add.account": "Add Account",
"label.add.acl": "\u0625\u0636\u0627\u0641\u0629 ACL",
"label.add.acl.list": "Add ACL List",
"label.add.acl.rule": "\u0625\u0636\u0627\u0641\u0629 ACL",
"label.add.acl": "Add ACL",
"label.add.affinity.group": "Add new affinity group",
"label.add.baremetal.dhcp.device": "Add Baremetal DHCP Device",
"label.add.bigswitchbcf.device": "Add BigSwitch BCF Controller",
@ -142,12 +142,12 @@
"label.add.ip.range": "Add IP Range",
"label.add.isolated.network": "Add Isolated Network",
"label.add.ldap.account": "Add LDAP account",
"label.add.list.name": "ACL List Name",
"label.add.acl.name": "ACL Name",
"label.add.more": "Add More",
"label.add.netscaler.device": "Add Netscaler device",
"label.add.network": "Add Network",
"label.add.network.acl": "\u0625\u0636\u0627\u0641\u0629 \u0634\u0628\u0643\u0629 ACL",
"label.add.network.acl.list": "Add Network ACL List",
"label.add.network.acl": "Add Network ACL",
"label.add.network.offering": "Add network offering",
"label.add.new.gateway": "\u0623\u0636\u0641 \u0628\u0648\u0627\u0628\u0629 \u062c\u062f\u064a\u062f\u0629",
"label.add.new.tier": "\u0625\u0636\u0627\u0641\u0629 \u0637\u0628\u0642\u0629 \u062c\u062f\u064a\u062f\u0629",
@ -334,7 +334,7 @@
"label.default.use": "Default Use",
"label.default.view": "\u0637\u0631\u064a\u0642\u0629 \u0627\u0644\u0639\u0631\u0636 \u0627\u0644\u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629",
"label.delete": "Delete",
"label.delete.acl.list": "Delete ACL List",
"label.delete.acl": "Delete ACL",
"label.delete.affinity.group": "Delete Affinity Group",
"label.delete.alerts": "Delete alerts",
"label.delete.bigswitchbcf": "Remove BigSwitch BCF Controller",
@ -419,7 +419,7 @@
"label.dpd": "\u0643\u0634\u0641 \u0627\u0644\u0642\u0631\u064a\u0646 \u0627\u0644\u0645\u0641\u0642\u0648\u062f",
"label.driver": "Driver",
"label.edit": "Edit",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Edit ACL rule",
"label.edit.project.details": "\u0627\u0636\u0627\u0641\u0629 \u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u0645\u0634\u0631\u0648\u0639",
"label.edit.role": "Edit Role",
@ -924,7 +924,6 @@
"label.remove.vpc.offering": "Remove VPC offering",
"label.removing": "Removing",
"label.replace.acl": "Replace ACL",
"label.replace.acl.list": "Replace ACL List",
"label.required": "Required",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Requires Upgrade",
@ -1150,8 +1149,7 @@
"label.usehttps": "\u0627\u0633\u062a\u062e\u062f\u0645 HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "User",
"label.userdata": "Userdata",
"label.userdatal2": "User Data",
"label.user.data": "User Data",
"label.username": "Username",
"label.users": "Users",
"label.utilization": "Utilisation",
@ -1329,7 +1327,7 @@
"message.confirm.archive.selected.alerts": "Please confirm you would like to archive the selected alerts",
"message.confirm.archive.selected.events": "Please confirm you would like to archive the selected events",
"message.confirm.attach.disk": "Are you sure you want to attach disk?",
"message.confirm.delete.acl.list": "Are you sure you want to delete this ACL list?",
"message.confirm.delete.acl": "Are you sure you want to delete this ACL?",
"message.confirm.delete.bigswitchbcf": "Please confirm that you would like to delete this BigSwitch BCF Controller",
"message.confirm.delete.brocadevcs": "Please confirm that you would like to delete Brocade Vcs Switch",
"message.confirm.delete.ciscoasa1000v": "Please confirm you want to delete CiscoASA1000v",

View File

@ -14,12 +14,12 @@
"label.account.specific": "Account-Specific",
"label.accounts": "Accounts",
"label.accounttype": "Account Type",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL List Rules",
"label.acl.rules": "ACL Rules",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL Name",
"label.acl.rule.name": "ACL Name",
"label.acquire.new.ip": "Acquire New IP",
"label.acquire.new.secondary.ip": "Acquire new secondary IP",
"label.action": "Action",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Active Sessions",
"label.add": "Add",
"label.add.account": "Add Account",
"label.add.acl.rule": "Add ACL rule",
"label.add.acl": "Add ACL",
"label.add.acl.list": "Add ACL List",
"label.add.affinity.group": "Add new affinity group",
"label.add.baremetal.dhcp.device": "Add Baremetal DHCP Device",
"label.add.bigswitchbcf.device": "Add BigSwitch BCF Controller",
@ -142,12 +142,12 @@
"label.add.ip.range": "Add IP Range",
"label.add.isolated.network": "Add Isolated Network",
"label.add.ldap.account": "Add LDAP account",
"label.add.list.name": "ACL List Name",
"label.add.acl.name": "ACL Name",
"label.add.more": "Add More",
"label.add.netscaler.device": "Add Netscaler device",
"label.add.network": "Add Network",
"label.add.network.acl": "Add network ACL",
"label.add.network.acl.list": "Add Network ACL List",
"label.add.network.acl": "Add Network ACL",
"label.add.network.offering": "Add network offering",
"label.add.new.gateway": "Add new gateway",
"label.add.new.tier": "Add new tier",
@ -334,7 +334,7 @@
"label.default.use": "Default Use",
"label.default.view": "Default View",
"label.delete": "Delete",
"label.delete.acl.list": "Delete ACL List",
"label.delete.acl": "Delete ACL",
"label.delete.affinity.group": "Delete Affinity Group",
"label.delete.alerts": "Delete alerts",
"label.delete.bigswitchbcf": "Remove BigSwitch BCF Controller",
@ -419,7 +419,7 @@
"label.dpd": "Dead Peer Detection",
"label.driver": "Driver",
"label.edit": "Edit",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Edit ACL rule",
"label.edit.project.details": "Editar detalls del projecte",
"label.edit.role": "Edit Role",
@ -924,7 +924,6 @@
"label.remove.vpc.offering": "Remove VPC offering",
"label.removing": "Esborrant",
"label.replace.acl": "Replace ACL",
"label.replace.acl.list": "Replace ACL List",
"label.required": "Required",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Requires Upgrade",
@ -1150,8 +1149,7 @@
"label.usehttps": "Use HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "User",
"label.userdata": "Userdata",
"label.userdatal2": "User Data",
"label.user.data": "User Data",
"label.username": "Username",
"label.users": "Users",
"label.utilization": "Utilisation",
@ -1329,7 +1327,7 @@
"message.confirm.archive.selected.alerts": "Please confirm you would like to archive the selected alerts",
"message.confirm.archive.selected.events": "Please confirm you would like to archive the selected events",
"message.confirm.attach.disk": "Are you sure you want to attach disk?",
"message.confirm.delete.acl.list": "Are you sure you want to delete this ACL list?",
"message.confirm.delete.acl": "Are you sure you want to delete this ACL?",
"message.confirm.delete.bigswitchbcf": "Please confirm that you would like to delete this BigSwitch BCF Controller",
"message.confirm.delete.brocadevcs": "Please confirm that you would like to delete Brocade Vcs Switch",
"message.confirm.delete.ciscoasa1000v": "Please confirm you want to delete CiscoASA1000v",

View File

@ -26,12 +26,12 @@
"label.account.specific": "Besonderheiten des Benutzerkontos",
"label.accounts": "Benutzerkonten",
"label.accounttype": "Benutzerkontotyp",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL-Kennung",
"label.acl.list.rules": "ACL-Listenregeln",
"label.acl.rules": "ACL-Listenregeln",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL-Name",
"label.acl.rule.name": "ACL-Name",
"label.acquire.new.ip": "Neue IP erwerben",
"label.acquire.new.secondary.ip": "Neue sekundäre IP anfordern",
"label.acquiring.ip": "IP anfordern",
@ -144,8 +144,8 @@
"label.activeviewersessions": "Aktive Sitzungen",
"label.add": "Hinzufügen",
"label.add.account": "Konto hinzufügen",
"label.add.acl": "ACL hinzufügen",
"label.add.acl.list": "ACL-Liste hinzufügen",
"label.add.acl.rule": "ACL hinzufügen",
"label.add.acl": "ACL-Liste hinzufügen",
"label.add.affinity.group": "Neue Affinitätsgruppe hinzufügen",
"label.add.baremetal.dhcp.device": "Baremetal DHCP-Gerät hinzufügen",
"label.add.bigswitchbcf.device": "Füge BigSwitch BCF Controller hinzu",
@ -169,12 +169,12 @@
"label.add.isolated.network": "Isoliertes Netzwerk hinzufügen",
"label.add.kubernetes.cluster": "Kubernetes Cluster hinzufügen",
"label.add.ldap.account": "LDAP-Konto hinzufügen",
"label.add.list.name": "ACL-Listename",
"label.add.acl.name": "ACL-Listename",
"label.add.more": "Mehr hinzufügen",
"label.add.netscaler.device": "Netscaler-Gerät hinzufügen",
"label.add.network": "Netzwerk hinzufügen",
"label.add.network.acl": "Netzwerk-ACL hinzufügen",
"label.add.network.acl.list": "Netzwerk-ACL-Liste hinzufügen",
"label.add.network.acl": "Netzwerk-ACL-Liste hinzufügen",
"label.add.network.offering": "Netzwerkangebot hinzufügen",
"label.add.new.gateway": "Neues Gateway hinzufügen",
"label.add.new.tier": "Neue Ebene hinzufügen",
@ -417,7 +417,7 @@
"label.default.view": "Standardansicht",
"label.defaultnetwork": "Standard-Netzwerk",
"label.delete": "Löschen",
"label.delete.acl.list": "ACL-Liste ersetzen",
"label.delete.acl": "ACL-Liste ersetzen",
"label.delete.affinity.group": "Affinitätsgruppe entfernen",
"label.delete.alerts": "Alarme löschen",
"label.delete.backup": "Backup löschen",
@ -525,7 +525,7 @@
"label.driver": "Treiber",
"label.dynamicscalingenabled": "Dynamische Skalierung aktiviert",
"label.edit": "Bearbeiten",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "ACL-Regel bearbeiten",
"label.edit.project.details": "Projektdetails bearbeiten",
"label.edit.role": "Rolle bearbeiten",
@ -948,7 +948,7 @@
"label.netscaler.vpx": "NetScaler VPX LoadBalancer",
"label.network": "Netzwerk",
"label.network.acl": "Netzwerk-ACL",
"label.network.acl.lists": "Netzwerk ACL Listen",
"label.network.acls": "Netzwerk ACL Listen",
"label.network.addvm": "Netzwerk zur VM hinzufügen",
"label.network.desc": "Netzwerkbeschreibung",
"label.network.domain": "Netzwerk-Domain",
@ -1198,7 +1198,6 @@
"label.remove.vpc.offering": "VPC-Angebot entfernen",
"label.removing": "am Entfernen",
"label.replace.acl": "ACL ersetzen",
"label.replace.acl.list": "ACL-Liste ersetzen",
"label.report.bug": "Fehler melden",
"label.required": "Erforderlich",
"label.requireshvm": "HVM",
@ -1492,8 +1491,7 @@
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "Benutzer",
"label.user.conflict": "Konflikt",
"label.userdata": "Benutzerdaten",
"label.userdatal2": "Benutzerdaten",
"label.user.data": "Benutzerdaten",
"label.username": "Benutzername",
"label.users": "Benutzer",
"label.usersource": "Benutzertyp",
@ -1733,7 +1731,7 @@
"message.confirm.archive.selected.alerts": "Bitte bestätigen Sie, dass Sie die ausgewählten Alarme archivieren möchten",
"message.confirm.archive.selected.events": "Bitte bestätigen Sie, dass Sie die ausgewählten Vorgänge archivieren möchten",
"message.confirm.attach.disk": "Sind Sie sicher, dass Sie eine Platte hinzufügen möchten?",
"message.confirm.delete.acl.list": "Sind Sie sicher, dass Sie diese ACL-Liste löschen möchten?",
"message.confirm.delete.acl": "Sind Sie sicher, dass Sie diese ACL-Liste löschen möchten?",
"message.confirm.delete.bigswitchbcf": "Bitte bestätigen Sie, dass Sie diesen BigSwitch BCF Controller löschen möchten",
"message.confirm.delete.brocadevcs": "Bitte bestätigen Sie, dass Sie Brocade Vcs Switch löschen möchten",
"message.confirm.delete.ciscoasa1000v": "Bitte bestätigen Sie, dass Sie CiscoASA1000v löschen möchten",

View File

@ -33,10 +33,10 @@
"label.access.kubernetes.nodes": "Πρόσβαση στους κόμβους Κυβερνητών",
"label.acl.export": "Εξαγωγή Λίστας Πρόσβασης",
"label.acl.id": "Αναγνωριστικό Λίστας Πρόσβασης",
"label.acl.list.rules": "Κανόνες λίστας Πρόσωασης",
"label.acl.rules": "Κανόνες λίστας Πρόσωασης",
"label.acl.reason.description": "Εισαγάγετε αιτιολογία για τον κανόνα",
"label.aclid": "Λίστα πρόσβασης",
"label.aclname": "Όνομα Λίστας Πρόσβασης",
"label.acl.rule.name": "Όνομα Λίστας Πρόσβασης",
"label.acquire.new.ip": "Απόκτηση νέας διεύθυνση IP",
"label.acquire.new.secondary.ip": "Απόκτηση νέας δευτερεύουσας διεύθυνσης IP",
"label.acquiring.ip": "Απόδοση IP",
@ -173,7 +173,7 @@
"label.action.unmanage.virtualmachine": "Μη διαχείριση εικονικής μηχανής",
"label.action.update.offering.access": "Ενημέρωση πρόσβασης για προσφορές",
"label.action.update.resource.count": "Ενημέρωση πλήθους πόρων",
"label.action.userdata.reset": "Επαναφορά δεδομένων χρήστη",
"label.action.user.data.reset": "Επαναφορά δεδομένων χρήστη",
"label.action.vmsnapshot.create": "Λήψη στιγμιότυπου εικονικής μηχανής",
"label.action.vmsnapshot.delete": "Διαγραφή στιγμιότυπου εικονικής μηχανής",
"label.action.vmsnapshot.revert": "Επαναφορά στο στιγμιότυπο εικονικής μηχανής",
@ -183,8 +183,8 @@
"label.activeviewersessions": "Ενεργές περίοδοι λειτουργίας",
"label.add": "Προσθήκη",
"label.add.account": "Προσθήκη λογαριασμού",
"label.add.acl": "Προσθήκη εγγραφής στην λίστα πρόσβασης",
"label.add.acl.list": "Προσθήκη λίστας πρόσβασης",
"label.add.acl.rule": "Προσθήκη εγγραφής στην λίστα πρόσβασης",
"label.add.acl": "Προσθήκη λίστας πρόσβασης",
"label.add.affinity.group": "Προσθήκη νέας ομάδας συνάφειας",
"label.add.baremetal.dhcp.device": "Προσθήκη συσκευής DHCP baremetal",
"label.add.bigswitchbcf.device": "Προσθήκη ελεγκτή BCF BigSwitch",
@ -209,12 +209,12 @@
"label.add.isolated.network": "Προσθήκη απομονωμένου δικτύου",
"label.add.kubernetes.cluster": "Προσθήκη ομάδας Κυβερνητών",
"label.add.ldap.account": "Προσθήκη λογαριασμού LDAP",
"label.add.list.name": "Όνομα λίστας Πρόσβασης",
"label.add.acl.name": "Όνομα λίστας Πρόσβασης",
"label.add.more": "Προσθήκη περισσότερων",
"label.add.netscaler.device": "Προσθήκη συσκευής Netsccaler",
"label.add.network": "Προσθήκη δικτύου",
"label.add.network.acl": "Προσθήκη εγγραφής πρόσβασης δικτύου",
"label.add.network.acl.list": "Προσθήκη λίστας πρόσβασης δικτύου",
"label.add.network.acl": "Προσθήκη λίστας πρόσβασης δικτύου",
"label.add.network.offering": "Προσθήκη προσφοράς υπηρεσίας δικτύου",
"label.add.network.permission": "Προσθήκη δικαιωμάτων δικτύου",
"label.add.new.gateway": "Προσθήκη νέας πύλης",
@ -516,7 +516,7 @@
"label.default.view": "Προεπιλεγμένη προβολή",
"label.defaultnetwork": "Προεπιλεγμένο δίκτυο",
"label.delete": "Διαγραφή",
"label.delete.acl.list": "Διαγραφή λίστας πρόσβασης",
"label.delete.acl": "Διαγραφή λίστας πρόσβασης",
"label.delete.affinity.group": "Διαγραφή ομάδας συνάφειας",
"label.delete.alerts": "Διαγραφή ειδοποιήσεων",
"label.delete.backup": "Διαγραφή αντιγράφου ασφαλείας",
@ -649,7 +649,7 @@
"label.dynamicscalingenabled": "Δυναμική αναπροσαρμογή Ενεργοποίημένη",
"label.dynamicscalingenabled.tooltip": "Η εικονική μηχανή μπορεί να αναπροσαρμόζεται δυναμικά μόνο αν το πρότυπο, η προσφερόμενη υπηρεσία και οι γενικές ρυθμίσεις έχουν την επιλογή δυναμικής αναπροσαρμογής ενεργοποιήμενη.",
"label.edit": "Επεξεργασία",
"label.edit.acl.list": "Επεξεργασία λίστας Πρόσβασης",
"label.edit.acl": "Επεξεργασία λίστας Πρόσβασης",
"label.edit.acl.rule": "Επεξεργασία κανόνα Λίστας Πρόσβασης",
"label.edit.project.details": "Επεξεργασία λεπτομερειών έργου",
"label.edit.project.role": "Επεξεργασία ρόλου έργου",
@ -1142,7 +1142,7 @@
"label.netscaler.vpx": "Εξισορρόπηση φόρτου VPX του NetScaler",
"label.network": "Δίκτυο",
"label.network.acl": "ACL δικτύου",
"label.network.acl.lists": "Λίστες Λίστα Πρόσβασης δικτύου",
"label.network.acls": "Λίστες Λίστα Πρόσβασης δικτύου",
"label.network.addvm": "Προσθήκη δικτύου για την εικονική μηχανή",
"label.network.addvm": "Προσθήκη δικτύου σε εικονική μηχανή",
"label.network.desc": "Δίκτυο Desc",
@ -1436,7 +1436,6 @@
"label.remove.vpc.offering": "Κατάργηση προσφοράς υπηρεσίας Εικον. Ιδιωτ. Νέφους",
"label.removing": "Αφαίρεση",
"label.replace.acl": "Αντικατάσταση λίστας Πρόσβασης",
"label.replace.acl.list": "Αντικατάσταση λίστας Πρόσβασης",
"label.report.bug": "Θέμα αναφοράς",
"label.required": "Απαιτείται",
"label.requireshvm": "HVM",
@ -1455,7 +1454,7 @@
"label.reset.config.value": "Επαναφορά στις τιμές προεπιλογής",
"label.reset.ssh.key.pair": "Επαναφορά ζεύγους κλειδιών SSH",
"label.reset.to.default": "Επαναφορά στην τιμή προεπιλογής",
"label.reset.userdata.on.vm": "Επαναφορά δεδομένων χρήστη της εικονικής μηχανής",
"label.reset.user.data.on.vm": "Επαναφορά δεδομένων χρήστη της εικονικής μηχανής",
"label.reset.vpn.connection": "Επαναφορά σύνδεσης Εικον. Ιδιωτ. Δικτύου",
"label.resource": "Πόρος",
"label.resource.limit.exceeded": "Υπέρβαση ορίου πόρων",
@ -1811,19 +1810,17 @@
"label.usenewdiskoffering": "Αντικατάσταση προσφοράς υπηρεσίας δίσκου;",
"label.user": "Χρήστη",
"label.user.conflict": "Σύγκρουση",
"label.user.data": "Δεδομένα χρηστών",
"label.userdata": "Δεδομένα χρήστη",
"label.userdata.do.append": "Πρόσθεση δεδομένων χρήστη",
"label.userdata.do.override": "Παράκαμψη δεδομένων χρήστη",
"label.userdata.registered": "Εγγεγραμένα δεδομένα χρήστη",
"label.userdata.text": "Κείμενο δεδομένων χρήστη",
"label.userdatadetails": "Λεπτομέρειες δεδομένων χρήστη",
"label.userdataid": "Αναγνωριστικό δεδομένων χρήστη",
"label.userdatal2": "Δεδομένα χρήστη",
"label.userdataname": "Όνομα δεδομένων χρήστη",
"label.userdataparams": "Παράμετροι δεδομένων χρήστη",
"label.userdatapolicy": "Συνδεμένες πολιτικές δεδομένων χρήστη",
"label.userdatapolicy.tooltip": "Τα δεδομένα χρήστη που έχουν συνδεθεί στο πρότυπο μπορούν να παρακαμφθούν απο τα δεδομένα χρηστών που ορίστηκαν κατα την δημιουργία της vm. Διαλέξτε την πολιτική παράκαμψης ανάλογα με τις απαιτήσεις.",
"label.user.data": "Δεδομένα χρήστη",
"label.user.data.do.append": "Πρόσθεση δεδομένων χρήστη",
"label.user.data.do.override": "Παράκαμψη δεδομένων χρήστη",
"label.user.data.registered": "Εγγεγραμένα δεδομένα χρήστη",
"label.user.data.text": "Κείμενο δεδομένων χρήστη",
"label.user.data.details": "Λεπτομέρειες δεδομένων χρήστη",
"label.user.data.id": "Αναγνωριστικό δεδομένων χρήστη",
"label.user.data.name": "Όνομα δεδομένων χρήστη",
"label.user.data.params": "Παράμετροι δεδομένων χρήστη",
"label.user.data.policy": "Συνδεμένες πολιτικές δεδομένων χρήστη",
"label.user.data.policy.tooltip": "Τα δεδομένα χρήστη που έχουν συνδεθεί στο πρότυπο μπορούν να παρακαμφθούν απο τα δεδομένα χρηστών που ορίστηκαν κατα την δημιουργία της vm. Διαλέξτε την πολιτική παράκαμψης ανάλογα με τις απαιτήσεις.",
"label.username": "Όνομα χρήστη",
"label.users": "Χρήστες",
"label.usersource": "Τύπος χρήστη",
@ -2116,7 +2113,7 @@
"message.confirm.attach.disk": "Είστε βέβαιοι ότι θέλετε να επισυνάψετε το δίσκο;",
"message.confirm.change.offering.for.volume": "Παρακαλώ επιβεβαιώστε ότι επιθυμείτε την αλλαγή της προσφοράς δίσκου για αυτόν τον τόμο",
"message.confirm.configure.ovs": "Είστε βέβαιοι ότι θέλετε να ρυθμίσετε τις παραμέτρους του Ovs;",
"message.confirm.delete.acl.list": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτήν τη λίστα Λίστα Πρόσβασης;",
"message.confirm.delete.acl": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτήν τη λίστα Λίστα Πρόσβασης;",
"message.confirm.delete.bigswitchbcf": "Επιβεβαιώστε ότι θέλετε να διαγράψετε αυτόν τον ελεγκτή BigSwitch BCF",
"message.confirm.delete.brocadevcs": "Επιβεβαιώστε ότι θέλετε να διαγράψετε το εναλλάκτη Brocade Vcs",
"message.confirm.delete.ciscoasa1000v": "Παρακαλώ επιβεβαιώστε ότι θέλετε να διαγράψετε CiscoASA1000v",
@ -2350,7 +2347,7 @@
"message.error.upload.template": "Η αποστολή του προτύπου απέτυχε",
"message.error.upload.template.description": "Μόνο ένα πρότυπο μπορεί να αποσταλεί κάθε φορά",
"message.error.url": "Πληκτρολογήστε διεύθυνση URL",
"message.error.userdata": "Εισάγωγή δεδομένων χρηστών",
"message.error.user.data": "Εισάγωγή δεδομένων χρηστών",
"message.error.username": "Εισάγετε το όνομα χρήστη σας",
"message.error.valid.iops.range": "Εισαγεται ένα σωστό εύρος εργασίων εισαγ./εξαγ ανα δευτ.",
"message.error.vcenter.datacenter": "Πληκτρολογήστε vCenter Datacenter",

File diff suppressed because it is too large Load Diff

View File

@ -14,12 +14,12 @@
"label.account.specific": "espec\u00edficas de la cuenta",
"label.accounts": "Cuentas",
"label.accounttype": "Tipo de Cuenta",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ID de ACL",
"label.acl.list.rules": "Lista de Reglas ACL",
"label.acl.rules": "Lista de Reglas ACL",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "Nombre de ACL",
"label.acl.rule.name": "Nombre de ACL",
"label.acquire.new.ip": "Adquirir nueva IP",
"label.acquire.new.secondary.ip": "Adquirir nueva IP secundaria",
"label.action": "Acci\u00f3n",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Sesiones activas",
"label.add": "Agregar",
"label.add.account": "A\u00f1adir Cuenta",
"label.add.acl": "Agregar ACL",
"label.add.acl.list": "Agregar Lista ACL",
"label.add.acl.rule": "Agregar ACL",
"label.add.acl": "Agregar Lista ACL",
"label.add.affinity.group": "Agregar un nuevo grupo de afinidad",
"label.add.baremetal.dhcp.device": "Agregar dispositivo DHCP Baremetal",
"label.add.bigswitchbcf.device": "Agregar Controlador BigSwitch BCF",
@ -142,12 +142,12 @@
"label.add.ip.range": "A\u00f1adir Rango IP",
"label.add.isolated.network": "Agregar Red Aislada",
"label.add.ldap.account": "Agregar cuenta LDAP",
"label.add.list.name": "Nombre de la Lista ACL",
"label.add.acl.name": "Nombre de la Lista ACL",
"label.add.more": "A\u00f1adir m\u00e1s",
"label.add.netscaler.device": "Agregar dispositivo Netscaler",
"label.add.network": "Agregar Red",
"label.add.network.acl": "Agregar ACL de Red",
"label.add.network.acl.list": "Agregar Lista ACL de Red",
"label.add.network.acl": "Agregar Lista ACL de Red",
"label.add.network.offering": "Agregar Oferta de Red",
"label.add.new.gateway": "Agregar nuevo gateway",
"label.add.new.tier": "Agregar un nuevo tier",
@ -344,7 +344,7 @@
"label.default.use": "Uso por defecto",
"label.default.view": "Vista Por Defecto",
"label.delete": "Eliminar",
"label.delete.acl.list": "Borrar Lista ACL",
"label.delete.acl": "Borrar Lista ACL",
"label.delete.affinity.group": "Borrar Grupo de Afinidad",
"label.delete.alerts": "Eliminar alertas",
"label.delete.bigswitchbcf": "Remover Controlador BigSwitch BCF",
@ -431,7 +431,7 @@
"label.driver": "Controlador",
"label.dynamicscalingenabled": "Escalado din\u00e1mico habilitado",
"label.edit": "Editar",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Editar regla ACL",
"label.edit.project.details": "Editar detalles de proyecto",
"label.edit.role": "Editar Rol",
@ -947,7 +947,6 @@
"label.remove.vpc.offering": "Quitar Oferta VPC",
"label.removing": "Quitando..",
"label.replace.acl": "Reemplazar ACL",
"label.replace.acl.list": "Reemplazar Lista ACL",
"label.report.bug": "Reportar un Error",
"label.required": "Requerido",
"label.requireshvm": "HVM",
@ -1180,8 +1179,7 @@
"label.usehttps": "Use HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "Usuario",
"label.userdata": "DatosUsuario",
"label.userdatal2": "Datos de Usuario",
"label.user.data": "DatosUsuario",
"label.username": "Nombre de usuario",
"label.users": "Usuarios",
"label.utilization": "Utilisation",
@ -1361,7 +1359,7 @@
"message.confirm.archive.selected.alerts": "Por favor confirme que desea archivar las alertas seleccionadas",
"message.confirm.archive.selected.events": "Por favor confirme que desea archivar los eventos seleccionados",
"message.confirm.attach.disk": "\u00bf Est\u00e1 seguro que desea conectar el disco?",
"message.confirm.delete.acl.list": "\u00bfEsta seguro que desea borrar esta lista de ACL?",
"message.confirm.delete.acl": "\u00bfEsta seguro que desea borrar esta lista de ACL?",
"message.confirm.delete.bigswitchbcf": "Por favor confirme que desa borrar este Controlador BigSwitch BCF",
"message.confirm.delete.brocadevcs": "Por favor confirme que desa borrar este Switch Brocade Vcs",
"message.confirm.delete.ciscoasa1000v": "Por favor confirme que desea borrar CiscoASA1000v",

View File

@ -14,12 +14,12 @@
"label.account.specific": "Sp\u00e9cifique au compte",
"label.accounts": "Comptes",
"label.accounttype": "Type Compte",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ID ACL",
"label.acl.list.rules": "Liste r\u00e8gles ACL",
"label.acl.rules": "Liste r\u00e8gles ACL",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "Nom ACL",
"label.acl.rule.name": "Nom ACL",
"label.acquire.new.ip": "Acqu\u00e9rir nouvelle adr. IP",
"label.acquire.new.secondary.ip": "Acqu\u00e9rir nouvelle IP secondaire",
"label.action": "Action",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Sessions actives",
"label.add": "Ajouter",
"label.add.account": "Ajouter un compte",
"label.add.acl": "Ajouter r\u00e8gle ACL",
"label.add.acl.list": "Ajouter Liste ACL",
"label.add.acl.rule": "Ajouter r\u00e8gle ACL",
"label.add.acl": "Ajouter Liste ACL",
"label.add.affinity.group": "Ajouter nouveau groupe d'affinit\u00e9",
"label.add.baremetal.dhcp.device": "Ajouter un DHCP Baremetal",
"label.add.bigswitchbcf.device": "Ajouter un contr\u00f4leur BigSwitch BCF",
@ -142,12 +142,12 @@
"label.add.ip.range": "Ajouter une plage IP",
"label.add.isolated.network": "Ajouter un r\u00e9seau isol\u00e9",
"label.add.ldap.account": "Ajouter un compte LDAP",
"label.add.list.name": "Nom Liste ACL",
"label.add.acl.name": "Nom Liste ACL",
"label.add.more": "Ajouter plus",
"label.add.netscaler.device": "Ajouter un Netscaler",
"label.add.network": "Ajouter un r\u00e9seau",
"label.add.network.acl": "Ajouter une r\u00e8gle d'acc\u00e8s r\u00e9seau ACL",
"label.add.network.acl.list": "Ajouter Liste ACL r\u00e9seau",
"label.add.network.acl": "Ajouter Liste ACL r\u00e9seau",
"label.add.network.offering": "Ajouter Offre R\u00e9seau",
"label.add.new.gateway": "Ajouter une nouvelle passerelle",
"label.add.new.tier": "Ajouter un nouveau tiers",
@ -334,7 +334,7 @@
"label.default.use": "Utilisation par d\u00e9faut",
"label.default.view": "Vue par d\u00e9faut",
"label.delete": "Supprimer",
"label.delete.acl.list": "Supprimer Liste ACL",
"label.delete.acl": "Supprimer Liste ACL",
"label.delete.affinity.group": "Supprimer le groupe d'affinit\u00e9",
"label.delete.alerts": "Supprimer alertes",
"label.delete.bigswitchbcf": "Supprimer contr\u00f4leur BigSwitch BCF",
@ -419,7 +419,7 @@
"label.dpd": "D\u00e9tection de pair mort",
"label.driver": "Pilote",
"label.edit": "Modifier",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Modifier r\u00e8gle ACL",
"label.edit.project.details": "Modifier les d\u00e9tails du projet",
"label.edit.role": "\u00c9diter R\u00f4le",
@ -926,7 +926,6 @@
"label.remove.vpc.offering": "Supprimer offre VPC",
"label.removing": "Suppression",
"label.replace.acl": "Remplacer ACL",
"label.replace.acl.list": "Remplacer Liste ACL",
"label.required": "Requis",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Mise \u00e0 jour n\u00e9cessaire",
@ -1152,8 +1151,7 @@
"label.usehttps": "Utiliser HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "Utilisateur",
"label.userdata": "Donn\u00e9es Utilisateur",
"label.userdatal2": "Donn\u00e9es utilisateur",
"label.user.data": "Donn\u00e9es Utilisateur",
"label.username": "Identifiant",
"label.users": "Utilisateurs",
"label.utilization": "Utilisation",
@ -1331,7 +1329,7 @@
"message.confirm.archive.selected.alerts": "Confirmer l'archivage des alertes s\u00e9lectionn\u00e9es",
"message.confirm.archive.selected.events": "Confirmez l'archivage des \u00e9v\u00e9nements s\u00e9lectionn\u00e9s",
"message.confirm.attach.disk": "Confirmer le rattachement de ce disque ?",
"message.confirm.delete.acl.list": "Confirmer la suppression de cette liste ACL ?",
"message.confirm.delete.acl": "Confirmer la suppression de cette liste ACL ?",
"message.confirm.delete.bigswitchbcf": "Confirmer que vous voulez supprimer ce contr\u00f4leur BigSwitch BCF",
"message.confirm.delete.brocadevcs": "Confirmer la suppression du switch Brocade Vcs",
"message.confirm.delete.ciscoasa1000v": "Confirmez la suppression du CiscoASA1000v",

View File

@ -6,7 +6,7 @@
"label.accounts": "लेखा",
"label.accounttype": "खाता प्रकार",
"label.aclid": "ACL",
"label.aclname": "ACL नाम",
"label.acl.rule.name": "ACL नाम",
"label.actions": "क्रियाएँ",
"label.add": "जोड़ें",
"label.adding": "जोड़ना",
@ -410,7 +410,7 @@
"label.usageunit": "Unit",
"label.usehttps": "HTTPS का उपयोग करें",
"label.user": "उपयोगकर्ता",
"label.userdata": "Userdata",
"label.user.data": "User Data",
"label.username": "उपयोगकर्ता नाम",
"label.users": "उपयोगकर्ता",
"label.uuid": "ID",

View File

@ -14,12 +14,12 @@
"label.account.specific": "Sz\u00e1mla-specifikus",
"label.accounts": "Sz\u00e1ml\u00e1k",
"label.accounttype": "Sz\u00e1mla t\u00edpus",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL List Rules",
"label.acl.rules": "ACL Rules",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL n\u00e9v",
"label.acl.rule.name": "ACL n\u00e9v",
"label.acquire.new.ip": "\u00daj IP c\u00edm beszerz\u00e9se",
"label.acquire.new.secondary.ip": "\u00daj m\u00e1sodlagos IP c\u00edm beszerz\u00e9se",
"label.action": "M\u0171velet",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Akt\u00edv munkamenetek",
"label.add": "Felv\u00e9tel",
"label.add.account": "Sz\u00e1mla felv\u00e9tele",
"label.add.acl": "ACL felv\u00e9tele",
"label.add.acl.list": "ACL lista felv\u00e9tele",
"label.add.acl.rule": "ACL felv\u00e9tele",
"label.add.acl": "ACL Lista felv\u00e9tele",
"label.add.affinity.group": "\u00daj affin\u00edt\u00e1si csoport felv\u00e9tele",
"label.add.baremetal.dhcp.device": "Baremetal DHCP eszk\u00f6z felv\u00e9tele",
"label.add.bigswitchbcf.device": "BigSwitch BCF vez\u00e9rl\u0151 felv\u00e9tele",
@ -142,12 +142,12 @@
"label.add.ip.range": "IP c\u00edmtartom\u00e1ny felv\u00e9tele",
"label.add.isolated.network": "Izol\u00e1lt h\u00e1l\u00f3zat felv\u00e9tele",
"label.add.ldap.account": "LDAP hozz\u00e1f\u00e9r\u00e9s felv\u00e9tele",
"label.add.list.name": "ACL lista n\u00e9v",
"label.add.acl.name": "ACL Lista n\u00e9v",
"label.add.more": "Tov\u00e1bbi felv\u00e9tele",
"label.add.netscaler.device": "Netscaler eszk\u00f6z felv\u00e9tele",
"label.add.network": "H\u00e1l\u00f3zat felv\u00e9tele",
"label.add.network.acl": "H\u00e1l\u00f3zati ACL felv\u00e9tele",
"label.add.network.acl.list": "H\u00e1l\u00f3zati ACL lista felv\u00e9tele",
"label.add.network.acl": "H\u00e1l\u00f3zati ACL Lista felv\u00e9tele",
"label.add.network.offering": "H\u00e1l\u00f3zati aj\u00e1nlat felv\u00e9tele",
"label.add.new.gateway": "\u00daj \u00e1tj\u00e1r\u00f3 felv\u00e9tele",
"label.add.new.tier": "\u00daj r\u00e9teg felv\u00e9tele",
@ -334,7 +334,7 @@
"label.default.use": "Alap\u00e9rtelmezett haszn\u00e1lat",
"label.default.view": "Alap\u00e9rtelmezett n\u00e9zet",
"label.delete": "T\u00f6rl\u00e9s",
"label.delete.acl.list": "ACL lista t\u00f6rl\u00e9se",
"label.delete.acl": "ACL Lista t\u00f6rl\u00e9se",
"label.delete.affinity.group": "Affin\u00edt\u00e1si csoport t\u00f6rl\u00e9se",
"label.delete.alerts": "T\u00f6rl\u00e9s riaszt\u00e1sok",
"label.delete.bigswitchbcf": "BigSwitch BCF vez\u00e9rl\u0151 elt\u00e1vol\u00edt\u00e1sa",
@ -419,7 +419,7 @@
"label.driver": "Driver",
"label.dynamicscalingenabled": "dinamikus m\u00e9retez\u00e9s enged\u00e9lyezve",
"label.edit": "Szerkeszt\u00e9s",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "ACL szab\u00e1ly szerkeszt\u00e9se",
"label.edit.project.details": "Projekt r\u00e9szletek szerkeszt\u00e9se",
"label.edit.role": "Edit Role",
@ -924,7 +924,6 @@
"label.remove.vpc.offering": "VPC aj\u00e1nlat t\u00f6rl\u00e9se",
"label.removing": "T\u00f6rl\u00e9s",
"label.replace.acl": "ACL csere",
"label.replace.acl.list": "ACL lista cser\u00e9je",
"label.required": "Sz\u00fcks\u00e9ges",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Friss\u00edt\u00e9st ig\u00e9nyel",
@ -1150,8 +1149,7 @@
"label.usehttps": "HTTPS haszn\u00e1lata",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "Felhaszn\u00e1l\u00f3",
"label.userdata": "Felhaszn\u00e1l\u00f3 adat",
"label.userdatal2": "Felhaszn\u00e1l\u00f3i adat",
"label.user.data": "Felhaszn\u00e1l\u00f3 adat",
"label.username": "Felhaszn\u00e1l\u00f3n\u00e9v",
"label.users": "Felhaszn\u00e1l\u00f3k",
"label.utilization": "Utilisation",
@ -1329,7 +1327,7 @@
"message.confirm.archive.selected.alerts": "Er\u0151s\u00edtsd meg, hogy le akarod archiv\u00e1lni a kiv\u00e1lasztott riaszt\u00e1sokat!",
"message.confirm.archive.selected.events": "Er\u0151s\u00edtsd meg, hogy archiv\u00e1lni szeretn\u00e9d a kiv\u00e1lasztott esem\u00e9nyeket!",
"message.confirm.attach.disk": "Biztosan csatolni szeretn\u00e9d a merevlemezt?",
"message.confirm.delete.acl.list": "Biztosan t\u00f6r\u00f6lni akarod ezt a ACL list\u00e1t?",
"message.confirm.delete.acl": "Biztosan t\u00f6r\u00f6lni akarod ezt a ACL List\u00e1t?",
"message.confirm.delete.bigswitchbcf": "Er\u0151s\u00edtsd meg, hogy t\u00f6r\u00f6lni szeretn\u00e9d ezt a BigSwitch BCF vez\u00e9rl\u0151t!",
"message.confirm.delete.brocadevcs": "Er\u0151s\u00edtsd meg, hogy t\u00f6r\u00f6lni szeretn\u00e9d a Brocade Vcs Switch-et",
"message.confirm.delete.ciscoasa1000v": "Er\u0151s\u00edtsd meg, hogy t\u00f6r\u00f6lni akarod a CiscoASA1000v-t",
@ -1354,7 +1352,7 @@
"message.confirm.remove.selected.events": "Er\u0151s\u00edtsd meg, hogy t\u00f6r\u00f6lni szeretn\u00e9d a kiv\u00e1lasztott esem\u00e9nyeket",
"message.confirm.remove.vmware.datacenter": "Er\u0151s\u00edtsd meg, hogy el akarod t\u00e1vol\u00edtani a VMware adatk\u00f6zpontot!",
"message.confirm.remove.vpc.offering": "Biztos vagy abban, hogy t\u00f6r\u00f6lni akarod ezt a VPC aj\u00e1nlatot?",
"message.confirm.replace.acl.new.one": "Le akarod cser\u00e9lni ez ACL list\u00e1t egy \u00fajjal?",
"message.confirm.replace.acl.new.one": "Le akarod cser\u00e9lni ez ACL List\u00e1t egy \u00fajjal?",
"message.confirm.scale.up.router.vm": "Biztosan fel akarod m\u00e9retezni a router VM-et?",
"message.confirm.scale.up.system.vm": "Biztosan fel akarod m\u00e9retezni a rendszer VM-et?",
"message.confirm.start.lb.vm": "Er\u0151s\u00edtsd meg, hogy el akarod ind\u00edtani az LB VM-et!",

View File

@ -14,12 +14,12 @@
"label.account.specific": "Specifico dell'Account",
"label.accounts": "Utenti",
"label.accounttype": "Account Type",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL List Rules",
"label.acl.rules": "ACL Rules",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL Name",
"label.acl.rule.name": "ACL Name",
"label.acquire.new.ip": "Acquisizione nuovo indirizzo IP",
"label.acquire.new.secondary.ip": "Acquisizione nuovo IP secondario",
"label.action": "Action",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Sessioni Attive",
"label.add": "Add",
"label.add.account": "Aggiungi un Account",
"label.add.acl": "Aggiungere ACL",
"label.add.acl.list": "Add ACL List",
"label.add.acl.rule": "Aggiungere ACL",
"label.add.acl": "Add ACL",
"label.add.affinity.group": "Aggiungere un nuovo gruppo di affinit\u00e0",
"label.add.baremetal.dhcp.device": "Add Baremetal DHCP Device",
"label.add.bigswitchbcf.device": "Aggiungere Controller BigSwitch BCF",
@ -142,12 +142,12 @@
"label.add.ip.range": "Aggiungere un IP Range",
"label.add.isolated.network": "Add Isolated Network",
"label.add.ldap.account": "Aggiungi un account LDAP",
"label.add.list.name": "ACL List Name",
"label.add.acl.name": "ACL Name",
"label.add.more": "Add More",
"label.add.netscaler.device": "Aggiungere device Netscaler",
"label.add.network": "Aggiungere una Rete",
"label.add.network.acl": "Aggiungere le ACL di rete",
"label.add.network.acl.list": "Add Network ACL List",
"label.add.network.acl": "Add Network ACL",
"label.add.network.offering": "Aggiungere offerta di rete",
"label.add.new.gateway": "Aggiungere un nuovo gateway",
"label.add.new.tier": "Aggiungere un nuovo livello",
@ -334,7 +334,7 @@
"label.default.use": "Default Use",
"label.default.view": "Vista di default",
"label.delete": "Cancellare",
"label.delete.acl.list": "Delete ACL List",
"label.delete.acl": "Delete ACL",
"label.delete.affinity.group": "Cancellare Gruppo di Affinit\u00e0",
"label.delete.alerts": "Cancella allarmi",
"label.delete.bigswitchbcf": "Rimuovere Controller BigSwitch BCF",
@ -419,7 +419,7 @@
"label.dpd": "Dead Peer Detection",
"label.driver": "Driver",
"label.edit": "Modifica",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Edit ACL rule",
"label.edit.project.details": "Modificare i dettagli del progetto",
"label.edit.role": "Edit Role",
@ -924,7 +924,6 @@
"label.remove.vpc.offering": "Remove VPC offering",
"label.removing": "Rimozione",
"label.replace.acl": "Replace ACL",
"label.replace.acl.list": "Replace ACL List",
"label.required": "Required",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Requires Upgrade",
@ -1150,8 +1149,7 @@
"label.usehttps": "Utilizzare HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "User",
"label.userdata": "Userdata",
"label.userdatal2": "User Data",
"label.user.data": "User Data",
"label.username": "Username",
"label.users": "Users",
"label.utilization": "Utilisation",
@ -1329,7 +1327,7 @@
"message.confirm.archive.selected.alerts": "Please confirm you would like to archive the selected alerts",
"message.confirm.archive.selected.events": "Please confirm you would like to archive the selected events",
"message.confirm.attach.disk": "Are you sure you want to attach disk?",
"message.confirm.delete.acl.list": "Are you sure you want to delete this ACL list?",
"message.confirm.delete.acl": "Are you sure you want to delete this ACL?",
"message.confirm.delete.bigswitchbcf": "Please confirm that you would like to delete this BigSwitch BCF Controller",
"message.confirm.delete.brocadevcs": "Please confirm that you would like to delete Brocade Vcs Switch",
"message.confirm.delete.ciscoasa1000v": "Please confirm you want to delete CiscoASA1000v",

View File

@ -58,11 +58,11 @@
"label.access.kubernetes.nodes": "Kubernetesードに接続",
"label.acl.export": "エクスポートACLs",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACLルールのリスト",
"label.acl.rules": "ACLルールのリスト",
"label.acl.reason.description": "ACLルールの理由を入力してください。",
"label.acl.replaced": "ACLが置き換えられました",
"label.aclid": "ACL",
"label.aclname": "ACL名",
"label.acl.rule.name": "ACL名",
"label.acltotal": "ネットワークACL合計",
"label.acquire.new.ip": "新しいIPアドレスの取得",
"label.acquire.new.secondary.ip": "セカンダリIPアドレスの取得",
@ -298,8 +298,8 @@
"label.add.account": "アカウント追加",
"label.add.accounts": "アカウント追加",
"label.add.accounts.to": "アカウントの追加先:",
"label.add.acl": "ACL追加",
"label.add.acl.list": "ACL一覧追加",
"label.add.acl.rule": "ACL追加",
"label.add.acl": "ACL一覧追加",
"label.add.affinity.group": "新しいアフィニティグループ追加",
"label.add.baremetal.dhcp.device": "ベアメタルDHCPデバイス追加",
"label.add.baremetal.rack.configuration": "ベアメタルラック設定追加",
@ -333,14 +333,14 @@
"label.add.l2.guest.network": "L2ゲストネットワーク追加",
"label.add.ldap.account": "LDAPアカウント追加",
"label.add.ldap.list.users": "LDAPユーザー一覧",
"label.add.list.name": "ACL一覧名",
"label.add.acl.name": "ACL一覧名",
"label.add.load.balancer": "ロードバランサー追加",
"label.add.management.ip.range": "マネージメントIP範囲追加",
"label.add.more": "その他の項目追加",
"label.add.netscaler.device": "NetScalerデバイス追加",
"label.add.network": "ネットワーク追加",
"label.add.network.acl": "ネットワークACL追加",
"label.add.network.acl.list": "ネットワークACL一覧追加",
"label.add.network.acl": "ネットワークACL一覧追加",
"label.add.network.device": "ネットワークデバイス追加",
"label.add.network.offering": "ネットワークオファリング追加",
"label.add.new.f5": "新しいF5追加",
@ -718,7 +718,7 @@
"label.default.view": "デフォルトビュー",
"label.defaultnetwork": "デフォルトネットワーク",
"label.delete": "削除",
"label.delete.acl.list": "ACL一覧削除",
"label.delete.acl": "ACL一覧削除",
"label.delete.affinity.group": "アフィニティグループ削除",
"label.delete.alerts": "アラート削除",
"label.delete.backup": "バックアップ削除",
@ -872,7 +872,7 @@
"label.dynamicscalingenabled": "ダイナミックスケーリング有効",
"label.dynamicscalingenabled.tooltip": "テンプレート、サービスオファリング、およびグローバル設定で動的スケーリングが有効になっている場合にのみ、VMは動的にスケーリングできます。",
"label.edit": "編集",
"label.edit.acl.list": "ACL一覧編集",
"label.edit.acl": "ACL一覧編集",
"label.edit.acl.rule": "ACLルール編集",
"label.edit.affinity.group": "アフィニティグループ編集",
"label.edit.lb.rule": "LBルール編集",
@ -1498,7 +1498,7 @@
"label.netscaler.vpx": "NetScaler VPXロードバランサー",
"label.network": "ネットワーク",
"label.network.acl": "ネットワークACL",
"label.network.acl.lists": "ネットワークACL一覧",
"label.network.acls": "ネットワークACL一覧",
"label.network.acls": "ネットワークACL",
"label.network.addvm": "VMへのネットワーク追加",
"label.network.desc": "ネットワークの説明",
@ -1871,7 +1871,6 @@
"label.removing": "削除しています",
"label.removing.user": "ユーザーを削除しています",
"label.replace.acl": "ACLの置き換え",
"label.replace.acl.list": "ACL一覧の置き換え",
"label.report.bug": "問題レポート",
"label.required": "必須です",
"label.requireshvm": "HVM",
@ -2321,8 +2320,7 @@
"label.user.details": "ユーザーの詳細",
"label.user.source": "ソース",
"label.user.vm": "ユーザーVM",
"label.userdata": "ユーザーデータ",
"label.userdatal2": "ユーザーデータ",
"label.user.data": "ユーザーデータ",
"label.username": "ユーザー名",
"label.users": "ユーザー",
"label.usersource": "ユーザータイプ",
@ -2727,7 +2725,7 @@
"message.confirm.dedicate.host.domain.account": "このホストをドメイン/アカウント専用に設定してもよろしいですか?",
"message.confirm.dedicate.pod.domain.account": "このポッドをドメイン/アカウント専用に設定してもよろしいですか?",
"message.confirm.dedicate.zone": "このゾーンをドメイン/アカウント専用に設定してもよろしいですか?",
"message.confirm.delete.acl.list": "このACL一覧を削除してもよろしいですか",
"message.confirm.delete.acl": "このACL一覧を削除してもよろしいですか",
"message.confirm.delete.alert": "このアラートを削除してもよろしいですか?",
"message.confirm.delete.baremetal.rack.configuration": "ベアメタルラック設定を削除してもよろしいですか?",
"message.confirm.delete.bigswitchbcf": "このBigSwitchBCFコントローラーを削除してもよろしいですか",

View File

@ -32,10 +32,10 @@
"label.accounttype": "\uacc4\uc815 \uc720\ud615",
"label.acl.export": "ACL \ub0b4\ubcf4\ub0b4\uae30",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL \ubaa9\ub85d \uaddc\uce59",
"label.acl.rules": "ACL \ubaa9\ub85d \uaddc\uce59",
"label.acl.reason.description": "ACL \uaddc\uce59 \ub4a4\uc5d0 \uc124\uba85\uc744 \uc785\ub825\ud558\uc2ed\uc2dc\uc624.",
"label.aclid": "ACL",
"label.aclname": "ACL \uc774\ub984",
"label.acl.rule.name": "ACL \uc774\ub984",
"label.acquire.new.ip": "\uc0c8 IP \uc8fc\uc18c \uac00\uc838\uc624\uae30",
"label.acquire.new.secondary.ip": "\uc0c8 \ubcf4\uc870 IP \uc8fc\uc18c \uac00\uc838\uc624\uae30",
"label.acquiring.ip": "IP \uac00\uc838\uc624\uae30",
@ -153,8 +153,8 @@
"label.activeviewersessions": "\ud65c\uc131 \uc138\uc158",
"label.add": "\ucd94\uac00",
"label.add.account": "\uacc4\uc815 \ucd94\uac00",
"label.add.acl": "\uad8c\ud55c \uad00\ub9ac(ACL) \ucd94\uac00",
"label.add.acl.list": "ACL \ubaa9\ub85d \ucd94\uac00",
"label.add.acl.rule": "\uad8c\ud55c \uad00\ub9ac(ACL) \ucd94\uac00",
"label.add.acl": "ACL \ubaa9\ub85d \ucd94\uac00",
"label.add.affinity.group": "\uc0c8 Affinity \uadf8\ub8f9 \ucd94\uac00",
"label.add.baremetal.dhcp.device": "Baremetal DHCP \uc7a5\uce58 \ucd94\uac00",
"label.add.bigswitchbcf.device": "BigSwitch BCF \ucee8\ud2b8\ub864\ub7ec \ucd94\uac00",
@ -178,12 +178,12 @@
"label.add.isolated.network": "isolated \ub124\ud2b8\uc6cc\ud06c \ucd94\uac00",
"label.add.kubernetes.cluster": "\ucfe0\ubc84\ub124\ud14c\uc2a4 \ud074\ub7ec\uc2a4\ud130 \ucd94\uac00",
"label.add.ldap.account": "LDAP \uacc4\uc815 \ucd94\uac00",
"label.add.list.name": "ACL \ubaa9\ub85d \uc774\ub984",
"label.add.acl.name": "ACL \ubaa9\ub85d \uc774\ub984",
"label.add.more": "\ub2e4\ub978 \ud56d\ubaa9 \ucd94\uac00",
"label.add.netscaler.device": "Netscaler \uc7a5\uce58 \ucd94\uac00",
"label.add.network": "\ub124\ud2b8\uc6cc\ud06c \ucd94\uac00",
"label.add.network.acl": "\ub124\ud2b8\uc6cc\ud06c \uad8c\ud55c \uad00\ub9ac(ACL) \ucd94\uac00",
"label.add.network.acl.list": "\ub124\ud2b8\uc6cc\ud06c ACL \ubaa9\ub85d \ucd94\uac00",
"label.add.network.acl": "\ub124\ud2b8\uc6cc\ud06c ACL \ubaa9\ub85d \ucd94\uac00",
"label.add.network.offering": "\ub124\ud2b8\uc6cc\ud06c \uc624\ud37c\ub9c1 \ucd94\uac00",
"label.add.new.gateway": "\uc0c8 \uac8c\uc774\ud2b8\uc6e8\uc774 \ucd94\uac00\ud558\uae30",
"label.add.new.tier": "\uc0c8 \uc11c\ube0c\ub137 \ucd94\uac00",
@ -436,7 +436,7 @@
"label.default.view": "\uae30\ubcf8 \ubcf4\uae30",
"label.defaultnetwork": "\uae30\ubcf8 \ub124\ud2b8\uc6cc\ud06c",
"label.delete": "\uc0ad\uc81c",
"label.delete.acl.list": "ACL \ubaa9\ub85d \uc0ad\uc81c",
"label.delete.acl": "ACL \ubaa9\ub85d \uc0ad\uc81c",
"label.delete.affinity.group": "Affinity \uadf8\ub8f9 \uc0ad\uc81c",
"label.delete.alerts": "\uc54c\ub9bc \uc0ad\uc81c",
"label.delete.backup": "\ubc31\uc5c5 \uc0ad\uc81c",
@ -549,7 +549,7 @@
"label.dpd": "Dead \ud53c\uc5b4 \uac10\uc9c0",
"label.driver": "\ub4dc\ub77c\uc774\ubc84",
"label.edit": "\ud3b8\uc9d1",
"label.edit.acl.list": "ACL \ubaa9\ub85d \ud3b8\uc9d1",
"label.edit.acl": "ACL \ubaa9\ub85d \ud3b8\uc9d1",
"label.edit.acl.rule": "ACL \uaddc\uce59 \ud3b8\uc9d1",
"label.edit.project.details": "\ud504\ub85c\uc81d\ud2b8 \uc0c1\uc138 \ud3b8\uc9d1",
"label.edit.project.role": "\ud504\ub85c\uc81d\ud2b8 \uc5ed\ud560 \ud3b8\uc9d1",
@ -985,7 +985,7 @@
"label.netscaler.vpx": "NetScaler VPX \ub85c\ub4dc\ubc38\ub7f0\uc11c",
"label.network": "\ub124\ud2b8\uc6cc\ud06c",
"label.network.acl": "\ub124\ud2b8\uc6cc\ud06c \uad8c\ud55c \uad00\ub9ac(ACL)",
"label.network.acl.lists": "Network ACL \ubaa9\ub85d",
"label.network.acls": "Network ACL \ubaa9\ub85d",
"label.network.addvm": "VM\uc5d0 \ub124\ud2b8\uc6cc\ud06c \ucd94\uac00",
"label.network.desc": "\ub124\ud2b8\uc6cc\ud06c \uc124\uba85",
"label.network.domain": "\ub124\ud2b8\uc6cc\ud06c \ub3c4\uba54\uc778",
@ -1251,7 +1251,6 @@
"label.remove.vpc.offering": "VPC \uc624\ud37c\ub9c1 \uc0ad\uc81c",
"label.removing": "\uc0ad\uc81c\ud558\ub294 \uc911...",
"label.replace.acl": "ACL \uad50\uccb4",
"label.replace.acl.list": "ACL \ubaa9\ub85d \uad50\uccb4",
"label.report.bug": "\uc774\uc288 \ub9ac\ud3ec\ud2b8",
"label.required": "\ud544\uc218 \uc0ac\ud56d",
"label.requireshvm": "HVM",
@ -1560,8 +1559,7 @@
"label.usenewdiskoffering": "\ub514\uc2a4\ud06c \uc624\ud37c\ub9c1\uc744 \ubcc0\uacbd\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
"label.user": "\uc0ac\uc6a9\uc790",
"label.user.conflict": "\ucda9\ub3cc",
"label.userdata": "\uc0ac\uc6a9\uc790 \ub370\uc774\ud130",
"label.userdatal2": "\uc0ac\uc6a9\uc790 \ub370\uc774\ud130",
"label.user.data": "\uc0ac\uc6a9\uc790 \ub370\uc774\ud130",
"label.username": "\uc0ac\uc6a9\uc790 \uc774\ub984",
"label.users": "\uc0ac\uc6a9\uc790",
"label.usersource": "\uc0ac\uc6a9\uc790 \uc720\ud615",
@ -1818,7 +1816,7 @@
"message.confirm.archive.selected.events": "\uc120\ud0dd\ud55c \uc774\ubca4\ud2b8\ub97c \ubcf4\uad00\ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.",
"message.confirm.attach.disk": "\ub514\uc2a4\ud06c\ub97c \uc5f0\uacb0 \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
"message.confirm.configure.ovs": "Ovs\ub97c \uad6c\uc131\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
"message.confirm.delete.acl.list": "\uc774 ACL \ubaa9\ub85d\uc744 \uc0ad\uc81c \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
"message.confirm.delete.acl": "\uc774 ACL \ubaa9\ub85d\uc744 \uc0ad\uc81c \ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
"message.confirm.delete.bigswitchbcf": "\uc774 BigSwitch BCF \ucee8\ud2b8\ub864\ub7ec\ub97c \uc0ad\uc81c\ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.",
"message.confirm.delete.brocadevcs": "Brocade Vcs \uc2a4\uc704\uce58\ub97c \uc0ad\uc81c\ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.",
"message.confirm.delete.ciscoasa1000v": "CiscoASA1000\uc744 \uc0ad\uc81c\ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.",

View File

@ -14,12 +14,12 @@
"label.account.specific": "Kontospesifikk",
"label.accounts": "Kontoer",
"label.accounttype": "Kontotype",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL Liste Regler",
"label.acl.rules": "ACL Liste Regler",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL Navn",
"label.acl.rule.name": "ACL Navn",
"label.acquire.new.ip": "Tilegne ny IP",
"label.acquire.new.secondary.ip": "Tilegne ny sekund\u00e6r IP",
"label.action": "Handling",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Aktive sesjoner",
"label.add": "Legg til",
"label.add.account": "Legg til konto",
"label.add.acl": "Legg til ACL",
"label.add.acl.list": "Legg til ACL liste",
"label.add.acl.rule": "Legg til ACL",
"label.add.acl": "Legg til ACL liste",
"label.add.affinity.group": "Legg til affinitetsgruppe",
"label.add.baremetal.dhcp.device": "Legg Til Barmetall DHCP Enhet",
"label.add.bigswitchbcf.device": "Legg til BigSwitch BCF kontroller",
@ -142,12 +142,12 @@
"label.add.ip.range": "Legg til IP-rekke",
"label.add.isolated.network": "Legg Til Isolert Nettverk",
"label.add.ldap.account": "Legg til LDAP-konto",
"label.add.list.name": "ACL listenavn",
"label.add.acl.name": "ACL listenavn",
"label.add.more": "Legg til mer",
"label.add.netscaler.device": "Legg til Netscaler enhet",
"label.add.network": "Legg til nettverk",
"label.add.network.acl": "Legg til nettverk ACL",
"label.add.network.acl.list": "Legg til nettverk ACL liste",
"label.add.network.acl": "Legg til nettverk ACL liste",
"label.add.network.offering": "Legg til nettverkstilbud",
"label.add.new.gateway": "Legg til ny gateway",
"label.add.new.tier": "Legg til ny gren",
@ -334,7 +334,7 @@
"label.default.use": "Standard bruk",
"label.default.view": "Standardvisning",
"label.delete": "Slett",
"label.delete.acl.list": "Slett ACL liste",
"label.delete.acl": "Slett ACL liste",
"label.delete.affinity.group": "Slett affinitetsgruppe",
"label.delete.alerts": "Slette varsler",
"label.delete.bigswitchbcf": "Fjern BigSwitch BCF-kontroller",
@ -419,7 +419,7 @@
"label.dpd": "D\u00f8d endepunkt-deteksjon",
"label.driver": "Driver",
"label.edit": "Editer",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Endre ACL regel",
"label.edit.project.details": "Editer prosjektdetaljer",
"label.edit.role": "Edit Role",
@ -924,7 +924,6 @@
"label.remove.vpc.offering": "Fjern VPC tilbud",
"label.removing": "Fjerner",
"label.replace.acl": "Erstatt ACL",
"label.replace.acl.list": "Erstatt ACL Liste",
"label.required": "P\u00e5krevd",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Krever oppgradering",
@ -1150,8 +1149,7 @@
"label.usehttps": "Bruk HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "Bruker",
"label.userdata": "Brukerdata",
"label.userdatal2": "Brukerdata",
"label.user.data": "Brukerdata",
"label.username": "Brukernavn",
"label.users": "Brukere",
"label.utilization": "Utilisation",
@ -1329,7 +1327,7 @@
"message.confirm.archive.selected.alerts": "Vennligst bekreft at du \u00f8nsker \u00e5 arkivere valgte varsler",
"message.confirm.archive.selected.events": "Vennligst bekreft at du vil arkivere valgte hendelser",
"message.confirm.attach.disk": "Er du sikker p\u00e5 at du vil tildele disk?",
"message.confirm.delete.acl.list": "Er du sikker p\u00e5 at du \u00f8nsker \u00e5 slette denne ACL listen?",
"message.confirm.delete.acl": "Er du sikker p\u00e5 at du \u00f8nsker \u00e5 slette denne ACL listen?",
"message.confirm.delete.bigswitchbcf": "Vennligst bekreft at du \u00f8nsker \u00e5 slette denne BigSwitch BCF Controlleren?",
"message.confirm.delete.brocadevcs": "Vennligst bekreft at du vil slette denne Brocade Vcs svitsjen",
"message.confirm.delete.ciscoasa1000v": "Vennligst bekreft at du vil slette CiscoASA1000v",

View File

@ -14,12 +14,12 @@
"label.account.specific": "Account-specifiek",
"label.accounts": "Accounts",
"label.accounttype": "Account type",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL lijst regels",
"label.acl.rules": "ACL lijst regels",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL naam",
"label.acl.rule.name": "ACL naam",
"label.acquire.new.ip": "Bemachtig nieuw IP",
"label.acquire.new.secondary.ip": "Verkrijg nieuw secundair IP",
"label.action": "Actie",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Actieve Sessies",
"label.add": "Voeg toe",
"label.add.account": "Voeg Account toe",
"label.add.acl": "Voeg ACL toe",
"label.add.acl.list": "voeg een ACL lijst toe",
"label.add.acl.rule": "Voeg ACL toe",
"label.add.acl": "voeg een ACL lijst toe",
"label.add.affinity.group": "Nieuwe affinity groep toevoegen",
"label.add.baremetal.dhcp.device": "Voeg Baremetal DHCP Apparaat toe",
"label.add.bigswitchbcf.device": "Voeg eenBigSwitch BCF controller toe",
@ -142,12 +142,12 @@
"label.add.ip.range": "Voeg IP range toe",
"label.add.isolated.network": "Geisoleerd Netwerk Toevoegen",
"label.add.ldap.account": "Voeg LDAP account toe",
"label.add.list.name": "ACL lijst naam",
"label.add.acl.name": "ACL lijst naam",
"label.add.more": "Voeg meer toe",
"label.add.netscaler.device": "Voeg Netscaler apparaat toe",
"label.add.network": "Voeg Netwerk toe",
"label.add.network.acl": "Voeg netwerk ACL toe",
"label.add.network.acl.list": "voeg netwerk ACL lijst toe",
"label.add.network.acl": "voeg netwerk ACL lijst toe",
"label.add.network.offering": "Voeg netwerk aanbieding toe",
"label.add.new.gateway": "Voeg nieuwe gateway toe",
"label.add.new.tier": "Voeg nieuwe Tier toe",
@ -334,7 +334,7 @@
"label.default.use": "Standaard Gebruik",
"label.default.view": "Standaard Weergave",
"label.delete": "Verwijder",
"label.delete.acl.list": "verwijder ACL lijst",
"label.delete.acl": "verwijder ACL lijst",
"label.delete.affinity.group": "Verwijder Affinity Groep",
"label.delete.alerts": "Verwijder waarschuwingen",
"label.delete.bigswitchbcf": "Verwijder BigSwitch BCF Controller",
@ -420,7 +420,7 @@
"label.driver": "Driver",
"label.dynamicscalingenabled": "Dynamisch schalen ingeschakeld\n",
"label.edit": "Wijzig",
"label.edit.acl.list": "Verander een ACL lijst",
"label.edit.acl": "Verander een ACL lijst",
"label.edit.acl.rule": "wijzig ACL regel",
"label.edit.project.details": "Wijzig project details",
"label.edit.role": "Edit Role",
@ -925,7 +925,6 @@
"label.remove.vpc.offering": "VPC aanbieding verwijderen",
"label.removing": "Verwijderen",
"label.replace.acl": "vervang ACL",
"label.replace.acl.list": "vervang ACL lijst",
"label.required": "Vereist",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Upgrade Benodigd",
@ -1151,8 +1150,7 @@
"label.usehttps": "Gebruik HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "Gebruiker",
"label.userdata": "Gebruikers gegevens",
"label.userdatal2": "Gebruiker Data",
"label.user.data": "Gebruiker Data",
"label.username": "Gebruikersnaam",
"label.users": "Gebruikers",
"label.utilization": "Utilisation",
@ -1330,7 +1328,7 @@
"message.confirm.archive.selected.alerts": "bevestig dat u de geselecteerde meldingen wilt archiveren, alstublieft",
"message.confirm.archive.selected.events": "bevestig dat u de geselecteerde gebeurtenissen wilt archiveren, alstublieft",
"message.confirm.attach.disk": "Weet U zeker dat U een disk wilt koppelen?",
"message.confirm.delete.acl.list": "Weet U zeker dat U dit ACL wilt verwijderen?",
"message.confirm.delete.acl": "Weet U zeker dat U dit ACL wilt verwijderen?",
"message.confirm.delete.bigswitchbcf": "bevestig dat u deze BigSwitch BCF Controller wilt verwijderen, alstublieft",
"message.confirm.delete.brocadevcs": "bevestigd dat Brocade Vcs Switch wilt verwijderen, altublieft",
"message.confirm.delete.ciscoasa1000v": "bevestig dat u CiscoASA100v wilt verwijderen, alstublieft",

View File

@ -14,12 +14,12 @@
"label.account.specific": "Account-Specific",
"label.accounts": "Konta",
"label.accounttype": "Account Type",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL List Rules",
"label.acl.rules": "ACL Rules",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL Name",
"label.acl.rule.name": "ACL Name",
"label.acquire.new.ip": "Acquire New IP",
"label.acquire.new.secondary.ip": "Acquire new secondary IP",
"label.action": "Action",
@ -119,8 +119,8 @@
"label.activeviewersessions": "Active Sessions",
"label.add": "Dodaj",
"label.add.account": "Dodaj konto",
"label.add.acl": "Dodaj ACL",
"label.add.acl.list": "Add ACL List",
"label.add.acl.rule": "Dodaj ACL",
"label.add.acl": "Add ACL rule List",
"label.add.affinity.group": "Add new affinity group",
"label.add.baremetal.dhcp.device": "Add Baremetal DHCP Device",
"label.add.bigswitchbcf.device": "Add BigSwitch BCF Controller",
@ -142,12 +142,12 @@
"label.add.ip.range": "Add IP Range",
"label.add.isolated.network": "Add Isolated Network",
"label.add.ldap.account": "Add LDAP account",
"label.add.list.name": "ACL List Name",
"label.add.acl.name": "ACL Name",
"label.add.more": "Dodaj wi\u0119cej",
"label.add.netscaler.device": "Add Netscaler device",
"label.add.network": "Dodaj sie\u0107",
"label.add.network.acl": "Add network ACL",
"label.add.network.acl.list": "Add Network ACL List",
"label.add.network.acl": "Add Network ACL",
"label.add.network.offering": "Add network offering",
"label.add.new.gateway": "Add new gateway",
"label.add.new.tier": "Add new tier",
@ -334,7 +334,7 @@
"label.default.use": "Default Use",
"label.default.view": "Widok domy\u015blny",
"label.delete": "Usu\u0144",
"label.delete.acl.list": "Delete ACL List",
"label.delete.acl": "Delete ACL",
"label.delete.affinity.group": "Delete Affinity Group",
"label.delete.alerts": "Delete alerts",
"label.delete.bigswitchbcf": "Remove BigSwitch BCF Controller",
@ -419,7 +419,7 @@
"label.dpd": "Dead Peer Detection",
"label.driver": "Driver",
"label.edit": "Edytuj",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Edit ACL rule",
"label.edit.project.details": "Zmie\u0144 szczeg\u00f3\u0142y projektu",
"label.edit.role": "Edit Role",
@ -924,7 +924,6 @@
"label.remove.vpc.offering": "Remove VPC offering",
"label.removing": "Usuwanie",
"label.replace.acl": "Replace ACL",
"label.replace.acl.list": "Replace ACL List",
"label.required": "Wymagane",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Requires Upgrade",
@ -1150,8 +1149,7 @@
"label.usehttps": "Use HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "U\u017cytkowni",
"label.userdata": "Userdata",
"label.userdatal2": "User Data",
"label.user.data": "User Data",
"label.username": "Nazwa u\u017cytkownika",
"label.users": "U\u017cytkownicy",
"label.utilization": "Utilisation",
@ -1329,7 +1327,7 @@
"message.confirm.archive.selected.alerts": "Please confirm you would like to archive the selected alerts",
"message.confirm.archive.selected.events": "Please confirm you would like to archive the selected events",
"message.confirm.attach.disk": "Are you sure you want to attach disk?",
"message.confirm.delete.acl.list": "Are you sure you want to delete this ACL list?",
"message.confirm.delete.acl": "Are you sure you want to delete this ACL?",
"message.confirm.delete.bigswitchbcf": "Please confirm that you would like to delete this BigSwitch BCF Controller",
"message.confirm.delete.brocadevcs": "Please confirm that you would like to delete Brocade Vcs Switch",
"message.confirm.delete.ciscoasa1000v": "Please confirm you want to delete CiscoASA1000v",

View File

@ -33,10 +33,10 @@
"label.accounttype": "Tipo de conta",
"label.acl.export": "Exportar ACLs",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "Lista de regras de ACL",
"label.acl.rules": "Lista de regras de ACL",
"label.acl.reason.description": "Motivo para se utilizar a regra.",
"label.aclid": "ACL",
"label.aclname": "Nome da ACL",
"label.acl.rule.name": "Nome da ACL",
"label.acquire.new.ip": "Adquirir novo IP",
"label.acquire.new.secondary.ip": "Adquira um novo IP secund\u00e1rio",
"label.acquiring.ip": "Obtendo IP",
@ -171,8 +171,8 @@
"label.activeviewersessions": "Sess\u00f5es ativas",
"label.add": "Adicionar",
"label.add.account": "Adicionar conta",
"label.add.acl": "Adicionar ACL",
"label.add.acl.list": "Adiciona lista ACL",
"label.add.acl.rule": "Adicionar ACL",
"label.add.acl": "Adiciona lista ACL",
"label.add.affinity.group": "Adicionar um grupo de afinidade",
"label.add.baremetal.dhcp.device": "Adicionar dispositivo DHCP baremetal",
"label.add.bigswitchbcf.device": "Adicionar controlador BigSwitch BCF",
@ -196,12 +196,12 @@
"label.add.isolated.network": "Adiciona rede isolada",
"label.add.kubernetes.cluster": "Adicionar cluster Kubernetes",
"label.add.ldap.account": "Adicionar conta LDAP",
"label.add.list.name": "Nome da lista ACL",
"label.add.acl.name": "Nome da lista ACL",
"label.add.more": "Adicionar mais",
"label.add.netscaler.device": "Adicionar dispositivo Netscaler",
"label.add.network": "Adicionar rede",
"label.add.network.acl": "Adicione ACL de rede",
"label.add.network.acl.list": "Adicionar lista de ACL de rede",
"label.add.network.acl": "Adicionar lista de ACL de rede",
"label.add.network.offering": "Adicionar oferta de rede",
"label.add.new.gateway": "Adicionar novo gateway",
"label.add.new.tier": "Adicionar nova camada",
@ -485,7 +485,7 @@
"label.default.view": "Visualiza\u00e7\u00e3o padr\u00e3o",
"label.defaultnetwork": "Rede padr\u00e3o",
"label.delete": "Remover",
"label.delete.acl.list": "Apagar lista ACL",
"label.delete.acl": "Apagar lista ACL",
"label.delete.affinity.group": "Apagar grupo de afinidade",
"label.delete.alerts": "Remover alertas",
"label.delete.backup": "Apagar backup",
@ -612,7 +612,7 @@
"label.dynamicscalingenabled": "Escalonamento din\u00e2mico habilitado",
"label.dynamicscalingenabled.tooltip": "VM s\u00f3 pode ser dinamicamente escalonada quando o escalonamento din\u00e2mico estiver habilitado no template, oferta de computa\u00e7\u00e3o e nas configura\u00e7\u00e3oes globais",
"label.edit": "Editar",
"label.edit.acl.list": "Editar lista ACL",
"label.edit.acl": "Editar lista ACL",
"label.edit.acl.rule": "Editar regra ACL",
"label.edit.project.details": "Editar detalhes do projeto",
"label.edit.project.role": "Editar fun\u00e7\u00e3o do projeto",
@ -1069,7 +1069,7 @@
"label.netscaler.vpx": "NetScaler VPX LoadBalancer",
"label.network": "Rede",
"label.network.acl": "ACL de rede",
"label.network.acl.lists": "Lista de redes ACL",
"label.network.acls": "Lista de redes ACL",
"label.network.addvm": "Adicionar rede para VM",
"label.network.desc": "Descri\u00e7\u00e3o de rede",
"label.network.domain": "Dom\u00ednio de rede",
@ -1356,7 +1356,6 @@
"label.removed": "Removido",
"label.removing": "Removendo",
"label.replace.acl": "Substituir ACL",
"label.replace.acl.list": "Substituir lista ACL",
"label.report.bug": "Reportar um problema",
"label.required": "Obrigat\u00f3rio",
"label.requireshvm": "HVM",
@ -1701,8 +1700,7 @@
"label.usenewdiskoffering": "Substituir a oferta de disco?",
"label.user": "Usu\u00e1rio",
"label.user.conflict": "Conflito",
"label.userdata": "Dados de usu\u00e1rio",
"label.userdatal2": "Dados de usu\u00e1rio",
"label.user.data": "Dados de usu\u00e1rio",
"label.username": "Nome de usu\u00e1rio",
"label.users": "Usu\u00e1rios",
"label.usersource": "Tipo de usu\u00e1rio",
@ -1978,7 +1976,7 @@
"message.confirm.archive.selected.events": "Por favor confirme que voc\u00ea deseja arquivar os eventos selecionados",
"message.confirm.attach.disk": "Voc\u00ea tem certeza que deseja conectar este disco?",
"message.confirm.configure.ovs": "Voc\u00ea tem certeza de que quer configurar os Ovs?",
"message.confirm.delete.acl.list": "Voc\u00ea tem certeza que deseja apagar esta lista ACL?",
"message.confirm.delete.acl": "Voc\u00ea tem certeza que deseja apagar esta lista ACL?",
"message.confirm.delete.bigswitchbcf": "Por favor, confirme que voc\u00ea deseja deletar este controlador BigSwitch BCF",
"message.confirm.delete.brocadevcs": "Por favor confirme que voc\u00ea deseja remover o switch Brocade Vcs",
"message.confirm.delete.ciscoasa1000v": "Favor confirmar que voc\u00ea deseja apagar este CiscoASA1000v",

View File

@ -14,12 +14,12 @@
"label.account.specific": "\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430 \u0430\u043a\u043a\u0430\u0443\u043d\u043d\u0442\u0430",
"label.accounts": "\u0423\u0447\u0451\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438",
"label.accounttype": "Account Type",
"label.acl.export": "Export ACLs",
"label.acl.export": "Export ACL rules",
"label.acl.id": "ACL ID",
"label.acl.list.rules": "ACL List Rules",
"label.acl.rules": "ACL Rules",
"label.acl.reason.description": "Enter the reason behind an ACL rule.",
"label.aclid": "ACL",
"label.aclname": "ACL Name",
"label.acl.rule.name": "ACL Name",
"label.acquire.new.ip": "\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 IP",
"label.acquire.new.secondary.ip": "\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 IP-\u0430\u0434\u0440\u0435\u0441",
"label.action": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f",
@ -119,8 +119,8 @@
"label.activeviewersessions": "\u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0435\u0441\u0441\u0438\u0438",
"label.add": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c",
"label.add.account": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c",
"label.add.acl": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c ACL",
"label.add.acl.list": "Add ACL List",
"label.add.acl.rule": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c ACL",
"label.add.acl": "Add ACL",
"label.add.affinity.group": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e affinity group",
"label.add.baremetal.dhcp.device": "Add Baremetal DHCP Device",
"label.add.bigswitchbcf.device": "Add BigSwitch BCF Controller",
@ -142,12 +142,12 @@
"label.add.ip.range": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0430\u0434\u0440\u0435\u0441\u043e\u0432",
"label.add.isolated.network": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0441\u0435\u0442\u044c",
"label.add.ldap.account": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c LDAP \u0430\u043a\u043a\u0430\u0443\u043d\u0442",
"label.add.list.name": "ACL List Name",
"label.add.acl.name": "ACL Name",
"label.add.more": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0435\u0449\u0435",
"label.add.netscaler.device": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c Netscaler \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e",
"label.add.network": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0442\u044c",
"label.add.network.acl": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u0443\u044e ACL",
"label.add.network.acl.list": "Add Network ACL List",
"label.add.network.acl": "Add Network ACL",
"label.add.network.offering": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b",
"label.add.new.gateway": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0448\u043b\u044e\u0437",
"label.add.new.tier": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 Tier",
@ -334,7 +334,7 @@
"label.default.use": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e",
"label.default.view": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u0438\u0434",
"label.delete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c",
"label.delete.acl.list": "Delete ACL List",
"label.delete.acl": "Delete ACL",
"label.delete.affinity.group": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c affinity group",
"label.delete.alerts": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0440\u0435\u0432\u043e\u0433\u0438",
"label.delete.bigswitchbcf": "Remove BigSwitch BCF Controller",
@ -418,7 +418,7 @@
"label.dpd": "Dead Peer Detection",
"label.driver": "Driver",
"label.edit": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
"label.edit.acl.list": "Edit ACL List",
"label.edit.acl": "Edit ACL",
"label.edit.acl.rule": "Edit ACL rule",
"label.edit.project.details": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u0442\u0430\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430",
"label.edit.role": "Edit Role",
@ -923,7 +923,6 @@
"label.remove.vpc.offering": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0443\u0441\u043b\u0443\u0433\u0443 VPC",
"label.removing": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435",
"label.replace.acl": "Replace ACL",
"label.replace.acl.list": "Replace ACL List",
"label.required": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f",
"label.requireshvm": "HVM",
"label.requiresupgrade": "Requires Upgrade",
@ -1149,8 +1148,7 @@
"label.usehttps": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 HTTPS",
"label.usenewdiskoffering": "Replace disk offering?",
"label.user": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c",
"label.userdata": "Userdata",
"label.userdatal2": "User Data",
"label.user.data": "User Data",
"label.username": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
"label.users": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
"label.utilization": "Utilisation",
@ -1328,7 +1326,7 @@
"message.confirm.archive.selected.alerts": "Please confirm you would like to archive the selected alerts",
"message.confirm.archive.selected.events": "Please confirm you would like to archive the selected events",
"message.confirm.attach.disk": "Are you sure you want to attach disk?",
"message.confirm.delete.acl.list": "Are you sure you want to delete this ACL list?",
"message.confirm.delete.acl": "Are you sure you want to delete this ACL?",
"message.confirm.delete.bigswitchbcf": "Please confirm that you would like to delete this BigSwitch BCF Controller",
"message.confirm.delete.brocadevcs": "Please confirm that you would like to delete Brocade Vcs Switch",
"message.confirm.delete.ciscoasa1000v": "Please confirm you want to delete CiscoASA1000v",

View File

@ -66,12 +66,12 @@
"label.acl.export": "\u5BFC\u51FA ACL \u89C4\u5219",
"label.acl.id": "ACL \u6807\u8BC6\u7801",
"label.acl.list.rules": "ACL\u5217\u8868\u7B56\u7565",
"label.acl.rules": "ACL\u5217\u8868\u7B56\u7565",
"label.acl.reason.description": "\u8F93\u5165\u5B9A\u4E49 ACL \u7B56\u7565\u7684\u539F\u56E0\u3002",
"label.acl.replaced": "ACL \u5DF2\u66FF\u6362",
"label.aclid": "\u8BBF\u95EE\u63A7\u5236\uFF08ACL\uFF09",
"label.aclname": "ACL \u540D\u79F0",
"label.acl.rule.name": "ACL \u540D\u79F0",
"label.acltotal": "\u7F51\u7EDC ACL \u603B\u6570",
"label.acquire.new.ip": "\u83B7\u53D6\u65B0 IP \u5730\u5740",
"label.acquire.new.secondary.ip": "\u83B7\u53D6\u65B0\u4E8C\u7EA7 IP \u5730\u5740",
@ -336,8 +336,8 @@
"label.add.account": "\u6DFB\u52A0\u5E10\u6237",
"label.add.accounts": "\u6DFB\u52A0\u5E10\u6237",
"label.add.accounts.to": "\u6DFB\u52A0\u5E10\u6237\u81F3",
"label.add.acl": "\u6DFB\u52A0 ACL",
"label.add.acl.list": "\u6DFB\u52A0 ACL \u5217\u8868",
"label.add.acl.rule": "\u6DFB\u52A0 ACL",
"label.add.acl": "\u6DFB\u52A0 ACL \u5217\u8868",
"label.add.affinity.group": "\u6DFB\u52A0\u65B0\u5173\u8054\u6027\u7EC4",
"label.add.baremetal.dhcp.device": "\u6DFB\u52A0\u88F8\u673A DHCP \u8BBE\u5907",
@ -381,7 +381,7 @@
"label.add.l2.guest.network": "\u6DFB\u52A0 L2 \u6765\u5BBE\u7F51\u7EDC",
"label.add.ldap.account": "\u6DFB\u52A0 LDAP \u8D26\u6237",
"label.add.ldap.list.users": "\u5217\u51FA LDAP \u7528\u6237",
"label.add.list.name": "ACL \u5217\u8868\u540D\u79F0",
"label.add.acl.name": "ACL \u5217\u8868\u540D\u79F0",
"label.add.load.balancer": "\u6DFB\u52A0\u8D1F\u8F7D\u5747\u8861\u5668",
"label.add.management.ip.range": "\u6DFB\u52A0\u7BA1\u7406 IP \u5730\u5740\u8303\u56F4",
@ -389,7 +389,7 @@
"label.add.netscaler.device": "\u6DFB\u52A0 Netscaler \u8BBE\u5907",
"label.add.network": "\u6DFB\u52A0\u7F51\u7EDC",
"label.add.network.acl": "\u6DFB\u52A0\u7F51\u7EDC ACL",
"label.add.network.acl.list": "\u6DFB\u52A0\u7F51\u7EDC ACL \u5217\u8868",
"label.add.network.acl": "\u6DFB\u52A0\u7F51\u7EDC ACL \u5217\u8868",
"label.add.network.device": "\u6DFB\u52A0\u7F51\u7EDC\u8BBE\u5907",
"label.add.network.offering": "\u6DFB\u52A0\u7F51\u7EDC\u65B9\u6848",
@ -829,7 +829,7 @@
"label.defaultnetwork": "\u9ED8\u8BA4\u7F51\u7EDC",
"label.delete": "\u5220\u9664",
"label.delete.acl.list": "\u5220\u9664 ACL \u5217\u8868",
"label.delete.acl": "\u5220\u9664 ACL \u5217\u8868",
"label.delete.affinity.group": "\u5220\u9664\u5173\u8054\u6027\u7EC4",
"label.delete.alerts": "\u5220\u9664\u8B66\u62A5",
"label.delete.backup": "\u5220\u9664\u5907\u4EFD",
@ -1007,7 +1007,7 @@
"label.computeonly.offering.tooltip": "\u5728\u8BA1\u7B97\u65B9\u6848\u4E2D\u6307\u5B9A\u4E0E\u6839\u78C1\u76D8\u76F8\u5173\u7684\u4FE1\u606F\u6216\u5C06\u78C1\u76D8\u65B9\u6848\u76F4\u63A5\u94FE\u63A5\u5230\u8BA1\u7B97\u65B9\u6848\u7684\u9009\u9879",
"label.edit": "\u7F16\u8F91",
"label.edit.acl.list": "\u7F16\u8F91 ACL \u5217\u8868",
"label.edit.acl": "\u7F16\u8F91 ACL \u5217\u8868",
"label.edit.acl.rule": "\u7F16\u8F91 ACL \u89C4\u5219",
"label.edit.affinity.group": "\u7F16\u8F91\u5173\u8054\u6027\u7EC4",
"label.edit.lb.rule": "\u7F16\u8F91\u8D1F\u8F7D\u5747\u8861\u5668\u89C4\u5219",
@ -1717,7 +1717,7 @@
"label.netscaler.vpx": "NetScaler VPX \u8D1F\u8F7D\u5747\u8861\u5668",
"label.network": "\u7F51\u7EDC",
"label.network.acl": "\u7F51\u7EDC ACL",
"label.network.acl.lists": "\u7F51\u7EDC ACL \u5217\u8868",
"label.network.acls": "\u7F51\u7EDC ACL \u5217\u8868",
"label.network.acls": "\u7F51\u7EDC ACL",
"label.network.addvm": "\u5C06\u7F51\u7EDC\u6DFB\u52A0\u5230\u865A\u62DF\u673A",
"label.network.desc": "\u7F51\u7EDC\u63CF\u8FF0",
@ -2136,7 +2136,6 @@
"label.removing.user": "\u6B63\u5728\u5220\u9664\u7528\u6237",
"label.replace.acl": "\u66FF\u6362 ACL",
"label.replace.acl.list": "\u66FF\u6362 ACL \u5217\u8868",
"label.report.bug": "\u62A5\u544A\u95EE\u9898",
"label.required": "\u5FC5\u586B\u9879",
@ -2666,8 +2665,7 @@
"label.user.details": "\u7528\u6237\u8BE6\u60C5",
"label.user.source": "\u6765\u6E90",
"label.user.vm": "\u7528\u6237\u865A\u62DF\u673A",
"label.userdata": "\u7528\u6237\u6570\u636E",
"label.userdatal2": "\u7528\u6237\u6570\u636E",
"label.user.data": "\u7528\u6237\u6570\u636E",
"label.username": "\u7528\u6237\u540D",
"label.users": "\u7528\u6237",
"label.usersource": "\u7528\u6237\u7C7B\u578B",
@ -3129,7 +3127,7 @@
"message.confirm.dedicate.pod.domain.account": "\u662F\u5426\u786E\u5B9E\u8981\u5C06\u6B64\u63D0\u4F9B\u70B9\u4E13\u7528\u4E8E\u57DF/\u5E10\u6237\uFF1F",
"message.confirm.dedicate.zone": "\u662F\u5426\u8981\u5C06\u6B64\u8D44\u6E90\u57DF\u4E13\u7528\u4E8E\u57DF/\u5E10\u6237\uFF1F",
"message.confirm.delete.acl.list": "\u662F\u5426\u786E\u5B9E\u8981\u5220\u9664\u6B64 ACL \u5217\u8868\uFF1F",
"message.confirm.delete.acl": "\u662F\u5426\u786E\u5B9E\u8981\u5220\u9664\u6B64 ACL \u5217\u8868\uFF1F",
"message.confirm.delete.alert": "\u662F\u5426\u786E\u5B9E\u8981\u5220\u9664\u6B64\u8B66\u62A5\uFF1F",
"message.confirm.delete.baremetal.rack.configuration": "\u8BF7\u786E\u8BA4\u60A8\u786E\u5B9E\u8981\u5220\u9664 Baremetal Rack \u914D\u7F6E",
"message.confirm.delete.bigswitchbcf": "\u8BF7\u786E\u8BA4\u60A8\u786E\u5B9E\u8981\u5220\u9664\u6B64 BigSwitch BCF \u63A7\u5236\u5668",

View File

@ -34,6 +34,9 @@
<span v-if="resourceIcon && !['router', 'systemvm', 'volume'].includes($route.path.split('/')[1])">
<resource-icon :image="resourceIcon" size="4x" style="margin-right: 5px"/>
</span>
<span v-else-if="resource.vmtype === 'sharedfsvm'">
<file-text-outlined style="font-size: 36px;" />
</span>
<span v-else>
<os-logo v-if="resource.ostypeid || resource.ostypename || ['guestoscategory'].includes($route.path.split('/')[1])" :osId="resource.ostypeid" :osName="resource.ostypename || resource.osdisplayname || resource.name" size="3x" />
<render-icon v-else-if="typeof $route.meta.icon ==='string'" style="font-size: 36px" :icon="$route.meta.icon" />
@ -695,7 +698,7 @@
</div>
</div>
<div class="resource-detail-item" v-if="resource.userdataname">
<div class="resource-detail-item__label">{{ $t('label.userdata') }}</div>
<div class="resource-detail-item__label">{{ $t('label.user.data') }}</div>
<div class="resource-detail-item__details">
<solution-outlined />
<router-link v-if="!isStatic && $router.resolve('/userdata/' + resource.userdataid).matched[0].redirect !== '/exception/404'" :to="{ path: '/userdata/' + resource.userdataid }">{{ resource.userdataname || resource.userdataid }}</router-link>
@ -761,6 +764,18 @@
<span v-else>{{ resource.webhookname || resource.webhookid }}</span>
</div>
</div>
<div class="resource-detail-item" v-if="resource.boottype">
<div class="resource-detail-item__label">{{ $t('label.boottype') }}</div>
<div class="resource-detail-item__details">
<span>{{ resource.boottype }}</span>
</div>
</div>
<div class="resource-detail-item" v-if="resource.bootmode">
<div class="resource-detail-item__label">{{ $t('label.bootmode') }}</div>
<div class="resource-detail-item__details">
<span>{{ resource.bootmode }}</span>
</div>
</div>
<div class="resource-detail-item" v-if="resource.managementserverid">
<div class="resource-detail-item__label">{{ $t('label.management.servers') }}</div>
<div class="resource-detail-item__details">
@ -913,6 +928,7 @@ import eventBus from '@/config/eventBus'
import ResourceIcon from '@/components/view/ResourceIcon'
import ResourceLabel from '@/components/widgets/ResourceLabel'
import ImageDeployInstanceButton from '@/components/view/ImageDeployInstanceButton'
import { FileTextOutlined } from '@ant-design/icons-vue'
export default {
name: 'InfoCard',
@ -926,6 +942,7 @@ export default {
ResourceIcon,
ResourceLabel,
ImageDeployInstanceButton
FileTextOutlined
},
props: {
resource: {
@ -1260,6 +1277,9 @@ export default {
if (item.name === 'template') {
query.templatefilter = 'self'
query.filter = 'self'
} else if (item.name === 'iso') {
query.isofilter = 'self'
query.filter = 'self'
}
if (item.param === 'account') {

View File

@ -44,6 +44,9 @@
<span v-if="record.icon && record.icon.base64image">
<resource-icon :image="record.icon.base64image" size="2x"/>
</span>
<span v-else-if="record.vmtype === 'sharedfsvm'">
<file-text-outlined style="font-size: 18px;" />
</span>
<os-logo v-else :osId="record.ostypeid" :osName="record.osdisplayname" size="xl" />
</span>
<span style="min-width: 120px" >
@ -625,6 +628,7 @@ import { createPathBasedOnVmType } from '@/utils/plugins'
import { validateLinks } from '@/utils/links'
import cronstrue from 'cronstrue/i18n'
import moment from 'moment-timezone'
import { FileTextOutlined } from '@ant-design/icons-vue'
export default {
name: 'ListView',
@ -635,7 +639,8 @@ export default {
CopyLabel,
TooltipButton,
ResourceIcon,
ResourceLabel
ResourceLabel,
FileTextOutlined
},
props: {
columns: {

View File

@ -55,7 +55,7 @@ export default {
param: 'account'
}, {
name: 'userdata',
title: 'label.userdata',
title: 'label.user.data',
param: 'account'
}, {
name: 'template',

View File

@ -400,7 +400,7 @@ export default {
{
api: 'resetUserDataForVirtualMachine',
icon: 'solution-outlined',
label: 'label.reset.userdata.on.vm',
label: 'label.reset.user.data.on.vm',
message: 'message.desc.reset.userdata',
docHelp: 'adminguide/virtual_machines.html#resetting-userdata',
dataView: true,
@ -932,7 +932,7 @@ export default {
},
{
name: 'userdata',
title: 'label.user.data',
title: 'label.user.data.library',
icon: 'solution-outlined',
docHelp: 'adminguide/virtual_machines.html#user-data-and-meta-data',
permission: ['listUserData'],
@ -971,7 +971,7 @@ export default {
api: 'registerUserData',
icon: 'plus-outlined',
label: 'label.register.user.data',
docHelp: 'adminguide/virtual_machines.html#creating-the-ssh-keypair',
docHelp: 'adminguide/virtual_machines.html#user-data-and-meta-data',
listView: true,
popup: true,
component: shallowRef(defineAsyncComponent(() => import('@/views/compute/RegisterUserData.vue')))

View File

@ -48,6 +48,11 @@ export default {
name: 'template',
title: 'label.templates',
param: 'domainid'
},
{
name: 'iso',
title: 'label.isos',
param: 'domainid'
}],
tabs: [
{

View File

@ -182,7 +182,7 @@ export default {
{
api: 'replaceNetworkACLList',
icon: 'swap-outlined',
label: 'label.replace.acl.list',
label: 'label.replace.acl',
message: 'message.confirm.replace.acl.new.one',
docHelp: 'adminguide/networking_and_traffic.html#configuring-network-access-control-list',
dataView: true,
@ -698,7 +698,7 @@ export default {
{
api: 'resetUserDataForVirtualMachine',
icon: 'solution-outlined',
label: 'label.reset.userdata.on.vm',
label: 'label.reset.user.data.on.vm',
message: 'message.desc.reset.userdata',
docHelp: 'adminguide/virtual_machines.html#resetting-userdata',
dataView: true,
@ -965,7 +965,7 @@ export default {
{
api: 'replaceNetworkACLList',
icon: 'swap-outlined',
label: 'label.replace.acl.list',
label: 'label.replace.acl',
message: 'message.confirm.replace.acl.new.one',
docHelp: 'adminguide/networking_and_traffic.html#acl-on-private-gateway',
dataView: true,
@ -1061,10 +1061,9 @@ export default {
},
{
name: 'acllist',
title: 'label.network.acl.lists',
title: 'label.network.acls',
icon: 'bars-outlined',
docHelp: 'adminguide/networking_and_traffic.html#configuring-network-access-control-list',
hidden: true,
permission: ['listNetworkACLLists'],
columns: ['name', 'description', 'id'],
details: ['name', 'description', 'id'],
@ -1072,15 +1071,15 @@ export default {
name: 'details',
component: shallowRef(defineAsyncComponent(() => import('@/components/view/DetailsTab.vue')))
}, {
name: 'acl.list.rules',
component: shallowRef(defineAsyncComponent(() => import('@/views/network/AclListRulesTab.vue'))),
name: 'acl.rules',
component: shallowRef(defineAsyncComponent(() => import('@/views/network/AclRulesTab.vue'))),
show: () => true
}],
actions: [
{
api: 'createNetworkACLList',
icon: 'plus-outlined',
label: 'label.add.acl.list',
label: 'label.add.acl',
docHelp: 'adminguide/networking_and_traffic.html#creating-acl-lists',
listView: true,
args: ['name', 'description', 'vpcid']
@ -1088,15 +1087,15 @@ export default {
{
api: 'updateNetworkACLList',
icon: 'edit-outlined',
label: 'label.edit.acl.list',
label: 'label.edit.acl',
dataView: true,
args: ['name', 'description']
},
{
api: 'deleteNetworkACLList',
icon: 'delete-outlined',
label: 'label.delete.acl.list',
message: 'message.confirm.delete.acl.list',
label: 'label.delete.acl',
message: 'message.confirm.delete.acl',
dataView: true
}
]

View File

@ -76,7 +76,7 @@
<div class="form" v-if="userdataid">
<div class="form__item">
<div class="form__label">
<tooltip-label :title="$t('label.userdataid')"/>
<tooltip-label :title="$t('label.user.data.id')"/>
</div>
{{ userdataid }}
</div>
@ -84,7 +84,7 @@
<div class="form" v-if="userdataname">
<div class="form__item">
<div class="form__label">
<tooltip-label :title="$t('label.userdataname')"/>
<tooltip-label :title="$t('label.user.data.name')"/>
</div>
{{ userdataname }}
</div>
@ -92,7 +92,7 @@
<div class="form" v-if="userdatadetails">
<div class="form__item">
<div class="form__label">
<tooltip-label :title="$t('label.userdatadetails')"/>
<tooltip-label :title="$t('label.user.data.details')"/>
</div>
{{ userdatadetails }}
</div>
@ -100,7 +100,7 @@
<div class="form" v-if="userdatapolicy">
<div class="form__item">
<div class="form__label">
<tooltip-label :title="$t('label.userdatapolicy')"/>
<tooltip-label :title="$t('label.user.data.policy')"/>
</div>
{{ userdatapolicy }}
</div>
@ -108,7 +108,7 @@
<div class="form">
<div class="form__item">
<div class="form__label">
<tooltip-label :title="$t('label.userdata')" :tooltip="createAutoScaleVmProfileApiParams.userdata.description"/>
<tooltip-label :title="$t('label.user.data')" :tooltip="createAutoScaleVmProfileApiParams.userdata.description"/>
</div>
<a-textarea v-model:value="userdata" rows="5" :disabled="true">
</a-textarea>
@ -124,7 +124,7 @@
<div class="form__item">
<a-button ref="submit" :disabled="!('updateAutoScaleVmProfile' in $store.getters.apis) || resource.state !== 'DISABLED'" type="primary" @click="showUpdateUserDataForm = true">
<template #icon><solution-outlined /></template>
{{ $t('label.reset.userdata.on.autoscale.vm.group') }}
{{ $t('label.reset.user.data.on.autoscale.vm.group') }}
</a-button>
</div>
</div>
@ -291,7 +291,7 @@
<a-modal
:visible="showUpdateUserDataForm"
:title="$t('label.reset.userdata.on.autoscale.vm.group')"
:title="$t('label.reset.user.data.on.autoscale.vm.group')"
:closable="true"
:maskClosable="false"
:footer="null"

View File

@ -762,7 +762,7 @@
</a-form-item>
<a-form-item>
<template #label>
<tooltip-label :title="$t('label.userdata')" :tooltip="createAutoScaleVmProfileApiParams.userdata.description"/>
<tooltip-label :title="$t('label.user.data')" :tooltip="createAutoScaleVmProfileApiParams.userdata.description"/>
</template>
<a-card>
<div v-if="this.template && this.template.userdataid">
@ -790,11 +790,11 @@
</div><br/><br/>
<div v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE' || userdataDefaultOverridePolicy === 'APPEND' || !userdataDefaultOverridePolicy">
<span v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE'" >
{{ $t('label.userdata.do.override') }}
{{ $t('label.user.data.do.override') }}
<a-switch v-model:checked="doUserdataOverride" style="margin-left: 10px"/>
</span>
<span v-if="userdataDefaultOverridePolicy === 'APPEND'">
{{ $t('label.userdata.do.append') }}
{{ $t('label.user.data.do.append') }}
<a-switch v-model:checked="doUserdataAppend" style="margin-left: 10px"/>
</span>
<a-step
@ -1257,11 +1257,11 @@ export default {
userDataValues: {},
templateUserDataCols: [
{
title: this.$t('label.userdata'),
title: this.$t('label.user.data'),
dataIndex: 'userdata'
},
{
title: this.$t('label.userdatapolicy'),
title: this.$t('label.user.data.policy'),
dataIndex: 'userdataoverridepolicy'
}
],
@ -1458,11 +1458,11 @@ export default {
let tabList = []
tabList = [{
key: 'userdataregistered',
tab: this.$t('label.userdata.registered')
tab: this.$t('label.user.data.registered')
},
{
key: 'userdatatext',
tab: this.$t('label.userdata.text')
tab: this.$t('label.user.data.text')
}]
return tabList
},

View File

@ -611,7 +611,7 @@
</a-form-item>
</a-col>
</a-row>
<a-form-item :label="$t('label.userdata')">
<a-form-item :label="$t('label.user.data')">
<a-card>
<div v-if="this.template && this.template.userdataid">
<a-typography-text>
@ -665,11 +665,11 @@
</div><br/><br/>
<div v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE' || userdataDefaultOverridePolicy === 'APPEND' || !userdataDefaultOverridePolicy">
<span v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE'" >
{{ $t('label.userdata.do.override') }}
{{ $t('label.user.data.do.override') }}
<a-switch v-model:checked="doUserdataOverride" style="margin-left: 10px"/>
</span>
<span v-if="userdataDefaultOverridePolicy === 'APPEND'">
{{ $t('label.userdata.do.append') }}
{{ $t('label.user.data.do.append') }}
<a-switch v-model:checked="doUserdataAppend" style="margin-left: 10px"/>
</span>
<a-step
@ -996,8 +996,7 @@ export default {
keyboards: [],
bootTypes: [],
bootModes: [],
ioPolicyTypes: [],
dynamicScalingVmConfig: false
ioPolicyTypes: []
},
rowCount: {},
loading: {
@ -1058,11 +1057,11 @@ export default {
userDataValues: {},
templateUserDataCols: [
{
title: this.$t('label.userdata'),
title: this.$t('label.user.data'),
dataIndex: 'userdata'
},
{
title: this.$t('label.userdatapolicy'),
title: this.$t('label.user.data.policy'),
dataIndex: 'userdataoverridepolicy'
}
],
@ -1418,11 +1417,11 @@ export default {
let tabList = []
tabList = [{
key: 'userdataregistered',
tab: this.$t('label.userdata.registered')
tab: this.$t('label.user.data.registered')
},
{
key: 'userdatatext',
tab: this.$t('label.userdata.text')
tab: this.$t('label.user.data.text')
}]
return tabList
@ -1449,7 +1448,7 @@ export default {
return Boolean('listUserData' in this.$store.getters.apis)
},
dynamicScalingVmConfigValue () {
return this.options.dynamicScalingVmConfig?.[0]?.value === 'true'
return this.$store.getters.features.dynamicscalingenabled
},
isCustomizedDiskIOPS () {
return this.diskSelected?.iscustomizediops || false
@ -2500,20 +2499,29 @@ export default {
if (exclude && exclude.length > 0 && exclude.includes(name)) {
return resolve(null)
}
this.loading[name] = true
param.loading = true
param.opts = []
const options = param.options || {}
if (!('listall' in options) && !['zones', 'pods', 'clusters', 'hosts', 'dynamicScalingVmConfig', 'hypervisors'].includes(name)) {
options.listall = true
}
postAPI(param.list, options).then((response) => {
param.loading = false
_.map(response, (responseItem, responseKey) => {
if (Object.keys(responseItem).length === 0) {
this.rowCount[name] = 0
this.options[name] = []
return resolve(null)
}
this.loading[name] = true
param.loading = true
param.opts = []
const options = param.options || {}
if (!('listall' in options) && !['zones', 'pods', 'clusters', 'hosts', 'hypervisors'].includes(name)) {
options.listall = true
}
postApi(param.list, options).then((response) => {
param.loading = false
_.map(response, (responseItem, responseKey) => {
if (Object.keys(responseItem).length === 0) {
this.rowCount[name] = 0
this.options[name] = []
return
}
if (!responseKey.includes('response')) {
return
}
_.map(responseItem, (response, key) => {
if (key === 'count') {
this.rowCount[name] = response
return
}
if (!responseKey.includes('response')) {
return resolve(null)

View File

@ -549,7 +549,7 @@
@change="val => { dynamicscalingenabled = val }"/>
</a-form-item>
</a-form-item>
<a-form-item :label="$t('label.userdata')">
<a-form-item :label="$t('label.user.data')">
<a-card>
<div v-if="this.template && this.template.userdataid">
<a-typography-text>
@ -603,11 +603,11 @@
</div><br/><br/>
<div v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE' || userdataDefaultOverridePolicy === 'APPEND' || !userdataDefaultOverridePolicy">
<span v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE'" >
{{ $t('label.userdata.do.override') }}
{{ $t('label.user.data.do.override') }}
<a-switch v-model:checked="doUserdataOverride" style="margin-left: 10px"/>
</span>
<span v-if="userdataDefaultOverridePolicy === 'APPEND'">
{{ $t('label.userdata.do.append') }}
{{ $t('label.user.data.do.append') }}
<a-switch v-model:checked="doUserdataAppend" style="margin-left: 10px"/>
</span>
<a-step
@ -952,8 +952,7 @@ export default {
keyboards: [],
bootTypes: [],
bootModes: [],
ioPolicyTypes: [],
dynamicScalingVmConfig: false
ioPolicyTypes: []
},
rowCount: {},
loading: {
@ -1011,11 +1010,11 @@ export default {
userDataValues: {},
templateUserDataCols: [
{
title: this.$t('label.userdata'),
title: this.$t('label.user.data'),
dataIndex: 'userdata'
},
{
title: this.$t('label.userdatapolicy'),
title: this.$t('label.user.data.policy'),
dataIndex: 'userdataoverridepolicy'
}
],
@ -1290,16 +1289,17 @@ export default {
}]
},
userdataTabList () {
return [
{
key: 'userdataregistered',
tab: this.$t('label.userdata.registered')
},
{
key: 'userdatatext',
tab: this.$t('label.userdata.text')
}
]
let tabList = []
tabList = [{
key: 'userdataregistered',
tab: this.$t('label.user.data.registered')
},
{
key: 'userdatatext',
tab: this.$t('label.user.data.text')
}]
return tabList
},
showVnfNicsSection () {
return this.networks && this.networks.length > 0 && this.vm.templateid && this.templateVnfNics && this.templateVnfNics.length > 0
@ -1330,7 +1330,7 @@ export default {
return Boolean('listUserData' in this.$store.getters.apis)
},
dynamicScalingVmConfigValue () {
return this.options.dynamicScalingVmConfig?.[0]?.value === 'true'
return this.$store.getters.features.dynamicscalingenabled
},
isCustomizedDiskIOPS () {
return this.diskSelected?.iscustomizediops || false
@ -2471,20 +2471,29 @@ export default {
if (exclude && exclude.length > 0 && exclude.includes(name)) {
return resolve(null)
}
this.loading[name] = true
param.loading = true
param.opts = []
const options = param.options || {}
if (!('listall' in options) && !['zones', 'pods', 'clusters', 'hosts', 'dynamicScalingVmConfig', 'hypervisors'].includes(name)) {
options.listall = true
}
postAPI(param.list, options).then((response) => {
param.loading = false
_.map(response, (responseItem, responseKey) => {
if (Object.keys(responseItem).length === 0) {
this.rowCount[name] = 0
this.options[name] = []
return resolve(null)
}
this.loading[name] = true
param.loading = true
param.opts = []
const options = param.options || {}
if (!('listall' in options) && !['zones', 'pods', 'clusters', 'hosts', 'hypervisors'].includes(name)) {
options.listall = true
}
postApi(param.list, options).then((response) => {
param.loading = false
_.map(response, (responseItem, responseKey) => {
if (Object.keys(responseItem).length === 0) {
this.rowCount[name] = 0
this.options[name] = []
return
}
if (!responseKey.includes('response')) {
return
}
_.map(responseItem, (response, key) => {
if (key === 'count') {
this.rowCount[name] = response
return
}
if (!responseKey.includes('response')) {
return resolve(null)

View File

@ -86,7 +86,7 @@
</a-form-item>
<a-form-item v-if="userDataEnabled">
<template #label>
<tooltip-label :title="$t('label.userdata')" :tooltip="apiParams.userdata.description"/>
<tooltip-label :title="$t('label.user.data')" :tooltip="apiParams.userdata.description"/>
</template>
<a-textarea v-model:value="form.userdata">
</a-textarea>
@ -180,7 +180,6 @@ export default {
template: {},
userDataEnabled: false,
securityGroupsEnabled: false,
dynamicScalingVmConfig: false,
loading: false,
securitygroups: {
loading: false,
@ -239,7 +238,6 @@ export default {
this.fetchInstaceGroups()
this.fetchServiceOfferingData()
this.fetchTemplateData()
this.fetchDynamicScalingVmConfig()
this.fetchUserData()
},
fetchZoneDetails () {
@ -304,6 +302,9 @@ export default {
canDynamicScalingEnabled () {
return this.template.isdynamicallyscalable && this.serviceOffering.dynamicscalingenabled && this.dynamicScalingVmConfig
},
isDynamicScalingEnabled () {
return this.template.isdynamicallyscalable && this.serviceOffering.dynamicscalingenabled && this.$store.getters.features.dynamicscalingenabled
},
fetchOsTypes () {
this.osTypes.loading = true
this.osTypes.opts = []

View File

@ -35,26 +35,22 @@
:placeholder="apiParams.name.description"
v-focus="true" />
</a-form-item>
<div v-if="$route.name === 'userdata'">
<a-form-item name="userdata" ref="userdata">
<template #label>
<tooltip-label :title="$t('label.userdata')" :tooltip="apiParams.userdata.description"/>
</template>
<a-textarea
v-model:value="form.userdata"
:placeholder="apiParams.userdata.description"/>
</a-form-item>
</div>
<div v-else>
<a-form-item name="cniconfig" ref="cniconfig">
<template #label>
<tooltip-label :title="$t('label.cniconfiguration')" :tooltip="apiParams.cniconfig.description"/>
</template>
<a-textarea
v-model:value="form.cniconfig"
:placeholder="apiParams.cniconfig.description"/>
</a-form-item>
</div>
<a-form-item name="userdata" ref="userdata">
<template #label>
<tooltip-label :title="$t('label.user.data')" :tooltip="$t('label.register.user.data.details')"/>
</template>
<a-textarea
v-model:value="form.userdata"
:placeholder="$t('label.register.user.data.details')"/>
</a-form-item>
<a-form-item name="cniconfig" ref="cniconfig">
<template #label>
<tooltip-label :title="$t('label.cniconfiguration')" :tooltip="apiParams.cniconfig.description"/>
</template>
<a-textarea
v-model:value="form.cniconfig"
:placeholder="apiParams.cniconfig.description"/>
</a-form-item>
<a-form-item name="isbase64" ref="isbase64" :label="$t('label.is.base64.encoded')">
<a-checkbox v-model:checked="form.isbase64"></a-checkbox>
</a-form-item>
@ -63,6 +59,7 @@
<tooltip-label
:title="$route.name === 'userdata' ? $t('label.userdataparams') : $t('label.cniconfigparams')"
:tooltip="apiParams.params.description"/>
<tooltip-label :title="$t('label.user.data.params')" :tooltip="apiParams.params.description"/>
</template>
<a-select
mode="tags"
@ -169,7 +166,7 @@ export default {
})
this.rules = reactive({
name: [{ required: true, message: this.$t('message.error.name') }],
userdata: [{ required: true, message: this.$t('message.error.userdata') }]
userdata: [{ required: true, message: this.$t('message.error.user.data') }]
})
},
fetchData () {

View File

@ -52,11 +52,11 @@
</div>
<div v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE' || userdataDefaultOverridePolicy === 'APPEND' || !userdataDefaultOverridePolicy">
<span v-if="userdataDefaultOverridePolicy === 'ALLOWOVERRIDE'" >
{{ $t('label.userdata.do.override') }}
{{ $t('label.user.data.do.override') }}
<a-switch v-model:checked="doUserdataOverride" style="margin-left: 10px"/>
</span>
<span v-if="userdataDefaultOverridePolicy === 'APPEND'">
{{ $t('label.userdata.do.append') }}
{{ $t('label.user.data.do.append') }}
<a-switch v-model:checked="doUserdataAppend" style="margin-left: 10px"/>
</span>
<a-step>
@ -198,11 +198,11 @@ export default {
userDataValues: {},
templateUserDataCols: [
{
title: this.$t('label.userdata'),
title: this.$t('label.user.data'),
dataIndex: 'userdata'
},
{
title: this.$t('label.userdatapolicy'),
title: this.$t('label.user.data.policy'),
dataIndex: 'userdataoverridepolicy'
}
],
@ -282,11 +282,11 @@ export default {
loadUserdataTabList () {
this.userdataTabList = [{
key: 'userdataregistered',
tab: this.$t('label.userdata.registered')
tab: this.$t('label.user.data.registered')
},
{
key: 'userdatatext',
tab: this.$t('label.userdata.text')
tab: this.$t('label.user.data.text')
}]
},
onUserdataTabChange (key, type) {
@ -365,7 +365,7 @@ export default {
postAPI(resetUserDataApiName, params).then(json => {
this.$message.success({
content: `${this.$t('label.action.userdata.reset')} - ${this.$t('label.success')}`,
content: `${this.$t('label.action.user.data.reset')} - ${this.$t('label.success')}`,
duration: 2
})
this.$emit('refresh-data')

View File

@ -34,7 +34,7 @@
:scroll="{ y: 225 }"
>
<template #headerCell="{ column }">
<template v-if="column.key === 'name'"><solution-outlined /> {{ $t('label.userdata') }}</template>
<template v-if="column.key === 'name'"><solution-outlined /> {{ $t('label.user.data') }}</template>
<template v-if="column.key === 'AS_NUMBER'"><user-outlined /> {{ $t('label.account') }}</template>
<template v-if="column.key === 'account'"><user-outlined /> {{ $t('label.account') }}</template>
<template v-if="column.key === 'domain'"><block-outlined /> {{ $t('label.domain') }}</template>
@ -87,7 +87,7 @@ export default {
{
key: 'name',
dataIndex: 'name',
title: this.$t('label.userdata'),
title: this.$t('label.user.data'),
width: '40%'
},
{

View File

@ -218,7 +218,7 @@
name="userdataid"
ref="userdataid">
<template #label>
<tooltip-label :title="$t('label.userdata')" :tooltip="linkUserDataParams.userdataid.description"/>
<tooltip-label :title="$t('label.user.data')" :tooltip="linkUserDataParams.userdataid.description"/>
</template>
<a-select
showSearch
@ -238,7 +238,7 @@
<a-col :md="24" :lg="12">
<a-form-item ref="userdatapolicy" name="userdatapolicy">
<template #label>
<tooltip-label :title="$t('label.userdatapolicy')" :tooltip="linkUserDataParams.userdatapolicy.description"/>
<tooltip-label :title="$t('label.user.data.policy')" :tooltip="linkUserDataParams.userdatapolicy.description"/>
</template>
<a-select
showSearch

View File

@ -377,7 +377,7 @@
name="userdataid"
ref="userdataid">
<template #label>
<tooltip-label :title="$t('label.userdata')" :tooltip="linkUserDataParams.userdataid.description"/>
<tooltip-label :title="$t('label.user.data')" :tooltip="linkUserDataParams.userdataid.description"/>
</template>
<a-select
showSearch
@ -397,7 +397,7 @@
<a-col :md="24" :lg="12">
<a-form-item ref="userdatapolicy" name="userdatapolicy">
<template #label>
<tooltip-label :title="$t('label.userdatapolicy')" :tooltip="linkUserDataParams.userdatapolicy.description"/>
<tooltip-label :title="$t('label.user.data.policy')" :tooltip="linkUserDataParams.userdatapolicy.description"/>
</template>
<a-select
showSearch

View File

@ -86,7 +86,7 @@
<a-form-item
name="userdataid"
ref="userdataid"
:label="$t('label.userdata')">
:label="$t('label.user.data')">
<a-select
showSearch
optionFilterProp="label"
@ -105,7 +105,7 @@
<a-col :md="24" :lg="12">
<a-form-item ref="userdatapolicy" name="userdatapolicy">
<template #label>
<tooltip-label :title="$t('label.userdatapolicy')" :tooltip="$t('label.userdatapolicy.tooltip')"/>
<tooltip-label :title="$t('label.user.data.policy')" :tooltip="$t('label.user.data.policy.tooltip')"/>
</template>
<a-select
showSearch

View File

@ -117,7 +117,7 @@
<a-form-item
name="userdataid"
ref="userdataid"
:label="$t('label.userdata')">
:label="$t('label.user.data')">
<a-select
showSearch
optionFilterProp="label"
@ -136,7 +136,7 @@
<a-col :md="24" :lg="12">
<a-form-item ref="userdatapolicy" name="userdatapolicy">
<template #label>
<tooltip-label :title="$t('label.userdatapolicy')" :tooltip="$t('label.userdatapolicy.tooltip')"/>
<tooltip-label :title="$t('label.user.data.policy')" :tooltip="$t('label.user.data.policy.tooltip')"/>
</template>
<a-select
showSearch

View File

@ -1118,7 +1118,7 @@ export default {
],
lists: [
{
title: 'label.nsx.controller',
title: 'label.nsx.provider',
api: 'listNsxControllers',
mapping: {
zoneid: {

Some files were not shown because too many files have changed in this diff Show More