aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorJason T. Greene <jason.greene@redhat.com>2022-08-30 23:23:14 -0500
committerJason T. Greene <jason.greene@redhat.com>2022-09-06 16:12:09 -0500
commitecb9f99b88f11556f3c5c3a890c130b16ea6f254 (patch)
tree297c9fa207752c7aaab93c4ac70e840f0c7d0a48 /cmd
parentf4c39df25e643957d9df3bca9536f18451381662 (diff)
downloadpodman-ecb9f99b88f11556f3c5c3a890c130b16ea6f254.tar.gz
podman-ecb9f99b88f11556f3c5c3a890c130b16ea6f254.tar.bz2
podman-ecb9f99b88f11556f3c5c3a890c130b16ea6f254.zip
Add new windows installer and build
Signed-off-by: Jason T. Greene <jason.greene@redhat.com>
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman-msihooks/main.go46
-rw-r--r--cmd/podman-wslkerninst/event-hook.go73
-rw-r--r--cmd/podman-wslkerninst/main.go103
3 files changed, 222 insertions, 0 deletions
diff --git a/cmd/podman-msihooks/main.go b/cmd/podman-msihooks/main.go
new file mode 100644
index 000000000..903c91abb
--- /dev/null
+++ b/cmd/podman-msihooks/main.go
@@ -0,0 +1,46 @@
+//go:build windows
+// +build windows
+
+package main
+
+import (
+ "C"
+ "syscall"
+ "unsafe"
+
+ "github.com/containers/podman/v4/pkg/machine/wsl"
+)
+
+const KernelWarning = "WSL Kernel installation did not complete successfully. " +
+ "Podman machine will attempt to install this at a later time. " +
+ "You can also manually complete the installation using the " +
+ "\"wsl --update\" command."
+
+//export CheckWSL
+func CheckWSL(hInstall uint32) uint32 {
+ installed := wsl.IsWSLInstalled()
+ feature := wsl.IsWSLFeatureEnabled()
+ setMsiProperty(hInstall, "HAS_WSL", strBool(installed))
+ setMsiProperty(hInstall, "HAS_WSLFEATURE", strBool(feature))
+
+ return 0
+}
+
+func setMsiProperty(hInstall uint32, name string, value string) {
+ nameW, _ := syscall.UTF16PtrFromString(name)
+ valueW, _ := syscall.UTF16PtrFromString(value)
+
+ msi := syscall.NewLazyDLL("msi")
+ proc := msi.NewProc("MsiSetPropertyW")
+ _, _, _ = proc.Call(uintptr(hInstall), uintptr(unsafe.Pointer(nameW)), uintptr(unsafe.Pointer(valueW)))
+
+}
+func strBool(val bool) string {
+ if val {
+ return "1"
+ }
+
+ return "0"
+}
+
+func main() {}
diff --git a/cmd/podman-wslkerninst/event-hook.go b/cmd/podman-wslkerninst/event-hook.go
new file mode 100644
index 000000000..a5c23e4cf
--- /dev/null
+++ b/cmd/podman-wslkerninst/event-hook.go
@@ -0,0 +1,73 @@
+//go:build windows
+// +build windows
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+
+ "github.com/sirupsen/logrus"
+ "golang.org/x/sys/windows/svc/eventlog"
+)
+
+// Logrus hook that delegates to windows event log
+type EventLogHook struct {
+ events *eventlog.Log
+}
+
+type LogFormat struct {
+ name string
+}
+
+func (f *LogFormat) Format(entry *logrus.Entry) ([]byte, error) {
+ var b *bytes.Buffer
+
+ if entry.Buffer != nil {
+ b = entry.Buffer
+ } else {
+ b = &bytes.Buffer{}
+ }
+
+ fmt.Fprintf(b, "[%-5s] %s: %s", entry.Level.String(), f.name, entry.Message)
+
+ for key, value := range entry.Data {
+ fmt.Fprintf(b, " {%s = %s}", key, value)
+ }
+
+ b.WriteByte('\n')
+ return b.Bytes(), nil
+}
+
+func NewEventHook(events *eventlog.Log, name string) *EventLogHook {
+ logrus.SetFormatter(&LogFormat{name})
+ return &EventLogHook{events}
+}
+
+func (hook *EventLogHook) Fire(entry *logrus.Entry) error {
+ line, err := entry.String()
+ if err != nil {
+ return err
+ }
+
+ switch entry.Level {
+ case logrus.PanicLevel:
+ return hook.events.Error(1002, line)
+ case logrus.FatalLevel:
+ return hook.events.Error(1001, line)
+ case logrus.ErrorLevel:
+ return hook.events.Error(1000, line)
+ case logrus.WarnLevel:
+ return hook.events.Warning(1000, line)
+ case logrus.InfoLevel:
+ return hook.events.Info(1000, line)
+ case logrus.DebugLevel, logrus.TraceLevel:
+ return hook.events.Info(1001, line)
+ default:
+ return nil
+ }
+}
+
+func (hook *EventLogHook) Levels() []logrus.Level {
+ return logrus.AllLevels
+}
diff --git a/cmd/podman-wslkerninst/main.go b/cmd/podman-wslkerninst/main.go
new file mode 100644
index 000000000..0485db13c
--- /dev/null
+++ b/cmd/podman-wslkerninst/main.go
@@ -0,0 +1,103 @@
+//go:build windows
+// +build windows
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "path"
+ "syscall"
+ "time"
+ "unsafe"
+
+ "github.com/containers/podman/v4/pkg/machine/wsl"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/sys/windows/svc/eventlog"
+)
+
+const (
+ MB_ICONWARNING = 0x00000030
+ MB_OK = 0x00000000
+ MB_DEFBUTTON1 = 0x00000000
+)
+
+const KernelWarning = "WSL Kernel installation did not complete successfully. " +
+ "Podman machine will attempt to install this at a later time. " +
+ "You can also manually complete the installation using the " +
+ "\"wsl --update\" command."
+
+func setupLogging(name string) (*eventlog.Log, error) {
+ // Reuse the Built-in .NET Runtime Source so that we do not
+ // have to provide a messaage table and modify the system
+ // event configuration
+ log, err := eventlog.Open(".NET Runtime")
+ if err != nil {
+ return nil, err
+ }
+
+ logrus.AddHook(NewEventHook(log, name))
+ logrus.SetLevel(logrus.InfoLevel)
+
+ return log, nil
+}
+
+func installWslKernel() error {
+ logrus.Info("Installing WSL Kernel update")
+ var (
+ err error
+ )
+ backoff := 500 * time.Millisecond
+ for i := 1; i < 6; i++ {
+ err = wsl.SilentExec("wsl", "--update")
+ if err == nil {
+ break
+ }
+
+ // In case of unusual circumstances (e.g. race with installer actions)
+ // retry a few times
+ logrus.Warn("An error occurred attempting the WSL Kernel update, retrying...")
+ time.Sleep(backoff)
+ backoff *= 2
+ }
+
+ if err != nil {
+ err = fmt.Errorf("could not install WSL Kernel: %w", err)
+ }
+
+ return err
+}
+
+// Creates an "warn" style pop-up window
+func warn(title string, caption string) int {
+ format := MB_ICONWARNING | MB_OK | MB_DEFBUTTON1
+
+ user32 := syscall.NewLazyDLL("user32.dll")
+ captionPtr, _ := syscall.UTF16PtrFromString(caption)
+ titlePtr, _ := syscall.UTF16PtrFromString(title)
+ ret, _, _ := user32.NewProc("MessageBoxW").Call(
+ uintptr(0),
+ uintptr(unsafe.Pointer(captionPtr)),
+ uintptr(unsafe.Pointer(titlePtr)),
+ uintptr(format))
+
+ return int(ret)
+}
+
+func main() {
+ args := os.Args
+ setupLogging(path.Base(args[0]))
+ if wsl.IsWSLInstalled() {
+ // nothing to do
+ logrus.Info("WSL Kernel already installed")
+ return
+ }
+
+ result := installWslKernel()
+ if result != nil {
+ logrus.Error(result.Error())
+ _ = warn("Podman Setup", KernelWarning)
+ }
+
+ logrus.Info("WSL Kernel update successful")
+}