mirror of
https://github.com/containers/podman.git
synced 2025-06-19 08:09:12 +08:00
Add API forwarding support for HyperV
Provides Docker API client access, allowing compose to work by default for HyperV. Basically the HyperV equiv of the work done here by #12916. [NO NEW TESTS NEEDED] Signed-off-by: Ashley Cui <acui@redhat.com>
This commit is contained in:
@ -187,7 +187,7 @@ func composeDockerHost() (string, error) {
|
|||||||
if info.State != define.Running {
|
if info.State != define.Running {
|
||||||
return "", fmt.Errorf("machine %s is not running but in state %s", item.Name, info.State)
|
return "", fmt.Errorf("machine %s is not running but in state %s", item.Name, info.State)
|
||||||
}
|
}
|
||||||
if machineProvider.VMType() == define.WSLVirt {
|
if machineProvider.VMType() == define.WSLVirt || machineProvider.VMType() == define.HyperVVirt {
|
||||||
if info.ConnectionInfo.PodmanPipe == nil {
|
if info.ConnectionInfo.PodmanPipe == nil {
|
||||||
return "", errors.New("pipe of machine is not set")
|
return "", errors.New("pipe of machine is not set")
|
||||||
}
|
}
|
||||||
|
@ -343,11 +343,14 @@ func (m *HyperVMachine) Inspect() (*machine.InspectInfo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
machinePipe := machine.ToDist(m.Name)
|
||||||
|
podmanPipe := &define.VMFile{Path: `\\.\pipe\` + machinePipe}
|
||||||
|
|
||||||
return &machine.InspectInfo{
|
return &machine.InspectInfo{
|
||||||
ConfigPath: m.ConfigPath,
|
ConfigPath: m.ConfigPath,
|
||||||
ConnectionInfo: machine.ConnectionConfig{
|
ConnectionInfo: machine.ConnectionConfig{
|
||||||
PodmanSocket: podmanSocket,
|
PodmanSocket: podmanSocket,
|
||||||
|
PodmanPipe: podmanPipe,
|
||||||
},
|
},
|
||||||
Created: m.Created,
|
Created: m.Created,
|
||||||
Image: machine.ImageConfig{
|
Image: machine.ImageConfig{
|
||||||
@ -592,6 +595,15 @@ func (m *HyperVMachine) Start(name string, opts machine.StartOptions) error {
|
|||||||
m.HostUser.Modified = false
|
m.HostUser.Modified = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
winProxyOpts := machine.WinProxyOpts{
|
||||||
|
Name: m.Name,
|
||||||
|
IdentityPath: m.IdentityPath,
|
||||||
|
Port: m.Port,
|
||||||
|
RemoteUsername: m.RemoteUsername,
|
||||||
|
Rootful: m.Rootful,
|
||||||
|
VMType: vmtype,
|
||||||
|
}
|
||||||
|
machine.LaunchWinProxy(winProxyOpts, opts.NoInfo)
|
||||||
|
|
||||||
// Write the config with updated starting status and hostuser modification
|
// Write the config with updated starting status and hostuser modification
|
||||||
if err := m.writeConfig(); err != nil {
|
if err := m.writeConfig(); err != nil {
|
||||||
@ -653,6 +665,10 @@ func (m *HyperVMachine) Stop(name string, opts machine.StopOptions) error {
|
|||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := machine.StopWinProxy(m.Name, vmtype); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Could not stop API forwarding service (win-sshproxy.exe): %s\n", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
if err := vm.Stop(); err != nil {
|
if err := vm.Stop(); err != nil {
|
||||||
return fmt.Errorf("stopping virtual machine: %w", err)
|
return fmt.Errorf("stopping virtual machine: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,38 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v4/pkg/machine/define"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
pipePrefix = "npipe:////./pipe/"
|
||||||
|
globalPipe = "docker_engine"
|
||||||
|
winSShProxy = "win-sshproxy.exe"
|
||||||
|
winSshProxyTid = "win-sshproxy.tid"
|
||||||
|
rootfulSock = "/run/podman/podman.sock"
|
||||||
|
rootlessSock = "/run/user/1000/podman/podman.sock"
|
||||||
|
)
|
||||||
|
|
||||||
|
const WM_QUIT = 0x12 //nolint
|
||||||
|
|
||||||
|
type WinProxyOpts struct {
|
||||||
|
Name string
|
||||||
|
IdentityPath string
|
||||||
|
Port int
|
||||||
|
RemoteUsername string
|
||||||
|
Rootful bool
|
||||||
|
VMType define.VMType
|
||||||
|
}
|
||||||
|
|
||||||
func GetProcessState(pid int) (active bool, exitCode int) {
|
func GetProcessState(pid int) (active bool, exitCode int) {
|
||||||
const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
|
const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
|
||||||
handle, err := syscall.OpenProcess(da, false, uint32(pid))
|
handle, err := syscall.OpenProcess(da, false, uint32(pid))
|
||||||
@ -45,3 +70,172 @@ func WaitPipeExists(pipeName string, retries int, checkFailure func() error) err
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LaunchWinProxy(opts WinProxyOpts, noInfo bool) {
|
||||||
|
globalName, pipeName, err := launchWinProxy(opts)
|
||||||
|
if !noInfo {
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, "API forwarding for Docker API clients is not available due to the following startup failures.")
|
||||||
|
fmt.Fprintf(os.Stderr, "\t%s\n", err.Error())
|
||||||
|
fmt.Fprintln(os.Stderr, "\nPodman clients are still able to connect.")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("API forwarding listening on: %s\n", pipeName)
|
||||||
|
if globalName {
|
||||||
|
fmt.Printf("\nDocker API clients default to this address. You do not need to set DOCKER_HOST.\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("\nAnother process was listening on the default Docker API pipe address.\n")
|
||||||
|
fmt.Printf("You can still connect Docker API clients by setting DOCKER HOST using the\n")
|
||||||
|
fmt.Printf("following powershell command in your terminal session:\n")
|
||||||
|
fmt.Printf("\n\t$Env:DOCKER_HOST = '%s'\n", pipeName)
|
||||||
|
fmt.Printf("\nOr in a classic CMD prompt:\n")
|
||||||
|
fmt.Printf("\n\tset DOCKER_HOST=%s\n", pipeName)
|
||||||
|
fmt.Printf("\nAlternatively, terminate the other process and restart podman machine.\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func launchWinProxy(opts WinProxyOpts) (bool, string, error) {
|
||||||
|
machinePipe := ToDist(opts.Name)
|
||||||
|
if !PipeNameAvailable(machinePipe) {
|
||||||
|
return false, "", fmt.Errorf("could not start api proxy since expected pipe is not available: %s", machinePipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
globalName := false
|
||||||
|
if PipeNameAvailable(globalPipe) {
|
||||||
|
globalName = true
|
||||||
|
}
|
||||||
|
|
||||||
|
command, err := FindExecutablePeer(winSShProxy)
|
||||||
|
if err != nil {
|
||||||
|
return globalName, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
stateDir, err := GetWinProxyStateDir(opts.Name, opts.VMType)
|
||||||
|
if err != nil {
|
||||||
|
return globalName, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
destSock := rootlessSock
|
||||||
|
forwardUser := opts.RemoteUsername
|
||||||
|
|
||||||
|
if opts.Rootful {
|
||||||
|
destSock = rootfulSock
|
||||||
|
forwardUser = "root"
|
||||||
|
}
|
||||||
|
|
||||||
|
dest := fmt.Sprintf("ssh://%s@localhost:%d%s", forwardUser, opts.Port, destSock)
|
||||||
|
args := []string{opts.Name, stateDir, pipePrefix + machinePipe, dest, opts.IdentityPath}
|
||||||
|
waitPipe := machinePipe
|
||||||
|
if globalName {
|
||||||
|
args = append(args, pipePrefix+globalPipe, dest, opts.IdentityPath)
|
||||||
|
waitPipe = globalPipe
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(command, args...)
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return globalName, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return globalName, pipePrefix + waitPipe, WaitPipeExists(waitPipe, 80, func() error {
|
||||||
|
active, exitCode := GetProcessState(cmd.Process.Pid)
|
||||||
|
if !active {
|
||||||
|
return fmt.Errorf("win-sshproxy.exe failed to start, exit code: %d (see windows event logs)", exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopWinProxy(name string, vmtype define.VMType) error {
|
||||||
|
pid, tid, tidFile, err := readWinProxyTid(name, vmtype)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
proc, err := os.FindProcess(int(pid))
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sendQuit(tid)
|
||||||
|
_ = waitTimeout(proc, 20*time.Second)
|
||||||
|
_ = os.Remove(tidFile)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readWinProxyTid(name string, vmtype define.VMType) (uint32, uint32, string, error) {
|
||||||
|
stateDir, err := GetWinProxyStateDir(name, vmtype)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
tidFile := filepath.Join(stateDir, winSshProxyTid)
|
||||||
|
contents, err := os.ReadFile(tidFile)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pid, tid uint32
|
||||||
|
fmt.Sscanf(string(contents), "%d:%d", &pid, &tid)
|
||||||
|
return pid, tid, tidFile, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitTimeout(proc *os.Process, timeout time.Duration) bool {
|
||||||
|
done := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
proc.Wait()
|
||||||
|
done <- true
|
||||||
|
}()
|
||||||
|
ret := false
|
||||||
|
select {
|
||||||
|
case <-time.After(timeout):
|
||||||
|
proc.Kill()
|
||||||
|
<-done
|
||||||
|
case <-done:
|
||||||
|
ret = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendQuit(tid uint32) {
|
||||||
|
user32 := syscall.NewLazyDLL("user32.dll")
|
||||||
|
postMessage := user32.NewProc("PostThreadMessageW")
|
||||||
|
postMessage.Call(uintptr(tid), WM_QUIT, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindExecutablePeer(name string) (string, error) {
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
exe, err = filepath.EvalSymlinks(exe)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(filepath.Dir(exe), name), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetWinProxyStateDir(name string, vmtype define.VMType) (string, error) {
|
||||||
|
dir, err := GetDataDir(vmtype)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
stateDir := filepath.Join(dir, name)
|
||||||
|
if err = os.MkdirAll(stateDir, 0755); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return stateDir, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToDist(name string) string {
|
||||||
|
if !strings.HasPrefix(name, "podman") {
|
||||||
|
name = "podman-" + name
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
@ -273,14 +273,13 @@ http://docs.microsoft.com/en-us/windows/wsl/install\
|
|||||||
`
|
`
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gvProxy = "gvproxy.exe"
|
gvProxy = "gvproxy.exe"
|
||||||
winSShProxy = "win-sshproxy.exe"
|
winSShProxy = "win-sshproxy.exe"
|
||||||
winSshProxyTid = "win-sshproxy.tid"
|
pipePrefix = "npipe:////./pipe/"
|
||||||
pipePrefix = "npipe:////./pipe/"
|
globalPipe = "docker_engine"
|
||||||
globalPipe = "docker_engine"
|
userModeDist = "podman-net-usermode"
|
||||||
userModeDist = "podman-net-usermode"
|
rootfulSock = "/run/podman/podman.sock"
|
||||||
rootfulSock = "/run/podman/podman.sock"
|
rootlessSock = "/run/user/1000/podman/podman.sock"
|
||||||
rootlessSock = "/run/user/1000/podman/podman.sock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MachineVM struct {
|
type MachineVM struct {
|
||||||
@ -1208,28 +1207,15 @@ func (v *MachineVM) Start(name string, opts machine.StartOptions) error {
|
|||||||
}
|
}
|
||||||
fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
|
fmt.Printf("\n\tpodman machine set --rootful%s\n\n", suffix)
|
||||||
}
|
}
|
||||||
|
winProxyOpts := machine.WinProxyOpts{
|
||||||
globalName, pipeName, err := launchWinProxy(v)
|
Name: v.Name,
|
||||||
if !opts.NoInfo {
|
IdentityPath: v.IdentityPath,
|
||||||
if err != nil {
|
Port: v.Port,
|
||||||
fmt.Fprintln(os.Stderr, "API forwarding for Docker API clients is not available due to the following startup failures.")
|
RemoteUsername: v.RemoteUsername,
|
||||||
fmt.Fprintf(os.Stderr, "\t%s\n", err.Error())
|
Rootful: v.Rootful,
|
||||||
fmt.Fprintln(os.Stderr, "\nPodman clients are still able to connect.")
|
VMType: vmtype,
|
||||||
} else {
|
|
||||||
fmt.Printf("API forwarding listening on: %s\n", pipeName)
|
|
||||||
if globalName {
|
|
||||||
fmt.Printf("\nDocker API clients default to this address. You do not need to set DOCKER_HOST.\n")
|
|
||||||
} else {
|
|
||||||
fmt.Printf("\nAnother process was listening on the default Docker API pipe address.\n")
|
|
||||||
fmt.Printf("You can still connect Docker API clients by setting DOCKER HOST using the\n")
|
|
||||||
fmt.Printf("following powershell command in your terminal session:\n")
|
|
||||||
fmt.Printf("\n\t$Env:DOCKER_HOST = '%s'\n", pipeName)
|
|
||||||
fmt.Printf("\nOr in a classic CMD prompt:\n")
|
|
||||||
fmt.Printf("\n\tset DOCKER_HOST=%s\n", pipeName)
|
|
||||||
fmt.Printf("\nAlternatively, terminate the other process and restart podman machine.\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
machine.LaunchWinProxy(winProxyOpts, opts.NoInfo)
|
||||||
|
|
||||||
_, _, err = v.updateTimeStamps(true)
|
_, _, err = v.updateTimeStamps(true)
|
||||||
return err
|
return err
|
||||||
@ -1303,85 +1289,6 @@ func (v *MachineVM) reassignSshPort() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findExecutablePeer(name string) (string, error) {
|
|
||||||
exe, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
exe, err = filepath.EvalSymlinks(exe)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return filepath.Join(filepath.Dir(exe), name), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func launchWinProxy(v *MachineVM) (bool, string, error) {
|
|
||||||
machinePipe := toDist(v.Name)
|
|
||||||
if !machine.PipeNameAvailable(machinePipe) {
|
|
||||||
return false, "", fmt.Errorf("could not start api proxy since expected pipe is not available: %s", machinePipe)
|
|
||||||
}
|
|
||||||
|
|
||||||
globalName := false
|
|
||||||
if machine.PipeNameAvailable(globalPipe) {
|
|
||||||
globalName = true
|
|
||||||
}
|
|
||||||
|
|
||||||
command, err := findExecutablePeer(winSShProxy)
|
|
||||||
if err != nil {
|
|
||||||
return globalName, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
stateDir, err := getWinProxyStateDir(v)
|
|
||||||
if err != nil {
|
|
||||||
return globalName, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
destSock := rootlessSock
|
|
||||||
forwardUser := v.RemoteUsername
|
|
||||||
|
|
||||||
if v.Rootful {
|
|
||||||
destSock = rootfulSock
|
|
||||||
forwardUser = "root"
|
|
||||||
}
|
|
||||||
|
|
||||||
dest := fmt.Sprintf("ssh://%s@localhost:%d%s", forwardUser, v.Port, destSock)
|
|
||||||
args := []string{v.Name, stateDir, pipePrefix + machinePipe, dest, v.IdentityPath}
|
|
||||||
waitPipe := machinePipe
|
|
||||||
if globalName {
|
|
||||||
args = append(args, pipePrefix+globalPipe, dest, v.IdentityPath)
|
|
||||||
waitPipe = globalPipe
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command(command, args...)
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return globalName, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return globalName, pipePrefix + waitPipe, machine.WaitPipeExists(waitPipe, 80, func() error {
|
|
||||||
active, exitCode := machine.GetProcessState(cmd.Process.Pid)
|
|
||||||
if !active {
|
|
||||||
return fmt.Errorf("win-sshproxy.exe failed to start, exit code: %d (see windows event logs)", exitCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getWinProxyStateDir(v *MachineVM) (string, error) {
|
|
||||||
dir, err := machine.GetDataDir(vmtype)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
stateDir := filepath.Join(dir, v.Name)
|
|
||||||
if err = os.MkdirAll(stateDir, 0755); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return stateDir, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsWSLFeatureEnabled() bool {
|
func IsWSLFeatureEnabled() bool {
|
||||||
return wutil.SilentExec("wsl", "--set-default-version", "2") == nil
|
return wutil.SilentExec("wsl", "--set-default-version", "2") == nil
|
||||||
}
|
}
|
||||||
@ -1487,7 +1394,7 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
|
|||||||
|
|
||||||
_, _, _ = v.updateTimeStamps(true)
|
_, _, _ = v.updateTimeStamps(true)
|
||||||
|
|
||||||
if err := stopWinProxy(v); err != nil {
|
if err := machine.StopWinProxy(v.Name, vmtype); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Could not stop API forwarding service (win-sshproxy.exe): %s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "Could not stop API forwarding service (win-sshproxy.exe): %s\n", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1527,59 +1434,6 @@ func (v *MachineVM) State(bypass bool) (define.Status, error) {
|
|||||||
return define.Stopped, nil
|
return define.Stopped, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func stopWinProxy(v *MachineVM) error {
|
|
||||||
pid, tid, tidFile, err := readWinProxyTid(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
proc, err := os.FindProcess(int(pid))
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
sendQuit(tid)
|
|
||||||
_ = waitTimeout(proc, 20*time.Second)
|
|
||||||
_ = os.Remove(tidFile)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func waitTimeout(proc *os.Process, timeout time.Duration) bool {
|
|
||||||
done := make(chan bool)
|
|
||||||
go func() {
|
|
||||||
proc.Wait()
|
|
||||||
done <- true
|
|
||||||
}()
|
|
||||||
ret := false
|
|
||||||
select {
|
|
||||||
case <-time.After(timeout):
|
|
||||||
proc.Kill()
|
|
||||||
<-done
|
|
||||||
case <-done:
|
|
||||||
ret = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
func readWinProxyTid(v *MachineVM) (uint32, uint32, string, error) {
|
|
||||||
stateDir, err := getWinProxyStateDir(v)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
tidFile := filepath.Join(stateDir, winSshProxyTid)
|
|
||||||
contents, err := os.ReadFile(tidFile)
|
|
||||||
if err != nil {
|
|
||||||
return 0, 0, "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var pid, tid uint32
|
|
||||||
fmt.Sscanf(string(contents), "%d:%d", &pid, &tid)
|
|
||||||
return pid, tid, tidFile, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint:cyclop
|
//nolint:cyclop
|
||||||
func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, func() error, error) {
|
func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, func() error, error) {
|
||||||
var files []string
|
var files []string
|
||||||
|
@ -74,7 +74,7 @@ func (v *MachineVM) startUserModeNetworking() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
exe, err := findExecutablePeer(gvProxy)
|
exe, err := machine.FindExecutablePeer(gvProxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,6 @@ const (
|
|||||||
TOKEN_QUERY = 0x0008
|
TOKEN_QUERY = 0x0008
|
||||||
SE_PRIVILEGE_ENABLED = 0x00000002
|
SE_PRIVILEGE_ENABLED = 0x00000002
|
||||||
SE_ERR_ACCESSDENIED = 0x05
|
SE_ERR_ACCESSDENIED = 0x05
|
||||||
WM_QUIT = 0x12
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func winVersionAtLeast(major uint, minor uint, build uint) bool {
|
func winVersionAtLeast(major uint, minor uint, build uint) bool {
|
||||||
@ -337,9 +336,3 @@ func buildCommandArgs(elevate bool) string {
|
|||||||
}
|
}
|
||||||
return strings.Join(args, " ")
|
return strings.Join(args, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendQuit(tid uint32) {
|
|
||||||
user32 := syscall.NewLazyDLL("user32.dll")
|
|
||||||
postMessage := user32.NewProc("PostThreadMessageW")
|
|
||||||
postMessage.Call(uintptr(tid), WM_QUIT, 0, 0)
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user