Files
Brent Baude 2430fc71a0 Allow podman machine to download from oci registry
this pr represents a shift in how we download podman machine images.
these images will now be stored in oci registry and will replace the
default method of downloading an image.  you can still use a reference
to a disk image as a path or url too with the --image-path switch.

the final registry and location of the images has not been determined;
and will need to be updated in podman as well.

i dont think we need to allow --image-path to accept a registry/image
for the podman 5.0 release.  i do think there will be demand for this.

upgrades also need to be plumbed.  for example, updating from an oci
registry.

once we make decisions on final image locations/registrties as well as
some behaviors of init and the oci pull, we must update the machine-init
documentation.

Signed-off-by: Brent Baude <bbaude@redhat.com>
2024-02-12 15:19:34 -06:00

115 lines
2.3 KiB
Go

package ocipull
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/blang/semver/v4"
"github.com/containers/image/v5/pkg/compression"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v5/pkg/machine/define"
"github.com/containers/podman/v5/version"
"github.com/containers/storage/pkg/archive"
"github.com/sirupsen/logrus"
)
type OSVersion struct {
*semver.Version
}
type Disker interface {
Get() error
}
type OCIOpts struct {
Scheme *OCIKind
Dir *string
}
type OCIKind string
var (
OCIDir OCIKind = "oci-dir"
OCIRegistry OCIKind = "docker"
OCIUnknown OCIKind = "unknown"
)
func (o OCIKind) String() string {
switch o {
case OCIDir:
return string(OCIDir)
case OCIRegistry:
return string(OCIRegistry)
}
return string(OCIUnknown)
}
func (o OCIKind) IsOCIDir() bool {
return o == OCIDir
}
func StripOCIReference(input string) string {
return strings.TrimPrefix(input, "docker://")
}
func getVersion() *OSVersion {
v := version.Version
return &OSVersion{&v}
}
func (o *OSVersion) majorMinor() string {
return fmt.Sprintf("%d.%d", o.Major, o.Minor)
}
func unpackOCIDir(ociTb, machineImageDir string) (*define.VMFile, error) {
imageFileName, err := findTarComponent(ociTb)
if err != nil {
return nil, err
}
unpackedFileName := filepath.Join(machineImageDir, imageFileName)
f, err := os.Open(ociTb)
if err != nil {
return nil, err
}
defer func() {
if err := f.Close(); err != nil {
logrus.Error(err)
}
}()
uncompressedReader, _, err := compression.AutoDecompress(f)
if err != nil {
return nil, err
}
defer func() {
if err := uncompressedReader.Close(); err != nil {
logrus.Error(err)
}
}()
logrus.Debugf("untarring %q to %q", ociTb, machineImageDir)
if err := archive.Untar(uncompressedReader, machineImageDir, &archive.TarOptions{
NoLchown: true,
}); err != nil {
return nil, err
}
return define.NewMachineFile(unpackedFileName, nil)
}
func localOCIDiskImageDir(blobDirPath string, localBlob *types.BlobInfo) string {
return filepath.Join(blobDirPath, "blobs", "sha256", localBlob.Digest.Hex())
}
func finalFQImagePathName(vmName, imageName string) string {
// imageName here is fully qualified. we need to break
// it apart and add the vmname
baseDir, filename := filepath.Split(imageName)
return filepath.Join(baseDir, fmt.Sprintf("%s-%s", vmName, filename))
}