blob: 52a87e88bc99d7ba4d1fa5434219475171f54a38 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "debugd/src/upstart_tools.h"
#include <utility>
#include <base/functional/callback_helpers.h>
#include <brillo/dbus/dbus_method_invoker.h>
#include <debugd/src/error_utils.h>
#include <dbus/message.h>
#include <dbus/object_proxy.h>
namespace debugd {
namespace {
constexpr char kUpstartToolsErrorString[] =
"org.chromium.debugd.error.UpstartTools";
constexpr char kUpstartServiceName[] = "com.ubuntu.Upstart";
constexpr char kUpstartServicePath[] = "/com/ubuntu/Upstart";
constexpr char kUpstartJobInterface[] = "com.ubuntu.Upstart0_6.Job";
constexpr char kGetInstanceMethod[] = "GetInstance";
constexpr char kRestartMethod[] = "Restart";
constexpr char kStartMethod[] = "Start";
constexpr char kStopMethod[] = "Stop";
constexpr char kUpstartJobPath[] = "/com/ubuntu/Upstart/jobs/";
} // namespace
UpstartToolsImpl::UpstartToolsImpl(const scoped_refptr<dbus::Bus>& bus)
: bus_(bus) {
upstart_proxy_ = bus_->GetObjectProxy(kUpstartServiceName,
dbus::ObjectPath(kUpstartServicePath));
}
bool UpstartToolsImpl::IsJobRunning(const std::string& job_name,
brillo::ErrorPtr* error) {
return CallJobMethod(job_name, kGetInstanceMethod, {}, error);
}
bool UpstartToolsImpl::RestartJob(const std::string& job_name,
brillo::ErrorPtr* error) {
return CallJobMethod(job_name, kRestartMethod, {}, error);
}
bool UpstartToolsImpl::StartJob(const std::string& job_name,
brillo::ErrorPtr* error) {
if (IsJobRunning(job_name, error)) {
return true;
}
return CallJobMethod(job_name, kStartMethod, {}, error);
}
bool UpstartToolsImpl::StopJob(const std::string& job_name,
brillo::ErrorPtr* error) {
if (!IsJobRunning(job_name, error)) {
return true;
}
return CallJobMethod(job_name, kStopMethod, {}, error);
}
bool UpstartToolsImpl::CallJobMethod(
const std::string& job_name,
const std::string& method,
const std::vector<std::string>& environment,
brillo::ErrorPtr* error) {
dbus::ObjectProxy* job_proxy = bus_->GetObjectProxy(
kUpstartServiceName, dbus::ObjectPath(kUpstartJobPath + job_name));
if (job_proxy == nullptr) {
DEBUGD_ADD_ERROR_FMT(error, kUpstartToolsErrorString,
"Failed to get job proxy for %s", job_name.c_str());
return false;
}
dbus::MethodCall method_call(kUpstartJobInterface, method);
dbus::MessageWriter writer(&method_call);
writer.AppendArrayOfStrings(environment);
writer.AppendBool(true /* wait for response */);
base::expected<std::unique_ptr<dbus::Response>, dbus::Error> method_result =
job_proxy->CallMethodAndBlock(&method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
if (!method_result.has_value()) {
DEBUGD_ADD_ERROR_FMT(error, kUpstartToolsErrorString,
"%s job (%s) request got error.", method.c_str(),
job_name.c_str());
return false;
}
std::unique_ptr<dbus::Response> method_response =
std::move(method_result.value());
if (!method_response) {
DEBUGD_ADD_ERROR_FMT(error, kUpstartToolsErrorString,
"%s job (%s) request had no response.", method.c_str(),
job_name.c_str());
return false;
}
dbus::MessageReader reader(method_response.get());
dbus::ObjectPath job_path;
if (!reader.PopObjectPath(&job_path)) {
DEBUGD_ADD_ERROR_FMT(error, kUpstartToolsErrorString,
"Failed to parse %s job (%s) response", method.c_str(),
job_name.c_str());
return false;
}
return true;
}
} // namespace debugd