@@ -76,6 +76,9 @@ type HostAgent struct {
76
76
guestAgentAliveChOnce sync.Once
77
77
78
78
showProgress bool // whether to show cloud-init progress
79
+
80
+ statusMu sync.RWMutex
81
+ currentStatus events.Status
79
82
}
80
83
81
84
type options struct {
@@ -284,6 +287,11 @@ func determineSSHLocalPort(confLocalPort int, instName, limaVersion string) (int
284
287
func (a * HostAgent ) emitEvent (_ context.Context , ev events.Event ) {
285
288
a .eventEncMu .Lock ()
286
289
defer a .eventEncMu .Unlock ()
290
+
291
+ a .statusMu .Lock ()
292
+ a .currentStatus = ev .Status
293
+ a .statusMu .Unlock ()
294
+
287
295
if ev .Time .IsZero () {
288
296
ev .Time = time .Now ()
289
297
}
@@ -292,6 +300,17 @@ func (a *HostAgent) emitEvent(_ context.Context, ev events.Event) {
292
300
}
293
301
}
294
302
303
+ func (a * HostAgent ) emitCloudInitProgressEvent (ctx context.Context , progress * events.CloudInitProgress ) {
304
+ a .statusMu .RLock ()
305
+ currentStatus := a .currentStatus
306
+ a .statusMu .RUnlock ()
307
+
308
+ currentStatus .CloudInitProgress = progress
309
+
310
+ ev := events.Event {Status : currentStatus }
311
+ a .emitEvent (ctx , ev )
312
+ }
313
+
295
314
func generatePassword (length int ) (string , error ) {
296
315
// avoid any special symbols, to make it easier to copy/paste
297
316
return password .Generate (length , length / 4 , 0 , false , false )
@@ -509,7 +528,10 @@ sudo chown -R "${USER}" /run/host-services`
509
528
if a .showProgress {
510
529
cloudInitDone := make (chan struct {})
511
530
go func () {
512
- a .watchCloudInitProgress (ctx )
531
+ timeoutCtx , cancel := context .WithTimeout (ctx , 10 * time .Minute )
532
+ defer cancel ()
533
+
534
+ a .watchCloudInitProgress (timeoutCtx )
513
535
close (cloudInitDone )
514
536
}()
515
537
@@ -816,15 +838,21 @@ func forwardSSH(ctx context.Context, sshConfig *ssh.SSHConfig, port int, local,
816
838
}
817
839
818
840
func (a * HostAgent ) watchCloudInitProgress (ctx context.Context ) {
841
+ exitReason := "Cloud-init monitoring completed successfully"
842
+
843
+ defer func () {
844
+ a .emitCloudInitProgressEvent (context .Background (), & events.CloudInitProgress {
845
+ Active : false ,
846
+ Completed : true ,
847
+ LogLine : exitReason ,
848
+ })
849
+ logrus .Debug ("Cloud-init progress monitoring completed" )
850
+ }()
851
+
819
852
logrus .Debug ("Starting cloud-init progress monitoring" )
820
853
821
- a .emitEvent (ctx , events.Event {
822
- Status : events.Status {
823
- SSHLocalPort : a .sshLocalPort ,
824
- CloudInitProgress : & events.CloudInitProgress {
825
- Active : true ,
826
- },
827
- },
854
+ a .emitCloudInitProgressEvent (ctx , & events.CloudInitProgress {
855
+ Active : true ,
828
856
})
829
857
830
858
maxRetries := 30
@@ -866,11 +894,13 @@ func (a *HostAgent) watchCloudInitProgress(ctx context.Context) {
866
894
stdout , err := cmd .StdoutPipe ()
867
895
if err != nil {
868
896
logrus .WithError (err ).Warn ("Failed to create stdout pipe for cloud-init monitoring" )
897
+ exitReason = "Failed to create stdout pipe for cloud-init monitoring"
869
898
return
870
899
}
871
900
872
901
if err := cmd .Start (); err != nil {
873
902
logrus .WithError (err ).Warn ("Failed to start cloud-init monitoring command" )
903
+ exitReason = "Failed to start cloud-init monitoring command"
874
904
return
875
905
}
876
906
@@ -883,23 +913,31 @@ func (a *HostAgent) watchCloudInitProgress(ctx context.Context) {
883
913
continue
884
914
}
885
915
886
- if strings .Contains (line , "Cloud-init" ) && strings .Contains (line , "finished" ) {
887
- cloudInitFinished = true
916
+ if ! cloudInitFinished {
917
+ if isCloudInitFinished (line ) {
918
+ logrus .Debug ("Cloud-init completion detected via log pattern" )
919
+ cloudInitFinished = true
920
+ }
888
921
}
889
922
890
- a .emitEvent (ctx , events.Event {
891
- Status : events.Status {
892
- SSHLocalPort : a .sshLocalPort ,
893
- CloudInitProgress : & events.CloudInitProgress {
894
- Active : ! cloudInitFinished ,
895
- LogLine : line ,
896
- Completed : cloudInitFinished ,
897
- },
898
- },
923
+ a .emitCloudInitProgressEvent (ctx , & events.CloudInitProgress {
924
+ Active : ! cloudInitFinished ,
925
+ LogLine : line ,
926
+ Completed : cloudInitFinished ,
899
927
})
928
+
929
+ if cloudInitFinished {
930
+ logrus .Debug ("Breaking from cloud-init monitoring loop - completion detected" )
931
+ break
932
+ }
900
933
}
901
934
902
935
if err := cmd .Wait (); err != nil {
936
+ if ctx .Err () == context .DeadlineExceeded {
937
+ logrus .Warn ("Cloud-init monitoring timed out after 10 minutes" )
938
+ exitReason = "Cloud-init monitoring timed out after 10 minutes"
939
+ return
940
+ }
903
941
logrus .WithError (err ).Debug ("SSH command finished (expected when cloud-init completes)" )
904
942
}
905
943
@@ -918,36 +956,24 @@ func (a *HostAgent) watchCloudInitProgress(ctx context.Context) {
918
956
lines := strings .Split (string (finalOutput ), "\n " )
919
957
for _ , line := range lines {
920
958
if strings .TrimSpace (line ) != "" {
921
- if strings . Contains ( line , "Cloud-init" ) && strings . Contains ( line , "finished" ) {
922
- cloudInitFinished = true
959
+ if ! cloudInitFinished {
960
+ cloudInitFinished = isCloudInitFinished ( line )
923
961
}
924
962
925
- a .emitEvent (ctx , events.Event {
926
- Status : events.Status {
927
- SSHLocalPort : a .sshLocalPort ,
928
- CloudInitProgress : & events.CloudInitProgress {
929
- Active : ! cloudInitFinished ,
930
- LogLine : line ,
931
- Completed : cloudInitFinished ,
932
- },
933
- },
963
+ a .emitCloudInitProgressEvent (ctx , & events.CloudInitProgress {
964
+ Active : ! cloudInitFinished ,
965
+ LogLine : line ,
966
+ Completed : cloudInitFinished ,
934
967
})
935
968
}
936
969
}
937
970
}
938
971
}
972
+ }
939
973
940
- a .emitEvent (ctx , events.Event {
941
- Status : events.Status {
942
- SSHLocalPort : a .sshLocalPort ,
943
- CloudInitProgress : & events.CloudInitProgress {
944
- Active : false ,
945
- Completed : true ,
946
- },
947
- },
948
- })
949
-
950
- logrus .Debug ("Cloud-init progress monitoring completed" )
974
+ func isCloudInitFinished (line string ) bool {
975
+ line = strings .ToLower (strings .TrimSpace (line ))
976
+ return strings .Contains (line , "cloud-init" ) && strings .Contains (line , "finished" )
951
977
}
952
978
953
979
func copyToHost (ctx context.Context , sshConfig * ssh.SSHConfig , port int , local , remote string ) error {
0 commit comments