Skip to content

Commit 65e4938

Browse files
author
Pearl Dsilva
committed
Support for persistence mode in L2 networks
1 parent 58a0a7b commit 65e4938

File tree

25 files changed

+447
-49
lines changed

25 files changed

+447
-49
lines changed

api/src/main/java/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
// under the License.
1717
package org.apache.cloudstack.api.command.user.network;
1818

19+
import org.apache.cloudstack.api.BaseAsyncCmd;
1920
import org.apache.log4j.Logger;
2021

2122
import org.apache.cloudstack.acl.RoleType;
2223
import org.apache.cloudstack.api.APICommand;
2324
import org.apache.cloudstack.api.ApiConstants;
2425
import org.apache.cloudstack.api.ApiErrorCode;
25-
import org.apache.cloudstack.api.BaseCmd;
2626
import org.apache.cloudstack.api.Parameter;
2727
import org.apache.cloudstack.api.ResponseObject.ResponseView;
2828
import org.apache.cloudstack.api.ServerApiException;
@@ -37,6 +37,7 @@
3737
import org.apache.cloudstack.api.response.ZoneResponse;
3838
import org.apache.cloudstack.context.CallContext;
3939

40+
import com.cloud.event.EventTypes;
4041
import com.cloud.exception.ConcurrentOperationException;
4142
import com.cloud.exception.InsufficientCapacityException;
4243
import com.cloud.exception.InvalidParameterValueException;
@@ -48,7 +49,7 @@
4849

4950
@APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class},
5051
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
51-
public class CreateNetworkCmd extends BaseCmd implements UserCmd {
52+
public class CreateNetworkCmd extends BaseAsyncCmd implements UserCmd {
5253
public static final Logger s_logger = Logger.getLogger(CreateNetworkCmd.class.getName());
5354

5455
private static final String s_name = "createnetworkresponse";
@@ -326,4 +327,14 @@ void execute() throws InsufficientCapacityException, ConcurrentOperationExceptio
326327
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create network");
327328
}
328329
}
330+
331+
@Override
332+
public String getEventType() {
333+
return EventTypes.EVENT_NETWORK_CREATE;
334+
}
335+
336+
@Override
337+
public String getEventDescription() {
338+
return "Creating network";
339+
}
329340
}

core/src/main/java/com/cloud/agent/api/MigrateCommand.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public class MigrateCommand extends Command {
4040
private boolean executeInSequence = false;
4141
private List<MigrateDiskInfo> migrateDiskInfoList = new ArrayList<>();
4242
private Map<String, DpdkTO> dpdkInterfaceMapping = new HashMap<>();
43+
Map<String, Boolean> vlanToPersistenceMap;
4344

4445
public Map<String, DpdkTO> getDpdkInterfaceMapping() {
4546
return dpdkInterfaceMapping;
@@ -49,6 +50,14 @@ public void setDpdkInterfaceMapping(Map<String, DpdkTO> dpdkInterfaceMapping) {
4950
this.dpdkInterfaceMapping = dpdkInterfaceMapping;
5051
}
5152

53+
public Map<String, Boolean> getVlanToPersistenceMap() {
54+
return vlanToPersistenceMap;
55+
}
56+
57+
public void setVlanToPersistenceMap(Map<String, Boolean> vlanToPersistenceMap) {
58+
this.vlanToPersistenceMap = vlanToPersistenceMap;
59+
}
60+
5261
protected MigrateCommand() {
5362
}
5463

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package com.cloud.agent.api;
19+
20+
public class SetupPersistentNetworkAnswer extends Answer{
21+
public SetupPersistentNetworkAnswer(){}
22+
23+
public SetupPersistentNetworkAnswer(SetupPersistentNetworkCommand cmd, boolean success, String result) {
24+
super(cmd, success, result);
25+
}
26+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package com.cloud.agent.api;
19+
20+
import com.cloud.agent.api.to.NicTO;
21+
22+
public class SetupPersistentNetworkCommand extends Command{
23+
24+
NicTO nic;
25+
26+
public SetupPersistentNetworkCommand(NicTO nic) {
27+
this.nic = nic;
28+
}
29+
30+
public NicTO getNic() {
31+
return nic;
32+
}
33+
34+
protected SetupPersistentNetworkCommand() {
35+
}
36+
37+
@Override
38+
public boolean executeInSequence() {
39+
return false;
40+
}
41+
}

core/src/main/java/com/cloud/agent/api/StopCommand.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class StopCommand extends RebootCommand {
3636
String controlIp = null;
3737
boolean forceStop = false;
3838
private Map<String, DpdkTO> dpdkInterfaceMapping;
39+
Map<String, Boolean> vlanToPersistenceMap;
3940

4041
public Map<String, DpdkTO> getDpdkInterfaceMapping() {
4142
return dpdkInterfaceMapping;
@@ -129,4 +130,12 @@ public void setVolumesToDisconnect(List<Map<String, String>> volumesToDisconnect
129130
public List<Map<String, String>> getVolumesToDisconnect() {
130131
return volumesToDisconnect;
131132
}
133+
134+
public Map<String, Boolean> getVlanToPersistenceMap() {
135+
return vlanToPersistenceMap;
136+
}
137+
138+
public void setVlanToPersistenceMap(Map<String, Boolean> vlanToPersistenceMap) {
139+
this.vlanToPersistenceMap = vlanToPersistenceMap;
140+
}
132141
}

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
import javax.inject.Inject;
4141
import javax.naming.ConfigurationException;
4242

43+
import com.cloud.api.query.dao.UserVmJoinDao;
44+
import com.cloud.api.query.vo.UserVmJoinVO;
4345
import com.cloud.deployasis.dao.UserVmDeployAsIsDetailsDao;
4446
import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
4547
import org.apache.cloudstack.api.ApiConstants;
@@ -166,6 +168,7 @@
166168
import com.cloud.hypervisor.HypervisorGuruManager;
167169
import com.cloud.network.Network;
168170
import com.cloud.network.NetworkModel;
171+
import com.cloud.network.Networks;
169172
import com.cloud.network.dao.NetworkDao;
170173
import com.cloud.network.dao.NetworkDetailVO;
171174
import com.cloud.network.dao.NetworkDetailsDao;
@@ -176,6 +179,8 @@
176179
import com.cloud.offering.DiskOfferingInfo;
177180
import com.cloud.offering.NetworkOffering;
178181
import com.cloud.offering.ServiceOffering;
182+
import com.cloud.offerings.NetworkOfferingVO;
183+
import com.cloud.offerings.dao.NetworkOfferingDao;
179184
import com.cloud.offerings.dao.NetworkOfferingDetailsDao;
180185
import com.cloud.org.Cluster;
181186
import com.cloud.resource.ResourceManager;
@@ -347,6 +352,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
347352
private SecurityGroupManager _securityGroupManager;
348353
@Inject
349354
private UserVmDeployAsIsDetailsDao userVmDeployAsIsDetailsDao;
355+
@Inject
356+
private UserVmJoinDao userVmJoinDao;
357+
@Inject
358+
private NetworkOfferingDao networkOfferingDao;
350359

351360
VmWorkJobHandlerProxy _jobHandlerProxy = new VmWorkJobHandlerProxy(this);
352361

@@ -1244,6 +1253,10 @@ public void orchestrateStart(final String vmUuid, final Map<VirtualMachineProfil
12441253
}
12451254
StopCommand stopCmd = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), false);
12461255
stopCmd.setControlIp(getControlNicIpForVM(vm));
1256+
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
1257+
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
1258+
stopCmd.setVlanToPersistenceMap(vlanToPersistenceMap);
1259+
}
12471260
final StopCommand cmd = stopCmd;
12481261
final Answer answer = _agentMgr.easySend(destHostId, cmd);
12491262
if (answer != null && answer instanceof StopAnswer) {
@@ -1640,7 +1653,11 @@ private List<Map<String, String>> getVolumesToDisconnect(VirtualMachine vm) {
16401653

16411654
protected boolean sendStop(final VirtualMachineGuru guru, final VirtualMachineProfile profile, final boolean force, final boolean checkBeforeCleanup) {
16421655
final VirtualMachine vm = profile.getVirtualMachine();
1656+
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
16431657
StopCommand stpCmd = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), checkBeforeCleanup);
1658+
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
1659+
stpCmd.setVlanToPersistenceMap(vlanToPersistenceMap);
1660+
}
16441661
stpCmd.setControlIp(getControlNicIpForVM(vm));
16451662
stpCmd.setVolumesToDisconnect(getVolumesToDisconnect(vm));
16461663
final StopCommand stop = stpCmd;
@@ -1827,6 +1844,26 @@ private void orchestrateStop(final String vmUuid, final boolean cleanUpEvenIfUna
18271844
advanceStop(vm, cleanUpEvenIfUnableToStop);
18281845
}
18291846

1847+
private Map<String, Boolean> getVlanToPersistenceMapForVM(long vmId) {
1848+
List<UserVmJoinVO> userVmJoinVOS = userVmJoinDao.searchByIds(vmId);
1849+
Map<String, Boolean> vlanToPersistenceMap = new HashMap<>();
1850+
for (UserVmJoinVO userVmJoinVO : userVmJoinVOS) {
1851+
NetworkVO networkVO = _networkDao.findById(userVmJoinVO.getNetworkId());
1852+
NetworkOfferingVO offeringVO = networkOfferingDao.findById(networkVO.getNetworkOfferingId());
1853+
Pair<String, Boolean> data = getVMNetworkDetails(networkVO, offeringVO.isPersistent());
1854+
vlanToPersistenceMap.put(data.first(), data.second());
1855+
}
1856+
return vlanToPersistenceMap;
1857+
}
1858+
1859+
private Pair<String, Boolean> getVMNetworkDetails(NetworkVO networkVO, boolean isPersistent) {
1860+
URI broadcastUri = networkVO.getBroadcastUri();
1861+
String scheme = broadcastUri.getScheme();
1862+
String vlanId = Networks.BroadcastDomainType.getValue(broadcastUri);
1863+
Boolean shouldDelete = !((networkVO.getGuestType() == Network.GuestType.L2 || networkVO.getGuestType() == Network.GuestType.Isolated) && scheme.equalsIgnoreCase("vlan") && isPersistent);
1864+
return new Pair<>(vlanId, shouldDelete);
1865+
}
1866+
18301867
private void advanceStop(final VMInstanceVO vm, final boolean cleanUpEvenIfUnableToStop) throws AgentUnavailableException, OperationTimedoutException,
18311868
ConcurrentOperationException {
18321869
final State state = vm.getState();
@@ -1925,8 +1962,13 @@ private void advanceStop(final VMInstanceVO vm, final boolean cleanUpEvenIfUnabl
19251962

19261963
vmGuru.prepareStop(profile);
19271964

1965+
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
1966+
19281967
final StopCommand stop = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), false, cleanUpEvenIfUnableToStop);
19291968
stop.setControlIp(getControlNicIpForVM(vm));
1969+
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
1970+
stop.setVlanToPersistenceMap(vlanToPersistenceMap);
1971+
}
19301972

19311973
boolean stopped = false;
19321974
Answer answer = null;
@@ -2582,7 +2624,11 @@ protected void migrate(final VMInstanceVO vm, final long srcHostId, final Deploy
25822624
Map<String, DpdkTO> dpdkInterfaceMapping = null;
25832625
try {
25842626
final boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
2627+
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
25852628
final MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows, to, getExecuteInSequence(vm.getHypervisorType()));
2629+
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
2630+
mc.setVlanToPersistenceMap(vlanToPersistenceMap);
2631+
}
25862632

25872633
boolean kvmAutoConvergence = StorageManager.KvmAutoConvergence.value();
25882634
mc.setAutoConvergence(kvmAutoConvergence);
@@ -3388,6 +3434,10 @@ public Command cleanup(final VirtualMachine vm, Map<String, DpdkTO> dpdkInterfac
33883434
if (MapUtils.isNotEmpty(dpdkInterfaceMapping)) {
33893435
cmd.setDpdkInterfaceMapping(dpdkInterfaceMapping);
33903436
}
3437+
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
3438+
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
3439+
cmd.setVlanToPersistenceMap(vlanToPersistenceMap);
3440+
}
33913441
return cmd;
33923442
}
33933443

@@ -3406,6 +3456,10 @@ public Command cleanup(final String vmName) {
34063456

34073457
StopCommand cmd = new StopCommand(vmName, getExecuteInSequence(null), false);
34083458
cmd.setControlIp(getControlNicIpForVM(vm));
3459+
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
3460+
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
3461+
cmd.setVlanToPersistenceMap(vlanToPersistenceMap);
3462+
}
34093463
return cmd;
34103464
}
34113465

@@ -4192,8 +4246,12 @@ private void orchestrateMigrateForScale(final String vmUuid, final long srcHostI
41924246

41934247
boolean migrated = false;
41944248
try {
4249+
Map<String, Boolean> vlanToPersistenceMap = getVlanToPersistenceMapForVM(vm.getId());
41954250
final boolean isWindows = _guestOsCategoryDao.findById(_guestOsDao.findById(vm.getGuestOSId()).getCategoryId()).getName().equalsIgnoreCase("Windows");
41964251
final MigrateCommand mc = new MigrateCommand(vm.getInstanceName(), dest.getHost().getPrivateIpAddress(), isWindows, to, getExecuteInSequence(vm.getHypervisorType()));
4252+
if (MapUtils.isNotEmpty(vlanToPersistenceMap)) {
4253+
mc.setVlanToPersistenceMap(vlanToPersistenceMap);
4254+
}
41974255

41984256
boolean kvmAutoConvergence = StorageManager.KvmAutoConvergence.value();
41994257
mc.setAutoConvergence(kvmAutoConvergence);

0 commit comments

Comments
 (0)