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 2017/12/20 03:41:45 UTC

[1/2] mesos git commit: Moved files related to volume profiles into `resource_provider/storage`.

Repository: mesos
Updated Branches:
  refs/heads/master a3febec7e -> 5f40f3d40


Moved files related to volume profiles into `resource_provider/storage`.

Review: https://reviews.apache.org/r/64727/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/835d2a2c
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/835d2a2c
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/835d2a2c

Branch: refs/heads/master
Commit: 835d2a2c483c72c389c5d38edefd05584af73e0f
Parents: a3febec
Author: Chun-Hung Hsiao <ch...@mesosphere.io>
Authored: Tue Dec 19 19:21:07 2017 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Tue Dec 19 19:35:18 2017 -0800

----------------------------------------------------------------------
 include/mesos/module/volume_profile.hpp         |   2 +-
 .../storage/volume_profile.hpp                  | 144 +++++++++
 .../mesos/resource_provider/volume_profile.hpp  | 144 ---------
 src/Makefile.am                                 |  22 +-
 src/resource_provider/storage/provider.cpp      |   2 +-
 .../storage/uri_volume_profile.cpp              | 321 +++++++++++++++++++
 .../storage/uri_volume_profile.hpp              | 248 ++++++++++++++
 .../storage/volume_profile.cpp                  | 131 ++++++++
 .../storage/volume_profile.proto                |  43 +++
 .../storage/volume_profile_utils.cpp            | 121 +++++++
 .../storage/volume_profile_utils.hpp            |  48 +++
 src/resource_provider/uri_volume_profile.cpp    | 321 -------------------
 src/resource_provider/uri_volume_profile.hpp    | 248 --------------
 src/resource_provider/volume_profile.cpp        | 131 --------
 src/resource_provider/volume_profile.proto      |  43 ---
 src/resource_provider/volume_profile_utils.cpp  | 121 -------
 src/resource_provider/volume_profile_utils.hpp  |  48 ---
 src/slave/slave.cpp                             |   2 +-
 src/tests/volume_profile_tests.cpp              |   6 +-
 19 files changed, 1073 insertions(+), 1073 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/include/mesos/module/volume_profile.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/module/volume_profile.hpp b/include/mesos/module/volume_profile.hpp
index 0c6cb95..bb95b32 100644
--- a/include/mesos/module/volume_profile.hpp
+++ b/include/mesos/module/volume_profile.hpp
@@ -20,7 +20,7 @@
 #include <mesos/mesos.hpp>
 #include <mesos/module.hpp>
 
-#include <mesos/resource_provider/volume_profile.hpp>
+#include <mesos/resource_provider/storage/volume_profile.hpp>
 
 namespace mesos {
 namespace modules {

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/include/mesos/resource_provider/storage/volume_profile.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/resource_provider/storage/volume_profile.hpp b/include/mesos/resource_provider/storage/volume_profile.hpp
new file mode 100644
index 0000000..7141a14
--- /dev/null
+++ b/include/mesos/resource_provider/storage/volume_profile.hpp
@@ -0,0 +1,144 @@
+// 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_RESOURCE_PROVIDER_VOLUME_PROFILE_HPP__
+#define __MESOS_RESOURCE_PROVIDER_VOLUME_PROFILE_HPP__
+
+#include <memory>
+#include <string>
+#include <tuple>
+
+#include <process/future.hpp>
+
+#include <stout/hashset.hpp>
+#include <stout/none.hpp>
+#include <stout/nothing.hpp>
+
+#include <csi/spec.hpp>
+
+namespace mesos {
+
+/**
+ * This module is used by Storage Resource Providers to translate the
+ * "profile" field of a `Resource::DiskInfo::Source` into fields that a
+ * Container Storage Interface (CSI) plugin can potentially
+ * understand. This affects the following CSI requests:
+ *   * ControllerPublishVolumeRequest
+ *   * CreateVolumeRequest
+ *   * GetCapacityRequest
+ *   * NodePublishVolumeRequest
+ *   * ValidateVolumeCapabilitiesRequest
+ *
+ * This module is not intended to interact with any CSI plugins directly.
+ *
+ * Documentation for each of the CSI requests can be found at:
+ *   https://github.com/container-storage-interface/spec/
+ */
+class VolumeProfileAdaptor
+{
+public:
+  struct ProfileInfo
+  {
+    /**
+     * Corresponds to the `volume_capability` or `volume_capabilities`
+     * fields of the affected CSI requests listed in the module description.
+     *
+     * NOTE: Some CSI requests take a list of `VolumeCapability` objects.
+     * However, because there is no existing way to choose between a list
+     * of `VolumeCapability` objects, the module will only allow a single
+     * `VolumeCapability`.
+     */
+    csi::VolumeCapability capability;
+
+    /**
+     * Free-form key-value pairs which should be passed into the body
+     * of a `CreateVolumeRequest`. Neither Mesos nor this module is expected
+     * to act upon these values (except copying them into the request).
+     */
+    google::protobuf::Map<std::string, std::string> parameters;
+  };
+
+  /**
+   * Factory method used to create a VolumeProfileAdaptor instance.
+   * If the `name` parameter is provided, the module is instantiated
+   * using the `ModuleManager`. Otherwise, a "default" volume profile
+   * adaptor instance (defined in `src/resource_provider/volume_profile.cpp`)
+   * is returned.
+   *
+   * NOTE: The lifecycle of the returned object is delegated to the caller.
+   */
+  static Try<VolumeProfileAdaptor*> create(
+      const Option<std::string>& name = None());
+
+  /**
+   * Global methods for setting and getting a VolumeProfileAdaptor instance.
+   *
+   * The agent (or test) is expected to create and set the adaptor instance
+   * and manage the pointer (this method will only keep a weak pointer).
+   * Each component that needs to use the VolumeProfileAdaptor, such as the
+   * Storage Local Resource Provider, should call `getAdaptor`.
+   */
+  static void setAdaptor(const std::shared_ptr<VolumeProfileAdaptor>& adaptor);
+  static std::shared_ptr<VolumeProfileAdaptor> getAdaptor();
+
+  virtual ~VolumeProfileAdaptor() {}
+
+  /**
+   * Called before a Storage Resource Provider makes an affected CSI request.
+   * The caller is responsible for copying the returned values into the request
+   * object.
+   *
+   * This method is expected to return a Failure if a matching "profile"
+   * cannot be found or retrieved. The caller should not proceed with
+   * any of the affected CSI requests if this method returns a failure.
+   *
+   * The `csiPluginInfoType` parameter is the `CSIPluginInfo::type` field
+   * found inside `ResourceProviderInfo::storage`. This module may choose to
+   * filter results based on the type of CSI plugin.
+   *
+   * NOTE: This module assumes that profiles are immutable after creation.
+   * Changing the `VolumeCapability` or Parameters of a profile after creation
+   * may result in undefined behavior from the SLRP or CSI plugins.
+   */
+  virtual process::Future<ProfileInfo> translate(
+      const std::string& profile,
+      const std::string& csiPluginInfoType) = 0;
+
+  /**
+   * Returns a future that will be satisifed iff the set of profiles known
+   * by the module differs from the `knownProfiles` parameter.
+   *
+   * The `csiPluginInfoType` parameter is the `CSIPluginInfo::type` field
+   * found inside `ResourceProviderInfo::storage`. This module may choose to
+   * filter results based on the type of CSI plugin.
+   *
+   * NOTE: It is highly recommended for the module to insert a random delay
+   * between discovering a different set of profiles and satisfying this
+   * future, because the SLRP is expected to update the set of offered
+   * resources based on this future. Adding a random delay may prevent
+   * a thundering herd of resource updates to the Mesos master.
+   */
+  virtual process::Future<hashset<std::string>> watch(
+      const hashset<std::string>& knownProfiles,
+      const std::string& csiPluginInfoType) = 0;
+
+protected:
+  VolumeProfileAdaptor() {}
+};
+
+} // namespace mesos {
+
+#endif // __MESOS_RESOURCE_PROVIDER_VOLUME_PROFILE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/include/mesos/resource_provider/volume_profile.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/resource_provider/volume_profile.hpp b/include/mesos/resource_provider/volume_profile.hpp
deleted file mode 100644
index 7141a14..0000000
--- a/include/mesos/resource_provider/volume_profile.hpp
+++ /dev/null
@@ -1,144 +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_RESOURCE_PROVIDER_VOLUME_PROFILE_HPP__
-#define __MESOS_RESOURCE_PROVIDER_VOLUME_PROFILE_HPP__
-
-#include <memory>
-#include <string>
-#include <tuple>
-
-#include <process/future.hpp>
-
-#include <stout/hashset.hpp>
-#include <stout/none.hpp>
-#include <stout/nothing.hpp>
-
-#include <csi/spec.hpp>
-
-namespace mesos {
-
-/**
- * This module is used by Storage Resource Providers to translate the
- * "profile" field of a `Resource::DiskInfo::Source` into fields that a
- * Container Storage Interface (CSI) plugin can potentially
- * understand. This affects the following CSI requests:
- *   * ControllerPublishVolumeRequest
- *   * CreateVolumeRequest
- *   * GetCapacityRequest
- *   * NodePublishVolumeRequest
- *   * ValidateVolumeCapabilitiesRequest
- *
- * This module is not intended to interact with any CSI plugins directly.
- *
- * Documentation for each of the CSI requests can be found at:
- *   https://github.com/container-storage-interface/spec/
- */
-class VolumeProfileAdaptor
-{
-public:
-  struct ProfileInfo
-  {
-    /**
-     * Corresponds to the `volume_capability` or `volume_capabilities`
-     * fields of the affected CSI requests listed in the module description.
-     *
-     * NOTE: Some CSI requests take a list of `VolumeCapability` objects.
-     * However, because there is no existing way to choose between a list
-     * of `VolumeCapability` objects, the module will only allow a single
-     * `VolumeCapability`.
-     */
-    csi::VolumeCapability capability;
-
-    /**
-     * Free-form key-value pairs which should be passed into the body
-     * of a `CreateVolumeRequest`. Neither Mesos nor this module is expected
-     * to act upon these values (except copying them into the request).
-     */
-    google::protobuf::Map<std::string, std::string> parameters;
-  };
-
-  /**
-   * Factory method used to create a VolumeProfileAdaptor instance.
-   * If the `name` parameter is provided, the module is instantiated
-   * using the `ModuleManager`. Otherwise, a "default" volume profile
-   * adaptor instance (defined in `src/resource_provider/volume_profile.cpp`)
-   * is returned.
-   *
-   * NOTE: The lifecycle of the returned object is delegated to the caller.
-   */
-  static Try<VolumeProfileAdaptor*> create(
-      const Option<std::string>& name = None());
-
-  /**
-   * Global methods for setting and getting a VolumeProfileAdaptor instance.
-   *
-   * The agent (or test) is expected to create and set the adaptor instance
-   * and manage the pointer (this method will only keep a weak pointer).
-   * Each component that needs to use the VolumeProfileAdaptor, such as the
-   * Storage Local Resource Provider, should call `getAdaptor`.
-   */
-  static void setAdaptor(const std::shared_ptr<VolumeProfileAdaptor>& adaptor);
-  static std::shared_ptr<VolumeProfileAdaptor> getAdaptor();
-
-  virtual ~VolumeProfileAdaptor() {}
-
-  /**
-   * Called before a Storage Resource Provider makes an affected CSI request.
-   * The caller is responsible for copying the returned values into the request
-   * object.
-   *
-   * This method is expected to return a Failure if a matching "profile"
-   * cannot be found or retrieved. The caller should not proceed with
-   * any of the affected CSI requests if this method returns a failure.
-   *
-   * The `csiPluginInfoType` parameter is the `CSIPluginInfo::type` field
-   * found inside `ResourceProviderInfo::storage`. This module may choose to
-   * filter results based on the type of CSI plugin.
-   *
-   * NOTE: This module assumes that profiles are immutable after creation.
-   * Changing the `VolumeCapability` or Parameters of a profile after creation
-   * may result in undefined behavior from the SLRP or CSI plugins.
-   */
-  virtual process::Future<ProfileInfo> translate(
-      const std::string& profile,
-      const std::string& csiPluginInfoType) = 0;
-
-  /**
-   * Returns a future that will be satisifed iff the set of profiles known
-   * by the module differs from the `knownProfiles` parameter.
-   *
-   * The `csiPluginInfoType` parameter is the `CSIPluginInfo::type` field
-   * found inside `ResourceProviderInfo::storage`. This module may choose to
-   * filter results based on the type of CSI plugin.
-   *
-   * NOTE: It is highly recommended for the module to insert a random delay
-   * between discovering a different set of profiles and satisfying this
-   * future, because the SLRP is expected to update the set of offered
-   * resources based on this future. Adding a random delay may prevent
-   * a thundering herd of resource updates to the Mesos master.
-   */
-  virtual process::Future<hashset<std::string>> watch(
-      const hashset<std::string>& knownProfiles,
-      const std::string& csiPluginInfoType) = 0;
-
-protected:
-  VolumeProfileAdaptor() {}
-};
-
-} // namespace mesos {
-
-#endif // __MESOS_RESOURCE_PROVIDER_VOLUME_PROFILE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 33677df..5c6f180 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -383,8 +383,8 @@ CXX_PROTOS +=								\
 
 if ENABLE_GRPC
 CXX_PROTOS +=								\
-  resource_provider/volume_profile.pb.cc				\
-  resource_provider/volume_profile.pb.h
+  resource_provider/storage/volume_profile.pb.cc			\
+  resource_provider/storage/volume_profile.pb.h
 
 CXX_CSI_PROTOS =							\
   ../include/csi/csi.grpc.pb.cc						\
@@ -781,7 +781,7 @@ resourceprovider_HEADERS =						\
 
 if ENABLE_GRPC
 resourceprovider_HEADERS +=						\
-  $(top_srcdir)/include/mesos/resource_provider/volume_profile.hpp
+  $(top_srcdir)/include/mesos/resource_provider/storage/volume_profile.hpp
 endif
 
 nodist_resourceprovider_HEADERS =					\
@@ -1472,10 +1472,10 @@ endif
 
 if ENABLE_GRPC
 libmesos_no_3rdparty_la_SOURCES +=					\
-  resource_provider/volume_profile.cpp					\
-  resource_provider/volume_profile.proto				\
-  resource_provider/volume_profile_utils.cpp				\
-  resource_provider/volume_profile_utils.hpp
+  resource_provider/storage/volume_profile.cpp				\
+  resource_provider/storage/volume_profile.proto			\
+  resource_provider/storage/volume_profile_utils.cpp			\
+  resource_provider/storage/volume_profile_utils.hpp
 
 if OS_LINUX
 libmesos_no_3rdparty_la_SOURCES +=					\
@@ -2345,10 +2345,10 @@ libload_qos_controller_la_LDFLAGS = $(MESOS_MODULE_LDFLAGS)
 if ENABLE_GRPC
 pkgmodule_LTLIBRARIES += liburi_volume_profile.la
 liburi_volume_profile_la_SOURCES =				\
-  resource_provider/uri_volume_profile.cpp			\
-  resource_provider/uri_volume_profile.hpp			\
-  resource_provider/volume_profile.ph.h				\
-  resource_provider/volume_profile_utils.hpp
+  resource_provider/storage/uri_volume_profile.cpp		\
+  resource_provider/storage/uri_volume_profile.hpp		\
+  resource_provider/storage/volume_profile.ph.h			\
+  resource_provider/storage/volume_profile_utils.hpp
 liburi_volume_profile_la_CPPFLAGS = $(MESOS_CPPFLAGS)
 liburi_volume_profile_la_LDFLAGS = $(MESOS_MODULE_LDFLAGS)
 endif

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/storage/provider.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/provider.cpp b/src/resource_provider/storage/provider.cpp
index 6fd82ba..833d929 100644
--- a/src/resource_provider/storage/provider.cpp
+++ b/src/resource_provider/storage/provider.cpp
@@ -37,7 +37,7 @@
 #include <mesos/type_utils.hpp>
 
 #include <mesos/resource_provider/resource_provider.hpp>
-#include <mesos/resource_provider/volume_profile.hpp>
+#include <mesos/resource_provider/storage/volume_profile.hpp>
 
 #include <mesos/v1/resource_provider.hpp>
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/storage/uri_volume_profile.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/uri_volume_profile.cpp b/src/resource_provider/storage/uri_volume_profile.cpp
new file mode 100644
index 0000000..4431ad1
--- /dev/null
+++ b/src/resource_provider/storage/uri_volume_profile.cpp
@@ -0,0 +1,321 @@
+// 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 "resource_provider/storage/uri_volume_profile.hpp"
+
+#include <map>
+#include <string>
+#include <tuple>
+
+#include <mesos/mesos.hpp>
+
+#include <mesos/module/volume_profile.hpp>
+
+#include <mesos/resource_provider/storage/volume_profile.hpp>
+
+#include <process/defer.hpp>
+#include <process/delay.hpp>
+#include <process/dispatch.hpp>
+#include <process/future.hpp>
+#include <process/owned.hpp>
+#include <process/socket.hpp>
+
+#include <stout/duration.hpp>
+#include <stout/error.hpp>
+#include <stout/json.hpp>
+#include <stout/option.hpp>
+#include <stout/protobuf.hpp>
+#include <stout/result.hpp>
+#include <stout/strings.hpp>
+
+#include <csi/spec.hpp>
+#include <csi/utils.hpp>
+
+#include "resource_provider/storage/volume_profile_utils.hpp"
+
+using namespace mesos;
+using namespace process;
+
+using std::map;
+using std::string;
+using std::tuple;
+
+using google::protobuf::Map;
+
+using mesos::resource_provider::VolumeProfileMapping;
+
+namespace mesos {
+namespace internal {
+namespace profile {
+
+bool operator==(
+    const Map<string, string>& left,
+    const Map<string, string>& right) {
+  if (left.size() != right.size()) {
+    return false;
+  }
+
+  typename Map<string, string>::const_iterator iterator = left.begin();
+  while (iterator != left.end()) {
+    if (right.count(iterator->first) != 1) {
+      return false;
+    }
+
+    if (iterator->second != right.at(iterator->first)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
+UriVolumeProfileAdaptor::UriVolumeProfileAdaptor(const Flags& _flags)
+  : flags(_flags),
+    process(new UriVolumeProfileAdaptorProcess(flags))
+{
+  spawn(process.get());
+}
+
+
+UriVolumeProfileAdaptor::~UriVolumeProfileAdaptor()
+{
+  terminate(process.get());
+  wait(process.get());
+}
+
+
+Future<VolumeProfileAdaptor::ProfileInfo> UriVolumeProfileAdaptor::translate(
+    const string& profile,
+    const std::string& csiPluginInfoType)
+{
+  return dispatch(
+      process.get(),
+      &UriVolumeProfileAdaptorProcess::translate,
+      profile,
+      csiPluginInfoType);
+}
+
+
+Future<hashset<string>> UriVolumeProfileAdaptor::watch(
+    const hashset<string>& knownProfiles,
+    const std::string& csiPluginInfoType)
+{
+  return dispatch(
+      process.get(),
+      &UriVolumeProfileAdaptorProcess::watch,
+      knownProfiles,
+      csiPluginInfoType);
+}
+
+
+UriVolumeProfileAdaptorProcess::UriVolumeProfileAdaptorProcess(
+    const Flags& _flags)
+  : ProcessBase(ID::generate("uri-volume-profile")),
+    flags(_flags),
+    watchPromise(new Promise<hashset<string>>()) {}
+
+
+void UriVolumeProfileAdaptorProcess::initialize()
+{
+  poll();
+}
+
+
+Future<VolumeProfileAdaptor::ProfileInfo>
+  UriVolumeProfileAdaptorProcess::translate(
+      const string& profile,
+      const std::string& csiPluginInfoType)
+{
+  if (data.count(profile) != 1) {
+    return Failure("Profile '" + profile + "' not found");
+  }
+
+  return data.at(profile);
+}
+
+
+Future<hashset<string>> UriVolumeProfileAdaptorProcess::watch(
+    const hashset<string>& knownProfiles,
+    const std::string& csiPluginInfoType)
+{
+  if (profiles != knownProfiles) {
+    return profiles;
+  }
+
+  return watchPromise->future();
+}
+
+
+void UriVolumeProfileAdaptorProcess::poll()
+{
+  // NOTE: The flags do not allow relative paths, so this is guaranteed to
+  // be either 'http://' or 'https://'.
+  if (strings::startsWith(flags.uri, "http")) {
+    // NOTE: We already validated that this URI is parsable in the flags.
+    Try<http::URL> url = http::URL::parse(flags.uri.string());
+    CHECK_SOME(url);
+
+    http::get(url.get())
+      .onAny(defer(self(), [=](const Future<http::Response>& future) {
+        if (future.isReady()) {
+          // NOTE: We don't check the HTTP status code because we don't know
+          // what potential codes are considered successful.
+          _poll(future->body);
+        } else if (future.isFailed()) {
+          _poll(Error(future.failure()));
+        } else {
+          _poll(Error("Future discarded or abandoned"));
+        }
+      }));
+  } else {
+    _poll(os::read(flags.uri.string()));
+  }
+}
+
+
+void UriVolumeProfileAdaptorProcess::_poll(const Try<string>& fetched)
+{
+  if (fetched.isSome()) {
+    Try<VolumeProfileMapping> parsed = parseVolumeProfileMapping(fetched.get());
+
+    if (parsed.isSome()) {
+      notify(parsed.get());
+    } else {
+      LOG(ERROR) << "Failed to parse result: " << parsed.error();
+    }
+  } else {
+    LOG(WARNING) << "Failed to poll URI: " << fetched.error();
+  }
+
+  // TODO(josephw): Do we want to retry if polling fails and no polling
+  // interval is set? Or perhaps we should exit in that case?
+  if (flags.poll_interval.isSome()) {
+    delay(flags.poll_interval.get(), self(), &Self::poll);
+  }
+}
+
+
+void UriVolumeProfileAdaptorProcess::notify(
+    const VolumeProfileMapping& parsed)
+{
+  bool hasErrors = false;
+
+  foreachkey (const string& profile, data) {
+    if (parsed.profile_matrix().count(profile) != 1) {
+      hasErrors = true;
+
+      LOG(WARNING)
+        << "Fetched profile mapping does not contain profile '" << profile
+        << "'. The fetched mapping will be ignored entirely";
+      continue;
+    }
+
+    bool matchingCapability =
+      data.at(profile).capability ==
+        parsed.profile_matrix().at(profile).volume_capabilities();
+
+    bool matchingParameters =
+      data.at(profile).parameters ==
+        parsed.profile_matrix().at(profile).create_parameters();
+
+    if (!matchingCapability || !matchingParameters) {
+      hasErrors = true;
+
+      LOG(WARNING)
+        << "Fetched profile mapping for profile '" << profile << "'"
+        << " does not match earlier data."
+        << " The fetched mapping will be ignored entirely";
+    }
+  }
+
+  // When encountering a data conflict, this module assumes there is a
+  // problem upstream (i.e. in the `--uri`). It is up to the operator
+  // to notice and resolve this.
+  if (hasErrors) {
+    return;
+  }
+
+  // Profiles can only be added, so if the parsed data is the same size,
+  // nothing has changed and no notifications need to be sent.
+  if (parsed.profile_matrix().size() <= data.size()) {
+    return;
+  }
+
+  // The fetched mapping satisfies our invariants.
+
+  // Save the protobuf as a map we can expose through the module interface.
+  // And update the convenience set of profile names.
+  profiles.clear();
+  auto iterator = parsed.profile_matrix().begin();
+  while (iterator != parsed.profile_matrix().end()) {
+    data[iterator->first] = {
+      iterator->second.volume_capabilities(),
+      iterator->second.create_parameters()
+    };
+
+    profiles.insert(iterator->first);
+    iterator++;
+  }
+
+  // Notify any watchers and then prepare a new promise for the next
+  // iteration of polling.
+  //
+  // TODO(josephw): Delay this based on the `--max_random_wait` option.
+  watchPromise->set(profiles);
+  watchPromise.reset(new Promise<hashset<string>>());
+
+  LOG(INFO)
+    << "Updated volume profile mapping to " << profiles.size()
+    << " total profiles";
+}
+
+} // namespace profile {
+} // namespace internal {
+} // namespace mesos {
+
+
+mesos::modules::Module<VolumeProfileAdaptor>
+org_apache_mesos_UriVolumeProfileAdaptor(
+    MESOS_MODULE_API_VERSION,
+    MESOS_VERSION,
+    "Apache Mesos",
+    "modules@mesos.apache.org",
+    "URI Volume Profile Adaptor module.",
+    nullptr,
+    [](const Parameters& parameters) -> VolumeProfileAdaptor* {
+      // Convert `parameters` into a map.
+      map<string, string> values;
+      foreach (const Parameter& parameter, parameters.parameter()) {
+        values[parameter.key()] = parameter.value();
+      }
+
+      // Load and validate flags from the map.
+      mesos::internal::profile::Flags flags;
+      Try<flags::Warnings> load = flags.load(values);
+
+      if (load.isError()) {
+        LOG(ERROR) << "Failed to parse parameters: " << load.error();
+        return nullptr;
+      }
+
+      // Log any flag warnings.
+      foreach (const flags::Warning& warning, load->warnings) {
+        LOG(WARNING) << warning.message;
+      }
+
+      return new mesos::internal::profile::UriVolumeProfileAdaptor(flags);
+    });

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/storage/uri_volume_profile.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/uri_volume_profile.hpp b/src/resource_provider/storage/uri_volume_profile.hpp
new file mode 100644
index 0000000..a58758c
--- /dev/null
+++ b/src/resource_provider/storage/uri_volume_profile.hpp
@@ -0,0 +1,248 @@
+// 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 __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__
+#define __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__
+
+#include <map>
+#include <string>
+#include <tuple>
+
+#include <mesos/resource_provider/storage/volume_profile.hpp>
+
+#include <process/future.hpp>
+#include <process/owned.hpp>
+#include <process/process.hpp>
+
+#include <process/ssl/flags.hpp>
+
+#include <stout/duration.hpp>
+#include <stout/error.hpp>
+#include <stout/flags.hpp>
+#include <stout/option.hpp>
+#include <stout/path.hpp>
+#include <stout/strings.hpp>
+
+#include <csi/spec.hpp>
+
+#include "resource_provider/storage/volume_profile_utils.hpp"
+
+namespace mesos {
+namespace internal {
+namespace profile {
+
+// Forward declaration.
+class UriVolumeProfileAdaptorProcess;
+
+struct Flags : public virtual flags::FlagsBase
+{
+  Flags()
+  {
+    add(&Flags::uri,
+        "uri",
+        None(),
+        "URI to a JSON object containing the volume profile mapping.\n"
+        "This module supports both HTTP(s) and file URIs\n."
+        "\n"
+        "The JSON object should consist of some top-level string keys\n"
+        "corresponding to the volume profile name. Each value should\n"
+        "contain a `VolumeCapability` under a 'volume_capabilities'\n"
+        "and a free-form string-string mapping under 'create_parameters'.\n"
+        "\n"
+        "The JSON is modeled after a protobuf found in\n"
+        "`src/csi/uri_volume_profile.proto`.\n"
+        "\n"
+        "For example:\n"
+        "{\n"
+        "  \"profile_matrix\" : {\n"
+        "    \"my-profile\" : {\n"
+        "      \"volume_capabilities\" : {\n"
+        "        \"block\" : {},\n"
+        "        \"access_mode\" : { \"mode\" : \"SINGLE_NODE_WRITER\" }\n"
+        "      },\n"
+        "      \"create_parameters\" : {\n"
+        "        \"mesos-does-not\" : \"interpret-these\",\n"
+        "        \"type\" : \"raid5\",\n"
+        "        \"stripes\" : \"3\",\n"
+        "        \"stripesize\" : \"64\"\n"
+        "      }\n"
+        "    }\n"
+        "  }\n"
+        "}",
+        static_cast<const Path*>(nullptr),
+        [](const Path& value) -> Option<Error> {
+          // For now, just check if the URI has a supported scheme.
+          //
+          // TODO(josephw): Once we have a proper URI class and parser,
+          // consider validating this URI more thoroughly.
+          if (strings::startsWith(value.string(), "http://")
+#ifdef USE_SSL_SOCKET
+              || (process::network::openssl::flags().enabled &&
+                  strings::startsWith(value.string(), "https://"))
+#endif // USE_SSL_SOCKET
+          ) {
+            Try<process::http::URL> url =
+              process::http::URL::parse(value.string());
+
+            if (url.isError()) {
+              return Error("Failed to parse URI: " + url.error());
+            }
+
+            return None();
+          }
+
+          // NOTE: The `Path` class will strip off the 'file://' prefix.
+          if (strings::contains(value.string(), "://")) {
+            return Error("--uri must use a supported scheme (file or http(s))");
+          }
+
+          // We only allow absolute paths for file paths.
+          if (!value.absolute()) {
+            return Error("--uri to a file must be an absolute path");
+          }
+
+          return None();
+        });
+
+    add(&Flags::poll_interval,
+        "poll_interval",
+        "How long to wait between polling the specified `--uri`.\n"
+        "The time is checked each time the `translate` method is called.\n"
+        "If the given time has elapsed, then the URI is re-fetched."
+        "If not specified, the URI is only fetched once.",
+        [](const Option<Duration>& value) -> Option<Error> {
+          if (value.isSome() && value.get() <= Seconds(0)) {
+            return Error("--poll_interval must be non-negative");
+          }
+
+          return None();
+        });
+
+    add(&Flags::max_random_wait,
+        "max_random_wait",
+        "How long at most to wait between discovering a new set of profiles\n"
+        "and notifying the callers of `watch`. The actual wait time is a\n"
+        "uniform random value between 0 and this value. If the `--uri` points\n"
+        "to a centralized location, it may be good to scale this number\n"
+        "according to the number of resource providers in the cluster.",
+        Seconds(0),
+        [](const Duration& value) -> Option<Error> {
+          if (value < Seconds(0)) {
+            return Error("--max_random_wait must be zero or greater");
+          }
+
+          return None();
+        });
+  }
+
+  // NOTE: We use the `Path` type here so that the stout flags parser
+  // does not attempt to read a file if given a `file://` prefixed value.
+  //
+  // TODO(josephw): Replace with a URI type when stout gets one.
+  Path uri;
+
+  Option<Duration> poll_interval;
+  Duration max_random_wait;
+};
+
+
+// The `UriVolumeProfileAdaptor` is an example VolumeProfile module that
+// takes a URI as a module parameter and fetches that URI periodically.
+// The fetched data is parsed into the required CSI protobufs
+// (which also acts as validation).
+//
+// If there is an error during fetching, any previously fetched results
+// will be used until fetching is successful.
+//
+// This module does not filter return results based on `CSIPluginInfo::type`
+// and assumes that all fetched profiles are meant for all resource providers.
+//
+// See `Flags` above for more information.
+class UriVolumeProfileAdaptor : public mesos::VolumeProfileAdaptor
+{
+public:
+  UriVolumeProfileAdaptor(const Flags& _flags);
+
+  virtual ~UriVolumeProfileAdaptor();
+
+  virtual process::Future<mesos::VolumeProfileAdaptor::ProfileInfo> translate(
+      const std::string& profile,
+      const std::string& csiPluginInfoType) override;
+
+  virtual process::Future<hashset<std::string>> watch(
+      const hashset<std::string>& knownProfiles,
+      const std::string& csiPluginInfoType) override;
+
+protected:
+  Flags flags;
+  process::Owned<UriVolumeProfileAdaptorProcess> process;
+};
+
+
+class UriVolumeProfileAdaptorProcess :
+  public process::Process<UriVolumeProfileAdaptorProcess>
+{
+public:
+  UriVolumeProfileAdaptorProcess(const Flags& _flags);
+
+  virtual void initialize() override;
+
+  process::Future<mesos::VolumeProfileAdaptor::ProfileInfo> translate(
+      const std::string& profile,
+      const std::string& csiPluginInfoType);
+
+  process::Future<hashset<std::string>> watch(
+      const hashset<std::string>& knownProfiles,
+      const std::string& csiPluginInfoType);
+
+private:
+  // Helpers for fetching the `--uri`.
+  // If `--poll_interval` is set, this method will dispatch to itself with
+  // a delay once the fetch is complete.
+  void poll();
+  void _poll(const Try<std::string>& fetched);
+
+  // Helper that is called upon successfully polling and parsing the `--uri`.
+  // This method will check the following conditions before updating the state
+  // of the module:
+  //   * All known profiles must be included in the updated set.
+  //   * All properties of known profiles must match those in the updated set.
+  void notify(const resource_provider::VolumeProfileMapping& parsed);
+
+private:
+  Flags flags;
+
+  // The last fetched profile mapping.
+  // This module assumes that profiles can only be added and never removed.
+  // Once added, profiles cannot be changed either.
+  //
+  // TODO(josephw): Consider persisting this mapping across agent restarts.
+  std::map<std::string, VolumeProfileAdaptor::ProfileInfo> data;
+
+  // Convenience set of the keys in `data` above.
+  // This module does not filter based on `CSIPluginInfo::type`, so this
+  // is valid for all input to `watch(...)`.
+  hashset<std::string> profiles;
+
+  // Will be satisfied whenever `data` is changed.
+  process::Owned<process::Promise<hashset<std::string>>> watchPromise;
+};
+
+} // namespace profile {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/storage/volume_profile.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/volume_profile.cpp b/src/resource_provider/storage/volume_profile.cpp
new file mode 100644
index 0000000..336220d
--- /dev/null
+++ b/src/resource_provider/storage/volume_profile.cpp
@@ -0,0 +1,131 @@
+// 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 <string>
+
+#include <mesos/mesos.hpp>
+
+#include <mesos/module/volume_profile.hpp>
+
+#include <mesos/resource_provider/storage/volume_profile.hpp>
+
+#include <process/future.hpp>
+
+#include <stout/hashset.hpp>
+
+#include <csi/spec.hpp>
+
+#include "module/manager.hpp"
+
+using std::string;
+using std::tuple;
+
+using process::Failure;
+using process::Future;
+
+using google::protobuf::Map;
+
+namespace mesos {
+namespace internal {
+
+// The default implementation does nothing and always returns a Failure
+// whenever called.
+class DefaultVolumeProfileAdaptor : public VolumeProfileAdaptor
+{
+public:
+  DefaultVolumeProfileAdaptor() {}
+
+  ~DefaultVolumeProfileAdaptor() {}
+
+  virtual Future<VolumeProfileAdaptor::ProfileInfo> translate(
+      const string& profile,
+      const string& csiPluginInfoType) override
+  {
+    return Failure("By default, volume profiles are not supported");
+  }
+
+  virtual Future<hashset<string>> watch(
+      const hashset<string>& knownProfiles,
+      const string& csiPluginInfoType) override
+  {
+    // If the input set of profiles is empty, that means the caller is in sync
+    // with this module. Hence, we return a future that will never be satisified
+    // because this module will never return a non-empty set of profiles.
+    if (knownProfiles.empty()) {
+      return Future<hashset<string>>();
+    }
+
+    return hashset<string>::EMPTY;
+  }
+};
+
+} // namespace internal {
+
+
+Try<VolumeProfileAdaptor*> VolumeProfileAdaptor::create(
+    const Option<string>& moduleName)
+{
+  if (moduleName.isNone()) {
+    LOG(INFO) << "Creating default volume profile adaptor module";
+    return new internal::DefaultVolumeProfileAdaptor();
+  }
+
+  LOG(INFO)
+    << "Creating volume profile adaptor module '" << moduleName.get() << "'";
+
+  Try<VolumeProfileAdaptor*> result =
+    modules::ModuleManager::create<VolumeProfileAdaptor>(moduleName.get());
+
+  if (result.isError()) {
+    return Error(
+        "Failed to initialize volume profile adaptor module: "
+        + result.error());
+  }
+
+  return result;
+}
+
+
+// NOTE: This is a pointer because we avoid using non-POD types
+// as global variables.
+//
+// NOTE: This is a `weak_ptr` because the ownership of the module should
+// belong to the caller of the `create` method above. This will, for example,
+// allow tests to instantiate an Agent and subsequently destruct the Agent
+// without leaving a module behind in a global variable.
+static std::weak_ptr<VolumeProfileAdaptor>* currentAdaptor = nullptr;
+
+
+void VolumeProfileAdaptor::setAdaptor(
+    const std::shared_ptr<VolumeProfileAdaptor>& adaptor)
+{
+  if (currentAdaptor != nullptr) {
+    delete currentAdaptor;
+  }
+
+  currentAdaptor = new std::weak_ptr<VolumeProfileAdaptor>(adaptor);
+}
+
+
+std::shared_ptr<VolumeProfileAdaptor> VolumeProfileAdaptor::getAdaptor()
+{
+  // This method should never be called before `setAdaptor` has been called.
+  CHECK_NOTNULL(currentAdaptor);
+
+  return currentAdaptor->lock();
+}
+
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/storage/volume_profile.proto
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/volume_profile.proto b/src/resource_provider/storage/volume_profile.proto
new file mode 100644
index 0000000..c0628ec
--- /dev/null
+++ b/src/resource_provider/storage/volume_profile.proto
@@ -0,0 +1,43 @@
+// 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.
+
+syntax = "proto3";
+
+import "csi.proto";
+
+package mesos.resource_provider;
+
+
+message VolumeProfileMapping {
+  message CSIManifest {
+    // Capabilities used for creating, publishing, and validating volumes.
+    // This field is REQUIRED.
+    //
+    // NOTE: The name of this field is plural because some CSI requests
+    // support multiple capabilities. However, Mesos currently does not
+    // support this.
+    .csi.VolumeCapability volume_capabilities = 1;
+
+    // Parameters passed to the CSI CreateVolume RPC.
+    // This field is OPTIONAL.
+    map<string, string> create_parameters = 2;
+  }
+
+  // Each map entry associates a profile name (type string) with the CSI
+  // capabilities and parameters used to make specific CSI requests.
+  // This field is OPTIONAL.
+  map<string, CSIManifest> profile_matrix = 1;
+}

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/storage/volume_profile_utils.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/volume_profile_utils.cpp b/src/resource_provider/storage/volume_profile_utils.cpp
new file mode 100644
index 0000000..3d04558
--- /dev/null
+++ b/src/resource_provider/storage/volume_profile_utils.cpp
@@ -0,0 +1,121 @@
+// 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 "resource_provider/storage/volume_profile_utils.hpp"
+
+#include <google/protobuf/util/json_util.h>
+
+#include <stout/bytes.hpp>
+#include <stout/foreach.hpp>
+
+using std::string;
+
+using mesos::resource_provider::VolumeProfileMapping;
+
+namespace mesos{
+namespace internal {
+namespace profile {
+
+Try<VolumeProfileMapping> parseVolumeProfileMapping(
+    const string& data)
+{
+  // Use Google's JSON utility function to parse the JSON string.
+  VolumeProfileMapping output;
+  google::protobuf::util::JsonParseOptions options;
+  options.ignore_unknown_fields = true;
+
+  google::protobuf::util::Status status =
+    google::protobuf::util::JsonStringToMessage(data, &output, options);
+
+  if (!status.ok()) {
+    return Error(
+        "Failed to parse VolumeProfileMapping message: "
+        + status.ToString());
+  }
+
+  Option<Error> validation = validate(output);
+  if (validation.isSome()) {
+    return Error(
+      "Fetched profile mapping failed validation with: " + validation->message);
+  }
+
+  return output;
+}
+
+
+Option<Error> validate(const VolumeProfileMapping& mapping)
+{
+  auto iterator = mapping.profile_matrix().begin();
+  while (iterator != mapping.profile_matrix().end()) {
+    if (!iterator->second.has_volume_capabilities()) {
+      return Error(
+          "Profile '" + iterator->first + "' is missing the required field "
+          + "'volume_capabilities");
+    }
+
+    Option<Error> capabilities =
+      validate(iterator->second.volume_capabilities());
+
+    if (capabilities.isSome()) {
+      return Error(
+          "Profile '" + iterator->first + "' VolumeCapabilities are invalid: "
+          + capabilities->message);
+    }
+
+    // NOTE: The `create_parameters` field is optional and needs no further
+    // validation after parsing.
+
+    iterator++;
+  }
+
+  return None();
+}
+
+
+// TODO(chhsiao): Move this to CSI validation implementation file.
+Option<Error> validate(const csi::VolumeCapability& capability)
+{
+  if (capability.has_mount()) {
+    // The total size of this repeated field may not exceed 4 KB.
+    //
+    // TODO(josephw): The specification does not state how this maximum
+    // size is calculated. So this check is conservative and does not
+    // include padding or array separators in the size calculation.
+    size_t size = 0;
+    foreach (const string& flag, capability.mount().mount_flags()) {
+      size += flag.size();
+    }
+
+    if (Bytes(size) > Kilobytes(4)) {
+      return Error("Size of 'mount_flags' may not exceed 4 KB");
+    }
+  }
+
+  if (!capability.has_access_mode()) {
+    return Error("'access_mode' is a required field");
+  }
+
+  if (capability.access_mode().mode() ==
+      csi::VolumeCapability::AccessMode::UNKNOWN) {
+    return Error("'access_mode.mode' is unknown or not set");
+  }
+
+  return None();
+}
+
+} // namespace profile {
+} // namespace internal {
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/storage/volume_profile_utils.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/volume_profile_utils.hpp b/src/resource_provider/storage/volume_profile_utils.hpp
new file mode 100644
index 0000000..29bdf44
--- /dev/null
+++ b/src/resource_provider/storage/volume_profile_utils.hpp
@@ -0,0 +1,48 @@
+// 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 __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_UTILS_HPP__
+#define __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_UTILS_HPP__
+
+#include <stout/option.hpp>
+#include <stout/try.hpp>
+
+// ONLY USEFUL AFTER RUNNING PROTOC.
+#include "resource_provider/volume_profile.pb.h"
+
+namespace mesos {
+namespace internal {
+namespace profile {
+
+// Helper for parsing a string as the expected data format.
+Try<resource_provider::VolumeProfileMapping> parseVolumeProfileMapping(
+    const std::string& data);
+
+
+// Checks the fields inside a `VolumeProfileMapping` according to the
+// comments above the protobuf.
+Option<Error> validate(const resource_provider::VolumeProfileMapping& mapping);
+
+
+// Checks the fields inside a `VolumeCapability` according to the
+// comments above the protobuf.
+Option<Error> validate(const csi::VolumeCapability& capability);
+
+} // namespace profile {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/uri_volume_profile.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/uri_volume_profile.cpp b/src/resource_provider/uri_volume_profile.cpp
deleted file mode 100644
index 9c5bcb9..0000000
--- a/src/resource_provider/uri_volume_profile.cpp
+++ /dev/null
@@ -1,321 +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 "resource_provider/uri_volume_profile.hpp"
-
-#include <map>
-#include <string>
-#include <tuple>
-
-#include <mesos/mesos.hpp>
-
-#include <mesos/module/volume_profile.hpp>
-
-#include <mesos/resource_provider/volume_profile.hpp>
-
-#include <process/defer.hpp>
-#include <process/delay.hpp>
-#include <process/dispatch.hpp>
-#include <process/future.hpp>
-#include <process/owned.hpp>
-#include <process/socket.hpp>
-
-#include <stout/duration.hpp>
-#include <stout/error.hpp>
-#include <stout/json.hpp>
-#include <stout/option.hpp>
-#include <stout/protobuf.hpp>
-#include <stout/result.hpp>
-#include <stout/strings.hpp>
-
-#include <csi/spec.hpp>
-#include <csi/utils.hpp>
-
-#include "resource_provider/volume_profile_utils.hpp"
-
-using namespace mesos;
-using namespace process;
-
-using std::map;
-using std::string;
-using std::tuple;
-
-using google::protobuf::Map;
-
-using mesos::resource_provider::VolumeProfileMapping;
-
-namespace mesos {
-namespace internal {
-namespace profile {
-
-bool operator==(
-    const Map<string, string>& left,
-    const Map<string, string>& right) {
-  if (left.size() != right.size()) {
-    return false;
-  }
-
-  typename Map<string, string>::const_iterator iterator = left.begin();
-  while (iterator != left.end()) {
-    if (right.count(iterator->first) != 1) {
-      return false;
-    }
-
-    if (iterator->second != right.at(iterator->first)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-
-UriVolumeProfileAdaptor::UriVolumeProfileAdaptor(const Flags& _flags)
-  : flags(_flags),
-    process(new UriVolumeProfileAdaptorProcess(flags))
-{
-  spawn(process.get());
-}
-
-
-UriVolumeProfileAdaptor::~UriVolumeProfileAdaptor()
-{
-  terminate(process.get());
-  wait(process.get());
-}
-
-
-Future<VolumeProfileAdaptor::ProfileInfo> UriVolumeProfileAdaptor::translate(
-    const string& profile,
-    const std::string& csiPluginInfoType)
-{
-  return dispatch(
-      process.get(),
-      &UriVolumeProfileAdaptorProcess::translate,
-      profile,
-      csiPluginInfoType);
-}
-
-
-Future<hashset<string>> UriVolumeProfileAdaptor::watch(
-    const hashset<string>& knownProfiles,
-    const std::string& csiPluginInfoType)
-{
-  return dispatch(
-      process.get(),
-      &UriVolumeProfileAdaptorProcess::watch,
-      knownProfiles,
-      csiPluginInfoType);
-}
-
-
-UriVolumeProfileAdaptorProcess::UriVolumeProfileAdaptorProcess(
-    const Flags& _flags)
-  : ProcessBase(ID::generate("uri-volume-profile")),
-    flags(_flags),
-    watchPromise(new Promise<hashset<string>>()) {}
-
-
-void UriVolumeProfileAdaptorProcess::initialize()
-{
-  poll();
-}
-
-
-Future<VolumeProfileAdaptor::ProfileInfo>
-  UriVolumeProfileAdaptorProcess::translate(
-      const string& profile,
-      const std::string& csiPluginInfoType)
-{
-  if (data.count(profile) != 1) {
-    return Failure("Profile '" + profile + "' not found");
-  }
-
-  return data.at(profile);
-}
-
-
-Future<hashset<string>> UriVolumeProfileAdaptorProcess::watch(
-    const hashset<string>& knownProfiles,
-    const std::string& csiPluginInfoType)
-{
-  if (profiles != knownProfiles) {
-    return profiles;
-  }
-
-  return watchPromise->future();
-}
-
-
-void UriVolumeProfileAdaptorProcess::poll()
-{
-  // NOTE: The flags do not allow relative paths, so this is guaranteed to
-  // be either 'http://' or 'https://'.
-  if (strings::startsWith(flags.uri, "http")) {
-    // NOTE: We already validated that this URI is parsable in the flags.
-    Try<http::URL> url = http::URL::parse(flags.uri.string());
-    CHECK_SOME(url);
-
-    http::get(url.get())
-      .onAny(defer(self(), [=](const Future<http::Response>& future) {
-        if (future.isReady()) {
-          // NOTE: We don't check the HTTP status code because we don't know
-          // what potential codes are considered successful.
-          _poll(future->body);
-        } else if (future.isFailed()) {
-          _poll(Error(future.failure()));
-        } else {
-          _poll(Error("Future discarded or abandoned"));
-        }
-      }));
-  } else {
-    _poll(os::read(flags.uri.string()));
-  }
-}
-
-
-void UriVolumeProfileAdaptorProcess::_poll(const Try<string>& fetched)
-{
-  if (fetched.isSome()) {
-    Try<VolumeProfileMapping> parsed = parseVolumeProfileMapping(fetched.get());
-
-    if (parsed.isSome()) {
-      notify(parsed.get());
-    } else {
-      LOG(ERROR) << "Failed to parse result: " << parsed.error();
-    }
-  } else {
-    LOG(WARNING) << "Failed to poll URI: " << fetched.error();
-  }
-
-  // TODO(josephw): Do we want to retry if polling fails and no polling
-  // interval is set? Or perhaps we should exit in that case?
-  if (flags.poll_interval.isSome()) {
-    delay(flags.poll_interval.get(), self(), &Self::poll);
-  }
-}
-
-
-void UriVolumeProfileAdaptorProcess::notify(
-    const VolumeProfileMapping& parsed)
-{
-  bool hasErrors = false;
-
-  foreachkey (const string& profile, data) {
-    if (parsed.profile_matrix().count(profile) != 1) {
-      hasErrors = true;
-
-      LOG(WARNING)
-        << "Fetched profile mapping does not contain profile '" << profile
-        << "'. The fetched mapping will be ignored entirely";
-      continue;
-    }
-
-    bool matchingCapability =
-      data.at(profile).capability ==
-        parsed.profile_matrix().at(profile).volume_capabilities();
-
-    bool matchingParameters =
-      data.at(profile).parameters ==
-        parsed.profile_matrix().at(profile).create_parameters();
-
-    if (!matchingCapability || !matchingParameters) {
-      hasErrors = true;
-
-      LOG(WARNING)
-        << "Fetched profile mapping for profile '" << profile << "'"
-        << " does not match earlier data."
-        << " The fetched mapping will be ignored entirely";
-    }
-  }
-
-  // When encountering a data conflict, this module assumes there is a
-  // problem upstream (i.e. in the `--uri`). It is up to the operator
-  // to notice and resolve this.
-  if (hasErrors) {
-    return;
-  }
-
-  // Profiles can only be added, so if the parsed data is the same size,
-  // nothing has changed and no notifications need to be sent.
-  if (parsed.profile_matrix().size() <= data.size()) {
-    return;
-  }
-
-  // The fetched mapping satisfies our invariants.
-
-  // Save the protobuf as a map we can expose through the module interface.
-  // And update the convenience set of profile names.
-  profiles.clear();
-  auto iterator = parsed.profile_matrix().begin();
-  while (iterator != parsed.profile_matrix().end()) {
-    data[iterator->first] = {
-      iterator->second.volume_capabilities(),
-      iterator->second.create_parameters()
-    };
-
-    profiles.insert(iterator->first);
-    iterator++;
-  }
-
-  // Notify any watchers and then prepare a new promise for the next
-  // iteration of polling.
-  //
-  // TODO(josephw): Delay this based on the `--max_random_wait` option.
-  watchPromise->set(profiles);
-  watchPromise.reset(new Promise<hashset<string>>());
-
-  LOG(INFO)
-    << "Updated volume profile mapping to " << profiles.size()
-    << " total profiles";
-}
-
-} // namespace profile {
-} // namespace internal {
-} // namespace mesos {
-
-
-mesos::modules::Module<VolumeProfileAdaptor>
-org_apache_mesos_UriVolumeProfileAdaptor(
-    MESOS_MODULE_API_VERSION,
-    MESOS_VERSION,
-    "Apache Mesos",
-    "modules@mesos.apache.org",
-    "URI Volume Profile Adaptor module.",
-    nullptr,
-    [](const Parameters& parameters) -> VolumeProfileAdaptor* {
-      // Convert `parameters` into a map.
-      map<string, string> values;
-      foreach (const Parameter& parameter, parameters.parameter()) {
-        values[parameter.key()] = parameter.value();
-      }
-
-      // Load and validate flags from the map.
-      mesos::internal::profile::Flags flags;
-      Try<flags::Warnings> load = flags.load(values);
-
-      if (load.isError()) {
-        LOG(ERROR) << "Failed to parse parameters: " << load.error();
-        return nullptr;
-      }
-
-      // Log any flag warnings.
-      foreach (const flags::Warning& warning, load->warnings) {
-        LOG(WARNING) << warning.message;
-      }
-
-      return new mesos::internal::profile::UriVolumeProfileAdaptor(flags);
-    });

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/uri_volume_profile.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/uri_volume_profile.hpp b/src/resource_provider/uri_volume_profile.hpp
deleted file mode 100644
index 11c1727..0000000
--- a/src/resource_provider/uri_volume_profile.hpp
+++ /dev/null
@@ -1,248 +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 __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__
-#define __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__
-
-#include <map>
-#include <string>
-#include <tuple>
-
-#include <mesos/resource_provider/volume_profile.hpp>
-
-#include <process/future.hpp>
-#include <process/owned.hpp>
-#include <process/process.hpp>
-
-#include <process/ssl/flags.hpp>
-
-#include <stout/duration.hpp>
-#include <stout/error.hpp>
-#include <stout/flags.hpp>
-#include <stout/option.hpp>
-#include <stout/path.hpp>
-#include <stout/strings.hpp>
-
-#include <csi/spec.hpp>
-
-#include "resource_provider/volume_profile_utils.hpp"
-
-namespace mesos {
-namespace internal {
-namespace profile {
-
-// Forward declaration.
-class UriVolumeProfileAdaptorProcess;
-
-struct Flags : public virtual flags::FlagsBase
-{
-  Flags()
-  {
-    add(&Flags::uri,
-        "uri",
-        None(),
-        "URI to a JSON object containing the volume profile mapping.\n"
-        "This module supports both HTTP(s) and file URIs\n."
-        "\n"
-        "The JSON object should consist of some top-level string keys\n"
-        "corresponding to the volume profile name. Each value should\n"
-        "contain a `VolumeCapability` under a 'volume_capabilities'\n"
-        "and a free-form string-string mapping under 'create_parameters'.\n"
-        "\n"
-        "The JSON is modeled after a protobuf found in\n"
-        "`src/csi/uri_volume_profile.proto`.\n"
-        "\n"
-        "For example:\n"
-        "{\n"
-        "  \"profile_matrix\" : {\n"
-        "    \"my-profile\" : {\n"
-        "      \"volume_capabilities\" : {\n"
-        "        \"block\" : {},\n"
-        "        \"access_mode\" : { \"mode\" : \"SINGLE_NODE_WRITER\" }\n"
-        "      },\n"
-        "      \"create_parameters\" : {\n"
-        "        \"mesos-does-not\" : \"interpret-these\",\n"
-        "        \"type\" : \"raid5\",\n"
-        "        \"stripes\" : \"3\",\n"
-        "        \"stripesize\" : \"64\"\n"
-        "      }\n"
-        "    }\n"
-        "  }\n"
-        "}",
-        static_cast<const Path*>(nullptr),
-        [](const Path& value) -> Option<Error> {
-          // For now, just check if the URI has a supported scheme.
-          //
-          // TODO(josephw): Once we have a proper URI class and parser,
-          // consider validating this URI more thoroughly.
-          if (strings::startsWith(value.string(), "http://")
-#ifdef USE_SSL_SOCKET
-              || (process::network::openssl::flags().enabled &&
-                  strings::startsWith(value.string(), "https://"))
-#endif // USE_SSL_SOCKET
-          ) {
-            Try<process::http::URL> url =
-              process::http::URL::parse(value.string());
-
-            if (url.isError()) {
-              return Error("Failed to parse URI: " + url.error());
-            }
-
-            return None();
-          }
-
-          // NOTE: The `Path` class will strip off the 'file://' prefix.
-          if (strings::contains(value.string(), "://")) {
-            return Error("--uri must use a supported scheme (file or http(s))");
-          }
-
-          // We only allow absolute paths for file paths.
-          if (!value.absolute()) {
-            return Error("--uri to a file must be an absolute path");
-          }
-
-          return None();
-        });
-
-    add(&Flags::poll_interval,
-        "poll_interval",
-        "How long to wait between polling the specified `--uri`.\n"
-        "The time is checked each time the `translate` method is called.\n"
-        "If the given time has elapsed, then the URI is re-fetched."
-        "If not specified, the URI is only fetched once.",
-        [](const Option<Duration>& value) -> Option<Error> {
-          if (value.isSome() && value.get() <= Seconds(0)) {
-            return Error("--poll_interval must be non-negative");
-          }
-
-          return None();
-        });
-
-    add(&Flags::max_random_wait,
-        "max_random_wait",
-        "How long at most to wait between discovering a new set of profiles\n"
-        "and notifying the callers of `watch`. The actual wait time is a\n"
-        "uniform random value between 0 and this value. If the `--uri` points\n"
-        "to a centralized location, it may be good to scale this number\n"
-        "according to the number of resource providers in the cluster.",
-        Seconds(0),
-        [](const Duration& value) -> Option<Error> {
-          if (value < Seconds(0)) {
-            return Error("--max_random_wait must be zero or greater");
-          }
-
-          return None();
-        });
-  }
-
-  // NOTE: We use the `Path` type here so that the stout flags parser
-  // does not attempt to read a file if given a `file://` prefixed value.
-  //
-  // TODO(josephw): Replace with a URI type when stout gets one.
-  Path uri;
-
-  Option<Duration> poll_interval;
-  Duration max_random_wait;
-};
-
-
-// The `UriVolumeProfileAdaptor` is an example VolumeProfile module that
-// takes a URI as a module parameter and fetches that URI periodically.
-// The fetched data is parsed into the required CSI protobufs
-// (which also acts as validation).
-//
-// If there is an error during fetching, any previously fetched results
-// will be used until fetching is successful.
-//
-// This module does not filter return results based on `CSIPluginInfo::type`
-// and assumes that all fetched profiles are meant for all resource providers.
-//
-// See `Flags` above for more information.
-class UriVolumeProfileAdaptor : public mesos::VolumeProfileAdaptor
-{
-public:
-  UriVolumeProfileAdaptor(const Flags& _flags);
-
-  virtual ~UriVolumeProfileAdaptor();
-
-  virtual process::Future<mesos::VolumeProfileAdaptor::ProfileInfo> translate(
-      const std::string& profile,
-      const std::string& csiPluginInfoType) override;
-
-  virtual process::Future<hashset<std::string>> watch(
-      const hashset<std::string>& knownProfiles,
-      const std::string& csiPluginInfoType) override;
-
-protected:
-  Flags flags;
-  process::Owned<UriVolumeProfileAdaptorProcess> process;
-};
-
-
-class UriVolumeProfileAdaptorProcess :
-  public process::Process<UriVolumeProfileAdaptorProcess>
-{
-public:
-  UriVolumeProfileAdaptorProcess(const Flags& _flags);
-
-  virtual void initialize() override;
-
-  process::Future<mesos::VolumeProfileAdaptor::ProfileInfo> translate(
-      const std::string& profile,
-      const std::string& csiPluginInfoType);
-
-  process::Future<hashset<std::string>> watch(
-      const hashset<std::string>& knownProfiles,
-      const std::string& csiPluginInfoType);
-
-private:
-  // Helpers for fetching the `--uri`.
-  // If `--poll_interval` is set, this method will dispatch to itself with
-  // a delay once the fetch is complete.
-  void poll();
-  void _poll(const Try<std::string>& fetched);
-
-  // Helper that is called upon successfully polling and parsing the `--uri`.
-  // This method will check the following conditions before updating the state
-  // of the module:
-  //   * All known profiles must be included in the updated set.
-  //   * All properties of known profiles must match those in the updated set.
-  void notify(const resource_provider::VolumeProfileMapping& parsed);
-
-private:
-  Flags flags;
-
-  // The last fetched profile mapping.
-  // This module assumes that profiles can only be added and never removed.
-  // Once added, profiles cannot be changed either.
-  //
-  // TODO(josephw): Consider persisting this mapping across agent restarts.
-  std::map<std::string, VolumeProfileAdaptor::ProfileInfo> data;
-
-  // Convenience set of the keys in `data` above.
-  // This module does not filter based on `CSIPluginInfo::type`, so this
-  // is valid for all input to `watch(...)`.
-  hashset<std::string> profiles;
-
-  // Will be satisfied whenever `data` is changed.
-  process::Owned<process::Promise<hashset<std::string>>> watchPromise;
-};
-
-} // namespace profile {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/volume_profile.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/volume_profile.cpp b/src/resource_provider/volume_profile.cpp
deleted file mode 100644
index 2b83703..0000000
--- a/src/resource_provider/volume_profile.cpp
+++ /dev/null
@@ -1,131 +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 <string>
-
-#include <mesos/mesos.hpp>
-
-#include <mesos/module/volume_profile.hpp>
-
-#include <mesos/resource_provider/volume_profile.hpp>
-
-#include <process/future.hpp>
-
-#include <stout/hashset.hpp>
-
-#include <csi/spec.hpp>
-
-#include "module/manager.hpp"
-
-using std::string;
-using std::tuple;
-
-using process::Failure;
-using process::Future;
-
-using google::protobuf::Map;
-
-namespace mesos {
-namespace internal {
-
-// The default implementation does nothing and always returns a Failure
-// whenever called.
-class DefaultVolumeProfileAdaptor : public VolumeProfileAdaptor
-{
-public:
-  DefaultVolumeProfileAdaptor() {}
-
-  ~DefaultVolumeProfileAdaptor() {}
-
-  virtual Future<VolumeProfileAdaptor::ProfileInfo> translate(
-      const string& profile,
-      const string& csiPluginInfoType) override
-  {
-    return Failure("By default, volume profiles are not supported");
-  }
-
-  virtual Future<hashset<string>> watch(
-      const hashset<string>& knownProfiles,
-      const string& csiPluginInfoType) override
-  {
-    // If the input set of profiles is empty, that means the caller is in sync
-    // with this module. Hence, we return a future that will never be satisified
-    // because this module will never return a non-empty set of profiles.
-    if (knownProfiles.empty()) {
-      return Future<hashset<string>>();
-    }
-
-    return hashset<string>::EMPTY;
-  }
-};
-
-} // namespace internal {
-
-
-Try<VolumeProfileAdaptor*> VolumeProfileAdaptor::create(
-    const Option<string>& moduleName)
-{
-  if (moduleName.isNone()) {
-    LOG(INFO) << "Creating default volume profile adaptor module";
-    return new internal::DefaultVolumeProfileAdaptor();
-  }
-
-  LOG(INFO)
-    << "Creating volume profile adaptor module '" << moduleName.get() << "'";
-
-  Try<VolumeProfileAdaptor*> result =
-    modules::ModuleManager::create<VolumeProfileAdaptor>(moduleName.get());
-
-  if (result.isError()) {
-    return Error(
-        "Failed to initialize volume profile adaptor module: "
-        + result.error());
-  }
-
-  return result;
-}
-
-
-// NOTE: This is a pointer because we avoid using non-POD types
-// as global variables.
-//
-// NOTE: This is a `weak_ptr` because the ownership of the module should
-// belong to the caller of the `create` method above. This will, for example,
-// allow tests to instantiate an Agent and subsequently destruct the Agent
-// without leaving a module behind in a global variable.
-static std::weak_ptr<VolumeProfileAdaptor>* currentAdaptor = nullptr;
-
-
-void VolumeProfileAdaptor::setAdaptor(
-    const std::shared_ptr<VolumeProfileAdaptor>& adaptor)
-{
-  if (currentAdaptor != nullptr) {
-    delete currentAdaptor;
-  }
-
-  currentAdaptor = new std::weak_ptr<VolumeProfileAdaptor>(adaptor);
-}
-
-
-std::shared_ptr<VolumeProfileAdaptor> VolumeProfileAdaptor::getAdaptor()
-{
-  // This method should never be called before `setAdaptor` has been called.
-  CHECK_NOTNULL(currentAdaptor);
-
-  return currentAdaptor->lock();
-}
-
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/volume_profile.proto
----------------------------------------------------------------------
diff --git a/src/resource_provider/volume_profile.proto b/src/resource_provider/volume_profile.proto
deleted file mode 100644
index c0628ec..0000000
--- a/src/resource_provider/volume_profile.proto
+++ /dev/null
@@ -1,43 +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.
-
-syntax = "proto3";
-
-import "csi.proto";
-
-package mesos.resource_provider;
-
-
-message VolumeProfileMapping {
-  message CSIManifest {
-    // Capabilities used for creating, publishing, and validating volumes.
-    // This field is REQUIRED.
-    //
-    // NOTE: The name of this field is plural because some CSI requests
-    // support multiple capabilities. However, Mesos currently does not
-    // support this.
-    .csi.VolumeCapability volume_capabilities = 1;
-
-    // Parameters passed to the CSI CreateVolume RPC.
-    // This field is OPTIONAL.
-    map<string, string> create_parameters = 2;
-  }
-
-  // Each map entry associates a profile name (type string) with the CSI
-  // capabilities and parameters used to make specific CSI requests.
-  // This field is OPTIONAL.
-  map<string, CSIManifest> profile_matrix = 1;
-}

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/volume_profile_utils.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/volume_profile_utils.cpp b/src/resource_provider/volume_profile_utils.cpp
deleted file mode 100644
index ec8b1f4..0000000
--- a/src/resource_provider/volume_profile_utils.cpp
+++ /dev/null
@@ -1,121 +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 "resource_provider/volume_profile_utils.hpp"
-
-#include <google/protobuf/util/json_util.h>
-
-#include <stout/bytes.hpp>
-#include <stout/foreach.hpp>
-
-using std::string;
-
-using mesos::resource_provider::VolumeProfileMapping;
-
-namespace mesos{
-namespace internal {
-namespace profile {
-
-Try<VolumeProfileMapping> parseVolumeProfileMapping(
-    const string& data)
-{
-  // Use Google's JSON utility function to parse the JSON string.
-  VolumeProfileMapping output;
-  google::protobuf::util::JsonParseOptions options;
-  options.ignore_unknown_fields = true;
-
-  google::protobuf::util::Status status =
-    google::protobuf::util::JsonStringToMessage(data, &output, options);
-
-  if (!status.ok()) {
-    return Error(
-        "Failed to parse VolumeProfileMapping message: "
-        + status.ToString());
-  }
-
-  Option<Error> validation = validate(output);
-  if (validation.isSome()) {
-    return Error(
-      "Fetched profile mapping failed validation with: " + validation->message);
-  }
-
-  return output;
-}
-
-
-Option<Error> validate(const VolumeProfileMapping& mapping)
-{
-  auto iterator = mapping.profile_matrix().begin();
-  while (iterator != mapping.profile_matrix().end()) {
-    if (!iterator->second.has_volume_capabilities()) {
-      return Error(
-          "Profile '" + iterator->first + "' is missing the required field "
-          + "'volume_capabilities");
-    }
-
-    Option<Error> capabilities =
-      validate(iterator->second.volume_capabilities());
-
-    if (capabilities.isSome()) {
-      return Error(
-          "Profile '" + iterator->first + "' VolumeCapabilities are invalid: "
-          + capabilities->message);
-    }
-
-    // NOTE: The `create_parameters` field is optional and needs no further
-    // validation after parsing.
-
-    iterator++;
-  }
-
-  return None();
-}
-
-
-// TODO(chhsiao): Move this to CSI validation implementation file.
-Option<Error> validate(const csi::VolumeCapability& capability)
-{
-  if (capability.has_mount()) {
-    // The total size of this repeated field may not exceed 4 KB.
-    //
-    // TODO(josephw): The specification does not state how this maximum
-    // size is calculated. So this check is conservative and does not
-    // include padding or array separators in the size calculation.
-    size_t size = 0;
-    foreach (const string& flag, capability.mount().mount_flags()) {
-      size += flag.size();
-    }
-
-    if (Bytes(size) > Kilobytes(4)) {
-      return Error("Size of 'mount_flags' may not exceed 4 KB");
-    }
-  }
-
-  if (!capability.has_access_mode()) {
-    return Error("'access_mode' is a required field");
-  }
-
-  if (capability.access_mode().mode() ==
-      csi::VolumeCapability::AccessMode::UNKNOWN) {
-    return Error("'access_mode.mode' is unknown or not set");
-  }
-
-  return None();
-}
-
-} // namespace profile {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/resource_provider/volume_profile_utils.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/volume_profile_utils.hpp b/src/resource_provider/volume_profile_utils.hpp
deleted file mode 100644
index 29bdf44..0000000
--- a/src/resource_provider/volume_profile_utils.hpp
+++ /dev/null
@@ -1,48 +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 __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_UTILS_HPP__
-#define __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_UTILS_HPP__
-
-#include <stout/option.hpp>
-#include <stout/try.hpp>
-
-// ONLY USEFUL AFTER RUNNING PROTOC.
-#include "resource_provider/volume_profile.pb.h"
-
-namespace mesos {
-namespace internal {
-namespace profile {
-
-// Helper for parsing a string as the expected data format.
-Try<resource_provider::VolumeProfileMapping> parseVolumeProfileMapping(
-    const std::string& data);
-
-
-// Checks the fields inside a `VolumeProfileMapping` according to the
-// comments above the protobuf.
-Option<Error> validate(const resource_provider::VolumeProfileMapping& mapping);
-
-
-// Checks the fields inside a `VolumeCapability` according to the
-// comments above the protobuf.
-Option<Error> validate(const csi::VolumeCapability& capability);
-
-} // namespace profile {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __RESOURCE_PROVIDER_URI_VOLUME_PROFILE_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/slave/slave.cpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.cpp b/src/slave/slave.cpp
index 55dea08..264705f 100644
--- a/src/slave/slave.cpp
+++ b/src/slave/slave.cpp
@@ -37,7 +37,7 @@
 #include <mesos/module/authenticatee.hpp>
 
 #ifdef ENABLE_GRPC
-#include <mesos/resource_provider/volume_profile.hpp>
+#include <mesos/resource_provider/storage/volume_profile.hpp>
 #endif
 
 #include <process/after.hpp>

http://git-wip-us.apache.org/repos/asf/mesos/blob/835d2a2c/src/tests/volume_profile_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/volume_profile_tests.cpp b/src/tests/volume_profile_tests.cpp
index 2f5018f..6ed81c9 100644
--- a/src/tests/volume_profile_tests.cpp
+++ b/src/tests/volume_profile_tests.cpp
@@ -21,7 +21,7 @@
 
 #include <mesos/module/volume_profile.hpp>
 
-#include <mesos/resource_provider/volume_profile.hpp>
+#include <mesos/resource_provider/storage/volume_profile.hpp>
 
 #include <process/clock.hpp>
 #include <process/future.hpp>
@@ -40,8 +40,8 @@
 
 #include "module/manager.hpp"
 
-#include "resource_provider/uri_volume_profile.hpp"
-#include "resource_provider/volume_profile_utils.hpp"
+#include "resource_provider/storage/uri_volume_profile.hpp"
+#include "resource_provider/storage/volume_profile_utils.hpp"
 
 #include "tests/flags.hpp"
 #include "tests/mesos.hpp"


[2/2] mesos git commit: Made volume secret isolator not standalone container aware.

Posted by ji...@apache.org.
Made volume secret isolator not standalone container aware.

We'll revisit this later.

Review: https://reviews.apache.org/r/64742


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/5f40f3d4
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/5f40f3d4
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/5f40f3d4

Branch: refs/heads/master
Commit: 5f40f3d401bbdd7e324113214c286a26faf67540
Parents: 835d2a2
Author: Jie Yu <yu...@gmail.com>
Authored: Tue Dec 19 19:35:49 2017 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Tue Dec 19 19:36:28 2017 -0800

----------------------------------------------------------------------
 src/slave/containerizer/mesos/isolators/volume/secret.cpp | 6 ------
 src/slave/containerizer/mesos/isolators/volume/secret.hpp | 1 -
 2 files changed, 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/5f40f3d4/src/slave/containerizer/mesos/isolators/volume/secret.cpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/secret.cpp b/src/slave/containerizer/mesos/isolators/volume/secret.cpp
index e754a1b..8071e4e 100644
--- a/src/slave/containerizer/mesos/isolators/volume/secret.cpp
+++ b/src/slave/containerizer/mesos/isolators/volume/secret.cpp
@@ -99,12 +99,6 @@ bool VolumeSecretIsolatorProcess::supportsNesting()
 }
 
 
-bool VolumeSecretIsolatorProcess::supportsStandalone()
-{
-  return true;
-}
-
-
 Future<Option<ContainerLaunchInfo>> VolumeSecretIsolatorProcess::prepare(
     const ContainerID& containerId,
     const ContainerConfig& containerConfig)

http://git-wip-us.apache.org/repos/asf/mesos/blob/5f40f3d4/src/slave/containerizer/mesos/isolators/volume/secret.hpp
----------------------------------------------------------------------
diff --git a/src/slave/containerizer/mesos/isolators/volume/secret.hpp b/src/slave/containerizer/mesos/isolators/volume/secret.hpp
index 4515777..2680345 100644
--- a/src/slave/containerizer/mesos/isolators/volume/secret.hpp
+++ b/src/slave/containerizer/mesos/isolators/volume/secret.hpp
@@ -46,7 +46,6 @@ public:
   virtual ~VolumeSecretIsolatorProcess() {}
 
   virtual bool supportsNesting();
-  virtual bool supportsStandalone();
 
   virtual process::Future<Option<mesos::slave::ContainerLaunchInfo>> prepare(
       const ContainerID& containerId,