Skip to content

Commit e84427f

Browse files
committed
Add Alpine Linux (APK) support to vmupdate
related: QubesOS/qubes-issues#7323
1 parent 65eb613 commit e84427f

File tree

4 files changed

+123
-1
lines changed

4 files changed

+123
-1
lines changed

vmupdate/agent/entrypoint.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def main(args=None):
3232
)
3333

3434
log.debug("Notify dom0 about upgrades.")
35-
os.system("/usr/lib/qubes/upgrades-status-notify")
35+
os.system("bash /usr/lib/qubes/upgrades-status-notify")
3636

3737
if not args.no_cleanup:
3838
return_code = max(pkg_mng.clean(), return_code)
@@ -101,6 +101,9 @@ def get_package_manager(os_data, log, log_handler, log_level, no_progress):
101101
elif os_data["os_family"] == "ArchLinux":
102102
from source.pacman.pacman_cli import PACMANCLI as PackageManager
103103
print(f"Progress reporting not supported.", flush=True)
104+
elif os_data["os_family"] == "Alpine":
105+
from source.apk.apk_cli import APKCLI as PackageManager
106+
print(f"Progress reporting not supported.", flush=True)
104107
else:
105108
raise NotImplementedError(
106109
"Only Debian, RedHat and ArchLinux based OS is supported.")
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# coding=utf-8
2+
#
3+
# The Qubes OS Project, http://www.qubes-os.org
4+
#
5+
# Copyright (C) 2022 Piotr Bartman <[email protected]>
6+
#
7+
# This program is free software; you can redistribute it and/or
8+
# modify it under the terms of the GNU General Public License
9+
# as published by the Free Software Foundation; either version 2
10+
# of the License, or (at your option) any later version.
11+
#
12+
# This program is distributed in the hope that it will be useful,
13+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
# GNU General Public License for more details.
16+
#
17+
# You should have received a copy of the GNU General Public License
18+
# along with this program; if not, write to the Free Software
19+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20+
# USA.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# coding=utf-8
2+
#
3+
# The Qubes OS Project, http://www.qubes-os.org
4+
#
5+
# Copyright (C) 2022 Piotr Bartman <[email protected]>
6+
# Copyright (C) 2025 Ali Mirjamali <[email protected]>
7+
#
8+
# This program is free software; you can redistribute it and/or
9+
# modify it under the terms of the GNU General Public License
10+
# as published by the Free Software Foundation; either version 2
11+
# of the License, or (at your option) any later version.
12+
#
13+
# This program is distributed in the hope that it will be useful,
14+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
# GNU General Public License for more details.
17+
#
18+
# You should have received a copy of the GNU General Public License
19+
# along with this program; if not, write to the Free Software
20+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21+
# USA.
22+
23+
from os import environ, path
24+
from typing import List, Dict
25+
26+
from source.common.package_manager import PackageManager
27+
from source.common.process_result import ProcessResult
28+
from source.common.exit_codes import EXIT
29+
30+
31+
class APKCLI(PackageManager):
32+
def __init__(self, log_handler, log_level):
33+
super().__init__(log_handler, log_level)
34+
self.package_manager = "apk"
35+
self.clear_https_proxy = False
36+
self.clear_http_proxy = False
37+
if path.exists("/run/qubes-service/updates-proxy-setup"):
38+
if not "https_proxy" in environ:
39+
environ["https_proxy"] = "http://127.0.0.1:8082/"
40+
self.clear_https_proxy = True
41+
if not "https_proxy" in environ:
42+
environ["https_proxy"] = "http://127.0.0.1:8082/"
43+
self.clear_http_proxy = True
44+
45+
def __del__(self):
46+
if self.clear_https_proxy:
47+
environ.pop("https_proxy")
48+
if self.clear_http_proxy:
49+
environ.pop("http_proxy")
50+
51+
def refresh(self, hard_fail: bool) -> ProcessResult:
52+
"""
53+
Use package manager to refresh available packages.
54+
55+
:param hard_fail: raise error if some repo is unavailable
56+
:return: (exit_code, stdout, stderr)
57+
"""
58+
cmd = [self.package_manager, "update"]
59+
result = self.run_cmd(cmd)
60+
if result.code != 0:
61+
result.code = 1
62+
result.error_from_messages()
63+
return result
64+
65+
def get_packages(self) -> Dict[str, List[str]]:
66+
"""
67+
Use apk to return the installed packages and their versions.
68+
"""
69+
70+
cmd = [self.package_manager, "info", "-v"]
71+
# EXAMPLE OUTPUT:
72+
# qubes-vm-core-4.2.25-r1
73+
result = self.run_cmd(cmd, realtime=False)
74+
75+
packages: Dict[str, List[str]] = {}
76+
for line in result.out.splitlines():
77+
package, version, release = line.rsplit("-", maxsplit=2)
78+
packages.setdefault(package, []).append(version + "-" + release)
79+
80+
return packages
81+
82+
def get_action(self, remove_obsolete) -> List[str]:
83+
"""
84+
APK will handle obsoletions itself
85+
"""
86+
return ["upgrade", "--force", "--no-interactive"]
87+
88+
def clean(self) -> int:
89+
"""
90+
Clean cache files of package manager.
91+
Should return 0 on success or EXIT.ERR_VM_CLEANUP otherwise.
92+
"""
93+
cmd = [self.package_manager, "cache", "clean", "-f", "--no-interactive"]
94+
result = self.run_cmd(cmd, realtime=False)
95+
return_code = EXIT.ERR_VM_CLEANUP if result.code != 0 else 0
96+
return return_code

vmupdate/agent/source/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ def get_os_data(logger: Optional = None) -> Dict[str, Any]:
6565
if 'arch' in family:
6666
data["os_family"] = 'ArchLinux'
6767

68+
if 'alpine' in family:
69+
data["os_family"] = 'Alpine'
70+
6871
return data
6972

7073

0 commit comments

Comments
 (0)