Skip to content

Commit 2845d3e

Browse files
committed
incus-migrate: Add support for .OVA import
Signed-off-by: Piotr Resztak <[email protected]>
1 parent 59fb539 commit 2845d3e

File tree

3 files changed

+565
-69
lines changed

3 files changed

+565
-69
lines changed

cmd/incus-migrate/main_migrate.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,9 +470,10 @@ func (c *cmdMigrate) run(_ *cobra.Command, _ []string) error {
470470
What would you like to create?
471471
1) Container
472472
2) Virtual Machine
473-
3) Custom Volume
473+
3) Virtual Machine (from .ova)
474+
4) Custom Volume
474475
475-
Please enter the number of your choice: `, 1, 3, "", nil)
476+
Please enter the number of your choice: `, 1, 4, "", nil)
476477
if err != nil {
477478
return err
478479
}
@@ -484,6 +485,8 @@ Please enter the number of your choice: `, 1, 3, "", nil)
484485
case 2:
485486
migrator = NewInstanceMigration(ctx, server, c.global.asker, c.flagRsyncArgs, MigrationTypeVM)
486487
case 3:
488+
migrator = NewOVAMigration(ctx, server, c.global.asker, c.flagRsyncArgs)
489+
case 4:
487490
migrator = NewVolumeMigration(ctx, server, c.global.asker, c.flagRsyncArgs)
488491
}
489492

cmd/incus-migrate/migrate_instance.go

Lines changed: 119 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -112,29 +112,9 @@ func (m *InstanceMigration) gatherInfo() error {
112112
return err
113113
}
114114

115-
if m.instanceArgs.Type == api.InstanceTypeVM {
116-
architectureName, _ := osarch.ArchitectureGetLocal()
117-
118-
if slices.Contains([]string{"x86_64", "aarch64"}, architectureName) {
119-
hasUEFI, err := m.asker.AskBool("Does the VM support UEFI booting? [default=yes]: ", "yes")
120-
if err != nil {
121-
return err
122-
}
123-
124-
if hasUEFI {
125-
hasSecureBoot, err := m.asker.AskBool("Does the VM support UEFI Secure Boot? [default=yes]: ", "yes")
126-
if err != nil {
127-
return err
128-
}
129-
130-
if !hasSecureBoot {
131-
m.instanceArgs.Config["security.secureboot"] = "false"
132-
}
133-
} else {
134-
m.instanceArgs.Config["security.csm"] = "true"
135-
m.instanceArgs.Config["security.secureboot"] = "false"
136-
}
137-
}
115+
err = m.askUEFISupport()
116+
if err != nil {
117+
return err
138118
}
139119

140120
var mounts []string
@@ -174,49 +154,7 @@ func (m *InstanceMigration) gatherInfo() error {
174154
}
175155
}
176156

177-
for {
178-
fmt.Println("\nInstance to be created:")
179-
180-
scanner := bufio.NewScanner(strings.NewReader(m.render()))
181-
for scanner.Scan() {
182-
fmt.Printf(" %s\n", scanner.Text())
183-
}
184-
185-
fmt.Print(`
186-
Additional overrides can be applied at this stage:
187-
1) Begin the migration with the above configuration
188-
2) Override profile list
189-
3) Set additional configuration options
190-
4) Change instance storage pool or volume size
191-
5) Change instance network
192-
6) Add additional disk
193-
194-
`)
195-
196-
choice, err := m.asker.AskInt("Please pick one of the options above [default=1]: ", 1, 6, "1", nil)
197-
if err != nil {
198-
return err
199-
}
200-
201-
switch choice {
202-
case 1:
203-
return nil
204-
case 2:
205-
err = m.askProfiles()
206-
case 3:
207-
err = m.askConfig()
208-
case 4:
209-
err = m.askStorage()
210-
case 5:
211-
err = m.askNetwork()
212-
case 6:
213-
err = m.askDisk()
214-
}
215-
216-
if err != nil {
217-
fmt.Println(err)
218-
}
219-
}
157+
return nil
220158
}
221159

222160
// migrate performs the instance migration.
@@ -276,7 +214,52 @@ func (m *InstanceMigration) migrate() error {
276214

277215
// renderObject renders the state of the instance.
278216
func (m *InstanceMigration) renderObject() error {
279-
return nil
217+
for {
218+
fmt.Println("\nInstance to be created:")
219+
220+
scanner := bufio.NewScanner(strings.NewReader(m.render()))
221+
for scanner.Scan() {
222+
fmt.Printf(" %s\n", scanner.Text())
223+
}
224+
225+
fmt.Print(`
226+
Additional overrides can be applied at this stage:
227+
1) Begin the migration with the above configuration
228+
2) Override profile list
229+
3) Set additional configuration options
230+
4) Change instance storage pool or volume size
231+
5) Change instance network
232+
6) Add additional disk
233+
7) Change additional disk storage pool
234+
235+
`)
236+
237+
choice, err := m.asker.AskInt("Please pick one of the options above [default=1]: ", 1, 6, "1", nil)
238+
if err != nil {
239+
return err
240+
}
241+
242+
switch choice {
243+
case 1:
244+
return nil
245+
case 2:
246+
err = m.askProfiles()
247+
case 3:
248+
err = m.askConfig()
249+
case 4:
250+
err = m.askStorage()
251+
case 5:
252+
err = m.askNetwork()
253+
case 6:
254+
err = m.askDisk()
255+
case 7:
256+
err = m.askDiskStorage()
257+
}
258+
259+
if err != nil {
260+
fmt.Println(err)
261+
}
262+
}
280263
}
281264

282265
func (m *InstanceMigration) render() string {
@@ -439,6 +422,46 @@ func (m *InstanceMigration) askStorage() error {
439422
return nil
440423
}
441424

425+
func (m *InstanceMigration) askDiskStorage() error {
426+
diskNames := []string{}
427+
for _, vol := range m.volumes {
428+
diskNames = append(diskNames, vol.customVolumeArgs.Name)
429+
}
430+
431+
if len(diskNames) == 0 {
432+
return fmt.Errorf("No additional disks available")
433+
}
434+
435+
diskName, err := m.asker.AskChoice("Please provide the disk name: ", diskNames, "")
436+
if err != nil {
437+
return err
438+
}
439+
440+
storagePools, err := m.server.GetStoragePoolNames()
441+
if err != nil {
442+
return err
443+
}
444+
445+
if len(storagePools) == 0 {
446+
return fmt.Errorf("No storage pools available")
447+
}
448+
449+
storagePool, err := m.asker.AskChoice("Please provide the storage pool to use: ", storagePools, "")
450+
if err != nil {
451+
return err
452+
}
453+
454+
m.instanceArgs.Devices[diskName]["pool"] = storagePool
455+
for _, vol := range m.volumes {
456+
if vol.customVolumeArgs.Name == diskName {
457+
vol.pool = storagePool
458+
break
459+
}
460+
}
461+
462+
return nil
463+
}
464+
442465
func (m *InstanceMigration) askNetwork() error {
443466
networks, err := m.server.GetNetworkNames()
444467
if err != nil {
@@ -496,3 +519,32 @@ func (m *InstanceMigration) askDisk() error {
496519

497520
return nil
498521
}
522+
523+
func (m *InstanceMigration) askUEFISupport() error {
524+
if m.instanceArgs.Type == api.InstanceTypeVM {
525+
architectureName, _ := osarch.ArchitectureGetLocal()
526+
527+
if slices.Contains([]string{"x86_64", "aarch64"}, architectureName) {
528+
hasUEFI, err := m.asker.AskBool("Does the VM support UEFI booting? [default=yes]: ", "yes")
529+
if err != nil {
530+
return err
531+
}
532+
533+
if hasUEFI {
534+
hasSecureBoot, err := m.asker.AskBool("Does the VM support UEFI Secure Boot? [default=yes]: ", "yes")
535+
if err != nil {
536+
return err
537+
}
538+
539+
if !hasSecureBoot {
540+
m.instanceArgs.Config["security.secureboot"] = "false"
541+
}
542+
} else {
543+
m.instanceArgs.Config["security.csm"] = "true"
544+
m.instanceArgs.Config["security.secureboot"] = "false"
545+
}
546+
}
547+
}
548+
549+
return nil
550+
}

0 commit comments

Comments
 (0)