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

Fixes #25695: Software update campaign does not work on Debian 10 Buster #5957

Draft
wants to merge 1 commit into
base: branches/rudder/8.2
Choose a base branch
from
Draft
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
5 changes: 3 additions & 2 deletions policies/module-types/system-updates/src/campaign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ pub fn check_update(
if do_update {
let report = update(pm, p.reboot_type, p.campaign_type, p.package_list)?;
db.store_report(&p.event_id, &report)?;

// Dubious }
}

// Update takes time
let do_post_actions = db.post_event(&p.event_id)?;

if do_post_actions {
let init_report = db.get_report(&p.event_id)?;
let report = post_update(init_report)?;
Expand All @@ -80,7 +81,7 @@ pub fn check_update(
}

let now_finished = Utc::now();
db.sent(&p.event_id, now_finished)?;
db.completed(&p.event_id, now_finished)?;

// The repaired status is the trigger to read and send the report.
Ok(Outcome::Repaired("Update has run".to_string()))
Expand Down
46 changes: 37 additions & 9 deletions policies/module-types/system-updates/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ impl PackageDatabase {

/// Schedule an event
///
/// The insertion also acts as the locking mechanism
pub fn schedule_event(
&mut self,
event_id: &str,
Expand All @@ -129,7 +128,7 @@ impl PackageDatabase {
if !already_scheduled {
tx.execute(
"insert into update_events (event_id, campaign_name, status, schedule_datetime) values (?1, ?2, ?3, ?4)",
(&event_id, &campaign_name, UpdateStatus::Scheduled.to_string(), schedule_datetime.to_rfc3339()),
(&event_id, &campaign_name, UpdateStatus::ScheduledUpdate.to_string(), schedule_datetime.to_rfc3339()),
)?;
}

Expand All @@ -140,6 +139,8 @@ impl PackageDatabase {
/// Start an event
///
/// The update also acts as the locking mechanism
///
/// We take the actual start time, which is >= scheduled.
pub fn start_event(
&mut self,
event_id: &str,
Expand All @@ -149,7 +150,7 @@ impl PackageDatabase {

let r = tx.query_row(
"select id from update_events where event_id = ?1 and status = ?2",
(&event_id, UpdateStatus::Scheduled.to_string()),
(&event_id, UpdateStatus::ScheduledUpdate.to_string()),
|_| Ok(()),
);
let pending_update = match r {
Expand All @@ -161,7 +162,7 @@ impl PackageDatabase {
tx.execute(
"update update_events set status = ?1, run_datetime = ?2 where event_id = ?3",
(
UpdateStatus::Running.to_string(),
UpdateStatus::RunningUpdate.to_string(),
start_datetime.to_rfc3339(),
&event_id,
),
Expand All @@ -172,6 +173,32 @@ impl PackageDatabase {
Ok(pending_update)
}

/// Schedule post-event action. Can happen after a reboot in a separate run.
///
pub fn schedule_post_event(&mut self, event_id: &str) -> Result<bool, rusqlite::Error> {
let tx = self.conn.transaction()?;

let r = tx.query_row(
"select event_id from update_events where event_id = ?1 and status = ?2",
(&event_id, UpdateStatus::RunningUpdate.to_string()),
|_| Ok(()),
);
let pending_post_actions = match r {
Ok(_) => true,
Err(rusqlite::Error::QueryReturnedNoRows) => false,
Err(e) => return Err(e),
};
if pending_post_actions {
tx.execute(
"update update_events set status = ?1 where event_id = ?2",
(UpdateStatus::PendingPostActions.to_string(), &event_id),
)?;
}

tx.commit()?;
Ok(pending_post_actions)
}

/// Start post-event action. Can happen after a reboot in a separate run.
///
/// The update also acts as the locking mechanism
Expand All @@ -180,7 +207,7 @@ impl PackageDatabase {

let r = tx.query_row(
"select event_id from update_events where event_id = ?1 and status = ?2",
(&event_id, UpdateStatus::Running.to_string()),
(&event_id, UpdateStatus::PendingPostActions.to_string()),
|_| Ok(()),
);
let pending_post_actions = match r {
Expand All @@ -191,7 +218,7 @@ impl PackageDatabase {
if pending_post_actions {
tx.execute(
"update update_events set status = ?1 where event_id = ?2",
(UpdateStatus::PendingPostActions.to_string(), &event_id),
(UpdateStatus::RunningPostActions.to_string(), &event_id),
)?;
}

Expand All @@ -207,6 +234,7 @@ impl PackageDatabase {
Ok(())
}

/// Assumes the report exists, fails otherwise
pub fn get_report(&self, event_id: &str) -> Result<Report, rusqlite::Error> {
self.conn.query_row(
"select report from update_events where event_id = ?1",
Expand All @@ -220,7 +248,7 @@ impl PackageDatabase {
}

/// Mark the event as completed
pub fn sent(
pub fn completed(
&self,
event_id: &str,
report_datetime: DateTime<Utc>,
Expand Down Expand Up @@ -334,7 +362,7 @@ mod tests {
let event = Event {
id: event_id.to_string(),
campaign_name: campaign_name.to_string(),
status: UpdateStatus::Running,
status: UpdateStatus::RunningUpdate,
scheduled_datetime: schedule,
run_datetime: Some(start),
report_datetime: None,
Expand All @@ -346,7 +374,7 @@ mod tests {
let ref_event = Event {
id: event_id.to_string(),
campaign_name: campaign_name.to_string(),
status: UpdateStatus::Running,
status: UpdateStatus::RunningUpdate,
scheduled_datetime: schedule,
run_datetime: Some(start),
report_datetime: None,
Expand Down
6 changes: 5 additions & 1 deletion policies/module-types/system-updates/src/packages.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ create table if not exists update_events (
report_datetime text,

-- report sent to the server
report text -- json string
report text, -- json string

-- process id of the current process handling the upgrade
-- when not null, acts as a lock
pid integer
);

create index if not exists idx_event_id on update_events (event_id);
20 changes: 14 additions & 6 deletions policies/module-types/system-updates/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,26 @@ use std::{
/// in case of interruption.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum UpdateStatus {
Scheduled,
Running,
/// Wait until schedule
ScheduledUpdate,
/// Schedule is reached, start update and reboot if necessary
RunningUpdate,
/// Update is over, waiting for next agent run for post-actions in case of a reboot
PendingPostActions,
/// Running post-actions and report
RunningPostActions,
/// Nothing to do
Completed,
}

impl Display for UpdateStatus {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Scheduled => "scheduled",
Self::Running => "running",
Self::ScheduledUpdate => "scheduled",
Self::RunningUpdate => "running",
Self::Completed => "completed",
Self::PendingPostActions => "pending-post-actions",
Self::RunningPostActions => "running-post-actions",
})
}
}
Expand All @@ -33,10 +40,11 @@ impl FromStr for UpdateStatus {

fn from_str(s: &str) -> anyhow::Result<Self, Self::Err> {
match s {
"running" => Ok(Self::Running),
"scheduled" => Ok(Self::Scheduled),
"running" => Ok(Self::RunningUpdate),
"scheduled" => Ok(Self::ScheduledUpdate),
"completed" => Ok(Self::Completed),
"pending-post-actions" => Ok(Self::PendingPostActions),
"running-post-actions" => Ok(Self::RunningPostActions),
_ => Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
"Invalid input",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"event_id": "30c87fee-f6b0-42b1-9adb-be067217f1a9",
"campaign_name": "My campaign",
"schedule": "immediate",
"reboot_type": "as_needed"
"reboot_type": "as-needed"
},
"node_id": "node",
"agent_frequency_minutes": 5,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@
"end": "2023-01-01T00:00:00Z"
}
},
"reboot_type": "as_needed",
"reboot_type": "as-needed",
"package_list": [
{
"name": "apache2",
"version": "2.4.29-1ubuntu4.14"
},
{
"name": "nginx",
"version": "1.14.0-0ubuntu1.7"
}
{
"name": "apache2",
"version": "2.4.29-1ubuntu4.14"
},
{
"name": "nginx",
"version": "1.14.0-0ubuntu1.7"
}
],
"report_file": "/tmp/report.json",
"schedule_file": "/tmp/schedule.json"
Expand Down