125125import com .cloud .utils .db .GlobalLock ;
126126import com .cloud .utils .db .Transaction ;
127127import com .cloud .utils .exception .CloudRuntimeException ;
128- import com .cloud .utils .fsm .StateListener ;
129128import com .cloud .utils .fsm .StateMachine2 ;
130129import com .cloud .vm .ItWorkVO .Step ;
131130import com .cloud .vm .VirtualMachine .Event ;
@@ -261,60 +260,6 @@ public <T extends VMInstanceVO> T allocate(T vm,
261260 return vm ;
262261 }
263262
264-
265-
266- protected void reserveNics (VirtualMachineProfile <? extends VMInstanceVO > vmProfile , DeployDestination dest , ReservationContext context ) throws InsufficientCapacityException , ConcurrentOperationException , ResourceUnavailableException {
267- // List<NicVO> nics = _nicsDao.listBy(vmProfile.getId());
268- // for (NicVO nic : nics) {
269- // Pair<NetworkGuru, NetworkVO> implemented = _networkMgr.implementNetwork(nic.getNetworkId(), dest, context);
270- // NetworkGuru concierge = implemented.first();
271- // NetworkVO network = implemented.second();
272- // NicProfile profile = null;
273- // if (nic.getReservationStrategy() == ReservationStrategy.Start) {
274- // nic.setState(Resource.State.Reserving);
275- // nic.setReservationId(context.getReservationId());
276- // _nicsDao.update(nic.getId(), nic);
277- // URI broadcastUri = nic.getBroadcastUri();
278- // if (broadcastUri == null) {
279- // network.getBroadcastUri();
280- // }
281- //
282- // URI isolationUri = nic.getIsolationUri();
283- //
284- // profile = new NicProfile(nic, network, broadcastUri, isolationUri);
285- // concierge.reserve(profile, network, vmProfile, dest, context);
286- // nic.setIp4Address(profile.getIp4Address());
287- // nic.setIp6Address(profile.getIp6Address());
288- // nic.setMacAddress(profile.getMacAddress());
289- // nic.setIsolationUri(profile.getIsolationUri());
290- // nic.setBroadcastUri(profile.getBroadCastUri());
291- // nic.setReserver(concierge.getName());
292- // nic.setState(Resource.State.Reserved);
293- // nic.setNetmask(profile.getNetmask());
294- // nic.setGateway(profile.getGateway());
295- // nic.setAddressFormat(profile.getFormat());
296- // _nicsDao.update(nic.getId(), nic);
297- // } else {
298- // profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri());
299- // }
300- //
301- // for (NetworkElement element : _networkElements) {
302- // if (s_logger.isDebugEnabled()) {
303- // s_logger.debug("Asking " + element.getName() + " to prepare for " + nic);
304- // }
305- // element.prepare(network, profile, vmProfile, dest, context);
306- // }
307- //
308- // vmProfile.addNic(profile);
309- // _networksDao.changeActiveNicsBy(network.getId(), 1);
310- // }
311- }
312-
313- protected void prepareNics (VirtualMachineProfile <? extends VMInstanceVO > vmProfile , DeployDestination dest , ReservationContext context ) {
314-
315- }
316-
317-
318263 @ Override
319264 public <T extends VMInstanceVO > T allocate (T vm ,
320265 VMTemplateVO template ,
@@ -353,7 +298,7 @@ public <T extends VMInstanceVO> boolean expunge(T vm, User caller, Account accou
353298 try {
354299 if (advanceExpunge (vm , caller , account )) {
355300 //Mark vms as removed
356- remove (vm , _accountMgr . getSystemUser () , account );
301+ remove (vm , caller , account );
357302 return true ;
358303 } else {
359304 s_logger .info ("Did not expunge " + vm );
@@ -507,7 +452,7 @@ protected boolean checkWorkItems(VMInstanceVO vm, State state) throws Concurrent
507452 protected <T extends VMInstanceVO > Ternary <T , ReservationContext , ItWorkVO > changeToStartState (VirtualMachineGuru <T > vmGuru , T vm , User caller , Account account ) throws ConcurrentOperationException {
508453 long vmId = vm .getId ();
509454
510- ItWorkVO work = new ItWorkVO (UUID .randomUUID ().toString (), _nodeId , State .Starting , vm .getId ());
455+ ItWorkVO work = new ItWorkVO (UUID .randomUUID ().toString (), _nodeId , State .Starting , vm .getType (), vm . getId ());
511456 int retry = _lockStateRetry ;
512457 while (retry -- != 0 ) {
513458 Transaction txn = Transaction .currentTxn ();
@@ -643,7 +588,7 @@ public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.P
643588 if (work == null || work .getStep () != Step .Prepare ) {
644589 throw new ConcurrentOperationException ("Work steps have been changed: " + work );
645590 }
646- _workDao .updateStep (work , Step .Start );
591+ _workDao .updateStep (work , Step .Starting );
647592
648593 _agentMgr .send (destHostId , cmds );
649594 _workDao .updateStep (work , Step .Started );
@@ -749,12 +694,12 @@ protected <T extends VMInstanceVO> boolean cleanup(VirtualMachineGuru<T> guru, V
749694 s_logger .debug ("Cleaning up resources for the vm " + vm + " in " + state + " state" );
750695 if (state == State .Starting ) {
751696 Step step = work .getStep ();
752- if (step == Step .Start && !force ) {
697+ if (step == Step .Starting && !force ) {
753698 s_logger .warn ("Unable to cleanup vm " + vm + "; work state is incorrect: " + step );
754699 return false ;
755700 }
756701
757- if (step == Step .Started || step == Step .Start ) {
702+ if (step == Step .Started || step == Step .Starting ) {
758703 if (vm .getHostId () != null ) {
759704 if (!sendStop (guru , profile , force )) {
760705 s_logger .warn ("Failed to stop vm " + vm + " in " + State .Starting + " state as a part of cleanup process" );
@@ -763,7 +708,7 @@ protected <T extends VMInstanceVO> boolean cleanup(VirtualMachineGuru<T> guru, V
763708 }
764709 }
765710
766- if (step != Step .Release && step != Step .Prepare && step != Step .Started && step != Step .Start ) {
711+ if (step != Step .Release && step != Step .Prepare && step != Step .Started && step != Step .Starting ) {
767712 s_logger .debug ("Cleanup is not needed for vm " + vm + "; work state is incorrect: " + step );
768713 return true ;
769714 }
@@ -950,6 +895,14 @@ public <T extends VMInstanceVO> boolean destroy(T vm, User user, Account caller)
950895 return true ;
951896 }
952897
898+ protected boolean checkVmOnHost (VirtualMachine vm , long hostId ) throws AgentUnavailableException , OperationTimedoutException {
899+ CheckVirtualMachineAnswer answer = (CheckVirtualMachineAnswer )_agentMgr .send (hostId , new CheckVirtualMachineCommand (vm .getInstanceName ()));
900+ if (!answer .getResult () || answer .getState () == State .Stopped ) {
901+ return false ;
902+ }
903+
904+ return true ;
905+ }
953906
954907 @ Override
955908 public <T extends VMInstanceVO > T migrate (T vm , long srcHostId , DeployDestination dest ) throws ResourceUnavailableException {
@@ -964,7 +917,7 @@ public <T extends VMInstanceVO> T migrate(T vm, long srcHostId, DeployDestinatio
964917 VirtualMachineGuru <T > vmGuru = getVmGuru (vm );
965918
966919 vm = vmGuru .findById (vm .getId ());
967- if (vm == null || vm . getRemoved () != null ) {
920+ if (vm == null ) {
968921 if (s_logger .isDebugEnabled ()) {
969922 s_logger .debug ("Unable to find the vm " + vm );
970923 }
@@ -986,69 +939,80 @@ public <T extends VMInstanceVO> T migrate(T vm, long srcHostId, DeployDestinatio
986939 VirtualMachineTO to = hvGuru .implement (profile );
987940 PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand (to );
988941
989- PrepareForMigrationAnswer pfma ;
942+ ItWorkVO work = new ItWorkVO (UUID .randomUUID ().toString (), _nodeId , State .Migrating , vm .getType (), vm .getId ());
943+ work .setStep (Step .Prepare );
944+ work .setResourceType (ItWorkVO .ResourceType .Host );
945+ work .setResourceId (dstHostId );
946+ _workDao .persist (work );
947+
948+ PrepareForMigrationAnswer pfma = null ;
990949 try {
991950 pfma = (PrepareForMigrationAnswer )_agentMgr .send (dstHostId , pfmc );
951+ if (!pfma .getResult ()) {
952+ String msg = "Unable to prepare for migration due to " + pfma .getDetails ();
953+ pfma = null ;
954+ throw new AgentUnavailableException (msg , dstHostId );
955+ }
992956 } catch (OperationTimedoutException e1 ) {
993957 throw new AgentUnavailableException ("Operation timed out" , dstHostId );
958+ } finally {
959+ if (pfma == null ) {
960+ work .setStep (Step .Done );
961+ _workDao .update (work .getId (), work );
962+ }
994963 }
995- if (!pfma .getResult ()) {
996- throw new AgentUnavailableException (pfma .getDetails (), dstHostId );
997- }
964+
965+ vm .setLastHostId (srcHostId );
966+ if (vm == null || vm .getHostId () == null || vm .getHostId () != srcHostId || !changeState (vm , Event .MigrationRequested , dstHostId , work , Step .Migrating )) {
967+ s_logger .info ("Migration cancelled because state has changed: " + vm );
968+ return null ;
969+ }
998970
999971 boolean migrated = false ;
1000972 try {
1001- vm .setLastHostId (srcHostId );
1002- if (vm == null || vm .getRemoved () != null || vm .getHostId () == null || vm .getHostId () != srcHostId || !stateTransitTo (vm , Event .MigrationRequested , dstHostId )) {
1003- s_logger .info ("Migration cancelled because state has changed: " + vm );
1004- return null ;
1005- }
1006-
1007973 boolean isWindows = _guestOsCategoryDao .findById (_guestOsDao .findById (vm .getGuestOSId ()).getCategoryId ()).getName ().equalsIgnoreCase ("Windows" );
1008974 MigrateCommand mc = new MigrateCommand (vm .getInstanceName (), dest .getHost ().getPrivateIpAddress (), isWindows );
1009- MigrateAnswer ma = (MigrateAnswer )_agentMgr .send (vm .getLastHostId (), mc );
1010- if (!ma .getResult ()) {
1011- return null ;
975+ try {
976+ MigrateAnswer ma = (MigrateAnswer )_agentMgr .send (vm .getLastHostId (), mc );
977+ if (!ma .getResult ()) {
978+ s_logger .error ("Unable to migrate due to " + ma .getDetails ());
979+ return null ;
980+ }
981+ } catch (OperationTimedoutException e ) {
982+ if (e .isActive ()) {
983+ s_logger .warn ("Active migration command so scheduling a restart for " + vm );
984+ _haMgr .scheduleRestart (vm , true );
985+ }
986+ throw new AgentUnavailableException ("Operation timed out on migrating " + vm , dstHostId );
1012987 }
1013- Commands cmds = new Commands (OnError .Revert );
1014- CheckVirtualMachineCommand cvm = new CheckVirtualMachineCommand (vm .getInstanceName ());
1015- cmds .addCommand (cvm );
1016988
1017- _agentMgr .send (dstHostId , cmds );
1018- CheckVirtualMachineAnswer answer = cmds .getAnswer (CheckVirtualMachineAnswer .class );
1019- if (!answer .getResult ()) {
1020- s_logger .debug ("Unable to complete migration for " + vm .toString ());
1021- stateTransitTo (vm , VirtualMachine .Event .AgentReportStopped , null );
1022- return null ;
1023- }
1024-
1025- State state = answer .getState ();
1026- if (state == State .Stopped ) {
1027- s_logger .warn ("Unable to complete migration as we can not detect it on " + dest .getHost ());
1028- stateTransitTo (vm , VirtualMachine .Event .AgentReportStopped , null );
1029- return null ;
989+ changeState (vm , VirtualMachine .Event .OperationSucceeded , dstHostId , work , Step .Started );
990+
991+ try {
992+ if (!checkVmOnHost (vm , dstHostId )) {
993+ s_logger .error ("Unable to complete migration for " + vm );
994+ _agentMgr .send (srcHostId , new Commands (cleanup (vm .getInstanceName ())), null );
995+ cleanup (vmGuru , new VirtualMachineProfileImpl <T >(vm ), work , Event .AgentReportStopped , true , _accountMgr .getSystemUser (), _accountMgr .getSystemAccount ());
996+ return null ;
997+ }
998+ } catch (OperationTimedoutException e ) {
1030999 }
1031-
1032- stateTransitTo (vm , VirtualMachine .Event .OperationSucceeded , dstHostId );
1000+
10331001 migrated = true ;
10341002 return vm ;
1035- } catch (final OperationTimedoutException e ) {
1036- s_logger .debug ("operation timed out" );
1037- if (e .isActive ()) {
1038- // FIXME: scheduleRestart(vm, true);
1039- }
1040- throw new AgentUnavailableException ("Operation timed out: " , dstHostId );
10411003 } finally {
10421004 if (!migrated ) {
10431005 s_logger .info ("Migration was unsuccessful. Cleaning up: " + vm );
10441006
10451007 _alertMgr .sendAlert (alertType , fromHost .getDataCenterId (), fromHost .getPodId (), "Unable to migrate vm " + vm .getName () + " from host " + fromHost .getName () + " in zone " + dest .getDataCenter ().getName () + " and pod " + dest .getPod ().getName (), "Migrate Command failed. Please check logs." );
10461008
1047- stateTransitTo ( vm , Event . MigrationFailedOnSource , srcHostId );
1009+ _agentMgr . send ( dstHostId , new Commands ( cleanup ( vm . getInstanceName ())), null );
10481010
1049- Command cleanup = cleanup (vm .getInstanceName ());
1050- _agentMgr .easySend (dstHostId , cleanup );
1011+ stateTransitTo (vm , Event .OperationFailed , srcHostId );
10511012 }
1013+
1014+ work .setStep (Step .Done );
1015+ _workDao .update (work .getId (), work );
10521016 }
10531017 }
10541018
@@ -1199,7 +1163,6 @@ public <T extends VMInstanceVO> T advanceReboot(T vm, Map<VirtualMachineProfile.
11991163 return rebootedVm ;
12001164 }
12011165
1202-
12031166 @ Override
12041167 public VMInstanceVO findById (VirtualMachine .Type type , long vmId ) {
12051168 VirtualMachineGuru <? extends VMInstanceVO > guru = _vmGurus .get (type );
0 commit comments