mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 01:32:18 +02:00
Merge branch '4.20'
This commit is contained in:
commit
bcafbd1649
@ -87,6 +87,8 @@ public interface AccountService {
|
||||
|
||||
boolean isDomainAdmin(Long accountId);
|
||||
|
||||
boolean isResourceDomainAdmin(Long accountId);
|
||||
|
||||
boolean isNormalUser(long accountId);
|
||||
|
||||
User getActiveUserByRegistrationToken(String registrationToken);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 + "]";
|
||||
}
|
||||
|
||||
@ -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 + "]";
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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, "");
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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/")) {
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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());
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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+",""));
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -21,3 +21,4 @@ consoleproxy.httpCmdListenPort=8001
|
||||
consoleproxy.jarDir=./applet/
|
||||
consoleproxy.viewerLinger=180
|
||||
consoleproxy.reconnectMaxRetry=5
|
||||
consoleproxy.defaultBufferSize=65536
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
}
|
||||
|
||||
@ -82,6 +82,7 @@ HTTP
|
||||
enable_fwding 0
|
||||
enable_irqbalance 0
|
||||
setup_ntp
|
||||
systemctl restart ntp
|
||||
|
||||
rm -f /etc/logrotate.d/cloud
|
||||
}
|
||||
|
||||
@ -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
|
||||
"""
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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!",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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コントローラーを削除してもよろしいですか?",
|
||||
|
||||
@ -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.",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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') {
|
||||
|
||||
@ -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: {
|
||||
|
||||
@ -55,7 +55,7 @@ export default {
|
||||
param: 'account'
|
||||
}, {
|
||||
name: 'userdata',
|
||||
title: 'label.userdata',
|
||||
title: 'label.user.data',
|
||||
param: 'account'
|
||||
}, {
|
||||
name: 'template',
|
||||
|
||||
@ -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')))
|
||||
|
||||
@ -48,6 +48,11 @@ export default {
|
||||
name: 'template',
|
||||
title: 'label.templates',
|
||||
param: 'domainid'
|
||||
},
|
||||
{
|
||||
name: 'iso',
|
||||
title: 'label.isos',
|
||||
param: 'domainid'
|
||||
}],
|
||||
tabs: [
|
||||
{
|
||||
|
||||
@ -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
|
||||
}
|
||||
]
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
},
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 = []
|
||||
|
||||
@ -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 () {
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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%'
|
||||
},
|
||||
{
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user