Skip to content

Commit 280f3d6

Browse files
committed
update_agent: add update finalization
This adds support for finalizating an OS update.
1 parent fcc1dac commit 280f3d6

File tree

2 files changed

+72
-13
lines changed

2 files changed

+72
-13
lines changed

src/update_agent/actor.rs

+50-8
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,15 @@ impl Handler<RefreshTick> for UpdateAgent {
3838
let update = release.clone();
3939
self.try_stage_update(update)
4040
}
41-
UpdateAgentState::UpdateStaged(_release) => self.todo(),
42-
UpdateAgentState::_EndState => self.nop(),
41+
UpdateAgentState::UpdateStaged(release) => {
42+
let update = release.clone();
43+
self.try_finalize_update(update)
44+
}
45+
UpdateAgentState::UpdateFinalized(release) => {
46+
let update = release.clone();
47+
self.end(update)
48+
}
49+
UpdateAgentState::EndState => self.nop(),
4350
};
4451

4552
let update_machine = state_action.then(move |_r, actor, ctx| {
@@ -127,6 +134,26 @@ impl UpdateAgent {
127134
Box::new(state_change)
128135
}
129136

137+
/// Try to finalize an update.
138+
fn try_finalize_update(&mut self, release: Release) -> ResponseActFuture<Self, (), ()> {
139+
trace!("trying to finalize an update");
140+
141+
let can_finalize = self.strategy.can_finalize(&self.identity);
142+
let state_change = actix::fut::wrap_future::<_, Self>(can_finalize)
143+
.and_then(|can_finalize, actor, _ctx| actor.finalize_deployment(can_finalize, release))
144+
.map(|release, actor, _ctx| actor.state.update_finalized(release));
145+
146+
Box::new(state_change)
147+
}
148+
149+
/// Actor job is done.
150+
fn end(&mut self, release: Release) -> ResponseActFuture<Self, (), ()> {
151+
log::info!("update applied, waiting for reboot: {}", release.version);
152+
let state_change = self.nop().map(|_r, actor, _ctx| actor.state.end());
153+
154+
Box::new(state_change)
155+
}
156+
130157
/// Fetch and stage an update, in finalization-locked mode.
131158
fn locked_upgrade(
132159
&mut self,
@@ -148,15 +175,30 @@ impl UpdateAgent {
148175
Box::new(upgrade)
149176
}
150177

178+
/// Finalize a deployment (unlock and reboot).
179+
fn finalize_deployment(
180+
&mut self,
181+
can_finalize: bool,
182+
release: Release,
183+
) -> ResponseActFuture<Self, Release, ()> {
184+
if !can_finalize {
185+
return Box::new(actix::fut::err(()));
186+
}
187+
188+
let msg = rpm_ostree::FinalizeDeployment { release };
189+
let upgrade = self
190+
.rpm_ostree_actor
191+
.send(msg)
192+
.flatten()
193+
.map_err(|e| log::error!("failed to finalize update: {}", e))
194+
.into_actor(self);
195+
196+
Box::new(upgrade)
197+
}
198+
151199
/// Do nothing, without errors.
152200
fn nop(&mut self) -> ResponseActFuture<Self, (), ()> {
153201
let nop = actix::fut::ok(());
154202
Box::new(nop)
155203
}
156-
157-
/// Pending implementation.
158-
fn todo(&mut self) -> ResponseActFuture<Self, (), ()> {
159-
log::error!("pending implementation");
160-
self.nop()
161-
}
162204
}

src/update_agent/mod.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ enum UpdateAgentState {
2727
UpdateAvailable(Release),
2828
/// Update staged by rpm-ostree.
2929
UpdateStaged(Release),
30-
// TODO(lucab): add all the "update in progress" states.
30+
/// Update finalized by rpm-ostree.
31+
UpdateFinalized(Release),
3132
/// Final state upon actor end.
32-
_EndState,
33+
EndState,
3334
}
3435

3536
impl Default for UpdateAgentState {
@@ -71,6 +72,16 @@ impl UpdateAgentState {
7172
fn update_staged(&mut self, update: Release) {
7273
*self = UpdateAgentState::UpdateStaged(update);
7374
}
75+
76+
/// Transition to the UpdateFinalized state.
77+
fn update_finalized(&mut self, update: Release) {
78+
*self = UpdateAgentState::UpdateFinalized(update);
79+
}
80+
81+
/// Transition to the End state.
82+
fn end(&mut self) {
83+
*self = UpdateAgentState::EndState;
84+
}
7485
}
7586

7687
/// Update agent.
@@ -143,9 +154,15 @@ mod tests {
143154
checksum: "ostree-checksum".to_string(),
144155
};
145156
machine.update_available(Some(update.clone()));
157+
assert_eq!(machine, UpdateAgentState::UpdateAvailable(update.clone()));
158+
159+
machine.update_staged(update.clone());
160+
assert_eq!(machine, UpdateAgentState::UpdateStaged(update.clone()));
161+
162+
machine.update_finalized(update.clone());
163+
assert_eq!(machine, UpdateAgentState::UpdateFinalized(update.clone()));
146164

147-
machine.update_staged(update);
148-
// TODO(lucab): complete the full path till reaching EndState.
149-
// assert_eq!(machine, UpdateAgentState::_EndState);
165+
machine.end();
166+
assert_eq!(machine, UpdateAgentState::EndState);
150167
}
151168
}

0 commit comments

Comments
 (0)