podman

Форк
0
143 строки · 4.1 Кб
1
package config
2

3
import (
4
	"fmt"
5
	"strings"
6

7
	"github.com/crc-org/vfkit/pkg/util"
8
)
9

10
// Bootloader is the base interface for all bootloader classes. It specifies how to
11
// boot the virtual machine. It is mandatory to set a Bootloader or the virtual
12
// machine won't start.
13
type Bootloader interface {
14
	FromOptions(options []option) error
15
	ToCmdLine() ([]string, error)
16
}
17

18
// LinuxBootloader determines which kernel/initrd/kernel args to use when starting
19
// the virtual machine.
20
type LinuxBootloader struct {
21
	VmlinuzPath   string
22
	KernelCmdLine string
23
	InitrdPath    string
24
}
25

26
// EFIBootloader allows to set a few options related to EFI variable storage
27
type EFIBootloader struct {
28
	EFIVariableStorePath string
29
	// TODO: virtualization framework allow both create and overwrite
30
	CreateVariableStore bool
31
}
32

33
// NewLinuxBootloader creates a new bootloader to start a VM with the file at
34
// vmlinuzPath as the kernel, kernelCmdLine as the kernel command line, and the
35
// file at initrdPath as the initrd. On ARM64, the kernel must be uncompressed
36
// otherwise the VM will fail to boot.
37
func NewLinuxBootloader(vmlinuzPath, kernelCmdLine, initrdPath string) *LinuxBootloader {
38
	return &LinuxBootloader{
39
		VmlinuzPath:   vmlinuzPath,
40
		KernelCmdLine: kernelCmdLine,
41
		InitrdPath:    initrdPath,
42
	}
43
}
44

45
func (bootloader *LinuxBootloader) FromOptions(options []option) error {
46
	for _, option := range options {
47
		switch option.key {
48
		case "kernel":
49
			bootloader.VmlinuzPath = option.value
50
		case "cmdline":
51
			bootloader.KernelCmdLine = util.TrimQuotes(option.value)
52
		case "initrd":
53
			bootloader.InitrdPath = option.value
54
		default:
55
			return fmt.Errorf("unknown option for linux bootloaders: %s", option.key)
56
		}
57
	}
58
	return nil
59
}
60

61
func (bootloader *LinuxBootloader) ToCmdLine() ([]string, error) {
62
	args := []string{}
63
	if bootloader.VmlinuzPath == "" {
64
		return nil, fmt.Errorf("missing kernel path")
65
	}
66
	args = append(args, "--kernel", bootloader.VmlinuzPath)
67

68
	if bootloader.InitrdPath == "" {
69
		return nil, fmt.Errorf("missing initrd path")
70
	}
71
	args = append(args, "--initrd", bootloader.InitrdPath)
72

73
	if bootloader.KernelCmdLine == "" {
74
		return nil, fmt.Errorf("missing kernel command line")
75
	}
76
	args = append(args, "--kernel-cmdline", bootloader.KernelCmdLine)
77

78
	return args, nil
79
}
80

81
// NewEFIBootloader creates a new bootloader to start a VM using EFI
82
// efiVariableStorePath is the path to a file for EFI storage
83
// create is a boolean indicating if the file for the store should be created or not
84
func NewEFIBootloader(efiVariableStorePath string, createVariableStore bool) *EFIBootloader {
85
	return &EFIBootloader{
86
		EFIVariableStorePath: efiVariableStorePath,
87
		CreateVariableStore:  createVariableStore,
88
	}
89
}
90

91
func (bootloader *EFIBootloader) FromOptions(options []option) error {
92
	for _, option := range options {
93
		switch option.key {
94
		case "variable-store":
95
			bootloader.EFIVariableStorePath = option.value
96
		case "create":
97
			if option.value != "" {
98
				return fmt.Errorf("unexpected value for EFI bootloader 'create' option: %s", option.value)
99
			}
100
			bootloader.CreateVariableStore = true
101
		default:
102
			return fmt.Errorf("unknown option for EFI bootloaders: %s", option.key)
103
		}
104
	}
105
	return nil
106
}
107

108
func (bootloader *EFIBootloader) ToCmdLine() ([]string, error) {
109
	if bootloader.EFIVariableStorePath == "" {
110
		return nil, fmt.Errorf("missing EFI store path")
111
	}
112

113
	builder := strings.Builder{}
114
	builder.WriteString("efi")
115
	builder.WriteString(fmt.Sprintf(",variable-store=%s", bootloader.EFIVariableStorePath))
116
	if bootloader.CreateVariableStore {
117
		builder.WriteString(",create")
118
	}
119

120
	return []string{"--bootloader", builder.String()}, nil
121
}
122

123
func BootloaderFromCmdLine(optsStrv []string) (Bootloader, error) {
124
	var bootloader Bootloader
125

126
	if len(optsStrv) < 1 {
127
		return nil, fmt.Errorf("empty option list in --bootloader command line argument")
128
	}
129
	bootloaderType := optsStrv[0]
130
	switch bootloaderType {
131
	case "efi":
132
		bootloader = &EFIBootloader{}
133
	case "linux":
134
		bootloader = &LinuxBootloader{}
135
	default:
136
		return nil, fmt.Errorf("unknown bootloader type: %s", bootloaderType)
137
	}
138
	options := strvToOptions(optsStrv[1:])
139
	if err := bootloader.FromOptions(options); err != nil {
140
		return nil, err
141
	}
142
	return bootloader, nil
143
}
144

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.