Skip to content

Commit

Permalink
Consolidate GetImageVirtualSize and DetectFileFormat functions
Browse files Browse the repository at this point in the history
Signed-off-by: Tim Serong <tserong@suse.com>
  • Loading branch information
tserong committed Mar 8, 2024
1 parent eca5852 commit a2a1c0e
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 63 deletions.
8 changes: 4 additions & 4 deletions pkg/backingimage/backingimage.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,13 @@ func OpenBackingImage(path string) (*BackingImage, error) {
return nil, err
}

format, err := util.DetectFileFormat(file)
imgInfo, err := util.GetQemuImgInfo(file)
if err != nil {
return nil, err
}

var f enginetypes.DiffDisk
switch format {
switch imgInfo.Format {
case "qcow2":
// This is only used when doing backup.
// We open qcow2 like raw file and simply backup all the blocks of the qcow2
Expand All @@ -202,7 +202,7 @@ func OpenBackingImage(path string) (*BackingImage, error) {
return nil, err
}
default:
return nil, fmt.Errorf("format %v of the backing file %v is not supported", format, file)
return nil, fmt.Errorf("format %v of the backing file %v is not supported", imgInfo.Format, file)
}

size, err := f.Size()
Expand All @@ -224,7 +224,7 @@ func OpenBackingImage(path string) (*BackingImage, error) {
SectorSize: diskutil.BackingImageSectorSize,
Path: file,
Disk: f,
Format: format,
Format: imgInfo.Format,

Location: location,
}, nil
Expand Down
4 changes: 2 additions & 2 deletions pkg/sync/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,9 @@ func (s *SyncTestSuite) TestDownloadToDst(c *C) {
c.Assert(err, IsNil)
c.Assert(downloadChecksum, Equals, checksum)
// Downloaded file can be identified as a qcow2 file as well.
downloadFileFormat, err := util.DetectFileFormat(unzipDownloadFilePath)
downloadFileInfo, err := util.GetQemuImgInfo(unzipDownloadFilePath)
c.Assert(err, IsNil)
c.Assert(downloadFileFormat, Equals, "qcow2")
c.Assert(downloadFileInfo.Format, Equals, "qcow2")
}

func (s *SyncTestSuite) TestDuplicateCalls(c *C) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/sync/sync_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -820,14 +820,14 @@ func (sf *SyncingFile) updateSyncReadyNoLock() {
func (sf *SyncingFile) updateVirtualSizeNoLock(filePath string) {
// This only works if filePath is valid - sometimes we need to call it
// with sf.tmpFilePath, sometimes with sf.filePath :-/
virtualSize, err := util.GetImageVirtualSize(filePath)
imgInfo, err := util.GetQemuImgInfo(filePath)
if err != nil {
sf.log.Warnf("SyncingFile: failed to get backing image virtual size: %v", err)
}
// This will be zero when there is an error, which allows components
// further up the stack to know that the virtual size somehow isn't
// available yet.
sf.virtualSize = virtualSize
sf.virtualSize = imgInfo.VirtualSize
}

func (sf *SyncingFile) handleFailureNoLock(err error) {
Expand Down
67 changes: 12 additions & 55 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package util

import (
"bufio"
"bytes"
"compress/gzip"
"context"
Expand All @@ -15,7 +14,6 @@ import (
"os/exec"
"path/filepath"
"regexp"
"strings"
"time"

"github.com/pkg/errors"
Expand Down Expand Up @@ -233,68 +231,27 @@ func ExecuteWithTimeout(timeout time.Duration, envs []string, binary string, arg
return output.String(), nil
}

func DetectFileFormat(filePath string) (string, error) {

/* Example command outputs
$ qemu-img info parrot.raw
image: parrot.raw
file format: raw
virtual size: 32M (33554432 bytes)
disk size: 2.2M
$ qemu-img info parrot.qcow2
image: parrot.qcow2
file format: qcow2
virtual size: 32M (33554432 bytes)
disk size: 2.3M
cluster_size: 65536
Format specific information:
compat: 1.1
lazy refcounts: false
refcount bits: 16
corrupt: false
*/

output, err := Execute([]string{}, QemuImgBinary, "info", filePath)
if err != nil {
return "", err
}

scanner := bufio.NewScanner(strings.NewReader(output))
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if strings.HasPrefix(line, "file format: ") {
return strings.TrimPrefix(line, "file format: "), nil
}
}

return "", fmt.Errorf("cannot find the file format in the output %s", output)
type QemuImgInfo struct {
// For qcow2 files, VirtualSize may be larger than the physical
// image size on disk. For raw files, `qemu-img info` will report
// VirtualSize as being the same as the physical file size.
VirtualSize int64 `json:"virtual-size"`
Format string `json:"format"`
}

func GetImageVirtualSize(filePath string) (int64, error) {
type qemuImgInfo struct {
VirtualSize int64 `json:"virtual-size"`
}

func GetQemuImgInfo(filePath string) (imgInfo QemuImgInfo, err error) {
output, err := Execute([]string{}, QemuImgBinary, "info", "--output=json", filePath)
if err != nil {
return 0, err
return
}

var q qemuImgInfo
err = json.Unmarshal([]byte(output), &q)
if err != nil {
return 0, err
}

// If it's a raw file, `qemu-img info` will return virtual size == size
return q.VirtualSize, nil
err = json.Unmarshal([]byte(output), &imgInfo)
return
}

func ConvertFromRawToQcow2(filePath string) error {
if format, err := DetectFileFormat(filePath); err != nil {
if imgInfo, err := GetQemuImgInfo(filePath); err != nil {
return err
} else if format == "qcow2" {
} else if imgInfo.Format == "qcow2" {
return nil
}

Expand Down

0 comments on commit a2a1c0e

Please sign in to comment.