Skip to content

Commit

Permalink
machine refactor 3: add symlinks for sockets
Browse files Browse the repository at this point in the history
to avoid errors on macos, we use symlinks to long socket names.

Fixes: containers#12751
Fixes: containers#13609

Signed-off-by: Brent Baude <bbaude@redhat.com>

[NO NEW TESTS NEEDED]

Signed-off-by: Brent Baude <bbaude@redhat.com>
  • Loading branch information
baude committed Apr 1, 2022
1 parent d1f3a2d commit 2afbc90
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 38 deletions.
11 changes: 7 additions & 4 deletions pkg/machine/qemu/config.go
Expand Up @@ -197,8 +197,11 @@ func NewMachineFile(path string, symlink *string) (*MachineFile, error) {
if symlink != nil && len(*symlink) < 1 {
return nil, errors.New("invalid symlink path")
}
return &MachineFile{
Path: path,
Symlink: symlink,
}, nil
mf := MachineFile{Path: path}
if symlink != nil {
if err := mf.makeSymlink(symlink); err != nil {
return nil, err
}
}
return &mf, nil
}
50 changes: 16 additions & 34 deletions pkg/machine/qemu/machine.go
Expand Up @@ -131,10 +131,11 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
// Add serial port for readiness
cmd = append(cmd, []string{
"-device", "virtio-serial",
"-chardev", "socket,path=" + vm.getReadySocket() + ",server=on,wait=off,id=" + vm.Name + "_ready",
// qemu needs to establish the long name; other connections can use the symlink'd
"-chardev", "socket,path=" + vm.ReadySocket.Path + ",server=on,wait=off,id=" + vm.Name + "_ready",
"-device", "virtserialport,chardev=" + vm.Name + "_ready" + ",name=org.fedoraproject.port.0"}...)
vm.CmdLine = cmd
if err := vm.setQEMUAndPIDSocket(); err != nil {
if err := vm.setPIDSocket(); err != nil {
return nil, err
}
return vm, nil
Expand Down Expand Up @@ -487,9 +488,6 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
return err
}
}
if err := v.setQEMUAndPIDSocket(); err != nil {
return err
}
// If the qemusocketpath exists and the vm is off/down, we should rm
// it before the dial as to avoid a segv
if err := v.QMPMonitor.Address.Delete(); err != nil {
Expand Down Expand Up @@ -700,7 +698,7 @@ func (v *MachineVM) Stop(_ string, _ machine.StopOptions) error {
return err
}

if _, err := os.Stat(v.getPidFile()); os.IsNotExist(err) {
if _, err := os.Stat(v.PidFilePath.GetPath()); os.IsNotExist(err) {
return nil
}
pidString, err := v.PidFilePath.Read()
Expand Down Expand Up @@ -748,7 +746,7 @@ func (v *MachineVM) Stop(_ string, _ machine.StopOptions) error {
waitInternal = waitInternal * 2
}

return nil
return v.ReadySocket.Delete()
}

// NewQMPMonitor creates the monitor subsection of our vm
Expand All @@ -770,7 +768,7 @@ func NewQMPMonitor(network, name string, timeout time.Duration) (Monitor, error)
if timeout == 0 {
timeout = defaultQMPTimeout
}
address, err := NewMachineFile(filepath.Join(rtDir, "qmp+"+name+".sock"), nil)
address, err := NewMachineFile(filepath.Join(rtDir, "qmp_"+name+".sock"), nil)
if err != nil {
return Monitor{}, err
}
Expand Down Expand Up @@ -831,7 +829,6 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func()
confirmationMessage += msg + "\n"
}

//silently try to delete socket and pid file
//remove socket and pid file if any: warn at low priority if things fail
// Remove the pidfile
if err := v.PidFilePath.Delete(); err != nil {
Expand Down Expand Up @@ -1083,7 +1080,7 @@ func (v *MachineVM) startHostNetworking() (string, apiForwardingState, error) {
files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
attr.Files = files
cmd := []string{binary}
cmd = append(cmd, []string{"-listen-qemu", fmt.Sprintf("unix://%s", v.getQMPMonitorSocket()), "-pid-file", v.getPidFile()}...)
cmd = append(cmd, []string{"-listen-qemu", fmt.Sprintf("unix://%s", v.QMPMonitor.Address.GetPath()), "-pid-file", v.PidFilePath.GetPath()}...)
// Add the ssh port
cmd = append(cmd, []string{"-ssh-port", fmt.Sprintf("%d", v.Port)}...)

Expand Down Expand Up @@ -1187,36 +1184,38 @@ func (v *MachineVM) setConfigPath() error {
}

func (v *MachineVM) setReadySocket() error {
readySocketName := v.Name + "_ready.sock"
rtPath, err := getRuntimeDir()
if err != nil {
return err
}
virtualSocketPath, err := NewMachineFile(filepath.Join(rtPath, "podman", v.Name+"_ready.sock"), nil)
virtualSocketPath, err := NewMachineFile(filepath.Join(rtPath, "podman", readySocketName), &readySocketName)
if err != nil {
return err
}
v.ReadySocket = *virtualSocketPath
return nil
}

func (v *MachineVM) setQEMUAndPIDSocket() error {
func (v *MachineVM) setPIDSocket() error {
rtPath, err := getRuntimeDir()
if err != nil {
return err
}
if !rootless.IsRootless() {
rtPath = "/run"
}
pidFileName := fmt.Sprintf("%s.pid", v.Name)
socketDir := filepath.Join(rtPath, "podman")
pidFilePath, err := NewMachineFile(filepath.Join(socketDir, fmt.Sprintf("%s.pid", v.Name)), nil)
pidFilePath, err := NewMachineFile(filepath.Join(socketDir, pidFileName), &pidFileName)
if err != nil {
return err
}
v.PidFilePath = *pidFilePath
return nil
}

// Deprecated: getSocketandPid is being replace by setQEMUAndPIDSocket and
// Deprecated: getSocketandPid is being replace by setPIDSocket and
// machinefiles.
func (v *MachineVM) getSocketandPid() (string, string, error) {
rtPath, err := getRuntimeDir()
Expand Down Expand Up @@ -1342,7 +1341,7 @@ func (v *MachineVM) update() error {
}
b, err := v.ConfigPath.Read()
if err != nil {
if os.IsNotExist(err) {
if errors.Is(err, os.ErrNotExist) {
return errors.Wrap(machine.ErrNoSuchVM, v.Name)
}
return err
Expand Down Expand Up @@ -1377,30 +1376,13 @@ func (v *MachineVM) writeConfig() error {
return nil
}

// getPidFile gets the file where the machine pid is stored
func (v *MachineVM) getPidFile() string {
return v.PidFilePath.GetPath()
}

// getQMPMonitorSocket gets the socket used by qemu to interact
// with the instance
func (v *MachineVM) getQMPMonitorSocket() string {
return v.QMPMonitor.Address.GetPath()
}

// getReadySocket returns the socket used to communicate
// with the machinevm and report when it is booted
func (v *MachineVM) getReadySocket() string {
return v.ReadySocket.GetPath()
}

// getImageFile returns the path to the image used
// getImageFile wrapper returns the path to the image used
// to boot the VM
func (v *MachineVM) getImageFile() string {
return v.ImagePath.GetPath()
}

// getIgnitionFile returns the path to the ignition file
// getIgnitionFile wrapper returns the path to the ignition file
func (v *MachineVM) getIgnitionFile() string {
return v.IgnitionFilePath.GetPath()
}
13 changes: 13 additions & 0 deletions pkg/machine/qemu/options_darwin.go
Expand Up @@ -2,6 +2,7 @@ package qemu

import (
"os"
"path/filepath"
)

func getRuntimeDir() (string, error) {
Expand All @@ -11,3 +12,15 @@ func getRuntimeDir() (string, error) {
}
return tmpDir, nil
}

// makeSymlink for macOS creates a symlink in $HOME/.podman/
// for a machinefile like a socket
func (m *MachineFile) makeSymlink(symlink *string) error {
homedir, err := os.UserHomeDir()
if err != nil {
return err
}
sl := filepath.Join(homedir, ".podman", *symlink)
m.Symlink = &sl
return os.Symlink(m.Path, sl)
}
5 changes: 5 additions & 0 deletions pkg/machine/qemu/options_linux.go
Expand Up @@ -11,3 +11,8 @@ func getRuntimeDir() (string, error) {
}
return util.GetRuntimeDir()
}

// makeSymlink is a no-op for Linux
func (m *MachineFile) makeSymlink(*string) error {
return nil
}

0 comments on commit 2afbc90

Please sign in to comment.