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

mendersoftware / mender / 1025244782

04 Oct 2023 09:45AM UTC coverage: 80.154% (-0.01%) from 80.164%
1025244782

push

gitlab-ci

kacf
chore: Take Update Control into account when upgrading.

Since we don't support it, fail instead. And when there is no
deployment in progress, remove the key, since we don't want it to
linger in the database, or it might screw up a deployment later.

Ticket: MEN-6647
Changelog: Update Control support has been removed from the client.

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

19 of 19 new or added lines in 1 file covered. (100.0%)

6462 of 8062 relevant lines covered (80.15%)

10753.37 hits per line

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

97.94
/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 <mender-update/daemon/state_machine.hpp>
16

17
#include <common/conf.hpp>
18
#include <common/key_value_database.hpp>
19
#include <common/log.hpp>
20

21
#include <mender-update/daemon/states.hpp>
22

23
namespace mender {
24
namespace update {
25
namespace daemon {
26

27
namespace conf = mender::common::conf;
28
namespace kvdb = mender::common::key_value_database;
29
namespace log = mender::common::log;
30

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

64
        runner_.AttachToEventLoop(event_loop_);
94✔
65

66
        using se = StateEvent;
67
        using tf = sm::TransitionFlag;
68

69
        auto &ss = state_scripts_;
70

71
        // When updating the table below, make sure that the initial states are in sync as well, in
72
        // LoadStateFromDb().
73

74
        // clang-format off
75
        main_states_.AddTransition(init_state_,                             se::Started,                     ss.idle_enter_,                          tf::Immediate);
94✔
76

77
        main_states_.AddTransition(ss.idle_enter_,                          se::Success,                     idle_state_,                             tf::Immediate);
94✔
78
        main_states_.AddTransition(ss.idle_enter_,                          se::Failure,                     idle_state_,                             tf::Immediate);
94✔
79

80
        main_states_.AddTransition(idle_state_,                             se::DeploymentPollingTriggered,  ss.idle_leave_deploy_,                   tf::Deferred);
94✔
81
        main_states_.AddTransition(idle_state_,                             se::InventoryPollingTriggered,   ss.idle_leave_inv_,                      tf::Deferred);
94✔
82

83
        main_states_.AddTransition(ss.idle_leave_deploy_,                   se::Success,                     ss.sync_enter_deployment_,               tf::Immediate);
94✔
84
        main_states_.AddTransition(ss.idle_leave_deploy_,                   se::Failure,                     ss.sync_enter_deployment_,               tf::Immediate);
94✔
85

86
        main_states_.AddTransition(ss.sync_enter_deployment_,               se::Success,                     poll_for_deployment_state_,              tf::Immediate);
94✔
87
        main_states_.AddTransition(ss.sync_enter_deployment_,               se::Failure,                     ss.sync_error_,                          tf::Immediate);
94✔
88

89
        main_states_.AddTransition(ss.sync_error_,                          se::Success,                     ss.idle_enter_,                          tf::Immediate);
94✔
90
        main_states_.AddTransition(ss.sync_error_,                          se::Failure,                     ss.idle_enter_,                          tf::Immediate);
94✔
91

92
        main_states_.AddTransition(ss.idle_leave_inv_,                      se::Success,                     ss.sync_enter_inventory_,                tf::Immediate);
94✔
93
        main_states_.AddTransition(ss.idle_leave_inv_,                      se::Failure,                     ss.sync_enter_inventory_,                tf::Immediate);
94✔
94

95
        main_states_.AddTransition(ss.sync_enter_inventory_,                se::Success,                     submit_inventory_state_,                 tf::Immediate);
94✔
96
        main_states_.AddTransition(ss.sync_enter_inventory_,                se::Failure,                     ss.sync_error_,                          tf::Immediate);
94✔
97

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

101
        main_states_.AddTransition(poll_for_deployment_state_,              se::Success,                     ss.sync_leave_download_,                 tf::Immediate);
94✔
102
        main_states_.AddTransition(poll_for_deployment_state_,              se::NothingToDo,                 ss.sync_leave_,                          tf::Immediate);
94✔
103
        main_states_.AddTransition(poll_for_deployment_state_,              se::Failure,                     ss.sync_error_,                          tf::Immediate);
94✔
104

105
        main_states_.AddTransition(ss.sync_leave_,                          se::Success,                     ss.idle_enter_,                          tf::Immediate);
94✔
106
        main_states_.AddTransition(ss.sync_leave_,                          se::Failure,                     ss.sync_error_,                          tf::Immediate);
94✔
107

108
        main_states_.AddTransition(ss.sync_leave_download_,                 se::Success,                     send_download_status_state_,             tf::Immediate);
94✔
109
        main_states_.AddTransition(ss.sync_leave_download_,                 se::Failure,                     ss.sync_error_,                          tf::Immediate);
94✔
110

111
        // Cannot fail due to FailureMode::Ignore.
112
        main_states_.AddTransition(send_download_status_state_,             se::Success,                     ss.download_enter_,                      tf::Immediate);
94✔
113

114
        main_states_.AddTransition(ss.download_enter_,                      se::Success,                     update_download_state_,                  tf::Immediate);
94✔
115
        main_states_.AddTransition(ss.download_enter_,                      se::Failure,                     ss.download_error_,                      tf::Immediate);
94✔
116
        main_states_.AddTransition(ss.download_enter_,                      se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
117
        main_states_.AddTransition(ss.download_error_,                      se::Success,                     update_rollback_not_needed_state_,       tf::Immediate);
94✔
118
        main_states_.AddTransition(ss.download_error_,                      se::Failure,                     update_rollback_not_needed_state_,       tf::Immediate);
94✔
119

120
        main_states_.AddTransition(update_download_state_,                  se::Success,                     ss.download_leave_,                      tf::Immediate);
94✔
121
        main_states_.AddTransition(update_download_state_,                  se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
122
        main_states_.AddTransition(update_download_state_,                  se::Failure,                     ss.download_error_,                      tf::Immediate);
94✔
123
        main_states_.AddTransition(update_download_state_,                  se::NothingToDo,                 ss.download_leave_save_provides,         tf::Immediate);
94✔
124

125
        main_states_.AddTransition(ss.download_leave_,                      se::Success,                     send_install_status_state_,              tf::Immediate);
94✔
126
        main_states_.AddTransition(ss.download_leave_,                      se::Failure,                     ss.download_error_,                      tf::Immediate);
94✔
127

128
        main_states_.AddTransition(ss.download_leave_save_provides,         se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
129
        main_states_.AddTransition(ss.download_leave_save_provides,         se::Failure,                     ss.download_error_,                      tf::Immediate);
94✔
130

131
        main_states_.AddTransition(ss.install_enter_,                       se::Success,                     update_install_state_,                   tf::Immediate);
94✔
132
        main_states_.AddTransition(ss.install_enter_,                       se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
94✔
133

134
        // Cannot fail due to FailureMode::Ignore.
135
        main_states_.AddTransition(send_install_status_state_,              se::Success,                     ss.install_enter_,                       tf::Immediate);
94✔
136

137
        main_states_.AddTransition(update_install_state_,                   se::Success,                     ss.install_leave_,                       tf::Immediate);
94✔
138
        main_states_.AddTransition(update_install_state_,                   se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
94✔
139
        main_states_.AddTransition(update_install_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
140

141
        main_states_.AddTransition(ss.install_leave_,                       se::Success,                     update_check_reboot_state_,              tf::Immediate);
94✔
142
        main_states_.AddTransition(ss.install_leave_,                       se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
94✔
143
        main_states_.AddTransition(ss.install_error_rollback_,              se::Success,                     update_check_rollback_state_,            tf::Immediate);
94✔
144
        main_states_.AddTransition(ss.install_error_rollback_,              se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
145

146
        main_states_.AddTransition(ss.failure_enter_,                       se::Success,                     update_failure_state_,                   tf::Immediate);
94✔
147
        main_states_.AddTransition(ss.failure_enter_,                       se::Failure,                     update_failure_state_,                   tf::Immediate);
94✔
148
        main_states_.AddTransition(ss.failure_enter_,                       se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
149

150

151
        main_states_.AddTransition(update_check_reboot_state_,              se::Success,                     send_reboot_status_state_,               tf::Immediate);
94✔
152
        main_states_.AddTransition(update_check_reboot_state_,              se::NothingToDo,                 update_before_commit_state_,             tf::Immediate);
94✔
153
        main_states_.AddTransition(update_check_reboot_state_,              se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
154
        main_states_.AddTransition(update_check_reboot_state_,              se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
155

156
        // Cannot fail due to FailureMode::Ignore.
157
        main_states_.AddTransition(send_reboot_status_state_,               se::Success,                     ss.reboot_enter_,                        tf::Immediate);
94✔
158

159
        main_states_.AddTransition(ss.reboot_enter_,                        se::Success,                     update_reboot_state_,                    tf::Immediate);
94✔
160
        main_states_.AddTransition(ss.reboot_enter_,                        se::Failure,                     ss.reboot_error_,                        tf::Immediate);
94✔
161

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

166
        main_states_.AddTransition(ss.reboot_error_,                        se::Success,                     update_check_rollback_state_,            tf::Immediate);
94✔
167
        main_states_.AddTransition(ss.reboot_error_,                        se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
168

169
        main_states_.AddTransition(update_verify_reboot_state_,             se::Success,                     ss.reboot_leave_,                        tf::Immediate);
94✔
170
        main_states_.AddTransition(update_verify_reboot_state_,             se::Failure,                     ss.reboot_error_,                        tf::Immediate);
94✔
171
        main_states_.AddTransition(update_verify_reboot_state_,             se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
172

173
        main_states_.AddTransition(ss.reboot_leave_,                        se::Success,                     update_before_commit_state_,             tf::Immediate);
94✔
174
        main_states_.AddTransition(ss.reboot_leave_,                        se::Failure,                     ss.reboot_error_,                        tf::Immediate);
94✔
175

176
        // Cannot fail.
177
        main_states_.AddTransition(update_before_commit_state_,             se::Success,                     send_commit_status_state_,               tf::Immediate);
94✔
178

179
        main_states_.AddTransition(send_commit_status_state_,               se::Success,                     ss.commit_enter_,                        tf::Immediate);
94✔
180
        main_states_.AddTransition(send_commit_status_state_,               se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
181

182
        main_states_.AddTransition(ss.commit_enter_,                        se::Success,                     update_commit_state_,                    tf::Immediate);
94✔
183
        main_states_.AddTransition(ss.commit_enter_,                        se::Failure,                     ss.commit_error_,                        tf::Immediate);
94✔
184

185
        main_states_.AddTransition(ss.commit_error_,                        se::Success,                     update_check_rollback_state_,            tf::Immediate);
94✔
186
        main_states_.AddTransition(ss.commit_error_,                        se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
187

188
        main_states_.AddTransition(update_commit_state_,                    se::Success,                     update_after_commit_state_,              tf::Immediate);
94✔
189
        main_states_.AddTransition(update_commit_state_,                    se::Failure,                     ss.commit_error_,                        tf::Immediate);
94✔
190
        main_states_.AddTransition(update_commit_state_,                    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
191

192
        main_states_.AddTransition(update_after_commit_state_,              se::Success,                     ss.commit_leave_,                        tf::Immediate);
94✔
193
        main_states_.AddTransition(update_after_commit_state_,              se::Failure,                     ss.commit_error_save_provides_,          tf::Immediate);
94✔
194
        main_states_.AddTransition(update_after_commit_state_,              se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
195

196
        main_states_.AddTransition(ss.commit_leave_,                        se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
197
        main_states_.AddTransition(ss.commit_leave_,                        se::Failure,                     ss.commit_error_save_provides_,          tf::Immediate);
94✔
198

199
        main_states_.AddTransition(ss.commit_error_save_provides_,          se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
200
        main_states_.AddTransition(ss.commit_error_save_provides_,          se::Failure,                     update_save_provides_state_,             tf::Immediate);
94✔
201

202
        main_states_.AddTransition(update_check_rollback_state_,            se::Success,                     ss.rollback_enter_,                      tf::Immediate);
94✔
203
        main_states_.AddTransition(update_check_rollback_state_,            se::NothingToDo,                 ss.failure_enter_,                       tf::Immediate);
94✔
204
        main_states_.AddTransition(update_check_rollback_state_,            se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
205
        main_states_.AddTransition(update_check_rollback_state_,            se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
206

207
        main_states_.AddTransition(ss.rollback_enter_,                      se::Success,                     update_rollback_state_,                  tf::Immediate);
94✔
208
        main_states_.AddTransition(ss.rollback_enter_,                      se::Failure,                     update_rollback_state_,                  tf::Immediate);
94✔
209

210
        main_states_.AddTransition(update_rollback_state_,                  se::Success,                     ss.rollback_leave_,                      tf::Immediate);
94✔
211
        main_states_.AddTransition(update_rollback_state_,                  se::Failure,                     ss.rollback_leave_error_,                tf::Immediate);
94✔
212
        main_states_.AddTransition(update_rollback_state_,                  se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
213

214
        main_states_.AddTransition(ss.rollback_leave_,                      se::Success,                     update_check_rollback_reboot_state_,     tf::Immediate);
94✔
215
        main_states_.AddTransition(ss.rollback_leave_,                      se::Failure,                     update_check_rollback_reboot_state_,     tf::Immediate);
94✔
216

217
        main_states_.AddTransition(ss.rollback_leave_error_,                se::Success,                     ss.failure_enter_,                       tf::Immediate);
94✔
218
        main_states_.AddTransition(ss.rollback_leave_error_,                se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
219

220
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::Success,                     ss.rollback_reboot_enter_,               tf::Immediate);
94✔
221
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::NothingToDo,                 update_rollback_successful_state_,       tf::Immediate);
94✔
222
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
223
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
224

225
        main_states_.AddTransition(ss.rollback_reboot_enter_,               se::Success,                     update_rollback_reboot_state_,           tf::Immediate);
94✔
226
        main_states_.AddTransition(ss.rollback_reboot_enter_,               se::Failure,                     update_rollback_reboot_state_,           tf::Immediate);
94✔
227

228
        main_states_.AddTransition(ss.rollback_reboot_error_,               se::Success,                     ss.failure_enter_,                       tf::Immediate);
94✔
229
        main_states_.AddTransition(ss.rollback_reboot_error_,               se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
230

231
        // No Failure transition for this state see comments in handler.
232
        main_states_.AddTransition(update_rollback_reboot_state_,           se::Success,                     update_verify_rollback_reboot_state_,    tf::Immediate);
94✔
233
        main_states_.AddTransition(update_rollback_reboot_state_,           se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
234

235
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::Success,                     ss.rollback_reboot_leave_,               tf::Immediate);
94✔
236
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::Retry,                       update_rollback_reboot_state_,           tf::Immediate);
94✔
237
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
238

239
        main_states_.AddTransition(ss.rollback_reboot_leave_,               se::Success,                     update_rollback_successful_state_,       tf::Immediate);
94✔
240
        main_states_.AddTransition(ss.rollback_reboot_leave_,               se::Failure,                     ss.rollback_reboot_error_,               tf::Immediate);
94✔
241

242
        main_states_.AddTransition(update_rollback_successful_state_,       se::Success,                     ss.failure_enter_,                       tf::Immediate);
94✔
243

244
        main_states_.AddTransition(update_failure_state_,                   se::Success,                     ss.failure_leave_update_save_provides_,  tf::Immediate);
94✔
245
        main_states_.AddTransition(update_failure_state_,                   se::Failure,                     ss.failure_leave_update_save_provides_,  tf::Immediate);
94✔
246
  main_states_.AddTransition(update_failure_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
247

248
        main_states_.AddTransition(ss.failure_leave_update_save_provides_,  se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
249
        main_states_.AddTransition(ss.failure_leave_update_save_provides_,  se::Failure,                     update_save_provides_state_,             tf::Immediate);
94✔
250

251
        // Even if this fails there is nothing we can do at this point.
252
        main_states_.AddTransition(update_save_provides_state_,             se::Success,                     update_cleanup_state_,                   tf::Immediate);
94✔
253
        main_states_.AddTransition(update_save_provides_state_,             se::Failure,                     update_cleanup_state_,                   tf::Immediate);
94✔
254
        main_states_.AddTransition(update_save_provides_state_,             se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
255

256
        main_states_.AddTransition(update_rollback_not_needed_state_,       se::Success,                     update_cleanup_state_,                   tf::Immediate);
94✔
257

258
        main_states_.AddTransition(update_cleanup_state_,                   se::Success,                     send_final_status_state_,                tf::Immediate);
94✔
259
        main_states_.AddTransition(update_cleanup_state_,                   se::Failure,                     send_final_status_state_,                tf::Immediate);
94✔
260
        main_states_.AddTransition(update_cleanup_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
261

262
        main_states_.AddTransition(state_loop_state_,                       se::Success,                     send_final_status_state_,                tf::Immediate);
94✔
263
        main_states_.AddTransition(state_loop_state_,                       se::Failure,                     send_final_status_state_,                tf::Immediate);
94✔
264

265
        main_states_.AddTransition(send_final_status_state_,                se::Success,                     clear_artifact_data_state_,              tf::Immediate);
94✔
266
        main_states_.AddTransition(send_final_status_state_,                se::Failure,                     clear_artifact_data_state_,              tf::Immediate);
94✔
267

268
        main_states_.AddTransition(clear_artifact_data_state_,              se::Success,                     end_of_deployment_state_,                tf::Immediate);
94✔
269
        main_states_.AddTransition(clear_artifact_data_state_,              se::Failure,                     end_of_deployment_state_,                tf::Immediate);
94✔
270

271
        main_states_.AddTransition(end_of_deployment_state_,                se::Success,                     submit_inventory_state_,                 tf::Immediate);
94✔
272

273
        auto &dt = deployment_tracking_;
274

275
        dt.states_.AddTransition(dt.idle_state_,                            se::DeploymentStarted,           dt.no_failures_state_,                   tf::Immediate);
94✔
276

277
        dt.states_.AddTransition(dt.no_failures_state_,                     se::Failure,                     dt.failure_state_,                       tf::Immediate);
94✔
278
        dt.states_.AddTransition(dt.no_failures_state_,                     se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
279

280
        dt.states_.AddTransition(dt.failure_state_,                         se::RollbackStarted,             dt.rollback_attempted_state_,            tf::Immediate);
94✔
281
        dt.states_.AddTransition(dt.failure_state_,                         se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
282

283
        dt.states_.AddTransition(dt.rollback_attempted_state_,              se::Failure,                     dt.rollback_failed_state_,               tf::Immediate);
94✔
284
        dt.states_.AddTransition(dt.rollback_attempted_state_,              se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
285

286
        dt.states_.AddTransition(dt.rollback_failed_state_,                 se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
287
        // clang-format on
288
}
94✔
289

290
StateMachine::StateMachine(
89✔
291
        Context &ctx, events::EventLoop &event_loop, chrono::milliseconds minimum_wait_time) :
89✔
292
        StateMachine(ctx, event_loop) {
89✔
293
        send_commit_status_state_.SetSmallestWaitInterval(minimum_wait_time);
89✔
294
        send_final_status_state_.SetSmallestWaitInterval(minimum_wait_time);
89✔
295
}
89✔
296

297
StateMachine::DeploymentTracking::DeploymentTracking() :
94✔
298
        states_(idle_state_) {
94✔
299
}
94✔
300

301
void StateMachine::LoadStateFromDb() {
90✔
302
        unique_ptr<StateData> state_data(new StateData);
124✔
303
        auto exp_loaded = ctx_.LoadDeploymentStateData(*state_data);
90✔
304
        if (!exp_loaded) {
90✔
305
                if (exp_loaded.error().code
2✔
306
                        == context::MakeError(context::StateDataStoreCountExceededError, "").code) {
2✔
307
                        log::Error("State loop detected. Forcefully aborting update.");
2✔
308

309
                        // This particular error code also fills in state_data.
310
                        ctx_.deployment.state_data = std::move(state_data);
1✔
311

312
                        ctx_.BeginDeploymentLogging();
1✔
313

314
                        main_states_.SetState(state_loop_state_);
1✔
315
                        deployment_tracking_.states_.SetState(deployment_tracking_.rollback_failed_state_);
1✔
316
                } else {
317
                        log::Error(
1✔
318
                                "Unable to load deployment data from database: " + exp_loaded.error().String());
2✔
319
                        log::Error("Starting from initial state");
2✔
320
                }
321
                return;
2✔
322
        }
323

324
        auto &store = ctx_.mender_context.GetMenderStoreDB();
88✔
325

326
        if (!exp_loaded.value()) {
88✔
327
                log::Debug("No existing deployment data, starting from initial state");
106✔
328

329
                auto err = store.Remove(ctx_.mender_context.update_control_maps);
53✔
330
                if (err != error::NoError) {
53✔
331
                        log::Error(
×
332
                                "Error removing " + ctx_.mender_context.update_control_maps
×
333
                                + " key from database: " + err.String());
×
334
                        // Nothing we can do about it.
335
                }
336

337
                return;
338
        }
339

340
        // We have state data, move it to the context.
341
        ctx_.deployment.state_data = std::move(state_data);
35✔
342

343
        ctx_.BeginDeploymentLogging();
35✔
344

345
        bool update_control_enabled = false;
346
        auto exp_update_control_data = store.Read(ctx_.mender_context.update_control_maps);
35✔
347
        if (exp_update_control_data) {
35✔
348
                auto update_control_data = common::StringFromByteVector(exp_update_control_data.value());
2✔
349
                if (update_control_data != "" && update_control_data != "{}") {
2✔
350
                        update_control_enabled = true;
351
                }
352
        } else if (exp_update_control_data.error().code != kvdb::MakeError(kvdb::KeyError, "").code) {
33✔
353
                log::Error("Error while loading update control data from database");
×
354
                // Since we don't actually need it, continue anyway.
355
        }
356

357
        auto &state = ctx_.deployment.state_data->state;
35✔
358

359
        if (state == ctx_.kUpdateStateDownload) {
35✔
360
                main_states_.SetState(update_cleanup_state_);
3✔
361
                // "rollback_attempted_state" because Download in its nature makes no system
362
                // changes, so a rollback is a no-op.
363
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
364

365
        } else if (state == ctx_.kUpdateStateArtifactReboot) {
32✔
366
                // Normal update path with a reboot.
367
                if (update_control_enabled) {
5✔
368
                        log::Error(
1✔
369
                                "This deployment was done using Update Control, but this client does not support Update Control. Failing / rolling back deployment.");
2✔
370
                        main_states_.SetState(state_scripts_.reboot_error_);
1✔
371
                        deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
1✔
372
                } else {
373
                        main_states_.SetState(update_verify_reboot_state_);
4✔
374
                        deployment_tracking_.states_.SetState(deployment_tracking_.no_failures_state_);
4✔
375
                }
376

377
        } else if (state == ctx_.kUpdateStateArtifactRollback) {
27✔
378
                // Installation failed, but rollback could still succeed.
379
                main_states_.SetState(state_scripts_.rollback_enter_);
3✔
380
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
381

382
        } else if (
383
                state == ctx_.kUpdateStateArtifactRollbackReboot
24✔
384
                || state == ctx_.kUpdateStateArtifactVerifyRollbackReboot
22✔
385
                || state == ctx_.kUpdateStateVerifyRollbackReboot) {
44✔
386
                // Normal flow for a rebooting rollback.
387
                main_states_.SetState(update_verify_rollback_reboot_state_);
4✔
388
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
4✔
389

390
        } else if (
391
                state == ctx_.kUpdateStateAfterArtifactCommit
20✔
392
                || state == ctx_.kUpdateStateUpdateAfterFirstCommit) {
20✔
393
                // Re-run commit Leave scripts if spontaneously rebooted after commit.
394
                main_states_.SetState(update_after_commit_state_);
2✔
395
                deployment_tracking_.states_.SetState(deployment_tracking_.no_failures_state_);
2✔
396

397
        } else if (state == ctx_.kUpdateStateArtifactFailure) {
18✔
398
                // Re-run ArtifactFailure if spontaneously rebooted before finishing.
399
                main_states_.SetState(state_scripts_.failure_enter_);
4✔
400
                if (ctx_.deployment.state_data->update_info.all_rollbacks_successful) {
4✔
401
                        deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
402
                } else {
403
                        deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
1✔
404
                }
405

406
        } else if (state == ctx_.kUpdateStateCleanup) {
14✔
407
                // Re-run Cleanup if spontaneously rebooted before finishing.
408
                main_states_.SetState(update_cleanup_state_);
2✔
409
                if (ctx_.deployment.state_data->update_info.all_rollbacks_successful) {
2✔
410
                        deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
1✔
411
                } else {
412
                        deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
1✔
413
                }
414

415
        } else {
416
                // All other states trigger a rollback.
417
                main_states_.SetState(update_check_rollback_state_);
12✔
418
                deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
12✔
419
        }
420

421
        auto &payload_types = ctx_.deployment.state_data->update_info.artifact.payload_types;
35✔
422
        if (payload_types.size() == 0) {
35✔
423
                ctx_.deployment.update_module.reset();
424
                return;
425
        }
426
        assert(payload_types.size() == 1);
427
        ctx_.deployment.update_module.reset(
428
                new update_module::UpdateModule(ctx_.mender_context, payload_types[0]));
34✔
429
}
430

431
error::Error StateMachine::Run() {
93✔
432
        // Client is supposed to do one handling of each on startup.
433
        runner_.PostEvent(StateEvent::InventoryPollingTriggered);
93✔
434
        runner_.PostEvent(StateEvent::DeploymentPollingTriggered);
93✔
435

436
        auto err = RegisterSignalHandlers();
93✔
437
        if (err != error::NoError) {
93✔
438
                return err;
×
439
        }
440

441
        log::Info("Running Mender client " + conf::kMenderVersion);
93✔
442

443
        event_loop_.Run();
93✔
444
        return exit_state_.exit_error;
93✔
445
}
446

447
void StateMachine::StopAfterDeployment() {
91✔
448
        main_states_.AddTransition(
91✔
449
                end_of_deployment_state_,
450
                StateEvent::DeploymentEnded,
451
                exit_state_,
452
                sm::TransitionFlag::Immediate);
453
}
91✔
454

455
} // namespace daemon
456
} // namespace update
457
} // 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