mirror of
https://github.com/containers/podman.git
synced 2025-12-02 02:58:03 +08:00
109 lines
2.7 KiB
Go
109 lines
2.7 KiB
Go
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")
|
|
}
|