mirror of
https://github.com/containers/podman.git
synced 2025-06-03 20:33:20 +08:00
Merge pull request #9836 from baude/vmcreateresize
Podman machine enhancements
This commit is contained in:
@ -8,6 +8,7 @@ import (
|
||||
"github.com/containers/podman/v3/pkg/domain/entities"
|
||||
"github.com/containers/podman/v3/pkg/machine"
|
||||
"github.com/containers/podman/v3/pkg/machine/qemu"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -23,17 +24,8 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type InitCLIOptions struct {
|
||||
CPUS uint64
|
||||
Memory uint64
|
||||
Devices []string
|
||||
ImagePath string
|
||||
IgnitionPath string
|
||||
Name string
|
||||
}
|
||||
|
||||
var (
|
||||
initOpts = InitCLIOptions{}
|
||||
initOpts = machine.InitOptions{}
|
||||
defaultMachineName string = "podman-machine-default"
|
||||
)
|
||||
|
||||
@ -53,6 +45,15 @@ func init() {
|
||||
)
|
||||
_ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)
|
||||
|
||||
diskSizeFlagName := "disk-size"
|
||||
flags.Uint64Var(
|
||||
&initOpts.DiskSize,
|
||||
diskSizeFlagName, 10,
|
||||
"Disk size in GB",
|
||||
)
|
||||
|
||||
_ = initCmd.RegisterFlagCompletionFunc(diskSizeFlagName, completion.AutocompleteNone)
|
||||
|
||||
memoryFlagName := "memory"
|
||||
flags.Uint64VarP(
|
||||
&initOpts.Memory,
|
||||
@ -72,28 +73,24 @@ func init() {
|
||||
|
||||
// TODO should we allow for a users to append to the qemu cmdline?
|
||||
func initMachine(cmd *cobra.Command, args []string) error {
|
||||
initOpts.Name = defaultMachineName
|
||||
if len(args) > 0 {
|
||||
initOpts.Name = args[0]
|
||||
}
|
||||
vmOpts := machine.InitOptions{
|
||||
CPUS: initOpts.CPUS,
|
||||
Memory: initOpts.Memory,
|
||||
IgnitionPath: initOpts.IgnitionPath,
|
||||
ImagePath: initOpts.ImagePath,
|
||||
Name: initOpts.Name,
|
||||
}
|
||||
var (
|
||||
vm machine.VM
|
||||
vmType string
|
||||
err error
|
||||
)
|
||||
initOpts.Name = defaultMachineName
|
||||
if len(args) > 0 {
|
||||
initOpts.Name = args[0]
|
||||
}
|
||||
switch vmType {
|
||||
default: // qemu is the default
|
||||
vm, err = qemu.NewMachine(vmOpts)
|
||||
if _, err := qemu.LoadVMByName(initOpts.Name); err == nil {
|
||||
return errors.Wrap(machine.ErrVMAlreadyExists, initOpts.Name)
|
||||
}
|
||||
vm, err = qemu.NewMachine(initOpts)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return vm.Init(vmOpts)
|
||||
return vm.Init(initOpts)
|
||||
}
|
||||
|
@ -17,13 +17,13 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
removeCmd = &cobra.Command{
|
||||
Use: "remove [options] NAME",
|
||||
rmCmd = &cobra.Command{
|
||||
Use: "rm [options] [NAME]",
|
||||
Short: "Remove an existing machine",
|
||||
Long: "Remove an existing machine ",
|
||||
RunE: remove,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Example: `podman machine remove myvm`,
|
||||
RunE: rm,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Example: `podman machine rm myvm`,
|
||||
ValidArgsFunction: completion.AutocompleteNone,
|
||||
}
|
||||
)
|
||||
@ -35,13 +35,13 @@ var (
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: removeCmd,
|
||||
Command: rmCmd,
|
||||
Parent: machineCmd,
|
||||
})
|
||||
|
||||
flags := removeCmd.Flags()
|
||||
flags := rmCmd.Flags()
|
||||
formatFlagName := "force"
|
||||
flags.BoolVar(&destoryOptions.Force, formatFlagName, false, "Do not prompt before removeing")
|
||||
flags.BoolVar(&destoryOptions.Force, formatFlagName, false, "Do not prompt before rming")
|
||||
|
||||
keysFlagName := "save-keys"
|
||||
flags.BoolVar(&destoryOptions.SaveKeys, keysFlagName, false, "Do not delete SSH keys")
|
||||
@ -53,20 +53,24 @@ func init() {
|
||||
flags.BoolVar(&destoryOptions.SaveImage, imageFlagName, false, "Do not delete the image file")
|
||||
}
|
||||
|
||||
func remove(cmd *cobra.Command, args []string) error {
|
||||
func rm(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
err error
|
||||
vm machine.VM
|
||||
vmType string
|
||||
)
|
||||
vmName := defaultMachineName
|
||||
if len(args) > 0 && len(args[0]) > 0 {
|
||||
vmName = args[0]
|
||||
}
|
||||
switch vmType {
|
||||
default:
|
||||
vm, err = qemu.LoadVMByName(args[0])
|
||||
vm, err = qemu.LoadVMByName(vmName)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
confirmationMessage, doIt, err := vm.Remove(args[0], machine.RemoveOptions{})
|
||||
confirmationMessage, remove, err := vm.Remove(vmName, machine.RemoveOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -84,5 +88,5 @@ func remove(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return doIt()
|
||||
return remove()
|
||||
}
|
@ -14,11 +14,11 @@ import (
|
||||
|
||||
var (
|
||||
sshCmd = &cobra.Command{
|
||||
Use: "ssh [options] NAME [COMMAND [ARG ...]]",
|
||||
Use: "ssh [options] [NAME] [COMMAND [ARG ...]]",
|
||||
Short: "SSH into a virtual machine",
|
||||
Long: "SSH into a virtual machine ",
|
||||
RunE: ssh,
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Example: `podman machine ssh myvm
|
||||
podman machine ssh -e myvm echo hello`,
|
||||
|
||||
@ -48,6 +48,10 @@ func ssh(cmd *cobra.Command, args []string) error {
|
||||
vm machine.VM
|
||||
vmType string
|
||||
)
|
||||
vmName := defaultMachineName
|
||||
if len(args) > 0 && len(args[0]) > 1 {
|
||||
vmName = args[0]
|
||||
}
|
||||
sshOpts.Args = args[1:]
|
||||
|
||||
// Error if no execute but args given
|
||||
@ -61,10 +65,10 @@ func ssh(cmd *cobra.Command, args []string) error {
|
||||
|
||||
switch vmType {
|
||||
default:
|
||||
vm, err = qemu.LoadVMByName(args[0])
|
||||
vm, err = qemu.LoadVMByName(vmName)
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "vm %s not found", args[0])
|
||||
}
|
||||
return vm.SSH(args[0], sshOpts)
|
||||
return vm.SSH(vmName, sshOpts)
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ import (
|
||||
|
||||
var (
|
||||
startCmd = &cobra.Command{
|
||||
Use: "start NAME",
|
||||
Use: "start [NAME]",
|
||||
Short: "Start an existing machine",
|
||||
Long: "Start an existing machine ",
|
||||
RunE: start,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Example: `podman machine start myvm`,
|
||||
ValidArgsFunction: completion.AutocompleteNone,
|
||||
}
|
||||
@ -37,12 +37,16 @@ func start(cmd *cobra.Command, args []string) error {
|
||||
vm machine.VM
|
||||
vmType string
|
||||
)
|
||||
vmName := defaultMachineName
|
||||
if len(args) > 0 && len(args[0]) > 0 {
|
||||
vmName = args[0]
|
||||
}
|
||||
switch vmType {
|
||||
default:
|
||||
vm, err = qemu.LoadVMByName(args[0])
|
||||
vm, err = qemu.LoadVMByName(vmName)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return vm.Start(args[0], machine.StartOptions{})
|
||||
return vm.Start(vmName, machine.StartOptions{})
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ import (
|
||||
|
||||
var (
|
||||
stopCmd = &cobra.Command{
|
||||
Use: "stop NAME",
|
||||
Use: "stop [NAME]",
|
||||
Short: "Stop an existing machine",
|
||||
Long: "Stop an existing machine ",
|
||||
RunE: stop,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Example: `podman machine stop myvm`,
|
||||
ValidArgsFunction: completion.AutocompleteNone,
|
||||
}
|
||||
@ -38,12 +38,16 @@ func stop(cmd *cobra.Command, args []string) error {
|
||||
vm machine.VM
|
||||
vmType string
|
||||
)
|
||||
vmName := defaultMachineName
|
||||
if len(args) > 0 && len(args[0]) > 0 {
|
||||
vmName = args[0]
|
||||
}
|
||||
switch vmType {
|
||||
default:
|
||||
vm, err = qemu.LoadVMByName(args[0])
|
||||
vm, err = qemu.LoadVMByName(vmName)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return vm.Stop(args[0], machine.StopOptions{})
|
||||
return vm.Stop(vmName, machine.StopOptions{})
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ Machine
|
||||
|
||||
|
||||
:doc:`init <markdown/podman-machine-init.1>` Initialize a new virtual machine
|
||||
:doc:`remove <markdown/podman-machine-remove.1>` Remove a virtual machine
|
||||
:doc:`rm <markdown/podman-machine-rm.1>` Remove a virtual machine
|
||||
:doc:`ssh <markdown/podman-machine-ssh.1>` SSH into a virtual machine
|
||||
:doc:`start <markdown/podman-machine-start.1>` Start a virtual machine
|
||||
:doc:`stop <markdown/podman-machine-stop.1>` Stop a virtual machine
|
||||
|
@ -22,6 +22,10 @@ tied to the Linux kernel.
|
||||
|
||||
Number of CPUs.
|
||||
|
||||
#### **--disk-size**=*number*
|
||||
|
||||
Size of the disk for the guest VM in GB.
|
||||
|
||||
#### **--ignition-path**
|
||||
|
||||
Fully qualified path of the ignition file
|
||||
|
@ -1,17 +1,17 @@
|
||||
% podman-machine-remove(1)
|
||||
% podman-machine-rm(1)
|
||||
|
||||
## NAME
|
||||
podman\-machine\-remove - Remove a virtual machine
|
||||
podman\-machine\-rm - Remove a virtual machine
|
||||
|
||||
## SYNOPSIS
|
||||
**podman machine remove** [*options*] *name*
|
||||
**podman machine rm** [*options*] [*name*]
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
Remove a virtual machine and its related files. What is actually deleted
|
||||
depends on the virtual machine type. For all virtual machines, the generated
|
||||
SSH keys and the podman system connection are deleted. The ignition files
|
||||
generated for that VM are also removeed as is its image file on the filesystem.
|
||||
generated for that VM are also removed as is its image file on the filesystem.
|
||||
|
||||
Users get a display of what will be deleted and are required to confirm unless the option `--force`
|
||||
is used.
|
||||
@ -45,7 +45,7 @@ deleted.
|
||||
Remove a VM named "test1"
|
||||
|
||||
```
|
||||
$ podman machine remove test1
|
||||
$ podman machine rm test1
|
||||
|
||||
The following files will be deleted:
|
||||
|
@ -4,7 +4,7 @@
|
||||
podman\-machine\-ssh - SSH into a virtual machine
|
||||
|
||||
## SYNOPSIS
|
||||
**podman machine ssh** [*options*] *name* [*command* [*arg* ...]]
|
||||
**podman machine ssh** [*options*] [*name*] [*command* [*arg* ...]]
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
podman\-machine\-start - Start a virtual machine
|
||||
|
||||
## SYNOPSIS
|
||||
**podman machine start** *name*
|
||||
**podman machine start** [*name*]
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
podman\-machine\-stop - Stop a virtual machine
|
||||
|
||||
## SYNOPSIS
|
||||
**podman machine stop** *name*
|
||||
**podman machine stop** [*name*]
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
|
@ -14,10 +14,10 @@ podman\-machine - Manage Podman's virtual machine
|
||||
| Command | Man Page | Description |
|
||||
| ------- | ------------------------------------------------------- | --------------------------------- |
|
||||
| init | [podman-machine-init(1)](podman-machine-init.1.md) | Initialize a new virtual machine |
|
||||
| remove | [podman-machine-remove(1)](podman-machine-remove.1.md) | Remove a virtual machine |
|
||||
| ssh | [podman-machine-ssh(1)](podman-machine-ssh.1.md) | SSH into a virtual machine |
|
||||
| start | [podman-machine-start(1)](podman-machine-start.1.md) | Start a virtual machine |
|
||||
| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |
|
||||
| rm | [podman-machine-rm(1)](podman-machine-rm.1.md)| Remove a virtual machine |
|
||||
| ssh | [podman-machine-ssh(1)](podman-machine-ssh.1.md) | SSH into a virtual machine |
|
||||
| start | [podman-machine-start(1)](podman-machine-start.1.md) | Start a virtual machine |
|
||||
| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |
|
||||
|
||||
## SEE ALSO
|
||||
podman(1)
|
||||
|
@ -7,19 +7,19 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containers/storage/pkg/homedir"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type InitOptions struct {
|
||||
Name string
|
||||
CPUS uint64
|
||||
Memory uint64
|
||||
DiskSize uint64
|
||||
IgnitionPath string
|
||||
ImagePath string
|
||||
Username string
|
||||
URI url.URL
|
||||
IsDefault bool
|
||||
//KernelPath string
|
||||
//Devices []VMDevices
|
||||
Memory uint64
|
||||
Name string
|
||||
URI url.URL
|
||||
Username string
|
||||
}
|
||||
|
||||
type RemoteConnectionType string
|
||||
@ -27,6 +27,8 @@ type RemoteConnectionType string
|
||||
var (
|
||||
SSHRemoteConnection RemoteConnectionType = "ssh"
|
||||
DefaultIgnitionUserName = "core"
|
||||
ErrNoSuchVM = errors.New("VM does not exist")
|
||||
ErrVMAlreadyExists = errors.New("VM already exists")
|
||||
)
|
||||
|
||||
type Download struct {
|
||||
|
@ -2,6 +2,7 @@ package machine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
@ -37,10 +38,17 @@ func getNodeGrp(grpName string) NodeGroup {
|
||||
return NodeGroup{Name: &grpName}
|
||||
}
|
||||
|
||||
type DynamicIgnition struct {
|
||||
Name string
|
||||
Key string
|
||||
VMName string
|
||||
WritePath string
|
||||
}
|
||||
|
||||
// NewIgnitionFile
|
||||
func NewIgnitionFile(name, key, writePath string) error {
|
||||
if len(name) < 1 {
|
||||
name = DefaultIgnitionUserName
|
||||
func NewIgnitionFile(ign DynamicIgnition) error {
|
||||
if len(ign.Name) < 1 {
|
||||
ign.Name = DefaultIgnitionUserName
|
||||
}
|
||||
ignVersion := Ignition{
|
||||
Version: "3.2.0",
|
||||
@ -48,23 +56,44 @@ func NewIgnitionFile(name, key, writePath string) error {
|
||||
|
||||
ignPassword := Passwd{
|
||||
Users: []PasswdUser{{
|
||||
Name: name,
|
||||
SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(key)},
|
||||
Name: ign.Name,
|
||||
SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(ign.Key)},
|
||||
}},
|
||||
}
|
||||
|
||||
ignStorage := Storage{
|
||||
Directories: getDirs(name),
|
||||
Files: getFiles(name),
|
||||
Links: getLinks(name),
|
||||
Directories: getDirs(ign.Name),
|
||||
Files: getFiles(ign.Name),
|
||||
Links: getLinks(ign.Name),
|
||||
}
|
||||
|
||||
// ready is a unit file that sets up the virtual serial device
|
||||
// where when the VM is done configuring, it will send an ack
|
||||
// so a listening host knows it can being interacting with it
|
||||
ready := `[Unit]
|
||||
Requires=dev-virtio\\x2dports-%s.device
|
||||
OnFailure=emergency.target
|
||||
OnFailureJobMode=isolate
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/bin/sh -c '/usr/bin/echo Ready >/dev/%s'
|
||||
[Install]
|
||||
RequiredBy=multi-user.target
|
||||
`
|
||||
_ = ready
|
||||
ignSystemd := Systemd{
|
||||
Units: []Unit{
|
||||
{
|
||||
Enabled: boolToPtr(true),
|
||||
Name: "podman.socket",
|
||||
}}}
|
||||
|
||||
},
|
||||
{
|
||||
Enabled: boolToPtr(true),
|
||||
Name: "ready.service",
|
||||
Contents: strToPtr(fmt.Sprintf(ready, "vport1p1", "vport1p1")),
|
||||
},
|
||||
}}
|
||||
ignConfig := Config{
|
||||
Ignition: ignVersion,
|
||||
Passwd: ignPassword,
|
||||
@ -75,7 +104,7 @@ func NewIgnitionFile(name, key, writePath string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(writePath, b, 0644)
|
||||
return ioutil.WriteFile(ign.WritePath, b, 0644)
|
||||
}
|
||||
|
||||
func getDirs(usrName string) []Directory {
|
||||
|
@ -1,9 +1,11 @@
|
||||
package qemu
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
@ -22,9 +24,6 @@ import (
|
||||
var (
|
||||
// vmtype refers to qemu (vs libvirt, krun, etc)
|
||||
vmtype = "qemu"
|
||||
// qemuCommon are the common command line arguments between the arches
|
||||
//qemuCommon = []string{"-cpu", "host", "-qmp", "unix://tmp/qmp.sock,server,nowait"}
|
||||
//qemuCommon = []string{"-cpu", "host", "-qmp", "tcp:localhost:4444,server,nowait"}
|
||||
)
|
||||
|
||||
// NewMachine initializes an instance of a virtual machine based on the qemu
|
||||
@ -89,6 +88,16 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) {
|
||||
// Add network
|
||||
cmd = append(cmd, "-nic", "user,model=virtio,hostfwd=tcp::"+strconv.Itoa(vm.Port)+"-:22")
|
||||
|
||||
socketPath, err := getSocketDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
virtualSocketPath := filepath.Join(socketPath, "podman", vm.Name+"_ready.sock")
|
||||
// Add serial port for readiness
|
||||
cmd = append(cmd, []string{
|
||||
"-device", "virtio-serial",
|
||||
"-chardev", "socket,path=" + virtualSocketPath + ",server,nowait,id=" + vm.Name + "_ready",
|
||||
"-device", "virtserialport,chardev=" + vm.Name + "_ready" + ",name=org.fedoraproject.port.0"}...)
|
||||
vm.CmdLine = cmd
|
||||
return vm, nil
|
||||
}
|
||||
@ -96,13 +105,15 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) {
|
||||
// LoadByName reads a json file that describes a known qemu vm
|
||||
// and returns a vm instance
|
||||
func LoadVMByName(name string) (machine.VM, error) {
|
||||
// TODO need to define an error relating to ErrMachineNotFound
|
||||
vm := new(MachineVM)
|
||||
vmConfigDir, err := machine.GetConfDir(vmtype)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := ioutil.ReadFile(filepath.Join(vmConfigDir, name+".json"))
|
||||
if os.IsNotExist(err) {
|
||||
return nil, errors.Wrap(machine.ErrNoSuchVM, name)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -159,14 +170,28 @@ func (v *MachineVM) Init(opts machine.InitOptions) error {
|
||||
if err := v.prepare(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resize the disk image to input disk size
|
||||
resize := exec.Command("qemu-img", []string{"resize", v.ImagePath, strconv.Itoa(int(opts.DiskSize)) + "G"}...)
|
||||
if err := resize.Run(); err != nil {
|
||||
return errors.Errorf("error resizing image: %q", err)
|
||||
}
|
||||
// Write the ignition file
|
||||
return machine.NewIgnitionFile(opts.Username, key, v.IgnitionFilePath)
|
||||
ign := machine.DynamicIgnition{
|
||||
Name: opts.Username,
|
||||
Key: key,
|
||||
VMName: v.Name,
|
||||
WritePath: v.IgnitionFilePath,
|
||||
}
|
||||
return machine.NewIgnitionFile(ign)
|
||||
}
|
||||
|
||||
// Start executes the qemu command line and forks it
|
||||
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||
var (
|
||||
err error
|
||||
conn net.Conn
|
||||
err error
|
||||
wait time.Duration = time.Millisecond * 500
|
||||
)
|
||||
attr := new(os.ProcAttr)
|
||||
files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
|
||||
@ -181,6 +206,30 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||
}
|
||||
|
||||
_, err = os.StartProcess(v.CmdLine[0], cmd, attr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Waiting for VM ...")
|
||||
socketPath, err := getSocketDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The socket is not made until the qemu process is running so here
|
||||
// we do a backoff waiting for it. Once we have a conn, we break and
|
||||
// then wait to read it.
|
||||
for i := 0; i < 6; i++ {
|
||||
conn, err = net.Dial("unix", filepath.Join(socketPath, "podman", v.Name+"_ready.sock"))
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(wait)
|
||||
wait++
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = bufio.NewReader(conn).ReadString('\n')
|
||||
return err
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user