This is an automated email from the ASF dual-hosted git repository.

gilbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit 8603cef151f18dd88045c6f942d6dba669fbb735
Author: Qian Zhang <[email protected]>
AuthorDate: Wed Feb 27 22:22:06 2019 -0800

    Made non-root containers can access PARENT type SANDBOX_PATH volume.
    
    If a nested container running as a non-root user tries to use a PARENT
    type SANDBOX_PATH volume, we will make sure the volume owned by a unique
    gid allocated by the volume gid manager and the container process
    launched with that gid as its supplementary group.
    
    Review: https://reviews.apache.org/r/69345/
---
 include/mesos/slave/containerizer.proto            |  3 +
 src/local/local.cpp                                |  9 +++
 src/slave/containerizer/containerizer.cpp          |  5 +-
 src/slave/containerizer/containerizer.hpp          |  5 +-
 src/slave/containerizer/mesos/containerizer.cpp    | 65 +++++++++++++++++++--
 src/slave/containerizer/mesos/containerizer.hpp    |  9 ++-
 .../mesos/isolators/volume/sandbox_path.cpp        | 67 ++++++++++++++++++++--
 .../mesos/isolators/volume/sandbox_path.hpp        | 14 ++++-
 src/slave/containerizer/mesos/launch.cpp           |  4 ++
 src/slave/main.cpp                                 | 28 ++++++++-
 src/slave/slave.cpp                                |  2 +
 src/slave/slave.hpp                                |  3 +
 src/tests/cluster.cpp                              | 28 ++++++++-
 src/tests/mock_slave.cpp                           |  3 +
 src/tests/mock_slave.hpp                           |  1 +
 15 files changed, 228 insertions(+), 18 deletions(-)

diff --git a/include/mesos/slave/containerizer.proto 
b/include/mesos/slave/containerizer.proto
index 7d16463..b93b5f4 100644
--- a/include/mesos/slave/containerizer.proto
+++ b/include/mesos/slave/containerizer.proto
@@ -221,6 +221,9 @@ message ContainerLaunchInfo {
   // (POSIX only) The user to launch the command as.
   optional string user = 10;
 
+  // (POSIX only) The supplementary group IDs to launch the command as.
+  repeated uint32 supplementary_groups = 19;
+
   // If specified, it'll become the launch command for the custom
   // executor, or the launch command for the user task in the case of
   // a command task.
diff --git a/src/local/local.cpp b/src/local/local.cpp
index 6087068..6ac6b02 100644
--- a/src/local/local.cpp
+++ b/src/local/local.cpp
@@ -166,6 +166,7 @@ static vector<Fetcher*>* fetchers = nullptr;
 static vector<ResourceEstimator*>* resourceEstimators = nullptr;
 static vector<QoSController*>* qosControllers = nullptr;
 static vector<SecretGenerator*>* secretGenerators = nullptr;
+static vector<SecretResolver*>* secretResolvers = nullptr;
 
 
 PID<Master> launch(const Flags& flags, Allocator* _allocator)
@@ -375,6 +376,7 @@ PID<Master> launch(const Flags& flags, Allocator* 
_allocator)
   resourceEstimators = new vector<ResourceEstimator*>();
   qosControllers = new vector<QoSController*>();
   secretGenerators = new vector<SecretGenerator*>();
+  secretResolvers = new vector<SecretResolver*>();
 
   vector<UPID> pids;
 
@@ -504,6 +506,8 @@ PID<Master> launch(const Flags& flags, Allocator* 
_allocator)
         << "Failed to initialize secret resolver: " << secretResolver.error();
     }
 
+    secretResolvers->push_back(secretResolver.get());
+
     Try<Containerizer*> containerizer = Containerizer::create(
         slaveFlags,
         true,
@@ -529,6 +533,7 @@ PID<Master> launch(const Flags& flags, Allocator* 
_allocator)
         resourceEstimators->back(),
         qosControllers->back(),
         secretGenerators->back(),
+        nullptr,
         authorizer_); // Same authorizer as master.
 
     slaves[containerizer.get()] = slave;
@@ -601,6 +606,10 @@ void shutdown()
     delete fetchers;
     fetchers = nullptr;
 
+    foreach (SecretResolver* secretResolver, *secretResolvers) {
+      delete secretResolver;
+    }
+
     foreach (SecretGenerator* secretGenerator, *secretGenerators) {
       delete secretGenerator;
     }
diff --git a/src/slave/containerizer/containerizer.cpp 
b/src/slave/containerizer/containerizer.cpp
index c6b5e64..5ce0d9c 100644
--- a/src/slave/containerizer/containerizer.cpp
+++ b/src/slave/containerizer/containerizer.cpp
@@ -218,7 +218,8 @@ Try<Containerizer*> Containerizer::create(
     bool local,
     Fetcher* fetcher,
     GarbageCollector* gc,
-    SecretResolver* secretResolver)
+    SecretResolver* secretResolver,
+    VolumeGidManager* volumeGidManager)
 {
   // Get the set of containerizer types.
   const vector<string> _types = strings::split(flags.containerizers, ",");
@@ -288,7 +289,7 @@ Try<Containerizer*> Containerizer::create(
   foreach (const string& type, containerizerTypes) {
     if (type == "mesos") {
       Try<MesosContainerizer*> containerizer = MesosContainerizer::create(
-          flags, local, fetcher, gc, secretResolver, nvidia);
+          flags, local, fetcher, gc, secretResolver, nvidia, volumeGidManager);
       if (containerizer.isError()) {
         return Error("Could not create MesosContainerizer: " +
                      containerizer.error());
diff --git a/src/slave/containerizer/containerizer.hpp 
b/src/slave/containerizer/containerizer.hpp
index 66f73a3..d33c65c 100644
--- a/src/slave/containerizer/containerizer.hpp
+++ b/src/slave/containerizer/containerizer.hpp
@@ -38,6 +38,8 @@
 
 #include "slave/gc.hpp"
 
+#include "slave/volume_gid_manager/volume_gid_manager.hpp"
+
 #include "slave/containerizer/fetcher.hpp"
 
 namespace mesos {
@@ -72,7 +74,8 @@ public:
       bool local,
       Fetcher* fetcher,
       GarbageCollector* gc,
-      SecretResolver* secretResolver = nullptr);
+      SecretResolver* secretResolver = nullptr,
+      VolumeGidManager* volumeGidManager = nullptr);
 
   // Determine slave resources from flags, probing the system or
   // querying a delegate.
diff --git a/src/slave/containerizer/mesos/containerizer.cpp 
b/src/slave/containerizer/mesos/containerizer.cpp
index 5e6b354..a30c00a 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -176,7 +176,8 @@ Try<MesosContainerizer*> MesosContainerizer::create(
     Fetcher* fetcher,
     GarbageCollector* gc,
     SecretResolver* secretResolver,
-    const Option<NvidiaComponents>& nvidia)
+    const Option<NvidiaComponents>& nvidia,
+    VolumeGidManager* volumeGidManager)
 {
   Try<hashset<string>> isolations = [&flags]() -> Try<hashset<string>> {
     const vector<string> tokens(strings::tokenize(flags.isolation, ","));
@@ -421,7 +422,12 @@ Try<MesosContainerizer*> MesosContainerizer::create(
     // Volume isolators.
 
 #ifndef __WINDOWS__
-    {"volume/sandbox_path", &VolumeSandboxPathIsolatorProcess::create},
+    {"volume/sandbox_path",
+      [volumeGidManager] (const Flags& flags) -> Try<Isolator*> {
+        return VolumeSandboxPathIsolatorProcess::create(
+            flags,
+            volumeGidManager);
+      }},
 #endif // __WINDOWS__
 
 #ifdef __linux__
@@ -562,7 +568,8 @@ Try<MesosContainerizer*> MesosContainerizer::create(
       gc,
       Owned<Launcher>(launcher.get()),
       provisioner,
-      isolators);
+      isolators,
+      volumeGidManager);
 }
 
 
@@ -573,7 +580,8 @@ Try<MesosContainerizer*> MesosContainerizer::create(
     GarbageCollector* gc,
     const Owned<Launcher>& launcher,
     const Shared<Provisioner>& provisioner,
-    const vector<Owned<Isolator>>& isolators)
+    const vector<Owned<Isolator>>& isolators,
+    VolumeGidManager* volumeGidManager)
 {
   // Add I/O switchboard to the isolator list.
   //
@@ -631,6 +639,7 @@ Try<MesosContainerizer*> MesosContainerizer::create(
           launcher,
           provisioner,
           _isolators,
+          volumeGidManager,
           initMemFd,
           commandExecutorMemFd)));
 }
@@ -1443,7 +1452,7 @@ Future<Nothing> MesosContainerizerProcess::prepare(
     const ContainerID& containerId,
     const Option<ProvisionInfo>& provisionInfo)
 {
-  // This is because if a 'destroy' happens during the provisoiner is
+  // This is because if a 'destroy' happens during the provisioner is
   // provisioning in '_launch', even if the '____destroy' will wait
   // for the 'provision' in '_launch' to finish, there is still a
   // chance that '____destroy' and its dependencies finish before
@@ -1665,6 +1674,17 @@ Future<Containerizer::LaunchResult> 
MesosContainerizerProcess::_launch(
     launchInfo.add_clone_namespaces(ns);
   }
 
+  // Remove duplicated entries in supplementary groups.
+  set<uint32_t> supplementaryGroups(
+      launchInfo.supplementary_groups().begin(),
+      launchInfo.supplementary_groups().end());
+
+  launchInfo.clear_supplementary_groups();
+
+  foreach (uint32_t gid, supplementaryGroups) {
+    launchInfo.add_supplementary_groups(gid);
+  }
+
   // Determine the launch command for the container.
   if (!launchInfo.has_command()) {
     launchInfo.mutable_command()->CopyFrom(container->config->command_info());
@@ -2702,6 +2722,41 @@ void MesosContainerizerProcess::____destroy(
 {
   CHECK(containers_.contains(containerId));
 
+#ifndef __WINDOWS__
+  if (volumeGidManager) {
+    const Owned<Container>& container = containers_.at(containerId);
+
+    if (container->config.isSome()) {
+      VLOG(1) << "Invoking volume gid manager to deallocate gid for container "
+              << containerId;
+
+      volumeGidManager->deallocate(container->config->directory())
+        .onAny(defer(self(), [=](const Future<Nothing>& future) {
+          CHECK(containers_.contains(containerId));
+
+          if (!future.isReady()) {
+            container->termination.fail(
+                "Failed to deallocate gid when destroying container: " +
+                (future.isFailed() ? future.failure() : "discarded future"));
+
+            ++metrics.container_destroy_errors;
+            return;
+          }
+
+          cleanupIsolators(containerId)
+            .onAny(defer(
+                self(),
+                &Self::_____destroy,
+                containerId,
+                termination,
+                lambda::_1));
+      }));
+
+      return;
+    }
+  }
+#endif // __WINDOWS__
+
   cleanupIsolators(containerId)
     .onAny(defer(
         self(),
diff --git a/src/slave/containerizer/mesos/containerizer.hpp 
b/src/slave/containerizer/mesos/containerizer.hpp
index 263a177..558e412 100644
--- a/src/slave/containerizer/mesos/containerizer.hpp
+++ b/src/slave/containerizer/mesos/containerizer.hpp
@@ -71,7 +71,8 @@ public:
       Fetcher* fetcher,
       GarbageCollector* gc = nullptr,
       SecretResolver* secretResolver = nullptr,
-      const Option<NvidiaComponents>& nvidia = None());
+      const Option<NvidiaComponents>& nvidia = None(),
+      VolumeGidManager* volumeGidManager = nullptr);
 
   static Try<MesosContainerizer*> create(
       const Flags& flags,
@@ -80,7 +81,8 @@ public:
       GarbageCollector* gc,
       const process::Owned<Launcher>& launcher,
       const process::Shared<Provisioner>& provisioner,
-      const std::vector<process::Owned<mesos::slave::Isolator>>& isolators);
+      const std::vector<process::Owned<mesos::slave::Isolator>>& isolators,
+      VolumeGidManager* volumeGidManager = nullptr);
 
   ~MesosContainerizer() override;
 
@@ -143,6 +145,7 @@ public:
       const process::Owned<Launcher>& _launcher,
       const process::Shared<Provisioner>& _provisioner,
       const std::vector<process::Owned<mesos::slave::Isolator>>& _isolators,
+      VolumeGidManager* _volumeGidManager,
       const Option<int_fd>& _initMemFd,
       const Option<int_fd>& _commandExecutorMemFd)
     : ProcessBase(process::ID::generate("mesos-containerizer")),
@@ -153,6 +156,7 @@ public:
       launcher(_launcher),
       provisioner(_provisioner),
       isolators(_isolators),
+      volumeGidManager(_volumeGidManager),
       initMemFd(_initMemFd),
       commandExecutorMemFd(_commandExecutorMemFd) {}
 
@@ -339,6 +343,7 @@ private:
   const process::Owned<Launcher> launcher;
   const process::Shared<Provisioner> provisioner;
   const std::vector<process::Owned<mesos::slave::Isolator>> isolators;
+  VolumeGidManager* volumeGidManager;
   const Option<int_fd> initMemFd;
   const Option<int_fd> commandExecutorMemFd;
 
diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp 
b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
index ecd467c..45bd143 100644
--- a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
@@ -18,6 +18,7 @@
 
 #include <glog/logging.h>
 
+#include <process/collect.hpp>
 #include <process/future.hpp>
 #include <process/id.hpp>
 
@@ -62,7 +63,8 @@ namespace internal {
 namespace slave {
 
 Try<Isolator*> VolumeSandboxPathIsolatorProcess::create(
-    const Flags& flags)
+    const Flags& flags,
+    VolumeGidManager* volumeGidManager)
 {
   bool bindMountSupported = false;
 
@@ -72,7 +74,12 @@ Try<Isolator*> VolumeSandboxPathIsolatorProcess::create(
   }
 
   Owned<MesosIsolatorProcess> process(
-      new VolumeSandboxPathIsolatorProcess(flags, bindMountSupported));
+      new VolumeSandboxPathIsolatorProcess(
+          flags,
+#ifdef __linux__
+          volumeGidManager,
+#endif // __linux__
+          bindMountSupported));
 
   return new MesosIsolator(process);
 }
@@ -80,9 +87,15 @@ Try<Isolator*> VolumeSandboxPathIsolatorProcess::create(
 
 VolumeSandboxPathIsolatorProcess::VolumeSandboxPathIsolatorProcess(
     const Flags& _flags,
+#ifdef __linux__
+    VolumeGidManager* _volumeGidManager,
+#endif // __linux__
     bool _bindMountSupported)
   : ProcessBase(process::ID::generate("volume-sandbox-path-isolator")),
     flags(_flags),
+#ifdef __linux__
+    volumeGidManager(_volumeGidManager),
+#endif // __linux__
     bindMountSupported(_bindMountSupported) {}
 
 
@@ -139,6 +152,7 @@ Future<Option<ContainerLaunchInfo>> 
VolumeSandboxPathIsolatorProcess::prepare(
   }
 
   ContainerLaunchInfo launchInfo;
+  vector<Future<gid_t>> futures;
 
   foreach (const Volume& volume, containerInfo.volumes()) {
     // NOTE: The validation here is for backwards compatibility. For
@@ -249,7 +263,6 @@ Future<Option<ContainerLaunchInfo>> 
VolumeSandboxPathIsolatorProcess::prepare(
 
       // Get 'sourceRoot''s user and group info for the source path.
       struct stat s;
-
       if (::stat(sourceRoot.c_str(), &s) < 0) {
         return ErrnoFailure("Failed to stat '" + sourceRoot + "'");
       }
@@ -380,6 +393,44 @@ Future<Option<ContainerLaunchInfo>> 
VolumeSandboxPathIsolatorProcess::prepare(
           source,
           target,
           MS_BIND | MS_REC | (volume.mode() == Volume::RO ? MS_RDONLY : 0));
+
+      // For the PARENT type SANDBOX_PATH volume, if the container's user is
+      // not root and not the owner of the volume, call volume gid manager to
+      // allocate a gid to make sure the container has the permission to access
+      // the volume. Please note that we only do this when `bindMountSupported`
+      // is true but not for the case of using symlink to do the SANDBOX_PATH
+      // volume, because container's sandbox is created with 0750 permissions
+      // (i.e., other users have no permissions, see MESOS-8332 for details), 
so
+      // the nested container actually has no permissions to access anything
+      // under its parent container's sandbox if their users are different,
+      // that means the nested container cannot access the source path of the
+      // volume (i.e., the source of the symlink) which is under its parent
+      // container's sandbox.
+      if (volumeGidManager &&
+          containerConfig.has_user() &&
+          containerConfig.user() != "root" &&
+          sandboxPath->type() == Volume::Source::SandboxPath::PARENT) {
+        Result<uid_t> uid = os::getuid(containerConfig.user());
+        if (!uid.isSome()) {
+          return Failure(
+              "Failed to get the uid of user '" + containerConfig.user() + "': 
"
+              + (uid.isError() ? uid.error() : "not found"));
+        }
+
+        struct stat s;
+        if (::stat(source.c_str(), &s) < 0) {
+          return ErrnoFailure("Failed to stat '" + source + "'");
+        }
+
+        if (uid.get() != s.st_uid) {
+          LOG(INFO) << "Invoking volume gid manager to allocate gid to the "
+                    << "volume path '" << source << "' for container "
+                    << containerId;
+
+          futures.push_back(
+              volumeGidManager->allocate(source, VolumeGidInfo::SANDBOX_PATH));
+        }
+      }
 #endif // __linux__
     } else {
       LOG(INFO) << "Linking SANDBOX_PATH volume from "
@@ -402,7 +453,15 @@ Future<Option<ContainerLaunchInfo>> 
VolumeSandboxPathIsolatorProcess::prepare(
     }
   }
 
-  return launchInfo;
+  return collect(futures)
+    .then([launchInfo](const vector<gid_t>& gids) mutable
+        -> Future<Option<ContainerLaunchInfo>> {
+      foreach (gid_t gid, gids) {
+        launchInfo.add_supplementary_groups(gid);
+      }
+
+      return launchInfo;
+    });
 }
 
 
diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp 
b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp
index 1631160..07cda22 100644
--- a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.hpp
@@ -23,6 +23,8 @@
 
 #include "slave/flags.hpp"
 
+#include "slave/volume_gid_manager/volume_gid_manager.hpp"
+
 #include "slave/containerizer/mesos/isolator.hpp"
 
 namespace mesos {
@@ -32,7 +34,9 @@ namespace slave {
 class VolumeSandboxPathIsolatorProcess : public MesosIsolatorProcess
 {
 public:
-  static Try<mesos::slave::Isolator*> create(const Flags& flags);
+  static Try<mesos::slave::Isolator*> create(
+      const Flags& flags,
+      VolumeGidManager* volumeGidManager);
 
   ~VolumeSandboxPathIsolatorProcess() override;
 
@@ -53,9 +57,17 @@ public:
 private:
   VolumeSandboxPathIsolatorProcess(
       const Flags& flags,
+#ifdef __linux__
+      VolumeGidManager* volumeGidManager,
+#endif // __linux__
       bool bindMountSupported);
 
   const Flags flags;
+
+#ifdef __linux__
+  VolumeGidManager* volumeGidManager;
+#endif // __linux__
+
   const bool bindMountSupported;
 
   hashmap<ContainerID, std::string> sandboxes;
diff --git a/src/slave/containerizer/mesos/launch.cpp 
b/src/slave/containerizer/mesos/launch.cpp
index 17dd671..88b97a5 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -824,6 +824,10 @@ int MesosContainerizerLaunch::execute()
         exitWithStatus(EXIT_FAILURE);
       }
 
+      foreach (uint32_t supplementaryGroup, launchInfo.supplementary_groups()) 
{
+        _gids->push_back(supplementaryGroup);
+      }
+
       uid = _uid.get();
       gid = _gid.get();
       gids = _gids.get();
diff --git a/src/slave/main.cpp b/src/slave/main.cpp
index d1ce454..344aa66 100644
--- a/src/slave/main.cpp
+++ b/src/slave/main.cpp
@@ -477,8 +477,27 @@ int main(int argc, char** argv)
         << "Failed to initialize secret resolver: " << secretResolver.error();
   }
 
-  Try<Containerizer*> containerizer =
-    Containerizer::create(flags, false, fetcher, gc, secretResolver.get());
+  VolumeGidManager* volumeGidManager = nullptr;
+
+#ifndef __WINDOWS__
+  if (flags.volume_gid_range.isSome()) {
+    Try<VolumeGidManager*> _volumeGidManager = VolumeGidManager::create(flags);
+    if (_volumeGidManager.isError()) {
+      EXIT(EXIT_FAILURE) << "Failed to initialize volume gid manager: "
+                         << _volumeGidManager.error();
+    }
+
+    volumeGidManager = _volumeGidManager.get();
+  }
+#endif // __WINDOWS__
+
+  Try<Containerizer*> containerizer = Containerizer::create(
+      flags,
+      false,
+      fetcher,
+      gc,
+      secretResolver.get(),
+      volumeGidManager);
 
   if (containerizer.isError()) {
     EXIT(EXIT_FAILURE)
@@ -591,6 +610,7 @@ int main(int argc, char** argv)
       resourceEstimator.get(),
       qosController.get(),
       secretGenerator,
+      volumeGidManager,
       authorizer_);
 
   process::spawn(slave);
@@ -616,6 +636,10 @@ int main(int argc, char** argv)
 
   delete containerizer.get();
 
+  delete volumeGidManager;
+
+  delete secretResolver.get();
+
   delete gc;
 
   delete fetcher;
diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp
index f6339e9..3b7870a 100644
--- a/src/slave/slave.cpp
+++ b/src/slave/slave.cpp
@@ -197,6 +197,7 @@ Slave::Slave(const string& id,
              ResourceEstimator* _resourceEstimator,
              QoSController* _qosController,
              SecretGenerator* _secretGenerator,
+             VolumeGidManager* _volumeGidManager,
              const Option<Authorizer*>& _authorizer)
   : ProcessBase(id),
     state(RECOVERING),
@@ -226,6 +227,7 @@ Slave::Slave(const string& id,
     resourceEstimator(_resourceEstimator),
     qosController(_qosController),
     secretGenerator(_secretGenerator),
+    volumeGidManager(_volumeGidManager),
     authorizer(_authorizer),
     resourceVersion(protobuf::createUUID()) {}
 
diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp
index 404f22f..808531c 100644
--- a/src/slave/slave.hpp
+++ b/src/slave/slave.hpp
@@ -127,6 +127,7 @@ public:
         mesos::slave::ResourceEstimator* resourceEstimator,
         mesos::slave::QoSController* qosController,
         mesos::SecretGenerator* secretGenerator,
+        VolumeGidManager* volumeGidManager,
         const Option<Authorizer*>& authorizer);
 
   ~Slave() override;
@@ -835,6 +836,8 @@ private:
 
   mesos::SecretGenerator* secretGenerator;
 
+  VolumeGidManager* volumeGidManager;
+
   const Option<Authorizer*> authorizer;
 
   // The most recent estimate of the total amount of oversubscribed
diff --git a/src/tests/cluster.cpp b/src/tests/cluster.cpp
index 6148984..b43f806 100644
--- a/src/tests/cluster.cpp
+++ b/src/tests/cluster.cpp
@@ -97,6 +97,8 @@
 #include "slave/containerizer/containerizer.hpp"
 #include "slave/containerizer/fetcher.hpp"
 
+#include "slave/volume_gid_manager/volume_gid_manager.hpp"
+
 #include "tests/cluster.hpp"
 #include "tests/mock_registrar.hpp"
 
@@ -427,6 +429,23 @@ Try<process::Owned<Slave>> Slave::create(
     slave->gc.reset(new slave::GarbageCollector(flags.work_dir));
   }
 
+  // If the flag `--volume_gid_range` is specified, create a volume gid 
manager.
+  slave::VolumeGidManager* volumeGidManager = nullptr;
+
+#ifndef __WINDOWS__
+  if (flags.volume_gid_range.isSome()) {
+    Try<slave::VolumeGidManager*> _volumeGidManager =
+      slave::VolumeGidManager::create(flags);
+
+    if (_volumeGidManager.isError()) {
+      return Error(
+          "Failed to create volume gid manager: " + _volumeGidManager.error());
+    }
+
+    volumeGidManager = _volumeGidManager.get();
+  }
+#endif // __WINDOWS__
+
   // If the containerizer is not provided, create a default one.
   if (containerizer.isSome()) {
     slave->containerizer = containerizer.get();
@@ -436,7 +455,12 @@ Try<process::Owned<Slave>> Slave::create(
 
     Try<slave::Containerizer*> _containerizer =
       slave::Containerizer::create(
-          flags, true, slave->fetcher.get(), gc.getOrElse(slave->gc.get()));
+          flags,
+          true,
+          slave->fetcher.get(),
+          gc.getOrElse(slave->gc.get()),
+          nullptr,
+          volumeGidManager);
 
     if (_containerizer.isError()) {
       return Error("Failed to create containerizer: " + 
_containerizer.error());
@@ -588,6 +612,7 @@ Try<process::Owned<Slave>> Slave::create(
         resourceEstimator.getOrElse(slave->resourceEstimator.get()),
         qosController.getOrElse(slave->qosController.get()),
         secretGenerator.getOrElse(slave->secretGenerator.get()),
+        volumeGidManager,
         authorizer));
   } else {
     slave->slave.reset(new slave::Slave(
@@ -601,6 +626,7 @@ Try<process::Owned<Slave>> Slave::create(
         resourceEstimator.getOrElse(slave->resourceEstimator.get()),
         qosController.getOrElse(slave->qosController.get()),
         secretGenerator.getOrElse(slave->secretGenerator.get()),
+        volumeGidManager,
         authorizer));
   }
 
diff --git a/src/tests/mock_slave.cpp b/src/tests/mock_slave.cpp
index a78ca9c..1122c2a 100644
--- a/src/tests/mock_slave.cpp
+++ b/src/tests/mock_slave.cpp
@@ -36,6 +36,7 @@ using mesos::master::detector::MasterDetector;
 using mesos::internal::slave::Containerizer;
 using mesos::internal::slave::GarbageCollector;
 using mesos::internal::slave::TaskStatusUpdateManager;
+using mesos::internal::slave::VolumeGidManager;
 
 using mesos::slave::ContainerTermination;
 using mesos::slave::ResourceEstimator;
@@ -101,6 +102,7 @@ MockSlave::MockSlave(
     ResourceEstimator* resourceEstimator,
     QoSController* qosController,
     SecretGenerator* secretGenerator,
+    VolumeGidManager* volumeGidManager,
     const Option<Authorizer*>& authorizer)
   // It is necessary to explicitly call `ProcessBase` constructor here even
   // though the direct parent `Slave` already does this. This is because
@@ -119,6 +121,7 @@ MockSlave::MockSlave(
         resourceEstimator,
         qosController,
         secretGenerator,
+        volumeGidManager,
         authorizer)
 {
   // Set up default behaviors, calling the original methods.
diff --git a/src/tests/mock_slave.hpp b/src/tests/mock_slave.hpp
index 3c0d602..326a450 100644
--- a/src/tests/mock_slave.hpp
+++ b/src/tests/mock_slave.hpp
@@ -99,6 +99,7 @@ public:
       mesos::slave::ResourceEstimator* resourceEstimator,
       mesos::slave::QoSController* qosController,
       SecretGenerator* secretGenerator,
+      slave::VolumeGidManager* volumeGidManager,
       const Option<Authorizer*>& authorizer);
 
   MOCK_METHOD6(___run, void(

Reply via email to