You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ch...@apache.org on 2018/03/21 20:31:23 UTC
[09/11] mesos git commit: Changed names related to
`DiskProfileAdaptor` for consistency.
Changed names related to `DiskProfileAdaptor` for consistency.
This patch makes name changes to make the code base consistent with the
finalized module name `DiskProfileAdaptor`. It also moves
`mesos::internal::storage::Flags` into the `UriDiskProfileAdaptor` class
since the flags are specific to this module.
Review: https://reviews.apache.org/r/66162
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/1231e8fe
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/1231e8fe
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/1231e8fe
Branch: refs/heads/master
Commit: 1231e8fe79baeda1a69f18831c883e17aebece67
Parents: edea176
Author: Chun-Hung Hsiao <ch...@mesosphere.io>
Authored: Mon Mar 19 15:43:31 2018 -0700
Committer: Chun-Hung Hsiao <ch...@mesosphere.io>
Committed: Wed Mar 21 13:22:51 2018 -0700
----------------------------------------------------------------------
src/Makefile.am | 2 +-
.../storage/uri_disk_profile_adaptor.cpp | 6 +-
.../storage/uri_disk_profile_adaptor.hpp | 243 +++----
src/tests/disk_profile_adaptor_tests.cpp | 685 +++++++++++++++++++
src/tests/disk_profile_tests.cpp | 683 ------------------
.../storage_local_resource_provider_tests.cpp | 56 +-
6 files changed, 839 insertions(+), 836 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/1231e8fe/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index d2c2416..56ce554 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2471,7 +2471,7 @@ mesos_tests_SOURCES = \
tests/cram_md5_authentication_tests.cpp \
tests/credentials_tests.cpp \
tests/default_executor_tests.cpp \
- tests/disk_profile_tests.cpp \
+ tests/disk_profile_adaptor_tests.cpp \
tests/disk_quota_tests.cpp \
tests/dynamic_weights_tests.cpp \
tests/environment.cpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/1231e8fe/src/resource_provider/storage/uri_disk_profile_adaptor.cpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/uri_disk_profile_adaptor.cpp b/src/resource_provider/storage/uri_disk_profile_adaptor.cpp
index 75b3d1d..300ea12 100644
--- a/src/resource_provider/storage/uri_disk_profile_adaptor.cpp
+++ b/src/resource_provider/storage/uri_disk_profile_adaptor.cpp
@@ -120,8 +120,8 @@ Future<hashset<string>> UriDiskProfileAdaptor::watch(
UriDiskProfileAdaptorProcess::UriDiskProfileAdaptorProcess(
- const Flags& _flags)
- : ProcessBase(ID::generate("uri-volume-profile")),
+ const UriDiskProfileAdaptor::Flags& _flags)
+ : ProcessBase(ID::generate("uri-disk-profile-adaptor")),
flags(_flags),
watchPromise(new Promise<Nothing>()) {}
@@ -324,7 +324,7 @@ org_apache_mesos_UriDiskProfileAdaptor(
}
// Load and validate flags from the map.
- mesos::internal::storage::Flags flags;
+ mesos::internal::storage::UriDiskProfileAdaptor::Flags flags;
Try<flags::Warnings> load = flags.load(values);
if (load.isError()) {
http://git-wip-us.apache.org/repos/asf/mesos/blob/1231e8fe/src/resource_provider/storage/uri_disk_profile_adaptor.hpp
----------------------------------------------------------------------
diff --git a/src/resource_provider/storage/uri_disk_profile_adaptor.hpp b/src/resource_provider/storage/uri_disk_profile_adaptor.hpp
index 5bdea89..0484933 100644
--- a/src/resource_provider/storage/uri_disk_profile_adaptor.hpp
+++ b/src/resource_provider/storage/uri_disk_profile_adaptor.hpp
@@ -47,124 +47,6 @@ namespace storage {
// Forward declaration.
class UriDiskProfileAdaptorProcess;
-struct Flags : public virtual flags::FlagsBase
-{
- Flags()
- {
- add(&Flags::uri,
- "uri",
- None(),
- "URI to a JSON object containing the disk 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 disk profile name. Each value should contain\n"
- "a `ResourceProviderSelector` under 'resource_provider_selector' or\n"
- "a `CSIPluginTypeSelector` under 'csi_plugin_type_selector' to\n"
- "specify the set of resource providers this profile applies to,\n"
- "followed by a `VolumeCapability` under '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/resource_provider/storage/disk_profile.proto`.\n"
- "\n"
- "For example:\n"
- "{\n"
- " \"profile_matrix\" : {\n"
- " \"my-profile\" : {\n"
- " \"csi_plugin_type_selector\": {\n"
- " \"plugin_type\" : \"org.apache.mesos.csi.test\"\n"
- " \"},\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 `UriDiskProfileAdaptor` is an example DiskProfileAdaptor module
// that takes a URI as a module parameter and fetches that URI
// periodically. The fetched data is parsed into the required CSI
@@ -177,10 +59,129 @@ struct Flags : public virtual flags::FlagsBase
// `CSIPluginInfo::type` and assumes that all fetched profiles are meant
// for all resource providers.
//
-// See `Flags` above for more information.
+// See `UriDiskProfileAdaptor::Flags` below for more information.
class UriDiskProfileAdaptor : public DiskProfileAdaptor
{
public:
+ struct Flags : public virtual flags::FlagsBase
+ {
+ Flags()
+ {
+ add(&Flags::uri,
+ "uri",
+ None(),
+ "URI to a JSON object containing the disk 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 disk profile name. Each value should contain\n"
+ "a `ResourceProviderSelector` under 'resource_provider_selector' or\n"
+ "a `CSIPluginTypeSelector` under 'csi_plugin_type_selector' to\n"
+ "specify the set of resource providers this profile applies to,\n"
+ "followed by a `VolumeCapability` under '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/resource_provider/storage/disk_profile.proto`.\n"
+ "\n"
+ "For example:\n"
+ "{\n"
+ " \"profile_matrix\" : {\n"
+ " \"my-profile\" : {\n"
+ " \"csi_plugin_type_selector\": {\n"
+ " \"plugin_type\" : \"org.apache.mesos.csi.test\"\n"
+ " \"},\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.\n"
+ "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 `--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;
+ };
+
+
UriDiskProfileAdaptor(const Flags& _flags);
virtual ~UriDiskProfileAdaptor();
@@ -203,7 +204,7 @@ class UriDiskProfileAdaptorProcess :
public process::Process<UriDiskProfileAdaptorProcess>
{
public:
- UriDiskProfileAdaptorProcess(const Flags& _flags);
+ UriDiskProfileAdaptorProcess(const UriDiskProfileAdaptor::Flags& _flags);
virtual void initialize() override;
@@ -230,7 +231,7 @@ private:
void notify(const resource_provider::DiskProfileMapping& parsed);
private:
- Flags flags;
+ UriDiskProfileAdaptor::Flags flags;
// The last fetched profile mapping.
// This module assumes that profiles can only be added and never
http://git-wip-us.apache.org/repos/asf/mesos/blob/1231e8fe/src/tests/disk_profile_adaptor_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/disk_profile_adaptor_tests.cpp b/src/tests/disk_profile_adaptor_tests.cpp
new file mode 100644
index 0000000..948f6ef
--- /dev/null
+++ b/src/tests/disk_profile_adaptor_tests.cpp
@@ -0,0 +1,685 @@
+// 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 <map>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include <mesos/module/disk_profile_adaptor.hpp>
+
+#include <mesos/resource_provider/storage/disk_profile_adaptor.hpp>
+
+#include <process/clock.hpp>
+#include <process/future.hpp>
+#include <process/gmock.hpp>
+#include <process/gtest.hpp>
+#include <process/owned.hpp>
+
+#include <stout/duration.hpp>
+#include <stout/gtest.hpp>
+#include <stout/hashset.hpp>
+#include <stout/path.hpp>
+#include <stout/stringify.hpp>
+#include <stout/try.hpp>
+
+#include <stout/os/write.hpp>
+
+#include "module/manager.hpp"
+
+#include "resource_provider/storage/uri_disk_profile_adaptor.hpp"
+#include "resource_provider/storage/disk_profile_utils.hpp"
+
+#include "tests/flags.hpp"
+#include "tests/mesos.hpp"
+#include "tests/utils.hpp"
+
+using namespace process;
+
+using std::map;
+using std::string;
+using std::tuple;
+using std::vector;
+
+using google::protobuf::Map;
+
+using mesos::resource_provider::DiskProfileMapping;
+
+using testing::_;
+using testing::DoAll;
+using testing::Return;
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+constexpr char URI_DISK_PROFILE_ADAPTOR_NAME[] =
+ "org_apache_mesos_UriDiskProfileAdaptor";
+
+
+class UriDiskProfileAdaptorTest : public MesosTest
+{
+public:
+ virtual void SetUp()
+ {
+ MesosTest::SetUp();
+
+ string libraryPath = getModulePath("uri_disk_profile_adaptor");
+
+ Modules::Library* library = modules.add_libraries();
+ library->set_name("uri_disk_profile_adaptor");
+ library->set_file(libraryPath);
+
+ Modules::Library::Module* module = library->add_modules();
+ module->set_name(URI_DISK_PROFILE_ADAPTOR_NAME);
+
+ ASSERT_SOME(modules::ModuleManager::load(modules));
+ }
+
+ virtual void TearDown()
+ {
+ foreach (const Modules::Library& library, modules.libraries()) {
+ foreach (const Modules::Library::Module& module, library.modules()) {
+ if (module.has_name()) {
+ ASSERT_SOME(modules::ModuleManager::unload(module.name()));
+ }
+ }
+ }
+
+ MesosTest::TearDown();
+ }
+
+protected:
+ Modules modules;
+};
+
+
+// Exercises the disk profile map parsing method with the example found
+// in the UriDiskProfileAdaptor module's help string.
+TEST_F(UriDiskProfileAdaptorTest, ParseExample)
+{
+ const string example = R"~(
+ {
+ "profile_matrix" : {
+ "my-profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test"
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode" : "SINGLE_NODE_WRITER" }
+ },
+ "create_parameters" : {
+ "mesos-does-not" : "interpret-these",
+ "type" : "raid5",
+ "stripes" : "3",
+ "stripesize" : "64"
+ }
+ }
+ }
+ })~";
+
+ Try<DiskProfileMapping> parsed =
+ mesos::internal::storage::parseDiskProfileMapping(example);
+ ASSERT_SOME(parsed);
+
+ const string key = "my-profile";
+ ASSERT_EQ(1u, parsed->profile_matrix().count(key));
+
+ csi::VolumeCapability capability =
+ parsed->profile_matrix().at(key).volume_capabilities();
+
+ ASSERT_TRUE(capability.has_block());
+ ASSERT_TRUE(capability.has_access_mode());
+ ASSERT_EQ(
+ csi::VolumeCapability::AccessMode::SINGLE_NODE_WRITER,
+ capability.access_mode().mode());
+
+ Map<string, string> parameters =
+ parsed->profile_matrix().at(key).create_parameters();
+
+ ASSERT_EQ(4u, parameters.size());
+ ASSERT_EQ(1u, parameters.count("mesos-does-not"));
+ ASSERT_EQ(1u, parameters.count("type"));
+ ASSERT_EQ(1u, parameters.count("stripes"));
+ ASSERT_EQ(1u, parameters.count("stripesize"));
+
+ ASSERT_EQ("interpret-these", parameters.at("mesos-does-not"));
+ ASSERT_EQ("raid5", parameters.at("type"));
+ ASSERT_EQ("3", parameters.at("stripes"));
+ ASSERT_EQ("64", parameters.at("stripesize"));
+}
+
+
+// Exercises the disk profile map parsing method with some slightly incorrect
+// inputs. Each item in the array of examples should error at a different area
+// of the code (and are ordered corresponding to the code as well).
+TEST_F(UriDiskProfileAdaptorTest, ParseInvalids)
+{
+ const vector<string> examples = {
+ "Not an object, but still JSON",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : "This is not an object"
+ }
+ })~",
+
+ // Missing one of 'resource_provider_selector' or
+ // 'csi_plugin_type_selector'.
+ R"~({
+ "profile_matrix" : {
+ "profile" : {}
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : "Wrong JSON type"
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : "Wrong JSON type"
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "not-type" : "Missing required key"
+ }
+ ]
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "type" : "org.apache.mesos.rp.local.storage",
+ "not-name" : "Missing required key"
+ }
+ ]
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : "Wrong JSON type"
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "not-plugin_type" : "Missing required key",
+ }
+ }
+ }
+ })~",
+
+ // More than one selector.
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "type" : "org.apache.mesos.rp.local.storage",
+ "name" : "test"
+ }
+ ]
+ },
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "not-volume_capabilities" : "Missing required key"
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "volume_capabilities" : "Wrong JSON type"
+ }
+ }
+ })~",
+
+ // Missing one of 'block' or 'mount'.
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "volume_capabilities" : {}
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "volume_capabilities" : {
+ "mount" : {
+ "fs_type" : [ "This should not be an array" ]
+ }
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode": "No-enum-of-this-name" }
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "volume_capabilities" : {
+ "mount" : {
+ "mount_flags" : [ "a", "b", "c" ]
+ },
+ "access_mode" : { "mode": "SINGLE_NODE_WRITER" }
+ },
+ "create_parameters" : "Wrong JSON type"
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "volume_capabilities" : {
+ "mount" : { "fs_type" : "abc" },
+ "access_mode" : { "mode": "SINGLE_NODE_READER_ONLY" }
+ },
+ "create_parameters" : {
+ "incorrect" : [ "JSON type of parameter" ]
+ }
+ }
+ }
+ })~",
+
+ R"~({
+ "profile_matrix" : {
+ "profile" : {
+ "csi_plugin_type_selector" : {
+ "plugin_type" : "org.apache.mesos.csi.test",
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode": "MULTI_NODE_READER_ONLY" }
+ }
+ },
+ "first profile is fine, second profile is broken" : {}
+ }
+ })~",
+ };
+
+ hashset<string> errors;
+ for (size_t i = 0; i < examples.size(); i++) {
+ Try<DiskProfileMapping> parsed =
+ mesos::internal::storage::parseDiskProfileMapping(examples[i]);
+
+ ASSERT_ERROR(parsed) << examples[i];
+ ASSERT_EQ(0u, errors.count(parsed.error())) << parsed.error();
+
+ errors.insert(parsed.error());
+ }
+}
+
+
+// This creates a UriDiskProfileAdaptor module configured to read from a
+// file and tests the basic `watch` -> `translate` workflow which
+// callers of the module are expected to follow.
+//
+// Enable this test once MESOS-8567 is resolved.
+TEST_F(UriDiskProfileAdaptorTest, DISABLED_FetchFromFile)
+{
+ Clock::pause();
+
+ const string contents =R"~(
+ {
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "type" : "resource_provider_type",
+ "name" : "resource_provider_name"
+ }
+ ]
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode": "MULTI_NODE_SINGLE_WRITER" }
+ }
+ }
+ }
+ })~";
+
+ const string profileName = "profile";
+ const string profileFile = path::join(sandbox.get(), "profiles.json");
+ const Duration pollInterval = Seconds(10);
+
+ ResourceProviderInfo resourceProviderInfo;
+ resourceProviderInfo.set_type("resource_provider_type");
+ resourceProviderInfo.set_name("resource_provider_name");
+
+ Parameters params;
+
+ Parameter* pollIntervalFlag = params.add_parameter();
+ pollIntervalFlag->set_key("poll_interval");
+ pollIntervalFlag->set_value(stringify(pollInterval));
+
+ // NOTE: We cannot use the `file://` URI to specify the file location,
+ // otherwise the file contents will be prematurely read. Therefore, we
+ // specify the absolute path of the file in the `uri` flag.
+ Parameter* uriFlag = params.add_parameter();
+ uriFlag->set_key("uri");
+ uriFlag->set_value(profileFile);
+
+ // Create the module before we've written anything to the file.
+ // This means the first poll will fail, so the module believes there
+ // are no profiles at the moment.
+ Try<DiskProfileAdaptor*> module =
+ modules::ModuleManager::create<DiskProfileAdaptor>(
+ URI_DISK_PROFILE_ADAPTOR_NAME,
+ params);
+ ASSERT_SOME(module);
+
+ // Start watching for updates.
+ // By the time this returns, we'll know that the first poll has finished
+ // because when the module reads from file, it does so immediately upon
+ // being initialized.
+ Future<hashset<string>> future =
+ module.get()->watch(hashset<string>::EMPTY, resourceProviderInfo);
+
+ // Write the single profile to the file.
+ ASSERT_SOME(os::write(profileFile, contents));
+
+ // Trigger the next poll.
+ Clock::advance(pollInterval);
+
+ AWAIT_ASSERT_READY(future);
+ ASSERT_EQ(1u, future->size());
+ EXPECT_EQ(profileName, *(future->begin()));
+
+ // Translate the profile name into the profile mapping.
+ Future<DiskProfileAdaptor::ProfileInfo> mapping =
+ module.get()->translate(profileName, resourceProviderInfo);
+
+ AWAIT_ASSERT_READY(mapping);
+ ASSERT_TRUE(mapping.get().capability.has_block());
+ ASSERT_EQ(
+ csi::VolumeCapability::AccessMode::MULTI_NODE_SINGLE_WRITER,
+ mapping.get().capability.access_mode().mode());
+
+ Clock::resume();
+}
+
+
+// Basic helper for UriDiskProfileAdaptor modules configured to fetch
+// from HTTP URIs.
+class MockProfileServer : public Process<MockProfileServer>
+{
+public:
+ MOCK_METHOD1(profiles, Future<http::Response>(const http::Request&));
+
+protected:
+ virtual void initialize()
+ {
+ route("/profiles", None(), &MockProfileServer::profiles);
+ }
+};
+
+
+class ServerWrapper
+{
+public:
+ ServerWrapper() : process(new MockProfileServer())
+ {
+ spawn(process.get());
+ }
+
+ ~ServerWrapper()
+ {
+ terminate(process.get());
+ wait(process.get());
+ }
+
+ Owned<MockProfileServer> process;
+};
+
+
+// This creates a UriDiskProfileAdaptor module configured to read from
+// an HTTP URI. The HTTP server will return a different profile mapping
+// between each of the calls. We expect the module to ignore the second
+// call because the module does not allow profiles to be renamed. This
+// is not a fatal error however, as the HTTP server can be "fixed"
+// without restarting the agent.
+TEST_F(UriDiskProfileAdaptorTest, FetchFromHTTP)
+{
+ Clock::pause();
+
+ const string contents1 =R"~(
+ {
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "type" : "resource_provider_type",
+ "name" : "resource_provider_name"
+ }
+ ]
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode": "MULTI_NODE_MULTI_WRITER" }
+ }
+ }
+ }
+ })~";
+
+ const string contents2 =R"~(
+ {
+ "profile_matrix" : {
+ "renamed-profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "type" : "resource_provider_type",
+ "name" : "resource_provider_name"
+ }
+ ]
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode": "SINGLE_NODE_WRITER" }
+ }
+ }
+ }
+ })~";
+
+ const string contents3 =R"~(
+ {
+ "profile_matrix" : {
+ "profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "type" : "resource_provider_type",
+ "name" : "resource_provider_name"
+ }
+ ]
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode": "MULTI_NODE_MULTI_WRITER" }
+ }
+ },
+ "another-profile" : {
+ "resource_provider_selector" : {
+ "resource_providers" : [
+ {
+ "type" : "resource_provider_type",
+ "name" : "resource_provider_name"
+ }
+ ]
+ },
+ "volume_capabilities" : {
+ "block" : {},
+ "access_mode" : { "mode": "SINGLE_NODE_WRITER" }
+ }
+ }
+ }
+ })~";
+
+ const Duration pollInterval = Seconds(10);
+
+ ResourceProviderInfo resourceProviderInfo;
+ resourceProviderInfo.set_type("resource_provider_type");
+ resourceProviderInfo.set_name("resource_provider_name");
+
+ ServerWrapper server;
+
+ // Wait for the server to finish initializing so that the routes are ready.
+ AWAIT_READY(dispatch(server.process->self(), []() { return Nothing(); }));
+
+ // We need to intercept this call since the module is expected to
+ // ignore the result of the second call.
+ Future<Nothing> secondCall;
+
+ EXPECT_CALL(*server.process, profiles(_))
+ .WillOnce(Return(http::OK(contents1)))
+ .WillOnce(DoAll(FutureSatisfy(&secondCall), Return(http::OK(contents2))))
+ .WillOnce(Return(http::OK(contents3)));
+
+ Parameters params;
+
+ Parameter* pollIntervalFlag = params.add_parameter();
+ pollIntervalFlag->set_key("poll_interval");
+ pollIntervalFlag->set_value(stringify(pollInterval));
+
+ Parameter* uriFlag = params.add_parameter();
+ uriFlag->set_key("uri");
+ uriFlag->set_value(stringify(process::http::URL(
+ "http",
+ process::address().ip,
+ process::address().port,
+ server.process->self().id + "/profiles")));
+
+ Try<DiskProfileAdaptor*> module =
+ modules::ModuleManager::create<DiskProfileAdaptor>(
+ URI_DISK_PROFILE_ADAPTOR_NAME,
+ params);
+ ASSERT_SOME(module);
+
+ // Wait for the first HTTP poll to complete.
+ Future<hashset<string>> future =
+ module.get()->watch(hashset<string>::EMPTY, resourceProviderInfo);
+
+ AWAIT_ASSERT_READY(future);
+ ASSERT_EQ(1u, future->size());
+ EXPECT_EQ("profile", *(future->begin()));
+
+ // Start watching for an update to the list of profiles.
+ future = module.get()->watch({"profile"}, resourceProviderInfo);
+
+ // Trigger the second HTTP poll.
+ Clock::advance(pollInterval);
+ AWAIT_ASSERT_READY(secondCall);
+
+ // Dispatch a call to the module, which ensures that the polling has actually
+ // completed (not just the HTTP call).
+ AWAIT_ASSERT_READY(module.get()->translate("profile", resourceProviderInfo));
+
+ // We don't expect the module to notify watcher(s) because the server's
+ // response is considered invalid (the module does not allow profiles
+ // to be renamed).
+ ASSERT_TRUE(future.isPending());
+
+ // Trigger the third HTTP poll.
+ Clock::advance(pollInterval);
+
+ // This time, the server's response is correct and also includes a second
+ // profile, which means that the watcher(s) should be notified.
+ AWAIT_ASSERT_READY(future);
+ ASSERT_EQ(2u, future->size());
+ EXPECT_EQ((hashset<string>{"profile", "another-profile"}), future.get());
+
+ Clock::resume();
+}
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/1231e8fe/src/tests/disk_profile_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/disk_profile_tests.cpp b/src/tests/disk_profile_tests.cpp
deleted file mode 100644
index da8d4e8..0000000
--- a/src/tests/disk_profile_tests.cpp
+++ /dev/null
@@ -1,683 +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 <map>
-#include <string>
-#include <tuple>
-#include <vector>
-
-#include <mesos/module/disk_profile_adaptor.hpp>
-
-#include <mesos/resource_provider/storage/disk_profile_adaptor.hpp>
-
-#include <process/clock.hpp>
-#include <process/future.hpp>
-#include <process/gmock.hpp>
-#include <process/gtest.hpp>
-#include <process/owned.hpp>
-
-#include <stout/duration.hpp>
-#include <stout/gtest.hpp>
-#include <stout/hashset.hpp>
-#include <stout/path.hpp>
-#include <stout/stringify.hpp>
-#include <stout/try.hpp>
-
-#include <stout/os/write.hpp>
-
-#include "module/manager.hpp"
-
-#include "resource_provider/storage/uri_disk_profile_adaptor.hpp"
-#include "resource_provider/storage/disk_profile_utils.hpp"
-
-#include "tests/flags.hpp"
-#include "tests/mesos.hpp"
-#include "tests/utils.hpp"
-
-using namespace process;
-
-using std::map;
-using std::string;
-using std::tuple;
-using std::vector;
-
-using google::protobuf::Map;
-
-using mesos::resource_provider::DiskProfileMapping;
-
-using testing::_;
-using testing::DoAll;
-using testing::Return;
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-constexpr char URI_DISK_PROFILE_ADAPTOR_NAME[] =
- "org_apache_mesos_UriDiskProfileAdaptor";
-
-
-class UriDiskProfileTest : public MesosTest
-{
-public:
- virtual void SetUp()
- {
- MesosTest::SetUp();
-
- string libraryPath = getModulePath("uri_disk_profile_adaptor");
-
- Modules::Library* library = modules.add_libraries();
- library->set_name("uri_disk_profile_adaptor");
- library->set_file(libraryPath);
-
- Modules::Library::Module* module = library->add_modules();
- module->set_name(URI_DISK_PROFILE_ADAPTOR_NAME);
-
- ASSERT_SOME(modules::ModuleManager::load(modules));
- }
-
- virtual void TearDown()
- {
- foreach (const Modules::Library& library, modules.libraries()) {
- foreach (const Modules::Library::Module& module, library.modules()) {
- if (module.has_name()) {
- ASSERT_SOME(modules::ModuleManager::unload(module.name()));
- }
- }
- }
-
- MesosTest::TearDown();
- }
-
-protected:
- Modules modules;
-};
-
-
-// Exercises the disk profile map parsing method with the example found
-// in the UriDiskProfile module's help string.
-TEST_F(UriDiskProfileTest, ParseExample)
-{
- const string example = R"~(
- {
- "profile_matrix" : {
- "my-profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test"
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode" : "SINGLE_NODE_WRITER" }
- },
- "create_parameters" : {
- "mesos-does-not" : "interpret-these",
- "type" : "raid5",
- "stripes" : "3",
- "stripesize" : "64"
- }
- }
- }
- })~";
-
- Try<DiskProfileMapping> parsed =
- mesos::internal::storage::parseDiskProfileMapping(example);
- ASSERT_SOME(parsed);
-
- const string key = "my-profile";
- ASSERT_EQ(1u, parsed->profile_matrix().count(key));
-
- csi::VolumeCapability capability =
- parsed->profile_matrix().at(key).volume_capabilities();
-
- ASSERT_TRUE(capability.has_block());
- ASSERT_TRUE(capability.has_access_mode());
- ASSERT_EQ(
- csi::VolumeCapability::AccessMode::SINGLE_NODE_WRITER,
- capability.access_mode().mode());
-
- Map<string, string> parameters =
- parsed->profile_matrix().at(key).create_parameters();
-
- ASSERT_EQ(4u, parameters.size());
- ASSERT_EQ(1u, parameters.count("mesos-does-not"));
- ASSERT_EQ(1u, parameters.count("type"));
- ASSERT_EQ(1u, parameters.count("stripes"));
- ASSERT_EQ(1u, parameters.count("stripesize"));
-
- ASSERT_EQ("interpret-these", parameters.at("mesos-does-not"));
- ASSERT_EQ("raid5", parameters.at("type"));
- ASSERT_EQ("3", parameters.at("stripes"));
- ASSERT_EQ("64", parameters.at("stripesize"));
-}
-
-
-// Exercises the disk profile map parsing method with some slightly incorrect
-// inputs. Each item in the array of examples should error at a different area
-// of the code (and are ordered corresponding to the code as well).
-TEST_F(UriDiskProfileTest, ParseInvalids)
-{
- const vector<string> examples = {
- "Not an object, but still JSON",
-
- R"~({
- "profile_matrix" : {
- "profile" : "This is not an object"
- }
- })~",
-
- // Missing one of 'resource_provider_selector' or
- // 'csi_plugin_type_selector'.
- R"~({
- "profile_matrix" : {
- "profile" : {}
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : "Wrong JSON type"
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : {
- "resource_providers" : "Wrong JSON type"
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "not-type" : "Missing required key"
- }
- ]
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "type" : "org.apache.mesos.rp.local.storage",
- "not-name" : "Missing required key"
- }
- ]
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : "Wrong JSON type"
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "not-plugin_type" : "Missing required key",
- }
- }
- }
- })~",
-
- // More than one selector.
- R"~({
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "type" : "org.apache.mesos.rp.local.storage",
- "name" : "test"
- }
- ]
- },
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "not-volume_capabilities" : "Missing required key"
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "volume_capabilities" : "Wrong JSON type"
- }
- }
- })~",
-
- // Missing one of 'block' or 'mount'.
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "volume_capabilities" : {}
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "volume_capabilities" : {
- "mount" : {
- "fs_type" : [ "This should not be an array" ]
- }
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode": "No-enum-of-this-name" }
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "volume_capabilities" : {
- "mount" : {
- "mount_flags" : [ "a", "b", "c" ]
- },
- "access_mode" : { "mode": "SINGLE_NODE_WRITER" }
- },
- "create_parameters" : "Wrong JSON type"
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "volume_capabilities" : {
- "mount" : { "fs_type" : "abc" },
- "access_mode" : { "mode": "SINGLE_NODE_READER_ONLY" }
- },
- "create_parameters" : {
- "incorrect" : [ "JSON type of parameter" ]
- }
- }
- }
- })~",
-
- R"~({
- "profile_matrix" : {
- "profile" : {
- "csi_plugin_type_selector" : {
- "plugin_type" : "org.apache.mesos.csi.test",
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode": "MULTI_NODE_READER_ONLY" }
- }
- },
- "first profile is fine, second profile is broken" : {}
- }
- })~",
- };
-
- hashset<string> errors;
- for (size_t i = 0; i < examples.size(); i++) {
- Try<DiskProfileMapping> parsed =
- mesos::internal::storage::parseDiskProfileMapping(examples[i]);
-
- ASSERT_ERROR(parsed) << examples[i];
- ASSERT_EQ(0u, errors.count(parsed.error())) << parsed.error();
-
- errors.insert(parsed.error());
- }
-}
-
-
-// This creates a UriDiskProfile module configured to read from a file
-// and tests the basic `watch` -> `translate` workflow which callers of
-// the module are expected to follow.
-//
-// Enable this test once MESOS-8567 is resolved.
-TEST_F(UriDiskProfileTest, DISABLED_FetchFromFile)
-{
- Clock::pause();
-
- const string contents =R"~(
- {
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "type" : "resource_provider_type",
- "name" : "resource_provider_name"
- }
- ]
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode": "MULTI_NODE_SINGLE_WRITER" }
- }
- }
- }
- })~";
-
- const string profileName = "profile";
- const string profileFile = path::join(sandbox.get(), "profiles.json");
- const Duration pollInterval = Seconds(10);
-
- ResourceProviderInfo resourceProviderInfo;
- resourceProviderInfo.set_type("resource_provider_type");
- resourceProviderInfo.set_name("resource_provider_name");
-
- Parameters params;
-
- Parameter* pollIntervalFlag = params.add_parameter();
- pollIntervalFlag->set_key("poll_interval");
- pollIntervalFlag->set_value(stringify(pollInterval));
-
- // NOTE: We cannot use the `file://` URI to specify the file location,
- // otherwise the file contents will be prematurely read. Therefore, we
- // specify the absolute path of the file in the `uri` flag.
- Parameter* uriFlag = params.add_parameter();
- uriFlag->set_key("uri");
- uriFlag->set_value(profileFile);
-
- // Create the module before we've written anything to the file.
- // This means the first poll will fail, so the module believes there
- // are no profiles at the moment.
- Try<DiskProfileAdaptor*> module =
- modules::ModuleManager::create<DiskProfileAdaptor>(
- URI_DISK_PROFILE_ADAPTOR_NAME,
- params);
- ASSERT_SOME(module);
-
- // Start watching for updates.
- // By the time this returns, we'll know that the first poll has finished
- // because when the module reads from file, it does so immediately upon
- // being initialized.
- Future<hashset<string>> future =
- module.get()->watch(hashset<string>::EMPTY, resourceProviderInfo);
-
- // Write the single profile to the file.
- ASSERT_SOME(os::write(profileFile, contents));
-
- // Trigger the next poll.
- Clock::advance(pollInterval);
-
- AWAIT_ASSERT_READY(future);
- ASSERT_EQ(1u, future->size());
- EXPECT_EQ(profileName, *(future->begin()));
-
- // Translate the profile name into the profile mapping.
- Future<DiskProfileAdaptor::ProfileInfo> mapping =
- module.get()->translate(profileName, resourceProviderInfo);
-
- AWAIT_ASSERT_READY(mapping);
- ASSERT_TRUE(mapping.get().capability.has_block());
- ASSERT_EQ(
- csi::VolumeCapability::AccessMode::MULTI_NODE_SINGLE_WRITER,
- mapping.get().capability.access_mode().mode());
-
- Clock::resume();
-}
-
-
-// Basic helper for UriDiskProfile modules configured to fetch from HTTP URIs.
-class MockProfileServer : public Process<MockProfileServer>
-{
-public:
- MOCK_METHOD1(profiles, Future<http::Response>(const http::Request&));
-
-protected:
- virtual void initialize()
- {
- route("/profiles", None(), &MockProfileServer::profiles);
- }
-};
-
-
-class ServerWrapper
-{
-public:
- ServerWrapper() : process(new MockProfileServer())
- {
- spawn(process.get());
- }
-
- ~ServerWrapper()
- {
- terminate(process.get());
- wait(process.get());
- }
-
- Owned<MockProfileServer> process;
-};
-
-
-// This creates a UriDiskProfile module configured to read from an HTTP URI.
-// The HTTP server will return a different profile mapping between each of the
-// calls. We expect the module to ignore the second call because the module
-// does not allow profiles to be renamed. This is not a fatal error however,
-// as the HTTP server can be "fixed" without restarting the agent.
-TEST_F(UriDiskProfileTest, FetchFromHTTP)
-{
- Clock::pause();
-
- const string contents1 =R"~(
- {
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "type" : "resource_provider_type",
- "name" : "resource_provider_name"
- }
- ]
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode": "MULTI_NODE_MULTI_WRITER" }
- }
- }
- }
- })~";
-
- const string contents2 =R"~(
- {
- "profile_matrix" : {
- "renamed-profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "type" : "resource_provider_type",
- "name" : "resource_provider_name"
- }
- ]
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode": "SINGLE_NODE_WRITER" }
- }
- }
- }
- })~";
-
- const string contents3 =R"~(
- {
- "profile_matrix" : {
- "profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "type" : "resource_provider_type",
- "name" : "resource_provider_name"
- }
- ]
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode": "MULTI_NODE_MULTI_WRITER" }
- }
- },
- "another-profile" : {
- "resource_provider_selector" : {
- "resource_providers" : [
- {
- "type" : "resource_provider_type",
- "name" : "resource_provider_name"
- }
- ]
- },
- "volume_capabilities" : {
- "block" : {},
- "access_mode" : { "mode": "SINGLE_NODE_WRITER" }
- }
- }
- }
- })~";
-
- const Duration pollInterval = Seconds(10);
-
- ResourceProviderInfo resourceProviderInfo;
- resourceProviderInfo.set_type("resource_provider_type");
- resourceProviderInfo.set_name("resource_provider_name");
-
- ServerWrapper server;
-
- // Wait for the server to finish initializing so that the routes are ready.
- AWAIT_READY(dispatch(server.process->self(), []() { return Nothing(); }));
-
- // We need to intercept this call since the module is expected to
- // ignore the result of the second call.
- Future<Nothing> secondCall;
-
- EXPECT_CALL(*server.process, profiles(_))
- .WillOnce(Return(http::OK(contents1)))
- .WillOnce(DoAll(FutureSatisfy(&secondCall), Return(http::OK(contents2))))
- .WillOnce(Return(http::OK(contents3)));
-
- Parameters params;
-
- Parameter* pollIntervalFlag = params.add_parameter();
- pollIntervalFlag->set_key("poll_interval");
- pollIntervalFlag->set_value(stringify(pollInterval));
-
- Parameter* uriFlag = params.add_parameter();
- uriFlag->set_key("uri");
- uriFlag->set_value(stringify(process::http::URL(
- "http",
- process::address().ip,
- process::address().port,
- server.process->self().id + "/profiles")));
-
- Try<DiskProfileAdaptor*> module =
- modules::ModuleManager::create<DiskProfileAdaptor>(
- URI_DISK_PROFILE_ADAPTOR_NAME,
- params);
- ASSERT_SOME(module);
-
- // Wait for the first HTTP poll to complete.
- Future<hashset<string>> future =
- module.get()->watch(hashset<string>::EMPTY, resourceProviderInfo);
-
- AWAIT_ASSERT_READY(future);
- ASSERT_EQ(1u, future->size());
- EXPECT_EQ("profile", *(future->begin()));
-
- // Start watching for an update to the list of profiles.
- future = module.get()->watch({"profile"}, resourceProviderInfo);
-
- // Trigger the second HTTP poll.
- Clock::advance(pollInterval);
- AWAIT_ASSERT_READY(secondCall);
-
- // Dispatch a call to the module, which ensures that the polling has actually
- // completed (not just the HTTP call).
- AWAIT_ASSERT_READY(module.get()->translate("profile", resourceProviderInfo));
-
- // We don't expect the module to notify watcher(s) because the server's
- // response is considered invalid (the module does not allow profiles
- // to be renamed).
- ASSERT_TRUE(future.isPending());
-
- // Trigger the third HTTP poll.
- Clock::advance(pollInterval);
-
- // This time, the server's response is correct and also includes a second
- // profile, which means that the watcher(s) should be notified.
- AWAIT_ASSERT_READY(future);
- ASSERT_EQ(2u, future->size());
- EXPECT_EQ((hashset<string>{"profile", "another-profile"}), future.get());
-
- Clock::resume();
-}
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/1231e8fe/src/tests/storage_local_resource_provider_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/storage_local_resource_provider_tests.cpp b/src/tests/storage_local_resource_provider_tests.cpp
index 47631ab..0ad2d24 100644
--- a/src/tests/storage_local_resource_provider_tests.cpp
+++ b/src/tests/storage_local_resource_provider_tests.cpp
@@ -83,7 +83,7 @@ public:
path::join(sandbox.get(), "resource_provider_configs");
ASSERT_SOME(os::mkdir(resourceProviderConfigDir));
- uriDiskProfileConfigPath =
+ uriDiskProfileMappingPath =
path::join(sandbox.get(), "disk_profiles.json");
}
@@ -140,7 +140,7 @@ public:
return flags;
}
- void loadUriDiskProfileModule()
+ void loadUriDiskProfileAdaptorModule()
{
const string libraryPath = getModulePath("uri_disk_profile_adaptor");
@@ -153,7 +153,7 @@ public:
Parameter* uri = module->add_parameters();
uri->set_key("uri");
- uri->set_value(uriDiskProfileConfigPath);
+ uri->set_value(uriDiskProfileMappingPath);
Parameter* pollInterval = module->add_parameters();
pollInterval->set_key("poll_interval");
pollInterval->set_value("1secs");
@@ -227,10 +227,10 @@ public:
resourceProviderConfig.get()));
}
- void setupDiskProfileConfig()
+ void setupDiskProfileMapping()
{
Try<Nothing> write = os::write(
- uriDiskProfileConfigPath,
+ uriDiskProfileMappingPath,
R"~(
{
"profile_matrix": {
@@ -267,7 +267,7 @@ protected:
Modules modules;
vector<string> slaveWorkDirs;
string resourceProviderConfigDir;
- string uriDiskProfileConfigPath;
+ string uriDiskProfileMappingPath;
};
@@ -441,10 +441,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_ZeroSizedDisk)
// handle disks less than 1MB correctly.
TEST_F(StorageLocalResourceProviderTest, ROOT_SmallDisk)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Kilobytes(512), "volume0:512KB");
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
@@ -565,7 +565,7 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_NewProfile)
{
Clock::pause();
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
@@ -627,7 +627,7 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_NewProfile)
FUTURE_PROTOBUF(UpdateSlaveMessage(), _, _);
// Add new profiles.
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
// A new storage pool for profile "volume-default" should be reported
// by the resource provider. Still expect no storage pool for
@@ -672,10 +672,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_NewProfile)
// create then destroy a new volume from a storage pool.
TEST_F(StorageLocalResourceProviderTest, ROOT_CreateDestroyVolume)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
masterFlags.allocation_interval = Milliseconds(50);
@@ -861,10 +861,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_CreateDestroyVolume)
// destroy a volume created from a storage pool after recovery.
TEST_F(StorageLocalResourceProviderTest, ROOT_CreateDestroyVolumeRecovery)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
masterFlags.allocation_interval = Milliseconds(50);
@@ -1070,10 +1070,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_CreateDestroyVolumeRecovery)
// created volume becomes a pre-existing volume.
TEST_F(StorageLocalResourceProviderTest, ROOT_AgentRegisteredWithNewId)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
masterFlags.allocation_interval = Milliseconds(50);
@@ -1282,10 +1282,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_AgentRegisteredWithNewId)
// volume after the task finishes.
TEST_F(StorageLocalResourceProviderTest, ROOT_PublishResources)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
masterFlags.allocation_interval = Milliseconds(50);
@@ -1508,10 +1508,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_PublishResources)
// destroy a published volume after recovery.
TEST_F(StorageLocalResourceProviderTest, ROOT_PublishResourcesRecovery)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
masterFlags.allocation_interval = Milliseconds(50);
@@ -1791,10 +1791,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_PublishResourcesRecovery)
// destroy a published volume after agent reboot.
TEST_F(StorageLocalResourceProviderTest, ROOT_PublishResourcesReboot)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
masterFlags.allocation_interval = Milliseconds(50);
@@ -2115,10 +2115,10 @@ TEST_F(
StorageLocalResourceProviderTest,
ROOT_PublishUnpublishResourcesPluginKilled)
{
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
masterFlags.allocation_interval = Milliseconds(50);
@@ -2622,10 +2622,10 @@ TEST_F(StorageLocalResourceProviderTest, ROOT_RetryOperationStatusUpdate)
{
Clock::pause();
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
@@ -2785,10 +2785,10 @@ TEST_F(
{
Clock::pause();
- loadUriDiskProfileModule();
+ loadUriDiskProfileAdaptorModule();
setupResourceProviderConfig(Gigabytes(4));
- setupDiskProfileConfig();
+ setupDiskProfileMapping();
master::Flags masterFlags = CreateMasterFlags();
Try<Owned<cluster::Master>> master = StartMaster(masterFlags);