[lxc-devel] [distrobuilder/master] Add gentoo and portage

monstermunchkin on Github lxc-bot at linuxcontainers.org
Tue Apr 3 15:33:38 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 309 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180403/bb300187/attachment.bin>
-------------- next part --------------
From b47fd377627bde3addf02560f04a67b3244e09cc Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Thu, 29 Mar 2018 15:38:10 +0200
Subject: [PATCH 1/4] shared,sources: Add functions DownloadSha{256,512}

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 shared/net.go             | 34 ++++++++++++++++++++++++++--------
 sources/alpine-http.go    |  4 ++--
 sources/archlinux-http.go |  4 ++--
 sources/centos-http.go    |  4 ++--
 sources/fedora-http.go    |  2 +-
 sources/ubuntu-http.go    |  6 +++---
 6 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/shared/net.go b/shared/net.go
index 84dcb78..589f984 100644
--- a/shared/net.go
+++ b/shared/net.go
@@ -3,7 +3,9 @@ package shared
 import (
 	"bufio"
 	"crypto/sha256"
+	"crypto/sha512"
 	"fmt"
+	"hash"
 	"io"
 	"io/ioutil"
 	"net/http"
@@ -16,9 +18,19 @@ import (
 	"github.com/lxc/lxd/shared/ioprogress"
 )
 
-// Download downloads a file. If a checksum file is provided will try and match
-// the hash.
-func Download(file, checksum string) error {
+// DownloadSha256 downloads a file. If a checksum file is provided will try and
+// match the sha256 hash.
+func DownloadSha256(file, checksum string) error {
+	return download(file, checksum, sha256.New())
+}
+
+// DownloadSha512 downloads a file. If a checksum file is provided will try and
+// match the sha512 hash.
+func DownloadSha512(file, checksum string) error {
+	return download(file, checksum, sha512.New())
+}
+
+func download(file, checksum string, sha hash.Hash) error {
 	var (
 		client http.Client
 		hash   string
@@ -43,13 +55,12 @@ func Download(file, checksum string) error {
 		defer image.Close()
 
 		if checksum != "" {
-			sha256 := sha256.New()
-			_, err = io.Copy(sha256, image)
+			_, err = io.Copy(sha, image)
 			if err != nil {
 				return err
 			}
 
-			result := fmt.Sprintf("%x", sha256.Sum(nil))
+			result := fmt.Sprintf("%x", sha.Sum(nil))
 			if result != hash {
 				return fmt.Errorf("Hash mismatch for %s: %s != %s", imagePath, result, hash)
 			}
@@ -68,8 +79,15 @@ func Download(file, checksum string) error {
 		fmt.Printf("%s\r", progress.Text)
 	}
 
-	_, err = lxd.DownloadFileSha256(&client, "", progress, nil, imagePath,
-		file, hash, image)
+	if sha.Size() == 32 {
+		_, err = lxd.DownloadFileSha256(&client, "", progress, nil, imagePath,
+			file, hash, image)
+	} else if sha.Size() == 64 {
+		_, err = lxd.DownloadFileSha512(&client, "", progress, nil, imagePath,
+			file, hash, image)
+	} else {
+		return fmt.Errorf("Cannot handle sha%d", sha.Size()*8)
+	}
 	if err != nil {
 		if checksum == "" && strings.HasPrefix(err.Error(), "Hash mismatch") {
 			return nil
diff --git a/sources/alpine-http.go b/sources/alpine-http.go
index 5be670b..6435bdc 100644
--- a/sources/alpine-http.go
+++ b/sources/alpine-http.go
@@ -38,14 +38,14 @@ func (s *AlpineLinuxHTTP) Run(definition shared.Definition, rootfsDir string) er
 		return errors.New("GPG keys are required if downloading from HTTP")
 	}
 
-	err = shared.Download(tarball, tarball+".sha256")
+	err = shared.DownloadSha256(tarball, tarball+".sha256")
 	if err != nil {
 		return err
 	}
 
 	// Force gpg checks when using http
 	if url.Scheme != "https" {
-		shared.Download(tarball+".asc", "")
+		shared.DownloadSha256(tarball+".asc", "")
 		valid, err := shared.VerifyFile(
 			filepath.Join(os.TempDir(), fname),
 			filepath.Join(os.TempDir(), fname+".asc"),
diff --git a/sources/archlinux-http.go b/sources/archlinux-http.go
index 6ca7d51..13b62c0 100644
--- a/sources/archlinux-http.go
+++ b/sources/archlinux-http.go
@@ -37,14 +37,14 @@ func (s *ArchLinuxHTTP) Run(definition shared.Definition, rootfsDir string) erro
 		return errors.New("GPG keys are required if downloading from HTTP")
 	}
 
-	err = shared.Download(tarball, "")
+	err = shared.DownloadSha256(tarball, "")
 	if err != nil {
 		return err
 	}
 
 	// Force gpg checks when using http
 	if url.Scheme != "https" {
-		shared.Download(tarball+".sig", "")
+		shared.DownloadSha256(tarball+".sig", "")
 
 		valid, err := shared.VerifyFile(
 			filepath.Join(os.TempDir(), fname),
diff --git a/sources/centos-http.go b/sources/centos-http.go
index f94f28e..e265fcd 100644
--- a/sources/centos-http.go
+++ b/sources/centos-http.go
@@ -51,7 +51,7 @@ func (s *CentOSHTTP) Run(definition shared.Definition, rootfsDir string) error {
 		}
 
 		checksumFile = "sha256sum.txt.asc"
-		shared.Download(baseURL+checksumFile, "")
+		shared.DownloadSha256(baseURL+checksumFile, "")
 		valid, err := shared.VerifyFile(filepath.Join(os.TempDir(), checksumFile), "",
 			definition.Source.Keys, definition.Source.Keyserver)
 		if err != nil {
@@ -62,7 +62,7 @@ func (s *CentOSHTTP) Run(definition shared.Definition, rootfsDir string) error {
 		}
 	}
 
-	err = shared.Download(baseURL+s.fname, checksumFile)
+	err = shared.DownloadSha256(baseURL+s.fname, checksumFile)
 	if err != nil {
 		return fmt.Errorf("Error downloading CentOS image: %s", err)
 	}
diff --git a/sources/fedora-http.go b/sources/fedora-http.go
index 7e87803..673936d 100644
--- a/sources/fedora-http.go
+++ b/sources/fedora-http.go
@@ -41,7 +41,7 @@ func (s *FedoraHTTP) Run(definition shared.Definition, rootfsDir string) error {
 		definition.Image.Release, build, definition.Image.ArchitectureMapped)
 
 	// Download image
-	err = shared.Download(fmt.Sprintf("%s/%s/%s/images/%s",
+	err = shared.DownloadSha256(fmt.Sprintf("%s/%s/%s/images/%s",
 		baseURL, definition.Image.Release, build, fname), "")
 	if err != nil {
 		return err
diff --git a/sources/ubuntu-http.go b/sources/ubuntu-http.go
index 1e7d71f..b875bcd 100644
--- a/sources/ubuntu-http.go
+++ b/sources/ubuntu-http.go
@@ -57,8 +57,8 @@ func (s *UbuntuHTTP) Run(definition shared.Definition, rootfsDir string) error {
 		}
 
 		checksumFile = baseURL + "SHA256SUMS"
-		shared.Download(baseURL+"SHA256SUMS.gpg", "")
-		shared.Download(checksumFile, "")
+		shared.DownloadSha256(baseURL+"SHA256SUMS.gpg", "")
+		shared.DownloadSha256(checksumFile, "")
 
 		valid, err := shared.VerifyFile(
 			filepath.Join(os.TempDir(), "SHA256SUMS"),
@@ -73,7 +73,7 @@ func (s *UbuntuHTTP) Run(definition shared.Definition, rootfsDir string) error {
 		}
 	}
 
-	err = shared.Download(baseURL+s.fname, checksumFile)
+	err = shared.DownloadSha256(baseURL+s.fname, checksumFile)
 	if err != nil {
 		return fmt.Errorf("Error downloading Ubuntu image: %s", err)
 	}

From 3a4d03ca82e6c7476b8a4a2e43eca0e4c105b4e2 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Thu, 29 Mar 2018 16:03:35 +0200
Subject: [PATCH 2/4] sources: Add Gentoo

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 shared/definition.go |   1 +
 sources/gentoo.go    | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++
 sources/source.go    |   2 +
 3 files changed, 106 insertions(+)
 create mode 100644 sources/gentoo.go

diff --git a/shared/definition.go b/shared/definition.go
index 8397725..4546530 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -187,6 +187,7 @@ func (d *Definition) Validate() error {
 		"centos-http",
 		"debootstrap",
 		"fedora-http",
+		"gentoo-http",
 		"ubuntu-http",
 	}
 	if !shared.StringInSlice(strings.TrimSpace(d.Source.Downloader), validDownloaders) {
diff --git a/sources/gentoo.go b/sources/gentoo.go
new file mode 100644
index 0000000..8a85069
--- /dev/null
+++ b/sources/gentoo.go
@@ -0,0 +1,103 @@
+package sources
+
+import (
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"os"
+	"path/filepath"
+	"regexp"
+
+	lxd "github.com/lxc/lxd/shared"
+
+	"github.com/lxc/distrobuilder/shared"
+)
+
+// GentooHTTP represents the Alpine Linux downloader.
+type GentooHTTP struct{}
+
+// NewGentooHTTP creates a new GentooHTTP instance.
+func NewGentooHTTP() *GentooHTTP {
+	return &GentooHTTP{}
+}
+
+// Run downloads a Gentoo stage3 tarball.
+func (s *GentooHTTP) Run(definition shared.Definition, rootfsDir string) error {
+	baseURL := fmt.Sprintf("%s/releases/%s/autobuilds/current-install-%s-minimal",
+		definition.Source.URL, definition.Image.ArchitectureMapped,
+		definition.Image.ArchitectureMapped)
+	fname, err := s.getLatestBuild(baseURL, definition.Image.ArchitectureMapped)
+	if err != nil {
+		return err
+	}
+
+	if fname == "" {
+		return errors.New("Failed to determine latest build")
+	}
+
+	tarball := fmt.Sprintf("%s/%s", baseURL, fname)
+
+	url, err := url.Parse(tarball)
+	if err != nil {
+		return err
+	}
+
+	if url.Scheme != "https" && len(definition.Source.Keys) == 0 {
+		return errors.New("GPG keys are required if downloading from HTTP")
+	}
+
+	err = shared.DownloadSha512(tarball, tarball+".DIGESTS")
+	if err != nil {
+		return err
+	}
+
+	// Force gpg checks when using http
+	if url.Scheme != "https" {
+		shared.DownloadSha512(tarball+".DIGESTS.asc", "")
+		valid, err := shared.VerifyFile(
+			filepath.Join(os.TempDir(), fname+".DIGESTS.asc"),
+			"",
+			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(os.TempDir(), fname), rootfsDir, false, false)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (s *GentooHTTP) getLatestBuild(baseURL, arch 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
+	}
+
+	regex := regexp.MustCompile(fmt.Sprintf("stage3-%s-\\d{8}T\\d{6}Z.tar.xz", arch))
+
+	// Find all stage3 related files
+	matches := regex.FindAllString(string(body), -1)
+	if len(matches) > 1 {
+		// Take the first match since they're all the same anyway
+		return matches[0], nil
+	}
+
+	return "", nil
+}
diff --git a/sources/source.go b/sources/source.go
index e7f6c8b..d84f4fe 100644
--- a/sources/source.go
+++ b/sources/source.go
@@ -20,6 +20,8 @@ func Get(name string) Downloader {
 		return NewDebootstrap()
 	case "fedora-http":
 		return NewFedoraHTTP()
+	case "gentoo-http":
+		return NewGentooHTTP()
 	case "ubuntu-http":
 		return NewUbuntuHTTP()
 	}

From d4e0bd1bf09ebf6da710b631204dbdf42b09e9c6 Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 3 Apr 2018 15:27:37 +0200
Subject: [PATCH 3/4] managers: Add portage

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 managers/manager.go  |  2 ++
 managers/portage.go  | 24 ++++++++++++++++++++++++
 shared/definition.go |  1 +
 3 files changed, 27 insertions(+)
 create mode 100644 managers/portage.go

diff --git a/managers/manager.go b/managers/manager.go
index 1c6e7af..17ebacf 100644
--- a/managers/manager.go
+++ b/managers/manager.go
@@ -35,6 +35,8 @@ func Get(name string) *Manager {
 		return NewDnf()
 	case "pacman":
 		return NewPacman()
+	case "portage":
+		return NewPortage()
 	case "yum":
 		return NewYum()
 	}
diff --git a/managers/portage.go b/managers/portage.go
new file mode 100644
index 0000000..dd12dbb
--- /dev/null
+++ b/managers/portage.go
@@ -0,0 +1,24 @@
+package managers
+
+// NewPortage creates a new Manager instance.
+func NewPortage() *Manager {
+	return &Manager{
+		command: "emerge",
+		flags: ManagerFlags{
+			global: []string{},
+			clean:  []string{},
+			install: []string{
+				"--autounmask-continue",
+			},
+			remove: []string{
+				"--unmerge",
+			},
+			refresh: []string{
+				"--sync",
+			},
+			update: []string{
+				"--update", "@world",
+			},
+		},
+	}
+}
diff --git a/shared/definition.go b/shared/definition.go
index 4546530..9a34938 100644
--- a/shared/definition.go
+++ b/shared/definition.go
@@ -199,6 +199,7 @@ func (d *Definition) Validate() error {
 		"apt",
 		"dnf",
 		"pacman",
+		"portage",
 		"yum",
 	}
 	if !shared.StringInSlice(strings.TrimSpace(d.Packages.Manager), validManagers) {

From f89b0306a89efdc617ce7b46a591f7689a10e61c Mon Sep 17 00:00:00 2001
From: Thomas Hipp <thomas.hipp at canonical.com>
Date: Tue, 3 Apr 2018 16:40:36 +0200
Subject: [PATCH 4/4] doc: Add gentoo example

Signed-off-by: Thomas Hipp <thomas.hipp at canonical.com>
---
 doc/examples/gentoo | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)
 create mode 100644 doc/examples/gentoo

diff --git a/doc/examples/gentoo b/doc/examples/gentoo
new file mode 100644
index 0000000..67ac247
--- /dev/null
+++ b/doc/examples/gentoo
@@ -0,0 +1,64 @@
+image:
+  distribution: gentoo
+  description: Gentoo
+  expiry: 30d
+  architecture: amd64
+
+source:
+  downloader: gentoo-http
+  url: http://distfiles.gentoo.org
+  keys:
+    - 13EBBDBEDE7A12775DFDB1BABB572E0E2D182910
+
+targets:
+  lxc:
+    create-message: |
+      You just created a Gentoo container (arch={{ image.architecture }})
+
+    config:
+      - type: all
+        before: 5
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/alpine.common.conf
+
+      - type: user
+        before: 5
+        content: |-
+          lxc.include = LXC_TEMPLATE_CONFIG/alpine.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: portage
+
+  update: true
+  install:
+    - neovim
+
+actions:
+  - trigger: post-packages
+    action: |-
+      #!/bin/sh
+      rm -rf /usr/portage/
+
+mappings:
+  architecture_map: debian


More information about the lxc-devel mailing list