[lxc-devel] [distrobuilder/master] Add Void Linux

MoritzMaxeiner on Github lxc-bot at linuxcontainers.org
Sat Jul 20 16:11:01 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 320 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190720/5b626371/attachment.bin>
-------------- next part --------------
From e71724980da1451a70b7c08b9fbb31dc5d8d47f7 Mon Sep 17 00:00:00 2001
From: Moritz Maxeiner <mm at ucw.sh>
Date: Sat, 20 Jul 2019 17:50:32 +0200
Subject: [PATCH] Add Void Linux

Fixes #156
---
 doc/examples/voidlinux      |  81 +++++++++++++++++++++++++
 doc/examples/voidlinux-musl |  82 +++++++++++++++++++++++++
 managers/manager.go         |   2 +
 managers/xbps.go            |  36 +++++++++++
 shared/definition.go        |   3 +
 shared/osarch.go            |   7 +++
 sources/source.go           |   2 +
 sources/voidlinux-http.go   | 116 ++++++++++++++++++++++++++++++++++++
 8 files changed, 329 insertions(+)
 create mode 100644 doc/examples/voidlinux
 create mode 100644 doc/examples/voidlinux-musl
 create mode 100644 managers/xbps.go
 create mode 100644 sources/voidlinux-http.go

diff --git a/doc/examples/voidlinux b/doc/examples/voidlinux
new file mode 100644
index 0000000..d3282df
--- /dev/null
+++ b/doc/examples/voidlinux
@@ -0,0 +1,81 @@
+image:
+  distribution: voidlinux
+  description: Void Linux
+  expiry: 30d
+  architecture: x86_64
+
+source:
+  downloader: voidlinux-http
+  url: https://alpha.de.repo.voidlinux.org/live/current
+  keys:
+    - CF24B9C038097D8A44958E2C8DEBDA68B48282A4
+
+targets:
+  lxc:
+    create-message: |
+      You just created a Void Linux container (arch={{ image.architecture }})
+
+    config:
+      - type: all
+        before: 5
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/voidlinux.common.conf
+
+      - type: user
+        before: 5
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/voidlinux.userns.conf
+
+      - type: all
+        after: 4
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/common.conf
+
+      - type: user
+        after: 4
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/userns.conf
+
+      - type: all
+        content: |-
+          lxc.arch = {{ image.architecture_kernel }}
+
+files:
+ - path: /etc/hostname
+   generator: hostname
+
+ - path: /etc/hosts
+   generator: hosts
+
+packages:
+  manager: xbps
+
+  update: true
+  cleanup: true
+
+  sets:
+    - packages:
+      - socklog-void
+      - cronie
+      action: install
+
+actions:
+  - trigger: post-packages
+    action: |-
+      #! /bin/sh
+      set -eux
+
+      # Enable services
+      ln -s /etc/sv/socklog-unix /etc/runit/runsvdir/default/
+      ln -s /etc/sv/nanoklogd /etc/runit/runsvdir/default/
+      ln -s /etc/sv/dhcpcd-eth0 /etc/runit/runsvdir/default/
+      ln -s /etc/sv/cronie /etc/runit/runsvdir/default/
+
+      # Disable services
+      for tty in 2 3 4 5 6; do
+          rm /etc/runit/runsvdir/default/agetty-tty${tty}
+          touch /etc/sv/agetty-tty${tty}/down
+      done
+
+mappings:
+  architecture_map: voidlinux
diff --git a/doc/examples/voidlinux-musl b/doc/examples/voidlinux-musl
new file mode 100644
index 0000000..4b97ff8
--- /dev/null
+++ b/doc/examples/voidlinux-musl
@@ -0,0 +1,82 @@
+image:
+  distribution: voidlinux
+  description: Void Linux
+  expiry: 30d
+  architecture: x86_64
+
+source:
+  downloader: voidlinux-http
+  url: https://alpha.de.repo.voidlinux.org/live/current
+  keys:
+    - CF24B9C038097D8A44958E2C8DEBDA68B48282A4
+  variant: musl
+
+targets:
+  lxc:
+    create-message: |
+      You just created a Void Linux container (arch={{ image.architecture }})
+
+    config:
+      - type: all
+        before: 5
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/voidlinux.common.conf
+
+      - type: user
+        before: 5
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/voidlinux.userns.conf
+
+      - type: all
+        after: 4
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/common.conf
+
+      - type: user
+        after: 4
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/userns.conf
+
+      - type: all
+        content: |-
+          lxc.arch = {{ image.architecture_kernel }}
+
+files:
+ - path: /etc/hostname
+   generator: hostname
+
+ - path: /etc/hosts
+   generator: hosts
+
+packages:
+  manager: xbps
+
+  update: true
+  cleanup: true
+
+  sets:
+    - packages:
+      - socklog-void
+      - cronie
+      action: install
+
+actions:
+  - trigger: post-packages
+    action: |-
+      #! /bin/sh
+      set -eux
+
+      # Enable services
+      ln -s /etc/sv/socklog-unix /etc/runit/runsvdir/default/
+      ln -s /etc/sv/nanoklogd /etc/runit/runsvdir/default/
+      ln -s /etc/sv/dhcpcd-eth0 /etc/runit/runsvdir/default/
+      ln -s /etc/sv/cronie /etc/runit/runsvdir/default/
+
+      # Disable services
+      for tty in 2 3 4 5 6; do
+          rm /etc/runit/runsvdir/default/agetty-tty${tty}
+          touch /etc/sv/agetty-tty${tty}/down
+      done
+
+mappings:
+  architecture_map: voidlinux
diff --git a/managers/manager.go b/managers/manager.go
index 4965e1a..39a2393 100644
--- a/managers/manager.go
+++ b/managers/manager.go
@@ -49,6 +49,8 @@ func Get(name string) *Manager {
 		return NewPacman()
 	case "portage":
 		return NewPortage()
+	case "xbps":
+		return NewXbps()
 	case "yum":
 		return NewYum()
 	case "equo":
diff --git a/managers/xbps.go b/managers/xbps.go
new file mode 100644
index 0000000..5c449e4
--- /dev/null
+++ b/managers/xbps.go
@@ -0,0 +1,36 @@
+package managers
+
+// NewXbps creates a new Manager instance.
+func NewXbps() *Manager {
+	return &Manager{
+		commands: ManagerCommands{
+			clean:   "xbps-remove",
+			install: "xbps-install",
+			refresh: "xbps-install",
+			remove:  "xbps-remove",
+			update:  "sh",
+		},
+		flags: ManagerFlags{
+			global: []string{},
+			clean: []string{
+				"--yes",
+				"--clean-cache",
+			},
+			install: []string{
+				"--yes",
+			},
+			refresh: []string{
+				"--sync",
+			},
+			remove: []string{
+				"--yes",
+				"--recursive",
+				"--remove-orphans",
+			},
+			update: []string{
+				"-c",
+				"xbps-install --yes --update && xbps-install --yes --update",
+			},
+		},
+	}
+}
diff --git a/shared/definition.go b/shared/definition.go
index 21463d0..d9ab154 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -262,6 +262,7 @@ func (d *Definition) Validate() error {
 		"opensuse-http",
 		"openwrt-http",
 		"plamolinux-http",
+		"voidlinux-http",
 	}
 	if !shared.StringInSlice(strings.TrimSpace(d.Source.Downloader), validDownloaders) {
 		return fmt.Errorf("source.downloader must be one of %v", validDownloaders)
@@ -277,6 +278,7 @@ func (d *Definition) Validate() error {
 			"portage",
 			"yum",
 			"equo",
+			"xbps",
 			"zypper",
 		}
 		if !shared.StringInSlice(strings.TrimSpace(d.Packages.Manager), validManagers) {
@@ -336,6 +338,7 @@ func (d *Definition) Validate() error {
 		"debian",
 		"gentoo",
 		"plamolinux",
+		"voidlinux",
 	}
 
 	architectureMap := strings.TrimSpace(d.Mappings.ArchitectureMap)
diff --git a/shared/osarch.go b/shared/osarch.go
index 88da923..4c316be 100644
--- a/shared/osarch.go
+++ b/shared/osarch.go
@@ -51,6 +51,12 @@ var altLinuxArchitectureNames = map[int]string{
 	osarch.ARCH_64BIT_ARMV8_LITTLE_ENDIAN: "aarch64",
 }
 
+var voidLinuxArchitectureNames = map[int]string{
+	osarch.ARCH_32BIT_INTEL_X86:           "i686",
+	osarch.ARCH_64BIT_INTEL_X86:           "x86_64",
+	osarch.ARCH_32BIT_ARMV7_LITTLE_ENDIAN: "armv7l",
+}
+
 var distroArchitecture = map[string]map[int]string{
 	"alpinelinux": alpineLinuxArchitectureNames,
 	"altlinux":    altLinuxArchitectureNames,
@@ -59,6 +65,7 @@ var distroArchitecture = map[string]map[int]string{
 	"debian":      debianArchitectureNames,
 	"gentoo":      gentooArchitectureNames,
 	"plamolinux":  plamoLinuxArchitectureNames,
+	"voidlinux":   voidLinuxArchitectureNames,
 }
 
 // GetArch returns the correct architecture name used by the specified
diff --git a/sources/source.go b/sources/source.go
index b6f9356..4c953e7 100644
--- a/sources/source.go
+++ b/sources/source.go
@@ -38,6 +38,8 @@ func Get(name string) Downloader {
 		return NewOpenWrtHTTP()
 	case "plamolinux-http":
 		return NewPlamoLinuxHTTP()
+	case "voidlinux-http":
+		return NewVoidLinuxHTTP()
 	}
 
 	return nil
diff --git a/sources/voidlinux-http.go b/sources/voidlinux-http.go
new file mode 100644
index 0000000..21f1416
--- /dev/null
+++ b/sources/voidlinux-http.go
@@ -0,0 +1,116 @@
+package sources
+
+import (
+	"crypto/sha256"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"path/filepath"
+	"regexp"
+	"strings"
+
+	lxd "github.com/lxc/lxd/shared"
+
+	"github.com/lxc/distrobuilder/shared"
+)
+
+// VoidLinuxHTTP represents the Alpine Linux downloader.
+type VoidLinuxHTTP struct{}
+
+// NewVoidLinuxHTTP creates a new VoidLinuxHTTP instance.
+func NewVoidLinuxHTTP() *VoidLinuxHTTP {
+	return &VoidLinuxHTTP{}
+}
+
+// Run downloads a Void Linux rootfs tarball.
+func (s *VoidLinuxHTTP) Run(definition shared.Definition, rootfsDir string) error {
+	baseURL := definition.Source.URL
+	fname, err := s.getLatestBuild(baseURL, definition.Image.ArchitectureMapped, definition.Source.Variant)
+	if err != nil {
+		return err
+	}
+
+	if fname == "" {
+		return errors.New("Failed to determine latest build")
+	}
+
+	tarball := fmt.Sprintf("%s/%s", baseURL, fname)
+	digests := fmt.Sprintf("%s/sha256sums.txt", baseURL)
+	signatures := fmt.Sprintf("%s/sha256sums.txt.sig", baseURL)
+
+	url, err := url.Parse(tarball)
+	if err != nil {
+		return err
+	}
+
+	if !definition.Source.SkipVerification && url.Scheme != "https" &&
+		len(definition.Source.Keys) == 0 {
+		return errors.New("GPG keys are required if downloading from HTTP")
+	}
+
+	var fpath string
+
+	if definition.Source.SkipVerification {
+		fpath, err = shared.DownloadHash(definition.Image, tarball, "", nil)
+	} else {
+		fpath, err = shared.DownloadHash(definition.Image, tarball, digests, sha256.New())
+	}
+	if err != nil {
+		return err
+	}
+
+	// Force gpg checks when using http
+	if !definition.Source.SkipVerification && url.Scheme != "https" {
+		shared.DownloadHash(definition.Image, signatures, "", nil)
+		valid, err := shared.VerifyFile(
+			filepath.Join(fpath, "sha256sums.txt.sig"),
+			"",
+			definition.Source.Keys,
+			definition.Source.Keyserver)
+		if err != nil {
+			return err
+		}
+		if !valid {
+			return errors.New("Failed to verify tarball")
+		}
+	}
+
+	// Unpack
+	err = lxd.Unpack(filepath.Join(fpath, fname), rootfsDir, false, false, nil)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (s *VoidLinuxHTTP) getLatestBuild(baseURL, arch, variant string) (string, error) {
+	resp, err := http.Get(baseURL)
+	if err != nil {
+		return "", err
+	}
+	defer resp.Body.Close()
+
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return "", err
+	}
+
+	// Look for .tar.xz
+	selector := arch
+	if variant != "" {
+		selector = fmt.Sprintf("%s-%s", selector, variant)
+	}
+	regex := regexp.MustCompile(fmt.Sprintf(">void-%s-ROOTFS-.*.tar.xz<", selector))
+
+	// Find all rootfs related files
+	matches := regex.FindAllString(string(body), -1)
+	if len(matches) > 0 {
+		// Take the first match since they're all the same anyway
+		return strings.Trim(matches[0], "<>"), nil
+	}
+
+	return "", nil
+}


More information about the lxc-devel mailing list