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