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@xxxxxxxxxxx> Signed-off-by: Haruka Ohata <ohata.haruka@xxxxxxxxxxx> --- 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