You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2016/11/12 02:57:22 UTC
[01/11] mesos git commit: Added a default PATH environment variable
when launching a container.
Repository: mesos
Updated Branches:
refs/heads/master befac1cde -> 757d2804d
Added a default PATH environment variable when launching a container.
Having an environment set but no PATH variable set inside of it,
will trigger an `execvpe` call in launch.cpp on the command we are
trying to launch. Normally this doesn't casue problems because
`execvpe` with call `confstr(_CS_PATH)` under the hood to set up a
default path to use when lookiing up our command.
However, when provisioning a new filesystem for a container, its
possible that the `confstr(_CS_PATH)` called from the agent may not
return the same path as a `confstr(_CS_PATH)` call would return using
the libc installed inside the container. This can lead to problems
(for example) with finding the `sh` command in containers based on an
alpine linux image.
We observed this in our test setup with `confstr(_CS_PATH)` on the
agent returning `/usr/bin`, while alpine linux only has the `sh`
command installed in `/bin`.
Review: https://reviews.apache.org/r/53585/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/b15b46ab
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/b15b46ab
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/b15b46ab
Branch: refs/heads/master
Commit: b15b46ab00ebffa2b8247ac7c4210da538efcea5
Parents: befac1c
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 16:03:04 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 16:13:45 2016 -0800
----------------------------------------------------------------------
src/slave/containerizer/mesos/launch.cpp | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/b15b46ab/src/slave/containerizer/mesos/launch.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.cpp b/src/slave/containerizer/mesos/launch.cpp
index 377a9d9..181d833 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -658,7 +658,15 @@ int MesosContainerizerLaunch::execute()
// specified, inherit the environment of the current process.
Option<os::raw::Envp> envp;
if (flags.environment.isSome()) {
- envp = os::raw::Envp(flags.environment.get());
+ JSON::Object environment = flags.environment.get();
+
+ Result<JSON::String> path = flags.environment->find<JSON::String>("PATH");
+ if (path.isNone()) {
+ environment.values["PATH"] =
+ "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
+ }
+
+ envp = os::raw::Envp(environment);
}
#ifndef __WINDOWS__
[09/11] mesos git commit: Fixed nvidia gpu isolator tests.
Posted by ji...@apache.org.
Fixed nvidia gpu isolator tests.
Make sure to use filesystem/linux isolator for those tests. Otherwise,
the newly introduced check will fail the tests.
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/781b9684
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/781b9684
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/781b9684
Branch: refs/heads/master
Commit: 781b96843a80a45667cd9a5c4f5132c81d4d37cb
Parents: c40765a
Author: Jie Yu <yu...@gmail.com>
Authored: Fri Nov 11 18:30:50 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:11 2016 -0800
----------------------------------------------------------------------
src/tests/containerizer/nvidia_gpu_isolator_tests.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/781b9684/src/tests/containerizer/nvidia_gpu_isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/nvidia_gpu_isolator_tests.cpp b/src/tests/containerizer/nvidia_gpu_isolator_tests.cpp
index fea1f9f..74e06f0 100644
--- a/src/tests/containerizer/nvidia_gpu_isolator_tests.cpp
+++ b/src/tests/containerizer/nvidia_gpu_isolator_tests.cpp
@@ -88,7 +88,7 @@ TEST_F(NvidiaGpuTest, ROOT_CGROUPS_NVIDIA_GPU_VerifyDeviceAccess)
// Turn on Nvidia GPU isolation.
// Assume at least one GPU is available for isolation.
slave::Flags flags = CreateSlaveFlags();
- flags.isolation = "cgroups/devices,gpu/nvidia";
+ flags.isolation = "filesystem/linux,cgroups/devices,gpu/nvidia";
flags.nvidia_gpu_devices = vector<unsigned int>({0u});
flags.resources = "gpus:1";
@@ -300,7 +300,7 @@ TEST_F(NvidiaGpuTest, ROOT_CGROUPS_NVIDIA_GPU_FractionalResources)
// Turn on Nvidia GPU isolation.
// Assume at least one GPU is available for isolation.
slave::Flags flags = CreateSlaveFlags();
- flags.isolation = "cgroups/devices,gpu/nvidia";
+ flags.isolation = "filesystem/linux,cgroups/devices,gpu/nvidia";
flags.nvidia_gpu_devices = vector<unsigned int>({0u});
flags.resources = "gpus:1";
[05/11] mesos git commit: Fixed a compile issue on OSX.
Posted by ji...@apache.org.
Fixed a compile issue on OSX.
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/c40765ad
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/c40765ad
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/c40765ad
Branch: refs/heads/master
Commit: c40765ad9f6ac6154f54f3b25842cad7b76a4cca
Parents: 0dafc55
Author: Jie Yu <yu...@gmail.com>
Authored: Fri Nov 11 18:20:41 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:11 2016 -0800
----------------------------------------------------------------------
src/tests/containerizer/mock_containerizer.hpp | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/c40765ad/src/tests/containerizer/mock_containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/mock_containerizer.hpp b/src/tests/containerizer/mock_containerizer.hpp
index 319b5c3..7a30b83 100644
--- a/src/tests/containerizer/mock_containerizer.hpp
+++ b/src/tests/containerizer/mock_containerizer.hpp
@@ -57,14 +57,15 @@ public:
const std::map<std::string, std::string>&,
bool));
- MOCK_METHOD5(
+ MOCK_METHOD6(
launch,
process::Future<bool>(
- const ContainerID& containerId,
- const CommandInfo& commandInfo,
- const Option<ContainerInfo>& containerInfo,
- const Option<std::string>& user,
- const SlaveID& slaveId));
+ const ContainerID&,
+ const CommandInfo&,
+ const Option<ContainerInfo>&,
+ const Option<std::string>&,
+ const SlaveID&,
+ const Option<mesos::slave::ContainerClass>&));
MOCK_METHOD2(
update,
[04/11] mesos git commit: Added 'ContainerClass' to help decide how
best to launch a container.
Posted by ji...@apache.org.
Added 'ContainerClass' to help decide how best to launch a container.
A 'ContainerClass' must now be passed to all *nested*
containerizer->launch() calls in order to specify the class of
container being launched. For now, we simply have the default nested
container class (called 'NESTED') in a subsequent commit we will
introduce the 'DEBUG' class to help classify debug-based nested
containers that should be launched slightly differently than default
nested containers.
The 'ContainerClass' specified is passed through to each isolator in
'ContainerConfig' so they have a chance to custiomize their isolation
policies based on the class as well.
Review: https://reviews.apache.org/r/53351/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/727ce3d4
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/727ce3d4
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/727ce3d4
Branch: refs/heads/master
Commit: 727ce3d4f8b7c6b489a431983666f340398b0c97
Parents: ed1b4bc
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 16:19:41 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:10 2016 -0800
----------------------------------------------------------------------
include/mesos/slave/containerizer.proto | 15 +++++++++++++++
src/slave/containerizer/composing.cpp | 16 +++++++++++-----
src/slave/containerizer/composing.hpp | 3 ++-
src/slave/containerizer/containerizer.hpp | 3 ++-
src/slave/containerizer/mesos/containerizer.cpp | 17 +++++++++++++----
src/slave/containerizer/mesos/containerizer.hpp | 6 ++++--
src/tests/api_tests.cpp | 2 +-
src/tests/containerizer.cpp | 20 +++++++++++++-------
src/tests/containerizer.hpp | 8 +++++---
9 files changed, 66 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/include/mesos/slave/containerizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/slave/containerizer.proto b/include/mesos/slave/containerizer.proto
index f4c4ad7..ee29468 100644
--- a/include/mesos/slave/containerizer.proto
+++ b/include/mesos/slave/containerizer.proto
@@ -23,6 +23,17 @@ import "mesos/appc/spec.proto";
import "mesos/docker/v1.proto";
/**
+ * Some containers are launched in conjunction with a specific
+ * `ContainerClass`. These classes allow an isolator to customize
+ * their functionality based on the class of container being isolated.
+ * The classes we currently define are below.
+ */
+enum ContainerClass {
+ DEFAULT = 1;
+}
+
+
+/**
* Information when an executor is impacted by a resource limitation
* and should be terminated. Intended to support resources like memory
* where the Linux kernel may invoke the OOM killer, killing some/all
@@ -105,6 +116,10 @@ message ContainerConfig {
// Resources associated with the container during launch.
repeated Resource resources = 13;
+ // The class of container being launched. Used by isolators to
+ // perform different operations depending on the class.
+ optional ContainerClass container_class = 14;
+
// The work directory for the container in the host filesystem.
required string directory = 3;
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/slave/containerizer/composing.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/composing.cpp b/src/slave/containerizer/composing.cpp
index 0c5489f..10bb618 100644
--- a/src/slave/containerizer/composing.cpp
+++ b/src/slave/containerizer/composing.cpp
@@ -41,6 +41,7 @@ using std::map;
using std::string;
using std::vector;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerTermination;
namespace mesos {
@@ -77,7 +78,8 @@ public:
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<string>& user,
- const SlaveID& slaveId);
+ const SlaveID& slaveId,
+ const Option<ContainerClass>& containerClass);
Future<Nothing> update(
const ContainerID& containerId,
@@ -202,7 +204,8 @@ Future<bool> ComposingContainerizer::launch(
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<string>& user,
- const SlaveID& slaveId)
+ const SlaveID& slaveId,
+ const Option<ContainerClass>& containerClass)
{
return dispatch(process,
&ComposingContainerizerProcess::launch,
@@ -210,7 +213,8 @@ Future<bool> ComposingContainerizer::launch(
commandInfo,
containerInfo,
user,
- slaveId);
+ slaveId,
+ containerClass);
}
@@ -474,7 +478,8 @@ Future<bool> ComposingContainerizerProcess::launch(
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<std::string>& user,
- const SlaveID& slaveId)
+ const SlaveID& slaveId,
+ const Option<ContainerClass>& containerClass)
{
ContainerID rootContainerId = getRootContainerId(containerId);
@@ -497,7 +502,8 @@ Future<bool> ComposingContainerizerProcess::launch(
commandInfo,
containerInfo,
user,
- slaveId)
+ slaveId,
+ containerClass)
.then(defer(self(),
&Self::_launch,
containerId,
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/slave/containerizer/composing.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/composing.hpp b/src/slave/containerizer/composing.hpp
index 68c0523..3a2c9b4 100644
--- a/src/slave/containerizer/composing.hpp
+++ b/src/slave/containerizer/composing.hpp
@@ -67,7 +67,8 @@ public:
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<std::string>& user,
- const SlaveID& slaveId);
+ const SlaveID& slaveId,
+ const Option<mesos::slave::ContainerClass>& containerClass = None());
virtual process::Future<Nothing> update(
const ContainerID& containerId,
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/slave/containerizer/containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/containerizer.hpp b/src/slave/containerizer/containerizer.hpp
index 7554446..73e74c9 100644
--- a/src/slave/containerizer/containerizer.hpp
+++ b/src/slave/containerizer/containerizer.hpp
@@ -100,7 +100,8 @@ public:
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<std::string>& user,
- const SlaveID& slaveId)
+ const SlaveID& slaveId,
+ const Option<mesos::slave::ContainerClass>& containerClass = None())
{
return process::Failure("Unsupported");
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index 44225eb..90f91b9 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -119,6 +119,7 @@ using mesos::internal::slave::state::RunState;
using mesos::modules::ModuleManager;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerLimitation;
@@ -478,7 +479,8 @@ Future<bool> MesosContainerizer::launch(
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<string>& user,
- const SlaveID& slaveId)
+ const SlaveID& slaveId,
+ const Option<ContainerClass>& containerClass)
{
// Need to disambiguate for the compiler.
Future<bool> (MesosContainerizerProcess::*launch)(
@@ -486,7 +488,8 @@ Future<bool> MesosContainerizer::launch(
const CommandInfo&,
const Option<ContainerInfo>&,
const Option<string>&,
- const SlaveID&) = &MesosContainerizerProcess::launch;
+ const SlaveID&,
+ const Option<ContainerClass>&) = &MesosContainerizerProcess::launch;
return dispatch(process.get(),
launch,
@@ -494,7 +497,8 @@ Future<bool> MesosContainerizer::launch(
commandInfo,
containerInfo,
user,
- slaveId);
+ slaveId,
+ containerClass);
}
@@ -1660,7 +1664,8 @@ Future<bool> MesosContainerizerProcess::launch(
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<string>& user,
- const SlaveID& slaveId)
+ const SlaveID& slaveId,
+ const Option<ContainerClass>& containerClass)
{
CHECK(containerId.has_parent());
@@ -1732,6 +1737,10 @@ Future<bool> MesosContainerizerProcess::launch(
containerConfig.mutable_container_info()->CopyFrom(containerInfo.get());
}
+ if (containerClass.isSome()) {
+ containerConfig.set_container_class(containerClass.get());
+ }
+
return launch(containerId,
containerConfig,
map<string, string>(),
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/slave/containerizer/mesos/containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.hpp b/src/slave/containerizer/mesos/containerizer.hpp
index c4fea8b..272052d 100644
--- a/src/slave/containerizer/mesos/containerizer.hpp
+++ b/src/slave/containerizer/mesos/containerizer.hpp
@@ -91,7 +91,8 @@ public:
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<std::string>& user,
- const SlaveID& slaveId);
+ const SlaveID& slaveId,
+ const Option<mesos::slave::ContainerClass>& containerClass = None());
virtual process::Future<Nothing> update(
const ContainerID& containerId,
@@ -157,7 +158,8 @@ public:
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<std::string>& user,
- const SlaveID& slaveId);
+ const SlaveID& slaveId,
+ const Option<mesos::slave::ContainerClass>& containerClass);
virtual process::Future<Nothing> update(
const ContainerID& containerId,
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/tests/api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/api_tests.cpp b/src/tests/api_tests.cpp
index 57981f1..8889e78 100644
--- a/src/tests/api_tests.cpp
+++ b/src/tests/api_tests.cpp
@@ -3437,7 +3437,7 @@ TEST_P(AgentAPITest, NestedContainerLaunchFalse)
{
// Return false here to indicate "unsupported".
- EXPECT_CALL(containerizer, launch(_, _, _, _, _))
+ EXPECT_CALL(containerizer, launch(_, _, _, _, _, _))
.WillOnce(Return(Future<bool>(false)));
v1::agent::Call call;
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/tests/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer.cpp b/src/tests/containerizer.cpp
index c3bcb85..6b7d3ed 100644
--- a/src/tests/containerizer.cpp
+++ b/src/tests/containerizer.cpp
@@ -33,6 +33,7 @@ using testing::_;
using testing::Invoke;
using testing::Return;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerTermination;
using mesos::v1::executor::Mesos;
@@ -191,7 +192,8 @@ public:
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<string>& user,
- const SlaveID& slaveId)
+ const SlaveID& slaveId,
+ const Option<ContainerClass>& containerClass)
{
CHECK(!terminatedContainers.contains(containerId))
<< "Failed to launch nested container " << containerId
@@ -440,10 +442,10 @@ void TestContainerizer::setup()
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<string>& user,
- const SlaveID& slaveId) =
- &TestContainerizer::_launch;
+ const SlaveID& slaveId,
+ const Option<ContainerClass>&) = &TestContainerizer::_launch;
- EXPECT_CALL(*this, launch(_, _, _, _, _))
+ EXPECT_CALL(*this, launch(_, _, _, _, _, _))
.WillRepeatedly(Invoke(this, _launchNested));
EXPECT_CALL(*this, wait(_))
@@ -504,7 +506,8 @@ Future<bool> TestContainerizer::_launch(
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<string>& user,
- const SlaveID& slaveId)
+ const SlaveID& slaveId,
+ const Option<ContainerClass>& containerClass)
{
// Need to disambiguate for the compiler.
Future<bool> (TestContainerizerProcess::*launch)(
@@ -512,7 +515,9 @@ Future<bool> TestContainerizer::_launch(
const CommandInfo&,
const Option<ContainerInfo>&,
const Option<string>&,
- const SlaveID&) = &TestContainerizerProcess::launch;
+ const SlaveID&,
+ const Option<ContainerClass>& containerClass) =
+ &TestContainerizerProcess::launch;
return process::dispatch(
process.get(),
@@ -521,7 +526,8 @@ Future<bool> TestContainerizer::_launch(
commandInfo,
containerInfo,
user,
- slaveId);
+ slaveId,
+ containerClass);
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/727ce3d4/src/tests/containerizer.hpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer.hpp b/src/tests/containerizer.hpp
index 080b8fa..d799285 100644
--- a/src/tests/containerizer.hpp
+++ b/src/tests/containerizer.hpp
@@ -93,14 +93,15 @@ public:
const std::map<std::string, std::string>&,
bool checkpoint));
- MOCK_METHOD5(
+ MOCK_METHOD6(
launch,
process::Future<bool>(
const ContainerID& containerId,
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<std::string>& user,
- const SlaveID& slaveId));
+ const SlaveID& slaveId,
+ const Option<mesos::slave::ContainerClass>& containerClass));
MOCK_METHOD2(
update,
@@ -154,7 +155,8 @@ private:
const CommandInfo& commandInfo,
const Option<ContainerInfo>& containerInfo,
const Option<std::string>& user,
- const SlaveID& slaveId);
+ const SlaveID& slaveId,
+ const Option<mesos::slave::ContainerClass>& containerClass = None());
process::Future<Nothing> _update(
const ContainerID& containerId,
[07/11] mesos git commit: Added proper dependencies on the
'filesystem/linux' isolator.
Posted by ji...@apache.org.
Added proper dependencies on the 'filesystem/linux' isolator.
For some isolators, this meant adding an explicit dependency on
'filesystem/linux' and then removing any of their local calls to
'set_clone_namespaces(CLONE_NEWNS)'. For others, this meant simply
removing their explicit 'set_clone_namespaces(CLONE_NEWNS)' calls
since they are redundant with the one made by 'filesystem/linux'.
The 'cni' isolator is a special case, however, because it may need to
call 'set_clone_namespaces(CLONE_NEWNS)' even if the
'filesystem/posix' isolator is enabled. For this we added a comment.
Review: https://reviews.apache.org/r/53682/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/09d42454
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/09d42454
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/09d42454
Branch: refs/heads/master
Commit: 09d42454c01398e0b7b6588aab4488b68cb82435
Parents: 329f3ea
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 16:52:54 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:11 2016 -0800
----------------------------------------------------------------------
.../mesos/isolators/gpu/isolator.cpp | 18 +++++++++++++++---
.../mesos/isolators/namespaces/pid.cpp | 9 ++++++++-
.../mesos/isolators/volume/image.cpp | 10 +++++++++-
.../mesos/isolators/volume/sandbox_path.cpp | 6 ------
4 files changed, 32 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/09d42454/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
index 4bd3785..a3a140d 100644
--- a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
+++ b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
@@ -92,14 +92,17 @@ Try<Isolator*> NvidiaGpuIsolatorProcess::create(
const Flags& flags,
const NvidiaComponents& components)
{
- // Make sure the 'cgroups/devices' isolator is present and
- // precedes the GPU isolator.
+ // Make sure both the 'cgroups/devices' isolator and the
+ // 'filesystem/linux' isolators are present and precede the GPU
+ // isolator.
vector<string> tokens = strings::tokenize(flags.isolation, ",");
auto gpuIsolator =
std::find(tokens.begin(), tokens.end(), "gpu/nvidia");
auto devicesIsolator =
std::find(tokens.begin(), tokens.end(), "cgroups/devices");
+ auto filesystemIsolator =
+ std::find(tokens.begin(), tokens.end(), "filesystem/linux");
CHECK(gpuIsolator != tokens.end());
@@ -108,11 +111,21 @@ Try<Isolator*> NvidiaGpuIsolatorProcess::create(
" order to use the 'gpu/nvidia' isolator");
}
+ if (filesystemIsolator == tokens.end()) {
+ return Error("The 'filesystem/linux' isolator must be enabled in"
+ " order to use the 'gpu/nvidia' isolator");
+ }
+
if (devicesIsolator > gpuIsolator) {
return Error("'cgroups/devices' must precede 'gpu/nvidia'"
" in the --isolation flag");
}
+ if (filesystemIsolator > gpuIsolator) {
+ return Error("'filesystem/linux' must precede 'gpu/nvidia'"
+ " in the --isolation flag");
+ }
+
// Retrieve the cgroups devices hierarchy.
Result<string> hierarchy = cgroups::hierarchy(CGROUP_SUBSYSTEM_DEVICES_NAME);
@@ -329,7 +342,6 @@ Future<Option<ContainerLaunchInfo>> NvidiaGpuIsolatorProcess::_prepare(
}
ContainerLaunchInfo launchInfo;
- launchInfo.set_clone_namespaces(CLONE_NEWNS);
// Inject the Nvidia volume into the container.
//
http://git-wip-us.apache.org/repos/asf/mesos/blob/09d42454/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
index f3438b8..8ebf2e7 100644
--- a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
+++ b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
@@ -79,7 +79,14 @@ Future<Option<ContainerLaunchInfo>> NamespacesPidIsolatorProcess::prepare(
const ContainerConfig& containerConfig)
{
ContainerLaunchInfo launchInfo;
- launchInfo.set_clone_namespaces(CLONE_NEWPID | CLONE_NEWNS);
+
+ if (containerId.has_parent()) {
+ // If we are a nested container, then we want to enter our
+ // parent's pid namespace before cloning a new one.
+ launchInfo.set_enter_namespaces(CLONE_NEWPID);
+ }
+
+ launchInfo.set_clone_namespaces(CLONE_NEWPID);
// Mount /proc with standard options for the container's pid
// namespace to show the container's pids (and other /proc files),
http://git-wip-us.apache.org/repos/asf/mesos/blob/09d42454/src/slave/containerizer/mesos/isolators/volume/image.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/image.cpp b/src/slave/containerizer/mesos/isolators/volume/image.cpp
index ee9bd35..e954182 100644
--- a/src/slave/containerizer/mesos/isolators/volume/image.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/image.cpp
@@ -72,6 +72,15 @@ Try<Isolator*> VolumeImageIsolatorProcess::create(
const Flags& flags,
const Shared<Provisioner>& provisioner)
{
+ // Make sure 'filesystem/linux' isolator is used.
+ // NOTE: 'filesystem/linux' isolator will make sure mounts in the
+ // child mount namespace will not be propagated back to the host
+ // mount namespace.
+ if (!strings::contains(flags.isolation, "filesystem/linux")) {
+ return Error("'filesystem/linux' must be enabled"
+ " to create the volume image isolator");
+ }
+
process::Owned<MesosIsolatorProcess> process(
new VolumeImageIsolatorProcess(flags, provisioner));
@@ -180,7 +189,6 @@ Future<Option<ContainerLaunchInfo>> VolumeImageIsolatorProcess::_prepare(
const list<Future<ProvisionInfo>>& futures)
{
ContainerLaunchInfo launchInfo;
- launchInfo.set_clone_namespaces(CLONE_NEWNS);
vector<string> messages;
vector<string> sources;
http://git-wip-us.apache.org/repos/asf/mesos/blob/09d42454/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
index a6f9794..cb7aa4f 100644
--- a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
@@ -120,12 +120,6 @@ Future<Option<ContainerLaunchInfo>> VolumeSandboxPathIsolatorProcess::prepare(
ContainerLaunchInfo launchInfo;
-#ifdef __linux__
- if (bindMountSupported) {
- launchInfo.set_clone_namespaces(CLONE_NEWNS);
- }
-#endif // __linux__
-
foreach (const Volume& volume, containerInfo.volumes()) {
if (!volume.has_source() ||
!volume.source().has_type() ||
[02/11] mesos git commit: Removed unnecessary 'parentHooks' parameter
from 'Launcher::fork()'.
Posted by ji...@apache.org.
Removed unnecessary 'parentHooks' parameter from 'Launcher::fork()'.
Review: https://reviews.apache.org/r/53350/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/0f3eabcf
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/0f3eabcf
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/0f3eabcf
Branch: refs/heads/master
Commit: 0f3eabcfaed5e449988c239d312f17d3b25a04ca
Parents: b15b46a
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 16:14:35 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 16:14:35 2016 -0800
----------------------------------------------------------------------
src/slave/containerizer/mesos/launcher.cpp | 5 +++--
src/slave/containerizer/mesos/launcher.hpp | 6 ++----
src/slave/containerizer/mesos/linux_launcher.cpp | 14 ++++++--------
src/slave/containerizer/mesos/linux_launcher.hpp | 3 +--
src/tests/containerizer/launcher.cpp | 6 +++---
src/tests/containerizer/launcher.hpp | 5 ++---
6 files changed, 17 insertions(+), 22 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/0f3eabcf/src/slave/containerizer/mesos/launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launcher.cpp b/src/slave/containerizer/mesos/launcher.cpp
index b45313f..bc33f19 100644
--- a/src/slave/containerizer/mesos/launcher.cpp
+++ b/src/slave/containerizer/mesos/launcher.cpp
@@ -87,8 +87,7 @@ Try<pid_t> PosixLauncher::fork(
const Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<map<string, string>>& environment,
- const Option<int>& namespaces,
- vector<process::Subprocess::ParentHook> parentHooks)
+ const Option<int>& namespaces)
{
if (namespaces.isSome() && namespaces.get() != 0) {
return Error("Posix launcher does not support namespaces");
@@ -101,6 +100,8 @@ Try<pid_t> PosixLauncher::fork(
// If we are on systemd, then extend the life of the child. Any
// grandchildren's lives will also be extended.
+ vector<process::Subprocess::ParentHook> parentHooks;
+
#ifdef __linux__
if (systemd::enabled()) {
parentHooks.emplace_back(Subprocess::ParentHook(
http://git-wip-us.apache.org/repos/asf/mesos/blob/0f3eabcf/src/slave/containerizer/mesos/launcher.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launcher.hpp b/src/slave/containerizer/mesos/launcher.hpp
index 6ceb02d..c1a390a 100644
--- a/src/slave/containerizer/mesos/launcher.hpp
+++ b/src/slave/containerizer/mesos/launcher.hpp
@@ -69,8 +69,7 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces,
- std::vector<process::Subprocess::ParentHook> parentHooks = {}) = 0;
+ const Option<int>& namespaces) = 0;
// Kill all processes in the containerized context.
virtual process::Future<Nothing> destroy(const ContainerID& containerId) = 0;
@@ -105,8 +104,7 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces,
- std::vector<process::Subprocess::ParentHook> parentHooks = {});
+ const Option<int>& namespaces);
virtual process::Future<Nothing> destroy(const ContainerID& containerId);
http://git-wip-us.apache.org/repos/asf/mesos/blob/0f3eabcf/src/slave/containerizer/mesos/linux_launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/linux_launcher.cpp b/src/slave/containerizer/mesos/linux_launcher.cpp
index 0305d14..e96090f 100644
--- a/src/slave/containerizer/mesos/linux_launcher.cpp
+++ b/src/slave/containerizer/mesos/linux_launcher.cpp
@@ -79,8 +79,7 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces,
- std::vector<process::Subprocess::ParentHook> parentHooks);
+ const Option<int>& namespaces);
virtual process::Future<Nothing> destroy(const ContainerID& containerId);
@@ -211,8 +210,7 @@ Try<pid_t> LinuxLauncher::fork(
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<map<string, string>>& environment,
- const Option<int>& namespaces,
- vector<Subprocess::ParentHook> parentHooks)
+ const Option<int>& namespaces)
{
return dispatch(
process.get(),
@@ -225,8 +223,7 @@ Try<pid_t> LinuxLauncher::fork(
err,
flags,
environment,
- namespaces,
- parentHooks).get();
+ namespaces).get();
}
@@ -388,8 +385,7 @@ Try<pid_t> LinuxLauncherProcess::fork(
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<map<string, string>>& environment,
- const Option<int>& namespaces,
- vector<Subprocess::ParentHook> parentHooks)
+ const Option<int>& namespaces)
{
// Make sure this container (nested or not) is unique.
if (containers.contains(containerId)) {
@@ -434,6 +430,8 @@ Try<pid_t> LinuxLauncherProcess::fork(
// Hook to extend the life of the child (and all of its
// descendants) using a systemd slice.
+ vector<Subprocess::ParentHook> parentHooks;
+
if (systemdHierarchy.isSome()) {
parentHooks.emplace_back(Subprocess::ParentHook([](pid_t child) {
return systemd::mesos::extendLifetime(child);
http://git-wip-us.apache.org/repos/asf/mesos/blob/0f3eabcf/src/slave/containerizer/mesos/linux_launcher.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/linux_launcher.hpp b/src/slave/containerizer/mesos/linux_launcher.hpp
index d235305..356d4de 100644
--- a/src/slave/containerizer/mesos/linux_launcher.hpp
+++ b/src/slave/containerizer/mesos/linux_launcher.hpp
@@ -51,8 +51,7 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces,
- std::vector<process::Subprocess::ParentHook> parentHooks);
+ const Option<int>& namespaces);
virtual process::Future<Nothing> destroy(const ContainerID& containerId);
http://git-wip-us.apache.org/repos/asf/mesos/blob/0f3eabcf/src/tests/containerizer/launcher.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/launcher.cpp b/src/tests/containerizer/launcher.cpp
index a92d989..51ae4f9 100644
--- a/src/tests/containerizer/launcher.cpp
+++ b/src/tests/containerizer/launcher.cpp
@@ -30,7 +30,7 @@ ACTION_P(InvokeRecover, launcher)
ACTION_P(InvokeFork, launcher)
{
return launcher->real->fork(
- arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
@@ -51,9 +51,9 @@ TestLauncher::TestLauncher(const process::Owned<slave::Launcher>& _real)
EXPECT_CALL(*this, recover(_))
.WillRepeatedly(DoDefault());
- ON_CALL(*this, fork(_, _, _, _, _, _, _, _, _, _))
+ ON_CALL(*this, fork(_, _, _, _, _, _, _, _, _))
.WillByDefault(InvokeFork(this));
- EXPECT_CALL(*this, fork(_, _, _, _, _, _, _, _, _, _))
+ EXPECT_CALL(*this, fork(_, _, _, _, _, _, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, destroy(_))
http://git-wip-us.apache.org/repos/asf/mesos/blob/0f3eabcf/src/tests/containerizer/launcher.hpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/launcher.hpp b/src/tests/containerizer/launcher.hpp
index 773b458..5dcc391 100644
--- a/src/tests/containerizer/launcher.hpp
+++ b/src/tests/containerizer/launcher.hpp
@@ -56,7 +56,7 @@ public:
process::Future<hashset<ContainerID>>(
const std::list<mesos::slave::ContainerState>& states));
- MOCK_METHOD10(
+ MOCK_METHOD9(
fork,
Try<pid_t>(
const ContainerID& containerId,
@@ -67,8 +67,7 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& env,
- const Option<int>& namespaces,
- std::vector<process::Subprocess::ParentHook> parentHooks));
+ const Option<int>& namespaces));
MOCK_METHOD1(
destroy,
[03/11] mesos git commit: Added a flag to optionally skip the
multithreaded check in setns().
Posted by ji...@apache.org.
Added a flag to optionally skip the multithreaded check in setns().
Review: https://reviews.apache.org/r/53681/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/ed1b4bc6
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/ed1b4bc6
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/ed1b4bc6
Branch: refs/heads/master
Commit: ed1b4bc62486e06a5e76922bcc2f9bd494ab01e8
Parents: 0f3eabc
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 16:14:51 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:07 2016 -0800
----------------------------------------------------------------------
src/linux/ns.hpp | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/ed1b4bc6/src/linux/ns.hpp
----------------------------------------------------------------------
diff --git a/src/linux/ns.hpp b/src/linux/ns.hpp
index 76db0dc..010a1fa 100644
--- a/src/linux/ns.hpp
+++ b/src/linux/ns.hpp
@@ -154,16 +154,21 @@ inline std::set<int> nstypes()
// allow a process with multiple threads to call this function because
// it will lead to some weird situations where different threads of a
// process are in different namespaces.
-inline Try<Nothing> setns(const std::string& path, const std::string& ns)
+inline Try<Nothing> setns(
+ const std::string& path,
+ const std::string& ns,
+ bool checkMultithreaded = true)
{
- // Return error if there're multiple threads in the calling process.
- Try<std::set<pid_t>> threads = proc::threads(::getpid());
- if (threads.isError()) {
- return Error(
- "Failed to get the threads of the current process: " +
- threads.error());
- } else if (threads.get().size() > 1) {
- return Error("Multiple threads exist in the current process");
+ if (checkMultithreaded) {
+ // Return error if there're multiple threads in the calling process.
+ Try<std::set<pid_t>> threads = proc::threads(::getpid());
+ if (threads.isError()) {
+ return Error(
+ "Failed to get the threads of the current process: " +
+ threads.error());
+ } else if (threads.get().size() > 1) {
+ return Error("Multiple threads exist in the current process");
+ }
}
if (ns::namespaces().count(ns) == 0) {
[08/11] mesos git commit: Updated namespace isolators to customize
based on 'ContainerClass'.
Posted by ji...@apache.org.
Updated namespace isolators to customize based on 'ContainerClass'.
The namespace-related isolators now do different things depending on
whether they are launching a "normal" nested container or a "debug"
nested container. Normal nested containers clone a new mount namespace
as well as a new pid namespace. Debug nested cotnainers do not -- they
simply inherit these namespaces from their parent.
Review: https://reviews.apache.org/r/53354/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/0dafc555
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/0dafc555
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/0dafc555
Branch: refs/heads/master
Commit: 0dafc55529e386e97e6384e1b8e5a19a84899b63
Parents: a012efa
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 17:01:23 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:11 2016 -0800
----------------------------------------------------------------------
src/slave/containerizer/mesos/containerizer.cpp | 6 -
.../mesos/isolators/filesystem/linux.cpp | 24 ++++
.../mesos/isolators/gpu/isolator.cpp | 21 +++-
.../mesos/isolators/namespaces/pid.cpp | 9 ++
.../mesos/isolators/network/cni/cni.cpp | 56 ++++++---
.../mesos/isolators/volume/image.cpp | 6 +
.../mesos/isolators/volume/sandbox_path.cpp | 7 ++
.../containerizer/mesos/linux_launcher.cpp | 6 +
.../nested_mesos_containerizer_tests.cpp | 117 +++++++++++++++++++
9 files changed, 225 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index 3c3bee4..2741497 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -1230,12 +1230,6 @@ Future<bool> MesosContainerizerProcess::_launch(
Option<int> enterNamespaces = None();
Option<int> cloneNamespaces = None();
- // TODO(klueska): Remove the following once we update
- // isolators to fill enterNamespaces for us.
- if (containerId.has_parent()) {
- enterNamespaces = CLONE_NEWUTS | CLONE_NEWNET | CLONE_NEWPID;
- }
-
CHECK_READY(container->launchInfos);
foreach (const Option<ContainerLaunchInfo>& launchInfo,
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
index 6535375..8f024d0 100644
--- a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
+++ b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
@@ -53,6 +53,7 @@ using std::ostringstream;
using std::string;
using std::vector;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerState;
using mesos::slave::ContainerLaunchInfo;
@@ -307,6 +308,29 @@ Future<Option<ContainerLaunchInfo>> LinuxFilesystemIsolatorProcess::prepare(
const ContainerID& containerId,
const ContainerConfig& containerConfig)
{
+ // If we are a nested container in the `DEBUG` class, then we only
+ // use this isolator to indicate that we should enter our parent's
+ // MOUNT namespace. We don't want to clone a new MOUNT namespace or
+ // run any new pre-exec commands in it. For now, we also don't
+ // support provisioning a new filesystem or setting a `rootfs` for
+ // the container. We also don't support mounting any volumes.
+ if (containerId.has_parent() &&
+ containerConfig.has_container_class() &&
+ containerConfig.container_class() == ContainerClass::DEBUG) {
+ if (containerConfig.has_rootfs()) {
+ return Failure("A 'rootfs' cannot be set for DEBUG containers");
+ }
+
+ if (containerConfig.has_container_info() &&
+ containerConfig.container_info().volumes().size() > 0) {
+ return Failure("Volumes not supported for DEBUG containers");
+ }
+
+ ContainerLaunchInfo launchInfo;
+ launchInfo.set_enter_namespaces(CLONE_NEWNS);
+ return launchInfo;
+ }
+
if (infos.contains(containerId)) {
return Failure("Container has already been prepared");
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
index a3a140d..a3b9fe7 100644
--- a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
+++ b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
@@ -53,6 +53,7 @@ using cgroups::devices::Entry;
using docker::spec::v1::ImageManifest;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerLimitation;
@@ -283,13 +284,21 @@ Future<Option<ContainerLaunchInfo>> NvidiaGpuIsolatorProcess::prepare(
const ContainerID& containerId,
const mesos::slave::ContainerConfig& containerConfig)
{
- // If we are a nested container, we don't need to maintain an `Info()`
- // struct about the container since we don't allocate GPUs to it
- // directly (we only allocate GPUs to top-level containers, and they
- // automatically get shared by nested containers). However, we do
- // still need to mount the necessary Nvidia libraries into the
- // container. We call `_prepare()` directly to do this for us.
if (containerId.has_parent()) {
+ // If we are a nested container in the `DEBUG` class, then we
+ // don't need to do anything special to prepare ourselves for GPU
+ // support. All Nvidia volumes will be inherited from our parent.
+ if (containerConfig.has_container_class() &&
+ containerConfig.container_class() == ContainerClass::DEBUG) {
+ return None();
+ }
+
+ // If we are a nested container in a different class, we don't
+ // need to maintain an `Info()` struct about the container (since
+ // we don't directly allocate any GPUs to it), but we do need to
+ // mount the necessary Nvidia libraries into the container (since
+ // we live in a different mount namespace than our parent). We
+ // directly call `_prepare()` to do this for us.
return _prepare(containerConfig);
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
index 8ebf2e7..5bf5ffb 100644
--- a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
+++ b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
@@ -25,6 +25,7 @@
using process::Future;
using process::Owned;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::Isolator;
@@ -84,6 +85,14 @@ Future<Option<ContainerLaunchInfo>> NamespacesPidIsolatorProcess::prepare(
// If we are a nested container, then we want to enter our
// parent's pid namespace before cloning a new one.
launchInfo.set_enter_namespaces(CLONE_NEWPID);
+
+ // However, if we are a nested container in the `DEBUG` class,
+ // then we don't want to clone a new PID namespace at all, so we
+ // short cirucuit here.
+ if (containerConfig.has_container_class() &&
+ containerConfig.container_class() == ContainerClass::DEBUG) {
+ return launchInfo;
+ }
}
launchInfo.set_clone_namespaces(CLONE_NEWPID);
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
index 74bb6eb..3b2d4db 100644
--- a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
+++ b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
@@ -54,6 +54,7 @@ using process::Owned;
using process::PID;
using process::Subprocess;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerLimitation;
@@ -590,6 +591,8 @@ Future<Option<ContainerLaunchInfo>> NetworkCniIsolatorProcess::prepare(
// * Cases where the containers don't need a new mount namespace:
// a) Containers (nested or stand alone) join the host network
// without an image.
+ // b) Nested DEBUG containers join the same mount namespace as
+ // their parent.
// * Cases where the container needs a new mount namespace:
// a) Containers (nested or stand alone) join the host network
// with an image.
@@ -610,19 +613,40 @@ Future<Option<ContainerLaunchInfo>> NetworkCniIsolatorProcess::prepare(
infos.put(containerId, info);
}
- // NOTE: No additional namespace needed. The container shares the
- // same network and UTS namesapces with the host. If container has
- // a rootfs, the filesystem/linux isolator will put the container
- // in a new mount namespace.
+ // NOTE: No additional namespaces needed. The container shares the
+ // same network and UTS namespaces with the host. If the container
+ // has a rootfs, the filesystem/linux isolator will put the
+ // container in a new mount namespace. If the *parent* container
+ // has a rootfs, the filesystem/linux isolator will properly set
+ // the MNT namespace to enter. If the parent does not have a
+ // rootfs, it will join the host network and there are no
+ // namespaces it needs to enter.
return None();
} else {
// This is the case where the container is joining a non-host
- // network namespace.
- if (containerConfig.has_rootfs()) {
- Owned<Info> info(new Info(containerNetworks, containerConfig.rootfs()));
- infos.put(containerId, info);
+ // network namespace. Non-DEBUG containers will need a new mount
+ // namespaces to bind mount their network files (/etc/hosts,
+ // /etc/hostname, /etc/resolv.conf) which will be different than
+ // those on the host file system.
+ //
+ // Unlike other isolators, we can't simply rely on the
+ // `filesystem/linux` isolator to give this container a new
+ // mount namespace (because we allow the `filesystem/posix`
+ // isolator to be used here). We must set the clone flags
+ // ourselves explicitly.
+
+ if (containerId.has_parent() &&
+ containerConfig.has_container_class() &&
+ containerConfig.container_class() == ContainerClass::DEBUG) {
+ // Nested DEBUG containers never need a new MOUNT namespace, so
+ // we don't mantain information about them in the `infos` map.
} else {
- infos.put(containerId, Owned<Info>(new Info(containerNetworks)));
+ if (containerConfig.has_rootfs()) {
+ Owned<Info> info(new Info(containerNetworks, containerConfig.rootfs()));
+ infos.put(containerId, info);
+ } else {
+ infos.put(containerId, Owned<Info>(new Info(containerNetworks)));
+ }
}
ContainerLaunchInfo launchInfo;
@@ -659,12 +683,14 @@ Future<Option<ContainerLaunchInfo>> NetworkCniIsolatorProcess::prepare(
}
} else {
// This is a nested container. This shares the parent's network
- // and UTS namespace. We still need to give this container a new
- // mount namespace since its joining a non-host network and
- // therefore we will need to bind mount its network files
- // (/etc/hosts, /etc/hostname, /etc/resolv.conf) which will be
- // different than those on the host file system.
- launchInfo.set_clone_namespaces(CLONE_NEWNS);
+ // and UTS namespace. For non-DEBUG containers it also needs a
+ // new mount namespace.
+ launchInfo.set_enter_namespaces(CLONE_NEWNET | CLONE_NEWUTS);
+
+ if (!containerConfig.has_container_class() ||
+ containerConfig.container_class() != ContainerClass::DEBUG) {
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
+ }
}
return launchInfo;
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/isolators/volume/image.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/image.cpp b/src/slave/containerizer/mesos/isolators/volume/image.cpp
index e954182..c89af3e 100644
--- a/src/slave/containerizer/mesos/isolators/volume/image.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/image.cpp
@@ -43,6 +43,7 @@ using process::Owned;
using process::PID;
using process::Shared;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::Isolator;
@@ -110,6 +111,11 @@ Future<Option<ContainerLaunchInfo>> VolumeImageIsolatorProcess::prepare(
continue;
}
+ if (containerConfig.has_container_class() &&
+ containerConfig.container_class() == ContainerClass::DEBUG) {
+ return Failure("Image volume is not supported for DEBUG containers");
+ }
+
// Determine the target of the mount. The mount target
// is determined by 'container_path'.
string target;
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
index cb7aa4f..6f7304d 100644
--- a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
@@ -36,6 +36,7 @@ using process::Failure;
using process::Future;
using process::Owned;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
using mesos::slave::ContainerState;
@@ -127,6 +128,12 @@ Future<Option<ContainerLaunchInfo>> VolumeSandboxPathIsolatorProcess::prepare(
continue;
}
+ if (containerConfig.has_container_class() &&
+ containerConfig.container_class() == ContainerClass::DEBUG) {
+ return Failure(
+ "SANDBOX_PATH volume is not supported for DEBUG containers");
+ }
+
if (!volume.source().has_sandbox_path()) {
return Failure("volume.source.sandbox_path is not specified");
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/slave/containerizer/mesos/linux_launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/linux_launcher.cpp b/src/slave/containerizer/mesos/linux_launcher.cpp
index 2c55d7b..a3409dc 100644
--- a/src/slave/containerizer/mesos/linux_launcher.cpp
+++ b/src/slave/containerizer/mesos/linux_launcher.cpp
@@ -416,6 +416,12 @@ Try<pid_t> LinuxLauncherProcess::fork(
target = container->pid.get();
}
+ // Ensure we didn't pass `enterNamespaces`
+ // if we aren't forking a nested contiainer.
+ if (!containerId.has_parent() && enterNamespaces.isSome()) {
+ return Error("Cannot enter parent namespaces for non-nested container");
+ }
+
int enterFlags = enterNamespaces.isSome() ? enterNamespaces.get() : 0;
int cloneFlags = cloneNamespaces.isSome() ? cloneNamespaces.get() : 0;
http://git-wip-us.apache.org/repos/asf/mesos/blob/0dafc555/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/nested_mesos_containerizer_tests.cpp b/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
index e6c690c..20bc9d5 100644
--- a/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
+++ b/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
@@ -58,6 +58,7 @@ using mesos::internal::slave::state::FrameworkState;
using mesos::internal::slave::state::RunState;
using mesos::internal::slave::state::SlaveState;
+using mesos::slave::ContainerClass;
using mesos::slave::ContainerState;
using mesos::slave::ContainerTermination;
@@ -232,6 +233,122 @@ TEST_F(NestedMesosContainerizerTest, ROOT_CGROUPS_LaunchNested)
}
+TEST_F(NestedMesosContainerizerTest,
+ ROOT_CGROUPS_LaunchNestedDebugCheckPidNamespace)
+{
+ slave::Flags flags = CreateSlaveFlags();
+ flags.launcher = "linux";
+ flags.isolation = "cgroups/cpu,filesystem/linux,namespaces/pid";
+
+ Fetcher fetcher;
+
+ Try<MesosContainerizer*> create = MesosContainerizer::create(
+ flags,
+ true,
+ &fetcher);
+
+ ASSERT_SOME(create);
+
+ Owned<MesosContainerizer> containerizer(create.get());
+
+ SlaveState state;
+ state.id = SlaveID();
+
+ AWAIT_READY(containerizer->recover(state));
+
+ ContainerID containerId;
+ containerId.set_value(UUID::random().toString());
+
+ Try<string> directory = environment->mkdtemp();
+ ASSERT_SOME(directory);
+
+ Future<bool> launch = containerizer->launch(
+ containerId,
+ None(),
+ createExecutorInfo("executor", "sleep 1000", "cpus:1"),
+ directory.get(),
+ None(),
+ state.id,
+ map<string, string>(),
+ true); // TODO(benh): Ever want to test not checkpointing?
+
+ AWAIT_ASSERT_TRUE(launch);
+
+ // Now launch nested container.
+ ContainerID nestedContainerId;
+ nestedContainerId.mutable_parent()->CopyFrom(containerId);
+ nestedContainerId.set_value(UUID::random().toString());
+
+ // Launch the nested container with the `ps | wc -l` command and
+ // launch the container without a `ContainerClass`. With this
+ // default setting, we should request to clone a new PID namespace.
+ //
+ // We expect to see exactly 6 lines of output from `ps`.
+ //
+ // 1) The 'ps' header
+ // 2) The init process of the container (i.e. `mesos-containerizer`).
+ // 3) The executor of the container (i.e. `mesos-executor`).
+ // 4) `sh`
+ // 5) `wc -l`
+ // 6) `ps`
+ launch = containerizer->launch(
+ nestedContainerId,
+ createCommandInfo(
+ "PS_LINES=`ps | wc -l`;"
+ "if [ ${PS_LINES} -ne 6 ]; then"
+ " exit ${PS_LINES};"
+ "fi;"),
+ None(),
+ None(),
+ state.id);
+
+ AWAIT_ASSERT_TRUE(launch);
+
+ Future<Option<ContainerTermination>> wait = containerizer->wait(
+ nestedContainerId);
+
+ AWAIT_READY(wait);
+ ASSERT_SOME(wait.get());
+ ASSERT_TRUE(wait.get()->has_status());
+ EXPECT_WEXITSTATUS_EQ(0, wait.get()->status());
+
+ // Relaunch the nested container with the `ps | wc -l` command and
+ // set the container class as `DEBUG`. In this class, we don't
+ // clone a new PID namespace.
+ //
+ // We expect to see much more than 6 lines of output from `ps`.
+ launch = containerizer->launch(
+ nestedContainerId,
+ createCommandInfo(
+ "PS_LINES=`ps | wc -l`;"
+ "if [ ${PS_LINES} -le 6 ]; then"
+ " exit ${PS_LINES};"
+ "fi;"),
+ None(),
+ None(),
+ state.id,
+ ContainerClass::DEBUG);
+
+ AWAIT_ASSERT_TRUE(launch);
+
+ wait = containerizer->wait(nestedContainerId);
+
+ AWAIT_READY(wait);
+ ASSERT_SOME(wait.get());
+ ASSERT_TRUE(wait.get()->has_status());
+ EXPECT_WEXITSTATUS_EQ(0, wait.get()->status());
+
+ wait = containerizer->wait(containerId);
+
+ containerizer->destroy(containerId);
+
+ AWAIT_READY(wait);
+ ASSERT_SOME(wait.get());
+ ASSERT_TRUE(wait.get()->has_status());
+ EXPECT_WTERMSIG_EQ(SIGKILL, wait.get()->status());
+}
+
+
TEST_F(NestedMesosContainerizerTest, ROOT_CGROUPS_DestroyNested)
{
slave::Flags flags = CreateSlaveFlags();
[11/11] mesos git commit: Added special case for entering "mnt"
namespaces for DEBUG containers.
Posted by ji...@apache.org.
Added special case for entering "mnt" namespaces for DEBUG containers.
Until we switch over to the default (a.k.a. "pod" executor) for
launching command tasks, we need to special case which `pid` we use
for entering the `mnt` namespace of a parent container. Specifically,
we need to enter the `mnt` namespace of the process representing the
command task itself, not the `mnt` namespace of the `init` process of
the container or the `executor` of the container because these run in
the same `mnt` namespace as the agent (not the task).
Unfortunately, there is no easy way to get the `pid` of tasks launched
with the command executor because we only checkpoint the `pid` of the
`init` process of these containers. For now, we compensate for this by
simply walking the process tree from the container's `init` process up
to 2-levels down (where the task process would exist) and look to see
if any process along the way has a different `mnt` namespace. If it
does, we return a reference to its `pid` as the `pid` for entering the
`mnt` namespace of the container. Otherwise, we return the `init`
process's `pid`.
We then pass this pid to the `mesos-containerizer launch` binary and
have it set the namespace, rather than letting the `ns::clone()` call
do it for us. This is important because otherwise we wouldn't be able
to find the `mesos-containerizer launch` itself (it only exists in the
host mount namespace!).
Review: https://reviews.apache.org/r/53586/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/757d2804
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/757d2804
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/757d2804
Branch: refs/heads/master
Commit: 757d2804d09da457103e67c843fdcebf52016097
Parents: 781b968
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 18:32:07 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:11 2016 -0800
----------------------------------------------------------------------
src/slave/containerizer/mesos/containerizer.cpp | 68 +++++++++--
src/slave/containerizer/mesos/launch.cpp | 20 ++++
src/slave/containerizer/mesos/launch.hpp | 1 +
src/slave/containerizer/mesos/utils.cpp | 90 ++++++++++++++
src/slave/containerizer/mesos/utils.hpp | 7 ++
.../nested_mesos_containerizer_tests.cpp | 119 +++++++++++++++++++
6 files changed, 293 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/757d2804/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index 2741497..ec4ae32 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -1201,16 +1201,21 @@ Future<bool> MesosContainerizerProcess::_launch(
environment.values[key] = value;
}
- // TODO(jieyu): Consider moving this to 'executorEnvironment' and
- // consolidating with docker containerizer.
- //
- // NOTE: For the command executor case, although it uses the host
- // filesystem for itself, we still set 'MESOS_SANDBOX' according to
- // the root filesystem of the task (if specified). Command executor
- // itself does not use this environment variable.
- environment.values["MESOS_SANDBOX"] = container->config.has_rootfs()
- ? flags.sandbox_directory
- : container->config.directory();
+ // TODO(klueska): Remove the check below once we have a good way of
+ // setting the sandbox directory for DEBUG containers.
+ if (!container->config.has_container_class() ||
+ container->config.container_class() != ContainerClass::DEBUG) {
+ // TODO(jieyu): Consider moving this to 'executorEnvironment' and
+ // consolidating with docker containerizer.
+ //
+ // NOTE: For the command executor case, although it uses the host
+ // filesystem for itself, we still set 'MESOS_SANDBOX' according to
+ // the root filesystem of the task (if specified). Command executor
+ // itself does not use this environment variable.
+ environment.values["MESOS_SANDBOX"] = container->config.has_rootfs()
+ ? flags.sandbox_directory
+ : container->config.directory();
+ }
// NOTE: Command task is a special case. Even if the container
// config has a root filesystem, the executor container still uses
@@ -1428,7 +1433,15 @@ Future<bool> MesosContainerizerProcess::_launch(
<< "host filesystem";
}
- launchFlags.working_directory = container->config.directory();
+ // TODO(klueska): Debug containers should set their working
+ // directory to their sandbox directory (once we know how to set
+ // that properly).
+ if (container->config.has_container_class() &&
+ container->config.container_class() == ContainerClass::DEBUG) {
+ launchFlags.working_directory = None();
+ } else {
+ launchFlags.working_directory = container->config.directory();
+ }
} else {
launchFlags.working_directory = workingDirectory.isSome()
? workingDirectory
@@ -1493,6 +1506,37 @@ Future<bool> MesosContainerizerProcess::_launch(
VLOG(1) << "Launching '" << MESOS_CONTAINERIZER << "' with flags '"
<< launchFlags << "'";
+ // For now we need to special case entering a parent container's
+ // mount namespace. We do this to ensure that we have access to
+ // the binary we launch with `launcher->fork()`.
+ //
+ // TODO(klueska): Remove this special case once we pull
+ // the container's `init` process out of its container.
+ Option<int> _enterNamespaces = enterNamespaces;
+
+#ifdef __linux__
+ if (enterNamespaces.isSome() && (enterNamespaces.get() & CLONE_NEWNS)) {
+ CHECK(containerId.has_parent());
+ if (!containers_.contains(containerId.parent())) {
+ return Failure("Unknown parent container");
+ }
+ if (containers_.at(containerId.parent())->pid.isNone()) {
+ return Failure("Unknown parent container pid");
+ }
+
+ pid_t parentPid = containers_.at(containerId.parent())->pid.get();
+
+ Try<pid_t> mountNamespaceTarget = getMountNamespaceTarget(parentPid);
+ if (mountNamespaceTarget.isError()) {
+ return Failure("Cannot get target mount namespace from process"
+ " '" + stringify(parentPid) + "'");
+ }
+
+ launchFlags.namespace_mnt_target = mountNamespaceTarget.get();
+ _enterNamespaces = enterNamespaces.get() & ~CLONE_NEWNS;
+ }
+#endif // __linux__
+
// Fork the child using launcher.
vector<string> argv(2);
argv[0] = MESOS_CONTAINERIZER;
@@ -1510,7 +1554,7 @@ Future<bool> MesosContainerizerProcess::_launch(
&launchFlags,
launchEnvironment,
// 'enterNamespaces' will be ignored by PosixLauncher.
- enterNamespaces,
+ _enterNamespaces,
// 'cloneNamespaces' will be ignored by PosixLauncher.
cloneNamespaces);
http://git-wip-us.apache.org/repos/asf/mesos/blob/757d2804/src/slave/containerizer/mesos/launch.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.cpp b/src/slave/containerizer/mesos/launch.cpp
index 181d833..320e427 100644
--- a/src/slave/containerizer/mesos/launch.cpp
+++ b/src/slave/containerizer/mesos/launch.cpp
@@ -146,6 +146,11 @@ MesosContainerizerLaunch::Flags::Flags()
"capabilities",
"Capabilities the command can use.");
+ add(&Flags::namespace_mnt_target,
+ "namespace_mnt_target",
+ "The target 'pid' of the process whose mount namespace we'd like\n"
+ "to enter before executing the command.");
+
add(&Flags::unshare_namespace_mnt,
"unshare_namespace_mnt",
"Whether to launch the command in a new mount namespace.",
@@ -391,6 +396,21 @@ int MesosContainerizerLaunch::execute()
}
#ifdef __linux__
+ if (flags.namespace_mnt_target.isSome()) {
+ string path = path::join(
+ "/proc",
+ stringify(flags.namespace_mnt_target.get()),
+ "ns",
+ "mnt");
+
+ Try<Nothing> setns = ns::setns(path, "mnt", false);
+ if (setns.isError()) {
+ cerr << "Failed to enter mount namespace: "
+ << setns.error() << endl;
+ exitWithStatus(EXIT_FAILURE);
+ }
+ }
+
if (flags.unshare_namespace_mnt) {
if (unshare(CLONE_NEWNS) != 0) {
cerr << "Failed to unshare mount namespace: "
http://git-wip-us.apache.org/repos/asf/mesos/blob/757d2804/src/slave/containerizer/mesos/launch.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launch.hpp b/src/slave/containerizer/mesos/launch.hpp
index 8b23c1b..155e3c5 100644
--- a/src/slave/containerizer/mesos/launch.hpp
+++ b/src/slave/containerizer/mesos/launch.hpp
@@ -52,6 +52,7 @@ public:
Option<JSON::Array> pre_exec_commands;
#ifdef __linux__
Option<CapabilityInfo> capabilities;
+ Option<pid_t> namespace_mnt_target;
bool unshare_namespace_mnt;
#endif // __linux__
};
http://git-wip-us.apache.org/repos/asf/mesos/blob/757d2804/src/slave/containerizer/mesos/utils.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/utils.cpp b/src/slave/containerizer/mesos/utils.cpp
index 237aea4..4e2a014 100644
--- a/src/slave/containerizer/mesos/utils.cpp
+++ b/src/slave/containerizer/mesos/utils.cpp
@@ -14,8 +14,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <set>
+
+#include <stout/os.hpp>
+#include <stout/try.hpp>
+
+#ifdef __linux__
+#include "linux/ns.hpp"
+#endif // __linux__
+
#include "slave/containerizer/mesos/utils.hpp"
+using std::set;
+
namespace mesos {
namespace internal {
namespace slave {
@@ -35,6 +46,85 @@ ContainerID getRootContainerId(const ContainerID& containerId)
return rootContainerId;
}
+
+#ifdef __linux__
+// This function can be used to find a new target `pid` for entering
+// the `mnt` namespace of a container (if necessary).
+//
+// Until we switch over to the default (a.k.a. "pod" executor) for
+// launching command tasks, we need to special case which `pid` we
+// use for entering the `mnt` namespace of a parent container.
+// Specifically, we need to enter the `mnt` namespace of the
+// process representing the command task itself, not the `mnt`
+// namespace of the `init` process of the container or the
+// `executor` of the container because these run in the same `mnt`
+// namespace as the agent (not the task).
+//
+// Unfortunately, there is no easy way to get the `pid` of tasks
+// launched with the command executor because we only checkpoint the
+// `pid` of the `init` process of these containers. For now, we
+// compensate for this by simply walking the process tree from the
+// container's `init` process up to 2-levels down (where the task
+// process would exist) and look to see if any process along the way
+// has a different `mnt` namespace. If it does, we return a reference
+// to its `pid` as the `pid` for entering the `mnt` namespace of the
+// container. Otherwise, we return the `init` process's `pid`.
+//
+// TODO(klueska): Remove this function once we start launching command
+// tasks with the default (a.k.a. "pod" executor).
+Try<pid_t> getMountNamespaceTarget(pid_t parent)
+{
+ Try<ino_t> parentNamespace = ns::getns(parent, "mnt");
+ if (parentNamespace.isError()) {
+ return Error("Cannot get 'mnt' namespace for"
+ " process '" + stringify(parent) + "'");
+ }
+
+ // Search for a new mount namespace in all direct children.
+ Try<set<pid_t>> children = os::children(parent, false);
+ if (children.isError()) {
+ return Error("Cannot get children for process"
+ " '" + stringify(parent) + "'");
+ }
+
+ foreach (pid_t child, children.get()) {
+ Try<ino_t> childNamespace = ns::getns(child, "mnt");
+ if (childNamespace.isError()) {
+ return Error("Cannot get 'mnt' namespace for"
+ " child process '" + stringify(child) + "'");
+ }
+
+ if (parentNamespace.get() != childNamespace.get()) {
+ return child;
+ }
+ }
+
+ // Search for a new mount namespace in all 2nd-level children.
+ foreach (pid_t child, children.get()) {
+ Try<set<pid_t>> children2 = os::children(child, false);
+ if (children2.isError()) {
+ return Error("Cannot get 2nd-level children for process"
+ " '" + stringify(parent) + "' with child"
+ " '" + stringify(child) + "'");
+ }
+
+ foreach (pid_t child2, children2.get()) {
+ Try<ino_t> child2Namespace = ns::getns(child2, "mnt");
+ if (child2Namespace.isError()) {
+ return Error("Cannot get 'mnt' namespace for 2nd-level"
+ " child process '" + stringify(child2) + "'");
+ }
+
+ if (parentNamespace.get() != child2Namespace.get()) {
+ return child2;
+ }
+ }
+ }
+
+ return parent;
+}
+#endif // __linux__
+
} // namespace slave {
} // namespace internal {
} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/757d2804/src/slave/containerizer/mesos/utils.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/utils.hpp b/src/slave/containerizer/mesos/utils.hpp
index f24215b..a54106d 100644
--- a/src/slave/containerizer/mesos/utils.hpp
+++ b/src/slave/containerizer/mesos/utils.hpp
@@ -19,12 +19,19 @@
#include <mesos/mesos.hpp>
+#include <stout/os.hpp>
+#include <stout/try.hpp>
+
namespace mesos {
namespace internal {
namespace slave {
ContainerID getRootContainerId(const ContainerID& containerId);
+#ifdef __linux__
+Try<pid_t> getMountNamespaceTarget(pid_t parent);
+#endif // __linux__
+
} // namespace slave {
} // namespace internal {
} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/757d2804/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/nested_mesos_containerizer_tests.cpp b/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
index 20bc9d5..6c341e1 100644
--- a/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
+++ b/src/tests/containerizer/nested_mesos_containerizer_tests.cpp
@@ -58,6 +58,8 @@ using mesos::internal::slave::state::FrameworkState;
using mesos::internal::slave::state::RunState;
using mesos::internal::slave::state::SlaveState;
+using mesos::master::detector::MasterDetector;
+
using mesos::slave::ContainerClass;
using mesos::slave::ContainerState;
using mesos::slave::ContainerTermination;
@@ -349,6 +351,123 @@ TEST_F(NestedMesosContainerizerTest,
}
+TEST_F(NestedMesosContainerizerTest,
+ ROOT_CGROUPS_CURL_INTERNET_LaunchNestedDebugCheckMntNamespace)
+{
+ Try<Owned<cluster::Master>> master = StartMaster();
+ ASSERT_SOME(master);
+
+ slave::Flags flags = CreateSlaveFlags();
+ flags.isolation = "docker/runtime,filesystem/linux,namespaces/pid";
+ flags.image_providers = "docker";
+
+ Owned<MasterDetector> detector = master.get()->createDetector();
+
+ Fetcher fetcher;
+
+ Try<MesosContainerizer*> _containerizer =
+ MesosContainerizer::create(flags, true, &fetcher);
+ ASSERT_SOME(_containerizer);
+
+ Owned<MesosContainerizer> containerizer(_containerizer.get());
+
+ Try<Owned<cluster::Slave>> slave = StartSlave(
+ detector.get(),
+ containerizer.get());
+ ASSERT_SOME(slave);
+
+ MockScheduler sched;
+
+ MesosSchedulerDriver driver(
+ &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL);
+
+ Future<Nothing> schedRegistered;
+ EXPECT_CALL(sched, registered(_, _, _))
+ .WillOnce(FutureSatisfy(&schedRegistered));
+
+ Future<vector<Offer>> offers;
+ EXPECT_CALL(sched, resourceOffers(_, _))
+ .WillOnce(FutureArg<1>(&offers))
+ .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+ driver.start();
+
+ AWAIT_READY(schedRegistered);
+
+ AWAIT_READY(offers);
+ ASSERT_EQ(1u, offers->size());
+
+ // Use a pipe to synchronize with the top-level container.
+ int pipes[2] = {-1, -1};
+ ASSERT_SOME(os::pipe(pipes));
+
+ // Launch a command task within the `alpine` docker image and
+ // synchronize its launch with the launch of a debug container below.
+ TaskInfo task = createTask(
+ offers->front().slave_id(),
+ offers->front().resources(),
+ "echo running >&" + stringify(pipes[1]) + ";" + "sleep 1000");
+
+ task.mutable_container()->CopyFrom(createContainerInfo("alpine"));
+
+ Future<TaskStatus> statusRunning;
+ EXPECT_CALL(sched, statusUpdate(_, _))
+ .WillOnce(FutureArg<1>(&statusRunning));
+
+ driver.launchTasks(offers->at(0).id(), {task});
+
+ // We wait wait up to 120 seconds
+ // to download the docker image.
+ AWAIT_READY_FOR(statusRunning, Seconds(120));
+ ASSERT_EQ(TASK_RUNNING, statusRunning->state());
+
+ close(pipes[1]);
+
+ // Wait for the parent container to start running its task
+ // before launching a debug container inside it.
+ AWAIT_READY(process::io::poll(pipes[0], process::io::READ));
+ close(pipes[0]);
+
+ ASSERT_TRUE(statusRunning->has_slave_id());
+ ASSERT_TRUE(statusRunning->has_container_status());
+ ASSERT_TRUE(statusRunning->container_status().has_container_id());
+
+ // Launch a nested debug container.
+ ContainerID nestedContainerId;
+ nestedContainerId.mutable_parent()->CopyFrom(
+ statusRunning->container_status().container_id());
+ nestedContainerId.set_value(UUID::random().toString());
+
+ // Launch a debug container inside the command task and check for
+ // the existence of a file we know to be inside the `alpine` docker
+ // image (but not on the host filesystem).
+ Future<bool> launch = containerizer->launch(
+ nestedContainerId,
+ createCommandInfo(
+ "LINES=`ls -la /etc/alpine-release | wc -l`;"
+ "if [ ${LINES} -ne 1 ]; then"
+ " exit 1;"
+ "fi;"),
+ None(),
+ None(),
+ statusRunning->slave_id(),
+ ContainerClass::DEBUG);
+
+ AWAIT_ASSERT_TRUE(launch);
+
+ Future<Option<ContainerTermination>> wait =
+ containerizer->wait(nestedContainerId);
+
+ AWAIT_READY(wait);
+ ASSERT_SOME(wait.get());
+ ASSERT_TRUE(wait.get()->has_status());
+ EXPECT_WEXITSTATUS_EQ(0, wait.get()->status());
+
+ driver.stop();
+ driver.join();
+}
+
+
TEST_F(NestedMesosContainerizerTest, ROOT_CGROUPS_DestroyNested)
{
slave::Flags flags = CreateSlaveFlags();
[10/11] mesos git commit: Introduced a new 'DEBUG' container class.
Posted by ji...@apache.org.
Introduced a new 'DEBUG' container class.
Review: https://reviews.apache.org/r/53353/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/a012efa0
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/a012efa0
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/a012efa0
Branch: refs/heads/master
Commit: a012efa0b57f0199b7ed54b12e9c522d695e09aa
Parents: 09d4245
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 16:53:07 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:11 2016 -0800
----------------------------------------------------------------------
include/mesos/slave/containerizer.proto | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/a012efa0/include/mesos/slave/containerizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/slave/containerizer.proto b/include/mesos/slave/containerizer.proto
index c9fcc24..2621522 100644
--- a/include/mesos/slave/containerizer.proto
+++ b/include/mesos/slave/containerizer.proto
@@ -30,6 +30,7 @@ import "mesos/docker/v1.proto";
*/
enum ContainerClass {
DEFAULT = 1;
+ DEBUG = 2;
}
[06/11] mesos git commit: Updated 'LinuxLauncher->fork()` with
*enter* and *clone* namespaces.
Posted by ji...@apache.org.
Updated 'LinuxLauncher->fork()` with *enter* and *clone* namespaces.
Instead of only taking the namespaces to *clone* inside a newly forked
container, 'LinuxLauncher->fork()' now takes a list of namespaces to
enter inside a parent container before forking. When both an *enter*
and a *clone* for the same namespace are passed, we will first enter
the namespace of the parent, and then clone a new one.
Review: https://reviews.apache.org/r/53352/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/329f3ea9
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/329f3ea9
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/329f3ea9
Branch: refs/heads/master
Commit: 329f3ea90ee9b4c49f7a35af76065b19dadedceb
Parents: 727ce3d
Author: Kevin Klues <kl...@gmail.com>
Authored: Fri Nov 11 16:20:25 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Fri Nov 11 18:54:11 2016 -0800
----------------------------------------------------------------------
include/mesos/slave/containerizer.proto | 8 ++++--
src/slave/containerizer/mesos/containerizer.cpp | 30 ++++++++++++++++----
.../mesos/isolators/docker/volume/isolator.cpp | 2 +-
.../mesos/isolators/filesystem/linux.cpp | 2 +-
.../mesos/isolators/filesystem/shared.cpp | 2 +-
.../mesos/isolators/gpu/isolator.cpp | 2 +-
.../mesos/isolators/namespaces/pid.cpp | 2 +-
.../mesos/isolators/network/cni/cni.cpp | 9 ++++--
.../mesos/isolators/network/port_mapping.cpp | 2 +-
.../mesos/isolators/volume/image.cpp | 2 +-
.../mesos/isolators/volume/sandbox_path.cpp | 2 +-
src/slave/containerizer/mesos/launcher.cpp | 11 +++++--
src/slave/containerizer/mesos/launcher.hpp | 6 ++--
.../containerizer/mesos/linux_launcher.cpp | 23 ++++++++-------
.../containerizer/mesos/linux_launcher.hpp | 3 +-
src/tests/containerizer/isolator_tests.cpp | 10 ++++---
src/tests/containerizer/launcher.cpp | 6 ++--
src/tests/containerizer/launcher.hpp | 5 ++--
.../containerizer/mesos_containerizer_tests.cpp | 1 +
src/tests/containerizer/port_mapping_tests.cpp | 1 +
20 files changed, 85 insertions(+), 44 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/include/mesos/slave/containerizer.proto
----------------------------------------------------------------------
diff --git a/include/mesos/slave/containerizer.proto b/include/mesos/slave/containerizer.proto
index ee29468..c9fcc24 100644
--- a/include/mesos/slave/containerizer.proto
+++ b/include/mesos/slave/containerizer.proto
@@ -166,9 +166,13 @@ message ContainerLaunchInfo {
// since 1.0.1.
optional string rootfs = 3 [deprecated = true]; // Since 1.0.1.
- // (Linux only) The namespaces required for the container.
+ // (Linux only) The namespaces a nested container
+ // should enter in its parent before cloning.
+ optional uint32 enter_namespaces = 9 [default = 0];
+
+ // (Linux only) The namespaces that should be cloned for the container.
// The namespaces are created while launching the executor.
- optional uint32 namespaces = 4 [default = 0];
+ optional uint32 clone_namespaces = 4 [default = 0];
// If specified, it'll become the launch command for the custom
// executor, or the launch command for the user task in the case of
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/containerizer.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/containerizer.cpp b/src/slave/containerizer/mesos/containerizer.cpp
index 90f91b9..3c3bee4 100644
--- a/src/slave/containerizer/mesos/containerizer.cpp
+++ b/src/slave/containerizer/mesos/containerizer.cpp
@@ -1227,9 +1227,14 @@ Future<bool> MesosContainerizerProcess::_launch(
Option<CapabilityInfo> capabilities;
Option<RLimitInfo> rlimits;
- // TODO(jieyu): We should use Option here. If no namespace is
- // required, we should pass None() to 'launcher->fork'.
- int namespaces = 0;
+ Option<int> enterNamespaces = None();
+ Option<int> cloneNamespaces = None();
+
+ // TODO(klueska): Remove the following once we update
+ // isolators to fill enterNamespaces for us.
+ if (containerId.has_parent()) {
+ enterNamespaces = CLONE_NEWUTS | CLONE_NEWNET | CLONE_NEWPID;
+ }
CHECK_READY(container->launchInfos);
@@ -1285,8 +1290,18 @@ Future<bool> MesosContainerizerProcess::_launch(
preExecCommands.values.emplace_back(JSON::protobuf(command));
}
- if (launchInfo->has_namespaces()) {
- namespaces |= launchInfo->namespaces();
+ if (launchInfo->has_enter_namespaces()) {
+ if (enterNamespaces.isNone()) {
+ enterNamespaces = 0;
+ }
+ enterNamespaces = enterNamespaces.get() | launchInfo->enter_namespaces();
+ }
+
+ if (launchInfo->has_clone_namespaces()) {
+ if (cloneNamespaces.isNone()) {
+ cloneNamespaces = 0;
+ }
+ cloneNamespaces = cloneNamespaces.get() | launchInfo->clone_namespaces();
}
if (launchInfo->has_capabilities()) {
@@ -1500,7 +1515,10 @@ Future<bool> MesosContainerizerProcess::_launch(
: Subprocess::IO(subprocessInfo.err)),
&launchFlags,
launchEnvironment,
- namespaces); // 'namespaces' will be ignored by PosixLauncher.
+ // 'enterNamespaces' will be ignored by PosixLauncher.
+ enterNamespaces,
+ // 'cloneNamespaces' will be ignored by PosixLauncher.
+ cloneNamespaces);
if (forked.isError()) {
return Failure("Failed to fork: " + forked.error());
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp b/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
index af9f373..6f0d6b0 100644
--- a/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
+++ b/src/slave/containerizer/mesos/isolators/docker/volume/isolator.cpp
@@ -467,7 +467,7 @@ Future<Option<ContainerLaunchInfo>> DockerVolumeIsolatorProcess::_prepare(
const list<Future<string>>& futures)
{
ContainerLaunchInfo launchInfo;
- launchInfo.set_namespaces(CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
vector<string> messages;
vector<string> sources;
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
index df16b8f..6535375 100644
--- a/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
+++ b/src/slave/containerizer/mesos/isolators/filesystem/linux.cpp
@@ -323,7 +323,7 @@ Future<Option<ContainerLaunchInfo>> LinuxFilesystemIsolatorProcess::prepare(
executorInfo)));
ContainerLaunchInfo launchInfo;
- launchInfo.set_namespaces(CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
// Prepare the commands that will be run in the container's mount
// namespace right after forking the executor process. We use these
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp b/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
index a1283e5..d16b42f 100644
--- a/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
+++ b/src/slave/containerizer/mesos/isolators/filesystem/shared.cpp
@@ -101,7 +101,7 @@ Future<Option<ContainerLaunchInfo>> SharedFilesystemIsolatorProcess::prepare(
containerPaths.insert(containerConfig.directory());
ContainerLaunchInfo launchInfo;
- launchInfo.set_namespaces(CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
foreach (const Volume& volume, executorInfo.container().volumes()) {
// Because the filesystem is shared we require the container path
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
index e3756c9..4bd3785 100644
--- a/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
+++ b/src/slave/containerizer/mesos/isolators/gpu/isolator.cpp
@@ -329,7 +329,7 @@ Future<Option<ContainerLaunchInfo>> NvidiaGpuIsolatorProcess::_prepare(
}
ContainerLaunchInfo launchInfo;
- launchInfo.set_namespaces(CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
// Inject the Nvidia volume into the container.
//
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
index 0d9ec57..f3438b8 100644
--- a/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
+++ b/src/slave/containerizer/mesos/isolators/namespaces/pid.cpp
@@ -79,7 +79,7 @@ Future<Option<ContainerLaunchInfo>> NamespacesPidIsolatorProcess::prepare(
const ContainerConfig& containerConfig)
{
ContainerLaunchInfo launchInfo;
- launchInfo.set_namespaces(CLONE_NEWPID | CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWPID | CLONE_NEWNS);
// Mount /proc with standard options for the container's pid
// namespace to show the container's pids (and other /proc files),
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
index 50b4377..74bb6eb 100644
--- a/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
+++ b/src/slave/containerizer/mesos/isolators/network/cni/cni.cpp
@@ -650,9 +650,12 @@ Future<Option<ContainerLaunchInfo>> NetworkCniIsolatorProcess::prepare(
// NOTE: There is an implicit assumption here that when used
// for testing, '__MESOS_TEST__' is the only network the
// container is going to join.
- launchInfo.set_namespaces(CLONE_NEWNS | CLONE_NEWUTS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS | CLONE_NEWUTS);
} else {
- launchInfo.set_namespaces(CLONE_NEWNET | CLONE_NEWNS | CLONE_NEWUTS);
+ launchInfo.set_clone_namespaces(
+ CLONE_NEWNET |
+ CLONE_NEWNS |
+ CLONE_NEWUTS);
}
} else {
// This is a nested container. This shares the parent's network
@@ -661,7 +664,7 @@ Future<Option<ContainerLaunchInfo>> NetworkCniIsolatorProcess::prepare(
// therefore we will need to bind mount its network files
// (/etc/hosts, /etc/hostname, /etc/resolv.conf) which will be
// different than those on the host file system.
- launchInfo.set_namespaces(CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
}
return launchInfo;
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp b/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
index 48202fb..a994adf 100644
--- a/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
+++ b/src/slave/containerizer/mesos/isolators/network/port_mapping.cpp
@@ -2522,7 +2522,7 @@ Future<Option<ContainerLaunchInfo>> PortMappingIsolatorProcess::prepare(
// other isolators, we need to set mount sharing accordingly for
// PORT_MAPPING_BIND_MOUNT_ROOT to avoid races described in
// MESOS-1558. So we turn on mount namespace here for consistency.
- launchInfo.set_namespaces(CLONE_NEWNET | CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNET | CLONE_NEWNS);
return launchInfo;
}
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/volume/image.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/image.cpp b/src/slave/containerizer/mesos/isolators/volume/image.cpp
index 210e67a..ee9bd35 100644
--- a/src/slave/containerizer/mesos/isolators/volume/image.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/image.cpp
@@ -180,7 +180,7 @@ Future<Option<ContainerLaunchInfo>> VolumeImageIsolatorProcess::_prepare(
const list<Future<ProvisionInfo>>& futures)
{
ContainerLaunchInfo launchInfo;
- launchInfo.set_namespaces(CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
vector<string> messages;
vector<string> sources;
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
index 7b976d2..a6f9794 100644
--- a/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/sandbox_path.cpp
@@ -122,7 +122,7 @@ Future<Option<ContainerLaunchInfo>> VolumeSandboxPathIsolatorProcess::prepare(
#ifdef __linux__
if (bindMountSupported) {
- launchInfo.set_namespaces(CLONE_NEWNS);
+ launchInfo.set_clone_namespaces(CLONE_NEWNS);
}
#endif // __linux__
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launcher.cpp b/src/slave/containerizer/mesos/launcher.cpp
index bc33f19..a6a8c01 100644
--- a/src/slave/containerizer/mesos/launcher.cpp
+++ b/src/slave/containerizer/mesos/launcher.cpp
@@ -87,10 +87,15 @@ Try<pid_t> PosixLauncher::fork(
const Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<map<string, string>>& environment,
- const Option<int>& namespaces)
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces)
{
- if (namespaces.isSome() && namespaces.get() != 0) {
- return Error("Posix launcher does not support namespaces");
+ if (enterNamespaces.isSome() && enterNamespaces.get() != 0) {
+ return Error("Posix launcher does not support entering namespaces");
+ }
+
+ if (cloneNamespaces.isSome() && cloneNamespaces.get() != 0) {
+ return Error("Posix launcher does not support cloning namespaces");
}
if (pids.contains(containerId)) {
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/launcher.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/launcher.hpp b/src/slave/containerizer/mesos/launcher.hpp
index c1a390a..79f6eea 100644
--- a/src/slave/containerizer/mesos/launcher.hpp
+++ b/src/slave/containerizer/mesos/launcher.hpp
@@ -69,7 +69,8 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces) = 0;
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces) = 0;
// Kill all processes in the containerized context.
virtual process::Future<Nothing> destroy(const ContainerID& containerId) = 0;
@@ -104,7 +105,8 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces);
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces);
virtual process::Future<Nothing> destroy(const ContainerID& containerId);
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/linux_launcher.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/linux_launcher.cpp b/src/slave/containerizer/mesos/linux_launcher.cpp
index e96090f..2c55d7b 100644
--- a/src/slave/containerizer/mesos/linux_launcher.cpp
+++ b/src/slave/containerizer/mesos/linux_launcher.cpp
@@ -79,7 +79,8 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces);
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces);
virtual process::Future<Nothing> destroy(const ContainerID& containerId);
@@ -210,7 +211,8 @@ Try<pid_t> LinuxLauncher::fork(
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<map<string, string>>& environment,
- const Option<int>& namespaces)
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces)
{
return dispatch(
process.get(),
@@ -223,7 +225,8 @@ Try<pid_t> LinuxLauncher::fork(
err,
flags,
environment,
- namespaces).get();
+ enterNamespaces,
+ cloneNamespaces).get();
}
@@ -385,7 +388,8 @@ Try<pid_t> LinuxLauncherProcess::fork(
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<map<string, string>>& environment,
- const Option<int>& namespaces)
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces)
{
// Make sure this container (nested or not) is unique.
if (containers.contains(containerId)) {
@@ -412,7 +416,9 @@ Try<pid_t> LinuxLauncherProcess::fork(
target = container->pid.get();
}
- int cloneFlags = namespaces.isSome() ? namespaces.get() : 0;
+ int enterFlags = enterNamespaces.isSome() ? enterNamespaces.get() : 0;
+
+ int cloneFlags = cloneNamespaces.isSome() ? cloneNamespaces.get() : 0;
LOG(INFO) << "Launching " << (target.isSome() ? "nested " : "")
<< "container " << containerId << " and cloning with namespaces "
@@ -454,14 +460,11 @@ Try<pid_t> LinuxLauncherProcess::fork(
err,
flags,
environment,
- [target, cloneFlags](const lambda::function<int()>& child) {
+ [target, enterFlags, cloneFlags](const lambda::function<int()>& child) {
if (target.isSome()) {
- // TODO(benh): Factor out this set of namespaces that we
- // enter and give a healthy comment for why these are the
- // only ones we enter.
Try<pid_t> pid = ns::clone(
target.get(),
- CLONE_NEWUTS | CLONE_NEWNET | CLONE_NEWPID,
+ enterFlags,
child,
cloneFlags);
if (pid.isError()) {
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/slave/containerizer/mesos/linux_launcher.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/linux_launcher.hpp b/src/slave/containerizer/mesos/linux_launcher.hpp
index 356d4de..e152523 100644
--- a/src/slave/containerizer/mesos/linux_launcher.hpp
+++ b/src/slave/containerizer/mesos/linux_launcher.hpp
@@ -51,7 +51,8 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& environment,
- const Option<int>& namespaces);
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces);
virtual process::Future<Nothing> destroy(const ContainerID& containerId);
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/tests/containerizer/isolator_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/isolator_tests.cpp b/src/tests/containerizer/isolator_tests.cpp
index 8fefeef..9766aaf 100644
--- a/src/tests/containerizer/isolator_tests.cpp
+++ b/src/tests/containerizer/isolator_tests.cpp
@@ -154,7 +154,7 @@ TEST_F(SharedFilesystemIsolatorTest, DISABLED_ROOT_RelativeVolume)
AWAIT_READY(prepare);
ASSERT_SOME(prepare.get());
ASSERT_EQ(1, prepare.get().get().pre_exec_commands().size());
- EXPECT_TRUE(prepare.get().get().has_namespaces());
+ EXPECT_TRUE(prepare.get().get().has_clone_namespaces());
// The test will touch a file in container path.
const string file = path::join(containerPath, UUID::random().toString());
@@ -178,7 +178,8 @@ TEST_F(SharedFilesystemIsolatorTest, DISABLED_ROOT_RelativeVolume)
Subprocess::FD(STDERR_FILENO),
nullptr,
None(),
- prepare.get().get().namespaces());
+ None(),
+ prepare.get().get().clone_namespaces());
ASSERT_SOME(pid);
// Set up the reaper to wait on the forked child.
@@ -260,7 +261,7 @@ TEST_F(SharedFilesystemIsolatorTest, DISABLED_ROOT_AbsoluteVolume)
AWAIT_READY(prepare);
ASSERT_SOME(prepare.get());
ASSERT_EQ(1, prepare.get().get().pre_exec_commands().size());
- EXPECT_TRUE(prepare.get().get().has_namespaces());
+ EXPECT_TRUE(prepare.get().get().has_clone_namespaces());
// Test the volume mounting by touching a file in the container's
// /tmp, which should then be in flags.work_dir.
@@ -284,7 +285,8 @@ TEST_F(SharedFilesystemIsolatorTest, DISABLED_ROOT_AbsoluteVolume)
Subprocess::FD(STDERR_FILENO),
nullptr,
None(),
- prepare.get().get().namespaces());
+ None(),
+ prepare.get().get().clone_namespaces());
ASSERT_SOME(pid);
// Set up the reaper to wait on the forked child.
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/tests/containerizer/launcher.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/launcher.cpp b/src/tests/containerizer/launcher.cpp
index 51ae4f9..a92d989 100644
--- a/src/tests/containerizer/launcher.cpp
+++ b/src/tests/containerizer/launcher.cpp
@@ -30,7 +30,7 @@ ACTION_P(InvokeRecover, launcher)
ACTION_P(InvokeFork, launcher)
{
return launcher->real->fork(
- arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
+ arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}
@@ -51,9 +51,9 @@ TestLauncher::TestLauncher(const process::Owned<slave::Launcher>& _real)
EXPECT_CALL(*this, recover(_))
.WillRepeatedly(DoDefault());
- ON_CALL(*this, fork(_, _, _, _, _, _, _, _, _))
+ ON_CALL(*this, fork(_, _, _, _, _, _, _, _, _, _))
.WillByDefault(InvokeFork(this));
- EXPECT_CALL(*this, fork(_, _, _, _, _, _, _, _, _))
+ EXPECT_CALL(*this, fork(_, _, _, _, _, _, _, _, _, _))
.WillRepeatedly(DoDefault());
ON_CALL(*this, destroy(_))
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/tests/containerizer/launcher.hpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/launcher.hpp b/src/tests/containerizer/launcher.hpp
index 5dcc391..a8e436f 100644
--- a/src/tests/containerizer/launcher.hpp
+++ b/src/tests/containerizer/launcher.hpp
@@ -56,7 +56,7 @@ public:
process::Future<hashset<ContainerID>>(
const std::list<mesos::slave::ContainerState>& states));
- MOCK_METHOD9(
+ MOCK_METHOD10(
fork,
Try<pid_t>(
const ContainerID& containerId,
@@ -67,7 +67,8 @@ public:
const process::Subprocess::IO& err,
const flags::FlagsBase* flags,
const Option<std::map<std::string, std::string>>& env,
- const Option<int>& namespaces));
+ const Option<int>& enterNamespaces,
+ const Option<int>& cloneNamespaces));
MOCK_METHOD1(
destroy,
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/tests/containerizer/mesos_containerizer_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/mesos_containerizer_tests.cpp b/src/tests/containerizer/mesos_containerizer_tests.cpp
index 16d7f12..5aae23b 100644
--- a/src/tests/containerizer/mesos_containerizer_tests.cpp
+++ b/src/tests/containerizer/mesos_containerizer_tests.cpp
@@ -1434,6 +1434,7 @@ TEST_F(MesosLauncherStatusTest, ExecutorPIDTest)
Subprocess::FD(STDERR_FILENO),
nullptr,
None(),
+ None(),
None());
ASSERT_SOME(forked);
http://git-wip-us.apache.org/repos/asf/mesos/blob/329f3ea9/src/tests/containerizer/port_mapping_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/port_mapping_tests.cpp b/src/tests/containerizer/port_mapping_tests.cpp
index fbdc0db..79b0a60 100644
--- a/src/tests/containerizer/port_mapping_tests.cpp
+++ b/src/tests/containerizer/port_mapping_tests.cpp
@@ -347,6 +347,7 @@ protected:
Subprocess::FD(STDERR_FILENO),
&launchFlags,
None(),
+ None(),
CLONE_NEWNET | CLONE_NEWNS);
return pid;