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 <[email protected]>
  • Loading branch information
tserong authored and mergify[bot] committed Mar 26, 2024
1 parent ceb51fd commit c5288d7
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 61 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
96 changes: 43 additions & 53 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,60 @@ func ExecuteWithTimeout(timeout time.Duration, envs []string, binary string, arg
return output.String(), nil
}

func DetectFileFormat(filePath string) (string, error) {
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 GetQemuImgInfo(filePath string) (imgInfo QemuImgInfo, err 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
$ qemu-img info --output=json SLE-Micro.x86_64-5.5.0-Default-qcow-GM.qcow2
{
"virtual-size": 21474836480,
"filename": "SLE-Micro.x86_64-5.5.0-Default-qcow-GM.qcow2",
"cluster-size": 65536,
"format": "qcow2",
"actual-size": 1001656320,
"format-specific": {
"type": "qcow2",
"data": {
"compat": "1.1",
"compression-type": "zlib",
"lazy-refcounts": false,
"refcount-bits": 16,
"corrupt": false,
"extended-l2": false
}
},
"dirty-flag": false
}
$ qemu-img info --output=json SLE-15-SP5-Full-x86_64-GM-Media1.iso
{
"virtual-size": 14548992000,
"filename": "SLE-15-SP5-Full-x86_64-GM-Media1.iso",
"format": "raw",
"actual-size": 14548996096,
"dirty-flag": 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)
}

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

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 c5288d7

Please sign in to comment.