// file      : bbot/agent/machine.hxx -*- C++ -*-
// license   : MIT; see accompanying LICENSE file

#ifndef BBOT_AGENT_MACHINE_HXX
#define BBOT_AGENT_MACHINE_HXX

#include <bbot/types.hxx>
#include <bbot/utility.hxx>

namespace bbot
{
  // A running build machine (container, vm, etc).
  //
  // Note that if the machine is destroyed while it is still running, the
  // destructor will block until the machine process terminates.
  //
  // Some functions can fail softly if the fail_hard argument is false.
  //
  class machine
  {
  public:
    // Shut the machine down cleanly waiting up to the specified number of
    // seconds for completion. Update the timeout and return false if the
    // machine is still running, true if the machine exited successfully, and
    // throw failed otherwise.
    //
    virtual bool
    shutdown (size_t& seconds) = 0;

    // Force the machine down.
    //
    virtual void
    forcedown (bool fail_hard = true) = 0;

    // Suspend the machine.
    //
    virtual void
    suspend (bool fail_hard = true) = 0;

    // Wait for the machine to terminate up to the specified number of seconds
    // (with 0 meaning don't wait). Update the timeout and return false if the
    // machine is still running, true if the machine exited successfully, and
    // throw failed otherwise.
    //
    virtual bool
    wait (size_t& seconds, bool fail_hard = true) = 0;

    bool
    wait (bool fail_hard = true)
    {
      size_t sec (~0); // Wait indefinitely.
      return wait (sec, fail_hard);
    }

    // Cleanup machine resources (logs, etc). Normally you would only call
    // this after a successful (or successfully investigated) completion.
    //
    virtual void
    cleanup () = 0;

    // Print information about the machine (as info diagnostics) that can be
    // useful for debugging (e.g., how to connect/login, etc).
    //
    virtual void
    print_info (diag_record&) = 0;

  public:
    const string mac; // MAC address (inside the machine).

  public:
    virtual
    ~machine () = default;

  protected:
    machine (string m)
        : mac (move (m)) {}
  };

  class machine_manifest;

  // The machine number should be between 0-9 with 0 for the build machine and
  // 1-9 for the auxiliary machines.
  //
  // Note that tftp_port is not a base (in other words, it is expected to
  // already be appropriately offset).
  //
  unique_ptr<machine>
  start_machine (const dir_path&,
                 const machine_manifest&,
                 uint16_t machine_num,
                 size_t cpus,
                 size_t ram, // In KiB.
                 const optional<string>& mac,
                 const string& br_iface,
                 uint16_t tftp_port,
                 bool public_vnc);

  // Return the machine's public or private VNC session endpoint in the
  // '<ip>:<port>' form.
  //
  string
  machine_vnc (uint16_t machine_num, bool public_vnc);
}

#endif // BBOT_AGENT_MACHINE_HXX
