sources: Add openSUSE
Signed-off-by: Thomas Hipp <thomas.hipp@canonical.com>
This commit is contained in:
parent
addeb7bc3e
commit
1609d38f61
162
sources/opensuse-http.go
Normal file
162
sources/opensuse-http.go
Normal file
@ -0,0 +1,162 @@
|
||||
package sources
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/lxc/distrobuilder/shared"
|
||||
lxd "github.com/lxc/lxd/shared"
|
||||
"gopkg.in/antchfx/htmlquery.v1"
|
||||
)
|
||||
|
||||
// OpenSUSEHTTP represents the OpenSUSE HTTP downloader.
|
||||
type OpenSUSEHTTP struct{}
|
||||
|
||||
// NewOpenSUSEHTTP creates a new OpenSUSEHTTP instance.
|
||||
func NewOpenSUSEHTTP() *OpenSUSEHTTP {
|
||||
return &OpenSUSEHTTP{}
|
||||
}
|
||||
|
||||
// Run downloads an OpenSUSE tarball.
|
||||
func (s *OpenSUSEHTTP) Run(definition shared.Definition, rootfsDir string) error {
|
||||
var baseURL string
|
||||
var fname string
|
||||
|
||||
tarballPath := s.getPathToTarball(definition.Source.URL, definition.Image.Release,
|
||||
definition.Image.ArchitectureMapped)
|
||||
|
||||
resp, err := http.Head(tarballPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't resolve URL: %v", err)
|
||||
}
|
||||
|
||||
baseURL, fname = path.Split(resp.Request.URL.String())
|
||||
|
||||
url, err := url.Parse(fmt.Sprintf("%s/%s", baseURL, fname))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fpath, err := shared.DownloadHash(definition.Image, url.String(), "", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error downloading openSUSE image: %s", err)
|
||||
}
|
||||
|
||||
if definition.Source.SkipVerification {
|
||||
// Unpack
|
||||
return lxd.Unpack(filepath.Join(fpath, fname), rootfsDir, false, false, nil)
|
||||
}
|
||||
|
||||
checksumPath := fmt.Sprintf("%s.sha256", tarballPath)
|
||||
checksumFile := path.Base(checksumPath)
|
||||
|
||||
shared.DownloadHash(definition.Image, checksumPath, "", nil)
|
||||
valid, err := shared.VerifyFile(filepath.Join(fpath, checksumFile), "",
|
||||
definition.Source.Keys, definition.Source.Keyserver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !valid {
|
||||
return errors.New("Failed to verify tarball")
|
||||
}
|
||||
|
||||
// Manually verify the checksum
|
||||
checksum, err := shared.GetSignedContent(filepath.Join(fpath, checksumFile),
|
||||
definition.Source.Keys, definition.Source.Keyserver)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to read signed file: %v", err)
|
||||
}
|
||||
|
||||
imagePath := filepath.Join(fpath, fname)
|
||||
|
||||
image, err := os.Open(imagePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to verify image: %v", err)
|
||||
}
|
||||
|
||||
hash := sha256.New()
|
||||
_, err = io.Copy(hash, image)
|
||||
if err != nil {
|
||||
image.Close()
|
||||
return fmt.Errorf("Failed to verify image: %v", err)
|
||||
}
|
||||
|
||||
image.Close()
|
||||
|
||||
result := fmt.Sprintf("%x", hash.Sum(nil))
|
||||
checksumStr := strings.TrimSpace(string(checksum))
|
||||
|
||||
if result != checksumStr {
|
||||
return fmt.Errorf("Hash mismatch for %s: %s != %s", imagePath, result, checksumStr)
|
||||
}
|
||||
|
||||
// Unpack
|
||||
return lxd.Unpack(filepath.Join(fpath, fname), rootfsDir, false, false, nil)
|
||||
}
|
||||
|
||||
func (s *OpenSUSEHTTP) getLatestBuild(URL string) string {
|
||||
doc, err := htmlquery.LoadURL(URL)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if doc == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
nodes := htmlquery.Find(doc, `//a[starts-with(text(),'opensuse')][ends-with(text(), 'tar.xz')][@href]/text()`)
|
||||
|
||||
if nodes == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return nodes[len(nodes)-1].Data
|
||||
}
|
||||
|
||||
func (s *OpenSUSEHTTP) getPathToTarball(baseURL string, release string, arch string) string {
|
||||
u, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
u.Path = path.Join(u.Path, "repositories", "Virtualization:", "containers:", "images:")
|
||||
|
||||
if strings.ToLower(release) == "tumbleweed" {
|
||||
u.Path = path.Join(u.Path, "openSUSE-Tumbleweed")
|
||||
|
||||
switch arch {
|
||||
case "i686", "x86_64":
|
||||
u.Path = path.Join(u.Path, "container")
|
||||
case "aarch64":
|
||||
u.Path = path.Join(u.Path, "container_ARM")
|
||||
case "ppc64le":
|
||||
u.Path = path.Join(u.Path, "container_PowerPC")
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
u.Path = path.Join(u.Path, fmt.Sprintf("opensuse-tumbleweed-image.%s-lxc.tar.xz",
|
||||
arch))
|
||||
} else {
|
||||
u.Path = path.Join(u.Path, fmt.Sprintf("openSUSE-Leap-%s", release))
|
||||
|
||||
switch arch {
|
||||
case "x86_64":
|
||||
u.Path = path.Join(u.Path, "containers")
|
||||
case "aarch64", "ppc64le":
|
||||
u.Path = path.Join(u.Path, "containers_ports")
|
||||
}
|
||||
|
||||
u.Path = path.Join(u.Path, s.getLatestBuild(u.String()))
|
||||
}
|
||||
|
||||
return u.String()
|
||||
}
|
@ -30,6 +30,8 @@ func Get(name string) Downloader {
|
||||
return NewDockerHTTP()
|
||||
case "oraclelinux-http":
|
||||
return NewOracleLinuxHTTP()
|
||||
case "opensuse-http":
|
||||
return NewOpenSUSEHTTP()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
Loading…
Reference in New Issue
Block a user