package hypervctl import ( "encoding/xml" "fmt" "strconv" "strings" "github.com/containers/common/pkg/strongunits" "github.com/containers/libhvee/pkg/wmiext" ) // ResizeDisk takes a diskPath and strongly typed new size and uses powershell // to change its size. There is no error protection for trying to size a disk // smaller than the current size. func ResizeDisk(diskPath string, newSize strongunits.GiB) error { var ( service *wmiext.Service err error job *wmiext.Instance ret int32 ) if service, err = NewLocalHyperVService(); err != nil { return err } defer service.Close() imms, err := service.GetSingletonInstance("Msvm_ImageManagementService") if err != nil { return err } defer imms.Close() err = imms.BeginInvoke("ResizeVirtualHardDisk"). In("Path", diskPath). In("MaxInternalSize", int64(newSize.ToBytes())). Execute(). Out("Job", &job). Out("ReturnValue", &ret). End() if err != nil { return fmt.Errorf("failed to resize disk: %w", err) } return waitVMResult(ret, service, job, "failed to resize disk", nil) } func GetDiskSize(diskPath string) (strongunits.B, error) { var ( service *wmiext.Service err error job *wmiext.Instance ret int32 results string ) if service, err = NewLocalHyperVService(); err != nil { return 0, err } defer service.Close() imms, err := service.GetSingletonInstance("Msvm_ImageManagementService") if err != nil { return 0, err } defer imms.Close() inv := imms.BeginInvoke("GetVirtualHardDiskSettingData"). In("Path", diskPath). Execute(). Out("Job", &job). Out("ReturnValue", &ret) if err := inv.Error(); err != nil { return 0, fmt.Errorf("failed to get setting data for disk %s: %q", diskPath, err) } if err := waitVMResult(ret, service, job, "failure waiting on result from disk settings", nil); err != nil { return 0, err } err = inv.Out("SettingData", &results).End() if err != nil { return 0, fmt.Errorf("failed to retrieve setting object payload for disk: %q", err) } type CimSingleInstance struct { XMLName xml.Name `xml:"INSTANCE"` Properties []CimKvpItemProperty `xml:"PROPERTY"` } diskSettings := CimSingleInstance{} if err := xml.Unmarshal([]byte(results), &diskSettings); err != nil { return 0, fmt.Errorf("unable to parse disk settings xml: %q", err) } for _, prop := range diskSettings.Properties { if strings.EqualFold(prop.Name, "MaxInternalSize") { size, err := strconv.ParseUint(prop.Value, 10, 64) if err != nil { return 0, fmt.Errorf("unable to parse size in disk settings") } return strongunits.B(size), nil } } return 0, fmt.Errorf("disk settings was missing a size value") }