[PATCH 1/3] virtinstall: Improve the progress bar output by meter.end()
Toshiki Sonoda
sonoda.toshiki at fujitsu.com
Wed Nov 9 09:33:55 UTC 2022
When virt-install transfers the vmlinuz and initrd.img from an iso disk,
virt-install prints the file size as 0B to the progress bar.
Therefore, we fix the meter to force update if meter.end()
is called earlier than self.update_period.
Signed-off-by: Toshiki Sonoda <sonoda.toshiki at fujitsu.com>
Signed-off-by: Haruka Ohata <ohata.haruka at fujitsu.com>
---
tests/data/meter/meter7.txt | 2 ++
tests/data/meter/meter8.txt | 6 ++++++
tests/test_misc.py | 35 ++++++++++++++++++++++++++------
virtManager/object/domain.py | 2 +-
virtinst/_progresspriv.py | 4 ++--
virtinst/diskbackend.py | 3 ++-
virtinst/install/urlfetcher.py | 6 ++++--
virtinst/install/volumeupload.py | 3 ++-
virtinst/progress.py | 4 ++--
virtinst/storage.py | 2 +-
10 files changed, 51 insertions(+), 16 deletions(-)
create mode 100644 tests/data/meter/meter7.txt
create mode 100644 tests/data/meter/meter8.txt
diff --git a/tests/data/meter/meter7.txt b/tests/data/meter/meter7.txt
new file mode 100644
index 00000000..ef467dcd
--- /dev/null
+++ b/tests/data/meter/meter7.txt
@@ -0,0 +1,2 @@
+
+Meter text test | 0 B 00:00 ...
diff --git a/tests/data/meter/meter8.txt b/tests/data/meter/meter8.txt
new file mode 100644
index 00000000..7e17ebf7
--- /dev/null
+++ b/tests/data/meter/meter8.txt
@@ -0,0 +1,6 @@
+
+Meter text test 40% [======- ] 0 B/s | 3.9 kB --:-- ETA
+
+Meter text test 80% [=============- ] 20 kB/s | 7.8 kB 00:00 ETA
+
+Meter text test | 7.8 kB 00:00 ...
diff --git a/tests/test_misc.py b/tests/test_misc.py
index aa610f4d..486d3d1e 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -167,20 +167,30 @@ def test_misc_meter():
with unittest.mock.patch("time.time", return_value=1.0):
m.start(text, startval)
with unittest.mock.patch("time.time", return_value=1.1):
- m.update(0)
+ m.update(0, False)
with unittest.mock.patch("time.time", return_value=1.5):
- m.update(0)
+ m.update(0, False)
with unittest.mock.patch("time.time", return_value=2.0):
- m.update(100)
+ m.update(100, False)
with unittest.mock.patch("time.time", return_value=3.0):
- m.update(200)
+ m.update(200, False)
with unittest.mock.patch("time.time", return_value=4.0):
- m.update(2000)
+ m.update(2000, False)
with unittest.mock.patch("time.time", return_value=5.0):
- m.update(4000)
+ m.update(4000, False)
with unittest.mock.patch("time.time", return_value=6.0):
m.end()
+ def _test_meter_end(m, force=False, startval=10000, text="Meter text test"):
+ with unittest.mock.patch("time.time", return_value=1.0):
+ m.start(text, startval)
+ with unittest.mock.patch("time.time", return_value=1.1):
+ m.update(4000, force)
+ with unittest.mock.patch("time.time", return_value=1.2):
+ m.update(8000, force)
+ with unittest.mock.patch("time.time", return_value=1.3):
+ m.end()
+
# Basic output testing
meter = _progresspriv.TextMeter(output=io.StringIO())
_test_meter_values(meter)
@@ -222,6 +232,19 @@ def test_misc_meter():
out = meter.output.getvalue().replace("\r", "\n")
utils.diff_compare(out, os.path.join(utils.DATADIR, "meter", "meter6.txt"))
+ # end() is called before meter is updated.
+ # In this case, we needs to call the update(num, True) before end() is called.
+ meter = _progresspriv.TextMeter(output=io.StringIO())
+ _test_meter_end(meter, False)
+ out = meter.output.getvalue().replace("\r", "\n")
+ utils.diff_compare(out, os.path.join(utils.DATADIR, "meter", "meter7.txt"))
+
+ # end() is called after meter is updated.
+ meter = _progresspriv.TextMeter(output=io.StringIO())
+ _test_meter_end(meter, True)
+ out = meter.output.getvalue().replace("\r", "\n")
+ utils.diff_compare(out, os.path.join(utils.DATADIR, "meter", "meter8.txt"))
+
# BaseMeter coverage
meter = _progresspriv.BaseMeter()
_test_meter_values(meter)
diff --git a/virtManager/object/domain.py b/virtManager/object/domain.py
index 2d6f5bca..e7d2afcc 100644
--- a/virtManager/object/domain.py
+++ b/virtManager/object/domain.py
@@ -50,7 +50,7 @@ def start_job_progress_thread(vm, meter, progtext):
meter.start(progtext, data_total)
progress = data_total - data_remaining
- meter.update(progress)
+ meter.update(progress, False)
except Exception: # pragma: no cover
log.exception("Error calling jobinfo")
return
diff --git a/virtinst/_progresspriv.py b/virtinst/_progresspriv.py
index 5a31a18c..119c4d2c 100644
--- a/virtinst/_progresspriv.py
+++ b/virtinst/_progresspriv.py
@@ -106,13 +106,13 @@ class BaseMeter:
self.last_amount_read = 0
self.last_update_time = now
- def update(self, amount_read):
+ def update(self, amount_read, force):
# for a real gui, you probably want to override and put a call
# to your mainloop iteration function here
assert type(amount_read) is int
now = time.time()
- if (not self.last_update_time or
+ if (force or not self.last_update_time or
(now >= self.last_update_time + self.update_period)):
self.re.update(amount_read, now)
self.last_amount_read = amount_read
diff --git a/virtinst/diskbackend.py b/virtinst/diskbackend.py
index 5f80c437..373797f1 100644
--- a/virtinst/diskbackend.py
+++ b/virtinst/diskbackend.py
@@ -617,6 +617,7 @@ class CloneStorageCreator(_StorageCreator):
l = os.read(src_fd, clone_block_size)
s = len(l)
if s == 0:
+ meter.update(i, True)
meter.end()
break
# check sequence of zeros
@@ -629,7 +630,7 @@ class CloneStorageCreator(_StorageCreator):
break
i += s
if i < size_bytes:
- meter.update(i)
+ meter.update(i, False)
except OSError as e: # pragma: no cover
log.debug("Error while cloning", exc_info=True)
msg = (_("Error cloning diskimage "
diff --git a/virtinst/install/urlfetcher.py b/virtinst/install/urlfetcher.py
index 4bd89c50..936d629a 100644
--- a/virtinst/install/urlfetcher.py
+++ b/virtinst/install/urlfetcher.py
@@ -118,10 +118,11 @@ class _URLFetcher(object):
while 1:
buff = urlobj.read(self._block_size)
if not buff:
+ self.meter.update(total, True)
break
fileobj.write(buff)
total += len(buff)
- self.meter.update(total)
+ self.meter.update(total, False)
fileobj.flush()
return total
@@ -253,7 +254,8 @@ class _HTTPURLFetcher(_URLFetcher):
for data in urlobj.iter_content(chunk_size=self._block_size):
fileobj.write(data)
total += len(data)
- self.meter.update(total)
+ self.meter.update(total, False)
+ self.meter.update(total, True)
fileobj.flush()
return total
diff --git a/virtinst/install/volumeupload.py b/virtinst/install/volumeupload.py
index 7046f294..21fa9f0a 100644
--- a/virtinst/install/volumeupload.py
+++ b/virtinst/install/volumeupload.py
@@ -112,11 +112,12 @@ def _upload_file(conn, meter, destpool, src):
blocksize = 1024 * 1024 # 1 MiB
data = fileobj.read(blocksize)
if not data:
+ meter.update(total, True)
break
safe_send(data)
total += len(data)
- meter.update(total)
+ meter.update(total, False)
# Cleanup
stream.finish()
diff --git a/virtinst/progress.py b/virtinst/progress.py
index b195b281..fe6f9933 100644
--- a/virtinst/progress.py
+++ b/virtinst/progress.py
@@ -34,9 +34,9 @@ class Meter:
self._total_read = 0
self._meter.start(text, size)
- def update(self, new_total):
+ def update(self, new_total, force):
self._total_read = new_total
- self._meter.update(new_total)
+ self._meter.update(new_total, force)
def end(self):
self._meter.end()
diff --git a/virtinst/storage.py b/virtinst/storage.py
index 509f5cb0..ee58c5f6 100644
--- a/virtinst/storage.py
+++ b/virtinst/storage.py
@@ -440,7 +440,7 @@ def _progress_thread(volname, pool, meter, event):
while True: # pragma: no cover
dummy1, dummy2, alloc = vol.info()
- meter.update(alloc)
+ meter.update(alloc, False)
if event.wait(1):
break
--
2.38.1
More information about the virt-tools-list
mailing list