The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/distrobuilder/pull/86
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) ===
From b47fd377627bde3addf02560f04a67b3244e09cc Mon Sep 17 00:00:00 2001 From: Thomas Hipp <thomas.h...@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.h...@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.h...@canonical.com> Date: Thu, 29 Mar 2018 16:03:35 +0200 Subject: [PATCH 2/4] sources: Add Gentoo Signed-off-by: Thomas Hipp <thomas.h...@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.h...@canonical.com> Date: Tue, 3 Apr 2018 15:27:37 +0200 Subject: [PATCH 3/4] managers: Add portage Signed-off-by: Thomas Hipp <thomas.h...@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.h...@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.h...@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
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel