Enabled network over vsock

podman machine with Microsoft HyperV will use hvsock on the guest and
vsock on the guest for its networking.  this pr enables the basics for
this to happen as well as changes to ignition to automatically set this
up with network manager.

the vm binary referenced in this pr is in containers/gvisor-tap-vsock
and will need to be added to distributions.

[NO NEW TESTS NEEDED]
Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
Brent Baude 2023-04-14 13:44:41 -05:00
parent ef4dbc27b0
commit 3222545ad5
10 changed files with 257 additions and 106 deletions

2
go.mod
View File

@ -16,7 +16,7 @@ require (
github.com/containers/common v0.52.1-0.20230411124844-19b624d9a20d github.com/containers/common v0.52.1-0.20230411124844-19b624d9a20d
github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.25.0 github.com/containers/image/v5 v5.25.0
github.com/containers/libhvee v0.0.2 github.com/containers/libhvee v0.0.4
github.com/containers/ocicrypt v1.1.7 github.com/containers/ocicrypt v1.1.7
github.com/containers/psgo v1.8.0 github.com/containers/psgo v1.8.0
github.com/containers/storage v1.46.1 github.com/containers/storage v1.46.1

4
go.sum
View File

@ -245,8 +245,8 @@ github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6J
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.25.0 h1:TJ0unmalbU+scd0i3Txap2wjGsAnv06MSCwgn6bsizk= github.com/containers/image/v5 v5.25.0 h1:TJ0unmalbU+scd0i3Txap2wjGsAnv06MSCwgn6bsizk=
github.com/containers/image/v5 v5.25.0/go.mod h1:EKvys0WVlRFkDw26R8y52TuhV9Tfn0yq2luLX6W52Ls= github.com/containers/image/v5 v5.25.0/go.mod h1:EKvys0WVlRFkDw26R8y52TuhV9Tfn0yq2luLX6W52Ls=
github.com/containers/libhvee v0.0.2 h1:eWtbOvpT8bD9jvksMES2yXUmEpcE0zENWkci+bbP7U8= github.com/containers/libhvee v0.0.4 h1:pt03gr9B0mhqg/pyzGHzQzRK1XVvFODWzwBQXNPY1SY=
github.com/containers/libhvee v0.0.2/go.mod h1:bV1MfbuXk/ZLWHiWZpm8aePOR6iJGD1q55guYhH4CnA= github.com/containers/libhvee v0.0.4/go.mod h1:AYsyMe44w9ylWWEZNW+IOzA7oZ2i/P9TChNljavhYMI=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=

View File

@ -15,8 +15,10 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/containers/common/pkg/config"
"github.com/containers/libhvee/pkg/hypervctl" "github.com/containers/libhvee/pkg/hypervctl"
"github.com/containers/podman/v4/pkg/machine" "github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/homedir" "github.com/containers/storage/pkg/homedir"
"github.com/docker/go-units" "github.com/docker/go-units"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -102,6 +104,15 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
sshDir := filepath.Join(homedir.Get(), ".ssh") sshDir := filepath.Join(homedir.Get(), ".ssh")
m.IdentityPath = filepath.Join(sshDir, m.Name) m.IdentityPath = filepath.Join(sshDir, m.Name)
// TODO This needs to be fixed in c-common
m.RemoteUsername = "core"
sshPort, err := utils.GetRandomPort()
if err != nil {
return false, err
}
m.Port = sshPort
if len(opts.IgnitionPath) < 1 { if len(opts.IgnitionPath) < 1 {
uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", fmt.Sprintf("/run/user/%d/podman/podman.sock", m.UID), strconv.Itoa(m.Port), m.RemoteUsername) uri := machine.SSHRemoteConnection.MakeSSHURL("localhost", fmt.Sprintf("/run/user/%d/podman/podman.sock", m.UID), strconv.Itoa(m.Port), m.RemoteUsername)
uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(m.Port), "root") uriRoot := machine.SSHRemoteConnection.MakeSSHURL("localhost", "/run/podman/podman.sock", strconv.Itoa(m.Port), "root")
@ -205,7 +216,61 @@ RequiredBy=default.target
Name: "ready.service", Name: "ready.service",
Contents: machine.StrToPtr(fmt.Sprintf(ready, m.ReadyHVSock.Port)), Contents: machine.StrToPtr(fmt.Sprintf(ready, m.ReadyHVSock.Port)),
} }
ign.Cfg.Systemd.Units = append(ign.Cfg.Systemd.Units, readyUnit)
// userNetwork is a systemd unit file that calls the vm helpoer utility
// needed to take traffic from a network vsock0 device to the actual vsock
// and onto the host
userNetwork := `
[Unit]
Description=vsock_network
After=NetworkManager.service
[Service]
ExecStart=/usr/libexec/podman/vm -preexisting -iface vsock0 -url vsock://2:%d/connect
ExecStartPost=/usr/bin/nmcli c up vsock0
[Install]
WantedBy=multi-user.target
`
vsockNetUnit := machine.Unit{
Contents: machine.StrToPtr(fmt.Sprintf(userNetwork, m.NetworkHVSock.Port)),
Enabled: machine.BoolToPtr(true),
Name: "vsock-network.service",
}
ign.Cfg.Systemd.Units = append(ign.Cfg.Systemd.Units, readyUnit, vsockNetUnit)
vSockNMConnection := `
[connection]
id=vsock0
type=tun
interface-name=vsock0
[tun]
mode=2
[802-3-ethernet]
cloned-mac-address=5A:94:EF:E4:0C:EE
[ipv4]
method=auto
[proxy]
`
ign.Cfg.Storage.Files = append(ign.Cfg.Storage.Files, machine.File{
Node: machine.Node{
Path: "/etc/NetworkManager/system-connections/vsock0.nmconnection",
},
FileEmbedded1: machine.FileEmbedded1{
Append: nil,
Contents: machine.Resource{
Source: machine.EncodeDataURLPtr(vSockNMConnection),
},
Mode: machine.IntToPtr(0600),
},
})
if err := ign.Write(); err != nil { if err := ign.Write(); err != nil {
return false, err return false, err
} }
@ -388,7 +453,19 @@ func (m *HyperVMachine) Set(name string, opts machine.SetOptions) ([]error, erro
} }
func (m *HyperVMachine) SSH(name string, opts machine.SSHOptions) error { func (m *HyperVMachine) SSH(name string, opts machine.SSHOptions) error {
return machine.ErrNotImplemented state, err := m.State(false)
if err != nil {
return err
}
if state != machine.Running {
return fmt.Errorf("vm %q is not running", m.Name)
}
username := opts.Username
if username == "" {
username = m.RemoteUsername
}
return machine.CommonSSH(username, m.IdentityPath, m.Name, m.Port, opts.Args)
} }
func (m *HyperVMachine) Start(name string, opts machine.StartOptions) error { func (m *HyperVMachine) Start(name string, opts machine.StartOptions) error {
@ -401,6 +478,10 @@ func (m *HyperVMachine) Start(name string, opts machine.StartOptions) error {
if vm.State() != hypervctl.Disabled { if vm.State() != hypervctl.Disabled {
return hypervctl.ErrMachineStateInvalid return hypervctl.ErrMachineStateInvalid
} }
_, _, err = m.startHostNetworking()
if err != nil {
return fmt.Errorf("unable to start host networking: %q", err)
}
if err := vm.Start(); err != nil { if err := vm.Start(); err != nil {
return err return err
} }
@ -501,3 +582,54 @@ func loadMacMachineFromJSON(fqConfigPath string, macMachine *HyperVMachine) erro
} }
return json.Unmarshal(b, macMachine) return json.Unmarshal(b, macMachine)
} }
func (m *HyperVMachine) startHostNetworking() (string, apiForwardingState, error) {
cfg, err := config.Default()
if err != nil {
return "", noForwarding, err
}
attr := new(os.ProcAttr)
dnr, err := os.OpenFile(os.DevNull, os.O_RDONLY, 0755)
if err != nil {
return "", noForwarding, err
}
dnw, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0755)
if err != nil {
return "", noForwarding, err
}
defer func() {
if err := dnr.Close(); err != nil {
logrus.Error(err)
}
}()
defer func() {
if err := dnw.Close(); err != nil {
logrus.Error(err)
}
}()
gvproxy, err := cfg.FindHelperBinary("gvproxy.exe", false)
if err != nil {
return "", 0, err
}
attr.Files = []*os.File{dnr, dnw, dnw}
cmd := []string{gvproxy}
// Add the ssh port
cmd = append(cmd, []string{"-ssh-port", fmt.Sprintf("%d", m.Port)}...)
cmd = append(cmd, []string{"-listen", fmt.Sprintf("vsock://%s", m.NetworkHVSock.KeyName)}...)
var forwardSock string
if logrus.GetLevel() == logrus.DebugLevel {
cmd = append(cmd, "--debug")
fmt.Println(cmd)
}
_, err = os.StartProcess(cmd[0], cmd, attr)
if err != nil {
return "", 0, fmt.Errorf("unable to execute: %q: %w", cmd, err)
}
return forwardSock, noForwarding, nil
}

View File

@ -239,7 +239,7 @@ func LoadHVSockRegistryEntry(port uint64) (*HVSockRegistryEntry, error) {
}, nil }, nil
} }
// Listen s used on the windows side to listen for anything to come // Listen is used on the windows side to listen for anything to come
// over the hvsock as a signal the vm is booted // over the hvsock as a signal the vm is booted
func (hv *HVSockRegistryEntry) Listen() error { func (hv *HVSockRegistryEntry) Listen() error {
n := winio.HvsockAddr{ n := winio.HvsockAddr{

View File

@ -29,7 +29,7 @@ const (
) )
// Convenience function to convert int to ptr // Convenience function to convert int to ptr
func intToPtr(i int) *int { func IntToPtr(i int) *int {
return &i return &i
} }
@ -43,11 +43,11 @@ func BoolToPtr(b bool) *bool {
return &b return &b
} }
func getNodeUsr(usrName string) NodeUser { func GetNodeUsr(usrName string) NodeUser {
return NodeUser{Name: &usrName} return NodeUser{Name: &usrName}
} }
func getNodeGrp(grpName string) NodeGroup { func GetNodeGrp(grpName string) NodeGroup {
return NodeGroup{Name: &grpName} return NodeGroup{Name: &grpName}
} }
@ -84,7 +84,8 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error {
Name: ign.Name, Name: ign.Name,
SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(ign.Key)}, SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(ign.Key)},
// Set the UID of the core user inside the machine // Set the UID of the core user inside the machine
UID: intToPtr(ign.UID), UID: IntToPtr(ign.UID),
PasswordHash: StrToPtr("$y$j9T$/us37H88.4.5WydimEMC3/$f0sz48KNYevw7RO8iT.9gjmqaUlpmhwfdk7nlTql8QB"),
}, },
{ {
Name: "root", Name: "root",
@ -117,10 +118,10 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error {
} }
tzLink := Link{ tzLink := Link{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/localtime", Path: "/etc/localtime",
Overwrite: BoolToPtr(false), Overwrite: BoolToPtr(false),
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
LinkEmbedded1: LinkEmbedded1{ LinkEmbedded1: LinkEmbedded1{
Hard: BoolToPtr(false), Hard: BoolToPtr(false),
@ -240,11 +241,11 @@ func getDirs(usrName string) []Directory {
for i, d := range newDirs { for i, d := range newDirs {
newDir := Directory{ newDir := Directory{
Node: Node{ Node: Node{
Group: getNodeGrp(usrName), Group: GetNodeGrp(usrName),
Path: d, Path: d,
User: getNodeUsr(usrName), User: GetNodeUsr(usrName),
}, },
DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)},
} }
dirs[i] = newDir dirs[i] = newDir
} }
@ -256,11 +257,11 @@ func getDirs(usrName string) []Directory {
// as a workaround. // as a workaround.
dirs = append(dirs, Directory{ dirs = append(dirs, Directory{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/containers/registries.conf.d", Path: "/etc/containers/registries.conf.d",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)},
}) })
// The directory is used by envset-fwcfg.service // The directory is used by envset-fwcfg.service
@ -268,18 +269,18 @@ func getDirs(usrName string) []Directory {
// from a host // from a host
dirs = append(dirs, Directory{ dirs = append(dirs, Directory{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/systemd/system.conf.d", Path: "/etc/systemd/system.conf.d",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)},
}, Directory{ }, Directory{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/environment.d", Path: "/etc/environment.d",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)}, DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)},
}) })
return dirs return dirs
@ -312,16 +313,16 @@ Delegate=memory pids cpu io
// Add a fake systemd service to get the user socket rolling // Add a fake systemd service to get the user socket rolling
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp(usrName), Group: GetNodeGrp(usrName),
Path: "/home/" + usrName + "/.config/systemd/user/linger-example.service", Path: "/home/" + usrName + "/.config/systemd/user/linger-example.service",
User: getNodeUsr(usrName), User: GetNodeUsr(usrName),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr(lingerExample), Source: EncodeDataURLPtr(lingerExample),
}, },
Mode: intToPtr(0744), Mode: IntToPtr(0744),
}, },
}) })
@ -329,16 +330,16 @@ Delegate=memory pids cpu io
// by default // by default
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp(usrName), Group: GetNodeGrp(usrName),
Path: "/home/" + usrName + "/.config/containers/containers.conf", Path: "/home/" + usrName + "/.config/containers/containers.conf",
User: getNodeUsr(usrName), User: GetNodeUsr(usrName),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr(containers), Source: EncodeDataURLPtr(containers),
}, },
Mode: intToPtr(0744), Mode: IntToPtr(0744),
}, },
}) })
@ -346,17 +347,17 @@ Delegate=memory pids cpu io
for _, sub := range []string{"/etc/subuid", "/etc/subgid"} { for _, sub := range []string{"/etc/subuid", "/etc/subgid"} {
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: sub, Path: sub,
User: getNodeUsr("root"), User: GetNodeUsr("root"),
Overwrite: BoolToPtr(true), Overwrite: BoolToPtr(true),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr(fmt.Sprintf(subUID, usrName)), Source: EncodeDataURLPtr(fmt.Sprintf(subUID, usrName)),
}, },
Mode: intToPtr(0744), Mode: IntToPtr(0744),
}, },
}) })
} }
@ -365,59 +366,59 @@ Delegate=memory pids cpu io
// by default // by default
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/systemd/system/user@.service.d/delegate.conf", Path: "/etc/systemd/system/user@.service.d/delegate.conf",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr(delegateConf), Source: EncodeDataURLPtr(delegateConf),
}, },
Mode: intToPtr(0644), Mode: IntToPtr(0644),
}, },
}) })
// Add a file into linger // Add a file into linger
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp(usrName), Group: GetNodeGrp(usrName),
Path: "/var/lib/systemd/linger/core", Path: "/var/lib/systemd/linger/core",
User: getNodeUsr(usrName), User: GetNodeUsr(usrName),
}, },
FileEmbedded1: FileEmbedded1{Mode: intToPtr(0644)}, FileEmbedded1: FileEmbedded1{Mode: IntToPtr(0644)},
}) })
// Set deprecated machine_enabled to true to indicate we're in a VM // Set deprecated machine_enabled to true to indicate we're in a VM
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/containers/containers.conf", Path: "/etc/containers/containers.conf",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr(rootContainers), Source: EncodeDataURLPtr(rootContainers),
}, },
Mode: intToPtr(0644), Mode: IntToPtr(0644),
}, },
}) })
// Set machine marker file to indicate podman is in a qemu based machine // Set machine marker file to indicate podman is in a qemu based machine
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/containers/podman-machine", Path: "/etc/containers/podman-machine",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
// TODO this should be fixed for all vmtypes // TODO this should be fixed for all vmtypes
Source: encodeDataURLPtr("qemu\n"), Source: EncodeDataURLPtr("qemu\n"),
}, },
Mode: intToPtr(0644), Mode: IntToPtr(0644),
}, },
}) })
@ -428,16 +429,16 @@ Delegate=memory pids cpu io
// as a workaround. // as a workaround.
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/containers/registries.conf.d/999-podman-machine.conf", Path: "/etc/containers/registries.conf.d/999-podman-machine.conf",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr("unqualified-search-registries=[\"docker.io\"]\n"), Source: EncodeDataURLPtr("unqualified-search-registries=[\"docker.io\"]\n"),
}, },
Mode: intToPtr(0644), Mode: IntToPtr(0644),
}, },
}) })
@ -450,9 +451,9 @@ Delegate=memory pids cpu io
// Create a symlink from the docker socket to the podman socket. // Create a symlink from the docker socket to the podman socket.
// Taken from https://github.com/containers/podman/blob/main/contrib/systemd/system/podman-docker.conf // Taken from https://github.com/containers/podman/blob/main/contrib/systemd/system/podman-docker.conf
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr("L+ /run/docker.sock - - - - /run/podman/podman.sock\n"), Source: EncodeDataURLPtr("L+ /run/docker.sock - - - - /run/podman/podman.sock\n"),
}, },
Mode: intToPtr(0644), Mode: IntToPtr(0644),
}, },
}) })
@ -461,16 +462,16 @@ Delegate=memory pids cpu io
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/profile.d/docker-host.sh", Path: "/etc/profile.d/docker-host.sh",
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr(setDockerHost), Source: EncodeDataURLPtr(setDockerHost),
}, },
Mode: intToPtr(0644), Mode: IntToPtr(0644),
}, },
}) })
@ -507,13 +508,13 @@ Delegate=memory pids cpu io
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
User: getNodeUsr("root"), User: GetNodeUsr("root"),
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/chrony.conf", Path: "/etc/chrony.conf",
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: []Resource{{ Append: []Resource{{
Source: encodeDataURLPtr("\nconfdir /etc/chrony.d\n"), Source: EncodeDataURLPtr("\nconfdir /etc/chrony.d\n"),
}}, }},
}, },
}) })
@ -522,13 +523,13 @@ Delegate=memory pids cpu io
// far from NTP time. // far from NTP time.
files = append(files, File{ files = append(files, File{
Node: Node{ Node: Node{
User: getNodeUsr("root"), User: GetNodeUsr("root"),
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/etc/chrony.d/50-podman-makestep.conf", Path: "/etc/chrony.d/50-podman-makestep.conf",
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr("makestep 1 -1\n"), Source: EncodeDataURLPtr("makestep 1 -1\n"),
}, },
}, },
}) })
@ -587,16 +588,16 @@ func prepareCertFile(path string, name string) (File, error) {
file := File{ file := File{
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: targetPath, Path: targetPath,
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
FileEmbedded1: FileEmbedded1{ FileEmbedded1: FileEmbedded1{
Append: nil, Append: nil,
Contents: Resource{ Contents: Resource{
Source: encodeDataURLPtr(string(b)), Source: EncodeDataURLPtr(string(b)),
}, },
Mode: intToPtr(0644), Mode: IntToPtr(0644),
}, },
} }
return file, nil return file, nil
@ -615,9 +616,9 @@ func GetProxyVariables() map[string]string {
func getLinks(usrName string) []Link { func getLinks(usrName string) []Link {
return []Link{{ return []Link{{
Node: Node{ Node: Node{
Group: getNodeGrp(usrName), Group: GetNodeGrp(usrName),
Path: "/home/" + usrName + "/.config/systemd/user/default.target.wants/linger-example.service", Path: "/home/" + usrName + "/.config/systemd/user/default.target.wants/linger-example.service",
User: getNodeUsr(usrName), User: GetNodeUsr(usrName),
}, },
LinkEmbedded1: LinkEmbedded1{ LinkEmbedded1: LinkEmbedded1{
Hard: BoolToPtr(false), Hard: BoolToPtr(false),
@ -625,10 +626,10 @@ func getLinks(usrName string) []Link {
}, },
}, { }, {
Node: Node{ Node: Node{
Group: getNodeGrp("root"), Group: GetNodeGrp("root"),
Path: "/usr/local/bin/docker", Path: "/usr/local/bin/docker",
Overwrite: BoolToPtr(true), Overwrite: BoolToPtr(true),
User: getNodeUsr("root"), User: GetNodeUsr("root"),
}, },
LinkEmbedded1: LinkEmbedded1{ LinkEmbedded1: LinkEmbedded1{
Hard: BoolToPtr(false), Hard: BoolToPtr(false),
@ -637,6 +638,6 @@ func getLinks(usrName string) []Link {
}} }}
} }
func encodeDataURLPtr(contents string) *string { func EncodeDataURLPtr(contents string) *string {
return StrToPtr(fmt.Sprintf("data:,%s", url.PathEscape(contents))) return StrToPtr(fmt.Sprintf("data:,%s", url.PathEscape(contents)))
} }

View File

@ -1069,25 +1069,7 @@ func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error {
username = v.RemoteUsername username = v.RemoteUsername
} }
sshDestination := username + "@localhost" return machine.CommonSSH(username, v.IdentityPath, v.Name, v.Port, opts.Args)
port := strconv.Itoa(v.Port)
args := []string{"-i", v.IdentityPath, "-p", port, sshDestination,
"-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR", "-o", "SetEnv=LC_ALL="}
if len(opts.Args) > 0 {
args = append(args, opts.Args...)
} else {
fmt.Printf("Connecting to vm %s. To close connection, use `~.` or `exit`\n", v.Name)
}
cmd := exec.Command("ssh", args...)
logrus.Debugf("Executing: ssh %v\n", args)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
return cmd.Run()
} }
// executes qemu-image info to get the virtual disk size // executes qemu-image info to get the virtual disk size

34
pkg/machine/ssh.go Normal file
View File

@ -0,0 +1,34 @@
package machine
import (
"fmt"
"os"
"os/exec"
"strconv"
"github.com/sirupsen/logrus"
)
// CommonSSH is a common function for ssh'ing to a podman machine using system-connections
// and a port
func CommonSSH(username, identityPath, name string, sshPort int, inputArgs []string) error {
sshDestination := username + "@localhost"
port := strconv.Itoa(sshPort)
args := []string{"-i", identityPath, "-p", port, sshDestination,
"-o", "StrictHostKeyChecking=no", "-o", "LogLevel=ERROR", "-o", "SetEnv=LC_ALL="}
if len(inputArgs) > 0 {
args = append(args, inputArgs...)
} else {
fmt.Printf("Connecting to vm %s. To close connection, use `~.` or `exit`\n", name)
}
cmd := exec.Command("ssh", args...)
logrus.Debugf("Executing: ssh %v\n", args)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
return cmd.Run()
}

View File

@ -395,9 +395,6 @@ func (vmm *VirtualMachineManager) NewVirtualMachine(name string, config *Hardwar
return err return err
} }
//if err := vmm.CreateVhdxFile(config.DiskPath, config.DiskSize*1024*1024*1024); err != nil {
// return err
//}
if err := NewDriveSettingsBuilder(systemSettings). if err := NewDriveSettingsBuilder(systemSettings).
AddScsiController(). AddScsiController().
AddSyntheticDiskDrive(0). AddSyntheticDiskDrive(0).
@ -416,13 +413,15 @@ func (vmm *VirtualMachineManager) NewVirtualMachine(name string, config *Hardwar
return err return err
} }
// Add default network connection // Add default network connection
if err := NewNetworkSettingsBuilder(systemSettings). if config.Network {
AddSyntheticEthernetPort(nil). if err := NewNetworkSettingsBuilder(systemSettings).
AddEthernetPortAllocation(""). // "" = connect to default switch AddSyntheticEthernetPort(nil).
Finish(). // allocation AddEthernetPortAllocation(""). // "" = connect to default switch
Finish(). // port Finish(). // allocation
Complete(); err != nil { Finish(). // port
return err Complete(); err != nil {
return err
}
} }
return nil return nil
} }

View File

@ -98,6 +98,9 @@ type HardwareConfig struct {
DiskSize uint64 DiskSize uint64
// Memory in megabytes assigned to the vm // Memory in megabytes assigned to the vm
Memory int32 Memory int32
// Network is bool to add a Network Connection to the
// default network switch in Microsoft HyperV
Network bool
} }
type Statuses struct { type Statuses struct {

2
vendor/modules.txt vendored
View File

@ -249,7 +249,7 @@ github.com/containers/image/v5/transports
github.com/containers/image/v5/transports/alltransports github.com/containers/image/v5/transports/alltransports
github.com/containers/image/v5/types github.com/containers/image/v5/types
github.com/containers/image/v5/version github.com/containers/image/v5/version
# github.com/containers/libhvee v0.0.2 # github.com/containers/libhvee v0.0.4
## explicit; go 1.18 ## explicit; go 1.18
github.com/containers/libhvee/pkg/hypervctl github.com/containers/libhvee/pkg/hypervctl
github.com/containers/libhvee/pkg/kvp/ginsu github.com/containers/libhvee/pkg/kvp/ginsu