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/01/20 19:08:58 UTC
[2/5] mesos git commit: Implemented the CgroupsNetClsIsolatorProcess.
Implemented the CgroupsNetClsIsolatorProcess.
Review: https://reviews.apache.org/r/42048/
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/d42ff293
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/d42ff293
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/d42ff293
Branch: refs/heads/master
Commit: d42ff29303edfd110c42419e55a45849cf196b93
Parents: 157160b
Author: Avinash sridharan <av...@mesosphere.io>
Authored: Wed Jan 20 10:00:47 2016 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Jan 20 10:00:47 2016 -0800
----------------------------------------------------------------------
.../mesos/isolators/cgroups/net_cls.cpp | 191 ++++++++++++++++++-
1 file changed, 183 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/d42ff293/src/slave/containerizer/mesos/isolators/cgroups/net_cls.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/cgroups/net_cls.cpp b/src/slave/containerizer/mesos/isolators/cgroups/net_cls.cpp
index 610d479..0160fe2 100644
--- a/src/slave/containerizer/mesos/isolators/cgroups/net_cls.cpp
+++ b/src/slave/containerizer/mesos/isolators/cgroups/net_cls.cpp
@@ -15,15 +15,21 @@
// limitations under the License.
#include <list>
+#include <vector>
-#include "slave/flags.hpp"
+#include <process/defer.hpp>
+#include <process/future.hpp>
+#include <process/pid.hpp>
-#include "slave/containerizer/mesos/isolators/cgroups/net_cls.hpp"
+#include <stout/os.hpp>
+#include <stout/path.hpp>
+#include <stout/try.hpp>
-using namespace process;
+#include "linux/cgroups.hpp"
-using std::string;
-using std::list;
+#include "slave/flags.hpp"
+
+#include "slave/containerizer/mesos/isolators/cgroups/net_cls.hpp"
using mesos::slave::ContainerConfig;
using mesos::slave::ContainerLaunchInfo;
@@ -31,6 +37,16 @@ using mesos::slave::ContainerLimitation;
using mesos::slave::ContainerState;
using mesos::slave::Isolator;
+using process::Failure;
+using process::Future;
+using process::Owned;
+using process::PID;
+
+using std::list;
+using std::set;
+using std::string;
+using std::vector;
+
namespace mesos {
namespace internal {
namespace slave {
@@ -47,7 +63,31 @@ CgroupsNetClsIsolatorProcess::~CgroupsNetClsIsolatorProcess() {}
Try<Isolator*> CgroupsNetClsIsolatorProcess::create(const Flags& flags)
{
- return nullptr;
+ Try<string> hierarchy = cgroups::prepare(
+ flags.cgroups_hierarchy,
+ "net_cls",
+ flags.cgroups_root);
+
+ if (hierarchy.isError()) {
+ return Error("Failed to create net_cls cgroup: " + hierarchy.error());
+ }
+
+ // Ensure that no other subsystem is attached to the hierarchy.
+ Try<set<string>> subsystems = cgroups::subsystems(hierarchy.get());
+ if (subsystems.isError()) {
+ return Error(
+ "Failed to get the list of attached subsystems for hierarchy " +
+ hierarchy.get());
+ } else if (subsystems.get().size() != 1) {
+ return Error(
+ "Unexpected subsystems found attached to the hierarchy " +
+ hierarchy.get());
+ }
+
+ process::Owned<MesosIsolatorProcess> process(
+ new CgroupsNetClsIsolatorProcess(flags, hierarchy.get()));
+
+ return new MesosIsolator(process);
}
@@ -55,6 +95,64 @@ Future<Nothing> CgroupsNetClsIsolatorProcess::recover(
const list<ContainerState>& states,
const hashset<ContainerID>& orphans)
{
+ foreach (const ContainerState& state, states) {
+ const ContainerID& containerId = state.container_id();
+ const string cgroup = path::join(flags.cgroups_root, containerId.value());
+
+ Try<bool> exists = cgroups::exists(hierarchy, cgroup);
+ if (exists.isError()) {
+ infos.clear();
+ return Failure("Failed to check cgroup for container '" +
+ stringify(containerId) + "'");
+ }
+
+ if (!exists.get()) {
+ VLOG(1) << "Couldn't find cgroup for container " << containerId;
+ // This may occur if the executor has exited and the isolator
+ // has destroyed the cgroup but the slave dies before noticing
+ // this. This will be detected when the containerizer tries to
+ // monitor the executor's pid.
+ continue;
+ }
+
+ infos.emplace(containerId, Info(cgroup));
+ }
+
+ // Remove orphan cgroups.
+ Try<vector<string>> cgroups = cgroups::get(hierarchy, flags.cgroups_root);
+ if (cgroups.isError()) {
+ infos.clear();
+ return Failure(cgroups.error());
+ }
+
+ foreach (const string& cgroup, cgroups.get()) {
+ // Ignore the slave cgroup (see the --slave_subsystems flag).
+ // TODO(idownes): Remove this when the cgroups layout is updated,
+ // see MESOS-1185.
+ if (cgroup == path::join(flags.cgroups_root, "slave")) {
+ continue;
+ }
+
+ ContainerID containerId;
+ containerId.set_value(Path(cgroup).basename());
+
+ if (infos.contains(containerId)) {
+ continue;
+ }
+
+ // Known orphan cgroups will be destroyed by the containerizer
+ // using the normal cleanup path. See MESOS-2367 for details.
+ if (orphans.contains(containerId)) {
+ infos.emplace(containerId, Info(cgroup));
+ continue;
+ }
+
+ LOG(INFO) << "Removing unknown orphaned cgroup '" << cgroup << "'";
+
+ // We don't wait on the destroy as we don't want to block recovery.
+ cgroups::destroy(hierarchy, cgroup, cgroups::DESTROY_TIMEOUT);
+ }
+
return Nothing();
}
@@ -77,6 +175,10 @@ Future<Nothing> CgroupsNetClsIsolatorProcess::update(
Future<ResourceStatistics> CgroupsNetClsIsolatorProcess::usage(
const ContainerID& containerId)
{
+ if (!infos.contains(containerId)) {
+ return Failure("Unknown container");
+ }
+
return ResourceStatistics();
}
@@ -86,7 +188,49 @@ Future<Option<ContainerLaunchInfo>> CgroupsNetClsIsolatorProcess::prepare(
const ExecutorInfo& executorInfo,
const ContainerConfig& containerConfig)
{
- return None();
+ if (infos.contains(containerId)) {
+ return Failure("Container has already been prepared");
+ }
+
+ // Use this info to create the cgroup, but do not insert it into
+ // infos till the cgroup has been created successfully.
+ Info info(path::join(flags.cgroups_root, containerId.value()));
+
+ // Create a cgroup for this container.
+ Try<bool> exists = cgroups::exists(hierarchy, info.cgroup);
+ if (exists.isError()) {
+ return Failure("Failed to check if the cgroup already exists: " +
+ exists.error());
+ } else if (exists.get()) {
+ return Failure("The cgroup already exists");
+ }
+
+ Try<Nothing> create = cgroups::create(hierarchy, info.cgroup);
+ if (create.isError()) {
+ return Failure("Failed to create the cgroup: " + create.error());
+ }
+
+ // 'chown' the cgroup so the executor can create nested cgroups. Do
+ // not recurse so the control files are still owned by the slave
+ // user and thus cannot be changed by the executor.
+ if (containerConfig.has_user()) {
+ Try<Nothing> chown = os::chown(
+ containerConfig.user(),
+ path::join(hierarchy, info.cgroup),
+ false);
+
+ if (chown.isError()) {
+ return Failure("Failed to change ownership of cgroup hierarchy: " +
+ chown.error());
+ }
+ }
+
+ infos.emplace(containerId, info);
+
+ return update(containerId, executorInfo.resources())
+ .then([]() -> Future<Option<ContainerLaunchInfo>> {
+ return None();
+ });
}
@@ -94,6 +238,20 @@ Future<Nothing> CgroupsNetClsIsolatorProcess::isolate(
const ContainerID& containerId,
pid_t pid)
{
+ if (!infos.contains(containerId)) {
+ return Failure("Unknown container");
+ }
+
+ const Info& info = infos.at(containerId);
+
+ Try<Nothing> assign = cgroups::assign(hierarchy, info.cgroup, pid);
+ if (assign.isError()) {
+ return Failure("Failed to assign container '" +
+ stringify(containerId) + "' to its own cgroup '" +
+ path::join(hierarchy, info.cgroup) +
+ "': " + assign.error());
+ }
+
return Nothing();
}
@@ -104,6 +262,10 @@ Future<Nothing> CgroupsNetClsIsolatorProcess::isolate(
Future<ContainerLimitation> CgroupsNetClsIsolatorProcess::watch(
const ContainerID& containerId)
{
+ if (!infos.contains(containerId)) {
+ return Failure("Unknown container");
+ }
+
return Future<ContainerLimitation>();
}
@@ -111,7 +273,20 @@ Future<ContainerLimitation> CgroupsNetClsIsolatorProcess::watch(
Future<Nothing> CgroupsNetClsIsolatorProcess::cleanup(
const ContainerID& containerId)
{
- return Nothing();
+ // Multiple calls may occur during test clean up.
+ if (!infos.contains(containerId)) {
+ VLOG(1) << "Ignoring cleanup request for unknown container: "
+ << containerId;
+ return Nothing();
+ }
+
+ const Info& info = infos.at(containerId);
+
+ return cgroups::destroy(hierarchy, info.cgroup, cgroups::DESTROY_TIMEOUT)
+ .then(defer(PID<CgroupsNetClsIsolatorProcess>(this), [=]() {
+ infos.erase(containerId);
+ return Nothing();
+ }));
}
} // namespace slave {