diff --git a/internal/cli/kraft/cloud/volume/import/cpio.go b/internal/cli/kraft/cloud/volume/import/cpio.go index 5800ce14f..6a06a84ac 100644 --- a/internal/cli/kraft/cloud/volume/import/cpio.go +++ b/internal/cli/kraft/cloud/volume/import/cpio.go @@ -129,8 +129,9 @@ func buildCPIO(ctx context.Context, source string) (path string, size int64, err } // copyCPIO copies the CPIO archive at the given path over the provided tls.Conn. -func copyCPIO(ctx context.Context, conn *tls.Conn, auth, path string, timeoutS uint64) error { +func copyCPIO(ctx context.Context, conn *tls.Conn, auth, path string, timeoutS, size uint64, callback progressCallbackFunc) error { var resp okResponse + var currentSize uint64 // NOTE(antoineco): this call is critical as it allows writes to be later // cancelled, because the deadline applies to all future and pending I/O and @@ -201,6 +202,8 @@ func copyCPIO(ctx context.Context, conn *tls.Conn, auth, path string, timeoutS u if err := resp.waitForOK(conn, "header copy failed"); err != nil { return err } + currentSize += uint64(len(raw.Bytes())) + updateProgress(float64(currentSize), float64(size), callback) nameBytesToSend := []byte(hdr.Name) @@ -222,6 +225,8 @@ func copyCPIO(ctx context.Context, conn *tls.Conn, auth, path string, timeoutS u if err := resp.waitForOK(conn, "name copy failed"); err != nil { return err } + currentSize += uint64(len(nameBytesToSend)) + updateProgress(float64(currentSize), float64(size), callback) // 2'. Stop when `TRAILER!!!` met if shouldStop { @@ -263,6 +268,8 @@ func copyCPIO(ctx context.Context, conn *tls.Conn, auth, path string, timeoutS u } empty = false + currentSize += uint64(bread) + updateProgress(float64(currentSize), float64(size), callback) } } else { bread := len(hdr.Linkname) @@ -279,6 +286,8 @@ func copyCPIO(ctx context.Context, conn *tls.Conn, auth, path string, timeoutS u } empty = false + currentSize += uint64(bread) + updateProgress(float64(currentSize), float64(size), callback) } // Don't wait for ok if nothing was written @@ -307,3 +316,17 @@ func isNetClosedError(err error) bool { } return false } + +type progressCallbackFunc func(progress float64) + +// updateProgress updates the progress bar with the current progress. +// NOTE(craciunoiuc): Currently the entry pad nd the name pad are not taken +// into consideration so the progress will fall behind at times by some bytes. +func updateProgress(progress float64, size float64, callback progressCallbackFunc) { + pct := progress / size + // FIXME(antoineco): the TUI component does not turn green at the end of the + // copy if we call callback() with a value of 1. + if pct < 1.0 { + callback(pct) + } +} diff --git a/internal/cli/kraft/cloud/volume/import/fileread.go b/internal/cli/kraft/cloud/volume/import/fileread.go deleted file mode 100644 index 48e9e2e61..000000000 --- a/internal/cli/kraft/cloud/volume/import/fileread.go +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// Copyright (c) 2024, Unikraft GmbH and The KraftKit Authors. -// Licensed under the BSD-3-Clause License (the "License"). -// You may not use this file except in compliance with the License. - -package vimport - -import ( - "io" - "os" -) - -// newFileProgress wraps the given os.File so that the number of bytes copied -// from it can be tracked an reported through the given callback function. -func newFileProgress(f *os.File, fsize int64, callback progressCallbackFunc) *fileProgress { - return &fileProgress{ - f: f, - fsize: fsize, - callback: callback, - } -} - -type progressCallbackFunc func(progress float64) - -// fileProgress can track the number of bytes copied from an os.File. -type fileProgress struct { - f *os.File - fsize int64 - cpBytes int - callback progressCallbackFunc -} - -// NOTE(antoineco): fileProgress must not implement io.WriterTo, otherwise -// io.Copy favours that implementation over Read() and we lose the ability to -// track progress. -var _ io.Reader = (*fileProgress)(nil) - -// Read implements io.Reader. -func (f *fileProgress) Read(b []byte) (int, error) { - n, err := f.f.Read(b) - - f.cpBytes += n - pct := float64(f.cpBytes) / float64(f.fsize) - // FIXME(antoineco): the TUI component does not turn green at the end of the - // copy if we call callback() with a value of 1. - if pct < 1.0 { - f.callback(pct) - } - - return n, err -} diff --git a/internal/cli/kraft/cloud/volume/import/import.go b/internal/cli/kraft/cloud/volume/import/import.go index a35e0f2d3..58a1c1fe4 100644 --- a/internal/cli/kraft/cloud/volume/import/import.go +++ b/internal/cli/kraft/cloud/volume/import/import.go @@ -180,7 +180,7 @@ func importVolumeData(ctx context.Context, opts *ImportOptions) (retErr error) { ctx, cancel := context.WithCancel(ctx) defer cancel() - err = copyCPIO(ctx, conn, authStr, cpioPath, opts.Timeout) + err = copyCPIO(ctx, conn, authStr, cpioPath, opts.Timeout, uint64(cpioSize), callback) copyCPIOErr = err return err },