[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