// Copyright 2020 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.

#include "vm_tools/concierge/vm_base_impl.h"

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/notreached.h>

#include "vm_tools/concierge/vm_util.h"

namespace vm_tools {
namespace concierge {

VmBaseImpl::VmBaseImpl(
    std::unique_ptr<patchpanel::Client> network_client,
    std::unique_ptr<SeneschalServerProxy> seneschal_server_proxy,
    base::FilePath runtime_dir)
    : VmBaseImpl(std::move(network_client),
                 0 /* vsock_cid */,
                 std::move(seneschal_server_proxy),
                 "",
                 std::move(runtime_dir)) {}

VmBaseImpl::VmBaseImpl(
    std::unique_ptr<patchpanel::Client> network_client,
    uint32_t vsock_cid,
    std::unique_ptr<SeneschalServerProxy> seneschal_server_proxy,
    std::string cros_vm_socket,
    base::FilePath runtime_dir)
    : network_client_(std::move(network_client)),
      seneschal_server_proxy_(std::move(seneschal_server_proxy)),
      vsock_cid_(vsock_cid),
      cros_vm_socket_(std::move(cros_vm_socket)) {
  // Take ownership of the runtime directory.
  CHECK(base::DirectoryExists(runtime_dir));
  CHECK(runtime_dir_.Set(runtime_dir));
}

base::Optional<BalloonStats> VmBaseImpl::GetBalloonStats() {
  return vm_tools::concierge::GetBalloonStats(GetVmSocketPath());
}

void VmBaseImpl::SetBalloonSize(int64_t byte_size) {
  if (byte_size < 0) {
    LOG(ERROR) << "Skipping setting a negative balloon size: " << byte_size;
  }
  vm_tools::concierge::RunCrosvmCommand(
      {"balloon", std::to_string(byte_size), GetVmSocketPath()});
}

const std::unique_ptr<BalloonPolicyInterface>& VmBaseImpl::GetBalloonPolicy(
    const MemoryMargins& margins, const std::string& vm) {
  if (!balloon_policy_) {
    balloon_policy_ = std::make_unique<BalanceAvailableBalloonPolicy>(
        margins.critical, 0, vm);
  }
  return balloon_policy_;
}

bool VmBaseImpl::AttachUsbDevice(uint8_t bus,
                                 uint8_t addr,
                                 uint16_t vid,
                                 uint16_t pid,
                                 int fd,
                                 UsbControlResponse* response) {
  return vm_tools::concierge::AttachUsbDevice(GetVmSocketPath(), bus, addr, vid,
                                              pid, fd, response);
}

bool VmBaseImpl::DetachUsbDevice(uint8_t port, UsbControlResponse* response) {
  return vm_tools::concierge::DetachUsbDevice(GetVmSocketPath(), port,
                                              response);
}

bool VmBaseImpl::ListUsbDevice(std::vector<UsbDevice>* devices) {
  return vm_tools::concierge::ListUsbDevice(GetVmSocketPath(), devices);
}

// static
bool VmBaseImpl::SetVmCpuRestriction(CpuRestrictionState cpu_restriction_state,
                                     const char* CpuCgroup) {
  int cpu_shares = 1024;  // TODO(sonnyrao): Adjust |cpu_shares|.
  switch (cpu_restriction_state) {
    case CPU_RESTRICTION_FOREGROUND:
      break;
    case CPU_RESTRICTION_BACKGROUND:
      cpu_shares = 64;
      break;
    default:
      NOTREACHED();
  }
  return UpdateCpuShares(base::FilePath(CpuCgroup), cpu_shares);
}

bool VmBaseImpl::StartProcess(base::StringPairs args) {
  std::string command_line_for_log{};

  for (std::pair<std::string, std::string>& arg : args) {
    command_line_for_log += arg.first;
    command_line_for_log += " ";

    process_.AddArg(std::move(arg.first));
    if (!arg.second.empty()) {
      command_line_for_log += arg.second;
      command_line_for_log += " ";
      process_.AddArg(std::move(arg.second));
    }
  }
  LOG(INFO) << "Invoking VM: " << command_line_for_log;
  if (!process_.Start()) {
    PLOG(ERROR) << "Failed to start VM process";
    return false;
  }

  return true;
}

std::string VmBaseImpl::GetVmSocketPath() const {
  return runtime_dir_.GetPath().Append(cros_vm_socket_).value();
}

void VmBaseImpl::RunCrosvmCommand(const std::string& command) const {
  vm_tools::concierge::RunCrosvmCommand(std::move(command), GetVmSocketPath());
}

uint32_t VmBaseImpl::seneschal_server_handle() const {
  if (seneschal_server_proxy_)
    return seneschal_server_proxy_->handle();

  return 0;
}

void VmBaseImpl::HandleSuspendImminent() {
  RunCrosvmCommand("suspend");
}

void VmBaseImpl::HandleSuspendDone() {
  RunCrosvmCommand("resume");
}

void VmBaseImpl::MakeRtVcpu() {
  RunCrosvmCommand("make_rt");
}

}  // namespace concierge
}  // namespace vm_tools
