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);
+}