• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender / 1019363462

28 Sep 2023 08:41AM UTC coverage: 78.477% (+0.9%) from 77.556%
1019363462

push

gitlab-ci

kacf
chore: Make out `optional` use compatible with C++17.

If the standard is pre-C++17, we use the `optional-lite` library, else
we use the one in `std`.

Signed-off-by: Kristian Amlie <kristian.amlie@northern.tech>

17 of 17 new or added lines in 6 files covered. (100.0%)

5546 of 7067 relevant lines covered (78.48%)

11103.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.3
/mender-update/daemon/state_machine/state_machine.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <common/conf.hpp>
16
#include <common/log.hpp>
17

18
#include <mender-update/daemon/states.hpp>
19
#include <mender-update/daemon/state_machine.hpp>
20

21
namespace mender {
22
namespace update {
23
namespace daemon {
24

25
namespace conf = mender::common::conf;
26
namespace log = mender::common::log;
27

28
StateMachine::StateMachine(Context &ctx, events::EventLoop &event_loop) :
91✔
29
        ctx_(ctx),
30
        event_loop_(event_loop),
31
        check_update_handler_(event_loop),
32
        inventory_update_handler_(event_loop),
33
        termination_handler_(event_loop),
34
        submit_inventory_state_(event_loop),
35
        poll_for_deployment_state_(event_loop),
36
        send_download_status_state_(deployments::DeploymentStatus::Downloading),
37
        send_install_status_state_(deployments::DeploymentStatus::Installing),
38
        send_reboot_status_state_(deployments::DeploymentStatus::Rebooting),
39
        send_commit_status_state_(
40
                deployments::DeploymentStatus::Installing,
41
                event_loop,
42
                ctx.mender_context.GetConfig().retry_poll_interval_seconds),
91✔
43
        // nullopt means: Fetch success/failure status from deployment context
44
        send_final_status_state_(
45
                nullopt, event_loop, ctx.mender_context.GetConfig().retry_poll_interval_seconds),
91✔
46
        exit_state_(event_loop),
47
        main_states_(init_state_),
48
        state_scripts_(
49
                event_loop,
50
                chrono::seconds {ctx.mender_context.GetConfig().state_script_timeout_seconds},
91✔
51
                ctx_.mender_context.GetConfig().paths.GetArtScriptsPath(),
182✔
52
                ctx_.mender_context.GetConfig().paths.GetRootfsScriptsPath()),
91✔
53
        runner_(ctx) {
364✔
54
        runner_.AddStateMachine(main_states_);
55
        runner_.AddStateMachine(deployment_tracking_.states_);
91✔
56

57
        runner_.AttachToEventLoop(event_loop_);
91✔
58

59
        using se = StateEvent;
60
        using tf = sm::TransitionFlag;
61

62
        auto &ss = state_scripts_;
63

64
        // When updating the table below, make sure that the initial states are in sync as well, in
65
        // LoadStateFromDb().
66

67
        // clang-format off
68
        main_states_.AddTransition(init_state_,                             se::Started,                     ss.idle_enter_,                          tf::Immediate);
91✔
69

70
        main_states_.AddTransition(ss.idle_enter_,                          se::Success,                     idle_state_,                             tf::Immediate);
91✔
71
        main_states_.AddTransition(ss.idle_enter_,                          se::Failure,                     idle_state_,                             tf::Immediate);
72

73
        main_states_.AddTransition(idle_state_,                             se::DeploymentPollingTriggered,  ss.idle_leave_deploy_,                   tf::Deferred);
91✔
74
        main_states_.AddTransition(idle_state_,                             se::InventoryPollingTriggered,   ss.idle_leave_inv_,                      tf::Deferred);
91✔
75

76
        main_states_.AddTransition(ss.idle_leave_deploy_,                   se::Success,                     ss.sync_enter_deployment_,               tf::Immediate);
91✔
77
        main_states_.AddTransition(ss.idle_leave_deploy_,                   se::Failure,                     ss.sync_enter_deployment_,               tf::Immediate);
78

79
        main_states_.AddTransition(ss.sync_enter_deployment_,               se::Success,                     poll_for_deployment_state_,              tf::Immediate);
91✔
80
        main_states_.AddTransition(ss.sync_enter_deployment_,               se::Failure,                     ss.sync_error_,                          tf::Immediate);
91✔
81

82
        main_states_.AddTransition(ss.sync_error_,                          se::Success,                     ss.idle_enter_,                          tf::Immediate);
83
        main_states_.AddTransition(ss.sync_error_,                          se::Failure,                     ss.idle_enter_,                          tf::Immediate);
84

85
        main_states_.AddTransition(ss.idle_leave_inv_,                      se::Success,                     ss.sync_enter_inventory_,                tf::Immediate);
91✔
86
        main_states_.AddTransition(ss.idle_leave_inv_,                      se::Failure,                     ss.sync_enter_inventory_,                tf::Immediate);
87

88
        main_states_.AddTransition(ss.sync_enter_inventory_,                se::Success,                     submit_inventory_state_,                 tf::Immediate);
91✔
89
        main_states_.AddTransition(ss.sync_enter_inventory_,                se::Failure,                     ss.sync_error_,                          tf::Immediate);
90

91
        main_states_.AddTransition(submit_inventory_state_,                 se::Success,                     ss.sync_leave_,                          tf::Immediate);
91✔
92
        main_states_.AddTransition(submit_inventory_state_,                 se::Failure,                     ss.sync_error_,                          tf::Immediate);
93

94
        main_states_.AddTransition(poll_for_deployment_state_,              se::Success,                     ss.sync_leave_download_,                 tf::Immediate);
91✔
95
        main_states_.AddTransition(poll_for_deployment_state_,              se::NothingToDo,                 ss.sync_leave_,                          tf::Immediate);
96
        main_states_.AddTransition(poll_for_deployment_state_,              se::Failure,                     ss.sync_error_,                          tf::Immediate);
97

98
        main_states_.AddTransition(ss.sync_leave_,                          se::Success,                     ss.idle_enter_,                          tf::Immediate);
99
        main_states_.AddTransition(ss.sync_leave_,                          se::Failure,                     ss.sync_error_,                          tf::Immediate);
100

101
        main_states_.AddTransition(ss.sync_leave_download_,                 se::Success,                     send_download_status_state_,             tf::Immediate);
91✔
102
        main_states_.AddTransition(ss.sync_leave_download_,                 se::Failure,                     ss.sync_error_,                          tf::Immediate);
103

104
        // Cannot fail due to FailureMode::Ignore.
105
        main_states_.AddTransition(send_download_status_state_,             se::Success,                     ss.download_enter_,                      tf::Immediate);
91✔
106

107
        main_states_.AddTransition(ss.download_enter_,                      se::Success,                     update_download_state_,                  tf::Immediate);
91✔
108
        main_states_.AddTransition(ss.download_enter_,                      se::Failure,                     ss.download_error_,                      tf::Immediate);
91✔
109
        main_states_.AddTransition(ss.download_enter_,                      se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
91✔
110
        main_states_.AddTransition(ss.download_error_,                      se::Success,                     update_rollback_not_needed_state_,       tf::Immediate);
111
        main_states_.AddTransition(ss.download_error_,                      se::Failure,                     update_rollback_not_needed_state_,       tf::Immediate);
112

113
        main_states_.AddTransition(update_download_state_,                  se::Success,                     ss.download_leave_,                      tf::Immediate);
91✔
114
        main_states_.AddTransition(update_download_state_,                  se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
115
        main_states_.AddTransition(update_download_state_,                  se::Failure,                     ss.download_error_,                      tf::Immediate);
116
        main_states_.AddTransition(update_download_state_,                  se::NothingToDo,                 ss.download_leave_save_provides,         tf::Immediate);
91✔
117

118
        main_states_.AddTransition(ss.download_leave_,                      se::Success,                     send_install_status_state_,              tf::Immediate);
91✔
119
        main_states_.AddTransition(ss.download_leave_,                      se::Failure,                     ss.download_error_,                      tf::Immediate);
120

121
        main_states_.AddTransition(ss.download_leave_save_provides,         se::Success,                     update_save_provides_state_,             tf::Immediate);
91✔
122
        main_states_.AddTransition(ss.download_leave_save_provides,         se::Failure,                     ss.download_error_,                      tf::Immediate);
123

124
        main_states_.AddTransition(ss.install_enter_,                       se::Success,                     update_install_state_,                   tf::Immediate);
91✔
125
        main_states_.AddTransition(ss.install_enter_,                       se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
91✔
126

127
        // Cannot fail due to FailureMode::Ignore.
128
        main_states_.AddTransition(send_install_status_state_,              se::Success,                     ss.install_enter_,                       tf::Immediate);
129

130
        main_states_.AddTransition(update_install_state_,                   se::Success,                     ss.install_leave_,                       tf::Immediate);
91✔
131
        main_states_.AddTransition(update_install_state_,                   se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
132
        main_states_.AddTransition(update_install_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
133

134
        main_states_.AddTransition(ss.install_leave_,                       se::Success,                     update_check_reboot_state_,              tf::Immediate);
91✔
135
        main_states_.AddTransition(ss.install_leave_,                       se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
136
        main_states_.AddTransition(ss.install_error_rollback_,              se::Success,                     update_check_rollback_state_,            tf::Immediate);
91✔
137
        main_states_.AddTransition(ss.install_error_rollback_,              se::Failure,                     update_check_rollback_state_,            tf::Immediate);
138

139
        main_states_.AddTransition(ss.failure_enter_,                       se::Success,                     update_failure_state_,                   tf::Immediate);
91✔
140
        main_states_.AddTransition(ss.failure_enter_,                       se::Failure,                     update_failure_state_,                   tf::Immediate);
141
        main_states_.AddTransition(ss.failure_enter_,                       se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
142

143

144
        main_states_.AddTransition(update_check_reboot_state_,              se::Success,                     send_reboot_status_state_,               tf::Immediate);
91✔
145
        main_states_.AddTransition(update_check_reboot_state_,              se::NothingToDo,                 update_before_commit_state_,             tf::Immediate);
91✔
146
        main_states_.AddTransition(update_check_reboot_state_,              se::Failure,                     update_check_rollback_state_,            tf::Immediate);
147
        main_states_.AddTransition(update_check_reboot_state_,              se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
148

149
        // Cannot fail due to FailureMode::Ignore.
150
        main_states_.AddTransition(send_reboot_status_state_,               se::Success,                     ss.reboot_enter_,                        tf::Immediate);
91✔
151

152
        main_states_.AddTransition(ss.reboot_enter_,                        se::Success,                     update_reboot_state_,                    tf::Immediate);
91✔
153
        main_states_.AddTransition(ss.reboot_enter_,                        se::Failure,                     ss.reboot_error_,                        tf::Immediate);
91✔
154

155
        main_states_.AddTransition(update_reboot_state_,                    se::Success,                     update_verify_reboot_state_,             tf::Immediate);
91✔
156
        main_states_.AddTransition(update_reboot_state_,                    se::Failure,                     ss.reboot_error_,                        tf::Immediate);
157
        main_states_.AddTransition(update_reboot_state_,                    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
158

159
        main_states_.AddTransition(ss.reboot_error_,                        se::Success,                     update_check_rollback_state_,            tf::Immediate);
160
        main_states_.AddTransition(ss.reboot_error_,                        se::Failure,                     update_check_rollback_state_,            tf::Immediate);
161

162
        main_states_.AddTransition(update_verify_reboot_state_,             se::Success,                     ss.reboot_leave_,                        tf::Immediate);
91✔
163
        main_states_.AddTransition(update_verify_reboot_state_,             se::Failure,                     ss.reboot_error_,                        tf::Immediate);
164
        main_states_.AddTransition(update_verify_reboot_state_,             se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
165

166
        main_states_.AddTransition(ss.reboot_leave_,                        se::Success,                     update_before_commit_state_,             tf::Immediate);
167
        main_states_.AddTransition(ss.reboot_leave_,                        se::Failure,                     ss.reboot_error_,                        tf::Immediate);
168

169
        // Cannot fail.
170
        main_states_.AddTransition(update_before_commit_state_,             se::Success,                     send_commit_status_state_,               tf::Immediate);
91✔
171

172
        main_states_.AddTransition(send_commit_status_state_,               se::Success,                     ss.commit_enter_,                        tf::Immediate);
91✔
173
        main_states_.AddTransition(send_commit_status_state_,               se::Failure,                     update_check_rollback_state_,            tf::Immediate);
174

175
        main_states_.AddTransition(ss.commit_enter_,                        se::Success,                     update_commit_state_,                    tf::Immediate);
91✔
176
        main_states_.AddTransition(ss.commit_enter_,                        se::Failure,                     ss.commit_error_,                        tf::Immediate);
91✔
177

178
        main_states_.AddTransition(ss.commit_error_,                        se::Success,                     update_check_rollback_state_,            tf::Immediate);
179
        main_states_.AddTransition(ss.commit_error_,                        se::Failure,                     update_check_rollback_state_,            tf::Immediate);
180

181
        main_states_.AddTransition(update_commit_state_,                    se::Success,                     update_after_commit_state_,              tf::Immediate);
91✔
182
        main_states_.AddTransition(update_commit_state_,                    se::Failure,                     ss.commit_error_,                        tf::Immediate);
183
        main_states_.AddTransition(update_commit_state_,                    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
184

185
        main_states_.AddTransition(update_after_commit_state_,              se::Success,                     ss.commit_leave_,                        tf::Immediate);
91✔
186
        main_states_.AddTransition(update_after_commit_state_,              se::Failure,                     ss.commit_error_save_provides_,          tf::Immediate);
91✔
187
        main_states_.AddTransition(update_after_commit_state_,              se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
188

189
        main_states_.AddTransition(ss.commit_leave_,                        se::Success,                     update_save_provides_state_,             tf::Immediate);
190
        main_states_.AddTransition(ss.commit_leave_,                        se::Failure,                     ss.commit_error_save_provides_,          tf::Immediate);
191

192
        main_states_.AddTransition(ss.commit_error_save_provides_,          se::Success,                     update_save_provides_state_,             tf::Immediate);
193
        main_states_.AddTransition(ss.commit_error_save_provides_,          se::Failure,                     update_save_provides_state_,             tf::Immediate);
194

195
        main_states_.AddTransition(update_check_rollback_state_,            se::Success,                     ss.rollback_enter_,                      tf::Immediate);
91✔
196
        main_states_.AddTransition(update_check_rollback_state_,            se::NothingToDo,                 ss.failure_enter_,                       tf::Immediate);
197
        main_states_.AddTransition(update_check_rollback_state_,            se::Failure,                     ss.failure_enter_,                       tf::Immediate);
198
        main_states_.AddTransition(update_check_rollback_state_,            se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
199

200
        main_states_.AddTransition(ss.rollback_enter_,                      se::Success,                     update_rollback_state_,                  tf::Immediate);
91✔
201
        main_states_.AddTransition(ss.rollback_enter_,                      se::Failure,                     update_rollback_state_,                  tf::Immediate);
202

203
        main_states_.AddTransition(update_rollback_state_,                  se::Success,                     ss.rollback_leave_,                      tf::Immediate);
91✔
204
        main_states_.AddTransition(update_rollback_state_,                  se::Failure,                     ss.rollback_leave_error_,                tf::Immediate);
91✔
205
        main_states_.AddTransition(update_rollback_state_,                  se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
206

207
        main_states_.AddTransition(ss.rollback_leave_,                      se::Success,                     update_check_rollback_reboot_state_,     tf::Immediate);
91✔
208
        main_states_.AddTransition(ss.rollback_leave_,                      se::Failure,                     update_check_rollback_reboot_state_,     tf::Immediate);
209

210
        main_states_.AddTransition(ss.rollback_leave_error_,                se::Success,                     ss.failure_enter_,                       tf::Immediate);
211
        main_states_.AddTransition(ss.rollback_leave_error_,                se::Failure,                     ss.failure_enter_,                       tf::Immediate);
212

213
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::Success,                     ss.rollback_reboot_enter_,               tf::Immediate);
91✔
214
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::NothingToDo,                 update_rollback_successful_state_,       tf::Immediate);
91✔
215
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::Failure,                     ss.failure_enter_,                       tf::Immediate);
216
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
217

218
        main_states_.AddTransition(ss.rollback_reboot_enter_,               se::Success,                     update_rollback_reboot_state_,           tf::Immediate);
91✔
219
        main_states_.AddTransition(ss.rollback_reboot_enter_,               se::Failure,                     update_rollback_reboot_state_,           tf::Immediate);
220

221
        main_states_.AddTransition(ss.rollback_reboot_error_,               se::Success,                     ss.failure_enter_,                       tf::Immediate);
91✔
222
        main_states_.AddTransition(ss.rollback_reboot_error_,               se::Failure,                     ss.failure_enter_,                       tf::Immediate);
223

224
        // No Failure transition for this state see comments in handler.
225
        main_states_.AddTransition(update_rollback_reboot_state_,           se::Success,                     update_verify_rollback_reboot_state_,    tf::Immediate);
91✔
226
        main_states_.AddTransition(update_rollback_reboot_state_,           se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
227

228
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::Success,                     ss.rollback_reboot_leave_,               tf::Immediate);
91✔
229
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::Retry,                       update_rollback_reboot_state_,           tf::Immediate);
230
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
231

232
        main_states_.AddTransition(ss.rollback_reboot_leave_,               se::Success,                     update_rollback_successful_state_,       tf::Immediate);
233
        main_states_.AddTransition(ss.rollback_reboot_leave_,               se::Failure,                     ss.rollback_reboot_error_,               tf::Immediate);
234

235
        main_states_.AddTransition(update_rollback_successful_state_,       se::Success,                     ss.failure_enter_,                       tf::Immediate);
236

237
        main_states_.AddTransition(update_failure_state_,                   se::Success,                     ss.failure_leave_update_save_provides_,  tf::Immediate);
91✔
238
        main_states_.AddTransition(update_failure_state_,                   se::Failure,                     ss.failure_leave_update_save_provides_,  tf::Immediate);
239
  main_states_.AddTransition(update_failure_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
240

241
        main_states_.AddTransition(ss.failure_leave_update_save_provides_,  se::Success,                     update_save_provides_state_,             tf::Immediate);
242
        main_states_.AddTransition(ss.failure_leave_update_save_provides_,  se::Failure,                     update_save_provides_state_,             tf::Immediate);
243

244
        // Even if this fails there is nothing we can do at this point.
245
        main_states_.AddTransition(update_save_provides_state_,             se::Success,                     update_cleanup_state_,                   tf::Immediate);
91✔
246
        main_states_.AddTransition(update_save_provides_state_,             se::Failure,                     update_cleanup_state_,                   tf::Immediate);
247
        main_states_.AddTransition(update_save_provides_state_,             se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
248

249
        main_states_.AddTransition(update_rollback_not_needed_state_,       se::Success,                     update_cleanup_state_,                   tf::Immediate);
250

251
        main_states_.AddTransition(update_cleanup_state_,                   se::Success,                     send_final_status_state_,                tf::Immediate);
91✔
252
        main_states_.AddTransition(update_cleanup_state_,                   se::Failure,                     send_final_status_state_,                tf::Immediate);
253
        main_states_.AddTransition(update_cleanup_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
254

255
        main_states_.AddTransition(state_loop_state_,                       se::Success,                     send_final_status_state_,                tf::Immediate);
256
        main_states_.AddTransition(state_loop_state_,                       se::Failure,                     send_final_status_state_,                tf::Immediate);
257

258
        main_states_.AddTransition(send_final_status_state_,                se::Success,                     clear_artifact_data_state_,              tf::Immediate);
91✔
259
        main_states_.AddTransition(send_final_status_state_,                se::Failure,                     clear_artifact_data_state_,              tf::Immediate);
260

261
        main_states_.AddTransition(clear_artifact_data_state_,              se::Success,                     end_of_deployment_state_,                tf::Immediate);
91✔
262
        main_states_.AddTransition(clear_artifact_data_state_,              se::Failure,                     end_of_deployment_state_,                tf::Immediate);
263

264
        main_states_.AddTransition(end_of_deployment_state_,                se::Success,                     submit_inventory_state_,                 tf::Immediate);
265

266
        auto &dt = deployment_tracking_;
267

268
        dt.states_.AddTransition(dt.idle_state_,                            se::DeploymentStarted,           dt.no_failures_state_,                   tf::Immediate);
91✔
269

270
        dt.states_.AddTransition(dt.no_failures_state_,                     se::Failure,                     dt.failure_state_,                       tf::Immediate);
91✔
271
        dt.states_.AddTransition(dt.no_failures_state_,                     se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
272

273
        dt.states_.AddTransition(dt.failure_state_,                         se::RollbackStarted,             dt.rollback_attempted_state_,            tf::Immediate);
91✔
274
        dt.states_.AddTransition(dt.failure_state_,                         se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
275

276
        dt.states_.AddTransition(dt.rollback_attempted_state_,              se::Failure,                     dt.rollback_failed_state_,               tf::Immediate);
91✔
277
        dt.states_.AddTransition(dt.rollback_attempted_state_,              se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
278

279
        dt.states_.AddTransition(dt.rollback_failed_state_,                 se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
280
        // clang-format on
281
}
91✔
282

283
StateMachine::StateMachine(
87✔
284
        Context &ctx, events::EventLoop &event_loop, chrono::milliseconds minimum_wait_time) :
87✔
285
        StateMachine(ctx, event_loop) {
87✔
286
        send_commit_status_state_.SetSmallestWaitInterval(minimum_wait_time);
87✔
287
        send_final_status_state_.SetSmallestWaitInterval(minimum_wait_time);
87✔
288
}
87✔
289

290
StateMachine::DeploymentTracking::DeploymentTracking() :
91✔
291
        states_(idle_state_) {
91✔
292
}
×
293

294
void StateMachine::LoadStateFromDb() {
87✔
295
        unique_ptr<StateData> state_data(new StateData);
119✔
296
        auto exp_loaded = ctx_.LoadDeploymentStateData(*state_data);
87✔
297
        if (!exp_loaded) {
87✔
298
                if (exp_loaded.error().code
2✔
299
                        == context::MakeError(context::StateDataStoreCountExceededError, "").code) {
4✔
300
                        log::Error("State loop detected. Forcefully aborting update.");
2✔
301

302
                        // This particular error code also fills in state_data.
303
                        ctx_.deployment.state_data = std::move(state_data);
1✔
304

305
                        ctx_.BeginDeploymentLogging();
1✔
306

307
                        main_states_.SetState(state_loop_state_);
1✔
308
                        deployment_tracking_.states_.SetState(deployment_tracking_.rollback_failed_state_);
1✔
309
                } else {
310
                        log::Error(
1✔
311
                                "Unable to load deployment data from database: " + exp_loaded.error().String());
2✔
312
                        log::Error("Starting from initial state");
2✔
313
                }
314
                return;
2✔
315
        }
316

317
        if (!exp_loaded.value()) {
85✔
318
                log::Debug("No existing deployment data, starting from initial state");
104✔
319
                return;
52✔
320
        }
321

322
        // We have state data, move it to the context.
323
        ctx_.deployment.state_data = std::move(state_data);
33✔
324

325
        ctx_.BeginDeploymentLogging();
33✔
326

327
        auto &state = ctx_.deployment.state_data->state;
33✔
328

329
        if (state == ctx_.kUpdateStateDownload) {
33✔
330
                main_states_.SetState(update_cleanup_state_);
3✔
331
                // "rollback_attempted_state" because Download in its nature makes no system
332
                // changes, so a rollback is a no-op.
333
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
334

335
        } else if (state == ctx_.kUpdateStateArtifactReboot) {
30✔
336
                // Normal update path with a reboot.
337
                main_states_.SetState(update_verify_reboot_state_);
3✔
338
                deployment_tracking_.states_.SetState(deployment_tracking_.no_failures_state_);
3✔
339

340
        } else if (state == ctx_.kUpdateStateArtifactRollback) {
27✔
341
                // Installation failed, but rollback could still succeed.
342
                main_states_.SetState(state_scripts_.rollback_enter_);
3✔
343
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
344

345
        } else if (
346
                state == ctx_.kUpdateStateArtifactRollbackReboot
24✔
347
                || state == ctx_.kUpdateStateArtifactVerifyRollbackReboot
22✔
348
                || state == ctx_.kUpdateStateVerifyRollbackReboot) {
44✔
349
                // Normal flow for a rebooting rollback.
350
                main_states_.SetState(update_verify_rollback_reboot_state_);
4✔
351
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
4✔
352

353
        } else if (
354
                state == ctx_.kUpdateStateAfterArtifactCommit
20✔
355
                || state == ctx_.kUpdateStateUpdateAfterFirstCommit) {
20✔
356
                // Re-run commit Leave scripts if spontaneously rebooted after commit.
357
                main_states_.SetState(update_after_commit_state_);
2✔
358
                deployment_tracking_.states_.SetState(deployment_tracking_.no_failures_state_);
2✔
359

360
        } else if (state == ctx_.kUpdateStateArtifactFailure) {
18✔
361
                // Re-run ArtifactFailure if spontaneously rebooted before finishing.
362
                main_states_.SetState(state_scripts_.failure_enter_);
4✔
363
                if (ctx_.deployment.state_data->update_info.all_rollbacks_successful) {
4✔
364
                        deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
365
                } else {
366
                        deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
1✔
367
                }
368

369
        } else if (state == ctx_.kUpdateStateCleanup) {
14✔
370
                // Re-run Cleanup if spontaneously rebooted before finishing.
371
                main_states_.SetState(update_cleanup_state_);
2✔
372
                if (ctx_.deployment.state_data->update_info.all_rollbacks_successful) {
2✔
373
                        deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
1✔
374
                } else {
375
                        deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
1✔
376
                }
377

378
        } else {
379
                // All other states trigger a rollback.
380
                main_states_.SetState(update_check_rollback_state_);
12✔
381
                deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
12✔
382
        }
383

384
        auto &payload_types = ctx_.deployment.state_data->update_info.artifact.payload_types;
385
        if (payload_types.size() == 0) {
33✔
386
                ctx_.deployment.update_module.reset();
387
                return;
1✔
388
        }
389
        assert(payload_types.size() == 1);
390
        ctx_.deployment.update_module.reset(
391
                new update_module::UpdateModule(ctx_.mender_context, payload_types[0]));
32✔
392
}
393

394
error::Error StateMachine::Run() {
91✔
395
        // Client is supposed to do one handling of each on startup.
396
        runner_.PostEvent(StateEvent::InventoryPollingTriggered);
91✔
397
        runner_.PostEvent(StateEvent::DeploymentPollingTriggered);
91✔
398

399
        auto err = RegisterSignalHandlers();
91✔
400
        if (err != error::NoError) {
91✔
401
                return err;
402
        }
403

404
        log::Info("Running Mender client " + conf::kMenderVersion);
91✔
405

406
        event_loop_.Run();
91✔
407
        return exit_state_.exit_error;
408
}
409

410
void StateMachine::StopAfterDeployment() {
89✔
411
        main_states_.AddTransition(
89✔
412
                end_of_deployment_state_,
413
                StateEvent::DeploymentEnded,
414
                exit_state_,
415
                sm::TransitionFlag::Immediate);
416
}
89✔
417

418
} // namespace daemon
419
} // namespace update
420
} // namespace mender
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc