Merge remote-tracking branch 'apache/4.15'

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2021-05-18 15:19:20 +05:30
commit 426f14b6ed
35 changed files with 515 additions and 182 deletions

View File

@ -37,6 +37,7 @@ public abstract class Command {
@LogLevel(Log4jLevel.Trace) @LogLevel(Log4jLevel.Trace)
protected Map<String, String> contextMap = new HashMap<String, String>(); protected Map<String, String> contextMap = new HashMap<String, String>();
private int wait; //in second private int wait; //in second
private boolean bypassHostMaintenance = false;
protected Command() { protected Command() {
this.wait = 0; this.wait = 0;
@ -74,6 +75,14 @@ public abstract class Command {
return true; return true;
} }
public boolean isBypassHostMaintenance() {
return bypassHostMaintenance;
}
public void setBypassHostMaintenance(boolean bypassHostMaintenance) {
this.bypassHostMaintenance = bypassHostMaintenance;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;

View File

@ -114,6 +114,7 @@ public enum ResourceState {
s_fsm.addTransition(ResourceState.Enabled, Event.Disable, ResourceState.Disabled); s_fsm.addTransition(ResourceState.Enabled, Event.Disable, ResourceState.Disabled);
s_fsm.addTransition(ResourceState.Enabled, Event.AdminAskMaintenance, ResourceState.PrepareForMaintenance); s_fsm.addTransition(ResourceState.Enabled, Event.AdminAskMaintenance, ResourceState.PrepareForMaintenance);
s_fsm.addTransition(ResourceState.Enabled, Event.InternalEnterMaintenance, ResourceState.Maintenance); 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.Enable, ResourceState.Enabled);
s_fsm.addTransition(ResourceState.Disabled, Event.Disable, ResourceState.Disabled); s_fsm.addTransition(ResourceState.Disabled, Event.Disable, ResourceState.Disabled);
s_fsm.addTransition(ResourceState.Disabled, Event.InternalCreated, ResourceState.Disabled); s_fsm.addTransition(ResourceState.Disabled, Event.InternalCreated, ResourceState.Disabled);

View File

@ -89,6 +89,11 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd {
@Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.") @Parameter(name = ApiConstants.TEMPLATE_TAG, type = CommandType.STRING, description = "the tag for this template.")
private String templateTag; 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() { public String getDisplayText() {
return displayText; return displayText;
} }
@ -153,6 +158,11 @@ public class GetUploadParamsForTemplateCmd extends AbstractGetUploadParamsCmd {
return templateTag; return templateTag;
} }
public boolean isDeployAsIs() {
return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor) &&
Boolean.TRUE.equals(deployAsIs);
}
@Override @Override
public void execute() throws ServerApiException { public void execute() throws ServerApiException {
validateRequest(); validateRequest();

View File

@ -347,10 +347,6 @@ public class HostResponse extends BaseResponse {
this.cpuSpeed = cpuSpeed; this.cpuSpeed = cpuSpeed;
} }
public String getCpuAllocated() {
return cpuAllocated;
}
public void setCpuAllocated(String cpuAllocated) { public void setCpuAllocated(String cpuAllocated) {
this.cpuAllocated = cpuAllocated; this.cpuAllocated = cpuAllocated;
} }
@ -622,6 +618,10 @@ public class HostResponse extends BaseResponse {
return cpuUsed; return cpuUsed;
} }
public String getCpuAllocated() {
return cpuAllocated;
}
public Double getAverageLoad() { public Double getAverageLoad() {
return cpuloadaverage; return cpuloadaverage;
} }

View File

@ -32,7 +32,7 @@ import java.util.List;
*/ */
public interface HighAvailabilityManager extends Manager { 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); "Force High-Availability to happen even if the VM says no.", true, Cluster);
ConfigKey<Integer> HAWorkers = new ConfigKey<>("Advanced", Integer.class, "ha.workers", "5", ConfigKey<Integer> HAWorkers = new ConfigKey<>("Advanced", Integer.class, "ha.workers", "5",

View File

@ -185,7 +185,7 @@ public interface IpAddressManager {
IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp, String ipaddress) IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone, Boolean displayIp, String ipaddress)
throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; 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; throws InsufficientAddressCapacityException;
PublicIp getAvailablePublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem) 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 assign,
final boolean allocate, final boolean allocate,
final String requestedIp, final String requestedIp,
final String requestedGateway,
final boolean isSystem, final boolean isSystem,
final Long vpcId, final Long vpcId,
final Boolean displayIp, final Boolean displayIp,

View File

@ -31,10 +31,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; 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 org.apache.cloudstack.agent.lb.SetupMSListCommand;
import com.cloud.agent.api.RollingMaintenanceCommand;
import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.log4j.Logger; 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.Command;
import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.MigrateCommand; 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.ModifyTargetsCommand;
import com.cloud.agent.api.PingTestCommand; import com.cloud.agent.api.PingTestCommand;
import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.PvlanSetupCommand;
import com.cloud.agent.api.ReadyCommand; import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RollingMaintenanceCommand;
import com.cloud.agent.api.SetupCommand; import com.cloud.agent.api.SetupCommand;
import com.cloud.agent.api.ShutdownCommand; import com.cloud.agent.api.ShutdownCommand;
import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StartCommand;
@ -167,7 +167,7 @@ public abstract class AgentAttache {
if (_maintenance) { if (_maintenance) {
for (final Command cmd : cmds) { 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); throw new AgentUnavailableException("Unable to send " + cmd.getClass().toString() + " because agent " + _name + " is in maintenance mode", _id);
} }
} }

View File

@ -535,6 +535,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
advanceExpunge(vm); 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 { protected void advanceExpunge(VMInstanceVO vm) throws ResourceUnavailableException, OperationTimedoutException, ConcurrentOperationException {
if (vm == null || vm.getRemoved() != null) { if (vm == null || vm.getRemoved() != null) {
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
@ -581,6 +586,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
final Commands cmds = new Commands(Command.OnError.Stop); final Commands cmds = new Commands(Command.OnError.Stop);
for (final Command volumeExpungeCommand : volumeExpungeCommands) { for (final Command volumeExpungeCommand : volumeExpungeCommands) {
volumeExpungeCommand.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm));
cmds.addCommand(volumeExpungeCommand); cmds.addCommand(volumeExpungeCommand);
} }
@ -622,10 +628,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
if (hostId != null) { if (hostId != null) {
final Commands cmds = new Commands(Command.OnError.Stop); final Commands cmds = new Commands(Command.OnError.Stop);
for (final Command command : finalizeExpungeCommands) { for (final Command command : finalizeExpungeCommands) {
command.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm));
cmds.addCommand(command); cmds.addCommand(command);
} }
if (nicExpungeCommands != null) { if (nicExpungeCommands != null) {
for (final Command command : nicExpungeCommands) { for (final Command command : nicExpungeCommands) {
command.setBypassHostMaintenance(expungeCommandCanBypassHostMaintenance(vm));
cmds.addCommand(command); 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" 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())); , 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() && HaVmRestartHostUp.value()
&& vm.getHypervisorType() != HypervisorType.VMware && vm.getHypervisorType() != HypervisorType.VMware
&& vm.getHypervisorType() != HypervisorType.Hyperv) { && vm.getHypervisorType() != HypervisorType.Hyperv) {

View File

@ -264,9 +264,6 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.valueIn(clusterId); final Double memoryThreshold = AlertManager.MemoryCapacityThreshold.valueIn(clusterId);
final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.valueIn(clusterId); final Float cpuDisableThreshold = DeploymentClusterPlanner.ClusterCPUCapacityDisableThreshold.valueIn(clusterId);
final Float memoryDisableThreshold = DeploymentClusterPlanner.ClusterMemoryCapacityDisableThreshold.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 upInstances = 0L;
Long totalInstances = 0L; Long totalInstances = 0L;
@ -283,11 +280,11 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
} }
metricsResponse.setPowerState(hostResponse.getOutOfBandManagementResponse().getPowerState()); metricsResponse.setPowerState(hostResponse.getOutOfBandManagementResponse().getPowerState());
metricsResponse.setInstances(upInstances, totalInstances); 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.setCpuUsed(hostResponse.getCpuUsed(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed());
metricsResponse.setCpuAllocated(hostResponse.getCpuAllocated(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed()); metricsResponse.setCpuAllocated(hostResponse.getCpuAllocated(), hostResponse.getCpuNumber(), hostResponse.getCpuSpeed());
metricsResponse.setLoadAverage(hostResponse.getAverageLoad()); metricsResponse.setLoadAverage(hostResponse.getAverageLoad());
metricsResponse.setMemTotal(hostResponse.getMemoryTotal(), memoryOvercommitRatio); metricsResponse.setMemTotal(hostResponse.getMemoryTotal());
metricsResponse.setMemAllocated(hostResponse.getMemoryAllocated()); metricsResponse.setMemAllocated(hostResponse.getMemoryAllocated());
metricsResponse.setMemUsed(hostResponse.getMemoryUsed()); metricsResponse.setMemUsed(hostResponse.getMemoryUsed());
metricsResponse.setNetworkRead(hostResponse.getNetworkKbsRead()); metricsResponse.setNetworkRead(hostResponse.getNetworkKbsRead());
@ -295,13 +292,13 @@ public class MetricsServiceImpl extends ComponentLifecycleBase implements Metric
// CPU thresholds // CPU thresholds
metricsResponse.setCpuUsageThreshold(hostResponse.getCpuUsed(), cpuThreshold); metricsResponse.setCpuUsageThreshold(hostResponse.getCpuUsed(), cpuThreshold);
metricsResponse.setCpuUsageDisableThreshold(hostResponse.getCpuUsed(), cpuDisableThreshold); metricsResponse.setCpuUsageDisableThreshold(hostResponse.getCpuUsed(), cpuDisableThreshold);
metricsResponse.setCpuAllocatedThreshold(hostResponse.getCpuAllocated(), cpuOvercommitRatio, cpuThreshold); metricsResponse.setCpuAllocatedThreshold(hostResponse.getCpuAllocated(), cpuThreshold);
metricsResponse.setCpuAllocatedDisableThreshold(hostResponse.getCpuAllocated(), cpuOvercommitRatio, cpuDisableThreshold); metricsResponse.setCpuAllocatedDisableThreshold(hostResponse.getCpuAllocated(), cpuDisableThreshold);
// Memory thresholds // Memory thresholds
metricsResponse.setMemoryUsageThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryThreshold); metricsResponse.setMemoryUsageThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryThreshold);
metricsResponse.setMemoryUsageDisableThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryDisableThreshold); metricsResponse.setMemoryUsageDisableThreshold(hostResponse.getMemoryUsed(), hostResponse.getMemoryTotal(), memoryDisableThreshold);
metricsResponse.setMemoryAllocatedThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryOvercommitRatio, memoryThreshold); metricsResponse.setMemoryAllocatedThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryThreshold);
metricsResponse.setMemoryAllocatedDisableThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryOvercommitRatio, memoryDisableThreshold); metricsResponse.setMemoryAllocatedDisableThreshold(hostResponse.getMemoryAllocated(), hostResponse.getMemoryTotal(), memoryDisableThreshold);
metricsResponses.add(metricsResponse); metricsResponses.add(metricsResponse);
} }
return metricsResponses; return metricsResponses;

View File

@ -17,14 +17,15 @@
package org.apache.cloudstack.response; package org.apache.cloudstack.response;
import com.cloud.serializer.Param; import java.text.DecimalFormat;
import com.cloud.utils.exception.CloudRuntimeException; import java.text.ParseException;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement; import org.apache.cloudstack.outofbandmanagement.OutOfBandManagement;
import java.text.DecimalFormat; import com.cloud.serializer.Param;
import java.text.ParseException; import com.cloud.utils.exception.CloudRuntimeException;
import com.google.gson.annotations.SerializedName;
public class HostMetricsResponse extends HostResponse { public class HostMetricsResponse extends HostResponse {
@SerializedName("powerstate") @SerializedName("powerstate")
@ -113,9 +114,9 @@ public class HostMetricsResponse extends HostResponse {
} }
} }
public void setCpuTotal(final Integer cpuNumber, final Long cpuSpeed, final Double overcommitRatio) { public void setCpuTotal(final Integer cpuNumber, final Long cpuSpeed) {
if (cpuNumber != null && cpuSpeed != null && overcommitRatio != null) { if (cpuNumber != null && cpuSpeed != null) {
this.cpuTotal = String.format("%.2f Ghz (x %.1f)", cpuNumber * cpuSpeed / 1000.0, overcommitRatio); 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) { public void setMemTotal(final Long memTotal) {
if (memTotal != null && overcommitRatio != null) { if (memTotal != null) {
this.memTotal = String.format("%.2f GB (x %.1f)", memTotal / (1024.0 * 1024.0 * 1024.0), overcommitRatio); 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) { public void setCpuAllocatedThreshold(final String cpuAllocated, final Double threshold) {
if (cpuAllocated != null && overCommitRatio != null && threshold != null) { if (cpuAllocated != null && threshold != null) {
this.cpuAllocatedThresholdExceeded = parseCPU(cpuAllocated) > (100.0 * threshold * overCommitRatio); this.cpuAllocatedThresholdExceeded = Double.valueOf(cpuAllocated.replace("%", "")) > (100.0 * threshold );
} }
} }
public void setCpuAllocatedDisableThreshold(final String cpuAllocated, final Double overCommitRatio, final Float threshold) { public void setCpuAllocatedDisableThreshold(final String cpuAllocated, final Float threshold) {
if (cpuAllocated != null && overCommitRatio != null && threshold != null) { if (cpuAllocated != null && threshold != null) {
this.cpuAllocatedDisableThresholdExceeded = parseCPU(cpuAllocated) > (100.0 * threshold * overCommitRatio); 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) { public void setMemoryAllocatedThreshold(final Long memAllocated, final Long memTotal, final Double threshold) {
if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null) { if (memAllocated != null && memTotal != null && threshold != null) {
this.memoryAllocatedThresholdExceeded = memAllocated > (memTotal * threshold * overCommitRatio); this.memoryAllocatedThresholdExceeded = memAllocated > (memTotal * threshold);
} }
} }
public void setMemoryAllocatedDisableThreshold(final Long memAllocated, final Long memTotal, final Double overCommitRatio, final Float threshold) { public void setMemoryAllocatedDisableThreshold(final Long memAllocated, final Long memTotal, final Float threshold) {
if (memAllocated != null && memTotal != null && overCommitRatio != null && threshold != null) { if (memAllocated != null && memTotal != null && threshold != null) {
this.memoryAllocatedDisableThresholdExceeded = memAllocated > (memTotal * threshold * overCommitRatio); this.memoryAllocatedDisableThresholdExceeded = memAllocated > (memTotal * threshold);
} }
} }

View File

@ -18,14 +18,14 @@
*/ */
package org.apache.cloudstack.storage.datastore.driver; package org.apache.cloudstack.storage.datastore.driver;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import javax.inject.Inject; 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.ChapInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; 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.SnapshotObjectTO;
import org.apache.cloudstack.storage.to.TemplateObjectTO; import org.apache.cloudstack.storage.to.TemplateObjectTO;
import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.cloudstack.storage.volume.VolumeObject;
import org.apache.log4j.Logger;
import com.cloud.agent.api.Answer; import com.cloud.agent.api.Answer;
import com.cloud.agent.api.storage.ResizeVolumeAnswer; 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.Storage;
import com.cloud.storage.StorageManager; import com.cloud.storage.StorageManager;
import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePool;
import com.cloud.storage.Volume;
import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.SnapshotDao;
import com.cloud.storage.dao.VMTemplateDao; 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.storage.snapshot.SnapshotManager;
import com.cloud.template.TemplateManager; import com.cloud.template.TemplateManager;
import com.cloud.utils.Pair; import com.cloud.utils.Pair;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.dao.VMInstanceDao;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver { public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver {
@Override @Override
public Map<String, String> getCapabilities() { 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 @Override
public void deleteAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback<CommandResult> callback) { public void deleteAsync(DataStore dataStore, DataObject data, AsyncCompletionCallback<CommandResult> callback) {
DeleteCommand cmd = new DeleteCommand(data.getTO()); DeleteCommand cmd = new DeleteCommand(data.getTO());
cmd.setBypassHostMaintenance(commandCanBypassHostMaintenance(data));
CommandResult result = new CommandResult(); CommandResult result = new CommandResult();
try { try {
EndPoint ep = null; EndPoint ep = null;

View File

@ -163,13 +163,15 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
DecimalFormat decimalFormat = new DecimalFormat("#.##"); DecimalFormat decimalFormat = new DecimalFormat("#.##");
if (host.getType() == Host.Type.Routing) { 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)) { if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) {
// set allocated capacities // set allocated capacities
Long mem = host.getMemReservedCapacity() + host.getMemUsedCapacity(); Long mem = host.getMemReservedCapacity() + host.getMemUsedCapacity();
Long cpu = host.getCpuReservedCapacity() + host.getCpuUsedCapacity(); Long cpu = host.getCpuReservedCapacity() + host.getCpuUsedCapacity();
hostResponse.setMemoryTotal(host.getTotalMemory());
Float memWithOverprovisioning = host.getTotalMemory() * ApiDBUtils.getMemOverprovisioningFactor(host.getClusterId()); Float memWithOverprovisioning = host.getTotalMemory() * ApiDBUtils.getMemOverprovisioningFactor(host.getClusterId());
hostResponse.setMemoryTotal(memWithOverprovisioning.longValue());
hostResponse.setMemWithOverprovisioning(decimalFormat.format(memWithOverprovisioning)); hostResponse.setMemWithOverprovisioning(decimalFormat.format(memWithOverprovisioning));
hostResponse.setMemoryAllocated(mem); hostResponse.setMemoryAllocated(mem);
hostResponse.setMemoryAllocatedBytes(mem); hostResponse.setMemoryAllocatedBytes(mem);
@ -188,12 +190,12 @@ public class HostJoinDaoImpl extends GenericDaoBase<HostJoinVO, Long> implements
hostResponse.setHypervisorVersion(host.getHypervisorVersion()); hostResponse.setHypervisorVersion(host.getHypervisorVersion());
float cpuWithOverprovisioning = host.getCpus() * host.getSpeed() * cpuOverprovisioningFactor;
hostResponse.setCpuAllocatedValue(cpu); hostResponse.setCpuAllocatedValue(cpu);
String cpuAlloc = decimalFormat.format(((float)cpu / (float)(host.getCpus() * host.getSpeed())) * 100f) + "%"; String cpuAllocated = calculateResourceAllocatedPercentage(cpu, cpuWithOverprovisioning);
hostResponse.setCpuAllocated(cpuAlloc); hostResponse.setCpuAllocated(cpuAllocated);
hostResponse.setCpuAllocatedPercentage(cpuAlloc); hostResponse.setCpuAllocatedPercentage(cpuAllocated);
float cpuWithOverprovisioning = host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor(host.getClusterId()); hostResponse.setCpuAllocatedWithOverprovisioning(cpuAllocated);
hostResponse.setCpuAllocatedWithOverprovisioning(calculateResourceAllocatedPercentage(cpu, cpuWithOverprovisioning));
hostResponse.setCpuWithOverprovisioning(decimalFormat.format(cpuWithOverprovisioning)); hostResponse.setCpuWithOverprovisioning(decimalFormat.format(cpuWithOverprovisioning));
} }

View File

@ -1006,6 +1006,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
} }
public boolean isZoneReady(Map<Long, ZoneHostInfo> zoneHostInfoMap, long dataCenterId) { 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); ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) { if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any); VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any);

View File

@ -16,9 +16,32 @@
// under the License. // under the License.
package com.cloud.ha; 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.agent.AgentManager;
import com.cloud.alert.AlertManager; import com.cloud.alert.AlertManager;
import com.cloud.cluster.ClusterManagerListener; import com.cloud.cluster.ClusterManagerListener;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO; import com.cloud.dc.HostPodVO;
@ -46,37 +69,16 @@ import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.StorageManager; import com.cloud.storage.StorageManager;
import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.user.AccountManager; import com.cloud.user.AccountManager;
import com.cloud.utils.component.ManagerBase; import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.VMInstanceDao; 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 * 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; HostPodDao _podDao;
@Inject @Inject
ClusterDetailsDao _clusterDetailsDao; ClusterDetailsDao _clusterDetailsDao;
@Inject @Inject
ServiceOfferingDao _serviceOfferingDao; ServiceOfferingDao _serviceOfferingDao;
@Inject
private ConsoleProxyManager consoleProxyManager;
@Inject
private SecondaryStorageVmManager secondaryStorageVmManager;
long _serverId; long _serverId;
@ -197,7 +202,6 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
int _maxRetries; int _maxRetries;
long _timeBetweenFailures; long _timeBetweenFailures;
long _timeBetweenCleanups; long _timeBetweenCleanups;
boolean _forceHA;
String _haTag = null; String _haTag = null;
protected HighAvailabilityManagerImpl() { protected HighAvailabilityManagerImpl() {
@ -364,7 +368,7 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
alertType = AlertManager.AlertType.ALERT_TYPE_SSVM; 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(); 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() + _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() + ") 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()); vm = _itMgr.findById(vm.getId());
if (!_forceHA && !vm.isHaEnabled()) { if (!ForceHA.value() && !vm.isHaEnabled()) {
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug("VM is not HA enabled so we're done."); 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); _haDao.delete(vm.getId(), WorkType.Destroy);
} }
protected Long destroyVM(final HaWorkVO work) { private void stopVMWithCleanup(VirtualMachine vm, VirtualMachine.State state) throws OperationTimedoutException, ResourceUnavailableException {
final VirtualMachine vm = _itMgr.findById(work.getInstanceId()); if (VirtualMachine.State.Running.equals(state)) {
s_logger.info("Destroying " + vm.toString()); _itMgr.advanceStop(vm.getUuid(), true);
try { }
if (vm.getState() != State.Destroyed) {
s_logger.info("VM is no longer in Destroyed state " + vm.toString());
return null;
} }
if (vm.getHostId() != null) { private void destroyVM(VirtualMachine vm, boolean expunge) throws OperationTimedoutException, AgentUnavailableException {
_itMgr.destroy(vm.getUuid(), false); s_logger.info("Destroying " + vm.toString());
s_logger.info("Successfully destroy " + vm); 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());
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 {
stopVMWithCleanup(vm, work.getPreviousState());
if (!VirtualMachine.State.Expunging.equals(work.getPreviousState())) {
destroyVM(vm, expunge);
return null; return null;
} else { } else {
if (s_logger.isDebugEnabled()) { s_logger.info("VM " + vm.getUuid() + " still in " + vm.getState() + " state.");
s_logger.debug(vm + " has already been stopped");
}
return null;
} }
} catch (final AgentUnavailableException e) { } 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) { } catch (OperationTimedoutException e) {
s_logger.debug("operation timed out: " + e.getMessage()); s_logger.debug("operation timed out: " + e.getMessage());
} catch (ConcurrentOperationException e) { } catch (ConcurrentOperationException e) {
s_logger.debug("concurrent operation: " + e.getMessage()); s_logger.debug("concurrent operation: " + e.getMessage());
} catch (ResourceUnavailableException e) {
s_logger.debug("Resource unavailable: " + e.getMessage());
} }
return (System.currentTimeMillis() >> 10) + _stopRetryInterval; return (System.currentTimeMillis() >> 10) + _stopRetryInterval;
@ -793,9 +817,8 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
case Stop: case Stop:
case CheckStop: case CheckStop:
case ForceStop: case ForceStop:
return ((System.currentTimeMillis() >> 10) + _stopRetryInterval);
case Destroy: case Destroy:
return ((System.currentTimeMillis() >> 10) + _restartRetryInterval); return ((System.currentTimeMillis() >> 10) + _stopRetryInterval);
} }
return 0; return 0;
} }
@ -861,7 +884,6 @@ public class HighAvailabilityManagerImpl extends ManagerBase implements Configur
_workers[i] = new WorkerThread("HA-Worker-" + i); _workers[i] = new WorkerThread("HA-Worker-" + i);
} }
_forceHA = ForceHA.value();
_timeToSleep = TimeToSleep.value() * SECONDS_TO_MILLISECONDS_FACTOR; _timeToSleep = TimeToSleep.value() * SECONDS_TO_MILLISECONDS_FACTOR;
_maxRetries = MigrationMaxRetries.value(); _maxRetries = MigrationMaxRetries.value();
_timeBetweenFailures = TimeBetweenFailures.value() * SECONDS_TO_MILLISECONDS_FACTOR; _timeBetweenFailures = TimeBetweenFailures.value() * SECONDS_TO_MILLISECONDS_FACTOR;

View File

@ -477,6 +477,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
SearchBuilder<VlanVO> vlanSearch = _vlanDao.createSearchBuilder(); SearchBuilder<VlanVO> vlanSearch = _vlanDao.createSearchBuilder();
vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ); vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ);
vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), 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.join("vlan", vlanSearch, vlanSearch.entity().getId(), AssignIpAddressSearch.entity().getVlanId(), JoinType.INNER);
AssignIpAddressSearch.done(); AssignIpAddressSearch.done();
@ -488,6 +489,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
SearchBuilder<VlanVO> podVlanSearch = _vlanDao.createSearchBuilder(); SearchBuilder<VlanVO> podVlanSearch = _vlanDao.createSearchBuilder();
podVlanSearch.and("type", podVlanSearch.entity().getVlanType(), Op.EQ); podVlanSearch.and("type", podVlanSearch.entity().getVlanType(), Op.EQ);
podVlanSearch.and("networkId", podVlanSearch.entity().getNetworkId(), Op.EQ); podVlanSearch.and("networkId", podVlanSearch.entity().getNetworkId(), Op.EQ);
podVlanSearch.and("vlanGateway", podVlanSearch.entity().getVlanGateway(), Op.EQ);
SearchBuilder<PodVlanMapVO> podVlanMapSB = _podVlanMapDao.createSearchBuilder(); SearchBuilder<PodVlanMapVO> podVlanMapSB = _podVlanMapDao.createSearchBuilder();
podVlanMapSB.and("podId", podVlanMapSB.entity().getPodId(), Op.EQ); podVlanMapSB.and("podId", podVlanMapSB.entity().getPodId(), Op.EQ);
AssignIpAddressFromPodVlanSearch.join("podVlanMapSB", podVlanMapSB, podVlanMapSB.entity().getVlanDbId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(), AssignIpAddressFromPodVlanSearch.join("podVlanMapSB", podVlanMapSB, podVlanMapSB.entity().getVlanDbId(), AssignIpAddressFromPodVlanSearch.entity().getVlanId(),
@ -756,34 +758,34 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
@Override @Override
public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem, boolean forSystemVms) public PublicIp assignPublicIpAddress(long dcId, Long podId, Account owner, VlanType type, Long networkId, String requestedIp, boolean isSystem, boolean forSystemVms)
throws InsufficientAddressCapacityException { 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 @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 { 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 @Override
public PublicIp getAvailablePublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem) public PublicIp getAvailablePublicIpAddressFromVlans(long dcId, Long podId, Account owner, VlanType type, List<Long> vlanDbIds, Long networkId, String requestedIp, boolean isSystem)
throws InsufficientAddressCapacityException { 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 @DB
public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId, 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 { throws InsufficientAddressCapacityException {
return fetchNewPublicIp(dcId, podId, vlanDbIds, owner, vlanUse, guestNetworkId, 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 @DB
public PublicIp fetchNewPublicIp(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId, 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 { 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); IPAddressVO addr = addrs.get(0);
if (vlanUse == VlanType.VirtualNetwork) { if (vlanUse == VlanType.VirtualNetwork) {
_firewallMgr.addSystemFirewallRules(addr, owner); _firewallMgr.addSystemFirewallRules(addr, owner);
@ -794,7 +796,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
@Override @Override
public List<IPAddressVO> listAvailablePublicIps(final long dcId, final Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType vlanUse, final Long guestNetworkId, 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 { final Long vpcId, final Boolean displayIp, final boolean forSystemVms, final boolean lockOneRow) throws InsufficientAddressCapacityException {
return Transaction.execute(new TransactionCallbackWithException<List<IPAddressVO>, InsufficientAddressCapacityException>() { return Transaction.execute(new TransactionCallbackWithException<List<IPAddressVO>, InsufficientAddressCapacityException>() {
@Override @Override
@ -865,6 +867,10 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
sc.setJoinParameters("vlan", "networkId", guestNetworkId); sc.setJoinParameters("vlan", "networkId", guestNetworkId);
errorMessage.append(", network id=" + guestNetworkId); errorMessage.append(", network id=" + guestNetworkId);
} }
if (requestedGateway != null) {
sc.setJoinParameters("vlan", "vlanGateway", requestedGateway);
errorMessage.append(", requested gateway=" + requestedGateway);
}
sc.setJoinParameters("vlan", "type", vlanUse); sc.setJoinParameters("vlan", "type", vlanUse);
String routerIpAddress = null; String routerIpAddress = null;
if (network != null) { if (network != null) {
@ -1030,7 +1036,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
VpcVO vpc = _vpcDao.findById(vpcId); VpcVO vpc = _vpcDao.findById(vpcId);
displayIp = vpc.isDisplay(); 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) { if (ip.getState() != State.Allocated) {
@ -1226,7 +1232,7 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage
ip = Transaction.execute(new TransactionCallbackWithException<PublicIp, InsufficientAddressCapacityException>() { ip = Transaction.execute(new TransactionCallbackWithException<PublicIp, InsufficientAddressCapacityException>() {
@Override @Override
public PublicIp doInTransaction(TransactionStatus status) throws InsufficientAddressCapacityException { 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) { if (ip == null) {
InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException("Unable to find available public IP addresses", DataCenter.class, zone

View File

@ -123,10 +123,10 @@ public class DhcpSubNetRules extends RuleApplier {
IpAddressManager ipAddrMgr = visitor.getVirtualNetworkApplianceFactory().getIpAddrMgr(); IpAddressManager ipAddrMgr = visitor.getVirtualNetworkApplianceFactory().getIpAddrMgr();
if (dc.getNetworkType() == NetworkType.Basic) { if (dc.getNetworkType() == NetworkType.Basic) {
routerPublicIP = ipAddrMgr.assignPublicIpAddressFromVlans(_router.getDataCenterId(), vm.getPodIdToDeployIn(), caller, Vlan.VlanType.DirectAttached, routerPublicIP = ipAddrMgr.assignPublicIpAddressFromVlans(_router.getDataCenterId(), vm.getPodIdToDeployIn(), caller, Vlan.VlanType.DirectAttached,
vlanDbIdList, _nic.getNetworkId(), null, false); vlanDbIdList, _nic.getNetworkId(), null, _nic.getIPv4Gateway(), false);
} else { } else {
routerPublicIP = ipAddrMgr.assignPublicIpAddressFromVlans(_router.getDataCenterId(), null, caller, Vlan.VlanType.DirectAttached, vlanDbIdList, 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(); _routerAliasIp = routerPublicIP.getAddress().addr();

View File

@ -16,6 +16,8 @@
// under the License. // under the License.
package com.cloud.resource; package com.cloud.resource;
import static com.cloud.configuration.ConfigurationManagerImpl.SET_HOST_DOWN_TO_MAINTENANCE;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URLDecoder; import java.net.URLDecoder;
@ -192,9 +194,6 @@ import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao; import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson; import com.google.gson.Gson;
import static com.cloud.configuration.ConfigurationManagerImpl.SET_HOST_DOWN_TO_MAINTENANCE;
@Component @Component
public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ResourceService, Manager { public class ResourceManagerImpl extends ManagerBase implements ResourceManager, ResourceService, Manager {
private static final Logger s_logger = Logger.getLogger(ResourceManagerImpl.class); 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); 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) { private boolean doMaintain(final long hostId) {
final HostVO host = _hostDao.findById(hostId); final HostVO host = _hostDao.findById(hostId);
s_logger.info("Maintenance: attempting maintenance of host " + host.getUuid()); 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) { for (final VMInstanceVO vm : vms) {
if (hosts == null || hosts.isEmpty() || !answer.getMigrate() if (hosts == null || hosts.isEmpty() || !answer.getMigrate()
|| _serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.vgpuType.toString()) != null) { || _serviceOfferingDetailsDao.findDetail(vm.getServiceOfferingId(), GPU.Keys.vgpuType.toString()) != null) {
// Migration is not supported for VGPU Vms so stop them. handleVmForLastHostOrWithVGpu(host, vm);
// 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);
} else if (HypervisorType.LXC.equals(host.getHypervisorType()) && VirtualMachine.Type.User.equals(vm.getType())){ } else if (HypervisorType.LXC.equals(host.getHypervisorType()) && VirtualMachine.Type.User.equals(vm.getType())){
//Migration is not supported for LXC Vms. Schedule restart instead. //Migration is not supported for LXC Vms. Schedule restart instead.
_haMgr.scheduleRestart(vm, false); _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 * on a host. We need to track the various VM states on each run and accordingly transit to the
* appropriate state. * 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 * 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 * to maintenance state. Note that there cannot be incoming migrations as the API Call prepare for
* maintenance checks incoming migrations before starting. * maintenance checks incoming migrations before starting.
@ -2449,11 +2458,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
s_logger.debug("Deleting Host: " + host.getId() + " Guid:" + host.getGuid()); 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 // put local storage into mainenance mode, will set all the VMs on
// this local storage into stopped state // 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) { if (storagePool.getStatus() == StoragePoolStatus.Up || storagePool.getStatus() == StoragePoolStatus.ErrorInMaintenance) {
try { try {
final StoragePool pool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId()); final StoragePool pool = _storageSvr.preparePrimaryStorageForMaintenance(storagePool.getId());
@ -2478,7 +2486,6 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); throw new UnableDeleteHostException(errorMsg + "," + e.getMessage());
} }
} }
}
} else { } else {
// Check if there are vms running/starting/stopping on this host // Check if there are vms running/starting/stopping on this host
final List<VMInstanceVO> vms = _vmDao.listByHostId(host.getId()); final List<VMInstanceVO> vms = _vmDao.listByHostId(host.getId());
@ -2486,17 +2493,22 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
if (isForced) { if (isForced) {
// Stop HA disabled vms and HA enabled vms in Stopping state // Stop HA disabled vms and HA enabled vms in Stopping state
// Restart HA enabled vms // 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) { 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()); s_logger.debug("Stopping vm: " + vm + " as a part of deleteHost id=" + host.getId());
try { try {
_vmMgr.advanceStop(vm.getUuid(), false); _haMgr.scheduleStop(vm, host.getId(), WorkType.Stop);
} catch (final Exception e) { } catch (final Exception e) {
final String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId(); final String errorMsg = "There was an error stopping the vm: " + vm + " as a part of hostDelete id=" + host.getId();
s_logger.debug(errorMsg, e); s_logger.debug(errorMsg, e);
throw new UnableDeleteHostException(errorMsg + "," + e.getMessage()); 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()); s_logger.debug("Scheduling restart for vm: " + vm + " " + vm.getState() + " on the host id=" + host.getId());
_haMgr.scheduleRestart(vm, false); _haMgr.scheduleRestart(vm, false);
} }

View File

@ -2198,7 +2198,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
long dcId = dc.getId(); long dcId = dc.getId();
try { try {
freeAddrs.addAll(_ipAddressMgr.listAvailablePublicIps(dcId, null, vlanDbIds, owner, VlanType.VirtualNetwork, associatedNetworkId, 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) { } catch (InsufficientAddressCapacityException e) {
s_logger.warn("no free address is found in zone " + dcId); s_logger.warn("no free address is found in zone " + dcId);
} }

View File

@ -29,10 +29,10 @@ public class TemplateUploadParams extends UploadParamsBase {
Long zoneId, Hypervisor.HypervisorType hypervisorType, String chksum, Long zoneId, Hypervisor.HypervisorType hypervisorType, String chksum,
String templateTag, long templateOwnerId, String templateTag, long templateOwnerId,
Map details, Boolean sshkeyEnabled, Map details, Boolean sshkeyEnabled,
Boolean isDynamicallyScalable, Boolean isRoutingType) { Boolean isDynamicallyScalable, Boolean isRoutingType, boolean deployAsIs) {
super(userId, name, displayText, bits, passwordEnabled, requiresHVM, isPublic, featured, isExtractable, super(userId, name, displayText, bits, passwordEnabled, requiresHVM, isPublic, featured, isExtractable,
format, guestOSId, zoneId, hypervisorType, chksum, templateTag, templateOwnerId, details, format, guestOSId, zoneId, hypervisorType, chksum, templateTag, templateOwnerId, details,
sshkeyEnabled, isDynamicallyScalable, isRoutingType); sshkeyEnabled, isDynamicallyScalable, isRoutingType, deployAsIs);
setBootable(true); setBootable(true);
} }
} }

View File

@ -44,6 +44,7 @@ public abstract class UploadParamsBase implements UploadParams {
private boolean sshkeyEnabled; private boolean sshkeyEnabled;
private boolean isDynamicallyScalable; private boolean isDynamicallyScalable;
private boolean isRoutingType; private boolean isRoutingType;
private boolean deployAsIs;
UploadParamsBase(long userId, String name, String displayText, UploadParamsBase(long userId, String name, String displayText,
Integer bits, boolean passwordEnabled, boolean requiresHVM, Integer bits, boolean passwordEnabled, boolean requiresHVM,
@ -52,7 +53,7 @@ public abstract class UploadParamsBase implements UploadParams {
Long zoneId, Hypervisor.HypervisorType hypervisorType, String checksum, Long zoneId, Hypervisor.HypervisorType hypervisorType, String checksum,
String templateTag, long templateOwnerId, String templateTag, long templateOwnerId,
Map details, boolean sshkeyEnabled, Map details, boolean sshkeyEnabled,
boolean isDynamicallyScalable, boolean isRoutingType) { boolean isDynamicallyScalable, boolean isRoutingType, boolean deployAsIs) {
this.userId = userId; this.userId = userId;
this.name = name; this.name = name;
this.displayText = displayText; this.displayText = displayText;
@ -73,6 +74,7 @@ public abstract class UploadParamsBase implements UploadParams {
this.sshkeyEnabled = sshkeyEnabled; this.sshkeyEnabled = sshkeyEnabled;
this.isDynamicallyScalable = isDynamicallyScalable; this.isDynamicallyScalable = isDynamicallyScalable;
this.isRoutingType = isRoutingType; this.isRoutingType = isRoutingType;
this.deployAsIs = deployAsIs;
} }
UploadParamsBase(long userId, String name, String displayText, boolean isPublic, boolean isFeatured, UploadParamsBase(long userId, String name, String displayText, boolean isPublic, boolean isFeatured,
@ -216,7 +218,7 @@ public abstract class UploadParamsBase implements UploadParams {
@Override @Override
public boolean isDeployAsIs() { public boolean isDeployAsIs() {
return false; return deployAsIs;
} }
void setIso(boolean iso) { void setIso(boolean iso) {

View File

@ -337,7 +337,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
params.isExtractable(), params.getFormat(), params.getGuestOSId(), zoneList, params.isExtractable(), params.getFormat(), params.getGuestOSId(), zoneList,
params.getHypervisorType(), params.getChecksum(), params.isBootable(), params.getTemplateTag(), owner, params.getHypervisorType(), params.getChecksum(), params.isBootable(), params.getTemplateTag(), owner,
params.getDetails(), params.isSshKeyEnabled(), params.getImageStoreUuid(), 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() { 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, BooleanUtils.toBoolean(cmd.isFeatured()), BooleanUtils.toBoolean(cmd.isExtractable()), cmd.getFormat(), osTypeId,
cmd.getZoneId(), HypervisorType.getType(cmd.getHypervisor()), cmd.getChecksum(), cmd.getZoneId(), HypervisorType.getType(cmd.getHypervisor()), cmd.getChecksum(),
cmd.getTemplateTag(), cmd.getEntityOwnerId(), cmd.getDetails(), BooleanUtils.toBoolean(cmd.isSshKeyEnabled()), 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); return prepareUploadParamsInternal(params);
} }

View File

@ -44,6 +44,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import com.cloud.agent.AgentManager; import com.cloud.agent.AgentManager;
import com.cloud.alert.AlertManager; import com.cloud.alert.AlertManager;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO; import com.cloud.dc.HostPodVO;
@ -64,6 +65,7 @@ import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.StorageManager; import com.cloud.storage.StorageManager;
import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.GuestOSCategoryDao;
import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.secondary.SecondaryStorageVmManager;
import com.cloud.user.AccountManager; import com.cloud.user.AccountManager;
import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine;
@ -112,6 +114,10 @@ public class HighAvailabilityManagerImplTest {
@Mock @Mock
VolumeOrchestrationService volumeMgr; VolumeOrchestrationService volumeMgr;
@Mock @Mock
ConsoleProxyManager consoleProxyManager;
@Mock
SecondaryStorageVmManager secondaryStorageVmManager;
@Mock
HostVO hostVO; HostVO hostVO;
HighAvailabilityManagerImpl highAvailabilityManager; HighAvailabilityManagerImpl highAvailabilityManager;

View File

@ -768,6 +768,13 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
} }
public boolean isZoneReady(Map<Long, ZoneHostInfo> zoneHostInfoMap, long dataCenterId) { 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); ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) { if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) {
VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any); VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any);

View File

@ -1070,6 +1070,7 @@ def main(argv):
config.address().process() config.address().process()
databag_map = OrderedDict([("guest_network", {"process_iptables": True, "executor": []}), 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_password", {"process_iptables": False, "executor": [CsPassword("vmpassword", config)]}),
("vm_metadata", {"process_iptables": False, "executor": [CsVmMetadata('vmdata', config)]}), ("vm_metadata", {"process_iptables": False, "executor": [CsVmMetadata('vmdata', config)]}),
("network_acl", {"process_iptables": True, "executor": []}), ("network_acl", {"process_iptables": True, "executor": []}),

View File

@ -869,7 +869,7 @@ class VirtualMachine:
if hostid: if hostid:
cmd.hostid = hostid cmd.hostid = hostid
if migrateto: if migrateto:
migrateto = [] cmd.migrateto = []
for volume, pool in list(migrateto.items()): for volume, pool in list(migrateto.items()):
cmd.migrateto.append({ cmd.migrateto.append({
'volume': volume, 'volume': volume,

View File

@ -24,9 +24,11 @@
"url": "https://github.com/apache/cloudstack/issues" "url": "https://github.com/apache/cloudstack/issues"
}, },
"scripts": { "scripts": {
"prebuild": "./prebuild.sh",
"start": "vue-cli-service lint --no-fix && vue-cli-service serve", "start": "vue-cli-service lint --no-fix && vue-cli-service serve",
"serve": "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", "build": "vue-cli-service build",
"postbuild": "./postbuild.sh",
"lint": "vue-cli-service lint", "lint": "vue-cli-service lint",
"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'", "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'",
"test:unit": "vue-cli-service test:unit" "test:unit": "vue-cli-service test:unit"

36
ui/postbuild.sh Executable file
View 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
View 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}

View File

@ -6,8 +6,8 @@
"logo": "assets/logo.svg", "logo": "assets/logo.svg",
"banner": "assets/banner.svg", "banner": "assets/banner.svg",
"error": { "error": {
"404": "assets/404.png",
"403": "assets/403.png", "403": "assets/403.png",
"404": "assets/404.png",
"500": "assets/500.png" "500": "assets/500.png"
}, },
"theme": { "theme": {
@ -46,7 +46,7 @@
"jp": "label.japanese.keyboard", "jp": "label.japanese.keyboard",
"sc": "label.simplified.chinese.keyboard" "sc": "label.simplified.chinese.keyboard"
}, },
"docHelpMappings": {},
"plugins": [], "plugins": [],
"basicZoneEnabled": true "basicZoneEnabled": true,
"docHelpMappings": {}
} }

View File

@ -174,7 +174,7 @@ export default {
icon: 'cloud-upload', icon: 'cloud-upload',
docHelp: 'adminguide/virtual_machines.html#backup-offerings', docHelp: 'adminguide/virtual_machines.html#backup-offerings',
permission: ['listBackupOfferings', 'listInfrastructure'], permission: ['listBackupOfferings', 'listInfrastructure'],
columns: ['name', 'description', 'zoneid'], columns: ['name', 'description', 'zonename'],
details: ['name', 'id', 'description', 'externalid', 'zone', 'created'], details: ['name', 'id', 'description', 'externalid', 'zone', 'created'],
actions: [{ actions: [{
api: 'importBackupOffering', api: 'importBackupOffering',

View File

@ -175,7 +175,7 @@ export const configUtilPlugin = {
if (docHelp && docHelpMappings && if (docHelp && docHelpMappings &&
docHelpMappings.constructor === Object && Object.keys(docHelpMappings).length > 0) { docHelpMappings.constructor === Object && Object.keys(docHelpMappings).length > 0) {
for (var key in docHelpMappings) { for (var key in docHelpMappings) {
if (docHelp.includes(key)) { if (docHelp.includes(key) && docHelp !== docHelpMappings[key]) {
docHelp = docHelp.replace(key, docHelpMappings[key]) docHelp = docHelp.replace(key, docHelpMappings[key])
break break
} }

View File

@ -149,7 +149,6 @@ export default {
page: this.page, page: this.page,
pagesize: this.pageSize pagesize: this.pageSize
}).then(response => { }).then(response => {
console.log(response)
this.items = response.listnetworksresponse.network ? response.listnetworksresponse.network : [] this.items = response.listnetworksresponse.network ? response.listnetworksresponse.network : []
this.total = response.listnetworksresponse.count || 0 this.total = response.listnetworksresponse.count || 0
}).catch(error => { }).catch(error => {

View File

@ -34,20 +34,20 @@
:rowKey="record => record.id" :rowKey="record => record.id"
:pagination="false" :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> <a-button @click="() => handleOpenAccountModal(record)">{{ `[${record.domain}] ${record.account === undefined ? '' : record.account}` }}</a-button>
</template> </template>
<template slot="actions" slot-scope="record"> <template slot="actions" slot-scope="record">
<div class="actions"> <div class="actions">
<tooltip-button <tooltip-button
v-if="record.account === 'system'" v-if="record.account === 'system' && !basicGuestNetwork"
tooltipPlacement="bottom" tooltipPlacement="bottom"
:tooltip="$t('label.add.account')" :tooltip="$t('label.add.account')"
icon="user-add" icon="user-add"
@click="() => handleOpenAddAccountModal(record)" @click="() => handleOpenAddAccountModal(record)"
:disabled="!('dedicatePublicIpRange' in $store.getters.apis)" /> :disabled="!('dedicatePublicIpRange' in $store.getters.apis)" />
<tooltip-button <tooltip-button
v-else v-if="record.account !== 'system' && !basicGuestNetwork"
tooltipPlacement="bottom" tooltipPlacement="bottom"
:tooltip="$t('label.release.account')" :tooltip="$t('label.release.account')"
icon="user-delete" icon="user-delete"
@ -137,6 +137,16 @@
layout="vertical" layout="vertical"
class="form" 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-form-item :label="$t('label.gateway')" class="form__item">
<a-input <a-input
autoFocus autoFocus
@ -148,7 +158,7 @@
v-decorator="['netmask', { rules: [{ required: true, message: `${$t('label.required')}` }] }]"> v-decorator="['netmask', { rules: [{ required: true, message: `${$t('label.required')}` }] }]">
</a-input> </a-input>
</a-form-item> </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 <a-input
v-decorator="['vlan']"> v-decorator="['vlan']">
</a-input> </a-input>
@ -163,11 +173,11 @@
v-decorator="['endip', { rules: [{ required: true, message: `${$t('label.required')}` }] }]"> v-decorator="['endip', { rules: [{ required: true, message: `${$t('label.required')}` }] }]">
</a-input> </a-input>
</a-form-item> </a-form-item>
<div class="form__item"> <div class="form__item" v-if="!basicGuestNetwork">
<div style="color: black;">{{ $t('label.set.reservation') }}</div> <div style="color: black;">{{ $t('label.set.reservation') }}</div>
<a-switch @change="handleShowAccountFields"></a-switch> <a-switch @change="handleShowAccountFields"></a-switch>
</div> </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> <div v-html="$t('label.set.reservation.desc')"></div>
<a-form-item :label="$t('label.system.vms')" class="form__item"> <a-form-item :label="$t('label.system.vms')" class="form__item">
<a-switch v-decorator="['forsystemvms']"></a-switch> <a-switch v-decorator="['forsystemvms']"></a-switch>
@ -214,6 +224,10 @@ export default {
network: { network: {
type: Object, type: Object,
required: true required: true
},
basicGuestNetwork: {
type: Boolean,
required: true
} }
}, },
data () { data () {
@ -232,6 +246,8 @@ export default {
domainsLoading: false, domainsLoading: false,
addIpRangeModal: false, addIpRangeModal: false,
showAccountFields: false, showAccountFields: false,
podsLoading: false,
pods: [],
page: 1, page: 1,
pageSize: 10, pageSize: 10,
columns: [ columns: [
@ -255,10 +271,6 @@ export default {
title: this.$t('label.endip'), title: this.$t('label.endip'),
dataIndex: 'endip' dataIndex: 'endip'
}, },
{
title: this.$t('label.account'),
scopedSlots: { customRender: 'account' }
},
{ {
title: this.$t('label.action'), title: this.$t('label.action'),
scopedSlots: { customRender: 'actions' } scopedSlots: { customRender: 'actions' }
@ -270,6 +282,19 @@ export default {
this.form = this.$form.createForm(this) this.form = this.$form.createForm(this)
}, },
created () { 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() this.fetchData()
}, },
watch: { watch: {
@ -296,6 +321,7 @@ export default {
}).finally(() => { }).finally(() => {
this.componentLoading = false this.componentLoading = false
}) })
this.fetchPods()
}, },
fetchDomains () { fetchDomains () {
this.domainsLoading = true this.domainsLoading = true
@ -314,6 +340,22 @@ export default {
this.domainsLoading = false 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 () { handleAddAccount () {
this.domainsLoading = true this.domainsLoading = true
@ -384,18 +426,25 @@ export default {
this.componentLoading = true this.componentLoading = true
this.addIpRangeModal = false this.addIpRangeModal = false
api('createVlanIpRange', { var params = {
zoneId: this.resource.zoneid,
vlan: values.vlan,
gateway: values.gateway, gateway: values.gateway,
netmask: values.netmask, netmask: values.netmask,
startip: values.startip, startip: values.startip,
endip: values.endip, endip: values.endip
forsystemvms: values.forsystemvms, }
account: values.forsystemvms ? null : values.account, if (!this.basicGuestNetwork) {
domainid: values.forsystemvms ? null : values.domain, params.zoneId = this.resource.zoneid
forvirtualnetwork: true params.vlan = values.vlan
}).then(() => { 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({ this.$notification.success({
message: this.$t('message.success.add.iprange') message: this.$t('message.success.add.iprange')
}) })

View File

@ -26,9 +26,17 @@
<div><strong>{{ $t(type) }}</strong></div> <div><strong>{{ $t(type) }}</strong></div>
<div>{{ item[type] || $t('label.network.label.display.for.blank.value') }}</div> <div>{{ item[type] || $t('label.network.label.display.for.blank.value') }}</div>
</div> </div>
<div v-if="item.traffictype === 'Guest'"> <div v-if="item.traffictype === 'Guest' && networkType === 'Advanced'">
<a-divider /> <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>
<div v-if="item.traffictype === 'Public'"> <div v-if="item.traffictype === 'Public'">
<div style="margin-bottom: 10px;"> <div style="margin-bottom: 10px;">
@ -40,7 +48,7 @@
<div>{{ publicNetwork.broadcastdomaintype }}</div> <div>{{ publicNetwork.broadcastdomaintype }}</div>
</div> </div>
<a-divider /> <a-divider />
<IpRangesTabPublic :resource="resource" :loading="loading" :network="publicNetwork" /> <IpRangesTabPublic :resource="resource" :loading="loading" :network="publicNetwork" :basicGuestNetwork="false" />
</div> </div>
<div v-if="item.traffictype === 'Management'"> <div v-if="item.traffictype === 'Management'">
<a-divider /> <a-divider />
@ -86,6 +94,8 @@ export default {
return { return {
traffictypes: [], traffictypes: [],
publicNetwork: {}, publicNetwork: {},
guestNetwork: {},
networkType: 'Advanced',
fetchLoading: false fetchLoading: false
} }
}, },
@ -102,7 +112,7 @@ export default {
} }
}, },
methods: { methods: {
fetchData () { async fetchData () {
this.fetchLoading = true this.fetchLoading = true
api('listTrafficTypes', { physicalnetworkid: this.resource.id }).then(json => { api('listTrafficTypes', { physicalnetworkid: this.resource.id }).then(json => {
this.traffictypes = json.listtraffictypesresponse.traffictype this.traffictypes = json.listtraffictypesresponse.traffictype
@ -111,7 +121,6 @@ export default {
}).finally(() => { }).finally(() => {
this.fetchLoading = false this.fetchLoading = false
}) })
this.fetchLoading = true this.fetchLoading = true
api('listNetworks', { api('listNetworks', {
listAll: true, listAll: true,
@ -129,6 +138,42 @@ export default {
}).finally(() => { }).finally(() => {
this.fetchLoading = false 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
})
} }
} }
} }

View File

@ -23,6 +23,17 @@
:form="form" :form="form"
@submit="handleSubmit" @submit="handleSubmit"
layout="vertical"> 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> <a-form-item>
<span slot="label"> <span slot="label">
{{ $t('label.gateway') }} {{ $t('label.gateway') }}
@ -195,6 +206,8 @@ export default {
data () { data () {
return { return {
loading: false, 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, 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 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.apiConfig.params.forEach(param => {
this.apiParams[param.name] = param this.apiParams[param.name] = param
}) })
this.fetchData()
}, },
methods: { 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) { handleSubmit (e) {
e.preventDefault() e.preventDefault()
@ -219,6 +265,9 @@ export default {
const params = {} const params = {}
params.forVirtualNetwork = false params.forVirtualNetwork = false
params.networkid = this.resource.id params.networkid = this.resource.id
if (values.podid) {
params.podid = values.podid
}
params.gateway = values.gateway params.gateway = values.gateway
params.netmask = values.netmask params.netmask = values.netmask
params.startip = values.startip params.startip = values.startip