Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop systemd service #663

Merged
merged 1 commit into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
device=$(losetup --list --noheadings --output NAME,BACK-FILE | grep myimage.raw | awk '{print $1}')
sudo mount "${device}p2" /mnt/
sudo ls /mnt/EFI/centos/{grub.cfg,shimx64.efi}
sudo umount /mnt
sudo losetup -D "${device}"
sudo rm -f myimage.raw
- name: bootc install to filesystem
Expand Down
12 changes: 2 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ ifeq ($(CONTAINER_RUNTIME), podman)
IMAGE_PREFIX = localhost/
endif

units = $(addprefix systemd/, bootupd.service bootupd.socket)

.PHONY: all
all: $(units)
all:
cargo build ${CARGO_ARGS}
ln -f target/${PROFILE}/bootupd target/${PROFILE}/bootupctl

Expand All @@ -33,17 +31,11 @@ create-build-container:
build-in-container: create-build-container
${CONTAINER_RUNTIME} run -ti --rm -v .:/srv/bootupd:z ${IMAGE_PREFIX}${IMAGE_NAME} make

.PHONY: install-units
install-units: $(units)
for unit in $(units); do install -D -m 644 --target-directory=$(DESTDIR)$(PREFIX)/lib/systemd/system/ $$unit; done

.PHONY: install
install: install-units
install:
mkdir -p "${DESTDIR}$(PREFIX)/bin" "${DESTDIR}$(LIBEXECDIR)"
install -D -t "${DESTDIR}$(LIBEXECDIR)" target/${PROFILE}/bootupd
ln -f ${DESTDIR}$(LIBEXECDIR)/bootupd ${DESTDIR}$(PREFIX)/bin/bootupctl
install -d "${DESTDIR}$(PREFIX)/lib/systemd/system/multi-user.target.wants"
ln -s ../bootupd.socket "${DESTDIR}$(PREFIX)/lib/systemd/system/multi-user.target.wants"

install-grub-static:
install -m 644 -D -t ${DESTDIR}$(PREFIX)/lib/bootupd/grub2-static src/grub2/*.cfg
Expand Down
9 changes: 0 additions & 9 deletions contrib/packaging/bootupd.spec
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,6 @@ cargo build --release
%make_install INSTALL="install -p -c"
make install-grub-static DESTDIR=%{?buildroot} INSTALL="%{__install} -p"

%post -n %{crate}
%systemd_post bootupd.service bootupd.socket

%preun -n %{crate}
%systemd_preun bootupd.service bootupd.socket

%postun -n %{crate}
%systemd_postun bootupd.service bootupd.socket

%changelog
* Tue Oct 18 2022 Colin Walters <walters@verbum.org> - 0.2.8-3
- Dummy changelog
43 changes: 11 additions & 32 deletions src/bootupd.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,18 @@
#[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))]
use crate::bios;
use crate::component;
use crate::component::{Component, ValidationResult};
use crate::coreos;
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
use crate::efi;
use crate::model::{ComponentStatus, ComponentUpdatable, ContentMetadata, SavedState, Status};
use crate::util;
use crate::{component, ipc};
use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::path::Path;

/// A message sent from client to server
#[derive(Debug, Serialize, Deserialize)]
pub(crate) enum ClientRequest {
/// Update a component
Update { component: String },
/// Update a component via adoption
AdoptAndUpdate { component: String },
/// Validate a component
Validate { component: String },
/// Print the current state
Status,
}

pub(crate) enum ConfigMode {
None,
Static,
Expand Down Expand Up @@ -408,8 +395,8 @@ pub(crate) fn print_status(status: &Status) -> Result<()> {
Ok(())
}

pub(crate) fn client_run_update(c: &mut ipc::ClientToDaemonConnection) -> Result<()> {
let status: Status = c.send(&ClientRequest::Status)?;
pub(crate) fn client_run_update() -> Result<()> {
let status: Status = status()?;
if status.components.is_empty() && status.adoptable.is_empty() {
println!("No components installed.");
return Ok(());
Expand All @@ -420,9 +407,7 @@ pub(crate) fn client_run_update(c: &mut ipc::ClientToDaemonConnection) -> Result
ComponentUpdatable::Upgradable => {}
_ => continue,
};
match c.send(&ClientRequest::Update {
component: name.to_string(),
})? {
match update(name)? {
ComponentUpdateResult::AtLatestVersion => {
// Shouldn't happen unless we raced with another client
eprintln!(
Expand Down Expand Up @@ -450,9 +435,7 @@ pub(crate) fn client_run_update(c: &mut ipc::ClientToDaemonConnection) -> Result
}
for (name, adoptable) in status.adoptable.iter() {
if adoptable.confident {
let r: ContentMetadata = c.send(&ClientRequest::AdoptAndUpdate {
component: name.to_string(),
})?;
let r: ContentMetadata = adopt_and_update(name)?;
println!("Adopted and updated: {}: {}", name, r.version);
updated = true;
} else {
Expand All @@ -465,32 +448,28 @@ pub(crate) fn client_run_update(c: &mut ipc::ClientToDaemonConnection) -> Result
Ok(())
}

pub(crate) fn client_run_adopt_and_update(c: &mut ipc::ClientToDaemonConnection) -> Result<()> {
let status: Status = c.send(&ClientRequest::Status)?;
pub(crate) fn client_run_adopt_and_update() -> Result<()> {
let status: Status = status()?;
if status.adoptable.is_empty() {
println!("No components are adoptable.");
} else {
for (name, _) in status.adoptable.iter() {
let r: ContentMetadata = c.send(&ClientRequest::AdoptAndUpdate {
component: name.to_string(),
})?;
let r: ContentMetadata = adopt_and_update(name)?;
println!("Adopted and updated: {}: {}", name, r.version);
}
}
Ok(())
}

pub(crate) fn client_run_validate(c: &mut ipc::ClientToDaemonConnection) -> Result<()> {
let status: Status = c.send(&ClientRequest::Status)?;
pub(crate) fn client_run_validate() -> Result<()> {
let status: Status = status()?;
if status.components.is_empty() {
println!("No components installed.");
return Ok(());
}
let mut caught_validation_error = false;
for (name, _) in status.components.iter() {
match c.send(&ClientRequest::Validate {
component: name.to_string(),
})? {
match validate(name)? {
ValidationResult::Valid => {
println!("Validated: {}", name);
}
Expand Down
79 changes: 53 additions & 26 deletions src/cli/bootupctl.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
use crate::bootupd;
use crate::ipc::ClientToDaemonConnection;
use crate::model::Status;
use anyhow::Result;
use clap::Parser;
use log::LevelFilter;

use std::os::unix::process::CommandExt;
use std::process::Command;

static SYSTEMD_ARGS_BOOTUPD: &[&str] = &[
"--unit",
"bootupd",
"--property",
"PrivateNetwork=yes",
"--property",
"ProtectHome=yes",
"--property",
"MountFlags=slave",
"--pipe",
];
cgwalters marked this conversation as resolved.
Show resolved Hide resolved

/// `bootupctl` sub-commands.
#[derive(Debug, Parser)]
#[clap(name = "bootupctl", about = "Bootupd client application", version)]
Expand Down Expand Up @@ -87,10 +100,8 @@ impl CtlCommand {

/// Runner for `status` verb.
fn run_status(opts: StatusOpts) -> Result<()> {
let mut client = ClientToDaemonConnection::new();
client.connect()?;

let r: Status = client.send(&bootupd::ClientRequest::Status)?;
ensure_running_in_systemd()?;
let r = bootupd::status()?;
HuijingHei marked this conversation as resolved.
Show resolved Hide resolved
if opts.json {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
Expand All @@ -101,38 +112,54 @@ impl CtlCommand {
bootupd::print_status(&r)?;
}

client.shutdown()?;
Ok(())
}

/// Runner for `update` verb.
fn run_update() -> Result<()> {
let mut client = ClientToDaemonConnection::new();
client.connect()?;

bootupd::client_run_update(&mut client)?;

client.shutdown()?;
Ok(())
ensure_running_in_systemd()?;
bootupd::client_run_update()
}

/// Runner for `update` verb.
fn run_adopt_and_update() -> Result<()> {
let mut client = ClientToDaemonConnection::new();
client.connect()?;

bootupd::client_run_adopt_and_update(&mut client)?;

client.shutdown()?;
Ok(())
ensure_running_in_systemd()?;
bootupd::client_run_adopt_and_update()
}

/// Runner for `validate` verb.
fn run_validate() -> Result<()> {
let mut client = ClientToDaemonConnection::new();
client.connect()?;
bootupd::client_run_validate(&mut client)?;
client.shutdown()?;
Ok(())
ensure_running_in_systemd()?;
bootupd::client_run_validate()
}
}

/// Checks if the current process is (apparently at least)
/// running under systemd.
fn running_in_systemd() -> bool {
std::env::var_os("INVOCATION_ID").is_some()
}

/// Require root permission
fn require_root_permission() -> Result<()> {
HuijingHei marked this conversation as resolved.
Show resolved Hide resolved
if !nix::unistd::Uid::effective().is_root() {
anyhow::bail!("This command requires root privileges")
}
Ok(())
}

/// Detect if we're running in systemd; if we're not, we re-exec ourselves via
/// systemd-run. Then we can just directly run code in what is now the daemon.
fn ensure_running_in_systemd() -> Result<()> {
require_root_permission()?;
let running_in_systemd = running_in_systemd();
if !running_in_systemd {
let r = Command::new("systemd-run")
.args(SYSTEMD_ARGS_BOOTUPD)
.args(std::env::args())
.exec();
// If we got here, it's always an error
return Err(r.into());
}
Ok(())
}
3 changes: 0 additions & 3 deletions src/cli/bootupd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ impl DCommand {
/// CLI sub-commands.
#[derive(Debug, Parser)]
pub enum DVerb {
#[clap(name = "daemon", about = "Run service logic")]
Daemon,
#[clap(name = "generate-update-metadata", about = "Generate metadata")]
GenerateUpdateMetadata(GenerateOpts),
#[clap(name = "install", about = "Install components")]
Expand Down Expand Up @@ -88,7 +86,6 @@ impl DCommand {
/// Run CLI application.
pub fn run(self) -> Result<()> {
match self.cmd {
DVerb::Daemon => crate::daemon::run(),
DVerb::Install(opts) => Self::run_install(opts),
DVerb::GenerateUpdateMetadata(opts) => Self::run_generate_meta(opts),
}
Expand Down
12 changes: 9 additions & 3 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ mod tests {
#[test]
fn test_multicall_dispatch() {
{
let d_argv = vec!["/usr/bin/bootupd".to_string(), "daemon".to_string()];
let d_argv = vec![
"/usr/bin/bootupd".to_string(),
"generate-update-metadata".to_string(),
];
let cli = MultiCall::from_args(d_argv);
match cli {
MultiCall::Ctl(cmd) => panic!("{:?}", cmd),
Expand All @@ -89,12 +92,15 @@ mod tests {

#[test]
fn test_verbosity() {
let default = MultiCall::from_args(vec!["bootupd".to_string(), "daemon".to_string()]);
let default = MultiCall::from_args(vec![
"bootupd".to_string(),
"generate-update-metadata".to_string(),
]);
assert_eq!(default.loglevel(), LevelFilter::Warn);

let info = MultiCall::from_args(vec![
"bootupd".to_string(),
"daemon".to_string(),
"generate-update-metadata".to_string(),
"-v".to_string(),
]);
assert_eq!(info.loglevel(), LevelFilter::Info);
Expand Down
Loading
Loading