Merge pull request #19364 from jakecorrenti/breakup-hyperv-machine-funcs

Breakup hyperv machine funcs
This commit is contained in:
OpenShift Merge Robot
2023-07-31 16:25:03 +02:00
committed by GitHub

View File

@ -67,37 +67,25 @@ type HyperVMachine struct {
LastUp time.Time
}
func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
var (
key string
)
// Add the network and ready sockets to the Windows registry
// addNetworkAndReadySocketsToRegistry adds the Network and Ready sockets to the
// Windows registry
func (m *HyperVMachine) addNetworkAndReadySocketsToRegistry() error {
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
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
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)
uriRoot := machine.SSHRemoteConnection.MakeSSHURL(machine.LocalhostIP, "/run/podman/podman.sock", strconv.Itoa(m.Port), "root")
@ -113,50 +101,18 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
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
return err
}
}
} else {
fmt.Println("An ignition path was provided. No SSH connection was added to Podman")
}
if len(opts.IgnitionPath) < 1 {
var err error
key, err = machine.CreateSSHKeys(m.IdentityPath)
if err != nil {
return false, err
}
}
return nil
}
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
// 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,
Key: key,
@ -168,7 +124,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
@ -248,22 +204,96 @@ method=auto
},
})
if err := ign.Write(); err != nil {
return false, err
}
// The ignition file has been written. We now need to
// read it so that we can put it into key-value pairs
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 {
return false, err
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
)
if err := m.addNetworkAndReadySocketsToRegistry(); err != nil {
return false, err
}
err = vm.SplitAndAddIgnition("ignition.config.", reader)
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
// read it so that we can put it into key-value pairs
err = m.readAndSplitIgnition()
return err == nil, err
}
@ -299,6 +329,53 @@ 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{}
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
}
// 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) {
logrus.Error(err)
}
}
if err := machine.RemoveConnections(m.Name, m.Name+"-root"); err != nil {
logrus.Error(err)
}
}
// 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 {
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
@ -320,19 +397,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"
@ -340,24 +406,8 @@ 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)
}
// 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.removeFilesAndConnections(files)
m.removeNetworkAndReadySocketsFromRegistry()
return vm.Remove(diskPath)
}, nil
}
@ -566,6 +616,24 @@ func (m *HyperVMachine) loadHyperVMachineFromJSON(fqConfigPath string) error {
return json.Unmarshal(b, m)
}
// 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 {
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
@ -577,11 +645,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
}