Skip to content

Commit

Permalink
Merge pull request #62 from n1hility/bypass-locale
Browse files Browse the repository at this point in the history
Avoid searching on locale sensitive properties
  • Loading branch information
openshift-merge-bot[bot] authored Nov 9, 2023
2 parents 9651e31 + 07fcd9c commit 5b0ce87
Show file tree
Hide file tree
Showing 16 changed files with 294 additions and 57 deletions.
2 changes: 1 addition & 1 deletion cmd/dumpvms/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func getVms() (string, error) {
vmms := hypervctl.VirtualMachineManager{}
vms, err := vmms.GetAll()
if err != nil {
return "", fmt.Errorf("Could not retrieve virtual machines : %s\n", err.Error())
return "", fmt.Errorf("Could not retrieve virtual machines: %s\n", err.Error())
}
b, err := json.MarshalIndent(vms, "", "\t")
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/hypervctl/diskdrive_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (d *SyntheticDiskDriveSettings) DefineVirtualHardDisk(vhdxFile string, befo
func createDiskResourceInternal(systemPath string, drivePath string, file string, settings diskAssociation, resourceType string, cb func()) error {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return err
}
defer service.Close()
Expand Down
17 changes: 17 additions & 0 deletions pkg/hypervctl/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package hypervctl
import (
"errors"
"fmt"

"github.com/containers/libhvee/pkg/wmiext"
)

// VM State errors
Expand Down Expand Up @@ -155,3 +157,18 @@ func translateModifyError(code int) error {

return &modifyResourceError{code, message}
}

var (
ErrHyperVNamespaceMissing = errors.New("HyperV namespace not found, is HyperV enabled?")
)

func translateCommonHyperVWmiError(wmiError error) error {
if werr, ok := wmiError.(*wmiext.WmiError); ok {
switch werr.Code() {
case wmiext.WBEM_E_INVALID_NAMESPACE:
return ErrHyperVNamespaceMissing
}
}

return wmiError
}
2 changes: 1 addition & 1 deletion pkg/hypervctl/ethernet_port_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (p *SyntheticEthernetPortSettings) DefineEthernetPortConnection(switchName

var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return nil, err
}
defer service.Close()
Expand Down
4 changes: 2 additions & 2 deletions pkg/hypervctl/resources_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func (s *ResourceSettings) Path() string {
func createResourceSettingGeneric(settings interface{}, resourceType string) (string, error) {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return "", err
}

Expand Down Expand Up @@ -84,7 +84,7 @@ func createResourceSettingGeneric(settings interface{}, resourceType string) (st
func populateDefaults(subType string, settings interface{}) error {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return err
}
defer service.Close()
Expand Down
2 changes: 1 addition & 1 deletion pkg/hypervctl/scsi_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (c *ScsiControllerSettings) AddSyntheticDvdDrive(slot uint) (*SyntheticDvdD
func (c *ScsiControllerSettings) createSyntheticDriveInternal(slot uint, settings driveAssociation, resourceType string) error {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return err
}
defer service.Close()
Expand Down
4 changes: 2 additions & 2 deletions pkg/hypervctl/system_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (s *SystemSettings) AddScsiController() (*ScsiControllerSettings, error) {
func (s *SystemSettings) createSystemResourceInternal(settings interface{}, resourceType string, cb func()) error {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return err
}
defer service.Close()
Expand Down Expand Up @@ -186,7 +186,7 @@ func addResource(service *wmiext.Service, systemSettingPath string, resourceSett
func (s *SystemSettings) GetVM() (*VirtualMachine, error) {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return nil, err
}
defer service.Close()
Expand Down
2 changes: 1 addition & 1 deletion pkg/hypervctl/system_settings_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (builder *SystemSettingsBuilder) Build() (*SystemSettings, error) {
return nil, err
}

if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return nil, err
}
defer service.Close()
Expand Down
16 changes: 8 additions & 8 deletions pkg/hypervctl/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (vm *VirtualMachine) GetKeyValuePairs() (map[string]string, error) {
var service *wmiext.Service
var err error

if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return nil, err
}

Expand Down Expand Up @@ -153,7 +153,7 @@ func (vm *VirtualMachine) kvpOperation(op string, key string, value string, ille
var vsms, job *wmiext.Instance
var err error

if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return err
}
defer service.Close()
Expand Down Expand Up @@ -226,7 +226,7 @@ func (vm *VirtualMachine) stop(force bool) error {
res int32
srv *wmiext.Service
)
if srv, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if srv, err = NewLocalHyperVService(); err != nil {
return err
}
wmiInst, err := srv.FindFirstRelatedInstance(vm.Path(), "Msvm_ShutdownComponent")
Expand Down Expand Up @@ -303,7 +303,7 @@ func (vm *VirtualMachine) Start() error {

func getService(_ *wmiext.Service) (*wmiext.Service, error) {
// any reason why when we instantiate a vm, we should NOT just embed a service?
return wmiext.NewLocalService(HyperVNamespace)
return NewLocalHyperVService()
}

func (vm *VirtualMachine) GetConfig(diskPath string) (*HyperVConfig, error) {
Expand Down Expand Up @@ -350,7 +350,7 @@ func (vm *VirtualMachine) GetConfig(diskPath string) (*HyperVConfig, error) {
// SummaryRequestCommon and SummaryRequestNearAll provide predefined combinations for this
// parameter
func (vm *VirtualMachine) GetSummaryInformation(requestedFields SummaryRequestSet) (*SummaryInformation, error) {
service, err := wmiext.NewLocalService(HyperVNamespace)
service, err := NewLocalHyperVService()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -469,7 +469,7 @@ func (vm *VirtualMachine) fetchExistingResourceSettings(service *wmiext.Service,
}

func (vm *VirtualMachine) getMemorySettings(m *MemorySettings) error {
service, err := wmiext.NewLocalService(HyperVNamespace)
service, err := NewLocalHyperVService()
if err != nil {
return err
}
Expand All @@ -479,7 +479,7 @@ func (vm *VirtualMachine) getMemorySettings(m *MemorySettings) error {

// Update processor and/or mem
func (vm *VirtualMachine) UpdateProcessorMemSettings(updateProcessor func(*ProcessorSettings), updateMemory func(*MemorySettings)) error {
service, err := wmiext.NewLocalService(HyperVNamespace)
service, err := NewLocalHyperVService()
if err != nil {
return err
}
Expand Down Expand Up @@ -556,7 +556,7 @@ func (vm *VirtualMachine) remove() (int32, error) {
if !Disabled.equal(vm.EnabledState) {
return -1, ErrMachineStateInvalid
}
if srv, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if srv, err = NewLocalHyperVService(); err != nil {
return -1, err
}

Expand Down
61 changes: 45 additions & 16 deletions pkg/hypervctl/vmm.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
const (
HyperVNamespace = "root\\virtualization\\v2"
VirtualSystemManagementService = "Msvm_VirtualSystemManagementService"
MsvmComputerSystem = "Msvm_ComputerSystem"
)

// https://learn.microsoft.com/en-us/windows/win32/hyperv_v2/msvm-computersystem
Expand All @@ -23,12 +24,22 @@ func NewVirtualMachineManager() *VirtualMachineManager {
return &VirtualMachineManager{}
}

func NewLocalHyperVService() (*wmiext.Service, error) {
service, err := wmiext.NewLocalService(HyperVNamespace)
if err != nil {
return nil, translateCommonHyperVWmiError(err)
}

return service, nil
}

func (vmm *VirtualMachineManager) GetAll() ([]*VirtualMachine, error) {
const wql = "Select * From Msvm_ComputerSystem Where Description = 'Microsoft Virtual Machine'"
// Fetch through settings to avoid locale sensitive properties
const wql = "Select * From Msvm_VirtualSystemSettingData Where VirtualSystemType = 'Microsoft:Hyper-V:System:Realized'"

var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return []*VirtualMachine{}, err
}
defer service.Close()
Expand All @@ -38,22 +49,31 @@ func (vmm *VirtualMachineManager) GetAll() ([]*VirtualMachine, error) {
return nil, err
}
defer enum.Close()

var vms []*VirtualMachine

for {
vm := &VirtualMachine{vmm: vmm}
done, err := wmiext.NextObject(enum, vm)
settings, err := enum.Next()
if err != nil {
return vms, err
}
if done {

// Finished iterating
if settings == nil {
break
}

vm, err := vmm.findVMFromSettings(service, settings)
settings.Close()
if err != nil {
return vms, err
}

vms = append(vms, vm)
}

return vms, nil
}

func (vmm *VirtualMachineManager) Exists(name string) (bool, error) {
vms, err := vmm.GetAll()
if err != nil {
Expand All @@ -68,14 +88,14 @@ func (vmm *VirtualMachineManager) Exists(name string) (bool, error) {
return false, nil
}

func (*VirtualMachineManager) GetMachine(name string) (*VirtualMachine, error) {
const wql = "Select * From Msvm_ComputerSystem Where Description = 'Microsoft Virtual Machine' And ElementName='%s'"
func (vmm *VirtualMachineManager) GetMachine(name string) (*VirtualMachine, error) {
const wql = "Select * From Msvm_VirtualSystemSettingData Where VirtualSystemType = 'Microsoft:Hyper-V:System:Realized' And ElementName='%s'"

vm := &VirtualMachine{}
var service *wmiext.Service
var err error

if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return vm, err
}
defer service.Close()
Expand All @@ -86,22 +106,31 @@ func (*VirtualMachineManager) GetMachine(name string) (*VirtualMachine, error) {
}
defer enum.Close()

done, err := wmiext.NextObject(enum, vm)
settings, err := service.FindFirstInstance(fmt.Sprintf(wql, name))
if err != nil {
return vm, err
return vm, fmt.Errorf("could not find virtual machine %q: %w", name, err)
}
defer settings.Close()

if done {
return vm, fmt.Errorf("could not find virtual machine %q", name)
return vmm.findVMFromSettings(service, settings)
}

func (vmm *VirtualMachineManager) findVMFromSettings(service *wmiext.Service, settings *wmiext.Instance) (*VirtualMachine, error) {
path, err := settings.Path()
if err != nil {
return nil, err
}

return vm, nil
vm := &VirtualMachine{vmm: vmm}
err = service.FindFirstRelatedObject(path, MsvmComputerSystem, vm)

return vm, err
}

func (*VirtualMachineManager) CreateVhdxFile(path string, maxSize uint64) error {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return err
}
defer service.Close()
Expand Down Expand Up @@ -152,7 +181,7 @@ func (vmm *VirtualMachineManager) GetSummaryInformation(requestedFields SummaryR
func (vmm *VirtualMachineManager) getSummaryInformation(settingsPath string, requestedFields SummaryRequestSet) ([]SummaryInformation, error) {
var service *wmiext.Service
var err error
if service, err = wmiext.NewLocalService(HyperVNamespace); err != nil {
if service, err = NewLocalHyperVService(); err != nil {
return nil, err
}
defer service.Close()
Expand Down
6 changes: 3 additions & 3 deletions pkg/wmiext/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func safeArrayDestroy(safearray *ole.SafeArray) (err error) {
ret, _, _ := procSafeArrayDestroy.Call(uintptr(unsafe.Pointer(safearray)))

if ret != 0 {
return ole.NewError(ret)
return NewWmiError(ret)
}

return nil
Expand All @@ -127,7 +127,7 @@ func safeArrayPutElement(safearray *ole.SafeArray, index int64, element uintptr)
element)

if ret != 0 {
return ole.NewError(ret)
return NewWmiError(ret)
}

return nil
Expand All @@ -141,7 +141,7 @@ func safeArrayGetElement(safearray *ole.SafeArray, index int64, element unsafe.P
uintptr(element))

if ret != 0 {
return ole.NewError(ret)
return NewWmiError(ret)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion pkg/wmiext/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (e *Enum) Next() (instance *Instance, err error) {
uintptr(unsafe.Pointer(&apObjects)), // [out] IWbemClassObject **apObjects,
uintptr(unsafe.Pointer(&uReturned))) // [out] ULONG *puReturned)
if int(res) < 0 {
return nil, ole.NewError(res)
return nil, NewWmiError(res)
}

if uReturned < 1 {
Expand Down
Loading

0 comments on commit 5b0ce87

Please sign in to comment.