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

mendersoftware / mender / 1480778148

03 Oct 2024 06:26PM UTC coverage: 76.372% (+0.06%) from 76.31%
1480778148

push

gitlab-ci

danielskinstad
fix: explicitly initialize ssl

From the OpenSSL man pages:
Numerous internal OpenSSL functions call OPENSSL_init_ssl().
Therefore, in order to perform nondefault initialisation,
OPENSSL_init_ssl() MUST be called by application code prior to any other OpenSSL function calls.
See: https://docs.openssl.org/3.3/man3/OPENSSL_init_ssl/#description

This fixes errors where e.g. the openssl config configures ssl_conf,
which requires ssl to be initialized.

Ticket: MEN-7549
Changelog: Fix error while loading OpenSSL config file, by explicitly
initializing the SSL context prior to loading. Without the explicit
initialisation of SSL, the config might not be properly loaded if e.g.
it has sections specifying ssl settings. This was the case with the
example configuration for OpenSSL 1.1.1w from Debian Bullseye.

Signed-off-by: Daniel Skinstad Drabitzius <daniel.drabitzius@northern.tech>

1 of 2 new or added lines in 1 file covered. (50.0%)

97 existing lines in 3 files now uncovered.

7350 of 9624 relevant lines covered (76.37%)

11242.72 hits per line

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

97.96
/src/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 <client_shared/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::client_shared::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},
58
                chrono::seconds {ctx.mender_context.GetConfig().state_script_retry_interval_seconds},
59
                chrono::seconds {ctx.mender_context.GetConfig().state_script_retry_timeout_seconds},
94✔
60
                ctx_.mender_context.GetConfig().paths.GetArtScriptsPath(),
188✔
61
                ctx_.mender_context.GetConfig().paths.GetRootfsScriptsPath()),
188✔
62
        runner_(ctx) {
282✔
63
        runner_.AddStateMachine(deployment_tracking_.states_);
94✔
64
        runner_.AddStateMachine(main_states_);
94✔
65

66
        runner_.AttachToEventLoop(event_loop_);
94✔
67

68
        using se = StateEvent;
69
        using tf = sm::TransitionFlag;
70

71
        auto &ss = state_scripts_;
72

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

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

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

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

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

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

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

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

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

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

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

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

110
        main_states_.AddTransition(ss.sync_leave_download_,                 se::Success,                     send_download_status_state_,             tf::Immediate);
94✔
111
        main_states_.AddTransition(ss.sync_leave_download_,                 se::Failure,                     ss.sync_error_download_,                 tf::Immediate);
94✔
112

113
        main_states_.AddTransition(ss.sync_error_download_,                 se::Success,                     end_of_deployment_state_,                tf::Immediate);
94✔
114
        main_states_.AddTransition(ss.sync_error_download_,                 se::Failure,                     end_of_deployment_state_,                tf::Immediate);
94✔
115

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

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

125
        main_states_.AddTransition(update_download_state_,                  se::Success,                     ss.download_leave_,                      tf::Immediate);
94✔
126
        main_states_.AddTransition(update_download_state_,                  se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
127
        main_states_.AddTransition(update_download_state_,                  se::Failure,                     ss.download_error_,                      tf::Immediate);
94✔
128
        main_states_.AddTransition(update_download_state_,                  se::NothingToDo,                 ss.download_leave_save_provides,         tf::Immediate);
94✔
129

130
        main_states_.AddTransition(ss.download_leave_,                      se::Success,                     send_install_status_state_,              tf::Immediate);
94✔
131
        main_states_.AddTransition(ss.download_leave_,                      se::Failure,                     ss.download_error_,                      tf::Immediate);
94✔
132

133
        main_states_.AddTransition(ss.download_leave_save_provides,         se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
134
        main_states_.AddTransition(ss.download_leave_save_provides,         se::Failure,                     ss.download_error_,                      tf::Immediate);
94✔
135

136
        main_states_.AddTransition(ss.install_enter_,                       se::Success,                     update_install_state_,                   tf::Immediate);
94✔
137
        main_states_.AddTransition(ss.install_enter_,                       se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
94✔
138

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

142
        main_states_.AddTransition(update_install_state_,                   se::Success,                     ss.install_leave_,                       tf::Immediate);
94✔
143
        main_states_.AddTransition(update_install_state_,                   se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
94✔
144
        main_states_.AddTransition(update_install_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
145

146
        main_states_.AddTransition(ss.install_leave_,                       se::Success,                     update_check_reboot_state_,              tf::Immediate);
94✔
147
        main_states_.AddTransition(ss.install_leave_,                       se::Failure,                     ss.install_error_rollback_,              tf::Immediate);
94✔
148
        main_states_.AddTransition(ss.install_error_rollback_,              se::Success,                     update_check_rollback_state_,            tf::Immediate);
94✔
149
        main_states_.AddTransition(ss.install_error_rollback_,              se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
150

151
        main_states_.AddTransition(ss.failure_enter_,                       se::Success,                     update_failure_state_,                   tf::Immediate);
94✔
152
        main_states_.AddTransition(ss.failure_enter_,                       se::Failure,                     update_failure_state_,                   tf::Immediate);
94✔
153
        main_states_.AddTransition(ss.failure_enter_,                       se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
154

155

156
        main_states_.AddTransition(update_check_reboot_state_,              se::Success,                     send_reboot_status_state_,               tf::Immediate);
94✔
157
        main_states_.AddTransition(update_check_reboot_state_,              se::NothingToDo,                 update_before_commit_state_,             tf::Immediate);
94✔
158
        main_states_.AddTransition(update_check_reboot_state_,              se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
159
        main_states_.AddTransition(update_check_reboot_state_,              se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
160

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

164
        main_states_.AddTransition(ss.reboot_enter_,                        se::Success,                     update_reboot_state_,                    tf::Immediate);
94✔
165
        main_states_.AddTransition(ss.reboot_enter_,                        se::Failure,                     ss.reboot_error_,                        tf::Immediate);
94✔
166

167
        main_states_.AddTransition(update_reboot_state_,                    se::Success,                     update_verify_reboot_state_,             tf::Immediate);
94✔
168
        main_states_.AddTransition(update_reboot_state_,                    se::Failure,                     ss.reboot_error_,                        tf::Immediate);
94✔
169
        main_states_.AddTransition(update_reboot_state_,                    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
170

171
        main_states_.AddTransition(ss.reboot_error_,                        se::Success,                     update_check_rollback_state_,            tf::Immediate);
94✔
172
        main_states_.AddTransition(ss.reboot_error_,                        se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
173

174
        main_states_.AddTransition(update_verify_reboot_state_,             se::Success,                     ss.reboot_leave_,                        tf::Immediate);
94✔
175
        main_states_.AddTransition(update_verify_reboot_state_,             se::Failure,                     ss.reboot_error_,                        tf::Immediate);
94✔
176
        main_states_.AddTransition(update_verify_reboot_state_,             se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
177

178
        main_states_.AddTransition(ss.reboot_leave_,                        se::Success,                     update_before_commit_state_,             tf::Immediate);
94✔
179
        main_states_.AddTransition(ss.reboot_leave_,                        se::Failure,                     ss.reboot_error_,                        tf::Immediate);
94✔
180

181
        // Cannot fail.
182
        main_states_.AddTransition(update_before_commit_state_,             se::Success,                     send_commit_status_state_,               tf::Immediate);
94✔
183

184
        main_states_.AddTransition(send_commit_status_state_,               se::Success,                     ss.commit_enter_,                        tf::Immediate);
94✔
185
        main_states_.AddTransition(send_commit_status_state_,               se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
186

187
        main_states_.AddTransition(ss.commit_enter_,                        se::Success,                     update_commit_state_,                    tf::Immediate);
94✔
188
        main_states_.AddTransition(ss.commit_enter_,                        se::Failure,                     ss.commit_error_,                        tf::Immediate);
94✔
189

190
        main_states_.AddTransition(ss.commit_error_,                        se::Success,                     update_check_rollback_state_,            tf::Immediate);
94✔
191
        main_states_.AddTransition(ss.commit_error_,                        se::Failure,                     update_check_rollback_state_,            tf::Immediate);
94✔
192

193
        main_states_.AddTransition(update_commit_state_,                    se::Success,                     update_after_commit_state_,              tf::Immediate);
94✔
194
        main_states_.AddTransition(update_commit_state_,                    se::Failure,                     ss.commit_error_,                        tf::Immediate);
94✔
195
        main_states_.AddTransition(update_commit_state_,                    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
196

197
        main_states_.AddTransition(update_after_commit_state_,              se::Success,                     ss.commit_leave_,                        tf::Immediate);
94✔
198
        main_states_.AddTransition(update_after_commit_state_,              se::Failure,                     ss.commit_error_save_provides_,          tf::Immediate);
94✔
199
        main_states_.AddTransition(update_after_commit_state_,              se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
200

201
        main_states_.AddTransition(ss.commit_leave_,                        se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
202
        main_states_.AddTransition(ss.commit_leave_,                        se::Failure,                     ss.commit_error_save_provides_,          tf::Immediate);
94✔
203

204
        main_states_.AddTransition(ss.commit_error_save_provides_,          se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
205
        main_states_.AddTransition(ss.commit_error_save_provides_,          se::Failure,                     update_save_provides_state_,             tf::Immediate);
94✔
206

207
        main_states_.AddTransition(update_check_rollback_state_,            se::Success,                     ss.rollback_enter_,                      tf::Immediate);
94✔
208
        main_states_.AddTransition(update_check_rollback_state_,            se::NothingToDo,                 ss.failure_enter_,                       tf::Immediate);
94✔
209
        main_states_.AddTransition(update_check_rollback_state_,            se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
210
        main_states_.AddTransition(update_check_rollback_state_,            se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
211

212
        main_states_.AddTransition(ss.rollback_enter_,                      se::Success,                     update_rollback_state_,                  tf::Immediate);
94✔
213
        main_states_.AddTransition(ss.rollback_enter_,                      se::Failure,                     update_rollback_state_,                  tf::Immediate);
94✔
214

215
        main_states_.AddTransition(update_rollback_state_,                  se::Success,                     ss.rollback_leave_,                      tf::Immediate);
94✔
216
        main_states_.AddTransition(update_rollback_state_,                  se::Failure,                     ss.rollback_leave_error_,                tf::Immediate);
94✔
217
        main_states_.AddTransition(update_rollback_state_,                  se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
218

219
        main_states_.AddTransition(ss.rollback_leave_,                      se::Success,                     update_check_rollback_reboot_state_,     tf::Immediate);
94✔
220
        main_states_.AddTransition(ss.rollback_leave_,                      se::Failure,                     update_check_rollback_reboot_state_,     tf::Immediate);
94✔
221

222
        main_states_.AddTransition(ss.rollback_leave_error_,                se::Success,                     ss.failure_enter_,                       tf::Immediate);
94✔
223
        main_states_.AddTransition(ss.rollback_leave_error_,                se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
224

225
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::Success,                     ss.rollback_reboot_enter_,               tf::Immediate);
94✔
226
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::NothingToDo,                 update_rollback_successful_state_,       tf::Immediate);
94✔
227
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
228
        main_states_.AddTransition(update_check_rollback_reboot_state_,     se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
229

230
        main_states_.AddTransition(ss.rollback_reboot_enter_,               se::Success,                     update_rollback_reboot_state_,           tf::Immediate);
94✔
231
        main_states_.AddTransition(ss.rollback_reboot_enter_,               se::Failure,                     update_rollback_reboot_state_,           tf::Immediate);
94✔
232

233
        main_states_.AddTransition(ss.rollback_reboot_error_,               se::Success,                     ss.failure_enter_,                       tf::Immediate);
94✔
234
        main_states_.AddTransition(ss.rollback_reboot_error_,               se::Failure,                     ss.failure_enter_,                       tf::Immediate);
94✔
235

236
        // No Failure transition for this state see comments in handler.
237
        main_states_.AddTransition(update_rollback_reboot_state_,           se::Success,                     update_verify_rollback_reboot_state_,    tf::Immediate);
94✔
238
        main_states_.AddTransition(update_rollback_reboot_state_,           se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
239

240
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::Success,                     ss.rollback_reboot_leave_,               tf::Immediate);
94✔
241
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::Retry,                       update_rollback_reboot_state_,           tf::Immediate);
94✔
242
        main_states_.AddTransition(update_verify_rollback_reboot_state_,    se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
243

244
        main_states_.AddTransition(ss.rollback_reboot_leave_,               se::Success,                     update_rollback_successful_state_,       tf::Immediate);
94✔
245
        main_states_.AddTransition(ss.rollback_reboot_leave_,               se::Failure,                     ss.rollback_reboot_error_,               tf::Immediate);
94✔
246

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

249
        main_states_.AddTransition(update_failure_state_,                   se::Success,                     ss.failure_leave_update_save_provides_,  tf::Immediate);
94✔
250
        main_states_.AddTransition(update_failure_state_,                   se::Failure,                     ss.failure_leave_update_save_provides_,  tf::Immediate);
94✔
251
        main_states_.AddTransition(update_failure_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
252

253
        main_states_.AddTransition(ss.failure_leave_update_save_provides_,  se::Success,                     update_save_provides_state_,             tf::Immediate);
94✔
254
        main_states_.AddTransition(ss.failure_leave_update_save_provides_,  se::Failure,                     update_save_provides_state_,             tf::Immediate);
94✔
255

256
        // Even if this fails there is nothing we can do at this point.
257
        main_states_.AddTransition(update_save_provides_state_,             se::Success,                     update_cleanup_state_,                   tf::Immediate);
94✔
258
        main_states_.AddTransition(update_save_provides_state_,             se::Failure,                     update_cleanup_state_,                   tf::Immediate);
94✔
259
        main_states_.AddTransition(update_save_provides_state_,             se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
260

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

263
        main_states_.AddTransition(update_cleanup_state_,                   se::Success,                     send_final_status_state_,                tf::Immediate);
94✔
264
        main_states_.AddTransition(update_cleanup_state_,                   se::Failure,                     send_final_status_state_,                tf::Immediate);
94✔
265
        main_states_.AddTransition(update_cleanup_state_,                   se::StateLoopDetected,           state_loop_state_,                       tf::Immediate);
94✔
266

267
        main_states_.AddTransition(state_loop_state_,                       se::Success,                     send_final_status_state_,                tf::Immediate);
94✔
268
        main_states_.AddTransition(state_loop_state_,                       se::Failure,                     send_final_status_state_,                tf::Immediate);
94✔
269

270
        main_states_.AddTransition(send_final_status_state_,                se::Success,                     clear_artifact_data_state_,              tf::Immediate);
94✔
271
        main_states_.AddTransition(send_final_status_state_,                se::Failure,                     clear_artifact_data_state_,              tf::Immediate);
94✔
272

273
        main_states_.AddTransition(clear_artifact_data_state_,              se::Success,                     end_of_deployment_state_,                tf::Immediate);
94✔
274
        main_states_.AddTransition(clear_artifact_data_state_,              se::Failure,                     end_of_deployment_state_,                tf::Immediate);
94✔
275

276
        main_states_.AddTransition(end_of_deployment_state_,                se::Success,                     ss.idle_enter_,                          tf::Immediate);
94✔
277

278
        auto &dt = deployment_tracking_;
279

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

282
        dt.states_.AddTransition(dt.no_failures_state_,                     se::Failure,                     dt.failure_state_,                       tf::Immediate);
94✔
283
        dt.states_.AddTransition(dt.no_failures_state_,                     se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
284

285
        dt.states_.AddTransition(dt.failure_state_,                         se::RollbackStarted,             dt.rollback_attempted_state_,            tf::Immediate);
94✔
286
        dt.states_.AddTransition(dt.failure_state_,                         se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
287

288
        dt.states_.AddTransition(dt.rollback_attempted_state_,              se::Failure,                     dt.rollback_failed_state_,               tf::Immediate);
94✔
289
        dt.states_.AddTransition(dt.rollback_attempted_state_,              se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
290

291
        dt.states_.AddTransition(dt.rollback_failed_state_,                 se::DeploymentEnded,             dt.idle_state_,                          tf::Immediate);
94✔
292
        // clang-format on
293
}
94✔
294

295
StateMachine::StateMachine(
89✔
296
        Context &ctx, events::EventLoop &event_loop, chrono::milliseconds minimum_wait_time) :
89✔
297
        StateMachine(ctx, event_loop) {
89✔
298
        send_commit_status_state_.SetSmallestWaitInterval(minimum_wait_time);
89✔
299
        send_final_status_state_.SetSmallestWaitInterval(minimum_wait_time);
89✔
300
}
89✔
301

302
StateMachine::DeploymentTracking::DeploymentTracking() :
94✔
303
        states_(idle_state_) {
94✔
304
}
94✔
305

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

314
                        // This particular error code also fills in state_data.
315
                        ctx_.deployment.state_data = std::move(state_data);
1✔
316

317
                        ctx_.BeginDeploymentLogging();
1✔
318

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

329
        auto &store = ctx_.mender_context.GetMenderStoreDB();
88✔
330

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

334
                auto err = store.Remove(ctx_.mender_context.update_control_maps);
53✔
335
                if (err != error::NoError) {
53✔
UNCOV
336
                        log::Error(
×
UNCOV
337
                                "Error removing " + ctx_.mender_context.update_control_maps
×
UNCOV
338
                                + " key from database: " + err.String());
×
339
                        // Nothing we can do about it.
340
                }
341

342
                return;
343
        }
344

345
        // We have state data, move it to the context.
346
        ctx_.deployment.state_data = std::move(state_data);
35✔
347

348
        ctx_.BeginDeploymentLogging();
35✔
349

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

362
        auto &state = ctx_.deployment.state_data->state;
35✔
363

364
        if (state == ctx_.kUpdateStateDownload) {
35✔
365
                main_states_.SetState(update_cleanup_state_);
3✔
366
                // "rollback_attempted_state" because Download in its nature makes no system
367
                // changes, so a rollback is a no-op.
368
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
369

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

382
        } else if (state == ctx_.kUpdateStateArtifactRollback) {
27✔
383
                // Installation failed, but rollback could still succeed.
384
                main_states_.SetState(state_scripts_.rollback_enter_);
3✔
385
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
3✔
386

387
        } else if (
388
                state == ctx_.kUpdateStateArtifactRollbackReboot
24✔
389
                || state == ctx_.kUpdateStateArtifactVerifyRollbackReboot
22✔
390
                || state == ctx_.kUpdateStateVerifyRollbackReboot) {
44✔
391
                // Normal flow for a rebooting rollback.
392
                main_states_.SetState(update_verify_rollback_reboot_state_);
4✔
393
                deployment_tracking_.states_.SetState(deployment_tracking_.rollback_attempted_state_);
4✔
394

395
        } else if (
396
                state == ctx_.kUpdateStateAfterArtifactCommit
20✔
397
                || state == ctx_.kUpdateStateUpdateAfterFirstCommit) {
20✔
398
                // Re-run commit Leave scripts if spontaneously rebooted after commit.
399
                main_states_.SetState(update_after_commit_state_);
2✔
400
                deployment_tracking_.states_.SetState(deployment_tracking_.no_failures_state_);
2✔
401

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

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

420
        } else {
421
                // All other states trigger a rollback.
422
                main_states_.SetState(update_check_rollback_state_);
12✔
423
                deployment_tracking_.states_.SetState(deployment_tracking_.failure_state_);
12✔
424
        }
425

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

436
error::Error StateMachine::Run() {
93✔
437
        // Client is supposed to do one handling of each on startup.
438
        runner_.PostEvent(StateEvent::InventoryPollingTriggered);
93✔
439
        runner_.PostEvent(StateEvent::DeploymentPollingTriggered);
93✔
440

441
        auto err = RegisterSignalHandlers();
93✔
442
        if (err != error::NoError) {
93✔
UNCOV
443
                return err;
×
444
        }
445

446
        log::Info("Running Mender client " + conf::kMenderVersion);
93✔
447

448
        event_loop_.Run();
93✔
449
        return exit_state_.exit_error;
93✔
450
}
451

452
void StateMachine::StopAfterDeployment() {
91✔
453
        main_states_.AddTransition(
91✔
454
                end_of_deployment_state_,
455
                StateEvent::DeploymentEnded,
456
                exit_state_,
457
                sm::TransitionFlag::Immediate);
458
}
91✔
459

460
#ifndef NDEBUG
461
void StateMachine::StopAfterDeployments(int number) {
462
        exit_state_.ExitAfter(number);
463
        main_states_.AddTransition(
464
                end_of_deployment_state_, StateEvent::Success, exit_state_, sm::TransitionFlag::Immediate);
465
        main_states_.AddTransition(
466
                exit_state_,
467
                StateEvent::Success,
468
                state_scripts_.idle_enter_,
469
                sm::TransitionFlag::Immediate);
470
}
471
#endif
472

473
} // namespace daemon
474
} // namespace update
475
} // 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