Skip to content

Commit 3c40ba4

Browse files
authored
Merge pull request #2562 from norio-nomura/vz-support-kernel-image
VZ: Support Kernel Image
2 parents df5d2e6 + 5223ad9 commit 3c40ba4

File tree

4 files changed

+115
-16
lines changed

4 files changed

+115
-16
lines changed

hack/inject-cmdline-to-template.sh

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@ readonly yq_filter="
3636
parsed=$(yq eval "${yq_filter}" "${template}")
3737

3838
# 3. get the image location
39+
function check_location() {
40+
local location=$1 http_code
41+
http_code=$(curl -sIL -w "%{http_code}" "${location}" -o /dev/null)
42+
[[ ${http_code} -eq 200 ]]
43+
}
3944
while IFS= read -r line; do arr+=("${line}"); done <<<"${parsed}"
4045
readonly locations=("${arr[@]}")
4146
for ((i = 0; i < ${#locations[@]}; i++)); do
4247
[[ ${locations[i]} != "null" ]] || continue
43-
http_code=$(curl -sIL -w "%{http_code}" "${locations[i]}" -o /dev/null)
44-
if [[ ${http_code} -eq 200 ]]; then
48+
# shellcheck disable=SC2310
49+
if check_location "${locations[i]}"; then
4550
location=${locations[i]}
4651
index=${i}
4752
break
@@ -78,14 +83,18 @@ initrd_digest=$(awk "/${initrd_basename}/{print \"sha256:\"\$1}" <<<"${sha256sum
7883
initrd_location="${location_dirname}/${initrd_basename}"
7984

8085
# 6. inject the kernel and initrd location, digest, and cmdline to the template
81-
yq -i eval "
82-
[(.images.[] | select(.arch == \"${arch}\") | path)].[${index}] + \"kernel\" as \$path|
83-
setpath(\$path; { \"location\": \"${kernel_location}\", \"digest\": \"${kernel_digest}\", \"cmdline\": \"${cmdline}\" })
84-
" "${template}"
85-
yq -i eval "
86-
[(.images.[] | select(.arch == \"${arch}\") | path)].[${index}] + \"initrd\" as \$path|
87-
setpath(\$path ; { \"location\": \"${initrd_location}\", \"digest\": \"${initrd_digest}\" })
88-
" "${template}"
86+
function inject_to() {
87+
# shellcheck disable=SC2034
88+
local template=$1 arch=$2 index=$3 key=$4 location=$5 digest=$6 cmdline=${7:-} fields=() IFS=,
89+
# shellcheck disable=SC2310
90+
check_location "${location}" || return 0
91+
for field_name in location digest cmdline; do
92+
[[ -z ${!field_name} ]] || fields+=("\"${field_name}\": \"${!field_name}\"")
93+
done
94+
yq -i -I 2 eval "setpath([(.images[] | select(.arch == \"${arch}\") | path)].[${index}] + \"${key}\"; { ${fields[*]}})" "${template}"
95+
}
96+
inject_to "${template}" "${arch}" "${index}" "kernel" "${kernel_location}" "${kernel_digest}" "${cmdline}"
97+
inject_to "${template}" "${arch}" "${index}" "initrd" "${initrd_location}" "${initrd_digest}"
8998

9099
# 7. output kernel_location, kernel_digest, cmdline, initrd_location, initrd_digest
91100
readonly outputs=(kernel_location kernel_digest cmdline initrd_location initrd_digest)

pkg/downloader/downloader.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,10 @@ func copyLocal(ctx context.Context, dst, src, ext string, decompress bool, descr
408408
if command != "" {
409409
return decompressLocal(ctx, command, dstPath, srcPath, ext, description)
410410
}
411+
commandByMagic := decompressorByMagic(srcPath)
412+
if commandByMagic != "" {
413+
return decompressLocal(ctx, commandByMagic, dstPath, srcPath, ext, description)
414+
}
411415
}
412416
// TODO: progress bar for copy
413417
return fs.CopyFile(dstPath, srcPath)
@@ -428,6 +432,34 @@ func decompressor(ext string) string {
428432
}
429433
}
430434

435+
func decompressorByMagic(file string) string {
436+
f, err := os.Open(file)
437+
if err != nil {
438+
return ""
439+
}
440+
defer f.Close()
441+
header := make([]byte, 6)
442+
if _, err := f.Read(header); err != nil {
443+
return ""
444+
}
445+
if _, err := f.Seek(0, io.SeekStart); err != nil {
446+
return ""
447+
}
448+
if bytes.HasPrefix(header, []byte{0x1f, 0x8b}) {
449+
return "gzip"
450+
}
451+
if bytes.HasPrefix(header, []byte{0x42, 0x5a}) {
452+
return "bzip2"
453+
}
454+
if bytes.HasPrefix(header, []byte{0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00}) {
455+
return "xz"
456+
}
457+
if bytes.HasPrefix(header, []byte{0x28, 0xb5, 0x2f, 0xfd}) {
458+
return "zstd"
459+
}
460+
return ""
461+
}
462+
431463
func decompressLocal(ctx context.Context, decompressCmd, dst, src, ext, description string) error {
432464
logrus.Infof("decompressing %s with %v", ext, decompressCmd)
433465

pkg/vz/disk.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ func EnsureDisk(ctx context.Context, driver *driver.BaseDriver) error {
2323
}
2424

2525
baseDisk := filepath.Join(driver.Instance.Dir, filenames.BaseDisk)
26+
kernel := filepath.Join(driver.Instance.Dir, filenames.Kernel)
27+
kernelCmdline := filepath.Join(driver.Instance.Dir, filenames.KernelCmdline)
28+
initrd := filepath.Join(driver.Instance.Dir, filenames.Initrd)
2629
if _, err := os.Stat(baseDisk); errors.Is(err, os.ErrNotExist) {
2730
var ensuredBaseDisk bool
2831
errs := make([]error, len(driver.Yaml.Images))
@@ -31,6 +34,25 @@ func EnsureDisk(ctx context.Context, driver *driver.BaseDriver) error {
3134
errs[i] = err
3235
continue
3336
}
37+
if f.Kernel != nil {
38+
// ensure decompress kernel because vz expects it to be decompressed
39+
if _, err := fileutils.DownloadFile(ctx, kernel, f.Kernel.File, true, "the kernel", *driver.Yaml.Arch); err != nil {
40+
errs[i] = err
41+
continue
42+
}
43+
if f.Kernel.Cmdline != "" {
44+
if err := os.WriteFile(kernelCmdline, []byte(f.Kernel.Cmdline), 0o644); err != nil {
45+
errs[i] = err
46+
continue
47+
}
48+
}
49+
}
50+
if f.Initrd != nil {
51+
if _, err := fileutils.DownloadFile(ctx, initrd, *f.Initrd, false, "the initrd", *driver.Yaml.Arch); err != nil {
52+
errs[i] = err
53+
continue
54+
}
55+
}
3456
ensuredBaseDisk = true
3557
break
3658
}

pkg/vz/vm_darwin.go

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,7 @@ func createVM(driver *driver.BaseDriver) (*vz.VirtualMachine, error) {
203203
}
204204

205205
func createInitialConfig(driver *driver.BaseDriver) (*vz.VirtualMachineConfiguration, error) {
206-
efiVariableStore, err := getEFI(driver)
207-
if err != nil {
208-
return nil, err
209-
}
210-
211-
bootLoader, err := vz.NewEFIBootLoader(vz.WithEFIVariableStore(efiVariableStore))
206+
bootLoader, err := bootLoader(driver)
212207
if err != nil {
213208
return nil, err
214209
}
@@ -686,6 +681,47 @@ func getMachineIdentifier(driver *driver.BaseDriver) (*vz.GenericMachineIdentifi
686681
return vz.NewGenericMachineIdentifierWithDataPath(identifier)
687682
}
688683

684+
func bootLoader(driver *driver.BaseDriver) (vz.BootLoader, error) {
685+
linuxBootLoder, err := linuxBootLoader(driver)
686+
if linuxBootLoder != nil {
687+
return linuxBootLoder, nil
688+
} else if !errors.Is(err, os.ErrNotExist) {
689+
return nil, err
690+
}
691+
692+
efiVariableStore, err := getEFI(driver)
693+
if err != nil {
694+
return nil, err
695+
}
696+
logrus.Debugf("Using EFI Boot Loader")
697+
return vz.NewEFIBootLoader(vz.WithEFIVariableStore(efiVariableStore))
698+
}
699+
700+
func linuxBootLoader(driver *driver.BaseDriver) (*vz.LinuxBootLoader, error) {
701+
kernel := filepath.Join(driver.Instance.Dir, filenames.Kernel)
702+
kernelCmdline := filepath.Join(driver.Instance.Dir, filenames.KernelCmdline)
703+
initrd := filepath.Join(driver.Instance.Dir, filenames.Initrd)
704+
if _, err := os.Stat(kernel); err != nil {
705+
if errors.Is(err, os.ErrNotExist) {
706+
logrus.Debugf("Kernel file %q not found", kernel)
707+
} else {
708+
logrus.WithError(err).Debugf("Error while checking kernel file %q", kernel)
709+
}
710+
return nil, err
711+
}
712+
var opt []vz.LinuxBootLoaderOption
713+
if b, err := os.ReadFile(kernelCmdline); err == nil {
714+
logrus.Debugf("Using kernel command line %q", string(b))
715+
opt = append(opt, vz.WithCommandLine(string(b)))
716+
}
717+
if _, err := os.Stat(initrd); err == nil {
718+
logrus.Debugf("Using initrd %q", initrd)
719+
opt = append(opt, vz.WithInitrd(initrd))
720+
}
721+
logrus.Debugf("Using Linux Boot Loader with kernel %q", kernel)
722+
return vz.NewLinuxBootLoader(kernel, opt...)
723+
}
724+
689725
func getEFI(driver *driver.BaseDriver) (*vz.EFIVariableStore, error) {
690726
efi := filepath.Join(driver.Instance.Dir, filenames.VzEfi)
691727
if _, err := os.Stat(efi); os.IsNotExist(err) {

0 commit comments

Comments
 (0)