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

mendersoftware / mender / 1022567176

02 Oct 2023 07:50AM UTC coverage: 80.127% (+2.5%) from 77.645%
1022567176

push

gitlab-ci

kacf
chore: Centralize selection of `std::filesystem` library.

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

6447 of 8046 relevant lines covered (80.13%)

9912.21 hits per line

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

0.0
/mender-update/daemon/states.hpp
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
#ifndef MENDER_UPDATE_STATES_HPP
16
#define MENDER_UPDATE_STATES_HPP
17

18
#include <common/io.hpp>
19
#include <common/optional.hpp>
20
#include <common/state_machine.hpp>
21

22
#include <artifact/artifact.hpp>
23

24
#include <mender-update/daemon/context.hpp>
25
#include <mender-update/daemon/state_events.hpp>
26

27
#include <artifact/v3/scripts/executor.hpp>
28

29
namespace mender {
30
namespace update {
31
namespace daemon {
32

33
using namespace std;
34

35
namespace io = mender::common::io;
36
namespace sm = mender::common::state_machine;
37

38
namespace artifact = mender::artifact;
39

40
namespace script_executor = ::mender::artifact::scripts::executor;
41

42
using StateType = sm::State<Context, StateEvent>;
43

44
class EmptyState : virtual public StateType {
45
public:
46
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
47
};
48

49
class InitState : virtual public StateType {
50
public:
51
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
52
};
53

54
class IdleState : virtual public StateType {
55
public:
56
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
57
};
58

59
class PollForDeploymentState : virtual public StateType {
60
public:
61
        PollForDeploymentState(events::EventLoop &loop) :
62
                poll_timer_(loop) {
63
        }
64
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
65

66
private:
67
        events::Timer poll_timer_;
68
};
69

70
class SubmitInventoryState : virtual public StateType {
71
public:
72
        SubmitInventoryState(events::EventLoop &loop) :
73
                poll_timer_(loop) {
74
        }
75
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
76

77
private:
78
        void DoSubmitInventory(Context &ctx, sm::EventPoster<StateEvent> &poster);
79
        events::Timer poll_timer_;
80
};
81

82
class SaveState : virtual public StateType {
83
public:
84
        // Sub states should implement OnEnterSaveState instead, since we do state saving in
85
        // here. Note that not all states that participate in an update are SaveStates that get
86
        // their database key saved. Some states are not because it's good enough to rely on the
87
        // previously saved state.
88
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override final;
89

90
        virtual void OnEnterSaveState(Context &ctx, sm::EventPoster<StateEvent> &poster) = 0;
91
        virtual const string &DatabaseStateString() const = 0;
92
        virtual bool IsFailureState() const = 0;
93
};
94

95
class UpdateDownloadState : virtual public StateType {
96
public:
97
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
98

99
private:
100
        // `static` since they only need the arguments, but are still strongly tied to
101
        // OnEnterSaveState.
102
        static void ParseArtifact(Context &ctx, sm::EventPoster<StateEvent> &poster);
103
        static void DoDownload(Context &ctx, sm::EventPoster<StateEvent> &poster);
104
};
105

106
class SendStatusUpdateState : virtual public StateType {
107
public:
108
        // Ignore-failure version.
109
        SendStatusUpdateState(optional<deployments::DeploymentStatus> status);
110
        // Retry-then-fail version.
111
        SendStatusUpdateState(
112
                optional<deployments::DeploymentStatus> status,
113
                events::EventLoop &event_loop,
114
                int retry_interval_seconds);
115
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
116

117
        // For tests.
118
        void SetSmallestWaitInterval(chrono::milliseconds interval);
119

120
private:
121
        void DoStatusUpdate(Context &ctx, sm::EventPoster<StateEvent> &poster);
122

123
        enum class FailureMode {
124
                Ignore,
125
                RetryThenFail,
126
        };
127

128
        optional<deployments::DeploymentStatus> status_;
129
        FailureMode mode_;
130
        struct Retry {
×
131
                http::ExponentialBackoff backoff;
132
                events::Timer wait_timer;
133
        };
134
        optional<Retry> retry_;
135
};
136

137
class UpdateInstallState : virtual public StateType {
138
public:
139
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
140
};
141

142
class UpdateCheckRebootState : virtual public StateType {
143
public:
144
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
145
};
146

147
class UpdateRebootState : virtual public StateType {
148
public:
149
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
150
};
151

152
class UpdateVerifyRebootState : virtual public SaveState {
153
public:
154
        void OnEnterSaveState(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
155
        const string &DatabaseStateString() const override {
156
                return Context::kUpdateStateArtifactVerifyReboot;
157
        }
158
        bool IsFailureState() const override {
159
                return false;
160
        }
161
};
162

163
class UpdateBeforeCommitState : virtual public StateType {
164
public:
165
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
166
};
167

168
class UpdateCommitState : virtual public StateType {
169
public:
170
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
171
};
172

173
class UpdateAfterCommitState : virtual public SaveState {
174
public:
175
        void OnEnterSaveState(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
176
        const string &DatabaseStateString() const override {
177
                return Context::kUpdateStateAfterArtifactCommit;
178
        }
179
        bool IsFailureState() const override {
180
                return false;
181
        }
182
};
183

184
class UpdateCheckRollbackState : virtual public StateType {
185
public:
186
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
187
};
188

189
class UpdateRollbackState : virtual public StateType {
190
public:
191
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
192
};
193

194
class UpdateRollbackRebootState : virtual public StateType {
195
public:
196
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
197
};
198

199
class UpdateVerifyRollbackRebootState : virtual public SaveState {
200
public:
201
        void OnEnterSaveState(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
202
        const string &DatabaseStateString() const override {
203
                return Context::kUpdateStateArtifactVerifyRollbackReboot;
204
        }
205
        bool IsFailureState() const override {
206
                return true;
207
        }
208
};
209

210
class UpdateRollbackSuccessfulState : virtual public StateType {
211
public:
212
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
213
};
214

215
class UpdateFailureState : virtual public SaveState {
216
public:
217
        void OnEnterSaveState(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
218
        const string &DatabaseStateString() const override {
219
                return Context::kUpdateStateArtifactFailure;
220
        }
221
        bool IsFailureState() const override {
222
                return true;
223
        }
224
};
225

226
class UpdateSaveProvidesState : virtual public StateType {
227
public:
228
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
229
};
230

231
class UpdateCleanupState : virtual public SaveState {
232
public:
233
        void OnEnterSaveState(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
234
        const string &DatabaseStateString() const override {
235
                return Context::kUpdateStateCleanup;
236
        }
237
        bool IsFailureState() const override {
238
                // This is actually both a failure and non-failure state, but it is executed in
239
                // every failure scenario, which is what is important here.
240
                return true;
241
        }
242
};
243

244
class ClearArtifactDataState : virtual public StateType {
245
public:
246
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
247
};
248

249
class StateLoopState : virtual public StateType {
250
public:
251
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
252
};
253

254
class EndOfDeploymentState : virtual public StateType {
255
public:
256
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
257
};
258

259
class ExitState : virtual public StateType {
260
public:
261
        ExitState(events::EventLoop &event_loop);
262
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
263

264
        error::Error exit_error;
265

266
private:
267
        events::EventLoop &event_loop_;
268
};
269

270

271
//
272
// State Script states
273
//
274

275
class StateScriptState : virtual public StateType {
276
public:
277
        StateScriptState(
278
                events::EventLoop &event_loop,
279
                script_executor::State state,
280
                script_executor::Action action,
281
                chrono::seconds retry_interval,
282
                const string &artifact_script_path,
283
                const string &rootfs_script_path) :
284
                script_ {
285
                        event_loop,
286
                        retry_interval,
287
                        artifact_script_path,
288
                        rootfs_script_path,
289
                },
290
                state_ {state},
291
                action_ {action} {};
292

293
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
294

295
private:
296
        script_executor::ScriptRunner script_;
297
        script_executor::State state_;
298
        script_executor::Action action_;
299
};
300

301
class SaveStateScriptState : virtual public SaveState {
302
public:
303
        SaveStateScriptState(
304
                events::EventLoop &event_loop,
305
                script_executor::State state,
306
                script_executor::Action action,
307
                chrono::seconds retry_interval,
308
                const string &artifact_script_path,
309
                const string &rootfs_script_path,
310
                const string &database_key,
311
                const bool is_failure_state = false) :
312
                state_script_state_ {
313
                        event_loop,
314
                        state,
315
                        action,
316
                        retry_interval,
317
                        artifact_script_path,
318
                        rootfs_script_path,
319
                },
320
                database_key_ {database_key},
321
                is_failure_state_ {is_failure_state} {};
322

323
        void OnEnterSaveState(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
324

325
        const string &DatabaseStateString() const override {
326
                return database_key_;
327
        }
328

329
        bool IsFailureState() const override {
330
                return is_failure_state_;
331
        }
332

333
private:
334
        StateScriptState state_script_state_;
335
        const string database_key_;
336
        const bool is_failure_state_;
337
};
338

339

340
//
341
// End State Script states
342
//
343

344

345
namespace deployment_tracking {
346

347
class NoFailuresState : virtual public StateType {
348
public:
349
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
350
};
351

352
class FailureState : virtual public StateType {
353
public:
354
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
355
};
356

357
class RollbackAttemptedState : virtual public StateType {
358
public:
359
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
360
};
361

362
class RollbackFailedState : virtual public StateType {
363
public:
364
        void OnEnter(Context &ctx, sm::EventPoster<StateEvent> &poster) override;
365
};
366

367
} // namespace deployment_tracking
368

369
} // namespace daemon
370
} // namespace update
371
} // namespace mender
372

373
#endif // MENDER_UPDATE_STATES_HPP
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