From 78d3b549cd0f349317646759afe5f61dcab625ce Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 15:36:38 -0400 Subject: [PATCH 1/9] `Init`: add SSH conns to podman sock Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 48 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 473676a40d..6c15e00587 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -67,6 +67,31 @@ type HyperVMachine struct { LastUp time.Time } +func (m *HyperVMachine) addSSHConnectionsToPodmanSocket(opts machine.InitOptions) error { + if len(opts.IgnitionPath) < 1 { + uri := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, fmt.Sprintf("/run/user/%d/podman/podman.sock", m.UID), strconv.Itoa(m.Port), m.RemoteUsername) + uriRoot := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, "/run/podman/podman.sock", strconv.Itoa(m.Port), "root") + + uris := []url.URL{uri, uriRoot} + names := []string{m.Name, m.Name + "-root"} + + // The first connection defined when connections is empty will become the default + // regardless of IsDefault, so order according to rootful + if opts.Rootful { + uris[0], names[0], uris[1], names[1] = uris[1], names[1], uris[0], names[0] + } + + for i := 0; i < 2; i++ { + if err := machine.AddConnection(&uris[i], names[i], m.IdentityPath, opts.IsDefault && i == 0); err != nil { + return err + } + } + } else { + fmt.Println("An ignition path was provided. No SSH connection was added to Podman") + } + return nil +} + func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { var ( key string @@ -98,27 +123,10 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { } m.Port = sshPort - if len(opts.IgnitionPath) < 1 { - uri := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, fmt.Sprintf("/run/user/%d/podman/podman.sock", m.UID), strconv.Itoa(m.Port), m.RemoteUsername) - uriRoot := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, "/run/podman/podman.sock", strconv.Itoa(m.Port), "root") - - uris := []url.URL{uri, uriRoot} - names := []string{m.Name, m.Name + "-root"} - - // The first connection defined when connections is empty will become the default - // regardless of IsDefault, so order according to rootful - if opts.Rootful { - uris[0], names[0], uris[1], names[1] = uris[1], names[1], uris[0], names[0] - } - - for i := 0; i < 2; i++ { - if err := machine.AddConnection(&uris[i], names[i], m.IdentityPath, opts.IsDefault && i == 0); err != nil { - return false, err - } - } - } else { - fmt.Println("An ignition path was provided. No SSH connection was added to Podman") + if err := m.addSSHConnectionsToPodmanSocket(opts); err != nil { + return false, err } + if len(opts.IgnitionPath) < 1 { var err error key, err = machine.CreateSSHKeys(m.IdentityPath) From cc30639d7bd549706c84d4dfadd68792e39f8afd Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 15:42:15 -0400 Subject: [PATCH 2/9] `Init`: add network and registry socks to registry Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 6c15e00587..8ec2f8843b 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -67,6 +67,21 @@ type HyperVMachine struct { LastUp time.Time } +func (m *HyperVMachine) addNetworkAndReadySocketsToRegistry() error { + // Add the network and ready sockets to the Windows registry + networkHVSock, err := NewHVSockRegistryEntry(m.Name, Network) + if err != nil { + return false, err + } + eventHVSocket, err := NewHVSockRegistryEntry(m.Name, Events) + if err != nil { + return false, err + } + m.NetworkHVSock = *networkHVSock + m.ReadyHVSock = *eventHVSocket + return nil +} + func (m *HyperVMachine) addSSHConnectionsToPodmanSocket(opts machine.InitOptions) error { if len(opts.IgnitionPath) < 1 { uri := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, fmt.Sprintf("/run/user/%d/podman/podman.sock", m.UID), strconv.Itoa(m.Port), m.RemoteUsername) @@ -97,17 +112,10 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { key string ) - // Add the network and ready sockets to the Windows registry - networkHVSock, err := NewHVSockRegistryEntry(m.Name, Network) - if err != nil { + if err := m.addNetworkAndReadySocketsToRegistry(); err != nil { return false, err } - eventHVSocket, err := NewHVSockRegistryEntry(m.Name, Events) - if err != nil { - return false, err - } - m.NetworkHVSock = *networkHVSock - m.ReadyHVSock = *eventHVSocket + m.IdentityPath = util.GetIdentityPath(m.Name) // TODO This needs to be fixed in c-common From aa6827a67ad5ed9352b896b5a56b7dd87af7abf5 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 15:49:03 -0400 Subject: [PATCH 3/9] `Init`: write ign config Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 140 +++++++++++++++++----------------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 8ec2f8843b..8b71a38e28 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -107,72 +107,7 @@ func (m *HyperVMachine) addSSHConnectionsToPodmanSocket(opts machine.InitOptions return nil } -func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { - var ( - key string - ) - - if err := m.addNetworkAndReadySocketsToRegistry(); err != nil { - return false, err - } - - m.IdentityPath = util.GetIdentityPath(m.Name) - - // TODO This needs to be fixed in c-common - m.RemoteUsername = "core" - - if m.UID == 0 { - m.UID = 1000 - } - - sshPort, err := utils.GetRandomPort() - if err != nil { - return false, err - } - m.Port = sshPort - - if err := m.addSSHConnectionsToPodmanSocket(opts); err != nil { - return false, err - } - - if len(opts.IgnitionPath) < 1 { - var err error - key, err = machine.CreateSSHKeys(m.IdentityPath) - if err != nil { - return false, err - } - } - - m.ResourceConfig = machine.ResourceConfig{ - CPUs: opts.CPUS, - DiskSize: opts.DiskSize, - Memory: opts.Memory, - } - - // If the user provides an ignition file, we need to - // copy it into the conf dir - if len(opts.IgnitionPath) > 0 { - inputIgnition, err := os.ReadFile(opts.IgnitionPath) - if err != nil { - return false, err - } - return false, os.WriteFile(m.IgnitionFile.GetPath(), inputIgnition, 0644) - } - - // Write the JSON file for the second time. First time was in NewMachine - if err := m.writeConfig(); err != nil { - return false, err - } - - // c/common sets the default machine user for "windows" to be "user"; this - // is meant for the WSL implementation that does not use FCOS. For FCOS, - // however, we want to use the DefaultIgnitionUserName which is currently - // "core" - user := opts.Username - if user == "user" { - user = machine.DefaultIgnitionUserName - } - // Write the ignition file +func (m *HyperVMachine) writeIgnitionConfigFile(opts machine.InitOptions, user, key string) error { ign := machine.DynamicIgnition{ Name: user, Key: key, @@ -184,7 +119,7 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { } if err := ign.GenerateIgnitionConfig(); err != nil { - return false, err + return err } // ready is a unit file that sets up the virtual serial device @@ -264,7 +199,76 @@ method=auto }, }) - if err := ign.Write(); err != nil { + return ign.Write() +} + +func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { + var ( + key string + ) + + if err := m.addNetworkAndReadySocketsToRegistry(); err != nil { + return false, err + } + + m.IdentityPath = util.GetIdentityPath(m.Name) + + // TODO This needs to be fixed in c-common + m.RemoteUsername = "core" + + if m.UID == 0 { + m.UID = 1000 + } + + sshPort, err := utils.GetRandomPort() + if err != nil { + return false, err + } + m.Port = sshPort + + if err := m.addSSHConnectionsToPodmanSocket(opts); err != nil { + return false, err + } + + if len(opts.IgnitionPath) < 1 { + var err error + key, err = machine.CreateSSHKeys(m.IdentityPath) + if err != nil { + return false, err + } + } + + m.ResourceConfig = machine.ResourceConfig{ + CPUs: opts.CPUS, + DiskSize: opts.DiskSize, + Memory: opts.Memory, + } + + // If the user provides an ignition file, we need to + // copy it into the conf dir + if len(opts.IgnitionPath) > 0 { + inputIgnition, err := os.ReadFile(opts.IgnitionPath) + if err != nil { + return false, err + } + return false, os.WriteFile(m.IgnitionFile.GetPath(), inputIgnition, 0644) + } + + // Write the JSON file for the second time. First time was in NewMachine + if err := m.writeConfig(); err != nil { + return false, err + } + + // c/common sets the default machine user for "windows" to be "user"; this + // is meant for the WSL implementation that does not use FCOS. For FCOS, + // however, we want to use the DefaultIgnitionUserName which is currently + // "core" + user := opts.Username + if user == "user" { + user = machine.DefaultIgnitionUserName + } + // Write the ignition file + if err := m.writeIgnitionConfigFile(opts, key, user); err != nil { return false, err } // The ignition file has been written. We now need to From 381b103dd1dd866beb5fe252c0bc0840fa037119 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 16:12:23 -0400 Subject: [PATCH 4/9] `Init`: read and split ign file Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 8b71a38e28..18802cc6e1 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -202,6 +202,20 @@ method=auto return ign.Write() } +func (m *HyperVMachine) readAndSplitIgnition() error { + ignFile, err := m.IgnitionFile.Read() + if err != nil { + return err + } + reader := bytes.NewReader(ignFile) + + vm, err := hypervctl.NewVirtualMachineManager().GetMachine(m.Name) + if err != nil { + return err + } + return vm.SplitAndAddIgnition("ignition.config.", reader) +} + func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { var ( key string @@ -273,17 +287,7 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) { } // The ignition file has been written. We now need to // read it so that we can put it into key-value pairs - ignFile, err := m.IgnitionFile.Read() - if err != nil { - return false, err - } - reader := bytes.NewReader(ignFile) - - vm, err := hypervctl.NewVirtualMachineManager().GetMachine(m.Name) - if err != nil { - return false, err - } - err = vm.SplitAndAddIgnition("ignition.config.", reader) + err = m.readAndSplitIgnition() return err == nil, err } From 32265e1f6478630efe6fd011b7b0fa8992bc2530 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 16:28:40 -0400 Subject: [PATCH 5/9] `Remove`: collect files to destroy Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 18802cc6e1..8ce50ff3a2 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -323,6 +323,25 @@ func (m *HyperVMachine) Inspect() (*machine.InspectInfo, error) { }, nil } +func (m *HyperVMachine) collectFilesToDestroy(opts machine.RemoveOptions, diskPath *string) []string { + files := []string{} + + if !opts.SaveKeys { + files = append(files, m.IdentityPath, m.IdentityPath+".pub") + } + if !opts.SaveIgnition { + files = append(files, m.IgnitionFile.GetPath()) + } + + if !opts.SaveImage { + *diskPath = m.ImagePath.GetPath() + files = append(files, *diskPath) + } + + files = append(files, getVMConfigPath(m.ConfigPath.GetPath(), m.Name)) + return files +} + func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, func() error, error) { var ( files []string @@ -344,19 +363,8 @@ func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, fu } // Collect all the files that need to be destroyed - if !opts.SaveKeys { - files = append(files, m.IdentityPath, m.IdentityPath+".pub") - } - if !opts.SaveIgnition { - files = append(files, m.IgnitionFile.GetPath()) - } + files = m.collectFilesToDestroy(opts, &diskPath) - if !opts.SaveImage { - diskPath = m.ImagePath.GetPath() - files = append(files, diskPath) - } - - files = append(files, getVMConfigPath(m.ConfigPath.GetPath(), m.Name)) confirmationMessage := "\nThe following files will be deleted:\n\n" for _, msg := range files { confirmationMessage += msg + "\n" From d896431b28364b8147a2233877a865151251f9e4 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 16:29:55 -0400 Subject: [PATCH 6/9] `Remove`: remove files and connections Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 8ce50ff3a2..4f8ead3815 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -342,6 +342,17 @@ func (m *HyperVMachine) collectFilesToDestroy(opts machine.RemoveOptions, diskPa return files } +func (m *HyperVMachine) removeFilesAndConnections(files []string) { + for _, f := range files { + if err := os.Remove(f); err != nil && !errors.Is(err, os.ErrNotExist) { + logrus.Error(err) + } + } + if err := machine.RemoveConnections(m.Name, m.Name+"-root"); err != nil { + logrus.Error(err) + } +} + func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, func() error, error) { var ( files []string @@ -372,14 +383,7 @@ func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, fu confirmationMessage += "\n" return confirmationMessage, func() error { - for _, f := range files { - if err := os.Remove(f); err != nil && !errors.Is(err, os.ErrNotExist) { - logrus.Error(err) - } - } - if err := machine.RemoveConnections(m.Name, m.Name+"-root"); err != nil { - logrus.Error(err) - } + m.removeFilesAndConnections(files) // Remove the HVSOCK for networking if err := m.NetworkHVSock.Remove(); err != nil { From 13da82466aa32ed7da902b53d33c407d535cf3d5 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 16:32:41 -0400 Subject: [PATCH 7/9] `Remove`: remove network and ready sockets from registry Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 4f8ead3815..15a442c6a0 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -353,6 +353,18 @@ func (m *HyperVMachine) removeFilesAndConnections(files []string) { } } +func (m *HyperVMachine) removeNetworkAndReadySocketsFromRegistry() { + // Remove the HVSOCK for networking + if err := m.NetworkHVSock.Remove(); err != nil { + logrus.Errorf("unable to remove registry entry for %s: %q", m.NetworkHVSock.KeyName, err) + } + + // Remove the HVSOCK for events + if err := m.ReadyHVSock.Remove(); err != nil { + logrus.Errorf("unable to remove registry entry for %s: %q", m.ReadyHVSock.KeyName, err) + } +} + func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, func() error, error) { var ( files []string @@ -384,16 +396,7 @@ func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, fu confirmationMessage += "\n" return confirmationMessage, func() error { m.removeFilesAndConnections(files) - - // Remove the HVSOCK for networking - if err := m.NetworkHVSock.Remove(); err != nil { - logrus.Errorf("unable to remove registry entry for %s: %q", m.NetworkHVSock.KeyName, err) - } - - // Remove the HVSOCK for events - if err := m.ReadyHVSock.Remove(); err != nil { - logrus.Errorf("unable to remove registry entry for %s: %q", m.NetworkHVSock.KeyName, err) - } + m.removeNetworkAndReadySocketsFromRegistry() return vm.Remove(diskPath) }, nil } From 481143e584c7573fbc30351e2c329a691d49db57 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Tue, 25 Jul 2023 16:47:11 -0400 Subject: [PATCH 8/9] `startHostNetworking`: get DevNull files [NO NEW TESTS NEEDED] Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index 15a442c6a0..f9a8caafa9 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -605,6 +605,23 @@ func loadMacMachineFromJSON(fqConfigPath string, macMachine *HyperVMachine) erro return json.Unmarshal(b, macMachine) } +func getDevNullFiles() (*os.File, *os.File, error) { + dnr, err := os.OpenFile(os.DevNull, os.O_RDONLY, 0755) + if err != nil { + return nil, nil, err + } + + dnw, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0755) + if err != nil { + if e := dnr.Close(); e != nil { + err = e + } + return nil, nil, err + } + + return dnr, dnw, nil +} + func (m *HyperVMachine) startHostNetworking() (string, machine.APIForwardingState, error) { var ( forwardSock string @@ -616,11 +633,7 @@ func (m *HyperVMachine) startHostNetworking() (string, machine.APIForwardingStat } attr := new(os.ProcAttr) - dnr, err := os.OpenFile(os.DevNull, os.O_RDONLY, 0755) - if err != nil { - return "", machine.NoForwarding, err - } - dnw, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0755) + dnr, dnw, err := getDevNullFiles() if err != nil { return "", machine.NoForwarding, err } From 19deb6a3466287e49433262e45a1ebc676ba6f23 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Sun, 30 Jul 2023 19:37:11 -0400 Subject: [PATCH 9/9] Adds documentation to new functions that were added Signed-off-by: Jake Correnti --- pkg/machine/hyperv/machine.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/pkg/machine/hyperv/machine.go b/pkg/machine/hyperv/machine.go index f9a8caafa9..9690381b56 100644 --- a/pkg/machine/hyperv/machine.go +++ b/pkg/machine/hyperv/machine.go @@ -67,21 +67,24 @@ type HyperVMachine struct { LastUp time.Time } +// addNetworkAndReadySocketsToRegistry adds the Network and Ready sockets to the +// Windows registry func (m *HyperVMachine) addNetworkAndReadySocketsToRegistry() error { - // Add the network and ready sockets to the Windows registry networkHVSock, err := NewHVSockRegistryEntry(m.Name, Network) if err != nil { - return false, err + return err } eventHVSocket, err := NewHVSockRegistryEntry(m.Name, Events) if err != nil { - return false, err + return err } m.NetworkHVSock = *networkHVSock m.ReadyHVSock = *eventHVSocket return nil } +// addSSHConnectionsToPodmanSocket adds SSH connections to the podman socket if +// no ignition path was provided func (m *HyperVMachine) addSSHConnectionsToPodmanSocket(opts machine.InitOptions) error { if len(opts.IgnitionPath) < 1 { uri := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, fmt.Sprintf("/run/user/%d/podman/podman.sock", m.UID), strconv.Itoa(m.Port), m.RemoteUsername) @@ -107,6 +110,8 @@ func (m *HyperVMachine) addSSHConnectionsToPodmanSocket(opts machine.InitOptions return nil } +// writeIgnitionConfigFile generates the ignition config and writes it to the +// filesystem func (m *HyperVMachine) writeIgnitionConfigFile(opts machine.InitOptions, user, key string) error { ign := machine.DynamicIgnition{ Name: user, @@ -202,6 +207,7 @@ method=auto return ign.Write() } +// readAndSplitIgnition reads the ignition file and splits it into key:value pairs func (m *HyperVMachine) readAndSplitIgnition() error { ignFile, err := m.IgnitionFile.Read() if err != nil { @@ -323,6 +329,7 @@ func (m *HyperVMachine) Inspect() (*machine.InspectInfo, error) { }, nil } +// collectFilesToDestroy retrieves the files that will be destroyed by `Remove` func (m *HyperVMachine) collectFilesToDestroy(opts machine.RemoveOptions, diskPath *string) []string { files := []string{} @@ -342,6 +349,8 @@ func (m *HyperVMachine) collectFilesToDestroy(opts machine.RemoveOptions, diskPa return files } +// removeFilesAndConnections removes any files and connections associated with +// the machine during `Remove` func (m *HyperVMachine) removeFilesAndConnections(files []string) { for _, f := range files { if err := os.Remove(f); err != nil && !errors.Is(err, os.ErrNotExist) { @@ -353,6 +362,8 @@ func (m *HyperVMachine) removeFilesAndConnections(files []string) { } } +// removeNetworkAndReadySocketsFromRegistry removes the Network and Ready sockets +// from the Windows Registry func (m *HyperVMachine) removeNetworkAndReadySocketsFromRegistry() { // Remove the HVSOCK for networking if err := m.NetworkHVSock.Remove(); err != nil { @@ -605,6 +616,7 @@ func loadMacMachineFromJSON(fqConfigPath string, macMachine *HyperVMachine) erro return json.Unmarshal(b, macMachine) } +// getDevNullFiles returns pointers to Read-only and Write-only DevNull files func getDevNullFiles() (*os.File, *os.File, error) { dnr, err := os.OpenFile(os.DevNull, os.O_RDONLY, 0755) if err != nil {