// 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 "lvmd/lvmd.h"

#include <cstdint>
#include <string>
#include <vector>

#include <base/files/file_path.h>
#include <base/strings/stringprintf.h>
#include <base/task/single_thread_task_runner.h>
#include <brillo/errors/error.h>
#include <brillo/errors/error_codes.h>
#include <brillo/strings/string_utils.h>
#include <chromeos/dbus/lvmd/dbus-constants.h>

namespace lvmd {

namespace {

brillo::ErrorPtr CreateError(const base::Location& location,
                             const std::string& code,
                             const std::string& msg) {
  return brillo::Error::Create(location, brillo::errors::dbus::kDomain, code,
                               msg);
}

}  // namespace

Lvmd::Lvmd(std::unique_ptr<brillo::LogicalVolumeManager> lvm)
    : DBusServiceDaemon(kLvmdServiceName), lvm_(std::move(lvm)) {}

bool Lvmd::GetPhysicalVolume(brillo::ErrorPtr* error,
                             const std::string& in_device_path,
                             lvmd::PhysicalVolume* out_physical_volume) {
  auto opt_pv = lvm_->GetPhysicalVolume(base::FilePath(in_device_path));

  if (!opt_pv) {
    *error = CreateError(
        FROM_HERE, kErrorInternal,
        base::StringPrintf("Failed to GetPhysicalVolume on device path (%s)",
                           in_device_path.c_str()));
    return false;
  }

  out_physical_volume->set_device_path(opt_pv->GetPath().value());
  return true;
}

bool Lvmd::GetVolumeGroup(brillo::ErrorPtr* error,
                          const lvmd::PhysicalVolume& in_physical_volume,
                          lvmd::VolumeGroup* out_volume_group) {
  auto device_path = base::FilePath(in_physical_volume.device_path());
  auto pv = brillo::PhysicalVolume(device_path, {});
  auto opt_vg = lvm_->GetVolumeGroup(pv);

  if (!opt_vg) {
    *error =
        CreateError(FROM_HERE, kErrorInternal,
                    base::StringPrintf("Failed to GetVolumeGroup for pv (%s)",
                                       device_path.value().c_str()));
    return false;
  }

  out_volume_group->set_name(opt_vg->GetName());
  return true;
}

bool Lvmd::GetThinpool(brillo::ErrorPtr* error,
                       const lvmd::VolumeGroup& in_volume_group,
                       const std::string& in_thinpool_name,
                       lvmd::Thinpool* out_thinpool) {
  auto vg_name = in_volume_group.name();
  auto vg = brillo::VolumeGroup(vg_name, {});
  auto opt_thinpool = lvm_->GetThinpool(vg, in_thinpool_name);

  if (!opt_thinpool) {
    *error = CreateError(
        FROM_HERE, kErrorInternal,
        base::StringPrintf("Failed to GetThinpool for thinpool (%s) in vg (%s)",
                           in_thinpool_name.c_str(), vg_name.c_str()));
    return false;
  }

  *out_thinpool->mutable_volume_group() = in_volume_group;
  out_thinpool->set_name(opt_thinpool->GetRawName());

  int64_t total_bytes;
  if (!opt_thinpool->GetTotalSpace(&total_bytes)) {
    *error =
        CreateError(FROM_HERE, kErrorInternal,
                    base::StringPrintf(
                        "Failed to GetTotalSpace for thinpool (%s) in vg (%s)",
                        in_thinpool_name.c_str(), vg_name.c_str()));
    return false;
  }
  out_thinpool->set_total_bytes(total_bytes);

  int64_t free_bytes;
  if (!opt_thinpool->GetFreeSpace(&free_bytes)) {
    *error =
        CreateError(FROM_HERE, kErrorInternal,
                    base::StringPrintf(
                        "Failed to GetFreeSpace for thinpool (%s) in vg (%s)",
                        in_thinpool_name.c_str(), vg_name.c_str()));
    return false;
  }
  out_thinpool->set_free_bytes(free_bytes);

  return true;
}

bool Lvmd::ListLogicalVolumes(
    brillo::ErrorPtr* error,
    const lvmd::VolumeGroup& in_volume_group,
    lvmd::LogicalVolumeList* out_logical_volume_list) {
  auto vg = brillo::VolumeGroup(in_volume_group.name(), {});
  auto lvs = lvm_->ListLogicalVolumes(vg);

  for (auto& lv : lvs) {
    auto* new_lv = out_logical_volume_list->add_logical_volume();
    *new_lv->mutable_volume_group() = in_volume_group;
    new_lv->set_name(lv.GetRawName());
    // Iteration cannot be const in order to call `GetPath()`.
    new_lv->set_path(lv.GetPath().value());
  }

  return true;
}

bool Lvmd::GetLogicalVolume(brillo::ErrorPtr* error,
                            const lvmd::VolumeGroup& in_volume_group,
                            const std::string& in_logical_volume_name,
                            lvmd::LogicalVolume* out_logical_volume) {
  auto vg_name = in_volume_group.name();
  auto vg = brillo::VolumeGroup(vg_name, {});
  auto opt_lv = lvm_->GetLogicalVolume(vg, in_logical_volume_name);

  if (!opt_lv) {
    *error = CreateError(
        FROM_HERE, kErrorInternal,
        base::StringPrintf("Failed to GetLogicalVolume for lv (%s) in vg (%s)",
                           in_logical_volume_name.c_str(), vg_name.c_str()));
    return false;
  }

  *out_logical_volume->mutable_volume_group() = in_volume_group;
  out_logical_volume->set_name(opt_lv->GetRawName());
  out_logical_volume->set_path(opt_lv->GetPath().value());
  if (auto size = opt_lv->GetSize()) {
    out_logical_volume->set_size(*size);
  } else {
    out_logical_volume->set_size(kErrorSize);
  }
  return true;
}

bool Lvmd::CreateLogicalVolume(
    brillo::ErrorPtr* error,
    const lvmd::Thinpool& in_thinpool,
    const lvmd::LogicalVolumeConfiguration& in_logical_volume_configuration,
    lvmd::LogicalVolume* out_logical_volume) {
  auto vg_name = in_thinpool.volume_group().name();
  auto vg = brillo::VolumeGroup(vg_name, {});

  auto thinpool_name = in_thinpool.name();
  auto thinpool = brillo::Thinpool(thinpool_name, vg_name, {});

  base::Value::Dict config;
  auto lv_name = in_logical_volume_configuration.name();
  config.Set("name", lv_name);
  config.Set("size", brillo::string_utils::ToString(
                         in_logical_volume_configuration.size()));

  auto opt_lv = lvm_->CreateLogicalVolume(vg, thinpool, config);

  if (!opt_lv) {
    *error =
        CreateError(FROM_HERE, kErrorInternal,
                    base::StringPrintf("Failed to CreateLogicalVolume for lv "
                                       "name (%s) in thinpool (%s) in vg (%s)",
                                       lv_name.c_str(), thinpool_name.c_str(),
                                       vg_name.c_str()));
    return false;
  }

  *out_logical_volume->mutable_volume_group() = in_thinpool.volume_group();
  out_logical_volume->set_name(opt_lv->GetRawName());
  out_logical_volume->set_path(opt_lv->GetPath().value());
  return true;
}

bool Lvmd::CreateLogicalVolumes(
    brillo::ErrorPtr* error,
    const lvmd::CreateLogicalVolumesRequest& in_request,
    lvmd::CreateLogicalVolumesResponse* out_response) {
  std::vector<std::string> failed_lvs;
  for (const auto& info : in_request.logical_volume_infos()) {
    const auto& thinpool = info.thinpool();
    const auto& lv_config = info.lv_config();

    brillo::ErrorPtr tmp_err;
    lvmd::LogicalVolume lv;
    if (!CreateLogicalVolume(&tmp_err, thinpool, lv_config, &lv)) {
      failed_lvs.push_back(base::StringPrintf(
          "lv name (%s) thinpool (%s) vg (%s) size (%ld)",
          lv_config.name().c_str(), thinpool.name().c_str(),
          thinpool.volume_group().name().c_str(), lv_config.size()));
      // Continue looping to handle remaining logical volumes to create.
      continue;
    }
    // Only add successfully created logical volumes into the response.
    auto* lv_added =
        out_response->mutable_logical_volume_list()->add_logical_volume();
    lv_added->Swap(&lv);
  }

  if (!failed_lvs.empty()) {
    *error = CreateError(
        FROM_HERE, kErrorInternal,
        base::StringPrintf("Failed to CreateLogicalVolumes: %s",
                           base::JoinString(failed_lvs, ", ").c_str()));
    return false;
  }
  return true;
}

bool Lvmd::RemoveLogicalVolume(brillo::ErrorPtr* error,
                               const lvmd::LogicalVolume& in_logical_volume) {
  auto vg_name = in_logical_volume.volume_group().name();
  auto vg = brillo::VolumeGroup(vg_name, {});

  std::string lv_name = in_logical_volume.name();

  if (!lvm_->RemoveLogicalVolume(vg, lv_name)) {
    *error =
        CreateError(FROM_HERE, kErrorInternal,
                    base::StringPrintf("Failed to RemoveLogicalVolume for lv "
                                       "name (%s) in vg (%s)",
                                       lv_name.c_str(), vg_name.c_str()));
    return false;
  }

  return true;
}

bool Lvmd::RemoveLogicalVolumes(
    brillo::ErrorPtr* error,
    const lvmd::RemoveLogicalVolumesRequest& in_request,
    lvmd::RemoveLogicalVolumesResponse* out_response) {
  out_response->clear_logical_volume_list();
  for (const auto& lv : in_request.logical_volume_list().logical_volume()) {
    brillo::ErrorPtr tmp_err;
    if (!RemoveLogicalVolume(&tmp_err, lv)) {
      // Only add failed to remove logical volumes into the response.
      // This will allow users to act on the logical volumes easier.
      auto* lv_added =
          out_response->mutable_logical_volume_list()->add_logical_volume();
      lv_added->CopyFrom(lv);
    }
  }

  if (out_response->has_logical_volume_list()) {
    std::vector<std::string> failed_lvs(
        out_response->logical_volume_list().logical_volume_size());
    for (const auto& lv :
         out_response->logical_volume_list().logical_volume()) {
      failed_lvs.push_back(lv.name());
    }
    *error = CreateError(
        FROM_HERE, kErrorInternal,
        base::StringPrintf("Failed to RemoveLogicalVolumes: %s",
                           base::JoinString(failed_lvs, ", ").c_str()));
    return false;
  }
  return true;
}

bool Lvmd::ToggleLogicalVolumeActivation(
    brillo::ErrorPtr* error,
    const lvmd::LogicalVolume& in_logical_volume,
    bool activate) {
  auto vg_name = in_logical_volume.volume_group().name();
  auto vg = brillo::VolumeGroup(vg_name, {});

  std::string lv_name = in_logical_volume.name();
  auto opt_lv = lvm_->GetLogicalVolume(vg, lv_name);

  if (!opt_lv) {
    *error = CreateError(
        FROM_HERE, kErrorInternal,
        base::StringPrintf("Failed to GetLogicalVolume for lv (%s) in vg (%s)",
                           lv_name.c_str(), vg_name.c_str()));
    return false;
  }

  if (activate) {
    if (!opt_lv->Activate()) {
      *error =
          CreateError(FROM_HERE, kErrorInternal,
                      base::StringPrintf("Failed to activate for lv "
                                         "name (%s) in vg (%s)",
                                         lv_name.c_str(), vg_name.c_str()));
      return false;
    }
  } else if (!opt_lv->Deactivate()) {
    *error = CreateError(FROM_HERE, kErrorInternal,
                         base::StringPrintf("Failed to deactivate for lv "
                                            "name (%s) in vg (%s)",
                                            lv_name.c_str(), vg_name.c_str()));
    return false;
  }

  return true;
}

bool Lvmd::ResizeLogicalVolume(brillo::ErrorPtr* error,
                               const lvmd::LogicalVolume& in_logical_volume,
                               int64_t size) {
  auto vg_name = in_logical_volume.volume_group().name();
  auto vg = brillo::VolumeGroup(vg_name, {});

  std::string lv_name = in_logical_volume.name();
  auto opt_lv = lvm_->GetLogicalVolume(vg, lv_name);

  if (!opt_lv) {
    *error = CreateError(
        FROM_HERE, kErrorInternal,
        base::StringPrintf("Failed to GetLogicalVolume for lv (%s) in vg (%s)",
                           lv_name.c_str(), vg_name.c_str()));
    return false;
  }

  auto current_size = opt_lv->GetSize();
  auto blk_size = opt_lv->GetBlockSize();
  if (!current_size || !blk_size) {
    LOG(WARNING) << "Unable to check existing size, resizing regardless.";
  } else {
    // No need to resize if the size difference is less than one block since the
    // LVM tool automatically rounds up to the same size.
    if (auto size_delta = *current_size - size;
        size_delta >= 0 && size_delta < *blk_size) {
      LOG(WARNING) << "The size would not change, skip resizing.";
      return true;
    }
  }
  if (!opt_lv->Resize(size)) {
    *error = CreateError(FROM_HERE, kErrorInternal,
                         base::StringPrintf("Failed to resize lv "
                                            "name (%s) in vg (%s)",
                                            lv_name.c_str(), vg_name.c_str()));
    return false;
  }
  return true;
}

int Lvmd::OnInit() {
  int return_code = brillo::DBusServiceDaemon::OnInit();
  if (return_code != EX_OK)
    return return_code;

  PostponeShutdown();
  return EX_OK;
}

void Lvmd::RegisterDBusObjectsAsync(
    brillo::dbus_utils::AsyncEventSequencer* sequencer) {
  dbus_object_.reset(new brillo::dbus_utils::DBusObject(
      nullptr, bus_, org::chromium::LvmdAdaptor::GetObjectPath()));

  dbus_adaptor_.RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(
      sequencer->GetHandler("RegisterAsync() failed.", true));
}

void Lvmd::OnShutdown(int* return_code) {
  brillo::DBusServiceDaemon::OnShutdown(return_code);
}

void Lvmd::PostponeShutdown() {
  shutdown_callback_.Reset(
      base::BindRepeating(&brillo::Daemon::Quit, weak_factory_.GetWeakPtr()));
  base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE, shutdown_callback_.callback(), kShutdownTimeout);
}

}  // namespace lvmd
