You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by vi...@apache.org on 2016/03/11 22:56:38 UTC
[2/3] mesos git commit: New python lib with only the executor driver.
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.hpp b/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.hpp
deleted file mode 100644
index 8c98d46..0000000
--- a/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.hpp
+++ /dev/null
@@ -1,134 +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_SCHEDULER_DRIVER_IMPL_HPP
-#define MESOS_SCHEDULER_DRIVER_IMPL_HPP
-
-#include <mesos/scheduler.hpp>
-
-
-namespace mesos { namespace python {
-
-class ProxyScheduler;
-
-/**
- * Python object structure for MesosSchedulerDriverImpl objects.
- */
-struct MesosSchedulerDriverImpl {
- PyObject_HEAD
- /* Type-specific fields go here. */
- MesosSchedulerDriver* driver;
- ProxyScheduler* proxyScheduler;
- PyObject* pythonScheduler;
-};
-
-/**
- * Python type object for MesosSchedulerDriverImpl.
- */
-extern PyTypeObject MesosSchedulerDriverImplType;
-
-/**
- * List of Python methods in MesosSchedulerDriverImpl.
- */
-extern PyMethodDef MesosSchedulerDriverImpl_methods[];
-
-/**
- * Create, but don't initialize, a new MesosSchedulerDriverImpl
- * (called by Python before init method).
- */
-PyObject* MesosSchedulerDriverImpl_new(PyTypeObject *type,
- PyObject *args,
- PyObject *kwds);
-
-/**
- * Initialize a MesosSchedulerDriverImpl with constructor arguments.
- */
-int MesosSchedulerDriverImpl_init(MesosSchedulerDriverImpl *self,
- PyObject *args,
- PyObject *kwds);
-
-/**
- * Free a MesosSchedulerDriverImpl.
- */
-void MesosSchedulerDriverImpl_dealloc(MesosSchedulerDriverImpl* self);
-
-/**
- * Traverse fields of a MesosSchedulerDriverImpl on a cyclic GC search.
- * See http://docs.python.org/extending/newtypes.html.
- */
-int MesosSchedulerDriverImpl_traverse(MesosSchedulerDriverImpl* self,
- visitproc visit,
- void* arg);
-/**
- * Clear fields of a MesosSchedulerDriverImpl that can participate in
- * GC cycles. See http://docs.python.org/extending/newtypes.html.
- */
-int MesosSchedulerDriverImpl_clear(MesosSchedulerDriverImpl* self);
-
-// MesosSchedulerDriverImpl methods.
-PyObject* MesosSchedulerDriverImpl_start(MesosSchedulerDriverImpl* self);
-
-PyObject* MesosSchedulerDriverImpl_stop(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_abort(MesosSchedulerDriverImpl* self);
-
-PyObject* MesosSchedulerDriverImpl_join(MesosSchedulerDriverImpl* self);
-
-PyObject* MesosSchedulerDriverImpl_run(MesosSchedulerDriverImpl* self);
-
-PyObject* MesosSchedulerDriverImpl_requestResources(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_launchTasks(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_killTask(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_acceptOffers(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_declineOffer(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_reviveOffers(MesosSchedulerDriverImpl* self);
-
-PyObject* MesosSchedulerDriverImpl_suppressOffers(
- MesosSchedulerDriverImpl* self);
-
-PyObject* MesosSchedulerDriverImpl_acknowledgeStatusUpdate(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_sendFrameworkMessage(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_reconcileTasks(
- MesosSchedulerDriverImpl* self,
- PyObject* args);
-
-} // namespace python {
-} // namespace mesos {
-
-#endif /* MESOS_SCHEDULER_DRIVER_IMPL_HPP */
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native/src/mesos/native/module.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/module.cpp b/src/python/native/src/mesos/native/module.cpp
deleted file mode 100644
index 9237361..0000000
--- a/src/python/native/src/mesos/native/module.cpp
+++ /dev/null
@@ -1,100 +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.
-
-/**
- * This file defines the _mesos.so binary module used by the Mesos Python API.
- * This module contains private implementations of MesosSchedulerDriver and
- * MesosExecutorDriver as Python types that get called from the public module
- * called mesos (in <root>/src/python/src/mesos.py). This design was chosen
- * so that most of the API (e.g. the Scheduler and Executor interfaces) can
- * be written in Python, and only the parts that need to call into C++ are
- * in C++. Note that the mesos module also contains public classes called
- * MesosSchedulerDriver and MesosExecutorDriver. These call into the private
- * _mesos.MesosSchedulerDriverImpl and _mesos.MesosExecutorDriverImpl.
- */
-
-// Python.h must be included before standard headers.
-// See: http://docs.python.org/2/c-api/intro.html#include-files
-#include <Python.h>
-
-#include <iostream>
-
-#include <mesos/executor.hpp>
-#include <mesos/scheduler.hpp>
-
-#include "module.hpp"
-#include "proxy_scheduler.hpp"
-#include "mesos_scheduler_driver_impl.hpp"
-#include "proxy_executor.hpp"
-#include "mesos_executor_driver_impl.hpp"
-
-using namespace mesos;
-using namespace mesos::python;
-
-using std::string;
-using std::vector;
-using std::map;
-
-
-/**
- * The Python module object for mesos_pb2 (which contains the protobuf
- * classes generated for Python).
- */
-PyObject* mesos::python::mesos_pb2 = NULL;
-
-
-namespace {
-
-/**
- * Method list for our Python module.
- */
-PyMethodDef MODULE_METHODS[] = {
- {NULL, NULL, 0, NULL} /* Sentinel */
-};
-
-} // namespace {
-
-
-/**
- * Entry point called by Python to initialize our module.
- */
-PyMODINIT_FUNC init_mesos()
-{
- // Ensure that the interpreter's threading support is enabled.
- PyEval_InitThreads();
-
- // Import the mesos_pb2 module (on which we depend for protobuf classes)
- mesos_pb2 = PyImport_ImportModule("mesos.interface.mesos_pb2");
- if (mesos_pb2 == NULL)
- return;
-
- // Initialize our Python types.
- if (PyType_Ready(&MesosSchedulerDriverImplType) < 0)
- return;
- if (PyType_Ready(&MesosExecutorDriverImplType) < 0)
- return;
-
- // Create the _mesos module and add our types to it.
- PyObject* module = Py_InitModule("_mesos", MODULE_METHODS);
- Py_INCREF(&MesosSchedulerDriverImplType);
- PyModule_AddObject(module,
- "MesosSchedulerDriverImpl",
- (PyObject*) &MesosSchedulerDriverImplType);
- Py_INCREF(&MesosExecutorDriverImplType);
- PyModule_AddObject(module,
- "MesosExecutorDriverImpl",
- (PyObject*) &MesosExecutorDriverImplType);
-}
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native/src/mesos/native/module.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/module.hpp b/src/python/native/src/mesos/native/module.hpp
deleted file mode 100644
index 2cf7b57..0000000
--- a/src/python/native/src/mesos/native/module.hpp
+++ /dev/null
@@ -1,136 +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 MODULE_HPP
-#define MODULE_HPP
-
-// Python.h must be included before standard headers.
-// See: http://docs.python.org/2/c-api/intro.html#include-files
-#include <Python.h>
-
-#include <iostream>
-
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-
-
-namespace mesos { namespace python {
-
-/**
- * The Python module object for mesos_pb2 (which contains the protobuf
- * classes generated for Python).
- */
-extern PyObject* mesos_pb2;
-
-
-/**
- * RAII utility class for acquiring the Python global interpreter lock.
- */
-class InterpreterLock {
- PyGILState_STATE state;
-
-public:
- InterpreterLock() {
- state = PyGILState_Ensure();
- }
-
- ~InterpreterLock() {
- PyGILState_Release(state);
- }
-};
-
-
-/**
- * Convert a Python protocol buffer object into a C++ one by serializing
- * it to a string and deserializing the result back in C++. Returns true
- * on success, or prints an error and returns false on failure.
- */
-template <typename T>
-bool readPythonProtobuf(PyObject* obj, T* t)
-{
- if (obj == Py_None) {
- std::cerr << "None object given where protobuf expected" << std::endl;
- return false;
- }
- PyObject* res = PyObject_CallMethod(obj,
- (char*) "SerializeToString",
- (char*) NULL);
- if (res == NULL) {
- std::cerr << "Failed to call Python object's SerializeToString "
- << "(perhaps it is not a protobuf?)" << std::endl;
- PyErr_Print();
- return false;
- }
- char* chars;
- Py_ssize_t len;
- if (PyString_AsStringAndSize(res, &chars, &len) < 0) {
- std::cerr << "SerializeToString did not return a string" << std::endl;
- PyErr_Print();
- Py_DECREF(res);
- return false;
- }
- google::protobuf::io::ArrayInputStream stream(chars, len);
- bool success = t->ParseFromZeroCopyStream(&stream);
- if (!success) {
- std::cerr << "Could not deserialize protobuf as expected type" << std::endl;
- }
- Py_DECREF(res);
- return success;
-}
-
-
-/**
- * Convert a C++ protocol buffer object into a Python one by serializing
- * it to a string and deserializing the result back in Python. Returns the
- * resulting PyObject* on success or raises a Python exception and returns
- * NULL on failure.
- */
-template <typename T>
-PyObject* createPythonProtobuf(const T& t, const char* typeName)
-{
- PyObject* dict = PyModule_GetDict(mesos_pb2);
- if (dict == NULL) {
- PyErr_Format(PyExc_Exception, "PyModule_GetDict failed");
- return NULL;
- }
-
- PyObject* type = PyDict_GetItemString(dict, typeName);
- if (type == NULL) {
- PyErr_Format(PyExc_Exception, "Could not resolve mesos_pb2.%s", typeName);
- return NULL;
- }
- if (!PyType_Check(type)) {
- PyErr_Format(PyExc_Exception, "mesos_pb2.%s is not a type", typeName);
- return NULL;
- }
-
- std::string str;
- if (!t.SerializeToString(&str)) {
- PyErr_Format(PyExc_Exception, "C++ %s SerializeToString failed", typeName);
- return NULL;
- }
-
- // Propagates any exception that might happen in FromString.
- return PyObject_CallMethod(type,
- (char*) "FromString",
- (char*) "s#",
- str.data(),
- str.size());
-}
-
-} // namespace python {
-} // namespace mesos {
-
-#endif /* MODULE_HPP */
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native/src/mesos/native/proxy_executor.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/proxy_executor.cpp b/src/python/native/src/mesos/native/proxy_executor.cpp
deleted file mode 100644
index 706f417..0000000
--- a/src/python/native/src/mesos/native/proxy_executor.cpp
+++ /dev/null
@@ -1,273 +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.
-
-// Python.h must be included before standard headers.
-// See: http://docs.python.org/2/c-api/intro.html#include-files
-#include <Python.h>
-
-#include <iostream>
-
-#include "proxy_executor.hpp"
-#include "module.hpp"
-#include "mesos_executor_driver_impl.hpp"
-
-using namespace mesos;
-
-using std::cerr;
-using std::endl;
-using std::string;
-using std::vector;
-using std::map;
-
-namespace mesos {
-namespace python {
-
-void ProxyExecutor::registered(ExecutorDriver* driver,
- const ExecutorInfo& executorInfo,
- const FrameworkInfo& frameworkInfo,
- const SlaveInfo& slaveInfo)
-{
- InterpreterLock lock;
-
- PyObject* executorInfoObj = NULL;
- PyObject* frameworkInfoObj = NULL;
- PyObject* slaveInfoObj = NULL;
- PyObject* res = NULL;
-
- executorInfoObj = createPythonProtobuf(executorInfo, "ExecutorInfo");
- frameworkInfoObj = createPythonProtobuf(frameworkInfo, "FrameworkInfo");
- slaveInfoObj = createPythonProtobuf(slaveInfo, "SlaveInfo");
-
- if (executorInfoObj == NULL ||
- frameworkInfoObj == NULL ||
- slaveInfoObj == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "registered",
- (char*) "OOOO",
- impl,
- executorInfoObj,
- frameworkInfoObj,
- slaveInfoObj);
- if (res == NULL) {
- cerr << "Failed to call executor registered" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(executorInfoObj);
- Py_XDECREF(frameworkInfoObj);
- Py_XDECREF(slaveInfoObj);
- Py_XDECREF(res);
-}
-
-
-void ProxyExecutor::reregistered(ExecutorDriver* driver,
- const SlaveInfo& slaveInfo)
-{
- InterpreterLock lock;
-
- PyObject* slaveInfoObj = NULL;
- PyObject* res = NULL;
-
- slaveInfoObj = createPythonProtobuf(slaveInfo, "SlaveInfo");
-
- if (slaveInfoObj == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "reregistered",
- (char*) "OO",
- impl,
- slaveInfoObj);
- if (res == NULL) {
- cerr << "Failed to call executor re-registered" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(slaveInfoObj);
- Py_XDECREF(res);
-}
-
-
-void ProxyExecutor::disconnected(ExecutorDriver* driver)
-{
- InterpreterLock lock;
- PyObject* res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "disconnected",
- (char*) "O",
- impl);
- if (res == NULL) {
- cerr << "Failed to call executor's disconnected" << endl;
- goto cleanup;
- }
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(res);
-}
-
-
-void ProxyExecutor::launchTask(ExecutorDriver* driver,
- const TaskInfo& task)
-{
- InterpreterLock lock;
-
- PyObject* taskObj = NULL;
- PyObject* res = NULL;
-
- taskObj = createPythonProtobuf(task, "TaskInfo");
- if (taskObj == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "launchTask",
- (char*) "OO",
- impl,
- taskObj);
- if (res == NULL) {
- cerr << "Failed to call executor's launchTask" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(taskObj);
- Py_XDECREF(res);
-}
-
-
-void ProxyExecutor::killTask(ExecutorDriver* driver,
- const TaskID& taskId)
-{
- InterpreterLock lock;
-
- PyObject* taskIdObj = NULL;
- PyObject* res = NULL;
-
- taskIdObj = createPythonProtobuf(taskId, "TaskID");
- if (taskIdObj == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "killTask",
- (char*) "OO",
- impl,
- taskIdObj);
- if (res == NULL) {
- cerr << "Failed to call executor's killTask" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(taskIdObj);
- Py_XDECREF(res);
-}
-
-
-void ProxyExecutor::frameworkMessage(ExecutorDriver* driver,
- const string& data)
-{
- InterpreterLock lock;
-
- PyObject* res = NULL;
-
- res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "frameworkMessage",
- (char*) "Os#",
- impl,
- data.data(),
- data.length());
- if (res == NULL) {
- cerr << "Failed to call executor's frameworkMessage" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(res);
-}
-
-
-void ProxyExecutor::shutdown(ExecutorDriver* driver)
-{
- InterpreterLock lock;
- PyObject* res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "shutdown",
- (char*) "O",
- impl);
- if (res == NULL) {
- cerr << "Failed to call executor's shutdown" << endl;
- goto cleanup;
- }
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(res);
-}
-
-
-void ProxyExecutor::error(ExecutorDriver* driver, const string& message)
-{
- InterpreterLock lock;
- PyObject* res = PyObject_CallMethod(impl->pythonExecutor,
- (char*) "error",
- (char*) "Os#",
- impl,
- message.data(),
- message.length());
- if (res == NULL) {
- cerr << "Failed to call executor's error" << endl;
- goto cleanup;
- }
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- // No need for driver.stop(); it should stop itself.
- }
- Py_XDECREF(res);
-}
-
-} // namespace python {
-} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native/src/mesos/native/proxy_executor.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/proxy_executor.hpp b/src/python/native/src/mesos/native/proxy_executor.hpp
deleted file mode 100644
index 23d64fd..0000000
--- a/src/python/native/src/mesos/native/proxy_executor.hpp
+++ /dev/null
@@ -1,64 +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 PROXY_EXECUTOR_HPP
-#define PROXY_EXECUTOR_HPP
-
-// Python.h must be included before standard headers.
-// See: http://docs.python.org/2/c-api/intro.html#include-files
-#include <Python.h>
-
-#include <string>
-#include <vector>
-
-#include <mesos/executor.hpp>
-
-namespace mesos {
-namespace python {
-
-struct MesosExecutorDriverImpl;
-
-/**
- * Proxy Executor implementation that will call into Python.
- */
-class ProxyExecutor : public Executor
-{
-public:
- explicit ProxyExecutor(MesosExecutorDriverImpl *_impl) : impl(_impl) {}
-
- virtual ~ProxyExecutor() {}
-
- virtual void registered(ExecutorDriver* driver,
- const ExecutorInfo& executorInfo,
- const FrameworkInfo& frameworkInfo,
- const SlaveInfo& slaveInfo);
- virtual void reregistered(ExecutorDriver* driver, const SlaveInfo& slaveInfo);
- virtual void disconnected(ExecutorDriver* driver);
- virtual void launchTask(ExecutorDriver* driver, const TaskInfo& task);
- virtual void killTask(ExecutorDriver* driver, const TaskID& taskId);
- virtual void frameworkMessage(ExecutorDriver* driver,
- const std::string& data);
- virtual void shutdown(ExecutorDriver* driver);
- virtual void error(ExecutorDriver* driver, const std::string& message);
-
-private:
- MesosExecutorDriverImpl *impl;
-};
-
-} // namespace python {
-} // namespace mesos {
-
-#endif // PROXY_EXECUTOR_HPP
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native/src/mesos/native/proxy_scheduler.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/proxy_scheduler.cpp b/src/python/native/src/mesos/native/proxy_scheduler.cpp
deleted file mode 100644
index 8afb338..0000000
--- a/src/python/native/src/mesos/native/proxy_scheduler.cpp
+++ /dev/null
@@ -1,384 +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.
-
-// Python.h must be included before standard headers.
-// See: http://docs.python.org/2/c-api/intro.html#include-files
-#include <Python.h>
-
-#include <iostream>
-
-#include "proxy_scheduler.hpp"
-#include "module.hpp"
-#include "mesos_scheduler_driver_impl.hpp"
-
-using namespace mesos;
-
-using std::cerr;
-using std::endl;
-using std::string;
-using std::vector;
-using std::map;
-
-namespace mesos {
-namespace python {
-
-void ProxyScheduler::registered(SchedulerDriver* driver,
- const FrameworkID& frameworkId,
- const MasterInfo& masterInfo)
-{
- InterpreterLock lock;
-
- PyObject* fid = NULL;
- PyObject* minfo = NULL;
- PyObject* res = NULL;
-
- fid = createPythonProtobuf(frameworkId, "FrameworkID");
- if (fid == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- minfo = createPythonProtobuf(masterInfo, "MasterInfo");
- if (minfo == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "registered",
- (char*) "OOO",
- impl,
- fid,
- minfo);
- if (res == NULL) {
- cerr << "Failed to call scheduler's registered" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(fid);
- Py_XDECREF(minfo);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::reregistered(SchedulerDriver* driver,
- const MasterInfo& masterInfo)
-{
- InterpreterLock lock;
-
- PyObject* minfo = NULL;
- PyObject* res = NULL;
-
- minfo = createPythonProtobuf(masterInfo, "MasterInfo");
- if (minfo == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "reregistered",
- (char*) "OO",
- impl,
- minfo);
- if (res == NULL) {
- cerr << "Failed to call scheduler's reregistered" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(minfo);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::disconnected(SchedulerDriver* driver)
-{
- InterpreterLock lock;
-
- PyObject* res = NULL;
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "disconnected",
- (char*) "O",
- impl);
- if (res == NULL) {
- cerr << "Failed to call scheduler's disconnected" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::resourceOffers(SchedulerDriver* driver,
- const vector<Offer>& offers)
-{
- InterpreterLock lock;
-
- PyObject* list = NULL;
- PyObject* res = NULL;
-
- list = PyList_New(offers.size());
- if (list == NULL) {
- goto cleanup;
- }
- for (size_t i = 0; i < offers.size(); i++) {
- PyObject* offer = createPythonProtobuf(offers[i], "Offer");
- if (offer == NULL) {
- goto cleanup;
- }
- PyList_SetItem(list, i, offer); // Steals the reference to offer.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "resourceOffers",
- (char*) "OO",
- impl,
- list);
-
- if (res == NULL) {
- cerr << "Failed to call scheduler's resourceOffer" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(list);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::offerRescinded(SchedulerDriver* driver,
- const OfferID& offerId)
-{
- InterpreterLock lock;
-
- PyObject* oid = NULL;
- PyObject* res = NULL;
-
- oid = createPythonProtobuf(offerId, "OfferID");
- if (oid == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "offerRescinded",
- (char*) "OO",
- impl,
- oid);
- if (res == NULL) {
- cerr << "Failed to call scheduler's offerRescinded" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(oid);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::statusUpdate(SchedulerDriver* driver,
- const TaskStatus& status)
-{
- InterpreterLock lock;
-
- PyObject* stat = NULL;
- PyObject* res = NULL;
-
- stat = createPythonProtobuf(status, "TaskStatus");
- if (stat == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "statusUpdate",
- (char*) "OO",
- impl,
- stat);
- if (res == NULL) {
- cerr << "Failed to call scheduler's statusUpdate" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(stat);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::frameworkMessage(SchedulerDriver* driver,
- const ExecutorID& executorId,
- const SlaveID& slaveId,
- const string& data)
-{
- InterpreterLock lock;
-
- PyObject* eid = NULL;
- PyObject* sid = NULL;
- PyObject* res = NULL;
-
- eid = createPythonProtobuf(executorId, "ExecutorID");
- if (eid == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- sid = createPythonProtobuf(slaveId, "SlaveID");
- if (sid == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "frameworkMessage",
- (char*) "OOOs#",
- impl,
- eid,
- sid,
- data.data(),
- data.length());
- if (res == NULL) {
- cerr << "Failed to call scheduler's frameworkMessage" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(eid);
- Py_XDECREF(sid);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::slaveLost(SchedulerDriver* driver, const SlaveID& slaveId)
-{
- InterpreterLock lock;
-
- PyObject* sid = NULL;
- PyObject* res = NULL;
-
- sid = createPythonProtobuf(slaveId, "SlaveID");
- if (sid == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "slaveLost",
- (char*) "OO",
- impl,
- sid);
- if (res == NULL) {
- cerr << "Failed to call scheduler's slaveLost" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(sid);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::executorLost(SchedulerDriver* driver,
- const ExecutorID& executorId,
- const SlaveID& slaveId,
- int status)
-{
- InterpreterLock lock;
-
- PyObject* executorIdObj = NULL;
- PyObject* slaveIdObj = NULL;
- PyObject* res = NULL;
-
- executorIdObj = createPythonProtobuf(executorId, "ExecutorID");
- slaveIdObj = createPythonProtobuf(slaveId, "SlaveID");
-
- if (executorIdObj == NULL || slaveIdObj == NULL) {
- goto cleanup; // createPythonProtobuf will have set an exception.
- }
-
- res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "executorLost",
- (char*) "OOOi",
- impl,
- executorIdObj,
- slaveIdObj,
- status);
- if (res == NULL) {
- cerr << "Failed to call scheduler's executorLost" << endl;
- goto cleanup;
- }
-
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- driver->abort();
- }
- Py_XDECREF(executorIdObj);
- Py_XDECREF(slaveIdObj);
- Py_XDECREF(res);
-}
-
-
-void ProxyScheduler::error(SchedulerDriver* driver, const string& message)
-{
- InterpreterLock lock;
- PyObject* res = PyObject_CallMethod(impl->pythonScheduler,
- (char*) "error",
- (char*) "Os#",
- impl,
- message.data(),
- message.length());
- if (res == NULL) {
- cerr << "Failed to call scheduler's error" << endl;
- goto cleanup;
- }
-cleanup:
- if (PyErr_Occurred()) {
- PyErr_Print();
- // No need for driver.stop(); it should stop itself.
- }
- Py_XDECREF(res);
-}
-
-} // namespace python {
-} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native/src/mesos/native/proxy_scheduler.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/proxy_scheduler.hpp b/src/python/native/src/mesos/native/proxy_scheduler.hpp
deleted file mode 100644
index 895892a..0000000
--- a/src/python/native/src/mesos/native/proxy_scheduler.hpp
+++ /dev/null
@@ -1,72 +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 PROXY_SCHEDULER_HPP
-#define PROXY_SCHEDULER_HPP
-
-// Python.h must be included before standard headers.
-// See: http://docs.python.org/2/c-api/intro.html#include-files
-#include <Python.h>
-
-#include <string>
-#include <vector>
-
-#include <mesos/scheduler.hpp>
-
-namespace mesos {
-namespace python {
-
-struct MesosSchedulerDriverImpl;
-
-/**
- * Proxy Scheduler implementation that will call into Python.
- */
-class ProxyScheduler : public Scheduler
-{
-public:
- explicit ProxyScheduler(MesosSchedulerDriverImpl* _impl) : impl(_impl) {}
-
- virtual ~ProxyScheduler() {}
-
- virtual void registered(SchedulerDriver* driver,
- const FrameworkID& frameworkId,
- const MasterInfo& masterInfo);
- virtual void reregistered(SchedulerDriver* driver,
- const MasterInfo& masterInfo);
- virtual void disconnected(SchedulerDriver* driver);
- virtual void resourceOffers(SchedulerDriver* driver,
- const std::vector<Offer>& offers);
- virtual void offerRescinded(SchedulerDriver* driver, const OfferID& offerId);
- virtual void statusUpdate(SchedulerDriver* driver, const TaskStatus& status);
- virtual void frameworkMessage(SchedulerDriver* driver,
- const ExecutorID& executorId,
- const SlaveID& slaveId,
- const std::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 std::string& message);
-
-private:
- MesosSchedulerDriverImpl* impl;
-};
-
-} // namespace python {
-} // namespace mesos {
-
-#endif // PROXY_SCHEDULER_HPP
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native_common/common.hpp
----------------------------------------------------------------------
diff --git a/src/python/native_common/common.hpp b/src/python/native_common/common.hpp
new file mode 100644
index 0000000..166adb3
--- /dev/null
+++ b/src/python/native_common/common.hpp
@@ -0,0 +1,136 @@
+// 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_NATIVE_COMMON_HPP
+#define MESOS_NATIVE_COMMON_HPP
+
+// Python.h must be included before standard headers.
+// See: http://docs.python.org/2/c-api/intro.html#include-files
+#include <Python.h>
+
+#include <iostream>
+
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+
+namespace mesos { namespace python {
+
+/**
+ * The Python module object for mesos_pb2 (which contains the protobuf
+ * classes generated for Python).
+ */
+extern PyObject* mesos_pb2;
+
+
+/**
+ * RAII utility class for acquiring the Python global interpreter lock.
+ */
+class InterpreterLock {
+ PyGILState_STATE state;
+
+public:
+ InterpreterLock() {
+ state = PyGILState_Ensure();
+ }
+
+ ~InterpreterLock() {
+ PyGILState_Release(state);
+ }
+};
+
+
+/**
+ * Convert a Python protocol buffer object into a C++ one by serializing
+ * it to a string and deserializing the result back in C++. Returns true
+ * on success, or prints an error and returns false on failure.
+ */
+template <typename T>
+bool readPythonProtobuf(PyObject* obj, T* t)
+{
+ if (obj == Py_None) {
+ std::cerr << "None object given where protobuf expected" << std::endl;
+ return false;
+ }
+ PyObject* res = PyObject_CallMethod(obj,
+ (char*) "SerializeToString",
+ (char*) NULL);
+ if (res == NULL) {
+ std::cerr << "Failed to call Python object's SerializeToString "
+ << "(perhaps it is not a protobuf?)" << std::endl;
+ PyErr_Print();
+ return false;
+ }
+ char* chars;
+ Py_ssize_t len;
+ if (PyString_AsStringAndSize(res, &chars, &len) < 0) {
+ std::cerr << "SerializeToString did not return a string" << std::endl;
+ PyErr_Print();
+ Py_DECREF(res);
+ return false;
+ }
+ google::protobuf::io::ArrayInputStream stream(chars, len);
+ bool success = t->ParseFromZeroCopyStream(&stream);
+ if (!success) {
+ std::cerr << "Could not deserialize protobuf as expected type" << std::endl;
+ }
+ Py_DECREF(res);
+ return success;
+}
+
+
+/**
+ * Convert a C++ protocol buffer object into a Python one by serializing
+ * it to a string and deserializing the result back in Python. Returns the
+ * resulting PyObject* on success or raises a Python exception and returns
+ * NULL on failure.
+ */
+template <typename T>
+PyObject* createPythonProtobuf(const T& t, const char* typeName)
+{
+ PyObject* dict = PyModule_GetDict(mesos_pb2);
+ if (dict == NULL) {
+ PyErr_Format(PyExc_Exception, "PyModule_GetDict failed");
+ return NULL;
+ }
+
+ PyObject* type = PyDict_GetItemString(dict, typeName);
+ if (type == NULL) {
+ PyErr_Format(PyExc_Exception, "Could not resolve mesos_pb2.%s", typeName);
+ return NULL;
+ }
+ if (!PyType_Check(type)) {
+ PyErr_Format(PyExc_Exception, "mesos_pb2.%s is not a type", typeName);
+ return NULL;
+ }
+
+ std::string str;
+ if (!t.SerializeToString(&str)) {
+ PyErr_Format(PyExc_Exception, "C++ %s SerializeToString failed", typeName);
+ return NULL;
+ }
+
+ // Propagates any exception that might happen in FromString.
+ return PyObject_CallMethod(type,
+ (char*) "FromString",
+ (char*) "s#",
+ str.data(),
+ str.size());
+}
+
+} // namespace python {
+} // namespace mesos {
+
+#endif /* MESOS_NATIVE_COMMON_HPP */
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/native_common/ext_modules.py.in
----------------------------------------------------------------------
diff --git a/src/python/native_common/ext_modules.py.in b/src/python/native_common/ext_modules.py.in
new file mode 100644
index 0000000..0a005dc
--- /dev/null
+++ b/src/python/native_common/ext_modules.py.in
@@ -0,0 +1,154 @@
+# 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.
+
+import errno
+import glob
+import os
+import shutil
+
+from setuptools import Extension
+
+def _create_module(module_name):
+ abs_top_srcdir = '@abs_top_srcdir@'
+ abs_top_builddir = '@abs_top_builddir@'
+
+ ext_src_dir = os.path.join(
+ 'src', 'python', module_name, 'src', 'mesos', module_name)
+ ext_common_dir = os.path.join(
+ 'src', 'python', 'native_common')
+
+ leveldb = os.path.join('3rdparty', 'leveldb-1.4')
+ zookeeper = os.path.join('3rdparty', 'zookeeper-3.4.5', 'src', 'c')
+ libprocess = os.path.join('3rdparty', 'libprocess')
+
+ # Even though a statically compiled libprocess should include glog,
+ # libev, gperftools, and protobuf before installation this isn't the
+ # case, so while a libtool managed build will correctly pull in these
+ # libraries when building the final result, we need to explicitly
+ # include them here (or more precisely, down where we actually include
+ # libev.a and libprofiler.a).
+ glog = os.path.join(libprocess, '3rdparty', 'glog-0.3.3')
+ gperftools = os.path.join(libprocess, '3rdparty', 'gperftools-2.0')
+ protobuf = os.path.join(libprocess, '3rdparty', 'protobuf-2.5.0')
+
+ # Build the list of source files. Note that each source must be
+ # relative to our current directory (where this script lives).
+ SOURCES = [
+ os.path.join('src', 'mesos', module_name, file)
+ for file in os.listdir(os.path.join(abs_top_srcdir, ext_src_dir))
+ if file.endswith('.cpp')
+ ]
+
+ INCLUDE_DIRS = [
+ os.path.join(abs_top_srcdir, 'include'),
+ os.path.join(abs_top_builddir, 'include'),
+ # Needed for the *.pb.h protobuf includes.
+ os.path.join(abs_top_builddir, 'include', 'mesos'),
+ os.path.join(abs_top_builddir, 'src'),
+ os.path.join(abs_top_builddir, ext_src_dir),
+ os.path.join(abs_top_builddir, ext_common_dir),
+ os.path.join(abs_top_builddir, protobuf, 'src'),
+ ]
+
+ LIBRARY_DIRS = []
+
+ EXTRA_OBJECTS = [
+ os.path.join(abs_top_builddir, 'src', '.libs', 'libmesos_no_3rdparty.a'),
+ os.path.join(abs_top_builddir, libprocess, '.libs', 'libprocess.a')
+ ]
+
+ # For leveldb, we need to check for the presence of libleveldb.a, since
+ # it is possible to disable leveldb inside mesos.
+ libglog = os.path.join(abs_top_builddir, glog, '.libs', 'libglog.a')
+ libleveldb = os.path.join(abs_top_builddir, leveldb, 'libleveldb.a')
+ libzookeeper = os.path.join(
+ abs_top_builddir, zookeeper, '.libs', 'libzookeeper_mt.a')
+ libprotobuf = os.path.join(
+ abs_top_builddir, protobuf, 'src', '.libs', 'libprotobuf.a')
+
+ if os.path.exists(libleveldb):
+ EXTRA_OBJECTS.append(libleveldb)
+ else:
+ EXTRA_OBJECTS.append('-lleveldb')
+
+ if os.path.exists(libzookeeper):
+ EXTRA_OBJECTS.append(libzookeeper)
+ else:
+ EXTRA_OBJECTS.append('-lzookeeper_mt')
+
+ if os.path.exists(libglog):
+ EXTRA_OBJECTS.append(libglog)
+ else:
+ EXTRA_OBJECTS.append('-lglog')
+
+ if os.path.exists(libprotobuf):
+ EXTRA_OBJECTS.append(libprotobuf)
+ else:
+ EXTRA_OBJECTS.append('-lprotobuf')
+
+
+ # libev is a special case because it needs to be enabled only when
+ # libevent *is not* enabled through the top level ./configure.
+ #
+ # TODO(hartem): this entire block MUST be removed once libev is deprecated
+ # in favor of libevent.
+ if '@ENABLE_LIBEVENT_TRUE@' == '#':
+ libev = os.path.join(libprocess, '3rdparty', 'libev-4.15')
+ libev = os.path.join(abs_top_builddir, libev, '.libs', 'libev.a')
+
+ if os.path.exists(libev):
+ EXTRA_OBJECTS.append(libev)
+ else:
+ EXTRA_OBJECTS.append('-lev')
+
+
+ # For gperftools, we need to check for the presence of libprofiler.a, since
+ # it is possible to disable perftools inside libprocess.
+ libprofiler = os.path.join(
+ abs_top_builddir, gperftools, '.libs', 'libprofiler.a')
+
+ if os.path.exists(libprofiler):
+ EXTRA_OBJECTS.append(libprofiler)
+
+ EXTRA_LINK_ARGS = ['-Wl,--as-needed']
+
+ # Add any flags from LDFLAGS.
+ if 'LDFLAGS' in os.environ:
+ for flag in os.environ['LDFLAGS'].split():
+ EXTRA_LINK_ARGS.append(flag)
+
+ # Add any libraries from LIBS.
+ if 'LIBS' in os.environ:
+ for library in os.environ['LIBS'].split():
+ EXTRA_LINK_ARGS.append(library)
+
+ # Note that we add EXTRA_OBJECTS to our dependency list to make sure
+ # that we rebuild this module when one of them changes (e.g.,
+ # libprocess).
+ mesos_module = \
+ Extension('mesos.%s._%s' % (module_name, module_name),
+ sources = SOURCES,
+ include_dirs = INCLUDE_DIRS,
+ library_dirs = LIBRARY_DIRS,
+ extra_objects = EXTRA_OBJECTS,
+ extra_link_args = EXTRA_LINK_ARGS,
+ depends = EXTRA_OBJECTS,
+ language = 'c++',
+ )
+ return mesos_module
+
+executor_module = _create_module("executor")
+scheduler_module = _create_module("scheduler")
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/scheduler/setup.py.in
----------------------------------------------------------------------
diff --git a/src/python/scheduler/setup.py.in b/src/python/scheduler/setup.py.in
new file mode 100644
index 0000000..9475aad
--- /dev/null
+++ b/src/python/scheduler/setup.py.in
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+
+# 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.
+
+import ext_modules
+
+config = {
+ 'name': 'mesos.scheduler',
+ 'version': '@PACKAGE_VERSION@',
+ 'description': 'Mesos native scheduler driver implementation',
+ 'author': 'Apache Mesos',
+ 'author_email': 'dev@mesos.apache.org',
+ 'url': 'http://pypi.python.org/pypi/mesos.scheduler',
+ 'namespace_packages': [ 'mesos' ],
+ 'packages': [ 'mesos', 'mesos.scheduler' ],
+ 'package_dir': { '': 'src' },
+ 'install_requires': [ 'mesos.interface == @PACKAGE_VERSION@' ],
+ 'license': 'Apache 2.0',
+ 'keywords': 'mesos',
+ 'classifiers': [ ],
+ 'ext_modules': [ ext_modules.scheduler_module ]
+}
+
+from setuptools import setup
+setup(**config)
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/scheduler/src/mesos/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/scheduler/src/mesos/__init__.py b/src/python/scheduler/src/mesos/__init__.py
new file mode 100644
index 0000000..3fcba01
--- /dev/null
+++ b/src/python/scheduler/src/mesos/__init__.py
@@ -0,0 +1,10 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+# Because python does not normally allow the contents of a package to be
+# retrieved from more than one location, this code snippet ensures that the
+# namespace package machinery is operating and that the current package is
+# registered as a namespace package.
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ from pkgutil import extend_path
+ __path__ = extend_path(__path__, __name__)
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/scheduler/src/mesos/scheduler/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/scheduler/src/mesos/scheduler/__init__.py b/src/python/scheduler/src/mesos/scheduler/__init__.py
new file mode 100644
index 0000000..d043232
--- /dev/null
+++ b/src/python/scheduler/src/mesos/scheduler/__init__.py
@@ -0,0 +1,17 @@
+# 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.
+
+from ._scheduler import MesosSchedulerDriverImpl as MesosSchedulerDriver
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.cpp
----------------------------------------------------------------------
diff --git a/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.cpp b/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.cpp
new file mode 100644
index 0000000..a18a470
--- /dev/null
+++ b/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.cpp
@@ -0,0 +1,782 @@
+// 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.
+
+// Python.h must be included before standard headers.
+// See: http://docs.python.org/2/c-api/intro.html#include-files
+#include <Python.h>
+
+#include <string>
+
+#include "common.hpp"
+#include "mesos_scheduler_driver_impl.hpp"
+#include "proxy_scheduler.hpp"
+
+using namespace mesos;
+using namespace mesos::python;
+
+using std::cerr;
+using std::endl;
+using std::string;
+using std::vector;
+using std::map;
+
+namespace mesos {
+namespace python {
+
+/**
+ * Python type object for MesosSchedulerDriverImpl.
+ */
+PyTypeObject MesosSchedulerDriverImplType = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "_mesos.MesosSchedulerDriverImpl", /* tp_name */
+ sizeof(MesosSchedulerDriverImpl), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) MesosSchedulerDriverImpl_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
+ "Private MesosSchedulerDriver implementation", /* tp_doc */
+ (traverseproc) MesosSchedulerDriverImpl_traverse, /* tp_traverse */
+ (inquiry) MesosSchedulerDriverImpl_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ MesosSchedulerDriverImpl_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc) MesosSchedulerDriverImpl_init, /* tp_init */
+ 0, /* tp_alloc */
+ MesosSchedulerDriverImpl_new, /* tp_new */
+};
+
+
+/**
+ * List of Python methods in MesosSchedulerDriverImpl.
+ */
+PyMethodDef MesosSchedulerDriverImpl_methods[] = {
+ { "start",
+ (PyCFunction) MesosSchedulerDriverImpl_start,
+ METH_NOARGS,
+ "Start the driver to connect to Mesos"
+ },
+ { "stop",
+ (PyCFunction) MesosSchedulerDriverImpl_stop,
+ METH_VARARGS,
+ "Stop the driver, disconnecting from Mesos"
+ },
+ { "abort",
+ (PyCFunction) MesosSchedulerDriverImpl_abort,
+ METH_NOARGS,
+ "Abort the driver, disabling calls from and to the driver"
+ },
+ { "join",
+ (PyCFunction) MesosSchedulerDriverImpl_join,
+ METH_NOARGS,
+ "Wait for a running driver to disconnect from Mesos"
+ },
+ { "run",
+ (PyCFunction) MesosSchedulerDriverImpl_run,
+ METH_NOARGS,
+ "Start a driver and run it, returning when it disconnects from Mesos"
+ },
+ { "requestResources",
+ (PyCFunction) MesosSchedulerDriverImpl_requestResources,
+ METH_VARARGS,
+ "Request resources from the Mesos allocator"
+ },
+ { "launchTasks",
+ (PyCFunction) MesosSchedulerDriverImpl_launchTasks,
+ METH_VARARGS,
+ "Reply to a Mesos offer with a list of tasks"
+ },
+ { "killTask",
+ (PyCFunction) MesosSchedulerDriverImpl_killTask,
+ METH_VARARGS,
+ "Kill the task with the given ID"
+ },
+ { "acceptOffers",
+ (PyCFunction) MesosSchedulerDriverImpl_acceptOffers,
+ METH_VARARGS,
+ "Reply to a Mesos offer with a list of offer operations"
+ },
+ { "declineOffer",
+ (PyCFunction) MesosSchedulerDriverImpl_declineOffer,
+ METH_VARARGS,
+ "Decline a Mesos offer"
+ },
+ { "reviveOffers",
+ (PyCFunction) MesosSchedulerDriverImpl_reviveOffers,
+ METH_NOARGS,
+ "Remove all filters and ask Mesos for new offers"
+ },
+ { "suppressOffers",
+ (PyCFunction) MesosSchedulerDriverImpl_suppressOffers,
+ METH_NOARGS,
+ "Set suppressed attribute as true for the Framework"
+ },
+ { "acknowledgeStatusUpdate",
+ (PyCFunction) MesosSchedulerDriverImpl_acknowledgeStatusUpdate,
+ METH_VARARGS,
+ "Acknowledge a status update"
+ },
+ { "sendFrameworkMessage",
+ (PyCFunction) MesosSchedulerDriverImpl_sendFrameworkMessage,
+ METH_VARARGS,
+ "Send a FrameworkMessage to a slave"
+ },
+ { "reconcileTasks",
+ (PyCFunction) MesosSchedulerDriverImpl_reconcileTasks,
+ METH_VARARGS,
+ "Master sends status updates if task status is different from expected"
+ },
+ { NULL } /* Sentinel */
+};
+
+
+/**
+ * Create, but don't initialize, a new MesosSchedulerDriverImpl
+ * (called by Python before init method).
+ */
+PyObject* MesosSchedulerDriverImpl_new(PyTypeObject* type,
+ PyObject* args,
+ PyObject* kwds)
+{
+ MesosSchedulerDriverImpl* self;
+ self = (MesosSchedulerDriverImpl*) type->tp_alloc(type, 0);
+ if (self != NULL) {
+ self->driver = NULL;
+ self->proxyScheduler = NULL;
+ self->pythonScheduler = NULL;
+ }
+ return (PyObject*) self;
+}
+
+
+/**
+ * Initialize a MesosSchedulerDriverImpl with constructor arguments.
+ */
+int MesosSchedulerDriverImpl_init(MesosSchedulerDriverImpl* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ // Note: We use an integer for 'implicitAcknoweldgements' because
+ // it is the recommended way to pass booleans through CPython.
+ PyObject* schedulerObj = NULL;
+ PyObject* frameworkObj = NULL;
+ const char* master;
+ int implicitAcknowledgements = 1; // Enabled by default.
+ PyObject* credentialObj = NULL;
+
+ if (!PyArg_ParseTuple(
+ args,
+ "OOs|iO",
+ &schedulerObj,
+ &frameworkObj,
+ &master,
+ &implicitAcknowledgements,
+ &credentialObj)) {
+ return -1;
+ }
+
+ if (schedulerObj != NULL) {
+ PyObject* tmp = self->pythonScheduler;
+ Py_INCREF(schedulerObj);
+ self->pythonScheduler = schedulerObj;
+ Py_XDECREF(tmp);
+ }
+
+ FrameworkInfo framework;
+ if (frameworkObj != NULL) {
+ if (!readPythonProtobuf(frameworkObj, &framework)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python FrameworkInfo");
+ return -1;
+ }
+ }
+
+ Credential credential;
+ if (credentialObj != NULL) {
+ if (!readPythonProtobuf(credentialObj, &credential)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python Credential");
+ return -1;
+ }
+ }
+
+
+ if (self->driver != NULL) {
+ delete self->driver;
+ self->driver = NULL;
+ }
+
+ if (self->proxyScheduler != NULL) {
+ delete self->proxyScheduler;
+ self->proxyScheduler = NULL;
+ }
+
+ self->proxyScheduler = new ProxyScheduler(self);
+
+ if (credentialObj != NULL) {
+ self->driver = new MesosSchedulerDriver(
+ self->proxyScheduler,
+ framework,
+ master,
+ implicitAcknowledgements != 0,
+ credential);
+ } else {
+ self->driver = new MesosSchedulerDriver(
+ self->proxyScheduler,
+ framework,
+ master,
+ implicitAcknowledgements != 0);
+ }
+
+ return 0;
+}
+
+
+/**
+ * Free a MesosSchedulerDriverImpl.
+ */
+void MesosSchedulerDriverImpl_dealloc(MesosSchedulerDriverImpl* self)
+{
+ if (self->driver != NULL) {
+ // We need to wrap the driver destructor in an "allow threads"
+ // macro since the MesosSchedulerDriver destructor waits for the
+ // SchedulerProcess to terminate and there might be a thread that
+ // is trying to acquire the GIL to call through the
+ // ProxyScheduler. It will only be after this thread executes that
+ // the SchedulerProcess might actually get a terminate.
+ Py_BEGIN_ALLOW_THREADS
+ delete self->driver;
+ Py_END_ALLOW_THREADS
+ self->driver = NULL;
+ }
+
+ if (self->proxyScheduler != NULL) {
+ delete self->proxyScheduler;
+ self->proxyScheduler = NULL;
+ }
+
+ MesosSchedulerDriverImpl_clear(self);
+ self->ob_type->tp_free((PyObject*) self);
+}
+
+
+/**
+ * Traverse fields of a MesosSchedulerDriverImpl on a cyclic GC search.
+ * See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosSchedulerDriverImpl_traverse(MesosSchedulerDriverImpl* self,
+ visitproc visit,
+ void* arg)
+{
+ Py_VISIT(self->pythonScheduler);
+ return 0;
+}
+
+
+/**
+ * Clear fields of a MesosSchedulerDriverImpl that can participate in
+ * GC cycles. See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosSchedulerDriverImpl_clear(MesosSchedulerDriverImpl* self)
+{
+ Py_CLEAR(self->pythonScheduler);
+ return 0;
+}
+
+
+PyObject* MesosSchedulerDriverImpl_start(MesosSchedulerDriverImpl* self)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ Status status = self->driver->start();
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_stop(MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ bool failover = false; // Should match default in mesos.py.
+
+ if (!PyArg_ParseTuple(args, "|b", &failover)) {
+ return NULL;
+ }
+
+ Status status = self->driver->stop(failover);
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_abort(MesosSchedulerDriverImpl* self)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ Status status = self->driver->abort();
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_join(MesosSchedulerDriverImpl* self)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ Status status;
+ Py_BEGIN_ALLOW_THREADS
+ status = self->driver->join();
+ Py_END_ALLOW_THREADS
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_run(MesosSchedulerDriverImpl* self)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ Status status;
+ Py_BEGIN_ALLOW_THREADS
+ status = self->driver->run();
+ Py_END_ALLOW_THREADS
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_requestResources(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* requestsObj = NULL;
+ vector<Request> requests;
+
+ if (!PyArg_ParseTuple(args, "O", &requestsObj)) {
+ return NULL;
+ }
+
+ if (!PyList_Check(requestsObj)) {
+ PyErr_Format(PyExc_Exception,
+ "Parameter 2 to requestsResources is not a list");
+ return NULL;
+ }
+ Py_ssize_t len = PyList_Size(requestsObj);
+ for (int i = 0; i < len; i++) {
+ PyObject* requestObj = PyList_GetItem(requestsObj, i);
+ if (requestObj == NULL) {
+ return NULL; // Exception will have been set by PyList_GetItem.
+ }
+ Request request;
+ if (!readPythonProtobuf(requestObj, &request)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python Request");
+ return NULL;
+ }
+ requests.push_back(request);
+ }
+
+ Status status = self->driver->requestResources(requests);
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_launchTasks(MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* offerIdsObj = NULL;
+ PyObject* tasksObj = NULL;
+ PyObject* filtersObj = NULL;
+ vector<OfferID> offerIds;
+ vector<TaskInfo> tasks;
+ Filters filters;
+
+ if (!PyArg_ParseTuple(args, "OO|O", &offerIdsObj, &tasksObj, &filtersObj)) {
+ return NULL;
+ }
+
+ // Offer argument can be a list of offer ids or a single offer id (for
+ // backward compatibility).
+ if (!PyList_Check(offerIdsObj)) {
+ OfferID offerId;
+ if (!readPythonProtobuf(offerIdsObj, &offerId)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python OfferID");
+ return NULL;
+ }
+ offerIds.push_back(offerId);
+ } else {
+ Py_ssize_t len = PyList_Size(offerIdsObj);
+ for (int i = 0; i < len; i++) {
+ PyObject* offerObj = PyList_GetItem(offerIdsObj, i);
+ if (offerObj == NULL) {
+ return NULL;
+ }
+ OfferID offerId;
+ if (!readPythonProtobuf(offerObj, &offerId)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python OfferID");
+ return NULL;
+ }
+ offerIds.push_back(offerId);
+ }
+ }
+
+ if (!PyList_Check(tasksObj)) {
+ PyErr_Format(PyExc_Exception, "Parameter 2 to launchTasks is not a list");
+ return NULL;
+ }
+ Py_ssize_t len = PyList_Size(tasksObj);
+ for (int i = 0; i < len; i++) {
+ PyObject* taskObj = PyList_GetItem(tasksObj, i);
+ if (taskObj == NULL) {
+ return NULL; // Exception will have been set by PyList_GetItem.
+ }
+ TaskInfo task;
+ if (!readPythonProtobuf(taskObj, &task)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python TaskInfo");
+ return NULL;
+ }
+ tasks.push_back(task);
+ }
+
+ if (filtersObj != NULL) {
+ if (!readPythonProtobuf(filtersObj, &filters)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python Filters");
+ return NULL;
+ }
+ }
+
+ Status status = self->driver->launchTasks(offerIds, tasks, filters);
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_killTask(MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* tidObj = NULL;
+ TaskID tid;
+ if (!PyArg_ParseTuple(args, "O", &tidObj)) {
+ return NULL;
+ }
+ if (!readPythonProtobuf(tidObj, &tid)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python TaskID");
+ return NULL;
+ }
+
+ Status status = self->driver->killTask(tid);
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_acceptOffers(MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* offerIdsObj = NULL;
+ PyObject* operationsObj = NULL;
+ PyObject* filtersObj = NULL;
+ Py_ssize_t len = 0;
+ vector<OfferID> offerIds;
+ vector<Offer::Operation> operations;
+ Filters filters;
+
+ if (!PyArg_ParseTuple(args,
+ "OO|O",
+ &offerIdsObj,
+ &operationsObj,
+ &filtersObj)) {
+ return NULL;
+ }
+
+ if (!PyList_Check(offerIdsObj)) {
+ PyErr_Format(PyExc_Exception, "Parameter 1 to acceptOffers is not a list");
+ return NULL;
+ }
+
+ len = PyList_Size(offerIdsObj);
+ for (int i = 0; i < len; i++) {
+ PyObject* offerObj = PyList_GetItem(offerIdsObj, i);
+ if (offerObj == NULL) {
+ return NULL;
+ }
+
+ OfferID offerId;
+ if (!readPythonProtobuf(offerObj, &offerId)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python OfferID");
+ return NULL;
+ }
+ offerIds.push_back(offerId);
+ }
+
+ if (!PyList_Check(operationsObj)) {
+ PyErr_Format(PyExc_Exception, "Parameter 2 to acceptOffers is not a list");
+ return NULL;
+ }
+
+ len = PyList_Size(operationsObj);
+ for (int i = 0; i < len; i++) {
+ PyObject* operationObj = PyList_GetItem(operationsObj, i);
+ if (operationObj == NULL) {
+ return NULL; // Exception will have been set by PyList_GetItem.
+ }
+
+ Offer::Operation operation;
+ if (!readPythonProtobuf(operationObj, &operation)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python Offer.Operation");
+ return NULL;
+ }
+ operations.push_back(operation);
+ }
+
+ if (filtersObj != NULL) {
+ if (!readPythonProtobuf(filtersObj, &filters)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python Filters");
+ return NULL;
+ }
+ }
+
+ Status status = self->driver->acceptOffers(offerIds, operations, filters);
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_declineOffer(MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* offerIdObj = NULL;
+ PyObject* filtersObj = NULL;
+ OfferID offerId;
+ Filters filters;
+
+ if (!PyArg_ParseTuple(args, "O|O", &offerIdObj, &filtersObj)) {
+ return NULL;
+ }
+
+ if (!readPythonProtobuf(offerIdObj, &offerId)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python OfferID");
+ return NULL;
+ }
+
+ if (filtersObj != NULL) {
+ if (!readPythonProtobuf(filtersObj, &filters)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python Filters");
+ return NULL;
+ }
+ }
+
+ Status status = self->driver->declineOffer(offerId, filters);
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_reviveOffers(MesosSchedulerDriverImpl* self)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ Status status = self->driver->reviveOffers();
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_suppressOffers(
+ MesosSchedulerDriverImpl* self)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ Status status = self->driver->suppressOffers();
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_acknowledgeStatusUpdate(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* taskStatusObj = NULL;
+ TaskStatus taskStatus;
+
+ if (!PyArg_ParseTuple(args, "O", &taskStatusObj)) {
+ return NULL;
+ }
+
+ if (!readPythonProtobuf(taskStatusObj, &taskStatus)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python TaskStatus");
+ return NULL;
+ }
+
+ Status status = self->driver->acknowledgeStatusUpdate(taskStatus);
+
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_sendFrameworkMessage(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* slaveIdObj = NULL;
+ PyObject* executorIdObj = NULL;
+ SlaveID slaveId;
+ ExecutorID executorId;
+ const char* data;
+ int length;
+
+ if (!PyArg_ParseTuple(
+ args, "OOs#", &executorIdObj, &slaveIdObj, &data, &length)) {
+ return NULL;
+ }
+
+ if (!readPythonProtobuf(executorIdObj, &executorId)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python ExecutorID");
+ return NULL;
+ }
+
+ if (!readPythonProtobuf(slaveIdObj, &slaveId)) {
+ PyErr_Format(PyExc_Exception, "Could not deserialize Python SlaveID");
+ return NULL;
+ }
+
+ Status status = self->driver->sendFrameworkMessage(
+ executorId, slaveId, string(data, length));
+
+ return PyInt_FromLong(status); // Sets exception if creating long fails.
+}
+
+
+PyObject* MesosSchedulerDriverImpl_reconcileTasks(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args)
+{
+ if (self->driver == NULL) {
+ PyErr_Format(PyExc_Exception, "MesosSchedulerDriverImpl.driver is NULL");
+ return NULL;
+ }
+
+ PyObject* statusesObj = NULL;
+ vector<TaskStatus> statuses;
+
+ if (!PyArg_ParseTuple(args, "O", &statusesObj)) {
+ return NULL;
+ }
+
+ if (!PyList_Check(statusesObj)) {
+ PyErr_Format(PyExc_Exception,
+ "Parameter 1 to reconcileTasks is not a list");
+
+ return NULL;
+ }
+
+ Py_ssize_t len = PyList_Size(statusesObj);
+ for (int i = 0; i < len; i++) {
+ PyObject* statusObj = PyList_GetItem(statusesObj, i);
+ if (statusObj == NULL) {
+ return NULL;
+ }
+
+ TaskStatus status;
+ if (!readPythonProtobuf(statusObj, &status)) {
+ PyErr_Format(PyExc_Exception,
+ "Could not deserialize Python TaskStatus");
+ return NULL;
+ }
+ statuses.push_back(status);
+ }
+
+ Status status = self->driver->reconcileTasks(statuses);
+ return PyInt_FromLong(status);
+}
+
+} // namespace python {
+} // namespace mesos {
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.hpp
----------------------------------------------------------------------
diff --git a/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.hpp b/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.hpp
new file mode 100644
index 0000000..8c98d46
--- /dev/null
+++ b/src/python/scheduler/src/mesos/scheduler/mesos_scheduler_driver_impl.hpp
@@ -0,0 +1,134 @@
+// 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_SCHEDULER_DRIVER_IMPL_HPP
+#define MESOS_SCHEDULER_DRIVER_IMPL_HPP
+
+#include <mesos/scheduler.hpp>
+
+
+namespace mesos { namespace python {
+
+class ProxyScheduler;
+
+/**
+ * Python object structure for MesosSchedulerDriverImpl objects.
+ */
+struct MesosSchedulerDriverImpl {
+ PyObject_HEAD
+ /* Type-specific fields go here. */
+ MesosSchedulerDriver* driver;
+ ProxyScheduler* proxyScheduler;
+ PyObject* pythonScheduler;
+};
+
+/**
+ * Python type object for MesosSchedulerDriverImpl.
+ */
+extern PyTypeObject MesosSchedulerDriverImplType;
+
+/**
+ * List of Python methods in MesosSchedulerDriverImpl.
+ */
+extern PyMethodDef MesosSchedulerDriverImpl_methods[];
+
+/**
+ * Create, but don't initialize, a new MesosSchedulerDriverImpl
+ * (called by Python before init method).
+ */
+PyObject* MesosSchedulerDriverImpl_new(PyTypeObject *type,
+ PyObject *args,
+ PyObject *kwds);
+
+/**
+ * Initialize a MesosSchedulerDriverImpl with constructor arguments.
+ */
+int MesosSchedulerDriverImpl_init(MesosSchedulerDriverImpl *self,
+ PyObject *args,
+ PyObject *kwds);
+
+/**
+ * Free a MesosSchedulerDriverImpl.
+ */
+void MesosSchedulerDriverImpl_dealloc(MesosSchedulerDriverImpl* self);
+
+/**
+ * Traverse fields of a MesosSchedulerDriverImpl on a cyclic GC search.
+ * See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosSchedulerDriverImpl_traverse(MesosSchedulerDriverImpl* self,
+ visitproc visit,
+ void* arg);
+/**
+ * Clear fields of a MesosSchedulerDriverImpl that can participate in
+ * GC cycles. See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosSchedulerDriverImpl_clear(MesosSchedulerDriverImpl* self);
+
+// MesosSchedulerDriverImpl methods.
+PyObject* MesosSchedulerDriverImpl_start(MesosSchedulerDriverImpl* self);
+
+PyObject* MesosSchedulerDriverImpl_stop(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_abort(MesosSchedulerDriverImpl* self);
+
+PyObject* MesosSchedulerDriverImpl_join(MesosSchedulerDriverImpl* self);
+
+PyObject* MesosSchedulerDriverImpl_run(MesosSchedulerDriverImpl* self);
+
+PyObject* MesosSchedulerDriverImpl_requestResources(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_launchTasks(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_killTask(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_acceptOffers(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_declineOffer(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_reviveOffers(MesosSchedulerDriverImpl* self);
+
+PyObject* MesosSchedulerDriverImpl_suppressOffers(
+ MesosSchedulerDriverImpl* self);
+
+PyObject* MesosSchedulerDriverImpl_acknowledgeStatusUpdate(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_sendFrameworkMessage(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_reconcileTasks(
+ MesosSchedulerDriverImpl* self,
+ PyObject* args);
+
+} // namespace python {
+} // namespace mesos {
+
+#endif /* MESOS_SCHEDULER_DRIVER_IMPL_HPP */
http://git-wip-us.apache.org/repos/asf/mesos/blob/c81a52ec/src/python/scheduler/src/mesos/scheduler/module.cpp
----------------------------------------------------------------------
diff --git a/src/python/scheduler/src/mesos/scheduler/module.cpp b/src/python/scheduler/src/mesos/scheduler/module.cpp
new file mode 100644
index 0000000..62eaf31
--- /dev/null
+++ b/src/python/scheduler/src/mesos/scheduler/module.cpp
@@ -0,0 +1,91 @@
+// 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.
+
+/**
+ * This file defines the _mesos.so binary module used by the Mesos Python API.
+ * This module contains private implementations of MesosSchedulerDriver and
+ * MesosExecutorDriver as Python types that get called from the public module
+ * called mesos (in <root>/src/python/src/mesos.py). This design was chosen
+ * so that most of the API (e.g. the Scheduler and Executor interfaces) can
+ * be written in Python, and only the parts that need to call into C++ are
+ * in C++. Note that the mesos module also contains public classes called
+ * MesosSchedulerDriver and MesosExecutorDriver. These call into the private
+ * _mesos.MesosSchedulerDriverImpl and _mesos.MesosExecutorDriverImpl.
+ */
+
+// Python.h must be included before standard headers.
+// See: http://docs.python.org/2/c-api/intro.html#include-files
+#include <Python.h>
+
+#include <iostream>
+
+#include <mesos/scheduler.hpp>
+
+#include "common.hpp"
+#include "mesos_scheduler_driver_impl.hpp"
+#include "proxy_scheduler.hpp"
+
+using namespace mesos;
+using namespace mesos::python;
+
+using std::map;
+using std::string;
+using std::vector;
+
+
+/**
+ * The Python module object for mesos_pb2 (which contains the protobuf
+ * classes generated for Python).
+ */
+PyObject* mesos::python::mesos_pb2 = NULL;
+
+
+namespace {
+
+/**
+ * Method list for our Python module.
+ */
+PyMethodDef MODULE_METHODS[] = {
+ {NULL, NULL, 0, NULL} /* Sentinel */
+};
+
+} // namespace {
+
+
+/**
+ * Entry point called by Python to initialize our module.
+ */
+PyMODINIT_FUNC init_scheduler()
+{
+ // Ensure that the interpreter's threading support is enabled.
+ PyEval_InitThreads();
+
+ // Import the mesos_pb2 module (on which we depend for protobuf classes)
+ mesos_pb2 = PyImport_ImportModule("mesos.interface.mesos_pb2");
+ if (mesos_pb2 == NULL)
+ return;
+
+ // Initialize our Python types.
+ if (PyType_Ready(&MesosSchedulerDriverImplType) < 0)
+ return;
+
+ // Create the _mesos module and add our types to it.
+ PyObject* module = Py_InitModule("_scheduler", MODULE_METHODS);
+ Py_INCREF(&MesosSchedulerDriverImplType);
+ PyModule_AddObject(module,
+ "MesosSchedulerDriverImpl",
+ (PyObject*) &MesosSchedulerDriverImplType);
+}