Let CreateInstance download and cache image
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
parent
9d200d5352
commit
132823b453
2 changed files with 27 additions and 104 deletions
|
|
@ -16,7 +16,6 @@ package lxd
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/cloudbase/garm/config"
|
||||
|
|
@ -65,83 +64,26 @@ func (i *image) getLocalImageByAlias(imageName string, imageType config.LXDImage
|
|||
return image, nil
|
||||
}
|
||||
|
||||
func (i *image) clientFromRemoteArgs(remote config.LXDImageRemote) (lxd.ImageServer, error) {
|
||||
connectArgs := &lxd.ConnectionArgs{
|
||||
InsecureSkipVerify: remote.InsecureSkipVerify,
|
||||
func (i *image) getInstanceSource(imageName string, imageType config.LXDImageType, arch string, cli lxd.InstanceServer) (api.InstanceSource, error) {
|
||||
instanceSource := api.InstanceSource{
|
||||
Type: "image",
|
||||
}
|
||||
d, err := lxd.ConnectSimpleStreams(remote.Address, connectArgs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "connecting to image server %s", remote.Address)
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (i *image) copyImageFromRemote(remote config.LXDImageRemote, imageName string, imageType config.LXDImageType, arch string, cli lxd.InstanceServer) (*api.Image, error) {
|
||||
imgCli, err := i.clientFromRemoteArgs(remote)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching image server client")
|
||||
}
|
||||
defer imgCli.Disconnect()
|
||||
|
||||
aliases, err := imgCli.GetImageAliasArchitectures(imageType.String(), imageName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resolving alias: %s", imageName)
|
||||
}
|
||||
|
||||
alias, ok := aliases[arch]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no image found for arch %s and image type %s with name %s", arch, imageType, imageName)
|
||||
}
|
||||
|
||||
image, _, err := imgCli.GetImage(alias.Target)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching image details")
|
||||
}
|
||||
|
||||
imgCopyArgs := &lxd.ImageCopyArgs{
|
||||
AutoUpdate: true,
|
||||
}
|
||||
|
||||
op, err := cli.CopyImage(imgCli, *image, imgCopyArgs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "copying image %s from %s", imageName, remote.Address)
|
||||
}
|
||||
|
||||
// And wait for it to finish
|
||||
err = op.Wait()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "waiting for image copy operation")
|
||||
}
|
||||
|
||||
return image, nil
|
||||
}
|
||||
|
||||
// EnsureImage will look for an image locally, then attempt to download it from a remote
|
||||
// server, if the name contains a remote. Allowed formats are:
|
||||
// remote_name:image_name
|
||||
// image_name
|
||||
func (i *image) EnsureImage(imageName string, imageType config.LXDImageType, arch string, cli lxd.InstanceServer) (*api.Image, error) {
|
||||
if !strings.Contains(imageName, ":") {
|
||||
// A remote was not specified, try to find an image using the imageName as
|
||||
// an alias.
|
||||
return i.getLocalImageByAlias(imageName, imageType, arch, cli)
|
||||
}
|
||||
|
||||
remote, parsedName, err := i.parseImageName(imageName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "parsing image name")
|
||||
}
|
||||
|
||||
if img, err := i.copyImageFromRemote(remote, parsedName, imageType, arch, cli); err == nil {
|
||||
return img, nil
|
||||
imageDetails, err := i.getLocalImageByAlias(imageName, imageType, arch, cli)
|
||||
if err != nil {
|
||||
return api.InstanceSource{}, errors.Wrap(err, "fetching image")
|
||||
}
|
||||
instanceSource.Fingerprint = imageDetails.Fingerprint
|
||||
} else {
|
||||
log.Printf("failed to fetch image of type %v with name %s and arch %s: %s", imageType, parsedName, arch, err)
|
||||
remote, parsedName, err := i.parseImageName(imageName)
|
||||
if err != nil {
|
||||
return api.InstanceSource{}, errors.Wrap(err, "parsing image name")
|
||||
}
|
||||
instanceSource.Alias = parsedName
|
||||
instanceSource.Server = remote.Address
|
||||
instanceSource.Protocol = string(remote.Protocol)
|
||||
}
|
||||
|
||||
log.Printf("attempting to find %s for arch %s locally", parsedName, arch)
|
||||
img, err := i.getLocalImageByAlias(parsedName, imageType, arch, cli)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching image")
|
||||
}
|
||||
return img, nil
|
||||
return instanceSource, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ package lxd
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/cloudbase/garm/config"
|
||||
|
|
@ -170,21 +169,7 @@ func (l *LXD) getProfiles(flavor string) ([]string, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (l *LXD) getTools(image *api.Image, tools []*github.RunnerApplicationDownload, assumedOSType params.OSType) (github.RunnerApplicationDownload, error) {
|
||||
if image == nil {
|
||||
return github.RunnerApplicationDownload{}, fmt.Errorf("nil image received")
|
||||
}
|
||||
osName, ok := image.ImagePut.Properties["os"]
|
||||
if !ok {
|
||||
return github.RunnerApplicationDownload{}, fmt.Errorf("missing OS info in image properties")
|
||||
}
|
||||
|
||||
osType, err := util.OSToOSType(osName)
|
||||
if err != nil {
|
||||
log.Printf("failed to determine OS type from image, assuming %s", assumedOSType)
|
||||
osType = assumedOSType
|
||||
}
|
||||
|
||||
func (l *LXD) getTools(tools []*github.RunnerApplicationDownload, osType params.OSType, architecture string) (github.RunnerApplicationDownload, error) {
|
||||
// Validate image OS. Linux only for now.
|
||||
switch osType {
|
||||
case params.Linux:
|
||||
|
|
@ -203,16 +188,16 @@ func (l *LXD) getTools(image *api.Image, tools []*github.RunnerApplicationDownlo
|
|||
|
||||
// fmt.Println(*tool.Architecture, *tool.OS)
|
||||
// fmt.Printf("image arch: %s --> osType: %s\n", image.Architecture, string(osType))
|
||||
if *tool.Architecture == image.Architecture && *tool.OS == string(osType) {
|
||||
if *tool.Architecture == architecture && *tool.OS == string(osType) {
|
||||
return *tool, nil
|
||||
}
|
||||
|
||||
arch, ok := lxdToGithubArchMap[image.Architecture]
|
||||
arch, ok := lxdToGithubArchMap[architecture]
|
||||
if ok && arch == *tool.Architecture && *tool.OS == string(osType) {
|
||||
return *tool, nil
|
||||
}
|
||||
}
|
||||
return github.RunnerApplicationDownload{}, fmt.Errorf("failed to find tools for OS %s and arch %s", osType, image.Architecture)
|
||||
return github.RunnerApplicationDownload{}, fmt.Errorf("failed to find tools for OS %s and arch %s", osType, architecture)
|
||||
}
|
||||
|
||||
// sadly, the security.secureboot flag is a string encoded boolean.
|
||||
|
|
@ -238,13 +223,12 @@ func (l *LXD) getCreateInstanceArgs(bootstrapParams params.BootstrapInstance) (a
|
|||
}
|
||||
|
||||
instanceType := l.cfg.LXD.GetInstanceType()
|
||||
|
||||
image, err := l.imageManager.EnsureImage(bootstrapParams.Image, instanceType, arch, l.cli)
|
||||
instanceSource, err := l.imageManager.getInstanceSource(bootstrapParams.Image, instanceType, arch, l.cli)
|
||||
if err != nil {
|
||||
return api.InstancesPost{}, errors.Wrap(err, "getting image details")
|
||||
return api.InstancesPost{}, errors.Wrap(err, "getting instance source")
|
||||
}
|
||||
|
||||
tools, err := l.getTools(image, bootstrapParams.Tools, bootstrapParams.OSType)
|
||||
tools, err := l.getTools(bootstrapParams.Tools, bootstrapParams.OSType, arch)
|
||||
if err != nil {
|
||||
return api.InstancesPost{}, errors.Wrap(err, "getting tools")
|
||||
}
|
||||
|
|
@ -268,17 +252,14 @@ func (l *LXD) getCreateInstanceArgs(bootstrapParams params.BootstrapInstance) (a
|
|||
|
||||
args := api.InstancesPost{
|
||||
InstancePut: api.InstancePut{
|
||||
Architecture: image.Architecture,
|
||||
Architecture: arch,
|
||||
Profiles: profiles,
|
||||
Description: "Github runner provisioned by garm",
|
||||
Config: configMap,
|
||||
},
|
||||
Source: api.InstanceSource{
|
||||
Type: "image",
|
||||
Fingerprint: image.Fingerprint,
|
||||
},
|
||||
Name: bootstrapParams.Name,
|
||||
Type: api.InstanceType(instanceType),
|
||||
Source: instanceSource,
|
||||
Name: bootstrapParams.Name,
|
||||
Type: api.InstanceType(instanceType),
|
||||
}
|
||||
return args, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue