diff --git a/api/src/main/java/com/cloud/user/AccountService.java b/api/src/main/java/com/cloud/user/AccountService.java index e2c3bed0c29..c0ebcf09f59 100644 --- a/api/src/main/java/com/cloud/user/AccountService.java +++ b/api/src/main/java/com/cloud/user/AccountService.java @@ -87,6 +87,8 @@ public interface AccountService { boolean isDomainAdmin(Long accountId); + boolean isResourceDomainAdmin(Long accountId); + boolean isNormalUser(long accountId); User getActiveUserByRegistrationToken(String registrationToken); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java index 65dd1b232fa..b38278e3946 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java @@ -190,7 +190,7 @@ public class ListClustersCmd extends BaseListCmd { @Override public void execute() { Pair, Integer> clusterResponses = getClusterResponses(); - ListResponse response = new ListResponse(); + ListResponse response = new ListResponse<>(); response.setResponses(clusterResponses.first(), clusterResponses.second()); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java index ca5635d4fe4..264e5263c4d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/pod/ListPodsByCmd.java @@ -103,8 +103,8 @@ public class ListPodsByCmd extends BaseListCmd { @Override public void execute() { Pair, Integer> result = _mgr.searchForPods(this); - ListResponse response = new ListResponse(); - List podResponses = new ArrayList(); + ListResponse response = new ListResponse<>(); + List podResponses = new ArrayList<>(); for (Pod pod : result.first()) { PodResponse podResponse = _responseGenerator.createPodResponse(pod, showCapacities); podResponse.setObjectName("pod"); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java index 91632b910ff..e73bb97a21b 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java @@ -74,6 +74,7 @@ public class ListCapabilitiesCmd extends BaseCmd { response.setSharedFsVmMinRamSize((Integer)capabilities.get(ApiConstants.SHAREDFSVM_MIN_RAM_SIZE)); response.setInstanceLeaseEnabled((Boolean) capabilities.get(ApiConstants.INSTANCE_LEASE_ENABLED)); response.setExtensionsPath((String)capabilities.get(ApiConstants.EXTENSIONS_PATH)); + response.setDynamicScalingEnabled((Boolean) capabilities.get(ApiConstants.DYNAMIC_SCALING_ENABLED)); response.setObjectName("capability"); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java index 0a7bf291843..5f09ac6698d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import com.cloud.cpu.CPU; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandResourceType; @@ -148,6 +149,11 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd { since = "4.19.0") private String accountName; + @Parameter(name = ApiConstants.ARCH, type = CommandType.STRING, + description = "the CPU arch of the template. Valid options are: x86_64, aarch64. Defaults to x86_64", + since = "4.20.2") + private String arch; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -234,6 +240,10 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd { return accountName; } + public CPU.CPUArch getArch() { + return CPU.CPUArch.fromType(arch); + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java index fabf8827796..2603209c540 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/userdata/RegisterUserDataCmd.java @@ -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; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java index a5e26f30dfb..36ce23cbc6e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/zone/ListZonesCmd.java @@ -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 response = _queryService.listDataCenters(this); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java index b0a82c86fb5..eb0daf75148 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java @@ -145,6 +145,10 @@ public class CapabilitiesResponse extends BaseResponse { @Param(description = "The path of the extensions directory", since = "4.21.0", authorized = {RoleType.Admin}) private String extensionsPath; + @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; } @@ -264,4 +268,8 @@ public class CapabilitiesResponse extends BaseResponse { public void setExtensionsPath(String extensionsPath) { this.extensionsPath = extensionsPath; } + + public void setDynamicScalingEnabled(Boolean dynamicScalingEnabled) { + this.dynamicScalingEnabled = dynamicScalingEnabled; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java index 2dfc66fa7d5..ce344596aeb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UserDataResponse.java @@ -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() { diff --git a/api/src/main/java/org/apache/cloudstack/query/QueryService.java b/api/src/main/java/org/apache/cloudstack/query/QueryService.java index 4278c9217b5..6a20c2fa248 100644 --- a/api/src/main/java/org/apache/cloudstack/query/QueryService.java +++ b/api/src/main/java/org/apache/cloudstack/query/QueryService.java @@ -114,11 +114,11 @@ public interface QueryService { ConfigKey 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 UserVMDeniedDetails = new ConfigKey<>(String.class, + ConfigKey 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 UserVMReadOnlyDetails = new ConfigKey<>(String.class, + ConfigKey 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 AllowUserViewAllDomainAccounts = new ConfigKey<>("Advanced", Boolean.class, + ConfigKey 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 SharePublicTemplatesWithOtherDomains = new ConfigKey<>("Advanced", Boolean.class, "share.public.templates.with.other.domains", "true", + ConfigKey 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 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 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 searchForUsers(ResponseObject.ResponseView responseView, ListUsersCmd cmd) throws PermissionDeniedException; ListResponse searchForUsers(Long domainId, boolean recursive) throws PermissionDeniedException; diff --git a/core/src/main/java/com/cloud/agent/api/CheckVolumeAnswer.java b/core/src/main/java/com/cloud/agent/api/CheckVolumeAnswer.java index 5a32ab59a7a..07b7e102df9 100644 --- a/core/src/main/java/com/cloud/agent/api/CheckVolumeAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/CheckVolumeAnswer.java @@ -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 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 volumeDetails) { + super(cmd, success, details); this.size = size; + this.volumeDetails = volumeDetails; } public long getSize() { return size; } + public Map getVolumeDetails() { + return volumeDetails; + } + public String getString() { return "CheckVolumeAnswer [size=" + size + "]"; } diff --git a/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeAnswer.java b/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeAnswer.java index e79005be71b..4aec0b26581 100644 --- a/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeAnswer.java +++ b/core/src/main/java/com/cloud/agent/api/CopyRemoteVolumeAnswer.java @@ -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 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 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 getVolumeDetails() { + return volumeDetails; + } + public String getString() { return "CopyRemoteVolumeAnswer [remoteIp=" + remoteIp + "]"; } diff --git a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java index f8032bf4b0e..76f0830f369 100644 --- a/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java +++ b/engine/api/src/main/java/com/cloud/vm/VirtualMachineGuru.java @@ -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 NTPServerConfig = new ConfigKey(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); /** diff --git a/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDao.java b/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDao.java index 718511746c2..9775f8ad5b1 100644 --- a/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDao.java +++ b/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDao.java @@ -37,4 +37,6 @@ public interface AutoScaleVmGroupVmMapDao extends GenericDao vmIds, Long batchSize); + + int getErroredInstanceCount(long vmGroupId); } diff --git a/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDaoImpl.java b/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDaoImpl.java index 1ae55d97da2..b2f4e578a82 100644 --- a/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/network/as/dao/AutoScaleVmGroupVmMapDaoImpl.java @@ -127,4 +127,13 @@ public class AutoScaleVmGroupVmMapDaoImpl extends GenericDaoBase sc = CountBy.create(); + sc.setParameters("vmGroupId", vmGroupId); + sc.setJoinParameters("vmSearch", "states", State.Error); + final List results = customSearch(sc, null); + return results.get(0); + } } diff --git a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java index 654d68ec6f1..f73d82d87c4 100644 --- a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java +++ b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java @@ -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 vmVolumes = volumeDao.findByInstance(vm.getId()); + vmVolumes.sort(Comparator.comparing(Volume::getDeviceId)); List 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 backedVolumes = backup.getBackedUpVolumes(); - List volumes = backedVolumes.stream().map(volume -> volumeDao.findByUuid(volume.getUuid())).collect(Collectors.toList()); + List 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())); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 3a6512cd01c..14fa2b080d0 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -3731,7 +3731,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv if (!meetRequirements) { return false; } - return isUbuntuHost() || isIoUringSupportedByQemu(); + return isUbuntuOrDebianHost() || isIoUringSupportedByQemu(); } /** @@ -3744,13 +3744,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 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) { @@ -5838,14 +5839,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; } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckConvertInstanceCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckConvertInstanceCommandWrapper.java index d3ebb28b106..b94b4830003 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckConvertInstanceCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCheckConvertInstanceCommandWrapper.java @@ -32,7 +32,7 @@ public class LibvirtCheckConvertInstanceCommandWrapper extends CommandWrapper { + private static final List 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 getVolumeDetails(KVMStoragePool pool, KVMPhysicalDisk disk) { + Map info = getDiskFileInfo(pool, disk, true); + if (MapUtils.isEmpty(info)) { + return null; + } + + Map 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 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 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 info = getDiskFileInfo(pool, disk, false); + return info == null; + } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java index e79a8da9dda..abc408f20f6 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapper.java @@ -60,7 +60,7 @@ public class LibvirtConvertInstanceCommandWrapper extends CommandWrapper { + private static final List 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 getVolumeDetails(KVMStoragePool pool, KVMPhysicalDisk disk) { + Map info = getDiskFileInfo(pool, disk, true); + if (MapUtils.isEmpty(info)) { + return null; + } + + Map 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 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 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 info = getDiskFileInfo(pool, disk, false); + return info == null; + } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVolumesOnStorageCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVolumesOnStorageCommandWrapper.java index 0f0c6488bb3..6d918435277 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVolumesOnStorageCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVolumesOnStorageCommandWrapper.java @@ -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 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 volumes = new ArrayList<>(); @@ -134,11 +144,21 @@ public final class LibvirtGetVolumesOnStorageCommandWrapper extends CommandWrapp if (!isDiskFormatSupported(disk)) { continue; } + Map 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); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReadyCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReadyCommandWrapper.java index 485254c6bb9..e74923b281f 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReadyCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtReadyCommandWrapper.java @@ -43,7 +43,7 @@ public final class LibvirtReadyCommandWrapper extends CommandWrapper hostDetails = new HashMap(); - 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 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, ""); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java index 2810f98c935..8abc359250c 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtRestoreBackupCommandWrapper.java @@ -62,16 +62,25 @@ public class LibvirtRestoreBackupCommandWrapper extends CommandWrapper(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 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 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 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(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) { diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMPhysicalDisk.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMPhysicalDisk.java index ab02e16603d..8a9d69c9795 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMPhysicalDisk.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMPhysicalDisk.java @@ -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 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; diff --git a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java index d30d7b2f74d..bc9dbfa7b43 100644 --- a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java +++ b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java @@ -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 diff --git a/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java b/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java index ef3d98354a0..a625761ec28 100644 --- a/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java +++ b/plugins/storage/sharedfs/storagevm/src/main/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycle.java @@ -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 volumes = volumeDao.findByInstanceAndType(vm.getId(), Volume.Type.DATADISK); - return new Pair<>(volumes.get(0).getId(), vm.getId()); + List 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 diff --git a/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java b/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java index 813d8978697..21753257f75 100644 --- a/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java +++ b/plugins/storage/sharedfs/storagevm/src/test/java/org/apache/cloudstack/storage/sharedfs/lifecycle/StorageVmSharedFSLifeCycleTest.java @@ -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 result = lifeCycle.deploySharedFS(sharedFS, s_networkId, s_diskOfferingId, s_size, s_minIops, s_maxIops); Assert.assertEquals(Optional.ofNullable(result.first()), Optional.ofNullable(s_volumeId)); diff --git a/plugins/storage/volume/linstor/CHANGELOG.md b/plugins/storage/volume/linstor/CHANGELOG.md index 2abda3ebc50..a96b7c75b2b 100644 --- a/plugins/storage/volume/linstor/CHANGELOG.md +++ b/plugins/storage/volume/linstor/CHANGELOG.md @@ -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 diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index ba4a7b14787..28928570732 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -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) { diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java index 574e5ddcfea..a0999090355 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java @@ -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> 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 { diff --git a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java index e60724c7025..d68d34ce1c0 100644 --- a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java +++ b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java @@ -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 diff --git a/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java b/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java index 921dd3d4d9f..610b595ee05 100644 --- a/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java +++ b/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java @@ -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), diff --git a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java index f6cc3c1e216..fdccd76b709 100644 --- a/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java +++ b/plugins/storage/volume/storpool/src/main/java/com/cloud/hypervisor/kvm/storage/StorPoolStorageAdaptor.java @@ -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/")) { diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapListUsersCmd.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapListUsersCmd.java index e5d434d3810..6bfc70ea139 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapListUsersCmd.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/api/command/LdapListUsersCmd.java @@ -140,10 +140,11 @@ public class LdapListUsersCmd extends BaseListCmd { try { final List 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(); + logger.debug(ex.getMessage()); + // ok, we'll make do with the empty list } finally { response.setResponses(ldapResponses); response.setResponseName(getCommandName()); diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapAuthenticator.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapAuthenticator.java index b8509881594..36c663566cb 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapAuthenticator.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapAuthenticator.java @@ -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 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 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 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 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 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 processResultAndAction(UserAccount user, boolean result) { - return (!result && user != null) ? + private Pair processResultAndAction(UserAccount user, boolean result, boolean timedOut) { + return (!result && (user != null || timedOut)) ? new Pair(result, ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT): new Pair(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()); } } diff --git a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java index 2394c0b3d1e..05b8578bb42 100644 --- a/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java +++ b/plugins/user-authenticators/ldap/src/main/java/org/apache/cloudstack/ldap/LdapManagerImpl.java @@ -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()); diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 1643c1962ce..59e37c9f4df 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -29,6 +29,7 @@ import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; @@ -169,13 +170,13 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.vm.lease.VMLeaseManager; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Component; import com.cloud.api.query.dao.AccountJoinDao; @@ -204,6 +205,7 @@ import com.cloud.api.query.dao.VolumeJoinDao; import com.cloud.api.query.vo.AccountJoinVO; import com.cloud.api.query.vo.AffinityGroupJoinVO; import com.cloud.api.query.vo.AsyncJobJoinVO; +import com.cloud.api.query.vo.BaseViewWithTagInformationVO; import com.cloud.api.query.vo.DataCenterJoinVO; import com.cloud.api.query.vo.DiskOfferingJoinVO; import com.cloud.api.query.vo.DomainJoinVO; @@ -260,7 +262,6 @@ import com.cloud.network.RouterHealthCheckResult; import com.cloud.network.VNF; import com.cloud.network.VpcVirtualNetworkApplianceService; import com.cloud.network.as.AutoScaleVmGroupVmMapVO; -import com.cloud.network.as.dao.AutoScaleVmGroupDao; import com.cloud.network.as.dao.AutoScaleVmGroupVmMapDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; @@ -305,7 +306,6 @@ import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; -import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolHostVO; import com.cloud.storage.StoragePoolStatus; @@ -322,7 +322,6 @@ import com.cloud.storage.dao.StoragePoolAndAccessGroupMapDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.StoragePoolTagsDao; import com.cloud.storage.dao.VMTemplateDao; -import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.storage.dao.VMTemplatePoolDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.tags.ResourceTagVO; @@ -543,9 +542,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Inject ProjectInvitationDao projectInvitationDao; - @Inject - TemplateDataStoreDao templateDataStoreDao; - @Inject VMTemplatePoolDao templatePoolDao; @@ -563,8 +559,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Inject ResourceIconDao resourceIconDao; - @Inject - StorageManager storageManager; @Inject ManagementServerHostDao msHostDao; @@ -602,9 +596,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Inject BackupOfferingDao backupOfferingDao; - @Inject - AutoScaleVmGroupDao autoScaleVmGroupDao; - @Inject AutoScaleVmGroupVmMapDao autoScaleVmGroupVmMapDao; @@ -634,8 +625,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Inject private AsyncJobManager jobManager; - @Inject - private VMTemplateDetailsDao templateDetailsDao; @Inject private StoragePoolAndAccessGroupMapDao storagePoolAndAccessGroupMapDao; @@ -655,45 +644,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Inject ExtensionHelper extensionHelper; - private SearchCriteria getMinimumCpuServiceOfferingJoinSearchCriteria(int cpu) { - SearchCriteria sc = _srvOfferingJoinDao.createSearchCriteria(); - SearchCriteria sc1 = _srvOfferingJoinDao.createSearchCriteria(); - sc1.addAnd("cpu", Op.GTEQ, cpu); - sc.addOr("cpu", Op.SC, sc1); - SearchCriteria sc2 = _srvOfferingJoinDao.createSearchCriteria(); - sc2.addAnd("cpu", Op.NULL); - sc2.addAnd("maxCpu", Op.NULL); - sc.addOr("cpu", Op.SC, sc2); - SearchCriteria sc3 = _srvOfferingJoinDao.createSearchCriteria(); - sc3.addAnd("cpu", Op.NULL); - sc3.addAnd("maxCpu", Op.GTEQ, cpu); - sc.addOr("cpu", Op.SC, sc3); - return sc; - } - - private SearchCriteria getMinimumMemoryServiceOfferingJoinSearchCriteria(int memory) { - SearchCriteria sc = _srvOfferingJoinDao.createSearchCriteria(); - SearchCriteria sc1 = _srvOfferingJoinDao.createSearchCriteria(); - sc1.addAnd("ramSize", Op.GTEQ, memory); - sc.addOr("ramSize", Op.SC, sc1); - SearchCriteria sc2 = _srvOfferingJoinDao.createSearchCriteria(); - sc2.addAnd("ramSize", Op.NULL); - sc2.addAnd("maxMemory", Op.NULL); - sc.addOr("ramSize", Op.SC, sc2); - SearchCriteria sc3 = _srvOfferingJoinDao.createSearchCriteria(); - sc3.addAnd("ramSize", Op.NULL); - sc3.addAnd("maxMemory", Op.GTEQ, memory); - sc.addOr("ramSize", Op.SC, sc3); - return sc; - } - - private SearchCriteria getMinimumCpuSpeedServiceOfferingJoinSearchCriteria(int speed) { - SearchCriteria sc = _srvOfferingJoinDao.createSearchCriteria(); - sc.addOr("speed", Op.GTEQ, speed); - sc.addOr("speed", Op.NULL); - return sc; - } - /* * (non-Javadoc) * @@ -709,7 +659,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q responseView = ResponseView.Full; } List userResponses = ViewResponseHelper.createUserResponse(responseView, CallContext.current().getCallingAccount().getDomainId(), - result.first().toArray(new UserAccountJoinVO[result.first().size()])); + result.first().toArray(new UserAccountJoinVO[0])); response.setResponses(userResponses, result.second()); return response; } @@ -717,17 +667,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse searchForUsers(Long domainId, boolean recursive) throws PermissionDeniedException { Account caller = CallContext.current().getCallingAccount(); - List permittedAccounts = new ArrayList(); + List permittedAccounts = new ArrayList<>(); boolean listAll = true; Long id = null; if (caller.getType() == Account.Type.NORMAL) { - long currentId = CallContext.current().getCallingUser().getId(); - if (id != null && currentId != id.longValue()) { - throw new PermissionDeniedException("Calling user is not authorized to see the user requested by id"); - } - id = currentId; + id = CallContext.current().getCallingUser().getId(); } Object username = null; Object type = null; @@ -737,9 +683,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = getUserListInternal(caller, permittedAccounts, listAll, id, username, type, accountName, state, keyword, null, domainId, recursive, null, null); - ListResponse response = new ListResponse(); + ListResponse response = new ListResponse<>(); List userResponses = ViewResponseHelper.createUserResponse(ResponseView.Restricted, CallContext.current().getCallingAccount().getDomainId(), - result.first().toArray(new UserAccountJoinVO[result.first().size()])); + result.first().toArray(new UserAccountJoinVO[0])); response.setResponses(userResponses, result.second()); return response; } @@ -747,13 +693,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private Pair, Integer> searchForUsersInternal(ListUsersCmd cmd) throws PermissionDeniedException { Account caller = CallContext.current().getCallingAccount(); - List permittedAccounts = new ArrayList(); + List permittedAccounts = new ArrayList<>(); boolean listAll = cmd.listAll(); Long id = cmd.getId(); if (caller.getType() == Account.Type.NORMAL) { long currentId = CallContext.current().getCallingUser().getId(); - if (id != null && currentId != id.longValue()) { + if (id != null && currentId != id) { throw new PermissionDeniedException("Calling user is not authorized to see the user requested by id"); } id = currentId; @@ -778,7 +724,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private Pair, Integer> getUserListInternal(Account caller, List permittedAccounts, boolean listAll, Long id, Object username, Object type, String accountName, Object state, String keyword, String apiKeyAccess, Long domainId, boolean recursive, Filter searchFilter, User.Source userSource) { - Ternary domainIdRecursiveListProject = new Ternary(domainId, recursive, null); + Ternary domainIdRecursiveListProject = new Ternary<>(domainId, recursive, null); accountMgr.buildACLSearchParameters(caller, id, accountName, null, permittedAccounts, domainIdRecursiveListProject, listAll, false); domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); @@ -789,8 +735,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q sb.and("username", sb.entity().getUsername(), Op.LIKE); if (id != null && id == 1) { // system user should NOT be searchable - List emptyList = new ArrayList(); - return new Pair, Integer>(emptyList, 0); + List emptyList = new ArrayList<>(); + return new Pair<>(emptyList, 0); } else if (id != null) { sb.and("id", sb.entity().getId(), Op.EQ); } else { @@ -881,7 +827,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse searchForEvents(ListEventsCmd cmd) { Pair, Integer> result = searchForEventsInternal(cmd); ListResponse response = new ListResponse<>(); - List eventResponses = ViewResponseHelper.createEventResponse(result.first().toArray(new EventJoinVO[result.first().size()])); + List eventResponses = ViewResponseHelper.createEventResponse(result.first().toArray(new EventJoinVO[0])); response.setResponses(eventResponses, result.second()); return response; } @@ -1081,7 +1027,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse listTags(ListTagsCmd cmd) { Pair, Integer> tags = listTagsInternal(cmd); ListResponse response = new ListResponse<>(); - List tagResponses = ViewResponseHelper.createResourceTagResponse(false, tags.first().toArray(new ResourceTagJoinVO[tags.first().size()])); + List tagResponses = ViewResponseHelper.createResourceTagResponse(false, tags.first().toArray(new ResourceTagJoinVO[0])); response.setResponses(tagResponses, tags.second()); return response; } @@ -1167,7 +1113,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse searchForVmGroups(ListVMGroupsCmd cmd) { Pair, Integer> groups = searchForVmGroupsInternal(cmd); ListResponse response = new ListResponse<>(); - List grpResponses = ViewResponseHelper.createInstanceGroupResponse(groups.first().toArray(new InstanceGroupJoinVO[groups.first().size()])); + List grpResponses = ViewResponseHelper.createInstanceGroupResponse(groups.first().toArray(new InstanceGroupJoinVO[0])); response.setResponses(grpResponses, groups.second()); return response; } @@ -1230,7 +1176,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q respView = ResponseView.Full; } List vmResponses = ViewResponseHelper.createUserVmResponse(respView, "virtualmachine", cmd.getDetails(), cmd.getAccumulate(), cmd.getShowUserData(), - result.first().toArray(new UserVmJoinVO[result.first().size()])); + result.first().toArray(new UserVmJoinVO[0])); response.setResponses(vmResponses, result.second()); return response; @@ -1515,11 +1461,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q resourceTagSearch.and().op(); for (int count = 0; count < tags.size(); count++) { if (count == 0) { - resourceTagSearch.op("tagKey" + String.valueOf(count), resourceTagSearch.entity().getKey(), Op.EQ); + resourceTagSearch.op("tagKey" + count, resourceTagSearch.entity().getKey(), Op.EQ); } else { - resourceTagSearch.or().op("tagKey" + String.valueOf(count), resourceTagSearch.entity().getKey(), Op.EQ); + resourceTagSearch.or().op("tagKey" + count, resourceTagSearch.entity().getKey(), Op.EQ); } - resourceTagSearch.and("tagValue" + String.valueOf(count), resourceTagSearch.entity().getValue(), Op.EQ); + resourceTagSearch.and("tagValue" + count, resourceTagSearch.entity().getValue(), Op.EQ); resourceTagSearch.cp(); } resourceTagSearch.cp(); @@ -1690,8 +1636,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q int count = 0; userVmSearchCriteria.setJoinParameters("tags","resourceType", ResourceObjectType.UserVm); for (Map.Entry entry : tags.entrySet()) { - userVmSearchCriteria.setJoinParameters("tags", "tagKey" + String.valueOf(count), entry.getKey()); - userVmSearchCriteria.setJoinParameters("tags", "tagValue" + String.valueOf(count), entry.getValue()); + userVmSearchCriteria.setJoinParameters("tags", "tagKey" + count, entry.getKey()); + userVmSearchCriteria.setJoinParameters("tags", "tagValue" + count, entry.getValue()); count++; } } @@ -1757,11 +1703,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q userVmSearchCriteria.setParameters("hostId", hostId); } - if (storageId != null && pool != null) { + if (storageId != null) { if (pool.getPoolType().equals(Storage.StoragePoolType.DatastoreCluster)) { List childDatastores = storagePoolDao.listChildStoragePoolsInDatastoreCluster(storageId); - List childDatastoreIds = childDatastores.stream().map(mo -> mo.getId()).collect(Collectors.toList()); - userVmSearchCriteria.setJoinParameters("volume", "storagePoolId", childDatastoreIds.toArray()); + userVmSearchCriteria.setJoinParameters("volume", "storagePoolId", childDatastores.stream().map(StoragePoolVO::getId).toArray()); } else { userVmSearchCriteria.setJoinParameters("volume", "storagePoolId", storageId); } @@ -1801,7 +1746,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q throw new InvalidParameterValueException("Unable to list network groups for virtual machine instance " + instanceId + "; instance not found."); } accountMgr.checkAccess(caller, null, true, userVM); - return listSecurityGroupRulesByVM(instanceId.longValue(), cmd.getStartIndex(), cmd.getPageSizeVal()); + return listSecurityGroupRulesByVM(instanceId, cmd.getStartIndex(), cmd.getPageSizeVal()); } Ternary domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null); @@ -1851,7 +1796,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q // search security group together with rules Pair, Integer> uniqueSgPair = _securityGroupJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueSgPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // handle empty result cases return uniqueSgPair; } @@ -1870,7 +1815,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Filter sf = new Filter(SecurityGroupVMMapVO.class, null, true, pageInd, pageSize); Pair, Integer> sgVmMappingPair = securityGroupVMMapDao.listByInstanceId(vmId, sf); Integer count = sgVmMappingPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // handle empty result cases return new Pair<>(new ArrayList<>(), count); } @@ -1889,7 +1834,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), cmd.getClusterId(), cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), cmd.getVersion(), cmd.isHealthCheckFailed()); ListResponse response = new ListResponse<>(); - List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); + List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[0])); if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { for (DomainRouterResponse res : routerResponses) { DomainRouterVO resRouter = _routerDao.findByUuid(res.getId()); @@ -1909,7 +1854,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = searchForRoutersInternal(cmd, cmd.getId(), cmd.getRouterName(), cmd.getState(), cmd.getZoneId(), cmd.getPodId(), null, cmd.getHostId(), cmd.getKeyword(), cmd.getNetworkId(), cmd.getVpcId(), cmd.getForVpc(), cmd.getRole(), null, null); ListResponse response = new ListResponse<>(); - List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[result.first().size()])); + List routerResponses = ViewResponseHelper.createDomainRouterResponse(result.first().toArray(new DomainRouterJoinVO[0])); if (VirtualNetworkApplianceManager.RouterHealthChecksEnabled.value()) { for (DomainRouterResponse res : routerResponses) { DomainRouterVO resRouter = _routerDao.findByUuid(res.getId()); @@ -2050,13 +1995,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } if (routersWithFailures != null && ! routersWithFailures.isEmpty()) { - sc.setParameters("routerId", routersWithFailures.toArray(new Object[routersWithFailures.size()])); + sc.setParameters("routerId", routersWithFailures.toArray(new Object[0])); } // search VR details by ids Pair, Integer> uniqueVrPair = _routerJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueVrPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // empty result return uniqueVrPair; } @@ -2074,7 +2019,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse listProjects(ListProjectsCmd cmd) { Pair, Integer> projects = listProjectsInternal(cmd); ListResponse response = new ListResponse<>(); - List projectResponses = ViewResponseHelper.createProjectResponse(cmd.getDetails(), projects.first().toArray(new ProjectJoinVO[projects.first().size()])); + List projectResponses = ViewResponseHelper.createProjectResponse(cmd.getDetails(), projects.first().toArray(new ProjectJoinVO[0])); response.setResponses(projectResponses, projects.second()); return response; } @@ -2230,7 +2175,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q // search distinct projects to get count Pair, Integer> uniquePrjPair = _projectJoinDao.searchAndCount(sc, searchFilter); Integer count = uniquePrjPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // handle empty result cases return uniquePrjPair; } @@ -2248,7 +2193,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse listProjectInvitations(ListProjectInvitationsCmd cmd) { Pair, Integer> invites = listProjectInvitationsInternal(cmd); ListResponse response = new ListResponse<>(); - List projectInvitationResponses = ViewResponseHelper.createProjectInvitationResponse(invites.first().toArray(new ProjectInvitationJoinVO[invites.first().size()])); + List projectInvitationResponses = ViewResponseHelper.createProjectInvitationResponse(invites.first().toArray(new ProjectInvitationJoinVO[0])); response.setResponses(projectInvitationResponses, invites.second()); return response; @@ -2324,7 +2269,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse listProjectAccounts(ListProjectAccountsCmd cmd) { Pair, Integer> projectAccounts = listProjectAccountsInternal(cmd); ListResponse response = new ListResponse<>(); - List projectResponses = ViewResponseHelper.createProjectAccountResponse(projectAccounts.first().toArray(new ProjectAccountJoinVO[projectAccounts.first().size()])); + List projectResponses = ViewResponseHelper.createProjectAccountResponse(projectAccounts.first().toArray(new ProjectAccountJoinVO[0])); response.setResponses(projectResponses, projectAccounts.second()); return response; } @@ -2418,7 +2363,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> hosts = searchForServersInternal(cmd); ListResponse response = new ListResponse<>(); logger.debug(">>>Generating Response>>>"); - List hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first().toArray(new HostJoinVO[hosts.first().size()])); + List hostResponses = ViewResponseHelper.createHostResponse(cmd.getDetails(), hosts.first().toArray(new HostJoinVO[0])); updateHostsExtensions(hostResponses); response.setResponses(hostResponses, hosts.second()); return response; @@ -2427,9 +2372,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private ListResponse searchForServersWithMinimalResponse(ListHostsCmd cmd) { logger.debug(">>>Searching for hosts>>>"); Pair, Integer> hosts = searchForServersInternal(cmd); - ListResponse response = new ListResponse(); + ListResponse response = new ListResponse<>(); logger.debug(">>>Generating Response>>>"); - List hostResponses = ViewResponseHelper.createMinimalHostResponse(hosts.first().toArray(new HostJoinVO[hosts.first().size()])); + List hostResponses = ViewResponseHelper.createMinimalHostResponse(hosts.first().toArray(new HostJoinVO[0])); response.setResponses(hostResponses, hosts.second()); return response; } @@ -2459,7 +2404,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Object outOfBandManagementEnabled = cmd.isOutOfBandManagementEnabled(); Object powerState = cmd.getHostOutOfBandManagementPowerState(); Object resourceState = cmd.getResourceState(); - Object haHosts = cmd.getHaHost(); + Boolean haHosts = cmd.getHaHost(); Long startIndex = cmd.getStartIndex(); Long pageSize = cmd.getPageSizeVal(); Hypervisor.HypervisorType hypervisorType = cmd.getHypervisor(); @@ -2509,7 +2454,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q String haTag = _haMgr.getHaTag(); if (haHosts != null && haTag != null && !haTag.isEmpty()) { SearchBuilder hostTagSearchBuilder = _hostTagDao.createSearchBuilder(); - if ((Boolean)haHosts) { + if (haHosts) { hostTagSearchBuilder.and("tag", hostTagSearchBuilder.entity().getTag(), SearchCriteria.Op.EQ); } else { hostTagSearchBuilder.and().op("tag", hostTagSearchBuilder.entity().getTag(), Op.NEQ); @@ -2610,7 +2555,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q respView = ResponseView.Full; } - List volumeResponses = ViewResponseHelper.createVolumeResponse(respView, result.first().toArray(new VolumeJoinVO[result.first().size()])); + List volumeResponses = ViewResponseHelper.createVolumeResponse(respView, result.first().toArray(new VolumeJoinVO[0])); for (VolumeResponse vr : volumeResponses) { String poolId = vr.getStoragePoolId(); @@ -2978,7 +2923,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q respView = ResponseView.Full; } - List accountResponses = ViewResponseHelper.createAccountResponse(respView, cmd.getDetails(), result.first().toArray(new AccountJoinVO[result.first().size()])); + List accountResponses = ViewResponseHelper.createAccountResponse(respView, cmd.getDetails(), result.first().toArray(new AccountJoinVO[0])); response.setResponses(accountResponses, result.second()); return response; } @@ -3158,7 +3103,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q public ListResponse searchForAsyncJobs(ListAsyncJobsCmd cmd) { Pair, Integer> result = searchForAsyncJobsInternal(cmd); ListResponse response = new ListResponse<>(); - List jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[result.first().size()])); + List jobResponses = ViewResponseHelper.createAsyncJobResponse(result.first().toArray(new AsyncJobJoinVO[0])); response.setResponses(jobResponses, result.second()); return response; } @@ -3275,7 +3220,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private ListResponse createStoragesPoolResponse(Pair, Integer> storagePools, boolean getCustomStats) { ListResponse response = new ListResponse<>(); - List poolResponses = ViewResponseHelper.createStoragePoolResponse(getCustomStats, storagePools.first().toArray(new StoragePoolJoinVO[storagePools.first().size()])); + List poolResponses = ViewResponseHelper.createStoragePoolResponse(getCustomStats, storagePools.first().toArray(new StoragePoolJoinVO[0])); Map poolUuidToIdMap = storagePools.first().stream().collect(Collectors.toMap(StoragePoolJoinVO::getUuid, StoragePoolJoinVO::getId, (a, b) -> a)); for (StoragePoolResponse poolResponse : poolResponses) { Long poolId = poolUuidToIdMap.get(poolResponse.getId()); @@ -3315,7 +3260,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = searchForStoragePoolsInternal(cmd); ListResponse response = new ListResponse<>(); - List poolResponses = ViewResponseHelper.createMinimalStoragePoolResponse(result.first().toArray(new StoragePoolJoinVO[result.first().size()])); + List poolResponses = ViewResponseHelper.createMinimalStoragePoolResponse(result.first().toArray(new StoragePoolJoinVO[0])); response.setResponses(poolResponses, result.second()); return response; } @@ -3350,9 +3295,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Override public ListResponse searchForStorageTags(ListStorageTagsCmd cmd) { - Pair, Integer> result = searchForStorageTagsInternal(cmd); + Pair, Integer> result = searchForStorageTagsInternal(); ListResponse response = new ListResponse<>(); - List tagResponses = ViewResponseHelper.createStorageTagResponse(result.first().toArray(new StoragePoolTagVO[result.first().size()])); + List tagResponses = ViewResponseHelper.createStorageTagResponse(result.first().toArray(new StoragePoolTagVO[0])); response.setResponses(tagResponses, result.second()); @@ -3452,7 +3397,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q return clusterResponse; } - private Pair, Integer> searchForStorageTagsInternal(ListStorageTagsCmd cmd) { + private Pair, Integer> searchForStorageTagsInternal() { Filter searchFilter = new Filter(StoragePoolTagVO.class, "id", Boolean.TRUE, null, null); SearchBuilder sb = _storageTagDao.createSearchBuilder(); @@ -3465,7 +3410,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> uniqueTagPair = _storageTagDao.searchAndCount(sc, searchFilter); Integer count = uniqueTagPair.second(); - if (count.intValue() == 0) { + if (count == 0) { return uniqueTagPair; } @@ -3484,16 +3429,16 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Override public ListResponse searchForHostTags(ListHostTagsCmd cmd) { - Pair, Integer> result = searchForHostTagsInternal(cmd); + Pair, Integer> result = searchForHostTagsInternal(); ListResponse response = new ListResponse<>(); - List tagResponses = ViewResponseHelper.createHostTagResponse(result.first().toArray(new HostTagVO[result.first().size()])); + List tagResponses = ViewResponseHelper.createHostTagResponse(result.first().toArray(new HostTagVO[0])); response.setResponses(tagResponses, result.second()); return response; } - private Pair, Integer> searchForHostTagsInternal(ListHostTagsCmd cmd) { + private Pair, Integer> searchForHostTagsInternal() { Filter searchFilter = new Filter(HostTagVO.class, "id", Boolean.TRUE, null, null); SearchBuilder sb = _hostTagDao.createSearchBuilder(); @@ -3506,7 +3451,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> uniqueTagPair = _hostTagDao.searchAndCount(sc, searchFilter); Integer count = uniqueTagPair.second(); - if (count.intValue() == 0) { + if (count == 0) { return uniqueTagPair; } @@ -3528,7 +3473,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = searchForImageStoresInternal(cmd); ListResponse response = new ListResponse<>(); - List poolResponses = ViewResponseHelper.createImageStoreResponse(result.first().toArray(new ImageStoreJoinVO[result.first().size()])); + List poolResponses = ViewResponseHelper.createImageStoreResponse(result.first().toArray(new ImageStoreJoinVO[0])); response.setResponses(poolResponses, result.second()); return response; } @@ -3592,7 +3537,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q // search Store details by ids Pair, Integer> uniqueStorePair = _imageStoreJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueStorePair.second(); - if (count.intValue() == 0) { + if (count == 0) { // empty result return uniqueStorePair; } @@ -3612,7 +3557,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = searchForCacheStoresInternal(cmd); ListResponse response = new ListResponse<>(); - List poolResponses = ViewResponseHelper.createImageStoreResponse(result.first().toArray(new ImageStoreJoinVO[result.first().size()])); + List poolResponses = ViewResponseHelper.createImageStoreResponse(result.first().toArray(new ImageStoreJoinVO[0])); response.setResponses(poolResponses, result.second()); return response; } @@ -3671,7 +3616,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q // search Store details by ids Pair, Integer> uniqueStorePair = _imageStoreJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueStorePair.second(); - if (count.intValue() == 0) { + if (count == 0) { // empty result return uniqueStorePair; } @@ -3738,10 +3683,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Object id = cmd.getId(); Object keyword = cmd.getKeyword(); Long domainId = cmd.getDomainId(); - Boolean isRootAdmin = accountMgr.isRootAdmin(account.getAccountId()); + boolean isRootAdmin = accountMgr.isRootAdmin(account.getAccountId()); Long projectId = cmd.getProjectId(); String accountName = cmd.getAccountName(); - Boolean isRecursive = cmd.isRecursive(); + boolean isRecursive = cmd.isRecursive(); Long zoneId = cmd.getZoneId(); Long volumeId = cmd.getVolumeId(); Long storagePoolId = cmd.getStoragePoolId(); @@ -3967,12 +3912,12 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } private List findRelatedDomainIds(Domain domain, boolean isRecursive) { - List domainIds = _domainDao.getDomainParentIds(domain.getId()) - .stream().collect(Collectors.toList()); + List domainIds = new ArrayList<>(_domainDao.getDomainParentIds(domain.getId())); if (isRecursive) { List childrenIds = _domainDao.getDomainChildrenIds(domain.getPath()); - if (childrenIds != null && !childrenIds.isEmpty()) - domainIds.addAll(childrenIds); + if (childrenIds != null && !childrenIds.isEmpty()) { + domainIds.addAll(childrenIds); + } } return domainIds; } @@ -3982,7 +3927,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = searchForServiceOfferingsInternal(cmd); result.first(); ListResponse response = new ListResponse<>(); - List offeringResponses = ViewResponseHelper.createServiceOfferingResponse(result.first().toArray(new ServiceOfferingJoinVO[result.first().size()])); + List offeringResponses = ViewResponseHelper.createServiceOfferingResponse(result.first().toArray(new ServiceOfferingJoinVO[0])); response.setResponses(offeringResponses, result.second()); return response; } @@ -4041,7 +3986,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q String vmTypeStr = cmd.getSystemVmType(); ServiceOfferingVO currentVmOffering = null; DiskOfferingVO diskOffering = null; - Boolean isRecursive = cmd.isRecursive(); + boolean isRecursive = cmd.isRecursive(); Long zoneId = cmd.getZoneId(); Integer cpuNumber = cmd.getCpuNumber(); Integer memory = cmd.getMemory(); @@ -4049,7 +3994,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Boolean encryptRoot = cmd.getEncryptRoot(); String storageType = cmd.getStorageType(); ServiceOffering.State state = cmd.getState(); - final Long templateId = cmd.getTemplateId(); final Long vgpuProfileId = cmd.getVgpuProfileId(); final Boolean gpuEnabled = cmd.getGpuEnabled(); @@ -4529,21 +4473,21 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q respView = ResponseView.Full; } - List dcResponses = ViewResponseHelper.createDataCenterResponse(respView, cmd.getShowCapacities(), cmd.getShowIcon(), result.first().toArray(new DataCenterJoinVO[result.first().size()])); + List dcResponses = ViewResponseHelper.createDataCenterResponse(respView, cmd.getShowCapacities(), cmd.getShowIcon(), result.first().toArray(new DataCenterJoinVO[0])); response.setResponses(dcResponses, result.second()); return response; } private ListResponse listDataCentersWithMinimalResponse(ListZonesCmd cmd) { Pair, Integer> result = listDataCentersInternal(cmd); - ListResponse response = new ListResponse(); + ListResponse response = new ListResponse<>(); ResponseView respView = ResponseView.Restricted; if (cmd instanceof ListZonesCmdByAdmin || CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) { respView = ResponseView.Full; } - List dcResponses = ViewResponseHelper.createMinimalDataCenterResponse(respView, result.first().toArray(new DataCenterJoinVO[result.first().size()])); + List dcResponses = ViewResponseHelper.createMinimalDataCenterResponse(respView, result.first().toArray(new DataCenterJoinVO[0])); response.setResponses(dcResponses, result.second()); return response; } @@ -4551,7 +4495,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private Pair, Integer> listDataCentersInternal(ListZonesCmd cmd) { Account account = CallContext.current().getCallingAccount(); Long domainId = cmd.getDomainId(); - Long id = cmd.getId(); + Long zoneId = cmd.getId(); + if( ! AllowUserViewAllDataCenters.valueInScope(ConfigKey.Scope.Domain, account.getDomainId())) { + zoneId = accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), zoneId); + logger.debug("not allowing users to view all zones ; selected zone is = {}", zoneId); + } List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); String keyword = cmd.getKeyword(); String name = cmd.getName(); @@ -4563,8 +4511,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q if (resourceTags != null && !resourceTags.isEmpty()) { SearchBuilder tagSearch = resourceTagDao.createSearchBuilder(); for (int count = 0; count < resourceTags.size(); count++) { - tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); - tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); + tagSearch.or().op("key" + count, tagSearch.entity().getKey(), SearchCriteria.Op.EQ); + tagSearch.and("value" + count, tagSearch.entity().getValue(), SearchCriteria.Op.EQ); tagSearch.cp(); } tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); @@ -4591,8 +4539,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q sc.addAnd("id", SearchCriteria.Op.IN, ids.toArray()); } - if (id != null) { - sc.addAnd("id", SearchCriteria.Op.EQ, id); + if (zoneId != null) { + sc.addAnd("id", SearchCriteria.Op.EQ, zoneId); } else if (name != null) { sc.addAnd("name", SearchCriteria.Op.EQ, name); } else { @@ -4603,109 +4551,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q sc.addAnd("name", SearchCriteria.Op.SC, ssc); } - /* - * List all resources due to Explicit Dedication except the - * dedicated resources of other account - */ - if (domainId != null) { // - // for domainId != null // right now, we made the decision to - // only list zones associated // with this domain, private zone - sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); - - if (accountMgr.isNormalUser(account.getId())) { - // accountId == null (zones dedicated to a domain) or - // accountId = caller - SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); - sdc.addOr("accountId", SearchCriteria.Op.EQ, account.getId()); - sdc.addOr("accountId", SearchCriteria.Op.NULL); - - sc.addAnd("accountId", SearchCriteria.Op.SC, sdc); - } - - } else if (accountMgr.isNormalUser(account.getId())) { - // it was decided to return all zones for the user's domain, and - // everything above till root - // list all zones belonging to this domain, and all of its - // parents - // check the parent, if not null, add zones for that parent to - // list - - // find all domain Id up to root domain for this account - List domainIds = new ArrayList<>(); - DomainVO domainRecord = _domainDao.findById(account.getDomainId()); - if (domainRecord == null) { - logger.error("Could not find the domainId for account: {}", account); - throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName()); - } - domainIds.add(domainRecord.getId()); - while (domainRecord.getParent() != null) { - domainRecord = _domainDao.findById(domainRecord.getParent()); - domainIds.add(domainRecord.getId()); - } - // domainId == null (public zones) or domainId IN [all domain id - // up to root domain] - SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); - sdc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); - sdc.addOr("domainId", SearchCriteria.Op.NULL); - sc.addAnd("domainId", SearchCriteria.Op.SC, sdc); - - // remove disabled zones - sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled); - - // accountId == null (zones dedicated to a domain) or - // accountId = caller - SearchCriteria sdc2 = _dcJoinDao.createSearchCriteria(); - sdc2.addOr("accountId", SearchCriteria.Op.EQ, account.getId()); - sdc2.addOr("accountId", SearchCriteria.Op.NULL); - - sc.addAnd("accountId", SearchCriteria.Op.SC, sdc2); - - // remove Dedicated zones not dedicated to this domainId or - // subdomainId - List dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds); - if (!dedicatedZoneIds.isEmpty()) { - sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); - } - - } else if (accountMgr.isDomainAdmin(account.getId()) || account.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN) { - // it was decided to return all zones for the domain admin, and - // everything above till root, as well as zones till the domain - // leaf - List domainIds = new ArrayList<>(); - DomainVO domainRecord = _domainDao.findById(account.getDomainId()); - if (domainRecord == null) { - logger.error("Could not find the domainId for account: {}", account); - throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName()); - } - domainIds.add(domainRecord.getId()); - // find all domain Ids till leaf - List allChildDomains = _domainDao.findAllChildren(domainRecord.getPath(), domainRecord.getId()); - for (DomainVO domain : allChildDomains) { - domainIds.add(domain.getId()); - } - // then find all domain Id up to root domain for this account - while (domainRecord.getParent() != null) { - domainRecord = _domainDao.findById(domainRecord.getParent()); - domainIds.add(domainRecord.getId()); - } - - // domainId == null (public zones) or domainId IN [all domain id - // up to root domain] - SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); - sdc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); - sdc.addOr("domainId", SearchCriteria.Op.NULL); - sc.addAnd("domainId", SearchCriteria.Op.SC, sdc); - - // remove disabled zones - sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled); - - // remove Dedicated zones not dedicated to this domainId or - // subdomainId - List dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds); - if (!dedicatedZoneIds.isEmpty()) { - sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); - } - } + buildSearchCriteriaForOwnedExplicitlyDedicatedResources(domainId, sc, account); // handle available=FALSE option, only return zones with at least // one VM running there @@ -4719,7 +4565,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q for (DomainRouterVO router : routers) { dcIds.add(router.getDataCenterId()); } - if (dcIds.size() == 0) { + if (dcIds.isEmpty()) { return new Pair<>(new ArrayList<>(), 0); } else { sc.addAnd("id", SearchCriteria.Op.IN, dcIds.toArray()); @@ -4729,15 +4575,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } } - if (resourceTags != null && !resourceTags.isEmpty()) { - int count = 0; - sc.setJoinParameters("tagSearch", "resourceType", ResourceObjectType.Zone.toString()); - for (Map.Entry entry : resourceTags.entrySet()) { - sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), entry.getKey()); - sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), entry.getValue()); - count++; - } - } + buildSearchCriteriaForTags(resourceTags, sc); if (storageAccessGroup != null) { sc.setParameters("storageAccessGroupExact", storageAccessGroup); @@ -4749,12 +4587,144 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q return _dcJoinDao.searchAndCount(sc, searchFilter); } - private List removeDedicatedZoneNotSuitabe(List domainIds) { + private static void buildSearchCriteriaForTags(Map resourceTags, SearchCriteria sc) { + if (resourceTags != null && !resourceTags.isEmpty()) { + int count = 0; + sc.setJoinParameters("tagSearch", "resourceType", ResourceObjectType.Zone.toString()); + for (Map.Entry entry : resourceTags.entrySet()) { + sc.setJoinParameters("tagSearch", "key" + count, entry.getKey()); + sc.setJoinParameters("tagSearch", "value" + count, entry.getValue()); + count++; + } + } + } + + /** + * List all resources due to Explicit Dedication except the + * dedicated resources of other account + */ + private void buildSearchCriteriaForOwnedExplicitlyDedicatedResources(Long domainId, SearchCriteria sc, Account account) { + if (domainId != null) { + buildSearchCriteriaForZonesBelongingToDomain(domainId, sc, account); + } else if (accountMgr.isNormalUser(account.getId())) { + buildSearchCriteriaForUserDomainAndAbove(sc, account); + } else if (accountMgr.isDomainAdmin(account.getId()) || accountMgr.isResourceDomainAdmin(account.getId())) { + buildSearchCriteriaForDomainAdmins(sc, account); + } + } + + /** + * Return all zones for the domain admin, and everything above till root, as well as zones till the domain leaf + */ + private void buildSearchCriteriaForDomainAdmins(SearchCriteria sc, Account account) { + List domainIds = new ArrayList<>(); + DomainVO domainRecord = getDomainForAccount(account); + logger.trace("adding caller's domain {} to the list of domains to search for zones", account.getDomainId()); + domainIds.add(domainRecord.getId()); + // find all domain Ids till leaf + List allChildDomains = _domainDao.findAllChildren(domainRecord.getPath(), domainRecord.getId()); + for (DomainVO domain : allChildDomains) { + logger.trace("adding caller domain's child {} to the list of domains to search for zones", domain.getId()); + domainIds.add(domain.getId()); + } + // then find all domain Id up to root domain for this account + while (domainRecord.getParent() != null) { + domainRecord = _domainDao.findById(domainRecord.getParent()); + logger.trace("adding caller domain's ancestor {} to the list of domains to search for zones", domainRecord.getId()); + domainIds.add(domainRecord.getId()); + } + + // so search for domainId == null (public zones) or domainId this user has access to + SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); + sdc.addOr("domainId", Op.IN, domainIds.toArray()); + sdc.addOr("domainId", Op.NULL); + sc.addAnd("domainId", Op.SC, sdc); + + // remove disabled zones + sc.addAnd("allocationState", Op.NEQ, Grouping.AllocationState.Disabled); + + // remove Dedicated zones not dedicated to this domainId or + // subdomainId + List dedicatedZoneIds = removeDedicatedZoneNotSuitable(domainIds); + if (!dedicatedZoneIds.isEmpty()) { + sdc.addAnd("id", Op.NIN, dedicatedZoneIds.toArray(new Object[0])); + } + } + + @NotNull + private DomainVO getDomainForAccount(Account account) { + DomainVO domainRecord = _domainDao.findById(account.getDomainId()); + if (domainRecord == null) { + logger.error("Could not find the domainId for account: {}", account); + throw new CloudAuthenticationException("Could not find the domainId for account:" + account.getAccountName()); + } + return domainRecord; + } + + /** + * Return all zones for the user's domain, and everything above till root + * list all zones belonging to this domain, and all of its parents + * check the parent, if not null, add zones for that parent to list + */ + private void buildSearchCriteriaForUserDomainAndAbove(SearchCriteria sc, Account account) { + + // find all domain Id up to root domain for this account + List domainIds = new ArrayList<>(); + DomainVO domainRecord = getDomainForAccount(account); + domainIds.add(domainRecord.getId()); + while (domainRecord.getParent() != null) { + domainRecord = _domainDao.findById(domainRecord.getParent()); + domainIds.add(domainRecord.getId()); + } + // domainId == null (public zones) or domainId IN [all domain id + // up to root domain] + SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); + sdc.addOr("domainId", Op.IN, domainIds.toArray()); + sdc.addOr("domainId", Op.NULL); + sc.addAnd("domainId", Op.SC, sdc); + + // remove disabled zones + sc.addAnd("allocationState", Op.NEQ, Grouping.AllocationState.Disabled); + + // accountId == null (zones dedicated to a domain) or + // accountId = caller + SearchCriteria sdc2 = _dcJoinDao.createSearchCriteria(); + sdc2.addOr("accountId", Op.EQ, account.getId()); + sdc2.addOr("accountId", Op.NULL); + + sc.addAnd("accountId", Op.SC, sdc2); + + // remove Dedicated zones not dedicated to this domainId or + // subdomainId + List dedicatedZoneIds = removeDedicatedZoneNotSuitable(domainIds); + if (!dedicatedZoneIds.isEmpty()) { + sdc.addAnd("id", Op.NIN, dedicatedZoneIds.toArray(new Object[0])); + } + } + + private void buildSearchCriteriaForZonesBelongingToDomain(Long domainId, SearchCriteria sc, Account account) { + // for domainId != null // right now, we made the decision to + // only list zones associated // with this domain, private zone + sc.addAnd("domainId", Op.EQ, domainId); + + if (accountMgr.isNormalUser(account.getId())) { + // accountId == null (zones dedicated to a domain) or + // accountId = caller + SearchCriteria sdc = _dcJoinDao.createSearchCriteria(); + sdc.addOr("accountId", Op.EQ, account.getId()); + sdc.addOr("accountId", Op.NULL); + + sc.addAnd("accountId", Op.SC, sdc); + } + } + + private List removeDedicatedZoneNotSuitable(List domainIds) { // remove dedicated zone of other domain List dedicatedZoneIds = new ArrayList<>(); List dedicatedResources = _dedicatedDao.listZonesNotInDomainIds(domainIds); for (DedicatedResourceVO dr : dedicatedResources) { if (dr != null) { + logger.trace("adding zone to exclude from callers list zones result: {}.", dr.getDataCenterId()); dedicatedZoneIds.add(dr.getDataCenterId()); } } @@ -4799,7 +4769,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q respView = ResponseView.Full; } - List templateResponses = ViewResponseHelper.createTemplateResponse(cmd.getDetails(), respView, result.first().toArray(new TemplateJoinVO[result.first().size()])); + List templateResponses = ViewResponseHelper.createTemplateResponse(cmd.getDetails(), respView, result.first().toArray(new TemplateJoinVO[0])); response.setResponses(templateResponses, result.second()); return response; } @@ -4811,6 +4781,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q boolean showRemovedTmpl = cmd.getShowRemoved(); Account caller = CallContext.current().getCallingAccount(); Long parentTemplateId = cmd.getParentTemplateId(); + Long domainId = cmd.getDomainId(); + boolean isRecursive = cmd.isRecursive(); boolean listAll = false; if (templateFilter != null && templateFilter == TemplateFilter.all) { @@ -4821,7 +4793,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } List permittedAccountIds = new ArrayList<>(); - Ternary domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null); + Ternary domainIdRecursiveListProject = new Ternary<>(domainId, isRecursive, null); accountMgr.buildACLSearchParameters( caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, domainIdRecursiveListProject, listAll, false @@ -4850,7 +4822,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q null, cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), cmd.getStoragePoolId(), cmd.getImageStoreId(), hypervisorType, showDomr, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedTmpl, cmd.getIds(), parentTemplateId, cmd.getShowUnique(), - templateType, isVnf, cmd.getArch(), cmd.getOsCategoryId(), forCks, cmd.getExtensionId()); + templateType, isVnf, domainId, isRecursive, cmd.getArch(), cmd.getOsCategoryId(), forCks, cmd.getExtensionId()); } private Pair, Integer> searchForTemplatesInternal(Long templateId, String name, String keyword, @@ -4859,7 +4831,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q boolean showDomr, boolean onlyReady, List permittedAccounts, Account caller, ListProjectResourcesCriteria listProjectResourcesCriteria, Map tags, boolean showRemovedTmpl, List ids, Long parentTemplateId, Boolean showUnique, String templateType, - Boolean isVnf, CPU.CPUArch arch, Long osCategoryId, Boolean forCks, Long extensionId) { + Boolean isVnf, Long domainId, boolean isRecursive, CPU.CPUArch arch, Long osCategoryId, Boolean forCks, Long extensionId) { // check if zone is configured, if not, just return empty list List hypers = null; @@ -4963,7 +4935,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q if (!permittedAccounts.isEmpty()) { domain = _domainDao.findById(permittedAccounts.get(0).getDomainId()); } else { - domain = _domainDao.findById(caller.getDomainId()); + domain = _domainDao.findById(Objects.requireNonNullElse(domainId, caller.getDomainId())); } setIdsListToSearchCriteria(sc, ids); @@ -4975,10 +4947,14 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q sc.addAnd("accountType", SearchCriteria.Op.EQ, Account.Type.PROJECT); } - // add criteria for domain path in case of domain admin + // add criteria for domain path in case of admins if ((templateFilter == TemplateFilter.self || templateFilter == TemplateFilter.selfexecutable) - && (caller.getType() == Account.Type.DOMAIN_ADMIN || caller.getType() == Account.Type.RESOURCE_DOMAIN_ADMIN)) { - sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%"); + && (accountMgr.isAdmin(caller.getAccountId()))) { + if (isRecursive) { + sc.addAnd("domainPath", SearchCriteria.Op.LIKE, domain.getPath() + "%"); + } else { + sc.addAnd("domainPath", SearchCriteria.Op.EQ, domain.getPath()); + } } List relatedDomainIds = new ArrayList<>(); @@ -5228,7 +5204,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q if (showRemovedTmpl) { uniqueTmplPair = _templateJoinDao.searchIncludingRemovedAndCount(sc, searchFilter); } else { - sc.addAnd("templateState", SearchCriteria.Op.IN, new State[] {State.Active, State.UploadAbandoned, State.UploadError, State.NotUploaded, State.UploadInProgress}); + sc.addAnd("templateState", SearchCriteria.Op.IN, State.Active, State.UploadAbandoned, State.UploadError, State.NotUploaded, State.UploadInProgress); if (showUnique) { final String[] distinctColumns = {"template_view.id"}; uniqueTmplPair = _templateJoinDao.searchAndDistinctCount(sc, searchFilter, distinctColumns); @@ -5250,17 +5226,17 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private Pair, Integer> findTemplatesByIdOrTempZonePair(Pair, Integer> templateDataPair, boolean showRemoved, boolean showUnique, Account caller) { Integer count = templateDataPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // empty result return templateDataPair; } List templateData = templateDataPair.first(); List templates; if (showUnique) { - Long[] templateIds = templateData.stream().map(template -> template.getId()).toArray(Long[]::new); + Long[] templateIds = templateData.stream().map(BaseViewWithTagInformationVO::getId).toArray(Long[]::new); templates = _templateJoinDao.findByDistinctIds(templateIds); } else { - String[] templateZonePairs = templateData.stream().map(template -> template.getTempZonePair()).toArray(String[]::new); + String[] templateZonePairs = templateData.stream().map(TemplateJoinVO::getTempZonePair).toArray(String[]::new); templates = _templateJoinDao.searchByTemplateZonePair(showRemoved, templateZonePairs); } @@ -5277,7 +5253,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q respView = ResponseView.Full; } - List templateResponses = ViewResponseHelper.createIsoResponse(respView, result.first().toArray(new TemplateJoinVO[result.first().size()])); + List templateResponses = ViewResponseHelper.createIsoResponse(respView, result.first().toArray(new TemplateJoinVO[0])); response.setResponses(templateResponses, result.second()); return response; } @@ -5288,6 +5264,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Map tags = cmd.getTags(); boolean showRemovedISO = cmd.getShowRemoved(); Account caller = CallContext.current().getCallingAccount(); + Long domainId = cmd.getDomainId(); + boolean isRecursive = cmd.isRecursive(); boolean listAll = false; if (isoFilter != null && isoFilter == TemplateFilter.all) { @@ -5299,7 +5277,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q List permittedAccountIds = new ArrayList<>(); - Ternary domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null); + Ternary domainIdRecursiveListProject = new Ternary<>(domainId, isRecursive, null); accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccountIds, domainIdRecursiveListProject, listAll, false); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); List permittedAccounts = new ArrayList<>(); @@ -5313,7 +5291,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q cmd.getPageSizeVal(), cmd.getStartIndex(), cmd.getZoneId(), cmd.getStoragePoolId(), cmd.getImageStoreId(), hypervisorType, true, cmd.listInReadyState(), permittedAccounts, caller, listProjectResourcesCriteria, tags, showRemovedISO, null, null, cmd.getShowUnique(), null, null, - cmd.getArch(), cmd.getOsCategoryId(), null, null); + domainId, isRecursive, cmd.getArch(), cmd.getOsCategoryId(), null, null); } @Override @@ -5341,13 +5319,11 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } if (CallContext.current().getCallingAccount().getType() != Account.Type.ADMIN) { final List userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(",")) - .map(item -> (item).trim()) + .map(String::trim) .collect(Collectors.toList()); userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings); for (final String detail : userDenyListedSettings) { - if (options.containsKey(detail)) { - options.remove(detail); - } + options.remove(detail); } } return new DetailOptionsResponse(options); @@ -5363,7 +5339,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q private void fillVnfTemplateDetailOptions(final Map> options) { for (VNF.AccessDetail detail : VNF.AccessDetail.values()) { if (VNF.AccessDetail.ACCESS_METHODS.equals(detail)) { - options.put(detail.name().toLowerCase(), Arrays.stream(VNF.AccessMethod.values()).map(method -> method.toString()).sorted().collect(Collectors.toList())); + options.put(detail.name().toLowerCase(), Arrays.stream(VNF.AccessMethod.values()).map(VNF.AccessMethod::toString).sorted().collect(Collectors.toList())); } else { options.put(detail.name().toLowerCase(), Collections.emptyList()); } @@ -5391,7 +5367,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q options.put(VmDetailConstants.VIDEO_HARDWARE, Arrays.asList("cirrus", "vga", "qxl", "virtio")); options.put(VmDetailConstants.VIDEO_RAM, Collections.emptyList()); options.put(VmDetailConstants.IO_POLICY, Arrays.asList("threads", "native", "io_uring", "storage_specific")); - options.put(VmDetailConstants.IOTHREADS, Arrays.asList("enabled")); + options.put(VmDetailConstants.IOTHREADS, List.of("enabled")); options.put(VmDetailConstants.NIC_MULTIQUEUE_NUMBER, Collections.emptyList()); options.put(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, Arrays.asList("true", "false")); options.put(VmDetailConstants.VIRTUAL_TPM_MODEL, Arrays.asList("tpm-tis", "tpm-crb")); @@ -5414,7 +5390,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Override public ListResponse searchForAffinityGroups(ListAffinityGroupsCmd cmd) { Pair, Integer> result = searchForAffinityGroupsInternal(cmd); - ListResponse response = new ListResponse(); + ListResponse response = new ListResponse<>(); List agResponses = ViewResponseHelper.createAffinityGroupResponses(result.first()); response.setResponses(agResponses, result.second()); return response; @@ -5430,7 +5406,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Long domainId = cmd.getDomainId(); final Long projectId = cmd.getProjectId(); Boolean isRecursive = cmd.isRecursive(); - final Boolean listAll = cmd.listAll(); + final boolean listAll = cmd.listAll(); final Long startIndex = cmd.getStartIndex(); final Long pageSize = cmd.getPageSizeVal(); final String keyword = cmd.getKeyword(); @@ -5443,7 +5419,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found."); } accountMgr.checkAccess(caller, null, true, userVM); - return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize); + return listAffinityGroupsByVM(vmId, startIndex, pageSize); } List permittedAccounts = new ArrayList<>(); @@ -5466,7 +5442,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q List affinityGroups = new ArrayList<>(); Integer count = uniqueGroupsPair.second(); - if (count.intValue() != 0) { + if (count != 0) { List uniqueGroups = uniqueGroupsPair.first(); Long[] vrIds = new Long[uniqueGroups.size()]; int i = 0; @@ -5588,7 +5564,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Filter sf = new Filter(SecurityGroupVMMapVO.class, null, true, pageInd, pageSize); Pair, Integer> agVmMappingPair = _affinityGroupVMMapDao.listByInstanceId(vmId, sf); Integer count = agVmMappingPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // handle empty result cases return new Pair<>(new ArrayList<>(), count); } @@ -5624,7 +5600,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, searchFilter); // search group by ids Integer count = uniqueGroupsPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // empty result return new Pair<>(new ArrayList<>(), 0); } @@ -5663,9 +5639,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q //Validation - 1.3 if (resourceIdStr != null) { resourceId = resourceManagerUtil.getResourceId(resourceIdStr, resourceType); - if (resourceId == null) { - throw new InvalidParameterValueException("Cannot find resource with resourceId " + resourceIdStr + " and of resource type " + resourceType); - } } List detailList = new ArrayList<>(); @@ -5702,7 +5675,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q resourceDetailResponse.setName(requestedDetail.getName()); resourceDetailResponse.setValue(requestedDetail.getValue()); resourceDetailResponse.setForDisplay(requestedDetail.isDisplay()); - resourceDetailResponse.setResourceType(resourceType.toString().toString()); + resourceDetailResponse.setResourceType(resourceType.toString()); resourceDetailResponse.setObjectName("resourcedetail"); return resourceDetailResponse; } @@ -5803,7 +5776,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q } List result = new ArrayList<>(routerHealthCheckResultDao.getHealthCheckResults(routerId)); - if (result == null || result.size() == 0) { + if (result.isEmpty()) { throw new CloudRuntimeException("No health check results found for the router. This could happen for " + "a newly created router. Please wait for periodic results to populate or manually call for checks to execute."); } @@ -5897,7 +5870,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q if (cmd instanceof ListSnapshotsCmdByAdmin) { respView = ResponseView.Full; } - List templateResponses = ViewResponseHelper.createSnapshotResponse(respView, cmd.isShowUnique(), result.first().toArray(new SnapshotJoinVO[result.first().size()])); + List templateResponses = ViewResponseHelper.createSnapshotResponse(respView, cmd.isShowUnique(), result.first().toArray(new SnapshotJoinVO[0])); response.setResponses(templateResponses, result.second()); return response; } @@ -5973,8 +5946,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q if (tags != null && !tags.isEmpty()) { SearchBuilder tagSearch = resourceTagDao.createSearchBuilder(); for (int count = 0; count < tags.size(); count++) { - tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ); - tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ); + tagSearch.or().op("key" + count, tagSearch.entity().getKey(), SearchCriteria.Op.EQ); + tagSearch.and("value" + count, tagSearch.entity().getValue(), SearchCriteria.Op.EQ); tagSearch.cp(); } tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); @@ -6012,8 +5985,8 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q int count = 0; sc.setJoinParameters("tagSearch", "resourceType", ResourceObjectType.Snapshot.toString()); for (String key : tags.keySet()) { - sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), key); - sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), tags.get(key)); + sc.setJoinParameters("tagSearch", "key" + count, key); + sc.setJoinParameters("tagSearch", "value" + count, tags.get(key)); count++; } } @@ -6088,7 +6061,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Pair, Integer> result = searchForObjectStoresInternal(cmd); ListResponse response = new ListResponse<>(); - List poolResponses = ViewResponseHelper.createObjectStoreResponse(result.first().toArray(new ObjectStoreVO[result.first().size()])); + List poolResponses = ViewResponseHelper.createObjectStoreResponse(result.first().toArray(new ObjectStoreVO[0])); response.setResponses(poolResponses, result.second()); return response; } @@ -6135,7 +6108,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q // search Store details by ids Pair, Integer> uniqueStorePair = objectStoreDao.searchAndCount(sc, searchFilter); Integer count = uniqueStorePair.second(); - if (count.intValue() == 0) { + if (count == 0) { // empty result return uniqueStorePair; } @@ -6166,7 +6139,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q Long id = cmd.getId(); String name = cmd.getBucketName(); - Long storeId = cmd.getObjectStorageId(); String keyword = cmd.getKeyword(); Long startIndex = cmd.getStartIndex(); Long pageSize = cmd.getPageSizeVal(); @@ -6222,7 +6194,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q // search Volume details by ids Pair, Integer> uniqueBktPair = bucketDao.searchAndCount(sc, searchFilter); Integer count = uniqueBktPair.second(); - if (count.intValue() == 0) { + if (count == 0) { // empty result return uniqueBktPair.first(); } @@ -6244,6 +6216,6 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q @Override public ConfigKey[] getConfigKeys() { return new ConfigKey[] {AllowUserViewDestroyedVM, UserVMDeniedDetails, UserVMReadOnlyDetails, SortKeyAscending, - AllowUserViewAllDomainAccounts, SharePublicTemplatesWithOtherDomains, ReturnVmStatsOnVmList}; + AllowUserViewAllDomainAccounts, AllowUserViewAllDataCenters, SharePublicTemplatesWithOtherDomains, ReturnVmStatsOnVmList}; } } diff --git a/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java index e2a3201e954..2fc3056af3e 100644 --- a/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/TemplateJoinDaoImpl.java @@ -482,6 +482,7 @@ public class TemplateJoinDaoImpl extends GenericDaoBaseWithTagInformation 0) { isoResponse.setSize(isoSize); } + long isoPhysicalSize = iso.getPhysicalSize(); + if (isoPhysicalSize > 0) { + isoResponse.setPhysicalSize(isoPhysicalSize); + } if (iso.getUserDataId() != null) { isoResponse.setUserDataId(iso.getUserDataUUid()); diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 03b97af4e10..64b2a66f452 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -50,12 +50,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.network.dao.NetrisProviderDao; -import com.cloud.network.element.NetrisProviderVO; -import com.cloud.network.netris.NetrisService; import org.apache.cloudstack.acl.RoleType; -import com.cloud.gpu.VgpuProfileVO; -import com.cloud.gpu.dao.VgpuProfileDao; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupService; @@ -207,6 +202,8 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.gpu.GPU; +import com.cloud.gpu.VgpuProfileVO; +import com.cloud.gpu.dao.VgpuProfileDao; import com.cloud.host.HostTagVO; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; @@ -230,10 +227,12 @@ import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetwork; import com.cloud.network.UserIpv6AddressVO; +import com.cloud.network.as.AutoScaleManager; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.Ipv6GuestPrefixSubnetNetworkMapDao; +import com.cloud.network.dao.NetrisProviderDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.NsxProviderDao; @@ -242,7 +241,9 @@ import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.dao.UserIpv6AddressDao; +import com.cloud.network.element.NetrisProviderVO; import com.cloud.network.element.NsxProviderVO; +import com.cloud.network.netris.NetrisService; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.network.vpc.VpcManager; import com.cloud.offering.DiskOffering; @@ -600,6 +601,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati configValuesForValidation.add(VMLeaseManager.InstanceLeaseSchedulerInterval.key()); configValuesForValidation.add(VMLeaseManager.InstanceLeaseExpiryEventSchedulerInterval.key()); configValuesForValidation.add(VMLeaseManager.InstanceLeaseExpiryEventDaysBefore.key()); + configValuesForValidation.add(AutoScaleManager.AutoScaleErroredInstanceThreshold.key()); } protected void weightBasedParametersForValidation() { diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 1c69e6ba59d..484193f2fcd 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -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 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); } diff --git a/server/src/main/java/com/cloud/network/as/AutoScaleManager.java b/server/src/main/java/com/cloud/network/as/AutoScaleManager.java index 04d4c8d2d62..88a9fd34bd1 100644 --- a/server/src/main/java/com/cloud/network/as/AutoScaleManager.java +++ b/server/src/main/java/com/cloud/network/as/AutoScaleManager.java @@ -39,6 +39,12 @@ public interface AutoScaleManager extends AutoScaleService { "The Number of worker threads to scan the autoscale vm groups.", false); + ConfigKey AutoScaleErroredInstanceThreshold = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Integer.class, + "autoscale.errored.instance.threshold", + "10", + "The number of Error Instances allowed in autoscale vm groups for scale up.", + true); + void checkAutoScaleUser(Long autoscaleUserId, long accountId); boolean deleteAutoScaleVmGroupsByAccount(Account account); diff --git a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java index 463014c0b84..7c7e0b662d7 100644 --- a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java +++ b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java @@ -1722,6 +1722,11 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage logger.warn("number of VM will greater than the maximum in this group if scaling up, so do nothing more"); return false; } + int erroredInstanceCount = autoScaleVmGroupVmMapDao.getErroredInstanceCount(asGroup.getId()); + if (erroredInstanceCount > AutoScaleManager.AutoScaleErroredInstanceThreshold.value()) { + logger.warn("Number of Errored Instances are greater than the threshold in this group for scaling up, so do nothing more"); + return false; + } return true; } @@ -2202,7 +2207,8 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage return new ConfigKey[] { AutoScaleStatsInterval, AutoScaleStatsCleanupDelay, - AutoScaleStatsWorker + AutoScaleStatsWorker, + AutoScaleErroredInstanceThreshold }; } diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java index 47f23bca4b0..27e7f27ae0e 100755 --- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java @@ -1365,7 +1365,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, for (int i = 0; i < retry; i++) { lsuccess = true; try { - Thread.currentThread().wait(5 * 1000); + Thread.sleep(5 * 1000); } catch (final InterruptedException e) { logger.debug("thread unexpectedly interrupted during wait, while updating cluster"); } diff --git a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 7ada4b7f4cc..9a6c8a85f18 100644 --- a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -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; @@ -356,7 +355,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); } @@ -372,7 +371,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, @@ -399,11 +398,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 { @@ -444,10 +443,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 { @@ -479,7 +478,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(); @@ -493,12 +492,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 @@ -517,7 +516,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 { @@ -556,9 +555,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; @@ -597,9 +594,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; @@ -618,14 +613,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; } @@ -703,8 +698,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim @Override public List searchForLimits(Long id, Long accountId, Long domainId, ResourceType resourceType, String tag, Long startIndex, Long pageSizeVal) { Account caller = CallContext.current().getCallingAccount(); - List limits = new ArrayList(); - boolean isAccount = true; + List limits = new ArrayList<>(); + boolean isAccount; if (!_accountMgr.isAdmin(caller.getId())) { accountId = caller.getId(); @@ -796,7 +791,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; @@ -814,8 +809,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 accountLimitStr = new ArrayList(); - List domainLimitStr = new ArrayList(); + List accountLimitStr = new ArrayList<>(); + List domainLimitStr = new ArrayList<>(); for (ResourceLimitVO foundLimit : foundLimits) { if (foundLimit.getAccountId() != null) { accountLimitStr.add(foundLimit.getType().toString()); @@ -909,8 +904,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'."); } @@ -918,7 +913,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; } } @@ -957,7 +952,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)); } @@ -993,12 +988,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"); } @@ -1013,7 +1008,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)); } } @@ -1031,7 +1026,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim ActionEventUtils.onActionEvent(caller.getId(), caller.getAccountId(), caller.getDomainId(), EventTypes.EVENT_RESOURCE_LIMIT_UPDATE, - "Resource limit updated. Resource Type: " + resourceType.toString() + ", New Value: " + max, + "Resource limit updated. Resource Type: " + resourceType + ", New Value: " + max, ownerResourceId, ownerResourceType.toString()); if (limit != null) { @@ -1110,15 +1105,15 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim @Override public List recalculateResourceCount(Long accountId, Long domainId, Integer typeId, String tag) throws CloudRuntimeException { Account callerAccount = CallContext.current().getCallingAccount(); - long count = 0; - List counts = new ArrayList(); - List resourceTypes = new ArrayList(); + long count; + List counts = new ArrayList<>(); + List 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; } } @@ -1137,12 +1132,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 { @@ -1191,7 +1187,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 rowIdsToUpdate = _resourceCountDao.listAllRowsToUpdate(accountId, ResourceOwnerType.Account, type, tag); return _resourceCountDao.updateCountByDeltaForIds(new ArrayList<>(rowIdsToUpdate), increment, delta); @@ -1246,6 +1242,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(); @@ -1255,11 +1252,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; }); @@ -1335,8 +1333,8 @@ 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."); + 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; @@ -1508,20 +1506,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 dedicatedVlans = _vlanDao.listDedicatedVlans(accountId); for (VlanVO dedicatedVlan : dedicatedVlans) { List 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) { @@ -1609,10 +1603,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) { @@ -1861,7 +1855,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim if (currentOfferingTags.isEmpty() && newOfferingTags.isEmpty()) { return null; } - Set sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet());; + Set sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet()); Set newTags = newOfferingTags.stream().filter(tag -> !currentOfferingTags.contains(tag)).collect(Collectors.toSet()); Set removedTags = currentOfferingTags.stream().filter(tag -> !newOfferingTags.contains(tag)).collect(Collectors.toSet()); return new Ternary<>(sameTags, newTags, removedTags); @@ -1936,7 +1930,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim if (currentOfferingTags.isEmpty() && newOfferingTags.isEmpty()) { return null; } - Set sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet());; + Set sameTags = currentOfferingTags.stream().filter(newOfferingTags::contains).collect(Collectors.toSet()); Set newTags = newOfferingTags.stream().filter(tag -> !currentOfferingTags.contains(tag)).collect(Collectors.toSet()); Set removedTags = currentOfferingTags.stream().filter(tag -> !newOfferingTags.contains(tag)).collect(Collectors.toSet()); return new Ternary<>(sameTags, newTags, removedTags); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 21e8c2eac8b..b09a675aa58 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -774,14 +774,12 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDomainDao; import com.cloud.network.dao.NetworkDomainVO; import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PublicIpQuarantineDao; import com.cloud.network.vpc.dao.VpcDao; import com.cloud.org.Cluster; 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; @@ -883,8 +881,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe static final ConfigKey sshKeyLength = new ConfigKey<>("Advanced", Integer.class, "ssh.key.length", "2048", "Specifies custom SSH key length (bit)", true, ConfigKey.Scope.Global); static final ConfigKey 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 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 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 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); + public static final ConfigKey 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 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 LIVE_MIGRATION_SUPPORTING_HYPERVISORS = List.of(HypervisorType.Hyperv, HypervisorType.KVM, @@ -991,8 +989,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private ProjectManager _projectMgr; @Inject - private ResourceManager _resourceMgr; - @Inject private HighAvailabilityManager _haMgr; @Inject private HostTagsDao _hostTagsDao; @@ -1050,10 +1046,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe StoragePoolTagsDao storagePoolTagsDao; @Inject protected ManagementServerJoinDao managementServerJoinDao; - - @Inject - private PublicIpQuarantineDao publicIpQuarantineDao; - @Inject ClusterManager _clusterMgr; @@ -1080,7 +1072,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private List _userAuthenticators; private List _userTwoFactorAuthenticators; private List _userPasswordEncoders; - protected boolean _executeInSequence; protected List _planners; @@ -4751,6 +4742,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); diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index a79ba15f740..8f374029b1d 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -2644,7 +2644,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic excludeLocalStorageIfNeeded(volumeToAttach); - checkForDevicesInCopies(vmId, vm); + checkForVMSnapshots(vmId, vm); + + checkForBackups(vm, true); checkRightsToAttach(caller, volumeToAttach, vm); @@ -2743,18 +2745,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 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 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())); - } } /** @@ -2854,7 +2850,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; } @@ -3074,7 +3070,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) { diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java index d041ac19430..81b75c23eba 100755 --- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java @@ -1854,6 +1854,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId + ") and snapshot ID (" + snapshotId + ")"); } + CPU.CPUArch arch = cmd.getArch(); HypervisorType hyperType; VolumeVO volume = null; @@ -1946,7 +1947,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, String description = cmd.getDisplayText(); boolean isExtractable = false; Long sourceTemplateId = null; - CPU.CPUArch arch = CPU.CPUArch.amd64; if (volume != null) { VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId()); isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM; diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index db79323ed1e..d93993af9ab 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -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); diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java index 4a53edd9570..a7d03f1a9a3 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -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 vmVolumes) { List 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())); } diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 4fed2ddd325..ad3d2a0f0ec 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -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 allDetails) { + if (StringUtils.isNotBlank(bootType) && bootType.equalsIgnoreCase("uefi") && StringUtils.isNotBlank(bootMode)) { + allDetails.put("UEFI", bootMode); + } + } + private HashMap getUnmanagedInstancesForHost(HostVO host, String instanceName, List managedVms) { HashMap 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 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; diff --git a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java index 5e37fe7b018..7f1030992f9 100644 --- a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java @@ -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 diff --git a/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java b/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java index 8c569fb3ec8..a84f02755c7 100644 --- a/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java +++ b/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java @@ -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 diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java index cf59129459d..0c46de2a4ac 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxy.java @@ -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() { diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVncClient.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVncClient.java index fece5bfaa22..85a2e5c541f 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVncClient.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyNoVncClient.java @@ -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); } diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/NoVncClient.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/NoVncClient.java index e4bb93711b9..493c2287931 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/NoVncClient.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/NoVncClient.java @@ -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(); diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocket.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocket.java index dfc47f33377..9bd2a10e6f0 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocket.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocket.java @@ -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); } diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandler.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandler.java index e1ccd6feb11..757f9c126ec 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandler.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandler.java @@ -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); diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandlerImpl.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandlerImpl.java index 3aa3524ea83..fc19c36b3ed 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandlerImpl.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketHandlerImpl.java @@ -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 diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketInputStream.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketInputStream.java index 8747afd85e2..e347c95f280 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketInputStream.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketInputStream.java @@ -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; } } diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketSSLEngineManager.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketSSLEngineManager.java index 2b0229b7567..826e7c6dd50 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketSSLEngineManager.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketSSLEngineManager.java @@ -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() { diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSInputStream.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSInputStream.java index f57a56e8a94..c3f46571e8a 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSInputStream.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSInputStream.java @@ -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; } diff --git a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSOutputStream.java b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSOutputStream.java index 6024e2718e9..f9bdb5cca49 100644 --- a/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSOutputStream.java +++ b/services/console-proxy/server/src/main/java/com/cloud/consoleproxy/vnc/network/NioSocketTLSOutputStream.java @@ -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) { diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index 836cb62adea..fae8e69a386 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -268,9 +268,6 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar private final GlobalLock _allocLock = GlobalLock.getInternLock(getAllocLockName()); - static final ConfigKey NTPServerConfig = new ConfigKey(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 MaxNumberOfSsvmsForMigration = new ConfigKey("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+","")); } diff --git a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java index 2cc61dae133..a580105d52a 100644 --- a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java +++ b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java @@ -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{startDate} to {endDate}", "label.datetime.filter.starting": "Starting {startDate}.", @@ -711,19 +710,19 @@ "label.days": "Days", "label.day.of.month": "Day of month", "label.day.of.week": "Day of week", -"label.db.usage.metrics": "DB/Usage server", +"label.db.usage.metrics": "DB/Usage Server", "label.dbislocal": "The db runs locally", "label.dc.name": "DC name", "label.declare.host.as.degraded": "Declare host as degraded", "label.decline.invitation": "Decline invitation", "label.dedicate": "Dedicate", "label.dedicate.bgp.peer": "Dedicate BGP peer", -"label.dedicate.cluster": "Dedicate cluster", -"label.dedicate.host": "Dedicate host", +"label.dedicate.cluster": "Dedicate Cluster", +"label.dedicate.host": "Dedicate Host", "label.dedicate.ipv4.subnet": "Dedicate IPv4 subnet", -"label.dedicate.pod": "Dedicate pod", +"label.dedicate.pod": "Dedicate Pod", "label.dedicate.vlan.vni.range": "Dedicate VLAN/VNI range", -"label.dedicate.zone": "Dedicate zone", +"label.dedicate.zone": "Dedicate Zone", "label.dedicated": "Dedicated", "label.dedicated.vlan.vni.ranges": "Dedicated VLAN/VNI ranges", "label.dedicatedresources": "Dedicated resources", @@ -734,7 +733,7 @@ "label.default.network.guestcidraddress.isolated.network": "Default guest CIDR for Isolated Networks", "label.defaultnetwork": "Default Network", "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.asnrange": "Delete AS Range", @@ -766,13 +765,13 @@ "label.delete.portforward.rules": "Delete port forward rules", "label.delete.project": "Delete project", "label.delete.project.role": "Delete project role", -"label.delete.role": "Delete role", -"label.delete.rule": "Delete rule", -"label.delete.setting": "Delete setting", +"label.delete.role": "Delete Role", +"label.delete.rule": "Delete Rule", +"label.delete.setting": "Delete Setting", "label.delete.snapshot.policy": "Delete Snapshot policy", "label.delete.srx": "Delete SRX", "label.delete.sslcertificate": "Delete SSL certificate", -"label.delete.tag": "Remove tag", +"label.delete.tag": "Remove Tag", "label.delete.term": "Delete term", "label.delete.traffic.type": "Delete traffic type", "label.delete.tungsten.address.group": "Delete Address Group", @@ -802,13 +801,13 @@ "label.deployasis": "Read Instance settings from OVA", "label.deploymentplanner": "Deployment planner", "label.desc.db.stats": "Database Statistics", -"label.desc.importexportinstancewizard": "Import and export Instances to/from an existing VMware or KVM cluster.", +"label.desc.importexportinstancewizard": "Import and export Instances to/from an existing VMware or KVM Cluster.", "label.desc.import.ext.kvm.wizard": "Import Instance from remote KVM host", "label.desc.import.local.kvm.wizard": "Import QCOW2 image from Local Storage", "label.desc.import.shared.kvm.wizard": "Import QCOW2 image from Shared Storage", "label.desc.import.unmanage.volume": "Import and unmanage volume on Storage Pools", "label.desc.ingesttinstancewizard": "Ingest instances from an external KVM host", -"label.desc.importmigratefromvmwarewizard": "Import instances from VMware into a KVM cluster", +"label.desc.importmigratefromvmwarewizard": "Import instances from VMware into a KVM Cluster", "label.desc.usage.stats": "Usage Server Statistics", "label.description": "Description", "label.destaddressgroupuuid": "Destination Address Group", @@ -847,17 +846,17 @@ "label.disable.custom.action": "Disable Custom Action", "label.disable.extension": "Disable Extension", "label.disable.host": "Disable host", -"label.disable.network.offering": "Disable Network offering", +"label.disable.network.offering": "Disable Network Offering", "label.disable.provider": "Disable provider", "label.disable.storage": "Disable storage pool", -"label.disable.vpc.offering": "Disable VPC offering", +"label.disable.vpc.offering": "Disable VPC Offering", "label.disable.vpn": "Disable remote access VPN", "label.disable.webhook": "Disable Webhook", "label.disabled": "Disabled", "label.disconnected": "Last disconnected", "label.discover.gpu.devices": "Discover GPU devices", "label.disk": "Disk", -"label.disk.offerings": "Disk offerings", +"label.disk.offerings": "Disk Offerings", "label.disk.path": "Disk Path", "label.disk.tooltip": "Disk Image filename in the selected Storage Pool", "label.disk.selection": "Disk selection", @@ -878,9 +877,9 @@ "label.diskkbswrite": "Disk write (KiB)", "label.diskread": "Disk read", "label.diskwrite": "Disk write", -"label.diskoffering": "Disk offering", -"label.diskofferingdisplaytext": "Disk offering", -"label.diskofferingid": "Disk offering", +"label.diskoffering": "Disk Offering", +"label.diskofferingdisplaytext": "Disk Offering", +"label.diskofferingid": "Disk Offering", "label.disksize": "Disk size (in GB)", "label.disksizeallocated": "Disk allocated", "label.disksizeallocatedgb": "Allocated", @@ -901,7 +900,7 @@ "label.domain": "Domain", "label.domain.id": "Domain ID", "label.domain.name": "Domain name", -"label.domain.router": "Domain router", +"label.domain.router": "Domain Router", "label.domain.suffix": "DNS domain suffix (i.e., xyz.com)", "label.domainid": "Domain", "label.domainname": "Domain", @@ -941,15 +940,15 @@ "label.edge.zone": "Edge Zone", "label.edit": "Edit", "label.edit.account": "Edit Account", -"label.edit.acl.list": "Edit ACL list", +"label.edit.acl": "Edit ACL", "label.edit.acl.rule": "Edit ACL rule", "label.edit.autoscale.vmprofile": "Edit AutoScale Instance Profile", "label.edit.project.details": "Edit project details", "label.edit.project.role": "Edit project role", -"label.edit.role": "Edit role", -"label.edit.rule": "Edit rule", +"label.edit.role": "Edit Role", +"label.edit.rule": "Edit Rule", "label.edit.secondary.ips": "Edit secondary IPs", -"label.edit.tags": "Edit tags", +"label.edit.tags": "Edit Tags", "label.edit.traffic.type": "Edit traffic type", "label.edit.user": "Edit User", "label.egress": "Egress", @@ -962,11 +961,11 @@ "label.enable.custom.action": "Enable Custom Action", "label.enable.extension": "Enable Extension", "label.enable.host": "Enable Host", -"label.enable.network.offering": "Enable Network offering", +"label.enable.network.offering": "Enable Network Offering", "label.enable.oauth": "Enable OAuth Login", "label.enable.provider": "Enable provider", -"label.enable.storage": "Enable storage pool", -"label.enable.vpc.offering": "Enable VPC offering", +"label.enable.storage": "Enable Storage Pool", +"label.enable.vpc.offering": "Enable VPC Offering", "label.enable.vpn": "Enable remote access VPN", "label.enable.webhook": "Enable Webhook", "label.enabled": "Enabled", @@ -1061,12 +1060,12 @@ "label.firewall": "Firewall", "label.firewall.policy": "Firewall Policy", "label.firewallpolicy": "Firewall Policy", -"label.firewallrule": "Firewall rule", +"label.firewallrule": "Firewall Rule", "label.firewallruleuuid": "Firewall Rule", "label.firstname": "First name", "label.firstname.lower": "firstname", "label.fix.errors": "Fix errors", -"label.fixed": "Fixed offering", +"label.fixed": "Fixed Offering", "label.for": "for", "label.forcks": "For CKS", "label.forbidden": "Forbidden", @@ -1196,7 +1195,7 @@ "label.hosttags.implicit.description": "The host tags defined by CloudStack Agent", "label.hourly": "Hourly", "label.hypervisor": "Hypervisor", -"label.hypervisor.capabilities": "Hypervisor capabilities", +"label.hypervisor.capabilities": "Hypervisor Capabilities", "label.hypervisor.type": "Hypervisor type", "label.hypervisors": "Hypervisors", "label.hypervisorsnapshotreserve": "Hypervisor Snapshot reserve", @@ -1220,10 +1219,10 @@ "label.image.type": "Image type", "label.images": "Images", "label.imagestoreid": "Secondary Storage", -"label.import.backup.offering": "Import backup offering", +"label.import.backup.offering": "Import Backup Offering", "label.import.instance": "Import Instance", -"label.import.offering": "Import offering", -"label.import.role": "Import role", +"label.import.offering": "Import Offering", +"label.import.role": "Import Role", "label.import.volume": "Import Volume", "label.inactive": "Inactive", "label.inbuilt": "Inbuilt", @@ -1238,12 +1237,12 @@ "label.initial": "Inital", "label.initialized": "Initalized", "label.insideportprofile": "Inside port profile", -"label.installwizard.addzoneintro.title": "Let's add a zone", +"label.installwizard.addzoneintro.title": "Let's add a Zone", "label.installwizard.subtitle": "This guide will aid you in setting up your CloudStack™ installation", "label.installwizard.title": "Hello and welcome to CloudStack™", "label.instance": "Instance", "label.instance.conversion.support": "Instance Conversion Supported", -"label.instance.groups": "Instance groups", +"label.instance.groups": "Instance Groups", "label.instance.name": "Instance name", "label.instancename": "Internal name", "label.instanceport": "Instance port", @@ -1366,18 +1365,18 @@ "label.keyboardtype": "Keyboard type", "label.keypair": "SSH key pair", "label.keypairs": "SSH key pair(s)", -"label.kubeconfig.cluster": "Kubernetes cluster config", +"label.kubeconfig.cluster": "Kubernetes Cluster config", "label.kubernetes": "Kubernetes", -"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] cloud@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", -"label.kubernetes.cluster": "Kubernetes cluster", +"label.kubernetes.access.details": "The kubernetes nodes can be accessed via ssh using:
ssh -i [ssh_key] -p [port_number] cloud@[public_ip_address]

where,
ssh_key: points to the ssh private key file corresponding to the key that was associated while creating the Kubernetes Cluster. If no ssh key was provided during Kubernetes cluster creation, use the ssh private key of the management server.
port_number: can be obtained from the Port Forwarding Tab (Public Port column)", "label.kubernetes.cluster.add.nodes.to.cluster": "Add nodes to Kubernetes cluster", -"label.kubernetes.cluster.create": "Create Kubernetes cluster", -"label.kubernetes.cluster.delete": "Delete Kubernetes cluster", -"label.kubernetes.cluster.scale": "Scale Kubernetes cluster", -"label.kubernetes.cluster.start": "Start Kubernetes cluster", -"label.kubernetes.cluster.stop": "Stop Kubernetes cluster", "label.kubernetes.cluster.remove.nodes.from.cluster": "Remove nodes from Kubernetes cluster", -"label.kubernetes.cluster.upgrade": "Upgrade Kubernetes cluster", +"label.kubernetes.cluster": "Kubernetes Cluster", +"label.kubernetes.cluster.create": "Create Kubernetes Cluster", +"label.kubernetes.cluster.delete": "Delete Kubernetes Cluster", +"label.kubernetes.cluster.scale": "Scale Kubernetes Cluster", +"label.kubernetes.cluster.start": "Start Kubernetes Cluster", +"label.kubernetes.cluster.stop": "Stop Kubernetes Cluster", +"label.kubernetes.cluster.upgrade": "Upgrade Kubernetes Cluster", "label.kubernetes.dashboard": "Kubernetes dashboard UI", "label.kubernetes.dashboard.create.token": "Create token for Kubernetes dashboard", "label.kubernetes.dashboard.create.token.desc": "Since Kubernetes v1.24.0, there is no auto-generation of secret-based service Account token due to security reason. You need to create a service Account and an optional long-lived Bearer Token for the service Account.", @@ -1407,9 +1406,9 @@ "label.launch": "Launch", "label.launch.vm": "Launch Instance", "label.launch.vm.and.stay": "Launch Instance & stay on this page", -"label.launch.vnf.appliance": "Launch VNF appliance", -"label.launch.vnf.appliance.and.stay": "Launch VNF appliance & stay on this page", -"label.launch.zone": "Launch zone", +"label.launch.vnf.appliance": "Launch VNF Appliance", +"label.launch.vnf.appliance.and.stay": "Launch VNF Appliance & stay on this page", +"label.launch.zone": "Launch Zone", "label.lb.algorithm.leastconn": "Least connections", "label.lb.algorithm.roundrobin": "Round-robin", "label.lb.algorithm.source": "Source", @@ -1423,8 +1422,8 @@ "label.lbruleid": "Load balancer ID", "label.lbtype": "Load balancer type", "label.ldap": "LDAP", -"label.ldap.configuration": "LDAP configuration", -"label.ldap.group.name": "LDAP group", +"label.ldap.configuration": "LDAP Configuration", +"label.ldap.group.name": "LDAP Group", "label.level": "Level", "label.license.agreements": "License agreements", "label.limit": "Limit", @@ -1438,11 +1437,11 @@ "label.list.ciscoasa1000v": "ASA 1000v", "label.list.ciscovnmc": "Cisco VNMC", "label.list.nodes": "List nodes", -"label.list.pods": "List pods", +"label.list.pods": "List Pods", "label.list.services": "List services", "label.list.vmware.vcenter.vms": "List VMware Instances", "label.livepatch": "Live patch Network's router(s)", -"label.load.balancer": "Load balancer", +"label.load.balancer": "Load Balancer", "label.loadbalancerinstance": "Assigned Instances", "label.loadbalancerrule": "Load balancing rule", "label.loadbalancing": "Load balancing", @@ -1484,8 +1483,8 @@ "label.managementserverid": "Management server", "label.managementservername": "Management server", "label.management.ips": "Management IP addresses", -"label.management.server": "Management server", -"label.management.servers": "Management servers", +"label.management.server": "Management Server", +"label.management.servers": "Management Servers", "label.management.server.peers": "Peers", "label.managementservers": "Number of management servers", "label.matchall": "Match all", @@ -1504,7 +1503,7 @@ "label.maxgpu": "Max. GPUs", "label.maxguestslimit": "Max guest limit", "label.maxheads": "Max. heads", -"label.maxhostspercluster": "Max hosts per cluster", +"label.maxhostspercluster": "Max hosts per Cluster", "label.maximum": "Maximum", "label.maxinstance": "Max Instances", "label.maxiops": "Max IOPS", @@ -1513,7 +1512,7 @@ "label.maxnetwork": "Max. Networks", "label.maxobjectstorage": "Max. Object Storage (GiB)", "label.maxprimarystorage": "Max. primary storage (GiB)", -"label.maxproject": "Max. projects", +"label.maxproject": "Max. Projects", "label.maxpublicip": "Max. public IPs", "label.maxresolutionx": "Max. resolution X", "label.maxresolutiony": "Max. resolution Y", @@ -1522,8 +1521,8 @@ "label.maxsnapshot": "Max. Snapshots", "label.maxtemplate": "Max. Templates", "label.maxuservm": "Max. User Instances", -"label.maxvolume": "Max. volumes", "label.maxvgpuperphysicalgpu": "Max. vGPUs per physical GPU", +"label.maxvolume": "Max. Volumes", "label.maxvpc": "Max. VPCs", "label.may.continue": "You may now continue.", "label.mb.memory": "MB memory", @@ -1543,8 +1542,8 @@ "label.memoryused": "Used memory", "label.memoryusedgb": "Memory used", "label.memused": "Memory usage", -"label.menu.security.groups": "Security groups", -"label.menu.service.offerings": "Service offerings", +"label.menu.security.groups": "Security Groups", +"label.menu.service.offerings": "Service Offerings", "label.metadata": "Metadata", "label.metadata.description": "Metadata of the Object", "label.metadata.upload.description": "Set metadata for the object", @@ -1556,8 +1555,8 @@ "label.migrate.instance.to.ps": "Migrate Instance to another primary storage", "label.migrate.instance.single.storage": "Migrate all volume(s) of the Instance to a single primary storage", "label.migrate.instance.specific.storages": "Migrate volume(s) of the Instance to specific primary storages", -"label.migrate.systemvm.to": "Migrate system VM to", -"label.migrate.volume": "Migrate volume", +"label.migrate.systemvm.to": "Migrate System VM to", +"label.migrate.volume": "Migrate Volume", "message.memory.usage.info.hypervisor.additionals": "The data shown may not reflect the actual memory usage if the Instance does not have the additional hypervisor tools installed", "message.memory.usage.info.negative.value": "If the Instance's memory usage cannot be obtained from the hypervisor, the lines for free memory in the raw data graph and memory usage in the percentage graph will be disabled", "message.migrate.volume.tooltip": "Volume can be migrated to any suitable storage pool. Admin has to choose the appropriate disk offering to replace, that supports the new storage pool", @@ -1620,14 +1619,14 @@ "label.netscaler.vpx": "NetScaler VPX LoadBalancer", "label.network": "Network", "label.network.acl": "Network ACL", -"label.network.acl.lists": "Network ACL lists", +"label.network.acls": "Network ACLs", "label.network.addvm": "Add Network to Instance", "label.network.desc": "Network desc", -"label.network.domain": "Network domain", +"label.network.domain": "Network Domain", "label.network.label.display.for.blank.value": "Use default gateway", "label.network.name": "Network name", -"label.network.offering": "Network offering", -"label.network.offerings": "Network offerings", +"label.network.offering": "Network Offerings", +"label.network.offerings": "Network Offerings", "label.network.policy": "Network Policy", "label.network.restart.required": "Network restart required", "label.network.route.table": "Network route table", @@ -1644,9 +1643,9 @@ "label.networklimit": "Network limits", "label.networkmode": "Network Mode", "label.networkname": "Network name", -"label.networkofferingdisplaytext": "Network offering", -"label.networkofferingid": "Network offering", -"label.networkofferingname": "Network offering", +"label.networkofferingdisplaytext": "Network Offering", +"label.networkofferingid": "Network Offering", +"label.networkofferingname": "Network Offering", "label.networkrate": "Network rate (Mb/s)", "label.networkread": "Network read", "label.networks": "Networks", @@ -1656,9 +1655,9 @@ "label.never": "Never", "label.new": "New", "label.new.autoscale.vmgroup": "New AutoScaling Group", -"label.new.instance.group": "New Instance group", +"label.new.instance.group": "New Instance Group", "label.new.password": "New password", -"label.new.project": "New project", +"label.new.project": "New Project", "label.new.secondaryip.description": "Enter new secondary IP address", "label.new.tag": "New tag", "label.new.vm": "New Instance", @@ -1701,9 +1700,9 @@ "label.nsx.provider.port": "NSX provider port", "label.nsx.provider.username": "NSX provider username", "label.nsx.provider.password": "NSX provider password", -"label.nsx.provider.edgecluster": "NSX provider edge cluster", +"label.nsx.provider.edgecluster": "NSX provider edge Cluster", "label.nsx.provider.tier0gateway": "NSX provider tier-0 gateway", -"label.nsx.provider.transportzone": "NSX provider transport zone", +"label.nsx.provider.transportzone": "NSX provider transport Zone", "label.nsx.supports.internal.lb": "Enable NSX internal LB service", "label.nsx.supports.lb": "Enable NSX LB service", "label.num.cpu.cores": "# of CPU cores", @@ -1711,7 +1710,7 @@ "label.number": "#Rule", "label.numretries": "Number of retries", "label.nvpdeviceid": "ID", -"label.oauth.configuration": "OAuth configuration", +"label.oauth.configuration": "OAuth Configuration", "label.oauth.verification": "OAuth verification", "label.ocfs2": "OCFS2", "label.object.storage" : "Object Storage", @@ -1729,7 +1728,7 @@ "label.of.month": "of month", "label.offerha": "Offer HA", "label.offeringid": "Offering ID", -"label.offeringtype": "Compute offering type", +"label.offeringtype": "Compute Offering type", "label.ok": "OK", "label.only.end.date.and.time": "Only end date and time", "label.only.start.date.and.time": "Only start date and time", @@ -1807,7 +1806,7 @@ "label.pathready": "Path Ready", "label.pathstate": "Path State", "label.patp": "Palo Alto threat profile", -"label.pavr": "Virtual router", +"label.pavr": "Virtual Router", "label.payload": "Payload", "label.payloadurl": "Payload URL", "label.pcidevice": "GPU", @@ -1821,7 +1820,7 @@ "label.pending.jobs": "Pending Jobs", "label.pendingjobscount": "Number Of pending jobs", "label.per.account": "Per Account", -"label.per.zone": "Per zone", +"label.per.zone": "Per Zone", "label.percentage": "Percentage", "label.perfectforwardsecrecy": "Perfect forward secrecy", "label.perform.fresh.checks": "Perform fresh checks", @@ -1853,7 +1852,7 @@ "label.powerflex.gateway": "Gateway", "label.powerflex.gateway.password": "Gateway password", "label.powerflex.gateway.username": "Gateway username", -"label.powerflex.storage.pool": "Storage pool", +"label.powerflex.storage.pool": "Storage Pool", "label.powerstate": "Power state", "label.preferred": "Preferred", "label.prefix": "Prefix", @@ -1870,13 +1869,13 @@ "label.flashArray.username.tooltip": "The username with edit privileges", "label.flashArray.url.tooltip": "URL designating the Flash Array endpoint, formatted as: http[s]://HOSTNAME:PORT?pod=NAME&hostgroup=NAME[&skipTlsValidation=true][&postCopyWaitMs=#][&keyttl=#][&connectTimeoutMs=#][&apiLoginVersion=#][&apiVersion=#] where values in [] are optional.", "label.primary": "Primary", -"label.primary.storage": "Primary storage", -"label.primary.storage.allocated": "Primary storage allocated", -"label.primary.storage.used": "Primary storage used", -"label.primarystoragelimit": "Primary storage limits (GiB)", -"label.primarystoragetotal": "Primary storage", +"label.primary.storage": "Primary Storage", +"label.primary.storage.allocated": "Primary Storage allocated", +"label.primary.storage.used": "Primary Storage used", +"label.primarystoragelimit": "Primary Storage limits (GiB)", +"label.primarystoragetotal": "Primary Storage", "label.privatemtu": "Private Interface MTU", -"label.private.gateway": "Private gateway", +"label.private.gateway": "Private Gateway", "label.private.interface": "Private interface", "label.private.registry": "Private registry", "label.privateinterface": "Private interface", @@ -1886,7 +1885,7 @@ "label.privateport": "Private port", "label.profilename": "Profile", "label.project": "Project", -"label.project.invitation": "Project invitations", +"label.project.invitation": "Project Invitations", "label.project.name": "Project name", "label.project.owner": "Project owner(s)", "label.project.role": "Project role", @@ -1914,7 +1913,7 @@ "label.publicmtu": "Public Interface MTU", "label.public.interface": "Public interface", "label.public.ip": "Public IP address", -"label.public.ip.addresses": "Public IP addresses", +"label.public.ip.addresses": "Public IP Addresses", "label.public.ips": "Public IP addresses", "label.public.lb": "Public LB", "label.public.traffic": "Public traffic", @@ -2002,6 +2001,7 @@ "label.register.template": "Register Template", "label.register.user.data": "Register User Data", "label.register.cni.config": "Register CNI Configuration", +"label.register.user.data.details": "Enter the User Data in plain text or in Base64 encoding. Up to 32KB of Base64 encoded User Data can be sent by default. The setting vm.userdata.max.length can be used to increase the limit to upto 1MB.", "label.reinstall.vm": "Reinstall Instance", "label.reject": "Reject", "label.related": "Related", @@ -2009,11 +2009,11 @@ "label.release": "Release", "label.release.account": "Release from Account", "label.release.dedicated.bgp.peer": "Release dedicated BGP peer", -"label.release.dedicated.cluster": "Release dedicated cluster", +"label.release.dedicated.cluster": "Release dedicated Cluster", "label.release.dedicated.host": "Release dedicated host", "label.release.dedicated.ipv4.subnet": "Release dedicated IPv4 subnet", -"label.release.dedicated.pod": "Release dedicated pod", -"label.release.dedicated.zone": "Release dedicated zone", +"label.release.dedicated.pod": "Release dedicated Pod", +"label.release.dedicated.zone": "Release dedicated Zone", "label.releasing.ip": "Releasing IP", "label.remote.instances": "Remote Instances", "label.remove": "Remove", @@ -2027,7 +2027,7 @@ "label.remove.ldap": "Remove LDAP", "label.remove.logical.network": "Remove Network from logical router", "label.remove.logical.router": "Remove logical router", -"label.remove.network.offering": "Remove Network offering", +"label.remove.network.offering": "Remove Network Offering", "label.remove.network.route.table": "Remove Tungsten Fabric Network routing table", "label.remove.nodes": "Remove nodes from Kubernetes cluster", "label.remove.pf": "Remove port forwarding rule", @@ -2039,15 +2039,14 @@ "label.remove.rule": "Remove rule", "label.remove.ssh.key.pair": "Remove SSH Key pair", "label.remove.tungsten.tag": "Remove Tag", -"label.remove.user.data": "Remove Userdata", +"label.remove.user.data": "Remove User Data", "label.remove.vm.from.lb": "Remove Instance from load balancer rule", "label.remove.vmware.datacenter": "Remove VMware Datacenter", "label.remove.vpc": "Remove VPC", -"label.remove.vpc.offering": "Remove VPC offering", +"label.remove.vpc.offering": "Remove VPC Offering", "label.removed": "Removed", "label.removing": "Removing", "label.replace.acl": "Replace ACL", -"label.replace.acl.list": "Replace ACL list", "label.report.bug": "Ask a question or Report an issue", "label.request": "Request", "label.required": "Required", @@ -2066,8 +2065,8 @@ "label.reset.config.value": "Reset to default value", "label.reset.ssh.key.pair": "Reset SSH key pair", "label.reset.to.default": "Reset to default", -"label.reset.userdata.on.autoscale.vm.group": "Reset Userdata on AutoScale VM Group", -"label.reset.userdata.on.vm": "Reset Userdata on Instance", +"label.reset.user.data.on.autoscale.vm.group": "Reset User Data on AutoScale VM Group", +"label.reset.user.data.on.vm": "Reset User Data on Instance", "label.reset.vpn.connection": "Reset VPN connection", "label.resolution": "Resolution", "label.resource": "Resource", @@ -2159,17 +2158,17 @@ "label.search": "Search", "label.secondary.isolated.vlan.type.isolated": "Isolated", "label.secondary.isolated.vlan.type.promiscuous": "Promiscuous", -"label.secondary.storage": "Secondary storage", -"label.secondary.storage.vm": "Secondary storage VM", +"label.secondary.storage": "Secondary Storage", +"label.secondary.storage.vm": "Secondary Storage VM", "label.secondaryips": "Secondary IPs", -"label.secondarystoragelimit": "Secondary storage limits (GiB)", +"label.secondarystoragelimit": "Secondary Storage limits (GiB)", "label.secretkey": "Secret key", "label.secured": "Secured", -"label.security.groups": "Security groups", -"label.securitygroup": "Security group", -"label.securitygroupenabled": "Security groups enabled", +"label.security.groups": "Security Groups", +"label.securitygroup": "Security Group", +"label.securitygroupenabled": "Security Groups enabled", "label.securitygroups": "Security groups", -"label.securitygroupsenabled": "Security groups enabled", +"label.securitygroupsenabled": "Security Groups enabled", "label.select": "Select", "label.see.more.info.cpu.usage": "See more info about CPU usage", "label.see.more.info.memory.usage": "See more info about memory usage", @@ -2177,20 +2176,20 @@ "label.see.more.info.disk.usage": "See more info about disk usage", "label.see.more.info.shown.charts": "See more info about the shown charts", "label.select-view": "Select view", -"label.select.a.zone": "Select a zone", "label.select.all": "Select all", "label.select.columns": "Select columns", +"label.select.a.zone": "Select a Zone", "label.select.deployment.infrastructure": "Select deployment infrastructure", "label.select.guest.os.type": "Please select the guest OS type", "label.select.network": "Select Network", "label.select.period": "Select period", -"label.select.project": "Select project", -"label.select.projects": "Select projects", -"label.select.ps": "Select primary storage", +"label.select.project": "Select Project", +"label.select.projects": "Select Projects", +"label.select.ps": "Select Primary Storage", "label.select.root.disk": "Select the ROOT disk", "label.select.source.vcenter.datacenter": "Select the source VMware vCenter Datacenter", "label.select.tier": "Select Network Tier", -"label.select.zones": "Select zones", +"label.select.zones": "Select Zones", "label.select.2fa.provider": "Select the provider", "label.selected.storage": "Selected storage", "label.self": "Mine", @@ -2201,26 +2200,26 @@ "label.sequence": "Sequence", "label.server": "Server", "label.server.certificate": "Server certificate", -"label.serviceip": "Service IP", +"label.serviceip": "Management Service IP", "label.service.connectivity.distributedroutercapabilitycheckbox": "Distributed router", "label.service.connectivity.regionlevelvpccapabilitycheckbox": "Region level VPC", -"label.service.group": "Service group", -"label.serviceip": "Management IP", +"label.service.group": "Service Group", +"label.management.ip": "Management IP", "label.service.lb.elasticlbcheckbox": "Elastic LB", "label.service.lb.inlinemodedropdown": "Mode", "label.service.lb.lbisolationdropdown": "LB isolation", "label.service.lb.netscaler.servicepackages": "Netscaler service packages", "label.service.lb.netscaler.servicepackages.description": "Service package description", -"label.service.offering": "Service offering", "label.service.offering.controlnodes": "Compute offering for Control Nodes", "label.service.offering.etcdnodes": "Compute offering for etcd Nodes", "label.service.offering.workernodes": "Compute offering for Worker Nodes", +"label.service.offering": "Service Offering", "label.service.staticnat.associatepublicip": "Associate public IP", "label.service.staticnat.elasticipcheckbox": "Elastic IP", "label.servicegroupuuid": "Service Group", "label.servicelist": "Services", -"label.serviceofferingid": "Compute offering", -"label.serviceofferingname": "Compute offering", +"label.serviceofferingid": "Compute Offering", +"label.serviceofferingname": "Compute Offering", "label.sessions": "Active client sessions", "label.set.default.nic": "Set default NIC", "label.set.reservation": "Set reservation", @@ -2291,25 +2290,26 @@ "label.srctaguuid": "Source Tag", "label.srx": "SRX", "label.srx.firewall": "Juniper SRX firewall", -"label.ssh.key.pairs": "SSH key pairs", "label.storageaccessgroups": "Storage Access Groups", "label.clusterstorageaccessgroups": "Cluster Storage Access Groups", "label.podstorageaccessgroups": "Pod Storage Access Groups", "label.zonestorageaccessgroups": "Zone Storage Access Groups", +"label.ssh.key.pairs": "SSH Key Pairs", "label.uefi.supported": "UEFI supported", "label.unregister.extension": "Unregister Extension", "label.usediops": "IOPS used", -"label.userdataid": "Userdata ID", -"label.userdataname": "Userdata name", -"label.userdatadetails": "Userdata details", -"label.userdataparams": "Userdata parameters", -"label.userdatapolicy": "Userdata link policy", -"label.userdata.text": "Manual Userdata entry", -"label.userdata.registered": "Stored Userdata", -"label.userdata.do.override": "Userdata override", -"label.userdata.do.append": "Userdata append", -"label.userdatapolicy.tooltip": "Userdata linked to the Template can be overridden by Userdata provided during Instance deploy. Select the override policy as required.", +"label.user.data.id": "User Data ID", +"label.user.data.name": "User Data name", +"label.user.data.details": "User Data details", +"label.user.data.params": "User Data parameters", +"label.user.data.policy": "User Data link policy", +"label.user.data.text": "Manual User Data entry", +"label.user.data.registered": "Stored User Data", +"label.user.data.do.override": "User Data override", +"label.user.data.do.append": "User Data append", +"label.user.data.policy.tooltip": "User Data linked to the Template can be overridden by User Data provided during Instance deploy. Select the override policy as required.", "label.user.data": "User Data", +"label.user.data.library": "User Data Library", "label.ssh.port": "SSH port", "label.sshkeypair": "New SSH key pair", "label.sshkeypairs": "SSH key pairs", @@ -2336,7 +2336,7 @@ "label.state.reported": "Reported State", "label.staticnat": "Static NAT", "label.static": "Static", -"label.static.routes": "Static routes", +"label.static.routes": "Static Routes", "label.status": "Status", "label.step.1": "Step 1", "label.step.2": "Step 2", @@ -2362,9 +2362,9 @@ "label.stopping": "Stopping", "label.storage": "Storage", "label.storage.migration.required": "Storage migration required", -"label.storage.tags": "Storage tags", +"label.storage.tags": "Storage Tags", "label.storage.traffic": "Storage traffic", -"label.storageid": "Primary storage", +"label.storageid": "Primary Storage", "label.storagemotionenabled": "Storage motion enabled", "label.storagepolicy": "Storage policy", "label.storagepool": "Storage pool", @@ -2392,12 +2392,12 @@ "label.supportspublicaccess": "Supports public access", "label.supportsstrechedl2subnet": "Supports stretched L2 subnet", "label.supportsvmautoscaling": "Supports auto scaling", -"label.suspend.project": "Suspend project", +"label.suspend.project": "Suspend Project", "label.switch.type": "Switch type", -"label.sync.storage": "Sync storage pool", +"label.sync.storage": "Sync Storage Pool", "label.system.ip.pool": "System Pool", -"label.system.offering": "System offering", -"label.system.offerings": "System offerings", +"label.system.offering": "System Offering", +"label.system.offerings": "System Offerings", "label.system.service.offering": "System service offering", "label.system.vm": "System VM", "label.system.vms": "System VMs", @@ -2466,6 +2466,7 @@ "label.threshold": "Threshold", "label.threshold.description": "Value for which the Counter will be evaluated with the Operator selected", "label.thursday": "Thursday", +"label.tier0gateway": "Tier-0 Gateway", "label.time": "Time", "label.timeout": "Timeout", "label.timeout.in.second ": " Timeout (seconds)", @@ -2479,11 +2480,12 @@ "label.total": "Total", "label.total.network": "Total Networks", "label.total.vms": "Total Instances", -"label.total.volume": "Total volumes", +"label.total.volume": "Total Volumes", "label.totalcpu": "Total CPU", "label.traffic.label": "Traffic label", "label.traffic.types": "Traffic types", "label.traffictype": "Traffic type", +"label.transportzone": "Transport Zone", "label.transportzoneuuid": "Transport zone UUID", "label.trigger.shutdown": "Trigger Safe Shutdown", "label.true": "True", @@ -2571,8 +2573,8 @@ "label.upload.resource.icon": "Upload icon", "label.upload.template.from.local": "Upload Template from local", "label.upload.volume": "Upload volume", -"label.upload.volume.from.local": "Upload volume from local", -"label.upload.volume.from.url": "Upload volume from URL", +"label.upload.volume.from.local": "Upload Volume from local", +"label.upload.volume.from.url": "Upload Volume from URL", "label.url": "URL", "label.usage.explanation": "Note: Only the usage server that owns the active usage job is shown here.", "label.usage": "Usage", @@ -2599,11 +2601,9 @@ "label.use.router.ip.resolver": "Use Virtual Router IP as resolver", "label.used": "Used", "label.usehttps": "Use HTTPS", -"label.usenewdiskoffering": "Replace disk offering?", +"label.usenewdiskoffering": "Replace Disk Offering?", "label.user": "User", "label.user.conflict": "Conflict", -"label.userdata": "Userdata", -"label.userdatal2": "User data", "label.username": "Username", "label.username.tooltip": "The Username for the Host", "label.users": "Users", @@ -2643,11 +2643,11 @@ "label.viewing": "Viewing", "label.virtualmachine": "Instance", "label.virtualmachinecount": "Instances Count", -"label.virtual.machine": "Virtual machine", -"label.virtual.machines": "Virtual machines", +"label.virtual.machine": "Virtual Machine", +"label.virtual.machines": "Virtual Machines", "label.virtual.network": "Virtual Network", "label.virtual.networking": "Virtual Networking", -"label.virtual.routers": "Virtual routers", +"label.virtual.routers": "Virtual Routers", "label.virtualmachineid": "Instance ID", "label.virtualmachinename": "Instance name", "label.virtualsize": "Virtual Size", @@ -2679,21 +2679,21 @@ "label.vmwaredcvcenter": "VMware datacenter vCenter", "label.vmwarenetworklabel": "VMware traffic label", "label.vnf.appliance": "VNF Appliance", -"label.vnf.appliances": "VNF appliances", +"label.vnf.appliances": "VNF Appliances", "label.vnf.appliance.add": "Add VNF Appliance", -"label.vnf.appliance.access.methods": "Management access information for this VNF appliance", -"label.vnf.app.action.destroy": "Destroy VNF appliance", -"label.vnf.app.action.edit": "Edit VNF appliance", -"label.vnf.app.action.expunge": "Expunge VNF appliance", -"label.vnf.app.action.migrate.to.host": "Migrate VNF appliance to another host", -"label.vnf.app.action.migrate.to.ps": "Migrate VNF appliance to another primary storage", -"label.vnf.app.action.recover": "Recover VNF appliance", -"label.vnf.app.action.scale": "Scale VNF appliance", -"label.vnf.app.action.start": "Start VNF appliance", -"label.vnf.app.action.stop": "Stop VNF appliance", -"label.vnf.app.action.reboot": "Reboot VNF appliance", -"label.vnf.app.action.reinstall": "Reinstall VNF appliance", -"label.vnf.cidr.list": "CIDR from which access to the VNF appliance’s Management interface should be allowed from", +"label.vnf.appliance.access.methods": "Management access information for this VNF Appliance", +"label.vnf.app.action.destroy": "Destroy VNF Appliance", +"label.vnf.app.action.edit": "Edit VNF Appliance", +"label.vnf.app.action.expunge": "Expunge VNF Appliance", +"label.vnf.app.action.migrate.to.host": "Migrate VNF Appliance to another host", +"label.vnf.app.action.migrate.to.ps": "Migrate VNF Appliance to another primary storage", +"label.vnf.app.action.recover": "Recover VNF Appliance", +"label.vnf.app.action.scale": "Scale VNF Appliance", +"label.vnf.app.action.start": "Start VNF Appliance", +"label.vnf.app.action.stop": "Stop VNF Appliance", +"label.vnf.app.action.reboot": "Reboot VNF Appliance", +"label.vnf.app.action.reinstall": "Reinstall VNF Appliance", +"label.vnf.cidr.list": "CIDR from which access to the VNF appliance's Management interface should be allowed from", "label.vnf.cidr.list.tooltip": "the CIDR list to forward traffic from to the VNF management interface. Multiple entries must be separated by a single comma character (,). The default value is 0.0.0.0/0.", "label.vnf.configure.management": "Configure Firewall and Port Forwarding rules for VNF's management interfaces", "label.vnf.configure.management.tooltip": "True by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. False otherwise. Learn what rules are configured at http://docs.cloudstack.apache.org/en/latest/adminguide/networking/vnf_templates_appliances.html#deploying-vnf-appliances", @@ -2716,7 +2716,7 @@ "label.vnf.templates": "VNF templates", "label.vnf.template.register": "Register VNF template", "label.vnmc": "VNMC", -"label.volgroup": "Volume group", +"label.volgroup": "Volume Group", "label.volume": "Volume", "label.vms.empty": "No VMs available to be added to the Kubernetes cluster", "label.vms.remove.empty": "No external VMs present in the Kubernetes cluster to be removed", @@ -2727,7 +2727,7 @@ "label.volumechecksum": "MD5 checksum", "label.volumechecksum.description": "Use the hash that you created at the start of the volume upload procedure.", "label.volumefileupload": "Local file", -"label.volumegroup": "Volume group", +"label.volumegroup": "Volume Group", "label.volumeid": "Volume", "label.volumeids": "Volumes to be deleted", "label.volumelimit": "Volume limits", @@ -2739,21 +2739,21 @@ "label.vpcs": "VPCs", "label.vpc.gateway.ip": "VPC Gateway IP", "label.vpc.id": "VPC ID", -"label.vpc.offerings": "VPC offerings", -"label.vpc.virtual.router": "VPC virtual router", +"label.vpc.offerings": "VPC Offerings", +"label.vpc.virtual.router": "VPC Virtual Router", "label.vpc.restart.required": "VPC restart required", "label.vpcid": "VPC", "label.vpclimit": "VPC limits", "label.vpcname": "VPC", -"label.vpcoffering": "VPC offering", -"label.vpcofferingid": "VPC offering", +"label.vpcoffering": "VPC Offering", +"label.vpcofferingid": "VPC Offering", "label.vpn": "VPN", "label.vpn.connection": "VPN connection", "label.vpn.gateway": "VPN gateway", "label.vpn.users": "VPN Users", "label.vpncustomergateway": "IP address of the remote gateway", -"label.vpncustomergatewayid": "VPN customer gateway", "label.vramsize": "VRAM Size", +"label.vpncustomergatewayid": "VPN Customer Gateway", "label.vsmipaddress": "Nexus 1000v IP address", "label.vsmpassword": "Nexus 1000v password", "label.vsmusername": "Nexus 1000v username", @@ -2788,7 +2788,7 @@ "label.xenservertoolsversion61plus": "Original XS Version is 6.1+", "label.yes": "Yes", "label.yourinstance": "Your Instance", -"label.your.autoscale.vmgroup": "Your autoscaling group", +"label.your.autoscale.vmgroup": "Your Autoscaling Group", "label.zone": "Zone", "label.zone.dedicated": "Zone dedicated", "label.zone.details": "Zone details", @@ -2811,6 +2811,8 @@ "label.bucket.update": "Update Bucket", "label.bucket.delete": "Delete Bucket", "label.quotagib": "Quota in GiB", +"label.quotagb": "Quota in GB", +"label.edgecluster": "Edge Cluster", "label.encryption": "Encryption", "label.etcdnodes": "Number of etcd nodes", "label.versioning": "Versioning", @@ -2839,7 +2841,7 @@ "message.action.delete.autoscale.vmgroup": "Please confirm that you want to delete this autoscaling group.", "message.action.delete.backup.offering": "Please confirm that you want to delete this backup offering?", "message.action.delete.backup.repository": "Please confirm that you want to delete this backup repository?", -"message.action.delete.cluster": "Please confirm that you want to delete this cluster.", +"message.action.delete.cluster": "Please confirm that you want to delete this Cluster.", "message.action.delete.custom.action": "Please confirm that you want to delete this custom action.", "message.action.delete.domain": "Please confirm that you want to delete this domain.", "message.action.delete.extension": "Please confirm that you want to delete the extension", @@ -2860,7 +2862,7 @@ "message.action.delete.node": "Please confirm that you want to delete this node.", "message.action.delete.oauth.provider": "Please confirm that you want to delete the OAuth provider.", "message.action.delete.physical.network": "Please confirm that you want to delete this physical Network.", -"message.action.delete.pod": "Please confirm that you want to delete this pod.", +"message.action.delete.pod": "Please confirm that you want to delete this Pod.", "message.action.delete.secondary.storage": "Please confirm that you want to delete this secondary storage.", "message.action.delete.security.group": "Please confirm that you want to delete this security group.", "message.action.delete.snapshot": "Please confirm that you want to delete this Snapshot.", @@ -2869,7 +2871,7 @@ "message.action.delete.vgpu.profile": "Please confirm that you want to delete this vGPU profile.", "message.action.delete.volume": "Please confirm that you want to delete this volume. Note: this will not delete any Snapshots of this volume.", "message.action.delete.vpn.user": "Please confirm that you want to delete the VPN user.", -"message.action.delete.zone": "Please confirm that you want to delete this zone.", +"message.action.delete.zone": "Please confirm that you want to delete this Zone.", "message.action.destroy.sharedfs": "Please confirm that you want to destroy this Shared FileSystem.
Caution: This will delete all the data of the Shared FileSystem as well.", "message.action.destroy.instance": "Please confirm that you want to destroy the Instance.", "message.action.destroy.instance.with.backups": "Please confirm that you want to destroy the Instance. There may be backups associated with the Instance which will not be deleted.", @@ -2877,36 +2879,36 @@ "message.action.destroy.volume": "Please confirm that you want to destroy the volume.", "message.action.disable.2FA.user.auth": "Please confirm that you want to disable User two factor authentication.", "message.action.about.mandate.and.disable.2FA.user.auth": "Two factor authentication is mandated for the User, if this is disabled now User will need to setup two factor authentication again during next login.

Please confirm that you want to disable.", -"message.action.disable.cluster": "Please confirm that you want to disable this cluster.", +"message.action.disable.cluster": "Please confirm that you want to disable this Cluster.", "message.action.disable.disk.offering": "Please confirm that you want to disable this disk offering.", "message.action.disable.service.offering": "Please confirm that you want to disable this service offering.", "message.action.disable.system.service.offering": "Please confirm that you want to disable this system service offering.", "message.action.disable.physical.network": "Please confirm that you want to disable this physical Network.", -"message.action.disable.pod": "Please confirm that you want to disable this pod.", +"message.action.disable.pod": "Please confirm that you want to disable this Pod.", "message.action.disable.static.nat": "Please confirm that you want to disable static NAT.", -"message.action.disable.zone": "Please confirm that you want to disable this zone.", +"message.action.disable.zone": "Please confirm that you want to disable this Zone.", "message.action.discover.gpu.devices": "Please confirm that you want to discover GPU devices.", "message.action.download.iso": "Please confirm that you want to download this ISO.", "message.action.download.snapshot": "Please confirm that you want to download this Snapshot.", "message.action.download.template": "Please confirm that you want to download this Template.", "message.action.edit.nfs.mount.options": "Changes to NFS mount options will only take affect on cancelling maintenance mode which will cause the storage pool to be remounted on all KVM hosts with the new mount options.", -"message.action.enable.cluster": "Please confirm that you want to enable this cluster.", +"message.action.enable.cluster": "Please confirm that you want to enable this Cluster.", "message.action.enable.disk.offering": "Please confirm that you want to enable this disk offering.", "message.action.enable.service.offering": "Please confirm that you want to enable this service offering.", "message.action.enable.system.service.offering": "Please confirm that you want to enable this system service offering.", "message.action.enable.physical.network": "Please confirm that you want to enable this physical Network.", -"message.action.enable.pod": "Please confirm that you want to enable this pod.", -"message.action.enable.zone": "Please confirm that you want to enable this zone.", +"message.action.enable.pod": "Please confirm that you want to enable this Pod.", +"message.action.enable.zone": "Please confirm that you want to enable this Zone.", "message.action.expunge.sharedfs": "Please confirm that you want to expunge this Shared FileSystem.", "message.action.expunge.instance": "Please confirm that you want to expunge this Instance.", "message.action.expunge.instance.with.backups": "Please confirm that you want to expunge this Instance. There may be backups associated with the Instance which will not be deleted.", "message.action.host.enable.maintenance.mode": "Enabling maintenance mode will cause a live migration of all running Instances on this host to any available host.", "message.action.instance.reset.password": "Please confirm that you want to change the ROOT password for this Instance.", -"message.action.manage.cluster": "Please confirm that you want to manage the cluster.", +"message.action.manage.cluster": "Please confirm that you want to manage the Cluster.", "message.action.patch.router": "Please confirm that you want to live patch the router.
This operation is equivalent updating the router packages and restarting the Network without cleanup.", "message.action.patch.systemvm": "Please confirm that you want to patch the System VM.", -"message.action.primary.storage.scope.cluster": "Please confirm that you want to change the scope from zone to the specified cluster.
This operation will update the database and disconnect the storage pool from all hosts that were previously connected to the primary storage and are not part of the specified cluster.", -"message.action.primary.storage.scope.zone": "Please confirm that you want to change the scope from cluster to zone.
This operation will update the database and connect the storage pool to all hosts of the zone running the same hypervisor as set on the storage pool.", +"message.action.primary.storage.scope.cluster": "Please confirm that you want to change the scope from Zone to the specified Cluster.
This operation will update the database and disconnect the storage pool from all hosts that were previously connected to the primary storage and are not part of the specified cluster.", +"message.action.primary.storage.scope.zone": "Please confirm that you want to change the scope from Cluster to Zone.
This operation will update the database and connect the storage pool to all hosts of the zone running the same hypervisor as set on the storage pool.", "message.action.primarystorage.enable.maintenance.mode": "Warning: placing the primary storage into maintenance mode will cause all Instances using volumes from it to be stopped. Do you want to continue?", "message.action.quota.tariff.create.error.namerequired": "Please, inform a name for the quota tariff.", "message.action.quota.tariff.create.error.usagetyperequired": "Please, select the usage type of the quota tariff.", @@ -2929,7 +2931,7 @@ "message.action.revert.snapshot": "Please confirm that you want to revert the owning volume to this Snapshot.", "message.action.router.health.checks": "Health checks result will be fetched from router.", "message.action.router.health.checks.disabled.warning": "Please enable router health checks.", -"message.action.scale.kubernetes.cluster.warning": "Please do not manually scale the cluster if cluster auto scaling is enabled.", +"message.action.scale.kubernetes.cluster.warning": "Please do not manually scale the Cluster if cluster auto scaling is enabled.", "message.action.secondary.storage.read.only": "Please confirm that you want to make this secondary storage read only.", "message.action.secondary.storage.read.write": "Please confirm that you want to make this secondary storage read write.", "message.action.secure.host": "This will restart the host agent and libvirtd process after applying new X509 certificates, please confirm?", @@ -2942,7 +2944,7 @@ "message.action.stop.instance": "Please confirm that you want to stop this Instance.", "message.action.stop.router": "All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router.", "message.action.stop.systemvm": "Please confirm that you want to stop this system VM.", -"message.action.unmanage.cluster": "Please confirm that you want to unmanage the cluster.", +"message.action.unmanage.cluster": "Please confirm that you want to unmanage the Cluster.", "message.action.unmanage.instance": "Please confirm that you want to unmanage the Instance.", "message.action.unmanage.instances": "Please confirm that you want to unmanage the Instances.", "message.action.unmanage.virtualmachine": "Please confirm that you want to unmanage the Instance.", @@ -2954,7 +2956,7 @@ "message.add.egress.rule.failed": "Adding new egress rule failed.", "message.add.egress.rule.processing": "Adding new egress rule...", "message.add.failed": "Adding failed.", -"message.add.firewall": "Add a firewall to zone", +"message.add.firewall": "Add a firewall to Zone", "message.add.firewall.rule.failed": "Adding new Firewall rule failed", "message.add.firewall.rule.processing": "Adding new Firewall rule...", "message.add.firewallrule.failed": "Adding Firewall Rule failed", @@ -2977,22 +2979,22 @@ "message.remove.ip.v6.firewall.rule.success": "Removed IPv6 firewall rule", "message.add.netris.controller": "Add Netris Provider", "message.add.nsx.controller": "Add NSX Provider", -"message.add.network": "Add a new network for zone: ", -"message.add.network.acl.failed": "Adding network ACL list failed.", -"message.add.network.acl.processing": "Adding network ACL list...", +"message.add.network": "Add a new network for Zone: ", +"message.add.network.acl.failed": "Adding network ACL failed.", +"message.add.network.acl.processing": "Adding network ACL...", "message.add.network.failed": "Adding network failed.", "message.add.network.processing": "Adding network...", "message.add.new.gateway.to.vpc": "Please specify the information to add a new gateway to this VPC.", "message.add.physical.network.failed": "Adding physical network failed", "message.add.physical.network.processing": "Adding a new physical network...", -"message.add.pod": "Add a new pod for zone ", -"message.add.pod.during.zone.creation": "Each zone must contain one or more pods. We will add the first pod now. A pod contains hosts and primary storage servers, which you will add in a later step. First, configure a range of reserved IP addresses for CloudStack's internal management traffic. The reserved IP range must be unique for each zone in the cloud.", +"message.add.pod": "Add a new Pod for Zone ", +"message.add.pod.during.zone.creation": "Each Zone must contain one or more Pods. We will add the first pod now. A pod contains hosts and primary storage servers, which you will add in a later step. First, configure a range of reserved IP addresses for CloudStack's internal management traffic. The reserved IP range must be unique for each zone in the cloud.", "message.add.port.forward.failed": "Adding new port forwarding rule failed.", "message.add.port.forward.processing": "Adding new port forwarding rule...", "message.add.private.gateway.failed": "Adding private gateway failed.", "message.add.private.gateway.processing": "Adding private gateway...", "message.add.resource.description": "Add infrastructure resources", -"message.add.resource.hint": "Add infrastructure resources - pods, clusters, primary/secondary storages.", +"message.add.resource.hint": "Add infrastructure resources - Pods, Clusters, primary/secondary storages.", "message.add.routing.firewall.rule.failed": "Failed to add IPv4 Routing firewall rule", "message.add.routing.firewall.rule.processing": "Adding IPv4 Routing firewall rule...", "message.add.routing.firewall.rule.success": "Added IPv4 Routing firewall rule", @@ -3080,7 +3082,7 @@ "message.confirm.change.offering.for.volume": "Please confirm that you want to change disk offering for the volume", "message.confirm.change.service.offering.for.sharedfs": "Please confirm that you want to change the service offering for the Shared FileSystem.", "message.confirm.configure.ovs": "Are you sure you want to configure Ovs?", -"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.", @@ -3138,7 +3140,7 @@ "message.cpu.usage.info": "The CPU usage percentage can exceed 100% if the Instance has more than 1 vCPU or when CPU Cap is not enabled. This behavior happens according to the hypervisor being used (e.g: in KVM), due to how they account the stats", "message.create.bucket.failed": "Failed to create bucket.", "message.create.bucket.processing": "Bucket creation in progress", -"message.create.compute.offering": "Compute offering created", +"message.create.compute.offering": "Compute Offering created", "message.create.sharedfs.failed": "Failed to create Shared FileSystem.", "message.create.sharedfs.processing": "Shared FileSystem creation in progress.", "message.create.tungsten.public.network": "Create Tungsten-Fabric public Network", @@ -3150,7 +3152,7 @@ "message.create.snapshot.from.vmsnapshot.progress": "Snapshot creation in progress", "message.create.template.failed": "Failed to create template.", "message.create.template.processing": "Template creation in progress", -"message.create.volume.failed": "Failed to create volume.", +"message.create.volume.failed": "Failed to create Volume.", "message.create.volume.processing": "Volume creation in progress", "message.create.vpc.offering": "VPC offering created.", "message.create.vpn.customer.gateway.failed": "VPN customer gateway creation failed.", @@ -3160,23 +3162,23 @@ "message.creating.autoscale.scaledown.policy": "Creating ScaleDown policy", "message.creating.autoscale.scaleup.conditions": "Creating ScaleUp conditions", "message.creating.autoscale.scaleup.policy": "Creating ScaleUp policy", -"message.creating.cluster": "Creating cluster", +"message.creating.cluster": "Creating Cluster", "message.creating.guest.network": "Creating guest Network", "message.creating.physical.networks": "Creating physical Networks", -"message.creating.pod": "Creating pod", +"message.creating.pod": "Creating Pod", "message.creating.primary.storage": "Creating primary storage", "message.creating.secondary.storage": "Creating secondary storage", -"message.creating.zone": "Creating zone", +"message.creating.zone": "Creating Zone", "message.data.migration": "Data migration", "message.data.migration.progress": "Data migration between image stores", "message.datacenter.description": "Name of the datacenter on vCenter.", "message.datastore.description": "Name of the datastore on vCenter.", -"message.dedicate.zone": "Dedicating zone", +"message.dedicate.zone": "Dedicating Zone", "message.dedicated.zone.released": "Zone dedication released.", -"message.dedicating.cluster": "Dedicating cluster...", +"message.dedicating.cluster": "Dedicating Cluster...", "message.dedicating.host": "Dedicating host...", -"message.dedicating.pod": "Dedicating pod...", -"message.dedicating.zone": "Dedicating zone...", +"message.dedicating.pod": "Dedicating Pod...", +"message.dedicating.zone": "Dedicating Zone...", "message.delete.account.confirm": "Please confirm that you want to delete this account by entering the name of the account below.", "message.delete.account.failed": "Delete account failed", "message.delete.account.processing": "Deleting account", @@ -3216,31 +3218,31 @@ "message.deployasis": "Selected Template is Deploy As-Is i.e., the Instance is deployed by importing an OVA with vApps directly into vCenter. Root disk(s) resize is allowed only on stopped Instances for such Templates.", "message.desc.advanced.zone": "This is recommended and allows more sophisticated Network topologies. This Network model provides the most flexibility in defining guest Networks and providing custom Network offerings such as firewall, VPN, or load balancer support.", "message.desc.basic.zone": "Provide a single Network where each Instance is assigned an IP directly from the Network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering).", -"message.desc.core.zone": "Core Zones are intended for Datacenter based deployments and allow the full range of Networking and other functionality in Apache CloudStack. Core zones have a number of prerequisites and rely on the presence of shared storage and helper Instances.", -"message.desc.edge.zone": "Edge Zones are lightweight zones, designed for deploying in edge computing scenarios. They are limited in functionality but have far fewer prerequisites than core zones.

Please refer to the Apache CloudStack documentation for more information on Zone Types
http://docs.cloudstack.apache.org/en/latest/installguide/configuration.html#adding-a-zone", -"message.desc.cluster": "Each pod must contain one or more clusters. We will add the first cluster now. A cluster provides a way to group hosts. The hosts in a cluster all have identical hardware, run the same hypervisor, are on the same subnet, and access the same shared storage. Each cluster consists of one or more hosts and one or more primary storage servers.", +"message.desc.core.zone": "Core Zones are intended for Datacenter based deployments and allow the full range of Networking and other functionality in Apache CloudStack. Core Zones have a number of prerequisites and rely on the presence of shared storage and helper Instances.", +"message.desc.edge.zone": "Edge Zones are lightweight Zones, designed for deploying in edge computing scenarios. They are limited in functionality but have far fewer prerequisites than core zones.

Please refer to the Apache CloudStack documentation for more information on Zone Types
http://docs.cloudstack.apache.org/en/latest/installguide/configuration.html#adding-a-zone", +"message.desc.cluster": "Each Pod must contain one or more Clusters. We will add the first cluster now. A cluster provides a way to group hosts. The hosts in a cluster all have identical hardware, run the same hypervisor, are on the same subnet, and access the same shared storage. Each cluster consists of one or more hosts and one or more primary storage servers.", "message.desc.create.ssh.key.pair": "Please fill in the following data to create or register a ssh key pair.

(1) If public key is set, CloudStack will register the public key. You can use it through your private key.

(2) If public key is not set, CloudStack will create a new SSH key pair. In this case, please copy and save the private key. CloudStack will not keep it.
", "message.desc.created.ssh.key.pair": "Created a SSH key pair.", -"message.desc.host": "Each cluster must contain at least one host (computer) for guest Instances to run on. We will add the first host now. For a host to function in CloudStack, you must install hypervisor software on the host, assign an IP address to the host, and ensure the host is connected to the CloudStack management server.

Give the host's DNS or IP address, the user name (usually root) and password, and any labels you use to categorize hosts.", -"message.desc.importingestinstancewizard": "This feature only applies to libvirt based KVM instances. Only Stopped instances can be ingested", +"message.desc.host": "Each Cluster must contain at least one host (computer) for guest Instances to run on. We will add the first host now. For a host to function in CloudStack, you must install hypervisor software on the host, assign an IP address to the host, and ensure the host is connected to the CloudStack management server.

Give the host's DNS or IP address, the user name (usually root) and password, and any labels you use to categorize hosts.", "message.desc.import.ext.kvm.wizard": "Import libvirt domain from External KVM Host not managed by CloudStack", "message.desc.import.local.kvm.wizard": "Import QCOW2 image from Local Storage of selected KVM Host", "message.desc.import.shared.kvm.wizard": "Import QCOW2 image from selected Primary Storage Pool", "message.desc.import.unmanage.volume": "Please choose a storage pool that you want to import or unmanage volumes. The storage pool should be in Up status.
This feature only supports KVM.", "message.desc.importexportinstancewizard": "By choosing to manage an Instance, CloudStack takes over the orchestration of that Instance. Unmanaging an Instance removes CloudStack ability to manage it. In both cases, the Instance is left running and no changes are done to the VM on the hypervisor.

For KVM, managing a VM is an experimental feature.", -"message.desc.importmigratefromvmwarewizard": "By selecting an existing or external VMware Datacenter and an instance to import, CloudStack migrates the selected instance from VMware to KVM on a conversion host using virt-v2v and imports it into a KVM cluster", -"message.desc.primary.storage": "Each cluster must contain one or more primary storage servers. We will add the first one now. Primary storage contains the disk volumes for all the Instances running on hosts in the cluster. Use any standards-compliant protocol that is supported by the underlying hypervisor.", +"message.desc.importingestinstancewizard": "This feature only applies to libvirt based KVM instances. Only Stopped instances can be ingested", +"message.desc.importmigratefromvmwarewizard": "By selecting an existing or external VMware Datacenter and an instance to import, CloudStack migrates the selected instance from VMware to KVM on a conversion host using virt-v2v and imports it into a KVM Cluster", +"message.desc.primary.storage": "Each Cluster must contain one or more primary storage servers. We will add the first one now. Primary storage contains the disk volumes for all the Instances running on hosts in the cluster. Use any standards-compliant protocol that is supported by the underlying hypervisor.", "message.desc.register.template": "Hosted on download.cloudstack.org, these templates can be easily registered directly within CloudStack. Simply click Register Template for the templates you wish to use.", -"message.desc.reset.ssh.key.pair": "Please specify a ssh key pair that you would like to add to this Instance.", -"message.desc.secondary.storage": "Each zone must have at least one NFS or secondary storage server. We will add the first one now. Secondary storage stores Instance Templates, ISO images, and Instance disk volume Snapshots. This server must be available to all hosts in the zone.

Provide the IP address and exported path.", -"message.desc.register.user.data": "Please fill in the following data to register a User data.", "message.desc.register.cni.config": "Please fill in the following data to register CNI Configuration as user data.", +"message.desc.register.user.data": "Please fill in the following to register new User Data.", "message.desc.registered.user.data": "Registered a User Data.", +"message.desc.reset.ssh.key.pair": "Please specify a ssh key pair that you would like to add to this Instance.", +"message.desc.secondary.storage": "Each Zone must have at least one NFS or secondary storage server. We will add the first one now. Secondary storage stores Instance Templates, ISO images, and Instance disk volume Snapshots. This server must be available to all hosts in the zone.

Provide the IP address and exported path.", "message.desc.validationformat": "Specifies the format used to validate the parameter value, such as EMAIL, URL, UUID, DECIMAL, etc.", "message.desc.valueoptions": "Provide a comma-separated list of values that will appear as selectable options for this parameter", -"message.desc.zone": "A zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone.", -"message.desc.zone.edge": "A zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. An edge zone consists of one or more hosts (each of which provides local storage as primary storage servers). Only shared and L2 Networks can be deployed in such zones and functionalities that require secondary storages are not supported.", -"message.drs.plan.description": "The maximum number of live migrations allowed for DRS. Configure DRS under the settings tab before generating a plan or to enable automatic DRS for the cluster.", +"message.desc.zone": "A Zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more Pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone.", +"message.desc.zone.edge": "A Zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. An edge zone consists of one or more hosts (each of which provides local storage as primary storage servers). Only shared and L2 Networks can be deployed in such zones and functionalities that require secondary storages are not supported.", +"message.drs.plan.description": "The maximum number of live migrations allowed for DRS. Configure DRS under the settings tab before generating a plan or to enable automatic DRS for the Cluster.", "message.drs.plan.executed": "DRS plan executed successfully.", "message.zone.edge.local.storage": "Local storage will be used by default for User Instances and virtual routers", "message.detach.disk": "Are you sure you want to detach this disk?", @@ -3298,8 +3300,8 @@ "message.error.cidr": "CIDR is required", "message.error.cidr.or.cidrsize": "CIDR or cidr size is required", "message.error.cloudian.console": "Single-Sign-On failed for Cloudian management console. Please ask your administrator to fix integration issues.", -"message.error.cluster.description": "Please enter Kubernetes cluster description.", -"message.error.cluster.name": "Please enter cluster name.", +"message.error.cluster.description": "Please enter Kubernetes Cluster description.", +"message.error.cluster.name": "Please enter Cluster name.", "message.error.confirm.password": "Please confirm new password.", "message.error.confirm.text": "Please enter the confirmation text", "message.error.current.password": "Please enter current password.", @@ -3343,7 +3345,7 @@ "message.error.ipv6.address": "Please enter a valid IP v6 address.", "message.error.ipv6.gateway": "Please enter IpV6 Gateway", "message.error.ipv6.gateway.format": "Please enter a valid IPv6 Gateway.", -"message.error.kubecluster.name": "Please enter Kubernetes cluster name.", +"message.error.kubecluster.name": "Please enter Kubernetes Cluster name.", "message.error.kuberversion": "Please enter Kubernetes semantic version.", "message.error.limit.value": "The value must not be less than", "message.error.loading.setting": "There was an error loading these settings.", @@ -3377,7 +3379,7 @@ "message.error.remove.vm.schedule": "Removing Instance Schedule failed", "message.error.required.input": "Please enter input", "message.error.reset.config": "Unable to reset config to default value", -"message.error.retrieve.kubeconfig": "Unable to retrieve Kubernetes cluster config", +"message.error.retrieve.kubeconfig": "Unable to retrieve Kubernetes Cluster config", "message.error.routing.policy.term": "Community need to have the following format number:number", "message.error.s3nfs.path": "Please enter S3 NFS Path", "message.error.s3nfs.server": "Please enter S3 NFS Server", @@ -3394,12 +3396,13 @@ "message.error.sbdomain.username": "Please enter SMB domain username.", "message.error.secret.key": "Please enter secret key.", "message.error.select": "Please select option.", +"message.error.select.account.to.dedicate": "Please select an account to dedicate to.", "message.error.select.domain.to.dedicate": "Please select domain to dedicate to.", -"message.error.select.zone.type": "Please select zone type below.", +"message.error.select.zone.type": "Please select Zone type below.", "message.error.server": "Please enter server.", -"message.error.serviceoffering.for.cluster": "Please select service offering for Kubernetes cluster.", +"message.error.serviceoffering.for.cluster": "Please select service offering for Kubernetes Cluster.", "message.error.size": "Please enter size in GB.", -"message.error.size.for.cluster": "Please enter size for Kubernetes cluster.", +"message.error.size.for.cluster": "Please enter size for Kubernetes Cluster.", "message.error.smb.password": "Please enter SMB password.", "message.error.smb.username": "Please enter SMB username.", "message.error.specify.stickiness.method": "Please specify a stickiness method", @@ -3417,7 +3420,7 @@ "message.error.upload.template": "Template upload failed.", "message.error.upload.template.description": "Only one Template can be uploaded at a time.", "message.error.url": "Please enter URL.", -"message.error.userdata": "Please enter Userdata", +"message.error.user.data": "Please enter the User Data", "message.error.username": "Enter your username.", "message.error.valid.iops.range": "Please enter a valid IOPS range.", "message.error.vcenter.datacenter": "Please enter vCenter datacenter.", @@ -3425,16 +3428,16 @@ "message.error.vcenter.host": "Please enter vCenter host.", "message.error.vcenter.password": "Please enter vCenter password.", "message.error.vcenter.username": "Please enter vCenter username.", -"message.error.version.for.cluster": "Please select Kubernetes version for Kubernetes cluster.", +"message.error.version.for.cluster": "Please select Kubernetes version for Kubernetes Cluster.", "message.error.vlan.range": "Please enter a valid VLAN/VNI range.", "message.error.volume.name": "Please enter volume name.", "message.error.volume": "Please enter volume.", "message.error.volume.group": "Please enter volume group.", -"message.error.zone": "Please select a zone.", -"message.error.zone.combined": "All zones cannot be combined with any other zone.", -"message.error.zone.for.cluster": "Please select zone for Kubernetes cluster.", -"message.error.zone.name": "Please enter zone name.", -"message.error.zone.type": "Please select zone type.", +"message.error.zone": "Please select a Zone.", +"message.error.zone.combined": "All Zones cannot be combined with any other zone.", +"message.error.zone.for.cluster": "Please select Zone for Kubernetes Cluster.", +"message.error.zone.name": "Please enter Zone name.", +"message.error.zone.type": "Please select Zone type.", "message.error.linstor.resourcegroup": "Please enter the Linstor Resource-Group.", "message.error.fixed.offering.kvm": "It's not possible to scale up Instances that utilize KVM hypervisor with a fixed compute offering.", "message.error.create.webhook.local.account": "Account must be provided for creating a Webhook with Local scope.", @@ -3460,8 +3463,8 @@ "message.info.cloudian.console": "Cloudian Management Console should open in another window.", "message.installwizard.cloudstack.helptext.website": " * Project website:\t ", "message.infra.setup.netris.description": "This zone must contain a Netris provider because the isolation method is Netris", -"message.infra.setup.nsx.description": "This zone must contain an NSX provider because the isolation method is NSX", -"message.infra.setup.tungsten.description": "This zone must contain a Tungsten-Fabric provider because the isolation method is TF", +"message.infra.setup.nsx.description": "This Zone must contain an NSX provider because the isolation method is NSX", +"message.infra.setup.tungsten.description": "This Zone must contain a Tungsten-Fabric provider because the isolation method is TF", "message.installwizard.cloudstack.helptext.document": " * Documentation:\t ", "message.installwizard.cloudstack.helptext.header": "\nYou can find more information about Apache CloudStack™ on the pages listed below.\n", "message.installwizard.cloudstack.helptext.issues": " * Report issues:\t ", @@ -3469,14 +3472,14 @@ "message.installwizard.cloudstack.helptext.releasenotes": " * Release notes:\t ", "message.installwizard.cloudstack.helptext.survey": " * Take the survey:\t ", "message.installwizard.copy.whatiscloudstack": "CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the Network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.\n\nExtending beyond individual Instance images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications.", -"message.installwizard.tooltip.addpod.name": "A name for the pod.", +"message.installwizard.tooltip.addpod.name": "A name for the Pod.", "message.installwizard.tooltip.addpod.reservedsystemendip": "This is the IP range in the private Network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers.", -"message.installwizard.tooltip.addpod.reservedsystemgateway": "The gateway for the hosts in that pod.", +"message.installwizard.tooltip.addpod.reservedsystemgateway": "The gateway for the hosts in that Pod.", "message.installwizard.tooltip.addpod.reservedsystemstartip": "This is the IP range in the private Network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers.", -"message.installwizard.tooltip.configureguesttraffic.guestendip": "The range of IP addresses that will be available for allocation to guests in this zone. If one NIC is used, these IPs should be in the same CIDR as the pod CIDR.", +"message.installwizard.tooltip.configureguesttraffic.guestendip": "The range of IP addresses that will be available for allocation to guests in this Zone. If one NIC is used, these IPs should be in the same CIDR as the Pod CIDR.", "message.installwizard.tooltip.configureguesttraffic.guestgateway": "The gateway that the guests should use.", "message.installwizard.tooltip.configureguesttraffic.guestnetmask": "The netmask in use on the subnet that the guests should use.", -"message.installwizard.tooltip.configureguesttraffic.gueststartip": "The range of IP addresses that will be available for allocation to guests in this zone. If one NIC is used, these IPs should be in the same CIDR as the pod CIDR.", +"message.installwizard.tooltip.configureguesttraffic.gueststartip": "The range of IP addresses that will be available for allocation to guests in this Zone. If one NIC is used, these IPs should be in the same CIDR as the Pod CIDR.", "message.installwizard.tooltip.netris.provider.name": "Netris Provider name is required", "message.installwizard.tooltip.netris.provider.url": "Netris Provider URL not provided", "message.installwizard.tooltip.netris.provider.username": "Netris Provider username not provided", @@ -3487,9 +3490,9 @@ "message.installwizard.tooltip.nsx.provider.hostname": "NSX Provider hostname / IP address not provided", "message.installwizard.tooltip.nsx.provider.username": "NSX Provider username not provided", "message.installwizard.tooltip.nsx.provider.password": "NSX Provider password not provided", -"message.installwizard.tooltip.nsx.provider.edgecluster": "NSX Provider edge cluster information not provided", +"message.installwizard.tooltip.nsx.provider.edgecluster": "NSX Provider edge Cluster information not provided", "message.installwizard.tooltip.nsx.provider.tier0gateway": "NSX Provider tier-0 gateway information not provided", -"message.installwizard.tooltip.nsx.provider.transportZone": "NSX Provider transport zone information not provided", +"message.installwizard.tooltip.nsx.provider.transportZone": "NSX Provider transport Zone information not provided", "message.installwizard.tooltip.tungsten.provider.gateway": "Tungsten provider gateway is required", "message.installwizard.tooltip.tungsten.provider.hostname": "Tungsten provider hostname is required", "message.installwizard.tooltip.tungsten.provider.introspectport": "Tungsten provider introspect port is required", @@ -3506,16 +3509,16 @@ "message.ip.v6.prefix.delete": "IPv6 prefix deleted", "message.iso.arch": "Please select an ISO architecture", "message.iso.desc": "Disc image containing data or bootable media for OS.", -"message.kubeconfig.cluster.not.available": "Kubernetes cluster kubeconfig not available currently.", "message.kubernetes.cluster.add.nodes": "Please confirm that you want to add the following nodes to the cluster", -"message.kubernetes.cluster.delete": "Please confirm that you want to destroy the cluster.", -"message.kubernetes.cluster.scale": "Please select desired cluster configuration.", -"message.kubernetes.cluster.start": "Please confirm that you want to start the cluster.", -"message.kubernetes.cluster.stop": "Please confirm that you want to stop the cluster.", +"message.kubernetes.cluster.delete": "Please confirm that you want to destroy the Cluster.", +"message.kubeconfig.cluster.not.available": "Kubernetes Cluster kubeconfig not available currently.", "message.kubernetes.cluster.remove.nodes": "Please confirm that you want to remove the following nodes from the cluster", +"message.kubernetes.cluster.scale": "Please select desired Cluster configuration.", +"message.kubernetes.cluster.start": "Please confirm that you want to start the Cluster.", +"message.kubernetes.cluster.stop": "Please confirm that you want to stop the Cluster.", "message.kubernetes.cluster.upgrade": "Please select new Kubernetes version.", "message.kubernetes.version.delete": "Please confirm that you want to delete this Kubernetes version.", -"message.l2.network.unsupported.for.nsx": "L2 networks aren't supported for NSX enabled zones", +"message.l2.network.unsupported.for.nsx": "L2 networks aren't supported for NSX enabled Zones", "message.launch.zone": "Zone is ready to launch; please proceed to the next step.", "message.launch.zone.description": "Zone is ready to launch; please proceed to the next step.", "message.launch.zone.hint": "Configure Network components and traffic including IP addresses.", @@ -3540,8 +3543,9 @@ "message.lock.user": "Please confirm that you want to lock the User \"{user}\". By locking this User, they will no longer be able to manage their cloud resources. Existing resources can still be accessed.", "message.lock.user.success": "Successfully locked User \"{user}\"", "message.login.failed": "Login Failed", -"message.migrate.instance.host.auto.assign": "Host for the Instance will be automatically chosen based on the suitability within the same cluster", -"message.migrate.instance.to.host": "Please confirm that you want to migrate this Instance to another host. When migration is between hosts of different clusters volume(s) of the Instance may get migrated to suitable storage pools.", +"message.maintenance.initiated": "Maintenance has been initiated. This Management Server will not accept new jobs", +"message.migrate.instance.host.auto.assign": "Host for the Instance will be automatically chosen based on the suitability within the same Cluster", +"message.migrate.instance.to.host": "Please confirm that you want to migrate this Instance to another host. When migration is between hosts of different Clusters volume(s) of the Instance may get migrated to suitable storage pools.", "message.migrate.instance.to.ps": "Please confirm that you want to migrate this Instance to another primary storage.", "message.migrate.resource.to.ss": "Please confirm that you want to migrate this resource to another secondary storage.", "message.migrate.router.confirm": "Please confirm the host you wish to migrate the router to:", @@ -3592,11 +3596,11 @@ "message.path.description": "NFS: exported path from the server. VMFS: /datacenter name/datastore name. SharedMountPoint: path where primary storage is mounted, such as /mnt/primary.", "message.please.confirm.remove.cni.configuration": "Please confirm that you want to remove this CNI Configuration", "message.please.confirm.remove.ssh.key.pair": "Please confirm that you want to remove this SSH key pair.", -"message.please.confirm.remove.user.data": "Please confirm that you want to remove this Userdata", +"message.please.confirm.remove.user.data": "Please confirm that you want to remove this User Data", "message.please.enter.valid.value": "Please enter a valid value.", "message.please.enter.value": "Please enter values.", "message.please.wait.while.autoscale.vmgroup.is.being.created": "Please wait while your AutoScaling Group is being created; this may take a while...", -"message.please.wait.while.zone.is.being.created": "Please wait while your zone is being created; this may take a while...", +"message.please.wait.while.zone.is.being.created": "Please wait while your Zone is being created; this may take a while...", "message.pod.dedicated": "Pod dedicated.", "message.pod.dedication.released": "Pod dedication released.", "message.prepare.for.shutdown": "Please confirm that you would like to prepare this Management Server for shutdown. It will not accept any new Async Jobs but will NOT terminate after there are no pending jobs.", @@ -3613,10 +3617,10 @@ "message.recover.vm": "Please confirm that you would like to recover this Instance.", "message.reinstall.vm": "NOTE: Proceed with caution. This will cause the Instance to be reinstalled from the Template; data on the root disk will be lost. Extra data volumes, if any, will not be touched.", "message.release.ip.failed": "Failed to release IP", -"message.releasing.dedicated.cluster": "Releasing dedicated cluster...", +"message.releasing.dedicated.cluster": "Releasing dedicated Cluster...", "message.releasing.dedicated.host": "Releasing dedicated host...", -"message.releasing.dedicated.pod": "Releasing dedicated pod...", -"message.releasing.dedicated.zone": "Releasing dedicated zone...", +"message.releasing.dedicated.pod": "Releasing dedicated Pod...", +"message.releasing.dedicated.zone": "Releasing dedicated Zone...", "message.remove.annotation": "Are you sure you want to delete the comment?", "message.remove.egress.rule.failed": "Removing egress rule failed", "message.remove.egress.rule.processing": "Deleting egress rule...", @@ -3663,7 +3667,7 @@ "message.scaleup.policy.continue": "Please add at least a condition to ScaleUp policy to continue", "message.scaleup.policy.duration.continue": "Please input a valid duration to ScaleUp policy to continue", "message.scaleup.policy.name.continue": "Please input a name to ScaleUp policy to continue", -"message.select.a.zone": "A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.", +"message.select.a.zone": "A Zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.", "message.select.affinity.groups": "Please select any affinity groups you want this Instance to belong to:", "message.select.bgp.peers": "Please select / deselect the BGP peers associated to the network or VPC:", "message.select.deselect.desired.options": "Please select / deselect the desired options", @@ -3671,29 +3675,28 @@ "message.select.destination.image.stores": "Please select Image Store(s) to which data is to be migrated to", "message.select.disk.offering": "Please select a disk offering for disk", "message.select.end.date.and.time": "Select an end date & time.", -"message.select.kvm.host.instance.conversion": "(Optional) Select a KVM host in the zone to perform the instance conversion through virt-v2v", -"message.select.kvm.host.instance.import": "(Optional) Select a KVM host in the cluster to perform the importing of the converted instance", +"message.select.kvm.host.instance.conversion": "(Optional) Select a KVM host in the Zone to perform the instance conversion through virt-v2v", +"message.select.kvm.host.instance.import": "(Optional) Select a KVM host in the Cluster to perform the importing of the converted instance", "message.select.load.balancer.rule": "Please select a load balancer rule for your AutoScale Instance group.", "message.select.migration.policy": "Please select a migration policy.", "message.select.nic.network": "Please select a Network for NIC", "message.select.security.groups": "Please select security group(s) for your new Instance.", "message.select.start.date.and.time": "Select a start date & time.", "message.select.temporary.storage.instance.conversion": "(Optional) Select a Storage temporary destination for the converted disks through virt-v2v", -"message.select.zone.description": "Select type of zone basic/advanced.", -"message.select.zone.hint": "This is the type of zone deployment that you want to use. Basic zone: provides a single Network where each Instance is assigned an IP directly from the Network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering). Advanced zone: For more sophisticated Network topologies. This Network model provides the most flexibility in defining guest Networks and providing custom Network offerings such as firewall, VPN, or load balancer support.", +"message.select.zone.description": "Select type of Zone basic/advanced.", +"message.select.zone.hint": "This is the type of Zone deployment that you want to use. Basic zone: provides a single Network where each Instance is assigned an IP directly from the Network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering). Advanced zone: For more sophisticated Network topologies. This Network model provides the most flexibility in defining guest Networks and providing custom Network offerings such as firewall, VPN, or load balancer support.", "message.server": "Server : ", "message.server.description": "NFS, iSCSI, or PreSetup: IP address or DNS name of the storage device. VMWare PreSetup: IP address or DNS name of the vCenter server. Linstor: http(s) url of the linstor-controller.", "message.set.default.nic": "Please confirm that you would like to make this NIC the default for this Instance.", "message.set.default.nic.manual": "Please manually update the default NIC on the Instance now.", "message.setting.updated": "Setting Updated:", "message.setting.update.delay": "The new value will take effect within 30 seconds.", -"message.setup.physical.network.during.zone.creation": "When adding a zone, you need to set up one or more physical networks. Each physical network can carry one or more types of traffic, with certain restrictions on how they may be combined. Add or remove one or more traffic types onto each physical network.", -"message.setup.physical.network.during.zone.creation.basic": "When adding a basic zone, you can set up one physical Network, which corresponds to a NIC on the hypervisor. The Network carries several types of traffic.

You may also add other traffic types onto the physical Network.", +"message.setup.physical.network.during.zone.creation": "When adding a Zone, you need to set up one or more physical networks. Each physical network can carry one or more types of traffic, with certain restrictions on how they may be combined. Add or remove one or more traffic types onto each physical network.", +"message.setup.physical.network.during.zone.creation.basic": "When adding a basic Zone, you can set up one physical Network, which corresponds to a NIC on the hypervisor. The Network carries several types of traffic.

You may also add other traffic types onto the physical Network.", "message.shared.network.offering.warning": "Domain admins and regular Users can only create shared Networks from Network offering with the setting specifyvlan=false. Please contact an administrator to create a Network offering if this list is empty.", -"message.shared.network.unsupported.for.nsx": "Shared networks aren't supported for NSX enabled zones", -"message.shutdown.triggered": "Shutdown has been triggered. This Management Server will not accept new jobs", -"message.maintenance.initiated": "Maintenance has been initiated. This Management Server will not accept new jobs", -"message.snapshot.additional.zones": "Snapshots will always be created in its native zone - %x, here you can select additional zone(s) where it will be copied to at creation time", +"message.shared.network.unsupported.for.nsx": "Shared networks aren't supported for NSX enabled Zones", +"message.shutdown.triggered": "A shutdown has been triggered. CloudStack will not accept new jobs", +"message.snapshot.additional.zones": "Snapshots will always be created in its native Zone - %x, here you can select additional zone(s) where it will be copied to at creation time", "message.sourcenatip.change.warning": "WARNING: Changing the sourcenat IP address of the network will cause connectivity downtime for the Instances with NICs in the Network.", "message.sourcenatip.change.inhibited": "Changing the sourcenat to this IP of the Network to this address is inhibited as firewall rules are defined for it. This can include port forwarding or load balancing rules.\n - If this is an Isolated Network, please use updateNetwork/click the edit button.\n - If this is a VPC, first clear all other rules for this address.", "message.specify.tag.key": "Please specify a tag key.", @@ -3716,7 +3719,7 @@ "message.success.add.kuberversion": "Successfully added Kubernetes version", "message.success.add.logical.router": "Successfully added Logical Router", "message.success.add.network": "Successfully added Network", -"message.success.add.network.acl": "Successfully added Network ACL list", +"message.success.add.network.acl": "Successfully added Network ACL", "message.success.add.network.static.route": "Successfully added Network Static Route", "message.success.add.network.permissions": "Successfully added Network permissions", "message.success.add.nodes.to.cluster": "Successfully added nodes to Kubernetes cluster", @@ -3763,7 +3766,7 @@ "message.success.create.internallb": "Successfully created Internal Load Balancer", "message.success.create.isolated.network": "Successfully created isolated Network", "message.success.create.keypair": "Successfully created SSH key pair", -"message.success.create.kubernetes.cluter": "Successfully created Kubernetes cluster", +"message.success.create.kubernetes.cluter": "Successfully created Kubernetes Cluster", "message.success.create.l2.network": "Successfully created L2 Network", "message.success.create.snapshot.from.vmsnapshot": "Successfully created Snapshot from Instance Snapshot", "message.success.create.template": "Successfully created Template", @@ -3811,7 +3814,7 @@ "message.success.register.iso": "Successfully registered ISO", "message.success.register.keypair": "Successfully registered SSH key pair", "message.success.register.template": "Successfully registered Template", -"message.success.register.user.data": "Successfully registered Userdata", +"message.success.register.user.data": "Successfully registered User Data", "message.success.release.ip": "Successfully released IP", "message.success.release.dedicated.bgp.peer": "Successfully released dedicated BGP peer", "message.success.release.dedicated.ipv4.subnet": "Successfully released dedicated IPv4 subnet", @@ -3834,7 +3837,7 @@ "message.success.remove.tungsten.routing.policy": "Successfully removed Tungsten-Fabric Routing Policy from Network", "message.success.reset.network.permissions": "Successfully reset Network Permissions", "message.success.resize.volume": "Successfully resized volume", -"message.success.scale.kubernetes": "Successfully scaled Kubernetes cluster", +"message.success.scale.kubernetes": "Successfully scaled Kubernetes Cluster", "message.success.unmanage.gpu.devices": "Successfully unmanaged GPU device(s)", "message.success.unmanage.instance": "Successfully unmanaged Instance", "message.success.unmanage.volume": "Successfully unmanaged Volume", @@ -3858,7 +3861,7 @@ "message.success.update.network": "Successfully updated Network", "message.success.update.template": "Successfully updated Template", "message.success.update.user": "Successfully updated User", -"message.success.upgrade.kubernetes": "Successfully upgraded Kubernetes cluster", +"message.success.upgrade.kubernetes": "Successfully upgraded Kubernetes Cluster", "message.success.upload": "Successfully uploaded", "message.success.upload.description": "This ISO file has been uploaded. Please check its status in the Templates menu.", "message.success.upload.icon": "Successfully uploaded icon for ", @@ -3873,10 +3876,10 @@ "message.template.import.vm.temporary": "If a temporary Template is used, the reset Instance operation will not work after importing it.", "message.template.iso": "Please select a Template or ISO to continue.", "message.template.type.change.warning": "WARNING: Changing the Template type to SYSTEM will disable further changes to the Template.", -"message.tooltip.reserved.system.netmask": "The Network prefix that defines the pod subnet. Uses CIDR notation.", +"message.tooltip.reserved.system.netmask": "The Network prefix that defines the Pod subnet. Uses CIDR notation.", "message.traffic.type.deleted": "Successfully deleted traffic type", -"message.traffic.type.to.basic.zone": "traffic type to basic zone", -"message.trigger.shutdown": "Please confirm that you would like to trigger a shutdown on this Management Server. It will not accept any new Async Jobs and will terminate after there are no pending jobs.", +"message.traffic.type.to.basic.zone": "traffic type to basic Zone", +"message.trigger.shutdown": "Please confirm that you would like to trigger a shutdown on this Management server. It will not accept any new Async Jobs and will terminate after there are no pending jobs.", "message.type.values.to.add": "Please add additional values by typing them in", "message.update.autoscale.policy.failed": "Failed to update autoscale policy", "message.update.autoscale.vmgroup.failed": "Failed to update autoscale group", @@ -3974,11 +3977,11 @@ "message.warn.filetype": "jpg, jpeg, png, bmp and svg are the only supported image formats.", "message.warn.importing.instance.without.nic": "WARNING: This Instance is being imported without NICs and many Network resources will not be available. Consider creating a NIC via vCenter before importing or as soon as the Instance is imported.", "message.warn.select.template": "Please select a Template for Registration.", -"message.warn.zone.mtu.update": "Please note that this limit won't affect pre-existing Network’s MTU settings", +"message.warn.zone.mtu.update": "Please note that this limit won't affect pre-existing Network's MTU settings", "message.webhook.deliveries.time.filter": "Webhook deliveries list can be filtered based on date-time. Select 'Custom' for specifying start and end date range.", "message.zone.creation.complete": "Zone creation complete.", -"message.zone.detail.description": "Populate zone details.", -"message.zone.detail.hint": "A zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone.", +"message.zone.detail.description": "Populate Zone details.", +"message.zone.detail.hint": "A Zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more Pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone.", "message.validate.min": "Please enter a value greater than or equal to {0}.", "message.action.delete.object.storage": "Please confirm that you want to delete this Object Store", "message.action.unregister.extension.resource": "Please confirm that you want to unregister extension with this resource", diff --git a/ui/public/locales/es.json b/ui/public/locales/es.json index ae4fa19f033..ab57c951531 100644 --- a/ui/public/locales/es.json +++ b/ui/public/locales/es.json @@ -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", diff --git a/ui/public/locales/fr_FR.json b/ui/public/locales/fr_FR.json index 48a0560f176..424f4749aa3 100644 --- a/ui/public/locales/fr_FR.json +++ b/ui/public/locales/fr_FR.json @@ -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", diff --git a/ui/public/locales/hi.json b/ui/public/locales/hi.json index 055909360b5..9d7440b9262 100644 --- a/ui/public/locales/hi.json +++ b/ui/public/locales/hi.json @@ -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", diff --git a/ui/public/locales/hu.json b/ui/public/locales/hu.json index 48275ce81fc..ae58379d343 100644 --- a/ui/public/locales/hu.json +++ b/ui/public/locales/hu.json @@ -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!", diff --git a/ui/public/locales/it_IT.json b/ui/public/locales/it_IT.json index 844763eba3a..a2907b71f23 100644 --- a/ui/public/locales/it_IT.json +++ b/ui/public/locales/it_IT.json @@ -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", diff --git a/ui/public/locales/ja_JP.json b/ui/public/locales/ja_JP.json index 8357b9d49a2..3ab374a2a06 100644 --- a/ui/public/locales/ja_JP.json +++ b/ui/public/locales/ja_JP.json @@ -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コントローラーを削除してもよろしいですか?", diff --git a/ui/public/locales/ko_KR.json b/ui/public/locales/ko_KR.json index f1fab4b584c..cc9683633be 100644 --- a/ui/public/locales/ko_KR.json +++ b/ui/public/locales/ko_KR.json @@ -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.", diff --git a/ui/public/locales/nb_NO.json b/ui/public/locales/nb_NO.json index ec51f7415d3..586d1fc5b25 100644 --- a/ui/public/locales/nb_NO.json +++ b/ui/public/locales/nb_NO.json @@ -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", diff --git a/ui/public/locales/nl_NL.json b/ui/public/locales/nl_NL.json index 6bd1bf67159..15b1bbb1394 100644 --- a/ui/public/locales/nl_NL.json +++ b/ui/public/locales/nl_NL.json @@ -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", diff --git a/ui/public/locales/pl.json b/ui/public/locales/pl.json index 6077da5928e..fbbbf612bc1 100644 --- a/ui/public/locales/pl.json +++ b/ui/public/locales/pl.json @@ -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", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 8aba6fe2c78..09b0242ef1a 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -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", diff --git a/ui/public/locales/ru_RU.json b/ui/public/locales/ru_RU.json index 46d70081f1b..4fb3788bc51 100644 --- a/ui/public/locales/ru_RU.json +++ b/ui/public/locales/ru_RU.json @@ -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", diff --git a/ui/public/locales/zh_CN.json b/ui/public/locales/zh_CN.json index fc3a456a8fb..d09f960edf5 100644 --- a/ui/public/locales/zh_CN.json +++ b/ui/public/locales/zh_CN.json @@ -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", diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index 449172112a0..6cfd243c438 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -34,6 +34,9 @@ + + + @@ -750,7 +753,7 @@
-
{{ $t('label.userdata') }}
+
{{ $t('label.user.data') }}
{{ resource.userdataname || resource.userdataid }} @@ -824,6 +827,18 @@ {{ resource.webhookname || resource.webhookid }}
+
+
{{ $t('label.boottype') }}
+
+ {{ resource.boottype }} +
+
+
+
{{ $t('label.bootmode') }}
+
+ {{ resource.bootmode }} +
+
{{ $t('label.management.servers') }}
@@ -976,6 +991,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', @@ -988,7 +1004,8 @@ export default { UploadResourceIcon, ResourceIcon, ResourceLabel, - ImageDeployInstanceButton + ImageDeployInstanceButton, + FileTextOutlined }, props: { resource: { @@ -1323,6 +1340,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') { diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index e5d843d4ce4..205e340652d 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -60,12 +60,10 @@ size="2x" /> - + + + + import('@/views/compute/RegisterUserData.vue'))) diff --git a/ui/src/config/section/domain.js b/ui/src/config/section/domain.js index e6807f06278..fbe20ef8891 100644 --- a/ui/src/config/section/domain.js +++ b/ui/src/config/section/domain.js @@ -48,6 +48,11 @@ export default { name: 'template', title: 'label.templates', param: 'domainid' + }, + { + name: 'iso', + title: 'label.isos', + param: 'domainid' }], tabs: [ { diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 42af53274f7..8c1ffcdf9cd 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -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 } ] diff --git a/ui/src/config/section/storage.js b/ui/src/config/section/storage.js index bcd48944497..5c98a81579e 100644 --- a/ui/src/config/section/storage.js +++ b/ui/src/config/section/storage.js @@ -39,7 +39,7 @@ export default { } }, columns: () => { - const fields = ['name', 'state', 'sizegb', 'type', 'vmname', 'vmstate'] + const fields = ['name', 'state', 'size', 'type', 'vmname', 'vmstate'] const metricsFields = ['diskkbsread', 'diskkbswrite', 'diskiopstotal'] if (store.getters.userInfo.roletype === 'Admin') { diff --git a/ui/src/views/compute/AutoScaleVmProfile.vue b/ui/src/views/compute/AutoScaleVmProfile.vue index b0430e8e9aa..92ff9c8777b 100644 --- a/ui/src/views/compute/AutoScaleVmProfile.vue +++ b/ui/src/views/compute/AutoScaleVmProfile.vue @@ -76,7 +76,7 @@
- +
{{ userdataid }}
@@ -84,7 +84,7 @@
- +
{{ userdataname }}
@@ -92,7 +92,7 @@
- +
{{ userdatadetails }}
@@ -100,7 +100,7 @@
- +
{{ userdatapolicy }}
@@ -108,7 +108,7 @@
- +
@@ -124,7 +124,7 @@
- {{ $t('label.reset.userdata.on.autoscale.vm.group') }} + {{ $t('label.reset.user.data.on.autoscale.vm.group') }}
@@ -291,7 +291,7 @@
@@ -791,11 +791,11 @@


- {{ $t('label.userdata.do.override') }} + {{ $t('label.user.data.do.override') }} - {{ $t('label.userdata.do.append') }} + {{ $t('label.user.data.do.append') }} - +
@@ -670,11 +670,11 @@


- {{ $t('label.userdata.do.override') }} + {{ $t('label.user.data.do.override') }} - {{ $t('label.userdata.do.append') }} + {{ $t('label.user.data.do.append') }} 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) diff --git a/ui/src/views/compute/DeployVnfAppliance.vue b/ui/src/views/compute/DeployVnfAppliance.vue index 06c41728a41..fd5a04d9b70 100644 --- a/ui/src/views/compute/DeployVnfAppliance.vue +++ b/ui/src/views/compute/DeployVnfAppliance.vue @@ -550,7 +550,7 @@ @change="val => { dynamicscalingenabled = val }"/> - +
@@ -604,11 +604,11 @@


- {{ $t('label.userdata.do.override') }} + {{ $t('label.user.data.do.override') }} - {{ $t('label.userdata.do.append') }} + {{ $t('label.user.data.do.append') }} 0 && this.vm.templateid && this.templateVnfNics && this.templateVnfNics.length > 0 @@ -1331,7 +1331,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 @@ -2472,20 +2472,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) diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue index f7b7649b96b..e35ca6dd49d 100644 --- a/ui/src/views/compute/EditVM.vue +++ b/ui/src/views/compute/EditVM.vue @@ -86,7 +86,7 @@ @@ -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 = [] diff --git a/ui/src/views/compute/RegisterUserData.vue b/ui/src/views/compute/RegisterUserData.vue index 4631ad70e7d..3958db7160e 100644 --- a/ui/src/views/compute/RegisterUserData.vue +++ b/ui/src/views/compute/RegisterUserData.vue @@ -38,11 +38,11 @@
+ :placeholder="$t('label.register.user.data.details')"/>
@@ -61,7 +61,7 @@
- {{ $t('label.userdata.do.override') }} + {{ $t('label.user.data.do.override') }} - {{ $t('label.userdata.do.append') }} + {{ $t('label.user.data.do.append') }} @@ -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') diff --git a/ui/src/views/compute/wizard/UserDataSelection.vue b/ui/src/views/compute/wizard/UserDataSelection.vue index 06eaefcc060..f1dd2481df4 100644 --- a/ui/src/views/compute/wizard/UserDataSelection.vue +++ b/ui/src/views/compute/wizard/UserDataSelection.vue @@ -34,8 +34,7 @@ :scroll="{ y: 225 }" > @@ -87,7 +86,7 @@ export default { { key: 'name', dataIndex: 'name', - title: this.$t('label.userdata'), + title: this.$t('label.user.data'), width: '40%' }, { diff --git a/ui/src/views/image/RegisterOrUploadIso.vue b/ui/src/views/image/RegisterOrUploadIso.vue index cb86d745e3c..e7536027e7c 100644 --- a/ui/src/views/image/RegisterOrUploadIso.vue +++ b/ui/src/views/image/RegisterOrUploadIso.vue @@ -218,7 +218,7 @@ name="userdataid" ref="userdataid"> + :label="$t('label.user.data')"> + :label="$t('label.user.data')"> + }" + @change="val => { fetchDomainAccounts(val) }"> {{ dom.path }} @@ -213,7 +214,20 @@ :label="$t('label.account')" v-bind="formItemLayout" v-if="isDedicated"> - + + + {{ acc.name }} + + { + // Clean up the selected account from a previous domain + this.form.account = null + this.selectedDomainAccounts = response.listaccountsresponse.account || [] + }).catch(error => { + this.$notifyError(error) + }) + }, fetchData () { getAPI('listHypervisors').then(json => { this.hypervisors = json.listhypervisorsresponse.hypervisor diff --git a/ui/src/views/network/AclListRulesTab.vue b/ui/src/views/network/AclRulesTab.vue similarity index 99% rename from ui/src/views/network/AclListRulesTab.vue rename to ui/src/views/network/AclRulesTab.vue index df1b8ac10ba..da6d834e4a3 100644 --- a/ui/src/views/network/AclListRulesTab.vue +++ b/ui/src/views/network/AclRulesTab.vue @@ -25,7 +25,7 @@ :disabled="!('createNetworkACL' in $store.getters.apis)" @click="openAddRuleModal"> - {{ $t('label.add') }} {{ $t('label.aclid') }} + {{ $t('label.add.acl.rule') }} diff --git a/ui/src/views/network/VpcTab.vue b/ui/src/views/network/VpcTab.vue index d2a714570d0..12e21cd8ec9 100644 --- a/ui/src/views/network/VpcTab.vue +++ b/ui/src/views/network/VpcTab.vue @@ -34,14 +34,14 @@ - + - {{ $t('label.add.network.acl.list') }} + {{ $t('label.add.network.acl') }} - + diff --git a/ui/src/views/offering/AddComputeOffering.vue b/ui/src/views/offering/AddComputeOffering.vue index da394ba6f8f..0455551723c 100644 --- a/ui/src/views/offering/AddComputeOffering.vue +++ b/ui/src/views/offering/AddComputeOffering.vue @@ -47,6 +47,7 @@
diff --git a/ui/src/views/offering/AddDiskOffering.vue b/ui/src/views/offering/AddDiskOffering.vue index a553e324b5c..886465cfcf7 100644 --- a/ui/src/views/offering/AddDiskOffering.vue +++ b/ui/src/views/offering/AddDiskOffering.vue @@ -218,6 +218,7 @@ - + @@ -334,6 +334,7 @@ + + + + + {{ opt.name || opt.description }} + + + @@ -163,7 +182,7 @@ - +
@@ -204,7 +223,8 @@ export default { accounts: [], domainLoading: false, domainid: null, - account: null + account: null, + architectureTypes: {} } }, computed: { @@ -239,6 +259,7 @@ export default { if ('listDomains' in this.$store.getters.apis) { this.fetchDomains() } + this.architectureTypes.opts = this.$fetchCpuArchitectureTypes() }, fetchOsTypes () { this.osTypes.opts = [] diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java index 189797a3cb2..d3c3a9d465e 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/HostMO.java @@ -41,7 +41,6 @@ import com.vmware.vim25.HostConnectInfo; import com.vmware.vim25.HostFirewallInfo; import com.vmware.vim25.HostFirewallRuleset; import com.vmware.vim25.HostHardwareSummary; -import com.vmware.vim25.HostHyperThreadScheduleInfo; import com.vmware.vim25.HostIpConfig; import com.vmware.vim25.HostIpRouteEntry; import com.vmware.vim25.HostListSummaryQuickStats; @@ -94,10 +93,6 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { return _context.getVimClient().getDynamicProperty(_mor, "configManager"); } - public List getHostVirtualNicManagerNetConfig() throws Exception { - return _context.getVimClient().getDynamicProperty(_mor, "config.virtualNicManagerInfo.netConfig"); - } - public List getHostIpRouteEntries() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "config.network.routeTableInfo.ipRoute"); } @@ -106,10 +101,6 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { return _context.getVimClient().getDynamicProperty(_mor, "summary.quickStats"); } - public HostHyperThreadScheduleInfo getHostHyperThreadInfo() throws Exception { - return _context.getVimClient().getDynamicProperty(_mor, "config.hyperThread"); - } - public HostNetworkInfo getHostNetworkInfo() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "config.network"); } @@ -260,7 +251,6 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { @Override public ManagedObjectReference getHyperHostDatacenter() throws Exception { Pair dcPair = DatacenterMO.getOwnerDatacenter(getContext(), getMor()); - assert (dcPair != null); return dcPair.first().getMor(); } @@ -282,19 +272,6 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { throw new Exception("Standalone host is not supported"); } - public ManagedObjectReference[] getHostLocalDatastore() throws Exception { - List datastores = _context.getVimClient().getDynamicProperty(_mor, "datastore"); - List l = new ArrayList<>(); - if (datastores != null) { - for (ManagedObjectReference mor : datastores) { - DatastoreSummary summary = _context.getVimClient().getDynamicProperty(mor, "summary"); - if (summary.getType().equalsIgnoreCase("VMFS") && !summary.isMultipleHostAccess()) - l.add(mor); - } - } - return l.toArray(new ManagedObjectReference[1]); - } - public HostVirtualSwitch getHostVirtualSwitchByName(String name) throws Exception { List switches = _context.getVimClient().getDynamicProperty(_mor, "config.network.vswitch"); @@ -307,16 +284,17 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { return null; } - public List getHostVirtualSwitch() throws Exception { - return _context.getVimClient().getDynamicProperty(_mor, "config.network.vswitch"); - } - public AboutInfo getHostAboutInfo() throws Exception { return _context.getVimClient().getDynamicProperty(_mor, "config.product"); } public VmwareHostType getHostType() throws Exception { AboutInfo aboutInfo = getHostAboutInfo(); + if (aboutInfo == null) { + String msg = "no type info about host known, assuming ESXi"; + logger.warn(msg); + return VmwareHostType.ESXi; + } if ("VMware ESXi".equals(aboutInfo.getName())) return VmwareHostType.ESXi; else if ("VMware ESX".equals(aboutInfo.getName())) @@ -325,50 +303,6 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { throw new Exception("Unrecognized VMware host type " + aboutInfo.getName()); } - // default virtual switch is which management network residents on - public HostVirtualSwitch getHostDefaultVirtualSwitch() throws Exception { - String managementPortGroup = getPortGroupNameByNicType(HostVirtualNicType.management); - if (managementPortGroup != null) - return getPortGroupVirtualSwitch(managementPortGroup); - - return null; - } - - public HostVirtualSwitch getPortGroupVirtualSwitch(String portGroupName) throws Exception { - String vSwitchName = getPortGroupVirtualSwitchName(portGroupName); - if (vSwitchName != null) - return getVirtualSwitchByName(vSwitchName); - - return null; - } - - public HostVirtualSwitch getVirtualSwitchByName(String vSwitchName) throws Exception { - - List vSwitchs = getHostVirtualSwitch(); - if (vSwitchs != null) { - for (HostVirtualSwitch vSwitch : vSwitchs) { - if (vSwitch.getName().equals(vSwitchName)) - return vSwitch; - } - } - - return null; - } - - public String getPortGroupVirtualSwitchName(String portGroupName) throws Exception { - HostNetworkInfo hostNetInfo = getHostNetworkInfo(); - List portGroups = hostNetInfo.getPortgroup(); - if (portGroups != null) { - for (HostPortGroup portGroup : portGroups) { - HostPortGroupSpec spec = portGroup.getSpec(); - if (spec.getName().equals(portGroupName)) - return spec.getVswitchName(); - } - } - - return null; - } - public HostPortGroupSpec getPortGroupSpec(String portGroupName) throws Exception { HostNetworkInfo hostNetInfo = getHostNetworkInfo(); List portGroups = hostNetInfo.getPortgroup(); @@ -383,40 +317,6 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { return null; } - public String getPortGroupNameByNicType(HostVirtualNicType nicType) throws Exception { - assert (nicType != null); - - List netConfigs = - _context.getVimClient().getDynamicProperty(_mor, "config.virtualNicManagerInfo.netConfig"); - - if (netConfigs != null) { - for (VirtualNicManagerNetConfig netConfig : netConfigs) { - if (netConfig.getNicType().equals(nicType.toString())) { - List nics = netConfig.getCandidateVnic(); - if (nics != null) { - for (HostVirtualNic nic : nics) { - return nic.getPortgroup(); - } - } - } - } - } - - if (nicType == HostVirtualNicType.management) { - // ESX management network is configured in service console - HostNetworkInfo netInfo = getHostNetworkInfo(); - assert (netInfo != null); - List nics = netInfo.getConsoleVnic(); - if (nics != null) { - for (HostVirtualNic nic : nics) { - return nic.getPortgroup(); - } - } - } - - return null; - } - public boolean hasOpaqueNSXNetwork() throws Exception{ HostNetworkInfo netInfo = getHostNetworkInfo(); List opaqueNetworks = netInfo.getOpaqueNetwork(); @@ -436,9 +336,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { public boolean hasPortGroup(HostVirtualSwitch vSwitch, String portGroupName) throws Exception { ManagedObjectReference morNetwork = getNetworkMor(portGroupName); - if (morNetwork != null) - return true; - return false; + return morNetwork != null; } public void createPortGroup(HostVirtualSwitch vSwitch, String portGroupName, Integer vlanId, HostNetworkSecurityPolicy secPolicy, @@ -451,7 +349,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { spec.setName(portGroupName); if (vlanId != null) - spec.setVlanId(vlanId.intValue()); + spec.setVlanId(vlanId); HostNetworkPolicy policy = new HostNetworkPolicy(); if (secPolicy != null) policy.setSecurity(secPolicy); @@ -471,7 +369,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { spec.setName(portGroupName); if (vlanId != null) - spec.setVlanId(vlanId.intValue()); + spec.setVlanId(vlanId); HostNetworkPolicy policy = new HostNetworkPolicy(); if (secPolicy != null) policy.setSecurity(secPolicy); @@ -525,15 +423,8 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { return null; } - public List getVmMorsOnNetwork(String portGroupName) throws Exception { - ManagedObjectReference morNetwork = getNetworkMor(portGroupName); - if (morNetwork != null) - return _context.getVimClient().getDynamicProperty(morNetwork, "vm"); - return null; - } - public String getHostName() throws Exception { - return (String)_context.getVimClient().getDynamicProperty(_mor, "name"); + return _context.getVimClient().getDynamicProperty(_mor, "name"); } @Override @@ -572,11 +463,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { String internalCSUserVMNamingPattern = "^[i][-][0-9]+[-][0-9]+[-]"; Pattern p = Pattern.compile(internalCSUserVMNamingPattern); java.util.regex.Matcher m = p.matcher(vmInternalCSName); - if (m.find()) { - return true; - } else { - return false; - } + return m.find(); } private void loadVmCache() throws Exception { @@ -723,7 +610,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { PropertyFilterSpec pfSpec = new PropertyFilterSpec(); pfSpec.getPropSet().add(pSpec); pfSpec.getObjectSet().add(oSpec); - List pfSpecArr = new ArrayList(); + List pfSpecArr = new ArrayList<>(); pfSpecArr.add(pfSpec); List properties = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); @@ -756,7 +643,7 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { PropertyFilterSpec pfSpec = new PropertyFilterSpec(); pfSpec.getPropSet().add(pSpec); pfSpec.getObjectSet().add(oSpec); - List pfSpecArr = new ArrayList(); + List pfSpecArr = new ArrayList<>(); pfSpecArr.add(pfSpec); List properties = _context.getService().retrieveProperties(_context.getPropertyCollector(), pfSpecArr); @@ -799,21 +686,6 @@ public class HostMO extends BaseMO implements VmwareHypervisorHost { return dsList; } - public void importVmFromOVF(String ovfFilePath, String vmName, String datastoreName, String diskOption, String configurationId) throws Exception { - if (logger.isTraceEnabled()) - logger.trace("vCenter API trace - importVmFromOVF(). target MOR: " + _mor.getValue() + ", ovfFilePath: " + ovfFilePath + ", vmName: " + vmName + - ",datastoreName: " + datastoreName + ", diskOption: " + diskOption); - - DatastoreMO dsMo = getHostDatastoreMO(datastoreName); - if (dsMo == null) - throw new Exception("Invalid datastore name: " + datastoreName); - - importVmFromOVF(ovfFilePath, vmName, dsMo, diskOption, configurationId); - - if (logger.isTraceEnabled()) - logger.trace("vCenter API trace - importVmFromOVF() done"); - } - @Override public void importVmFromOVF(String ovfFilePath, String vmName, DatastoreMO dsMo, String diskOption, String configurationId) throws Exception {