mirror of
https://github.com/containers/podman.git
synced 2025-06-19 08:09:12 +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/define"
|
||||
"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/vmconfigs"
|
||||
"github.com/containers/podman/v5/utils"
|
||||
@ -38,6 +39,10 @@ type AppleHVStubber struct {
|
||||
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 {
|
||||
mc.AppleHypervisor = new(vmconfigs.AppleHVConfig)
|
||||
mc.AppleHypervisor.Vfkit = vfkit.VfkitHelper{}
|
||||
@ -317,3 +322,7 @@ func (a AppleHVStubber) PrepareIgnition(_ *vmconfigs.MachineConfig, _ *ignition.
|
||||
func (a AppleHVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
||||
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 {
|
||||
Name string
|
||||
Dirs *MachineDirs
|
||||
Name string
|
||||
Dirs *MachineDirs
|
||||
ReExec bool
|
||||
UserModeNetworking bool
|
||||
}
|
||||
|
||||
type MachineDirs struct {
|
||||
|
@ -2,6 +2,7 @@ package e2e_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containers/podman/v4/pkg/machine/wsl"
|
||||
"io"
|
||||
url2 "net/url"
|
||||
"os"
|
||||
@ -61,9 +62,20 @@ var _ = BeforeSuite(func() {
|
||||
|
||||
downloadLocation := os.Getenv("MACHINE_IMAGE")
|
||||
if downloadLocation == "" {
|
||||
downloadLocation, err = GetDownload(testProvider.VMType())
|
||||
if err != nil {
|
||||
Fail("unable to derive download disk from fedora coreos")
|
||||
// TODO so beautifully gross ... ideally we can spend some time
|
||||
// here making life easier on the next person
|
||||
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 {
|
||||
Skip("Test is only for WSL")
|
||||
}
|
||||
// TODO - this currently fails
|
||||
Skip("test fails bc usermode network needs plumbing for WSL")
|
||||
|
||||
name := randomString()
|
||||
i := new(initMachine)
|
||||
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/podman/v5/pkg/machine/shim/diskpull"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/containers/common/pkg/strongunits"
|
||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||
@ -27,6 +29,10 @@ type HyperVStubber struct {
|
||||
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 {
|
||||
var (
|
||||
err error
|
||||
@ -459,6 +465,10 @@ func (h HyperVStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
||||
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 {
|
||||
resize := exec.Command("powershell", []string{"-command", fmt.Sprintf("Resize-VHD %s %d", imagePath.GetPath(), newSize.ToBytes())}...)
|
||||
logrus.Debug(resize.Args)
|
||||
|
@ -134,6 +134,13 @@ func launchWinProxy(opts WinProxyOpts) (bool, string, error) {
|
||||
|
||||
cmd := exec.Command(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 {
|
||||
return globalName, "", err
|
||||
}
|
||||
|
@ -2,9 +2,11 @@ package provider
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||
"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/podman/v5/pkg/machine/define"
|
||||
"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())
|
||||
switch resolvedVMType {
|
||||
// TODO re-enable this with WSL
|
||||
//case define.WSLVirt:
|
||||
// return wsl.VirtualizationProvider(), nil
|
||||
case define.WSLVirt:
|
||||
return new(wsl.WSLStubber), nil
|
||||
case define.HyperVVirt:
|
||||
return new(hyperv.HyperVStubber), nil
|
||||
default:
|
||||
|
@ -11,14 +11,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v5/pkg/machine/ignition"
|
||||
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/containers/common/pkg/strongunits"
|
||||
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/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/vmconfigs"
|
||||
"github.com/sirupsen/logrus"
|
||||
@ -30,6 +30,10 @@ type QEMUStubber struct {
|
||||
Command command.QemuCmd
|
||||
}
|
||||
|
||||
func (q QEMUStubber) UserModeNetworkEnabled(*vmconfigs.MachineConfig) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (q *QEMUStubber) setQEMUCommandLine(mc *vmconfigs.MachineConfig) error {
|
||||
qemuBinary, err := findQEMUBinary()
|
||||
if err != nil {
|
||||
@ -326,3 +330,7 @@ func (q *QEMUStubber) MountType() vmconfigs.VolumeMountType {
|
||||
func (q *QEMUStubber) PostStartNetworking(mc *vmconfigs.MachineConfig) error {
|
||||
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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/common/pkg/util"
|
||||
@ -14,30 +12,13 @@ import (
|
||||
"github.com/containers/podman/v5/pkg/machine/connection"
|
||||
machineDefine "github.com/containers/podman/v5/pkg/machine/define"
|
||||
"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/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
|
||||
// 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 (
|
||||
lrs []*machine.ListResponse
|
||||
)
|
||||
@ -114,6 +95,10 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
||||
Dirs: dirs,
|
||||
}
|
||||
|
||||
if umn := opts.UserModeNetworking; umn != nil {
|
||||
createOpts.UserModeNetworking = *umn
|
||||
}
|
||||
|
||||
// Get Image
|
||||
// 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
|
||||
@ -137,8 +122,7 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var mydisk ocipull.Disker
|
||||
mc.ImagePath = imagePath
|
||||
|
||||
// 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.
|
||||
@ -149,25 +133,12 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
||||
// "/path
|
||||
// "docker://quay.io/something/someManifest
|
||||
|
||||
if opts.ImagePath == "" {
|
||||
mydisk, err = ocipull.NewVersioned(context.Background(), dirs.DataDir, opts.Name, mp.VMType().String(), imagePath)
|
||||
} 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()
|
||||
// TODO Ideally this changes into some way better ...
|
||||
err = mp.GetDisk(opts.ImagePath, dirs, mc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mc.ImagePath = imagePath
|
||||
callbackFuncs.Add(mc.ImagePath.Delete)
|
||||
|
||||
logrus.Debugf("--> imagePath is %q", imagePath.GetPath())
|
||||
@ -182,8 +153,18 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
||||
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{
|
||||
Name: opts.Username,
|
||||
Name: userName,
|
||||
Key: sshKey,
|
||||
TimeZone: opts.TimeZone,
|
||||
UID: uid,
|
||||
@ -223,7 +204,9 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) (*vmconfigs.M
|
||||
ignBuilder.WithUnit(readyUnit)
|
||||
|
||||
// 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
|
||||
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
|
||||
gvproxyPidFile, err := dirs.RuntimeDir.AppendToNewVMFile("gvproxy.pid", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := machine.CleanupGVProxy(*gvproxyPidFile); err != nil {
|
||||
logrus.Errorf("unable to clean up gvproxy: %q", err)
|
||||
if mp.UserModeNetworkEnabled(mc) {
|
||||
gvproxyPidFile, err := dirs.RuntimeDir.AppendToNewVMFile("gvproxy.pid", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
if err := machine.CleanupGVProxy(*gvproxyPidFile); err != nil {
|
||||
logrus.Errorf("unable to clean up gvproxy: %q", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
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
|
||||
maxBackoffs := 6
|
||||
|
||||
|
@ -23,16 +23,12 @@ const (
|
||||
dockerConnectTimeout = 5 * time.Second
|
||||
)
|
||||
|
||||
func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider) (string, machine.APIForwardingState, error) {
|
||||
var (
|
||||
forwardingState machine.APIForwardingState
|
||||
forwardSock string
|
||||
)
|
||||
// the guestSock is "inside" the guest machine
|
||||
guestSock := fmt.Sprintf(defaultGuestSock, mc.HostUser.UID)
|
||||
func startUserModeNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider, dirs *define.MachineDirs, hostSocket *define.VMFile) error {
|
||||
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 {
|
||||
guestSock = "/run/podman/podman.sock"
|
||||
forwardUser = "root"
|
||||
@ -40,38 +36,18 @@ func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider)
|
||||
|
||||
cfg, err := config.Default()
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
return err
|
||||
}
|
||||
|
||||
binary, err := cfg.FindHelperBinary(machine.ForwarderBinaryName, false)
|
||||
if err != nil {
|
||||
return "", 0, 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
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := gvproxy.NewGvproxyCommand()
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// add in any provider specific options for gvproxy
|
||||
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
|
||||
}
|
||||
|
||||
@ -101,21 +107,15 @@ func startNetworking(mc *vmconfigs.MachineConfig, provider vmconfigs.VMProvider)
|
||||
forwardSock, forwardingState = setupAPIForwarding(hostSocket, linkSocket)
|
||||
}
|
||||
|
||||
c := cmd.Cmd(binary)
|
||||
|
||||
logrus.Debugf("gvproxy command-line: %s %s", binary, strings.Join(cmd.ToCmdline(), " "))
|
||||
if err := c.Start(); err != nil {
|
||||
return forwardSock, 0, fmt.Errorf("unable to execute: %q: %w", cmd.ToCmdline(), err)
|
||||
if provider.UserModeNetworkEnabled(mc) {
|
||||
if err := startUserModeNetworking(mc, provider, dirs, hostSocket); err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return forwardSock, forwardingState, nil
|
||||
}
|
||||
|
||||
type apiOptions struct { //nolint:unused
|
||||
socketpath, destinationSocketPath *define.VMFile
|
||||
fowardUser string
|
||||
}
|
||||
|
||||
func setupAPIForwarding(hostSocket, linkSocket *define.VMFile) (string, machine.APIForwardingState) {
|
||||
// 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
|
||||
|
@ -23,7 +23,7 @@ type DiskFromURL struct {
|
||||
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 (
|
||||
err error
|
||||
)
|
||||
@ -40,6 +40,9 @@ func NewDiskFromURL(inputPath string, finalPath *define.VMFile, tempDir *define.
|
||||
}
|
||||
|
||||
remoteImageName := path.Base(inputPath)
|
||||
if optionalTempFileName != nil {
|
||||
remoteImageName = *optionalTempFileName
|
||||
}
|
||||
if remoteImageName == "" {
|
||||
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
|
||||
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)
|
||||
GetHyperVisorVMs() ([]string, error)
|
||||
MountType() VolumeMountType
|
||||
@ -121,6 +125,7 @@ type VMProvider interface { //nolint:interfacebloat
|
||||
StopVM(mc *MachineConfig, hardStop bool) error
|
||||
StopHostNetworking(mc *MachineConfig, vmType define.VMType) error
|
||||
VMType() define.VMType
|
||||
UserModeNetworkEnabled(mc *MachineConfig) bool
|
||||
}
|
||||
|
||||
// HostUser describes the host user
|
||||
|
@ -13,7 +13,8 @@ type HyperVConfig struct {
|
||||
}
|
||||
|
||||
type WSLConfig struct {
|
||||
//wslstuff *aThing
|
||||
// Uses usermode networking
|
||||
UserModeNetworking bool
|
||||
}
|
||||
|
||||
// Stubs
|
||||
|
@ -77,6 +77,7 @@ func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIden
|
||||
}
|
||||
mc.Resources = mrc
|
||||
|
||||
// TODO WSL had a locking port mechanism, we should consider this.
|
||||
sshPort, err := utils.GetRandomPort()
|
||||
if err != nil {
|
||||
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
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/sirupsen/logrus"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -27,8 +26,10 @@ type FedoraDownload struct {
|
||||
machine.Download
|
||||
}
|
||||
|
||||
// NewFedoraDownloader
|
||||
// deprecated
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@ -82,7 +83,7 @@ func (f FedoraDownload) CleanCache() error {
|
||||
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
|
||||
arch := machine.DetermineMachineArch()
|
||||
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)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
bytes, err := io.ReadAll(&io.LimitedReader{R: resp.Body, N: 1024})
|
||||
defer func() {
|
||||
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 {
|
||||
return nil, "", "", -1, fmt.Errorf("failed reading: %s: %w", verURL.String(), err)
|
||||
}
|
||||
|
||||
return downloadURL, strings.TrimSpace(string(bytes)), arch, contentLen, nil
|
||||
return downloadURL, strings.TrimSpace(string(b)), 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -69,8 +70,8 @@ func verifyWSLUserModeCompat() error {
|
||||
prefix)
|
||||
}
|
||||
|
||||
func (v *MachineVM) startUserModeNetworking() error {
|
||||
if !v.UserModeNetworking {
|
||||
func startUserModeNetworking(mc *vmconfigs.MachineConfig) error {
|
||||
if !mc.WSLHypervisor.UserModeNetworking {
|
||||
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)
|
||||
}
|
||||
|
||||
flock, err := v.obtainUserModeNetLock()
|
||||
flock, err := obtainUserModeNetLock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -93,17 +94,17 @@ func (v *MachineVM) startUserModeNetworking() error {
|
||||
|
||||
// Start or reuse
|
||||
if !running {
|
||||
if err := v.launchUserModeNetDist(exe); err != nil {
|
||||
if err := launchUserModeNetDist(exe); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := createUserModeResolvConf(toDist(v.Name)); err != nil {
|
||||
if err := createUserModeResolvConf(mc.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Register in-use
|
||||
err = v.addUserModeNetEntry()
|
||||
err = addUserModeNetEntry(mc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -111,23 +112,23 @@ func (v *MachineVM) startUserModeNetworking() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *MachineVM) stopUserModeNetworking(dist string) error {
|
||||
if !v.UserModeNetworking {
|
||||
func stopUserModeNetworking(mc *vmconfigs.MachineConfig) error {
|
||||
if !mc.WSLHypervisor.UserModeNetworking {
|
||||
return nil
|
||||
}
|
||||
|
||||
flock, err := v.obtainUserModeNetLock()
|
||||
flock, err := obtainUserModeNetLock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer flock.unlock()
|
||||
|
||||
err = v.removeUserModeNetEntry()
|
||||
err = removeUserModeNetEntry(mc.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
count, err := v.cleanupAndCountNetEntries()
|
||||
count, err := cleanupAndCountNetEntries()
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
func (v *MachineVM) launchUserModeNetDist(exeFile string) error {
|
||||
func launchUserModeNetDist(exeFile string) error {
|
||||
fmt.Println("Starting user-mode networking...")
|
||||
|
||||
exe, err := specgen.ConvertWinMountPath(exeFile)
|
||||
@ -220,7 +221,7 @@ func createUserModeResolvConf(dist string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (v *MachineVM) getUserModeNetDir() (string, error) {
|
||||
func getUserModeNetDir() (string, error) {
|
||||
vmDataDir, err := machine.GetDataDir(vmtype)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -234,8 +235,8 @@ func (v *MachineVM) getUserModeNetDir() (string, error) {
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
func (v *MachineVM) getUserModeNetEntriesDir() (string, error) {
|
||||
netDir, err := v.getUserModeNetDir()
|
||||
func getUserModeNetEntriesDir() (string, error) {
|
||||
netDir, err := getUserModeNetDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -248,13 +249,13 @@ func (v *MachineVM) getUserModeNetEntriesDir() (string, error) {
|
||||
return dir, nil
|
||||
}
|
||||
|
||||
func (v *MachineVM) addUserModeNetEntry() error {
|
||||
entriesDir, err := v.getUserModeNetEntriesDir()
|
||||
func addUserModeNetEntry(mc *vmconfigs.MachineConfig) error {
|
||||
entriesDir, err := getUserModeNetEntriesDir()
|
||||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not add user-mode networking registration: %w", err)
|
||||
@ -263,18 +264,18 @@ func (v *MachineVM) addUserModeNetEntry() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *MachineVM) removeUserModeNetEntry() error {
|
||||
entriesDir, err := v.getUserModeNetEntriesDir()
|
||||
func removeUserModeNetEntry(name string) error {
|
||||
entriesDir, err := getUserModeNetEntriesDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
path := filepath.Join(entriesDir, toDist(v.Name))
|
||||
path := filepath.Join(entriesDir, name)
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
||||
func (v *MachineVM) cleanupAndCountNetEntries() (uint, error) {
|
||||
entriesDir, err := v.getUserModeNetEntriesDir()
|
||||
func cleanupAndCountNetEntries() (uint, error) {
|
||||
entriesDir, err := getUserModeNetEntriesDir()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -302,8 +303,8 @@ func (v *MachineVM) cleanupAndCountNetEntries() (uint, error) {
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (v *MachineVM) obtainUserModeNetLock() (*fileLock, error) {
|
||||
dir, err := v.getUserModeNetDir()
|
||||
func obtainUserModeNetLock() (*fileLock, error) {
|
||||
dir, err := getUserModeNetDir()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
Reference in New Issue
Block a user