Added an example Docker framework for testing.
Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/e66eab2c Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/e66eab2c Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/e66eab2c Branch: refs/heads/master Commit: e66eab2cbb34d86fd2111b935388689c775ef02e Parents: a5d683b Author: Benjamin Hindman <[email protected]> Authored: Tue Jul 8 14:45:42 2014 -0700 Committer: Benjamin Hindman <[email protected]> Committed: Mon Aug 4 15:08:17 2014 -0700 ---------------------------------------------------------------------- src/Makefile.am | 5 + src/examples/docker_no_executor_framework.cpp | 222 +++++++++++++++++++++ 2 files changed, 227 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/e66eab2c/src/Makefile.am ---------------------------------------------------------------------- diff --git a/src/Makefile.am b/src/Makefile.am index e5b26df..d0b3285 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1020,6 +1020,11 @@ no_executor_framework_SOURCES = examples/no_executor_framework.cpp no_executor_framework_CPPFLAGS = $(MESOS_CPPFLAGS) no_executor_framework_LDADD = libmesos.la +check_PROGRAMS += docker-no-executor-framework +docker_no_executor_framework_SOURCES = examples/docker_no_executor_framework.cpp +docker_no_executor_framework_CPPFLAGS = $(MESOS_CPPFLAGS) +docker_no_executor_framework_LDADD = libmesos.la + check_PROGRAMS += balloon-framework balloon_framework_SOURCES = examples/balloon_framework.cpp balloon_framework_CPPFLAGS = $(MESOS_CPPFLAGS) http://git-wip-us.apache.org/repos/asf/mesos/blob/e66eab2c/src/examples/docker_no_executor_framework.cpp ---------------------------------------------------------------------- diff --git a/src/examples/docker_no_executor_framework.cpp b/src/examples/docker_no_executor_framework.cpp new file mode 100644 index 0000000..d64c23b --- /dev/null +++ b/src/examples/docker_no_executor_framework.cpp @@ -0,0 +1,222 @@ +/** + * 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 <libgen.h> + +#include <iostream> +#include <string> + +#include <boost/lexical_cast.hpp> + +#include <mesos/scheduler.hpp> + +#include <stout/exit.hpp> +#include <stout/os.hpp> + +using namespace mesos; + +using boost::lexical_cast; + +using std::cout; +using std::cerr; +using std::endl; +using std::flush; +using std::string; +using std::vector; + +const int32_t CPUS_PER_TASK = 1; +const int32_t MEM_PER_TASK = 32; + +class DockerNoExecutorScheduler : public Scheduler +{ +public: + DockerNoExecutorScheduler() + : tasksLaunched(0), tasksFinished(0), totalTasks(5) {} + + virtual ~DockerNoExecutorScheduler() {} + + virtual void registered(SchedulerDriver*, + const FrameworkID&, + const MasterInfo&) + { + cout << "Registered!" << endl; + } + + virtual void reregistered(SchedulerDriver*, const MasterInfo& masterInfo) {} + + virtual void disconnected(SchedulerDriver* driver) {} + + virtual void resourceOffers(SchedulerDriver* driver, + const vector<Offer>& offers) + { + cout << "." << flush; + for (size_t i = 0; i < offers.size(); i++) { + const Offer& offer = offers[i]; + + // Lookup resources we care about. + // TODO(benh): It would be nice to ultimately have some helper + // functions for looking up resources. + double cpus = 0; + double mem = 0; + + for (int i = 0; i < offer.resources_size(); i++) { + const Resource& resource = offer.resources(i); + if (resource.name() == "cpus" && + resource.type() == Value::SCALAR) { + cpus = resource.scalar().value(); + } else if (resource.name() == "mem" && + resource.type() == Value::SCALAR) { + mem = resource.scalar().value(); + } + } + + // Launch tasks. + vector<TaskInfo> tasks; + while (tasksLaunched < totalTasks && + cpus >= CPUS_PER_TASK && + mem >= MEM_PER_TASK) { + int taskId = tasksLaunched++; + + cout << "Starting task " << taskId << " on " + << offer.hostname() << endl; + + TaskInfo task; + task.set_name("Task " + lexical_cast<string>(taskId)); + task.mutable_task_id()->set_value(lexical_cast<string>(taskId)); + task.mutable_slave_id()->MergeFrom(offer.slave_id()); + task.mutable_command()->set_value("echo hello"); + + // Use Docker to run the task. + CommandInfo::ContainerInfo* container = + task.mutable_command()->mutable_container(); + container->set_image("docker://ubuntu"); + + Resource* resource; + + resource = task.add_resources(); + resource->set_name("cpus"); + resource->set_type(Value::SCALAR); + resource->mutable_scalar()->set_value(CPUS_PER_TASK); + + resource = task.add_resources(); + resource->set_name("mem"); + resource->set_type(Value::SCALAR); + resource->mutable_scalar()->set_value(MEM_PER_TASK); + + tasks.push_back(task); + + cpus -= CPUS_PER_TASK; + mem -= MEM_PER_TASK; + } + + driver->launchTasks(offer.id(), tasks); + } + } + + virtual void offerRescinded(SchedulerDriver* driver, + const OfferID& offerId) {} + + virtual void statusUpdate(SchedulerDriver* driver, const TaskStatus& status) + { + int taskId = lexical_cast<int>(status.task_id().value()); + + cout << "Task " << taskId << " is in state " << status.state() << endl; + + if (status.state() == TASK_FINISHED) + tasksFinished++; + + if (tasksFinished == totalTasks) + driver->stop(); + } + + virtual void frameworkMessage(SchedulerDriver* driver, + const ExecutorID& executorId, + const SlaveID& slaveId, + const string& data) {} + + virtual void slaveLost(SchedulerDriver* driver, const SlaveID& slaveId) {} + + virtual void executorLost(SchedulerDriver* driver, + const ExecutorID& executorId, + const SlaveID& slaveId, + int status) {} + + virtual void error(SchedulerDriver* driver, const string& message) {} + +private: + int tasksLaunched; + int tasksFinished; + int totalTasks; +}; + + +int main(int argc, char** argv) +{ + if (argc != 2) { + cerr << "Usage: " << argv[0] << " <master>" << endl; + return -1; + } + + DockerNoExecutorScheduler scheduler; + + FrameworkInfo framework; + framework.set_user(""); // Have Mesos fill in the current user. + framework.set_name("No Executor Framework (C++)"); + + // TODO(vinod): Make checkpointing the default when it is default + // on the slave. + if (os::hasenv("MESOS_CHECKPOINT")) { + cout << "Enabling checkpoint for the framework" << endl; + framework.set_checkpoint(true); + } + + MesosSchedulerDriver* driver; + if (os::hasenv("MESOS_AUTHENTICATE")) { + cout << "Enabling authentication for the framework" << endl; + + if (!os::hasenv("DEFAULT_PRINCIPAL")) { + EXIT(1) << "Expecting authentication principal in the environment"; + } + + if (!os::hasenv("DEFAULT_SECRET")) { + EXIT(1) << "Expecting authentication secret in the environment"; + } + + Credential credential; + credential.set_principal(getenv("DEFAULT_PRINCIPAL")); + credential.set_secret(getenv("DEFAULT_SECRET")); + + framework.set_principal(getenv("DEFAULT_PRINCIPAL")); + + driver = new MesosSchedulerDriver( + &scheduler, framework, argv[1], credential); + } else { + framework.set_principal("no-executor-framework-cpp"); + + driver = new MesosSchedulerDriver( + &scheduler, framework, argv[1]); + } + + int status = driver->run() == DRIVER_STOPPED ? 0 : 1; + + // Ensure that the driver process terminates. + driver->stop(); + + delete driver; + return status; +}
