1616// under the License.
1717package com .cloud .agent .manager ;
1818
19+ import java .util .ArrayList ;
1920import java .util .HashMap ;
2021import java .util .List ;
2122import java .util .Map ;
7576import com .cloud .agent .api .to .NicTO ;
7677import com .cloud .agent .api .to .VirtualMachineTO ;
7778import 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 ;
7981import com .cloud .simulator .MockHost ;
8082import com .cloud .simulator .MockSecurityRulesVO ;
8183import com .cloud .simulator .MockVMVO ;
8688import com .cloud .utils .Pair ;
8789import com .cloud .utils .Ternary ;
8890import com .cloud .utils .component .ManagerBase ;
91+ import com .cloud .utils .db .SearchBuilder ;
92+ import com .cloud .utils .db .SearchCriteria ;
8993import com .cloud .utils .db .TransactionLegacy ;
94+ import com .cloud .utils .db .SearchCriteria .Func ;
9095import com .cloud .utils .exception .CloudRuntimeException ;
96+ import com .cloud .vm .DomainRouterVO ;
9197import com .cloud .vm .VirtualMachine .PowerState ;
98+ import com .cloud .vm .dao .DomainRouterDao ;
9299
93100@ Component
94101public 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