mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Merge remote-tracking branch 'apache/4.15'
Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
commit
426f14b6ed
@ -37,6 +37,7 @@ public abstract class Command {
|
||||
@LogLevel(Log4jLevel.Trace)
|
||||
protected Map<String, String> contextMap = new HashMap<String, String>();
|
||||
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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ import java.util.List;
|
||||
*/
|
||||
public interface HighAvailabilityManager extends Manager {
|
||||
|
||||
ConfigKey<Boolean> ForceHA = new ConfigKey<>("Advanced", Boolean.class, "force.ha", "false",
|
||||
public ConfigKey<Boolean> ForceHA = new ConfigKey<>("Advanced", Boolean.class, "force.ha", "false",
|
||||
"Force High-Availability to happen even if the VM says no.", true, Cluster);
|
||||
|
||||
ConfigKey<Integer> HAWorkers = new ConfigKey<>("Advanced", Integer.class, "ha.workers", "5",
|
||||
|
||||
@ -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<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem)
|
||||
PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, String requestedGateway, boolean isSystem)
|
||||
throws InsufficientAddressCapacityException;
|
||||
|
||||
PublicIp getAvailablePublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> 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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<String, String> 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<CommandResult> callback) {
|
||||
DeleteCommand cmd = new DeleteCommand(data.getTO());
|
||||
|
||||
cmd.setBypassHostMaintenance(commandCanBypassHostMaintenance(data));
|
||||
CommandResult result = new CommandResult();
|
||||
try {
|
||||
EndPoint ep = null;
|
||||
|
||||
@ -163,13 +163,15 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> 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<HostJoinVO, Long> 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));
|
||||
}
|
||||
|
||||
|
||||
@ -1006,6 +1006,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
||||
}
|
||||
|
||||
public boolean isZoneReady(Map<Long, ZoneHostInfo> zoneHostInfoMap, long dataCenterId) {
|
||||
List <HostVO> 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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -477,6 +477,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
|
||||
SearchBuilder<VlanVO> 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<VlanVO> 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<PodVlanMapVO> 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<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem)
|
||||
public PublicIp assignPublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> 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<Long> 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<Long> 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<Long> 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<IPAddressVO> addrs = listAvailablePublicIps(dcId, podId, vlanDbIds, owner, vlanUse, guestNetworkId, sourceNat, assign, allocate, requestedIp, isSystem, vpcId, displayIp, forSystemVms, true);
|
||||
List<IPAddressVO> 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<IPAddressVO> listAvailablePublicIps(final long dcId, final Long podId, final List<Long> 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<List<IPAddressVO>, 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<PublicIp, InsufficientAddressCapacityException>() {
|
||||
@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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<VMInstanceVO> 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<VMInstanceVO> 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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -768,6 +768,13 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
||||
}
|
||||
|
||||
public boolean isZoneReady(Map<Long, ZoneHostInfo> zoneHostInfoMap, long dataCenterId) {
|
||||
List <HostVO> 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);
|
||||
|
||||
@ -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": []}),
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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"
|
||||
|
||||
36
ui/postbuild.sh
Executable file
36
ui/postbuild.sh
Executable file
@ -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} <<EOF
|
||||
// Read config
|
||||
var data = require('${configFile}');
|
||||
|
||||
// Clear docHelpMappings
|
||||
data.docHelpMappings = {};
|
||||
|
||||
// Output config
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
|
||||
EOF
|
||||
|
||||
mv ${tmpFile} ${configFile}
|
||||
47
ui/prebuild.sh
Executable file
47
ui/prebuild.sh
Executable file
@ -0,0 +1,47 @@
|
||||
#!/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 "Pre-build: list all docHelp suffixes in ${configFile}"
|
||||
for m in $(grep "docHelp: '" -R ./src | sed "s/^.*: '//g" | sed "s/',//g" | sort | uniq); do
|
||||
docHelpMappings+="${m},"
|
||||
done;
|
||||
|
||||
node > ${tmpFile} <<EOF
|
||||
// Read config
|
||||
var data = require('${configFile}');
|
||||
|
||||
// Add docHelpMappings
|
||||
var suffixes = '${docHelpMappings}';
|
||||
suffixes = suffixes.split(',');
|
||||
var mappings = {}
|
||||
for (const suffix of suffixes) {
|
||||
if (suffix) {
|
||||
mappings[suffix] = suffix;
|
||||
}
|
||||
}
|
||||
data.docHelpMappings = mappings;
|
||||
|
||||
// Output config
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
|
||||
EOF
|
||||
|
||||
mv ${tmpFile} ${configFile}
|
||||
6
ui/public/config.json
vendored
6
ui/public/config.json
vendored
@ -6,8 +6,8 @@
|
||||
"logo": "assets/logo.svg",
|
||||
"banner": "assets/banner.svg",
|
||||
"error": {
|
||||
"404": "assets/404.png",
|
||||
"403": "assets/403.png",
|
||||
"404": "assets/404.png",
|
||||
"500": "assets/500.png"
|
||||
},
|
||||
"theme": {
|
||||
@ -46,7 +46,7 @@
|
||||
"jp": "label.japanese.keyboard",
|
||||
"sc": "label.simplified.chinese.keyboard"
|
||||
},
|
||||
"docHelpMappings": {},
|
||||
"plugins": [],
|
||||
"basicZoneEnabled": true
|
||||
"basicZoneEnabled": true,
|
||||
"docHelpMappings": {}
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ export default {
|
||||
icon: 'cloud-upload',
|
||||
docHelp: 'adminguide/virtual_machines.html#backup-offerings',
|
||||
permission: ['listBackupOfferings', 'listInfrastructure'],
|
||||
columns: ['name', 'description', 'zoneid'],
|
||||
columns: ['name', 'description', 'zonename'],
|
||||
details: ['name', 'id', 'description', 'externalid', 'zone', 'created'],
|
||||
actions: [{
|
||||
api: 'importBackupOffering',
|
||||
|
||||
@ -175,7 +175,7 @@ export const configUtilPlugin = {
|
||||
if (docHelp && docHelpMappings &&
|
||||
docHelpMappings.constructor === Object && Object.keys(docHelpMappings).length > 0) {
|
||||
for (var key in docHelpMappings) {
|
||||
if (docHelp.includes(key)) {
|
||||
if (docHelp.includes(key) && docHelp !== docHelpMappings[key]) {
|
||||
docHelp = docHelp.replace(key, docHelpMappings[key])
|
||||
break
|
||||
}
|
||||
|
||||
@ -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 => {
|
||||
|
||||
@ -34,20 +34,20 @@
|
||||
:rowKey="record => record.id"
|
||||
:pagination="false"
|
||||
>
|
||||
<template slot="account" slot-scope="record">
|
||||
<template slot="account" slot-scope="record" v-if="!basicGuestNetwork">
|
||||
<a-button @click="() => handleOpenAccountModal(record)">{{ `[${record.domain}] ${record.account === undefined ? '' : record.account}` }}</a-button>
|
||||
</template>
|
||||
<template slot="actions" slot-scope="record">
|
||||
<div class="actions">
|
||||
<tooltip-button
|
||||
v-if="record.account === 'system'"
|
||||
v-if="record.account === 'system' && !basicGuestNetwork"
|
||||
tooltipPlacement="bottom"
|
||||
:tooltip="$t('label.add.account')"
|
||||
icon="user-add"
|
||||
@click="() => handleOpenAddAccountModal(record)"
|
||||
:disabled="!('dedicatePublicIpRange' in $store.getters.apis)" />
|
||||
<tooltip-button
|
||||
v-else
|
||||
v-if="record.account !== 'system' && !basicGuestNetwork"
|
||||
tooltipPlacement="bottom"
|
||||
:tooltip="$t('label.release.account')"
|
||||
icon="user-delete"
|
||||
@ -137,6 +137,16 @@
|
||||
layout="vertical"
|
||||
class="form"
|
||||
>
|
||||
<a-form-item :label="$t('label.podid')" class="form__item" v-if="basicGuestNetwork">
|
||||
<a-select
|
||||
autoFocus
|
||||
v-decorator="['podid', {
|
||||
rules: [{ required: true, message: `${$t('label.required')}` }]
|
||||
}]"
|
||||
>
|
||||
<a-select-option v-for="pod in pods" :key="pod.id" :value="pod.id">{{ pod.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('label.gateway')" class="form__item">
|
||||
<a-input
|
||||
autoFocus
|
||||
@ -148,7 +158,7 @@
|
||||
v-decorator="['netmask', { rules: [{ required: true, message: `${$t('label.required')}` }] }]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-form-item :label="$t('label.vlan')" class="form__item">
|
||||
<a-form-item :label="$t('label.vlan')" class="form__item" v-if="!basicGuestNetwork">
|
||||
<a-input
|
||||
v-decorator="['vlan']">
|
||||
</a-input>
|
||||
@ -163,11 +173,11 @@
|
||||
v-decorator="['endip', { rules: [{ required: true, message: `${$t('label.required')}` }] }]">
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<div class="form__item">
|
||||
<div class="form__item" v-if="!basicGuestNetwork">
|
||||
<div style="color: black;">{{ $t('label.set.reservation') }}</div>
|
||||
<a-switch @change="handleShowAccountFields"></a-switch>
|
||||
</div>
|
||||
<div v-if="showAccountFields" style="margin-top: 20px;">
|
||||
<div v-if="showAccountFields && !basicGuestNetwork" style="margin-top: 20px;">
|
||||
<div v-html="$t('label.set.reservation.desc')"></div>
|
||||
<a-form-item :label="$t('label.system.vms')" class="form__item">
|
||||
<a-switch v-decorator="['forsystemvms']"></a-switch>
|
||||
@ -214,6 +224,10 @@ export default {
|
||||
network: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
basicGuestNetwork: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@ -232,6 +246,8 @@ export default {
|
||||
domainsLoading: false,
|
||||
addIpRangeModal: false,
|
||||
showAccountFields: false,
|
||||
podsLoading: false,
|
||||
pods: [],
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
columns: [
|
||||
@ -255,10 +271,6 @@ export default {
|
||||
title: this.$t('label.endip'),
|
||||
dataIndex: 'endip'
|
||||
},
|
||||
{
|
||||
title: this.$t('label.account'),
|
||||
scopedSlots: { customRender: 'account' }
|
||||
},
|
||||
{
|
||||
title: this.$t('label.action'),
|
||||
scopedSlots: { customRender: 'actions' }
|
||||
@ -270,6 +282,19 @@ export default {
|
||||
this.form = this.$form.createForm(this)
|
||||
},
|
||||
created () {
|
||||
if (!this.basicGuestNetwork) {
|
||||
this.columns.splice(5, 0,
|
||||
{
|
||||
title: this.$t('label.account'),
|
||||
scopedSlots: { customRender: 'account' }
|
||||
}
|
||||
)
|
||||
} else {
|
||||
this.columns.unshift({
|
||||
title: this.$t('label.pod'),
|
||||
dataIndex: 'podname'
|
||||
})
|
||||
}
|
||||
this.fetchData()
|
||||
},
|
||||
watch: {
|
||||
@ -296,6 +321,7 @@ export default {
|
||||
}).finally(() => {
|
||||
this.componentLoading = false
|
||||
})
|
||||
this.fetchPods()
|
||||
},
|
||||
fetchDomains () {
|
||||
this.domainsLoading = true
|
||||
@ -314,6 +340,22 @@ export default {
|
||||
this.domainsLoading = false
|
||||
})
|
||||
},
|
||||
fetchPods () {
|
||||
this.podsLoading = true
|
||||
api('listPods', {
|
||||
zoneid: this.resource.zoneid,
|
||||
page: this.page,
|
||||
pagesize: this.pageSize
|
||||
}).then(response => {
|
||||
this.total = response.listpodsresponse.count || 0
|
||||
this.pods = response.listpodsresponse.pod ? response.listpodsresponse.pod : []
|
||||
}).catch(error => {
|
||||
console.log(error)
|
||||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
this.podsLoading = false
|
||||
})
|
||||
},
|
||||
handleAddAccount () {
|
||||
this.domainsLoading = true
|
||||
|
||||
@ -384,18 +426,25 @@ export default {
|
||||
|
||||
this.componentLoading = true
|
||||
this.addIpRangeModal = false
|
||||
api('createVlanIpRange', {
|
||||
zoneId: this.resource.zoneid,
|
||||
vlan: values.vlan,
|
||||
var params = {
|
||||
gateway: values.gateway,
|
||||
netmask: values.netmask,
|
||||
startip: values.startip,
|
||||
endip: values.endip,
|
||||
forsystemvms: values.forsystemvms,
|
||||
account: values.forsystemvms ? null : values.account,
|
||||
domainid: values.forsystemvms ? null : values.domain,
|
||||
forvirtualnetwork: true
|
||||
}).then(() => {
|
||||
endip: values.endip
|
||||
}
|
||||
if (!this.basicGuestNetwork) {
|
||||
params.zoneId = this.resource.zoneid
|
||||
params.vlan = values.vlan
|
||||
params.forsystemvms = values.forsystemvms
|
||||
params.account = values.forsystemvms ? null : values.account
|
||||
params.domainid = values.forsystemvms ? null : values.domain
|
||||
params.forvirtualnetwork = true
|
||||
} else {
|
||||
params.forvirtualnetwork = false
|
||||
params.podid = values.podid
|
||||
params.networkid = this.network.id
|
||||
}
|
||||
api('createVlanIpRange', params).then(() => {
|
||||
this.$notification.success({
|
||||
message: this.$t('message.success.add.iprange')
|
||||
})
|
||||
|
||||
@ -26,9 +26,17 @@
|
||||
<div><strong>{{ $t(type) }}</strong></div>
|
||||
<div>{{ item[type] || $t('label.network.label.display.for.blank.value') }}</div>
|
||||
</div>
|
||||
<div v-if="item.traffictype === 'Guest'">
|
||||
<div v-if="item.traffictype === 'Guest' && networkType === 'Advanced'">
|
||||
<a-divider />
|
||||
<IpRangesTabGuest :resource="resource" :loading="loading" />
|
||||
<IpRangesTabGuest :resource="resource" :loading="loading"/>
|
||||
</div>
|
||||
<div v-if="item.traffictype === 'Guest' && networkType === 'Basic'">
|
||||
<a-divider />
|
||||
<IpRangesTabPublic
|
||||
:resource="resource"
|
||||
:loading="loading"
|
||||
:network="guestNetwork"
|
||||
:basicGuestNetwork="networkType === 'Basic' && item.traffictype === 'Guest'"/>
|
||||
</div>
|
||||
<div v-if="item.traffictype === 'Public'">
|
||||
<div style="margin-bottom: 10px;">
|
||||
@ -40,7 +48,7 @@
|
||||
<div>{{ publicNetwork.broadcastdomaintype }}</div>
|
||||
</div>
|
||||
<a-divider />
|
||||
<IpRangesTabPublic :resource="resource" :loading="loading" :network="publicNetwork" />
|
||||
<IpRangesTabPublic :resource="resource" :loading="loading" :network="publicNetwork" :basicGuestNetwork="false" />
|
||||
</div>
|
||||
<div v-if="item.traffictype === 'Management'">
|
||||
<a-divider />
|
||||
@ -86,6 +94,8 @@ export default {
|
||||
return {
|
||||
traffictypes: [],
|
||||
publicNetwork: {},
|
||||
guestNetwork: {},
|
||||
networkType: 'Advanced',
|
||||
fetchLoading: false
|
||||
}
|
||||
},
|
||||
@ -102,7 +112,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
async fetchData () {
|
||||
this.fetchLoading = true
|
||||
api('listTrafficTypes', { physicalnetworkid: this.resource.id }).then(json => {
|
||||
this.traffictypes = json.listtraffictypesresponse.traffictype
|
||||
@ -111,7 +121,6 @@ export default {
|
||||
}).finally(() => {
|
||||
this.fetchLoading = false
|
||||
})
|
||||
|
||||
this.fetchLoading = true
|
||||
api('listNetworks', {
|
||||
listAll: true,
|
||||
@ -129,6 +138,42 @@ export default {
|
||||
}).finally(() => {
|
||||
this.fetchLoading = false
|
||||
})
|
||||
await this.fetchZones()
|
||||
if (this.networkType === 'Basic') {
|
||||
this.fetchGuestNetwork()
|
||||
}
|
||||
},
|
||||
fetchZones () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.fetchLoading = true
|
||||
api('listZones', { id: this.resource.zoneid }).then(json => {
|
||||
const zone = json.listzonesresponse.zone || []
|
||||
this.networkType = zone[0].networktype
|
||||
resolve(this.networkType)
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.fetchLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
fetchGuestNetwork () {
|
||||
api('listNetworks', {
|
||||
listAll: true,
|
||||
trafficType: 'Guest',
|
||||
zoneId: this.resource.zoneid
|
||||
}).then(json => {
|
||||
if (json.listnetworksresponse?.network?.length > 0) {
|
||||
this.guestNetwork = json.listnetworksresponse.network[0]
|
||||
} else {
|
||||
this.guestNetwork = {}
|
||||
}
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
this.fetchLoading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,17 @@
|
||||
:form="form"
|
||||
@submit="handleSubmit"
|
||||
layout="vertical">
|
||||
<a-form-item :label="$t('label.podid')" v-if="pods && pods.length > 0">
|
||||
<a-select
|
||||
autoFocus
|
||||
v-decorator="['podid', {
|
||||
initialValue: this.pods && this.pods.length > 0 ? this.pods[0].id : '',
|
||||
rules: [{ required: true, message: `${$t('label.required')}` }]
|
||||
}]"
|
||||
>
|
||||
<a-select-option v-for="pod in pods" :key="pod.id" :value="pod.id">{{ pod.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<span slot="label">
|
||||
{{ $t('label.gateway') }}
|
||||
@ -195,6 +206,8 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
zone: {},
|
||||
pods: [],
|
||||
ipV4Regex: /^(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)\.(25[0-5]|2[0-4]\d|[01]?\d\d?)$/i,
|
||||
ipV6Regex: /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i
|
||||
}
|
||||
@ -206,8 +219,41 @@ export default {
|
||||
this.apiConfig.params.forEach(param => {
|
||||
this.apiParams[param.name] = param
|
||||
})
|
||||
this.fetchData()
|
||||
},
|
||||
methods: {
|
||||
async fetchData () {
|
||||
await this.fetchZone()
|
||||
if (this.zone.networktype === 'Basic') {
|
||||
this.fetchPods()
|
||||
}
|
||||
},
|
||||
fetchZone () {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
api('listZones', { id: this.resource.zoneid }).then(json => {
|
||||
this.zone = json.listzonesresponse.zone[0] || {}
|
||||
resolve(this.zone)
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
reject(error)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
fetchPods () {
|
||||
this.loading = true
|
||||
api('listPods', {
|
||||
zoneid: this.resource.zoneid
|
||||
}).then(response => {
|
||||
this.pods = response.listpodsresponse.pod ? response.listpodsresponse.pod : []
|
||||
}).catch(error => {
|
||||
this.$notifyError(error)
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
handleSubmit (e) {
|
||||
e.preventDefault()
|
||||
|
||||
@ -219,6 +265,9 @@ export default {
|
||||
const params = {}
|
||||
params.forVirtualNetwork = false
|
||||
params.networkid = this.resource.id
|
||||
if (values.podid) {
|
||||
params.podid = values.podid
|
||||
}
|
||||
params.gateway = values.gateway
|
||||
params.netmask = values.netmask
|
||||
params.startip = values.startip
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user