diff --git a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java index d86eb2a3a7f..18737c584b3 100644 --- a/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java +++ b/api/src/main/java/com/cloud/agent/api/to/RemoteInstanceTO.java @@ -27,6 +27,7 @@ public class RemoteInstanceTO implements Serializable { private Hypervisor.HypervisorType hypervisorType; private String instanceName; + private String instancePath; // VMware Remote Instances parameters (required for exporting OVA through ovftool) // TODO: cloud.agent.transport.Request#getCommands() cannot handle gsoc decode for polymorphic classes @@ -44,9 +45,10 @@ public class RemoteInstanceTO implements Serializable { this.instanceName = instanceName; } - public RemoteInstanceTO(String instanceName, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) { + public RemoteInstanceTO(String instanceName, String instancePath, String vcenterHost, String vcenterUsername, String vcenterPassword, String datacenterName) { this.hypervisorType = Hypervisor.HypervisorType.VMware; this.instanceName = instanceName; + this.instancePath = instancePath; this.vcenterHost = vcenterHost; this.vcenterUsername = vcenterUsername; this.vcenterPassword = vcenterPassword; @@ -61,6 +63,10 @@ public class RemoteInstanceTO implements Serializable { return this.instanceName; } + public String getInstancePath() { + return this.instancePath; + } + public String getVcenterUsername() { return vcenterUsername; } diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java index 3a72f8bddc4..b7b5423244c 100644 --- a/api/src/main/java/com/cloud/storage/VolumeApiService.java +++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java @@ -22,7 +22,12 @@ import java.net.MalformedURLException; import java.util.List; import java.util.Map; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.offering.DiskOffering; +import com.cloud.user.Account; import com.cloud.utils.Pair; +import com.cloud.utils.fsm.NoTransitionException; + import org.apache.cloudstack.api.command.user.volume.AssignVolumeCmd; import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ChangeOfferingForVolumeCmd; @@ -37,13 +42,9 @@ import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd; import org.apache.cloudstack.api.response.GetUploadParamsResponse; import org.apache.cloudstack.framework.config.ConfigKey; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.user.Account; -import com.cloud.utils.fsm.NoTransitionException; - public interface VolumeApiService { - ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey("Advanced" + ConfigKey ConcurrentMigrationsThresholdPerDatastore = new ConfigKey<>("Advanced" , Long.class , "concurrent.migrations.per.target.datastore" , "0" @@ -51,7 +52,7 @@ public interface VolumeApiService { , true // not sure if this is to be dynamic , ConfigKey.Scope.Global); - ConfigKey UseHttpsToUpload = new ConfigKey("Advanced", + ConfigKey UseHttpsToUpload = new ConfigKey<>("Advanced", Boolean.class, "use.https.to.upload", "true", @@ -85,7 +86,7 @@ public interface VolumeApiService { * @param cmd * the API command wrapping the criteria * @return the volume object - * @throws ResourceAllocationException + * @throws ResourceAllocationException no capacity to allocate the new volume size */ Volume resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationException; @@ -139,13 +140,13 @@ public interface VolumeApiService { Snapshot allocSnapshotForVm(Long vmId, Long volumeId, String snapshotName) throws ResourceAllocationException; /** - * Checks if the target storage supports the disk offering. + * Checks if the storage pool supports the disk offering tags. * This validation is consistent with the mechanism used to select a storage pool to deploy a volume when a virtual machine is deployed or when a data disk is allocated. * * The scenarios when this method returns true or false is presented in the following table. * * - * + * * * * @@ -169,7 +170,8 @@ public interface VolumeApiService { * *
#Disk offering tagsStorage tagsDoes the storage support the disk offering?#Disk offering diskOfferingTagsStorage diskOfferingTagsDoes the storage support the disk offering?
*/ - boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, String diskOfferingTags); + boolean doesStoragePoolSupportDiskOffering(StoragePool destPool, DiskOffering diskOffering); + boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags); Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java index e94bff1fce8..fcd6b03d3e5 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/IsAccountAllowedToCreateOfferingsWithTagsCmd.java @@ -29,7 +29,7 @@ import org.apache.cloudstack.api.response.IsAccountAllowedToCreateOfferingsWithT responseObject = IsAccountAllowedToCreateOfferingsWithTagsResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class IsAccountAllowedToCreateOfferingsWithTagsCmd extends BaseCmd { - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account UUID") + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "Account UUID", required = true) private Long id; @Override diff --git a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java index 0802098cb4f..3d5646f68c9 100644 --- a/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java +++ b/api/src/main/java/org/apache/cloudstack/vm/UnmanagedInstanceTO.java @@ -33,6 +33,8 @@ public class UnmanagedInstanceTO { private String internalCSName; + private String path; + private PowerState powerState; private PowerState cloneSourcePowerState; @@ -75,6 +77,14 @@ public class UnmanagedInstanceTO { this.internalCSName = internalCSName; } + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + public PowerState getPowerState() { return powerState; } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 6d27b0efed3..7b231d02cb0 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -707,7 +707,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac private void handleUnsuccessfulExpungeOperation(List finalizeExpungeCommands, List nicExpungeCommands, VMInstanceVO vm, Long hostId) throws OperationTimedoutException, AgentUnavailableException { - if (CollectionUtils.isNotEmpty(finalizeExpungeCommands) || CollectionUtils.isNotEmpty(nicExpungeCommands) && (hostId != null)) { + if ((CollectionUtils.isNotEmpty(finalizeExpungeCommands) || CollectionUtils.isNotEmpty(nicExpungeCommands)) && hostId != null) { final Commands cmds = new Commands(Command.OnError.Stop); addAllExpungeCommandsFromList(finalizeExpungeCommands, cmds, vm); addAllExpungeCommandsFromList(nicExpungeCommands, cmds, vm); diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java index f8ffbf74f85..99ba3587688 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageNetworksDaoImpl.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.usage.dao; -import com.cloud.network.Network; import com.cloud.usage.UsageNetworksVO; import com.cloud.utils.DateUtil; import com.cloud.utils.db.GenericDaoBase; @@ -70,11 +69,10 @@ public class UsageNetworksDaoImpl extends GenericDaoBase SearchCriteria sc = this.createSearchCriteria(); sc.addAnd("networkId", SearchCriteria.Op.EQ, networkId); sc.addAnd("removed", SearchCriteria.Op.NULL); - UsageNetworksVO vo = findOneBy(sc); - if (vo != null) { - vo.setRemoved(removed); - vo.setState(Network.State.Destroy.name()); - update(vo.getId(), vo); + List usageNetworksVOs = listBy(sc); + for (UsageNetworksVO entry : usageNetworksVOs) { + entry.setRemoved(removed); + update(entry.getId(), entry); } } catch (final Exception e) { txn.rollback(); diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java index 45ae845e58f..70cdadd1629 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.usage.dao; -import com.cloud.network.vpc.Vpc; import com.cloud.usage.UsageVpcVO; import com.cloud.utils.DateUtil; import com.cloud.utils.db.GenericDaoBase; @@ -64,11 +63,10 @@ public class UsageVpcDaoImpl extends GenericDaoBase implements SearchCriteria sc = this.createSearchCriteria(); sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId); sc.addAnd("removed", SearchCriteria.Op.NULL); - UsageVpcVO vo = findOneBy(sc); - if (vo != null) { - vo.setRemoved(removed); - vo.setState(Vpc.State.Inactive.name()); - update(vo.getId(), vo); + List usageVpcVOs = listBy(sc); + for (UsageVpcVO entry : usageVpcVOs) { + entry.setRemoved(removed); + update(entry.getId(), entry); } } catch (final Exception e) { txn.rollback(); diff --git a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java index 0735136d15d..a7ce0c09cc6 100644 --- a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java +++ b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java @@ -45,6 +45,8 @@ import com.cloud.dc.VmwareDatacenter; import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMap; import com.cloud.dc.dao.VmwareDatacenterDao; import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.user.User; import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; import com.cloud.utils.exception.CloudRuntimeException; @@ -100,6 +102,8 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, private AgentManager agentMgr; @Inject private VirtualMachineManager virtualMachineManager; + @Inject + private VolumeDao volumeDao; protected VeeamClient getClient(final Long zoneId) { try { @@ -340,6 +344,59 @@ public class VeeamBackupProvider extends AdapterBase implements BackupProvider, return getClient(vm.getDataCenterId()).listRestorePoints(backupName, vm.getInstanceName()); } + @Override + public void syncBackups(VirtualMachine vm, Backup.Metric metric) { + List restorePoints = listRestorePoints(vm); + if (CollectionUtils.isEmpty(restorePoints)) { + logger.debug("Can't find any restore point to VM: {}", vm); + return; + } + Transaction.execute(new TransactionCallbackNoReturn() { + @Override + public void doInTransactionWithoutResult(TransactionStatus status) { + final List backupsInDb = backupDao.listByVmId(null, vm.getId()); + final List removeList = backupsInDb.stream().map(InternalIdentity::getId).collect(Collectors.toList()); + for (final Backup.RestorePoint restorePoint : restorePoints) { + if (!(restorePoint.getId() == null || restorePoint.getType() == null || restorePoint.getCreated() == null)) { + Backup existingBackupEntry = checkAndUpdateIfBackupEntryExistsForRestorePoint(backupsInDb, restorePoint, metric); + if (existingBackupEntry != null) { + removeList.remove(existingBackupEntry.getId()); + continue; + } + + BackupVO backup = new BackupVO(); + backup.setVmId(vm.getId()); + backup.setExternalId(restorePoint.getId()); + backup.setType(restorePoint.getType()); + backup.setDate(restorePoint.getCreated()); + backup.setStatus(Backup.Status.BackedUp); + if (metric != null) { + backup.setSize(metric.getBackupSize()); + backup.setProtectedSize(metric.getDataSize()); + } + backup.setBackupOfferingId(vm.getBackupOfferingId()); + backup.setAccountId(vm.getAccountId()); + backup.setDomainId(vm.getDomainId()); + backup.setZoneId(vm.getDataCenterId()); + backup.setBackedUpVolumes(BackupManagerImpl.createVolumeInfoFromVolumes(volumeDao.findByInstance(vm.getId()))); + + logger.debug("Creating a new entry in backups: [id: {}, uuid: {}, name: {}, vm_id: {}, external_id: {}, type: {}, date: {}, backup_offering_id: {}, account_id: {}, " + + "domain_id: {}, zone_id: {}].", backup.getId(), backup.getUuid(), backup.getName(), backup.getVmId(), backup.getExternalId(), backup.getType(), backup.getDate(), backup.getBackupOfferingId(), backup.getAccountId(), backup.getDomainId(), backup.getZoneId()); + backupDao.persist(backup); + + ActionEventUtils.onCompletedActionEvent(User.UID_SYSTEM, vm.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_VM_BACKUP_CREATE, + String.format("Created backup %s for VM ID: %s", backup.getUuid(), vm.getUuid()), + vm.getId(), ApiCommandResourceType.VirtualMachine.toString(),0); + } + } + for (final Long backupIdToRemove : removeList) { + logger.warn(String.format("Removing backup with ID: [%s].", backupIdToRemove)); + backupDao.remove(backupIdToRemove); + } + } + }); + } + @Override public String getConfigComponentName() { return BackupService.class.getSimpleName(); 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 3ba1bc11975..a11730a1240 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 @@ -70,7 +70,6 @@ public class LibvirtConvertInstanceCommandWrapper extends CommandWrapper destinationStoragePools = cmd.getDestinationStoragePools(); DataStoreTO conversionTemporaryLocation = cmd.getConversionTemporaryLocation(); long timeout = (long) cmd.getWait() * 1000; @@ -193,9 +192,15 @@ public class LibvirtConvertInstanceCommandWrapper extends CommandWrapper capabilities = new ArrayList<>(); - - private static String cpuInfoFreqFileName = "/sys/devices/system/cpu/cpu0/cpufreq/base_frequency"; private static String cpuArchCommand = "/usr/bin/arch"; + private static List cpuInfoFreqFileNames = List.of("/sys/devices/system/cpu/cpu0/cpufreq/base_frequency","/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"); public KVMHostInfo(long reservedMemory, long overCommitMemory, long manualSpeed, int reservedCpus) { this.cpuSpeed = manualSpeed; @@ -138,32 +137,44 @@ public class KVMHostInfo { } private static long getCpuSpeedFromCommandLscpu() { + long speed = 0L; + LOGGER.info("Fetching CPU speed from command \"lscpu\"."); try { - LOGGER.info("Fetching CPU speed from command \"lscpu\"."); String command = "lscpu | grep -i 'Model name' | head -n 1 | egrep -o '[[:digit:]].[[:digit:]]+GHz' | sed 's/GHz//g'"; if(isHostS390x()) { command = "lscpu | grep 'CPU dynamic MHz' | cut -d ':' -f 2 | tr -d ' ' | awk '{printf \"%.1f\\n\", $1 / 1000}'"; } String result = Script.runSimpleBashScript(command); - long speed = (long) (Float.parseFloat(result) * 1000); + speed = (long) (Float.parseFloat(result) * 1000); LOGGER.info(String.format("Command [%s] resulted in the value [%s] for CPU speed.", command, speed)); return speed; } catch (NullPointerException | NumberFormatException e) { LOGGER.error(String.format("Unable to retrieve the CPU speed from lscpu."), e); - return 0L; } + try { + String command = "lscpu | grep -i 'CPU max MHz' | head -n 1 | sed 's/^.*: //' | xargs"; + String result = Script.runSimpleBashScript(command); + speed = (long) (Float.parseFloat(result)); + LOGGER.info(String.format("Command [%s] resulted in the value [%s] for CPU speed.", command, speed)); + return speed; + } catch (NullPointerException | NumberFormatException e) { + LOGGER.error(String.format("Unable to retrieve the CPU speed from lscpu."), e); + } + return speed; } private static long getCpuSpeedFromFile() { - LOGGER.info(String.format("Fetching CPU speed from file [%s].", cpuInfoFreqFileName)); - try (Reader reader = new FileReader(cpuInfoFreqFileName)) { - Long cpuInfoFreq = Long.parseLong(IOUtils.toString(reader).trim()); - LOGGER.info(String.format("Retrieved value [%s] from file [%s]. This corresponds to a CPU speed of [%s] MHz.", cpuInfoFreq, cpuInfoFreqFileName, cpuInfoFreq / 1000)); - return cpuInfoFreq / 1000; - } catch (IOException | NumberFormatException e) { - LOGGER.error(String.format("Unable to retrieve the CPU speed from file [%s]", cpuInfoFreqFileName), e); - return 0L; + for (final String cpuInfoFreqFileName: cpuInfoFreqFileNames) { + LOGGER.info(String.format("Fetching CPU speed from file [%s].", cpuInfoFreqFileName)); + try (Reader reader = new FileReader(cpuInfoFreqFileName)) { + Long cpuInfoFreq = Long.parseLong(IOUtils.toString(reader).trim()); + LOGGER.info(String.format("Retrieved value [%s] from file [%s]. This corresponds to a CPU speed of [%s] MHz.", cpuInfoFreq, cpuInfoFreqFileName, cpuInfoFreq / 1000)); + return cpuInfoFreq / 1000; + } catch (IOException | NumberFormatException e) { + LOGGER.error(String.format("Unable to retrieve the CPU speed from file [%s]", cpuInfoFreqFileName), e); + } } + return 0L; } protected static long getCpuSpeedFromHostCapabilities(final String capabilities) { diff --git a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java index 2fe74759410..6c528863484 100644 --- a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java +++ b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolOutOfBandManagementDriver.java @@ -45,13 +45,13 @@ public final class IpmitoolOutOfBandManagementDriver extends AdapterBase impleme private final ExecutorService ipmitoolExecutor = Executors.newFixedThreadPool(OutOfBandManagementService.SyncThreadPoolSize.value(), new NamedThreadFactory("IpmiToolDriver")); private final IpmitoolWrapper IPMITOOL = new IpmitoolWrapper(ipmitoolExecutor); - public final ConfigKey IpmiToolPath = new ConfigKey("Advanced", String.class, "outofbandmanagement.ipmitool.path", "/usr/bin/ipmitool", + public final ConfigKey IpmiToolPath = new ConfigKey<>("Advanced", String.class, "outofbandmanagement.ipmitool.path", "/usr/bin/ipmitool", "The out of band management ipmitool path used by the IpmiTool driver. Default: /usr/bin/ipmitool.", true, ConfigKey.Scope.Global); - public final ConfigKey IpmiToolInterface = new ConfigKey("Advanced", String.class, "outofbandmanagement.ipmitool.interface", "lanplus", + public final ConfigKey IpmiToolInterface = new ConfigKey<>("Advanced", String.class, "outofbandmanagement.ipmitool.interface", "lanplus", "The out of band management IpmiTool driver interface to use. Default: lanplus. Valid values are: lan, lanplus, open etc.", true, ConfigKey.Scope.Global); - public final ConfigKey IpmiToolRetries = new ConfigKey("Advanced", String.class, "outofbandmanagement.ipmitool.retries", "1", + public final ConfigKey IpmiToolRetries = new ConfigKey<>("Advanced", String.class, "outofbandmanagement.ipmitool.retries", "1", "The out of band management IpmiTool driver retries option -R. Default 1.", true, ConfigKey.Scope.Global); private String getIpmiUserId(ImmutableMap options, final Duration timeOut) { @@ -120,7 +120,7 @@ public final class IpmitoolOutOfBandManagementDriver extends AdapterBase impleme final OutOfBandManagementDriverResponse response = IPMITOOL.executeCommands(ipmiToolCommands, cmd.getTimeout()); - String oneLineCommand = StringUtils.join(ipmiToolCommands, " "); + String oneLineCommand = StringUtils.join(IPMITOOL.getSanatisedCommandStrings(ipmiToolCommands), " "); String result = response.getResult().trim(); if (response.isSuccess()) { diff --git a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java index 86ec615e552..b0ded5350a3 100644 --- a/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java +++ b/plugins/outofbandmanagement-drivers/ipmitool/src/main/java/org/apache/cloudstack/outofbandmanagement/driver/ipmitool/IpmitoolWrapper.java @@ -27,6 +27,7 @@ import org.apache.cloudstack.utils.process.ProcessResult; import org.apache.cloudstack.utils.process.ProcessRunner; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; + import org.joda.time.Duration; import java.util.ArrayList; @@ -34,7 +35,7 @@ import java.util.List; import java.util.concurrent.ExecutorService; public final class IpmitoolWrapper { - protected Logger logger = LogManager.getLogger(getClass()); + Logger logger = LogManager.getLogger(getClass()); private final ProcessRunner RUNNER; @@ -110,12 +111,12 @@ public final class IpmitoolWrapper { return ipmiToolCommands.build(); } + /** + * Expected usersList string contains legends on first line and users on rest + * ID Name Callin Link Auth IPMI Msg Channel Priv Limit + * 1 admin true true true ADMINISTRATOR + */ public String findIpmiUser(final String usersList, final String username) { - /** - * Expected usersList string contains legends on first line and users on rest - * ID Name Callin Link Auth IPMI Msg Channel Priv Limit - * 1 admin true true true ADMINISTRATOR - */ // Assuming user 'ID' index on 1st position int idIndex = 0; @@ -157,25 +158,31 @@ public final class IpmitoolWrapper { public OutOfBandManagementDriverResponse executeCommands(final List commands, final Duration timeOut) { final ProcessResult result = RUNNER.executeCommands(commands, timeOut); if (logger.isTraceEnabled()) { - List cleanedCommands = new ArrayList(); - int maskNextCommand = 0; - for (String command : commands) { - if (maskNextCommand > 0) { - cleanedCommands.add("**** "); - maskNextCommand--; - continue; - } - if (command.equalsIgnoreCase("-P")) { - maskNextCommand = 1; - } else if (command.toLowerCase().endsWith("password")) { - maskNextCommand = 2; - } - cleanedCommands.add(command); - } - logger.trace("Executed ipmitool process with commands: " + StringUtils.join(cleanedCommands, ", ") + - "\nIpmitool execution standard output: " + result.getStdOutput() + - "\nIpmitool execution error output: " + result.getStdError()); + List cleanedCommands = getSanatisedCommandStrings(commands); + logger.trace("Executed ipmitool process with commands: {}\nIpmitool execution standard output: {}\nIpmitool execution error output: {}", + StringUtils.join(cleanedCommands, ", "), + result.getStdOutput(), + result.getStdError()); } return new OutOfBandManagementDriverResponse(result.getStdOutput(), result.getStdError(), result.isSuccess()); } + + List getSanatisedCommandStrings(List commands) { + List cleanedCommands = new ArrayList<>(); + int maskNextCommand = 0; + for (String command : commands) { + if (maskNextCommand > 0) { + cleanedCommands.add("**** "); + maskNextCommand--; + continue; + } + if (command.equalsIgnoreCase("-P")) { + maskNextCommand = 1; + } else if (command.toLowerCase().endsWith("password")) { + maskNextCommand = 2; + } + cleanedCommands.add(command); + } + return cleanedCommands; + } } diff --git a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java index f4a8167c5a2..60ba90b77d5 100644 --- a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java @@ -778,13 +778,14 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi AlertVO alert = null; Long clusterId = cluster == null ? null : cluster.getId(); Long podId = pod == null ? null : pod.getId(); + long dcId = dataCenter == null ? 0L : dataCenter.getId(); if ((alertType != AlertManager.AlertType.ALERT_TYPE_HOST) && (alertType != AlertManager.AlertType.ALERT_TYPE_USERVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_DOMAIN_ROUTER) && (alertType != AlertManager.AlertType.ALERT_TYPE_CONSOLE_PROXY) && (alertType != AlertManager.AlertType.ALERT_TYPE_SSVM) && (alertType != AlertManager.AlertType.ALERT_TYPE_STORAGE_MISC) && (alertType != AlertManager.AlertType.ALERT_TYPE_MANAGEMENT_NODE) && (alertType != AlertManager.AlertType.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED) && (alertType != AlertManager.AlertType.ALERT_TYPE_UPLOAD_FAILED) && (alertType != AlertManager.AlertType.ALERT_TYPE_OOBM_AUTH_ERROR) && (alertType != AlertManager.AlertType.ALERT_TYPE_HA_ACTION) && (alertType != AlertManager.AlertType.ALERT_TYPE_CA_CERT)) { - alert = _alertDao.getLastAlert(alertType.getType(), dataCenter.getId(), podId, clusterId); + alert = _alertDao.getLastAlert(alertType.getType(), dcId, podId, clusterId); } if (alert == null) { @@ -794,7 +795,7 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi newAlert.setContent(content); newAlert.setClusterId(clusterId); newAlert.setPodId(podId); - newAlert.setDataCenterId(dataCenter.getId()); + newAlert.setDataCenterId(dcId); newAlert.setSentCount(1); newAlert.setLastSent(new Date()); newAlert.setName(alertType.getName()); diff --git a/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java b/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java index 101731774e7..c003bd05a51 100644 --- a/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java +++ b/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java @@ -255,9 +255,9 @@ public class BGPServiceImpl implements BGPService { netName = network.getName(); } - LOGGER.debug("Allocating the AS Number {} to {} on zone {}", asNumber::toString, - (Objects.nonNull(vpcId) ? "VPC " + vpc : "network " + network)::toString, - () -> dataCenterDao.findById(zoneId)); + String networkName = Objects.nonNull(vpcId) ? ("VPC " + vpc) : ("network " + network); + LOGGER.debug("Allocating the AS Number {} to {} on zone {}", asNumberVO::toString, + networkName::toString, () -> dataCenterDao.findById(zoneId)); asNumberVO.setAllocated(true); asNumberVO.setAllocatedTime(new Date()); if (Objects.nonNull(vpcId)) { diff --git a/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java b/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java index e1f850978d5..47c9979c2f6 100644 --- a/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java +++ b/server/src/main/java/com/cloud/network/element/ConfigDriveNetworkElement.java @@ -220,7 +220,7 @@ public class ConfigDriveNetworkElement extends AdapterBase implements NetworkEle @Override public boolean canEnableIndividualServices() { - return false; + return true; } private String getSshKey(VirtualMachineProfile profile) { diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 2eaf437af01..89cfb3509cb 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -44,6 +44,7 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.cpu.CPU; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.affinity.AffinityGroupProcessor; @@ -1612,6 +1613,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe logger.debug("Hosts having capacity and suitable for migration: {}", suitableHosts); } + // Only list hosts of the same architecture as the source Host in a multi-arch zone + if (!suitableHosts.isEmpty()) { + List clusterArchs = ApiDBUtils.listZoneClustersArchs(vm.getDataCenterId()); + if (CollectionUtils.isNotEmpty(clusterArchs) && clusterArchs.size() > 1) { + suitableHosts = suitableHosts.stream().filter(h -> h.getArch() == srcHost.getArch()).collect(Collectors.toList()); + } + } + return new Ternary<>(otherHosts, suitableHosts, requiresStorageMotion); } diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 12d3d315052..1a25f36efe2 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -368,15 +368,15 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this); - static final ConfigKey VmJobCheckInterval = new ConfigKey("Advanced", Long.class, "vm.job.check.interval", "3000", "Interval in milliseconds to check if the job is complete", false); + static final ConfigKey VmJobCheckInterval = new ConfigKey<>("Advanced", Long.class, "vm.job.check.interval", "3000", "Interval in milliseconds to check if the job is complete", false); - static final ConfigKey VolumeUrlCheck = new ConfigKey("Advanced", Boolean.class, "volume.url.check", "true", + static final ConfigKey VolumeUrlCheck = new ConfigKey<>("Advanced", Boolean.class, "volume.url.check", "true", "Check the url for a volume before downloading it from the management server. Set to false when your management has no internet access.", true); - public static final ConfigKey AllowUserExpungeRecoverVolume = new ConfigKey("Advanced", Boolean.class, "allow.user.expunge.recover.volume", "true", + public static final ConfigKey AllowUserExpungeRecoverVolume = new ConfigKey<>("Advanced", Boolean.class, "allow.user.expunge.recover.volume", "true", "Determines whether users can expunge or recover their volume", true, ConfigKey.Scope.Account); - public static final ConfigKey MatchStoragePoolTagsWithDiskOffering = new ConfigKey("Advanced", Boolean.class, "match.storage.pool.tags.with.disk.offering", "true", + public static final ConfigKey MatchStoragePoolTagsWithDiskOffering = new ConfigKey<>("Advanced", Boolean.class, "match.storage.pool.tags.with.disk.offering", "true", "If true, volume's disk offering can be changed only with the matched storage tags", true, ConfigKey.Scope.Zone); public static final ConfigKey WaitDetachDevice = new ConfigKey<>( @@ -390,7 +390,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic public static ConfigKey storageTagRuleExecutionTimeout = new ConfigKey<>("Advanced", Long.class, "storage.tag.rule.execution.timeout", "2000", "The maximum runtime," + " in milliseconds, to execute a storage tag rule; if it is reached, a timeout will happen.", true); - public static final ConfigKey AllowCheckAndRepairVolume = new ConfigKey("Advanced", Boolean.class, "volume.check.and.repair.leaks.before.use", "false", + public static final ConfigKey AllowCheckAndRepairVolume = new ConfigKey<>("Advanced", Boolean.class, "volume.check.and.repair.leaks.before.use", "false", "To check and repair the volume if it has any leaks before performing volume attach or VM start operations", true, ConfigKey.Scope.StoragePool); private final StateMachine2 _volStateMachine; @@ -639,7 +639,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic return Transaction.execute(new TransactionCallbackWithException() { @Override public VolumeVO doInTransaction(TransactionStatus status) { - VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, Storage.ProvisioningType.THIN, 0, Volume.Type.DATADISK); + VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, -1L, null, null, Storage.ProvisioningType.THIN, 0, Volume.Type.DATADISK); DataCenter zone = _dcDao.findById(zoneId); volume.setPoolId(null); volume.setDataCenterId(zoneId); @@ -841,7 +841,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic maxIops = diskOffering.getMaxIops(); } - if (!validateVolumeSizeInBytes(size)) { + if (!validateVolumeSizeInBytes(size == null ? 0 : size)) { throw new InvalidParameterValueException(String.format("Invalid size for custom volume creation: %s, max volume size is: %s GB", NumbersUtil.toReadableSize(size), VolumeOrchestrationService.MaxVolumeSize.value())); } } @@ -3592,7 +3592,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic if ((destPool.isShared() && newDiskOffering.isUseLocalStorage()) || destPool.isLocal() && newDiskOffering.isShared()) { throw new InvalidParameterValueException("You cannot move the volume to a shared storage and assign a disk offering for local storage and vice versa."); } - if (!doesTargetStorageSupportDiskOffering(destPool, newDiskOffering)) { + if (!doesStoragePoolSupportDiskOffering(destPool, newDiskOffering)) { throw new InvalidParameterValueException(String.format("Migration failed: target pool [%s, tags:%s] has no matching tags for volume [%s, uuid:%s, tags:%s]", destPool.getName(), storagePoolTagsDao.getStoragePoolTags(destPool.getId()), volume.getName(), volume.getUuid(), newDiskOffering.getTags())); } @@ -3618,7 +3618,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } /** - * Checks if the target storage supports the new disk offering. + * Checks if the storage pool supports the new disk offering. * This validation is consistent with the mechanism used to select a storage pool to deploy a volume when a virtual machine is deployed or when a new data disk is allocated. * * The scenarios when this method returns true or false is presented in the following table. @@ -3649,9 +3649,9 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic * * */ - protected boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, DiskOfferingVO diskOffering) { - String targetStoreTags = diskOffering.getTags(); - return doesTargetStorageSupportDiskOffering(destPool, targetStoreTags); + public boolean doesStoragePoolSupportDiskOffering(StoragePool destPool, DiskOffering diskOffering) { + String offeringTags = diskOffering != null ? diskOffering.getTags() : null; + return doesStoragePoolSupportDiskOfferingTags(destPool, offeringTags); } public static boolean doesNewDiskOfferingHasTagsAsOldDiskOffering(DiskOfferingVO oldDO, DiskOfferingVO newDO) { @@ -3667,19 +3667,19 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } @Override - public boolean doesTargetStorageSupportDiskOffering(StoragePool destPool, String diskOfferingTags) { + public boolean doesStoragePoolSupportDiskOfferingTags(StoragePool destPool, String diskOfferingTags) { Pair, Boolean> storagePoolTags = getStoragePoolTags(destPool); if ((storagePoolTags == null || !storagePoolTags.second()) && org.apache.commons.lang.StringUtils.isBlank(diskOfferingTags)) { if (storagePoolTags == null) { - logger.debug(String.format("Destination storage pool [%s] does not have any tags, and so does the disk offering. Therefore, they are compatible", destPool.getUuid())); + logger.debug("Storage pool [{}] does not have any tags, and so does the disk offering. Therefore, they are compatible", destPool.getUuid()); } else { - logger.debug("Destination storage pool has tags [%s], and the disk offering has no tags. Therefore, they are compatible."); + logger.debug("Storage pool has tags [%s], and the disk offering has no tags. Therefore, they are compatible.", destPool.getUuid()); } return true; } if (storagePoolTags == null || CollectionUtils.isEmpty(storagePoolTags.first())) { - logger.debug(String.format("Destination storage pool [%s] has no tags, while disk offering has tags [%s]. Therefore, they are not compatible", destPool.getUuid(), - diskOfferingTags)); + logger.debug("Destination storage pool [{}] has no tags, while disk offering has tags [{}]. Therefore, they are not compatible", destPool.getUuid(), + diskOfferingTags); return false; } List storageTagsList = storagePoolTags.first(); @@ -3691,7 +3691,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } else { result = CollectionUtils.isSubCollection(Arrays.asList(newDiskOfferingTagsAsStringArray), storageTagsList); } - logger.debug(String.format("Destination storage pool [%s] accepts tags [%s]? %s", destPool.getUuid(), diskOfferingTags, result)); + logger.debug(String.format("Destination storage pool [{}] accepts tags [{}]? {}", destPool.getUuid(), diskOfferingTags, result)); return result; } diff --git a/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java b/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java index aac5d1277a6..9e1fc46e02e 100644 --- a/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImpl.java @@ -79,7 +79,7 @@ import org.apache.logging.log4j.Logger; import javax.inject.Inject; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @@ -206,7 +206,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ if (diskOffering.isCustomized()) { volumeApiService.validateCustomDiskOfferingSizeRange(volume.getVirtualSize() / ByteScaleUtils.GiB); } - if (!volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags())) { + if (!volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { logFailureAndThrowException(String.format("Disk offering: %s storage tags are not compatible with selected storage pool: %s", diskOffering, pool)); } @@ -248,7 +248,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ StorageFilerTO storageTO = new StorageFilerTO(pool); GetVolumesOnStorageCommand command = new GetVolumesOnStorageCommand(storageTO, volumePath, keyword); Answer answer = agentManager.easySend(host.getId(), command); - if (answer == null || !(answer instanceof GetVolumesOnStorageAnswer)) { + if (!(answer instanceof GetVolumesOnStorageAnswer)) { logFailureAndThrowException(String.format("Cannot get volumes on storage pool via host %s", host)); } if (!answer.getResult()) { @@ -366,7 +366,7 @@ public class VolumeImportUnmanageManagerImpl implements VolumeImportUnmanageServ } private boolean checkIfVolumeForSnapshot(StoragePoolVO pool, String fullVolumePath) { - List absPathList = Arrays.asList(fullVolumePath); + List absPathList = Collections.singletonList(fullVolumePath); return CollectionUtils.isNotEmpty(snapshotDataStoreDao.listByStoreAndInstallPaths(pool.getId(), DataStoreRole.Primary, absPathList)); } 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 d8b6acccd03..8d5387b3ffd 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -460,7 +460,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { if (diskOffering == null) { return false; } - return volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags()); + return volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering); } private ServiceOfferingVO getUnmanagedInstanceServiceOffering(final UnmanagedInstanceTO instance, ServiceOfferingVO serviceOffering, final Account owner, final DataCenter zone, final Map details, Hypervisor.HypervisorType hypervisorType) @@ -538,7 +538,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { return nicIpAddresses; } - private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, String diskOfferingTags) { + private StoragePool getStoragePool(final UnmanagedInstanceTO.Disk disk, final DataCenter zone, final Cluster cluster, DiskOffering diskOffering) { StoragePool storagePool = null; final String dsHost = disk.getDatastoreHost(); final String dsPath = disk.getDatastorePath(); @@ -549,7 +549,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { for (StoragePool pool : pools) { if (pool.getDataCenterId() == zone.getId() && (pool.getClusterId() == null || pool.getClusterId().equals(cluster.getId())) && - volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) { + volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { storagePool = pool; break; } @@ -562,7 +562,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { for (StoragePool pool : pools) { String searchPoolParam = StringUtils.isNotBlank(dsPath) ? dsPath : dsName; if (StringUtils.contains(pool.getPath(), searchPoolParam) && - volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOfferingTags)) { + volumeApiService.doesStoragePoolSupportDiskOffering(pool, diskOffering)) { storagePool = pool; break; } @@ -626,7 +626,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Size of disk offering(ID: %s) %dGB is found less than the size of disk(ID: %s) %dGB during VM import", diskOffering.getUuid(), (diskOffering.getDiskSize() / Resource.ResourceType.bytesToGiB), disk.getDiskId(), (disk.getCapacity() / (Resource.ResourceType.bytesToGiB)))); } diskOffering = diskOffering != null ? diskOffering : diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); - StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering != null ? diskOffering.getTags() : null); + StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering); if (diskOffering != null && !migrateAllowed && !storagePoolSupportsDiskOffering(storagePool, diskOffering)) { throw new InvalidParameterValueException(String.format("Disk offering: %s is not compatible with storage pool: %s of unmanaged disk: %s", diskOffering.getUuid(), storagePool.getUuid(), disk.getDiskId())); } @@ -863,7 +863,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { diskInfo.setDiskChain(new String[]{disk.getImagePath()}); chainInfo = gson.toJson(diskInfo); } - StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering != null ? diskOffering.getTags() : null); + StoragePool storagePool = getStoragePool(disk, zone, cluster, diskOffering); DiskProfile profile = volumeManager.importVolume(type, name, diskOffering, diskSize, minIops, maxIops, vm.getDataCenterId(), vm.getHypervisorType(), vm, template, owner, deviceId, storagePool.getId(), path, chainInfo); @@ -1765,9 +1765,9 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { convertedInstance.setPowerState(UnmanagedInstanceTO.PowerState.PowerOff); List convertedInstanceDisks = convertedInstance.getDisks(); List sourceVMwareInstanceDisks = sourceVMwareInstance.getDisks(); - for (UnmanagedInstanceTO.Disk sourceVMwareInstanceDisk : sourceVMwareInstanceDisks) { - UnmanagedInstanceTO.Disk convertedDisk = convertedInstanceDisks.get(sourceVMwareInstanceDisk.getPosition()); - convertedDisk.setDiskId(sourceVMwareInstanceDisk.getDiskId()); + for (int i = 0; i < convertedInstanceDisks.size(); i++) { + UnmanagedInstanceTO.Disk disk = convertedInstanceDisks.get(i); + disk.setDiskId(sourceVMwareInstanceDisks.get(i).getDiskId()); } List convertedInstanceNics = convertedInstance.getNics(); List sourceVMwareInstanceNics = sourceVMwareInstance.getNics(); @@ -1994,7 +1994,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { ) { logger.debug("Delegating the conversion of instance {} from VMware to KVM to the host {} after OVF export through ovftool", sourceVM, convertHost); - RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName); + RemoteInstanceTO remoteInstanceTO = new RemoteInstanceTO(sourceVMwareInstance.getName(), sourceVMwareInstance.getPath(), vcenterHost, vcenterUsername, vcenterPassword, datacenterName); List destinationStoragePools = selectInstanceConversionStoragePools(convertStoragePools, sourceVMwareInstance.getDisks(), serviceOffering, dataDiskOfferingMap); ConvertInstanceCommand cmd = new ConvertInstanceCommand(remoteInstanceTO, Hypervisor.HypervisorType.KVM, destinationStoragePools, temporaryConvertLocation, null, false, true); @@ -2066,6 +2066,25 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { pools.addAll(primaryDataStoreDao.findClusterWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); pools.addAll(primaryDataStoreDao.findZoneWideStoragePoolsByHypervisorAndPoolType(destinationCluster.getDataCenterId(), Hypervisor.HypervisorType.KVM, Storage.StoragePoolType.NetworkFilesystem)); List diskOfferingTags = new ArrayList<>(); + if (pools.isEmpty()) { + String msg = String.format("Cannot find suitable storage pools in the cluster %s for the conversion", destinationCluster.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + + if (serviceOffering.getDiskOfferingId() != null) { + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + if (diskOffering == null) { + String msg = String.format("Cannot find disk offering with ID %s that belongs to the service offering %s", serviceOffering.getDiskOfferingId(), serviceOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + if (getStoragePoolWithTags(pools, diskOffering.getTags()) == null) { + String msg = String.format("Cannot find suitable storage pool for disk offering %s that belongs to the service offering %s", diskOffering.getName(), serviceOffering.getName()); + logger.error(msg); + throw new CloudRuntimeException(msg); + } + } for (Long diskOfferingId : dataDiskOfferingMap.values()) { DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); if (diskOffering == null) { @@ -2099,7 +2118,7 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { for (String tags : diskOfferingTags) { boolean tagsMatched = false; for (StoragePoolVO pool : pools) { - if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, tags)) { + if (volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, tags)) { poolsSupportingTags.add(pool); tagsMatched = true; } @@ -2110,7 +2129,20 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { throw new CloudRuntimeException(msg); } } - return poolsSupportingTags; + + return pools; + } + + private StoragePoolVO getStoragePoolWithTags(List pools, String tags) { + if (StringUtils.isEmpty(tags)) { + return pools.get(0); + } + for (StoragePoolVO pool : pools) { + if (volumeApiService.doesStoragePoolSupportDiskOfferingTags(pool, tags)) { + return pool; + } + } + return null; } private List selectInstanceConversionStoragePools( @@ -2118,26 +2150,22 @@ public class UnmanagedVMsManagerImpl implements UnmanagedVMsManager { ServiceOfferingVO serviceOffering, Map dataDiskOfferingMap ) { List storagePools = new ArrayList<>(disks.size()); - for (int i = 0; i < disks.size(); i++) { - storagePools.add(null); - } Set dataDiskIds = dataDiskOfferingMap.keySet(); for (UnmanagedInstanceTO.Disk disk : disks) { - Long diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); - if (diskOfferingId == null && !dataDiskIds.contains(disk.getDiskId())) { + Long diskOfferingId = null; + if (dataDiskIds.contains(disk.getDiskId())) { + diskOfferingId = dataDiskOfferingMap.get(disk.getDiskId()); + } else { diskOfferingId = serviceOffering.getDiskOfferingId(); } + //TODO: Choose pools by capacity if (diskOfferingId == null) { - storagePools.set(disk.getPosition(), pools.get(0).getUuid()); + storagePools.add(pools.get(0).getUuid()); } else { DiskOfferingVO diskOffering = diskOfferingDao.findById(diskOfferingId); - for (StoragePoolVO pool : pools) { - if (volumeApiService.doesTargetStorageSupportDiskOffering(pool, diskOffering.getTags())) { - storagePools.set(disk.getPosition(), pool.getUuid()); - break; - } - } + StoragePoolVO pool = getStoragePoolWithTags(pools, diskOffering.getTags()); + storagePools.add(pool.getUuid()); } } return storagePools; diff --git a/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java b/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java index 2959e73ae9e..d34d0b5873f 100644 --- a/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java +++ b/server/src/test/java/com/cloud/alert/AlertManagerImplTest.java @@ -26,8 +26,10 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.utils.mailing.SMTPMailSender; import org.apache.logging.log4j.Logger; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; @@ -48,6 +50,12 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.storage.StorageManager; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + @RunWith(MockitoJUnitRunner.class) public class AlertManagerImplTest { @@ -56,7 +64,7 @@ public class AlertManagerImplTest { AlertManagerImpl alertManagerImplMock; @Mock - AlertDao alertDaoMock; + AlertDao _alertDao; @Mock private DataCenterDao _dcDao; @@ -88,7 +96,16 @@ public class AlertManagerImplTest { @Mock SMTPMailSender mailSenderMock; - private void sendMessage (){ + private final String[] recipients = new String[]{"test@test.com"}; + private final String senderAddress = "sender@test.com"; + + @Before + public void setUp() { + alertManagerImplMock.recipients = recipients; + alertManagerImplMock.senderAddress = senderAddress; + } + + private void sendMessage() { try { DataCenterVO zone = Mockito.mock(DataCenterVO.class); Mockito.when(zone.getId()).thenReturn(0L); @@ -100,7 +117,7 @@ public class AlertManagerImplTest { Mockito.when(cluster.getId()).thenReturn(1L); Mockito.when(_clusterDao.findById(1L)).thenReturn(cluster); - alertManagerImplMock.sendAlert(AlertManager.AlertType.ALERT_TYPE_CPU, 0, 1l, 1l, "", ""); + alertManagerImplMock.sendAlert(AlertManager.AlertType.ALERT_TYPE_CPU, 0, 1L, 1L, "", ""); } catch (UnsupportedEncodingException | MessagingException e) { Assert.fail(); } @@ -108,39 +125,69 @@ public class AlertManagerImplTest { @Test public void sendAlertTestSendMail() { - Mockito.doReturn(null).when(alertDaoMock).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), + Mockito.doReturn(null).when(_alertDao).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong()); - Mockito.doReturn(null).when(alertDaoMock).persist(Mockito.any()); - alertManagerImplMock.recipients = new String [] {""}; + Mockito.doReturn(null).when(_alertDao).persist(any()); + alertManagerImplMock.recipients = new String[]{""}; sendMessage(); - Mockito.verify(alertManagerImplMock).sendMessage(Mockito.any()); + Mockito.verify(alertManagerImplMock).sendMessage(any()); } @Test public void sendAlertTestDebugLogging() { Mockito.doReturn(0).when(alertVOMock).getSentCount(); - Mockito.doReturn(alertVOMock).when(alertDaoMock).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), + Mockito.doReturn(alertVOMock).when(_alertDao).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong()); sendMessage(); Mockito.verify(alertManagerImplMock.logger).debug(Mockito.anyString()); - Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(Mockito.any()); + Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(any()); } @Test public void sendAlertTestWarnLogging() { - Mockito.doReturn(null).when(alertDaoMock).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), + Mockito.doReturn(null).when(_alertDao).getLastAlert(Mockito.anyShort(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong()); - Mockito.doReturn(null).when(alertDaoMock).persist(Mockito.any()); + Mockito.doReturn(null).when(_alertDao).persist(Mockito.any()); alertManagerImplMock.recipients = null; sendMessage(); Mockito.verify(alertManagerImplMock.logger, Mockito.times(2)).warn(Mockito.anyString()); - Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(Mockito.any()); + Mockito.verify(alertManagerImplMock, Mockito.never()).sendMessage(any()); + } + + @Test + public void testSendAlertWithNullParameters() throws MessagingException, UnsupportedEncodingException { + // Given + String subject = "Test Subject"; + String content = "Test Content"; + AlertManager.AlertType alertType = AlertManager.AlertType.ALERT_TYPE_MEMORY; + + // When + alertManagerImplMock.sendAlert(alertType, null, null, null, subject, content); + + // Then + ArgumentCaptor alertCaptor = ArgumentCaptor.forClass(AlertVO.class); + verify(_alertDao).persist(alertCaptor.capture()); + + AlertVO capturedAlert = alertCaptor.getValue(); + assertNotNull("Captured alert should not be null", capturedAlert); + assertEquals(0L, capturedAlert.getDataCenterId()); + assertNull(capturedAlert.getPodId()); + assertNull(capturedAlert.getClusterId()); + assertEquals(subject, capturedAlert.getSubject()); + assertEquals(content, capturedAlert.getContent()); + assertEquals(alertType.getType(), capturedAlert.getType()); + } + + @Test(expected = NullPointerException.class) + public void testSendAlertWithNullAlertType() throws MessagingException, UnsupportedEncodingException { + // When + alertManagerImplMock.sendAlert(null, 0, 1L, 1L, "subject", "content"); } @Test diff --git a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java index a55f9b26a2c..7dcf30c55e4 100644 --- a/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java +++ b/server/src/test/java/com/cloud/storage/VolumeApiServiceImplTest.java @@ -1178,7 +1178,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("A"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1191,7 +1191,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("A","B","C","D","X","Y"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1204,7 +1204,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.lenient().doReturn(new Pair<>(List.of("A,B,C,D,X,Y"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1217,7 +1217,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of(""), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1230,7 +1230,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.lenient().doReturn(new Pair<>(List.of(""), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1243,7 +1243,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("C,D"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1256,7 +1256,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("A"), false)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1269,7 +1269,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("tags[0] == 'A'"), true)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertTrue(result); } @@ -1282,7 +1282,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("tags[0] == 'A'"), true)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } @@ -1295,7 +1295,7 @@ public class VolumeApiServiceImplTest { StoragePool storagePoolMock = Mockito.mock(StoragePool.class); Mockito.doReturn(new Pair<>(List.of("tags[0] == 'A'"), true)).when(volumeApiServiceImpl).getStoragePoolTags(storagePoolMock); - boolean result = volumeApiServiceImpl.doesTargetStorageSupportDiskOffering(storagePoolMock, diskOfferingVoMock); + boolean result = volumeApiServiceImpl.doesStoragePoolSupportDiskOffering(storagePoolMock, diskOfferingVoMock); Assert.assertFalse(result); } diff --git a/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java index 8982034a8c5..419acc0ca0b 100644 --- a/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/storage/volume/VolumeImportUnmanageManagerImplTest.java @@ -275,7 +275,7 @@ public class VolumeImportUnmanageManagerImplTest { when(diskOffering.isCustomized()).thenReturn(true); doReturn(diskOffering).when(volumeImportUnmanageManager).getOrCreateDiskOffering(account, diskOfferingId, zoneId, isLocal); doNothing().when(volumeApiService).validateCustomDiskOfferingSizeRange(anyLong()); - doReturn(true).when(volumeApiService).doesTargetStorageSupportDiskOffering(any(), isNull()); + doReturn(true).when(volumeApiService).doesStoragePoolSupportDiskOffering(any(), any()); doReturn(diskProfile).when(volumeManager).importVolume(any(), anyString(), any(), eq(virtualSize), isNull(), isNull(), anyLong(), any(), isNull(), isNull(), any(), isNull(), anyLong(), anyString(), isNull()); when(diskProfile.getVolumeId()).thenReturn(volumeId); diff --git a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java index 92681e058a2..8cfae6b9a6e 100644 --- a/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImplTest.java @@ -37,6 +37,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import com.cloud.offering.DiskOffering; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.ResponseObject; import org.apache.cloudstack.api.ServerApiException; @@ -45,6 +46,7 @@ import org.apache.cloudstack.api.command.admin.vm.ImportVmCmd; import org.apache.cloudstack.api.command.admin.vm.ListUnmanagedInstancesCmd; import org.apache.cloudstack.api.command.admin.vm.ListVmsForImportCmd; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UnmanagedInstanceResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -56,6 +58,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.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -135,7 +138,6 @@ import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; -import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; @@ -154,7 +156,6 @@ import com.cloud.utils.db.EntityManager; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DiskProfile; import com.cloud.vm.NicProfile; -import com.cloud.vm.NicVO; import com.cloud.vm.UserVmManager; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; @@ -162,7 +163,6 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; -import com.cloud.vm.snapshot.dao.VMSnapshotDao; @RunWith(MockitoJUnitRunner.class) public class UnmanagedVMsManagerImplTest { @@ -175,10 +175,6 @@ public class UnmanagedVMsManagerImplTest { @Mock private ClusterDao clusterDao; @Mock - private ClusterVO clusterVO; - @Mock - private UserVmVO userVm; - @Mock private ResourceManager resourceManager; @Mock private VMTemplatePoolDao templatePoolDao; @@ -219,10 +215,6 @@ public class UnmanagedVMsManagerImplTest { @Mock private ConfigurationDao configurationDao; @Mock - private VMSnapshotDao vmSnapshotDao; - @Mock - private SnapshotDao snapshotDao; - @Mock private UserVmDao userVmDao; @Mock private NicDao nicDao; @@ -242,8 +234,6 @@ public class UnmanagedVMsManagerImplTest { @Mock private VMInstanceVO virtualMachine; @Mock - private NicVO nicVO; - @Mock EntityManager entityMgr; @Mock DeploymentPlanningManager deploymentPlanningManager; @@ -276,19 +266,7 @@ public class UnmanagedVMsManagerImplTest { instance.setCpuSpeed(1000); instance.setMemory(1024); instance.setOperatingSystem("CentOS 7"); - List instanceDisks = new ArrayList<>(); - UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); - instanceDisk.setDiskId("1000-1"); - instanceDisk.setPosition(0); - instanceDisk.setLabel("DiskLabel"); - instanceDisk.setController("scsi"); - instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); - instanceDisk.setCapacity(5242880L); - instanceDisk.setDatastoreName("Test"); - instanceDisk.setDatastoreHost("Test"); - instanceDisk.setDatastorePath("Test"); - instanceDisk.setDatastoreType("NFS"); - instanceDisks.add(instanceDisk); + List instanceDisks = getDisks(); instance.setDisks(instanceDisks); List instanceNics = new ArrayList<>(); UnmanagedInstanceTO.Nic instanceNic = new UnmanagedInstanceTO.Nic(); @@ -388,6 +366,24 @@ public class UnmanagedVMsManagerImplTest { when(virtualMachine.getState()).thenReturn(VirtualMachine.State.Running); } + @NotNull + private static List getDisks() { + List instanceDisks = new ArrayList<>(); + UnmanagedInstanceTO.Disk instanceDisk = new UnmanagedInstanceTO.Disk(); + instanceDisk.setDiskId("1000-1"); + instanceDisk.setPosition(0); + instanceDisk.setLabel("DiskLabel"); + instanceDisk.setController("scsi"); + instanceDisk.setImagePath("[b6ccf44a1fa13e29b3667b4954fa10ee] TestInstance/ROOT-1.vmdk"); + instanceDisk.setCapacity(5242880L); + instanceDisk.setDatastoreName("Test"); + instanceDisk.setDatastoreHost("Test"); + instanceDisk.setDatastorePath("Test"); + instanceDisk.setDatastoreType("NFS"); + instanceDisks.add(instanceDisk); + return instanceDisks; + } + @After public void tearDown() throws Exception { closeable.close(); @@ -425,7 +421,7 @@ public class UnmanagedVMsManagerImplTest { ImportUnmanagedInstanceCmd importUnmanageInstanceCmd = Mockito.mock(ImportUnmanagedInstanceCmd.class); when(importUnmanageInstanceCmd.getName()).thenReturn("TestInstance"); when(importUnmanageInstanceCmd.getDomainId()).thenReturn(null); - when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class)) { unmanagedVMsManager.importUnmanagedInstance(importUnmanageInstanceCmd); } @@ -489,7 +485,7 @@ public class UnmanagedVMsManagerImplTest { when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); when(cmd.getUsername()).thenReturn("user"); when(cmd.getPassword()).thenReturn("pass"); - ListResponse response = unmanagedVMsManager.listVmsForImport(cmd); + ListResponse response = unmanagedVMsManager.listVmsForImport(cmd); Assert.assertEquals(1, response.getCount().intValue()); } @@ -586,7 +582,6 @@ public class UnmanagedVMsManagerImplTest { boolean selectTemporaryStorage) throws OperationTimedoutException, AgentUnavailableException { long clusterId = 1L; long zoneId = 1L; - long podId = 1L; long existingDatacenterId = 1L; String vcenterHost = "192.168.1.2"; String datacenter = "Datacenter"; @@ -704,7 +699,8 @@ public class UnmanagedVMsManagerImplTest { when(agentManager.send(Mockito.eq(convertHostId), Mockito.any(CheckConvertInstanceCommand.class))).thenReturn(checkConvertInstanceAnswer); } - when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any(DiskOffering.class))).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOfferingTags(any(StoragePool.class), any())).thenReturn(true); ConvertInstanceAnswer convertInstanceAnswer = mock(ConvertInstanceAnswer.class); ImportConvertedInstanceAnswer convertImportedInstanceAnswer = mock(ImportConvertedInstanceAnswer.class); @@ -727,16 +723,16 @@ public class UnmanagedVMsManagerImplTest { } @Test - public void testImportFromLocalDisk() throws InsufficientServerCapacityException { - testImportFromDisk("local"); + public void importFromLocalDisk() throws InsufficientServerCapacityException { + importFromDisk("local"); } @Test - public void testImportFromsharedStorage() throws InsufficientServerCapacityException { - testImportFromDisk("shared"); + public void importFromsharedStorage() throws InsufficientServerCapacityException { + importFromDisk("shared"); } - private void testImportFromDisk(String source) throws InsufficientServerCapacityException { + private void importFromDisk(String source) throws InsufficientServerCapacityException { String vmname = "testVm"; ImportVmCmd cmd = Mockito.mock(ImportVmCmd.class); when(cmd.getHypervisor()).thenReturn(Hypervisor.HypervisorType.KVM.toString()); @@ -770,7 +766,7 @@ public class UnmanagedVMsManagerImplTest { storagePools.add(storagePool); when(primaryDataStoreDao.findLocalStoragePoolsByHostAndTags(anyLong(), any())).thenReturn(storagePools); when(primaryDataStoreDao.findById(anyLong())).thenReturn(storagePool); - when(volumeApiService.doesTargetStorageSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); + when(volumeApiService.doesStoragePoolSupportDiskOffering(any(StoragePool.class), any())).thenReturn(true); StoragePoolHostVO storagePoolHost = Mockito.mock(StoragePoolHostVO.class); when(storagePoolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(storagePoolHost); try (MockedStatic ignored = Mockito.mockStatic(UsageEventUtils.class)) { diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py index c68e4fde16b..cf0b71ab436 100755 --- a/systemvm/debian/opt/cloud/bin/configure.py +++ b/systemvm/debian/opt/cloud/bin/configure.py @@ -932,6 +932,7 @@ class CsVmMetadata(CsDataBag): if os.path.exists(htaccessFile): fh = open(htaccessFile, "a+") self.__exflock(fh) + fh.seek(0) if entry not in fh.read(): fh.write(entry + '\n') self.__unflock(fh) @@ -969,6 +970,7 @@ class CsVmMetadata(CsDataBag): fh = open(htaccessFile, "a+") self.__exflock(fh) + fh.seek(0) if entry not in fh.read(): fh.write(entry + '\n') diff --git a/ui/public/locales/ar.json b/ui/public/locales/ar.json index 2cf51c2c385..20499c63e04 100644 --- a/ui/public/locales/ar.json +++ b/ui/public/locales/ar.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"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.

Extending beyond individual virtual machine 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. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"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.

Extending beyond individual virtual machine 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.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.", diff --git a/ui/public/locales/ca.json b/ui/public/locales/ca.json index e97d11d101f..30ed3161448 100644 --- a/ui/public/locales/ca.json +++ b/ui/public/locales/ca.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"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.

Extending beyond individual virtual machine 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. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"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.

Extending beyond individual virtual machine 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": "Un nom per al pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Aquest \u00e9s el rang IP a la xarxa privada que el CloudStack fa servir per administrar MVs per al Secondary Storage i Proxy de consoles. Aquestes IP es prenen de la mateixa sub-xarxa que els servidors de virtualitzaci\u00f3.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "La passarel\u00b7la per als amfitrions en aquest pot.", diff --git a/ui/public/locales/de_DE.json b/ui/public/locales/de_DE.json index abf471ae17d..c20bf175826 100644 --- a/ui/public/locales/de_DE.json +++ b/ui/public/locales/de_DE.json @@ -1954,7 +1954,7 @@ "message.host.dedicated": "Host dediziert", "message.host.dedication.released": "Host-Dedizierung freigegeben", "message.info.cloudian.console": "Cloudian Management Konsole sollte ein anderes Fenster öffnen", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ ist eine Software-Plattform welche Rechenressourcen zusammenfasst, um öffentliche, private oder hybride \"Infrastructure as a Service\" (IaaS) Clouds zu bauen. CloudStack™ verwaltet das Netzwerk-, Speicher- und Computingknoten was eine Cloud-Infrastruktur ausmacht. Benutzen Sie CloudStack™ um Computing-Umgebungen zu erstellen, verwalten und zu konfigurieren.

Neben dem Erweitern von individuellen virtuellen Maschinenabbilder auf auf Standardhardware bietet CloudStack™ einen schlüsselfertigen Cloud Infrastruktur-Software-Stack für die Bereitstellung von virtueller Rechenzentren as a Service – Liefert alle wesentlichen Komponenten für das Bauen, Bereitstellen und Verwalten von multi-tier- und mandantenfähigen Cloud-Anwendungen. Open-Source sowie Premium-Versionen sind verfügbar, mit nahezu identischen Features.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ ist eine Software-Plattform welche Rechenressourcen zusammenfasst, um öffentliche, private oder hybride \"Infrastructure as a Service\" (IaaS) Clouds zu bauen. CloudStack™ verwaltet das Netzwerk-, Speicher- und Computingknoten was eine Cloud-Infrastruktur ausmacht. Benutzen Sie CloudStack™ um Computing-Umgebungen zu erstellen, verwalten und zu konfigurieren.

Neben dem Erweitern von individuellen virtuellen Maschinenabbilder auf auf Standardhardware bietet CloudStack™ einen schlüsselfertigen Cloud Infrastruktur-Software-Stack für die Bereitstellung von virtueller Rechenzentren as a Service – Liefert alle wesentlichen Komponenten für das Bauen, Bereitstellen und Verwalten von multi-tier- und mandantenfähigen Cloud-Anwendungen.", "message.installwizard.tooltip.addpod.name": "Der Name für den pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Dies ist der IP-Bereich im privaten Netzwerk, welches CloudStack verwendet um Sekundärspeicher-VMs und Konsolen-Proxies zu verwalten. Diese IP-Adressen werden vom selben Subnetz genommen wie Computing-Server.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Das Gateways für die Hosts des pod", diff --git a/ui/public/locales/el_GR.json b/ui/public/locales/el_GR.json index 7b7f4b29e12..d26362907e4 100644 --- a/ui/public/locales/el_GR.json +++ b/ui/public/locales/el_GR.json @@ -2385,7 +2385,7 @@ "message.installwizard.cloudstack.helptext.releasenotes": " * Σημειώσης εκδόσεων:\t ", "message.installwizard.cloudstack.helptext.survey": " * Απαντήστε στην συλλογή στοιχείων:\t ", "message.installwizard.cloudstack.helptext.website": " * Σελίδα έργου:\t ", -"message.installwizard.copy.whatiscloudstack": "Το CloudStack™ είναι μια πλατφόρμα λογισμικού που συγκεντρώνει υπολογιστικούς πόρους για τη δημιουργία δημόσιων, ιδιωτικών και υβριδικών υποδομων ως υπηρεσίας (IaaS) cloud. Το CloudStack™ διαχειρίζεται τους κόμβους δικτύου, αποθήκευσης και υπολογισμού που αποτελούν μια υποδομή cloud. Χρησιμοποιήστε το CloudStack™ για να αναπτύξετε, να διαχειριστείτε και να ρυθμίσετε τις παραμέτρους περιβαλλόντων Cloud.\n\nΤο CloudStack™ παρέχει μια στοίβα λογισμικού υποδομής cloud για την παροχή εικονικών κέντρων δεδομένων ως υπηρεσία - παρέχοντας όλα τα βασικά στοιχεία για τη δημιουργία, την ανάπτυξη και τη διαχείριση εφαρμογών cloud πολλαπλών επιπέδων και πολλών tenants. Και οι εκδόσεις ανοιχτού κώδικα και Premium είναι διαθέσιμες, με την έκδοση ανοιχτού κώδικα να προσφέρει σχεδόν πανομοιότυπα χαρακτηριστικά.", +"message.installwizard.copy.whatiscloudstack": "Το CloudStack™ είναι μια πλατφόρμα λογισμικού που συγκεντρώνει υπολογιστικούς πόρους για τη δημιουργία δημόσιων, ιδιωτικών και υβριδικών υποδομων ως υπηρεσίας (IaaS) cloud. Το CloudStack™ διαχειρίζεται τους κόμβους δικτύου, αποθήκευσης και υπολογισμού που αποτελούν μια υποδομή cloud. Χρησιμοποιήστε το CloudStack™ για να αναπτύξετε, να διαχειριστείτε και να ρυθμίσετε τις παραμέτρους περιβαλλόντων Cloud.\n\nΤο CloudStack™ παρέχει μια στοίβα λογισμικού υποδομής cloud για την παροχή εικονικών κέντρων δεδομένων ως υπηρεσία - παρέχοντας όλα τα βασικά στοιχεία για τη δημιουργία, την ανάπτυξη και τη διαχείριση εφαρμογών cloud πολλαπλών επιπέδων και πολλών tenants.", "message.installwizard.tooltip.addpod.name": "Ένα όνομα για το pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Αυτή είναι η περιοχή IP στο ιδιωτικό δίκτυο που χρησιμοποιεί το CloudStack για τη διαχείριση των εικονικής μηχανής δευτερεύουσας αποθήκευσης και των εικονικής μηχανής διακομιστή μεσολάβησης κονσόλας. Αυτές οι διευθύνσεις IP λαμβάνονται από το ίδιο υποδίκτυο με τους διακομιστές υπολογιστών.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Η πύλη για τους κεντρικους υπολογιστές σε αυτό το pod.", diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 1bfc22ecb76..7b7b9807165 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1742,6 +1742,8 @@ "label.prepare.for.shutdown": "Prepare for Shutdown", "label.prepare.for.maintenance": "Prepare for Maintenance", "label.presetup": "PreSetup", +"label.press.enter": "Press enter when done.", +"label.press.enter.tooltip": "On leaving a any of these fields above, when they all contain values, or on pressing enter, ESXi hosts will be retrieved. If this is successful, a dropdown will appear with the list of ESXi hosts.", "label.prev": "Prev", "label.previous": "Previous", "label.primera.username.tooltip": "The username with edit privileges", @@ -3241,7 +3243,7 @@ "message.installwizard.cloudstack.helptext.mailinglists": " * Join mailing lists:\t ", "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. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"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.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.", @@ -3285,7 +3287,7 @@ "message.license.agreements.not.accepted": "License agreements not accepted.", "message.linstor.resourcegroup.description": "Linstor resource group to use for primary storage.", "message.list.zone.vmware.datacenter.empty": "No VMware Datacenter exists in the selected Zone", -"message.list.zone.vmware.hosts.empty": "No VMware hosts were found in the selected Datacenter", +"message.list.zone.vmware.hosts.empty": "No EXSi hosts were found in the selected Datacenter.\nAre the entered credentials correct?\n", "message.listnsp.not.return.providerid": "error: listNetworkServiceProviders API doesn't return VirtualRouter provider ID.", "message.load.host.failed": "Failed to load hosts.", "message.loadbalancer.stickypolicy.configuration": "Customize the load balancer stickiness policy:", diff --git a/ui/public/locales/es.json b/ui/public/locales/es.json index 76488937574..ae4fa19f033 100644 --- a/ui/public/locales/es.json +++ b/ui/public/locales/es.json @@ -1437,7 +1437,7 @@ "message.guest.traffic.in.basic.zone": "El tr\u00e1fico de las redes invitado es el generado entre las m\u00e1quina virtuales del usuario final. Especifique un rango de direcciones IP para que CloudStack pueda asignar a las MVs Invitado. Asegures\u00e9 que este rango no se solape con el rango IP reservado para el sistema.", "message.host.dedicated": "Servidor Dedicado", "message.host.dedication.released": "Dedicaci\u00f3n de Servidor liberada", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ es una plataforma de software que aglutina recursos c\u00f3mputo para construir Infraestructuras como Servicio (IaaS), tanto de cloud p\u00fablico como privado e h\u00edbrido.\nCloudStack™ gestiona la red, el almacenamiento y los nodos de c\u00f3mputo que conforma la infraestructura de cloud. Se puede usar CloudStack™ para desplegar, gestionar y configurar entornos de computaci\u00f3n en la nube.

Cloudstack™ vam\u00e1s all\u00e1 del manejo individual de m\u00e1quinas virtuales en hardware de prop\u00f3sito general, ya que proporciona una soluci\u00f3n llave en mano para desplegar datacenters como servicio - proporcionando todos los componentes esenciales para construir, desplegar y gestionar aplicaciones cloud multi-tier y multi-tenant. Se ofrecen dos versiones, la open source y la Premium, brindando la primera caracter\u00edsticas casi id\u00e9nticas.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ es una plataforma de software que aglutina recursos c\u00f3mputo para construir Infraestructuras como Servicio (IaaS), tanto de cloud p\u00fablico como privado e h\u00edbrido.\nCloudStack™ gestiona la red, el almacenamiento y los nodos de c\u00f3mputo que conforma la infraestructura de cloud. Se puede usar CloudStack™ para desplegar, gestionar y configurar entornos de computaci\u00f3n en la nube.

Cloudstack™ vam\u00e1s all\u00e1 del manejo individual de m\u00e1quinas virtuales en hardware de prop\u00f3sito general, ya que proporciona una soluci\u00f3n llave en mano para desplegar datacenters como servicio - proporcionando todos los componentes esenciales para construir, desplegar y gestionar aplicaciones cloud multi-tier y multi-tenant.", "message.installwizard.tooltip.addpod.name": "Nombre del POD", "message.installwizard.tooltip.addpod.reservedsystemendip": "Este es el rango de direcciones IP en la red privada que CloudStack utiliza para administrar las MVs del Almacenamiento Secundario y proxy de consolas. Estas direcciones IP se han tomado de la misma subred que los servidores inform\u00e1ticos.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "La puerta de enlace para los host en ese pod.", diff --git a/ui/public/locales/fr_FR.json b/ui/public/locales/fr_FR.json index f11f4ac5c94..48a0560f176 100644 --- a/ui/public/locales/fr_FR.json +++ b/ui/public/locales/fr_FR.json @@ -1407,7 +1407,7 @@ "message.guest.traffic.in.basic.zone": "Le trafic r\u00e9seau d'invit\u00e9 est la communication entre les machines virtuelles utilisateur. Sp\u00e9cifier une plage d'adresses IP que CloudStack peut assigner aux machines virtuelles Invit\u00e9. S'assurer que cette plage n'empi\u00e8te pas sur la plage r\u00e9serv\u00e9e aux adresses IP Syst\u00e8me.", "message.host.dedicated": "H\u00f4te d\u00e9di\u00e9e", "message.host.dedication.released": "Lib\u00e9ration de l'h\u00f4te d\u00e9di\u00e9", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ est une plate-forme logicielle de pools de ressources informatiques pour construire des infrastructures publiques, priv\u00e9es et hybrides en tant que services (IaaS) dans les nuages. CloudStack™ g\u00e8re le r\u00e9seau, le stockage et les noeuds de calcul qui composent une infrastructure dans les nuages. Utilisez CloudStack™ pour d\u00e9ployer, g\u00e9rer et configurer les environnements d'informatiques dans les nuages.

S'\u00e9tendant au-del\u00e0 des machines virtuelles individuelles fonctionnant sur du mat\u00e9riel standard, CloudStack™ offre une solution d'informatique en nuage cl\u00e9 en main pour fournir des centres de donn\u00e9es virtuels comme service - fournissant tous les composants essentiels pour construire, d\u00e9ployer et g\u00e9rer des applications 'cloud' multi-niveaux et multi-locataire. Les versions libre et Premium sont disponibles, la version Libre offrant des caract\u00e9ristiques presque identiques.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ est une plate-forme logicielle de pools de ressources informatiques pour construire des infrastructures publiques, priv\u00e9es et hybrides en tant que services (IaaS) dans les nuages. CloudStack™ g\u00e8re le r\u00e9seau, le stockage et les noeuds de calcul qui composent une infrastructure dans les nuages. Utilisez CloudStack™ pour d\u00e9ployer, g\u00e9rer et configurer les environnements d'informatiques dans les nuages.

S'\u00e9tendant au-del\u00e0 des machines virtuelles individuelles fonctionnant sur du mat\u00e9riel standard, CloudStack™ offre une solution d'informatique en nuage cl\u00e9 en main pour fournir des centres de donn\u00e9es virtuels comme service - fournissant tous les composants essentiels pour construire, d\u00e9ployer et g\u00e9rer des applications 'cloud' multi-niveaux et multi-locataire.", "message.installwizard.tooltip.addpod.name": "Nom pour le pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Ceci est la plage d'adresses IP dans le r\u00e9seau priv\u00e9 que CloudStack utilise la gestion des VMs du stockage secondaire et les VMs Console Proxy. Ces adresses IP sont prises dans le m\u00eame sous-r\u00e9seau que les serveurs h\u00f4tes.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Passerelle pour les serveurs dans ce pod", diff --git a/ui/public/locales/hu.json b/ui/public/locales/hu.json index 445d3a1d5f5..48275ce81fc 100644 --- a/ui/public/locales/hu.json +++ b/ui/public/locales/hu.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "A vend\u00e9g h\u00e1l\u00f3zat forgalma kommunik\u00f3ci\u00f3 v\u00e9gfelhaszn\u00e1l\u00f3i virtu\u00e1lis g\u00e9pek k\u00f6z\u00f6tt. Hat\u00e1rozz meg egy IP c\u00edmtartom\u00e1nyt, amelyb\u0151l a CloudStack a virtu\u00e1lis g\u00e9pekhez rendelhet c\u00edmet. Gy\u0151z\u0151dj meg r\u00f3la, hogy ez a tartom\u00e1ny nincs \u00e1tfed\u00e9sben az elk\u00fcl\u00f6n\u00edtett rendszer IP tartom\u00e1nnyal!", "message.host.dedicated": "Dedik\u00e1lt kiszolg\u00e1l\u00f3", "message.host.dedication.released": "Kiszolg\u00e1l\u00f3 elengedve", -"message.installwizard.copy.whatiscloudstack": "A CloudStack™ egy szoftver, amely sz\u00e1m\u00edt\u00e1si er\u0151forr\u00e1sokat fel\u00fcgyel \u00e9s alkalmas publikus, priv\u00e1t, vagy hibrid infrastrukt\u00fara szolg\u00e1ltat\u00e1s (IaaS) felh\u0151k \u00e9p\u00edt\u00e9s\u00e9re. A CloudStack™ ir\u00e1ny\u00edtja a h\u00e1l\u00f3zatokat, az adatt\u00e1rol\u00f3kat \u00e9s kiszolg\u00e1l\u00f3kat, amelyek a felh\u0151 infrastrukt\u00far\u00e1t alkotj\u00e1k.

A k\u00fcl\u00f6n\u00e1ll\u00f3 virtu\u00e1lis g\u00e9peken t\u00fal a CloudStack™ teljes felh\u0151 insfrastrukt\u00far\u00e1t szolg\u00e1ltat. Ny\u00edlt forr\u00e1sk\u00f3d\u00fa \u00e9s pr\u00e9mium verzi\u00f3k egyar\u00e1nt el\u00e9rhet\u0151ek, a ny\u00edlt forr\u00e1sk\u00f3d\u00fa verzi\u00f3k k\u00f6zel azonos k\u00e9pess\u00e9gekkel rendelkeznek.", +"message.installwizard.copy.whatiscloudstack": "A CloudStack™ egy szoftver, amely sz\u00e1m\u00edt\u00e1si er\u0151forr\u00e1sokat fel\u00fcgyel \u00e9s alkalmas publikus, priv\u00e1t, vagy hibrid infrastrukt\u00fara szolg\u00e1ltat\u00e1s (IaaS) felh\u0151k \u00e9p\u00edt\u00e9s\u00e9re. A CloudStack™ ir\u00e1ny\u00edtja a h\u00e1l\u00f3zatokat, az adatt\u00e1rol\u00f3kat \u00e9s kiszolg\u00e1l\u00f3kat, amelyek a felh\u0151 infrastrukt\u00far\u00e1t alkotj\u00e1k.

A k\u00fcl\u00f6n\u00e1ll\u00f3 virtu\u00e1lis g\u00e9peken t\u00fal a CloudStack™ teljes felh\u0151 insfrastrukt\u00far\u00e1t szolg\u00e1ltat.", "message.installwizard.tooltip.addpod.name": "A pod neve", "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": "\u00c1tj\u00e1r\u00f3 a pod kiszolg\u00e1l\u00f3inak.", diff --git a/ui/public/locales/it_IT.json b/ui/public/locales/it_IT.json index fa09e189d98..844763eba3a 100644 --- a/ui/public/locales/it_IT.json +++ b/ui/public/locales/it_IT.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"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.

Extending beyond individual virtual machine 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. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"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.

Extending beyond individual virtual machine 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": "Un nome per il pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Questo \u00e8 l'intervallo di indirizzi IP nella rete privata che CloudStack utilizza per la gestione delle VM del Secondary Storage e le VM della Console Proxy. Questi indirizzi IP sono ricavati dalla stessa subnet dei server computazionali.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Il gateway per gli host appartenenti al pod.", diff --git a/ui/public/locales/ja_JP.json b/ui/public/locales/ja_JP.json index 53009781500..8357b9d49a2 100644 --- a/ui/public/locales/ja_JP.json +++ b/ui/public/locales/ja_JP.json @@ -3063,7 +3063,7 @@ "message.installwizard.copy.whatisahost": "ホストは単一のコンピューターで、ゲスト仮想マシンを実行するコンピューティング リソースをオファリングします。ベア メタル ホストを除いて、各ホストにはゲスト仮想マシンを管理するためのハイパーバイザー ソフトウェアをインストールします。ベア メタル ホストについては、『インストールガイド上級編』で特殊例として説明します。たとえば、KVM が有効な Linux サーバー、Citrix XenServer が動作するサーバー、および ESXi サーバーがホストです。基本インストールでは、XenServer または KVM を実行する単一のホストを使用します。

ホストは CloudStack™ 環境内の最小の組織単位です。ホストはクラスターに含まれ、クラスターはポッドに含まれ、ポッドはゾーンに含まれます。", "message.installwizard.copy.whatisapod": "通常、1つのポッドは単一のラックを表します。同じポッド内のホストは同じサブネットに含まれます。

ポッドはCloudStack™環境内の2番目に大きな組織単位です。ポッドはゾーンに含まれます。各ゾーンは1つ以上のポッドを含むことができます。基本インストールでは、ゾーン内のポッドは1つです。", "message.installwizard.copy.whatisazone": "ゾーンはCloudStack™環境内の最大の組織単位です。1つのデータセンター内に複数のゾーンを設定できますが、通常、ゾーンは単一のデータセンターに相当します。インフラストラクチャをゾーンに組織化すると、ゾーンを物理的に分離して冗長化することができます。たとえば、各ゾーンに電源とネットワークアップリンクを配備します。必須ではありませんが、ゾーンは遠隔地に分散することができます。", - "message.installwizard.copy.whatiscloudstack": "CloudStack™はコンピューティングリソースをプールするソフトウェアプラットフォームで、パブリック、プライベート、およびハイブリッドのInfrastructure as a Service(IaaS)クラウドを構築することができます。CloudStack™を使用して、クラウドインフラストラクチャを構成するネットワーク、ストレージ、およびコンピューティングノードを管理し、クラウドコンピューティング環境を展開、管理、および構成します。

CloudStack™はコモディティ化したハードウェア上で動作する個別の仮想マシンイメージを超えて拡張することができ、簡単な設定で動作するクラウドインフラストラクチャのソフトウェアスタックによって、仮想データセンターつまり多層型のマルチテナントクラウドアプリケーションをサービスとして構築し、展開し、管理するために不可欠なコンポーネントがすべてオファリングされます。オープンソースバージョンとプレミアムバージョンの両方がオファリングされますが、オープンソースバージョンでもほとんどの機能を使用できます。", + "message.installwizard.copy.whatiscloudstack": "CloudStack™はコンピューティングリソースをプールするソフトウェアプラットフォームで、パブリック、プライベート、およびハイブリッドのInfrastructure as a Service(IaaS)クラウドを構築することができます。CloudStack™を使用して、クラウドインフラストラクチャを構成するネットワーク、ストレージ、およびコンピューティングノードを管理し、クラウドコンピューティング環境を展開、管理、および構成します。

CloudStack™はコモディティ化したハードウェア上で動作する個別の仮想マシンイメージを超えて拡張することができ、簡単な設定で動作するクラウドインフラストラクチャのソフトウェアスタックによって、仮想データセンターつまり多層型のマルチテナントクラウドアプリケーションをサービスとして構築し、展開し、管理するために不可欠なコンポーネントがすべてオファリングされます。", "message.installwizard.copy.whatisprimarystorage": "CloudStack™のクラウドインフラストラクチャでは、プライマリストレージとセカンダリストレージの2種類のストレージを使用します。どちらのストレージにも、iSCSI、NFSサーバー、またはローカルディスクを使用できます。

プライマリストレージはクラスターに関連付けられ、そのクラスター内のホストで動作するすべてのVMの各ゲストVMのディスクボリュームを格納します。通常、プライマリストレージサーバーはホストの近くに設置します。", "message.installwizard.copy.whatissecondarystorage": "セカンダリストレージはゾーンと関連付けられ、次の項目を格納します。
  • テンプレート - VMの起動に使用できるOSイメージで、アプリケーションのインストールなど追加の構成を含めることができます。
  • ISOイメージ - 起動可能または起動不可のOSイメージです。
  • ディスクボリュームのスナップショット - VMデータの保存コピーです。データの復元または新しいテンプレートの作成に使用できます。
", "message.installwizard.now.building": "クラウドを構築しています...", diff --git a/ui/public/locales/ko_KR.json b/ui/public/locales/ko_KR.json index 153bfd64cef..f1fab4b584c 100644 --- a/ui/public/locales/ko_KR.json +++ b/ui/public/locales/ko_KR.json @@ -2052,7 +2052,7 @@ "message.host.dedicated": "\uc804\uc6a9 \ud638\uc2a4\ud2b8", "message.host.dedication.released": "\uc804\uc6a9 \ud638\uc2a4\ud2b8 \ucd9c\uc2dc", "message.info.cloudian.console": "Cloudian \uad00\ub9ac \ucf58\uc194\uc774 \ub2e4\ub978 \ucc3d\uc5d0\uc11c \uc5f4\ub9bd\ub2c8\ub2e4.", -"message.installwizard.copy.whatiscloudstack": "CloudStack\u2122\uc740 \ucef4\ud4e8\ud305 \ub9ac\uc18c\uc2a4\ub97c \ud3ec\ud568\ud558\uc5ec \uacf5\uac1c, \uc0ac\uc124, \ubc0f \ud558\uc774\ube0c\ub9ac\ub4dc\uc758 Infrastructure as a Service (IaaS) \ud074\ub77c\uc6b0\ub4dc\ub97c \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ud50c\ub7ab\ud3fc\uc785\ub2c8\ub2e4. CloudStack \u2122\uc740 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c\ub97c \uad6c\uc131\ud558\ub294 \ub124\ud2b8\uc6cc\ud06c, \uc2a4\ud1a0\ub9ac\uc9c0 \ubc0f \ucef4\ud4e8\ud305 \ub178\ub4dc\ub97c \uad00\ub9ac\ud569\ub2c8\ub2e4. CloudStack \u2122\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud074\ub77c\uc6b0\ub4dc \ucef4\ud4e8\ud305 \ud658\uacbd\uc744 \ubc30\ud3ec, \uad00\ub9ac \ubc0f \uad6c\uc131\ud558\uc2ed\uc2dc\uc624. \n\nCloudStack \u2122 \uc77c\ubc18 \ud558\ub4dc\uc6e8\uc5b4\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uac1c\ubcc4 \uac00\uc0c1\uba38\uc2e0 \uc774\ubbf8\uc9c0\ub97c \ub118\uc5b4 \ud655\uc7a5\ub418\uc5b4 \uac00\uc0c1 \ub370\uc774\ud130 \uc13c\ud130\ub97c \uc11c\ube44\uc2a4\ub85c \uc81c\uacf5\ud558\uae30\uc704\ud55c \ud134\ud0a4 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc2a4\ud0dd\uc744 \uc81c\uacf5\ud558\uc5ec \ubaa8\ub4e0 \ud544\uc218 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \ub2e4\uc911 \uacc4\uce35 \ubc0f \ub2e4\uc911 \ud14c\ub10c\ud2b8 \ud074\ub77c\uc6b0\ub4dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube4c\ub4dc, \ubc30\ud3ec \ubc0f \uad00\ub9ac\ud558\uae30\uc704\ud55c \uad6c\uc131 \uc694\uc18c\uc785\ub2c8\ub2e4. \uc624\ud508 \uc18c\uc2a4 \ubc0f \ud504\ub9ac\ubbf8\uc5c4 \ubc84\uc804\uc744 \ubaa8\ub450 \uc0ac\uc6a9\ud560 \uc218 \uc788\uc73c\uba70 \uc624\ud508 \uc18c\uc2a4 \ubc84\uc804\uc740 \uac70\uc758 \ub3d9\uc77c\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4.", +"message.installwizard.copy.whatiscloudstack": "CloudStack\u2122\uc740 \ucef4\ud4e8\ud305 \ub9ac\uc18c\uc2a4\ub97c \ud3ec\ud568\ud558\uc5ec \uacf5\uac1c, \uc0ac\uc124, \ubc0f \ud558\uc774\ube0c\ub9ac\ub4dc\uc758 Infrastructure as a Service (IaaS) \ud074\ub77c\uc6b0\ub4dc\ub97c \uad6c\ucd95\ud560 \uc218 \uc788\ub294 \uc18c\ud504\ud2b8\uc6e8\uc5b4 \ud50c\ub7ab\ud3fc\uc785\ub2c8\ub2e4. CloudStack \u2122\uc740 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c\ub97c \uad6c\uc131\ud558\ub294 \ub124\ud2b8\uc6cc\ud06c, \uc2a4\ud1a0\ub9ac\uc9c0 \ubc0f \ucef4\ud4e8\ud305 \ub178\ub4dc\ub97c \uad00\ub9ac\ud569\ub2c8\ub2e4. CloudStack \u2122\uc744 \uc0ac\uc6a9\ud558\uc5ec \ud074\ub77c\uc6b0\ub4dc \ucef4\ud4e8\ud305 \ud658\uacbd\uc744 \ubc30\ud3ec, \uad00\ub9ac \ubc0f \uad6c\uc131\ud558\uc2ed\uc2dc\uc624. \n\nCloudStack \u2122 \uc77c\ubc18 \ud558\ub4dc\uc6e8\uc5b4\uc5d0\uc11c \uc2e4\ud589\ub418\ub294 \uac1c\ubcc4 \uac00\uc0c1\uba38\uc2e0 \uc774\ubbf8\uc9c0\ub97c \ub118\uc5b4 \ud655\uc7a5\ub418\uc5b4 \uac00\uc0c1 \ub370\uc774\ud130 \uc13c\ud130\ub97c \uc11c\ube44\uc2a4\ub85c \uc81c\uacf5\ud558\uae30\uc704\ud55c \ud134\ud0a4 \ud074\ub77c\uc6b0\ub4dc \uc778\ud504\ub77c \uc18c\ud504\ud2b8\uc6e8\uc5b4 \uc2a4\ud0dd\uc744 \uc81c\uacf5\ud558\uc5ec \ubaa8\ub4e0 \ud544\uc218 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4. \ub2e4\uc911 \uacc4\uce35 \ubc0f \ub2e4\uc911 \ud14c\ub10c\ud2b8 \ud074\ub77c\uc6b0\ub4dc \uc560\ud50c\ub9ac\ucf00\uc774\uc158\uc744 \ube4c\ub4dc, \ubc30\ud3ec \ubc0f \uad00\ub9ac\ud558\uae30\uc704\ud55c \uad6c\uc131 \uc694\uc18c\uc785\ub2c8\ub2e4.", "message.installwizard.tooltip.addpod.name": "Pod \uc774\ub984\uc785\ub2c8\ub2e4.", "message.installwizard.tooltip.addpod.reservedsystemendip": "\uc774\uac83\uc740 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0 VM \ubc0f \ucf58\uc194 \ud504\ub85d\uc2dc VM\ub97c \uad00\ub9ac\ud558\uae30 \uc704\ud574\uc11c CloudStack\uc5d0\uc11c \uc0ac\uc6a9\ud558\ub294 \uc0ac\uc124 \ub124\ud2b8\uc6cc\ud06c\ub0b4 IP \uc8fc\uc18c \ubc94\uc704\uc785\ub2c8\ub2e4. \uc774\ub7ec\ud55c IP \uc8fc\uc18c\ub294 \ucef4\ud4e8\ud305 \uc11c\ubc84\uc640 \uac19\uc740 \uc11c\ube0c\ub124\ud2b8\uc6cc\ud06c\uc5d0\uc11c \ud560\ub2f9\ud569\ub2c8\ub2e4.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "\ud604\uc7ac Pod\ub0b4 \ud638\uc2a4\ud2b8 \uac8c\uc774\ud2b8\uc6e8\uc774\uc785\ub2c8\ub2e4.", diff --git a/ui/public/locales/nb_NO.json b/ui/public/locales/nb_NO.json index a0fbd8927df..ec51f7415d3 100644 --- a/ui/public/locales/nb_NO.json +++ b/ui/public/locales/nb_NO.json @@ -1405,7 +1405,7 @@ "message.guest.traffic.in.basic.zone": "Gjestetrafikk er kommunikasjon mellom sluttbrukers virtuelle gjester. Spesifiser en rekke med IP-adresser som CloudStack kan tildele virtuelle gjester. S\u00f8rg for at denne rekken ikke overlapper IP-rekken(e) som er reservert systemmaskiner.", "message.host.dedicated": "Dedikert Vert", "message.host.dedication.released": "Vert dedikering frigitt", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ er en programvare-plattform som grupperer dataressurser for \u00e5 bygge offentlige, private og hybride infrastruktur som en tjeneste (IaaS) skyer. CloudStack™ administrerer nettverk, lagring og regnekraft-verter som til sammen blir en sky-infrastruktur. Bruk CloudStack™ til \u00e5 distribuere, administrerre og konfigurere dine skyressurser og milj\u00f8er.

Utvid forbi individuelle virtuelle gjester som kj\u00f8rer p\u00e5 typisk maskinvare, CloudStack™ gir en skybasert infrastruktur-programvare for levering av virtuelle datasentre som en tjeneste - lever alle de essensielle komponenente for \u00e5 bygge, distribuere og administrere multi-tier og multi-tenant sky-applikasjoner. B\u00e5de fri kildekode- og premium-versjoner er tilgjengelig, hvor den fri kildekode-basert gir tiln\u00e6rmet samme funksjonalitet.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ er en programvare-plattform som grupperer dataressurser for \u00e5 bygge offentlige, private og hybride infrastruktur som en tjeneste (IaaS) skyer. CloudStack™ administrerer nettverk, lagring og regnekraft-verter som til sammen blir en sky-infrastruktur. Bruk CloudStack™ til \u00e5 distribuere, administrerre og konfigurere dine skyressurser og milj\u00f8er.

Utvid forbi individuelle virtuelle gjester som kj\u00f8rer p\u00e5 typisk maskinvare, CloudStack™ gir en skybasert infrastruktur-programvare for levering av virtuelle datasentre som en tjeneste - lever alle de essensielle komponenente for \u00e5 bygge, distribuere og administrere multi-tier og multi-tenant sky-applikasjoner.", "message.installwizard.tooltip.addpod.name": "Et navn for poden", "message.installwizard.tooltip.addpod.reservedsystemendip": "Dette er IP-rekken i det private nettverket som CloudStack bruker for \u00e5 administrere Sekund\u00e6rlagrins-servere og Konsollproxy-servere. Disse IP-adressene tas fra samme subnett som regnekraft-serverne.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "Gatewayen til vertene i poden.", diff --git a/ui/public/locales/nl_NL.json b/ui/public/locales/nl_NL.json index 8e637f190b3..6bd1bf67159 100644 --- a/ui/public/locales/nl_NL.json +++ b/ui/public/locales/nl_NL.json @@ -1406,7 +1406,7 @@ "message.guest.traffic.in.basic.zone": "Gast netwerk verkeer is communicatie tussen virtuele machines van de eindgebruiker. Specificeer een range van IP adressen welke CloudStack kan uitdelen aan gast VMs. Let erop dat deze range niet overlapt met de gereserveerde systeem IP range.", "message.host.dedicated": "Host toegewijd", "message.host.dedication.released": "Toegewijde host losgekoppeld", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ is een software platform welke computer capaciteit herenigd om public, private en hybrid infrastructure as a Service (IaaS) clouds te bouwen. CloudStack™ beheert het netwerk, de opslag en de computer nodes welke de cloud infrastructuur vertegenwoordigen. Gebruik CloudStack™ om cloud computing omgevingen uit te rollen, te beheren en te configureren.

CloudStack™ gaat veel verder dan het draaien van virtuele machine bestanden op commodity hardware, het is een turnkey oplossing om virtuele datacenters (as a service) te realiseren. Daarbij levert het alle essenti\u00eble componenten om multi-tier en multi-tentant cloud applicaties te bouwen en te beheren. Er is een zowel een open-source als Premium versie beschikbaar, waarbij de open-source versie nagenoeg dezelfde functionaliteit biedt als de Premium versie.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ is een software platform welke computer capaciteit herenigd om public, private en hybrid infrastructure as a Service (IaaS) clouds te bouwen. CloudStack™ beheert het netwerk, de opslag en de computer nodes welke de cloud infrastructuur vertegenwoordigen. Gebruik CloudStack™ om cloud computing omgevingen uit te rollen, te beheren en te configureren.

CloudStack™ gaat veel verder dan het draaien van virtuele machine bestanden op commodity hardware, het is een turnkey oplossing om virtuele datacenters (as a service) te realiseren. Daarbij levert het alle essenti\u00eble componenten om multi-tier en multi-tentant cloud applicaties te bouwen en te beheren.", "message.installwizard.tooltip.addpod.name": "Een naam voor de pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Dit is de IP range van het private netwerk dat CloudStack gebruikt om met Secundaire Opslag VMs en Console Proxy VMs te communiceren. Deze IP adressen komen uit hetzelfde subnet als de gast VMs.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "De gateway voor de hosts in die pod.", diff --git a/ui/public/locales/pl.json b/ui/public/locales/pl.json index 6838b5e2a59..6077da5928e 100644 --- a/ui/public/locales/pl.json +++ b/ui/public/locales/pl.json @@ -1406,7 +1406,7 @@ "message.guest.traffic.in.basic.zone": "Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"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.

Extending beyond individual virtual machine 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. Both open-source and Premium versions are available, with the open-source version offering nearly identical features.", +"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.

Extending beyond individual virtual machine 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.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.", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 9de19db7442..af331765101 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -2223,7 +2223,7 @@ "message.host.dedicated": "Host dedicado", "message.host.dedication.released": "Host dedicado liberado", "message.info.cloudian.console": "O Cloudian management console deve abrir em outra janela", -"message.installwizard.copy.whatiscloudstack": "O CloudStack™ \u00e9 uma plataforma de software que agrega recursos computacionais para construir uma Cloud de infraestrutura como servi\u00e7o (IaaS) p\u00fablica, privada ou h\u00edbrida. O CloudStack™ ger\u00eancia a rede, o armazenamento e os recursos computacionais que comp\u00f5em a infraestrutura de cloud. utilize o CloudStack™ para instalar, gerenciar e configurar os ambientes de cloud computing.

Indo al\u00e9m de imagens de m\u00e1quinas virtuais individuais rodando em hardware commodity, CloudStack™ prov\u00ea uma solu\u00e7\u00e3o completa de software de infraestrutura de cloud para entregar datacenters virtuais como um servi\u00e7o - possuindo todos os componentes essenciais para contruir, instalar e gerenciar aplica\u00e7\u00f5es na cloud multi-camadas e multi-tenant. Ambas as vers\u00f5es open-source e premium est\u00e3o dispon\u00edveis, com a vers\u00e3o opensource oferecendo praticamente os mesmos recursos.", +"message.installwizard.copy.whatiscloudstack": "O CloudStack™ \u00e9 uma plataforma de software que agrega recursos computacionais para construir uma Cloud de infraestrutura como servi\u00e7o (IaaS) p\u00fablica, privada ou h\u00edbrida. O CloudStack™ ger\u00eancia a rede, o armazenamento e os recursos computacionais que comp\u00f5em a infraestrutura de cloud. utilize o CloudStack™ para instalar, gerenciar e configurar os ambientes de cloud computing.

Indo al\u00e9m de imagens de m\u00e1quinas virtuais individuais rodando em hardware commodity, CloudStack™ prov\u00ea uma solu\u00e7\u00e3o completa de software de infraestrutura de cloud para entregar datacenters virtuais como um servi\u00e7o - possuindo todos os componentes essenciais para contruir, instalar e gerenciar aplica\u00e7\u00f5es na cloud multi-camadas e multi-tenant.", "message.installwizard.tooltip.addpod.name": "O nome para o pod", "message.installwizard.tooltip.addpod.reservedsystemendip": "Este \u00e9 o range de IP na rede privada que o CloudStack utiliza para gerenciar o armazenamento secund\u00e1rio das VMs e proxy console das VMs. estes endere\u00e7os IP s\u00e3o obtidos da mesma subrede dos servidores hosts.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "O gateway para os hosts neste pod.", diff --git a/ui/public/locales/ru_RU.json b/ui/public/locales/ru_RU.json index f68d767d762..46d70081f1b 100644 --- a/ui/public/locales/ru_RU.json +++ b/ui/public/locales/ru_RU.json @@ -1404,7 +1404,7 @@ "message.guest.traffic.in.basic.zone": "\u0413\u043e\u0441\u0442\u0435\u0432\u043e\u0439 \u0442\u0440\u0430\u0444\u0438\u043a \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043e\u0431\u0449\u0435\u043d\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043c\u0430\u0448\u0438\u043d\u0430\u043c\u0438. \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0430\u0434\u0440\u0435\u0441\u043e\u0432 IP, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 CloudStack \u0441\u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0434\u043b\u044f \u0412\u041c. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043d\u0435 \u043f\u0435\u0440\u0435\u043a\u0440\u0435\u0449\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u043c \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432.", "message.host.dedicated": "Host Dedicated", "message.host.dedication.released": "Host dedication released", -"message.installwizard.copy.whatiscloudstack": "CloudStack™ - \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0430\u044f \u043f\u043b\u0430\u0444\u0442\u043e\u0440\u043c\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445, \u0447\u0430\u0441\u0442\u043d\u044b\u0445 \u0438 \u0433\u0438\u0431\u0440\u0438\u0434\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u043a\u043e\u0432 \u043f\u043e \u0441\u0445\u0435\u043c\u0435 \u00ab\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u00bb (IaaS). CloudStack™ \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0435\u0442\u044c\u044e, \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443. \u0413\u043b\u0430\u0432\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, CloudStack™ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.

CloudStack™ \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438 \u0446\u0435\u043b\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0431\u043b\u0430\u043a\u0430. \u041c\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043c\u0435\u0436\u0434\u0443 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0439 \u0438 \u0411\u0435\u0437\u043d\u0435\u0441-\u0432\u0435\u0440\u0441\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u0447\u0435\u043c \u043d\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f.", +"message.installwizard.copy.whatiscloudstack": "CloudStack™ - \u044d\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0430\u044f \u043f\u043b\u0430\u0444\u0442\u043e\u0440\u043c\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445, \u0447\u0430\u0441\u0442\u043d\u044b\u0445 \u0438 \u0433\u0438\u0431\u0440\u0438\u0434\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u043a\u043e\u0432 \u043f\u043e \u0441\u0445\u0435\u043c\u0435 \u00ab\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0438\u0441\u00bb (IaaS). CloudStack™ \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0435\u0442\u044c\u044e, \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u0443\u0437\u043b\u0430\u043c\u0438, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u043e\u0431\u043b\u0430\u0447\u043d\u0443\u044e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443. \u0413\u043b\u0430\u0432\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, CloudStack™ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.

CloudStack™ \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438 \u0446\u0435\u043b\u043e\u0433\u043e \u0446\u0435\u043d\u0442\u0440\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043e\u0431\u043b\u0430\u043a\u0430.", "message.installwizard.tooltip.addpod.name": "\u0418\u043c\u044f \u0441\u0442\u0435\u043d\u0434\u0430", "message.installwizard.tooltip.addpod.reservedsystemendip": "\u042d\u0442\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d IP \u0447\u0430\u0441\u0442\u043d\u043e\u0439 \u0441\u0435\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f CloudStack \u0434\u043b\u044f \u0412\u041c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u043a\u0441\u0438. \u042d\u0442\u0438 \u0430\u0434\u0440\u0435\u0441\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u0441\u0435\u0442\u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.", "message.installwizard.tooltip.addpod.reservedsystemgateway": "\u0428\u043b\u044e\u0437 \u0434\u043b\u044f \u0443\u0437\u043b\u043e\u0432 \u044d\u0442\u043e\u0433\u043e \u0441\u0442\u0435\u043d\u0434\u0430.", diff --git a/ui/public/locales/zh_CN.json b/ui/public/locales/zh_CN.json index 5337829b53d..fc3a456a8fb 100644 --- a/ui/public/locales/zh_CN.json +++ b/ui/public/locales/zh_CN.json @@ -3498,7 +3498,7 @@ "message.installwizard.copy.whatisahost": "\u4E3B\u673A\u662F\u6307\u4E00\u53F0\u8BA1\u7B97\u673A\u3002\u4E3B\u673A\u63D0\u4F9B\u8FD0\u884C\u6765\u5BBE\u865A\u62DF\u673A\u7684\u8BA1\u7B97\u8D44\u6E90\u3002\u6BCF\u53F0\u4E3B\u673A\u4E0A\u90FD\u5B89\u88C5\u6709\u865A\u62DF\u673A\u7BA1\u7406\u7A0B\u5E8F\u8F6F\u4EF6\uFF0C\u7528\u4E8E\u7BA1\u7406\u6765\u5BBE\u865A\u62DF\u673A\uFF08\u88F8\u673A\u4E3B\u673A\u9664\u5916\uFF0C\u5C06\u5728\u201C\u9AD8\u7EA7\u5B89\u88C5\u6307\u5357\u201D\u4E2D\u8BA8\u8BBA\u8FD9\u4E00\u7279\u6B8A\u6848\u4F8B\uFF09\u3002\u4F8B\u5982\uFF0C\u542F\u7528\u4E86 KVM \u7684 Linux \u670D\u52A1\u5668\u3001Citrix XenServer \u670D\u52A1\u5668\u548C ESXi \u670D\u52A1\u5668\u90FD\u53EF\u7528\u4F5C\u4E3B\u673A\u3002\u5728\u57FA\u672C\u5B89\u88C5\u4E2D\uFF0C\u6211\u4EEC\u5C06\u4F7F\u7528\u4E00\u53F0\u8FD0\u884C XenServer \u7684\u4E3B\u673A\u3002

\u4E3B\u673A\u662F CloudStack\u2122 \u90E8\u7F72\u4E2D\u6700\u5C0F\u7684\u7EC4\u7EC7\u5355\u4F4D\u3002\u4E3B\u673A\u5305\u542B\u5728\u96C6\u7FA4\u4E2D\uFF0C\u96C6\u7FA4\u5305\u542B\u5728\u63D0\u4F9B\u70B9\u4E2D\uFF0C\u63D0\u4F9B\u70B9\u5305\u542B\u5728\u8D44\u6E90\u57DF\u4E2D\u3002", "message.installwizard.copy.whatisapod": "\u4E00\u4E2A\u63D0\u4F9B\u70B9\u901A\u5E38\u4EE3\u8868\u4E00\u4E2A\u673A\u67B6\u3002\u540C\u4E00\u63D0\u4F9B\u70B9\u4E2D\u7684\u4E3B\u673A\u4F4D\u4E8E\u540C\u4E00\u5B50\u7F51\u4E2D\u3002

\u63D0\u4F9B\u70B9\u662F CloudStack\u2122 \u90E8\u7F72\u4E2D\u7684\u7B2C\u4E8C\u5927\u7EC4\u7EC7\u5355\u4F4D\u3002\u63D0\u4F9B\u70B9\u5305\u542B\u5728\u8D44\u6E90\u57DF\u4E2D\u3002\u6BCF\u4E2A\u8D44\u6E90\u57DF\u4E2D\u53EF\u4EE5\u5305\u542B\u4E00\u4E2A\u6216\u591A\u4E2A\u63D0\u4F9B\u70B9\uFF1B\u5728\u57FA\u672C\u5B89\u88C5\u4E2D\uFF0C\u60A8\u7684\u8D44\u6E90\u57DF\u4E2D\u5C06\u4EC5\u5305\u542B\u4E00\u4E2A\u63D0\u4F9B\u70B9\u3002", "message.installwizard.copy.whatisazone": "\u8D44\u6E90\u57DF\u662F CloudStack\u2122 \u90E8\u7F72\u4E2D\u6700\u5927\u7684\u7EC4\u7EC7\u5355\u4F4D\u3002\u867D\u7136\u5141\u8BB8\u4E00\u4E2A\u6570\u636E\u4E2D\u5FC3\u4E2D\u5B58\u5728\u591A\u4E2A\u8D44\u6E90\u57DF\uFF0C\u4F46\u662F\u4E00\u4E2A\u8D44\u6E90\u57DF\u901A\u5E38\u4E0E\u4E00\u4E2A\u6570\u636E\u4E2D\u5FC3\u76F8\u5BF9\u5E94\u3002\u5C06\u57FA\u7840\u67B6\u6784\u7F16\u7EC4\u5230\u8D44\u6E90\u57DF\u4E2D\u7684\u597D\u5904\u662F\u53EF\u4EE5\u63D0\u4F9B\u7269\u7406\u9694\u79BB\u548C\u5197\u4F59\u3002\u4F8B\u5982\uFF0C\u6BCF\u4E2A\u8D44\u6E90\u57DF\u90FD\u53EF\u4EE5\u62E5\u6709\u5404\u81EA\u7684\u7535\u6E90\u4F9B\u5E94\u548C\u7F51\u7EDC\u4E0A\u884C\u65B9\u6848\uFF0C\u5E76\u4E14\u5404\u8D44\u6E90\u57DF\u53EF\u4EE5\u5728\u5730\u7406\u4F4D\u7F6E\u4E0A\u76F8\u9694\u5F88\u8FDC\uFF08\u867D\u7136\u5E76\u975E\u5FC5\u987B\u76F8\u9694\u5F88\u8FDC\uFF09\u3002", - "message.installwizard.copy.whatiscloudstack": "CloudStack\u2122 \u662F\u4E00\u4E2A\u8F6F\u4EF6\u5E73\u53F0\uFF0C\u53EF\u5C06\u8BA1\u7B97\u8D44\u6E90\u96C6\u4E2D\u5728\u4E00\u8D77\u4EE5\u6784\u5EFA\u516C\u6709\u3001\u79C1\u6709\u548C\u6DF7\u5408\u57FA\u7840\u8BBE\u65BD\u5373\u670D\u52A1\uFF08IaaS\uFF09\u4E91\u3002 CloudStack\u2122 \u8D1F\u8D23\u7BA1\u7406\u7EC4\u6210\u4E91\u57FA\u7840\u67B6\u6784\u7684\u7F51\u7EDC\u3001\u5B58\u50A8\u548C\u8BA1\u7B97\u8282\u70B9\u3002\u4F7F\u7528 CloudStack\u2122 \u53EF\u4EE5\u90E8\u7F72\u3001\u7BA1\u7406\u548C\u914D\u7F6E\u4E91\u8BA1\u7B97\u73AF\u5883\u3002

CloudStack\u2122 \u901A\u8FC7\u6269\u5C55\u5546\u7528\u786C\u4EF6\u4E0A\u8FD0\u884C\u7684\u6BCF\u4E2A\u865A\u62DF\u673A\u6620\u50CF\u7684\u8303\u56F4\uFF0C\u63D0\u4F9B\u4E86\u4E00\u4E2A\u5B9E\u65F6\u53EF\u7528\u7684\u4E91\u57FA\u7840\u67B6\u6784\u8F6F\u4EF6\u5806\u6808\u7528\u4E8E\u4EE5\u670D\u52A1\u65B9\u5F0F\u4EA4\u4ED8\u865A\u62DF\u6570\u636E\u4E2D\u5FC3\uFF0C\u5373\u4EA4\u4ED8\u6784\u5EFA\u3001\u90E8\u7F72\u548C\u7BA1\u7406\u591A\u5C42\u6B21\u548C\u591A\u79DF\u6237\u4E91\u5E94\u7528\u7A0B\u5E8F\u5FC5\u9700\u7684\u6240\u6709\u7EC4\u4EF6\u3002\u5F00\u6E90\u7248\u672C\u548C Premium \u7248\u672C\u90FD\u5DF2\u53EF\u7528\uFF0C\u4E14\u63D0\u4F9B\u7684\u529F\u80FD\u51E0\u4E4E\u5B8C\u5168\u76F8\u540C\u3002", + "message.installwizard.copy.whatiscloudstack": "CloudStack\u2122 \u662F\u4E00\u4E2A\u8F6F\u4EF6\u5E73\u53F0\uFF0C\u53EF\u5C06\u8BA1\u7B97\u8D44\u6E90\u96C6\u4E2D\u5728\u4E00\u8D77\u4EE5\u6784\u5EFA\u516C\u6709\u3001\u79C1\u6709\u548C\u6DF7\u5408\u57FA\u7840\u8BBE\u65BD\u5373\u670D\u52A1\uFF08IaaS\uFF09\u4E91\u3002 CloudStack\u2122 \u8D1F\u8D23\u7BA1\u7406\u7EC4\u6210\u4E91\u57FA\u7840\u67B6\u6784\u7684\u7F51\u7EDC\u3001\u5B58\u50A8\u548C\u8BA1\u7B97\u8282\u70B9\u3002\u4F7F\u7528 CloudStack\u2122 \u53EF\u4EE5\u90E8\u7F72\u3001\u7BA1\u7406\u548C\u914D\u7F6E\u4E91\u8BA1\u7B97\u73AF\u5883\u3002

CloudStack\u2122 \u901A\u8FC7\u6269\u5C55\u5546\u7528\u786C\u4EF6\u4E0A\u8FD0\u884C\u7684\u6BCF\u4E2A\u865A\u62DF\u673A\u6620\u50CF\u7684\u8303\u56F4\uFF0C\u63D0\u4F9B\u4E86\u4E00\u4E2A\u5B9E\u65F6\u53EF\u7528\u7684\u4E91\u57FA\u7840\u67B6\u6784\u8F6F\u4EF6\u5806\u6808\u7528\u4E8E\u4EE5\u670D\u52A1\u65B9\u5F0F\u4EA4\u4ED8\u865A\u62DF\u6570\u636E\u4E2D\u5FC3\uFF0C\u5373\u4EA4\u4ED8\u6784\u5EFA\u3001\u90E8\u7F72\u548C\u7BA1\u7406\u591A\u5C42\u6B21\u548C\u591A\u79DF\u6237\u4E91\u5E94\u7528\u7A0B\u5E8F\u5FC5\u9700\u7684\u6240\u6709\u7EC4\u4EF6\u3002", "message.installwizard.copy.whatisprimarystorage": "CloudStack\u2122 \u4E91\u57FA\u7840\u67B6\u6784\u4F7F\u7528\u4EE5\u4E0B\u4E24\u79CD\u7C7B\u578B\u7684\u5B58\u50A8: \u4E3B\u5B58\u50A8\u548C\u4E8C\u7EA7\u5B58\u50A8\u3002\u8FD9\u4E24\u79CD\u7C7B\u578B\u7684\u5B58\u50A8\u53EF\u4EE5\u662F iSCSI \u6216 NFS \u670D\u52A1\u5668\uFF0C\u4E5F\u53EF\u4EE5\u662F\u672C\u5730\u78C1\u76D8\u3002

\u4E3B\u5B58\u50A8\u4E0E\u96C6\u7FA4\u76F8\u5173\u8054\uFF0C\u7528\u4E8E\u5B58\u50A8\u8BE5\u96C6\u7FA4\u4E2D\u7684\u4E3B\u673A\u4E0A\u6B63\u5728\u8FD0\u884C\u7684\u6240\u6709\u865A\u62DF\u673A\u5BF9\u5E94\u7684\u6BCF\u4E2A\u6765\u5BBE\u865A\u62DF\u673A\u7684\u78C1\u76D8\u5377\u3002\u4E3B\u5B58\u50A8\u670D\u52A1\u5668\u901A\u5E38\u4F4D\u4E8E\u9760\u8FD1\u4E3B\u673A\u7684\u4F4D\u7F6E\u3002", "message.installwizard.copy.whatissecondarystorage": "\u4E8C\u7EA7\u5B58\u50A8\u4E0E\u8D44\u6E90\u57DF\u76F8\u5173\u8054\uFF0C\u7528\u4E8E\u5B58\u50A8\u4EE5\u4E0B\u9879\u76EE:
  • \u6A21\u677F - \u53EF\u7528\u4E8E\u542F\u52A8\u865A\u62DF\u673A\u5E76\u53EF\u4EE5\u5305\u542B\u5176\u4ED6\u914D\u7F6E\u4FE1\u606F\uFF08\u4F8B\u5982\uFF0C\u5DF2\u5B89\u88C5\u7684\u5E94\u7528\u7A0B\u5E8F\uFF09\u7684\u64CD\u4F5C\u7CFB\u7EDF\u6620\u50CF
  • ISO \u6620\u50CF - \u53EF\u91CD\u65B0\u542F\u52A8\u6216\u4E0D\u53EF\u91CD\u65B0\u542F\u52A8\u7684\u64CD\u4F5C\u7CFB\u7EDF\u6620\u50CF
  • \u78C1\u76D8\u5377\u5FEB\u7167 - \u5DF2\u4FDD\u5B58\u7684\u865A\u62DF\u673A\u6570\u636E\u526F\u672C\uFF0C\u53EF\u7528\u4E8E\u6267\u884C\u6570\u636E\u6062\u590D\u6216\u521B\u5EFA\u65B0\u6A21\u677F
", "message.installwizard.now.building": "\u73B0\u5728\u6B63\u5728\u6784\u5EFA\u60A8\u7684\u4E91...", diff --git a/ui/src/components/view/SearchView.vue b/ui/src/components/view/SearchView.vue index 27142e521ba..76ccde802f7 100644 --- a/ui/src/components/view/SearchView.vue +++ b/ui/src/components/view/SearchView.vue @@ -80,7 +80,7 @@ - + @@ -90,13 +90,6 @@ {{ $t((['storageid'].includes(field.name) || !opt.path) ? opt.name : opt.path) }} - - - - - - - {{ $t(opt.path || opt.name) }} @@ -256,7 +249,8 @@ export default { this.fetchDynamicFieldData(fieldname, event.target.value) }, onSelectFieldChange (fieldname) { - if (fieldname === 'domainid') { + const fetchAccountOptions = fieldname === 'domainid' && this.fields.some((field) => field.name === 'account') + if (fetchAccountOptions) { this.fetchDynamicFieldData('account') } }, @@ -716,10 +710,6 @@ export default { if (Array.isArray(arrayField)) { this.fillFormFieldValues() } - if (networkIndex > -1) { - this.fields[networkIndex].loading = false - } - this.fillFormFieldValues() }) }, initFormFieldData () { @@ -787,7 +777,7 @@ export default { params.domainid = this.form.domainid } api('listAccounts', params).then(json => { - var account = json.listaccountsresponse.account + let account = json?.listaccountsresponse?.account || [] if (this.form.domainid) { account = account.filter(a => a.domainid === this.form.domainid) } @@ -1316,7 +1306,7 @@ export default { this.searchQuery = value this.$emit('search', { searchQuery: this.searchQuery }) }, - onClear () { + async onClear () { this.formRef.value.resetFields() this.form = reactive({}) this.isFiltered = false @@ -1324,6 +1314,14 @@ export default { this.inputValue = null this.searchQuery = null this.paramsFilter = {} + + const refreshAccountOptions = ['account', 'domainid'].every((field) => { + return this.fields.some((searchViewField) => searchViewField.name === field) + }) + if (refreshAccountOptions) { + await this.fetchDynamicFieldData('account') + } + this.$emit('search', this.paramsFilter) }, handleSubmit () { diff --git a/ui/src/config/section/infra/clusters.js b/ui/src/config/section/infra/clusters.js index c7edc6560ef..c304a8a7e6c 100644 --- a/ui/src/config/section/infra/clusters.js +++ b/ui/src/config/section/infra/clusters.js @@ -73,7 +73,7 @@ export default { api: 'addCluster', icon: 'plus-outlined', label: 'label.add.cluster', - docHelp: 'adminguide/installguide/configuration.html#adding-a-cluster', + docHelp: 'installguide/configuration.html#adding-a-cluster', listView: true, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/infra/ClusterAdd.vue'))) @@ -95,7 +95,7 @@ export default { icon: 'play-circle-outlined', label: 'label.action.enable.cluster', message: 'message.action.enable.cluster', - docHelp: 'adminguide/installguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', + docHelp: 'adminguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', dataView: true, defaultArgs: { allocationstate: 'Enabled' }, show: (record) => { return record.allocationstate === 'Disabled' } @@ -105,7 +105,7 @@ export default { icon: 'pause-circle-outlined', label: 'label.action.disable.cluster', message: 'message.action.disable.cluster', - docHelp: 'adminguide/installguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', + docHelp: 'adminguide/hosts.html#disabling-and-enabling-zones-pods-and-clusters', dataView: true, defaultArgs: { allocationstate: 'Disabled' }, show: (record) => { return record.allocationstate === 'Enabled' } diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index 81c666c1845..12a958a6211 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -65,7 +65,7 @@ export default { api: 'addHost', icon: 'plus-outlined', label: 'label.add.host', - docHelp: 'adminguide/installguide/configuration.html#adding-a-host', + docHelp: 'installguide/configuration.html#adding-a-host', listView: true, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/infra/HostAdd.vue'))) diff --git a/ui/src/views/auth/ForgotPassword.vue b/ui/src/views/auth/ForgotPassword.vue index 2d45938417f..87f2d1d0c33 100644 --- a/ui/src/views/auth/ForgotPassword.vue +++ b/ui/src/views/auth/ForgotPassword.vue @@ -129,7 +129,9 @@ export default { initForm () { this.formRef = ref() this.form = reactive({ - server: (this.server.apiHost || '') + this.server.apiBase + server: (this.server.apiHost || '') + this.server.apiBase, + username: this.$route.query?.username || '', + domain: this.$route.query?.domain || '' }) this.rules = { username: [{ diff --git a/ui/src/views/auth/Login.vue b/ui/src/views/auth/Login.vue index 10963073c18..47e2f34c57e 100644 --- a/ui/src/views/auth/Login.vue +++ b/ui/src/views/auth/Login.vue @@ -253,7 +253,9 @@ export default { initForm () { this.formRef = ref() this.form = reactive({ - server: (this.server.apiHost || '') + this.server.apiBase + server: (this.server.apiHost || '') + this.server.apiBase, + username: this.$route.query?.username || '', + domain: this.$route.query?.domain || '' }) this.rules = reactive({}) this.setRules() diff --git a/ui/src/views/auth/ResetPassword.vue b/ui/src/views/auth/ResetPassword.vue index 8a9047c5d3e..0250e60008a 100644 --- a/ui/src/views/auth/ResetPassword.vue +++ b/ui/src/views/auth/ResetPassword.vue @@ -157,6 +157,7 @@ export default { this.form = reactive({ server: (this.server.apiHost || '') + this.server.apiBase, username: this.$route.query?.username || '', + domain: this.$route.query?.domain || '', token: this.$route.query?.token || '' }) this.rules = { diff --git a/ui/src/views/tools/SelectVmwareVcenter.vue b/ui/src/views/tools/SelectVmwareVcenter.vue index 1d25657b11b..e93d893e9fc 100644 --- a/ui/src/views/tools/SelectVmwareVcenter.vue +++ b/ui/src/views/tools/SelectVmwareVcenter.vue @@ -89,7 +89,8 @@ @@ -99,7 +100,8 @@ @@ -109,7 +111,8 @@ @@ -119,13 +122,16 @@ +   +
- + + {{ }} {{ 'ESXi: ' + opt.name }} @@ -283,7 +290,7 @@ export default { this.loading = false }) }, - listZoneVmwareDcHosts () { + loadZoneVmwareDcHosts (doNotify) { this.loading = true const params = {} if (this.vcenterSelectedOption === 'new') { @@ -299,18 +306,23 @@ export default { this.hosts = response.listvmwaredchostsresponse.host } }).catch(error => { - this.$notifyError(error) + if (doNotify) { + this.$notifyError(error) + } + this.hosts = [] + return false }).finally(() => { this.loading = false + return true }) }, onSelectExistingVmwareDatacenter (value) { this.selectedExistingVcenterId = value - this.listZoneVmwareDcHosts() + this.loadZoneVmwareDcHosts(true) }, onSelectExternalVmwareDatacenter (value) { if (this.vcenterSelectedOption === 'new' && !(this.vcenter === '' || this.datacentername === '' || this.username === '' || this.password === '')) { - this.listZoneVmwareDcHosts() + this.loadZoneVmwareDcHosts(false) } }, onSelectExistingVmwareHost (value) { diff --git a/usage/pom.xml b/usage/pom.xml index 90a044633dc..cfc9317d597 100644 --- a/usage/pom.xml +++ b/usage/pom.xml @@ -61,7 +61,7 @@ com.mysql mysql-connector-j - provided + runtime org.dbunit diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index b9b32e7ff9b..9be7c0538b7 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -1544,7 +1544,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna //For volumes which are 'attached' successfully, set the 'deleted' column in the usage_storage table, //so that the secondary storage should stop accounting and only primary will be accounted. SearchCriteria sc = _usageStorageDao.createSearchCriteria(); - sc.addAnd("id", SearchCriteria.Op.EQ, volId); + sc.addAnd("entityId", SearchCriteria.Op.EQ, volId); sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME); List volumesVOs = _usageStorageDao.search(sc, null); if (volumesVOs != null) { @@ -1599,7 +1599,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna //For Upload event add an entry to the usage_storage table. SearchCriteria sc = _usageStorageDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, volId); + sc.addAnd("entityId", SearchCriteria.Op.EQ, volId); + sc.addAnd("storageType", SearchCriteria.Op.EQ, StorageTypes.VOLUME); sc.addAnd("deleted", SearchCriteria.Op.NULL); List volumesVOs = _usageStorageDao.search(sc, null); @@ -1776,7 +1777,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } else if (EventTypes.EVENT_LOAD_BALANCER_DELETE.equals(event.getType())) { SearchCriteria sc = _usageLoadBalancerPolicyDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.addAnd("lbId", SearchCriteria.Op.EQ, id); sc.addAnd("deleted", SearchCriteria.Op.NULL); List lbVOs = _usageLoadBalancerPolicyDao.search(sc, null); if (lbVOs.size() > 1) { @@ -1810,7 +1811,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } else if (EventTypes.EVENT_NET_RULE_DELETE.equals(event.getType())) { SearchCriteria sc = _usagePortForwardingRuleDao.createSearchCriteria(); sc.addAnd("accountId", SearchCriteria.Op.EQ, event.getAccountId()); - sc.addAnd("id", SearchCriteria.Op.EQ, id); + sc.addAnd("pfId", SearchCriteria.Op.EQ, id); sc.addAnd("deleted", SearchCriteria.Op.NULL); List pfVOs = _usagePortForwardingRuleDao.search(sc, null); if (pfVOs.size() > 1) { @@ -2111,7 +2112,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } else if (EventTypes.EVENT_VM_SNAPSHOT_OFF_PRIMARY.equals(event.getType())) { QueryBuilder sc = QueryBuilder.create(UsageSnapshotOnPrimaryVO.class); sc.and(sc.entity().getAccountId(), SearchCriteria.Op.EQ, event.getAccountId()); - sc.and(sc.entity().getId(), SearchCriteria.Op.EQ, vmId); + sc.and(sc.entity().getVmId(), SearchCriteria.Op.EQ, vmId); sc.and(sc.entity().getName(), SearchCriteria.Op.EQ, name); sc.and(sc.entity().getDeleted(), SearchCriteria.Op.NULL); List vmsnaps = sc.list(); @@ -2154,6 +2155,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna if (EventTypes.EVENT_NETWORK_DELETE.equals(event.getType())) { usageNetworksDao.remove(event.getResourceId(), event.getCreateDate()); } else if (EventTypes.EVENT_NETWORK_CREATE.equals(event.getType())) { + logger.debug("Marking existing helper entries for network [{}] as removed.", event.getResourceId()); + usageNetworksDao.remove(event.getResourceId(), event.getCreateDate()); + logger.debug("Creating a helper entry for network [{}].", event.getResourceId()); UsageNetworksVO usageNetworksVO = new UsageNetworksVO(event.getResourceId(), event.getOfferingId(), event.getZoneId(), event.getAccountId(), domainId, Network.State.Allocated.name(), event.getCreateDate(), null); usageNetworksDao.persist(usageNetworksVO); } else if (EventTypes.EVENT_NETWORK_UPDATE.equals(event.getType())) { @@ -2169,10 +2173,13 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna if (EventTypes.EVENT_VPC_DELETE.equals(event.getType())) { usageVpcDao.remove(event.getResourceId(), event.getCreateDate()); } else if (EventTypes.EVENT_VPC_CREATE.equals(event.getType())) { + logger.debug("Marking existing helper entries for VPC [{}] as removed.", event.getResourceId()); + usageVpcDao.remove(event.getResourceId(), event.getCreateDate()); + logger.debug("Creating a helper entry for VPC [{}].", event.getResourceId()); UsageVpcVO usageVPCVO = new UsageVpcVO(event.getResourceId(), event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null); usageVpcDao.persist(usageVPCVO); } else { - logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType())); + logger.error("Unknown event type [{}] in VPC event parser. Skipping it.", event.getType()); } } diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java index 888af714f31..c0e7f29375f 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/BaseMO.java @@ -34,6 +34,7 @@ import com.vmware.vim25.ObjectContent; import com.vmware.vim25.RetrieveResult; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.List; public class BaseMO { @@ -66,6 +67,9 @@ public class BaseMO { if (logger.isDebugEnabled()) { logger.debug("vmware result : {} ", ReflectionToStringBuilderUtils.reflectCollection(result)); } + if (result == null) { + return new Pair<>(null, new ArrayList<>()); + } String tokenForRetrievingNewResults = result.getToken(); List listOfObjects = result.getObjects(); return new Pair<>(tokenForRetrievingNewResults, listOfObjects); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java index 14bee5876ff..169959fdb91 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/mo/VirtualMachineMO.java @@ -889,6 +889,32 @@ public class VirtualMachineMO extends BaseMO { return fileLayout; } + public String getPath() throws Exception { + List subPaths = new ArrayList<>(); + ManagedObjectReference mor = _context.getVimClient().getDynamicProperty(_mor, "parent"); + while (mor != null && mor.getType().equalsIgnoreCase("Folder")) { + String subPath = _context.getVimClient().getDynamicProperty(mor, "name"); + if (StringUtils.isBlank(subPath)) { + return null; + } + subPaths.add(subPath); + mor = _context.getVimClient().getDynamicProperty(mor, "parent"); + } + + if (!subPaths.isEmpty()) { + Collections.reverse(subPaths); + String path = StringUtils.join(subPaths, "/"); + return path; + } + + return null; + } + + @Override + public ManagedObjectReference getParentMor() throws Exception { + return _context.getVimClient().getDynamicProperty(_mor, "parent"); + } + public String[] getNetworks() throws Exception { PropertySpec pSpec = new PropertySpec(); pSpec.setType("Network"); diff --git a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java index 9a6457017d7..62d283e0e0d 100644 --- a/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java +++ b/vmware-base/src/main/java/com/cloud/hypervisor/vmware/util/VmwareHelper.java @@ -802,6 +802,7 @@ public class VmwareHelper { instance = new UnmanagedInstanceTO(); instance.setName(vmMo.getVmName()); instance.setInternalCSName(vmMo.getInternalCSName()); + instance.setPath((vmMo.getPath())); instance.setCpuCoresPerSocket(vmMo.getCoresPerSocket()); instance.setOperatingSystemId(vmMo.getVmGuestInfo().getGuestId()); VirtualMachineConfigSummary configSummary = vmMo.getConfigSummary();