Skip to content

Commit 70a4503

Browse files
committed
Merge remote-tracking branch 'apache/4.20'
2 parents b46e29d + 38006b2 commit 70a4503

File tree

11 files changed

+119
-19
lines changed

11 files changed

+119
-19
lines changed

api/src/main/java/com/cloud/hypervisor/Hypervisor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,22 @@
3131
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.DirectDownloadTemplate;
3232
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.RootDiskSizeOverride;
3333
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigration;
34+
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Functionality.VmStorageMigrationWithSnapshots;
3435

3536
public class Hypervisor {
3637
public static class HypervisorType {
3738
public enum Functionality {
3839
DirectDownloadTemplate,
3940
RootDiskSizeOverride,
40-
VmStorageMigration
41+
VmStorageMigration,
42+
VmStorageMigrationWithSnapshots
4143
}
4244

4345
private static final Map<String, HypervisorType> hypervisorTypeMap = new LinkedHashMap<>();
4446
public static final HypervisorType None = new HypervisorType("None"); //for storage hosts
4547
public static final HypervisorType XenServer = new HypervisorType("XenServer", ImageFormat.VHD, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
4648
public static final HypervisorType KVM = new HypervisorType("KVM", ImageFormat.QCOW2, EnumSet.of(DirectDownloadTemplate, RootDiskSizeOverride, VmStorageMigration));
47-
public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA, EnumSet.of(RootDiskSizeOverride, VmStorageMigration));
49+
public static final HypervisorType VMware = new HypervisorType("VMware", ImageFormat.OVA, EnumSet.of(RootDiskSizeOverride, VmStorageMigration, VmStorageMigrationWithSnapshots));
4850
public static final HypervisorType Hyperv = new HypervisorType("Hyperv");
4951
public static final HypervisorType VirtualBox = new HypervisorType("VirtualBox");
5052
public static final HypervisorType Parralels = new HypervisorType("Parralels");

api/src/main/java/com/cloud/kubernetes/cluster/KubernetesCluster.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum State {
6060
Stopping("Resources for the Kubernetes cluster are being destroyed"),
6161
Stopped("All resources for the Kubernetes cluster are destroyed, Kubernetes cluster may still have ephemeral resource like persistent volumes provisioned"),
6262
Scaling("Transient state in which resources are either getting scaled up/down"),
63+
ScalingStoppedCluster("Transient state in which the service offerings of stopped clusters are getting scaled"),
6364
Upgrading("Transient state in which cluster is getting upgraded"),
6465
Importing("Transient state in which additional nodes are added as worker nodes to a cluster"),
6566
RemovingNodes("Transient state in which additional nodes are removed from a cluster"),
@@ -93,8 +94,11 @@ enum State {
9394
s_fsm.addTransition(State.Running, Event.AutoscaleRequested, State.Scaling);
9495
s_fsm.addTransition(State.Running, Event.ScaleUpRequested, State.Scaling);
9596
s_fsm.addTransition(State.Running, Event.ScaleDownRequested, State.Scaling);
97+
s_fsm.addTransition(State.Stopped, Event.ScaleUpRequested, State.ScalingStoppedCluster);
9698
s_fsm.addTransition(State.Scaling, Event.OperationSucceeded, State.Running);
9799
s_fsm.addTransition(State.Scaling, Event.OperationFailed, State.Alert);
100+
s_fsm.addTransition(State.ScalingStoppedCluster, Event.OperationSucceeded, State.Stopped);
101+
s_fsm.addTransition(State.ScalingStoppedCluster, Event.OperationFailed, State.Alert);
98102

99103
s_fsm.addTransition(State.Running, Event.UpgradeRequested, State.Upgrading);
100104
s_fsm.addTransition(State.Upgrading, Event.OperationSucceeded, State.Running);

engine/orchestration/src/main/java/com/cloud/agent/manager/AgentManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ protected AgentAttache notifyMonitorsOfConnection(final AgentAttache attache, fi
809809
if (ObjectUtils.anyNotNull(uefiEnabled, virtv2vVersion, ovftoolVersion)) {
810810
_hostDao.loadDetails(host);
811811
boolean updateNeeded = false;
812-
if (!uefiEnabled.equals(host.getDetails().get(Host.HOST_UEFI_ENABLE))) {
812+
if (StringUtils.isNotBlank(uefiEnabled) && !uefiEnabled.equals(host.getDetails().get(Host.HOST_UEFI_ENABLE))) {
813813
host.getDetails().put(Host.HOST_UEFI_ENABLE, uefiEnabled);
814814
updateNeeded = true;
815815
}

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,20 @@ private String matchPifFileInDirectory(final String bridgeName) {
19021902
return "";
19031903
}
19041904

1905+
public Integer getVlanIdForBridge(final String bridge) {
1906+
String pif = matchPifFileInDirectory(bridge);
1907+
final File vlanfile = new File("/proc/net/vlan/" + pif);
1908+
if (vlanfile.isFile()) {
1909+
String vlan = Script.runSimpleBashScript("awk '/VID:/ {print $3}' /proc/net/vlan/" + pif);
1910+
try {
1911+
return Integer.parseInt(vlan);
1912+
} catch (final NumberFormatException e) {
1913+
return null;
1914+
}
1915+
}
1916+
return null;
1917+
}
1918+
19051919
static String [] ifNamePatterns = {
19061920
"^eth",
19071921
"^bond",

plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetUnmanagedInstancesCommandWrapper.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ private UnmanagedInstanceTO getUnmanagedInstance(LibvirtComputingResource libvir
132132
}
133133
instance.setPowerState(getPowerState(libvirtComputingResource.getVmState(conn,domain.getName())));
134134
instance.setMemory((int) LibvirtComputingResource.getDomainMemory(domain) / 1024);
135-
instance.setNics(getUnmanagedInstanceNics(parser.getInterfaces()));
135+
instance.setNics(getUnmanagedInstanceNics(libvirtComputingResource, parser.getInterfaces()));
136136
instance.setDisks(getUnmanagedInstanceDisks(parser.getDisks(),libvirtComputingResource, conn, domain.getName()));
137137
instance.setVncPassword(getFormattedVncPassword(parser.getVncPasswd()));
138138
if (parser.getBootType() != null) {
@@ -169,7 +169,7 @@ private UnmanagedInstanceTO.PowerState getPowerState(VirtualMachine.PowerState v
169169
}
170170
}
171171

172-
private List<UnmanagedInstanceTO.Nic> getUnmanagedInstanceNics(List<LibvirtVMDef.InterfaceDef> interfaces) {
172+
private List<UnmanagedInstanceTO.Nic> getUnmanagedInstanceNics(LibvirtComputingResource libvirtComputingResource, List<LibvirtVMDef.InterfaceDef> interfaces) {
173173
final ArrayList<UnmanagedInstanceTO.Nic> nics = new ArrayList<>(interfaces.size());
174174
int counter = 0;
175175
for (LibvirtVMDef.InterfaceDef interfaceDef : interfaces) {
@@ -180,6 +180,10 @@ private List<UnmanagedInstanceTO.Nic> getUnmanagedInstanceNics(List<LibvirtVMDef
180180
nic.setNetwork(interfaceDef.getDevName());
181181
nic.setPciSlot(interfaceDef.getSlot().toString());
182182
nic.setVlan(interfaceDef.getVlanTag());
183+
if (nic.getVlan() == -1
184+
&& LibvirtVMDef.InterfaceDef.GuestNetType.BRIDGE.equals(interfaceDef.getNetType())) {
185+
nic.setVlan(libvirtComputingResource.getVlanIdForBridge(interfaceDef.getBrName()));
186+
}
183187
nics.add(nic);
184188
}
185189
return nics;

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,8 @@ private void validateKubernetesClusterScaleSizeParameters() throws CloudRuntimeE
358358
private void scaleKubernetesClusterOffering(KubernetesClusterNodeType nodeType, ServiceOffering serviceOffering,
359359
boolean updateNodeOffering, boolean updateClusterOffering) throws CloudRuntimeException {
360360
validateKubernetesClusterScaleOfferingParameters();
361-
if (!kubernetesCluster.getState().equals(KubernetesCluster.State.Scaling)) {
361+
List<KubernetesCluster.State> scalingStates = List.of(KubernetesCluster.State.Scaling, KubernetesCluster.State.ScalingStoppedCluster);
362+
if (!scalingStates.contains(kubernetesCluster.getState())) {
362363
stateTransitTo(kubernetesCluster.getId(), KubernetesCluster.Event.ScaleUpRequested);
363364
}
364365
if (KubernetesCluster.State.Created.equals(originalState)) {
@@ -581,6 +582,8 @@ public boolean scaleCluster() throws CloudRuntimeException {
581582
scaleKubernetesClusterOffering(nodeType, scalingServiceOffering, updateNodeOffering, updateClusterOffering);
582583
} else if (clusterSizeScalingNeeded) {
583584
scaleKubernetesClusterSize(nodeType);
585+
} else {
586+
return true;
584587
}
585588
}
586589

server/src/main/java/com/cloud/vm/UserVmManagerImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7712,7 +7712,8 @@ public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinatio
77127712
HypervisorType.getListOfHypervisorsSupportingFunctionality(Functionality.VmStorageMigration)));
77137713
}
77147714

7715-
if (_vmSnapshotDao.findByVm(vmId).size() > 0) {
7715+
if (!vm.getHypervisorType().isFunctionalitySupported(Functionality.VmStorageMigrationWithSnapshots) &&
7716+
CollectionUtils.isNotEmpty(_vmSnapshotDao.findByVm(vmId))) {
77167717
throw new InvalidParameterValueException("VM with VM Snapshots cannot be migrated with storage, please remove all VM snapshots");
77177718
}
77187719

services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,11 @@
8585
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
8686
import org.apache.cloudstack.utils.security.DigestHelper;
8787
import org.apache.commons.codec.digest.DigestUtils;
88+
import org.apache.commons.collections.MapUtils;
8889
import org.apache.commons.io.FileUtils;
8990
import org.apache.commons.io.FilenameUtils;
9091
import org.apache.commons.lang3.BooleanUtils;
92+
import org.apache.commons.lang3.ObjectUtils;
9193
import org.apache.http.HttpEntity;
9294
import org.apache.http.HttpResponse;
9395
import org.apache.http.NameValuePair;
@@ -2742,6 +2744,20 @@ public PingCommand getCurrentStatus(final long id) {
27422744
return new PingStorageCommand(Host.Type.Storage, id, new HashMap<String, Boolean>());
27432745
}
27442746

2747+
protected void configureStorageNetwork(Map<String, Object> params) {
2748+
_storageIp = MapUtils.getString(params, "storageip");
2749+
_storageNetmask = (String) params.get("storagenetmask");
2750+
_storageGateway = (String) params.get("storagegateway");
2751+
if (_storageIp == null && _inSystemVM && _eth1ip != null) {
2752+
String eth1Gateway = ObjectUtils.firstNonNull(_localgw, MapUtils.getString(params, "localgw"));
2753+
logger.info("Storage network not configured, using management network[ip: {}, netmask: {}, gateway: {}] for storage traffic",
2754+
_eth1ip, _eth1mask, eth1Gateway);
2755+
_storageIp = _eth1ip;
2756+
_storageNetmask = _eth1mask;
2757+
_storageGateway = eth1Gateway;
2758+
}
2759+
}
2760+
27452761
@Override
27462762
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
27472763
_eth1ip = (String)params.get("eth1ip");
@@ -2764,12 +2780,10 @@ public boolean configure(String name, Map<String, Object> params) throws Configu
27642780
_inSystemVM = true;
27652781
}
27662782

2767-
_storageIp = (String)params.get("storageip");
2783+
configureStorageNetwork(params);
27682784
if (_storageIp == null && _inSystemVM) {
2769-
logger.warn("There is no storageip in /proc/cmdline, something wrong!");
2785+
logger.warn("No storageip in /proc/cmdline, something wrong! Even fallback to management network did not resolve storage IP.");
27702786
}
2771-
_storageNetmask = (String)params.get("storagenetmask");
2772-
_storageGateway = (String)params.get("storagegateway");
27732787
super.configure(name, params);
27742788

27752789
_params = params;

services/secondary-storage/server/src/test/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResourceTest.java

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,38 @@
1818
*/
1919
package org.apache.cloudstack.storage.resource;
2020

21-
import org.apache.logging.log4j.Logger;
2221
import static org.mockito.ArgumentMatchers.any;
23-
import org.mockito.Mock;
2422
import static org.mockito.Mockito.doThrow;
23+
import static org.mockito.Mockito.times;
2524

2625
import java.io.File;
2726
import java.nio.file.Files;
2827
import java.nio.file.Path;
28+
import java.util.HashMap;
2929
import java.util.List;
30+
import java.util.Map;
3031
import java.util.stream.Stream;
3132

32-
import com.cloud.exception.InvalidParameterValueException;
33-
import com.cloud.utils.EncryptionUtil;
34-
import com.cloud.utils.net.NetUtils;
3533
import org.apache.cloudstack.storage.command.DeleteCommand;
3634
import org.apache.cloudstack.storage.command.QuerySnapshotZoneCopyAnswer;
3735
import org.apache.cloudstack.storage.command.QuerySnapshotZoneCopyCommand;
3836
import org.apache.cloudstack.storage.to.SnapshotObjectTO;
3937
import org.apache.cloudstack.storage.to.TemplateObjectTO;
38+
import org.apache.logging.log4j.Logger;
4039
import org.junit.Assert;
4140
import org.junit.Test;
4241
import org.junit.runner.RunWith;
42+
import org.mockito.Mock;
4343
import org.mockito.MockedStatic;
4444
import org.mockito.Mockito;
45-
import static org.mockito.Mockito.times;
4645
import org.mockito.Spy;
4746
import org.mockito.junit.MockitoJUnitRunner;
47+
import org.springframework.test.util.ReflectionTestUtils;
4848

4949
import com.cloud.agent.api.to.DataStoreTO;
50+
import com.cloud.exception.InvalidParameterValueException;
51+
import com.cloud.utils.EncryptionUtil;
52+
import com.cloud.utils.net.NetUtils;
5053

5154
@RunWith(MockitoJUnitRunner.class)
5255
public class NfsSecondaryStorageResourceTest {
@@ -241,4 +244,45 @@ public void getUploadProtocolTestReturnHttpWhenUseHttpsToUploadIsFalse() {
241244

242245
Assert.assertEquals(NetUtils.HTTP_PROTO, result);
243246
}
247+
248+
@Test
249+
public void configureStorageNetworkSetsStorageNetworkWhenParamsContainValues() {
250+
Map<String, Object> params = new HashMap<>();
251+
String ip = "192.168.1.10";
252+
String netmask = "255.255.255.0";
253+
String gateway = "192.168.1.1";
254+
params.put("storageip", ip);
255+
params.put("storagenetmask", netmask);
256+
params.put("storagegateway", gateway);
257+
resource.configureStorageNetwork(params);
258+
Assert.assertEquals(ip, ReflectionTestUtils.getField(resource, "_storageIp"));
259+
Assert.assertEquals(netmask, ReflectionTestUtils.getField(resource, "_storageNetmask"));
260+
Assert.assertEquals(gateway, ReflectionTestUtils.getField(resource, "_storageGateway"));
261+
}
262+
263+
@Test
264+
public void configureStorageNetworkUsesManagementNetworkWhenStorageIpIsNullAndInSystemVM() {
265+
Map<String, Object> params = new HashMap<>();
266+
resource._inSystemVM = true;
267+
String ip = "10.0.0.10";
268+
String netmask = "255.255.255.0";
269+
String gateway = "10.0.0.1";
270+
ReflectionTestUtils.setField(resource, "_eth1ip", ip);
271+
ReflectionTestUtils.setField(resource, "_eth1mask", netmask);
272+
ReflectionTestUtils.setField(resource, "_localgw", gateway);
273+
resource.configureStorageNetwork(params);
274+
Assert.assertEquals(ip, ReflectionTestUtils.getField(resource, "_storageIp"));
275+
Assert.assertEquals(netmask, ReflectionTestUtils.getField(resource, "_storageNetmask"));
276+
Assert.assertEquals(gateway, ReflectionTestUtils.getField(resource, "_storageGateway"));
277+
}
278+
279+
@Test
280+
public void configureStorageNetworkDoesNotSetStorageNetworkWhenNotInSystemVMAndStorageIpIsNull() {
281+
Map<String, Object> params = new HashMap<>();
282+
resource._inSystemVM = false;
283+
resource.configureStorageNetwork(params);
284+
Assert.assertNull(ReflectionTestUtils.getField(resource, "_storageIp"));
285+
Assert.assertNull(ReflectionTestUtils.getField(resource, "_storageNetmask"));
286+
Assert.assertNull(ReflectionTestUtils.getField(resource, "_storageGateway"));
287+
}
244288
}

systemvm/debian/opt/cloud/bin/cs/CsNetfilter.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ def add_ip6_chain(self, address_family, table, chain, hook, action):
232232
if hook == "input" or hook == "output":
233233
CsHelper.execute("nft add rule %s %s %s icmpv6 type { echo-request, echo-reply, \
234234
nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept" % (address_family, table, chain))
235+
elif hook == "forward":
236+
CsHelper.execute("nft add rule %s %s %s ct state established,related accept" % (address_family, table, chain))
235237

236238
def add_ip4_chain(self, address_family, table, chain, hook, action):
237239
chain_policy = ""

0 commit comments

Comments
 (0)