summaryrefslogtreecommitdiff
path: root/pkg/machine
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/machine')
-rw-r--r--pkg/machine/config.go19
-rw-r--r--pkg/machine/e2e/basic_test.go4
-rw-r--r--pkg/machine/e2e/config_basic_test.go (renamed from pkg/machine/e2e/config_basic.go)3
-rw-r--r--pkg/machine/e2e/config_info_test.go (renamed from pkg/machine/e2e/config_info.go)2
-rw-r--r--pkg/machine/e2e/config_init_test.go (renamed from pkg/machine/e2e/config_init.go)6
-rw-r--r--pkg/machine/e2e/config_inspect_test.go (renamed from pkg/machine/e2e/config_inspect.go)2
-rw-r--r--pkg/machine/e2e/config_list_test.go (renamed from pkg/machine/e2e/config_list.go)2
-rw-r--r--pkg/machine/e2e/config_rm_test.go (renamed from pkg/machine/e2e/config_rm.go)8
-rw-r--r--pkg/machine/e2e/config_set_test.go (renamed from pkg/machine/e2e/config_set.go)2
-rw-r--r--pkg/machine/e2e/config_ssh_test.go (renamed from pkg/machine/e2e/config_ssh.go)8
-rw-r--r--pkg/machine/e2e/config_start_test.go (renamed from pkg/machine/e2e/config_start.go)3
-rw-r--r--pkg/machine/e2e/config_stop_test.go (renamed from pkg/machine/e2e/config_stop.go)3
-rw-r--r--pkg/machine/e2e/config_test.go (renamed from pkg/machine/e2e/config.go)26
-rw-r--r--pkg/machine/e2e/info_test.go6
-rw-r--r--pkg/machine/e2e/init_test.go8
-rw-r--r--pkg/machine/e2e/inspect_test.go8
-rw-r--r--pkg/machine/e2e/list_test.go10
-rw-r--r--pkg/machine/e2e/machine_test.go4
-rw-r--r--pkg/machine/e2e/rm_test.go2
-rw-r--r--pkg/machine/e2e/set_test.go8
-rw-r--r--pkg/machine/e2e/ssh_test.go14
-rw-r--r--pkg/machine/e2e/start_test.go2
-rw-r--r--pkg/machine/e2e/stop_test.go2
-rw-r--r--pkg/machine/fcos.go19
-rw-r--r--pkg/machine/fedora.go89
-rw-r--r--pkg/machine/keys.go3
-rw-r--r--pkg/machine/pull.go61
-rw-r--r--pkg/machine/qemu/machine.go34
-rw-r--r--pkg/machine/wsl/machine.go28
29 files changed, 205 insertions, 181 deletions
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index 29cd7bc00..253601dad 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -73,6 +73,7 @@ type Download struct {
Arch string
Artifact string
CompressionType string
+ CacheDir string
Format string
ImageName string
LocalPath string
@@ -139,6 +140,7 @@ type VM interface {
type DistributionDownload interface {
HasUsableCache() (bool, error)
Get() *Download
+ CleanCache() error
}
type InspectInfo struct {
ConfigPath VMFile
@@ -172,6 +174,19 @@ func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url
return uri
}
+// GetCacheDir returns the dir where VM images are downladed into when pulled
+func GetCacheDir(vmType string) (string, error) {
+ dataDir, err := GetDataDir(vmType)
+ if err != nil {
+ return "", err
+ }
+ cacheDir := filepath.Join(dataDir, "cache")
+ if _, err := os.Stat(cacheDir); !errors.Is(err, os.ErrNotExist) {
+ return cacheDir, nil
+ }
+ return cacheDir, os.MkdirAll(cacheDir, 0755)
+}
+
// GetDataDir returns the filepath where vm images should
// live for podman-machine.
func GetDataDir(vmType string) (string, error) {
@@ -180,7 +195,7 @@ func GetDataDir(vmType string) (string, error) {
return "", err
}
dataDir := filepath.Join(dataDirPrefix, vmType)
- if _, err := os.Stat(dataDir); !os.IsNotExist(err) {
+ if _, err := os.Stat(dataDir); !errors.Is(err, os.ErrNotExist) {
return dataDir, nil
}
mkdirErr := os.MkdirAll(dataDir, 0755)
@@ -205,7 +220,7 @@ func GetConfDir(vmType string) (string, error) {
return "", err
}
confDir := filepath.Join(confDirPrefix, vmType)
- if _, err := os.Stat(confDir); !os.IsNotExist(err) {
+ if _, err := os.Stat(confDir); !errors.Is(err, os.ErrNotExist) {
return confDir, nil
}
mkdirErr := os.MkdirAll(confDir, 0755)
diff --git a/pkg/machine/e2e/basic_test.go b/pkg/machine/e2e/basic_test.go
index f67fb4c67..da0310485 100644
--- a/pkg/machine/e2e/basic_test.go
+++ b/pkg/machine/e2e/basic_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
@@ -20,7 +20,7 @@ var _ = Describe("run basic podman commands", func() {
})
It("Basic ops", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/config_basic.go b/pkg/machine/e2e/config_basic_test.go
index be0896156..d1cb24174 100644
--- a/pkg/machine/e2e/config_basic.go
+++ b/pkg/machine/e2e/config_basic_test.go
@@ -1,8 +1,7 @@
-package e2e
+package e2e_test
type basicMachine struct {
args []string
- cmd []string
}
func (s basicMachine) buildCmd(m *machineTestBuilder) []string {
diff --git a/pkg/machine/e2e/config_info.go b/pkg/machine/e2e/config_info_test.go
index 410c7e518..4da40ab99 100644
--- a/pkg/machine/e2e/config_info.go
+++ b/pkg/machine/e2e/config_info_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type infoMachine struct {
format string
diff --git a/pkg/machine/e2e/config_init.go b/pkg/machine/e2e/config_init_test.go
index 7f18cce7d..d6c7990b0 100644
--- a/pkg/machine/e2e/config_init.go
+++ b/pkg/machine/e2e/config_init_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strconv"
@@ -25,7 +25,7 @@ type initMachine struct {
memory *uint
now bool
timezone string
- rootful bool
+ rootful bool //nolint:unused,structcheck
volumes []string
cmd []string
@@ -71,7 +71,7 @@ func (i *initMachine) withDiskSize(size uint) *initMachine {
return i
}
-func (i *initMachine) withIgnitionPath(path string) *initMachine {
+func (i *initMachine) withIgnitionPath(path string) *initMachine { //nolint:unused
i.ignitionPath = path
return i
}
diff --git a/pkg/machine/e2e/config_inspect.go b/pkg/machine/e2e/config_inspect_test.go
index 74c9a5d9c..ffd74220f 100644
--- a/pkg/machine/e2e/config_inspect.go
+++ b/pkg/machine/e2e/config_inspect_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type inspectMachine struct {
/*
diff --git a/pkg/machine/e2e/config_list.go b/pkg/machine/e2e/config_list_test.go
index 150f984bc..78f9edc62 100644
--- a/pkg/machine/e2e/config_list.go
+++ b/pkg/machine/e2e/config_list_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type listMachine struct {
/*
diff --git a/pkg/machine/e2e/config_rm.go b/pkg/machine/e2e/config_rm_test.go
index 6cf262a22..1f9c9b4ec 100644
--- a/pkg/machine/e2e/config_rm.go
+++ b/pkg/machine/e2e/config_rm_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type rmMachine struct {
/*
@@ -40,17 +40,17 @@ func (i *rmMachine) withForce() *rmMachine {
return i
}
-func (i *rmMachine) withSaveIgnition() *rmMachine {
+func (i *rmMachine) withSaveIgnition() *rmMachine { //nolint:unused
i.saveIgnition = true
return i
}
-func (i *rmMachine) withSaveImage() *rmMachine {
+func (i *rmMachine) withSaveImage() *rmMachine { //nolint:unused
i.saveImage = true
return i
}
-func (i *rmMachine) withSaveKeys() *rmMachine {
+func (i *rmMachine) withSaveKeys() *rmMachine { //nolint:unused
i.saveKeys = true
return i
}
diff --git a/pkg/machine/e2e/config_set.go b/pkg/machine/e2e/config_set_test.go
index b310ab1b9..3c773b970 100644
--- a/pkg/machine/e2e/config_set.go
+++ b/pkg/machine/e2e/config_set_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strconv"
diff --git a/pkg/machine/e2e/config_ssh.go b/pkg/machine/e2e/config_ssh_test.go
index b09eed47d..f062625fa 100644
--- a/pkg/machine/e2e/config_ssh.go
+++ b/pkg/machine/e2e/config_ssh_test.go
@@ -1,14 +1,12 @@
-package e2e
+package e2e_test
type sshMachine struct {
/*
--username string Username to use when ssh-ing into the VM.
*/
- username string
+ username string //nolint:unused
sshCommand []string
-
- cmd []string
}
func (s sshMachine) buildCmd(m *machineTestBuilder) []string {
@@ -22,7 +20,7 @@ func (s sshMachine) buildCmd(m *machineTestBuilder) []string {
return cmd
}
-func (s *sshMachine) withUsername(name string) *sshMachine {
+func (s *sshMachine) withUsername(name string) *sshMachine { //nolint:unused
s.username = name
return s
}
diff --git a/pkg/machine/e2e/config_start.go b/pkg/machine/e2e/config_start_test.go
index 86b1721f8..d9efbf489 100644
--- a/pkg/machine/e2e/config_start.go
+++ b/pkg/machine/e2e/config_start_test.go
@@ -1,10 +1,9 @@
-package e2e
+package e2e_test
type startMachine struct {
/*
No command line args other than a machine vm name (also not required)
*/
- cmd []string
}
func (s startMachine) buildCmd(m *machineTestBuilder) []string {
diff --git a/pkg/machine/e2e/config_stop.go b/pkg/machine/e2e/config_stop_test.go
index 04dcfb524..41142ec7e 100644
--- a/pkg/machine/e2e/config_stop.go
+++ b/pkg/machine/e2e/config_stop_test.go
@@ -1,10 +1,9 @@
-package e2e
+package e2e_test
type stopMachine struct {
/*
No command line args other than a machine vm name (also not required)
*/
- cmd []string
}
func (s stopMachine) buildCmd(m *machineTestBuilder) []string {
diff --git a/pkg/machine/e2e/config.go b/pkg/machine/e2e/config_test.go
index b3fe74b0c..9940e711b 100644
--- a/pkg/machine/e2e/config.go
+++ b/pkg/machine/e2e/config_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"encoding/json"
@@ -10,13 +10,11 @@ import (
"time"
"github.com/containers/podman/v4/pkg/machine"
- "github.com/containers/podman/v4/pkg/machine/qemu"
"github.com/containers/podman/v4/pkg/util"
"github.com/containers/storage/pkg/stringid"
- . "github.com/onsi/ginkgo" //nolint:golint,stylecheck
+ . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "github.com/onsi/gomega/gexec"
- . "github.com/onsi/gomega/gexec" //nolint:golint,stylecheck
+ . "github.com/onsi/gomega/gexec"
)
var originalHomeDir = os.Getenv("HOME")
@@ -36,7 +34,7 @@ type MachineTestBuilder interface {
run() (*machineSession, error)
}
type machineSession struct {
- *gexec.Session
+ *Session
}
type machineTestBuilder struct {
@@ -47,10 +45,6 @@ type machineTestBuilder struct {
podmanBinary string
timeout time.Duration
}
-type qemuMachineInspectInfo struct {
- State machine.Status
- VM qemu.MachineVM
-}
// waitWithTimeout waits for a command to complete for a given
// number of seconds
@@ -121,7 +115,7 @@ func (m *machineTestBuilder) setCmd(mc machineCommand) *machineTestBuilder {
// If no name for the machine exists, we set a random name.
if !util.StringInSlice(m.name, m.names) {
if len(m.name) < 1 {
- m.name = randomString(12)
+ m.name = randomString()
}
m.names = append(m.names, m.name)
}
@@ -136,10 +130,10 @@ func (m *machineTestBuilder) setTimeout(timeout time.Duration) *machineTestBuild
// toQemuInspectInfo is only for inspecting qemu machines. Other providers will need
// to make their own.
-func (mb *machineTestBuilder) toQemuInspectInfo() ([]machine.InspectInfo, int, error) {
+func (m *machineTestBuilder) toQemuInspectInfo() ([]machine.InspectInfo, int, error) {
args := []string{"machine", "inspect"}
- args = append(args, mb.names...)
- session, err := runWrapper(mb.podmanBinary, args, defaultTimeout, true)
+ args = append(args, m.names...)
+ session, err := runWrapper(m.podmanBinary, args, defaultTimeout, true)
if err != nil {
return nil, -1, err
}
@@ -175,9 +169,7 @@ func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration, wa
return &ms, nil
}
-func (m *machineTestBuilder) init() {}
-
// randomString returns a string of given length composed of random characters
-func randomString(n int) string {
+func randomString() string {
return stringid.GenerateRandomID()[0:12]
}
diff --git a/pkg/machine/e2e/info_test.go b/pkg/machine/e2e/info_test.go
index eeabb78af..fe0cfba32 100644
--- a/pkg/machine/e2e/info_test.go
+++ b/pkg/machine/e2e/info_test.go
@@ -1,7 +1,7 @@
-package e2e
+package e2e_test
import (
- "github.com/containers/podman/v4/cmd/podman/machine"
+ "github.com/containers/podman/v4/pkg/domain/entities"
jsoniter "github.com/json-iterator/go"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -51,7 +51,7 @@ var _ = Describe("podman machine info", func() {
Expect(err).NotTo(HaveOccurred())
Expect(infoSession).Should(Exit(0))
- infoReport := &machine.Info{}
+ infoReport := &entities.MachineInfo{}
err = jsoniter.Unmarshal(infoSession.Bytes(), infoReport)
Expect(err).To(BeNil())
})
diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go
index 40f140cae..b246dc4da 100644
--- a/pkg/machine/e2e/init_test.go
+++ b/pkg/machine/e2e/init_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"io/ioutil"
@@ -78,7 +78,7 @@ var _ = Describe("podman machine init", func() {
})
It("machine init with cpus, disk size, memory, timezone", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withCPUs(2).withDiskSize(102).withMemory(4000).withTimezone("Pacific/Honolulu")).run()
Expect(err).To(BeNil())
@@ -108,7 +108,7 @@ var _ = Describe("podman machine init", func() {
switch runtime.GOOS {
// os's handle memory differently
case "linux":
- Expect(memorySession.outputToString()).To(ContainSubstring("3821"))
+ Expect(memorySession.outputToString()).To(ContainSubstring("3822"))
case "darwin":
Expect(memorySession.outputToString()).To(ContainSubstring("3824"))
default:
@@ -130,7 +130,7 @@ var _ = Describe("podman machine init", func() {
mount := tmpDir + ":/testmountdir"
defer os.RemoveAll(tmpDir)
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withVolume(mount)).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go
index 93fb8cc2b..0ab928205 100644
--- a/pkg/machine/e2e/inspect_test.go
+++ b/pkg/machine/e2e/inspect_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strings"
@@ -52,15 +52,15 @@ var _ = Describe("podman machine stop", func() {
})
It("inspect with go format", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
Expect(session).To(Exit(0))
// regular inspect should
- inspectJson := new(inspectMachine)
- inspectSession, err := mb.setName(name).setCmd(inspectJson).run()
+ inspectJSON := new(inspectMachine)
+ inspectSession, err := mb.setName(name).setCmd(inspectJSON).run()
Expect(err).To(BeNil())
Expect(inspectSession).To(Exit(0))
diff --git a/pkg/machine/e2e/list_test.go b/pkg/machine/e2e/list_test.go
index fb855c61e..5c7ae6c5e 100644
--- a/pkg/machine/e2e/list_test.go
+++ b/pkg/machine/e2e/list_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strings"
@@ -45,8 +45,8 @@ var _ = Describe("podman machine list", func() {
It("list machines with quiet or noheading", func() {
// Random names for machines to test list
- name1 := randomString(12)
- name2 := randomString(12)
+ name1 := randomString()
+ name2 := randomString()
list := new(listMachine)
firstList, err := mb.setCmd(list.withQuiet()).run()
@@ -109,7 +109,7 @@ var _ = Describe("podman machine list", func() {
It("list with --format", func() {
// Random names for machines to test list
- name1 := randomString(12)
+ name1 := randomString()
i := new(initMachine)
session, err := mb.setName(name1).setCmd(i.withImagePath(mb.imagePath)).run()
@@ -135,7 +135,7 @@ var _ = Describe("podman machine list", func() {
Expect(listSession2).To(Exit(0))
var listResponse []*entities.ListReporter
- err = jsoniter.Unmarshal(listSession.Bytes(), &listResponse)
+ err = jsoniter.Unmarshal(listSession2.Bytes(), &listResponse)
Expect(err).To(BeNil())
// table format includes the header
diff --git a/pkg/machine/e2e/machine_test.go b/pkg/machine/e2e/machine_test.go
index 7b063937d..5de04b9f7 100644
--- a/pkg/machine/e2e/machine_test.go
+++ b/pkg/machine/e2e/machine_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"fmt"
@@ -57,7 +57,7 @@ var _ = BeforeSuite(func() {
Fail(fmt.Sprintf("unable to create url for download: %q", err))
}
now := time.Now()
- if err := machine.DownloadVMImage(getMe, fqImageName+".xz"); err != nil {
+ if err := machine.DownloadVMImage(getMe, suiteImageName, fqImageName+".xz"); err != nil {
Fail(fmt.Sprintf("unable to download machine image: %q", err))
}
fmt.Println("Download took: ", time.Since(now).String())
diff --git a/pkg/machine/e2e/rm_test.go b/pkg/machine/e2e/rm_test.go
index 43b8c594c..e33eaf702 100644
--- a/pkg/machine/e2e/rm_test.go
+++ b/pkg/machine/e2e/rm_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
diff --git a/pkg/machine/e2e/set_test.go b/pkg/machine/e2e/set_test.go
index 80cb89488..4839e33da 100644
--- a/pkg/machine/e2e/set_test.go
+++ b/pkg/machine/e2e/set_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"runtime"
@@ -22,7 +22,7 @@ var _ = Describe("podman machine set", func() {
})
It("set machine cpus, disk, memory", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
@@ -62,7 +62,7 @@ var _ = Describe("podman machine set", func() {
switch runtime.GOOS {
// it seems macos and linux handle memory differently
case "linux":
- Expect(memorySession.outputToString()).To(ContainSubstring("3821"))
+ Expect(memorySession.outputToString()).To(ContainSubstring("3822"))
case "darwin":
Expect(memorySession.outputToString()).To(ContainSubstring("3824"))
default:
@@ -75,7 +75,7 @@ var _ = Describe("podman machine set", func() {
})
It("no settings should change if no flags", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/ssh_test.go b/pkg/machine/e2e/ssh_test.go
index 9ee31ac26..52d714c91 100644
--- a/pkg/machine/e2e/ssh_test.go
+++ b/pkg/machine/e2e/ssh_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
@@ -20,17 +20,16 @@ var _ = Describe("podman machine ssh", func() {
})
It("bad machine name", func() {
- name := randomString(12)
+ name := randomString()
ssh := sshMachine{}
session, err := mb.setName(name).setCmd(ssh).run()
Expect(err).To(BeNil())
Expect(session).To(Exit(125))
- // TODO seems like stderr is not being returned; re-enabled when fixed
- //Expect(session.outputToString()).To(ContainSubstring("not exist"))
+ Expect(session.errorToString()).To(ContainSubstring("not exist"))
})
It("ssh to non-running machine", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
@@ -39,13 +38,12 @@ var _ = Describe("podman machine ssh", func() {
ssh := sshMachine{}
sshSession, err := mb.setName(name).setCmd(ssh).run()
Expect(err).To(BeNil())
- // TODO seems like stderr is not being returned; re-enabled when fixed
- //Expect(sshSession.outputToString()).To(ContainSubstring("is not running"))
+ Expect(sshSession.errorToString()).To(ContainSubstring("is not running"))
Expect(sshSession).To(Exit(125))
})
It("ssh to running machine and check os-type", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/start_test.go b/pkg/machine/e2e/start_test.go
index 1de66eb9a..1f9405569 100644
--- a/pkg/machine/e2e/start_test.go
+++ b/pkg/machine/e2e/start_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"github.com/containers/podman/v4/pkg/machine"
diff --git a/pkg/machine/e2e/stop_test.go b/pkg/machine/e2e/stop_test.go
index 0c27045a6..621bbdb16 100644
--- a/pkg/machine/e2e/stop_test.go
+++ b/pkg/machine/e2e/stop_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
diff --git a/pkg/machine/fcos.go b/pkg/machine/fcos.go
index 4ccb99e96..246f92a19 100644
--- a/pkg/machine/fcos.go
+++ b/pkg/machine/fcos.go
@@ -13,6 +13,7 @@ import (
"path/filepath"
"runtime"
"strings"
+ "time"
"github.com/coreos/stream-metadata-go/fedoracoreos"
"github.com/coreos/stream-metadata-go/release"
@@ -53,7 +54,7 @@ func NewFcosDownloader(vmType, vmName, imageStream string) (DistributionDownload
return nil, err
}
- dataDir, err := GetDataDir(vmType)
+ cacheDir, err := GetCacheDir(vmType)
if err != nil {
return nil, err
}
@@ -62,15 +63,20 @@ func NewFcosDownloader(vmType, vmName, imageStream string) (DistributionDownload
Download: Download{
Arch: getFcosArch(),
Artifact: artifact,
+ CacheDir: cacheDir,
Format: Format,
ImageName: imageName,
- LocalPath: filepath.Join(dataDir, imageName),
+ LocalPath: filepath.Join(cacheDir, imageName),
Sha256sum: info.Sha256Sum,
URL: url,
VMName: vmName,
},
}
- fcd.Download.LocalUncompressedFile = fcd.getLocalUncompressedName()
+ dataDir, err := GetDataDir(vmType)
+ if err != nil {
+ return nil, err
+ }
+ fcd.Download.LocalUncompressedFile = fcd.getLocalUncompressedFile(dataDir)
return fcd, nil
}
@@ -108,6 +114,13 @@ func (f FcosDownload) HasUsableCache() (bool, error) {
return sum.Encoded() == f.Sha256sum, nil
}
+func (f FcosDownload) CleanCache() error {
+ // Set cached image to expire after 2 weeks
+ // FCOS refreshes around every 2 weeks, assume old images aren't needed
+ expire := 14 * 24 * time.Hour
+ return removeImageAfterExpire(f.CacheDir, expire)
+}
+
func getFcosArch() string {
var arch string
// TODO fill in more architectures
diff --git a/pkg/machine/fedora.go b/pkg/machine/fedora.go
index 46e450418..497265269 100644
--- a/pkg/machine/fedora.go
+++ b/pkg/machine/fedora.go
@@ -7,50 +7,55 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
+ "os"
+ "path"
+ "strings"
+
"net/http"
"net/url"
- "os"
"path/filepath"
- "regexp"
-
- "github.com/sirupsen/logrus"
+ "time"
)
const (
- githubURL = "http://github.com/fedora-cloud/docker-brew-fedora/"
+ githubLatestReleaseURL = "https://github.com/containers/podman-wsl-fedora/releases/latest/download/rootfs.tar.xz"
)
-var fedoraxzRegex = regexp.MustCompile(`fedora[^\"]+xz`)
-
type FedoraDownload struct {
Download
}
func NewFedoraDownloader(vmType, vmName, releaseStream string) (DistributionDownload, error) {
- imageName, downloadURL, size, err := getFedoraDownload(releaseStream)
+ downloadURL, version, size, err := getFedoraDownload(githubLatestReleaseURL)
if err != nil {
return nil, err
}
- dataDir, err := GetDataDir(vmType)
+ cacheDir, err := GetCacheDir(vmType)
if err != nil {
return nil, err
}
+ imageName := fmt.Sprintf("fedora-podman-%s.tar.xz", version)
+
f := FedoraDownload{
Download: Download{
Arch: getFcosArch(),
Artifact: artifact,
+ CacheDir: cacheDir,
Format: Format,
ImageName: imageName,
- LocalPath: filepath.Join(dataDir, imageName),
+ LocalPath: filepath.Join(cacheDir, imageName),
URL: downloadURL,
VMName: vmName,
Size: size,
},
}
- f.Download.LocalUncompressedFile = f.getLocalUncompressedName()
+ dataDir, err := GetDataDir(vmType)
+ if err != nil {
+ return nil, err
+ }
+ f.Download.LocalUncompressedFile = f.getLocalUncompressedFile(dataDir)
return f, nil
}
@@ -69,56 +74,42 @@ func (f FedoraDownload) HasUsableCache() (bool, error) {
return info.Size() == f.Size, nil
}
-func truncRead(url string) ([]byte, error) {
- resp, err := http.Get(url)
- if err != nil {
- return nil, err
- }
-
- defer func() {
- if err := resp.Body.Close(); err != nil {
- logrus.Error(err)
- }
- }()
+func (f FedoraDownload) CleanCache() error {
+ // Set cached image to expire after 2 weeks
+ expire := 14 * 24 * time.Hour
+ return removeImageAfterExpire(f.CacheDir, expire)
+}
- body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 10*1024*1024))
+func getFedoraDownload(releaseURL string) (*url.URL, string, int64, error) {
+ downloadURL, err := url.Parse(releaseURL)
if err != nil {
- return nil, err
+ return nil, "", -1, fmt.Errorf("invalid URL generated from discovered Fedora file: %s: %w", releaseURL, err)
}
- _, _ = io.Copy(io.Discard, resp.Body)
-
- return body, nil
-}
-
-func getFedoraDownload(releaseStream string) (string, *url.URL, int64, error) {
- dirURL := githubURL + "tree/" + releaseStream + "/" + getFcosArch() + "/"
- body, err := truncRead(dirURL)
+ resp, err := http.Head(releaseURL)
if err != nil {
- return "", nil, -1, err
+ return nil, "", -1, fmt.Errorf("head request failed: %s: %w", releaseURL, err)
}
+ _ = resp.Body.Close()
+ contentLen := resp.ContentLength
- file := fedoraxzRegex.FindString(string(body))
- if len(file) == 0 {
- return "", nil, -1, fmt.Errorf("could not locate Fedora download at %s", dirURL)
+ if resp.StatusCode != http.StatusOK {
+ return nil, "", -1, fmt.Errorf("head request failed: %s: %w", releaseURL, err)
}
- rawURL := githubURL + "raw/" + releaseStream + "/" + getFcosArch() + "/"
- newLocation := rawURL + file
- downloadURL, err := url.Parse(newLocation)
- if err != nil {
- return "", nil, -1, fmt.Errorf("invalid URL generated from discovered Fedora file: %s: %w", newLocation, err)
- }
+ verURL := *downloadURL
+ verURL.Path = path.Join(path.Dir(downloadURL.Path), "version")
- resp, err := http.Head(newLocation)
+ resp, err = http.Get(verURL.String())
if err != nil {
- return "", nil, -1, fmt.Errorf("head request failed: %s: %w", newLocation, err)
+ return nil, "", -1, fmt.Errorf("get request failed: %s: %w", verURL.String(), err)
}
- _ = resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- return "", nil, -1, fmt.Errorf("head request failed [%d] on download: %s", resp.StatusCode, newLocation)
+ defer resp.Body.Close()
+ bytes, err := io.ReadAll(&io.LimitedReader{R: resp.Body, N: 1024})
+ if err != nil {
+ return nil, "", -1, fmt.Errorf("failed reading: %s: %w", verURL.String(), err)
}
- return file, downloadURL, resp.ContentLength, nil
+ return downloadURL, strings.TrimSpace(string(bytes)), contentLen, nil
}
diff --git a/pkg/machine/keys.go b/pkg/machine/keys.go
index 0c7d7114e..94cbdac04 100644
--- a/pkg/machine/keys.go
+++ b/pkg/machine/keys.go
@@ -21,6 +21,9 @@ var sshCommand = []string{"ssh-keygen", "-N", "", "-t", "ed25519", "-f"}
// CreateSSHKeys makes a priv and pub ssh key for interacting
// the a VM.
func CreateSSHKeys(writeLocation string) (string, error) {
+ if err := os.MkdirAll(filepath.Dir(writeLocation), 0700); err != nil {
+ return "", err
+ }
if err := generatekeys(writeLocation); err != nil {
return "", err
}
diff --git a/pkg/machine/pull.go b/pkg/machine/pull.go
index 7e6f01bad..26b6adc67 100644
--- a/pkg/machine/pull.go
+++ b/pkg/machine/pull.go
@@ -5,6 +5,7 @@ package machine
import (
"bufio"
+ "errors"
"fmt"
"io"
"io/ioutil"
@@ -39,6 +40,10 @@ func NewGenericDownloader(vmType, vmName, pullPath string) (DistributionDownload
if err != nil {
return nil, err
}
+ cacheDir, err := GetCacheDir(vmType)
+ if err != nil {
+ return nil, err
+ }
dl := Download{}
// Is pullpath a file or url?
getURL, err := url2.Parse(pullPath)
@@ -48,25 +53,23 @@ func NewGenericDownloader(vmType, vmName, pullPath string) (DistributionDownload
if len(getURL.Scheme) > 0 {
urlSplit := strings.Split(getURL.Path, "/")
imageName = urlSplit[len(urlSplit)-1]
- dl.LocalUncompressedFile = filepath.Join(dataDir, imageName)
dl.URL = getURL
- dl.LocalPath = filepath.Join(dataDir, imageName)
+ dl.LocalPath = filepath.Join(cacheDir, imageName)
} else {
// Dealing with FilePath
imageName = filepath.Base(pullPath)
- dl.LocalUncompressedFile = filepath.Join(dataDir, imageName)
dl.LocalPath = pullPath
}
dl.VMName = vmName
dl.ImageName = imageName
+ dl.LocalUncompressedFile = filepath.Join(dataDir, imageName)
// The download needs to be pulled into the datadir
gd := GenericDownload{Download: dl}
- gd.LocalUncompressedFile = gd.getLocalUncompressedName()
return gd, nil
}
-func (d Download) getLocalUncompressedName() string {
+func (d Download) getLocalUncompressedFile(dataDir string) string {
var (
extension string
)
@@ -78,8 +81,8 @@ func (d Download) getLocalUncompressedName() string {
case strings.HasSuffix(d.LocalPath, ".xz"):
extension = ".xz"
}
- uncompressedFilename := filepath.Join(filepath.Dir(d.LocalPath), d.VMName+"_"+d.ImageName)
- return strings.TrimSuffix(uncompressedFilename, extension)
+ uncompressedFilename := d.VMName + "_" + d.ImageName
+ return filepath.Join(dataDir, strings.TrimSuffix(uncompressedFilename, extension))
}
func (g GenericDownload) Get() *Download {
@@ -91,6 +94,18 @@ func (g GenericDownload) HasUsableCache() (bool, error) {
return g.URL == nil, nil
}
+// CleanCache cleans out downloaded uncompressed image files
+func (g GenericDownload) CleanCache() error {
+ // Remove any image that has been downloaded via URL
+ // We never read from cache for generic downloads
+ if g.URL != nil {
+ if err := os.Remove(g.LocalPath); err != nil && !errors.Is(err, os.ErrNotExist) {
+ return err
+ }
+ }
+ return nil
+}
+
func DownloadImage(d DistributionDownload) error {
// check if the latest image is already present
ok, err := d.HasUsableCache()
@@ -98,16 +113,22 @@ func DownloadImage(d DistributionDownload) error {
return err
}
if !ok {
- if err := DownloadVMImage(d.Get().URL, d.Get().LocalPath); err != nil {
+ if err := DownloadVMImage(d.Get().URL, d.Get().ImageName, d.Get().LocalPath); err != nil {
return err
}
+ // Clean out old cached images, since we didn't find needed image in cache
+ defer func() {
+ if err = d.CleanCache(); err != nil {
+ logrus.Warnf("error cleaning machine image cache: %s", err)
+ }
+ }()
}
- return Decompress(d.Get().LocalPath, d.Get().getLocalUncompressedName())
+ return Decompress(d.Get().LocalPath, d.Get().LocalUncompressedFile)
}
// DownloadVMImage downloads a VM image from url to given path
// with download status
-func DownloadVMImage(downloadURL *url2.URL, localImagePath string) error {
+func DownloadVMImage(downloadURL *url2.URL, imageName string, localImagePath string) error {
out, err := os.Create(localImagePath)
if err != nil {
return err
@@ -132,8 +153,7 @@ func DownloadVMImage(downloadURL *url2.URL, localImagePath string) error {
return fmt.Errorf("downloading VM image %s: %s", downloadURL, resp.Status)
}
size := resp.ContentLength
- urlSplit := strings.Split(downloadURL.Path, "/")
- prefix := "Downloading VM image: " + urlSplit[len(urlSplit)-1]
+ prefix := "Downloading VM image: " + imageName
onComplete := prefix + ": done"
p := mpb.New(
@@ -253,3 +273,20 @@ func decompressEverythingElse(src string, output io.WriteCloser) error {
_, err = io.Copy(output, uncompressStream)
return err
}
+
+func removeImageAfterExpire(dir string, expire time.Duration) error {
+ now := time.Now()
+ err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+ // Delete any cache files that are older than expiry date
+ if !info.IsDir() && (now.Sub(info.ModTime()) > expire) {
+ err := os.Remove(path)
+ if err != nil && !errors.Is(err, os.ErrNotExist) {
+ logrus.Warnf("unable to clean up cached image: %s", path)
+ } else {
+ logrus.Debugf("cleaning up cached image: %s", path)
+ }
+ }
+ return nil
+ })
+ return err
+}
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 6134e69e1..7974c261e 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -240,20 +240,6 @@ func (p *Provider) LoadVMByName(name string) (machine.VM, error) {
return nil, err
}
- // It is here for providing the ability to propagate
- // proxy settings (e.g. HTTP_PROXY and others) on a start
- // and avoid a need of re-creating/re-initiating a VM
- if proxyOpts := machine.GetProxyVariables(); len(proxyOpts) > 0 {
- proxyStr := "name=opt/com.coreos/environment,string="
- var proxies string
- for k, v := range proxyOpts {
- proxies = fmt.Sprintf("%s%s=\"%s\"|", proxies, k, v)
- }
- proxyStr = fmt.Sprintf("%s%s", proxyStr, base64.StdEncoding.EncodeToString([]byte(proxies)))
- vm.CmdLine = append(vm.CmdLine, "-fw_cfg", proxyStr)
- }
-
- logrus.Debug(vm.CmdLine)
return vm, nil
}
@@ -573,15 +559,29 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
attr := new(os.ProcAttr)
files := []*os.File{dnr, dnw, dnw, fd}
attr.Files = files
- logrus.Debug(v.CmdLine)
cmdLine := v.CmdLine
+ // It is here for providing the ability to propagate
+ // proxy settings (e.g. HTTP_PROXY and others) on a start
+ // and avoid a need of re-creating/re-initiating a VM
+ if proxyOpts := machine.GetProxyVariables(); len(proxyOpts) > 0 {
+ proxyStr := "name=opt/com.coreos/environment,string="
+ var proxies string
+ for k, v := range proxyOpts {
+ proxies = fmt.Sprintf("%s%s=\"%s\"|", proxies, k, v)
+ }
+ proxyStr = fmt.Sprintf("%s%s", proxyStr, base64.StdEncoding.EncodeToString([]byte(proxies)))
+ cmdLine = append(cmdLine, "-fw_cfg", proxyStr)
+ }
+
// Disable graphic window when not in debug mode
// Done in start, so we're not suck with the debug level we used on init
if !logrus.IsLevelEnabled(logrus.DebugLevel) {
cmdLine = append(cmdLine, "-display", "none")
}
+ logrus.Debugf("qemu cmd: %v", cmdLine)
+
stderrBuf := &bytes.Buffer{}
cmd := &exec.Cmd{
@@ -670,11 +670,11 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
// because / is immutable, we have to monkey around with permissions
// if we dont mount in /home or /mnt
args := []string{"-q", "--"}
- if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ if !strings.HasPrefix(mount.Target, "/home") && !strings.HasPrefix(mount.Target, "/mnt") {
args = append(args, "sudo", "chattr", "-i", "/", ";")
}
args = append(args, "sudo", "mkdir", "-p", mount.Target)
- if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ if !strings.HasPrefix(mount.Target, "/home") && !strings.HasPrefix(mount.Target, "/mnt") {
args = append(args, ";", "sudo", "chattr", "+i", "/", ";")
}
err = v.SSH(name, machine.SSHOptions{Args: args})
diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go
index 450d8b877..189723ac7 100644
--- a/pkg/machine/wsl/machine.go
+++ b/pkg/machine/wsl/machine.go
@@ -386,7 +386,7 @@ func downloadDistro(v *MachineVM, opts machine.InitOptions) error {
if _, e := strconv.Atoi(opts.ImagePath); e == nil {
v.ImageStream = opts.ImagePath
- dd, err = machine.NewFedoraDownloader(vmtype, v.Name, v.ImageStream)
+ dd, err = machine.NewFedoraDownloader(vmtype, v.Name, opts.ImagePath)
} else {
v.ImageStream = "custom"
dd, err = machine.NewGenericDownloader(vmtype, v.Name, opts.ImagePath)
@@ -449,34 +449,14 @@ func provisionWSLDist(v *MachineVM) (string, error) {
}
dist := toDist(v.Name)
- fmt.Println("Importing operating system into WSL (this may take 5+ minutes on a new WSL install)...")
+ fmt.Println("Importing operating system into WSL (this may take a few minutes on a new WSL install)...")
if err = runCmdPassThrough("wsl", "--import", dist, distTarget, v.ImagePath); err != nil {
return "", fmt.Errorf("the WSL import of guest OS failed: %w", err)
}
- fmt.Println("Installing packages (this will take awhile)...")
- if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "upgrade", "-y"); err != nil {
- return "", fmt.Errorf("package upgrade on guest OS failed: %w", err)
- }
-
- fmt.Println("Enabling Copr")
- if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "install", "-y", "'dnf-command(copr)'"); err != nil {
- return "", fmt.Errorf("enabling copr failed: %w", err)
- }
-
- fmt.Println("Enabling podman4 repo")
- if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "-y", "copr", "enable", "rhcontainerbot/podman4"); err != nil {
- return "", fmt.Errorf("enabling copr failed: %w", err)
- }
-
- if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "install",
- "podman", "podman-docker", "openssh-server", "procps-ng", "-y"); err != nil {
- return "", fmt.Errorf("package installation on guest OS failed: %w", err)
- }
-
// Fixes newuidmap
- if err = runCmdPassThrough("wsl", "-d", dist, "dnf", "reinstall", "shadow-utils", "-y"); err != nil {
- return "", fmt.Errorf("package reinstallation of shadow-utils on guest OS failed: %w", err)
+ if err = runCmdPassThrough("wsl", "-d", dist, "rpm", "-q", "--restore", "shadow-utils", "2>/dev/null"); err != nil {
+ return "", fmt.Errorf("package permissions restore of shadow-utils on guest OS failed: %w", err)
}
// Windows 11 (NT Version = 10, Build 22000) generates harmless but scary messages on every