Repository: mesos Updated Branches: refs/heads/master 15c0d8029 -> 9fb62cecc
Added Docker provisioner paths which handles path manipulation. Review: https://reviews.apache.org/r/37497 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/19d787b5 Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/19d787b5 Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/19d787b5 Branch: refs/heads/master Commit: 19d787b5c6a634d09067fe0ce83ed29e0346eaf5 Parents: 31b62d6 Author: Lily Chen <[email protected]> Authored: Fri Aug 14 17:12:52 2015 -0700 Committer: Timothy Chen <[email protected]> Committed: Fri Sep 25 09:02:04 2015 -0700 ---------------------------------------------------------------------- src/Makefile.am | 4 +- .../provisioners/docker/local_store.cpp | 68 ++++++------ .../containerizer/provisioners/docker/paths.cpp | 104 +++++++++++++++++++ .../containerizer/provisioners/docker/paths.hpp | 88 ++++++++++++++++ .../provisioners/docker/reference_store.cpp | 22 ++-- 5 files changed, 235 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/19d787b5/src/Makefile.am ---------------------------------------------------------------------- diff --git a/src/Makefile.am b/src/Makefile.am index 0b7018c..fd367d3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -701,6 +701,7 @@ if OS_LINUX libmesos_no_3rdparty_la_SOURCES += slave/containerizer/provisioner/backends/bind.cpp libmesos_no_3rdparty_la_SOURCES += slave/containerizer/provisioner/docker.cpp libmesos_no_3rdparty_la_SOURCES += slave/containerizer/provisioner/docker/local_store.cpp + libmesos_no_3rdparty_la_SOURCES += slave/containerizer/provisioner/docker/paths.cpp libmesos_no_3rdparty_la_SOURCES += slave/containerizer/provisioner/docker/reference_store.cpp else EXTRA_DIST += linux/cgroups.cpp @@ -827,7 +828,8 @@ libmesos_no_3rdparty_la_SOURCES += \ slave/containerizer/provisioner/backends/bind.hpp \ slave/containerizer/provisioner/backends/copy.hpp \ slave/containerizer/provisioner/docker.hpp \ - slave/containerizer/provisioners/docker/local_store.hpp \ + slave/containerizer/provisioner/docker/local_store.hpp \ + slave/containerizer/provisioner/docker/paths.hpp \ slave/containerizer/provisioner/docker/reference_store.hpp \ slave/containerizer/provisioner/docker/registry_client.hpp \ slave/containerizer/provisioner/docker/store.hpp \ http://git-wip-us.apache.org/repos/asf/mesos/blob/19d787b5/src/slave/containerizer/provisioners/docker/local_store.cpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/provisioners/docker/local_store.cpp b/src/slave/containerizer/provisioners/docker/local_store.cpp index 5f80b43..d46f4bc 100644 --- a/src/slave/containerizer/provisioners/docker/local_store.cpp +++ b/src/slave/containerizer/provisioners/docker/local_store.cpp @@ -34,9 +34,11 @@ #include "common/status_utils.hpp" #include "slave/containerizer/fetcher.hpp" -#include "slave/flags.hpp" #include "slave/containerizer/provisioners/docker/store.hpp" +#include "slave/containerizer/provisioners/docker/paths.hpp" + +#include "slave/flags.hpp" using namespace process; @@ -175,22 +177,24 @@ Future<DockerImage> LocalStoreProcess::put( const string& name, const string& sandbox) { - string tarName = name + ".tar"; - Try<string> tarPath = path::join(flags.docker_discovery_local_dir, tarName); - if (tarPath.isError()) { - return Failure(tarPath.error()); + string tarPath = + paths::getLocalImageTarPath(flags.docker_discovery_local_dir, name); + if (!os::exists(tarPath)) { + return Failure("No Docker image tar archive found"); } - if (!os::exists(tarPath.get())) { - return Failure("No Docker image tar archive found: " + name); + + if (!os::exists(paths::getStagingDir(flags.docker_store_dir))) { + os::mkdir(paths::getStagingDir(flags.docker_store_dir)); } // Create a temporary staging directory. - Try<string> staging = os::mkdtemp(); + Try<string> staging = + os::mkdtemp(paths::getTempStaging(flags.docker_store_dir)); if (staging.isError()) { return Failure("Failed to create a staging directory"); } - return untarImage(tarPath.get(), staging.get()) + return untarImage(tarPath, staging.get()) .then(defer(self(), &Self::putImage, name, staging.get(), sandbox)); } @@ -199,7 +203,7 @@ Future<Nothing> LocalStoreProcess::untarImage( const string& tarPath, const string& staging) { - LOG(INFO) << "Untarring image at: " << tarPath; + VLOG(1) << "Untarring image at: " << tarPath; // Untar discovery_local_dir/name.tar into staging/. vector<string> argv = { @@ -244,13 +248,8 @@ Future<DockerImage> LocalStoreProcess::putImage( const string& sandbox) { ImageName imageName(name); - // Read repository json. - Try<string> repoPath = path::join(staging, "repositories"); - if (repoPath.isError()) { - return Failure("Failed to create path to repository: " + repoPath.error()); - } - Try<string> value = os::read(repoPath.get()); + Try<string> value = os::read(paths::getLocalImageRepositoriesPath(staging)); if (value.isError()) { return Failure("Failed to read repository JSON: " + value.error()); } @@ -279,16 +278,10 @@ Future<DockerImage> LocalStoreProcess::putImage( return Failure("Tag JSON value expected to be JSON::String"); } - Try<string> layerPath = path::join( - staging, - entry->second.as<JSON::String>().value); - if (layerPath.isError()) { - return Failure("Failed to create path to image layer: " + - layerPath.error()); - } string layerId = entry->second.as<JSON::String>().value; - Try<string> manifest = os::read(path::join(staging, layerId, "json")); + Try<string> manifest = + os::read(paths::getLocalImageLayerManifestPath(staging, layerId)); if (manifest.isError()) { return Failure("Failed to read manifest: " + manifest.error()); } @@ -320,7 +313,8 @@ Result<string> LocalStoreProcess::getParentId( const string& staging, const string& layerId) { - Try<string> manifest = os::read(path::join(staging, layerId, "json")); + Try<string> manifest = + os::read(paths::getLocalImageLayerManifestPath(staging, layerId)); if (manifest.isError()) { return Error("Failed to read manifest: " + manifest.error()); } @@ -363,28 +357,29 @@ Future<Nothing> LocalStoreProcess::untarLayer( const string& sandbox) { // Check if image layer is already in store. - if (os::exists(path::join(flags.docker_store_dir, id))) { + if (os::exists(paths::getImageLayerPath(flags.docker_store_dir, id))) { VLOG(1) << "Image layer: " << id << " already in store. Skipping untar" << " and putLayer."; return Nothing(); } // Image layer has been untarred but is not present in the store directory. - if (os::exists(path::join(staging, id, "rootfs"))) { + string localRootfsPath = paths::getLocalImageLayerRootfsPath(staging, id); + if (os::exists(localRootfsPath)) { LOG(WARNING) << "Image layer rootfs present at but not in store directory: " - << path::join(staging, id) << "Skipping untarLayer."; + << localRootfsPath << "Skipping untarLayer."; return moveLayer(staging, id, sandbox); } - os::mkdir(path::join(staging, id, "rootfs")); + os::mkdir(localRootfsPath); // Untar staging/id/layer.tar into staging/id/rootfs. vector<string> argv = { "tar", "-C", - path::join(staging, id, "rootfs"), + localRootfsPath, "-x", "-f", - path::join(staging, id, "layer.tar") + paths::getLocalImageLayerTarPath(staging, id) }; Try<Subprocess> s = subprocess( @@ -399,11 +394,10 @@ Future<Nothing> LocalStoreProcess::untarLayer( return s.get().status() .then([=](const Option<int>& status) -> Future<Nothing> { - Try<string> layerPath = path::join(staging, id, "rootfs"); if (status.isNone()) { return Failure("Failed to reap subprocess to untar image"); } else if (!WIFEXITED(status.get()) || WEXITSTATUS(status.get()) != 0) { - return Failure("Untar image failed with exit code: " + + return Failure("Untar failed with exit code: " + WSTRINGIFY(status.get())); } @@ -442,13 +436,13 @@ Future<Nothing> LocalStoreProcess::moveLayer( os::mkdir(flags.docker_store_dir); } - if (!os::exists(path::join(flags.docker_store_dir, id))) { - os::mkdir(path::join(flags.docker_store_dir, id)); + if (!os::exists(paths::getImageLayerPath(flags.docker_store_dir, id))) { + os::mkdir(paths::getImageLayerPath(flags.docker_store_dir, id)); } Try<Nothing> status = os::rename( - path::join(staging, id, "rootfs"), - path::join(flags.docker_store_dir, id, "rootfs")); + paths::getLocalImageLayerRootfsPath(staging, id), + paths::getImageLayerRootfsPath(flags.docker_store_dir, id)); if (status.isError()) { return Failure("Failed to move layer to store directory:" + status.error()); http://git-wip-us.apache.org/repos/asf/mesos/blob/19d787b5/src/slave/containerizer/provisioners/docker/paths.cpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/provisioners/docker/paths.cpp b/src/slave/containerizer/provisioners/docker/paths.cpp new file mode 100644 index 0000000..ca35e0a --- /dev/null +++ b/src/slave/containerizer/provisioners/docker/paths.cpp @@ -0,0 +1,104 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "slave/containerizer/provisioners/docker/paths.hpp" + +#include <stout/path.hpp> + +using std::string; + +namespace mesos { +namespace internal { +namespace slave { +namespace docker { +namespace paths { + +string getStagingDir(const string& storeDir) +{ + return path::join(storeDir, "staging"); +} + +string getTempStaging(const string& storeDir) +{ + return path::join(getStagingDir(storeDir), "XXXXXX"); +} + +string getLocalImageTarPath( + const string& discoveryDir, + const string& name) +{ + return path::join(discoveryDir, name + ".tar"); +} + +string getLocalImageRepositoriesPath(const string& staging) +{ + return path::join(staging, "repositories"); +} + +std::string getLocalImageLayerPath( + const string& staging, + const string& layerId) +{ + return path::join(staging, layerId); +} + +string getLocalImageLayerManifestPath( + const string& staging, + const string& layerId) +{ + return path::join(getLocalImageLayerPath(staging, layerId), "json"); +} + +string getLocalImageLayerTarPath( + const string& staging, + const string& layerId) +{ + return path::join(getLocalImageLayerPath(staging, layerId), "layer.tar"); +} + +string getLocalImageLayerRootfsPath( + const string& staging, + const string& layerId) +{ + return path::join(getLocalImageLayerPath(staging, layerId), "rootfs"); +} + +string getImageLayerPath( + const string& storeDir, + const string& layerId) +{ + return path::join(storeDir, layerId); +} + +string getImageLayerRootfsPath( + const string& storeDir, + const string& layerId) +{ + return path::join(getImageLayerPath(storeDir, layerId), "rootfs"); +} + +string getStoredImagesPath(const string& storeDir) +{ + return path::join(storeDir, "storedImages"); +} + +} // namespace paths { +} // namespace docker { +} // namespace slave { +} // namespace internal { +} // namespace mesos { http://git-wip-us.apache.org/repos/asf/mesos/blob/19d787b5/src/slave/containerizer/provisioners/docker/paths.hpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/provisioners/docker/paths.hpp b/src/slave/containerizer/provisioners/docker/paths.hpp new file mode 100644 index 0000000..4aae0d0 --- /dev/null +++ b/src/slave/containerizer/provisioners/docker/paths.hpp @@ -0,0 +1,88 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MESOS_DOCKER_PATHS__ +#define __MESOS_DOCKER_PATHS__ + +#include <list> +#include <string> + +#include <mesos/mesos.hpp> + +namespace mesos { +namespace internal { +namespace slave { +namespace docker { +namespace paths { + +/** + * The Docker store file system layout is as follows: + * <root> + * |-- Local image discovery dir ('--docker_discovery_local_dir' slave flag) + * |--<name>.tar + * | + * |-- Image store dir ('--docker_store_dir' slave flag) + * |--staging + * |--<image_id> + * |--rootfs + * |--storedImages + */ + +std::string getStagingDir(const std::string& storeDir); + +std::string getTempStaging(const std::string& storeDir); + +std::string getLocalImageTarPath( + const std::string& discoveryDir, + const std::string& name); + +std::string getLocalImageRepositoriesPath(const std::string& staging); + +std::string getLocalImageLayerPath( + const std::string& staging, + const std::string& layerId); + +std::string getLocalImageLayerManifestPath( + const std::string& staging, + const std::string& layerId); + +std::string getLocalImageLayerTarPath( + const std::string& staging, + const std::string& layerId); + +std::string getLocalImageLayerRootfsPath( + const std::string& staging, + const std::string& layerId); + +std::string getImageLayerPath( + const std::string& storeDir, + const std::string& layerId); + +std::string getImageLayerRootfsPath( + const std::string& storeDir, + const std::string& layerId); + +std::string getStoredImagesPath(const std::string& storeDir); + +} // namespace paths { +} // namespace docker { +} // namespace slave { +} // namespace internal { +} // namespace mesos { + +#endif // __MESOS_DOCKER_PATHS__ http://git-wip-us.apache.org/repos/asf/mesos/blob/19d787b5/src/slave/containerizer/provisioners/docker/reference_store.cpp ---------------------------------------------------------------------- diff --git a/src/slave/containerizer/provisioners/docker/reference_store.cpp b/src/slave/containerizer/provisioners/docker/reference_store.cpp index b435ed4..e890b3c 100644 --- a/src/slave/containerizer/provisioners/docker/reference_store.cpp +++ b/src/slave/containerizer/provisioners/docker/reference_store.cpp @@ -33,6 +33,7 @@ #include "messages/docker_provisioner.hpp" +#include "slave/containerizer/provisioners/docker/paths.hpp" #include "slave/containerizer/provisioners/docker/reference_store.hpp" #include "slave/state.hpp" @@ -147,14 +148,8 @@ Try<Nothing> ReferenceStoreProcess::persist() } } - Try<string> path = path::join(flags.docker_store_dir, "storedImages"); - if (path.isError()) { - return Error("Failure to construct path to repositories lookup: " + - path.error()); - } - - Try<Nothing> status = - mesos::internal::slave::state::checkpoint(path.get(), images); + Try<Nothing> status = mesos::internal::slave::state::checkpoint( + paths::getStoredImagesPath(flags.docker_store_dir), images); if (status.isError()) { return Error("Failed to perform checkpoint: " + status.error()); } @@ -165,17 +160,17 @@ Try<Nothing> ReferenceStoreProcess::persist() void ReferenceStoreProcess::initialize() { - Try<string> path = path::join(flags.docker_store_dir, "storedImages"); + string storedImagesPath = paths::getStoredImagesPath(flags.docker_store_dir); storedImages.clear(); - if (!os::exists(path.get())) { + if (!os::exists(storedImagesPath)) { LOG(INFO) << "No images to load from disk. Docker provisioner image " - << "storage path: " << path.get() << " does not exist."; + << "storage path: " << storedImagesPath << " does not exist."; return; } Result<DockerProvisionerImages> images = - ::protobuf::read<DockerProvisionerImages>(path.get()); + ::protobuf::read<DockerProvisionerImages>(storedImagesPath); if (images.isError()) { LOG(ERROR) << "Failed to read protobuf for Docker provisioner image: " << images.error(); @@ -192,7 +187,8 @@ void ReferenceStoreProcess::initialize() layers.push_back(layerId); - if (!os::exists(path::join(flags.docker_store_dir, layerId))) { + if (!os::exists( + paths::getImageLayerPath(flags.docker_store_dir, layerId))) { missingLayers.push_back(layerId); } }
