Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 4 additions & 34 deletions cmd/run.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package cmd

import (
"context"
"errors"
"fmt"
"os"
"time"

"github.com/containers/podman-bootc/pkg/bootc"
Expand All @@ -13,7 +10,6 @@ import (
"github.com/containers/podman-bootc/pkg/utils"
"github.com/containers/podman-bootc/pkg/vm"

"github.com/containers/podman/v5/pkg/bindings"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -66,42 +62,16 @@ func doRun(flags *cobra.Command, args []string) error {
return fmt.Errorf("unable to get user: %w", err)
}

//podman machine connection
machineInfo, err := utils.GetMachineInfo()
if err != nil {
return err
}

if machineInfo == nil {
println(utils.PodmanMachineErrorMessage)
return errors.New("rootful podman machine is required, please run 'podman machine init --rootful'")
}

if !machineInfo.Rootful {
println(utils.PodmanMachineErrorMessage)
return errors.New("rootful podman machine is required, please run 'podman machine set --rootful'")
}

if _, err := os.Stat(machineInfo.PodmanSocket); err != nil {
println(utils.PodmanMachineErrorMessage)
logrus.Errorf("podman machine socket is missing. Is podman machine running?\n%s", err)
return err
}

ctx, err := bindings.NewConnectionWithIdentity(
context.Background(),
fmt.Sprintf("unix://%s", machineInfo.PodmanSocket),
machineInfo.SSHIdentityPath,
true)
machine, err := utils.GetMachineContext()
if err != nil {
println(utils.PodmanMachineErrorMessage)
logrus.Errorf("failed to connect to the podman socket. Is podman machine running?\n%s", err)
logrus.Errorf("failed to connect to podman machine. Is podman machine running?\n%s", err)
return err
}

// create the disk image
idOrName := args[0]
bootcDisk := bootc.NewBootcDisk(idOrName, ctx, user)
bootcDisk := bootc.NewBootcDisk(idOrName, machine.Ctx, user)
err = bootcDisk.Install(vmConfig.Quiet, diskImageConfigInstance)

if err != nil {
Expand Down Expand Up @@ -143,7 +113,7 @@ func doRun(flags *cobra.Command, args []string) error {
RemoveVm: vmConfig.RemoveVm,
Background: vmConfig.Background,
SSHPort: sshPort,
SSHIdentity: machineInfo.SSHIdentityPath,
SSHIdentity: machine.SSHIdentityPath,
VMUser: vmConfig.User,
})

Expand Down
30 changes: 7 additions & 23 deletions pkg/bootc/bootc_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/containers/podman-bootc/pkg/utils"

"github.com/containers/podman/v5/pkg/bindings/containers"
"github.com/containers/podman/v5/pkg/bindings/images"
"github.com/containers/podman/v5/pkg/domain/entities/types"
"github.com/containers/podman/v5/pkg/specgen"
"github.com/docker/go-units"
Expand Down Expand Up @@ -277,32 +276,17 @@ func (p *BootcDisk) bootcInstallImageToDisk(quiet bool, diskConfig DiskImageConf
}

// pullImage fetches the container image if not present
func (p *BootcDisk) pullImage() (err error) {
pullPolicy := "missing"
ids, err := images.Pull(p.Ctx, p.ImageNameOrId, &images.PullOptions{Policy: &pullPolicy})
func (p *BootcDisk) pullImage() error {
imageData, err := utils.PullAndInspect(p.Ctx, p.ImageNameOrId)
if err != nil {
return fmt.Errorf("failed to pull image: %w", err)
}

if len(ids) == 0 {
return fmt.Errorf("no ids returned from image pull")
}

if len(ids) > 1 {
return fmt.Errorf("multiple ids returned from image pull")
}

image, err := images.GetImage(p.Ctx, p.ImageNameOrId, &images.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get image: %w", err)
return err
}
p.imageData = image

imageId := ids[0]
p.ImageId = imageId
p.RepoTag = image.RepoTags[0]
p.imageData = imageData
p.ImageId = imageData.ID
p.RepoTag = imageData.RepoTags[0]

return
return nil
}

// runInstallContainer runs the bootc installer in a container to create a disk image
Expand Down
91 changes: 76 additions & 15 deletions pkg/utils/podman.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,88 @@
package utils

import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/containers/podman/v5/pkg/bindings/images"
"github.com/containers/podman/v5/pkg/domain/entities/types"
"os"
"os/exec"
"strings"

"github.com/containers/podman/v5/pkg/bindings"
"github.com/containers/podman/v5/pkg/machine"
"github.com/containers/podman/v5/pkg/machine/define"
"github.com/containers/podman/v5/pkg/machine/env"
"github.com/containers/podman/v5/pkg/machine/provider"
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
)

type MachineInfo struct {
PodmanSocket string
type MachineContext struct {
Ctx context.Context
SSHIdentityPath string
Rootful bool
}

func GetMachineInfo() (*MachineInfo, error) {
minfo, err := getMachineInfo()
type machineInfo struct {
podmanSocket string
sshIdentityPath string
rootful bool
}

// PullAndInspect inpects the image, pulling in if the image if required
func PullAndInspect(ctx context.Context, imageNameOrId string) (*types.ImageInspectReport, error) {
pullPolicy := "missing"
_, err := images.Pull(ctx, imageNameOrId, &images.PullOptions{Policy: &pullPolicy})
if err != nil {
return nil, fmt.Errorf("failed to pull image: %w", err)
}

imageInfo, err := images.GetImage(ctx, imageNameOrId, &images.GetOptions{})
if err != nil {
return nil, fmt.Errorf("failed to inspect image: %w", err)
}

return imageInfo, nil
}

func GetMachineContext() (*MachineContext, error) {
//podman machine connection
machineInfo, err := getMachineInfo()
if err != nil {
return nil, fmt.Errorf("unable to get podman machine info: %w", err)
}

if machineInfo == nil {
return nil, errors.New("rootful podman machine is required, please run 'podman machine init --rootful'")
}

if !machineInfo.rootful {
return nil, errors.New("rootful podman machine is required, please run 'podman machine set --rootful'")
}

if _, err := os.Stat(machineInfo.podmanSocket); err != nil {
return nil, fmt.Errorf("podman machine socket is missing: %w", err)
}

ctx, err := bindings.NewConnectionWithIdentity(
context.Background(),
fmt.Sprintf("unix://%s", machineInfo.podmanSocket),
machineInfo.sshIdentityPath,
true)
if err != nil {
return nil, fmt.Errorf("failed to connect to the podman socket: %w", err)
}

mc := &MachineContext{
Ctx: ctx,
SSHIdentityPath: machineInfo.sshIdentityPath,
}
return mc, nil
}

func getMachineInfo() (*machineInfo, error) {
minfo, err := getPv5MachineInfo()
if err != nil {
var errIncompatibleMachineConfig *define.ErrIncompatibleMachineConfig
var errVMDoesNotExist *define.ErrVMDoesNotExist
Expand All @@ -39,7 +100,7 @@ func GetMachineInfo() (*MachineInfo, error) {
}

// Get podman v5 machine info
func getMachineInfo() (*MachineInfo, error) {
func getPv5MachineInfo() (*machineInfo, error) {
prov, err := provider.Get()
if err != nil {
return nil, fmt.Errorf("getting podman machine provider: %w", err)
Expand All @@ -60,16 +121,16 @@ func getMachineInfo() (*MachineInfo, error) {
return nil, fmt.Errorf("getting podman machine connection info: %w", err)
}

pmi := MachineInfo{
PodmanSocket: podmanSocket.GetPath(),
SSHIdentityPath: pm.SSH.IdentityPath,
Rootful: pm.HostUser.Rootful,
pmi := machineInfo{
podmanSocket: podmanSocket.GetPath(),
sshIdentityPath: pm.SSH.IdentityPath,
rootful: pm.HostUser.Rootful,
}
return &pmi, nil
}

// Just to support podman v4.9, it will be removed in the future
func getPv4MachineInfo() (*MachineInfo, error) {
func getPv4MachineInfo() (*machineInfo, error) {
//check if a default podman machine exists
listCmd := exec.Command("podman", "machine", "list", "--format", "json")
var listCmdOutput strings.Builder
Expand Down Expand Up @@ -135,9 +196,9 @@ func getPv4MachineInfo() (*MachineInfo, error) {
return nil, errors.New("no podman machine found")
}

return &MachineInfo{
PodmanSocket: machineInspect[0].ConnectionInfo.PodmanSocket.Path,
SSHIdentityPath: machineInspect[0].SSHConfig.IdentityPath,
Rootful: machineInspect[0].Rootful,
return &machineInfo{
podmanSocket: machineInspect[0].ConnectionInfo.PodmanSocket.Path,
sshIdentityPath: machineInspect[0].SSHConfig.IdentityPath,
rootful: machineInspect[0].Rootful,
}, nil
}
35 changes: 3 additions & 32 deletions podman-bootc.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package main

import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
Expand All @@ -12,7 +10,6 @@ import (
"github.com/containers/podman-bootc/pkg/user"
"github.com/containers/podman-bootc/pkg/utils"

"github.com/containers/podman/v5/pkg/bindings"
"github.com/sirupsen/logrus"
)

Expand All @@ -23,41 +20,15 @@ func cleanup() {
os.Exit(0)
}

//podman machine connection
machineInfo, err := utils.GetMachineInfo()
if err != nil {
logrus.Errorf("unable to get podman machine info: %s", err)
os.Exit(1)
}

if machineInfo == nil {
logrus.Errorf("rootful podman machine is required, please run 'podman machine init --rootful'")
os.Exit(1)
}

if !machineInfo.Rootful {
logrus.Errorf("rootful podman machine is required, please run 'podman machine set --rootful'")
os.Exit(1)
}

if _, err := os.Stat(machineInfo.PodmanSocket); err != nil {
logrus.Errorf("podman machine socket is missing. Is podman machine running?\n%s", err)
os.Exit(1)
}

ctx, err := bindings.NewConnectionWithIdentity(
context.Background(),
fmt.Sprintf("unix://%s", machineInfo.PodmanSocket),
machineInfo.SSHIdentityPath,
true)
machine, err := utils.GetMachineContext()
if err != nil {
println(utils.PodmanMachineErrorMessage)
logrus.Errorf("failed to connect to the podman socket. Is podman machine running?\n%s", err)
logrus.Errorf("failed to connect to podman machine. Is podman machine running?\n%s", err)
os.Exit(1)
}

//delete the disk image
err = bootc.NewBootcDisk("", ctx, user).Cleanup()
err = bootc.NewBootcDisk("", machine.Ctx, user).Cleanup()
if err != nil {
logrus.Errorf("unable to get podman machine info: %s", err)
os.Exit(0)
Expand Down