Future<Option<ContainerLaunchInfo>> CgroupsNetClsIsolatorProcess::prepare( const ContainerID& containerId, const ContainerConfig& containerConfig) { 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, containerConfig.executorinfo().resources()) .then([]() -> Future<Option<ContainerLaunchInfo>> { return None(); }); }
Future<Option<ContainerLaunchInfo>> LinuxFilesystemIsolatorProcess::prepare( const ContainerID& containerId, const ContainerConfig& containerConfig) { const string& directory = containerConfig.directory(); Option<string> user; if (containerConfig.has_user()) { user = containerConfig.user(); } if (infos.contains(containerId)) { return Failure("Container has already been prepared"); } Owned<Info> info(new Info( directory, containerConfig.executor_info())); infos.put(containerId, info); ContainerLaunchInfo launchInfo; launchInfo.set_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 // commands to mount those volumes specified in the container info // so that they don't pollute the host mount namespace. Try<string> _script = script(containerId, containerConfig); if (_script.isError()) { return Failure("Failed to generate isolation script: " + _script.error()); } CommandInfo* command = launchInfo.add_commands(); command->set_value(_script.get()); return update(containerId, containerConfig.executor_info().resources()) .then([launchInfo]() -> Future<Option<ContainerLaunchInfo>> { return launchInfo; }); }