mirror of https://github.com/containers/podman.git
Merge pull request #10488 from baude/machinehostnetwork
Enable port forwarding on host
This commit is contained in:
commit
cbffdddce6
|
@ -85,7 +85,10 @@ func DefineNetFlags(cmd *cobra.Command) {
|
|||
)
|
||||
}
|
||||
|
||||
func NetFlagsToNetOptions(cmd *cobra.Command) (*entities.NetOptions, error) {
|
||||
// NetFlagsToNetOptions parses the network flags for the given cmd.
|
||||
// The netnsFromConfig bool is used to indicate if the --network flag
|
||||
// should always be parsed regardless if it was set on the cli.
|
||||
func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.NetOptions, error) {
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
@ -193,7 +196,9 @@ func NetFlagsToNetOptions(cmd *cobra.Command) (*entities.NetOptions, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("network") {
|
||||
// parse the --network value only when the flag is set or we need to use
|
||||
// the netns config value, e.g. when --pod is not used
|
||||
if netnsFromConfig || cmd.Flag("network").Changed {
|
||||
network, err := cmd.Flags().GetString("network")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -87,7 +87,7 @@ func create(cmd *cobra.Command, args []string) error {
|
|||
var (
|
||||
err error
|
||||
)
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(cmd)
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ func init() {
|
|||
|
||||
func run(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(cmd)
|
||||
cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -166,10 +166,11 @@ func create(cmd *cobra.Command, args []string) error {
|
|||
defer errorhandling.SyncQuiet(podIDFD)
|
||||
}
|
||||
|
||||
createOptions.Net, err = common.NetFlagsToNetOptions(cmd)
|
||||
createOptions.Net, err = common.NetFlagsToNetOptions(cmd, createOptions.Infra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(createOptions.Net.PublishPorts) > 0 {
|
||||
if !createOptions.Infra {
|
||||
return errors.Errorf("you must have an infra container to publish port bindings to the host")
|
||||
|
|
|
@ -273,7 +273,6 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) {
|
|||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating rootless cni network namespace")
|
||||
}
|
||||
|
||||
// setup slirp4netns here
|
||||
path := r.config.Engine.NetworkCmdPath
|
||||
if path == "" {
|
||||
|
@ -437,9 +436,32 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) {
|
|||
return rootlessCNINS, nil
|
||||
}
|
||||
|
||||
// setPrimaryMachineIP is used for podman-machine and it sets
|
||||
// and environment variable with the IP address of the podman-machine
|
||||
// host.
|
||||
func setPrimaryMachineIP() error {
|
||||
// no connection is actually made here
|
||||
conn, err := net.Dial("udp", "8.8.8.8:80")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err := conn.Close(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
addr := conn.LocalAddr().(*net.UDPAddr)
|
||||
return os.Setenv("PODMAN_MACHINE_HOST", addr.IP.String())
|
||||
}
|
||||
|
||||
// setUpOCICNIPod will set up the cni networks, on error it will also tear down the cni
|
||||
// networks. If rootless it will join/create the rootless cni namespace.
|
||||
func (r *Runtime) setUpOCICNIPod(podNetwork ocicni.PodNetwork) ([]ocicni.NetResult, error) {
|
||||
if r.config.MachineEnabled() {
|
||||
if err := setPrimaryMachineIP(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
rootlessCNINS, err := r.GetRootlessCNINetNs(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -32,6 +32,7 @@ var (
|
|||
ErrVMAlreadyExists = errors.New("VM already exists")
|
||||
ErrVMAlreadyRunning = errors.New("VM already running")
|
||||
ErrMultipleActiveVM = errors.New("only one VM can be active at a time")
|
||||
ForwarderBinaryName = "gvproxy"
|
||||
)
|
||||
|
||||
type Download struct {
|
||||
|
|
|
@ -118,6 +118,7 @@ func getDirs(usrName string) []Directory {
|
|||
// in one swoop, then the leading dirs are creates as root.
|
||||
newDirs := []string{
|
||||
"/home/" + usrName + "/.config",
|
||||
"/home/" + usrName + "/.config/containers",
|
||||
"/home/" + usrName + "/.config/systemd",
|
||||
"/home/" + usrName + "/.config/systemd/user",
|
||||
"/home/" + usrName + "/.config/systemd/user/default.target.wants",
|
||||
|
@ -159,6 +160,22 @@ func getFiles(usrName string) []File {
|
|||
},
|
||||
})
|
||||
|
||||
// Set containers.conf up for core user to use cni networks
|
||||
// by default
|
||||
files = append(files, File{
|
||||
Node: Node{
|
||||
Group: getNodeGrp(usrName),
|
||||
Path: "/home/" + usrName + "/.config/containers/containers.conf",
|
||||
User: getNodeUsr(usrName),
|
||||
},
|
||||
FileEmbedded1: FileEmbedded1{
|
||||
Append: nil,
|
||||
Contents: Resource{
|
||||
Source: strToPtr("data:,%5Bcontainers%5D%0D%0Anetns%3D%22bridge%22%0D%0Arootless_networking%3D%22cni%22"),
|
||||
},
|
||||
Mode: intToPtr(484),
|
||||
},
|
||||
})
|
||||
// Add a file into linger
|
||||
files = append(files, File{
|
||||
Node: Node{
|
||||
|
|
|
@ -13,6 +13,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
|
||||
"github.com/containers/podman/v3/pkg/machine"
|
||||
"github.com/containers/podman/v3/utils"
|
||||
"github.com/containers/storage/pkg/homedir"
|
||||
|
@ -82,9 +84,10 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) {
|
|||
cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address + ",server=on,wait=off"}...)
|
||||
|
||||
// Add network
|
||||
cmd = append(cmd, "-nic", "user,model=virtio,hostfwd=tcp::"+strconv.Itoa(vm.Port)+"-:22")
|
||||
|
||||
socketPath, err := getSocketDir()
|
||||
// Right now the mac address is hardcoded so that the host networking gives it a specific IP address. This is
|
||||
// why we can only run one vm at a time right now
|
||||
cmd = append(cmd, []string{"-netdev", "socket,id=vlan,fd=3", "-device", "virtio-net-pci,netdev=vlan,mac=5a:94:ef:e4:0c:ee"}...)
|
||||
socketPath, err := getRuntimeDir()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -235,12 +238,35 @@ func (v *MachineVM) Init(opts machine.InitOptions) error {
|
|||
// Start executes the qemu command line and forks it
|
||||
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
||||
var (
|
||||
conn net.Conn
|
||||
err error
|
||||
wait time.Duration = time.Millisecond * 500
|
||||
conn net.Conn
|
||||
err error
|
||||
qemuSocketConn net.Conn
|
||||
wait time.Duration = time.Millisecond * 500
|
||||
)
|
||||
if err := v.startHostNetworking(); err != nil {
|
||||
return errors.Errorf("unable to start host networking: %q", err)
|
||||
}
|
||||
qemuSocketPath, _, err := v.getSocketandPid()
|
||||
|
||||
for i := 0; i < 6; i++ {
|
||||
qemuSocketConn, err = net.Dial("unix", qemuSocketPath)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(wait)
|
||||
wait++
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fd, err := qemuSocketConn.(*net.UnixConn).File()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attr := new(os.ProcAttr)
|
||||
files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
|
||||
files := []*os.File{os.Stdin, os.Stdout, os.Stderr, fd}
|
||||
attr.Files = files
|
||||
logrus.Debug(v.CmdLine)
|
||||
cmd := v.CmdLine
|
||||
|
@ -256,7 +282,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
|
|||
return err
|
||||
}
|
||||
fmt.Println("Waiting for VM ...")
|
||||
socketPath, err := getSocketDir()
|
||||
socketPath, err := getRuntimeDir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -309,16 +335,42 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
|
|||
logrus.Error(err)
|
||||
}
|
||||
}()
|
||||
_, err = qmpMonitor.Run(input)
|
||||
return err
|
||||
if _, err = qmpMonitor.Run(input); err != nil {
|
||||
return err
|
||||
}
|
||||
_, pidFile, err := v.getSocketandPid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := os.Stat(pidFile); os.IsNotExist(err) {
|
||||
logrus.Infof("pid file %s does not exist", pidFile)
|
||||
return nil
|
||||
}
|
||||
pidString, err := ioutil.ReadFile(pidFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pidNum, err := strconv.Atoi(string(pidString))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p, err := os.FindProcess(pidNum)
|
||||
if p == nil && err != nil {
|
||||
return err
|
||||
}
|
||||
return p.Kill()
|
||||
}
|
||||
|
||||
// NewQMPMonitor creates the monitor subsection of our vm
|
||||
func NewQMPMonitor(network, name string, timeout time.Duration) (Monitor, error) {
|
||||
rtDir, err := getSocketDir()
|
||||
rtDir, err := getRuntimeDir()
|
||||
if err != nil {
|
||||
return Monitor{}, err
|
||||
}
|
||||
if !rootless.IsRootless() {
|
||||
rtDir = "/run"
|
||||
}
|
||||
rtDir = filepath.Join(rtDir, "podman")
|
||||
if _, err := os.Stat(filepath.Join(rtDir)); os.IsNotExist(err) {
|
||||
// TODO 0644 is fine on linux but macos is weird
|
||||
|
@ -533,3 +585,47 @@ func CheckActiveVM() (bool, string, error) {
|
|||
}
|
||||
return false, "", nil
|
||||
}
|
||||
|
||||
// startHostNetworking runs a binary on the host system that allows users
|
||||
// to setup port forwarding to the podman virtual machine
|
||||
func (v *MachineVM) startHostNetworking() error {
|
||||
binary, err := exec.LookPath(machine.ForwarderBinaryName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Listen on all at port 7777 for setting up and tearing
|
||||
// down forwarding
|
||||
listenSocket := "tcp://0.0.0.0:7777"
|
||||
qemuSocket, pidFile, err := v.getSocketandPid()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attr := new(os.ProcAttr)
|
||||
// Pass on stdin, stdout, stderr
|
||||
files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
|
||||
attr.Files = files
|
||||
cmd := []string{binary}
|
||||
cmd = append(cmd, []string{"-listen", listenSocket, "-listen-qemu", fmt.Sprintf("unix://%s", qemuSocket), "-pid-file", pidFile}...)
|
||||
// Add the ssh port
|
||||
cmd = append(cmd, []string{"-ssh-port", fmt.Sprintf("%d", v.Port)}...)
|
||||
if logrus.GetLevel() == logrus.DebugLevel {
|
||||
cmd = append(cmd, "--debug")
|
||||
fmt.Println(cmd)
|
||||
}
|
||||
_, err = os.StartProcess(cmd[0], cmd, attr)
|
||||
return err
|
||||
}
|
||||
|
||||
func (v *MachineVM) getSocketandPid() (string, string, error) {
|
||||
rtPath, err := getRuntimeDir()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
if !rootless.IsRootless() {
|
||||
rtPath = "/run"
|
||||
}
|
||||
socketDir := filepath.Join(rtPath, "podman")
|
||||
pidFile := filepath.Join(socketDir, fmt.Sprintf("%s.pid", v.Name))
|
||||
qemuSocket := filepath.Join(socketDir, fmt.Sprintf("qemu_%s.sock", v.Name))
|
||||
return qemuSocket, pidFile, nil
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func getSocketDir() (string, error) {
|
||||
func getRuntimeDir() (string, error) {
|
||||
tmpDir, ok := os.LookupEnv("TMPDIR")
|
||||
if !ok {
|
||||
return "", errors.New("unable to resolve TMPDIR")
|
||||
|
|
|
@ -5,7 +5,7 @@ var (
|
|||
)
|
||||
|
||||
func (v *MachineVM) addArchOptions() []string {
|
||||
opts := []string{"-cpu", "host"}
|
||||
opts := []string{"-machine", "q35,accel=hvf:tcg"}
|
||||
return opts
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
package qemu
|
||||
|
||||
import "github.com/containers/podman/v3/pkg/util"
|
||||
import (
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
)
|
||||
|
||||
func getSocketDir() (string, error) {
|
||||
func getRuntimeDir() (string, error) {
|
||||
if !rootless.IsRootless() {
|
||||
return "/run", nil
|
||||
}
|
||||
return util.GetRuntimeDir()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue