mirror of
https://github.com/containers/podman.git
synced 2025-07-28 02:42:23 +08:00
Various updates for hyperv and machine e2e tests
This PR is a mishmash of updates needed so that the hyperv provider can begin to passd the machine e2e tests. Summary as follows: * Added custom error handling for machine errors so that all providers can generate the same formatted error messages. The ones implemented thus far are needed for the basic and init tests. More will come as they are identified. * Vendored new libhvee for better memory inspection. The memory type changed from uint32 to uint64. * Some machine e2e tests used linux-specific utilities to check various error conditions and messages (like pgrep). Those were made into functions and implemented on an operating system level. [NO NEW TESTS NEEDED] Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
2
go.mod
2
go.mod
@ -17,7 +17,7 @@ require (
|
|||||||
github.com/containers/conmon v2.0.20+incompatible
|
github.com/containers/conmon v2.0.20+incompatible
|
||||||
github.com/containers/gvisor-tap-vsock v0.7.1-0.20230921084021-9298405740ad
|
github.com/containers/gvisor-tap-vsock v0.7.1-0.20230921084021-9298405740ad
|
||||||
github.com/containers/image/v5 v5.28.0
|
github.com/containers/image/v5 v5.28.0
|
||||||
github.com/containers/libhvee v0.4.1-0.20230905135638-56fb23533417
|
github.com/containers/libhvee v0.4.1-0.20230920190832-6ab399cadb68
|
||||||
github.com/containers/ocicrypt v1.1.8
|
github.com/containers/ocicrypt v1.1.8
|
||||||
github.com/containers/psgo v1.8.0
|
github.com/containers/psgo v1.8.0
|
||||||
github.com/containers/storage v1.50.2
|
github.com/containers/storage v1.50.2
|
||||||
|
4
go.sum
4
go.sum
@ -257,8 +257,8 @@ github.com/containers/gvisor-tap-vsock v0.7.1-0.20230921084021-9298405740ad h1:b
|
|||||||
github.com/containers/gvisor-tap-vsock v0.7.1-0.20230921084021-9298405740ad/go.mod h1:n7xPNoTHhif+K4S9zZMUmBNUvt5tcLfkHlQHreTLomM=
|
github.com/containers/gvisor-tap-vsock v0.7.1-0.20230921084021-9298405740ad/go.mod h1:n7xPNoTHhif+K4S9zZMUmBNUvt5tcLfkHlQHreTLomM=
|
||||||
github.com/containers/image/v5 v5.28.0 h1:H4cWbdI88UA/mDb6SxMo3IxpmS1BSs/Kifvhwt9g048=
|
github.com/containers/image/v5 v5.28.0 h1:H4cWbdI88UA/mDb6SxMo3IxpmS1BSs/Kifvhwt9g048=
|
||||||
github.com/containers/image/v5 v5.28.0/go.mod h1:9aPnNkwHNHgGl9VlQxXEshvmOJRbdRAc1rNDD6sP2eU=
|
github.com/containers/image/v5 v5.28.0/go.mod h1:9aPnNkwHNHgGl9VlQxXEshvmOJRbdRAc1rNDD6sP2eU=
|
||||||
github.com/containers/libhvee v0.4.1-0.20230905135638-56fb23533417 h1:fr+j21PD+IYR6Kvlf2Zrm1x9oAjV12T2Vz3oZIGTusw=
|
github.com/containers/libhvee v0.4.1-0.20230920190832-6ab399cadb68 h1:QIwOjkVpJp/onBOozw+MSr1mow9f5XQ8QG7Y8AP2Xp0=
|
||||||
github.com/containers/libhvee v0.4.1-0.20230905135638-56fb23533417/go.mod h1:HiXu8GZyjzGjU834fROO00Ka/4B1IM8qxy/6q6x1f+4=
|
github.com/containers/libhvee v0.4.1-0.20230920190832-6ab399cadb68/go.mod h1:HiXu8GZyjzGjU834fROO00Ka/4B1IM8qxy/6q6x1f+4=
|
||||||
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/luksy v0.0.0-20230808154129-d2d74a56682f h1:/HjLNYkVoUJNT4mm2dzGl63x7nD6YHxxI/k1kR0TkzA=
|
github.com/containers/luksy v0.0.0-20230808154129-d2d74a56682f h1:/HjLNYkVoUJNT4mm2dzGl63x7nD6YHxxI/k1kR0TkzA=
|
||||||
|
@ -353,7 +353,7 @@ func (m *MacMachine) Remove(name string, opts machine.RemoveOptions) (string, fu
|
|||||||
|
|
||||||
if vmState == machine.Running {
|
if vmState == machine.Running {
|
||||||
if !opts.Force {
|
if !opts.Force {
|
||||||
return "", nil, fmt.Errorf("invalid state: %s is running", m.Name)
|
return "", nil, &machine.ErrVMRunningCannotDestroyed{Name: m.Name}
|
||||||
}
|
}
|
||||||
if err := m.Vfkit.stop(true, true); err != nil {
|
if err := m.Vfkit.stop(true, true); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Working README for running the machine tests
|
# Working README for running the machine tests
|
||||||
|
|
||||||
|
Note: you must not have any machines defined before running tests
|
||||||
## Linux
|
## Linux
|
||||||
|
|
||||||
### QEMU
|
### QEMU
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os/exec"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
@ -69,9 +68,9 @@ var _ = Describe("run basic podman commands", func() {
|
|||||||
Expect(runAlp).To(Exit(0))
|
Expect(runAlp).To(Exit(0))
|
||||||
testHTTPServer("62544", false, "podman rulez")
|
testHTTPServer("62544", false, "podman rulez")
|
||||||
|
|
||||||
out, err := exec.Command("pgrep", "gvproxy").Output()
|
out, err := pgrep("gvproxy")
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(string(out)).ToNot(BeEmpty())
|
Expect(out).ToNot(BeEmpty())
|
||||||
|
|
||||||
rmCon, err := mb.setCmd(bm.withPodmanCommand([]string{"rm", "-af"})).run()
|
rmCon, err := mb.setCmd(bm.withPodmanCommand([]string{"rm", "-af"})).run()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
@ -84,8 +83,8 @@ var _ = Describe("run basic podman commands", func() {
|
|||||||
Expect(stopSession).To(Exit(0))
|
Expect(stopSession).To(Exit(0))
|
||||||
|
|
||||||
// gxproxy should exit after machine is stopped
|
// gxproxy should exit after machine is stopped
|
||||||
_, err = exec.Command("pgrep", "gvproxy").Output()
|
out, _ = pgrep("gvproxy")
|
||||||
Expect(err).To(HaveOccurred())
|
Expect(out).ToNot(ContainSubstring("gvproxy"))
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
package e2e_test
|
package e2e_test
|
||||||
|
|
||||||
|
import "os/exec"
|
||||||
|
|
||||||
const podmanBinary = "../../../bin/podman-remote"
|
const podmanBinary = "../../../bin/podman-remote"
|
||||||
|
|
||||||
|
func pgrep(n string) (string, error) {
|
||||||
|
out, err := exec.Command("pgrep", "gvproxy").Output()
|
||||||
|
return string(out), err
|
||||||
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package e2e_test
|
package e2e_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containers/podman/v4/pkg/machine"
|
"github.com/containers/podman/v4/pkg/machine"
|
||||||
"github.com/containers/podman/v4/pkg/machine/wsl"
|
"github.com/containers/podman/v4/pkg/machine/wsl"
|
||||||
. "github.com/onsi/ginkgo/v2"
|
. "github.com/onsi/ginkgo/v2"
|
||||||
@ -15,3 +19,19 @@ func getDownloadLocation(_ machine.VirtProvider) string {
|
|||||||
}
|
}
|
||||||
return fd.Get().URL.String()
|
return fd.Get().URL.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pgrep emulates the pgrep linux command
|
||||||
|
func pgrep(n string) (string, error) {
|
||||||
|
// add filter to find the process and do no display a header
|
||||||
|
args := []string{"/fi", fmt.Sprintf("IMAGENAME eq %s", n), "/nh"}
|
||||||
|
out, err := exec.Command("tasklist.exe", args...).Output()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
strOut := string(out)
|
||||||
|
// in pgrep, if no running process is found, it exits 1 and the output is zilch
|
||||||
|
if strings.Contains(strOut, "INFO: No tasks are running which match the specified search") {
|
||||||
|
return "", fmt.Errorf("no task found")
|
||||||
|
}
|
||||||
|
return strOut, nil
|
||||||
|
}
|
||||||
|
@ -130,6 +130,9 @@ func setup() (string, *machineTestBuilder) {
|
|||||||
if _, err := io.Copy(n, f); err != nil {
|
if _, err := io.Copy(n, f); err != nil {
|
||||||
Fail(fmt.Sprintf("failed to copy %ss to %s: %q", fqImageName, mb.imagePath, err))
|
Fail(fmt.Sprintf("failed to copy %ss to %s: %q", fqImageName, mb.imagePath, err))
|
||||||
}
|
}
|
||||||
|
if err := n.Close(); err != nil {
|
||||||
|
Fail(fmt.Sprintf("failed to close image copy handler: %q", err))
|
||||||
|
}
|
||||||
return homeDir, mb
|
return homeDir, mb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/containers/podman/v4/pkg/strongunits"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNoSuchVM = errors.New("VM does not exist")
|
ErrNoSuchVM = errors.New("VM does not exist")
|
||||||
@ -10,3 +15,28 @@ var (
|
|||||||
ErrMultipleActiveVM = errors.New("only one VM can be active at a time")
|
ErrMultipleActiveVM = errors.New("only one VM can be active at a time")
|
||||||
ErrNotImplemented = errors.New("functionality not implemented")
|
ErrNotImplemented = errors.New("functionality not implemented")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ErrVMRunningCannotDestroyed struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *ErrVMRunningCannotDestroyed) Error() string {
|
||||||
|
return fmt.Sprintf("running vm %q cannot be destroyed", err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrVMDoesNotExist struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *ErrVMDoesNotExist) Error() string {
|
||||||
|
// the current error in qemu is not quoted
|
||||||
|
return fmt.Sprintf("%s: VM does not exist", err.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ErrNewDiskSizeTooSmall struct {
|
||||||
|
OldSize, NewSize strongunits.GiB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err *ErrNewDiskSizeTooSmall) Error() string {
|
||||||
|
return fmt.Sprintf("invalid disk size %d: new disk must be larger than %dGB", err.OldSize, err.NewSize)
|
||||||
|
}
|
||||||
|
@ -44,20 +44,23 @@ func (v HyperVVirtualization) CheckExclusiveActiveVM() (bool, string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v HyperVVirtualization) IsValidVMName(name string) (bool, error) {
|
func (v HyperVVirtualization) IsValidVMName(name string) (bool, error) {
|
||||||
// We check both the local filesystem and hyperv for the valid name
|
var found bool
|
||||||
mm := HyperVMachine{Name: name}
|
vms, err := v.loadFromLocalJson()
|
||||||
configDir, err := machine.GetConfDir(v.VMType())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if err := mm.loadHyperVMachineFromJSON(configDir); err != nil {
|
for _, vm := range vms {
|
||||||
return false, err
|
if vm.Name == name {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
// The name is valid for the local filesystem
|
|
||||||
if _, err := hypervctl.NewVirtualMachineManager().GetMachine(name); err != nil {
|
if _, err := hypervctl.NewVirtualMachineManager().GetMachine(name); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
// The lookup in hyperv worked, so it is also valid there
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +162,7 @@ func (v HyperVVirtualization) NewMachine(opts machine.InitOptions) (machine.VM,
|
|||||||
CPUs: uint16(opts.CPUS),
|
CPUs: uint16(opts.CPUS),
|
||||||
DiskPath: imagePath.GetPath(),
|
DiskPath: imagePath.GetPath(),
|
||||||
DiskSize: opts.DiskSize,
|
DiskSize: opts.DiskSize,
|
||||||
Memory: int32(opts.Memory),
|
Memory: opts.Memory,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the json configuration file which will be loaded by
|
// Write the json configuration file which will be loaded by
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -17,9 +18,9 @@ import (
|
|||||||
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
gvproxy "github.com/containers/gvisor-tap-vsock/pkg/types"
|
||||||
"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/pkg/strongunits"
|
||||||
"github.com/containers/podman/v4/pkg/util"
|
"github.com/containers/podman/v4/pkg/util"
|
||||||
"github.com/containers/podman/v4/utils"
|
"github.com/containers/podman/v4/utils"
|
||||||
"github.com/docker/go-units"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -253,7 +254,6 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
return false, os.WriteFile(m.IgnitionFile.GetPath(), inputIgnition, 0644)
|
return false, os.WriteFile(m.IgnitionFile.GetPath(), inputIgnition, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the JSON file for the second time. First time was in NewMachine
|
|
||||||
if err := m.writeConfig(); err != nil {
|
if err := m.writeConfig(); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -262,6 +262,10 @@ func (m *HyperVMachine) Init(opts machine.InitOptions) (bool, error) {
|
|||||||
if err := m.writeIgnitionConfigFile(opts, m.RemoteUsername, key); err != nil {
|
if err := m.writeIgnitionConfigFile(opts, m.RemoteUsername, key); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := m.resizeDisk(strongunits.GiB(opts.DiskSize)); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
// The ignition file has been written. We now need to
|
// The ignition file has been written. We now need to
|
||||||
// read it so that we can put it into key-value pairs
|
// read it so that we can put it into key-value pairs
|
||||||
err = m.readAndSplitIgnition()
|
err = m.readAndSplitIgnition()
|
||||||
@ -284,16 +288,16 @@ func (m *HyperVMachine) Inspect() (*machine.InspectInfo, error) {
|
|||||||
ConnectionInfo: machine.ConnectionConfig{},
|
ConnectionInfo: machine.ConnectionConfig{},
|
||||||
Created: m.Created,
|
Created: m.Created,
|
||||||
Image: machine.ImageConfig{
|
Image: machine.ImageConfig{
|
||||||
IgnitionFile: machine.VMFile{},
|
IgnitionFile: m.IgnitionFile,
|
||||||
ImageStream: "",
|
ImageStream: "",
|
||||||
ImagePath: machine.VMFile{},
|
ImagePath: m.ImagePath,
|
||||||
},
|
},
|
||||||
LastUp: m.LastUp,
|
LastUp: m.LastUp,
|
||||||
Name: m.Name,
|
Name: m.Name,
|
||||||
Resources: machine.ResourceConfig{
|
Resources: machine.ResourceConfig{
|
||||||
CPUs: uint64(cfg.Hardware.CPUs),
|
CPUs: uint64(cfg.Hardware.CPUs),
|
||||||
DiskSize: 0,
|
DiskSize: 0,
|
||||||
Memory: uint64(cfg.Hardware.Memory),
|
Memory: cfg.Hardware.Memory,
|
||||||
},
|
},
|
||||||
SSHConfig: m.SSHConfig,
|
SSHConfig: m.SSHConfig,
|
||||||
State: vm.State().String(),
|
State: vm.State().String(),
|
||||||
@ -348,7 +352,7 @@ func (m *HyperVMachine) Remove(_ string, opts machine.RemoveOptions) (string, fu
|
|||||||
// In hyperv, they call running 'enabled'
|
// In hyperv, they call running 'enabled'
|
||||||
if vm.State() == hypervctl.Enabled {
|
if vm.State() == hypervctl.Enabled {
|
||||||
if !opts.Force {
|
if !opts.Force {
|
||||||
return "", nil, hypervctl.ErrMachineStateInvalid
|
return "", nil, &machine.ErrVMRunningCannotDestroyed{Name: m.Name}
|
||||||
}
|
}
|
||||||
if err := vm.Stop(); err != nil {
|
if err := vm.Stop(); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
@ -399,7 +403,10 @@ func (m *HyperVMachine) Set(name string, opts machine.SetOptions) ([]error, erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if opts.DiskSize != nil && m.DiskSize != *opts.DiskSize {
|
if opts.DiskSize != nil && m.DiskSize != *opts.DiskSize {
|
||||||
setErrors = append(setErrors, hypervctl.ErrNotImplemented)
|
newDiskSize := strongunits.GiB(*opts.DiskSize)
|
||||||
|
if err := m.resizeDisk(newDiskSize); err != nil {
|
||||||
|
setErrors = append(setErrors, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if opts.CPUs != nil && m.CPUs != *opts.CPUs {
|
if opts.CPUs != nil && m.CPUs != *opts.CPUs {
|
||||||
m.CPUs = *opts.CPUs
|
m.CPUs = *opts.CPUs
|
||||||
@ -545,6 +552,9 @@ func (m *HyperVMachine) loadFromFile() (*HyperVMachine, error) {
|
|||||||
mm := HyperVMachine{}
|
mm := HyperVMachine{}
|
||||||
|
|
||||||
if err := mm.loadHyperVMachineFromJSON(jsonPath); err != nil {
|
if err := mm.loadHyperVMachineFromJSON(jsonPath); err != nil {
|
||||||
|
if errors.Is(err, machine.ErrNoSuchVM) {
|
||||||
|
return nil, &machine.ErrVMDoesNotExist{Name: m.Name}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
vmm := hypervctl.NewVirtualMachineManager()
|
vmm := hypervctl.NewVirtualMachineManager()
|
||||||
@ -566,8 +576,6 @@ func (m *HyperVMachine) loadFromFile() (*HyperVMachine, error) {
|
|||||||
if cfg.Hardware.Memory > 0 {
|
if cfg.Hardware.Memory > 0 {
|
||||||
mm.Memory = uint64(cfg.Hardware.Memory)
|
mm.Memory = uint64(cfg.Hardware.Memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
mm.DiskSize = cfg.Hardware.DiskSize * units.MiB
|
|
||||||
mm.LastUp = cfg.Status.LastUp
|
mm.LastUp = cfg.Status.LastUp
|
||||||
|
|
||||||
return &mm, nil
|
return &mm, nil
|
||||||
@ -583,7 +591,7 @@ func (m *HyperVMachine) loadHyperVMachineFromJSON(fqConfigPath string) error {
|
|||||||
b, err := os.ReadFile(fqConfigPath)
|
b, err := os.ReadFile(fqConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
return fmt.Errorf("%q: %w", fqConfigPath, machine.ErrNoSuchVM)
|
return machine.ErrNoSuchVM
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -634,7 +642,7 @@ func (m *HyperVMachine) startHostNetworking() (string, machine.APIForwardingStat
|
|||||||
|
|
||||||
c := cmd.Cmd(gvproxyBinary)
|
c := cmd.Cmd(gvproxyBinary)
|
||||||
if err := c.Start(); err != nil {
|
if err := c.Start(); err != nil {
|
||||||
return "", 0, fmt.Errorf("unable to execute: %q: %w", cmd, err)
|
return "", 0, fmt.Errorf("unable to execute: %s: %w", cmd.ToCmdline(), err)
|
||||||
}
|
}
|
||||||
return forwardSock, state, nil
|
return forwardSock, state, nil
|
||||||
}
|
}
|
||||||
@ -691,3 +699,16 @@ func (m *HyperVMachine) setRootful(rootful bool) error {
|
|||||||
m.HostUser.Modified = true
|
m.HostUser.Modified = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *HyperVMachine) resizeDisk(newSize strongunits.GiB) error {
|
||||||
|
if m.DiskSize > uint64(newSize) {
|
||||||
|
return &machine.ErrNewDiskSizeTooSmall{OldSize: strongunits.ToGiB(strongunits.B(m.DiskSize)), NewSize: newSize}
|
||||||
|
}
|
||||||
|
resize := exec.Command("powershell", []string{"-command", fmt.Sprintf("Resize-VHD %s %d", m.ImagePath.GetPath(), newSize.ToBytes())}...)
|
||||||
|
resize.Stdout = os.Stdout
|
||||||
|
resize.Stderr = os.Stderr
|
||||||
|
if err := resize.Run(); err != nil {
|
||||||
|
return fmt.Errorf("resizing image: %q", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -1174,7 +1174,7 @@ func (v *MachineVM) Remove(_ string, opts machine.RemoveOptions) (string, func()
|
|||||||
}
|
}
|
||||||
if state == machine.Running {
|
if state == machine.Running {
|
||||||
if !opts.Force {
|
if !opts.Force {
|
||||||
return "", nil, fmt.Errorf("running vm %q cannot be destroyed", v.Name)
|
return "", nil, &machine.ErrVMRunningCannotDestroyed{Name: v.Name}
|
||||||
}
|
}
|
||||||
err := v.stopLocked()
|
err := v.stopLocked()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1523,7 +1523,7 @@ func (v *MachineVM) Remove(name string, opts machine.RemoveOptions) (string, fun
|
|||||||
|
|
||||||
if v.isRunning() {
|
if v.isRunning() {
|
||||||
if !opts.Force {
|
if !opts.Force {
|
||||||
return "", nil, fmt.Errorf("running vm %q cannot be destroyed", v.Name)
|
return "", nil, &machine.ErrVMRunningCannotDestroyed{Name: v.Name}
|
||||||
}
|
}
|
||||||
if err := v.Stop(v.Name, machine.StopOptions{}); err != nil {
|
if err := v.Stop(v.Name, machine.StopOptions{}); err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
@ -1631,14 +1631,14 @@ func (v *MachineVM) SSH(name string, opts machine.SSHOptions) error {
|
|||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vm *MachineVM) updateTimeStamps(updateLast bool) (time.Time, time.Time, error) {
|
func (v *MachineVM) updateTimeStamps(updateLast bool) (time.Time, time.Time, error) {
|
||||||
var err error
|
var err error
|
||||||
if updateLast {
|
if updateLast {
|
||||||
vm.LastUp = time.Now()
|
v.LastUp = time.Now()
|
||||||
err = vm.writeConfig()
|
err = v.writeConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
return vm.Created, vm.LastUp, err
|
return v.Created, v.LastUp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDiskSize(vm *MachineVM) uint64 {
|
func getDiskSize(vm *MachineVM) uint64 {
|
||||||
|
23
vendor/github.com/containers/libhvee/pkg/hypervctl/vm.go
generated
vendored
23
vendor/github.com/containers/libhvee/pkg/hypervctl/vm.go
generated
vendored
@ -326,13 +326,18 @@ func (vm *VirtualMachine) GetConfig(diskPath string) (*HyperVConfig, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
diskSize = uint64(diskPathInfo.Size())
|
diskSize = uint64(diskPathInfo.Size())
|
||||||
|
mem := MemorySettings{}
|
||||||
|
if err := vm.getMemorySettings(&mem); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
config := HyperVConfig{
|
config := HyperVConfig{
|
||||||
Hardware: HardwareConfig{
|
Hardware: HardwareConfig{
|
||||||
|
// TODO we could implement a getProcessorSettings like we did for memory
|
||||||
CPUs: summary.NumberOfProcessors,
|
CPUs: summary.NumberOfProcessors,
|
||||||
DiskPath: diskPath,
|
DiskPath: diskPath,
|
||||||
DiskSize: diskSize,
|
DiskSize: diskSize,
|
||||||
Memory: summary.MemoryAvailable,
|
Memory: mem.Limit,
|
||||||
},
|
},
|
||||||
Status: Statuses{
|
Status: Statuses{
|
||||||
Created: vm.InstallDate,
|
Created: vm.InstallDate,
|
||||||
@ -403,8 +408,8 @@ func (vmm *VirtualMachineManager) NewVirtualMachine(name string, config *Hardwar
|
|||||||
|
|
||||||
// The API seems to require both of these even
|
// The API seems to require both of these even
|
||||||
// when not using dynamic memory
|
// when not using dynamic memory
|
||||||
ms.Limit = uint64(config.Memory)
|
ms.Limit = config.Memory
|
||||||
ms.VirtualQuantity = uint64(config.Memory)
|
ms.VirtualQuantity = config.Memory
|
||||||
}).
|
}).
|
||||||
PrepareProcessorSettings(func(ps *ProcessorSettings) {
|
PrepareProcessorSettings(func(ps *ProcessorSettings) {
|
||||||
ps.VirtualQuantity = uint64(config.CPUs) // 4 cores
|
ps.VirtualQuantity = uint64(config.CPUs) // 4 cores
|
||||||
@ -468,6 +473,15 @@ func (vm *VirtualMachine) fetchExistingResourceSettings(service *wmiext.Service,
|
|||||||
return service.FindFirstRelatedObject(path, resourceType, resourceSettings)
|
return service.FindFirstRelatedObject(path, resourceType, resourceSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (vm *VirtualMachine) getMemorySettings(m *MemorySettings) error {
|
||||||
|
service, err := wmiext.NewLocalService(HyperVNamespace)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer service.Close()
|
||||||
|
return vm.fetchExistingResourceSettings(service, "Msvm_MemorySettingData", m)
|
||||||
|
}
|
||||||
|
|
||||||
// Update processor and/or mem
|
// Update processor and/or mem
|
||||||
func (vm *VirtualMachine) UpdateProcessorMemSettings(updateProcessor func(*ProcessorSettings), updateMemory func(*MemorySettings)) error {
|
func (vm *VirtualMachine) UpdateProcessorMemSettings(updateProcessor func(*ProcessorSettings), updateMemory func(*MemorySettings)) error {
|
||||||
service, err := wmiext.NewLocalService(HyperVNamespace)
|
service, err := wmiext.NewLocalService(HyperVNamespace)
|
||||||
@ -496,8 +510,7 @@ func (vm *VirtualMachine) UpdateProcessorMemSettings(updateProcessor func(*Proce
|
|||||||
}
|
}
|
||||||
|
|
||||||
if updateMemory != nil {
|
if updateMemory != nil {
|
||||||
err = vm.fetchExistingResourceSettings(service, "Msvm_MemorySettingData", mem)
|
if err := vm.getMemorySettings(mem); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/containers/libhvee/pkg/hypervctl/vm_config.go
generated
vendored
2
vendor/github.com/containers/libhvee/pkg/hypervctl/vm_config.go
generated
vendored
@ -97,7 +97,7 @@ type HardwareConfig struct {
|
|||||||
// Disk size in gigabytes assigned to the vm
|
// Disk size in gigabytes assigned to the vm
|
||||||
DiskSize uint64
|
DiskSize uint64
|
||||||
// Memory in megabytes assigned to the vm
|
// Memory in megabytes assigned to the vm
|
||||||
Memory int32
|
Memory uint64
|
||||||
// Network is bool to add a Network Connection to the
|
// Network is bool to add a Network Connection to the
|
||||||
// default network switch in Microsoft HyperV
|
// default network switch in Microsoft HyperV
|
||||||
Network bool
|
Network bool
|
||||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -301,7 +301,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.4.1-0.20230905135638-56fb23533417
|
# github.com/containers/libhvee v0.4.1-0.20230920190832-6ab399cadb68
|
||||||
## 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
|
||||||
|
Reference in New Issue
Block a user