diff --git a/api/src/main/java/com/cloud/agent/api/Command.java b/api/src/main/java/com/cloud/agent/api/Command.java index 4a698e46bde..b3c6120462a 100644 --- a/api/src/main/java/com/cloud/agent/api/Command.java +++ b/api/src/main/java/com/cloud/agent/api/Command.java @@ -37,6 +37,7 @@ public abstract class Command { @LogLevel(Log4jLevel.Trace) protected Map contextMap = new HashMap(); private int wait; //in second + private boolean bypassHostMaintenance = false; protected Command() { this.wait = 0; @@ -74,6 +75,14 @@ public abstract class Command { return true; } + public boolean isBypassHostMaintenance() { + return bypassHostMaintenance; + } + + public void setBypassHostMaintenance(boolean bypassHostMaintenance) { + this.bypassHostMaintenance = bypassHostMaintenance; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/api/src/main/java/com/cloud/resource/ResourceState.java b/api/src/main/java/com/cloud/resource/ResourceState.java index 9b3bafe28db..6e0fa909230 100644 --- a/api/src/main/java/com/cloud/resource/ResourceState.java +++ b/api/src/main/java/com/cloud/resource/ResourceState.java @@ -114,6 +114,7 @@ public enum ResourceState { s_fsm.addTransition(ResourceState.Enabled, Event.Disable, ResourceState.Disabled); s_fsm.addTransition(ResourceState.Enabled, Event.AdminAskMaintenance, ResourceState.PrepareForMaintenance); s_fsm.addTransition(ResourceState.Enabled, Event.InternalEnterMaintenance, ResourceState.Maintenance); + s_fsm.addTransition(ResourceState.Enabled, Event.DeleteHost, ResourceState.Disabled); s_fsm.addTransition(ResourceState.Disabled, Event.Enable, ResourceState.Enabled); s_fsm.addTransition(ResourceState.Disabled, Event.Disable, ResourceState.Disabled); s_fsm.addTransition(ResourceState.Disabled, Event.InternalCreated, ResourceState.Disabled); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java index b42b2717b91..2fafe933968 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/template/GetUploadParamsForTemplateCmd.java @@ -89,6 +89,11 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd { @Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.") private String templateTag; + @Parameter(name=ApiConstants.DEPLOY_AS_IS, + type = CommandType.BOOLEAN, + description = "(VMware only) true if VM deployments should preserve all the configurations defined for this template", since = "4.15.1") + private Boolean deployAsIs; + public String getDisplayText() { return displayText; } @@ -153,6 +158,11 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd { return templateTag; } + public boolean isDeployAsIs() { + return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor) && + Boolean.TRUE.equals(deployAsIs); + } + @Override public void execute() throws ServerApiException { validateRequest(); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java index 79e3d4b57c7..526dffa707a 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/HostResponse.java @@ -347,10 +347,6 @@ public class HostResponse extends BaseResponse { this.cpuSpeed = cpuSpeed; } - public String getCpuAllocated() { - return cpuAllocated; - } - public void setCpuAllocated(String cpuAllocated) { this.cpuAllocated = cpuAllocated; } @@ -622,6 +618,10 @@ public class HostResponse extends BaseResponse { return cpuUsed; } + public String getCpuAllocated() { + return cpuAllocated; + } + public Double getAverageLoad() { return cpuloadaverage; } diff --git a/engine/components-api/src/main/java/com/cloud/ha/HighAvailabilityManager.java b/engine/components-api/src/main/java/com/cloud/ha/HighAvailabilityManager.java index 18ceddbf68d..1dd999dad97 100644 --- a/engine/components-api/src/main/java/com/cloud/ha/HighAvailabilityManager.java +++ b/engine/components-api/src/main/java/com/cloud/ha/HighAvailabilityManager.java @@ -32,7 +32,7 @@ import java.util.List; */ public interface HighAvailabilityManager extends Manager { - ConfigKey ForceHA = new ConfigKey<>("Advanced", Boolean.class, "force.ha", "false", + public ConfigKey ForceHA = new ConfigKey<>("Advanced", Boolean.class, "force.ha", "false", "Force High-Availability to happen even if the VM says no.", true, Cluster); ConfigKey HAWorkers = new ConfigKey<>("Advanced", Integer.class, "ha.workers", "5", diff --git a/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java b/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java index 0a50e4b29df..61489e5f7c8 100644 --- a/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java +++ b/engine/components-api/src/main/java/com/cloud/network/IpAddressManager.java @@ -185,7 +185,7 @@ public interface IpAddressManager { IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp, String ipaddress) throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; - PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, boolean isSystem) + PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, String requestedGateway, boolean isSystem) throws InsufficientAddressCapacityException; PublicIp getAvailablePublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, boolean isSystem) @@ -219,6 +219,7 @@ public interface IpAddressManager { final boolean assign, final boolean allocate, final String requestedIp, + final String requestedGateway, final boolean isSystem, final Long vpcId, final Boolean displayIp, diff --git a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentAttache.java b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentAttache.java index 45df2311f3a..8810465d794 100644 --- a/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentAttache.java +++ b/engine/orchestration/src/main/java/com/cloud/agent/manager/AgentAttache.java @@ -31,10 +31,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import com.cloud.agent.api.ModifySshKeysCommand; -import com.cloud.agent.api.ModifyStoragePoolCommand; import org.apache.cloudstack.agent.lb.SetupMSListCommand; -import com.cloud.agent.api.RollingMaintenanceCommand; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.log4j.Logger; @@ -48,10 +45,13 @@ import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.Command; import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.ModifySshKeysCommand; +import com.cloud.agent.api.ModifyStoragePoolCommand; import com.cloud.agent.api.ModifyTargetsCommand; import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.ReadyCommand; +import com.cloud.agent.api.RollingMaintenanceCommand; import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.ShutdownCommand; import com.cloud.agent.api.StartCommand; @@ -167,7 +167,7 @@ public abstract class AgentAttache { if (_maintenance) { for (final Command cmd : cmds) { - if (Arrays.binarySearch(s_commandsAllowedInMaintenanceMode, cmd.getClass().toString()) < 0) { + if (Arrays.binarySearch(s_commandsAllowedInMaintenanceMode, cmd.getClass().toString()) < 0 && !cmd.isBypassHostMaintenance()) { throw new AgentUnavailableException("Unable to send " + cmd.getClass().toString() + " because agent " + _name + " is in maintenance mode", _id); } } 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 5fe3de523bb..565d4de8788 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -535,6 +535,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac advanceExpunge(vm); } + private boolean expungeCommandCanBypassHostMaintenance(VirtualMachine vm) { + return VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType()) || + VirtualMachine.Type.ConsoleProxy.equals(vm.getType()); + } + protected void advanceExpunge(VMInstanceVO vm) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException { if (vm == null || vm.getRemoved() != null) { if (s_logger.isDebugEnabled()) { @@ -581,6 +586,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac final Commands cmds = new Commands(Command.OnError.Stop); for (final Command volumeExpungeCommand : volumeExpungeCommands) { + volumeExpungeCommand.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm)); cmds.addCommand(volumeExpungeCommand); } @@ -622,10 +628,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (hostId != null) { final Commands cmds = new Commands(Command.OnError.Stop); for (final Command command : finalizeExpungeCommands) { + command.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm)); cmds.addCommand(command); } if (nicExpungeCommands != null) { for (final Command command : nicExpungeCommands) { + command.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm)); cmds.addCommand(command); } } @@ -4891,7 +4899,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac String.format("VM %s is at %s and we received a %s report while there is no pending jobs on it" , vm.getInstanceName(), vm.getState(), vm.getPowerState())); } - if (vm.isHaEnabled() && vm.getState() == State.Running + if((HighAvailabilityManager.ForceHA.value() || vm.isHaEnabled()) && vm.getState() == State.Running && HaVmRestartHostUp.value() && vm.getHypervisorType() != HypervisorType.VMware && vm.getHypervisorType() != HypervisorType.Hyperv) { diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index 14ee29c08dc..5307f4b9d66 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -264,9 +264,6 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.valueIn(clusterId); final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.valueIn(clusterId); final Float memoryDisableThreshold = DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.valueIn(clusterId); - // Over commit ratios - final Double cpuOvercommitRatio = findRatioValue(ApiDBUtils.findClusterDetails(clusterId, "cpuOvercommitRatio")); - final Double memoryOvercommitRatio = findRatioValue(ApiDBUtils.findClusterDetails(clusterId, "memoryOvercommitRatio")); Long upInstances = 0L; Long totalInstances = 0L; @@ -283,11 +280,11 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric } metricsResponse.setPowerState(hostResponse.getOutOfBandManagementResponse().getPowerState()); metricsResponse.setInstances(upInstances, totalInstances); - metricsResponse.setCpuTotal(hostResponse.getCpuNumber(), hostResponse.getCpuSpeed(), cpuOvercommitRatio); + metricsResponse.setCpuTotal(hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); metricsResponse.setCpuUsed(hostResponse.getCpuUsed(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); metricsResponse.setCpuAllocated(hostResponse.getCpuAllocated(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); metricsResponse.setLoadAverage(hostResponse.getAverageLoad()); - metricsResponse.setMemTotal(hostResponse.getMemoryTotal(), memoryOvercommitRatio); + metricsResponse.setMemTotal(hostResponse.getMemoryTotal()); metricsResponse.setMemAllocated(hostResponse.getMemoryAllocated()); metricsResponse.setMemUsed(hostResponse.getMemoryUsed()); metricsResponse.setNetworkRead(hostResponse.getNetworkKbsRead()); @@ -295,13 +292,13 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric // CPU thresholds metricsResponse.setCpuUsageThreshold(hostResponse.getCpuUsed(), cpuThreshold); metricsResponse.setCpuUsageDisableThreshold(hostResponse.getCpuUsed(), cpuDisableThreshold); - metricsResponse.setCpuAllocatedThreshold(hostResponse.getCpuAllocated(), cpuOvercommitRatio, cpuThreshold); - metricsResponse.setCpuAllocatedDisableThreshold(hostResponse.getCpuAllocated(), cpuOvercommitRatio, cpuDisableThreshold); + metricsResponse.setCpuAllocatedThreshold(hostResponse.getCpuAllocated(), cpuThreshold); + metricsResponse.setCpuAllocatedDisableThreshold(hostResponse.getCpuAllocated(), cpuDisableThreshold); // Memory thresholds metricsResponse.setMemoryUsageThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryThreshold); metricsResponse.setMemoryUsageDisableThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryDisableThreshold); - metricsResponse.setMemoryAllocatedThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryOvercommitRatio, memoryThreshold); - metricsResponse.setMemoryAllocatedDisableThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryOvercommitRatio, memoryDisableThreshold); + metricsResponse.setMemoryAllocatedThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryThreshold); + metricsResponse.setMemoryAllocatedDisableThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryDisableThreshold); metricsResponses.add(metricsResponse); } return metricsResponses; diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java index 30a3fb73670..7a557e36ac6 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/HostMetricsResponse.java @@ -17,14 +17,15 @@ package org.apache.cloudstack.response; -import com.cloud.serializer.Param; -import com.cloud.utils.exception.CloudRuntimeException; -import com.google.gson.annotations.SerializedName; +import java.text.DecimalFormat; +import java.text.ParseException; + import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement; -import java.text.DecimalFormat; -import java.text.ParseException; +import com.cloud.serializer.Param; +import com.cloud.utils.exception.CloudRuntimeException; +import com.google.gson.annotations.SerializedName; public class HostMetricsResponse extends HostResponse { @SerializedName("powerstate") @@ -113,9 +114,9 @@ public class HostMetricsResponse extends HostResponse { } } - public void setCpuTotal(final Integer cpuNumber, final Long cpuSpeed, final Double overcommitRatio) { - if (cpuNumber != null && cpuSpeed != null && overcommitRatio != null) { - this.cpuTotal = String.format("%.2f Ghz (x %.1f)", cpuNumber * cpuSpeed / 1000.0, overcommitRatio); + public void setCpuTotal(final Integer cpuNumber, final Long cpuSpeed) { + if (cpuNumber != null && cpuSpeed != null) { + this.cpuTotal = String.format("%.2f Ghz", cpuNumber * cpuSpeed / 1000.0); } } @@ -137,9 +138,9 @@ public class HostMetricsResponse extends HostResponse { } } - public void setMemTotal(final Long memTotal, final Double overcommitRatio) { - if (memTotal != null && overcommitRatio != null) { - this.memTotal = String.format("%.2f GB (x %.1f)", memTotal / (1024.0 * 1024.0 * 1024.0), overcommitRatio); + public void setMemTotal(final Long memTotal) { + if (memTotal != null) { + this.memTotal = String.format("%.2f GB", memTotal / (1024.0 * 1024.0 * 1024.0)); } } @@ -179,15 +180,15 @@ public class HostMetricsResponse extends HostResponse { } } - public void setCpuAllocatedThreshold(final String cpuAllocated, final Double overCommitRatio, final Double threshold) { - if (cpuAllocated != null && overCommitRatio != null && threshold != null) { - this.cpuAllocatedThresholdExceeded = parseCPU(cpuAllocated) > (100.0 * threshold * overCommitRatio); + public void setCpuAllocatedThreshold(final String cpuAllocated, final Double threshold) { + if (cpuAllocated != null && threshold != null) { + this.cpuAllocatedThresholdExceeded = Double.valueOf(cpuAllocated.replace("%", "")) > (100.0 * threshold ); } } - public void setCpuAllocatedDisableThreshold(final String cpuAllocated, final Double overCommitRatio, final Float threshold) { - if (cpuAllocated != null && overCommitRatio != null && threshold != null) { - this.cpuAllocatedDisableThresholdExceeded = parseCPU(cpuAllocated) > (100.0 * threshold * overCommitRatio); + public void setCpuAllocatedDisableThreshold(final String cpuAllocated, final Float threshold) { + if (cpuAllocated != null && threshold != null) { + this.cpuAllocatedDisableThresholdExceeded = Double.valueOf(cpuAllocated.replace("%", "")) > (100.0 * threshold); } } @@ -203,15 +204,15 @@ public class HostMetricsResponse extends HostResponse { } } - public void setMemoryAllocatedThreshold(final Long memAllocated, final Long memTotal, final Double overCommitRatio, final Double threshold) { - if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null) { - this.memoryAllocatedThresholdExceeded = memAllocated > (memTotal * threshold * overCommitRatio); + public void setMemoryAllocatedThreshold(final Long memAllocated, final Long memTotal, final Double threshold) { + if (memAllocated != null && memTotal != null && threshold != null) { + this.memoryAllocatedThresholdExceeded = memAllocated > (memTotal * threshold); } } - public void setMemoryAllocatedDisableThreshold(final Long memAllocated, final Long memTotal, final Double overCommitRatio, final Float threshold) { - if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null) { - this.memoryAllocatedDisableThresholdExceeded = memAllocated > (memTotal * threshold * overCommitRatio); + public void setMemoryAllocatedDisableThreshold(final Long memAllocated, final Long memTotal, final Float threshold) { + if (memAllocated != null && memTotal != null && threshold != null) { + this.memoryAllocatedDisableThresholdExceeded = memAllocated > (memTotal * threshold); } } diff --git a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index 3cbcc8541ad..3cdb843e0d7 100644 --- a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -18,14 +18,14 @@ */ package org.apache.cloudstack.storage.datastore.driver; +import static com.cloud.utils.NumbersUtil.toHumanReadableSize; + import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.inject.Inject; -import org.apache.log4j.Logger; - import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; @@ -53,6 +53,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.SnapshotObjectTO; import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.volume.VolumeObject; +import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.storage.ResizeVolumeAnswer; @@ -70,6 +71,7 @@ import com.cloud.storage.ResizeVolumePayload; import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePool; +import com.cloud.storage.Volume; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; @@ -77,10 +79,10 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.template.TemplateManager; import com.cloud.utils.Pair; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; -import static com.cloud.utils.NumbersUtil.toHumanReadableSize; - public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver { @Override public Map getCapabilities() { @@ -212,10 +214,22 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri } } + private boolean commandCanBypassHostMaintenance(DataObject data) { + if (DataObjectType.VOLUME.equals(data.getType())) { + Volume volume = (Volume)data; + if (volume.getInstanceId() != null) { + VMInstanceVO vm = vmDao.findById(volume.getInstanceId()); + return vm != null && (VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType()) || + VirtualMachine.Type.ConsoleProxy.equals(vm.getType())); + } + } + return false; + } + @Override public void deleteAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback callback) { DeleteCommand cmd = new DeleteCommand(data.getTO()); - + cmd.setBypassHostMaintenance(commandCanBypassHostMaintenance(data)); CommandResult result = new CommandResult(); try { EndPoint ep = null; 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 de87a0a0d5f..32236093f03 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 @@ -163,13 +163,15 @@ 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(); Long cpu = host.getCpuReservedCapacity() + host.getCpuUsedCapacity(); - hostResponse.setMemoryTotal(host.getTotalMemory()); Float memWithOverprovisioning = host.getTotalMemory() * ApiDBUtils.getMemOverprovisioningFactor(host.getClusterId()); + hostResponse.setMemoryTotal(memWithOverprovisioning.longValue()); hostResponse.setMemWithOverprovisioning(decimalFormat.format(memWithOverprovisioning)); hostResponse.setMemoryAllocated(mem); hostResponse.setMemoryAllocatedBytes(mem); @@ -188,12 +190,12 @@ public class HostJoinDaoImpl extends GenericDaoBase implements hostResponse.setHypervisorVersion(host.getHypervisorVersion()); + float cpuWithOverprovisioning = host.getCpus() * host.getSpeed() * cpuOverprovisioningFactor; 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)); + String cpuAllocated = calculateResourceAllocatedPercentage(cpu, cpuWithOverprovisioning); + hostResponse.setCpuAllocated(cpuAllocated); + hostResponse.setCpuAllocatedPercentage(cpuAllocated); + hostResponse.setCpuAllocatedWithOverprovisioning(cpuAllocated); hostResponse.setCpuWithOverprovisioning(decimalFormat.format(cpuWithOverprovisioning)); } diff --git a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 8dfa1f67db0..3a89d9641c5 100644 --- a/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/main/java/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1006,6 +1006,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } public boolean isZoneReady(Map zoneHostInfoMap, long dataCenterId) { + List hosts = _hostDao.listByDataCenterId(dataCenterId); + if (CollectionUtils.isEmpty(hosts)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Zone " + dataCenterId + " has no host available which is enabled and in Up state"); + } + return false; + } ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) { VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any); diff --git a/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java index b05e008546b..8dd9c9b6d6f 100644 --- a/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/main/java/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -16,9 +16,32 @@ // under the License. package com.cloud.ha; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.managed.context.ManagedContext; +import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.management.ManagementServerHost; +import org.apache.log4j.Logger; +import org.apache.log4j.NDC; + import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; import com.cloud.cluster.ClusterManagerListener; +import com.cloud.consoleproxy.ConsoleProxyManager; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -46,37 +69,16 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.StorageManager; import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.user.AccountManager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; -import org.apache.cloudstack.framework.config.ConfigKey; -import org.apache.cloudstack.framework.config.Configurable; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.cloudstack.managed.context.ManagedContext; -import org.apache.cloudstack.managed.context.ManagedContextRunnable; -import org.apache.cloudstack.management.ManagementServerHost; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.inject.Inject; -import javax.naming.ConfigurationException; /** * HighAvailabilityManagerImpl coordinates the HA process. VMs are registered with the HA Manager for HA. The request is stored @@ -125,9 +127,12 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur HostPodDao _podDao; @Inject ClusterDetailsDao _clusterDetailsDao; - @Inject ServiceOfferingDao _serviceOfferingDao; + @Inject + private ConsoleProxyManager consoleProxyManager; + @Inject + private SecondaryStorageVmManager secondaryStorageVmManager; long _serverId; @@ -197,7 +202,6 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur int _maxRetries; long _timeBetweenFailures; long _timeBetweenCleanups; - boolean _forceHA; String _haTag = null; protected HighAvailabilityManagerImpl() { @@ -364,7 +368,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur alertType = AlertManager.AlertType.ALERT_TYPE_SSVM; } - if (!(_forceHA || vm.isHaEnabled())) { + if (!(ForceHA.value() || vm.isHaEnabled())) { String hostDesc = "id:" + vm.getHostId() + ", availability zone id:" + vm.getDataCenterId() + ", pod id:" + vm.getPodIdToDeployIn(); _alertMgr.sendAlert(alertType, vm.getDataCenterId(), vm.getPodIdToDeployIn(), "VM (name: " + vm.getHostName() + ", id: " + vm.getId() + ") stopped unexpectedly on host " + hostDesc, "Virtual Machine " + vm.getHostName() + " (id: " + vm.getId() + ") running on host [" + vm.getHostId() + @@ -569,7 +573,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur vm = _itMgr.findById(vm.getId()); - if (!_forceHA && !vm.isHaEnabled()) { + if (!ForceHA.value() && !vm.isHaEnabled()) { if (s_logger.isDebugEnabled()) { s_logger.debug("VM is not HA enabled so we're done."); } @@ -680,31 +684,51 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur _haDao.delete(vm.getId(), WorkType.Destroy); } + private void stopVMWithCleanup(VirtualMachine vm, VirtualMachine.State state) throws OperationTimedoutException, ResourceUnavailableException { + if (VirtualMachine.State.Running.equals(state)) { + _itMgr.advanceStop(vm.getUuid(), true); + } + } + + private void destroyVM(VirtualMachine vm, boolean expunge) throws OperationTimedoutException, AgentUnavailableException { + s_logger.info("Destroying " + vm.toString()); + if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) { + consoleProxyManager.destroyProxy(vm.getId()); + } else if (VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType())) { + secondaryStorageVmManager.destroySecStorageVm(vm.getId()); + } else { + _itMgr.destroy(vm.getUuid(), expunge); + } + } + protected Long destroyVM(final HaWorkVO work) { final VirtualMachine vm = _itMgr.findById(work.getInstanceId()); - s_logger.info("Destroying " + vm.toString()); + if (vm == null) { + s_logger.info("No longer can find VM " + work.getInstanceId() + ". Throwing away " + work); + return null; + } + boolean expunge = VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType()) + || VirtualMachine.Type.ConsoleProxy.equals(vm.getType()); + if (!expunge && VirtualMachine.State.Destroyed.equals(work.getPreviousState())) { + s_logger.info("VM " + vm.getUuid() + " already in " + vm.getState() + " state. Throwing away " + work); + return null; + } try { - if (vm.getState() != State.Destroyed) { - s_logger.info("VM is no longer in Destroyed state " + vm.toString()); - return null; - } - - if (vm.getHostId() != null) { - _itMgr.destroy(vm.getUuid(), false); - s_logger.info("Successfully destroy " + vm); + stopVMWithCleanup(vm, work.getPreviousState()); + if (!VirtualMachine.State.Expunging.equals(work.getPreviousState())) { + destroyVM(vm, expunge); return null; } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug(vm + " has already been stopped"); - } - return null; + s_logger.info("VM " + vm.getUuid() + " still in " + vm.getState() + " state."); } } catch (final AgentUnavailableException e) { - s_logger.debug("Agnet is not available" + e.getMessage()); + s_logger.debug("Agent is not available" + e.getMessage()); } catch (OperationTimedoutException e) { s_logger.debug("operation timed out: " + e.getMessage()); } catch (ConcurrentOperationException e) { s_logger.debug("concurrent operation: " + e.getMessage()); + } catch (ResourceUnavailableException e) { + s_logger.debug("Resource unavailable: " + e.getMessage()); } return (System.currentTimeMillis() >> 10) + _stopRetryInterval; @@ -793,9 +817,8 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur case Stop: case CheckStop: case ForceStop: - return ((System.currentTimeMillis() >> 10) + _stopRetryInterval); case Destroy: - return ((System.currentTimeMillis() >> 10) + _restartRetryInterval); + return ((System.currentTimeMillis() >> 10) + _stopRetryInterval); } return 0; } @@ -861,7 +884,6 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur _workers[i] = new WorkerThread("HA-Worker-" + i); } - _forceHA = ForceHA.value(); _timeToSleep = TimeToSleep.value() * SECONDS_TO_MILLISECONDS_FACTOR; _maxRetries = MigrationMaxRetries.value(); _timeBetweenFailures = TimeBetweenFailures.value() * SECONDS_TO_MILLISECONDS_FACTOR; diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java index 3a6e1842b18..9ba8c1f6fde 100644 --- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java @@ -477,6 +477,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage SearchBuilder vlanSearch = _vlanDao.createSearchBuilder(); vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ); vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), Op.EQ); + vlanSearch.and("vlanGateway", vlanSearch.entity().getVlanGateway(), Op.EQ); AssignIpAddressSearch.join("vlan", vlanSearch, vlanSearch.entity().getId(), AssignIpAddressSearch.entity().getVlanId(), JoinType.INNER); AssignIpAddressSearch.done(); @@ -488,6 +489,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage SearchBuilder podVlanSearch = _vlanDao.createSearchBuilder(); podVlanSearch.and("type", podVlanSearch.entity().getVlanType(), Op.EQ); podVlanSearch.and("networkId", podVlanSearch.entity().getNetworkId(), Op.EQ); + podVlanSearch.and("vlanGateway", podVlanSearch.entity().getVlanGateway(), Op.EQ); SearchBuilder podVlanMapSB = _podVlanMapDao.createSearchBuilder(); podVlanMapSB.and("podId", podVlanMapSB.entity().getPodId(), Op.EQ); AssignIpAddressFromPodVlanSearch.join("podVlanMapSB", podVlanMapSB, podVlanMapSB.entity().getVlanDbId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), @@ -756,34 +758,34 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage @Override public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem, boolean forSystemVms) throws InsufficientAddressCapacityException { - return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp, isSystem, null, null, forSystemVms); + return fetchNewPublicIp(dcId, podId, null, owner, type, networkId, false, true, requestedIp, null, isSystem, null, null, forSystemVms); } @Override - public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, boolean isSystem) + public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, String requestedGateway, boolean isSystem) throws InsufficientAddressCapacityException { - return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, type, networkId, false, true, requestedIp, isSystem, null, null, false); + return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, type, networkId, false, true, requestedIp, requestedGateway, isSystem, null, null, false); } @Override public PublicIp getAvailablePublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List vlanDbIds, Long networkId, String requestedIp, boolean isSystem) throws InsufficientAddressCapacityException { - return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, type, networkId, false, false, false, requestedIp, isSystem, null, null, false); + return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, type, networkId, false, false, false, requestedIp, null, isSystem, null, null, false); } @DB public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId, - final boolean sourceNat, final boolean allocate, final String requestedIp, final boolean isSystem, final Long vpcId, final Boolean displayIp, final boolean forSystemVms) + final boolean sourceNat, final boolean allocate, final String requestedIp, final String requestedGateway, final boolean isSystem, final Long vpcId, final Boolean displayIp, final boolean forSystemVms) throws InsufficientAddressCapacityException { return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, vlanUse, guestNetworkId, - sourceNat, true, allocate, requestedIp, isSystem, vpcId, displayIp, forSystemVms); + sourceNat, true, allocate, requestedIp, requestedGateway, isSystem, vpcId, displayIp, forSystemVms); } @DB public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId, - final boolean sourceNat, final boolean assign, final boolean allocate, final String requestedIp, final boolean isSystem, final Long vpcId, final Boolean displayIp, final boolean forSystemVms) + final boolean sourceNat, final boolean assign, final boolean allocate, final String requestedIp, final String requestedGateway, final boolean isSystem, final Long vpcId, final Boolean displayIp, final boolean forSystemVms) throws InsufficientAddressCapacityException { - List addrs = listAvailablePublicIps(dcId, podId, vlanDbIds, owner, vlanUse, guestNetworkId, sourceNat, assign, allocate, requestedIp, isSystem, vpcId, displayIp, forSystemVms, true); + List addrs = listAvailablePublicIps(dcId, podId, vlanDbIds, owner, vlanUse, guestNetworkId, sourceNat, assign, allocate, requestedIp, requestedGateway, isSystem, vpcId, displayIp, forSystemVms, true); IPAddressVO addr = addrs.get(0); if (vlanUse == VlanType.VirtualNetwork) { _firewallMgr.addSystemFirewallRules(addr, owner); @@ -794,7 +796,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage @Override public List listAvailablePublicIps(final long dcId, final Long podId, final List vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId, - final boolean sourceNat, final boolean assign, final boolean allocate, final String requestedIp, final boolean isSystem, + final boolean sourceNat, final boolean assign, final boolean allocate, final String requestedIp, final String requestedGateway, final boolean isSystem, final Long vpcId, final Boolean displayIp, final boolean forSystemVms, final boolean lockOneRow) throws InsufficientAddressCapacityException { return Transaction.execute(new TransactionCallbackWithException, InsufficientAddressCapacityException>() { @Override @@ -865,6 +867,10 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage sc.setJoinParameters("vlan", "networkId", guestNetworkId); errorMessage.append(", network id=" + guestNetworkId); } + if (requestedGateway != null) { + sc.setJoinParameters("vlan", "vlanGateway", requestedGateway); + errorMessage.append(", requested gateway=" + requestedGateway); + } sc.setJoinParameters("vlan", "type", vlanUse); String routerIpAddress = null; if (network != null) { @@ -1030,7 +1036,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage VpcVO vpc = _vpcDao.findById(vpcId); displayIp = vpc.isDisplay(); } - return fetchNewPublicIp(dcId, null, null, owner, VlanType.VirtualNetwork, guestNtwkId, isSourceNat, true, null, false, vpcId, displayIp, false); + return fetchNewPublicIp(dcId, null, null, owner, VlanType.VirtualNetwork, guestNtwkId, isSourceNat, true, null, null, false, vpcId, displayIp, false); } }); if (ip.getState() != State.Allocated) { @@ -1226,7 +1232,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage ip = Transaction.execute(new TransactionCallbackWithException() { @Override public PublicIp doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException { - PublicIp ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, ipaddress, isSystem, null, displayIp, false); + PublicIp ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, ipaddress, null, isSystem, null, displayIp, false); if (ip == null) { InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone diff --git a/server/src/main/java/com/cloud/network/rules/DhcpSubNetRules.java b/server/src/main/java/com/cloud/network/rules/DhcpSubNetRules.java index ed5513795a3..dd12acd8972 100644 --- a/server/src/main/java/com/cloud/network/rules/DhcpSubNetRules.java +++ b/server/src/main/java/com/cloud/network/rules/DhcpSubNetRules.java @@ -123,10 +123,10 @@ public class DhcpSubNetRules extends RuleApplier { IpAddressManager ipAddrMgr = visitor.getVirtualNetworkApplianceFactory().getIpAddrMgr(); if (dc.getNetworkType() == NetworkType.Basic) { routerPublicIP = ipAddrMgr.assignPublicIpAddressFromVlans(_router.getDataCenterId(), vm.getPodIdToDeployIn(), caller, Vlan.VlanType.DirectAttached, - vlanDbIdList, _nic.getNetworkId(), null, false); + vlanDbIdList, _nic.getNetworkId(), null, _nic.getIPv4Gateway(), false); } else { routerPublicIP = ipAddrMgr.assignPublicIpAddressFromVlans(_router.getDataCenterId(), null, caller, Vlan.VlanType.DirectAttached, vlanDbIdList, - _nic.getNetworkId(), null, false); + _nic.getNetworkId(), null, _nic.getIPv4Gateway(), false); } _routerAliasIp = routerPublicIP.getAddress().addr(); @@ -171,4 +171,4 @@ public class DhcpSubNetRules extends RuleApplier { public String getRouterAliasIp() { return _routerAliasIp; } -} \ No newline at end of file +} diff --git a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java index a3b9df8fb1c..ca3505fb680 100755 --- a/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.resource; +import static com.cloud.configuration.ConfigurationManagerImpl.SET_HOST_DOWN_TO_MAINTENANCE; + import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; @@ -192,9 +194,6 @@ import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; import com.google.gson.Gson; - -import static com.cloud.configuration.ConfigurationManagerImpl.SET_HOST_DOWN_TO_MAINTENANCE; - @Component public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ResourceService, Manager { private static final Logger s_logger = Logger.getLogger(ResourceManagerImpl.class); @@ -1249,6 +1248,19 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, return _hostDao.updateResourceState(currentState, event, nextState, host); } + private void handleVmForLastHostOrWithVGpu(final HostVO host, final VMInstanceVO vm) { + // Migration is not supported for VGPU Vms so stop them. + // for the last host in this cluster, destroy SSVM/CPVM and stop all other VMs + if (VirtualMachine.Type.SecondaryStorageVm.equals(vm.getType()) + || VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) { + s_logger.error(String.format("Maintenance: VM is of type %s. Destroying VM %s (ID: %s) immediately instead of migration.", vm.getType().toString(), vm.getInstanceName(), vm.getUuid())); + _haMgr.scheduleDestroy(vm, host.getId()); + return; + } + s_logger.error(String.format("Maintenance: No hosts available for migrations. Scheduling shutdown for VM %s instead of migration.", vm.getUuid())); + _haMgr.scheduleStop(vm, host.getId(), WorkType.ForceStop); + } + private boolean doMaintain(final long hostId) { final HostVO host = _hostDao.findById(hostId); s_logger.info("Maintenance: attempting maintenance of host " + host.getUuid()); @@ -1286,10 +1298,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, for (final VMInstanceVO vm : vms) { if (hosts == null || hosts.isEmpty() || !answer.getMigrate() || _serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.vgpuType.toString()) != null) { - // Migration is not supported for VGPU Vms so stop them. - // for the last host in this cluster, stop all the VMs - s_logger.error("Maintenance: No hosts available for migrations. Scheduling shutdown instead of migrations."); - _haMgr.scheduleStop(vm, hostId, WorkType.ForceStop); + handleVmForLastHostOrWithVGpu(host, vm); } else if (HypervisorType.LXC.equals(host.getHypervisorType()) && VirtualMachine.Type.User.equals(vm.getType())){ //Migration is not supported for LXC Vms. Schedule restart instead. _haMgr.scheduleRestart(vm, false); @@ -1505,7 +1514,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, * on a host. We need to track the various VM states on each run and accordingly transit to the * appropriate state. * - * We change states as follws - + * We change states as follows - * 1. If there are no VMs in running, migrating, starting, stopping, error, unknown states we can move * to maintenance state. Note that there cannot be incoming migrations as the API Call prepare for * maintenance checks incoming migrations before starting. @@ -2449,34 +2458,32 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, s_logger.debug("Deleting Host: " + host.getId() + " Guid:" + host.getGuid()); } - if (forceDestroyStorage) { + final StoragePoolVO storagePool = _storageMgr.findLocalStorageOnHost(host.getId()); + if (forceDestroyStorage && storagePool != null) { // put local storage into mainenance mode, will set all the VMs on // this local storage into stopped state - final StoragePoolVO storagePool = _storageMgr.findLocalStorageOnHost(host.getId()); - if (storagePool != null) { - if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) { - try { - final StoragePool pool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId()); - if (pool == null) { - s_logger.debug("Failed to set primary storage into maintenance mode"); + if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) { + try { + final StoragePool pool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId()); + if (pool == null) { + s_logger.debug("Failed to set primary storage into maintenance mode"); - throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode"); - } - } catch (final Exception e) { - s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString()); - throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e.toString()); + throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode"); } + } catch (final Exception e) { + s_logger.debug("Failed to set primary storage into maintenance mode, due to: " + e.toString()); + throw new UnableDeleteHostException("Failed to set primary storage into maintenance mode, due to: " + e.toString()); } + } - final List vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId()); - for (final VMInstanceVO vm : vmsOnLocalStorage) { - try { - _vmMgr.destroy(vm.getUuid(), false); - } catch (final Exception e) { - final String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); - s_logger.debug(errorMsg, e); - throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); - } + final List vmsOnLocalStorage = _storageMgr.listByStoragePool(storagePool.getId()); + for (final VMInstanceVO vm : vmsOnLocalStorage) { + try { + _vmMgr.destroy(vm.getUuid(), false); + } catch (final Exception e) { + final String errorMsg = "There was an error Destory the vm: " + vm + " as a part of hostDelete id=" + host.getId(); + s_logger.debug(errorMsg, e); + throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); } } } else { @@ -2486,17 +2493,22 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (isForced) { // Stop HA disabled vms and HA enabled vms in Stopping state // Restart HA enabled vms + try { + resourceStateTransitTo(host, ResourceState.Event.DeleteHost, host.getId()); + } catch (final NoTransitionException e) { + s_logger.debug("Cannot transmit host " + host.getId() + " to Disabled state", e); + } for (final VMInstanceVO vm : vms) { - if (!vm.isHaEnabled() || vm.getState() == State.Stopping) { + if ((! HighAvailabilityManager.ForceHA.value() && !vm.isHaEnabled()) || vm.getState() == State.Stopping) { s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + host.getId()); try { - _vmMgr.advanceStop(vm.getUuid(), false); + _haMgr.scheduleStop(vm, host.getId(), WorkType.Stop); } catch (final Exception e) { final String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); s_logger.debug(errorMsg, e); throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); } - } else if (vm.isHaEnabled() && (vm.getState() == State.Running || vm.getState() == State.Starting)) { + } else if ((HighAvailabilityManager.ForceHA.value() || vm.isHaEnabled()) && (vm.getState() == State.Running || vm.getState() == State.Starting)) { s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + host.getId()); _haMgr.scheduleRestart(vm, false); } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index e68f03d2ed6..2e7c8fe49a1 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -2198,7 +2198,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe long dcId = dc.getId(); try { freeAddrs.addAll(_ipAddressMgr.listAvailablePublicIps(dcId, null, vlanDbIds, owner, VlanType.VirtualNetwork, associatedNetworkId, - false, false, false, null, false, cmd.getVpcId(), cmd.isDisplay(), false, false)); // Free + false, false, false, null, null, false, cmd.getVpcId(), cmd.isDisplay(), false, false)); // Free } catch (InsufficientAddressCapacityException e) { s_logger.warn("no free address is found in zone " + dcId); } diff --git a/server/src/main/java/com/cloud/storage/upload/params/TemplateUploadParams.java b/server/src/main/java/com/cloud/storage/upload/params/TemplateUploadParams.java index 9dede2ee5a3..31206ca31b3 100644 --- a/server/src/main/java/com/cloud/storage/upload/params/TemplateUploadParams.java +++ b/server/src/main/java/com/cloud/storage/upload/params/TemplateUploadParams.java @@ -29,10 +29,10 @@ public class TemplateUploadParams extends UploadParamsBase { Long zoneId, Hypervisor.HypervisorType hypervisorType, String chksum, String templateTag, long templateOwnerId, Map details, Boolean sshkeyEnabled, - Boolean isDynamicallyScalable, Boolean isRoutingType) { + Boolean isDynamicallyScalable, Boolean isRoutingType, boolean deployAsIs) { super(userId, name, displayText, bits, passwordEnabled, requiresHVM, isPublic, featured, isExtractable, format, guestOSId, zoneId, hypervisorType, chksum, templateTag, templateOwnerId, details, - sshkeyEnabled, isDynamicallyScalable, isRoutingType); + sshkeyEnabled, isDynamicallyScalable, isRoutingType, deployAsIs); setBootable(true); } } diff --git a/server/src/main/java/com/cloud/storage/upload/params/UploadParamsBase.java b/server/src/main/java/com/cloud/storage/upload/params/UploadParamsBase.java index e5bc1a3c906..60ccc27a48f 100644 --- a/server/src/main/java/com/cloud/storage/upload/params/UploadParamsBase.java +++ b/server/src/main/java/com/cloud/storage/upload/params/UploadParamsBase.java @@ -44,6 +44,7 @@ public abstract class UploadParamsBase implements UploadParams { private boolean sshkeyEnabled; private boolean isDynamicallyScalable; private boolean isRoutingType; + private boolean deployAsIs; UploadParamsBase(long userId, String name, String displayText, Integer bits, boolean passwordEnabled, boolean requiresHVM, @@ -52,7 +53,7 @@ public abstract class UploadParamsBase implements UploadParams { Long zoneId, Hypervisor.HypervisorType hypervisorType, String checksum, String templateTag, long templateOwnerId, Map details, boolean sshkeyEnabled, - boolean isDynamicallyScalable, boolean isRoutingType) { + boolean isDynamicallyScalable, boolean isRoutingType, boolean deployAsIs) { this.userId = userId; this.name = name; this.displayText = displayText; @@ -73,6 +74,7 @@ public abstract class UploadParamsBase implements UploadParams { this.sshkeyEnabled = sshkeyEnabled; this.isDynamicallyScalable = isDynamicallyScalable; this.isRoutingType = isRoutingType; + this.deployAsIs = deployAsIs; } UploadParamsBase(long userId, String name, String displayText, boolean isPublic, boolean isFeatured, @@ -216,7 +218,7 @@ public abstract class UploadParamsBase implements UploadParams { @Override public boolean isDeployAsIs() { - return false; + return deployAsIs; } void setIso(boolean iso) { diff --git a/server/src/main/java/com/cloud/template/TemplateAdapterBase.java b/server/src/main/java/com/cloud/template/TemplateAdapterBase.java index 52628ee2e23..290a895adc0 100644 --- a/server/src/main/java/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/main/java/com/cloud/template/TemplateAdapterBase.java @@ -337,7 +337,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat params.isExtractable(), params.getFormat(), params.getGuestOSId(), zoneList, params.getHypervisorType(), params.getChecksum(), params.isBootable(), params.getTemplateTag(), owner, params.getDetails(), params.isSshKeyEnabled(), params.getImageStoreUuid(), - params.isDynamicallyScalable(), params.isRoutingType() ? TemplateType.ROUTING : TemplateType.USER, params.isDirectDownload(), false); + params.isDynamicallyScalable(), params.isRoutingType() ? TemplateType.ROUTING : TemplateType.USER, params.isDirectDownload(), params.isDeployAsIs()); } private Long getDefaultDeployAsIsGuestOsId() { @@ -358,7 +358,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat BooleanUtils.toBoolean(cmd.isFeatured()), BooleanUtils.toBoolean(cmd.isExtractable()), cmd.getFormat(), osTypeId, cmd.getZoneId(), HypervisorType.getType(cmd.getHypervisor()), cmd.getChecksum(), cmd.getTemplateTag(), cmd.getEntityOwnerId(), cmd.getDetails(), BooleanUtils.toBoolean(cmd.isSshKeyEnabled()), - BooleanUtils.toBoolean(cmd.isDynamicallyScalable()), BooleanUtils.toBoolean(cmd.isRoutingType())); + BooleanUtils.toBoolean(cmd.isDynamicallyScalable()), BooleanUtils.toBoolean(cmd.isRoutingType()), cmd.isDeployAsIs()); return prepareUploadParamsInternal(params); } diff --git a/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java b/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java index 7410f1e6e03..39fa6bb2d67 100644 --- a/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java +++ b/server/src/test/java/com/cloud/ha/HighAvailabilityManagerImplTest.java @@ -44,6 +44,7 @@ import org.mockito.runners.MockitoJUnitRunner; import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; +import com.cloud.consoleproxy.ConsoleProxyManager; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -64,6 +65,7 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.StorageManager; import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.GuestOSDao; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.user.AccountManager; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; @@ -112,6 +114,10 @@ public class HighAvailabilityManagerImplTest { @Mock VolumeOrchestrationService volumeMgr; @Mock + ConsoleProxyManager consoleProxyManager; + @Mock + SecondaryStorageVmManager secondaryStorageVmManager; + @Mock HostVO hostVO; HighAvailabilityManagerImpl highAvailabilityManager; diff --git a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index 85f8bbb803b..20db0fb0fa4 100644 --- a/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/main/java/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -768,6 +768,13 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } public boolean isZoneReady(Map zoneHostInfoMap, long dataCenterId) { + List hosts = _hostDao.listByDataCenterId(dataCenterId); + if (CollectionUtils.isEmpty(hosts)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Zone " + dataCenterId + " has no host available which is enabled and in Up state"); + } + return false; + } ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId); if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) { VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any); diff --git a/systemvm/debian/opt/cloud/bin/configure.py b/systemvm/debian/opt/cloud/bin/configure.py index d0a83abd855..8fdf134b506 100755 --- a/systemvm/debian/opt/cloud/bin/configure.py +++ b/systemvm/debian/opt/cloud/bin/configure.py @@ -1070,6 +1070,7 @@ def main(argv): config.address().process() databag_map = OrderedDict([("guest_network", {"process_iptables": True, "executor": []}), + ("ip_aliases", {"process_iptables": True, "executor": []}), ("vm_password", {"process_iptables": False, "executor": [CsPassword("vmpassword", config)]}), ("vm_metadata", {"process_iptables": False, "executor": [CsVmMetadata('vmdata', config)]}), ("network_acl", {"process_iptables": True, "executor": []}), diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index 14432fb6a39..e0b3772b5f3 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -869,7 +869,7 @@ class VirtualMachine: if hostid: cmd.hostid = hostid if migrateto: - migrateto = [] + cmd.migrateto = [] for volume, pool in list(migrateto.items()): cmd.migrateto.append({ 'volume': volume, diff --git a/ui/package.json b/ui/package.json index fcc561fb6e3..3879ee92a6c 100644 --- a/ui/package.json +++ b/ui/package.json @@ -24,9 +24,11 @@ "url": "https://github.com/apache/cloudstack/issues" }, "scripts": { + "prebuild": "./prebuild.sh", "start": "vue-cli-service lint --no-fix && vue-cli-service serve", "serve": "vue-cli-service lint --no-fix && vue-cli-service serve", "build": "vue-cli-service build", + "postbuild": "./postbuild.sh", "lint": "vue-cli-service lint", "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'", "test:unit": "vue-cli-service test:unit" diff --git a/ui/postbuild.sh b/ui/postbuild.sh new file mode 100755 index 00000000000..ab7734f3838 --- /dev/null +++ b/ui/postbuild.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +DIR=$(dirname $0) +configFile="$DIR/public/config.json" +tmpFile="$DIR/public/config.json.tmp" +echo "Post-build: removing all docHelp suffixes in ${configFile}" + +node > ${tmpFile} < ${tmpFile} < 0) { for (var key in docHelpMappings) { - if (docHelp.includes(key)) { + if (docHelp.includes(key) && docHelp !== docHelpMappings[key]) { docHelp = docHelp.replace(key, docHelpMappings[key]) break } diff --git a/ui/src/views/infra/network/IpRangesTabGuest.vue b/ui/src/views/infra/network/IpRangesTabGuest.vue index 58e1e659215..29a62ff8e8b 100644 --- a/ui/src/views/infra/network/IpRangesTabGuest.vue +++ b/ui/src/views/infra/network/IpRangesTabGuest.vue @@ -149,7 +149,6 @@ export default { page: this.page, pagesize: this.pageSize }).then(response => { - console.log(response) this.items = response.listnetworksresponse.network ? response.listnetworksresponse.network : [] this.total = response.listnetworksresponse.count || 0 }).catch(error => { diff --git a/ui/src/views/infra/network/IpRangesTabPublic.vue b/ui/src/views/infra/network/IpRangesTabPublic.vue index 3d96b416f01..9564ea1683f 100644 --- a/ui/src/views/infra/network/IpRangesTabPublic.vue +++ b/ui/src/views/infra/network/IpRangesTabPublic.vue @@ -34,20 +34,20 @@ :rowKey="record => record.id" :pagination="false" > -