This commit is contained in:
arcolinuxz 2024-05-29 21:15:47 +02:00
parent a62abdff41
commit b09f56fa6c
15 changed files with 450 additions and 406 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
usr/share/archlinux-kernel-manager/libs/__pycache__
usr/share/archlinux-kernel-manager/ui/__pycache__

View file

@ -1,6 +1,6 @@
# Arch Linux Kernel Manager
A GTK4 Python application used to install and remove Linux Kernels on an Arch based system.
A GTK4 Python application which installs and removes Linux Kernels on Arch Linux based systems.
Installation and removal of Kernels is carried out using Pacman.
@ -20,7 +20,7 @@ Both official and un-official community based Kernels are supported.
Since the ALA has a lot of kernel packages any versions found older than 2 years or more are ignored.
These kernels are considerably out of date and have shown to fail to install properly with issues related to missing modules.
![Official kernels](https://github.com/DeltaCopy/archlinux-kernel-manager/assets/121581829/d3e0416d-5ba8-4906-bada-835f4d949130)
![Official kernels](https://github.com/arcolinux/archlinux-kernel-manager-dev/assets/121581829/2e30c26f-a06d-4ab9-91a7-14e1ced99389)
## What happens if a kernel installation fails
@ -43,11 +43,11 @@ Most of these are sourced from the [Chaotic AUR](https://aur.chaotic.cx)
See updating the [configuration file](#Adding-new-community-based-kernels) for adding new kernels.
![Community kernels](https://github.com/DeltaCopy/archlinux-kernel-manager/assets/121581829/072bc9b2-cca4-4c5a-ae91-be9c0440feb3)
![Community kernels](https://github.com/arcolinux/archlinux-kernel-manager-dev/assets/121581829/8e28de8d-35eb-45b2-b799-cd691c092852)
# Installed kernels
![Installed kernels](https://github.com/DeltaCopy/archlinux-kernel-manager/assets/121581829/1120c9cc-adc1-4f2c-92c5-dff8d1d1c841)
![Installed kernels](https://github.com/arcolinux/archlinux-kernel-manager-dev/assets/121581829/75e98bd6-dd46-4c91-807c-a042cb3a3f04)
# Progress window
@ -75,13 +75,13 @@ By default, the application will use `bootctl` to distinguish which bootloader (
The bootloader settings can be overridden using the Advanced settings window.
Or you can manually update the configuration file (see the custom bootloader example).
![Advanced settings](https://github.com/DeltaCopy/archlinux-kernel-manager/assets/121581829/827033b1-9250-4967-9431-e2b6205ed3a0)
![Advanced settings](https://github.com/arcolinux/archlinux-kernel-manager-dev/assets/121581829/0a5cd26d-7991-4cea-ab43-26c36e57b135)
## Latest kernel versions
Based on the latest information taken from the configured pacman mirrors.
![Kernel versions](https://github.com/DeltaCopy/archlinux-kernel-manager/assets/121581829/43416b00-3759-4913-8d09-8f9083edc358)
![Kernel versions](https://github.com/arcolinux/archlinux-kernel-manager-dev/assets/121581829/a4dccbf9-969a-4ef0-bd8c-b212f31ea2cb)
# Default configuration file
@ -156,12 +156,6 @@ Logs can be found inside `/var/log/archlinux-kernel-manager`
- python-psutil
# Installing the application
`wget https://raw.githubusercontent.com/DeltaCopy/archlinux-kernel-manager/main/PKGBUILD`
`makepkg -si`
# Running the application
Run `akm` or `archlinux-kernel-manager` to launch the application.

View file

@ -4,49 +4,93 @@
# the polkit agent running on the desktop environment should prompt for root password
echo "---------------------------------------------------------------------------"
echo "[INFO] Checking session"
test $(whoami) == "root" && echo "[ERROR] Do not run this script as root." && exit 1
test -z $DISPLAY && echo "[ERROR] DISPLAY variable is not set." && exit 1
echo "[INFO]: Checking session"
test $(whoami) == "root" && echo "[ERROR]: Do not run this script as root." && exit 1
test -z $DISPLAY && echo "[ERROR]: DISPLAY variable is not set." && exit 1
# check session is either one of X11, Wayland or TTY
session=$(loginctl show-session $(loginctl|grep $(whoami) | awk '{print $1}') -p Type | awk -F= '{print $2}' | grep "x11\|wayland\|tty")
SESSION=$(loginctl show-session $(loginctl|grep $(whoami) | awk '{print $1}') -p Type | awk -F= '{print $2}' | grep "x11\|wayland\|tty")
test -z "$SESSION" && echo "[ERROR]: Failed to verify session for user, SESSION = $SESSION" && exit 1
test -z "$session" && echo "[ERROR] Failed to verify session for user." && exit 1
XAUTHORITY=$(xauth info | awk -F"Authority file:" '{print $2}' | tr -d ' ')
test -z "$XAUTHORITY" && echo "[ERROR]: XAUTHORIY file is not set" && exit 1
test -s "$XAUTHORITY" || touch "$XAUTHORITY"
xauth_file=$(xauth info | awk -F"Authority file:" '{print $2}' | tr -d ' ')
test -s "$xauth_file" || touch "$xauth_file"
XAUTH_HONORED=$(xauth info | awk -F"Changes honored:" '{print $2}' | tr -d ' ')
test $XAUTH_HONORED = "yes" || echo "[ERROR]: Xauth changes honored = no, restart X server" || exit 1
case "$session" in
"wayland")
# Wayland session, generate Xauth session cookie for $DISPLAY
xauth gen $DISPLAY &> /dev/null
echo "[INFO] Display = $DISPLAY"
echo "[INFO] Session = $session"
# GTK_A11Y=none - fixes the dbus-launch errors with GTK4
test -z "$(xauth list)" || echo "[INFO] Xauth session = OK"
;;
"x11")
# X11 session, don't do anything here
echo "[INFO] Display = $DISPLAY"
echo "[INFO] Session = $session"
echo "[INFO]: XAUTHORITY = $XAUTHORITY"
echo "[INFO]: DBUS_SESSION_BUS_ADDRESS = $DBUS_SESSION_BUS_ADDRESS"
echo "[INFO]: DESKTOP SESSION = $DESKTOP_SESSION"
# just show msg on whether the Xauth session cookie is setup
test -z "$(xauth list)" || echo "[INFO] Xauth session = OK"
;;
"tty")
# TTY session, as user may not use a display manager
echo "[INFO] Display = $DISPLAY"
echo "[INFO] Session = $session"
function start_in_wayland() {
echo "[INFO]: Starting in Wayland session"
xauth gen $DISPLAY &> /dev/null
test -z "$(xauth list)" || echo "[INFO] Xauth session = OK"
;;
*)
# anything here is an unknown session, most likely AKM will fail to load
echo "[WARN] Continuing, but cannot verify session for user."
;;
esac
case "$DESKTOP_SESSION" in
plasma | gnome)
pkexec env DISPLAY=$DISPLAY WAYLAND_DISPLAY="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" XAUTHORITY=$XAUTHORITY DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS GDK_BACKEND=x11 GTK_A11Y=none '/usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py'
;;
*)
pkexec env DISPLAY=$DISPLAY WAYLAND_DISPLAY="$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" XAUTHORITY=$XAUTHORITY DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS GTK_A11Y=none '/usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py'
;;
esac
}
function start_in_x11() {
echo "[INFO]: Starting in X11 session"
pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS GTK_A11Y=none '/usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py'
}
function start_in_tty() {
echo "[INFO]: Starting in TTY session"
pkexec '/usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py'
}
case "$SESSION" in
"wayland")
# Wayland session, generate Xauth session cookie for $DISPLAY
echo "[INFO]: Display = $DISPLAY"
echo "[INFO]: Session = $SESSION"
start_in_wayland
;;
"x11")
# X11 session, don't do anything here
echo "[INFO]: Display = $DISPLAY"
echo "[INFO]: Session = $SESSION"
# just show msg on whether the Xauth session cookie is setup
start_in_x11
;;
"tty")
# TTY session, as user may not use a display manager
echo "[INFO]: Display = $DISPLAY"
echo "[INFO]: Session = $SESSION"
start_in_tty
;;
*)
# anything here is an unknown session, most likely AKM will fail to load
echo "[INFO]: Display = $DISPLAY"
echo "[INFO]: Session could not be verified ... falling back to use XDG_SESSION_TYPE"
case "$XDG_SESSION_TYPE" in
"wayland")
start_in_wayland
;;
"tty")
start_in_tty
;;
"x11")
start_in_x11
;;
*)
echo "[ERROR]: $XDG_SESSION_TYPE is empty, cannot continue"
exit 1
;;
esac
;;
esac
echo "---------------------------------------------------------------------------"
echo "[INFO] Starting Arch Linux Kernel Manager"
pkexec '/usr/share/archlinux-kernel-manager/archlinux-kernel-manager.py'

View file

@ -39,7 +39,7 @@ box#box_row{
box#hbox_kernel{
background-color: @theme_base_color;
padding-bottom: 8px;
box-shadow: -6px 8px 10px rgba(81,41,10,0.1),0px 2px 2px rgba(81,41,10,0.2);
/*box-shadow: -6px 8px 10px rgba(81,41,10,0.1),0px 2px 2px rgba(81,41,10,0.2);*/
}
box#vbox_header{
@ -53,7 +53,7 @@ box#vbox_header{
border-spacing: 5px;
font-weight: bold;
font-family: 'Noto Sans', 'Helvetica', sans-serif;
box-shadow: -6px 8px 10px rgba(81,41,10,0.1),0px 2px 2px rgba(81,41,10,0.2);
/*box-shadow: -6px 8px 10px rgba(81,41,10,0.1),0px 2px 2px rgba(81,41,10,0.2);*/
}
box#hbox_warning{
@ -156,15 +156,6 @@ button#button_uninstall_kernel{
padding: 10px 10px 10px 10px;
}
.sidebar label:hover,
.sidebar label:focus{
font-weight: bold;
}
#hbox_stack_sidebar{
box-shadow: rgba(33, 35, 38, 0.1) 0px 10px 10px -10px;
}
#textview_log text{
background-color: #232627;
color: #fcfcfc;

View file

@ -17,7 +17,7 @@ base_dir = fn.os.path.dirname(fn.os.path.realpath(__file__))
app_name = "Arch Linux Kernel Manager"
app_version = "${app_version}"
app_name_dir = "archlinux-kernel-manager"
app_id = "com.deltacopy.kernelmanager"
app_id = "com.arcolinux.kernelmanager"
lock_file = "/tmp/akm.lock"
pid_file = "/tmp/akm.pid"
@ -30,6 +30,7 @@ class Main(Gtk.Application):
default_context = GLib.MainContext.default()
win = self.props.active_window
if not win:
win = ManagerGUI(
application=self,
@ -42,7 +43,6 @@ class Main(Gtk.Application):
# sourced from /usr/share/icons/hicolor/scalable/apps
win.set_icon_name("archlinux-kernel-manager-tux")
provider = Gtk.CssProvider.new()
css_file = Gio.file_new_for_path(base_dir + "/akm.css")
provider.load_from_file(css_file)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before After
Before After

View file

@ -395,64 +395,67 @@ def write_cache():
# install from the ALA
def install_archive_kernel(self):
try:
for pkg_archive_url in self.official_kernels:
if self.errors_found is True:
break
install_cmd_str = [
"pacman",
"-U",
self.official_kernels[0],
self.official_kernels[1],
"--noconfirm",
"--needed",
]
install_cmd_str = [
"pacman",
"-U",
pkg_archive_url,
"--noconfirm",
"--needed",
]
wait_for_pacman_process()
wait_for_pacman_process()
logger.info("Running %s" % install_cmd_str)
logger.info("Running %s" % install_cmd_str)
event = "%s [INFO]: Running %s\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(install_cmd_str),
)
event = "%s [INFO]: Running %s\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(install_cmd_str),
)
event_log = []
self.messages_queue.put(event)
event_log = []
self.messages_queue.put(event)
with subprocess.Popen(
install_cmd_str,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
universal_newlines=True,
) as process:
while True:
if process.poll() is not None:
break
for line in process.stdout:
print(line.strip())
self.messages_queue.put(line)
event_log.append(line.lower().strip())
with subprocess.Popen(
install_cmd_str,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
universal_newlines=True,
) as process:
while True:
if process.poll() is not None:
break
for line in process.stdout:
print(line.strip())
self.messages_queue.put(line)
event_log.append(line.lower().strip())
time.sleep(0.3)
time.sleep(0.3)
error = None
error = None
if (
"installation finished. no error reported."
or "initcpio image generation successful" in event_log
):
error = False
if "installation finished. no error reported." in event_log:
error = False
else:
else:
if error is None:
# check errors and indicate to user install failed
for log in event_log:
# if "installation finished. no error reported." in log:
# error = False
# break
if "error" in log or "errors" in log:
event = (
"%s <b>[ERROR]: Errors have been encountered during installation</b>\n"
% (datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"))
)
logger.error(log)
self.messages_queue.put(event)
self.errors_found = True
@ -471,57 +474,49 @@ def install_archive_kernel(self):
break
# query to check if kernel installed
if "headers" in pkg_archive_url:
if (
check_kernel_installed(self.kernel.name + "-headers")
and error is False
):
# query to check if kernel installed
self.kernel_state_queue.put(
(0, "install", self.kernel.name + "-headers")
)
if check_kernel_installed(self.kernel.name + "-headers") and error is False:
event = "%s [INFO]: Installation of %s-headers completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
self.kernel_state_queue.put((0, "install", self.kernel.name + "-headers"))
self.messages_queue.put(event)
event = "%s [INFO]: Installation of %s-headers completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
else:
self.kernel_state_queue.put(
(1, "install", self.kernel.name + "-headers")
)
self.messages_queue.put(event)
event = "%s [ERROR]: Installation of %s-headers failed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
else:
self.kernel_state_queue.put((1, "install", self.kernel.name + "-headers"))
self.errors_found = True
self.messages_queue.put(event)
event = "%s [ERROR]: Installation of %s-headers failed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
else:
if check_kernel_installed(self.kernel.name) and error is False:
self.kernel_state_queue.put((0, "install", self.kernel.name))
self.errors_found = True
self.messages_queue.put(event)
event = "%s [INFO]: Installation of kernel %s completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
if check_kernel_installed(self.kernel.name) and error is False:
self.kernel_state_queue.put((0, "install", self.kernel.name))
self.messages_queue.put(event)
event = "%s [INFO]: Installation of kernel %s completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
else:
self.kernel_state_queue.put((1, "install", self.kernel.name))
self.messages_queue.put(event)
event = "%s [ERROR]: Installation of kernel %s failed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
else:
self.kernel_state_queue.put((1, "install", self.kernel.name))
self.messages_queue.put(event)
event = "%s [ERROR]: Installation of kernel %s failed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
self.messages_queue.put(event)
# signal to say end reached
self.kernel_state_queue.put(None)
@ -1117,80 +1112,76 @@ def get_community_kernels(self):
# =====================================================
def install_community_kernel(self):
try:
for kernel in [self.kernel.name, "%s-headers" % self.kernel.name]:
error = False
error = False
install_cmd_str = [
"pacman",
"-S",
"%s/%s" % (self.kernel.repository, self.kernel.name),
"%s/%s" % (self.kernel.repository, "%s-headers" % self.kernel.name),
"--noconfirm",
"--needed",
]
if self.errors_found is True:
logger.info("Running %s" % install_cmd_str)
event = "%s [INFO]: Running %s\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(install_cmd_str),
)
event_log = []
self.messages_queue.put(event)
with subprocess.Popen(
install_cmd_str,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
universal_newlines=True,
) as process:
while True:
if process.poll() is not None:
break
for line in process.stdout:
print(line.strip())
self.messages_queue.put(line)
event_log.append(line.lower().strip())
time.sleep(0.3)
for log in event_log:
if "installation finished. no error reported." in log:
error = False
break
install_cmd_str = [
"pacman",
"-S",
"%s/%s" % (self.kernel.repository, kernel),
"--noconfirm",
"--needed",
]
if "error" in log:
error = True
logger.info("Running %s" % install_cmd_str)
if check_kernel_installed(self.kernel.name) and error is False:
logger.info("Kernel = installed")
event = "%s [INFO]: Running %s\n" % (
self.kernel_state_queue.put((0, "install", self.kernel.name))
event = "%s [INFO]: Installation of %s completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(install_cmd_str),
self.kernel.name,
)
event_log = []
self.messages_queue.put(event)
with subprocess.Popen(
install_cmd_str,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
universal_newlines=True,
) as process:
while True:
if process.poll() is not None:
break
for line in process.stdout:
print(line.strip())
self.messages_queue.put(line)
event_log.append(line.lower().strip())
else:
logger.error("Kernel = install failed")
time.sleep(0.3)
self.kernel_state_queue.put((1, "install", self.kernel.name))
for log in event_log:
if "installation finished. no error reported." in log:
error = False
break
event = "%s [ERROR]: Installation of %s failed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.kernel.name,
)
if "error" in log:
error = True
if check_kernel_installed(kernel) and error == False:
logger.info("Kernel = installed")
self.kernel_state_queue.put((0, "install", kernel))
event = "%s [INFO]: Installation of %s completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
kernel,
)
self.messages_queue.put(event)
else:
logger.error("Kernel = install failed")
self.kernel_state_queue.put((1, "install", kernel))
event = "%s [ERROR]: Installation of %s failed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
kernel,
)
self.errors_found = True
self.messages_queue.put(event)
self.errors_found = True
self.messages_queue.put(event)
# signal to say end reached
self.kernel_state_queue.put(None)
@ -1407,8 +1398,9 @@ def get_boot_loader():
def get_kernel_version(kernel):
cmd = ["pacman", "-Q", kernel]
cmd = ["pacman", "-Qli", kernel]
# pacman_kernel_version = None
kernel_modules_path = None
try:
logger.debug("Running %s" % " ".join(cmd))
process = subprocess.run(
@ -1423,12 +1415,68 @@ def get_kernel_version(kernel):
if process.returncode == 0:
for line in process.stdout.splitlines():
print(line.strip())
return line.split(" ")[1]
# if line.startswith("Version :"):
# pacman_kernel_version = line.split("Version :")[1].strip()
# print(pacman_kernel_version)
if "/usr/lib/modules/" in line:
if "kernel" in line.split(" ")[1]:
kernel_modules_path = line.split(" ")[1]
break
if kernel_modules_path is not None:
return (
kernel_modules_path.split("/usr/lib/modules/")[1]
.strip()
.split("/kernel/")[0]
.strip()
)
else:
return None
except Exception as e:
logger.error("Exception in get_kernel_version(): %s" % e)
def run_process(self):
error = False
logger.debug("Running process = %s" % " ".join(self.cmd))
with subprocess.Popen(
self.cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
universal_newlines=True,
) as process:
while True:
if process.poll() is not None:
break
for line in process.stdout:
self.messages_queue.put(line)
self.stdout_lines.append(line.lower().strip())
print(line.strip())
for log in self.stdout_lines:
if "error" in log or "errors" in log:
self.errors_found = True
error = True
if error is True:
self.label_notify_revealer.set_text("%s failed" % " ".join(self.cmd))
self.reveal_notify()
logger.error("%s failed" % " ".join(self.cmd))
else:
self.label_notify_revealer.set_text("%s completed" % " ".join(self.cmd))
self.reveal_notify()
logger.info("%s completed" % " ".join(self.cmd))
# time.sleep(0.3)
# ======================================================================
# UPDATE BOOTLOADER ENTRIES
# ======================================================================
@ -1437,14 +1485,30 @@ def get_kernel_version(kernel):
# grub - grub-mkconfig /boot/grub/grub.cfg
# systemd-boot - bootctl update
def update_bootloader(self):
cmd = None
cmds = []
error = False
self.stdout_lines = []
if self.action == "install":
image = "images/48x48/akm-install.png"
cmd = ["kernel-install", "add-all"]
if self.installed_kernel_version is not None:
for self.cmd in [
["kernel-install", "add-all"],
["kernel-install", "remove", self.installed_kernel_version],
]:
run_process(self)
else:
self.cmd = ["kernel-install", "add-all"]
run_process(self)
else:
image = "images/48x48/akm-remove.png"
cmd = ["kernel-install", "remove", self.installed_kernel_version]
if self.installed_kernel_version is not None:
self.cmd = ["kernel-install", "remove", self.installed_kernel_version]
run_process(self)
try:
@ -1460,17 +1524,35 @@ def update_bootloader(self):
logger.info("Current bootloader = %s" % self.bootloader)
if cmd is not None:
stdout_lines = []
cmd = None
if self.bootloader == "grub":
if self.bootloader_grub_cfg is not None:
cmd = ["grub-mkconfig", "-o", self.bootloader_grub_cfg]
else:
logger.error("Bootloader grub config file not specified")
event = "%s [INFO]: Running %s\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(cmd),
)
self.messages_queue.put(event)
logger.info("Running %s" % " ".join(cmd))
elif self.bootloader == "systemd-boot":
# cmd = ["bootctl", "update"]
# graceful update systemd-boot
cmd = ["bootctl", "--no-variables", "--graceful", "update"]
event = "%s [INFO]: Running %s\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(cmd),
)
self.messages_queue.put(event)
else:
logger.error("Bootloader is empty / not supported")
if cmd is not None:
self.stdout_lines = []
logger.info("Running %s" % " ".join(cmd))
with subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
@ -1482,183 +1564,105 @@ def update_bootloader(self):
if process.poll() is not None:
break
for line in process.stdout:
self.stdout_lines.append(line.strip())
self.messages_queue.put(line)
stdout_lines.append(line.lower().strip())
print(line.strip())
# time.sleep(0.3)
error = False
if process.returncode == 0:
self.label_notify_revealer.set_text(
"Bootloader %s updated" % self.bootloader
)
self.reveal_notify()
for log in stdout_lines:
if "error" in log or "errors" in log:
logger.info("%s update completed" % self.bootloader)
# event = (
# "%s <b>[ERROR]: Errors have been encountered during installation</b>\n"
# % (datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"))
# )
#
# self.messages_queue.put(event)
event = "%s [INFO]: %s update completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.bootloader,
)
self.messages_queue.put(event)
self.errors_found = True
logger.info("Linux packages have changed a reboot is recommended")
event = "%s [INFO]: <b>#### Linux packages have changed a reboot is recommended ####</b>\n" % datetime.datetime.now().strftime(
"%Y-%m-%d-%H-%M-%S"
)
self.messages_queue.put(event)
error = True
if self.restore is False:
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} completed</b>\n"
f"This window can now be closed\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
else:
if (
"Skipping"
or "same boot loader version in place already." in stdout_lines
):
logger.info("%s update completed" % self.bootloader)
if error is True:
self.label_notify_revealer.set_text("%s failed" % " ".join(cmd))
self.reveal_notify()
event = "%s [INFO]: <b>%s update completed</b>\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.bootloader,
)
self.messages_queue.put(event)
logger.error("%s failed" % " ".join(cmd))
else:
self.label_notify_revealer.set_text("%s completed" % " ".join(cmd))
self.reveal_notify()
if self.restore is False:
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} completed</b>\n"
f"This window can now be closed\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
logger.info("%s completed" % " ".join(cmd))
if self.bootloader == "grub":
if self.bootloader_grub_cfg is not None:
cmd = ["grub-mkconfig", "-o", self.bootloader_grub_cfg]
else:
logger.error("Bootloader grub config file not specified")
self.label_notify_revealer.set_text(
"Bootloader %s update failed" % self.bootloader
)
self.reveal_notify()
event = "%s [INFO]: Running %s\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(cmd),
)
self.messages_queue.put(event)
event = "%s [ERROR]: <b>%s update failed</b>\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.bootloader,
)
elif self.bootloader == "systemd-boot":
# cmd = ["bootctl", "update"]
# graceful update systemd-boot
cmd = ["bootctl", "--no-variables", "--graceful", "update"]
event = "%s [INFO]: Running %s\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
" ".join(cmd),
)
self.messages_queue.put(event)
else:
logger.error("Bootloader is empty / not supported")
logger.error("%s update failed" % self.bootloader)
logger.error(str(stdout_lines))
self.messages_queue.put(event)
if cmd is not None:
stdout_lines = []
logger.info("Running %s" % " ".join(cmd))
with subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
universal_newlines=True,
) as process:
while True:
if process.poll() is not None:
break
for line in process.stdout:
stdout_lines.append(line.strip())
self.messages_queue.put(line)
print(line.strip())
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} failed .. attempting kernel restore</b>\n"
f"There have been errors, please review the logs\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
# time.sleep(0.3)
if process.returncode == 0:
self.label_notify_revealer.set_text(
"Bootloader %s updated" % self.bootloader
)
self.reveal_notify()
logger.info("%s update completed" % self.bootloader)
event = "%s [INFO]: %s update completed\n" % (
datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
self.bootloader,
)
self.messages_queue.put(event)
logger.info(
"Linux packages have changed a reboot is recommended"
)
event = "%s [INFO]: <b>#### Linux packages have changed a reboot is recommended ####</b>\n" % datetime.datetime.now().strftime(
"%Y-%m-%d-%H-%M-%S"
)
self.messages_queue.put(event)
if self.restore is False:
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} completed</b>\n"
f"This window can now be closed\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
else:
if (
"Skipping"
or "same boot loader version in place already."
in stdout_lines
):
logger.info("%s update completed" % self.bootloader)
event = "%s [INFO]: <b>%s update completed</b>\n" % (
datetime.datetime.now().strftime(
"%Y-%m-%d-%H-%M-%S"
),
self.bootloader,
)
self.messages_queue.put(event)
if self.restore is False:
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} completed</b>\n"
f"This window can now be closed\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
else:
self.label_notify_revealer.set_text(
"Bootloader %s update failed" % self.bootloader
)
self.reveal_notify()
event = "%s [ERROR]: <b>%s update failed</b>\n" % (
datetime.datetime.now().strftime(
"%Y-%m-%d-%H-%M-%S"
),
self.bootloader,
)
logger.error("%s update failed" % self.bootloader)
logger.error(str(stdout_lines))
self.messages_queue.put(event)
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} failed .. attempting kernel restore</b>\n"
f"There have been errors, please review the logs\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
else:
logger.error("Bootloader update failed")
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} failed</b>\n"
f"There have been errors, please review the logs\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
else:
logger.error("Bootloader update cannot continue, failed to set command.")
logger.error("Bootloader update failed")
GLib.idle_add(
show_mw,
self,
"System changes",
f"<b>Kernel {self.action} failed</b>\n"
f"There have been errors, please review the logs\n",
image,
priority=GLib.PRIORITY_DEFAULT,
)
# else:
# logger.error("Bootloader update cannot continue, failed to set command.")
except Exception as e:
logger.error("Exception in update_bootloader(): %s" % e)

View file

@ -13,14 +13,13 @@ class AboutDialog(Gtk.AboutDialog):
def __init__(self, manager_gui, **kwargs):
super().__init__(**kwargs)
website = "https://github.com/DeltaCopy/archlinux-kernel-manager"
authors = ["fennec (DeltaCopy)"]
website = "http://arcolinux.info/"
authors = ["Erik Dubois", "Fennec"]
program_name = "Arch Linux Kernel Manager"
comments = (
f"Add/Remove Officially supported Linux kernels on Arch based systems\n"
f"Powered by the Arch Linux Archive (a.k.a ALA)\n"
f"Community based Linux kernels are also supported\n"
f"This application matches your system theme !\n"
f"Developed in Python with GTK 4\n"
)
@ -40,7 +39,7 @@ class AboutDialog(Gtk.AboutDialog):
tux_icon = Gdk.Texture.new_from_file(
file=Gio.File.new_for_path(
os.path.join(base_dir, "images/364x408/akm-tux-splash.png")
os.path.join(base_dir, "images/96x96/akm-tux.png")
)
)

View file

@ -107,26 +107,29 @@ class FlowBox(Gtk.FlowBox):
) == "{}-{}".format(cache.name, cache.version):
installed = True
if (
cache.name == installed_kernel.name
and cache.version > installed_kernel.version
):
fn.logger.info(
"Kernel upgrade available - %s %s"
% (cache.name, cache.version)
)
tux_icon = Gtk.Picture.new_for_file(
file=Gio.File.new_for_path(
os.path.join(base_dir, "images/48x48/akm-update.png")
if cache.name == installed_kernel.name:
if (
cache.version > installed_kernel.version
or cache.version != installed_kernel.version
):
fn.logger.info(
"Kernel upgrade available - %s %s"
% (cache.name, cache.version)
)
)
tux_icon.set_can_shrink(True)
label_kernel_name.set_markup(
"<b>*%s</b> %s <i>%s</i>"
% (cache.name, cache.version, cache.repository)
)
tux_icon = Gtk.Picture.new_for_file(
file=Gio.File.new_for_path(
os.path.join(
base_dir, "images/48x48/akm-update.png"
)
)
)
tux_icon.set_can_shrink(True)
label_kernel_name.set_markup(
"<b>*%s</b> %s <i>%s</i>"
% (cache.name, cache.version, cache.repository)
)
if installed is True:
switch_kernel.set_state(True)

View file

@ -15,6 +15,8 @@ class MessageWindow(Gtk.Window):
# self.set_title(title=title)
self.set_modal(modal=True)
self.set_resizable(False)
icon_name = "akm-tux"
self.set_icon_name(icon_name)
header_bar = Gtk.HeaderBar()
header_bar.set_show_title_buttons(True)
@ -57,7 +59,7 @@ class MessageWindow(Gtk.Window):
msg_buffer.insert(
msg_buffer.get_end_iter(),
"Event timestamp = %s\n"
% fn.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
% fn.datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
)
msg_buffer.insert(msg_buffer.get_end_iter(), "%s\n" % message)
@ -82,7 +84,7 @@ class MessageWindow(Gtk.Window):
button_ok.set_halign(Gtk.Align.END)
button_ok.connect("clicked", self.on_button_ok_clicked)
hbox_buttons = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
hbox_buttons = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=20)
hbox_buttons.set_halign(Gtk.Align.END)
hbox_buttons.append(button_ok)

View file

@ -94,8 +94,15 @@ class ProgressWindow(Gtk.Window):
% (self.kernel.name, self.kernel.version)
)
# get kernel version from pacman
self.installed_kernel_version = fn.get_kernel_version(self.kernel.name)
# get kernel version from pacman
self.installed_kernel_version = fn.get_kernel_version(self.kernel.name)
if self.installed_kernel_version is not None:
fn.logger.debug(
"Installed kernel version = %s" % self.installed_kernel_version
)
else:
fn.logger.debug("Nothing to remove .. previous kernel not installed")
image_settings.set_halign(Gtk.Align.START)
image_settings.set_icon_size(Gtk.IconSize.LARGE)
@ -418,8 +425,9 @@ class ProgressWindow(Gtk.Window):
)
mw.present()
else:
self.destroy()
return True
return False
def check_kernel_state(self):
returncode = None
@ -439,12 +447,6 @@ class ProgressWindow(Gtk.Window):
fn.logger.info("Kernel %s completed" % action)
event = "%s [INFO]: <b>Kernel %s completed</b>\n" % (
fn.datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S"),
action,
)
self.messages_queue.put(event)
if returncode == 1:
self.errors_found = True

View file

@ -2,7 +2,7 @@ import gi
import libs.functions as fn
gi.require_version("Gtk", "4.0")
from gi.repository import Gtk, Gio, GLib, GdkPixbuf, GObject, Gdk
from gi.repository import Gtk, Gio
base_dir = fn.os.path.abspath(fn.os.path.join(fn.os.path.dirname(__file__), ".."))
@ -12,15 +12,18 @@ class SplashScreen(Gtk.Window):
super().__init__(**kwargs)
self.set_decorated(False)
self.set_resizable(False)
self.set_default_size(600, 400)
self.set_modal(True)
self.set_title(app_name)
self.set_icon_name("archlinux-kernel-manager-tux")
tux_icon = Gtk.Picture.new_for_file(
file=Gio.File.new_for_path(
fn.os.path.join(base_dir, "images/364x408/akm-tux-splash.png")
fn.os.path.join(base_dir, "images/600x400/akm-tux-splash.png")
)
)
tux_icon.set_content_fit(content_fit=Gtk.ContentFit.FILL)
self.set_child(child=tux_icon)