Skip to content

Commit d868cd1

Browse files
richardlawleyandrijapanicsb
authored andcommitted
Simulator: Better VR Redundant Status Behaviour (#3313)
* Make VRs change redundant status in simulator with start/stop/reboot * Prevent getMockRouters returning null elements
1 parent 74f5632 commit d868cd1

1 file changed

Lines changed: 199 additions & 44 deletions

File tree

plugins/hypervisors/simulator/src/main/java/com/cloud/agent/manager/MockVmManagerImpl.java

Lines changed: 199 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// under the License.
1717
package com.cloud.agent.manager;
1818

19+
import java.util.ArrayList;
1920
import java.util.HashMap;
2021
import java.util.List;
2122
import java.util.Map;
@@ -75,7 +76,8 @@
7576
import com.cloud.agent.api.to.NicTO;
7677
import com.cloud.agent.api.to.VirtualMachineTO;
7778
import com.cloud.network.Networks.TrafficType;
78-
import com.cloud.network.router.VirtualRouter;
79+
import com.cloud.network.dao.NetworkDao;
80+
import com.cloud.network.router.VirtualRouter.Role;
7981
import com.cloud.simulator.MockHost;
8082
import com.cloud.simulator.MockSecurityRulesVO;
8183
import com.cloud.simulator.MockVMVO;
@@ -86,9 +88,14 @@
8688
import com.cloud.utils.Pair;
8789
import com.cloud.utils.Ternary;
8890
import com.cloud.utils.component.ManagerBase;
91+
import com.cloud.utils.db.SearchBuilder;
92+
import com.cloud.utils.db.SearchCriteria;
8993
import com.cloud.utils.db.TransactionLegacy;
94+
import com.cloud.utils.db.SearchCriteria.Func;
9095
import com.cloud.utils.exception.CloudRuntimeException;
96+
import com.cloud.vm.DomainRouterVO;
9197
import com.cloud.vm.VirtualMachine.PowerState;
98+
import com.cloud.vm.dao.DomainRouterDao;
9299

93100
@Component
94101
public class MockVmManagerImpl extends ManagerBase implements MockVmManager {
@@ -102,6 +109,10 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager {
102109
MockHostDao _mockHostDao = null;
103110
@Inject
104111
MockSecurityRulesDao _mockSecurityDao = null;
112+
@Inject
113+
DomainRouterDao _routerDao = null;
114+
@Inject
115+
NetworkDao _networkDao = null;
105116
private final Map<String, Map<String, Ternary<String, Long, Long>>> _securityRules = new ConcurrentHashMap<String, Map<String, Ternary<String, Long, Long>>>();
106117

107118
public MockVmManagerImpl() {
@@ -190,44 +201,51 @@ public String startVM(final String vmName, final NicTO[] nics, final int cpuHz,
190201
}
191202
}
192203

193-
if (vm.getPowerState() == PowerState.PowerOn && vmName.startsWith("s-")) {
194-
String prvIp = null;
195-
String prvMac = null;
196-
String prvNetMask = null;
204+
if (vm.getPowerState() == PowerState.PowerOn) {
197205

198-
for (final NicTO nic : nics) {
199-
if (nic.getType() == TrafficType.Management) {
200-
prvIp = nic.getIp();
201-
prvMac = nic.getMac();
202-
prvNetMask = nic.getNetmask();
206+
if (vmName.startsWith("s-")) {
207+
String prvIp = null;
208+
String prvMac = null;
209+
String prvNetMask = null;
210+
211+
for (final NicTO nic : nics) {
212+
if (nic.getType() == TrafficType.Management) {
213+
prvIp = nic.getIp();
214+
prvMac = nic.getMac();
215+
prvNetMask = nic.getNetmask();
216+
}
203217
}
204-
}
205-
long dcId = 0;
206-
long podId = 0;
207-
String name = null;
208-
String vmType = null;
209-
String url = null;
210-
final String[] args = bootArgs.trim().split(" ");
211-
for (final String arg : args) {
212-
final String[] params = arg.split("=");
213-
if (params.length < 1) {
214-
continue;
218+
long dcId = 0;
219+
long podId = 0;
220+
String name = null;
221+
String vmType = null;
222+
String url = null;
223+
final String[] args = bootArgs.trim().split(" ");
224+
for (final String arg : args) {
225+
final String[] params = arg.split("=");
226+
if (params.length < 1) {
227+
continue;
228+
}
229+
230+
if (params[0].equalsIgnoreCase("zone")) {
231+
dcId = Long.parseLong(params[1]);
232+
} else if (params[0].equalsIgnoreCase("name")) {
233+
name = params[1];
234+
} else if (params[0].equalsIgnoreCase("type")) {
235+
vmType = params[1];
236+
} else if (params[0].equalsIgnoreCase("url")) {
237+
url = params[1];
238+
} else if (params[0].equalsIgnoreCase("pod")) {
239+
podId = Long.parseLong(params[1]);
240+
}
215241
}
216242

217-
if (params[0].equalsIgnoreCase("zone")) {
218-
dcId = Long.parseLong(params[1]);
219-
} else if (params[0].equalsIgnoreCase("name")) {
220-
name = params[1];
221-
} else if (params[0].equalsIgnoreCase("type")) {
222-
vmType = params[1];
223-
} else if (params[0].equalsIgnoreCase("url")) {
224-
url = params[1];
225-
} else if (params[0].equalsIgnoreCase("pod")) {
226-
podId = Long.parseLong(params[1]);
227-
}
243+
_mockAgentMgr.handleSystemVMStart(vm.getId(), prvIp, prvMac, prvNetMask, dcId, podId, name, vmType, url);
228244
}
229245

230-
_mockAgentMgr.handleSystemVMStart(vm.getId(), prvIp, prvMac, prvNetMask, dcId, podId, name, vmType, url);
246+
if (vmName.startsWith("r-") && bootArgs.indexOf("redundant_router=1") > 0) {
247+
handleRouterStartStop(vmName, true);
248+
}
231249
}
232250

233251
return null;
@@ -260,17 +278,14 @@ public CheckRouterAnswer checkRouter(final CheckRouterCommand cmd) {
260278
final String router_name = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME);
261279
final MockVm vm = _mockVmDao.findByVmName(router_name);
262280
final String args = vm.getBootargs();
263-
if (args.indexOf("router_pr=100") > 0) {
264-
s_logger.debug("Router priority is for MASTER");
265-
final CheckRouterAnswer ans = new CheckRouterAnswer(cmd, "Status: MASTER", true);
266-
ans.setState(VirtualRouter.RedundantState.MASTER);
267-
return ans;
268-
} else {
269-
s_logger.debug("Router priority is for BACKUP");
270-
final CheckRouterAnswer ans = new CheckRouterAnswer(cmd, "Status: BACKUP", true);
271-
ans.setState(VirtualRouter.RedundantState.BACKUP);
272-
return ans;
281+
282+
String state = "UNKNOWN";
283+
if (args.indexOf("redundant_router=1") > 0) {
284+
state = getRedundantState(vm);
273285
}
286+
287+
final CheckRouterAnswer ans = new CheckRouterAnswer(cmd, "Status: " + state, true);
288+
return ans;
274289
}
275290

276291
@Override
@@ -512,10 +527,10 @@ public Answer revertVmSnapshot(final RevertToVMSnapshotCommand cmd) {
512527

513528
@Override
514529
public StopAnswer stopVM(final StopCommand cmd) {
530+
final String vmName = cmd.getVmName();
515531
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.SIMULATOR_DB);
516532
try {
517533
txn.start();
518-
final String vmName = cmd.getVmName();
519534
final MockVm vm = _mockVmDao.findByVmName(vmName);
520535
if (vm != null) {
521536
vm.setPowerState(PowerState.PowerOff);
@@ -525,7 +540,16 @@ public StopAnswer stopVM(final StopCommand cmd) {
525540
if (vmName.startsWith("s-")) {
526541
_mockAgentMgr.handleSystemVMStop(vm.getId());
527542
}
543+
528544
txn.commit();
545+
txn.close();
546+
txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
547+
txn.close();
548+
549+
if (vmName.startsWith("r-")) {
550+
handleRouterStartStop(vmName, false);
551+
}
552+
529553
return new StopAnswer(cmd, null, true);
530554
} catch (final Exception ex) {
531555
txn.rollback();
@@ -539,6 +563,13 @@ public StopAnswer stopVM(final StopCommand cmd) {
539563

540564
@Override
541565
public RebootAnswer rebootVM(final RebootCommand cmd) {
566+
567+
String vmName = cmd.getVmName();
568+
if (vmName.startsWith("r-")) {
569+
handleRouterStartStop(vmName, false);
570+
handleRouterStartStop(vmName, true);
571+
}
572+
542573
return new RebootAnswer(cmd, "Rebooted " + cmd.getVmName(), true);
543574
}
544575

@@ -654,4 +685,128 @@ public HashMap<String, Pair<Long, Long>> syncNetworkGroups(final SimulatorInfo i
654685
public Answer fence(final FenceCommand cmd) {
655686
return new FenceAnswer(cmd);
656687
}
688+
689+
private void handleRouterStartStop(String vrName, Boolean start) {
690+
SearchBuilder<DomainRouterVO> sb = _routerDao.createSearchBuilder();
691+
sb.select(null, Func.DISTINCT, sb.entity().getId());
692+
sb.and("name", sb.entity().getInstanceName(), SearchCriteria.Op.EQ);
693+
SearchCriteria<DomainRouterVO> sc = sb.create();
694+
sc.setParameters("name", vrName);
695+
696+
DomainRouterVO router = _routerDao.findOneBy(sc);
697+
List<Long> networkIds = _routerDao.getRouterNetworks(router.getId());
698+
if (networkIds.size() == 0) {
699+
throw new CloudRuntimeException("Could not find a network for VR " + vrName);
700+
}
701+
702+
List<MockVm> vrs = getMockRouters(networkIds.get(0));
703+
MockVm vm = vrs.stream().filter(v -> v.getName().equalsIgnoreCase(vrName)).findFirst().get();
704+
String currentRedundantState = getRedundantState(vm);
705+
706+
if (start) {
707+
// If no master found, make us the master
708+
Boolean foundMaster = vrs.stream()
709+
.filter(v -> !v.getName().equals(vrName)
710+
&& v.getPowerState() == PowerState.PowerOn
711+
&& getRedundantState(v).equalsIgnoreCase("MASTER"))
712+
.findFirst()
713+
.isPresent();
714+
715+
if (!foundMaster) {
716+
if (!currentRedundantState.equalsIgnoreCase("MASTER")) {
717+
// There are no MASTER routers on this network - make this master instead
718+
updateRedundantState(vm, "MASTER");
719+
s_logger.debug("Promoted " + vm.getName() + " to MASTER");
720+
}
721+
} else if (!currentRedundantState.equals("BACKUP")) {
722+
updateRedundantState(vm, "BACKUP");
723+
s_logger.debug("Demoted " + vm.getName() + " to BACKUP");
724+
}
725+
726+
} else {
727+
// If we were master, make someone else
728+
if (currentRedundantState.equals("MASTER")) {
729+
// Need to make something else master..
730+
MockVm backupVr = vrs.stream()
731+
.filter(v -> !v.getName().equals(vrName)
732+
&& v.getPowerState() == PowerState.PowerOn
733+
&& getRedundantState(v).equalsIgnoreCase("BACKUP"))
734+
.findFirst()
735+
.orElse(null);
736+
if (backupVr != null) {
737+
updateRedundantState(backupVr, "MASTER");
738+
s_logger.debug("Promoted " + backupVr.getName() + " to MASTER");
739+
}
740+
updateRedundantState(vm, "BACKUP");
741+
s_logger.debug("Demoted " + vm.getName() + " to BACKUP");
742+
}
743+
}
744+
}
745+
746+
private List<MockVm> getMockRouters(Long networkId) {
747+
748+
List<DomainRouterVO> routers = _routerDao.listByNetworkAndRole(networkId, Role.VIRTUAL_ROUTER);
749+
if (routers.size() == 0) {
750+
throw new CloudRuntimeException("Didn't find any Virtual Routers on " + networkId);
751+
}
752+
753+
ArrayList<MockVm> vrs = new ArrayList<MockVm>();
754+
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.SIMULATOR_DB);
755+
try {
756+
txn.close();
757+
758+
for (final DomainRouterVO router : routers) {
759+
MockVm v = _mockVmDao.findByVmName(router.getInstanceName());
760+
if (v != null) {
761+
vrs.add(v);
762+
}
763+
}
764+
} finally {
765+
txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
766+
txn.close();
767+
}
768+
769+
return vrs;
770+
}
771+
772+
private String getRedundantState(MockVm vm) {
773+
String state = "UNKNOWN";
774+
for (final String arg : vm.getBootargs().trim().split(" ")) {
775+
final String[] params = arg.split("=");
776+
if (params.length < 1) {
777+
continue;
778+
}
779+
if (params[0].equalsIgnoreCase("redundant_state")) {
780+
state = params[1];
781+
}
782+
}
783+
return state;
784+
}
785+
786+
private void updateRedundantState(MockVm vm, String newState) {
787+
// Replace the current state
788+
ArrayList<String> args = new ArrayList<String>();
789+
for (final String arg : vm.getBootargs().trim().split(" ")) {
790+
if (arg.startsWith("redundant_state=")) {
791+
args.add("redundant_state=" + newState);
792+
} else {
793+
args.add(arg);
794+
}
795+
}
796+
vm.setBootargs(" " + String.join(" ", args));
797+
798+
TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.SIMULATOR_DB);
799+
try {
800+
txn.start();
801+
_mockVmDao.update(vm.getId(), (MockVMVO)vm);
802+
txn.commit();
803+
} catch (final Exception ex) {
804+
txn.rollback();
805+
throw new CloudRuntimeException("unable to update vm " + vm.getName(), ex);
806+
} finally {
807+
txn.close();
808+
txn = TransactionLegacy.open(TransactionLegacy.CLOUD_DB);
809+
txn.close();
810+
}
811+
}
657812
}

0 commit comments

Comments
 (0)