You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ji...@apache.org on 2015/02/04 21:08:07 UTC
mesos git commit: Added validation for CREATE offer operation.
Repository: mesos
Updated Branches:
refs/heads/master 6e5212e4c -> 66157a6ce
Added validation for CREATE offer operation.
Review: https://reviews.apache.org/r/30513
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/66157a6c
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/66157a6c
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/66157a6c
Branch: refs/heads/master
Commit: 66157a6ce2d82f446fd3b59b252d8b473f5b2006
Parents: 6e5212e
Author: Jie Yu <yu...@gmail.com>
Authored: Fri Jan 30 14:42:03 2015 -0800
Committer: Jie Yu <yu...@gmail.com>
Committed: Wed Feb 4 12:07:15 2015 -0800
----------------------------------------------------------------------
src/Makefile.am | 1 +
src/master/validation.cpp | 40 ++-
src/master/validation.hpp | 6 +-
src/tests/master_validation_tests.cpp | 156 ++++++++++
src/tests/resource_offers_tests.cpp | 440 -----------------------------
5 files changed, 201 insertions(+), 442 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 5b1885d..93537d1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1279,6 +1279,7 @@ mesos_tests_SOURCES = \
tests/master_contender_detector_tests.cpp \
tests/master_slave_reconciliation_tests.cpp \
tests/master_tests.cpp \
+ tests/master_validation_tests.cpp \
tests/mesos.cpp \
tests/metrics_tests.cpp \
tests/module.cpp \
http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/master/validation.cpp
----------------------------------------------------------------------
diff --git a/src/master/validation.cpp b/src/master/validation.cpp
index 8804ba6..550782e 100644
--- a/src/master/validation.cpp
+++ b/src/master/validation.cpp
@@ -121,6 +121,22 @@ Option<Error> validateUniquePersistenceID(
}
+// Validates that all the given resources are persistent volumes.
+Option<Error> validatePersistentVolume(
+ const RepeatedPtrField<Resource>& volumes)
+{
+ foreach (const Resource& volume, volumes) {
+ if (!volume.has_disk()) {
+ return Error("Resource " + stringify(volume) + " does not have DiskInfo");
+ } else if (!volume.disk().has_persistence()) {
+ return Error("'persistence' is not set in DiskInfo");
+ }
+ }
+
+ return None();
+}
+
+
Option<Error> validate(const RepeatedPtrField<Resource>& resources)
{
Option<Error> error = Resources::validate(resources);
@@ -516,7 +532,29 @@ Option<Error> validate(
namespace operation {
-// TODO(jieyu): Added validate functions for Offer operations.
+Option<Error> validate(
+ const Offer::Operation::Create& create,
+ const Resources& checkpointedResources)
+{
+ Option<Error> error = resource::validate(create.volumes());
+ if (error.isSome()) {
+ return Error("Invalid resources: " + error.get().message);
+ }
+
+ error = resource::validatePersistentVolume(create.volumes());
+ if (error.isSome()) {
+ return Error("Not a persistent volume: " + error.get().message);
+ }
+
+ error = resource::validateUniquePersistenceID(
+ checkpointedResources + create.volumes());
+
+ if (error.isSome()) {
+ return error;
+ }
+
+ return None();
+}
} // namespace operation {
http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/master/validation.hpp
----------------------------------------------------------------------
diff --git a/src/master/validation.hpp b/src/master/validation.hpp
index 642c375..81dc7ee 100644
--- a/src/master/validation.hpp
+++ b/src/master/validation.hpp
@@ -81,7 +81,11 @@ Option<Error> validate(
namespace operation {
-// TODO(jieyu): Added validate functions for Offer operations.
+// Validates the CREATE operation. We need slave's checkpointed
+// resources so that we can validate persistence ID uniqueness.
+Option<Error> validate(
+ const Offer::Operation::Create& create,
+ const Resources& checkpointedResources);
} // namespace operation {
http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/tests/master_validation_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_validation_tests.cpp b/src/tests/master_validation_tests.cpp
new file mode 100644
index 0000000..1277311
--- /dev/null
+++ b/src/tests/master_validation_tests.cpp
@@ -0,0 +1,156 @@
+/**
+ * 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 <google/protobuf/repeated_field.h>
+
+#include <gtest/gtest.h>
+
+#include <mesos/mesos.hpp>
+#include <mesos/resources.hpp>
+
+#include <stout/gtest.hpp>
+
+#include "master/validation.hpp"
+
+#include "tests/mesos.hpp"
+
+using namespace mesos;
+using namespace mesos::internal::tests;
+using namespace mesos::internal::master::validation;
+
+using google::protobuf::RepeatedPtrField;
+
+
+class ResourceValidationTest : public ::testing::Test
+{
+protected:
+ RepeatedPtrField<Resource> CreateResources(const Resource& resource)
+ {
+ RepeatedPtrField<Resource> resources;
+ resources.Add()->CopyFrom(resource);
+ return resources;
+ }
+};
+
+
+TEST_F(ResourceValidationTest, PersistentVolume)
+{
+ Resource volume = Resources::parse("disk", "128", "role1").get();
+ volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1"));
+
+ EXPECT_NONE(resource::validate(CreateResources(volume)));
+}
+
+
+TEST_F(ResourceValidationTest, UnreservedDiskInfo)
+{
+ Resource volume = Resources::parse("disk", "128", "*").get();
+ volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1"));
+
+ EXPECT_SOME(resource::validate(CreateResources(volume)));
+}
+
+
+TEST_F(ResourceValidationTest, InvalidPersistenceID)
+{
+ Resource volume = Resources::parse("disk", "128", "role1").get();
+ volume.mutable_disk()->CopyFrom(createDiskInfo("id1/", "path1"));
+
+ EXPECT_SOME(resource::validate(CreateResources(volume)));
+}
+
+
+TEST_F(ResourceValidationTest, PersistentVolumeWithoutVolumeInfo)
+{
+ Resource volume = Resources::parse("disk", "128", "role1").get();
+ volume.mutable_disk()->CopyFrom(createDiskInfo("id1", None()));
+
+ EXPECT_SOME(resource::validate(CreateResources(volume)));
+}
+
+
+TEST_F(ResourceValidationTest, ReadOnlyPersistentVolume)
+{
+ Resource volume = Resources::parse("disk", "128", "role1").get();
+ volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1", Volume::RO));
+
+ EXPECT_SOME(resource::validate(CreateResources(volume)));
+}
+
+
+TEST_F(ResourceValidationTest, PersistentVolumeWithHostPath)
+{
+ Resource volume = Resources::parse("disk", "128", "role1").get();
+ volume.mutable_disk()->CopyFrom(
+ createDiskInfo("id1", "path1", Volume::RW, "foo"));
+
+ EXPECT_SOME(resource::validate(CreateResources(volume)));
+}
+
+
+TEST_F(ResourceValidationTest, NonPersistentVolume)
+{
+ Resource volume = Resources::parse("disk", "128", "role1").get();
+ volume.mutable_disk()->CopyFrom(createDiskInfo(None(), "path1"));
+
+ EXPECT_SOME(resource::validate(CreateResources(volume)));
+}
+
+
+class CreateOperationValidationTest : public ::testing::Test {};
+
+
+// This test verifies that all resources specified in the CREATE
+// operation are persistent volumes.
+TEST_F(CreateOperationValidationTest, PersistentVolumes)
+{
+ Resource volume = Resources::parse("disk", "128", "role1").get();
+ volume.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1"));
+
+ Offer::Operation::Create create;
+ create.add_volumes()->CopyFrom(volume);
+
+ EXPECT_NONE(operation::validate(create, Resources()));
+
+ Resource cpus = Resources::parse("cpus", "2", "*").get();
+
+ create.add_volumes()->CopyFrom(cpus);
+
+ EXPECT_SOME(operation::validate(create, Resources()));
+}
+
+
+TEST_F(CreateOperationValidationTest, DuplicatedPersistenceID)
+{
+ Resource volume1 = Resources::parse("disk", "128", "role1").get();
+ volume1.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1"));
+
+ Offer::Operation::Create create;
+ create.add_volumes()->CopyFrom(volume1);
+
+ EXPECT_NONE(operation::validate(create, Resources()));
+
+ Resource volume2 = Resources::parse("disk", "64", "role1").get();
+ volume2.mutable_disk()->CopyFrom(createDiskInfo("id1", "path1"));
+
+ EXPECT_SOME(operation::validate(create, volume1));
+
+ create.add_volumes()->CopyFrom(volume2);
+
+ EXPECT_SOME(operation::validate(create, Resources()));
+}
http://git-wip-us.apache.org/repos/asf/mesos/blob/66157a6c/src/tests/resource_offers_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/resource_offers_tests.cpp b/src/tests/resource_offers_tests.cpp
index 24a7eab..3e529ba 100644
--- a/src/tests/resource_offers_tests.cpp
+++ b/src/tests/resource_offers_tests.cpp
@@ -553,446 +553,6 @@ TEST_F(TaskValidationTest, ExecutorInfoDiffersOnDifferentSlaves)
}
-// TODO(jieyu): Disable all persistent volume related tests for now.
-// Those tests should be moved to OfferOperationValidationTest.
-TEST_F(TaskValidationTest, DISABLED_UnreservedDiskInfo)
-{
- Try<PID<Master>> master = StartMaster();
- ASSERT_SOME(master);
-
- Try<PID<Slave>> slave = StartSlave();
- ASSERT_SOME(slave);
-
- MockScheduler sched;
- MesosSchedulerDriver driver(
- &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
-
- EXPECT_CALL(sched, registered(&driver, _, _))
- .Times(1);
-
- Future<vector<Offer>> offers;
- EXPECT_CALL(sched, resourceOffers(&driver, _))
- .WillOnce(FutureArg<1>(&offers))
- .WillRepeatedly(Return()); // Ignore subsequent offers.
-
- driver.start();
-
- AWAIT_READY(offers);
- EXPECT_NE(0u, offers.get().size());
-
- // Create a persistent volume with "*" role.
- Resource diskResource = Resources::parse("disk", "128", "*").get();
- diskResource.mutable_disk()->CopyFrom(createDiskInfo("1", "1"));
-
- // Include other resources in task resources.
- Resources taskResources =
- Resources::parse("cpus:1;mem:128").get() + diskResource;
-
- Offer offer = offers.get()[0];
- TaskInfo task =
- createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID);
-
- vector<TaskInfo> tasks;
- tasks.push_back(task);
-
- Future<TaskStatus> status;
- EXPECT_CALL(sched, statusUpdate(&driver, _))
- .WillOnce(FutureArg<1>(&status));
-
- driver.launchTasks(offer.id(), tasks);
-
- AWAIT_READY(status);
- EXPECT_EQ(task.task_id(), status.get().task_id());
- EXPECT_EQ(TASK_ERROR, status.get().state());
- EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason());
- EXPECT_TRUE(status.get().has_message());
- EXPECT_TRUE(strings::contains(
- status.get().message(),
- "Persistent disk volume is disallowed for '*' role"));
-
- driver.stop();
- driver.join();
-
- Shutdown();
-}
-
-
-TEST_F(TaskValidationTest, DISABLED_InvalidPersistenceID)
-{
- Try<PID<Master>> master = StartMaster();
- ASSERT_SOME(master);
-
- Try<PID<Slave>> slave = StartSlave();
- ASSERT_SOME(slave);
-
- MockScheduler sched;
- MesosSchedulerDriver driver(
- &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
-
- EXPECT_CALL(sched, registered(&driver, _, _))
- .Times(1);
-
- Future<vector<Offer>> offers;
- EXPECT_CALL(sched, resourceOffers(&driver, _))
- .WillOnce(FutureArg<1>(&offers))
- .WillRepeatedly(Return()); // Ignore subsequent offers.
-
- driver.start();
-
- AWAIT_READY(offers);
- EXPECT_NE(0u, offers.get().size());
-
- // Create a persistent volume with an invalid persistence id.
- Resource diskResource = Resources::parse("disk", "128", "role1").get();
- diskResource.mutable_disk()->CopyFrom(createDiskInfo("1/", "1"));
-
- // Include other resources in task resources.
- Resources taskResources =
- Resources::parse("cpus:1;mem:128").get() + diskResource;
-
- Offer offer = offers.get()[0];
- TaskInfo task =
- createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID);
-
- vector<TaskInfo> tasks;
- tasks.push_back(task);
-
- Future<TaskStatus> status;
- EXPECT_CALL(sched, statusUpdate(&driver, _))
- .WillOnce(FutureArg<1>(&status));
-
- driver.launchTasks(offer.id(), tasks);
-
- AWAIT_READY(status);
- EXPECT_EQ(task.task_id(), status.get().task_id());
- EXPECT_EQ(TASK_ERROR, status.get().state());
- EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason());
- EXPECT_TRUE(status.get().has_message());
- EXPECT_TRUE(strings::contains(
- status.get().message(),
- "Persistence ID '1/' contains invalid characters"));
-
- driver.stop();
- driver.join();
-
- Shutdown();
-}
-
-
-TEST_F(TaskValidationTest, DISABLED_PersistentDiskInfoWithoutVolume)
-{
- Try<PID<Master>> master = StartMaster();
- ASSERT_SOME(master);
-
- Try<PID<Slave>> slave = StartSlave();
- ASSERT_SOME(slave);
-
- MockScheduler sched;
- MesosSchedulerDriver driver(
- &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
-
- EXPECT_CALL(sched, registered(&driver, _, _))
- .Times(1);
-
- Future<vector<Offer>> offers;
- EXPECT_CALL(sched, resourceOffers(&driver, _))
- .WillOnce(FutureArg<1>(&offers))
- .WillRepeatedly(Return()); // Ignore subsequent offers.
-
- driver.start();
-
- AWAIT_READY(offers);
- EXPECT_NE(0u, offers.get().size());
-
- // Create a persistent volume no volume information.
- Resource diskResource = Resources::parse("disk", "128", "role1").get();
- diskResource.mutable_disk()->CopyFrom(createDiskInfo("1", None()));
-
- // Include other resources in task resources.
- Resources taskResources =
- Resources::parse("cpus:1;mem:128").get() + diskResource;
-
- Offer offer = offers.get()[0];
- TaskInfo task =
- createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID);
-
- vector<TaskInfo> tasks;
- tasks.push_back(task);
-
- Future<TaskStatus> status;
- EXPECT_CALL(sched, statusUpdate(&driver, _))
- .WillOnce(FutureArg<1>(&status));
-
- driver.launchTasks(offer.id(), tasks);
-
- AWAIT_READY(status);
- EXPECT_EQ(task.task_id(), status.get().task_id());
- EXPECT_EQ(TASK_ERROR, status.get().state());
- EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason());
- EXPECT_TRUE(status.get().has_message());
- EXPECT_TRUE(strings::contains(
- status.get().message(),
- "Persistent disk should specify a volume"));
-
- driver.stop();
- driver.join();
-
- Shutdown();
-}
-
-
-TEST_F(TaskValidationTest, DISABLED_PersistentDiskInfoWithReadOnlyVolume)
-{
- Try<PID<Master>> master = StartMaster();
- ASSERT_SOME(master);
-
- Try<PID<Slave>> slave = StartSlave();
- ASSERT_SOME(slave);
-
- MockScheduler sched;
- MesosSchedulerDriver driver(
- &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
-
- EXPECT_CALL(sched, registered(&driver, _, _))
- .Times(1);
-
- Future<vector<Offer>> offers;
- EXPECT_CALL(sched, resourceOffers(&driver, _))
- .WillOnce(FutureArg<1>(&offers))
- .WillRepeatedly(Return()); // Ignore subsequent offers.
-
- driver.start();
-
- AWAIT_READY(offers);
- EXPECT_NE(0u, offers.get().size());
-
- // Create a read-only persistent volume.
- Resource diskResource = Resources::parse("disk", "128", "role1").get();
- diskResource.mutable_disk()->CopyFrom(createDiskInfo("1", "1", Volume::RO));
-
- // Include other resources in task resources.
- Resources taskResources =
- Resources::parse("cpus:1;mem:128").get() + diskResource;
-
- Offer offer = offers.get()[0];
- TaskInfo task =
- createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID);
-
- vector<TaskInfo> tasks;
- tasks.push_back(task);
-
- Future<TaskStatus> status;
- EXPECT_CALL(sched, statusUpdate(&driver, _))
- .WillOnce(FutureArg<1>(&status));
-
- driver.launchTasks(offer.id(), tasks);
-
- AWAIT_READY(status);
- EXPECT_EQ(task.task_id(), status.get().task_id());
- EXPECT_EQ(TASK_ERROR, status.get().state());
- EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason());
- EXPECT_TRUE(status.get().has_message());
- EXPECT_TRUE(strings::contains(
- status.get().message(),
- "Read-only volume is not supported for DiskInfo"));
-
- driver.stop();
- driver.join();
-
- Shutdown();
-}
-
-
-TEST_F(TaskValidationTest, DISABLED_PersistentDiskInfoWithHostPath)
-{
- Try<PID<Master>> master = StartMaster();
- ASSERT_SOME(master);
-
- Try<PID<Slave>> slave = StartSlave();
- ASSERT_SOME(slave);
-
- MockScheduler sched;
- MesosSchedulerDriver driver(
- &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
-
- EXPECT_CALL(sched, registered(&driver, _, _))
- .Times(1);
-
- Future<vector<Offer>> offers;
- EXPECT_CALL(sched, resourceOffers(&driver, _))
- .WillOnce(FutureArg<1>(&offers))
- .WillRepeatedly(Return()); // Ignore subsequent offers.
-
- driver.start();
-
- AWAIT_READY(offers);
- EXPECT_NE(0u, offers.get().size());
-
- // Create a persistent volume with host path.
- Resource diskResource = Resources::parse("disk", "128", "role1").get();
- diskResource.mutable_disk()->CopyFrom(
- createDiskInfo("1", "1", Volume::RW, "foo"));
-
- // Include other resources in task resources.
- Resources taskResources =
- Resources::parse("cpus:1;mem:128").get() + diskResource;
-
- Offer offer = offers.get()[0];
- TaskInfo task =
- createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID);
-
- vector<TaskInfo> tasks;
- tasks.push_back(task);
-
- Future<TaskStatus> status;
- EXPECT_CALL(sched, statusUpdate(&driver, _))
- .WillOnce(FutureArg<1>(&status));
-
- driver.launchTasks(offer.id(), tasks);
-
- AWAIT_READY(status);
- EXPECT_EQ(task.task_id(), status.get().task_id());
- EXPECT_EQ(TASK_ERROR, status.get().state());
- EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason());
- EXPECT_TRUE(status.get().has_message());
- EXPECT_TRUE(strings::contains(
- status.get().message(),
- "Volume in DiskInfo should not have 'host_path' set"));
-
- driver.stop();
- driver.join();
-
- Shutdown();
-}
-
-
-TEST_F(TaskValidationTest, DISABLED_NonPersistentDiskInfoWithVolume)
-{
- Try<PID<Master>> master = StartMaster();
- ASSERT_SOME(master);
-
- Try<PID<Slave>> slave = StartSlave();
- ASSERT_SOME(slave);
-
- MockScheduler sched;
- MesosSchedulerDriver driver(
- &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
-
- EXPECT_CALL(sched, registered(&driver, _, _))
- .Times(1);
-
- Future<vector<Offer>> offers;
- EXPECT_CALL(sched, resourceOffers(&driver, _))
- .WillOnce(FutureArg<1>(&offers))
- .WillRepeatedly(Return()); // Ignore subsequent offers.
-
- driver.start();
-
- AWAIT_READY(offers);
- EXPECT_NE(0u, offers.get().size());
-
- // Create a non-persistent volume.
- Resource diskResource = Resources::parse("disk", "128", "role1").get();
- diskResource.mutable_disk()->CopyFrom(createDiskInfo(None(), "1"));
-
- // Include other resources in task resources.
- Resources taskResources =
- Resources::parse("cpus:1;mem:128").get() + diskResource;
-
- Offer offer = offers.get()[0];
- TaskInfo task =
- createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID);
-
- vector<TaskInfo> tasks;
- tasks.push_back(task);
-
- Future<TaskStatus> status;
- EXPECT_CALL(sched, statusUpdate(&driver, _))
- .WillOnce(FutureArg<1>(&status));
-
- driver.launchTasks(offer.id(), tasks);
-
- AWAIT_READY(status);
- EXPECT_EQ(task.task_id(), status.get().task_id());
- EXPECT_EQ(TASK_ERROR, status.get().state());
- EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason());
- EXPECT_TRUE(status.get().has_message());
- EXPECT_TRUE(strings::contains(
- status.get().message(),
- "Non-persistent volume is not supported"));
-
- driver.stop();
- driver.join();
-
- Shutdown();
-}
-
-
-TEST_F(TaskValidationTest, DISABLED_DuplicatedPersistenceIDWithinTask)
-{
- Try<PID<Master>> master = StartMaster();
- ASSERT_SOME(master);
-
- Try<PID<Slave>> slave = StartSlave();
- ASSERT_SOME(slave);
-
- MockScheduler sched;
- MesosSchedulerDriver driver(
- &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
-
- EXPECT_CALL(sched, registered(&driver, _, _))
- .Times(1);
-
- Future<vector<Offer>> offers;
- EXPECT_CALL(sched, resourceOffers(&driver, _))
- .WillOnce(FutureArg<1>(&offers))
- .WillRepeatedly(Return()); // Ignore subsequent offers.
-
- driver.start();
-
- AWAIT_READY(offers);
- EXPECT_NE(0u, offers.get().size());
-
- // Create two persistent volumes with the same id.
- Resource diskResource1 = Resources::parse("disk", "128", "role1").get();
- diskResource1.mutable_disk()->CopyFrom(createDiskInfo("1", "1"));
-
- Resource diskResource2 = Resources::parse("disk", "64", "role1").get();
- diskResource2.mutable_disk()->CopyFrom(createDiskInfo("1", "1"));
-
- // Include other resources in task resources.
- Resources taskResources =
- Resources::parse("cpus:1;mem:128").get() + diskResource1 + diskResource2;
-
- Offer offer = offers.get()[0];
- TaskInfo task =
- createTask(offer.slave_id(), taskResources, "", DEFAULT_EXECUTOR_ID);
-
- vector<TaskInfo> tasks;
- tasks.push_back(task);
-
- Future<TaskStatus> status;
- EXPECT_CALL(sched, statusUpdate(&driver, _))
- .WillOnce(FutureArg<1>(&status));
-
- driver.launchTasks(offer.id(), tasks);
-
- AWAIT_READY(status);
- EXPECT_EQ(task.task_id(), status.get().task_id());
- EXPECT_EQ(TASK_ERROR, status.get().state());
- EXPECT_EQ(TaskStatus::REASON_TASK_INVALID, status.get().reason());
- EXPECT_TRUE(status.get().has_message());
- EXPECT_TRUE(strings::contains(
- status.get().message(),
- "Task uses duplicated persistence ID 1"));
-
- driver.stop();
- driver.join();
-
- Shutdown();
-}
-
-
// This test ensures that a persistent volume that is larger than the
// offered disk resources results in a failed task.
TEST_F(TaskValidationTest, DISABLED_AcquirePersistentDiskTooBig)