Merge pull request #18236 from baude/vsock0

Enabled network over vsock
This commit is contained in:
OpenShift Merge Robot
2023-04-17 17:25:24 -04:00
committed by GitHub
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/conmon v2.0.20+incompatible
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/psgo v1.8.0
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/image/v5 v5.25.0 h1:TJ0unmalbU+scd0i3Txap2wjGsAnv06MSCwgn6bsizk=
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.2/go.mod h1:bV1MfbuXk/ZLWHiWZpm8aePOR6iJGD1q55guYhH4CnA=
github.com/containers/libhvee v0.0.4 h1:pt03gr9B0mhqg/pyzGHzQzRK1XVvFODWzwBQXNPY1SY=
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/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=

View File

@@ -15,8 +15,10 @@ import (
"strconv"
"time"
"github.com/containers/common/pkg/config"
"github.com/containers/libhvee/pkg/hypervctl"
"github.com/containers/podman/v4/pkg/machine"
"github.com/containers/podman/v4/utils"
"github.com/containers/storage/pkg/homedir"
"github.com/docker/go-units"
"github.com/sirupsen/logrus"
@@ -102,6 +104,15 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
sshDir := filepath.Join(homedir.Get(), ".ssh")
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 {
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")
@@ -205,7 +216,61 @@ RequiredBy=default.target
Name: "ready.service",
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 {
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 {
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 {
@@ -401,6 +478,10 @@ func (m *HyperVMachine) Start(name string, opts machine.StartOptions) error {
if vm.State() != hypervctl.Disabled {
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 {
return err
}
@@ -501,3 +582,54 @@ func loadMacMachineFromJSON(fqConfigPath string, macMachine *HyperVMachine) erro
}
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
}
// 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
func (hv *HVSockRegistryEntry) Listen() error {
n := winio.HvsockAddr{

View File

@@ -29,7 +29,7 @@ const (
)
// Convenience function to convert int to ptr
func intToPtr(i int) *int {
func IntToPtr(i int) *int {
return &i
}
@@ -43,11 +43,11 @@ func BoolToPtr(b bool) *bool {
return &b
}
func getNodeUsr(usrName string) NodeUser {
func GetNodeUsr(usrName string) NodeUser {
return NodeUser{Name: &usrName}
}
func getNodeGrp(grpName string) NodeGroup {
func GetNodeGrp(grpName string) NodeGroup {
return NodeGroup{Name: &grpName}
}
@@ -84,7 +84,8 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error {
Name: ign.Name,
SSHAuthorizedKeys: []SSHAuthorizedKey{SSHAuthorizedKey(ign.Key)},
// 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",
@@ -117,10 +118,10 @@ func (ign *DynamicIgnition) GenerateIgnitionConfig() error {
}
tzLink := Link{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/localtime",
Overwrite: BoolToPtr(false),
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
LinkEmbedded1: LinkEmbedded1{
Hard: BoolToPtr(false),
@@ -240,11 +241,11 @@ func getDirs(usrName string) []Directory {
for i, d := range newDirs {
newDir := Directory{
Node: Node{
Group: getNodeGrp(usrName),
Group: GetNodeGrp(usrName),
Path: d,
User: getNodeUsr(usrName),
User: GetNodeUsr(usrName),
},
DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)},
DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)},
}
dirs[i] = newDir
}
@@ -256,11 +257,11 @@ func getDirs(usrName string) []Directory {
// as a workaround.
dirs = append(dirs, Directory{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
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
@@ -268,18 +269,18 @@ func getDirs(usrName string) []Directory {
// from a host
dirs = append(dirs, Directory{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/systemd/system.conf.d",
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)},
DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)},
}, Directory{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/environment.d",
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
DirectoryEmbedded1: DirectoryEmbedded1{Mode: intToPtr(0755)},
DirectoryEmbedded1: DirectoryEmbedded1{Mode: IntToPtr(0755)},
})
return dirs
@@ -312,16 +313,16 @@ Delegate=memory pids cpu io
// Add a fake systemd service to get the user socket rolling
files = append(files, File{
Node: Node{
Group: getNodeGrp(usrName),
Group: GetNodeGrp(usrName),
Path: "/home/" + usrName + "/.config/systemd/user/linger-example.service",
User: getNodeUsr(usrName),
User: GetNodeUsr(usrName),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
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
files = append(files, File{
Node: Node{
Group: getNodeGrp(usrName),
Group: GetNodeGrp(usrName),
Path: "/home/" + usrName + "/.config/containers/containers.conf",
User: getNodeUsr(usrName),
User: GetNodeUsr(usrName),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
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"} {
files = append(files, File{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: sub,
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
Overwrite: BoolToPtr(true),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
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
files = append(files, File{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/systemd/system/user@.service.d/delegate.conf",
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
Source: encodeDataURLPtr(delegateConf),
Source: EncodeDataURLPtr(delegateConf),
},
Mode: intToPtr(0644),
Mode: IntToPtr(0644),
},
})
// Add a file into linger
files = append(files, File{
Node: Node{
Group: getNodeGrp(usrName),
Group: GetNodeGrp(usrName),
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
files = append(files, File{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/containers/containers.conf",
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
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
files = append(files, File{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/containers/podman-machine",
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
// 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.
files = append(files, File{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/containers/registries.conf.d/999-podman-machine.conf",
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
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.
// Taken from https://github.com/containers/podman/blob/main/contrib/systemd/system/podman-docker.conf
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{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/etc/profile.d/docker-host.sh",
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
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{
Node: Node{
User: getNodeUsr("root"),
Group: getNodeGrp("root"),
User: GetNodeUsr("root"),
Group: GetNodeGrp("root"),
Path: "/etc/chrony.conf",
},
FileEmbedded1: FileEmbedded1{
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.
files = append(files, File{
Node: Node{
User: getNodeUsr("root"),
Group: getNodeGrp("root"),
User: GetNodeUsr("root"),
Group: GetNodeGrp("root"),
Path: "/etc/chrony.d/50-podman-makestep.conf",
},
FileEmbedded1: FileEmbedded1{
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{
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: targetPath,
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
FileEmbedded1: FileEmbedded1{
Append: nil,
Contents: Resource{
Source: encodeDataURLPtr(string(b)),
Source: EncodeDataURLPtr(string(b)),
},
Mode: intToPtr(0644),
Mode: IntToPtr(0644),
},
}
return file, nil
@@ -615,9 +616,9 @@ func GetProxyVariables() map[string]string {
func getLinks(usrName string) []Link {
return []Link{{
Node: Node{
Group: getNodeGrp(usrName),
Group: GetNodeGrp(usrName),
Path: "/home/" + usrName + "/.config/systemd/user/default.target.wants/linger-example.service",
User: getNodeUsr(usrName),
User: GetNodeUsr(usrName),
},
LinkEmbedded1: LinkEmbedded1{
Hard: BoolToPtr(false),
@@ -625,10 +626,10 @@ func getLinks(usrName string) []Link {
},
}, {
Node: Node{
Group: getNodeGrp("root"),
Group: GetNodeGrp("root"),
Path: "/usr/local/bin/docker",
Overwrite: BoolToPtr(true),
User: getNodeUsr("root"),
User: GetNodeUsr("root"),
},
LinkEmbedded1: LinkEmbedded1{
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)))
}

View File

@@ -1069,25 +1069,7 @@ func (v *MachineVM) SSH(_ string, opts machine.SSHOptions) error {
username = v.RemoteUsername
}
sshDestination := username + "@localhost"
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()
return machine.CommonSSH(username, v.IdentityPath, v.Name, v.Port, opts.Args)
}
// 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
}
//if err := vmm.CreateVhdxFile(config.DiskPath, config.DiskSize*1024*1024*1024); err != nil {
// return err
//}
if err := NewDriveSettingsBuilder(systemSettings).
AddScsiController().
AddSyntheticDiskDrive(0).
@@ -416,6 +413,7 @@ func (vmm *VirtualMachineManager) NewVirtualMachine(name string, config *Hardwar
return err
}
// Add default network connection
if config.Network {
if err := NewNetworkSettingsBuilder(systemSettings).
AddSyntheticEthernetPort(nil).
AddEthernetPortAllocation(""). // "" = connect to default switch
@@ -424,6 +422,7 @@ func (vmm *VirtualMachineManager) NewVirtualMachine(name string, config *Hardwar
Complete(); err != nil {
return err
}
}
return nil
}

View File

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

2
vendor/modules.txt vendored
View File

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