@@ -34,6 +34,10 @@ var applicationsSeed *apiseed.Applications
3434
3535var incusSeed * apiseed.Incus
3636
37+ var migrationManagerSeed * apiseed.MigrationManager
38+
39+ var operationsCenterSeed * apiseed.OperationsCenter
40+
3741var installSeed * apiseed.Install
3842
3943var networkSeed * apiseed.Network
@@ -199,6 +203,20 @@ func mainMenu(ctx context.Context, asker ask.Asker, imageFilename string) error
199203 menuSelectionOptions = append (menuSelectionOptions , strconv .Itoa (len (menuOptions )))
200204 }
201205
206+ if applicationsSeed != nil && slices .ContainsFunc (applicationsSeed .Applications , func (a apiseed.Application ) bool {
207+ return a .Name == "migration-manager"
208+ }) {
209+ menuOptions = append (menuOptions , "Configure Migration Manager seed" )
210+ menuSelectionOptions = append (menuSelectionOptions , strconv .Itoa (len (menuOptions )))
211+ }
212+
213+ if applicationsSeed != nil && slices .ContainsFunc (applicationsSeed .Applications , func (a apiseed.Application ) bool {
214+ return a .Name == "operations-center"
215+ }) {
216+ menuOptions = append (menuOptions , "Configure Operations Center seed" )
217+ menuSelectionOptions = append (menuSelectionOptions , strconv .Itoa (len (menuOptions )))
218+ }
219+
202220 menuOptions = append (menuOptions , "Write image and exit" )
203221 menuSelectionOptions = append (menuSelectionOptions , strconv .Itoa (len (menuOptions )))
204222
@@ -240,6 +258,16 @@ func mainMenu(ctx context.Context, asker ask.Asker, imageFilename string) error
240258 if err != nil {
241259 return err
242260 }
261+ case "Configure Migration Manager seed" :
262+ err := configureMigrationManagerSeed (ctx )
263+ if err != nil {
264+ return err
265+ }
266+ case "Configure Operations Center seed" :
267+ err := configureOperationsCenterSeed (ctx )
268+ if err != nil {
269+ return err
270+ }
243271 case "Write image and exit" :
244272 return writeImage (asker , imageFilename )
245273 default :
@@ -307,17 +335,63 @@ func toggleInstallRunningMode(ctx context.Context, asker ask.Asker, imageFilenam
307335}
308336
309337func selectApplications (asker ask.Asker ) error {
310- installIncus , err := asker .AskBool ("Install Incus? [Y/n] " , "y" )
338+ menuOptions := []string {"Incus" , "Migration Manager" , "Operations Center" , "None" }
339+
340+ var menuPrompt strings.Builder
341+
342+ _ , _ = menuPrompt .WriteString ("\n Application selection:\n " )
343+ for i := range menuOptions {
344+ _ , _ = menuPrompt .WriteString (fmt .Sprintf ("%d) %s\n " , i + 1 , menuOptions [i ]))
345+ }
346+
347+ _ , _ = menuPrompt .WriteString ("\n Selection: " )
348+
349+ // Prompt the user for a selection.
350+ selection , err := asker .AskChoice (menuPrompt .String (), []string {"1" , "2" , "3" , "4" }, strconv .Itoa (len (menuOptions )))
311351 if err != nil {
312352 return err
313353 }
314354
355+ selectionInt , _ := strconv .Atoi (selection )
356+
315357 applicationsSeed = & apiseed.Applications {}
316358
317- if installIncus {
359+ switch menuOptions [selectionInt - 1 ] {
360+ case "Incus" :
318361 applicationsSeed .Applications = append (applicationsSeed .Applications , apiseed.Application {
319362 Name : "incus" ,
320363 })
364+
365+ installIncusCeph , err := asker .AskBool ("Install Incus Ceph add-on? [y/N] " , "n" )
366+ if err != nil {
367+ return err
368+ }
369+
370+ if installIncusCeph {
371+ applicationsSeed .Applications = append (applicationsSeed .Applications , apiseed.Application {
372+ Name : "incus-ceph" ,
373+ })
374+ }
375+
376+ installIncusLinstor , err := asker .AskBool ("Install Incus Linstor add-on? [y/N] " , "n" )
377+ if err != nil {
378+ return err
379+ }
380+
381+ if installIncusLinstor {
382+ applicationsSeed .Applications = append (applicationsSeed .Applications , apiseed.Application {
383+ Name : "incus-linstor" ,
384+ })
385+ }
386+ case "Migration Manager" :
387+ applicationsSeed .Applications = append (applicationsSeed .Applications , apiseed.Application {
388+ Name : "migration-manager" ,
389+ })
390+ case "Operations Center" :
391+ applicationsSeed .Applications = append (applicationsSeed .Applications , apiseed.Application {
392+ Name : "operations-center" ,
393+ })
394+ default :
321395 }
322396
323397 return nil
@@ -407,6 +481,76 @@ func configureIncusSeed(ctx context.Context) error {
407481 return nil
408482}
409483
484+ func configureMigrationManagerSeed (ctx context.Context ) error {
485+ var err error
486+
487+ existingContents := []byte ("# Provide Migration Manager seed in yaml format" )
488+
489+ if migrationManagerSeed != nil {
490+ existingContents , err = yaml .Marshal (migrationManagerSeed )
491+ if err != nil {
492+ return err
493+ }
494+ }
495+
496+ // Launch an editor to allow user to provide an Incus seed.
497+ newContents , err := textEditor (ctx , existingContents )
498+ if err != nil {
499+ slog .ErrorContext (ctx , err .Error ())
500+
501+ return nil
502+ }
503+
504+ var newSeed apiseed.MigrationManager
505+
506+ err = yaml .Unmarshal (newContents , & newSeed )
507+ if err != nil {
508+ slog .ErrorContext (ctx , err .Error ())
509+
510+ return nil
511+ }
512+
513+ // Save the Incus seed.
514+ migrationManagerSeed = & newSeed
515+
516+ return nil
517+ }
518+
519+ func configureOperationsCenterSeed (ctx context.Context ) error {
520+ var err error
521+
522+ existingContents := []byte ("# Provide Operations Center seed in yaml format" )
523+
524+ if operationsCenterSeed != nil {
525+ existingContents , err = yaml .Marshal (operationsCenterSeed )
526+ if err != nil {
527+ return err
528+ }
529+ }
530+
531+ // Launch an editor to allow user to provide an Incus seed.
532+ newContents , err := textEditor (ctx , existingContents )
533+ if err != nil {
534+ slog .ErrorContext (ctx , err .Error ())
535+
536+ return nil
537+ }
538+
539+ var newSeed apiseed.OperationsCenter
540+
541+ err = yaml .Unmarshal (newContents , & newSeed )
542+ if err != nil {
543+ slog .ErrorContext (ctx , err .Error ())
544+
545+ return nil
546+ }
547+
548+ // Save the Incus seed.
549+ operationsCenterSeed = & newSeed
550+
551+ return nil
552+ }
553+
410554func writeImage (asker ask.Asker , sourceImage string ) error {
411555 targetImage , err := asker .AskString ("Filename to write image to [" + sourceImage + "]: " , sourceImage , nil )
412556 if err != nil {
@@ -457,6 +601,26 @@ func writeImage(asker ask.Asker, sourceImage string) error {
457601 archiveContents = append (archiveContents , []string {"incus.yaml" , string (yamlContents )})
458602 }
459603
604+ // Create migration-manager yaml contents.
605+ if migrationManagerSeed != nil {
606+ yamlContents , err := yaml .Marshal (migrationManagerSeed )
607+ if err != nil {
608+ return err
609+ }
610+
611+ archiveContents = append (archiveContents , []string {"migration-manager.yaml" , string (yamlContents )})
612+ }
613+
614+ // Create operations-center yaml contents.
615+ if operationsCenterSeed != nil {
616+ yamlContents , err := yaml .Marshal (operationsCenterSeed )
617+ if err != nil {
618+ return err
619+ }
620+
621+ archiveContents = append (archiveContents , []string {"operations-center.yaml" , string (yamlContents )})
622+ }
623+
460624 // Create install yaml contents.
461625 if installSeed != nil {
462626 yamlContents , err := yaml .Marshal (installSeed )
0 commit comments