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