mirror of
https://github.com/containers/podman.git
synced 2025-06-19 16:33:24 +08:00
wsl - wip
Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:

committed by
Jason T. Greene

parent
7c7b4430a5
commit
d7cb66492b
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/containers/podman/v5/pkg/machine/applehv/vfkit"
|
"github.com/containers/podman/v5/pkg/machine/applehv/vfkit"
|
||||||
"github.com/containers/podman/v5/pkg/machine/define"
|
"github.com/containers/podman/v5/pkg/machine/define"
|
||||||
"github.com/containers/podman/v5/pkg/machine/ignition"
|
"github.com/containers/podman/v5/pkg/machine/ignition"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/shim/diskpull"
|
||||||
"github.com/containers/podman/v5/pkg/machine/sockets"
|
"github.com/containers/podman/v5/pkg/machine/sockets"
|
||||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
"github.com/containers/podman/v5/utils"
|
"github.com/containers/podman/v5/utils"
|
||||||
@ -38,6 +39,10 @@ type AppleHVStubber struct {
|
|||||||
vmconfigs.AppleHVConfig
|
vmconfigs.AppleHVConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AppleHVStubber) UserModeNetworkEnabled(_ *vmconfigs.MachineConfig) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (a AppleHVStubber) CreateVM(opts define.CreateVMOpts, mc *vmconfigs.MachineConfig, ignBuilder *ignition.IgnitionBuilder) error {
|
func (a AppleHVStubber) CreateVM(opts define.CreateVMOpts, mc *vmconfigs.MachineConfig, ignBuilder *ignition.IgnitionBuilder) error {
|
||||||
mc.AppleHypervisor = new(vmconfigs.AppleHVConfig)
|
mc.AppleHypervisor = new(vmconfigs.AppleHVConfig)
|
||||||
mc.AppleHypervisor.Vfkit = vfkit.VfkitHelper{}
|
mc.AppleHypervisor.Vfkit = vfkit.VfkitHelper{}
|
||||||
@ -317,3 +322,7 @@ func (a AppleHVStubber) PrepareIgnition(_ *vmconfigs.MachineConfig, _ *ignition.
|
|||||||
func (a AppleHVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
func (a AppleHVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a AppleHVStubber) GetDisk(userInputPath string, dirs *define.MachineDirs, mc *vmconfigs.MachineConfig) error {
|
||||||
|
return diskpull.GetDisk(userInputPath, dirs, mc.ImagePath, a.VMType(), mc.Name)
|
||||||
|
}
|
||||||
|
@ -10,8 +10,10 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type CreateVMOpts struct {
|
type CreateVMOpts struct {
|
||||||
Name string
|
Name string
|
||||||
Dirs *MachineDirs
|
Dirs *MachineDirs
|
||||||
|
ReExec bool
|
||||||
|
UserModeNetworking bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type MachineDirs struct {
|
type MachineDirs struct {
|
||||||
|
@ -2,6 +2,7 @@ package e2e_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/containers/podman/v4/pkg/machine/wsl"
|
||||||
"io"
|
"io"
|
||||||
url2 "net/url"
|
url2 "net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -61,9 +62,20 @@ var _ = BeforeSuite(func() {
|
|||||||
|
|
||||||
downloadLocation := os.Getenv("MACHINE_IMAGE")
|
downloadLocation := os.Getenv("MACHINE_IMAGE")
|
||||||
if downloadLocation == "" {
|
if downloadLocation == "" {
|
||||||
downloadLocation, err = GetDownload(testProvider.VMType())
|
// TODO so beautifully gross ... ideally we can spend some time
|
||||||
if err != nil {
|
// here making life easier on the next person
|
||||||
Fail("unable to derive download disk from fedora coreos")
|
switch testProvider.VMType() {
|
||||||
|
case define.WSLVirt:
|
||||||
|
dl, _, _, _, err := wsl.GetFedoraDownloadForWSL()
|
||||||
|
if err != nil {
|
||||||
|
Fail("unable to determine WSL download")
|
||||||
|
}
|
||||||
|
downloadLocation = dl.String()
|
||||||
|
default:
|
||||||
|
downloadLocation, err = GetDownload(testProvider.VMType())
|
||||||
|
if err != nil {
|
||||||
|
Fail("unable to derive download disk from fedora coreos")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +171,9 @@ var _ = Describe("podman machine set", func() {
|
|||||||
if testProvider.VMType() != define.WSLVirt {
|
if testProvider.VMType() != define.WSLVirt {
|
||||||
Skip("Test is only for WSL")
|
Skip("Test is only for WSL")
|
||||||
}
|
}
|
||||||
|
// TODO - this currently fails
|
||||||
|
Skip("test fails bc usermode network needs plumbing for WSL")
|
||||||
|
|
||||||
name := randomString()
|
name := randomString()
|
||||||
i := new(initMachine)
|
i := new(initMachine)
|
||||||
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
|
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
|
||||||
|
@ -10,6 +10,8 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/shim/diskpull"
|
||||||
|
|
||||||
"github.com/Microsoft/go-winio"
|
"github.com/Microsoft/go-winio"
|
||||||
"github.com/containers/common/pkg/strongunits"
|
"github.com/containers/common/pkg/strongunits"
|
||||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||||
@ -27,6 +29,10 @@ type HyperVStubber struct {
|
|||||||
vmconfigs.HyperVConfig
|
vmconfigs.HyperVConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h HyperVStubber) UserModeNetworkEnabled(mc *vmconfigs.MachineConfig) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (h HyperVStubber) CreateVM(opts define.CreateVMOpts, mc *vmconfigs.MachineConfig, builder *ignition.IgnitionBuilder) error {
|
func (h HyperVStubber) CreateVM(opts define.CreateVMOpts, mc *vmconfigs.MachineConfig, builder *ignition.IgnitionBuilder) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
@ -459,6 +465,10 @@ func (h HyperVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h HyperVStubber) GetDisk(userInputPath string, dirs *define.MachineDirs, mc *vmconfigs.MachineConfig) error {
|
||||||
|
return diskpull.GetDisk(userInputPath, dirs, mc.ImagePath, h.VMType(), mc.Name)
|
||||||
|
}
|
||||||
|
|
||||||
func resizeDisk(newSize strongunits.GiB, imagePath *define.VMFile) error {
|
func resizeDisk(newSize strongunits.GiB, imagePath *define.VMFile) error {
|
||||||
resize := exec.Command("powershell", []string{"-command", fmt.Sprintf("Resize-VHD %s %d", imagePath.GetPath(), newSize.ToBytes())}...)
|
resize := exec.Command("powershell", []string{"-command", fmt.Sprintf("Resize-VHD %s %d", imagePath.GetPath(), newSize.ToBytes())}...)
|
||||||
logrus.Debug(resize.Args)
|
logrus.Debug(resize.Args)
|
||||||
|
@ -134,6 +134,13 @@ func launchWinProxy(opts WinProxyOpts) (bool, string, error) {
|
|||||||
|
|
||||||
cmd := exec.Command(command, args...)
|
cmd := exec.Command(command, args...)
|
||||||
logrus.Debugf("winssh command: %s %v", command, args)
|
logrus.Debugf("winssh command: %s %v", command, args)
|
||||||
|
f, err := os.Open("c:\\Users\\baude\\sshproxy.log")
|
||||||
|
if err != nil {
|
||||||
|
return false, "", err
|
||||||
|
}
|
||||||
|
cmd.Stderr = f
|
||||||
|
cmd.Stdout = f
|
||||||
|
defer f.Close()
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return globalName, "", err
|
return globalName, "", err
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,11 @@ package provider
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/wsl"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
"github.com/containers/podman/v5/pkg/machine/define"
|
"github.com/containers/podman/v5/pkg/machine/define"
|
||||||
"github.com/containers/podman/v5/pkg/machine/hyperv"
|
"github.com/containers/podman/v5/pkg/machine/hyperv"
|
||||||
@ -27,9 +29,8 @@ func Get() (vmconfigs.VMProvider, error) {
|
|||||||
|
|
||||||
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
|
logrus.Debugf("Using Podman machine with `%s` virtualization provider", resolvedVMType.String())
|
||||||
switch resolvedVMType {
|
switch resolvedVMType {
|
||||||
// TODO re-enable this with WSL
|
case define.WSLVirt:
|
||||||
//case define.WSLVirt:
|
return new(wsl.WSLStubber), nil
|
||||||
// return wsl.VirtualizationProvider(), nil
|
|
||||||
case define.HyperVVirt:
|
case define.HyperVVirt:
|
||||||
return new(hyperv.HyperVStubber), nil
|
return new(hyperv.HyperVStubber), nil
|
||||||
default:
|
default:
|
||||||
|
@ -11,14 +11,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/podman/v5/pkg/machine/ignition"
|
|
||||||
|
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
"github.com/containers/common/pkg/strongunits"
|
"github.com/containers/common/pkg/strongunits"
|
||||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||||
"github.com/containers/podman/v5/pkg/machine"
|
"github.com/containers/podman/v5/pkg/machine"
|
||||||
"github.com/containers/podman/v5/pkg/machine/define"
|
"github.com/containers/podman/v5/pkg/machine/define"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/ignition"
|
||||||
"github.com/containers/podman/v5/pkg/machine/qemu/command"
|
"github.com/containers/podman/v5/pkg/machine/qemu/command"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/shim/diskpull"
|
||||||
"github.com/containers/podman/v5/pkg/machine/sockets"
|
"github.com/containers/podman/v5/pkg/machine/sockets"
|
||||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -30,6 +30,10 @@ type QEMUStubber struct {
|
|||||||
Command command.QemuCmd
|
Command command.QemuCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q QEMUStubber) UserModeNetworkEnabled(*vmconfigs.MachineConfig) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (q *QEMUStubber) setQEMUCommandLine(mc *vmconfigs.MachineConfig) error {
|
func (q *QEMUStubber) setQEMUCommandLine(mc *vmconfigs.MachineConfig) error {
|
||||||
qemuBinary, err := findQEMUBinary()
|
qemuBinary, err := findQEMUBinary()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -326,3 +330,7 @@ func (q *QEMUStubber) MountType() vmconfigs.VolumeMountType {
|
|||||||
func (q *QEMUStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
func (q *QEMUStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *QEMUStubber) GetDisk(userInputPath string, dirs *define.MachineDirs, mc *vmconfigs.MachineConfig) error {
|
||||||
|
return diskpull.GetDisk(userInputPath, dirs, mc.ImagePath, q.VMType(), mc.Name)
|
||||||
|
}
|
||||||
|
32
pkg/machine/shim/diskpull/diskpull.go
Normal file
32
pkg/machine/shim/diskpull/diskpull.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package diskpull
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/define"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/ocipull"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/stdpull"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetDisk(userInputPath string, dirs *define.MachineDirs, imagePath *define.VMFile, vmType define.VMType, name string) error {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
mydisk ocipull.Disker
|
||||||
|
)
|
||||||
|
|
||||||
|
if userInputPath == "" {
|
||||||
|
mydisk, err = ocipull.NewVersioned(context.Background(), dirs.DataDir, name, vmType.String(), imagePath)
|
||||||
|
} else {
|
||||||
|
if strings.HasPrefix(userInputPath, "http") {
|
||||||
|
// TODO probably should use tempdir instead of datadir
|
||||||
|
mydisk, err = stdpull.NewDiskFromURL(userInputPath, imagePath, dirs.DataDir, nil)
|
||||||
|
} else {
|
||||||
|
mydisk, err = stdpull.NewStdDiskPull(userInputPath, imagePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return mydisk.Get()
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
package shim
|
package shim
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/util"
|
"github.com/containers/common/pkg/util"
|
||||||
@ -14,30 +12,13 @@ import (
|
|||||||
"github.com/containers/podman/v5/pkg/machine/connection"
|
"github.com/containers/podman/v5/pkg/machine/connection"
|
||||||
machineDefine "github.com/containers/podman/v5/pkg/machine/define"
|
machineDefine "github.com/containers/podman/v5/pkg/machine/define"
|
||||||
"github.com/containers/podman/v5/pkg/machine/ignition"
|
"github.com/containers/podman/v5/pkg/machine/ignition"
|
||||||
"github.com/containers/podman/v5/pkg/machine/ocipull"
|
|
||||||
"github.com/containers/podman/v5/pkg/machine/stdpull"
|
|
||||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
Host
|
|
||||||
├ Info
|
|
||||||
├ OS Apply
|
|
||||||
├ SSH
|
|
||||||
├ List
|
|
||||||
├ Init
|
|
||||||
├ VMExists
|
|
||||||
├ CheckExclusiveActiveVM *HyperV/WSL need to check their hypervisors as well
|
|
||||||
*/
|
|
||||||
|
|
||||||
func Info() {}
|
|
||||||
func OSApply() {}
|
|
||||||
func SSH() {}
|
|
||||||
|
|
||||||
// List is done at the host level to allow for a *possible* future where
|
// List is done at the host level to allow for a *possible* future where
|
||||||
// more than one provider is used
|
// more than one provider is used
|
||||||
func List(vmstubbers []vmconfigs.VMProvider, opts machine.ListOptions) ([]*machine.ListResponse, error) {
|
func List(vmstubbers []vmconfigs.VMProvider, _ machine.ListOptions) ([]*machine.ListResponse, error) {
|
||||||
var (
|
var (
|
||||||
lrs []*machine.ListResponse
|
lrs []*machine.ListResponse
|
||||||
)
|
)
|
||||||
@ -114,6 +95,10 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
|||||||
Dirs: dirs,
|
Dirs: dirs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if umn := opts.UserModeNetworking; umn != nil {
|
||||||
|
createOpts.UserModeNetworking = *umn
|
||||||
|
}
|
||||||
|
|
||||||
// Get Image
|
// Get Image
|
||||||
// TODO This needs rework bigtime; my preference is most of below of not living in here.
|
// TODO This needs rework bigtime; my preference is most of below of not living in here.
|
||||||
// ideally we could get a func back that pulls the image, and only do so IF everything works because
|
// ideally we could get a func back that pulls the image, and only do so IF everything works because
|
||||||
@ -137,8 +122,7 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
mc.ImagePath = imagePath
|
||||||
var mydisk ocipull.Disker
|
|
||||||
|
|
||||||
// TODO The following stanzas should be re-written in a differeent place. It should have a custom
|
// TODO The following stanzas should be re-written in a differeent place. It should have a custom
|
||||||
// parser for our image pulling. It would be nice if init just got an error and mydisk back.
|
// parser for our image pulling. It would be nice if init just got an error and mydisk back.
|
||||||
@ -149,25 +133,12 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
|||||||
// "/path
|
// "/path
|
||||||
// "docker://quay.io/something/someManifest
|
// "docker://quay.io/something/someManifest
|
||||||
|
|
||||||
if opts.ImagePath == "" {
|
// TODO Ideally this changes into some way better ...
|
||||||
mydisk, err = ocipull.NewVersioned(context.Background(), dirs.DataDir, opts.Name, mp.VMType().String(), imagePath)
|
err = mp.GetDisk(opts.ImagePath, dirs, mc)
|
||||||
} else {
|
|
||||||
if strings.HasPrefix(opts.ImagePath, "http") {
|
|
||||||
// TODO probably should use tempdir instead of datadir
|
|
||||||
mydisk, err = stdpull.NewDiskFromURL(opts.ImagePath, imagePath, dirs.DataDir)
|
|
||||||
} else {
|
|
||||||
mydisk, err = stdpull.NewStdDiskPull(opts.ImagePath, imagePath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
err = mydisk.Get()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mc.ImagePath = imagePath
|
|
||||||
callbackFuncs.Add(mc.ImagePath.Delete)
|
callbackFuncs.Add(mc.ImagePath.Delete)
|
||||||
|
|
||||||
logrus.Debugf("--> imagePath is %q", imagePath.GetPath())
|
logrus.Debugf("--> imagePath is %q", imagePath.GetPath())
|
||||||
@ -182,8 +153,18 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
|||||||
uid = 1000
|
uid = 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO the definition of "user" should go into
|
||||||
|
// common for WSL
|
||||||
|
userName := opts.Username
|
||||||
|
if mp.VMType() == machineDefine.WSLVirt {
|
||||||
|
if opts.Username == "core" {
|
||||||
|
userName = "user"
|
||||||
|
mc.SSH.RemoteUsername = "user"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ignBuilder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
|
ignBuilder := ignition.NewIgnitionBuilder(ignition.DynamicIgnition{
|
||||||
Name: opts.Username,
|
Name: userName,
|
||||||
Key: sshKey,
|
Key: sshKey,
|
||||||
TimeZone: opts.TimeZone,
|
TimeZone: opts.TimeZone,
|
||||||
UID: uid,
|
UID: uid,
|
||||||
@ -223,7 +204,9 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
|||||||
ignBuilder.WithUnit(readyUnit)
|
ignBuilder.WithUnit(readyUnit)
|
||||||
|
|
||||||
// Mounts
|
// Mounts
|
||||||
mc.Mounts = CmdLineVolumesToMounts(opts.Volumes, mp.MountType())
|
if mp.VMType() != machineDefine.WSLVirt {
|
||||||
|
mc.Mounts = CmdLineVolumesToMounts(opts.Volumes, mp.MountType())
|
||||||
|
}
|
||||||
|
|
||||||
// TODO AddSSHConnectionToPodmanSocket could take an machineconfig instead
|
// TODO AddSSHConnectionToPodmanSocket could take an machineconfig instead
|
||||||
if err := connection.AddSSHConnectionsToPodmanSocket(mc.HostUser.UID, mc.SSH.Port, mc.SSH.IdentityPath, mc.Name, mc.SSH.RemoteUsername, opts); err != nil {
|
if err := connection.AddSSHConnectionsToPodmanSocket(mc.HostUser.UID, mc.SSH.Port, mc.SSH.IdentityPath, mc.Name, mc.SSH.RemoteUsername, opts); err != nil {
|
||||||
@ -347,21 +330,23 @@ func Stop(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDef
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stop GvProxy and remove PID file
|
// Stop GvProxy and remove PID file
|
||||||
gvproxyPidFile, err := dirs.RuntimeDir.AppendToNewVMFile("gvproxy.pid", nil)
|
if mp.UserModeNetworkEnabled(mc) {
|
||||||
if err != nil {
|
gvproxyPidFile, err := dirs.RuntimeDir.AppendToNewVMFile("gvproxy.pid", nil)
|
||||||
return err
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := machine.CleanupGVProxy(*gvproxyPidFile); err != nil {
|
|
||||||
logrus.Errorf("unable to clean up gvproxy: %q", err)
|
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
|
defer func() {
|
||||||
|
if err := machine.CleanupGVProxy(*gvproxyPidFile); err != nil {
|
||||||
|
logrus.Errorf("unable to clean up gvproxy: %q", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDefine.MachineDirs, opts machine.StartOptions) error {
|
func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, _ *machineDefine.MachineDirs, opts machine.StartOptions) error {
|
||||||
defaultBackoff := 500 * time.Millisecond
|
defaultBackoff := 500 * time.Millisecond
|
||||||
maxBackoffs := 6
|
maxBackoffs := 6
|
||||||
|
|
||||||
|
@ -23,16 +23,12 @@ const (
|
|||||||
dockerConnectTimeout = 5 * time.Second
|
dockerConnectTimeout = 5 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider) (string, machine.APIForwardingState, error) {
|
func startUserModeNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider, dirs *define.MachineDirs, hostSocket *define.VMFile) error {
|
||||||
var (
|
|
||||||
forwardingState machine.APIForwardingState
|
|
||||||
forwardSock string
|
|
||||||
)
|
|
||||||
// the guestSock is "inside" the guest machine
|
|
||||||
guestSock := fmt.Sprintf(defaultGuestSock, mc.HostUser.UID)
|
|
||||||
forwardUser := mc.SSH.RemoteUsername
|
forwardUser := mc.SSH.RemoteUsername
|
||||||
|
|
||||||
// TODO should this go up the stack higher
|
// TODO should this go up the stack higher or
|
||||||
|
// the guestSock is "inside" the guest machine
|
||||||
|
guestSock := fmt.Sprintf(defaultGuestSock, mc.HostUser.UID)
|
||||||
if mc.HostUser.Rootful {
|
if mc.HostUser.Rootful {
|
||||||
guestSock = "/run/podman/podman.sock"
|
guestSock = "/run/podman/podman.sock"
|
||||||
forwardUser = "root"
|
forwardUser = "root"
|
||||||
@ -40,38 +36,18 @@ func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider)
|
|||||||
|
|
||||||
cfg, err := config.Default()
|
cfg, err := config.Default()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
binary, err := cfg.FindHelperBinary(machine.ForwarderBinaryName, false)
|
binary, err := cfg.FindHelperBinary(machine.ForwarderBinaryName, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", 0, err
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
dataDir, err := mc.DataDir()
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, err
|
|
||||||
}
|
|
||||||
hostSocket, err := dataDir.AppendToNewVMFile("podman.sock", nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
runDir, err := mc.RuntimeDir()
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
linkSocketPath := filepath.Dir(dataDir.GetPath())
|
|
||||||
linkSocket, err := define.NewMachineFile(filepath.Join(linkSocketPath, "podman.sock"), nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", 0, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := gvproxy.NewGvproxyCommand()
|
cmd := gvproxy.NewGvproxyCommand()
|
||||||
|
|
||||||
// GvProxy PID file path is now derived
|
// GvProxy PID file path is now derived
|
||||||
cmd.PidFile = filepath.Join(runDir.GetPath(), "gvproxy.pid")
|
cmd.PidFile = filepath.Join(dirs.RuntimeDir.GetPath(), "gvproxy.pid")
|
||||||
|
|
||||||
// TODO This can be re-enabled when gvisor-tap-vsock #305 is merged
|
// TODO This can be re-enabled when gvisor-tap-vsock #305 is merged
|
||||||
// debug is set, we dump to a logfile as well
|
// debug is set, we dump to a logfile as well
|
||||||
@ -94,6 +70,36 @@ func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider)
|
|||||||
// This allows a provider to perform additional setup as well as
|
// This allows a provider to perform additional setup as well as
|
||||||
// add in any provider specific options for gvproxy
|
// add in any provider specific options for gvproxy
|
||||||
if err := provider.StartNetworking(mc, &cmd); err != nil {
|
if err := provider.StartNetworking(mc, &cmd); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := cmd.Cmd(binary)
|
||||||
|
|
||||||
|
logrus.Debugf("gvproxy command-line: %s %s", binary, strings.Join(cmd.ToCmdline(), " "))
|
||||||
|
if err := c.Start(); err != nil {
|
||||||
|
return fmt.Errorf("unable to execute: %q: %w", cmd.ToCmdline(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider) (string, machine.APIForwardingState, error) {
|
||||||
|
var (
|
||||||
|
forwardingState machine.APIForwardingState
|
||||||
|
forwardSock string
|
||||||
|
)
|
||||||
|
dirs, err := machine.GetMachineDirs(provider.VMType())
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
hostSocket, err := dirs.DataDir.AppendToNewVMFile("podman.sock", nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
linkSocketPath := filepath.Dir(dirs.DataDir.GetPath())
|
||||||
|
linkSocket, err := define.NewMachineFile(filepath.Join(linkSocketPath, "podman.sock"), nil)
|
||||||
|
if err != nil {
|
||||||
return "", 0, err
|
return "", 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,21 +107,15 @@ func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider)
|
|||||||
forwardSock, forwardingState = setupAPIForwarding(hostSocket, linkSocket)
|
forwardSock, forwardingState = setupAPIForwarding(hostSocket, linkSocket)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := cmd.Cmd(binary)
|
if provider.UserModeNetworkEnabled(mc) {
|
||||||
|
if err := startUserModeNetworking(mc, provider, dirs, hostSocket); err != nil {
|
||||||
logrus.Debugf("gvproxy command-line: %s %s", binary, strings.Join(cmd.ToCmdline(), " "))
|
return "", 0, err
|
||||||
if err := c.Start(); err != nil {
|
}
|
||||||
return forwardSock, 0, fmt.Errorf("unable to execute: %q: %w", cmd.ToCmdline(), err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return forwardSock, forwardingState, nil
|
return forwardSock, forwardingState, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type apiOptions struct { //nolint:unused
|
|
||||||
socketpath, destinationSocketPath *define.VMFile
|
|
||||||
fowardUser string
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupAPIForwarding(hostSocket, linkSocket *define.VMFile) (string, machine.APIForwardingState) {
|
func setupAPIForwarding(hostSocket, linkSocket *define.VMFile) (string, machine.APIForwardingState) {
|
||||||
// The linking pattern is /var/run/docker.sock -> user global sock (link) -> machine sock (socket)
|
// The linking pattern is /var/run/docker.sock -> user global sock (link) -> machine sock (socket)
|
||||||
// This allows the helper to only have to maintain one constant target to the user, which can be
|
// This allows the helper to only have to maintain one constant target to the user, which can be
|
||||||
|
@ -23,7 +23,7 @@ type DiskFromURL struct {
|
|||||||
tempLocation *define.VMFile
|
tempLocation *define.VMFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDiskFromURL(inputPath string, finalPath *define.VMFile, tempDir *define.VMFile) (*DiskFromURL, error) {
|
func NewDiskFromURL(inputPath string, finalPath *define.VMFile, tempDir *define.VMFile, optionalTempFileName *string) (*DiskFromURL, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
@ -40,6 +40,9 @@ func NewDiskFromURL(inputPath string, finalPath *define.VMFile, tempDir *define.
|
|||||||
}
|
}
|
||||||
|
|
||||||
remoteImageName := path.Base(inputPath)
|
remoteImageName := path.Base(inputPath)
|
||||||
|
if optionalTempFileName != nil {
|
||||||
|
remoteImageName = *optionalTempFileName
|
||||||
|
}
|
||||||
if remoteImageName == "" {
|
if remoteImageName == "" {
|
||||||
return nil, fmt.Errorf("invalid url: unable to determine image name in %q", inputPath)
|
return nil, fmt.Errorf("invalid url: unable to determine image name in %q", inputPath)
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,10 @@ func (f fcosMachineImage) path() string {
|
|||||||
|
|
||||||
type VMProvider interface { //nolint:interfacebloat
|
type VMProvider interface { //nolint:interfacebloat
|
||||||
CreateVM(opts define.CreateVMOpts, mc *MachineConfig, builder *ignition.IgnitionBuilder) error
|
CreateVM(opts define.CreateVMOpts, mc *MachineConfig, builder *ignition.IgnitionBuilder) error
|
||||||
|
// GetDisk should be only temporary. It is largely here only because WSL disk pulling is different
|
||||||
|
// TODO
|
||||||
|
// Let's deprecate this ASAP
|
||||||
|
GetDisk(userInputPath string, dirs *define.MachineDirs, mc *MachineConfig) error
|
||||||
PrepareIgnition(mc *MachineConfig, ignBuilder *ignition.IgnitionBuilder) (*ignition.ReadyUnitOpts, error)
|
PrepareIgnition(mc *MachineConfig, ignBuilder *ignition.IgnitionBuilder) (*ignition.ReadyUnitOpts, error)
|
||||||
GetHyperVisorVMs() ([]string, error)
|
GetHyperVisorVMs() ([]string, error)
|
||||||
MountType() VolumeMountType
|
MountType() VolumeMountType
|
||||||
@ -121,6 +125,7 @@ type VMProvider interface { //nolint:interfacebloat
|
|||||||
StopVM(mc *MachineConfig, hardStop bool) error
|
StopVM(mc *MachineConfig, hardStop bool) error
|
||||||
StopHostNetworking(mc *MachineConfig, vmType define.VMType) error
|
StopHostNetworking(mc *MachineConfig, vmType define.VMType) error
|
||||||
VMType() define.VMType
|
VMType() define.VMType
|
||||||
|
UserModeNetworkEnabled(mc *MachineConfig) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostUser describes the host user
|
// HostUser describes the host user
|
||||||
|
@ -13,7 +13,8 @@ type HyperVConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WSLConfig struct {
|
type WSLConfig struct {
|
||||||
//wslstuff *aThing
|
// Uses usermode networking
|
||||||
|
UserModeNetworking bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stubs
|
// Stubs
|
||||||
|
@ -77,6 +77,7 @@ func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIden
|
|||||||
}
|
}
|
||||||
mc.Resources = mrc
|
mc.Resources = mrc
|
||||||
|
|
||||||
|
// TODO WSL had a locking port mechanism, we should consider this.
|
||||||
sshPort, err := utils.GetRandomPort()
|
sshPort, err := utils.GetRandomPort()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
247
pkg/machine/wsl/declares.go
Normal file
247
pkg/machine/wsl/declares.go
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
package wsl
|
||||||
|
|
||||||
|
const (
|
||||||
|
ErrorSuccessRebootInitiated = 1641
|
||||||
|
ErrorSuccessRebootRequired = 3010
|
||||||
|
currentMachineVersion = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
const containersConf = `[containers]
|
||||||
|
|
||||||
|
[engine]
|
||||||
|
cgroup_manager = "cgroupfs"
|
||||||
|
`
|
||||||
|
|
||||||
|
const registriesConf = `unqualified-search-registries=["docker.io"]
|
||||||
|
`
|
||||||
|
|
||||||
|
const appendPort = `grep -q Port\ %d /etc/ssh/sshd_config || echo Port %d >> /etc/ssh/sshd_config`
|
||||||
|
|
||||||
|
const changePort = `sed -E -i 's/^Port[[:space:]]+[0-9]+/Port %d/' /etc/ssh/sshd_config`
|
||||||
|
|
||||||
|
const configServices = `ln -fs /usr/lib/systemd/system/sshd.service /etc/systemd/system/multi-user.target.wants/sshd.service
|
||||||
|
ln -fs /usr/lib/systemd/system/podman.socket /etc/systemd/system/sockets.target.wants/podman.socket
|
||||||
|
rm -f /etc/systemd/system/getty.target.wants/console-getty.service
|
||||||
|
rm -f /etc/systemd/system/getty.target.wants/getty@tty1.service
|
||||||
|
rm -f /etc/systemd/system/multi-user.target.wants/systemd-resolved.service
|
||||||
|
rm -f /etc/systemd/system/sysinit.target.wants//systemd-resolved.service
|
||||||
|
rm -f /etc/systemd/system/dbus-org.freedesktop.resolve1.service
|
||||||
|
ln -fs /dev/null /etc/systemd/system/console-getty.service
|
||||||
|
ln -fs /dev/null /etc/systemd/system/systemd-oomd.socket
|
||||||
|
mkdir -p /etc/systemd/system/systemd-sysusers.service.d/
|
||||||
|
echo CREATE_MAIL_SPOOL=no >> /etc/default/useradd
|
||||||
|
adduser -m [USER] -G wheel
|
||||||
|
mkdir -p /home/[USER]/.config/systemd/[USER]/
|
||||||
|
chown [USER]:[USER] /home/[USER]/.config
|
||||||
|
`
|
||||||
|
|
||||||
|
const sudoers = `%wheel ALL=(ALL) NOPASSWD: ALL
|
||||||
|
`
|
||||||
|
|
||||||
|
const bootstrap = `#!/bin/bash
|
||||||
|
ps -ef | grep -v grep | grep -q systemd && exit 0
|
||||||
|
nohup unshare --kill-child --fork --pid --mount --mount-proc --propagation shared /lib/systemd/systemd >/dev/null 2>&1 &
|
||||||
|
sleep 0.1
|
||||||
|
`
|
||||||
|
|
||||||
|
const wslmotd = `
|
||||||
|
You will be automatically entered into a nested process namespace where
|
||||||
|
systemd is running. If you need to access the parent namespace, hit ctrl-d
|
||||||
|
or type exit. This also means to log out you need to exit twice.
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
const sysdpid = "SYSDPID=`ps -eo cmd,pid | grep -m 1 ^/lib/systemd/systemd | awk '{print $2}'`"
|
||||||
|
|
||||||
|
const profile = sysdpid + `
|
||||||
|
if [ ! -z "$SYSDPID" ] && [ "$SYSDPID" != "1" ]; then
|
||||||
|
cat /etc/wslmotd
|
||||||
|
/usr/local/bin/enterns
|
||||||
|
fi
|
||||||
|
`
|
||||||
|
|
||||||
|
const enterns = "#!/bin/bash\n" + sysdpid + `
|
||||||
|
if [ ! -z "$SYSDPID" ] && [ "$SYSDPID" != "1" ]; then
|
||||||
|
NSENTER=("nsenter" "-m" "-p" "-t" "$SYSDPID" "--wd=$PWD")
|
||||||
|
|
||||||
|
if [ "$UID" != "0" ]; then
|
||||||
|
NSENTER=("sudo" "${NSENTER[@]}")
|
||||||
|
if [ "$#" != "0" ]; then
|
||||||
|
NSENTER+=("sudo" "-u" "$USER")
|
||||||
|
else
|
||||||
|
NSENTER+=("su" "-l" "$USER")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
"${NSENTER[@]}" "$@"
|
||||||
|
fi`
|
||||||
|
|
||||||
|
const waitTerm = sysdpid + `
|
||||||
|
if [ ! -z "$SYSDPID" ]; then
|
||||||
|
timeout 60 tail -f /dev/null --pid $SYSDPID
|
||||||
|
fi
|
||||||
|
`
|
||||||
|
|
||||||
|
const wslConf = `[user]
|
||||||
|
default=[USER]
|
||||||
|
`
|
||||||
|
|
||||||
|
const wslConfUserNet = `
|
||||||
|
[network]
|
||||||
|
generateResolvConf = false
|
||||||
|
`
|
||||||
|
|
||||||
|
const resolvConfUserNet = `
|
||||||
|
nameserver 192.168.127.1
|
||||||
|
`
|
||||||
|
|
||||||
|
// WSL kernel does not have sg and crypto_user modules
|
||||||
|
const overrideSysusers = `[Service]
|
||||||
|
LoadCredential=
|
||||||
|
`
|
||||||
|
|
||||||
|
const lingerService = `[Unit]
|
||||||
|
Description=A systemd user unit demo
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target podman.socket
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/sleep infinity
|
||||||
|
`
|
||||||
|
|
||||||
|
const lingerSetup = `mkdir -p /home/[USER]/.config/systemd/user/default.target.wants
|
||||||
|
ln -fs /home/[USER]/.config/systemd/user/linger-example.service \
|
||||||
|
/home/[USER]/.config/systemd/user/default.target.wants/linger-example.service
|
||||||
|
`
|
||||||
|
|
||||||
|
const bindMountSystemService = `
|
||||||
|
[Unit]
|
||||||
|
Description=Bind mount for system podman sockets
|
||||||
|
After=podman.socket
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
RemainAfterExit=true
|
||||||
|
Type=oneshot
|
||||||
|
# Ensure user services can register sockets as well
|
||||||
|
ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets
|
||||||
|
ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets/%[1]s
|
||||||
|
ExecStartPre=touch /mnt/wsl/podman-sockets/%[1]s/podman-root.sock
|
||||||
|
ExecStart=mount --bind %%t/podman/podman.sock /mnt/wsl/podman-sockets/%[1]s/podman-root.sock
|
||||||
|
ExecStop=umount /mnt/wsl/podman-sockets/%[1]s/podman-root.sock
|
||||||
|
`
|
||||||
|
|
||||||
|
const bindMountUserService = `
|
||||||
|
[Unit]
|
||||||
|
Description=Bind mount for user podman sockets
|
||||||
|
After=podman.socket
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
RemainAfterExit=true
|
||||||
|
Type=oneshot
|
||||||
|
# Consistency with system service (supports racing)
|
||||||
|
ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets
|
||||||
|
ExecStartPre=mkdir -p -m 777 /mnt/wsl/podman-sockets/%[1]s
|
||||||
|
ExecStartPre=touch /mnt/wsl/podman-sockets/%[1]s/podman-user.sock
|
||||||
|
# Relies on /etc/fstab entry for user mounting
|
||||||
|
ExecStart=mount /mnt/wsl/podman-sockets/%[1]s/podman-user.sock
|
||||||
|
ExecStop=umount /mnt/wsl/podman-sockets/%[1]s/podman-user.sock
|
||||||
|
`
|
||||||
|
|
||||||
|
const bindMountFsTab = `/run/user/1000/podman/podman.sock /mnt/wsl/podman-sockets/%s/podman-user.sock none noauto,user,bind,defaults 0 0
|
||||||
|
`
|
||||||
|
const (
|
||||||
|
defaultTargetWants = "default.target.wants"
|
||||||
|
userSystemdPath = "/home/%[1]s/.config/systemd/user"
|
||||||
|
sysSystemdPath = "/etc/systemd/system"
|
||||||
|
userSystemdWants = userSystemdPath + "/" + defaultTargetWants
|
||||||
|
sysSystemdWants = sysSystemdPath + "/" + defaultTargetWants
|
||||||
|
bindUnitFileName = "podman-mnt-bindings.service"
|
||||||
|
bindUserUnitPath = userSystemdPath + "/" + bindUnitFileName
|
||||||
|
bindUserUnitWant = userSystemdWants + "/" + bindUnitFileName
|
||||||
|
bindSysUnitPath = sysSystemdPath + "/" + bindUnitFileName
|
||||||
|
bindSysUnitWant = sysSystemdWants + "/" + bindUnitFileName
|
||||||
|
podmanSocketDropin = "podman.socket.d"
|
||||||
|
podmanSocketDropinPath = sysSystemdPath + "/" + podmanSocketDropin
|
||||||
|
)
|
||||||
|
|
||||||
|
const configBindServices = "mkdir -p " + userSystemdWants + " " + sysSystemdWants + " " + podmanSocketDropinPath + "\n" +
|
||||||
|
"ln -fs " + bindUserUnitPath + " " + bindUserUnitWant + "\n" +
|
||||||
|
"ln -fs " + bindSysUnitPath + " " + bindSysUnitWant + "\n"
|
||||||
|
|
||||||
|
const overrideSocketGroup = `
|
||||||
|
[Socket]
|
||||||
|
SocketMode=0660
|
||||||
|
SocketGroup=wheel
|
||||||
|
`
|
||||||
|
|
||||||
|
const proxyConfigSetup = `#!/bin/bash
|
||||||
|
|
||||||
|
SYSTEMD_CONF=/etc/systemd/system.conf.d/default-env.conf
|
||||||
|
ENVD_CONF=/etc/environment.d/default-env.conf
|
||||||
|
PROFILE_CONF=/etc/profile.d/default-env.sh
|
||||||
|
|
||||||
|
IFS="|"
|
||||||
|
read proxies
|
||||||
|
|
||||||
|
mkdir -p /etc/profile.d /etc/environment.d /etc/systemd/system.conf.d/
|
||||||
|
rm -f $SYSTEMD_CONF
|
||||||
|
for proxy in $proxies; do
|
||||||
|
output+="$proxy "
|
||||||
|
done
|
||||||
|
echo "[Manager]" >> $SYSTEMD_CONF
|
||||||
|
echo -ne "DefaultEnvironment=" >> $SYSTEMD_CONF
|
||||||
|
|
||||||
|
echo $output >> $SYSTEMD_CONF
|
||||||
|
rm -f $ENVD_CONF
|
||||||
|
for proxy in $proxies; do
|
||||||
|
echo "$proxy" >> $ENVD_CONF
|
||||||
|
done
|
||||||
|
rm -f $PROFILE_CONF
|
||||||
|
for proxy in $proxies; do
|
||||||
|
echo "export $proxy" >> $PROFILE_CONF
|
||||||
|
done
|
||||||
|
`
|
||||||
|
|
||||||
|
const proxyConfigAttempt = `if [ -f /usr/local/bin/proxyinit ]; \
|
||||||
|
then /usr/local/bin/proxyinit; \
|
||||||
|
else exit 42; \
|
||||||
|
fi`
|
||||||
|
|
||||||
|
const clearProxySettings = `rm -f /etc/systemd/system.conf.d/default-env.conf \
|
||||||
|
/etc/environment.d/default-env.conf \
|
||||||
|
/etc/profile.d/default-env.sh`
|
||||||
|
|
||||||
|
const wslInstallError = `Could not %s. See previous output for any potential failure details.
|
||||||
|
If you can not resolve the issue, and rerunning fails, try the "wsl --install" process
|
||||||
|
outlined in the following article:
|
||||||
|
|
||||||
|
http://docs.microsoft.com/en-us/windows/wsl/install
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
const wslKernelError = `Could not %s. See previous output for any potential failure details.
|
||||||
|
If you can not resolve the issue, try rerunning the "podman machine init command". If that fails
|
||||||
|
try the "wsl --update" command and then rerun "podman machine init". Finally, if all else fails,
|
||||||
|
try following the steps outlined in the following article:
|
||||||
|
|
||||||
|
http://docs.microsoft.com/en-us/windows/wsl/install
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
const wslInstallKernel = "install the WSL Kernel"
|
||||||
|
|
||||||
|
const wslOldVersion = `Automatic installation of WSL can not be performed on this version of Windows
|
||||||
|
Either update to Build 19041 (or later), or perform the manual installation steps
|
||||||
|
outlined in the following article:
|
||||||
|
|
||||||
|
http://docs.microsoft.com/en-us/windows/wsl/install\
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
const (
|
||||||
|
gvProxy = "gvproxy.exe"
|
||||||
|
winSShProxy = "win-sshproxy.exe"
|
||||||
|
pipePrefix = "npipe:////./pipe/"
|
||||||
|
globalPipe = "docker_engine"
|
||||||
|
userModeDist = "podman-net-usermode"
|
||||||
|
rootfulSock = "/run/podman/podman.sock"
|
||||||
|
rootlessSock = "/run/user/1000/podman/podman.sock"
|
||||||
|
)
|
@ -1,10 +1,9 @@
|
|||||||
//go:build windows
|
|
||||||
|
|
||||||
package wsl
|
package wsl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -27,8 +26,10 @@ type FedoraDownload struct {
|
|||||||
machine.Download
|
machine.Download
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFedoraDownloader
|
||||||
|
// deprecated
|
||||||
func NewFedoraDownloader(vmType define.VMType, vmName, releaseStream string) (machine.DistributionDownload, error) {
|
func NewFedoraDownloader(vmType define.VMType, vmName, releaseStream string) (machine.DistributionDownload, error) {
|
||||||
downloadURL, version, arch, size, err := getFedoraDownload()
|
downloadURL, version, arch, size, err := GetFedoraDownloadForWSL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -82,7 +83,7 @@ func (f FedoraDownload) CleanCache() error {
|
|||||||
return machine.RemoveImageAfterExpire(f.CacheDir, expire)
|
return machine.RemoveImageAfterExpire(f.CacheDir, expire)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFedoraDownload() (*url.URL, string, string, int64, error) {
|
func GetFedoraDownloadForWSL() (*url.URL, string, string, int64, error) {
|
||||||
var releaseURL string
|
var releaseURL string
|
||||||
arch := machine.DetermineMachineArch()
|
arch := machine.DetermineMachineArch()
|
||||||
switch arch {
|
switch arch {
|
||||||
@ -118,11 +119,14 @@ func getFedoraDownload() (*url.URL, string, string, int64, error) {
|
|||||||
return nil, "", "", -1, fmt.Errorf("get request failed: %s: %w", verURL.String(), err)
|
return nil, "", "", -1, fmt.Errorf("get request failed: %s: %w", verURL.String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer func() {
|
||||||
bytes, err := io.ReadAll(&io.LimitedReader{R: resp.Body, N: 1024})
|
if err := resp.Body.Close(); err != nil {
|
||||||
|
logrus.Errorf("error closing http boddy: %q", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
b, err := io.ReadAll(&io.LimitedReader{R: resp.Body, N: 1024})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", "", -1, fmt.Errorf("failed reading: %s: %w", verURL.String(), err)
|
return nil, "", "", -1, fmt.Errorf("failed reading: %s: %w", verURL.String(), err)
|
||||||
}
|
}
|
||||||
|
return downloadURL, strings.TrimSpace(string(b)), arch, contentLen, nil
|
||||||
return downloadURL, strings.TrimSpace(string(bytes)), arch, contentLen, nil
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
362
pkg/machine/wsl/stubber.go
Normal file
362
pkg/machine/wsl/stubber.go
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package wsl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/ocipull"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/stdpull"
|
||||||
|
|
||||||
|
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/define"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/ignition"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WSLStubber struct {
|
||||||
|
vmconfigs.WSLConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) CreateVM(opts define.CreateVMOpts, mc *vmconfigs.MachineConfig, _ *ignition.IgnitionBuilder) error {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
// cleanup half-baked files if init fails at any point
|
||||||
|
callbackFuncs := machine.InitCleanup()
|
||||||
|
defer callbackFuncs.CleanIfErr(&err)
|
||||||
|
go callbackFuncs.CleanOnSignal()
|
||||||
|
mc.WSLHypervisor = new(vmconfigs.WSLConfig)
|
||||||
|
// TODO
|
||||||
|
// USB opts are unsupported in WSL. Need to account for that here
|
||||||
|
// or up the stack
|
||||||
|
// if len(opts.USBs) > 0 {
|
||||||
|
// return nil, fmt.Errorf("USB host passthrough is not supported for WSL machines")
|
||||||
|
// }
|
||||||
|
|
||||||
|
if cont, err := checkAndInstallWSL(opts.ReExec); !cont {
|
||||||
|
appendOutputIfError(opts.ReExec, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = setupWslProxyEnv()
|
||||||
|
|
||||||
|
if opts.UserModeNetworking {
|
||||||
|
if err = verifyWSLUserModeCompat(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mc.WSLHypervisor.UserModeNetworking = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const prompt = "Importing operating system into WSL (this may take a few minutes on a new WSL install)..."
|
||||||
|
dist, err := provisionWSLDist(mc.Name, mc.ImagePath.GetPath(), prompt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
unprovisionCallbackFunc := func() error {
|
||||||
|
return unprovisionWSL(mc)
|
||||||
|
}
|
||||||
|
callbackFuncs.Add(unprovisionCallbackFunc)
|
||||||
|
|
||||||
|
if mc.WSLHypervisor.UserModeNetworking {
|
||||||
|
if err = installUserModeDist(dist, mc.ImagePath.GetPath()); err != nil {
|
||||||
|
_ = unregisterDist(dist)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Configuring system...")
|
||||||
|
if err = configureSystem(mc, dist); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = installScripts(dist); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = createKeys(mc, dist); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// recycle vm
|
||||||
|
return terminateDist(dist)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) PrepareIgnition(_ *vmconfigs.MachineConfig, _ *ignition.IgnitionBuilder) (*ignition.ReadyUnitOpts, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) GetHyperVisorVMs() ([]string, error) {
|
||||||
|
vms, err := getAllWSLDistros(false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
wslVMs := make([]string, 0)
|
||||||
|
for name := range vms {
|
||||||
|
wslVMs = append(wslVMs, name)
|
||||||
|
}
|
||||||
|
return wslVMs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) MountType() vmconfigs.VolumeMountType {
|
||||||
|
//TODO implement me
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) MountVolumesToVM(mc *vmconfigs.MachineConfig, quiet bool) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) Remove(mc *vmconfigs.MachineConfig) ([]string, func() error, error) {
|
||||||
|
// Note: we could consider swapping the two conditionals
|
||||||
|
// below if we wanted to hard error on the wsl unregister
|
||||||
|
// of the vm
|
||||||
|
wslRemoveFunc := func() error {
|
||||||
|
if err := runCmdPassThrough("wsl", "--unregister", mc.Name); err != nil {
|
||||||
|
logrus.Error(err)
|
||||||
|
}
|
||||||
|
return machine.ReleaseMachinePort(mc.SSH.Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{}, wslRemoveFunc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) RemoveAndCleanMachines(_ *define.MachineDirs) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (w WSLStubber) SetProviderAttrs(mc *vmconfigs.MachineConfig, opts define.SetOptions) error {
|
||||||
|
mc.Lock()
|
||||||
|
defer mc.Unlock()
|
||||||
|
|
||||||
|
// TODO the check for running when setting rootful is something I have not
|
||||||
|
// seen in the other distributions. I wonder if this is true everywhere or just
|
||||||
|
// with WSL?
|
||||||
|
// TODO maybe the "rule" for set is that it must be done when the machine is
|
||||||
|
// stopped?
|
||||||
|
// if opts.Rootful != nil && v.Rootful != *opts.Rootful {
|
||||||
|
// err := v.setRootful(*opts.Rootful)
|
||||||
|
// if err != nil {
|
||||||
|
// setErrors = append(setErrors, fmt.Errorf("setting rootful option: %w", err))
|
||||||
|
// } else {
|
||||||
|
// if v.isRunning() {
|
||||||
|
// logrus.Warn("restart is necessary for rootful change to go into effect")
|
||||||
|
// }
|
||||||
|
// v.Rootful = *opts.Rootful
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
if opts.Rootful != nil && mc.HostUser.Rootful != *opts.Rootful {
|
||||||
|
if err := mc.SetRootful(*opts.Rootful); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.CPUs != nil {
|
||||||
|
return errors.New("changing CPUs not supported for WSL machines")
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Memory != nil {
|
||||||
|
return errors.New("changing memory not supported for WSL machines")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO USB still needs to be plumbed for all providers
|
||||||
|
// if USBs != nil {
|
||||||
|
// setErrors = append(setErrors, errors.New("changing USBs not supported for WSL machines"))
|
||||||
|
// }
|
||||||
|
|
||||||
|
if opts.DiskSize != nil {
|
||||||
|
return errors.New("changing disk size not supported for WSL machines")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO This needs to be plumbed in for set as well
|
||||||
|
//if opts.UserModeNetworking != nil && *opts.UserModeNetworking != v.UserModeNetworking {
|
||||||
|
// update := true
|
||||||
|
//
|
||||||
|
// if v.isRunning() {
|
||||||
|
// update = false
|
||||||
|
// setErrors = append(setErrors, fmt.Errorf("user-mode networking can only be changed when the machine is not running"))
|
||||||
|
// } else {
|
||||||
|
// dist := toDist(v.Name)
|
||||||
|
// if err := changeDistUserModeNetworking(dist, v.RemoteUsername, v.ImagePath, *opts.UserModeNetworking); err != nil {
|
||||||
|
// update = false
|
||||||
|
// setErrors = append(setErrors, err)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if update {
|
||||||
|
// v.UserModeNetworking = *opts.UserModeNetworking
|
||||||
|
// }
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) StartNetworking(mc *vmconfigs.MachineConfig, cmd *gvproxy.GvproxyCommand) error {
|
||||||
|
// Startup user-mode networking if enabled
|
||||||
|
if mc.WSLHypervisor.UserModeNetworking {
|
||||||
|
return startUserModeNetworking(mc)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) UserModeNetworkEnabled(mc *vmconfigs.MachineConfig) bool {
|
||||||
|
return mc.WSLHypervisor.UserModeNetworking
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
||||||
|
if mc.WSLHypervisor.UserModeNetworking {
|
||||||
|
winProxyOpts := machine.WinProxyOpts{
|
||||||
|
Name: mc.Name,
|
||||||
|
IdentityPath: mc.SSH.IdentityPath,
|
||||||
|
Port: mc.SSH.Port,
|
||||||
|
RemoteUsername: mc.SSH.RemoteUsername,
|
||||||
|
Rootful: mc.HostUser.Rootful,
|
||||||
|
VMType: w.VMType(),
|
||||||
|
}
|
||||||
|
machine.LaunchWinProxy(winProxyOpts, false)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) StartVM(mc *vmconfigs.MachineConfig) (func() error, func() error, error) {
|
||||||
|
useProxy := setupWslProxyEnv()
|
||||||
|
|
||||||
|
// TODO Quiet is hard set to false: follow up
|
||||||
|
if err := configureProxy(mc.Name, useProxy, false); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO The original code checked to see if the SSH port was actually open and re-assigned if it was
|
||||||
|
// we could consider this but it should be higher up the stack
|
||||||
|
// if !machine.IsLocalPortAvailable(v.Port) {
|
||||||
|
// logrus.Warnf("SSH port conflict detected, reassigning a new port")
|
||||||
|
// if err := v.reassignSshPort(); err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
err := wslInvoke(mc.Name, "/root/bootstrap")
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("the WSL bootstrap script failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO we dont show this for any other provider. perhaps we should ? and if
|
||||||
|
// so, we need to move it up the stack
|
||||||
|
//if !v.Rootful && !opts.NoInfo {
|
||||||
|
// fmt.Printf("\nThis machine is currently configured in rootless mode. If your containers\n")
|
||||||
|
// fmt.Printf("require root permissions (e.g. ports < 1024), or if you run into compatibility\n")
|
||||||
|
// fmt.Printf("issues with non-podman clients, you can switch using the following command: \n")
|
||||||
|
//
|
||||||
|
// suffix := ""
|
||||||
|
// if name != machine.DefaultMachineName {
|
||||||
|
// suffix = " " + name
|
||||||
|
// }
|
||||||
|
// fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
|
||||||
|
//}
|
||||||
|
|
||||||
|
readyFunc := func() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, readyFunc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) State(mc *vmconfigs.MachineConfig, bypass bool) (define.Status, error) {
|
||||||
|
running, err := isRunning(mc.Name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if running {
|
||||||
|
return define.Running, nil
|
||||||
|
}
|
||||||
|
return define.Stopped, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) StopVM(mc *vmconfigs.MachineConfig, hardStop bool) error {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
// by this time, state has been verified to be running and a request
|
||||||
|
// to stop is fair game
|
||||||
|
mc.Lock()
|
||||||
|
defer mc.Unlock()
|
||||||
|
|
||||||
|
// Stop user-mode networking if enabled
|
||||||
|
if err := stopUserModeNetworking(mc); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Could not cleanly stop user-mode networking: %s\n", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := machine.StopWinProxy(mc.Name, vmtype); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Could not stop API forwarding service (win-sshproxy.exe): %s\n", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("wsl", "-u", "root", "-d", mc.Name, "sh")
|
||||||
|
cmd.Stdin = strings.NewReader(waitTerm)
|
||||||
|
if err = cmd.Start(); err != nil {
|
||||||
|
return fmt.Errorf("executing wait command: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
exitCmd := exec.Command("wsl", "-u", "root", "-d", mc.Name, "/usr/local/bin/enterns", "systemctl", "exit", "0")
|
||||||
|
if err = exitCmd.Run(); err != nil {
|
||||||
|
return fmt.Errorf("stopping sysd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = cmd.Wait(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return terminateDist(mc.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) StopHostNetworking(mc *vmconfigs.MachineConfig, vmType define.VMType) error {
|
||||||
|
return stopUserModeNetworking(mc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) VMType() define.VMType {
|
||||||
|
return define.WSLVirt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w WSLStubber) GetDisk(_ string, dirs *define.MachineDirs, mc *vmconfigs.MachineConfig) error {
|
||||||
|
var (
|
||||||
|
myDisk ocipull.Disker
|
||||||
|
)
|
||||||
|
|
||||||
|
// check github for the latest version of the WSL dist
|
||||||
|
downloadURL, downloadVersion, _, _, err := GetFedoraDownloadForWSL()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// we now save the "cached" rootfs in the form of "v<version-number>-rootfs.tar.xz"
|
||||||
|
// i.e.v39.0.31-rootfs.tar.xz
|
||||||
|
versionedBase := fmt.Sprintf("%s-%s", downloadVersion, filepath.Base(downloadURL.Path))
|
||||||
|
|
||||||
|
// TODO we need a mechanism for "flushing" old cache files
|
||||||
|
cachedFile, err := dirs.DataDir.AppendToNewVMFile(versionedBase, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we find the same file cached (determined by filename only), then dont pull
|
||||||
|
if _, err = os.Stat(cachedFile.GetPath()); err == nil {
|
||||||
|
logrus.Debugf("%q already exists locally", cachedFile.GetPath())
|
||||||
|
myDisk, err = stdpull.NewStdDiskPull(cachedFile.GetPath(), mc.ImagePath)
|
||||||
|
} else {
|
||||||
|
// no cached file
|
||||||
|
myDisk, err = stdpull.NewDiskFromURL(downloadURL.String(), mc.ImagePath, dirs.DataDir, &versionedBase)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// up until now, nothing has really happened
|
||||||
|
// pull if needed and decompress to image location
|
||||||
|
return myDisk.Get()
|
||||||
|
}
|
@ -5,6 +5,7 @@ package wsl
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -69,8 +70,8 @@ func verifyWSLUserModeCompat() error {
|
|||||||
prefix)
|
prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) startUserModeNetworking() error {
|
func startUserModeNetworking(mc *vmconfigs.MachineConfig) error {
|
||||||
if !v.UserModeNetworking {
|
if !mc.WSLHypervisor.UserModeNetworking {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ func (v *MachineVM) startUserModeNetworking() error {
|
|||||||
return fmt.Errorf("could not locate %s, which is necessary for user-mode networking, please reinstall", gvProxy)
|
return fmt.Errorf("could not locate %s, which is necessary for user-mode networking, please reinstall", gvProxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
flock, err := v.obtainUserModeNetLock()
|
flock, err := obtainUserModeNetLock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -93,17 +94,17 @@ func (v *MachineVM) startUserModeNetworking() error {
|
|||||||
|
|
||||||
// Start or reuse
|
// Start or reuse
|
||||||
if !running {
|
if !running {
|
||||||
if err := v.launchUserModeNetDist(exe); err != nil {
|
if err := launchUserModeNetDist(exe); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := createUserModeResolvConf(toDist(v.Name)); err != nil {
|
if err := createUserModeResolvConf(mc.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register in-use
|
// Register in-use
|
||||||
err = v.addUserModeNetEntry()
|
err = addUserModeNetEntry(mc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -111,23 +112,23 @@ func (v *MachineVM) startUserModeNetworking() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) stopUserModeNetworking(dist string) error {
|
func stopUserModeNetworking(mc *vmconfigs.MachineConfig) error {
|
||||||
if !v.UserModeNetworking {
|
if !mc.WSLHypervisor.UserModeNetworking {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
flock, err := v.obtainUserModeNetLock()
|
flock, err := obtainUserModeNetLock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer flock.unlock()
|
defer flock.unlock()
|
||||||
|
|
||||||
err = v.removeUserModeNetEntry()
|
err = removeUserModeNetEntry(mc.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := v.cleanupAndCountNetEntries()
|
count, err := cleanupAndCountNetEntries()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -159,7 +160,7 @@ func isGvProxyVMRunning() bool {
|
|||||||
return wslInvoke(userModeDist, "bash", "-c", "ps -eo args | grep -q -m1 ^/usr/local/bin/vm || exit 42") == nil
|
return wslInvoke(userModeDist, "bash", "-c", "ps -eo args | grep -q -m1 ^/usr/local/bin/vm || exit 42") == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) launchUserModeNetDist(exeFile string) error {
|
func launchUserModeNetDist(exeFile string) error {
|
||||||
fmt.Println("Starting user-mode networking...")
|
fmt.Println("Starting user-mode networking...")
|
||||||
|
|
||||||
exe, err := specgen.ConvertWinMountPath(exeFile)
|
exe, err := specgen.ConvertWinMountPath(exeFile)
|
||||||
@ -220,7 +221,7 @@ func createUserModeResolvConf(dist string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) getUserModeNetDir() (string, error) {
|
func getUserModeNetDir() (string, error) {
|
||||||
vmDataDir, err := machine.GetDataDir(vmtype)
|
vmDataDir, err := machine.GetDataDir(vmtype)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -234,8 +235,8 @@ func (v *MachineVM) getUserModeNetDir() (string, error) {
|
|||||||
return dir, nil
|
return dir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) getUserModeNetEntriesDir() (string, error) {
|
func getUserModeNetEntriesDir() (string, error) {
|
||||||
netDir, err := v.getUserModeNetDir()
|
netDir, err := getUserModeNetDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -248,13 +249,13 @@ func (v *MachineVM) getUserModeNetEntriesDir() (string, error) {
|
|||||||
return dir, nil
|
return dir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) addUserModeNetEntry() error {
|
func addUserModeNetEntry(mc *vmconfigs.MachineConfig) error {
|
||||||
entriesDir, err := v.getUserModeNetEntriesDir()
|
entriesDir, err := getUserModeNetEntriesDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(entriesDir, toDist(v.Name))
|
path := filepath.Join(entriesDir, mc.Name)
|
||||||
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not add user-mode networking registration: %w", err)
|
return fmt.Errorf("could not add user-mode networking registration: %w", err)
|
||||||
@ -263,18 +264,18 @@ func (v *MachineVM) addUserModeNetEntry() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) removeUserModeNetEntry() error {
|
func removeUserModeNetEntry(name string) error {
|
||||||
entriesDir, err := v.getUserModeNetEntriesDir()
|
entriesDir, err := getUserModeNetEntriesDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
path := filepath.Join(entriesDir, toDist(v.Name))
|
path := filepath.Join(entriesDir, name)
|
||||||
return os.Remove(path)
|
return os.Remove(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) cleanupAndCountNetEntries() (uint, error) {
|
func cleanupAndCountNetEntries() (uint, error) {
|
||||||
entriesDir, err := v.getUserModeNetEntriesDir()
|
entriesDir, err := getUserModeNetEntriesDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -302,8 +303,8 @@ func (v *MachineVM) cleanupAndCountNetEntries() (uint, error) {
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *MachineVM) obtainUserModeNetLock() (*fileLock, error) {
|
func obtainUserModeNetLock() (*fileLock, error) {
|
||||||
dir, err := v.getUserModeNetDir()
|
dir, err := getUserModeNetDir()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Reference in New Issue
Block a user