fix(host): qemu-image info with json

This commit is contained in:
Qu Xuan
2021-10-22 17:23:16 +08:00
parent ccbe03881e
commit 0e3b83f85b
+37 -78
View File
@@ -17,11 +17,11 @@ package qemuimg
import (
"fmt"
"io"
"io/ioutil"
"os"
"strconv"
"strings"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
@@ -110,90 +110,49 @@ func (img *SQemuImage) parse() error {
img.ActualSizeBytes = fileInfo.Size()
}
}
cmd := procutils.NewRemoteCommandAsFarAsPossible(qemutils.GetQemuImg(), "info", img.Path)
var stdin io.WriteCloser
var err error
if len(img.Password) > 0 {
stdin, err = cmd.StdinPipe()
resp, err := func() (jsonutils.JSONObject, error) {
output, err := procutils.NewRemoteCommandAsFarAsPossible(qemutils.GetQemuImg(), "info", img.Path, "--output", "json").Output()
if err != nil {
return errors.Wrap(err, "cmd stdin pipe")
return nil, errors.Wrapf(err, "qemu-img info")
}
defer stdin.Close()
}
outb, err := cmd.StdoutPipe()
if err != nil {
return errors.Wrap(err, "cmd stdout pipe")
}
defer outb.Close()
return jsonutils.Parse(output)
}()
errb, err := cmd.StderrPipe()
if err != nil {
return errors.Wrap(err, "cmd stderr pipe")
}
defer errb.Close()
info := struct {
VirtualSizeBytes int64 `json:"virtual-size"`
Filename string `json:"filename"`
Format string `json:"format"`
ActualSizeBytes int64 `json:"actual-size"`
ClusterSize int `json:"cluster-size"`
BackingFilename string `json:"backing-filename"`
FullBackingFilename string `json:"full-backing-filename"`
BackingFilenameFormat string `json:"backing-filename-format"`
Encrypted bool `json:"encrypted"`
FormatSpecific struct {
Type string `json:"type"`
Data struct {
Compat string `json:"compat"`
LazyRefcounts int `json:"lazy-refcounts"`
RefcountBits int `json:"refcount-bits"`
Corrupt bool `json:"corrupt"`
} `json:"data"`
} `json:"format-specific"`
CreateType string `json:"create-type"`
DirtyFlag bool `json:"dirty-flag"`
}{}
err = cmd.Start()
if len(img.Password) > 0 {
io.WriteString(stdin, img.Password+"\n")
}
out, err := ioutil.ReadAll(outb)
err = resp.Unmarshal(&info)
if err != nil {
return errors.Wrap(err, "read stdout pipe")
}
errOut, err := ioutil.ReadAll(errb)
if err != nil {
return errors.Wrap(err, "read stderr pipe")
return errors.Wrapf(err, "resp.Unmarshal")
}
img.Format = TImageFormat(info.Format)
img.SizeBytes = info.VirtualSizeBytes
img.ClusterSize = info.ClusterSize
img.Compat = info.FormatSpecific.Data.Compat
img.Encryption = info.Encrypted
img.BackFilePath = info.FullBackingFilename
img.Subformat = info.CreateType
err = cmd.Wait()
if err != nil {
log.Errorf("qemu-img info %s fail %s: %s", img.Path, err, errOut)
return fmt.Errorf("qemu-img info error %s", errOut)
}
lines := strings.Split(string(out), "\n")
for i := 0; i < len(lines); i++ {
line := lines[i]
if len(line) > 0 {
line = strings.TrimSpace(line)
switch {
case strings.HasPrefix(line, "file format:"):
img.Format = String2ImageFormat(line[strings.LastIndexByte(line, ' ')+1:])
case strings.HasPrefix(line, "virtual size:"):
if img.SizeBytes == 0 {
sizeStr := line[strings.LastIndexByte(line, '(')+1 : strings.LastIndexByte(line, ' ')]
size, err := strconv.ParseInt(sizeStr, 10, 64)
if err != nil {
return fmt.Errorf("invalid size str %s: %s", sizeStr, err)
}
img.SizeBytes = size
}
case strings.HasPrefix(line, "cluster_size:"):
sizeStr := line[strings.LastIndexByte(line, ' ')+1:]
size, err := strconv.ParseInt(sizeStr, 10, 64)
if err != nil {
return fmt.Errorf("invalid cluster size str %s", sizeStr)
}
img.ClusterSize = int(size)
case strings.HasPrefix(line, "backing file:"):
img.BackFilePath = line[strings.LastIndexByte(line, ' ')+1:]
case strings.HasPrefix(line, "compat:"):
img.Compat = line[strings.LastIndexByte(line, ' ')+1:]
case strings.HasPrefix(line, "encrypted:"):
if line[strings.LastIndexByte(line, ' ')+1:] == "yes" {
img.Encryption = true
}
case strings.HasPrefix(line, "create type:"):
img.Subformat = line[strings.LastIndexByte(line, ' ')+1:]
}
}
if err != nil {
log.Errorf("read output fail %s", err)
return fmt.Errorf("read output fail %s", err)
}
}
if img.Format == RAW && fileutils2.IsFile(img.Path) {
// test if it is an ISO
blkType := fileutils2.GetBlkidType(img.Path)