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 2015/09/17 00:54:36 UTC

[2/6] mesos git commit: Moved files to prepare for unifying provisioners.

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/appc/store.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/appc/store.cpp b/src/slave/containerizer/provisioners/appc/store.cpp
deleted file mode 100644
index 33f692c..0000000
--- a/src/slave/containerizer/provisioners/appc/store.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/**
- * 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 <list>
-
-#include <glog/logging.h>
-
-#include <process/defer.hpp>
-#include <process/dispatch.hpp>
-
-#include <stout/check.hpp>
-#include <stout/hashmap.hpp>
-#include <stout/os.hpp>
-#include <stout/path.hpp>
-
-#include "slave/containerizer/provisioners/appc/paths.hpp"
-#include "slave/containerizer/provisioners/appc/spec.hpp"
-#include "slave/containerizer/provisioners/appc/store.hpp"
-
-using namespace process;
-
-using std::list;
-using std::string;
-using std::vector;
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace appc {
-
-// Defines a locally cached image (which has passed validation).
-struct CachedImage
-{
-  CachedImage(
-      const AppcImageManifest& _manifest,
-      const string& _id,
-      const string& _path)
-    : manifest(_manifest), id(_id), path(_path) {}
-
-  string rootfs() const
-  {
-    return path::join(path, "rootfs");
-  }
-
-  const AppcImageManifest manifest;
-
-  // Image ID of the format "sha512-value" where "value" is the hex
-  // encoded string of the sha512 digest of the uncompressed tar file
-  // of the image.
-  const string id;
-
-  // Absolute path to the extracted image.
-  const string path;
-};
-
-
-// Helper that implements this:
-// https://github.com/appc/spec/blob/master/spec/aci.md#dependency-matching
-static bool matches(Image::Appc requirements, const CachedImage& candidate)
-{
-  // The name must match.
-  if (candidate.manifest.name() != requirements.name()) {
-    return false;
-  }
-
-  // If an id is specified the candidate must match.
-  if (requirements.has_id() && (candidate.id != requirements.id())) {
-    return false;
-  }
-
-  // Extract labels for easier comparison, this also weeds out duplicates.
-  // TODO(xujyan): Detect duplicate labels in image manifest validation
-  // and Image::Appc validation.
-  hashmap<string, string> requiredLabels;
-  foreach (const Label& label, requirements.labels().labels()) {
-    requiredLabels[label.key()] = label.value();
-  }
-
-  hashmap<string, string> candidateLabels;
-  foreach (const AppcImageManifest::Label& label,
-           candidate.manifest.labels()) {
-    candidateLabels[label.name()] = label.value();
-  }
-
-  // Any label specified must be present and match in the candidate.
-  foreachpair (const string& name,
-               const string& value,
-               requiredLabels) {
-    if (!candidateLabels.contains(name) ||
-        candidateLabels.get(name).get() != value) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-
-class StoreProcess : public Process<StoreProcess>
-{
-public:
-  StoreProcess(const string& root);
-
-  ~StoreProcess() {}
-
-  Future<Nothing> recover();
-
-  Future<vector<string>> get(const Image::Appc& image);
-
-private:
-  // Absolute path to the root directory of the store as defined by
-  // --appc_store_dir.
-  const string root;
-
-  // Mappings: name -> id -> image.
-  hashmap<string, hashmap<string, CachedImage>> images;
-};
-
-
-Try<Owned<Store>> Store::create(const Flags& flags)
-{
-  Try<Nothing> mkdir = os::mkdir(paths::getImagesDir(flags.appc_store_dir));
-  if (mkdir.isError()) {
-    return Error("Failed to create the images directory: " + mkdir.error());
-  }
-
-  // Make sure the root path is canonical so all image paths derived
-  // from it are canonical too.
-  Result<string> root = os::realpath(flags.appc_store_dir);
-  if (!root.isSome()) {
-    // The above mkdir call recursively creates the store directory
-    // if necessary so it cannot be None here.
-    CHECK_ERROR(root);
-    return Error(
-        "Failed to get the realpath of the store directory: " + root.error());
-  }
-
-  return Owned<Store>(new Store(
-      Owned<StoreProcess>(new StoreProcess(root.get()))));
-}
-
-
-Store::Store(Owned<StoreProcess> _process)
-  : process(_process)
-{
-  spawn(CHECK_NOTNULL(process.get()));
-}
-
-
-Store::~Store()
-{
-  terminate(process.get());
-  wait(process.get());
-}
-
-
-Future<Nothing> Store::recover()
-{
-  return dispatch(process.get(), &StoreProcess::recover);
-}
-
-
-Future<vector<string>> Store::get(const Image::Appc& image)
-{
-  return dispatch(process.get(), &StoreProcess::get, image);
-}
-
-
-StoreProcess::StoreProcess(const string& _root) : root(_root) {}
-
-
-// Implemented as a helper function because it's going to be used for a
-// newly downloaded image too.
-static Try<CachedImage> createImage(const string& imagePath)
-{
-  Option<Error> error = spec::validateLayout(imagePath);
-  if (error.isSome()) {
-    return Error("Invalid image layout: " + error.get().message);
-  }
-
-  string imageId = Path(imagePath).basename();
-
-  error = spec::validateImageID(imageId);
-  if (error.isSome()) {
-    return Error("Invalid image ID: " + error.get().message);
-  }
-
-  Try<string> read = os::read(paths::getImageManifestPath(imagePath));
-  if (read.isError()) {
-    return Error("Failed to read manifest: " + read.error());
-  }
-
-  Try<AppcImageManifest> manifest = spec::parse(read.get());
-  if (manifest.isError()) {
-    return Error("Failed to parse manifest: " + manifest.error());
-  }
-
-  return CachedImage(manifest.get(), imageId, imagePath);
-}
-
-
-Future<vector<string>> StoreProcess::get(const Image::Appc& image)
-{
-  if (!images.contains(image.name())) {
-    return Failure("No image named '" + image.name() + "' can be found");
-  }
-
-  // Get local candidates.
-  vector<CachedImage> candidates;
-  foreach (const CachedImage& candidate, images[image.name()].values()) {
-    // The first match is returned.
-    // TODO(xujyan): Some tie-breaking rules are necessary.
-    if (matches(image, candidate)) {
-      LOG(INFO) << "Found match for image '" << image.name()
-                << "' in the store";
-
-      // The Appc store current doesn't support dependencies and this is
-      // enforced by manifest validation: if the image's manifest contains
-      // dependencies it would fail the validation and wouldn't be stored
-      // in the store.
-      return vector<string>({candidate.rootfs()});
-    }
-  }
-
-  return Failure("No image named '" + image.name() +
-                 "' can match the requirements");
-}
-
-
-Future<Nothing> StoreProcess::recover()
-{
-  // Recover everything in the store.
-  Try<list<string>> imageIds = os::ls(paths::getImagesDir(root));
-  if (imageIds.isError()) {
-    return Failure(
-        "Failed to list images under '" +
-        paths::getImagesDir(root) + "': " +
-        imageIds.error());
-  }
-
-  foreach (const string& imageId, imageIds.get()) {
-    string path = paths::getImagePath(root, imageId);
-    if (!os::stat::isdir(path)) {
-      LOG(WARNING) << "Unexpected entry in storage: " << imageId;
-      continue;
-    }
-
-    Try<CachedImage> image = createImage(path);
-    if (image.isError()) {
-      LOG(WARNING) << "Unexpected entry in storage: " << image.error();
-      continue;
-    }
-
-    LOG(INFO) << "Restored image '" << image.get().manifest.name() << "'";
-
-    images[image.get().manifest.name()].put(image.get().id, image.get());
-  }
-
-  return Nothing();
-}
-
-} // namespace appc {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/appc/store.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/appc/store.hpp b/src/slave/containerizer/provisioners/appc/store.hpp
deleted file mode 100644
index c4ce4b9..0000000
--- a/src/slave/containerizer/provisioners/appc/store.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * 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_APPC_STORE_HPP__
-#define __MESOS_APPC_STORE_HPP__
-
-#include <string>
-#include <vector>
-
-#include <mesos/mesos.hpp>
-
-#include <process/future.hpp>
-#include <process/owned.hpp>
-
-#include <stout/try.hpp>
-
-#include "slave/flags.hpp"
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace appc {
-
-// Forward declaration.
-class StoreProcess;
-
-
-// An image store abstraction that "stores" images. It serves as a read-through
-// cache (cache misses are fetched remotely and transparently) for images.
-// TODO(xujyan): The store currently keeps cached images indefinitely and we
-// should introduce cache eviction policies.
-class Store
-{
-public:
-  static Try<process::Owned<Store>> create(const Flags& flags);
-
-  ~Store();
-
-  process::Future<Nothing> recover();
-
-  // Get the specified image (and all its recursive dependencies) as a list
-  // of rootfs layers in the topological order (dependencies go before
-  // dependents in the list). The images required to build this list are
-  // either retrieved from the local cache or fetched remotely.
-  // NOTE: The returned list should not have duplicates. e.g., in the
-  // following scenario the result should be [C, B, D, A] (B before D in this
-  // example is decided by the order in which A specifies its dependencies).
-  //
-  // A --> B --> C
-  // |           ^
-  // |---> D ----|
-  //
-  // The returned future fails if the requested image or any of its
-  // dependencies cannot be found or failed to be fetched.
-  // TODO(xujyan): Fetching remotely is not implemented for now and until
-  // then the future fails directly if the image is not in the local cache.
-  // TODO(xujyan): The store currently doesn't support images that have
-  // dependencies and we should add it later.
-  process::Future<std::vector<std::string>> get(const Image::Appc& image);
-
-private:
-  Store(process::Owned<StoreProcess> process);
-
-  Store(const Store&); // Not copyable.
-  Store& operator=(const Store&); // Not assignable.
-
-  process::Owned<StoreProcess> process;
-};
-
-} // namespace appc {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __MESOS_APPC_STORE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/backend.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/backend.cpp b/src/slave/containerizer/provisioners/backend.cpp
deleted file mode 100644
index 6560ece..0000000
--- a/src/slave/containerizer/provisioners/backend.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * 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 <glog/logging.h>
-
-#include <stout/os.hpp>
-
-#include "slave/containerizer/provisioners/backend.hpp"
-
-#include "slave/containerizer/provisioners/backends/bind.hpp"
-#include "slave/containerizer/provisioners/backends/copy.hpp"
-
-using namespace process;
-
-using std::string;
-
-namespace mesos {
-namespace internal {
-namespace slave {
-
-hashmap<string, Owned<Backend>> Backend::create(const Flags& flags)
-{
-  hashmap<string, Try<Owned<Backend>>(*)(const Flags&)> creators;
-
-#ifdef __linux__
-  creators.put("bind", &BindBackend::create);
-#endif // __linux__
-  creators.put("copy", &CopyBackend::create);
-
-  hashmap<string, Owned<Backend>> backends;
-
-  foreachkey (const string& name, creators) {
-    Try<Owned<Backend>> backend = creators[name](flags);
-    if (backend.isError()) {
-      LOG(WARNING) << "Failed to create '" << name << "' backend: "
-                   << backend.error();
-      continue;
-    }
-    backends.put(name, backend.get());
-  }
-
-  return backends;
-}
-
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/backend.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/backend.hpp b/src/slave/containerizer/provisioners/backend.hpp
deleted file mode 100644
index a25b4ea..0000000
--- a/src/slave/containerizer/provisioners/backend.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * 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_PROVISIONER_BACKEND_HPP__
-#define __MESOS_PROVISIONER_BACKEND_HPP__
-
-#include <string>
-#include <vector>
-
-#include <process/future.hpp>
-#include <process/owned.hpp>
-
-#include <stout/hashmap.hpp>
-#include <stout/try.hpp>
-
-#include "slave/flags.hpp"
-
-namespace mesos {
-namespace internal {
-namespace slave {
-
-// Provision a root filesystem for a container.
-class Backend
-{
-public:
-  virtual ~Backend() {}
-
-  // Return a map of all supported backends keyed by their names. Note
-  // that Backends that failed to be created due to incorrect flags are
-  // simply not added to the result.
-  static hashmap<std::string, process::Owned<Backend>> create(
-      const Flags& flags);
-
-  // Provision a root filesystem for a container into the specified 'rootfs'
-  // directory by applying the specified list of root filesystem layers in
-  // the list order, i.e., files in a layer can overwrite/shadow those from
-  // another layer earlier in the list.
-  virtual process::Future<Nothing> provision(
-      const std::vector<std::string>& layers,
-      const std::string& rootfs) = 0;
-
-  // Destroy the root filesystem provisioned at the specified 'rootfs'
-  // directory. Return false if there is no provisioned root filesystem
-  // to destroy for the given directory.
-  virtual process::Future<bool> destroy(const std::string& rootfs) = 0;
-};
-
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __MESOS_PROVISIONER_BACKEND_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/backends/bind.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/backends/bind.cpp b/src/slave/containerizer/provisioners/backends/bind.cpp
deleted file mode 100644
index 71861a9..0000000
--- a/src/slave/containerizer/provisioners/backends/bind.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/**
- * 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 <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <process/dispatch.hpp>
-#include <process/process.hpp>
-
-#include <stout/foreach.hpp>
-#include <stout/os.hpp>
-
-#include "linux/fs.hpp"
-
-#include "slave/containerizer/provisioners/backends/bind.hpp"
-
-using namespace process;
-
-using std::string;
-using std::vector;
-
-namespace mesos {
-namespace internal {
-namespace slave {
-
-class BindBackendProcess : public Process<BindBackendProcess>
-{
-public:
-  Future<Nothing> provision(const vector<string>& layers, const string& rootfs);
-
-  Future<bool> destroy(const string& rootfs);
-};
-
-
-Try<Owned<Backend>> BindBackend::create(const Flags&)
-{
-  Result<string> user = os::user();
-  if (!user.isSome()) {
-    return Error("Failed to determine user: " +
-                 (user.isError() ? user.error() : "username not found"));
-  }
-
-  if (user.get() != "root") {
-    return Error("BindBackend requires root privileges");
-  }
-
-  return Owned<Backend>(new BindBackend(
-      Owned<BindBackendProcess>(new BindBackendProcess())));
-}
-
-
-BindBackend::~BindBackend()
-{
-  terminate(process.get());
-  wait(process.get());
-}
-
-
-BindBackend::BindBackend(Owned<BindBackendProcess> _process)
-  : process(_process)
-{
-  spawn(CHECK_NOTNULL(process.get()));
-}
-
-
-Future<Nothing> BindBackend::provision(
-    const vector<string>& layers,
-    const string& rootfs)
-{
-  return dispatch(
-      process.get(), &BindBackendProcess::provision, layers, rootfs);
-}
-
-
-Future<bool> BindBackend::destroy(const string& rootfs)
-{
-  return dispatch(process.get(), &BindBackendProcess::destroy, rootfs);
-}
-
-
-Future<Nothing> BindBackendProcess::provision(
-    const vector<string>& layers,
-    const string& rootfs)
-{
-  if (layers.size() > 1) {
-    return Failure(
-        "Multiple layers are not supported by the bind backend");
-  }
-
-  if (layers.size() == 0) {
-    return Failure("No filesystem layer provided");
-  }
-
-  Try<Nothing> mkdir = os::mkdir(rootfs);
-  if (mkdir.isError()) {
-    return Failure("Failed to create container rootfs at " + rootfs);
-  }
-
-  // TODO(xujyan): Use MS_REC? Does any provisioner use mounts within
-  // its image store in a single layer?
-  Try<Nothing> mount = fs::mount(
-      layers.front(),
-      rootfs,
-      None(),
-      MS_BIND,
-      NULL);
-
-  if (mount.isError()) {
-    return Failure(
-        "Failed to bind mount rootfs '" + layers.front() +
-        "' to '" + rootfs + "': " + mount.error());
-  }
-
-  // And remount it read-only.
-  mount = fs::mount(
-      None(), // Ignored.
-      rootfs,
-      None(),
-      MS_BIND | MS_RDONLY | MS_REMOUNT,
-      NULL);
-
-  if (mount.isError()) {
-    return Failure(
-        "Failed to remount rootfs '" + rootfs + "' read-only: " +
-        mount.error());
-  }
-
-  return Nothing();
-}
-
-
-Future<bool> BindBackendProcess::destroy(const string& rootfs)
-{
-  Try<fs::MountInfoTable> mountTable = fs::MountInfoTable::read();
-
-  if (mountTable.isError()) {
-    return Failure("Failed to read mount table: " + mountTable.error());
-  }
-
-  foreach (const fs::MountInfoTable::Entry& entry, mountTable.get().entries) {
-    // TODO(xujyan): If MS_REC was used in 'provision()' we would need
-    // to check `strings::startsWith(entry.target, rootfs)` here to
-    // unmount all nested mounts.
-    if (entry.target == rootfs) {
-      // NOTE: This would fail if the rootfs is still in use.
-      Try<Nothing> unmount = fs::unmount(entry.target);
-      if (unmount.isError()) {
-        return Failure(
-            "Failed to destroy bind-mounted rootfs '" + rootfs + "': " +
-            unmount.error());
-      }
-
-      // TODO(jieyu): If 'rmdir' here returns EBUSY, we still returns
-      // a success. This is currently possible because the parent
-      // mount of 'rootfs' might not be a shared mount. Thus,
-      // containers in different mount namespaces might hold extra
-      // references to this mount. It is OK to ignore the EBUSY error
-      // because the provisioner will later try to delete all the
-      // rootfses for the terminated containers.
-      if (::rmdir(rootfs.c_str()) != 0) {
-        string message =
-          "Failed to remove rootfs mount point '" + rootfs +
-          "': " + strerror(errno);
-
-        if (errno == EBUSY) {
-          LOG(ERROR) << message;
-        } else {
-          return Failure(message);
-        }
-      }
-
-      return true;
-    }
-  }
-
-  return false;
-}
-
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/backends/bind.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/backends/bind.hpp b/src/slave/containerizer/provisioners/backends/bind.hpp
deleted file mode 100644
index 61a8838..0000000
--- a/src/slave/containerizer/provisioners/backends/bind.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * 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_PROVISIONER_BIND_HPP__
-#define __MESOS_PROVISIONER_BIND_HPP__
-
-#include "slave/containerizer/provisioners/backend.hpp"
-
-namespace mesos {
-namespace internal {
-namespace slave {
-
-// Forward declaration.
-class BindBackendProcess;
-
-
-// This is a specialized backend that may be useful for deployments
-// using large (multi-GB) single-layer images *and* where more recent
-// kernel features such as overlayfs are not available (overlayfs-based
-// backend tracked by MESOS-2971). For small images (10's to 100's of MB)
-// the copy backend may be sufficient. NOTE:
-// 1) BindBackend supports only a single layer. Multi-layer images will
-//    fail to provision and the container will fail to launch!
-// 2) The filesystem is read-only because all containers using this
-//    image share the source. Select writable areas can be achieved by
-//    mounting read-write volumes to places like /tmp, /var/tmp,
-//    /home, etc. using the ContainerInfo. These can be relative to
-//    the executor work directory.
-//    N.B. Since the filesystem is read-only, '--sandbox_directory' must
-//    already exist within the filesystem because the filesystem isolator
-//    is unable to create it!
-// 3) It's fast because the bind mount requires (nearly) zero IO.
-class BindBackend : public Backend
-{
-public:
-  virtual ~BindBackend();
-
-  // BindBackend doesn't use any flag.
-  static Try<process::Owned<Backend>> create(const Flags&);
-
-  virtual process::Future<Nothing> provision(
-      const std::vector<std::string>& layers,
-      const std::string& rootfs);
-
-  virtual process::Future<bool> destroy(const std::string& rootfs);
-
-private:
-  explicit BindBackend(process::Owned<BindBackendProcess> process);
-
-  BindBackend(const BindBackend&); // Not copyable.
-  BindBackend& operator=(const BindBackend&); // Not assignable.
-
-  process::Owned<BindBackendProcess> process;
-};
-
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __MESOS_PROVISIONER_BIND_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/backends/copy.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/backends/copy.cpp b/src/slave/containerizer/provisioners/backends/copy.cpp
deleted file mode 100644
index b569465..0000000
--- a/src/slave/containerizer/provisioners/backends/copy.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
- * 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 <list>
-
-#include <process/collect.hpp>
-#include <process/defer.hpp>
-#include <process/dispatch.hpp>
-#include <process/io.hpp>
-#include <process/process.hpp>
-#include <process/subprocess.hpp>
-
-
-#include <stout/foreach.hpp>
-#include <stout/os.hpp>
-
-#include "common/status_utils.hpp"
-
-#include "slave/containerizer/provisioners/backends/copy.hpp"
-
-
-using namespace process;
-
-using std::string;
-using std::list;
-using std::vector;
-
-namespace mesos {
-namespace internal {
-namespace slave {
-
-class CopyBackendProcess : public Process<CopyBackendProcess>
-{
-public:
-  Future<Nothing> provision(const vector<string>& layers, const string& rootfs);
-
-  Future<bool> destroy(const string& rootfs);
-
-private:
-  Future<Nothing> _provision(string layer, const string& rootfs);
-};
-
-
-Try<Owned<Backend>> CopyBackend::create(const Flags&)
-{
-  return Owned<Backend>(new CopyBackend(
-      Owned<CopyBackendProcess>(new CopyBackendProcess())));
-}
-
-
-CopyBackend::~CopyBackend()
-{
-  terminate(process.get());
-  wait(process.get());
-}
-
-
-CopyBackend::CopyBackend(Owned<CopyBackendProcess> _process)
-  : process(_process)
-{
-  spawn(CHECK_NOTNULL(process.get()));
-}
-
-
-Future<Nothing> CopyBackend::provision(
-    const vector<string>& layers,
-    const string& rootfs)
-{
-  return dispatch(
-      process.get(), &CopyBackendProcess::provision, layers, rootfs);
-}
-
-
-Future<bool> CopyBackend::destroy(const string& rootfs)
-{
-  return dispatch(process.get(), &CopyBackendProcess::destroy, rootfs);
-}
-
-
-Future<Nothing> CopyBackendProcess::provision(
-    const vector<string>& layers,
-    const string& rootfs)
-{
-  if (layers.size() == 0) {
-    return Failure("No filesystem layers provided");
-  }
-
-  if (os::exists(rootfs)) {
-    return Failure("Rootfs is already provisioned");
-  }
-
-  Try<Nothing> mkdir = os::mkdir(rootfs);
-  if (mkdir.isError()) {
-    return Failure("Failed to create rootfs directory: " + mkdir.error());
-  }
-
-  list<Future<Nothing>> futures{Nothing()};
-
-  foreach (const string layer, layers) {
-    futures.push_back(
-        futures.back().then(
-            defer(self(), &Self::_provision, layer, rootfs)));
-  }
-
-  return collect(futures)
-    .then([]() -> Future<Nothing> { return Nothing(); });
-}
-
-
-Future<Nothing> CopyBackendProcess::_provision(
-  string layer,
-  const string& rootfs)
-{
-  VLOG(1) << "Copying layer path '" << layer << "' to rootfs '" << rootfs
-          << "'";
-
-#ifdef __APPLE__
-  if (!strings::endsWith(layer, "/")) {
-    layer += "/";
-  }
-
-  // OSX cp doesn't support -T flag, but supports source trailing
-  // slash so we only copy the content but not the folder.
-  vector<string> args{"cp", "-a", layer, rootfs};
-#else
-  vector<string> args{"cp", "-aT", layer, rootfs};
-#endif // __APPLE__
-
-  Try<Subprocess> s = subprocess(
-      "cp",
-      args,
-      Subprocess::PATH("/dev/null"),
-      Subprocess::PATH("/dev/null"),
-      Subprocess::PIPE());
-
-  if (s.isError()) {
-    return Failure("Failed to create 'cp' subprocess: " + s.error());
-  }
-
-  Subprocess cp = s.get();
-
-  return cp.status()
-    .then([cp](const Option<int>& status) -> Future<Nothing> {
-      if (status.isNone()) {
-        return Failure("Failed to reap subprocess to copy image");
-      } else if (status.get() != 0) {
-        return io::read(cp.err().get())
-          .then([](const string& err) -> Future<Nothing> {
-            return Failure("Failed to copy layer: " + err);
-          });
-      }
-
-      return Nothing();
-    });
-}
-
-
-Future<bool> CopyBackendProcess::destroy(const string& rootfs)
-{
-  vector<string> argv{"rm", "-rf", rootfs};
-
-  Try<Subprocess> s = subprocess(
-      "rm",
-      argv,
-      Subprocess::PATH("/dev/null"),
-      Subprocess::FD(STDOUT_FILENO),
-      Subprocess::FD(STDERR_FILENO));
-
-  if (s.isError()) {
-    return Failure("Failed to create 'rm' subprocess: " + s.error());
-  }
-
-  return s.get().status()
-    .then([](const Option<int>& status) -> Future<bool> {
-      if (status.isNone()) {
-        return Failure("Failed to reap subprocess to destroy rootfs");
-      } else if (status.get() != 0) {
-        return Failure("Failed to destroy rootfs, exit status: " +
-                       WSTRINGIFY(status.get()));
-      }
-
-      return true;
-    });
-}
-
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/backends/copy.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/backends/copy.hpp b/src/slave/containerizer/provisioners/backends/copy.hpp
deleted file mode 100644
index 2abca37..0000000
--- a/src/slave/containerizer/provisioners/backends/copy.hpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * 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_PROVISIONER_COPY_HPP__
-#define __MESOS_PROVISIONER_COPY_HPP__
-
-#include "slave/containerizer/provisioners/backend.hpp"
-
-namespace mesos {
-namespace internal {
-namespace slave {
-
-// Forward declaration.
-class CopyBackendProcess;
-
-
-class CopyBackend : public Backend
-{
-public:
-  virtual ~CopyBackend();
-
-  // CopyBackend doesn't use any flag.
-  static Try<process::Owned<Backend>> create(const Flags&);
-
-  // Provisions a rootfs given the layers' paths and target rootfs
-  // path.
-  virtual process::Future<Nothing> provision(
-      const std::vector<std::string>& layers,
-      const std::string& rootfs);
-
-  virtual process::Future<bool> destroy(const std::string& rootfs);
-
-private:
-  explicit CopyBackend(process::Owned<CopyBackendProcess> process);
-
-  CopyBackend(const CopyBackend&); // Not copyable.
-  CopyBackend& operator=(const CopyBackend&); // Not assignable.
-
-  process::Owned<CopyBackendProcess> process;
-};
-
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __MESOS_PROVISIONER_COPY_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/docker/registry_client.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/docker/registry_client.cpp b/src/slave/containerizer/provisioners/docker/registry_client.cpp
deleted file mode 100644
index b262ef0..0000000
--- a/src/slave/containerizer/provisioners/docker/registry_client.cpp
+++ /dev/null
@@ -1,575 +0,0 @@
-/**
- * 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 <vector>
-
-#include <process/defer.hpp>
-#include <process/dispatch.hpp>
-#include <process/io.hpp>
-
-#include "slave/containerizer/provisioners/docker/registry_client.hpp"
-#include "slave/containerizer/provisioners/docker/token_manager.hpp"
-
-using std::string;
-using std::vector;
-
-using process::Failure;
-using process::Future;
-using process::Owned;
-using process::Process;
-
-using process::http::Request;
-using process::http::Response;
-using process::http::URL;
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace docker {
-namespace registry {
-
-using FileSystemLayerInfo = RegistryClient::FileSystemLayerInfo;
-
-using ManifestResponse = RegistryClient::ManifestResponse;
-
-const Duration RegistryClient::DEFAULT_MANIFEST_TIMEOUT_SECS = Seconds(10);
-
-const size_t RegistryClient::DEFAULT_MANIFEST_MAXSIZE_BYTES = 4096;
-
-static const uint16_t DEFAULT_SSL_PORT = 443;
-
-class RegistryClientProcess : public Process<RegistryClientProcess>
-{
-public:
-  static Try<Owned<RegistryClientProcess>> create(
-      const URL& authServer,
-      const URL& registry,
-      const Option<RegistryClient::Credentials>& creds);
-
-  Future<RegistryClient::ManifestResponse> getManifest(
-      const string& path,
-      const Option<string>& tag,
-      const Duration& timeout);
-
-  Future<size_t> getBlob(
-      const string& path,
-      const Option<string>& digest,
-      const Path& filePath,
-      const Duration& timeout,
-      size_t maxSize);
-
-private:
-  RegistryClientProcess(
-    const Owned<TokenManager>& tokenMgr,
-    const URL& registryServer,
-    const Option<RegistryClient::Credentials>& creds);
-
-  Future<Response> doHttpGet(
-      const URL& url,
-      const Option<hashmap<string, string>>& headers,
-      const Duration& timeout,
-      bool resend,
-      const Option<string>& lastResponse) const;
-
-  Try<hashmap<string, string>> getAuthenticationAttributes(
-      const Response& httpResponse) const;
-
-  Owned<TokenManager> tokenManager_;
-  const URL registryServer_;
-  const Option<RegistryClient::Credentials> credentials_;
-
-  RegistryClientProcess(const RegistryClientProcess&) = delete;
-  RegistryClientProcess& operator = (const RegistryClientProcess&) = delete;
-};
-
-
-Try<Owned<RegistryClient>> RegistryClient::create(
-    const URL& authServer,
-    const URL& registryServer,
-    const Option<Credentials>& creds)
-{
-  Try<Owned<RegistryClientProcess>> process =
-    RegistryClientProcess::create(authServer, registryServer, creds);
-
-  if (process.isError()) {
-    return Error(process.error());
-  }
-
-  return Owned<RegistryClient>(
-      new RegistryClient(authServer, registryServer, creds, process.get()));
-}
-
-
-RegistryClient::RegistryClient(
-    const URL& authServer,
-    const URL& registryServer,
-    const Option<Credentials>& creds,
-    const Owned<RegistryClientProcess>& process)
-  : authServer_(authServer),
-    registryServer_(registryServer),
-    credentials_(creds),
-    process_(process)
-{
-  spawn(CHECK_NOTNULL(process_.get()));
-}
-
-
-RegistryClient::~RegistryClient()
-{
-  terminate(process_.get());
-  process::wait(process_.get());
-}
-
-
-Future<ManifestResponse> RegistryClient::getManifest(
-    const string& _path,
-    const Option<string>& _tag,
-    const Option<Duration>& _timeout)
-{
-  Duration timeout = _timeout.getOrElse(DEFAULT_MANIFEST_TIMEOUT_SECS);
-
-  return dispatch(
-      process_.get(),
-      &RegistryClientProcess::getManifest,
-      _path,
-      _tag,
-      timeout);
-}
-
-
-Future<size_t> RegistryClient::getBlob(
-    const string& _path,
-    const Option<string>& _digest,
-    const Path& _filePath,
-    const Option<Duration>& _timeout,
-    const Option<size_t>& _maxSize)
-{
-  Duration timeout = _timeout.getOrElse(DEFAULT_MANIFEST_TIMEOUT_SECS);
-  size_t maxSize = _maxSize.getOrElse(DEFAULT_MANIFEST_MAXSIZE_BYTES);
-
-  return dispatch(
-        process_.get(),
-        &RegistryClientProcess::getBlob,
-        _path,
-        _digest,
-        _filePath,
-        timeout,
-        maxSize);
-}
-
-
-Try<Owned<RegistryClientProcess>> RegistryClientProcess::create(
-    const URL& authServer,
-    const URL& registryServer,
-    const Option<RegistryClient::Credentials>& creds)
-{
-  Try<Owned<TokenManager>> tokenMgr = TokenManager::create(authServer);
-  if (tokenMgr.isError()) {
-    return Error("Failed to create token manager: " + tokenMgr.error());
-  }
-
-  return Owned<RegistryClientProcess>(
-      new RegistryClientProcess(tokenMgr.get(), registryServer, creds));
-}
-
-
-RegistryClientProcess::RegistryClientProcess(
-    const Owned<TokenManager>& tokenMgr,
-    const URL& registryServer,
-    const Option<RegistryClient::Credentials>& creds)
-  : tokenManager_(tokenMgr),
-    registryServer_(registryServer),
-    credentials_(creds) {}
-
-
-Try<hashmap<string, string>>
-RegistryClientProcess::getAuthenticationAttributes(
-    const Response& httpResponse) const
-{
-  if (httpResponse.headers.find("WWW-Authenticate") ==
-      httpResponse.headers.end()) {
-    return Error("Failed to find WWW-Authenticate header value");
-  }
-
-  const string& authString = httpResponse.headers.at("WWW-Authenticate");
-
-  const vector<string> authStringTokens = strings::tokenize(authString, " ");
-  if ((authStringTokens.size() != 2) || (authStringTokens[0] != "Bearer")) {
-    // TODO(jojy): Look at various possibilities of auth response. We currently
-    // assume that the string will have realm information.
-    return Error("Invalid authentication header value: " + authString);
-  }
-
-  const vector<string> authParams = strings::tokenize(authStringTokens[1], ",");
-
-  hashmap<string, string> authAttributes;
-  auto addAttribute = [&authAttributes](
-      const string& param) -> Try<Nothing> {
-    const vector<string> paramTokens =
-      strings::tokenize(param, "=\"");
-
-    if (paramTokens.size() != 2) {
-      return Error(
-          "Failed to get authentication attribute from response parameter " +
-          param);
-    }
-
-    authAttributes.insert({paramTokens[0], paramTokens[1]});
-
-    return Nothing();
-  };
-
-  foreach (const string& param, authParams) {
-    Try<Nothing> addRes = addAttribute(param);
-    if (addRes.isError()) {
-      return Error(addRes.error());
-    }
-  }
-
-  return authAttributes;
-}
-
-
-Future<Response>
-RegistryClientProcess::doHttpGet(
-    const URL& url,
-    const Option<hashmap<string, string>>& headers,
-    const Duration& timeout,
-    bool resend,
-    const Option<string>& lastResponseStatus) const
-{
-  return process::http::get(url, headers)
-    .after(timeout, [](
-        const Future<Response>& httpResponseFuture) -> Future<Response> {
-      return Failure("Response timeout");
-    })
-    .then(defer(self(), [=](
-        const Response& httpResponse) -> Future<Response> {
-      VLOG(1) << "Response status: " + httpResponse.status;
-
-      // Set the future if we get a OK response.
-      if (httpResponse.status == "200 OK") {
-        return httpResponse;
-      } else if (httpResponse.status == "400 Bad Request") {
-        Try<JSON::Object> errorResponse =
-          JSON::parse<JSON::Object>(httpResponse.body);
-
-        if (errorResponse.isError()) {
-          return Failure("Failed to parse bad request response JSON: " +
-                         errorResponse.error());
-        }
-
-        std::ostringstream out;
-        bool first = true;
-        Result<JSON::Array> errorObjects =
-          errorResponse.get().find<JSON::Array>("errors");
-
-        if (errorObjects.isError()) {
-          return Failure("Failed to find 'errors' in bad request response: " +
-                         errorObjects.error());
-        } else if (errorObjects.isNone()) {
-          return Failure("Errors not found in bad request response");
-        }
-
-        foreach (const JSON::Value& error, errorObjects.get().values) {
-          Result<JSON::String> message =
-            error.as<JSON::Object>().find<JSON::String>("message");
-          if (message.isError()) {
-            return Failure("Failed to parse bad request error message: " +
-                           message.error());
-          } else if (message.isNone()) {
-            continue;
-          }
-
-          if (first) {
-            out << message.get().value;
-            first = false;
-          } else {
-            out << ", " << message.get().value;
-          }
-        }
-        return Failure("Received Bad request, errors: [" + out.str() + "]");
-      }
-
-      // Prevent infinite recursion.
-      if (lastResponseStatus.isSome() &&
-          (lastResponseStatus.get() == httpResponse.status)) {
-        return Failure("Invalid response: " + httpResponse.status);
-      }
-
-      // If resend is not set, we dont try again and stop here.
-      if (!resend) {
-        return Failure("Bad response: " + httpResponse.status);
-      }
-
-      // Handle 401 Unauthorized.
-      if (httpResponse.status == "401 Unauthorized") {
-        Try<hashmap<string, string>> authAttributes =
-          getAuthenticationAttributes(httpResponse);
-
-        if (authAttributes.isError()) {
-          return Failure(
-              "Failed to get authentication attributes: " +
-              authAttributes.error());
-        }
-
-        // TODO(jojy): Currently only handling TLS/cert authentication.
-        Future<Token> tokenResponse = tokenManager_->getToken(
-          authAttributes.get().at("service"),
-          authAttributes.get().at("scope"),
-          None());
-
-        return tokenResponse
-          .after(timeout, [=](
-              Future<Token> tokenResponse) -> Future<Token> {
-            tokenResponse.discard();
-            return Failure("Token response timeout");
-          })
-          .then(defer(self(), [=](
-              const Future<Token>& tokenResponse) {
-            // Send request with acquired token.
-            hashmap<string, string> authHeaders = {
-              {"Authorization", "Bearer " + tokenResponse.get().raw}
-            };
-
-            return doHttpGet(
-                url,
-                authHeaders,
-                timeout,
-                true,
-                httpResponse.status);
-        }));
-      } else if (httpResponse.status == "307 Temporary Redirect") {
-        // Handle redirect.
-
-        // TODO(jojy): Add redirect functionality in http::get.
-
-        auto toURL = [](
-            const string& urlString) -> Try<URL> {
-          // TODO(jojy): Need to add functionality to URL class that parses a
-          // string to its URL components. For now, assuming:
-          //  - scheme is https
-          //  - path always ends with /
-
-          static const string schemePrefix = "https://";
-
-          if (!strings::contains(urlString, schemePrefix)) {
-            return Error(
-                "Failed to find expected token '" + schemePrefix +
-                "' in redirect url");
-          }
-
-          const string schemeSuffix = urlString.substr(schemePrefix.length());
-
-          const vector<string> components =
-            strings::tokenize(schemeSuffix, "/");
-
-          const string path = schemeSuffix.substr(components[0].length());
-
-          const vector<string> addrComponents =
-            strings::tokenize(components[0], ":");
-
-          uint16_t port = DEFAULT_SSL_PORT;
-          string domain = components[0];
-
-          // Parse the port.
-          if (addrComponents.size() == 2) {
-            domain = addrComponents[0];
-
-            Try<uint16_t> tryPort = numify<uint16_t>(addrComponents[1]);
-            if (tryPort.isError()) {
-              return Error(
-                  "Failed to parse location: " + urlString + " for port.");
-            }
-
-            port = tryPort.get();
-          }
-
-          return URL("https", domain, port, path);
-        };
-
-        if (httpResponse.headers.find("Location") ==
-            httpResponse.headers.end()) {
-          return Failure(
-              "Invalid redirect response: 'Location' not found in headers.");
-        }
-
-        const string& location = httpResponse.headers.at("Location");
-        Try<URL> tryUrl = toURL(location);
-        if (tryUrl.isError()) {
-          return Failure(
-              "Failed to parse '" + location + "': " + tryUrl.error());
-        }
-
-        return doHttpGet(
-            tryUrl.get(),
-            headers,
-            timeout,
-            false,
-            httpResponse.status);
-      } else {
-        return Failure("Invalid response: " + httpResponse.status);
-      }
-    }));
-}
-
-
-Future<ManifestResponse> RegistryClientProcess::getManifest(
-    const string& path,
-    const Option<string>& tag,
-    const Duration& timeout)
-{
-  //TODO(jojy): These validations belong in the URL class.
-  if (strings::contains(path, " ")) {
-    return Failure("Invalid repository path: " + path);
-  }
-
-  string repoTag = tag.getOrElse("latest");
-  if (strings::contains(repoTag, " ")) {
-    return Failure("Invalid repository tag: " + repoTag);
-  }
-
-  URL manifestURL(registryServer_);
-  manifestURL.path =
-    "v2/" + path + "/manifests/" + repoTag;
-
-  auto getManifestResponse = [](
-      const Response& httpResponse) -> Try<ManifestResponse> {
-    if (!httpResponse.headers.contains("Docker-Content-Digest")) {
-      return Error("Docker-Content-Digest header missing in response");
-    }
-
-    Try<JSON::Object> responseJSON =
-      JSON::parse<JSON::Object>(httpResponse.body);
-
-    if (responseJSON.isError()) {
-      return Error(responseJSON.error());
-    }
-
-    Result<JSON::String> name = responseJSON.get().find<JSON::String>("name");
-    if (name.isNone()) {
-      return Error("Failed to find \"name\" in manifest response");
-    }
-
-    Result<JSON::Array> fsLayers =
-      responseJSON.get().find<JSON::Array>("fsLayers");
-
-    if (fsLayers.isNone()) {
-      return Error("Failed to find \"fsLayers\" in manifest response");
-    }
-
-    vector<FileSystemLayerInfo> fsLayerInfoList;
-    foreach (const JSON::Value& layer, fsLayers.get().values) {
-      const JSON::Object& layerInfoJSON = layer.as<JSON::Object>();
-      Result<JSON::String> blobSumInfo =
-        layerInfoJSON.find<JSON::String>("blobSum");
-
-      if (blobSumInfo.isNone()) {
-        return Error("Failed to find \"blobSum\" in manifest response");
-      }
-
-      fsLayerInfoList.emplace_back(
-          FileSystemLayerInfo{blobSumInfo.get().value});
-    }
-
-    return ManifestResponse {
-      name.get().value,
-      httpResponse.headers.at("Docker-Content-Digest"),
-      fsLayerInfoList,
-    };
-  };
-
-  return doHttpGet(manifestURL, None(), timeout, true, None())
-    .then([getManifestResponse] (
-        const Response& response) -> Future<ManifestResponse> {
-      Try<ManifestResponse> manifestResponse = getManifestResponse(response);
-
-      if (manifestResponse.isError()) {
-        return Failure(
-            "Failed to parse manifest response: " + manifestResponse.error());
-      }
-
-      return manifestResponse.get();
-    });
-}
-
-
-Future<size_t> RegistryClientProcess::getBlob(
-    const string& path,
-    const Option<string>& digest,
-    const Path& filePath,
-    const Duration& timeout,
-    size_t maxSize)
-{
-  auto prepare = ([&filePath]() -> Try<Nothing> {
-      const string dirName = filePath.dirname();
-
-      //TODO(jojy): Return more state, for example - if the directory is new.
-      Try<Nothing> dirResult = os::mkdir(dirName, true);
-      if (dirResult.isError()) {
-        return Error(
-            "Failed to create directory to download blob: " +
-            dirResult.error());
-      }
-
-      return dirResult;
-  })();
-
-  // TODO(jojy): This currently leaves a residue in failure cases. Would be
-  // ideal if we can completely rollback.
-  if (prepare.isError()) {
-     return Failure(prepare.error());
-  }
-
-  if (strings::contains(path, " ")) {
-    return Failure("Invalid repository path: " + path);
-  }
-
-  URL blobURL(registryServer_);
-  blobURL.path =
-    "v2/" + path + "/blobs/" + digest.getOrElse("");
-
-  auto saveBlob = [filePath](
-      const Response& httpResponse) -> Future<size_t> {
-    // TODO(jojy): Add verification step.
-    // TODO(jojy): Add check for max size.
-    size_t size = httpResponse.body.length();
-    Try<int> fd = os::open(
-        filePath.value,
-        O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
-        S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
-    if (fd.isError()) {
-      return Failure("Failed to open file '" + filePath.value + "': " +
-                     fd.error());
-    }
-
-    return process::io::write(fd.get(), httpResponse.body)
-      .then([size](const Future<Nothing>&) { return size; })
-      .onAny([fd]() { os::close(fd.get()); } );
-  };
-
-  return doHttpGet(blobURL, None(), timeout, true, None())
-    .then([saveBlob](const Response& response) { return saveBlob(response); });
-}
-
-} // namespace registry {
-} // namespace docker {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/docker/registry_client.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/docker/registry_client.hpp b/src/slave/containerizer/provisioners/docker/registry_client.hpp
deleted file mode 100644
index 3ec3741..0000000
--- a/src/slave/containerizer/provisioners/docker/registry_client.hpp
+++ /dev/null
@@ -1,163 +0,0 @@
-/**
- * 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 __PROVISIONERS_DOCKER_REGISTRY_CLIENT_HPP__
-#define __PROVISIONERS_DOCKER_REGISTRY_CLIENT_HPP__
-
-#include <string>
-#include <vector>
-
-#include <stout/duration.hpp>
-#include <stout/hashmap.hpp>
-#include <stout/json.hpp>
-#include <stout/path.hpp>
-
-#include <process/future.hpp>
-#include <process/http.hpp>
-#include <process/process.hpp>
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace docker {
-namespace registry {
-
-// Forward declarations.
-class RegistryClientProcess;
-
-
-class RegistryClient
-{
-public:
-  /**
-   * Encapsulates information about a file system layer.
-   */
-  struct FileSystemLayerInfo {
-    //TODO(jojy): This string includes the checksum type also now. Need to
-    //separate this into checksum method and checksum.
-    std::string checksumInfo;
-  };
-
-  /**
-   * Encapsulates response of "GET Manifest" request.
-   *
-   * Reference: https://docs.docker.com/registry/spec/api
-   */
-  struct ManifestResponse {
-    const std::string name;
-    const std::string digest;
-    const std::vector<FileSystemLayerInfo> fsLayerInfoList;
-  };
-
-  /**
-   * Encapsulates auth credentials for the client sessions.
-   * TODO(jojy): Secure heap to protect the credentials.
-   */
-  struct Credentials {
-    /**
-     * UserId for basic authentication.
-     */
-    const Option<std::string> userId;
-    /**
-     * Password for basic authentication.
-     */
-    const Option<std::string> password;
-    /**
-     * Account for fetching data from registry.
-     */
-    const Option<std::string> account;
-  };
-
-  /**
-   * Factory method for creating RegistryClient objects.
-   *
-   * @param authServer URL of authorization server.
-   * @param registryServer URL of docker registry server.
-   * @param credentials credentials for client session (optional).
-   * @return RegistryClient on Success.
-   *         Error on failure.
-   */
-  static Try<process::Owned<RegistryClient>> create(
-      const process::http::URL& authServer,
-      const process::http::URL& registryServer,
-      const Option<Credentials>& credentials);
-
-  /**
-   * Fetches manifest for a repository from the client's remote registry server.
-   *
-   * @param path path of the repository on the registry.
-   * @param tag unique tag that identifies the repository. Will default to
-   *    latest.
-   * @param timeout Maximum time ater which the request will timeout and return
-   *    a failure. Will default to RESPONSE_TIMEOUT.
-   * @return JSON object on success.
-   *         Failure on process failure.
-   */
-  process::Future<ManifestResponse> getManifest(
-      const std::string& path,
-      const Option<std::string>& tag,
-      const Option<Duration>& timeout);
-
-  /**
-   * Fetches blob for a repository from the client's remote registry server.
-   *
-   * @param path path of the repository on the registry.
-   * @param digest digest of the blob (from manifest).
-   * @param filePath file path to store the fetched blob.
-   * @param timeout Maximum time ater which the request will timeout and return
-   *    a failure. Will default to RESPONSE_TIMEOUT.
-   * @param maxSize Maximum size of the response thats acceptable. Will default
-   *    to MAX_RESPONSE_SIZE.
-   * @return size of downloaded blob on success.
-   *         Failure in case of any errors.
-   */
-  process::Future<size_t> getBlob(
-      const std::string& path,
-      const Option<std::string>& digest,
-      const Path& filePath,
-      const Option<Duration>& timeout,
-      const Option<size_t>& maxSize);
-
-  ~RegistryClient();
-
-private:
-  RegistryClient(
-    const process::http::URL& authServer,
-    const process::http::URL& registryServer,
-    const Option<Credentials>& credentials,
-    const process::Owned<RegistryClientProcess>& process);
-
-  static const Duration DEFAULT_MANIFEST_TIMEOUT_SECS;
-  static const size_t DEFAULT_MANIFEST_MAXSIZE_BYTES;
-
-  const process::http::URL authServer_;
-  const process::http::URL registryServer_;
-  const Option<Credentials> credentials_;
-  process::Owned<RegistryClientProcess> process_;
-
-  RegistryClient(const RegistryClient&) = delete;
-  RegistryClient& operator=(const RegistryClient&) = delete;
-};
-
-} // namespace registry {
-} // namespace docker {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __PROVISIONERS_DOCKER_REGISTRY_CLIENT_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/docker/token_manager.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/docker/token_manager.cpp b/src/slave/containerizer/provisioners/docker/token_manager.cpp
deleted file mode 100644
index aec915f..0000000
--- a/src/slave/containerizer/provisioners/docker/token_manager.cpp
+++ /dev/null
@@ -1,361 +0,0 @@
-/**
- * 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 <process/defer.hpp>
-#include <process/dispatch.hpp>
-
-#include "slave/containerizer/provisioners/docker/token_manager.hpp"
-
-using std::hash;
-using std::string;
-using std::vector;
-
-using process::Clock;
-using process::Failure;
-using process::Future;
-using process::Owned;
-using process::Process;
-using process::Time;
-
-using process::http::Request;
-using process::http::Response;
-using process::http::URL;
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace docker {
-namespace registry {
-
-class TokenManagerProcess : public Process<TokenManagerProcess>
-{
-public:
-  static Try<Owned<TokenManagerProcess>> create(const URL& realm);
-
-  Future<Token> getToken(
-      const string& service,
-      const string& scope,
-      const Option<string>& account);
-
-private:
-  static const string TOKEN_PATH_PREFIX;
-  static const Duration RESPONSE_TIMEOUT;
-
-  TokenManagerProcess(const URL& realm)
-    : realm_(realm) {}
-
-  Try<Token> getTokenFromResponse(const Response& response) const;
-
-  /**
-   * Key for the token cache.
-   */
-  struct TokenCacheKey
-  {
-    string service;
-    string scope;
-  };
-
-  struct TokenCacheKeyHash
-  {
-    size_t operator()(const TokenCacheKey& key) const
-    {
-      hash<string> hashFn;
-
-      return (hashFn(key.service) ^
-          (hashFn(key.scope) << 1));
-    }
-  };
-
-  struct TokenCacheKeyEqual
-  {
-    bool operator()(
-        const TokenCacheKey& left,
-        const TokenCacheKey& right) const
-    {
-      return ((left.service == right.service) &&
-          (left.scope == right.scope));
-    }
-  };
-
-  typedef hashmap<
-    const TokenCacheKey,
-    Token,
-    TokenCacheKeyHash,
-    TokenCacheKeyEqual> TokenCacheType;
-
-  const URL realm_;
-  TokenCacheType tokenCache_;
-
-  TokenManagerProcess(const TokenManagerProcess&) = delete;
-  TokenManagerProcess& operator=(const TokenManagerProcess&) = delete;
-};
-
-const Duration TokenManagerProcess::RESPONSE_TIMEOUT = Seconds(10);
-const string TokenManagerProcess::TOKEN_PATH_PREFIX = "/v2/token/";
-
-
-Token::Token(
-    const string& _raw,
-    const JSON::Object& _header,
-    const JSON::Object& _claims,
-    const Option<Time>& _expiration,
-    const Option<Time>& _notBefore)
-  : raw(_raw),
-    header(_header),
-    claims(_claims),
-    expiration(_expiration),
-    notBefore(_notBefore) {}
-
-
-Try<Token> Token::create(const string& raw)
-{
-  auto decode = [](
-      const string& segment) -> Try<JSON::Object> {
-    const auto padding = segment.length() % 4;
-    string paddedSegment(segment);
-
-    if (padding) {
-      paddedSegment.append(padding, '=');
-    }
-
-    Try<string> decoded = base64::decode(paddedSegment);
-    if (decoded.isError()) {
-      return Error(decoded.error());
-    }
-
-    return JSON::parse<JSON::Object>(decoded.get());
-  };
-
-  const vector<string> tokens = strings::tokenize(raw, ".");
-
-  if (tokens.size() != 3) {
-    return Error("Invalid raw token string");
-  }
-
-  Try<JSON::Object> header = decode(tokens[0]);
-  if (header.isError()) {
-    return Error("Failed to decode 'header' segment: " + header.error());
-  }
-
-  Try<JSON::Object> claims = decode(tokens[1]);
-  if (claims.isError()) {
-    return Error("Failed to decode 'claims' segment: " + claims.error());
-  }
-
-  Result<Time> expirationTime = getTimeValue(claims.get(), "exp");
-  if (expirationTime.isError()) {
-    return Error("Failed to decode expiration time: " + expirationTime.error());
-  }
-
-  Option<Time> expiration;
-  if (expirationTime.isSome()) {
-    expiration = expirationTime.get();
-  }
-
-  Result<Time> notBeforeTime = getTimeValue(claims.get(), "nbf");
-  if (notBeforeTime.isError()) {
-    return Error("Failed to decode not-before time: " + notBeforeTime.error());
-  }
-
-  Option<Time> notBefore;
-  if (notBeforeTime.isSome()) {
-    notBefore = notBeforeTime.get();
-  }
-
-  Token token(raw, header.get(), claims.get(), expiration, notBefore);
-
-  if (token.isExpired()) {
-    return Error("Token has expired");
-  }
-
-  // TODO(jojy): Add signature validation.
-  return token;
-}
-
-
-Result<Time> Token::getTimeValue(const JSON::Object& object, const string& key)
-{
-  Result<JSON::Number> jsonValue = object.find<JSON::Number>(key);
-
-  Option<Time> timeValue;
-
-  // If expiration is provided, we will process it for future validations.
-  if (jsonValue.isSome()) {
-    Try<Time> time = Time::create(jsonValue.get().value);
-    if (time.isError()) {
-      return Error("Failed to decode time: " + time.error());
-    }
-
-    timeValue = time.get();
-  }
-
-  return timeValue;
-}
-
-
-bool Token::isExpired() const
-{
-  if (expiration.isSome()) {
-    return (Clock::now() >= expiration.get());
-  }
-
-  return false;
-}
-
-
-bool Token::isValid() const
-{
-  if (!isExpired()) {
-    if (notBefore.isSome()) {
-      return (Clock::now() >= notBefore.get());
-    }
-
-    return true;
-  }
-
-  // TODO(jojy): Add signature validation.
-  return false;
-}
-
-
-Try<Owned<TokenManager>> TokenManager::create(
-    const URL& realm)
-{
-  Try<Owned<TokenManagerProcess>> process = TokenManagerProcess::create(realm);
-  if (process.isError()) {
-    return Error(process.error());
-  }
-
-  return Owned<TokenManager>(new TokenManager(process.get()));
-}
-
-
-TokenManager::TokenManager(Owned<TokenManagerProcess>& process)
-  : process_(process)
-{
-  spawn(CHECK_NOTNULL(process_.get()));
-}
-
-
-TokenManager::~TokenManager()
-{
-  terminate(process_.get());
-  process::wait(process_.get());
-}
-
-
-Future<Token> TokenManager::getToken(
-    const string& service,
-    const string& scope,
-    const Option<string>& account)
-{
-  return dispatch(
-      process_.get(),
-      &TokenManagerProcess::getToken,
-      service,
-      scope,
-      account);
-}
-
-
-Try<Owned<TokenManagerProcess>> TokenManagerProcess::create(const URL& realm)
-{
-  return Owned<TokenManagerProcess>(new TokenManagerProcess(realm));
-}
-
-
-Try<Token> TokenManagerProcess::getTokenFromResponse(
-    const Response& response) const
-{
-  Try<JSON::Object> tokenJSON = JSON::parse<JSON::Object>(response.body);
-  if (tokenJSON.isError()) {
-    return Error(tokenJSON.error());
-  }
-
-  Result<JSON::String> tokenString =
-    tokenJSON.get().find<JSON::String>("token");
-
-  if (tokenString.isError()) {
-    return Error(tokenString.error());
-  }
-
-  Try<Token> result = Token::create(tokenString.get().value);
-  if (result.isError()) {
-    return Error(result.error());
-  }
-
-  return result.get();;
-}
-
-
-Future<Token> TokenManagerProcess::getToken(
-    const string& service,
-    const string& scope,
-    const Option<string>& account)
-{
-  const TokenCacheKey tokenKey = {service, scope};
-
-  if (tokenCache_.contains(tokenKey)) {
-    Token token = tokenCache_.at(tokenKey);
-
-    if (token.isValid()) {
-      return token;
-    } else {
-      LOG(WARNING) << "Cached token was invalid. Will fetch once again";
-    }
-  }
-
-  URL tokenUrl = realm_;
-  tokenUrl.path = TOKEN_PATH_PREFIX;
-
-  tokenUrl.query = {
-    {"service", service},
-    {"scope", scope},
-  };
-
-  if (account.isSome()) {
-    tokenUrl.query.insert({"account", account.get()});
-  }
-
-  return process::http::get(tokenUrl, None())
-    .after(RESPONSE_TIMEOUT, [] (Future<Response> resp) -> Future<Response> {
-      resp.discard();
-      return Failure("Timeout waiting for response to token request");
-    })
-    .then(defer(self(), [this, tokenKey](
-        const Future<Response>& response) -> Future<Token> {
-      Try<Token> token = getTokenFromResponse(response.get());
-      if (token.isError()) {
-        return Failure(
-            "Failed to parse JSON Web Token object from response: " +
-            token.error());
-      }
-
-      tokenCache_.insert({tokenKey, token.get()});
-
-      return token.get();
-    }));
-}
-
-// TODO(jojy): Add implementation for basic authentication based getToken API.
-
-} // namespace registry {
-} // namespace docker {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/docker/token_manager.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/docker/token_manager.hpp b/src/slave/containerizer/provisioners/docker/token_manager.hpp
deleted file mode 100644
index 879269d..0000000
--- a/src/slave/containerizer/provisioners/docker/token_manager.hpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- * 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 __PROVISIONERS_DOCKER_TOKEN_MANAGER_HPP__
-#define __PROVISIONERS_DOCKER_TOKEN_MANAGER_HPP__
-
-#include <functional>
-#include <string>
-
-#include <stout/base64.hpp>
-#include <stout/duration.hpp>
-#include <stout/hashmap.hpp>
-#include <stout/strings.hpp>
-
-#include <process/future.hpp>
-#include <process/http.hpp>
-#include <process/process.hpp>
-#include <process/time.hpp>
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace docker {
-namespace registry {
-
-
-/**
- * Encapsulates JSON Web Token.
- *
- * Reference: https://tools.ietf.org/html/rfc7519.
- */
-struct Token
-{
-  /**
-   * Factory method for Token object.
-   *
-   * Parses the raw token string and validates for token's expiration.
-   *
-   * @returns Token if parsing and validation succeeds.
-   *          Error if parsing or validation fails.
-   */
-  static Try<Token> create(const std::string& rawString);
-
-  /**
-   * Compares token's expiration time(expressed in seconds) with current time.
-   *
-   * @returns True if token's expiration time is greater than current time.
-   *          False if token's expiration time is less than or equal to current
-   *          time.
-   */
-  bool isExpired() const;
-
-  /**
-   * Validates the token if its "exp" "nbf" values are in range.
-   *
-   * @returns True if current time is within token's "exp" and "nbf" values.
-   *          False if current time is not within token's "exp" and "nbf"
-   *          values.
-   */
-  bool isValid() const;
-
-  const std::string raw;
-  const JSON::Object header;
-  const JSON::Object claims;
-  // TODO(jojy): Add signature information.
-
-private:
-  Token(
-      const std::string& raw,
-      const JSON::Object& headerJson,
-      const JSON::Object& claimsJson,
-      const Option<process::Time>& expireTime,
-      const Option<process::Time>& notBeforeTime);
-
-  static Result<process::Time> getTimeValue(
-      const JSON::Object& object,
-      const std::string& key);
-
-  const Option<process::Time> expiration;
-  const Option<process::Time> notBefore;
-};
-
-
-// Forward declaration.
-class TokenManagerProcess;
-
-
-/**
- *  Acquires and manages docker registry tokens. It keeps the tokens in its
- *  cache to server any future request for the same token.
- *  The cache grows unbounded.
- *  TODO(jojy): The cache can be optimized to prune based on the expiry time of
- *  the token and server's issue time.
- */
-class TokenManager
-{
-public:
-  /**
-   * Factory method for creating TokenManager object.
-   *
-   * TokenManager and registry authorization realm has a 1:1 relationship.
-   *
-   * @param realm URL of the authorization server from where token will be
-   *     requested by this TokenManager.
-   * @returns Owned<TokenManager> if success.
-   *          Error on failure.
-   */
-  static Try<process::Owned<TokenManager>> create(
-      const process::http::URL& realm);
-
-  /**
-   * Returns JSON Web Token from cache or from remote server using "Basic
-   * authorization".
-   *
-   * @param service Name of the service that hosts the resource for which
-   *     token is being requested.
-   * @param scope unique scope returned by the 401 Unauthorized response
-   *     from the registry.
-   * @param account Name of the account which the client is acting as.
-   * @param user base64 encoded userid for basic authorization.
-   * @param password base64 encoded password for basic authorization.
-   * @returns Token struct that encapsulates JSON Web Token.
-   */
-  process::Future<Token> getToken(
-      const std::string& service,
-      const std::string& scope,
-      const Option<std::string>& account,
-      const std::string& user,
-      const Option<std::string>& password);
-
-  /**
-   * Returns JSON Web Token from cache or from remote server using "TLS/Cert"
-   * based authorization.
-   *
-   * @param service Name of the service that hosts the resource for which
-   *     token is being requested.
-   * @param scope unique scope returned by the 401 Unauthorized response
-   *     from the registry.
-   * @param account Name of the account which the client is acting as.
-   * @returns Token struct that encapsulates JSON Web Token.
-   */
-  process::Future<Token> getToken(
-      const std::string& service,
-      const std::string& scope,
-      const Option<std::string>& account);
-
-  ~TokenManager();
-
-private:
-  TokenManager(process::Owned<TokenManagerProcess>& process);
-
-  TokenManager(const TokenManager&) = delete;
-  TokenManager& operator=(const TokenManager&) = delete;
-
-  process::Owned<TokenManagerProcess> process_;
-};
-
-} // namespace registry {
-} // namespace docker {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __PROVISIONERS_DOCKER_TOKEN_MANAGER_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/paths.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/paths.cpp b/src/slave/containerizer/provisioners/paths.cpp
deleted file mode 100644
index 4293dd2..0000000
--- a/src/slave/containerizer/provisioners/paths.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- * 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 <list>
-
-#include <glog/logging.h>
-
-#include <mesos/type_utils.hpp>
-
-#include <stout/os.hpp>
-#include <stout/path.hpp>
-
-#include <stout/os/stat.hpp>
-
-#include "slave/containerizer/provisioners/paths.hpp"
-#include "slave/paths.hpp"
-
-using std::list;
-using std::string;
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace provisioners {
-namespace paths {
-
-static string getContainersDir(const string& provisionerDir)
-{
-  return path::join(provisionerDir, "containers");
-}
-
-
-static string getBackendsDir(const string& containerDir)
-{
-  return path::join(containerDir, "backends");
-}
-
-
-static string getBackendDir(const string& backendsDir, const string& backend)
-{
-  return path::join(backendsDir, backend);
-}
-
-
-static string getRootfsesDir(const string& backendDir)
-{
-  return path::join(backendDir, "rootfses");
-}
-
-
-static string getRootfsDir(const string& rootfsesDir, const string& roofsId)
-{
-  return path::join(rootfsesDir, roofsId);
-}
-
-
-string getContainerDir(
-    const string& provisionerDir,
-    const ContainerID& containerId)
-{
-  return path::join(getContainersDir(provisionerDir), containerId.value());
-}
-
-
-string getContainerRootfsDir(
-    const string& provisionerDir,
-    const ContainerID& containerId,
-    const string& backend,
-    const string& rootfsId)
-{
-  return getRootfsDir(
-      getRootfsesDir(
-          getBackendDir(
-              getBackendsDir(
-                  getContainerDir(
-                      provisionerDir,
-                      containerId)),
-              backend)),
-      rootfsId);
-}
-
-
-Try<hashmap<ContainerID, string>> listContainers(
-    const string& provisionerDir)
-{
-  hashmap<ContainerID, string> results;
-
-  string containersDir = getContainersDir(provisionerDir);
-  if (!os::exists(containersDir)) {
-    // No container has been created yet.
-    return results;
-  }
-
-  Try<list<string>> containerIds = os::ls(containersDir);
-  if (containerIds.isError()) {
-    return Error("Unable to list the containers directory: " +
-                 containerIds.error());
-  }
-
-  foreach (const string& entry, containerIds.get()) {
-    string containerPath = path::join(containersDir, entry);
-
-    if (!os::stat::isdir(containerPath)) {
-      LOG(WARNING) << "Ignoring unexpected container entry at: "
-                   << containerPath;
-      continue;
-    }
-
-    ContainerID containerId;
-    containerId.set_value(entry);
-    results.put(containerId, containerPath);
-  }
-
-  return results;
-}
-
-
-Try<hashmap<string, hashmap<string, string>>> listContainerRootfses(
-    const string& provisionerDir,
-    const ContainerID& containerId)
-{
-  hashmap<string, hashmap<string, string>> results;
-
-  string backendsDir = getBackendsDir(
-      getContainerDir(
-          provisionerDir,
-          containerId));
-
-  Try<list<string>> backends = os::ls(backendsDir);
-  if (backends.isError()) {
-    return Error("Unable to list the container directory: " + backends.error());
-  }
-
-  foreach (const string& backend, backends.get()) {
-    string backendDir = getBackendDir(backendsDir, backend);
-    if (!os::stat::isdir(backendDir)) {
-      LOG(WARNING) << "Ignoring unexpected backend entry at: " << backendDir;
-      continue;
-    }
-
-    Try<list<string>> rootfses = os::ls(getRootfsesDir(backendDir));
-    if (rootfses.isError()) {
-      return Error("Unable to list the backend directory: " + rootfses.error());
-    }
-
-    hashmap<string, string> backendResults;
-
-    foreach (const string& rootfsId, rootfses.get()) {
-      string rootfs = getRootfsDir(getRootfsesDir(backendDir), rootfsId);
-
-      if (!os::stat::isdir(rootfs)) {
-        LOG(WARNING) << "Ignoring unexpected rootfs entry at: " << backendDir;
-        continue;
-      }
-
-      backendResults.put(rootfsId, rootfs);
-    }
-
-    if (backendResults.empty()) {
-      LOG(WARNING) << "Ignoring a backend directory with no rootfs in it: "
-                   << backendDir;
-      continue;
-    }
-
-    // The rootfs directory has passed validation.
-    results.put(backend, backendResults);
-  }
-
-  return results;
-}
-
-} // namespace paths {
-} // namespace provisioners {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/cc1f8f54/src/slave/containerizer/provisioners/paths.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/provisioners/paths.hpp b/src/slave/containerizer/provisioners/paths.hpp
deleted file mode 100644
index 5b82591..0000000
--- a/src/slave/containerizer/provisioners/paths.hpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * 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_PROVISIONERS_PATHS_HPP__
-#define __MESOS_PROVISIONERS_PATHS_HPP__
-
-#include <string>
-
-#include <mesos/mesos.hpp>
-
-#include <stout/hashmap.hpp>
-#include <stout/try.hpp>
-
-namespace mesos {
-namespace internal {
-namespace slave {
-namespace provisioners {
-namespace paths {
-
-// The provisioner rootfs directory is as follows:
-// <work_dir> ('--work_dir' flag)
-// |-- provisioners
-//     |-- <provisioner_type> (APPC, DOCKER, etc.)
-//         |-- containers
-//             |-- <container_id>
-//                 |-- backends
-//                     |-- <backend> (copy, bind, etc.)
-//                         |-- rootfses
-//                             |-- <rootfs_id> (the rootfs)
-//
-// NOTE: Each container could have multiple image types, therefore there
-// can be the same <container_id> directory under other provisioners e.g.,
-// <work_dir>/provisioners/DOCKER, <work_dir>/provisioners/APPC, etc.
-// Under each provisioner + container there can be multiple backends
-// due to the change of backend flags. Under each backend a rootfs is
-// identified by the 'rootfs_id' which is a UUID.
-
-std::string getContainerDir(
-    const std::string& provisionerDir,
-    const ContainerID& containerId);
-
-
-std::string getContainerRootfsDir(
-    const std::string& provisionerDir,
-    const ContainerID& containerId,
-    const std::string& backend,
-    const std::string& rootfsId);
-
-
-// Recursively "ls" the container directory and return a map of
-// backend -> rootfsId -> rootfsPath.
-Try<hashmap<std::string, hashmap<std::string, std::string>>>
-listContainerRootfses(
-    const std::string& provisionerDir,
-    const ContainerID& containerId);
-
-
-// Return a map of containerId -> containerPath;
-Try<hashmap<ContainerID, std::string>> listContainers(
-    const std::string& provisionerDir);
-
-} // namespace paths {
-} // namespace provisioners {
-} // namespace slave {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __MESOS_PROVISIONERS_PATHS__