mirror of
https://github.com/containers/podman
synced 2024-10-21 01:34:37 +00:00
833456e079
This PR introduces a test suite for podman machine. It can currently be run on developers' local machines and is not part of the official CI testing; however, the expectation is that any work on machine should come with an accompanying test. At present, the test must be run on Linux. It is untested on Darwin. There is no Makefile target for the test. It can be run like `ginkgo -v pkg/machine/test/.`. It should be run as a unprivileged user. Signed-off-by: Brent Baude <bbaude@redhat.com>
238 lines
5.7 KiB
Go
238 lines
5.7 KiB
Go
//go:build amd64 || arm64
|
|
// +build amd64 arm64
|
|
|
|
package machine
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
url2 "net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/coreos/stream-metadata-go/fedoracoreos"
|
|
"github.com/coreos/stream-metadata-go/release"
|
|
"github.com/coreos/stream-metadata-go/stream"
|
|
"github.com/pkg/errors"
|
|
|
|
digest "github.com/opencontainers/go-digest"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// These should eventually be moved into machine/qemu as
|
|
// they are specific to running qemu
|
|
var (
|
|
artifact = "qemu"
|
|
Format = "qcow2.xz"
|
|
)
|
|
|
|
const (
|
|
// Used for testing the latest podman in fcos
|
|
// special builds
|
|
podmanTesting = "podman-testing"
|
|
PodmanTestingHost = "fedorapeople.org"
|
|
PodmanTestingURL = "groups/podman/testing"
|
|
)
|
|
|
|
type FcosDownload struct {
|
|
Download
|
|
}
|
|
|
|
func NewFcosDownloader(vmType, vmName, imageStream string) (DistributionDownload, error) {
|
|
info, err := GetFCOSDownload(imageStream)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
urlSplit := strings.Split(info.Location, "/")
|
|
imageName := urlSplit[len(urlSplit)-1]
|
|
url, err := url2.Parse(info.Location)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
dataDir, err := GetDataDir(vmType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fcd := FcosDownload{
|
|
Download: Download{
|
|
Arch: getFcosArch(),
|
|
Artifact: artifact,
|
|
Format: Format,
|
|
ImageName: imageName,
|
|
LocalPath: filepath.Join(dataDir, imageName),
|
|
Sha256sum: info.Sha256Sum,
|
|
URL: url,
|
|
VMName: vmName,
|
|
},
|
|
}
|
|
fcd.Download.LocalUncompressedFile = fcd.getLocalUncompressedName()
|
|
return fcd, nil
|
|
}
|
|
|
|
func (f FcosDownload) Get() *Download {
|
|
return &f.Download
|
|
}
|
|
|
|
type FcosDownloadInfo struct {
|
|
CompressionType string
|
|
Location string
|
|
Release string
|
|
Sha256Sum string
|
|
}
|
|
|
|
func (f FcosDownload) HasUsableCache() (bool, error) {
|
|
// check the sha of the local image if it exists
|
|
// get the sha of the remote image
|
|
// == dont bother to pull
|
|
if _, err := os.Stat(f.LocalPath); os.IsNotExist(err) {
|
|
return false, nil
|
|
}
|
|
fd, err := os.Open(f.LocalPath)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
defer func() {
|
|
if err := fd.Close(); err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
}()
|
|
sum, err := digest.SHA256.FromReader(fd)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return sum.Encoded() == f.Sha256sum, nil
|
|
}
|
|
|
|
func getFcosArch() string {
|
|
var arch string
|
|
// TODO fill in more architectures
|
|
switch runtime.GOARCH {
|
|
case "arm64":
|
|
arch = "aarch64"
|
|
default:
|
|
arch = "x86_64"
|
|
}
|
|
return arch
|
|
}
|
|
|
|
// getStreamURL is a wrapper for the fcos.GetStream URL
|
|
// so that we can inject a special stream and url for
|
|
// testing podman before it merges into fcos builds
|
|
func getStreamURL(streamType string) url2.URL {
|
|
// For the podmanTesting stream type, we point to
|
|
// a custom url on fedorapeople.org
|
|
if streamType == podmanTesting {
|
|
return url2.URL{
|
|
Scheme: "https",
|
|
Host: PodmanTestingHost,
|
|
Path: fmt.Sprintf("%s/%s.json", PodmanTestingURL, "podman4"),
|
|
}
|
|
}
|
|
return fedoracoreos.GetStreamURL(streamType)
|
|
}
|
|
|
|
// This should get Exported and stay put as it will apply to all fcos downloads
|
|
// getFCOS parses fedoraCoreOS's stream and returns the image download URL and the release version
|
|
func GetFCOSDownload(imageStream string) (*FcosDownloadInfo, error) { //nolint:staticcheck
|
|
var (
|
|
fcosstable stream.Stream
|
|
altMeta release.Release
|
|
streamType string
|
|
)
|
|
|
|
// This is being hard set to testing. Once podman4 is in the
|
|
// fcos trees, we should remove it and re-release at least on
|
|
// macs.
|
|
// TODO: remove when podman4.0 is in coreos
|
|
|
|
imageStream = "podman-testing" //nolint:staticcheck
|
|
|
|
switch imageStream {
|
|
case "podman-testing":
|
|
streamType = "podman-testing"
|
|
case "testing", "":
|
|
streamType = fedoracoreos.StreamTesting
|
|
case "next":
|
|
streamType = fedoracoreos.StreamNext
|
|
case "stable":
|
|
streamType = fedoracoreos.StreamStable
|
|
default:
|
|
return nil, errors.Errorf("invalid stream %s: valid streams are `testing` and `stable`", imageStream)
|
|
}
|
|
streamurl := getStreamURL(streamType)
|
|
resp, err := http.Get(streamurl.String())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() {
|
|
if err := resp.Body.Close(); err != nil {
|
|
logrus.Error(err)
|
|
}
|
|
}()
|
|
if imageStream == podmanTesting {
|
|
if err := json.Unmarshal(body, &altMeta); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
arches, ok := altMeta.Architectures[getFcosArch()]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unable to pull VM image: no targetArch in stream")
|
|
}
|
|
qcow2, ok := arches.Media.Qemu.Artifacts["qcow2.xz"]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unable to pull VM image: no qcow2.xz format in stream")
|
|
}
|
|
disk := qcow2.Disk
|
|
|
|
return &FcosDownloadInfo{
|
|
Location: disk.Location,
|
|
Sha256Sum: disk.Sha256,
|
|
CompressionType: "xz",
|
|
}, nil
|
|
}
|
|
|
|
if err := json.Unmarshal(body, &fcosstable); err != nil {
|
|
return nil, err
|
|
}
|
|
arch, ok := fcosstable.Architectures[getFcosArch()]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unable to pull VM image: no targetArch in stream")
|
|
}
|
|
artifacts := arch.Artifacts
|
|
if artifacts == nil {
|
|
return nil, fmt.Errorf("unable to pull VM image: no artifact in stream")
|
|
}
|
|
qemu, ok := artifacts[artifact]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unable to pull VM image: no qemu artifact in stream")
|
|
}
|
|
formats := qemu.Formats
|
|
if formats == nil {
|
|
return nil, fmt.Errorf("unable to pull VM image: no formats in stream")
|
|
}
|
|
qcow, ok := formats[Format]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unable to pull VM image: no qcow2.xz format in stream")
|
|
}
|
|
disk := qcow.Disk
|
|
if disk == nil {
|
|
return nil, fmt.Errorf("unable to pull VM image: no disk in stream")
|
|
}
|
|
return &FcosDownloadInfo{
|
|
Location: disk.Location,
|
|
Release: qemu.Release,
|
|
Sha256Sum: disk.Sha256,
|
|
CompressionType: "xz",
|
|
}, nil
|
|
}
|