AU: Beginnings of dbus support. The AU will be a daemon that runs as root. Non-root will communicate via dbus with the updater to do things such as: query status, request forced or full updates, etc. New files for dbus: UpdateEngine.conf - security configuration dbus_constants.h - common constants dbus_service.* - The object exposed over dbus org.chromium.UpdateEngine.service - the dbus service file udpate_attempter.* - Refactored this out of main.cc update_engine_client.cc - Simple command line utility to interact with Update Engine over dbus. Whereas Update Engine runs as root, this tool runs as non-root user. Review URL: http://codereview.chromium.org/1733013
diff --git a/main.cc b/main.cc index cbd6e44..a796a98 100644 --- a/main.cc +++ b/main.cc
@@ -1,26 +1,24 @@ -// Copyright (c) 2009 The Chromium OS Authors. All rights reserved. +// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// TODO(adlr): get rid of commented out lines or comment them back in. -// Look for "// re-add" next to those comments. - #include <string> #include <tr1/memory> #include <vector> #include <gflags/gflags.h> #include <glib.h> +#include "base/command_line.h" #include "chromeos/obsolete_logging.h" -#include "update_engine/action_processor.h" -#include "update_engine/download_action.h" -#include "update_engine/filesystem_copier_action.h" -// #include "update_engine/install_action.h" // re-add -#include "update_engine/libcurl_http_fetcher.h" -#include "update_engine/omaha_request_prep_action.h" -#include "update_engine/omaha_response_handler_action.h" -#include "update_engine/postinstall_runner_action.h" -#include "update_engine/set_bootable_flag_action.h" -#include "update_engine/update_check_action.h" +#include "update_engine/dbus_constants.h" +#include "update_engine/dbus_service.h" +#include "update_engine/update_attempter.h" + +extern "C" { +#include "update_engine/update_engine.dbusserver.h" +} + +DEFINE_bool(logtostderr, false, + "Write logs to stderr instead of to a file in log_dir."); using std::string; using std::tr1::shared_ptr; @@ -28,121 +26,64 @@ namespace chromeos_update_engine { -class UpdateAttempter : public ActionProcessorDelegate { - public: - UpdateAttempter(GMainLoop *loop) - : full_update_(false), - loop_(loop) {} - void Update(bool force_full_update); - - // Delegate method: - void ProcessingDone(const ActionProcessor* processor, bool success); - private: - bool full_update_; - vector<shared_ptr<AbstractAction> > actions_; - ActionProcessor processor_; - GMainLoop *loop_; +gboolean SetupInMainLoop(void* arg) { + // TODO(adlr): Tell update_attempter to start working. + // Comment this in for that: + //UpdateAttempter* update_attempter = reinterpret_cast<UpdateAttempter*>(arg); - // pointer to the OmahaResponseHandlerAction in the actions_ vector; - shared_ptr<OmahaResponseHandlerAction> response_handler_action_; - DISALLOW_COPY_AND_ASSIGN(UpdateAttempter); -}; - -// Returns true on success. If there was no update available, that's still -// success. -// If force_full is true, try to force a full update. -void UpdateAttempter::Update(bool force_full_update) { - full_update_ = force_full_update; - CHECK(!processor_.IsRunning()); - processor_.set_delegate(this); - - // Actions: - shared_ptr<OmahaRequestPrepAction> request_prep_action( - new OmahaRequestPrepAction(force_full_update)); - shared_ptr<UpdateCheckAction> update_check_action( - new UpdateCheckAction(new LibcurlHttpFetcher)); - shared_ptr<OmahaResponseHandlerAction> response_handler_action( - new OmahaResponseHandlerAction); - shared_ptr<FilesystemCopierAction> filesystem_copier_action( - new FilesystemCopierAction); - shared_ptr<DownloadAction> download_action( - new DownloadAction(new LibcurlHttpFetcher)); - // shared_ptr<InstallAction> install_action( // re-add - // new InstallAction); - shared_ptr<PostinstallRunnerAction> postinstall_runner_action( - new PostinstallRunnerAction); - shared_ptr<SetBootableFlagAction> set_bootable_flag_action( - new SetBootableFlagAction); - - response_handler_action_ = response_handler_action; - - actions_.push_back(shared_ptr<AbstractAction>(request_prep_action)); - actions_.push_back(shared_ptr<AbstractAction>(update_check_action)); - actions_.push_back(shared_ptr<AbstractAction>(response_handler_action)); - actions_.push_back(shared_ptr<AbstractAction>(filesystem_copier_action)); - actions_.push_back(shared_ptr<AbstractAction>(download_action)); - // actions_.push_back(shared_ptr<AbstractAction>(install_action)); // re-add - actions_.push_back(shared_ptr<AbstractAction>(postinstall_runner_action)); - actions_.push_back(shared_ptr<AbstractAction>(set_bootable_flag_action)); - - // Enqueue the actions - for (vector<shared_ptr<AbstractAction> >::iterator it = actions_.begin(); - it != actions_.end(); ++it) { - processor_.EnqueueAction(it->get()); - } - - // Bond them together. We have to use the leaf-types when calling - // BondActions(). - BondActions(request_prep_action.get(), update_check_action.get()); - BondActions(update_check_action.get(), response_handler_action.get()); - BondActions(response_handler_action.get(), filesystem_copier_action.get()); - BondActions(filesystem_copier_action.get(), download_action.get()); - // BondActions(download_action.get(), install_action.get()); // re-add - // BondActions(install_action.get(), postinstall_runner_action.get()); - BondActions(postinstall_runner_action.get(), set_bootable_flag_action.get()); - - processor_.StartProcessing(); -} - -void UpdateAttempter::ProcessingDone(const ActionProcessor* processor, - bool success) { - CHECK(response_handler_action_); - if (response_handler_action_->GotNoUpdateResponse()) { - // All done. - g_main_loop_quit(loop_); - return; - } - if (!success) { - if (!full_update_) { - LOG(ERROR) << "Update failed. Attempting full update"; - actions_.clear(); - response_handler_action_.reset(); - Update(true); - return; - } else { - LOG(ERROR) << "Full update failed. Aborting"; - } - } - g_main_loop_quit(loop_); -} - -gboolean UpdateInMainLoop(void* arg) { - UpdateAttempter* update_attempter = reinterpret_cast<UpdateAttempter*>(arg); - update_attempter->Update(false); return FALSE; // Don't call this callback function again } +void SetupDbusService(UpdateEngineService* service) { + DBusGConnection *bus; + DBusGProxy *proxy; + GError *error = NULL; + + bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error); + if (!bus) { + LOG(FATAL) << "Failed to get bus"; + } + proxy = dbus_g_proxy_new_for_name(bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + + guint32 request_name_ret; + if (!org_freedesktop_DBus_request_name(proxy, + kUpdateEngineServiceName, + 0, + &request_name_ret, + &error)) { + LOG(FATAL) << "Failed to get name: " << error->message; + } + if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_warning("Got result code %u from requesting name", request_name_ret); + g_error_free(error); + exit(1); + LOG(FATAL) << "Got result code " << request_name_ret + << " from requesting name, but expected " + << DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; + } + dbus_g_connection_register_g_object(bus, + "/org/chromium/UpdateEngine", + G_OBJECT(service)); +} + } // namespace chromeos_update_engine #include "update_engine/subprocess.h" int main(int argc, char** argv) { + ::g_type_init(); g_thread_init(NULL); + dbus_g_thread_init(); chromeos_update_engine::Subprocess::Init(); google::ParseCommandLineFlags(&argc, &argv, true); - // TODO(adlr): figure out log file - logging::InitLogging("", - logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG, + CommandLine::Init(argc, argv); + logging::InitLogging("logfile.txt", + FLAGS_logtostderr ? + logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG : + logging::LOG_ONLY_TO_FILE, logging::DONT_LOCK_LOG_FILE, logging::APPEND_TO_OLD_LOG_FILE); LOG(INFO) << "Chrome OS Update Engine starting"; @@ -150,13 +91,26 @@ // Create the single GMainLoop GMainLoop *loop = g_main_loop_new(g_main_context_default(), FALSE); + // Create the update attempter: chromeos_update_engine::UpdateAttempter update_attempter(loop); - g_timeout_add(0, &chromeos_update_engine::UpdateInMainLoop, - &update_attempter); + // Create the dbus service object: + dbus_g_object_type_install_info(UPDATE_ENGINE_TYPE_SERVICE, + &dbus_glib_update_engine_service_object_info); + UpdateEngineService* service = + UPDATE_ENGINE_SERVICE(g_object_new(UPDATE_ENGINE_TYPE_SERVICE, NULL)); + service->update_attempter_ = &update_attempter; + chromeos_update_engine::SetupDbusService(service); + // Set up init routine to run within the main loop. + g_timeout_add(0, &chromeos_update_engine::SetupInMainLoop, &update_attempter); + + // Run the main loop until exit time: g_main_loop_run(loop); + + // Cleanup: g_main_loop_unref(loop); + g_object_unref(G_OBJECT(service)); LOG(INFO) << "Chrome OS Update Engine terminating"; return 0;