diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java index 24015e0b459..b4de48baec4 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/HostForMigrationResponse.java @@ -16,465 +16,20 @@ // under the License. package org.apache.cloudstack.api.response; -import java.util.Date; - -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; import com.cloud.host.Host; -import com.cloud.host.Status; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; @EntityReference(value = Host.class) -public class HostForMigrationResponse extends BaseResponse { - @SerializedName(ApiConstants.ID) - @Param(description = "the ID of the host") - private String id; - - @SerializedName(ApiConstants.NAME) - @Param(description = "the name of the host") - private String name; - - @SerializedName(ApiConstants.STATE) - @Param(description = "the state of the host") - private Status state; - - @SerializedName("disconnected") - @Param(description = "true if the host is disconnected. False otherwise.") - private Date disconnectedOn; - - @SerializedName(ApiConstants.TYPE) - @Param(description = "the host type") - private Host.Type hostType; - - @SerializedName("oscategoryid") - @Param(description = "the OS category ID of the host") - private String osCategoryId; - - @SerializedName("oscategoryname") - @Param(description = "the OS category name of the host") - private String osCategoryName; - - @SerializedName(ApiConstants.IP_ADDRESS) - @Param(description = "the IP address of the host") - private String ipAddress; - - @SerializedName(ApiConstants.ZONE_ID) - @Param(description = "the Zone ID of the host") - private String zoneId; - - @SerializedName(ApiConstants.ZONE_NAME) - @Param(description = "the Zone name of the host") - private String zoneName; - - @SerializedName(ApiConstants.POD_ID) - @Param(description = "the Pod ID of the host") - private String podId; - - @SerializedName("podname") - @Param(description = "the Pod name of the host") - private String podName; - - @SerializedName("version") - @Param(description = "the host version") - private String version; - - @SerializedName(ApiConstants.HYPERVISOR) - @Param(description = "the host hypervisor") - private String hypervisor; - - @SerializedName("cpunumber") - @Param(description = "the CPU number of the host") - private Integer cpuNumber; - - @SerializedName("cpuspeed") - @Param(description = "the CPU speed of the host") - private Long cpuSpeed; - - @Deprecated - @SerializedName("cpuallocated") - @Param(description = "the amount of the host's CPU currently allocated") - private String cpuAllocated; - - @SerializedName("cpuallocatedvalue") - @Param(description = "the amount of the host's CPU currently allocated in MHz") - private Long cpuAllocatedValue; - - @SerializedName("cpuallocatedpercentage") - @Param(description = "the amount of the host's CPU currently allocated in percentage") - private String cpuAllocatedPercentage; - - @SerializedName("cpuallocatedwithoverprovisioning") - @Param(description = "the amount of the host's CPU currently allocated after applying the cpu.overprovisioning.factor") - private String cpuAllocatedWithOverprovisioning; - - @SerializedName("cpuused") - @Param(description = "the amount of the host's CPU currently used") - private String cpuUsed; - - @SerializedName("cpuwithoverprovisioning") - @Param(description = "the amount of the host's CPU after applying the cpu.overprovisioning.factor ") - private String cpuWithOverprovisioning; - - @Deprecated - @SerializedName("memorytotal") - @Param(description = "the memory total of the host, this parameter is deprecated use memorywithoverprovisioning") - private Long memoryTotal; - - @SerializedName("memorywithoverprovisioning") - @Param(description = "the amount of the host's memory after applying the mem.overprovisioning.factor ") - private String memWithOverprovisioning; - - @SerializedName("averageload") - @Param(description = "the cpu average load on the host") - private Long averageLoad; - - @SerializedName("networkkbsread") - @Param(description = "the incoming network traffic on the host") - private Long networkKbsRead; - - @SerializedName("networkkbswrite") - @Param(description = "the outgoing network traffic on the host") - private Long networkKbsWrite; - - @Deprecated - @SerializedName("memoryallocated") - @Param(description = "the amount of the host's memory currently allocated") - private String memoryAllocated; - - @SerializedName("memoryallocatedpercentage") - @Param(description = "the amount of the host's memory currently allocated in percentage") - private String memoryAllocatedPercentage; - - @SerializedName("memoryallocatedbytes") - @Param(description = "the amount of the host's memory currently allocated in bytes") - private Long memoryAllocatedBytes; - - @SerializedName("memoryused") - @Param(description = "the amount of the host's memory currently used") - private Long memoryUsed; - - @SerializedName("disksizetotal") - @Param(description = "the total disk size of the host") - private Long diskSizeTotal; - - @SerializedName("disksizeallocated") - @Param(description = "the host's currently allocated disk size") - private Long diskSizeAllocated; - - @SerializedName("capabilities") - @Param(description = "capabilities of the host") - private String capabilities; - - @SerializedName("lastpinged") - @Param(description = "the date and time the host was last pinged") - private Date lastPinged; - - @SerializedName("managementserverid") - @Param(description = "the management server ID of the host") - private Long managementServerId; - - @SerializedName("clusterid") - @Param(description = "the cluster ID of the host") - private String clusterId; - - @SerializedName("clustername") - @Param(description = "the cluster name of the host") - private String clusterName; - - @SerializedName("clustertype") - @Param(description = "the cluster type of the cluster that host belongs to") - private String clusterType; - - @SerializedName("islocalstorageactive") - @Param(description = "true if local storage is active, false otherwise") - private Boolean localStorageActive; - - @SerializedName(ApiConstants.CREATED) - @Param(description = "the date and time the host was created") - private Date created; - - @SerializedName("removed") - @Param(description = "the date and time the host was removed") - private Date removed; - - @SerializedName("events") - @Param(description = "events available for the host") - private String events; - - @SerializedName("hosttags") - @Param(description = "comma-separated list of tags for the host") - private String hostTags; - - @SerializedName("explicithosttags") - @Param(description = "comma-separated list of explicit host tags for the host", since = "4.20.0") - private String explicitHostTags; - - @SerializedName("implicithosttags") - @Param(description = "comma-separated list of implicit host tags for the host", since = "4.20.0") - private String implicitHostTags; - - @SerializedName("hasenoughcapacity") - @Param(description = "true if this host has enough CPU and RAM capacity to migrate a VM to it, false otherwise") - private Boolean hasEnoughCapacity; - - @SerializedName("suitableformigration") - @Param(description = "true if this host is suitable(has enough capacity and satisfies all conditions like hosttags, " + - "max guests vm limit etc) to migrate a VM to it , false otherwise") - private Boolean suitableForMigration; +public class HostForMigrationResponse extends HostResponse { @SerializedName("requiresStorageMotion") @Param(description = "true if migrating a vm to this host requires storage motion, false otherwise") private Boolean requiresStorageMotion; - @SerializedName("resourcestate") - @Param(description = "the resource state of the host") - private String resourceState; - - @SerializedName(ApiConstants.HYPERVISOR_VERSION) - @Param(description = "the hypervisor version") - private String hypervisorVersion; - - @SerializedName(ApiConstants.HA_HOST) - @Param(description = "true if the host is Ha host (dedicated to vms started by HA process; false otherwise") - private Boolean haHost; - - @Override - public String getObjectId() { - return getId(); - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public void setName(String name) { - this.name = name; - } - - public void setState(Status state) { - this.state = state; - } - - public void setDisconnectedOn(Date disconnectedOn) { - this.disconnectedOn = disconnectedOn; - } - - public void setHostType(Host.Type hostType) { - this.hostType = hostType; - } - - public void setOsCategoryId(String osCategoryId) { - this.osCategoryId = osCategoryId; - } - - public void setOsCategoryName(String osCategoryName) { - this.osCategoryName = osCategoryName; - } - - public void setIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - } - - public void setZoneId(String zoneId) { - this.zoneId = zoneId; - } - - public void setZoneName(String zoneName) { - this.zoneName = zoneName; - } - - public void setPodId(String podId) { - this.podId = podId; - } - - public void setPodName(String podName) { - this.podName = podName; - } - - public void setVersion(String version) { - this.version = version; - } - - public void setHypervisor(String hypervisor) { - this.hypervisor = hypervisor; - } - - public void setCpuNumber(Integer cpuNumber) { - this.cpuNumber = cpuNumber; - } - - public void setCpuSpeed(Long cpuSpeed) { - this.cpuSpeed = cpuSpeed; - } - - public String getCpuAllocated() { - return cpuAllocated; - } - - public void setCpuAllocated(String cpuAllocated) { - this.cpuAllocated = cpuAllocated; - } - - public void setCpuAllocatedValue(Long cpuAllocatedValue) { - this.cpuAllocatedValue = cpuAllocatedValue; - } - - public void setCpuAllocatedPercentage(String cpuAllocatedPercentage) { - this.cpuAllocatedPercentage = cpuAllocatedPercentage; - } - - public void setCpuAllocatedWithOverprovisioning(String cpuAllocatedWithOverprovisioning) { - this.cpuAllocatedWithOverprovisioning = cpuAllocatedWithOverprovisioning; - } - - public void setCpuUsed(String cpuUsed) { - this.cpuUsed = cpuUsed; - } - - public void setAverageLoad(Long averageLoad) { - this.averageLoad = averageLoad; - } - - public void setNetworkKbsRead(Long networkKbsRead) { - this.networkKbsRead = networkKbsRead; - } - - public void setNetworkKbsWrite(Long networkKbsWrite) { - this.networkKbsWrite = networkKbsWrite; - } - - public void setMemoryAllocated(String memoryAllocated) { - this.memoryAllocated = memoryAllocated; - } - - public void setMemoryAllocatedPercentage(String memoryAllocatedPercentage) { - this.memoryAllocatedPercentage = memoryAllocatedPercentage; - } - - public void setMemoryAllocatedBytes(Long memoryAllocatedBytes) { - this.memoryAllocatedBytes = memoryAllocatedBytes; - } - - public void setMemoryUsed(Long memoryUsed) { - this.memoryUsed = memoryUsed; - } - - public void setDiskSizeTotal(Long diskSizeTotal) { - this.diskSizeTotal = diskSizeTotal; - } - - public void setDiskSizeAllocated(Long diskSizeAllocated) { - this.diskSizeAllocated = diskSizeAllocated; - } - - public void setCapabilities(String capabilities) { - this.capabilities = capabilities; - } - - public void setLastPinged(Date lastPinged) { - this.lastPinged = lastPinged; - } - - public void setManagementServerId(Long managementServerId) { - this.managementServerId = managementServerId; - } - - public void setClusterId(String clusterId) { - this.clusterId = clusterId; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public void setClusterType(String clusterType) { - this.clusterType = clusterType; - } - - public void setLocalStorageActive(Boolean localStorageActive) { - this.localStorageActive = localStorageActive; - } - - public void setCreated(Date created) { - this.created = created; - } - - public void setRemoved(Date removed) { - this.removed = removed; - } - - public void setEvents(String events) { - this.events = events; - } - - public String getHostTags() { - return hostTags; - } - - public void setHostTags(String hostTags) { - this.hostTags = hostTags; - } - - public void setExplicitHostTags(String explicitHostTags) { - this.explicitHostTags = explicitHostTags; - } - - public void setImplicitHostTags(String implicitHostTags) { - this.implicitHostTags = implicitHostTags; - } - - public void setHasEnoughCapacity(Boolean hasEnoughCapacity) { - this.hasEnoughCapacity = hasEnoughCapacity; - } - - public void setSuitableForMigration(Boolean suitableForMigration) { - this.suitableForMigration = suitableForMigration; - } - public void setRequiresStorageMotion(Boolean requiresStorageMotion) { this.requiresStorageMotion = requiresStorageMotion; } - - public String getResourceState() { - return resourceState; - } - - public void setResourceState(String resourceState) { - this.resourceState = resourceState; - } - - public String getCpuWithOverprovisioning() { - return cpuWithOverprovisioning; - } - - public void setCpuWithOverprovisioning(String cpuWithOverprovisioning) { - this.cpuWithOverprovisioning = cpuWithOverprovisioning; - } - - public void setMemWithOverprovisioning(String memWithOverprovisioning){ - this.memWithOverprovisioning=memWithOverprovisioning; - } - - public void setHypervisorVersion(String hypervisorVersion) { - this.hypervisorVersion = hypervisorVersion; - } - - public Boolean getHaHost() { - return haHost; - } - - public void setHaHost(Boolean haHost) { - this.haHost = haHost; - } - - public void setMemoryTotal(Long memoryTotal) { - this.memoryTotal = memoryTotal; - } } diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java index 63e97519534..09fb211fedf 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java @@ -54,6 +54,7 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.outofbandmanagement.dao.OutOfBandManagementDao; import org.apache.cloudstack.utils.identity.ManagementServerNode; import org.apache.commons.collections.MapUtils; +import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; import org.apache.commons.lang3.BooleanUtils; import com.cloud.agent.AgentManager; @@ -618,30 +619,25 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl logger.debug("Sending Connect to listener: {}", monitor.second().getClass().getSimpleName()); for (int i = 0; i < cmd.length; i++) { try { + logger.debug("process connection to issue {} forRebalance == {}", ReflectionToStringBuilderUtils.reflectCollection(cmd[i]), forRebalance); monitor.second().processConnect(host, cmd[i], forRebalance); - } catch (final Exception e) { - if (e instanceof ConnectionException) { - final ConnectionException ce = (ConnectionException)e; - if (ce.isSetupError()) { - logger.warn("Monitor {} says there is an error in the connect process for {} due to {}", - monitor.second().getClass().getSimpleName(), host, e.getMessage()); - handleDisconnectWithoutInvestigation(attache, Event.AgentDisconnected, true, true); - throw ce; - } else { - logger.info("Monitor {} says not to continue the connect process for {} due to {}", - monitor.second().getClass().getSimpleName(), host, e.getMessage()); - handleDisconnectWithoutInvestigation(attache, Event.ShutdownRequested, true, true); - return attache; - } - } else if (e instanceof HypervisorVersionChangedException) { - handleDisconnectWithoutInvestigation(attache, Event.ShutdownRequested, true, true); - throw new CloudRuntimeException(String.format("Unable to connect %s", attache), e); - } else { - logger.error("Monitor {} says there is an error in the connect process for {} due to {}", - monitor.second().getClass().getSimpleName(), host, e.getMessage(), e); + } catch (final ConnectionException ce) { + if (ce.isSetupError()) { + logger.warn("Monitor {} says there is an error in the connect process for {} due to {}", monitor.second().getClass().getSimpleName(), hostId, ce.getMessage()); handleDisconnectWithoutInvestigation(attache, Event.AgentDisconnected, true, true); - throw new CloudRuntimeException(String.format("Unable to connect %s", attache), e); + throw ce; + } else { + logger.info("Monitor {} says not to continue the connect process for {} due to {}", monitor.second().getClass().getSimpleName(), hostId, ce.getMessage()); + handleDisconnectWithoutInvestigation(attache, Event.ShutdownRequested, true, true); + return attache; } + } catch (final HypervisorVersionChangedException hvce) { + handleDisconnectWithoutInvestigation(attache, Event.ShutdownRequested, true, true); + throw new CloudRuntimeException("Unable to connect " + attache.getId(), hvce); + } catch (final Exception e) { + logger.error("Monitor {} says there is an error in the connect process for {} due to {}", monitor.second().getClass().getSimpleName(), hostId, e.getMessage(), e); + handleDisconnectWithoutInvestigation(attache, Event.AgentDisconnected, true, true); + throw new CloudRuntimeException("Unable to connect " + attache.getId(), e); } } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index ca3395be5dc..47edd2eff18 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -437,7 +437,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv protected static final String LOCAL_STORAGE_PATH = "local.storage.path"; protected static final String LOCAL_STORAGE_UUID = "local.storage.uuid"; - protected static final String DEFAULT_LOCAL_STORAGE_PATH = "/var/lib/libvirt/images/"; + public static final String DEFAULT_LOCAL_STORAGE_PATH = "/var/lib/libvirt/images"; protected List localStoragePaths = new ArrayList<>(); protected List localStorageUUIDs = new ArrayList<>(); @@ -2661,7 +2661,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv Map details = vmTO.getDetails(); boolean isIothreadsEnabled = details != null && details.containsKey(VmDetailConstants.IOTHREADS); - devices.addDevice(createSCSIDef(vcpus, isIothreadsEnabled)); + addSCSIControllers(devices, vcpus, vmTO.getDisks().length, isIothreadsEnabled); } return devices; } @@ -2699,8 +2699,19 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv * Creates Virtio SCSI controller.
* The respective Virtio SCSI XML definition is generated only if the VM's Disk Bus is of ISCSI. */ - protected SCSIDef createSCSIDef(int vcpus, boolean isIothreadsEnabled) { - return new SCSIDef((short)0, 0, 0, 9, 0, vcpus, isIothreadsEnabled); + protected SCSIDef createSCSIDef(short index, int vcpus, boolean isIothreadsEnabled) { + return new SCSIDef(index, 0, 0, 9 + index, 0, vcpus, isIothreadsEnabled); + } + + + private void addSCSIControllers(DevicesDef devices, int vcpus, int diskCount, boolean isIothreadsEnabled) { + int controllers = diskCount / 7; + if (diskCount % 7 != 0) { + controllers++; + } + for (int i = 0; i < controllers; i++) { + devices.addDevice(createSCSIDef((short)i, vcpus, isIothreadsEnabled)); + } } protected ConsoleDef createConsoleDef() { diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteStoragePoolCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteStoragePoolCommandWrapper.java index 716df4789f8..ad3ba80253e 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteStoragePoolCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtDeleteStoragePoolCommandWrapper.java @@ -22,12 +22,20 @@ package com.cloud.hypervisor.kvm.resource.wrapper; import com.cloud.agent.api.Answer; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.dao.impl.PropertiesStorage; +import com.cloud.agent.properties.AgentProperties; +import com.cloud.agent.properties.AgentPropertiesFileHandler; import com.cloud.hypervisor.kvm.resource.LibvirtComputingResource; import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; +import com.cloud.storage.Storage; import com.cloud.utils.exception.CloudRuntimeException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.stream.Collectors; + @ResourceWrapper(handles = DeleteStoragePoolCommand.class) public final class LibvirtDeleteStoragePoolCommandWrapper extends CommandWrapper { @Override @@ -35,15 +43,57 @@ public final class LibvirtDeleteStoragePoolCommandWrapper extends CommandWrapper try { // if getRemoveDatastore() is true, then we are dealing with managed storage and can skip the delete logic here if (!command.getRemoveDatastore()) { - final StorageFilerTO pool = command.getPool(); - final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr(); - - storagePoolMgr.deleteStoragePool(pool.getType(), pool.getUuid()); + handleStoragePoolDeletion(command, libvirtComputingResource); } - return new Answer(command); } catch (final CloudRuntimeException e) { return new Answer(command, false, e.toString()); } } + + private void handleStoragePoolDeletion(final DeleteStoragePoolCommand command, final LibvirtComputingResource libvirtComputingResource) { + final StorageFilerTO pool = command.getPool(); + final KVMStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr(); + storagePoolMgr.deleteStoragePool(pool.getType(), pool.getUuid()); + + if (isLocalStorageAndNotHavingDefaultPath(pool, libvirtComputingResource)) { + updateLocalStorageProperties(pool); + } + } + + private boolean isLocalStorageAndNotHavingDefaultPath(final StorageFilerTO pool, final LibvirtComputingResource libvirtComputingResource) { + return Storage.StoragePoolType.Filesystem.equals(pool.getType()) + && !libvirtComputingResource.DEFAULT_LOCAL_STORAGE_PATH.equals(pool.getPath()); + } + + private void updateLocalStorageProperties(final StorageFilerTO pool) { + String localStoragePath = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.LOCAL_STORAGE_PATH); + String localStorageUuid = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.LOCAL_STORAGE_UUID); + + String uuidToRemove = pool.getUuid(); + String pathToRemove = pool.getPath(); + + if (localStorageUuid != null && uuidToRemove != null) { + localStorageUuid = Arrays.stream(localStorageUuid.split(",")) + .filter(uuid -> !uuid.equals(uuidToRemove)) + .collect(Collectors.joining(",")); + } + + if (localStoragePath != null && pathToRemove != null) { + localStoragePath = Arrays.stream(localStoragePath.split(",")) + .filter(path -> !path.equals(pathToRemove)) + .collect(Collectors.joining(",")); + } + + PropertiesStorage agentProperties = new PropertiesStorage(); + agentProperties.configure("AgentProperties", new HashMap()); + + if (localStorageUuid != null) { + agentProperties.persist(AgentProperties.LOCAL_STORAGE_UUID.getName(), localStorageUuid); + } + + if (localStoragePath != null) { + agentProperties.persist(AgentProperties.LOCAL_STORAGE_PATH.getName(), localStoragePath); + } + } } diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 961537a534e..7faebb01b6b 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -461,6 +461,9 @@ public class LibvirtComputingResourceTest { to.setDetails(new HashMap<>()); to.setPlatformEmulator("Other PV Virtio-SCSI"); + final DiskTO diskTO = Mockito.mock(DiskTO.class); + to.setDisks(new DiskTO[]{diskTO}); + GuestDef guest = new GuestDef(); guest.setGuestType(GuestType.KVM); @@ -648,7 +651,7 @@ public class LibvirtComputingResourceTest { public void testCreateSCSIDef() { VirtualMachineTO to = createDefaultVM(false); - SCSIDef scsiDef = libvirtComputingResourceSpy.createSCSIDef(to.getCpus(), false); + SCSIDef scsiDef = libvirtComputingResourceSpy.createSCSIDef((short)0, to.getCpus(), false); Document domainDoc = parse(scsiDef.toString()); verifyScsi(to, domainDoc, ""); } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index 477eb257dee..bf7a2a5344a 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -568,7 +568,7 @@ public class KubernetesClusterManagerImpl extends ManagerBase implements Kuberne if (template != null) { response.setTemplateId(template.getUuid()); } - ServiceOfferingVO offering = serviceOfferingDao.findById(kubernetesCluster.getServiceOfferingId()); + ServiceOfferingVO offering = serviceOfferingDao.findByIdIncludingRemoved(kubernetesCluster.getServiceOfferingId()); if (offering != null) { response.setServiceOfferingId(offering.getUuid()); response.setServiceOfferingName(offering.getName()); diff --git a/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java index 59de277aa4b..42966435d4a 100644 --- a/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -113,9 +113,7 @@ public class HostJoinDaoImpl extends GenericDaoBase implements return result; } - @Override - public HostResponse newHostResponse(HostJoinVO host, EnumSet details) { - HostResponse hostResponse = new HostResponse(); + private void setNewHostResponseBase(HostJoinVO host, EnumSet details, HostResponse hostResponse) { hostResponse.setId(host.getUuid()); hostResponse.setCapabilities(host.getCapabilities()); hostResponse.setClusterId(host.getClusterUuid()); @@ -187,7 +185,6 @@ public class HostJoinDaoImpl extends GenericDaoBase implements DecimalFormat decimalFormat = new DecimalFormat("#.##"); if (host.getType() == Host.Type.Routing) { float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor(host.getClusterId()); - hostResponse.setCpuNumber((int)(host.getCpus() * cpuOverprovisioningFactor)); if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) { // set allocated capacities Long mem = host.getMemReservedCapacity() + host.getMemUsedCapacity(); @@ -298,124 +295,19 @@ public class HostJoinDaoImpl extends GenericDaoBase implements hostResponse.setUsername(host.getUsername()); hostResponse.setObjectName("host"); + } + @Override + public HostResponse newHostResponse(HostJoinVO host, EnumSet details) { + HostResponse hostResponse = new HostResponse(); + setNewHostResponseBase(host, details, hostResponse); return hostResponse; } @Override public HostForMigrationResponse newHostForMigrationResponse(HostJoinVO host, EnumSet details) { HostForMigrationResponse hostResponse = new HostForMigrationResponse(); - hostResponse.setId(host.getUuid()); - hostResponse.setCapabilities(host.getCapabilities()); - hostResponse.setClusterId(host.getClusterUuid()); - hostResponse.setCpuNumber(host.getCpus()); - hostResponse.setZoneId(host.getZoneUuid()); - hostResponse.setDisconnectedOn(host.getDisconnectedOn()); - hostResponse.setHypervisor(host.getHypervisorType().getHypervisorDisplayName()); - hostResponse.setHostType(host.getType()); - hostResponse.setLastPinged(new Date(host.getLastPinged())); - hostResponse.setManagementServerId(host.getManagementServerId()); - hostResponse.setName(host.getName()); - hostResponse.setPodId(host.getPodUuid()); - hostResponse.setRemoved(host.getRemoved()); - hostResponse.setCpuSpeed(host.getSpeed()); - hostResponse.setState(host.getStatus()); - hostResponse.setIpAddress(host.getPrivateIpAddress()); - hostResponse.setVersion(host.getVersion()); - hostResponse.setCreated(host.getCreated()); - - if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity) || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) { - - hostResponse.setOsCategoryId(host.getOsCategoryUuid()); - hostResponse.setOsCategoryName(host.getOsCategoryName()); - hostResponse.setZoneName(host.getZoneName()); - hostResponse.setPodName(host.getPodName()); - if (host.getClusterId() > 0) { - hostResponse.setClusterName(host.getClusterName()); - hostResponse.setClusterType(host.getClusterType().toString()); - } - } - - DecimalFormat decimalFormat = new DecimalFormat("#.##"); - if (host.getType() == Host.Type.Routing) { - if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) { - // set allocated capacities - Long mem = host.getMemReservedCapacity() + host.getMemUsedCapacity(); - Long cpu = host.getCpuReservedCapacity() + host.getCpuUsedCapacity(); - - hostResponse.setMemoryTotal(host.getTotalMemory()); - Float memWithOverprovisioning = host.getTotalMemory() * ApiDBUtils.getMemOverprovisioningFactor(host.getClusterId()); - hostResponse.setMemWithOverprovisioning(decimalFormat.format(memWithOverprovisioning)); - String memoryAllocatedPercentage = decimalFormat.format((float) mem / memWithOverprovisioning * 100.0f) +"%"; - hostResponse.setMemoryAllocated(memoryAllocatedPercentage); - hostResponse.setMemoryAllocatedPercentage(memoryAllocatedPercentage); - hostResponse.setMemoryAllocatedBytes(mem); - - String hostTags = host.getTag(); - hostResponse.setHostTags(hostTags); - hostResponse.setHaHost(containsHostHATag(hostTags)); - hostResponse.setImplicitHostTags(host.getImplicitTag()); - - hostResponse.setHypervisorVersion(host.getHypervisorVersion()); - - hostResponse.setCpuAllocatedValue(cpu); - String cpuAlloc = decimalFormat.format(((float)cpu / (float)(host.getCpus() * host.getSpeed())) * 100f) + "%"; - hostResponse.setCpuAllocated(cpuAlloc); - hostResponse.setCpuAllocatedPercentage(cpuAlloc); - float cpuWithOverprovisioning = host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor(host.getClusterId()); - hostResponse.setCpuAllocatedWithOverprovisioning(calculateResourceAllocatedPercentage(cpu, cpuWithOverprovisioning)); - hostResponse.setCpuWithOverprovisioning(decimalFormat.format(cpuWithOverprovisioning)); - } - - if (details.contains(HostDetails.all) || details.contains(HostDetails.stats)) { - // set CPU/RAM/Network stats - String cpuUsed = null; - HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId()); - if (hostStats != null) { - float cpuUtil = (float)hostStats.getCpuUtilization(); - cpuUsed = decimalFormat.format(cpuUtil) + "%"; - hostResponse.setCpuUsed(cpuUsed); - hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue()); - hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue()); - hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue()); - - } - } - - } else if (host.getType() == Host.Type.SecondaryStorage) { - StorageStats secStorageStats = ApiDBUtils.getSecondaryStorageStatistics(host.getId()); - if (secStorageStats != null) { - hostResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes()); - hostResponse.setDiskSizeAllocated(secStorageStats.getByteUsed()); - } - } - - hostResponse.setLocalStorageActive(ApiDBUtils.isLocalStorageActiveOnHost(host.getId())); - - if (details.contains(HostDetails.all) || details.contains(HostDetails.events)) { - Set possibleEvents = host.getStatus().getPossibleEvents(); - if ((possibleEvents != null) && !possibleEvents.isEmpty()) { - String events = ""; - Iterator iter = possibleEvents.iterator(); - while (iter.hasNext()) { - com.cloud.host.Status.Event event = iter.next(); - events += event.toString(); - if (iter.hasNext()) { - events += "; "; - } - } - hostResponse.setEvents(events); - } - } - - hostResponse.setResourceState(host.getResourceState().toString()); - - // set async job - hostResponse.setJobId(host.getJobUuid()); - hostResponse.setJobStatus(host.getJobStatus()); - - hostResponse.setObjectName("host"); - + setNewHostResponseBase(host, details, hostResponse); return hostResponse; } diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index 1c5da19fbbc..4ca5bf2eb92 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -808,7 +808,9 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (!(dc.isLocalStorageEnabled() || useLocalStorageForSystemVM)) { return null; } - DataStore store; + DataStore store = null; + DataStoreProvider provider = _dataStoreProviderMgr.getDefaultPrimaryDataStoreProvider(); + DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); try { String hostAddress = pInfo.getHost(); if (host.getHypervisorType() == Hypervisor.HypervisorType.VMware) { @@ -834,8 +836,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } - DataStoreProvider provider = _dataStoreProviderMgr.getDefaultPrimaryDataStoreProvider(); - DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); if (pool == null) { Map params = new HashMap<>(); String name = pInfo.getName() != null ? pInfo.getName() : createLocalStoragePoolName(host, pInfo); @@ -864,7 +864,15 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } catch (Exception e) { - logger.warn("Unable to setup the local storage pool for " + host, e); + logger.warn("Unable to setup the local storage pool for {}", host, e); + try { + if (store != null) { + logger.debug("Trying to delete storage pool entry if exists {}", store); + lifeCycle.deleteDataStore(store); + } + } catch (Exception ex) { + logger.debug("Failed to clean up local storage pool: {}", ex.getMessage()); + } throw new ConnectionException(true, "Unable to setup the local storage pool for " + host, e); } diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index db20b859cf7..a2d82d477aa 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -2315,6 +2315,8 @@ "label.traffictype": "Traffic type", "label.transportzoneuuid": "Transport zone UUID", "label.trigger.shutdown": "Trigger Safe Shutdown", +"label.true": "True", +"label.false": "False", "label.try.again": "Try again", "label.tuesday": "Tuesday", "label.two.factor.authentication.secret.key": "Your Two factor authentication secret key", diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index 5a2bca13381..37c22edba77 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -87,6 +87,9 @@ {{ $t(text.toLowerCase()) }} {{ $t(text.toLowerCase()) }} + + {{ $t(text.toLowerCase()) }} + {{ text }} {{ text }} @@ -231,6 +234,10 @@ + diff --git a/ui/src/components/view/SearchView.vue b/ui/src/components/view/SearchView.vue index 786a9f15be6..3bd7ad5ef68 100644 --- a/ui/src/components/view/SearchView.vue +++ b/ui/src/components/view/SearchView.vue @@ -311,9 +311,12 @@ export default { if (item === 'isencrypted' && !('listVolumes' in this.$store.getters.apis)) { return true } + if (item === 'displaynetwork' && this.$store.getters.userInfo.roletype !== 'Admin') { + return true + } if (['zoneid', 'domainid', 'imagestoreid', 'storageid', 'state', 'account', 'hypervisor', 'level', 'clusterid', 'podid', 'groupid', 'entitytype', 'accounttype', 'systemvmtype', 'scope', 'provider', - 'type', 'scope', 'managementserverid', 'serviceofferingid', 'diskofferingid', 'networkid', 'usagetype', 'restartrequired'].includes(item) + 'type', 'scope', 'managementserverid', 'serviceofferingid', 'diskofferingid', 'networkid', 'usagetype', 'restartrequired', 'displaynetwork'].includes(item) ) { type = 'list' } else if (item === 'tags') { @@ -335,6 +338,12 @@ export default { return arrayField }, fetchStaticFieldData (arrayField) { + if (arrayField.includes('displaynetwork')) { + const typeIndex = this.fields.findIndex(item => item.name === 'displaynetwork') + this.fields[typeIndex].loading = true + this.fields[typeIndex].opts = this.fetchBoolean() + this.fields[typeIndex].loading = false + } if (arrayField.includes('type')) { if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) { const typeIndex = this.fields.findIndex(item => item.name === 'type') @@ -1009,6 +1018,18 @@ export default { } return types }, + fetchBoolean () { + const types = [] + types.push({ + id: 'true', + name: 'label.true' + }) + types.push({ + id: 'false', + name: 'label.false' + }) + return types + }, fetchAccountTypes () { const types = [] if (this.apiName.indexOf('listAccounts') > -1) { diff --git a/ui/src/components/widgets/Status.vue b/ui/src/components/widgets/Status.vue index 50340c2faa2..af52de7ceb9 100644 --- a/ui/src/components/widgets/Status.vue +++ b/ui/src/components/widgets/Status.vue @@ -119,6 +119,7 @@ export default { case 'up': case 'success': case 'poweron': + case 'primary': status = 'success' break case 'alert': @@ -155,6 +156,7 @@ export default { case 'pending': case 'unsecure': case 'warning': + case 'backup': status = 'warning' break } diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index e87127b15b7..2fee9fca319 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -47,14 +47,14 @@ export default { return fields }, details: () => { - var fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'broadcasturi', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'asnumber', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domainpath', 'associatednetwork', 'associatednetworkid', 'ip4routing', 'ip6routing', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu', 'privatemtu'] + var fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'broadcasturi', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domainpath', 'associatednetwork', 'associatednetworkid', 'ip6firewall', 'ip6routing', 'ip6routes', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu', 'privatemtu'] if (!isAdmin()) { fields = fields.filter(function (e) { return e !== 'broadcasturi' }) } return fields }, filters: ['all', 'account', 'domainpath', 'shared'], - searchFilters: ['keyword', 'zoneid', 'domainid', 'account', 'type', 'restartrequired', 'tags'], + searchFilters: ['keyword', 'zoneid', 'domainid', 'account', 'type', 'restartrequired', 'displaynetwork', 'tags'], related: [{ name: 'vm', title: 'label.instances', @@ -66,15 +66,7 @@ export default { }, { name: 'egress.rules', component: shallowRef(defineAsyncComponent(() => import('@/views/network/EgressRulesTab.vue'))), - show: (record, route, user) => { return record.type === 'Isolated' && !record.ip4routing && !('vpcname' in record) && 'listEgressFirewallRules' in store.getters.apis && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid) } - }, { - name: 'bgp.peers', - component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/BgpPeersTab.vue'))), - show: (record, route, user) => { return !record.vpcid && ['Admin'].includes(user.roletype) && record.ip4routing === 'Dynamic' } - }, { - name: 'routing.firewall', - component: shallowRef(defineAsyncComponent(() => import('@/views/network/RoutingFirewallRulesTab.vue'))), - show: (record, route, user) => { return record.type === 'Isolated' && record.ip4routing && !('vpcname' in record) && 'listRoutingFirewallRules' in store.getters.apis && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid) } + show: (record, route, user) => { return record.type === 'Isolated' && !('vpcname' in record) && 'listEgressFirewallRules' in store.getters.apis && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid) } }, { name: 'ip.v6.firewall', component: shallowRef(defineAsyncComponent(() => import('@/views/network/Ipv6FirewallRulesTab.vue'))), @@ -82,7 +74,7 @@ export default { }, { name: (record) => { return record.type === 'Shared' ? 'ip.addresses' : 'public.ip.addresses' }, component: shallowRef(defineAsyncComponent(() => import('@/views/network/IpAddressesTab.vue'))), - show: (record, route, user) => { return 'listPublicIpAddresses' in store.getters.apis && (record.type === 'Shared' || (record.type === 'Isolated' && !record.ip4routing && !('vpcname' in record) && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid))) } + show: (record, route, user) => { return 'listPublicIpAddresses' in store.getters.apis && (record.type === 'Shared' || (record.type === 'Isolated' && !('vpcname' in record) && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid))) } }, { name: 'virtual.routers', component: shallowRef(defineAsyncComponent(() => import('@/views/network/RoutersTab.vue'))), @@ -148,9 +140,7 @@ export default { icon: 'edit-outlined', label: 'label.update.network', dataView: true, - disabled: (record, user) => { - return !record.projectid && (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) - }, + disabled: (record, user) => { return (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) }, popup: true, component: shallowRef(defineAsyncComponent(() => import('@/views/network/UpdateNetwork.vue'))) }, @@ -160,9 +150,7 @@ export default { label: 'label.restart.network', message: 'message.restart.network', dataView: true, - disabled: (record, user) => { - return !record.projectid && (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) - }, + disabled: (record, user) => { return (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) }, args: (record, store, isGroupAction) => { var fields = [] if (isGroupAction || record.vpcid == null) { @@ -201,9 +189,7 @@ export default { label: 'label.action.delete.network', message: 'message.action.delete.network', dataView: true, - disabled: (record, user) => { - return !record.projectid && (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) - }, + disabled: (record, user) => { return (record.account !== user.userInfo.account && !['Admin', 'DomainAdmin'].includes(user.userInfo.roletype)) }, groupAction: true, popup: true, groupMap: (selection) => { return selection.map(x => { return { id: x } }) } @@ -225,8 +211,8 @@ export default { fields.push(...['domain', 'zonename']) return fields }, - details: ['name', 'id', 'displaytext', 'cidr', 'networkdomain', 'ip4routing', 'ip4routes', 'ip6routes', 'ispersistent', 'redundantvpcrouter', 'restartrequired', 'zonename', 'account', 'domain', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu'], - searchFilters: ['name', 'zoneid', 'domainid', 'account', 'restartrequired', 'tags'], + details: ['name', 'id', 'displaytext', 'cidr', 'networkdomain', 'ip6routes', 'ispersistent', 'redundantvpcrouter', 'restartrequired', 'zonename', 'account', 'domain', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu'], + searchFilters: ['name', 'zoneid', 'domainid', 'account', 'tags'], related: [{ name: 'vm', title: 'label.instances', @@ -315,7 +301,10 @@ export default { return false } const listZoneHaveSGEnabled = store.getters.zones.filter(zone => zone.securitygroupsenabled === true) - return (listZoneHaveSGEnabled && listZoneHaveSGEnabled.length > 0) || store.getters.showSecurityGroups + if (!listZoneHaveSGEnabled || listZoneHaveSGEnabled.length === 0) { + return false + } + return true }, actions: [ { @@ -866,54 +855,6 @@ export default { } ] }, - { - name: 'asnumbers', - title: 'label.asnumbers', - icon: 'partition-outlined', - permission: ['listASNumbers'], - show: () => { - if (!store.getters.zones || store.getters.zones.length === 0) { - return false - } - const AdvancedZonesWithRoutedmode = store.getters.zones.filter(zone => zone.routedmodeenabled) - if (isAdmin() && (AdvancedZonesWithRoutedmode && AdvancedZonesWithRoutedmode.length > 0)) { - return true - } - return false - }, - filters: ['all', 'allocatedonly', 'free'], - columns: ['asnumber', 'allocationstate', 'asnrange', 'associatednetworkname', 'vpcname', 'allocated', 'account', 'domain', 'zonename'], - searchFilters: ['zoneid', 'associatednetworkid', 'account', 'domainid'], - resourceType: 'ASNumber', - actions: [ - { - api: 'releaseASNumber', - icon: 'delete-outlined', - label: 'label.action.release.asnumber', - message: 'message.action.release.asnumber', - show: (record) => { return record.allocationstate === 'Allocated' }, - args: ['zoneid', 'asnumber'], - mapping: { - zoneid: { - value: (record) => { return record.zoneid } - }, - asnumber: { - value: (record) => { return record.asnumber } - } - }, - dataView: true, - groupAction: true, - popup: true, - groupShow: (selectedItems, storegetters) => { - return selectedItems.length === 1 && selectedItems[0].allocationstate === 'Allocated' - }, - groupMap: (selectedId, values, records) => { - const record = records.filter(x => { return x.id === selectedId[0] }) - return record - } - } - ] - }, { name: 'privategw', title: 'label.private.gateway', @@ -1440,46 +1381,6 @@ export default { } return true } - }, - { - name: 'ipv4subnets', - title: 'label.ipv4.subnets', - icon: 'pic-center-outlined', - permission: ['listIpv4SubnetsForGuestNetwork'], - columns: ['subnet', 'zonename', 'parentsubnet', 'networkname', 'vpcname', 'created', 'allocated'], - details: ['subnet', 'zonename', 'zoneid', 'parentsubnet', 'networkname', 'networkid', 'vpcname', 'vpcid', 'created', 'allocated', 'state'], - searchFilters: ['zoneid'], - show: () => { - if (!store.getters.zones || store.getters.zones.length === 0) { - return false - } - const AdvancedZonesWithRoutedmode = store.getters.zones.filter(zone => zone.routedmodeenabled) - if (isAdmin() && (AdvancedZonesWithRoutedmode && AdvancedZonesWithRoutedmode.length > 0)) { - return true - } - return false - }, - actions: [ - { - api: 'createIpv4SubnetForGuestNetwork', - icon: 'plus-outlined', - label: 'label.add.ipv4.subnet', - listView: true, - popup: true, - component: shallowRef(defineAsyncComponent(() => import('@/views/network/CreateIpv4SubnetForNetwork.vue'))) - }, - { - api: 'deleteIpv4SubnetForGuestNetwork', - icon: 'delete-outlined', - label: 'label.delete.ipv4.subnet', - message: 'message.action.delete.ipv4.subnet', - dataView: true, - show: (record) => { return !record.networkid }, - groupAction: true, - popup: true, - groupMap: (selection) => { return selection.map(x => { return { id: x } }) } - } - ] } ] } diff --git a/ui/src/views/AutogenView.vue b/ui/src/views/AutogenView.vue index bfdde77191e..9b94e1d7686 100644 --- a/ui/src/views/AutogenView.vue +++ b/ui/src/views/AutogenView.vue @@ -920,6 +920,9 @@ export default { this.loading = true if (this.$route.params && this.$route.params.id) { params.id = this.$route.params.id + if (['listNetworks'].includes(this.apiName) && 'displaynetwork' in this.$route.query) { + params.displaynetwork = this.$route.query.displaynetwork + } if (['listSSHKeyPairs'].includes(this.apiName)) { if (!this.$isValidUuid(params.id)) { delete params.id diff --git a/ui/src/views/dashboard/CapacityDashboard.vue b/ui/src/views/dashboard/CapacityDashboard.vue index dae53cf0015..c2461b5adce 100644 --- a/ui/src/views/dashboard/CapacityDashboard.vue +++ b/ui/src/views/dashboard/CapacityDashboard.vue @@ -174,6 +174,12 @@
@@ -184,15 +190,19 @@

- {{ displayData(ctype, statsMap[ctype]?.capacityused) }} {{ $t('label.allocated') }} | {{ displayData(ctype, statsMap[ctype]?.capacitytotal) }} {{ $t('label.total') }} + {{ displayDataUsedOrAllocated(ctype, statsMap[ctype]?.capacityused, statsMap[ctype]?.capacityallocated) }} {{ this.displayAllocatedCompute ? $t('label.allocated') : $t('label.used') }} | {{ displayData(ctype, statsMap[ctype]?.capacitytotal) }} {{ $t('label.total') }}
@@ -346,6 +356,7 @@ export default { zones: [], zoneSelected: {}, statsMap: {}, + displayAllocatedCompute: false, data: { pods: 0, clusters: 0, @@ -402,6 +413,18 @@ export default { } return 'normal' }, + displayPercentUsedOrAllocated (used, allocated, total) { + var value = this.displayAllocatedCompute ? allocated : used + return parseFloat(100.0 * value / total) + }, + displayPercentFormatUsedOrAllocated (used, allocated, total) { + var value = this.displayAllocatedCompute ? allocated : used + return parseFloat(100.0 * value / total).toFixed(2) + '%' + }, + displayDataUsedOrAllocated (dataType, used, allocated) { + var value = this.displayAllocatedCompute ? allocated : used + return this.displayData(dataType, value) + }, displayData (dataType, value) { if (!value) { value = 0 diff --git a/ui/src/views/network/AclListRulesTab.vue b/ui/src/views/network/AclListRulesTab.vue index 5303a97aefb..e01e61289e5 100644 --- a/ui/src/views/network/AclListRulesTab.vue +++ b/ui/src/views/network/AclListRulesTab.vue @@ -781,7 +781,7 @@ export default { const csvData = this.csv({ data: this.acls }) const hiddenElement = document.createElement('a') - hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csvData) + hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent(csvData) hiddenElement.target = '_blank' hiddenElement.download = 'AclRules-' + this.resource.name + '-' + this.resource.id + '.csv' hiddenElement.click() diff --git a/ui/src/views/network/VpcTiersTab.vue b/ui/src/views/network/VpcTiersTab.vue index e9eaddf149e..5d985ae7688 100644 --- a/ui/src/views/network/VpcTiersTab.vue +++ b/ui/src/views/network/VpcTiersTab.vue @@ -213,7 +213,7 @@ @change="updateMtu()"/>
- +