// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <sched.h>
#include <unistd.h>

#include <linux/sched.h>

#include <vector>

#include <process/collect.hpp>

#include <stout/abort.hpp>
#include <stout/check.hpp>
#include <stout/hashset.hpp>
#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/strings.hpp>
#include <stout/stringify.hpp>

#include "linux/cgroups.hpp"
#ifdef ENABLE_CGROUPS_V2
#include "linux/cgroups2.hpp"
#endif // ENABLE_CGROUPS_V2
#include "linux/ns.hpp"
#include "linux/systemd.hpp"

#include "mesos/resources.hpp"

#include "slave/containerizer/mesos/linux_launcher.hpp"
#include "slave/containerizer/mesos/paths.hpp"

using namespace process;

using lambda::function;
using std::map;
using std::set;
using std::string;
using std::vector;

using mesos::slave::ContainerState;

namespace mesos {
namespace internal {
namespace slave {

// Launcher for Linux systems with cgroups. Uses a freezer cgroup to
// track pids.
class LinuxLauncherProcess : public Process<LinuxLauncherProcess>
{
public:
  LinuxLauncherProcess(
      const Flags& flags,
      bool cgroupsV2,
      const Option<string>& freezerHierarchy,
      const Option<string>& systemdHierarchy);

  virtual Future<hashset<ContainerID>> recover(
      const vector<mesos::slave::ContainerState>& states);

  virtual Try<pid_t> fork(
      const ContainerID& containerId,
      const string& path,
      const vector<string>& argv,
      const mesos::slave::ContainerIO& containerIO,
      const flags::FlagsBase* flags,
      const Option<map<string, string>>& environment,
      const Option<int>& enterNamespaces,
      const Option<int>& cloneNamespaces,
      const vector<int_fd>& whitelistFds);

  virtual Future<Nothing> destroy(const ContainerID& containerId);

  virtual Future<ContainerStatus> status(
      const ContainerID& containerId);

private:
  // Helper struct for storing information about each container. A
  // "container" here means a cgroup in the freezer subsystem that is
  // used to represent a collection of processes. This container may
  // also have multiple namespaces associated with it but that is not
  // managed explicitly here.
  struct Container
  {
    ContainerID id;

    // NOTE: this represents the "init" of the container that we
    // created (it may be for an executor, or any arbitrary process
    // that has been launched in the event of nested containers).
    //
    // This is none when it's an orphan container (i.e., we have a
    // freezer cgroup but we were not expecting the container during
    // `LinuxLauncher::recover`).
    Option<pid_t> pid = None();
  };

  Try<Nothing> recoverContainersFromCgroups();
  Try<Nothing> recoverContainersFromCgroups2();

  Future<Nothing> destroyCgroups(const Container& container);
  Future<Nothing> _destroyCgroups(const Container& container);
  Future<Nothing> destroyCgroups2(const Container& container);

  const Flags flags;

  struct CgroupsInfo
  {
    // Flag indicating whether cgroups v2 is used.
    bool v2;

    // Absolute path of the cgroup freezer hierarchy.
    // Only present when cgroups v1 is used.
    Option<string> freezerHierarchy;

    // Absolute path the systemd hierarchy.
    // Only present in cgroups v1 when systemd is enabled
    // (i.e. `systemd::enabled()`).
    Option<string> systemdHierarchy;
  } cgroupsInfo;

  hashmap<ContainerID, Container> containers;
};


Try<Launcher*> LinuxLauncher::create(const Flags& flags)
{
#ifdef ENABLE_CGROUPS_V2
  Try<bool> mounted = cgroups2::mounted();
  if (mounted.isError()) {
    return Error("Failed to check if cgroups2 is mounted: " + mounted.error());
  }
  if (*mounted) {
    return createCgroups2Launcher(flags);
  }
#endif // ENABLE_CGROUPS_V2
  return createCgroupsLauncher(flags);
}


Try<Launcher*> LinuxLauncher::createCgroupsLauncher(const Flags& flags)
{
  Try<string> freezerHierarchy = cgroups::prepare(
      flags.cgroups_hierarchy,
      "freezer",
      flags.cgroups_root);

  if (freezerHierarchy.isError()) {
    return Error(
        "Failed to create Linux launcher: " + freezerHierarchy.error());
  }

  // Ensure that no other subsystem is attached to the freezer hierarchy.
  Try<set<string>> subsystems = cgroups::subsystems(*freezerHierarchy);
  if (subsystems.isError()) {
    return Error(
        "Failed to get the list of attached subsystems for hierarchy " +
        *freezerHierarchy);
  } else if (subsystems->size() != 1) {
    return Error(
        "Unexpected subsystems found attached to the hierarchy " +
        *freezerHierarchy);
  }

  LOG(INFO) << "Using " << *freezerHierarchy
            << " as the freezer hierarchy for the Linux launcher";

  // On systemd environments, we currently do the following:
  //
  // (1) For Mesos version < 1.6, we migrate executor pids into a
  // separate slice. This allows the life-time of the executor to be
  // extended past the life-time of the slave. See MESOS-3352.
  //
  // (2) For Mesos version >= 1.6, we create the cgroups under the
  // systemd hierarchy directly, and use the same layout as that in
  // the freezer hierarchy. This should prevent systemd from migrating
  // pids in other hierarchies as well because the pids are unknown to
  // systemd.
  Option<string> systemdHierarchy;

  if (systemd::enabled()) {
    systemdHierarchy = systemd::hierarchy();

    // Create the root cgroup if does not exist.
    if (!cgroups::exists(*systemdHierarchy, flags.cgroups_root)) {
      Try<Nothing> create = cgroups::create(
          *systemdHierarchy,
          flags.cgroups_root);

      if (create.isError()) {
        return Error(
            "Failed to create cgroup root under systemd hierarchy: " +
            create.error());
      }
    }

    LOG(INFO) << "Using " << *systemdHierarchy
              << " as the systemd hierarchy for the Linux launcher";
  }

  return new LinuxLauncher(flags, false, *freezerHierarchy, systemdHierarchy);
}


Try<Launcher*> LinuxLauncher::createCgroups2Launcher(const Flags& flags)
{
  return new LinuxLauncher(flags, true, None(), None());
}


bool LinuxLauncher::available()
{
  bool available = false;

#ifdef ENABLE_CGROUPS_V2
  // Check if cgroups v2 is available.
  Try<bool> mounted = cgroups2::mounted();
  available |= mounted.isSome() && *mounted;
#endif // ENABLE_CGROUPS_V2

  // Check if cgroups v1 is available.
  // Make sure:
  // 1. Are running as root.
  // 2. 'freezer' subsystem is enabled.
  Try<bool> freezer = cgroups::enabled("freezer");
  available |= ::geteuid() == 0 && freezer.isSome() && *freezer;

  return available;
}


LinuxLauncher::LinuxLauncher(
    const Flags& flags,
    bool cgroupsV2,
    const Option<string>& freezerHierarchy,
    const Option<string>& systemdHierarchy)
  : process(new LinuxLauncherProcess(
      flags, cgroupsV2, freezerHierarchy, systemdHierarchy))
{
  process::spawn(process.get());
}


LinuxLauncher::~LinuxLauncher()
{
  process::terminate(process.get());
  process::wait(process.get());
}


Future<hashset<ContainerID>> LinuxLauncher::recover(
    const vector<mesos::slave::ContainerState>& states)
{
  return dispatch(process.get(), &LinuxLauncherProcess::recover, states);
}


Try<pid_t> LinuxLauncher::fork(
    const ContainerID& containerId,
    const string& path,
    const vector<string>& argv,
    const mesos::slave::ContainerIO& containerIO,
    const flags::FlagsBase* flags,
    const Option<map<string, string>>& environment,
    const Option<int>& enterNamespaces,
    const Option<int>& cloneNamespaces,
    const vector<int_fd>& whitelistFds)
{
  return dispatch(
      process.get(),
      &LinuxLauncherProcess::fork,
      containerId,
      path,
      argv,
      containerIO,
      flags,
      environment,
      enterNamespaces,
      cloneNamespaces,
      whitelistFds).get();
}


Future<Nothing> LinuxLauncher::destroy(const ContainerID& containerId)
{
  return dispatch(process.get(), &LinuxLauncherProcess::destroy, containerId);
}


Future<ContainerStatus> LinuxLauncher::status(
    const ContainerID& containerId)
{
  return dispatch(process.get(), &LinuxLauncherProcess::status, containerId);
}


LinuxLauncherProcess::LinuxLauncherProcess(
    const Flags& flags,
    bool cgroupsV2,
    const Option<string>& freezerHierarchy,
    const Option<string>& systemdHierarchy)
  : flags(flags)
{
  cgroupsInfo.v2 = cgroupsV2;
  cgroupsInfo.freezerHierarchy = freezerHierarchy;
  cgroupsInfo.systemdHierarchy = systemdHierarchy;
}


Future<hashset<ContainerID>> LinuxLauncherProcess::recover(
    const vector<ContainerState>& states)
{
  // 1. Cgroups v1: We recover container ids by looking at the cgroups in the
  //                freezer or (optional) systemd hierarchy.
  //    Cgroups v2: We recover container ids by looking at the cgroups in the
  //                `flags.cgroups_root` directory, in `/sys/fs/cgroup`.
  //
  // 2. Create a list of the container ids that we expect to recover
  //    based on the persisted `ContainerState`s. If a container is expected
  //    to be recovered but was not found while parsing the cgroups, we create
  //    a container for it from the `ContainerState`, so
  //    `LinuxLauncher::destroy` doesn't fail when called for this container.
  //
  // 3. Cgroups v1: In a systemd environment, check that the container pids are
  //                being managed by either the Mesos `systemd` cgroup or the
  //                systemd `MESOS_EXECUTORS_SLICE`.
  //
  // 4. Return a list of "orphan" containers, that is, containers that were
  //    recovered but were not expected to be recovered.
  LOG(INFO) << "Recovering Linux launcher";

  // Recover containers by looking at the cgroups found in the cgroups
  // filesystem.
  Try<Nothing> recover = cgroupsInfo.v2
    ? recoverContainersFromCgroups2()
    : recoverContainersFromCgroups();

  if (recover.isError()) {
    return Failure("Failed to recover containers from the cgroup filesystem: "
                   + recover.error());
  }

  // Now loop through the containers expected by ContainerState so we
  // can have a complete list of the containers we might ever want to
  // destroy as well as be able to determine orphans below.
  hashset<ContainerID> expected = {};

  foreach (const ContainerState& state, states) {
    expected.insert(state.container_id());

    if (!containers.contains(state.container_id())) {
      // Given that the container was not recovered, that implies that
      // the container was previously destroyed.
      //
      // We still add it to `containers` so that when `LinuxLauncher::destroy`
      // gets called for this container below we don't fail.
      Container container;
      container.id = state.container_id();
      container.pid = state.pid();

      containers.put(container.id, container);

      LOG(INFO) << "Recovered (destroyed) container " << container.id;
    } else {
      // This container exists, so we save the pid so we can check
      // that it's part of the systemd "Mesos executor slice" below.
      containers[state.container_id()].pid = state.pid();
    }
  }

  if (!cgroupsInfo.v2) {
    // TODO(benh): In the past we used to make sure that we didn't have
    // multiple containers that had the same pid. This seemed pretty
    // random, and is highly unlikely to occur in practice. That being
    // said, a good sanity check we could do here is to make sure that
    // the pid is actually contained within each container's freezer
    // cgroup.

    // If we are on a systemd environment, check that container pids are
    // either in the `MESOS_EXECUTORS_SLICE`, or under Mesos cgroup root
    // under the systemd hierarchy. If they are not, warn the operator
    // that resource isolation may be invalidated.
    //
    // TODO(jmlvanre): Add a flag that enforces this rather than just
    // logs a warning (i.e., we exit if a pid was found in the freezer
    // but not in the `MESOS_EXECUTORS_SLICE` or Mesos cgroup root under
    // the systemd hierarhcy). We need a flag to support the upgrade
    // path.
    if (cgroupsInfo.systemdHierarchy.isSome()) {
      foreachvalue (const Container& container, containers) {
        if (container.pid.isNone()) {
          continue;
        }

        pid_t pid = container.pid.get();

        // No need to proceed the check if the pid does not exist
        // anymore. This is possible if the container terminates when
        // the agent is down.
        if (os::kill(pid, 0) != 0) {
          continue;
        }

        Result<string> cgroup = cgroups::named::cgroup("systemd", pid);
        if (!cgroup.isSome()) {
          LOG(ERROR) << "Failed to get cgroup in systemd hierarchy for "
                    << "container pid " << pid << ": "
                    << (cgroup.isError() ? cgroup.error() : "Not found");
          continue;
        }

        bool inMesosCgroupRoot =
          strings::startsWith(*cgroup, flags.cgroups_root);

        bool inMesosExecutorSlice =
          strings::contains(*cgroup, systemd::mesos::MESOS_EXECUTORS_SLICE);

        if (!inMesosCgroupRoot && !inMesosExecutorSlice) {
          LOG(WARNING)
            << "Couldn't find pid " << pid << " in either Mesos cgroup root '"
            << flags.cgroups_root << "' under systemd hierarchy, or systemd "
            << "slice '" << systemd::mesos::MESOS_EXECUTORS_SLICE << "'; "
            << "This can lead to lack of proper resource isolation";
        }
      }
    }
  }

  // Return the list of top-level AND nested orphaned containers,
  // i.e., a container that we recovered but was not expected during
  // recovery.
  hashset<ContainerID> orphans = {};

  foreachvalue (const Container& container, containers) {
    if (!expected.contains(container.id)) {
      LOG(INFO) << container.id << " is a known orphaned container";
      orphans.insert(container.id);
    }
  }

  return orphans;
}


Try<Nothing> LinuxLauncherProcess::recoverContainersFromCgroups()
{
  // Recover all of the "containers" we know about based on the
  // existing cgroups. Note that we check both the freezer hierarchy
  // and the systemd hierarchy (if enabled), and combine the results.
  hashset<string> cgroups;

  Try<vector<string>> freezerCgroups =
    cgroups::get(*cgroupsInfo.freezerHierarchy, flags.cgroups_root);

  if (freezerCgroups.isError()) {
    return Error(
        "Failed to get cgroups from "
        + path::join(*cgroupsInfo.freezerHierarchy, flags.cgroups_root)
        + ": " + freezerCgroups.error());
  }

  foreach (const string& cgroup, freezerCgroups.get()) {
    cgroups.insert(cgroup);
  }

  if (cgroupsInfo.systemdHierarchy.isSome()) {
    Try<vector<string>> systemdCgroups =
      cgroups::get(*cgroupsInfo.systemdHierarchy, flags.cgroups_root);

    if (systemdCgroups.isError()) {
      return Error(
          "Failed to get cgroups from " +
          path::join(*cgroupsInfo.systemdHierarchy, flags.cgroups_root) +
          ": " + systemdCgroups.error());
    }

    foreach (const string& cgroup, systemdCgroups.get()) {
      cgroups.insert(cgroup);
    }
  }

  foreach (const string& cgroup, cgroups) {
    // Need to parse the cgroup to see if it's one we created (i.e.,
    // matches our separator structure) or one that someone else
    // created (e.g., in the future we might have nested containers
    // that are managed by something else rooted within the freezer
    // hierarchy).
    Option<ContainerID> containerId =
      containerizer::paths::parseCgroupPath(flags.cgroups_root, cgroup);

    if (containerId.isNone()) {
      LOG(INFO) << "Not recovering cgroup " << cgroup;
      continue;
    }

    Container container;
    container.id = containerId.get();

    // Add this to `containers` so when `destroy` gets called we
    // properly destroy the container, even if we determine it's an
    // orphan below.
    containers.put(container.id, container);

    LOG(INFO) << "Recovered container " << container.id;
  }

  return Nothing();
}


Try<Nothing> LinuxLauncherProcess::recoverContainersFromCgroups2()
{
#ifdef ENABLE_CGROUPS_V2
  Try<set<string>> cgroups = cgroups2::get(flags.cgroups_root);
  if (cgroups.isError()) {
    return Error("Failed to get cgroups: " + cgroups.error());
  }

  foreach (const string& cgroup, *cgroups) {
    // Parse the cgroups to see if we created them. Add the container ids
    // of the cgroups that parse to `containers` so that on `destroy` they
    // get properly disposed.
    Option<ContainerID> containerId =
      containerizer::paths::cgroups2::containerId(flags.cgroups_root, cgroup);
    if (containerId.isNone()) {
      continue;
    }

    Container container;
    container.id = *containerId;

    containers.put(container.id, container);

    LOG(INFO) << "Recovered container " << container.id;
  }
  return Nothing();
#else
  return Error("cgroups2 is not enabled");
#endif // ENABLE_CGROUPS_V2
}


Try<pid_t> LinuxLauncherProcess::fork(
    const ContainerID& containerId,
    const string& path,
    const vector<string>& argv,
    const mesos::slave::ContainerIO& containerIO,
    const flags::FlagsBase* flags,
    const Option<map<string, string>>& environment,
    const Option<int>& enterNamespaces,
    const Option<int>& cloneNamespaces,
    const vector<int_fd>& whitelistFds)
{
  // Make sure this container (nested or not) is unique.
  if (containers.contains(containerId)) {
    return Error("Container '" + stringify(containerId) + "' already exists");
  }

  Option<pid_t> parentPid = None();

  // Ensure nested containers have known parents.
  if (containerId.has_parent()) {
    Option<Container> parent = containers.get(containerId.parent());
    if (parent.isNone()) {
      return Error("Unknown parent container");
    }

    if (parent->pid.isNone()) {
      // TODO(benh): Could also look up a pid in the container and use
      // that in order to enter the namespaces? This would be best
      // effort because we don't know the namespaces that had been
      // created for the original pid.
      return Error("Unknown parent container pid, can not enter namespaces");
    }

    parentPid = parent->pid;
  }

  // Ensure we didn't pass `enterNamespaces`
  // if we aren't forking a nested container.
  if (!containerId.has_parent() && enterNamespaces.isSome()) {
    return Error("Cannot enter parent namespaces for non-nested container");
  }

  int enterFlags = enterNamespaces.getOrElse(0);
  int cloneFlags = cloneNamespaces.getOrElse(0);

  LOG(INFO) << "Launching " << (parentPid.isSome() ? "nested " : "")
            << "container " << containerId << " and cloning with namespaces "
            << ns::stringify(cloneFlags);

  cloneFlags |= SIGCHLD; // Specify SIGCHLD as child termination signal.

  vector<Subprocess::ParentHook> parentHooks;
  if (!cgroupsInfo.v2) {
    // The ordering of the hooks is:
    // (1) Create the freezer cgroup, and add the child to the cgroup.
    // (2) Create the systemd cgroup, and add the child to the cgroup.
    //
    // NOTE: The order is important here because the destroy code will
    // always kill the container based on the pids in the freezer
    // cgroup. The systemd cgroup will be removed after that. Therefore,
    // we want to make sure that if the pid is in the systemd cgroup, it
    // must be in the freezer cgroup.

    // Hook for creating and assigning the child into a freezer cgroup.
    parentHooks.emplace_back(Subprocess::ParentHook([=](pid_t child) {
      return cgroups::isolate(
        *cgroupsInfo.freezerHierarchy,
        containerizer::paths::getCgroupPath(
          this->flags.cgroups_root, containerId),
        child);
    }));

    // Hook for creating and assigning the child into a systemd cgroup.
    if (cgroupsInfo.systemdHierarchy.isSome()) {
      parentHooks.emplace_back(Subprocess::ParentHook([=](pid_t child) {
        return cgroups::isolate(
          *cgroupsInfo.systemdHierarchy,
          containerizer::paths::getCgroupPath(
            this->flags.cgroups_root, containerId),
          child);
      }));
    }
  }

  vector<Subprocess::ChildHook> childHooks;

  // Create a new session id so termination signals from the parent process
  // to not terminate the child.
  childHooks.push_back(Subprocess::ChildHook::SETSID());

  Try<Subprocess> child = subprocess(
    path,
    argv,
    containerIO.in,
    containerIO.out,
    containerIO.err,
    flags,
    environment,
    [parentPid, enterFlags, cloneFlags](const lambda::function<int()>& child) {
      if (parentPid.isSome()) {
        Try<pid_t> pid = ns::clone(*parentPid, enterFlags, child, cloneFlags);
        if (pid.isError()) {
          LOG(WARNING) << "Failed to enter namespaces and clone: "
                       << pid.error();
          return -1;
        }
        return *pid;
      } else {
        return os::clone(child, cloneFlags);
      }
    },
    parentHooks,
    childHooks,
    whitelistFds);

  if (child.isError()) {
    return Error("Failed to clone child process: " + child.error());
  }

  Container container;
  container.id = containerId;
  container.pid = child->pid();

  containers.put(container.id, container);

  return container.pid.get();
}


Future<Nothing> LinuxLauncherProcess::destroy(const ContainerID& containerId)
{
  LOG(INFO) << "Asked to destroy container " << containerId;

  Option<Container> container = containers.get(containerId);

  if (container.isNone()) {
    return Nothing();
  }

  // Check if `container` has any nested containers.
  foreachkey (const ContainerID& id, containers) {
    if (id.has_parent()) {
      if (container->id == id.parent()) {
        return Failure("Container has nested containers");
      }
    }
  }

  return cgroupsInfo.v2
    ? destroyCgroups2(*container)
    : destroyCgroups(*container);
}


Future<Nothing> LinuxLauncherProcess::destroyCgroups(const Container& container)
{
  const string cgroup =
    containerizer::paths::getCgroupPath(flags.cgroups_root, container.id);

  // We remove the container so that we don't attempt multiple
  // destroys simultaneously and no other functions will return
  // information about the container that is currently being (or has
  // been) destroyed. This implies, however, that if the destroy fails
  // the caller won't be able to retry because we won't know about the
  // container anymore.
  //
  // NOTE: it's safe to use `container->id` from here on because it's
  // a copy of the Container that we're about to delete.
  containers.erase(container.id);

  // Determine if this is a partially destroyed container. A container
  // is considered partially destroyed if we have recovered it from
  // ContainerState but we don't have a freezer cgroup for it. If this
  // is a partially destroyed container than there is nothing to do.
  if (!cgroups::exists(*cgroupsInfo.freezerHierarchy, cgroup)) {
    LOG(WARNING) << "Couldn't find freezer cgroup for container "
                 << container.id << " so assuming partially destroyed";

    return _destroyCgroups(container);
  }

  LOG(INFO) << "Destroying cgroup"
               " '" << path::join(*cgroupsInfo.freezerHierarchy, cgroup) << "'";

  // TODO(benh): If this is the last container at a nesting level,
  // should we also delete the `CGROUP_SEPARATOR` cgroup too?

  // TODO(benh): What if we fail to destroy the container? Should we
  // retry?
  return cgroups::destroy(
      *cgroupsInfo.freezerHierarchy,
      cgroup,
      flags.cgroups_destroy_timeout)
    .then(defer(self(), &LinuxLauncherProcess::_destroyCgroups, container));
}


Future<Nothing> LinuxLauncherProcess::_destroyCgroups(
  const Container& container)
{
  if (cgroupsInfo.systemdHierarchy.isNone()) {
    return Nothing();
  }

  const string cgroup =
    containerizer::paths::getCgroupPath(flags.cgroups_root, container.id);

  if (!cgroups::exists(*cgroupsInfo.systemdHierarchy, cgroup)) {
    return Nothing();
  }

  LOG(INFO) << "Destroying cgroup"
               " '" << path::join(*cgroupsInfo.systemdHierarchy, cgroup) << "'";

  return cgroups::destroy(
      *cgroupsInfo.systemdHierarchy,
      cgroup,
      flags.cgroups_destroy_timeout);
}


Future<Nothing> LinuxLauncherProcess::destroyCgroups2(
  const Container& container)
{
#ifdef ENABLE_CGROUPS_V2
  const string& cgroup =
    containerizer::paths::cgroups2::container(flags.cgroups_root, container.id);

  containers.erase(container.id);

  LOG(INFO) << "Destroying cgroup '" << cgroup << "'";

  return cgroups2::destroy(cgroup);
#else
  return Failure("cgroups2 is not enabled");
#endif // ENABLE_CGROUPS_V2
}


Future<ContainerStatus> LinuxLauncherProcess::status(
    const ContainerID& containerId)
{
  Option<Container> container = containers.get(containerId);
  if (container.isNone()) {
    return Failure("Container does not exist");
  }

  ContainerStatus status;
  if (container->pid.isSome()) {
    status.set_executor_pid(container->pid.get());
  }

  return status;
}

} // namespace slave {
} // namespace internal {
} // namespace mesos {
