Aktualizr
C++ SOTA Client
All Classes Namespaces Files Functions Variables Enumerations Enumerator Pages
main.cc
1 #include <iostream>
2 
3 #include <boost/filesystem.hpp>
4 #include <boost/program_options.hpp>
5 #include <boost/property_tree/ini_parser.hpp>
6 #include <boost/signals2.hpp>
7 
8 #include "config/config.h"
9 #include "logging/logging.h"
10 #include "primary/aktualizr.h"
11 #include "primary/aktualizr_helpers.h"
12 #include "secondary.h"
13 #include "utilities/aktualizr_version.h"
14 #include "utilities/sig_handler.h"
15 #include "utilities/utils.h"
16 
17 namespace bpo = boost::program_options;
18 
19 void checkInfoOptions(const bpo::options_description &description, const bpo::variables_map &vm) {
20  if (vm.count("help") != 0) {
21  std::cout << description << '\n';
22  exit(EXIT_SUCCESS);
23  }
24  if (vm.count("version") != 0) {
25  std::cout << "Current aktualizr version is: " << aktualizr_version() << "\n";
26  exit(EXIT_SUCCESS);
27  }
28 }
29 
30 bpo::variables_map parseOptions(int argc, char *argv[]) {
31  bpo::options_description description("aktualizr command line options");
32  // clang-format off
33  // Try to keep these options in the same order as Config::updateFromCommandLine().
34  // The first three are commandline only.
35  description.add_options()
36  ("help,h", "print usage")
37  ("version,v", "Current aktualizr version")
38  ("config,c", bpo::value<std::vector<boost::filesystem::path> >()->composing(), "configuration file or directory")
39  ("loglevel", bpo::value<int>(), "set log level 0-5 (trace, debug, info, warning, error, fatal)")
40  ("run-mode", bpo::value<std::string>(), "run mode of aktualizr: full, once, campaign_check, campaign_accept, campaign_decline, campaign_postpone, check, download, or install")
41  ("tls-server", bpo::value<std::string>(), "URL of device gateway")
42  ("repo-server", bpo::value<std::string>(), "URL of the Uptane Image repository")
43  ("director-server", bpo::value<std::string>(), "URL of the Uptane Director repository")
44  ("primary-ecu-serial", bpo::value<std::string>(), "serial number of Primary ECU")
45  ("primary-ecu-hardware-id", bpo::value<std::string>(), "hardware ID of Primary ECU")
46  ("secondary-config-file", bpo::value<boost::filesystem::path>(), "secondary ECUs configuration file")
47  ("campaign-id", bpo::value<std::string>(), "ID of the campaign to act on");
48  // clang-format on
49 
50  // consider the first positional argument as the aktualizr run mode
51  bpo::positional_options_description pos;
52  pos.add("run-mode", 1);
53 
54  bpo::variables_map vm;
55  std::vector<std::string> unregistered_options;
56  try {
57  bpo::basic_parsed_options<char> parsed_options =
58  bpo::command_line_parser(argc, argv).options(description).positional(pos).allow_unregistered().run();
59  bpo::store(parsed_options, vm);
60  checkInfoOptions(description, vm);
61  bpo::notify(vm);
62  unregistered_options = bpo::collect_unrecognized(parsed_options.options, bpo::exclude_positional);
63  if (vm.count("help") == 0 && !unregistered_options.empty()) {
64  std::cout << description << "\n";
65  exit(EXIT_FAILURE);
66  }
67  } catch (const bpo::required_option &ex) {
68  // print the error and append the default commandline option description
69  std::cout << ex.what() << std::endl << description;
70  exit(EXIT_FAILURE);
71  } catch (const bpo::error &ex) {
72  checkInfoOptions(description, vm);
73 
74  // log boost error
75  LOG_ERROR << "boost command line option error: " << ex.what();
76 
77  // print the error message to the standard output too, as the user provided
78  // a non-supported commandline option
79  std::cout << ex.what() << '\n';
80 
81  // set the returnValue, thereby ctest will recognize
82  // that something went wrong
83  exit(EXIT_FAILURE);
84  }
85 
86  return vm;
87 }
88 
89 void processEvent(const std::shared_ptr<event::BaseEvent> &event) {
90  if (event->isTypeOf<event::DownloadProgressReport>()) {
91  // Do nothing; libaktualizr already logs it.
92  } else if (event->variant == "UpdateCheckComplete") {
93  // Do nothing; libaktualizr already logs it.
94  } else if (event->variant == "AllDownloadsComplete") {
95  const auto downloads_complete = dynamic_cast<event::AllDownloadsComplete *>(event.get());
96  LOG_INFO << "got " << event->variant << " event with status: " << downloads_complete->result.status;
97  } else if (event->variant == "AllInstallsComplete") {
98  const auto installs_complete = dynamic_cast<event::AllInstallsComplete *>(event.get());
99  LOG_INFO << "got " << event->variant << " event with status: " << installs_complete->result.dev_report.result_code;
100  } else {
101  LOG_INFO << "got " << event->variant << " event";
102  }
103 }
104 
105 int main(int argc, char *argv[]) {
106  logger_init();
107  logger_set_threshold(boost::log::trivial::info);
108 
109  bpo::variables_map commandline_map = parseOptions(argc, argv);
110 
111  LOG_INFO << "Aktualizr version " << aktualizr_version() << " starting";
112 
113  int r = EXIT_FAILURE;
114 
115  try {
116  if (geteuid() != 0) {
117  LOG_WARNING << "\033[31mAktualizr is currently running as non-root and may not work as expected! Aktualizr "
118  "should be run as root for proper functionality.\033[0m\n";
119  }
120  Config config(commandline_map);
121  LOG_DEBUG << "Current directory: " << boost::filesystem::current_path().string();
122 
123  Aktualizr aktualizr(config);
124  std::function<void(std::shared_ptr<event::BaseEvent> event)> f_cb = processEvent;
125  boost::signals2::scoped_connection conn;
126 
127  conn = aktualizr.SetSignalHandler(f_cb);
128 
129  if (!config.uptane.secondary_config_file.empty()) {
130  try {
131  Primary::initSecondaries(aktualizr, config.uptane.secondary_config_file);
132  } catch (const std::exception &e) {
133  LOG_ERROR << "Failed to init secondaries :" << e.what();
134  LOG_ERROR << "Exiting...";
135  return EXIT_FAILURE;
136  }
137  }
138 
139  aktualizr.Initialize();
140 
141  // handle unix signals
142  SigHandler::get().start([&aktualizr]() {
143  aktualizr.Abort();
144  aktualizr.Shutdown();
145  });
146  SigHandler::signal(SIGHUP);
147  SigHandler::signal(SIGINT);
148  SigHandler::signal(SIGTERM);
149 
150  std::string run_mode;
151  if (commandline_map.count("run-mode") != 0) {
152  run_mode = commandline_map["run-mode"].as<std::string>();
153  }
154  // launch the first event
155  if (run_mode == "campaign_check") {
156  aktualizr.CampaignCheck().get();
157  } else if (run_mode == "campaign_accept" || run_mode == "campaign_decline" || run_mode == "campaign_postpone") {
158  if (commandline_map.count("campaign-id") == 0) {
159  throw std::runtime_error(run_mode + " requires a campaign ID");
160  }
161  aktualizr.CampaignControl(commandline_map["campaign-id"].as<std::string>(), campaign::cmdFromName(run_mode))
162  .get();
163  } else if (run_mode == "check") {
164  aktualizr.SendDeviceData().get();
165  aktualizr.CheckUpdates().get();
166  } else if (run_mode == "download") {
167  result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
168  aktualizr.Download(update_result.updates).get();
169  } else if (run_mode == "install") {
170  result::UpdateCheck update_result = aktualizr.CheckUpdates().get();
171  aktualizr.Install(update_result.updates).get();
172  } else if (run_mode == "once") {
173  aktualizr.SendDeviceData().get();
174  aktualizr.UptaneCycle();
175  } else {
176  boost::signals2::connection ac_conn =
177  aktualizr.SetSignalHandler(std::bind(targets_autoclean_cb, std::ref(aktualizr), std::placeholders::_1));
178 
179  try {
180  aktualizr.RunForever().get();
181  } catch (const std::exception &ex) {
182  LOG_ERROR << ex.what();
183  }
184 
185  LOG_DEBUG << "Aktualizr daemon exiting...";
186  }
187  r = EXIT_SUCCESS;
188  } catch (const std::exception &ex) {
189  LOG_ERROR << ex.what();
190  }
191 
192  return r;
193 }
result::UpdateCheck
Container for information about available updates.
Definition: results.h:38
Config
Configuration object for an aktualizr instance running on a primary ECU.
Definition: config.h:74
Aktualizr
This class provides the main APIs necessary for launching and controlling libaktualizr.
Definition: aktualizr.h:20
event::DownloadProgressReport
A report for a download in progress.
Definition: events.h:71
event
Aktualizr status events.
Definition: events.h:18