4 #include <boost/filesystem.hpp> 5 #include <boost/program_options.hpp> 8 #include "libaktualizr/config.h" 9 #include "utilities/aktualizr_version.h" 11 namespace bpo = boost::program_options;
13 static void log_info_target(
const std::string &prefix,
const Config &config,
const Uptane::Target &t) {
14 auto name = t.filename();
15 if (t.custom_version().length() > 0) {
16 name = t.custom_version();
18 LOG_INFO << prefix + name <<
"\tsha256:" << t.sha256Hash();
19 if (config.pacman.type == PACKAGE_MANAGER_OSTREEDOCKERAPP) {
21 auto apps = t.custom_data()[
"docker_apps"];
22 for (Json::ValueIterator i = apps.begin(); i != apps.end(); ++i) {
25 LOG_INFO <<
"\tDocker Apps:";
27 if ((*i).isObject() && (*i).isMember(
"filename")) {
28 LOG_INFO <<
"\t\t" << i.key().asString() <<
" -> " << (*i)[
"filename"].asString();
30 if ((*i).isObject() && (*i).isMember(
"uri")) {
31 LOG_INFO <<
"\t\t" << i.key().asString() <<
" -> " << (*i)[
"uri"].asString();
37 static int status_main(
LiteClient &client,
const bpo::variables_map &unused) {
39 auto target = client.primary->getCurrent();
41 if (target.MatchTarget(Uptane::Target::Unknown())) {
42 LOG_INFO <<
"No active deployment found";
44 auto name = target.filename();
45 if (target.custom_version().length() > 0) {
46 name = target.custom_version();
48 log_info_target(
"Active image is: ", client.config, target);
53 static int list_main(
LiteClient &client,
const bpo::variables_map &unused) {
57 LOG_INFO <<
"Refreshing Targets metadata";
59 client.primary->updateImageMeta();
60 }
catch (
const std::exception &e) {
61 LOG_WARNING <<
"Unable to update latest metadata, using local copy";
63 client.primary->checkImageMetaOffline();
64 }
catch (
const std::exception &e2) {
65 LOG_ERROR <<
"Unable to use local copy of TUF data";
70 LOG_INFO <<
"Updates available to " << hwid <<
":";
71 for (
auto &t : client.primary->allTargets()) {
72 for (
auto const &it : t.hardwareIds()) {
74 log_info_target(
"", client.config, t);
82 static std::unique_ptr<Uptane::Target> find_target(
const std::shared_ptr<SotaUptaneClient> &client,
84 std::unique_ptr<Uptane::Target> rv;
86 client->updateImageMeta();
87 }
catch (
const std::exception &e) {
88 LOG_WARNING <<
"Unable to update latest metadata, using local copy";
90 client->checkImageMetaOffline();
91 }
catch (
const std::exception &e2) {
92 throw std::runtime_error(
"Unable to find update");
96 bool find_latest = (version ==
"latest");
97 std::unique_ptr<Uptane::Target> latest =
nullptr;
98 for (
auto &t : client->allTargets()) {
99 for (
auto const &it : t.hardwareIds()) {
102 if (latest ==
nullptr ||
Version(latest->custom_version()) <
Version(t.custom_version())) {
103 latest = std_::make_unique<Uptane::Target>(t);
105 }
else if (version == t.filename() || version == t.custom_version()) {
106 return std_::make_unique<Uptane::Target>(t);
111 if (find_latest && latest !=
nullptr) {
114 throw std::runtime_error(
"Unable to find update");
118 target.InsertEcu(client.primary_ecu);
119 if (!client.primary->downloadImage(target).first) {
123 if (client.primary->VerifyTarget(target) != TargetStatus::kGood) {
124 LOG_ERROR <<
"Downloaded target is invalid";
128 auto iresult = client.primary->PackageInstall(target);
129 if (iresult.result_code.num_code == data::ResultCode::Numeric::kNeedCompletion) {
130 LOG_INFO <<
"Update complete. Please reboot the device to activate";
131 client.storage->savePrimaryInstalledVersion(target, InstalledVersionUpdateMode::kPending);
132 }
else if (iresult.result_code.num_code == data::ResultCode::Numeric::kOk) {
133 client.storage->savePrimaryInstalledVersion(target, InstalledVersionUpdateMode::kCurrent);
135 LOG_ERROR <<
"Unable to install update: " << iresult.description;
138 LOG_INFO << iresult.description;
142 static int update_main(
LiteClient &client,
const bpo::variables_map &variables_map) {
145 std::string version(
"latest");
146 if (variables_map.count(
"update-name") > 0) {
147 version = variables_map[
"update-name"].as<std::string>();
149 LOG_INFO <<
"Finding " << version <<
" to update to...";
150 auto target = find_target(client.primary, hwid, version);
151 LOG_INFO <<
"Updating to: " << *target;
152 return do_update(client, *target);
157 int (*main)(
LiteClient &,
const bpo::variables_map &);
159 static std::array<SubCommand, 3> commands{{{
"status", status_main}, {
"list", list_main}, {
"update", update_main}}};
161 void check_info_options(
const bpo::options_description &description,
const bpo::variables_map &vm) {
162 if (vm.count(
"help") != 0 || (vm.count(
"command") == 0 && vm.count(
"version") == 0)) {
163 std::cout << description <<
'\n';
166 if (vm.count(
"version") != 0) {
167 std::cout <<
"Current aktualizr-lite version is: " << aktualizr_version() <<
"\n";
172 bpo::variables_map parse_options(
int argc,
char **argv) {
173 std::string subs(
"Command to execute: ");
174 for (
size_t i = 0; i < commands.size(); i++) {
178 subs += commands[i].name;
180 bpo::options_description description(
"aktualizr-lite command line options");
184 description.add_options()
185 (
"help,h",
"print usage")
186 (
"version,v",
"Current aktualizr-lite version")
187 (
"config,c", bpo::value<std::vector<boost::filesystem::path> >()->composing(),
"configuration file or directory")
188 (
"loglevel", bpo::value<int>(),
"set log level 0-5 (trace, debug, info, warning, error, fatal)")
189 (
"repo-server", bpo::value<std::string>(),
"URL of the Uptane Image repository")
190 (
"primary-ecu-hardware-id", bpo::value<std::string>(),
"hardware ID of Primary ecu")
191 (
"update-name", bpo::value<std::string>(),
"optional name of the update when running \"update\". default=latest")
192 (
"command", bpo::value<std::string>(), subs.c_str());
196 bpo::positional_options_description pos;
197 pos.add(
"command", 1);
199 bpo::variables_map vm;
200 std::vector<std::string> unregistered_options;
202 bpo::basic_parsed_options<char> parsed_options =
203 bpo::command_line_parser(argc, argv).options(description).positional(pos).allow_unregistered().run();
204 bpo::store(parsed_options, vm);
205 check_info_options(description, vm);
207 unregistered_options = bpo::collect_unrecognized(parsed_options.options, bpo::exclude_positional);
208 if (vm.count(
"help") == 0 && !unregistered_options.empty()) {
209 std::cout << description <<
"\n";
212 }
catch (
const bpo::required_option &ex) {
214 std::cout << ex.what() << std::endl << description;
216 }
catch (
const bpo::error &ex) {
217 check_info_options(description, vm);
220 LOG_ERROR <<
"boost command line option error: " << ex.what();
224 std::cout << ex.what() <<
'\n';
234 int main(
int argc,
char *argv[]) {
235 logger_init(isatty(1) == 1);
236 logger_set_threshold(boost::log::trivial::info);
238 bpo::variables_map commandline_map = parse_options(argc, argv);
240 int r = EXIT_FAILURE;
242 if (geteuid() != 0) {
243 LOG_WARNING <<
"\033[31mRunning as non-root and may not work as expected!\033[0m\n";
246 Config config(commandline_map);
247 config.storage.uptane_metadata_path =
utils::BasedPath(config.storage.path /
"metadata");
248 LOG_DEBUG <<
"Current directory: " << boost::filesystem::current_path().string();
250 std::string cmd = commandline_map[
"command"].as<std::string>();
251 for (
size_t i = 0; i < commands.size(); i++) {
252 if (cmd == commands[i].name) {
254 return commands[i].main(client, commandline_map);
257 throw bpo::invalid_option_value(cmd);
259 }
catch (
const std::exception &ex) {
260 LOG_ERROR << ex.what();
Configuration object for an aktualizr instance running on a Primary ECU.
The BasedPath class Can represent an absolute or relative path, only readable through the BasePath::g...