2
0
mirror of https://github.com/linka-cloud/d2vm.git synced 2024-11-24 16:46:24 +00:00

arm64 support with grub-efi

* build / convert: add `--platform` flag to support linux/amd64 &
linux/arm64
* build: add `--pull` flag
* run/hetzner: add `--type` flag to select server type
* run/hetzner: add `--location` flag to select server location

Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
Adphi 2023-09-13 15:37:29 +02:00
parent f8fc729486
commit d54b3f9a2c
Signed by: adphi
GPG Key ID: F2159213400E50AB
29 changed files with 197 additions and 83 deletions

2
.gitignore vendored
View File

@ -17,4 +17,4 @@ images
docs/build docs/build
docs-src docs-src
/completions /completions
/cmd/d2vm/run/sparsecat-linux-amd64 /cmd/d2vm/run/sparsecat-linux-*

View File

@ -38,7 +38,7 @@ RUN apt-get update && \
dosfstools \ dosfstools \
mount \ mount \
tar \ tar \
extlinux \ "$([ "$(uname -m)" = "x86_64" ] && echo extlinux)" \
cryptsetup-bin \ cryptsetup-bin \
qemu-utils && \ qemu-utils && \
apt-get clean && \ apt-get clean && \

View File

@ -160,7 +160,7 @@ Flags:
--append-to-cmdline string Extra kernel cmdline arguments to append to the generated one --append-to-cmdline string Extra kernel cmdline arguments to append to the generated one
--boot-fs string Filesystem to use for the boot partition, ext4 or fat32 --boot-fs string Filesystem to use for the boot partition, ext4 or fat32
--boot-size uint Size of the boot partition in MB (default 100) --boot-size uint Size of the boot partition in MB (default 100)
--bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi (default "syslinux") --bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi, defaults to syslinux on amd64 and grub-efi on arm64
--force Override output qcow2 image --force Override output qcow2 image
-h, --help help for convert -h, --help help for convert
--keep-cache Keep the images after the build --keep-cache Keep the images after the build
@ -168,6 +168,7 @@ Flags:
--network-manager string Network manager to use for the image: none, netplan, ifupdown --network-manager string Network manager to use for the image: none, netplan, ifupdown
-o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2") -o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2")
-p, --password string Optional root user password -p, --password string Optional root user password
--platform string Platform to use for the container disk image, linux/arm64 and linux/arm64 are supported (default "linux/amd64")
--pull Always pull docker image --pull Always pull docker image
--push Push the container disk image to the registry --push Push the container disk image to the registry
--raw Just convert the container to virtual machine image without installing anything more --raw Just convert the container to virtual machine image without installing anything more
@ -317,7 +318,7 @@ Flags:
--append-to-cmdline string Extra kernel cmdline arguments to append to the generated one --append-to-cmdline string Extra kernel cmdline arguments to append to the generated one
--boot-fs string Filesystem to use for the boot partition, ext4 or fat32 --boot-fs string Filesystem to use for the boot partition, ext4 or fat32
--boot-size uint Size of the boot partition in MB (default 100) --boot-size uint Size of the boot partition in MB (default 100)
--bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi (default "syslinux") --bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi, defaults to syslinux on amd64 and grub-efi on arm64
--build-arg stringArray Set build-time variables --build-arg stringArray Set build-time variables
-f, --file string Name of the Dockerfile -f, --file string Name of the Dockerfile
--force Override output qcow2 image --force Override output qcow2 image
@ -327,6 +328,8 @@ Flags:
--network-manager string Network manager to use for the image: none, netplan, ifupdown --network-manager string Network manager to use for the image: none, netplan, ifupdown
-o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2") -o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2")
-p, --password string Optional root user password -p, --password string Optional root user password
--platform string Platform to use for the container disk image, linux/arm64 and linux/arm64 are supported (default "linux/amd64")
--pull Always pull docker image
--push Push the container disk image to the registry --push Push the container disk image to the registry
--raw Just convert the container to virtual machine image without installing anything more --raw Just convert the container to virtual machine image without installing anything more
-s, --size string The output image size (default "10G") -s, --size string The output image size (default "10G")

View File

@ -33,7 +33,7 @@ func BootloaderByName(name string) (BootloaderProvider, error) {
} }
type BootloaderProvider interface { type BootloaderProvider interface {
New(c Config, r OSRelease) (Bootloader, error) New(c Config, r OSRelease, arch string) (Bootloader, error)
Name() string Name() string
} }

View File

@ -82,11 +82,18 @@ type builder struct {
luksPassword string luksPassword string
cmdLineExtra string cmdLineExtra string
arch string
} }
func NewBuilder(ctx context.Context, workdir, imgTag, disk string, size uint64, osRelease OSRelease, format string, cmdLineExtra string, splitBoot bool, bootFS BootFS, bootSize uint64, luksPassword string, bootLoader string) (Builder, error) { func NewBuilder(ctx context.Context, workdir, imgTag, disk string, size uint64, osRelease OSRelease, format string, cmdLineExtra string, splitBoot bool, bootFS BootFS, bootSize uint64, luksPassword string, bootLoader string, platform string) (Builder, error) {
if err := checkDependencies(); err != nil { var arch string
return nil, err switch platform {
case "linux/amd64":
arch = "x86_64"
case "linux/arm64", "linux/aarch64":
arch = "arm64"
default:
return nil, fmt.Errorf("unexpected platform: %s, supported platforms: linux/amd64, linux/arm64", platform)
} }
if luksPassword != "" { if luksPassword != "" {
if !splitBoot { if !splitBoot {
@ -141,7 +148,7 @@ func NewBuilder(ctx context.Context, workdir, imgTag, disk string, size uint64,
if err != nil { if err != nil {
return nil, err return nil, err
} }
bl, err := blp.New(config, osRelease) bl, err := blp.New(config, osRelease, arch)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -184,6 +191,10 @@ func NewBuilder(ctx context.Context, workdir, imgTag, disk string, size uint64,
bootSize: bootSize, bootSize: bootSize,
bootFS: bootFS, bootFS: bootFS,
luksPassword: luksPassword, luksPassword: luksPassword,
arch: arch,
}
if err := b.checkDependencies(); err != nil {
return nil, err
} }
if err := os.MkdirAll(b.mntPoint, os.ModePerm); err != nil { if err := os.MkdirAll(b.mntPoint, os.ModePerm); err != nil {
return nil, err return nil, err
@ -490,9 +501,13 @@ func block(path string, size uint64) error {
return f.Truncate(int64(size)) return f.Truncate(int64(size))
} }
func checkDependencies() error { func (b *builder) checkDependencies() error {
var merr error var merr error
for _, v := range []string{"mount", "blkid", "tar", "losetup", "parted", "kpartx", "qemu-img", "extlinux", "dd", "mkfs.ext4", "cryptsetup"} { deps := []string{"mount", "blkid", "tar", "losetup", "parted", "kpartx", "qemu-img", "dd", "mkfs.ext4", "cryptsetup"}
if _, ok := b.bootloader.(*syslinux); ok {
deps = append(deps, "extlinux")
}
for _, v := range deps {
if _, err := exec2.LookPath(v); err != nil { if _, err := exec2.LookPath(v); err != nil {
merr = multierr.Append(merr, err) merr = multierr.Append(merr, err)
} }

View File

@ -90,7 +90,7 @@ var (
file = filepath.Join(args[0], "Dockerfile") file = filepath.Join(args[0], "Dockerfile")
} }
logrus.Infof("building docker image from %s", file) logrus.Infof("building docker image from %s", file)
if err := docker.Build(cmd.Context(), tag, file, args[0], buildArgs...); err != nil { if err := docker.Build(cmd.Context(), pull, tag, file, args[0], platform, buildArgs...); err != nil {
return err return err
} }
if err := d2vm.Convert( if err := d2vm.Convert(
@ -108,6 +108,8 @@ var (
d2vm.WithBootFS(d2vm.BootFS(bootFS)), d2vm.WithBootFS(d2vm.BootFS(bootFS)),
d2vm.WithLuksPassword(luksPassword), d2vm.WithLuksPassword(luksPassword),
d2vm.WithKeepCache(keepCache), d2vm.WithKeepCache(keepCache),
d2vm.WithPlatform(platform),
d2vm.WithPull(false),
); err != nil { ); err != nil {
return err return err
} }

View File

@ -29,7 +29,7 @@ func maybeMakeContainerDisk(ctx context.Context) error {
return nil return nil
} }
logrus.Infof("creating container disk image %s", containerDiskTag) logrus.Infof("creating container disk image %s", containerDiskTag)
if err := d2vm.MakeContainerDisk(ctx, output, containerDiskTag); err != nil { if err := d2vm.MakeContainerDisk(ctx, output, containerDiskTag, platform); err != nil {
return err return err
} }
if !push { if !push {

View File

@ -70,7 +70,7 @@ var (
} }
if pull || !found { if pull || !found {
logrus.Infof("pulling image %s", img) logrus.Infof("pulling image %s", img)
if err := docker.Pull(cmd.Context(), img); err != nil { if err := docker.Pull(cmd.Context(), platform, img); err != nil {
return err return err
} }
} }
@ -89,6 +89,8 @@ var (
d2vm.WithBootFS(d2vm.BootFS(bootFS)), d2vm.WithBootFS(d2vm.BootFS(bootFS)),
d2vm.WithLuksPassword(luksPassword), d2vm.WithLuksPassword(luksPassword),
d2vm.WithKeepCache(keepCache), d2vm.WithKeepCache(keepCache),
d2vm.WithPlatform(platform),
d2vm.WithPull(pull),
); err != nil { ); err != nil {
return err return err
} }
@ -112,7 +114,6 @@ func parseSize(s string) (uint64, error) {
} }
func init() { func init() {
convertCmd.Flags().BoolVar(&pull, "pull", false, "Always pull docker image")
convertCmd.Flags().AddFlagSet(buildFlags()) convertCmd.Flags().AddFlagSet(buildFlags())
rootCmd.AddCommand(convertCmd) rootCmd.AddCommand(convertCmd)
} }

View File

@ -43,9 +43,26 @@ var (
luksPassword string luksPassword string
keepCache bool keepCache bool
platform string
) )
func validateFlags() error { func validateFlags() error {
switch platform {
case "linux/amd64":
if bootloader == "" {
bootloader = "syslinux"
}
case "linux/arm64", "linux/aarch64":
platform = "linux/arm64"
if bootloader == "" {
bootloader = "grub-efi"
}
if bootloader != "grub-efi" {
return fmt.Errorf("unsupported bootloader for platform %s: %s, only grub-efi is supported", platform, bootloader)
}
default:
return fmt.Errorf("unexpected platform: %s, supported platforms: linux/amd64, linux/arm64", platform)
}
if luksPassword != "" && !splitBoot { if luksPassword != "" && !splitBoot {
logrus.Warnf("luks password is set: enabling split boot") logrus.Warnf("luks password is set: enabling split boot")
splitBoot = true splitBoot = true
@ -94,8 +111,10 @@ func buildFlags() *pflag.FlagSet {
flags.BoolVar(&splitBoot, "split-boot", false, "Split the boot partition from the root partition") flags.BoolVar(&splitBoot, "split-boot", false, "Split the boot partition from the root partition")
flags.Uint64Var(&bootSize, "boot-size", 100, "Size of the boot partition in MB") flags.Uint64Var(&bootSize, "boot-size", 100, "Size of the boot partition in MB")
flags.StringVar(&bootFS, "boot-fs", "", "Filesystem to use for the boot partition, ext4 or fat32") flags.StringVar(&bootFS, "boot-fs", "", "Filesystem to use for the boot partition, ext4 or fat32")
flags.StringVar(&bootloader, "bootloader", "syslinux", "Bootloader to use: syslinux, grub, grub-bios, grub-efi") flags.StringVar(&bootloader, "bootloader", "", "Bootloader to use: syslinux, grub, grub-bios, grub-efi, defaults to syslinux on amd64 and grub-efi on arm64")
flags.StringVar(&luksPassword, "luks-password", "", "Password to use for the LUKS encrypted root partition. If not set, the root partition will not be encrypted") flags.StringVar(&luksPassword, "luks-password", "", "Password to use for the LUKS encrypted root partition. If not set, the root partition will not be encrypted")
flags.BoolVar(&keepCache, "keep-cache", false, "Keep the images after the build") flags.BoolVar(&keepCache, "keep-cache", false, "Keep the images after the build")
flags.StringVar(&platform, "platform", d2vm.Arch, "Platform to use for the container disk image, linux/arm64 and linux/arm64 are supported")
flags.BoolVar(&pull, "pull", false, "Always pull docker image")
return flags return flags
} }

View File

@ -70,6 +70,8 @@ func init() {
HetznerCmd.Flags().StringVarP(&hetznerSSHKeyPath, "ssh-key", "i", "", "d2vm image identity key") HetznerCmd.Flags().StringVarP(&hetznerSSHKeyPath, "ssh-key", "i", "", "d2vm image identity key")
HetznerCmd.Flags().BoolVar(&hetznerRemove, "rm", false, "remove server when done") HetznerCmd.Flags().BoolVar(&hetznerRemove, "rm", false, "remove server when done")
HetznerCmd.Flags().StringVarP(&hetznerServerName, "name", "n", "d2vm", "d2vm server name") HetznerCmd.Flags().StringVarP(&hetznerServerName, "name", "n", "d2vm", "d2vm server name")
HetznerCmd.Flags().StringVarP(&hetznerVMType, "type", "t", hetznerVMType, "d2vm server type")
HetznerCmd.Flags().StringVarP(&hetznerDatacenter, "location", "l", hetznerDatacenter, "d2vm server location")
} }
func Hetzner(cmd *cobra.Command, args []string) { func Hetzner(cmd *cobra.Command, args []string) {
@ -113,10 +115,23 @@ func runHetzner(ctx context.Context, imgPath string, stdin io.Reader, stderr io.
if err != nil { if err != nil {
return err return err
} }
img, _, err := c.Image.GetByName(ctx, serverImg) arch := "amd64"
harch := hcloud.ArchitectureX86
if strings.HasPrefix(strings.ToLower(hetznerVMType), "cax") {
harch = hcloud.ArchitectureARM
arch = "arm64"
}
sparsecatBin, err := Sparsecat(arch)
if err != nil { if err != nil {
return err return err
} }
imgs, _, err := c.Image.List(ctx, hcloud.ImageListOpts{Name: serverImg, Architecture: []hcloud.Architecture{harch}})
if err != nil {
return err
}
if len(imgs) == 0 {
return fmt.Errorf("no image found with name %s", serverImg)
}
l, _, err := c.Location.Get(ctx, hetznerDatacenter) l, _, err := c.Location.Get(ctx, hetznerDatacenter)
if err != nil { if err != nil {
return err return err
@ -125,9 +140,9 @@ func runHetzner(ctx context.Context, imgPath string, stdin io.Reader, stderr io.
sres, _, err := c.Server.Create(ctx, hcloud.ServerCreateOpts{ sres, _, err := c.Server.Create(ctx, hcloud.ServerCreateOpts{
Name: hetznerServerName, Name: hetznerServerName,
ServerType: st, ServerType: st,
Image: img, Image: imgs[0],
Location: l, Location: l,
StartAfterCreate: hcloud.Bool(false), StartAfterCreate: hcloud.Ptr(false),
}) })
if err != nil { if err != nil {
return err return err
@ -186,7 +201,7 @@ func runHetzner(ctx context.Context, imgPath string, stdin io.Reader, stderr io.
return err return err
} }
defer f.Close() defer f.Close()
if _, err := io.Copy(f, bytes.NewReader(sparsecatBinary)); err != nil { if _, err := io.Copy(f, bytes.NewReader(sparsecatBin)); err != nil {
return err return err
} }
if err := f.Close(); err != nil { if err := f.Close(); err != nil {

View File

@ -1,4 +1,5 @@
//go:generate env GOOS=linux GOARCH=amd64 go build -o sparsecat-linux-amd64 github.com/svenwiltink/sparsecat/cmd/sparsecat //go:generate env GOOS=linux GOARCH=amd64 go build -o sparsecat-linux-amd64 github.com/svenwiltink/sparsecat/cmd/sparsecat
//go:generate env GOOS=linux GOARCH=arm64 go build -o sparsecat-linux-arm64 github.com/svenwiltink/sparsecat/cmd/sparsecat
// Copyright 2022 Linka Cloud All rights reserved. // Copyright 2022 Linka Cloud All rights reserved.
// //
@ -33,7 +34,21 @@ import (
) )
//go:embed sparsecat-linux-amd64 //go:embed sparsecat-linux-amd64
var sparsecatBinary []byte var sparsecatAmdBinary []byte
//go:embed sparsecat-linux-arm64
var sparsecatArmBinary []byte
func Sparsecat(arch string) ([]byte, error) {
switch arch {
case "amd64":
return sparsecatAmdBinary, nil
case "arm64":
return sparsecatArmBinary, nil
default:
return nil, fmt.Errorf("unsupported architecture: %s", arch)
}
}
// Handle flags with multiple occurrences // Handle flags with multiple occurrences
type MultipleFlag []string type MultipleFlag []string

View File

@ -30,7 +30,7 @@ import (
) )
func testConfig(t *testing.T, ctx context.Context, name, img string, config Config, luks, grubBIOS, grubEFI bool) { func testConfig(t *testing.T, ctx context.Context, name, img string, config Config, luks, grubBIOS, grubEFI bool) {
require.NoError(t, docker.Pull(ctx, img)) require.NoError(t, docker.Pull(ctx, Arch, img))
tmpPath := filepath.Join(os.TempDir(), "d2vm-tests", strings.NewReplacer(":", "-", ".", "-").Replace(name)) tmpPath := filepath.Join(os.TempDir(), "d2vm-tests", strings.NewReplacer(":", "-", ".", "-").Replace(name))
require.NoError(t, os.MkdirAll(tmpPath, 0755)) require.NoError(t, os.MkdirAll(tmpPath, 0755))
defer os.RemoveAll(tmpPath) defer os.RemoveAll(tmpPath)
@ -52,7 +52,7 @@ func testConfig(t *testing.T, ctx context.Context, name, img string, config Conf
require.NoError(t, d.Render(f)) require.NoError(t, d.Render(f))
imgUUID := uuid.New().String() imgUUID := uuid.New().String()
logrus.Infof("building kernel enabled image") logrus.Infof("building kernel enabled image")
require.NoError(t, docker.Build(ctx, imgUUID, p, dir)) require.NoError(t, docker.Build(ctx, false, imgUUID, p, dir, Arch))
defer docker.Remove(ctx, imgUUID) defer docker.Remove(ctx, imgUUID)
// we don't need to test the kernel location if grub is enabled // we don't need to test the kernel location if grub is enabled
if grubBIOS || grubEFI { if grubBIOS || grubEFI {

View File

@ -36,7 +36,7 @@ ADD --chown=%[1]d:%[1]d %[2]s /disk/
` `
) )
func MakeContainerDisk(ctx context.Context, path string, tag string) error { func MakeContainerDisk(ctx context.Context, path string, tag string, platform string) error {
tmpPath := filepath.Join(os.TempDir(), "d2vm", uuid.New().String()) tmpPath := filepath.Join(os.TempDir(), "d2vm", uuid.New().String())
if err := os.MkdirAll(tmpPath, os.ModePerm); err != nil { if err := os.MkdirAll(tmpPath, os.ModePerm); err != nil {
return err return err
@ -60,7 +60,7 @@ func MakeContainerDisk(ctx context.Context, path string, tag string) error {
if err := os.WriteFile(dockerfile, []byte(dockerfileContent), os.ModePerm); err != nil { if err := os.WriteFile(dockerfile, []byte(dockerfileContent), os.ModePerm); err != nil {
return fmt.Errorf("failed to write dockerfile: %w", err) return fmt.Errorf("failed to write dockerfile: %w", err)
} }
if err := docker.Build(ctx, tag, dockerfile, tmpPath); err != nil { if err := docker.Build(ctx, false, tag, dockerfile, tmpPath, platform); err != nil {
return fmt.Errorf("failed to build container disk: %w", err) return fmt.Errorf("failed to build container disk: %w", err)
} }
return nil return nil

View File

@ -67,7 +67,7 @@ func Convert(ctx context.Context, img string, opts ...ConvertOption) error {
return err return err
} }
logrus.Infof("building kernel enabled image") logrus.Infof("building kernel enabled image")
if err := docker.Build(ctx, imgUUID, p, dir); err != nil { if err := docker.Build(ctx, o.pull, imgUUID, p, dir, o.platform); err != nil {
return err return err
} }
if !o.keepCache { if !o.keepCache {
@ -88,7 +88,7 @@ func Convert(ctx context.Context, img string, opts ...ConvertOption) error {
if format == "" { if format == "" {
format = "raw" format = "raw"
} }
b, err := NewBuilder(ctx, tmpPath, imgUUID, "", o.size, r, format, o.cmdLineExtra, o.splitBoot, o.bootFS, o.bootSize, o.luksPassword, o.bootLoader) b, err := NewBuilder(ctx, tmpPath, imgUUID, "", o.size, r, format, o.cmdLineExtra, o.splitBoot, o.bootFS, o.bootSize, o.luksPassword, o.bootLoader, o.platform)
if err != nil { if err != nil {
return err return err
} }

View File

@ -32,6 +32,8 @@ type convertOptions struct {
luksPassword string luksPassword string
keepCache bool keepCache bool
platform string
pull bool
} }
func (o *convertOptions) hasGrubBIOS() bool { func (o *convertOptions) hasGrubBIOS() bool {
@ -113,3 +115,15 @@ func WithKeepCache(b bool) ConvertOption {
o.keepCache = b o.keepCache = b
} }
} }
func WithPlatform(platform string) ConvertOption {
return func(o *convertOptions) {
o.platform = platform
}
}
func WithPull(b bool) ConvertOption {
return func(o *convertOptions) {
o.pull = b
}
}

View File

@ -140,7 +140,7 @@ RUN rm -rf /etc/apk
require.NoError(t, os.WriteFile(filepath.Join(tmp, "hostname"), []byte("d2vm-flatten-test"), perm)) require.NoError(t, os.WriteFile(filepath.Join(tmp, "hostname"), []byte("d2vm-flatten-test"), perm))
require.NoError(t, os.WriteFile(filepath.Join(tmp, "resolv.conf"), []byte("nameserver 8.8.8.8"), perm)) require.NoError(t, os.WriteFile(filepath.Join(tmp, "resolv.conf"), []byte("nameserver 8.8.8.8"), perm))
require.NoError(t, os.WriteFile(filepath.Join(tmp, "Dockerfile"), []byte(dockerfile), perm)) require.NoError(t, os.WriteFile(filepath.Join(tmp, "Dockerfile"), []byte(dockerfile), perm))
require.NoError(t, docker.Build(ctx, img, "", tmp)) require.NoError(t, docker.Build(ctx, false, img, "", tmp, "linux/amd64"))
defer docker.Remove(ctx, img) defer docker.Remove(ctx, img)
imgTmp := filepath.Join(tmp, "image") imgTmp := filepath.Join(tmp, "image")

View File

@ -12,7 +12,7 @@ d2vm build [context directory] [flags]
--append-to-cmdline string Extra kernel cmdline arguments to append to the generated one --append-to-cmdline string Extra kernel cmdline arguments to append to the generated one
--boot-fs string Filesystem to use for the boot partition, ext4 or fat32 --boot-fs string Filesystem to use for the boot partition, ext4 or fat32
--boot-size uint Size of the boot partition in MB (default 100) --boot-size uint Size of the boot partition in MB (default 100)
--bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi (default "syslinux") --bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi, defaults to syslinux on amd64 and grub-efi on arm64
--build-arg stringArray Set build-time variables --build-arg stringArray Set build-time variables
-f, --file string Name of the Dockerfile -f, --file string Name of the Dockerfile
--force Override output qcow2 image --force Override output qcow2 image
@ -22,6 +22,8 @@ d2vm build [context directory] [flags]
--network-manager string Network manager to use for the image: none, netplan, ifupdown --network-manager string Network manager to use for the image: none, netplan, ifupdown
-o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2") -o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2")
-p, --password string Optional root user password -p, --password string Optional root user password
--platform string Platform to use for the container disk image, linux/arm64 and linux/arm64 are supported (default "linux/amd64")
--pull Always pull docker image
--push Push the container disk image to the registry --push Push the container disk image to the registry
--raw Just convert the container to virtual machine image without installing anything more --raw Just convert the container to virtual machine image without installing anything more
-s, --size string The output image size (default "10G") -s, --size string The output image size (default "10G")

View File

@ -12,7 +12,7 @@ d2vm convert [docker image] [flags]
--append-to-cmdline string Extra kernel cmdline arguments to append to the generated one --append-to-cmdline string Extra kernel cmdline arguments to append to the generated one
--boot-fs string Filesystem to use for the boot partition, ext4 or fat32 --boot-fs string Filesystem to use for the boot partition, ext4 or fat32
--boot-size uint Size of the boot partition in MB (default 100) --boot-size uint Size of the boot partition in MB (default 100)
--bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi (default "syslinux") --bootloader string Bootloader to use: syslinux, grub, grub-bios, grub-efi, defaults to syslinux on amd64 and grub-efi on arm64
--force Override output qcow2 image --force Override output qcow2 image
-h, --help help for convert -h, --help help for convert
--keep-cache Keep the images after the build --keep-cache Keep the images after the build
@ -20,6 +20,7 @@ d2vm convert [docker image] [flags]
--network-manager string Network manager to use for the image: none, netplan, ifupdown --network-manager string Network manager to use for the image: none, netplan, ifupdown
-o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2") -o, --output string The output image, the extension determine the image format, raw will be used if none. Supported formats: qcow2 qed raw vdi vhd vmdk (default "disk0.qcow2")
-p, --password string Optional root user password -p, --password string Optional root user password
--platform string Platform to use for the container disk image, linux/arm64 and linux/arm64 are supported (default "linux/amd64")
--pull Always pull docker image --pull Always pull docker image
--push Push the container disk image to the registry --push Push the container disk image to the registry
--raw Just convert the container to virtual machine image without installing anything more --raw Just convert the container to virtual machine image without installing anything more

View File

@ -10,10 +10,12 @@ d2vm run hetzner [options] image-path [flags]
``` ```
-h, --help help for hetzner -h, --help help for hetzner
-l, --location string d2vm server location (default "hel1-dc2")
-n, --name string d2vm server name (default "d2vm") -n, --name string d2vm server name (default "d2vm")
--rm remove server when done --rm remove server when done
-i, --ssh-key string d2vm image identity key -i, --ssh-key string d2vm image identity key
--token string Hetzner Cloud API token [$HETZNER_TOKEN] --token string Hetzner Cloud API token [$HETZNER_TOKEN]
-t, --type string d2vm server type (default "cx11")
-u, --user string d2vm image ssh user (default "root") -u, --user string d2vm image ssh user (default "root")
``` ```

28
go.mod
View File

@ -8,24 +8,24 @@ require (
github.com/fatih/color v1.13.0 github.com/fatih/color v1.13.0
github.com/google/go-containerregistry v0.14.0 github.com/google/go-containerregistry v0.14.0
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/hetznercloud/hcloud-go v1.35.2 github.com/hetznercloud/hcloud-go v1.50.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/pkg/sftp v1.10.1 github.com/pkg/sftp v1.10.1
github.com/sirupsen/logrus v1.9.0 github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.7.0 github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.1 github.com/stretchr/testify v1.8.4
github.com/svenwiltink/sparsecat v1.0.0 github.com/svenwiltink/sparsecat v1.0.0
go.linka.cloud/console v0.0.0-20220910100646-48f9f2b8843b go.linka.cloud/console v0.0.0-20220910100646-48f9f2b8843b
go.uber.org/multierr v1.11.0 go.uber.org/multierr v1.11.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 golang.org/x/crypto v0.11.0
golang.org/x/sys v0.7.0 golang.org/x/sys v0.10.0
) )
require ( require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/creack/pty v1.1.15 // indirect github.com/creack/pty v1.1.15 // indirect
@ -42,23 +42,23 @@ require (
github.com/kr/pretty v0.3.1 // indirect github.com/kr/pretty v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2 // indirect github.com/opencontainers/image-spec v1.1.0-rc2 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/vbatts/tar-split v0.11.3 // indirect github.com/vbatts/tar-split v0.11.3 // indirect
golang.org/x/net v0.8.0 // indirect golang.org/x/net v0.12.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.2.0 // indirect
golang.org/x/text v0.8.0 // indirect golang.org/x/text v0.11.0 // indirect
google.golang.org/protobuf v1.29.0 // indirect google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

43
go.sum
View File

@ -8,8 +8,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdSE0JxlhR2hKnGPcNB35BjQf4RYQDY=
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
@ -37,6 +37,7 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
@ -53,8 +54,8 @@ github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMd
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hetznercloud/hcloud-go v1.35.2 h1:eEDtmDiI2plZ2UQmj4YpiYse5XbtpXOUBpAdIOLxzgE= github.com/hetznercloud/hcloud-go v1.50.0 h1:vS9tJvmSRwgDpMLmPnThGN87Rz8OMP3D4M3rWm8QHEQ=
github.com/hetznercloud/hcloud-go v1.35.2/go.mod h1:mepQwR6va27S3UQthaEPGS86jtzSY9xWL1e9dyxXpgA= github.com/hetznercloud/hcloud-go v1.50.0/go.mod h1:VzDWThl47lOnZXY0q5/LPFD+M62pfe/52TV+mOrpp9Q=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
@ -78,8 +79,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI=
@ -101,12 +102,15 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s= github.com/prometheus/client_golang v1.11.1 h1:+4eQaD7vAZ6DsfsxB15hbE0odUjGI5ARs9yskGu1v4s=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
@ -128,8 +132,9 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/svenwiltink/sparsecat v1.0.0 h1:SBDEIImxhD//8MskqodFR9VcixWKkZAPAW35nmA4vcw= github.com/svenwiltink/sparsecat v1.0.0 h1:SBDEIImxhD//8MskqodFR9VcixWKkZAPAW35nmA4vcw=
github.com/svenwiltink/sparsecat v1.0.0/go.mod h1:TdtvJbeTZcd+3cMQpttW6MJl/iPGZT0GHmckep0hoxU= github.com/svenwiltink/sparsecat v1.0.0/go.mod h1:TdtvJbeTZcd+3cMQpttW6MJl/iPGZT0GHmckep0hoxU=
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
@ -147,15 +152,15 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -171,15 +176,15 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=

View File

@ -57,7 +57,10 @@ type grubProvider struct {
config Config config Config
} }
func (g grubProvider) New(c Config, r OSRelease) (Bootloader, error) { func (g grubProvider) New(c Config, r OSRelease, arch string) (Bootloader, error) {
if arch != "x86_64" {
return nil, fmt.Errorf("grub is only supported for amd64")
}
if r.ID == ReleaseCentOS { if r.ID == ReleaseCentOS {
return nil, fmt.Errorf("grub (efi) is not supported for CentOS, use grub-bios instead") return nil, fmt.Errorf("grub (efi) is not supported for CentOS, use grub-bios instead")
} }

View File

@ -16,6 +16,7 @@ package d2vm
import ( import (
"context" "context"
"fmt"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -48,7 +49,10 @@ type grubBiosProvider struct {
config Config config Config
} }
func (g grubBiosProvider) New(c Config, r OSRelease) (Bootloader, error) { func (g grubBiosProvider) New(c Config, r OSRelease, arch string) (Bootloader, error) {
if arch != "x86_64" {
return nil, fmt.Errorf("grub-bios is only supported for amd64")
}
return grubBios{grubCommon: newGrubCommon(c, r)}, nil return grubBios{grubCommon: newGrubCommon(c, r)}, nil
} }

View File

@ -23,6 +23,7 @@ import (
type grubEFI struct { type grubEFI struct {
*grubCommon *grubCommon
arch string
} }
func (g grubEFI) Validate(fs BootFS) error { func (g grubEFI) Validate(fs BootFS) error {
@ -41,7 +42,7 @@ func (g grubEFI) Setup(ctx context.Context, dev, root string, cmdline string) er
return err return err
} }
defer clean() defer clean()
if err := g.install(ctx, "--target=x86_64-efi", "--efi-directory=/boot", "--no-nvram", "--removable", "--no-floppy"); err != nil { if err := g.install(ctx, "--target="+g.arch+"-efi", "--efi-directory=/boot", "--no-nvram", "--removable", "--no-floppy"); err != nil {
return err return err
} }
if err := g.mkconfig(ctx); err != nil { if err := g.mkconfig(ctx); err != nil {
@ -54,11 +55,11 @@ type grubEFIProvider struct {
config Config config Config
} }
func (g grubEFIProvider) New(c Config, r OSRelease) (Bootloader, error) { func (g grubEFIProvider) New(c Config, r OSRelease, arch string) (Bootloader, error) {
if r.ID == ReleaseCentOS { if r.ID == ReleaseCentOS {
return nil, fmt.Errorf("grub-efi is not supported for CentOS, use grub-bios instead") return nil, fmt.Errorf("grub-efi is not supported for CentOS, use grub-bios instead")
} }
return grubEFI{grubCommon: newGrubCommon(c, r)}, nil return grubEFI{grubCommon: newGrubCommon(c, r), arch: arch}, nil
} }
func (g grubEFIProvider) Name() string { func (g grubEFIProvider) Name() string {

View File

@ -50,11 +50,14 @@ func CmdOut(ctx context.Context, args ...string) (string, string, error) {
return exec.RunOut(ctx, "docker", args...) return exec.RunOut(ctx, "docker", args...)
} }
func Build(ctx context.Context, tag, dockerfile, dir string, buildArgs ...string) error { func Build(ctx context.Context, pull bool, tag, dockerfile, dir, platform string, buildArgs ...string) error {
if dockerfile == "" { if dockerfile == "" {
dockerfile = filepath.Join(dir, "Dockerfile") dockerfile = filepath.Join(dir, "Dockerfile")
} }
args := []string{"image", "build", "-t", tag, "-f", dockerfile} args := []string{"image", "build", "-t", tag, "-f", dockerfile, "--platform", platform}
if pull {
args = append(args, "--pull")
}
for _, v := range buildArgs { for _, v := range buildArgs {
args = append(args, "--build-arg", v) args = append(args, "--build-arg", v)
} }
@ -96,8 +99,8 @@ func ImageSave(ctx context.Context, tag, file string) error {
return Cmd(ctx, "image", "save", "-o", file, tag) return Cmd(ctx, "image", "save", "-o", file, tag)
} }
func Pull(ctx context.Context, tag string) error { func Pull(ctx context.Context, platform, tag string) error {
return Cmd(ctx, "image", "pull", tag) return Cmd(ctx, "image", "pull", "--platform", platform, tag)
} }
func Push(ctx context.Context, tag string) error { func Push(ctx context.Context, tag string) error {

View File

@ -71,7 +71,10 @@ func (s syslinux) Setup(ctx context.Context, dev, root string, cmdline string) e
type syslinuxProvider struct{} type syslinuxProvider struct{}
func (s syslinuxProvider) New(c Config, _ OSRelease) (Bootloader, error) { func (s syslinuxProvider) New(c Config, _ OSRelease, arch string) (Bootloader, error) {
if arch != "x86_64" {
return nil, fmt.Errorf("syslinux is only supported for amd64")
}
mbrBin := "" mbrBin := ""
for _, v := range mbrPaths { for _, v := range mbrPaths {
if _, err := os.Stat(v); err == nil { if _, err := os.Stat(v); err == nil {

View File

@ -15,7 +15,8 @@ RUN apt-get update && \
linux-image-amd64 && \ linux-image-amd64 && \
find /boot -type l -exec rm {} \; find /boot -type l -exec rm {} \;
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ RUN ARCH="$([ "$(uname -m)" = "x86_64" ] && echo amd64 || echo arm64)"; \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
systemd-sysv \ systemd-sysv \
systemd \ systemd \
{{- if .Grub }} {{- if .Grub }}
@ -26,7 +27,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
grub-pc-bin \ grub-pc-bin \
{{- end }} {{- end }}
{{- if .GrubEFI }} {{- if .GrubEFI }}
grub-efi-amd64-bin \ grub-efi-${ARCH}-bin \
{{- end }} {{- end }}
dbus \ dbus \
iproute2 \ iproute2 \

View File

@ -2,7 +2,8 @@ FROM {{ .Image }}
USER root USER root
RUN apt-get update && \ RUN ARCH="$([ "$(uname -m)" = "x86_64" ] && echo amd64 || echo arm64)"; \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \ DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
linux-image-virtual \ linux-image-virtual \
initramfs-tools \ initramfs-tools \
@ -16,7 +17,7 @@ RUN apt-get update && \
grub-pc-bin \ grub-pc-bin \
{{- end }} {{- end }}
{{- if .GrubEFI }} {{- if .GrubEFI }}
grub-efi-amd64-bin \ grub-efi-${ARCH}-bin \
{{- end }} {{- end }}
dbus \ dbus \
isc-dhcp-client \ isc-dhcp-client \

View File

@ -15,10 +15,14 @@
package d2vm package d2vm
import ( import (
"fmt"
"runtime"
"go.linka.cloud/d2vm/pkg/qemu_img" "go.linka.cloud/d2vm/pkg/qemu_img"
) )
var ( var (
Arch = fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH)
Version = "" Version = ""
BuildDate = "" BuildDate = ""
Image = "linkacloud/d2vm" Image = "linkacloud/d2vm"