// 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 <sys/socket.h>
#include <sys/types.h>

#include <string>

#include <base/files/file_util.h>
#include <base/guid.h>

#include "vm_tools/concierge/plugin_vm.h"
#include "vm_tools/concierge/plugin_vm_helper.h"
#include "vm_tools/concierge/service.h"
#include "vm_tools/concierge/shared_data.h"
#include "vm_tools/concierge/vmplugin_dispatcher_interface.h"

namespace vm_tools {
namespace concierge {

namespace {

bool GetPluginStatefulDirectory(const std::string& vm_id,
                                const std::string& cryptohome_id,
                                bool create,
                                base::FilePath* path_out) {
  return GetPluginDirectory(base::FilePath(kCryptohomeRoot)
                                .Append(kPluginVmDir)
                                .Append(cryptohome_id),
                            "pvm", vm_id, create, path_out);
}

bool GetPluginRuntimeDirectory(const std::string& vm_id,
                               base::ScopedTempDir* runtime_dir_out) {
  base::FilePath path;
  if (GetPluginDirectory(base::FilePath("/run/pvm"), "", vm_id,
                         true /*create */, &path)) {
    // Take ownership of directory
    CHECK(runtime_dir_out->Set(path));
    return true;
  }

  return false;
}

bool GetPluginRootDirectory(const std::string& vm_id,
                            base::ScopedTempDir* root_dir_out) {
  base::FilePath path;
  if (!base::CreateTemporaryDirInDir(base::FilePath(kRuntimeDir), "vm.",
                                     &path)) {
    PLOG(ERROR) << "Unable to create root directory for VM";
    return false;
  }

  // Take ownership of directory
  CHECK(root_dir_out->Set(path));
  return true;
}

bool CreatePluginRootHierarchy(const base::FilePath& root_path) {
  base::FilePath etc_dir(root_path.Append("etc"));
  base::File::Error dir_error;
  if (!CreateDirectoryAndGetError(etc_dir, &dir_error)) {
    LOG(ERROR) << "Unable to create /etc in root directory for VM "
               << base::File::ErrorToString(dir_error);
    return false;
  }

  // Note that this will be dangling (or rather point to concierge's timezone
  // instance) until crosvm bind mounts /var/lib/timezone and
  // /usr/share/zoneinfo into plugin jail.
  if (!base::CreateSymbolicLink(base::FilePath("/var/lib/timezone/localtime"),
                                etc_dir.Append("localtime"))) {
    PLOG(ERROR) << "Unable to create /etc/localtime symlink";
    return false;
  }

  return true;
}

bool GetPlugin9PSocketPath(const std::string& vm_id, base::FilePath* path_out) {
  base::FilePath runtime_dir;
  if (!GetPluginDirectory(base::FilePath("/run/pvm"), "", vm_id,
                          true /* create */, &runtime_dir)) {
    LOG(ERROR) << "Unable to get runtime directory for 9P socket";
    return false;
  }

  *path_out = runtime_dir.Append("9p.sock");
  return true;
}

}  // namespace

std::unique_ptr<dbus::Response> Service::StartPluginVm(
    dbus::MethodCall* method_call) {
  LOG(INFO) << "Received StartPluginVm request";

  std::unique_ptr<dbus::Response> dbus_response(
      dbus::Response::FromMethodCall(method_call));
  dbus::MessageReader reader(method_call);
  dbus::MessageWriter writer(dbus_response.get());
  StartPluginVmRequest request;
  StartVmResponse response;
  auto helper_result = StartVmHelper<StartPluginVmRequest>(
      method_call, &reader, &writer, true /* allow_zero_cpus */);
  if (!helper_result) {
    return dbus_response;
  }
  std::tie(request, response) = *helper_result;
  VmInfo* vm_info = response.mutable_vm_info();
  vm_info->set_vm_type(VmInfo::PLUGIN_VM);

  // Get the stateful directory.
  base::FilePath stateful_dir;
  if (!GetPluginStatefulDirectory(request.name(), request.owner_id(),
                                  true /* create */, &stateful_dir)) {
    LOG(ERROR) << "Unable to create stateful directory for VM";

    response.set_failure_reason("Unable to create stateful directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Get the directory for ISO images.
  base::FilePath iso_dir;
  if (!GetPluginIsoDirectory(request.name(), request.owner_id(),
                             true /* create */, &iso_dir)) {
    LOG(ERROR) << "Unable to create directory holding ISOs for VM";

    response.set_failure_reason("Unable to create ISO directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Create the runtime directory.
  base::ScopedTempDir runtime_dir;
  if (!GetPluginRuntimeDirectory(request.name(), &runtime_dir)) {
    LOG(ERROR) << "Unable to create runtime directory for VM";

    response.set_failure_reason("Unable to create runtime directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Create the root directory.
  base::ScopedTempDir root_dir;
  if (!GetPluginRootDirectory(request.name(), &root_dir)) {
    LOG(ERROR) << "Unable to create runtime directory for VM";

    response.set_failure_reason("Unable to create runtime directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  if (!CreatePluginRootHierarchy(root_dir.GetPath())) {
    response.set_failure_reason("Unable to create plugin root hierarchy");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  if (!PluginVm::WriteResolvConf(root_dir.GetPath().Append("etc"), nameservers_,
                                 search_domains_)) {
    LOG(ERROR) << "Unable to seed resolv.conf for the Plugin VM";

    response.set_failure_reason("Unable to seed resolv.conf");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Generate the token used by cicerone to identify the VM and write it to
  // a VM specific directory that gets mounted into the VM.
  std::string vm_token = base::GenerateGUID();
  if (base::WriteFile(runtime_dir.GetPath().Append("cicerone.token"),
                      vm_token.c_str(),
                      vm_token.length()) != vm_token.length()) {
    PLOG(ERROR) << "Failure writing out cicerone token to file";

    response.set_failure_reason("Unable to set cicerone token");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  base::FilePath p9_socket_path;
  if (!GetPlugin9PSocketPath(request.name(), &p9_socket_path)) {
    response.set_failure_reason("Internal error: unable to get 9P directory");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  base::ScopedFD p9_socket =
      PluginVm::CreateUnixSocket(p9_socket_path, SOCK_STREAM);
  if (!p9_socket.is_valid()) {
    LOG(ERROR) << "Failed creating 9P socket for file sharing";

    response.set_failure_reason("Internal error: unable to create 9P socket");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  std::unique_ptr<patchpanel::Client> network_client =
      patchpanel::Client::New(bus_);
  if (!network_client) {
    LOG(ERROR) << "Unable to open networking service client";

    response.set_failure_reason("Unable to open network service client");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  std::unique_ptr<SeneschalServerProxy> seneschal_server_proxy =
      SeneschalServerProxy::CreateFdProxy(bus_, seneschal_service_proxy_,
                                          p9_socket);
  if (!seneschal_server_proxy) {
    LOG(ERROR) << "Unable to start shared directory server";

    response.set_failure_reason("Unable to start shared directory server");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  // Build the plugin params.
  std::vector<std::string> params(
      std::make_move_iterator(request.mutable_params()->begin()),
      std::make_move_iterator(request.mutable_params()->end()));

  // Now start the VM.
  VmId vm_id(request.owner_id(), request.name());
  SendVmStartingUpSignal(vm_id, *vm_info);

  VmBuilder vm_builder;
  vm_builder.SetCpus(request.cpus());
  for (auto& param : params) {
    // Because additional parameters may start with a '--', we should use
    // --params=<Param> instead of --params <Param> to make explicit <Param>
    // is a parameter for the plugin rather than just another parameter to
    // the crosvm process.
    vm_builder.AppendCustomParam(std::string("--params=") + param, "");
  }

  auto vm = PluginVm::Create(
      vm_id, std::move(stateful_dir), std::move(iso_dir), root_dir.Take(),
      runtime_dir.Take(), std::move(network_client), request.subnet_index(),
      request.net_options().enable_vnet_hdr(), bus_,
      std::move(seneschal_server_proxy), vm_permission_service_proxy_,
      vmplugin_service_proxy_, std::move(vm_builder));
  if (!vm) {
    LOG(ERROR) << "Unable to start VM";
    response.set_failure_reason("Unable to start VM");
    writer.AppendProtoAsArrayOfBytes(response);
    return dbus_response;
  }

  VmInterface::Info info = vm->GetInfo();

  vm_info->set_ipv4_address(info.ipv4_address);
  vm_info->set_pid(info.pid);
  vm_info->set_cid(info.cid);
  vm_info->set_seneschal_server_handle(info.seneschal_server_handle);
  vm_info->set_permission_token(info.permission_token);
  switch (info.status) {
    case VmInterface::Status::STARTING: {
      response.set_status(VM_STATUS_STARTING);
      break;
    }
    case VmInterface::Status::RUNNING: {
      response.set_status(VM_STATUS_RUNNING);
      break;
    }
    default: {
      response.set_status(VM_STATUS_UNKNOWN);
      break;
    }
  }
  response.set_success(true);
  writer.AppendProtoAsArrayOfBytes(response);

  NotifyCiceroneOfVmStarted(vm_id, 0 /* cid */, info.pid, std::move(vm_token));
  SendVmStartedSignal(vm_id, *vm_info, response.status());

  vms_[vm_id] = std::move(vm);
  return dbus_response;
}

bool Service::RenamePluginVm(const std::string& owner_id,
                             const std::string& old_name,
                             const std::string& new_name,
                             std::string* failure_reason) {
  base::FilePath old_dir;
  if (!GetPluginStatefulDirectory(old_name, owner_id, false /* create */,
                                  &old_dir)) {
    *failure_reason = "unable to determine current VM directory";
    return false;
  }

  base::FilePath old_iso_dir;
  if (!GetPluginIsoDirectory(old_name, owner_id, false /* create */,
                             &old_iso_dir)) {
    *failure_reason = "unable to determine current VM ISO directory";
    return false;
  }

  base::FilePath new_dir;
  if (!GetPluginStatefulDirectory(new_name, owner_id, false /* create */,
                                  &new_dir)) {
    *failure_reason = "unable to determine new VM directory";
    return false;
  }

  base::FilePath new_iso_dir;
  if (!GetPluginIsoDirectory(new_name, owner_id, false /* create */,
                             &new_iso_dir)) {
    *failure_reason = "unable to determine new VM ISO directory";
    return false;
  }

  VmId old_id(owner_id, old_name);
  bool registered;
  if (!pvm::dispatcher::IsVmRegistered(bus_, vmplugin_service_proxy_, old_id,
                                       &registered)) {
    *failure_reason = "failed to check Plugin VM registration status";
    return false;
  }

  // This is unexpected: the VM is not registered. Better leave it alone.
  if (!registered) {
    *failure_reason = "the VM is not registered";
    return false;
  }

  bool is_shut_down;
  if (!pvm::dispatcher::IsVmShutDown(bus_, vmplugin_service_proxy_, old_id,
                                     &is_shut_down)) {
    *failure_reason = "failed to check Plugin VM state";
    return false;
  }

  if (!is_shut_down) {
    *failure_reason = "VM is not shut down";
    return false;
  }

  base::File::Error move_error;
  if (base::PathExists(old_iso_dir) &&
      !base::ReplaceFile(old_iso_dir, new_iso_dir, &move_error)) {
    *failure_reason = std::string("failed to rename VM ISO directory: ") +
                      base::File::ErrorToString(move_error);
    return false;
  }

  if (!pvm::dispatcher::UnregisterVm(bus_, vmplugin_service_proxy_, old_id)) {
    *failure_reason = "failed to temporarily unregister VM";
    return false;
  }

  if (!base::ReplaceFile(old_dir, new_dir, &move_error)) {
    *failure_reason = std::string("failed to rename VM directory: ") +
                      base::File::ErrorToString(move_error);
    return false;
  }

  if (!pvm::dispatcher::RegisterVm(bus_, vmplugin_service_proxy_,
                                   VmId(owner_id, new_name), new_dir)) {
    *failure_reason = "Failed to re-register renamed VM";
    return false;
  }

  return true;
}

}  // namespace concierge
}  // namespace vm_tools
