func()

in cli_tools/common/imagefile/qemu_img.go [115:162]


func (client defaultInfoClient) getFileChecksum(ctx context.Context, filename string, virtualSizeBytes int64) (checksum string, err error) {
	// We calculate 4 chunks' checksum. Each of them is 100MB: 0~100MB, 0.9GB~1GB, 9.9GB~10GB, the last 100MB.
	// It is align with what we did for "daisy_workflows/image_import/import_image.sh" so that we can compare them.
	// Each block size is 512 Bytes. So, we need to check 20000 blocks: 200000 * 512 Bytes = 100MB
	// "skips" is also the start point of each chunks.
	checkBlockCount := int64(200000)
	blockSize := int64(512)
	totalBlockCount := virtualSizeBytes / blockSize
	skips := []int64{0, int64(2000000) - checkBlockCount, int64(20000000) - checkBlockCount, totalBlockCount - checkBlockCount}
	for i, skip := range skips {
		tmpOutFileName := fmt.Sprintf("%v%v", client.tmpOutFilePrefix, i)
		defer os.Remove(tmpOutFileName)

		if skip < 0 {
			skip = 0
		}

		// Write 100MB data to a file.
		var out string
		out, err = client.shellExecutor.Exec("qemu-img", "dd", fmt.Sprintf("if=%v", filename),
			fmt.Sprintf("of=%v", tmpOutFileName), fmt.Sprintf("bs=%v", blockSize),
			fmt.Sprintf("count=%v", skip+checkBlockCount), fmt.Sprintf("skip=%v", skip))
		err = constructCmdErr(out, err, "inspection for checksum failure")
		if err != nil {
			return
		}

		// Calculate checksum for the 100MB file.
		f, fileErr := os.Open(tmpOutFileName)
		if fileErr != nil {
			err = daisy.Errf("Failed to open file '%v' for QEMU md5 checksum calculation: %v", tmpOutFileName, fileErr)
			return
		}
		defer f.Close()
		h := md5.New()
		if _, md5Err := io.Copy(h, f); md5Err != nil {
			err = daisy.Errf("Failed to copy data from file '%v' for QEMU md5 checksum calculation: %v", tmpOutFileName, md5Err)
			return
		}
		newChecksum := fmt.Sprintf("%x", h.Sum(nil))

		if checksum != "" {
			checksum += "-"
		}
		checksum += newChecksum
	}
	return
}