Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions vmupdate/agent/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ def get_package_manager(os_data, log, log_handler, log_level, no_progress):
try:
from source.apt.apt_api import APT as PackageManager
except ImportError:
log.warning("Failed to load apt with progress bar. Use apt cli.")
log.warning("Failed to load apt with progress bar. Using apt cli.")
# no progress reporting
no_progress = True
print(f"Progress reporting not supported.", flush=True)

if no_progress:
from source.apt.apt_cli import APTCLI as PackageManager
Expand All @@ -77,20 +78,29 @@ def get_package_manager(os_data, log, log_handler, log_level, no_progress):
version = int(os_data["release"].split(".")[0])
except ValueError:
version = 99 # fedora changed its version
try:
if version < 41:
from source.dnf.dnf_api import DNF as PackageManager
else:

loaded = False
if version >= 41:
try:
from source.dnf.dnf5_api import DNF as PackageManager
except ImportError:
log.warning("Failed to load dnf with progress bar. Use dnf cli.")
# no progress reporting
no_progress = True
loaded = True
except ImportError:
log.warning("Failed to load dnf5.")

if no_progress:
if not loaded:
try:
from source.dnf.dnf_api import DNF as PackageManager
loaded = True
except ImportError:
log.warning(
"Failed to load dnf with progress bar. Using dnf cli.")
print(f"Progress reporting not supported.", flush=True)

if no_progress or not loaded:
from source.dnf.dnf_cli import DNFCLI as PackageManager
elif os_data["os_family"] == "ArchLinux":
from source.pacman.pacman_cli import PACMANCLI as PackageManager
print(f"Progress reporting not supported.", flush=True)
else:
raise NotImplementedError(
"Only Debian, RedHat and ArchLinux based OS is supported.")
Expand Down
84 changes: 43 additions & 41 deletions vmupdate/agent/source/dnf/dnf5_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,49 @@ def __init__(self, weight: int, log):
self.package_bytes = {}
self.package_names = {}
self.count = 0
self.fetching_notified = False

def add_new_download(
self, _user_data, description: str, total_to_download: float
) -> int:
"""
Notify the client that a new download has been created.

:param _user_data: User data entered together with url/package to download.
:param description: The message describing new download (url/packagename).
:param total_to_download: Total number of bytes to download.
:return: Associated user data for new download.
"""
self.count += 1
self.bytes_to_fetch += total_to_download
self.package_bytes[self.count] = 0
self.package_names[self.count] = description
# downloading is not started yet
self.notify_callback(0)
return self.count

def progress(
self, user_cb_data: int, total_to_download: float, downloaded: float
) -> int:
"""
Download progress callback.

:param user_cb_data: Associated user data obtained from add_new_download.
:param total_to_download: Total number of bytes to download.
:param downloaded: Number of bytes downloaded.
"""
if not self.fetching_notified:
print(f"Fetching {self.count} packages", flush=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe include total download size too here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I did it for all package managers

self.fetching_notified = True
self.bytes_fetched += downloaded - self.package_bytes[user_cb_data]
if downloaded > self.package_bytes[user_cb_data]:
self.package_bytes[user_cb_data] = downloaded
percent = self.bytes_fetched / self.bytes_to_fetch * 100
self.notify_callback(percent)
# Should return 0 on success,
# in case anything in dnf5 changed we return their default value
return DownloadCallbacks.progress(
self, user_cb_data, total_to_download, downloaded)

def end(self, user_cb_data: int, status: int, msg: str) -> int:
"""
Expand All @@ -144,8 +187,6 @@ def end(self, user_cb_data: int, status: int, msg: str) -> int:
"""
if status != 0:
print(msg, flush=True, file=self._stdout)
else:
print(f"{self.package_names[user_cb_data]}: Fetched", flush=True)
return DownloadCallbacks.end(self, user_cb_data, status, msg)

def mirror_failure(
Expand All @@ -165,45 +206,6 @@ def mirror_failure(
return DownloadCallbacks.mirror_failure(
self, user_cb_data, msg, url, metadata)

def progress(
self, user_cb_data: int, total_to_download: float, downloaded: float
) -> int:
"""
Download progress callback.

:param user_cb_data: Associated user data obtained from add_new_download.
:param total_to_download: Total number of bytes to download.
:param downloaded: Number of bytes downloaded.
"""
self.bytes_fetched += downloaded - self.package_bytes[user_cb_data]
self.package_bytes[user_cb_data] = downloaded
percent = self.bytes_fetched / self.bytes_to_fetch * 100
self.notify_callback(percent)
# Should return 0 on success,
# in case anything in dnf5 changed we return their default value
return DownloadCallbacks.progress(
self, user_cb_data, total_to_download, downloaded)

def add_new_download(
self, _user_data, description: str, total_to_download: float
) -> int:
"""
Notify the client that a new download has been created.

:param _user_data: User data entered together with url/package to download.
:param description: The message describing new download (url/packagename).
:param total_to_download: Total number of bytes to download.
:return: Associated user data for new download.
"""
print(f"Fetching package: {description}", flush=True)
self.count += 1
self.bytes_to_fetch += total_to_download
self.package_bytes[self.count] = 0
self.package_names[self.count] = description
# downloading is not started yet
self.notify_callback(0)
return self.count


class UpgradeProgress(TransactionCallbacks, Progress):
def __init__(self, weight: int, log):
Expand Down