Aktualizr
C++ SOTA Client
aktualizr.cc
1 #include <chrono>
2 
3 #include <sodium.h>
4 
5 #include "libaktualizr/aktualizr.h"
6 #include "libaktualizr/events.h"
7 
8 #include "sotauptaneclient.h"
9 #include "utilities/apiqueue.h"
10 #include "utilities/timer.h"
11 
12 using std::make_shared;
13 using std::shared_ptr;
14 
16  : Aktualizr(config, INvStorage::newStorage(config.storage), std::make_shared<HttpClient>()) {}
17 
18 Aktualizr::Aktualizr(Config config, std::shared_ptr<INvStorage> storage_in,
19  const std::shared_ptr<HttpInterface> &http_in)
20  : config_{std::move(config)}, sig_{new event::Channel()}, api_queue_(new api::CommandQueue()) {
21  if (sodium_init() == -1) { // Note that sodium_init doesn't require a matching 'sodium_deinit'
22  throw std::runtime_error("Unable to initialize libsodium");
23  }
24 
25  storage_ = std::move(storage_in);
26  storage_->importData(config_.import);
27 
28  uptane_client_ = std::make_shared<SotaUptaneClient>(config_, storage_, http_in, sig_);
29 }
30 
31 Aktualizr::~Aktualizr() { api_queue_.reset(nullptr); }
32 
34  uptane_client_->initialize();
35  api_queue_->run();
36 }
37 
39  result::UpdateCheck update_result = CheckUpdates().get();
40  if (update_result.updates.empty()) {
41  if (update_result.status == result::UpdateStatus::kError) {
42  // If the metadata verification failed, inform the backend immediately.
43  SendManifest().get();
44  }
45  return true;
46  }
47 
48  result::Download download_result = Download(update_result.updates).get();
49  if (download_result.status != result::DownloadStatus::kSuccess || download_result.updates.empty()) {
50  if (download_result.status != result::DownloadStatus::kNothingToDownload) {
51  // If the download failed, inform the backend immediately.
52  SendManifest().get();
53  }
54  return true;
55  }
56 
57  Install(download_result.updates).get();
58 
59  if (uptane_client_->isInstallCompletionRequired()) {
60  // If there are some pending updates then effectively either reboot (OSTree) or aktualizr restart (fake pack mngr)
61  // is required to apply the update(s)
62  LOG_INFO << "Exiting aktualizr so that pending updates can be applied after reboot";
63  return false;
64  }
65 
66  if (!uptane_client_->hasPendingUpdates()) {
67  // If updates were applied and no any reboot/finalization is required then send/put manifest
68  // as soon as possible, don't wait for config_.uptane.polling_sec
69  SendManifest().get();
70  }
71 
72  return true;
73 }
74 
75 std::future<void> Aktualizr::RunForever(const Json::Value &custom_hwinfo) {
76  std::future<void> future = std::async(std::launch::async, [this, custom_hwinfo]() {
77  SendDeviceData(custom_hwinfo).get();
78 
79  std::unique_lock<std::mutex> l(exit_cond_.m);
80  while (true) {
81  if (!UptaneCycle()) {
82  break;
83  }
84 
85  if (exit_cond_.cv.wait_for(l, std::chrono::seconds(config_.uptane.polling_sec),
86  [this] { return exit_cond_.flag; })) {
87  break;
88  }
89  }
90  uptane_client_->completeInstall();
91  });
92  return future;
93 }
94 
96  {
97  std::lock_guard<std::mutex> g(exit_cond_.m);
98  exit_cond_.flag = true;
99  }
100  exit_cond_.cv.notify_all();
101 }
102 
103 void Aktualizr::AddSecondary(const std::shared_ptr<SecondaryInterface> &secondary) {
104  uptane_client_->addSecondary(secondary);
105 }
106 
107 void Aktualizr::SetSecondaryData(const Uptane::EcuSerial &ecu, const std::string &data) {
108  storage_->saveSecondaryData(ecu, data);
109 }
110 
111 std::vector<SecondaryInfo> Aktualizr::GetSecondaries() const {
112  std::vector<SecondaryInfo> info;
113  storage_->loadSecondariesInfo(&info);
114 
115  return info;
116 }
117 
118 std::future<result::CampaignCheck> Aktualizr::CampaignCheck() {
119  std::function<result::CampaignCheck()> task([this] { return uptane_client_->campaignCheck(); });
120  return api_queue_->enqueue(task);
121 }
122 
123 std::future<void> Aktualizr::CampaignControl(const std::string &campaign_id, campaign::Cmd cmd) {
124  std::function<void()> task([this, campaign_id, cmd] {
125  switch (cmd) {
126  case campaign::Cmd::Accept:
127  uptane_client_->campaignAccept(campaign_id);
128  break;
129  case campaign::Cmd::Decline:
130  uptane_client_->campaignDecline(campaign_id);
131  break;
132  case campaign::Cmd::Postpone:
133  uptane_client_->campaignPostpone(campaign_id);
134  break;
135  default:
136  break;
137  }
138  });
139  return api_queue_->enqueue(task);
140 }
141 
142 std::future<void> Aktualizr::SendDeviceData(const Json::Value &custom_hwinfo) {
143  std::function<void()> task([this, custom_hwinfo] { uptane_client_->sendDeviceData(custom_hwinfo); });
144  return api_queue_->enqueue(task);
145 }
146 
147 std::future<result::UpdateCheck> Aktualizr::CheckUpdates() {
148  std::function<result::UpdateCheck()> task([this] { return uptane_client_->fetchMeta(); });
149  return api_queue_->enqueue(task);
150 }
151 
152 std::future<result::Download> Aktualizr::Download(const std::vector<Uptane::Target> &updates) {
153  std::function<result::Download(const api::FlowControlToken *)> task(
154  [this, updates](const api::FlowControlToken *token) { return uptane_client_->downloadImages(updates, token); });
155  return api_queue_->enqueue(task);
156 }
157 
158 std::future<result::Install> Aktualizr::Install(const std::vector<Uptane::Target> &updates) {
159  std::function<result::Install()> task([this, updates] { return uptane_client_->uptaneInstall(updates); });
160  return api_queue_->enqueue(task);
161 }
162 
163 bool Aktualizr::SetInstallationRawReport(const std::string &custom_raw_report) {
164  return storage_->storeDeviceInstallationRawReport(custom_raw_report);
165 }
166 
167 std::future<bool> Aktualizr::SendManifest(const Json::Value &custom) {
168  std::function<bool()> task([this, custom]() { return uptane_client_->putManifest(custom); });
169  return api_queue_->enqueue(task);
170 }
171 
173  if (api_queue_->pause(true)) {
174  uptane_client_->reportPause();
175  return result::PauseStatus::kSuccess;
176  } else {
177  return result::PauseStatus::kAlreadyPaused;
178  }
179 }
180 
182  if (api_queue_->pause(false)) {
183  uptane_client_->reportResume();
184  return result::PauseStatus::kSuccess;
185  } else {
186  return result::PauseStatus::kAlreadyRunning;
187  }
188 }
189 
190 void Aktualizr::Abort() { api_queue_->abort(); }
191 
192 boost::signals2::connection Aktualizr::SetSignalHandler(
193  const std::function<void(shared_ptr<event::BaseEvent>)> &handler) {
194  return sig_->connect(handler);
195 }
196 
197 Aktualizr::InstallationLog Aktualizr::GetInstallationLog() {
198  std::vector<Aktualizr::InstallationLogEntry> ilog;
199 
200  EcuSerials serials;
201  if (!storage_->loadEcuSerials(&serials)) {
202  throw std::runtime_error("Could not load ECU serials");
203  }
204 
205  ilog.reserve(serials.size());
206  for (const auto &s : serials) {
207  Uptane::EcuSerial serial = s.first;
208  std::vector<Uptane::Target> installs;
209 
210  std::vector<Uptane::Target> log;
211  storage_->loadInstallationLog(serial.ToString(), &log, true);
212 
213  ilog.emplace_back(Aktualizr::InstallationLogEntry{serial, std::move(log)});
214  }
215 
216  return ilog;
217 }
218 
219 std::vector<Uptane::Target> Aktualizr::GetStoredTargets() { return uptane_client_->getStoredTargets(); }
220 
221 void Aktualizr::DeleteStoredTarget(const Uptane::Target &target) { uptane_client_->deleteStoredTarget(target); }
222 
223 std::ifstream Aktualizr::OpenStoredTarget(const Uptane::Target &target) {
224  return uptane_client_->openStoredTarget(target);
225 }
Aktualizr::Resume
result::Pause Resume()
Resume the library operations.
Definition: aktualizr.cc:181
Aktualizr::Install
std::future< result::Install > Install(const std::vector< Uptane::Target > &updates)
Install targets.
Definition: aktualizr.cc:158
Aktualizr::SendDeviceData
std::future< void > SendDeviceData(const Json::Value &custom_hwinfo=Json::nullValue)
Send local device data to the server.
Definition: aktualizr.cc:142
Aktualizr::OpenStoredTarget
std::ifstream OpenStoredTarget(const Uptane::Target &target)
Get target downloaded in Download call.
Definition: aktualizr.cc:223
Aktualizr::Aktualizr
Aktualizr(const Config &config)
Aktualizr requires a configuration object.
Definition: aktualizr.cc:15
Aktualizr::DeleteStoredTarget
void DeleteStoredTarget(const Uptane::Target &target)
Delete a stored target from storage.
Definition: aktualizr.cc:221
Aktualizr::RunForever
std::future< void > RunForever(const Json::Value &custom_hwinfo=Json::nullValue)
Asynchronously run aktualizr indefinitely until Shutdown is called.
Definition: aktualizr.cc:75
Aktualizr::SendManifest
std::future< bool > SendManifest(const Json::Value &custom=Json::nullValue)
Send installation report to the backend.
Definition: aktualizr.cc:167
Aktualizr::CampaignControl
std::future< void > CampaignControl(const std::string &campaign_id, campaign::Cmd cmd)
Act on campaign: accept, decline or postpone.
Definition: aktualizr.cc:123
Aktualizr::SetInstallationRawReport
bool SetInstallationRawReport(const std::string &custom_raw_report)
SetInstallationRawReport allows setting a custom raw report field in the device installation result.
Definition: aktualizr.cc:163
Aktualizr::Shutdown
void Shutdown()
Shuts down currently running RunForever() method.
Definition: aktualizr.cc:95
result::UpdateCheck
Container for information about available updates.
Definition: results.h:37
Aktualizr::Initialize
void Initialize()
Initialize aktualizr.
Definition: aktualizr.cc:33
Aktualizr::CheckUpdates
std::future< result::UpdateCheck > CheckUpdates()
Fetch Uptane metadata and check for updates.
Definition: aktualizr.cc:147
data
General data structures.
Definition: types.h:217
Aktualizr::CampaignCheck
std::future< result::CampaignCheck > CampaignCheck()
Check for campaigns.
Definition: aktualizr.cc:118
Config
Configuration object for an aktualizr instance running on a Primary ECU.
Definition: config.h:208
events.h
Uptane::EcuSerial
Definition: types.h:346
Aktualizr
This class provides the main APIs necessary for launching and controlling libaktualizr.
Definition: aktualizr.h:24
HttpClient
Definition: httpclient.h:28
result::Download
Container for information about downloading an update.
Definition: results.h:116
Aktualizr::AddSecondary
void AddSecondary(const std::shared_ptr< SecondaryInterface > &secondary)
Add new Secondary to aktualizr.
Definition: aktualizr.cc:103
Aktualizr::Abort
void Abort()
Aborts the currently running command, if it can be aborted, or waits for it to finish; then removes a...
Definition: aktualizr.cc:190
Aktualizr::GetStoredTargets
std::vector< Uptane::Target > GetStoredTargets()
Get list of targets currently in storage.
Definition: aktualizr.cc:219
Aktualizr::InstallationLogEntry
Definition: aktualizr.h:147
result::Pause
Definition: results.h:68
api::FlowControlToken
Provides a thread-safe way to pause and terminate task execution.
Definition: apiqueue.h:19
Aktualizr::SetSignalHandler
boost::signals2::connection SetSignalHandler(const SigHandler &handler)
Provide a function to receive event notifications.
Definition: aktualizr.cc:192
Aktualizr::GetSecondaries
std::vector< SecondaryInfo > GetSecondaries() const
Returns a list of the registered Secondaries, along with some associated metadata.
Definition: aktualizr.cc:111
Aktualizr::GetInstallationLog
InstallationLog GetInstallationLog()
Get log of installations.
Definition: aktualizr.cc:197
result::Install
Container for information about installing an update.
Definition: results.h:129
api::CommandQueue
Definition: apiqueue.h:57
Aktualizr::UptaneCycle
bool UptaneCycle()
Synchronously run an Uptane cycle: check for updates, download any new targets, install them,...
Definition: aktualizr.cc:38
Uptane::Target
Definition: types.h:379
result::CampaignCheck
Container for information about available campaigns.
Definition: results.h:16
Aktualizr::SetSecondaryData
void SetSecondaryData(const Uptane::EcuSerial &ecu, const std::string &data)
Store some free-form data to be associated with a particular Secondary, to be retrieved later through...
Definition: aktualizr.cc:107
INvStorage
Definition: invstorage.h:43
Aktualizr::Download
std::future< result::Download > Download(const std::vector< Uptane::Target > &updates)
Download targets.
Definition: aktualizr.cc:152
Aktualizr::Pause
result::Pause Pause()
Pause the library operations.
Definition: aktualizr.cc:172