You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2014/08/01 18:39:17 UTC

[1/3] Refactored the python bindings into multiple modules.

Repository: mesos
Updated Branches:
  refs/heads/master 3047bbe41 -> c5a68be12


http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/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
new file mode 100644
index 0000000..5e8637e
--- /dev/null
+++ b/src/python/native/src/mesos/native/proxy_executor.cpp
@@ -0,0 +1,275 @@
+/**
+ * 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/c5a68be1/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
new file mode 100644
index 0000000..eeefc5e
--- /dev/null
+++ b/src/python/native/src/mesos/native/proxy_executor.hpp
@@ -0,0 +1,66 @@
+/**
+ * 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/c5a68be1/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
new file mode 100644
index 0000000..95b09cf
--- /dev/null
+++ b/src/python/native/src/mesos/native/proxy_scheduler.cpp
@@ -0,0 +1,386 @@
+/**
+ * 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/c5a68be1/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
new file mode 100644
index 0000000..501c574
--- /dev/null
+++ b/src/python/native/src/mesos/native/proxy_scheduler.hpp
@@ -0,0 +1,74 @@
+/**
+ * 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/c5a68be1/src/python/protocol/setup.py.in
----------------------------------------------------------------------
diff --git a/src/python/protocol/setup.py.in b/src/python/protocol/setup.py.in
new file mode 100644
index 0000000..72cb770
--- /dev/null
+++ b/src/python/protocol/setup.py.in
@@ -0,0 +1,35 @@
+# 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.
+
+config = {
+    'name': 'mesos.protocol',
+    'version': '@PACKAGE_VERSION@',
+    'description': 'Mesos protobuf definitions',
+    'author': 'Apache Mesos',
+    'author_email': 'dev@mesos.apache.org',
+    'url': 'http://pypi.python.org/pypi/mesos.protocol',
+    'namespace_packages': [ 'mesos' ],
+    'packages': [ 'mesos', 'mesos.protocol' ],
+    'package_dir': { '': 'src' },
+    'install_requires': [ 'protobuf>=2.5.0,<3' ],
+    'license': 'Apache 2.0',
+    'keywords': 'mesos',
+    'classifiers': [ ]
+}
+
+from setuptools import setup
+
+setup(**config)

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/protocol/src/mesos/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/protocol/src/mesos/__init__.py b/src/python/protocol/src/mesos/__init__.py
new file mode 100644
index 0000000..f48ad10
--- /dev/null
+++ b/src/python/protocol/src/mesos/__init__.py
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+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/c5a68be1/src/python/protocol/src/mesos/protocol/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/protocol/src/mesos/protocol/__init__.py b/src/python/protocol/src/mesos/protocol/__init__.py
new file mode 100644
index 0000000..635f0d9
--- /dev/null
+++ b/src/python/protocol/src/mesos/protocol/__init__.py
@@ -0,0 +1,15 @@
+# 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.

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/setup.py.in
----------------------------------------------------------------------
diff --git a/src/python/setup.py.in b/src/python/setup.py.in
index 60add3b..304c4bf 100644
--- a/src/python/setup.py.in
+++ b/src/python/setup.py.in
@@ -1,148 +1,38 @@
-import sys
-
-try:
-  import setuptools as distutils
-except ImportError:
-  print 'Could not find setuptools, bailing.'
-  sys.exit(1)
-
-import errno
-import glob
-import os
-import shutil
-
-from distutils.core import setup, Extension
-
-abs_top_srcdir = '@abs_top_srcdir@'
-abs_top_builddir = '@abs_top_builddir@'
-
-src_python_dist = os.path.join('src', 'python', 'dist')
-src_python_native = os.path.join('src', 'python', 'native')
-
-leveldb = os.path.join('3rdparty', 'leveldb')
-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')
-libev = os.path.join(libprocess, '3rdparty', 'libev-4.15')
-gperftools = os.path.join(libprocess, '3rdparty', 'gperftools-2.0')
-protobuf = os.path.join(libprocess, '3rdparty', 'protobuf-2.5.0')
-
-# We need to execute from the same directory as this script.
-os.chdir(os.path.abspath(os.path.dirname(__file__)))
-
-# Copy the native source files if we are building in a remote build
-# directory. This is necessary because the sources list must be
-# relative to the directory where this script resides.
-# $ cp -rf abs_top_srcdir/native abs_top_builddir/native
-if os.path.abspath(abs_top_srcdir) != os.path.abspath(abs_top_builddir):
-  try:
-    shutil.rmtree(os.path.join(abs_top_builddir, src_python_native), ignore_errors=True)
-    shutil.copytree(os.path.join(abs_top_srcdir, src_python_native),
-                    os.path.join(abs_top_builddir, src_python_native))
-  except OSError, e:
-    if e.errno != errno.EEXIST:
-      raise
-
-
-# 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('native', file)
-    for file in os.listdir(os.path.join(abs_top_srcdir, src_python_native))
-      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, src_python_native),
-   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, protobuf, 'src', '.libs', 'libprotobuf.a'),
-  os.path.join(abs_top_builddir, libprocess, '.libs', 'libprocess.a'),
-  os.path.join(abs_top_builddir, glog, '.libs', 'libglog.a')
-]
-
-# For leveldb, we need to check for the presence of libleveldb.a, since
-# it is possible to disable leveldb inside mesos.
-libev = os.path.join(abs_top_builddir, libev, '.libs', 'libev.a')
-libleveldb = os.path.join(abs_top_builddir, leveldb, 'libleveldb.a')
-libzookeeper = os.path.join(
-    abs_top_builddir, zookeeper, '.libs', 'libzookeeper_mt.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(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 = []
-
-# 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)
-
-DEPENDS = [
-  os.path.join(abs_top_srcdir, 'src', 'python', source)
-    for source in SOURCES
-]
-
-# 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',
-            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++',
-            )
-
-setup(name = 'mesos',
-      version = '@PACKAGE_VERSION@',
-      description = 'Mesos',
-      package_dir = { '': 'src' },
-      packages = ['.'],
-      install_requires = ['protobuf>=2.5.0'],
-      ext_modules = [mesos_module])
+# 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.
+
+config = {
+    'name': 'mesos',
+    'version': '@PACKAGE_VERSION@',
+    'description': 'Python bindings for mesos',
+    'author': 'Apache Mesos',
+    'author_email': 'mesos@apache.com',
+    'url': 'http://pypi.python.org/pypi/mesos',
+    'namespace_packages': [ 'mesos' ],
+    'packages': [ 'mesos' ],
+    'package_dir': { '': 'src' },
+    'install_requires': [
+        'mesos.interface',
+        'mesos.native'
+    ],
+    'license': 'Apache 2.0',
+    'keywords': 'mesos',
+    'classifiers': [ ]
+}
+
+from setuptools import setup
+
+setup(**config)

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/src/mesos.py
----------------------------------------------------------------------
diff --git a/src/python/src/mesos.py b/src/python/src/mesos.py
deleted file mode 100644
index 0152ab4..0000000
--- a/src/python/src/mesos.py
+++ /dev/null
@@ -1,361 +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.
-
-# See include/mesos/scheduler.hpp, include/mesos/executor.hpp and
-# include/mesos/mesos.proto for more information documenting this
-# interface.
-
-"""Python bindings for Mesos."""
-
-from __future__ import print_function
-
-import sys
-import _mesos
-
-
-# Alias the implementations from _mesos.
-
-# TODO(wickman): Make Mesos{Scheduler,Executor}DriverImpl inherit from the
-# superclasses defined here.
-MesosSchedulerDriver = _mesos.MesosSchedulerDriverImpl
-MesosExecutorDriver = _mesos.MesosExecutorDriverImpl
-
-
-__all__ = (
-  'Executor',
-  'ExecutorDriver'
-  'MesosExecutorDriver',
-  'MesosSchedulerDriver',
-  'Scheduler',
-  'SchedulerDriver',
-)
-
-
-class Scheduler(object):
-  """
-    Base class for Mesos schedulers. Users' schedulers should extend this
-    class to get default implementations of methods they don't override.
-  """
-
-  def registered(self, driver, frameworkId, masterInfo):
-    """
-      Invoked when the scheduler successfully registers with a Mesos master.
-      It is called with the frameworkId, a unique ID generated by the
-      master, and the masterInfo which is information about the master
-      itself.
-    """
-
-  def reregistered(self, driver, masterInfo):
-    """
-      Invoked when the scheduler re-registers with a newly elected Mesos
-      master.  This is only called when the scheduler has previously been
-      registered.  masterInfo contains information about the newly elected
-      master.
-    """
-
-  def disconnected(self, driver):
-    """
-      Invoked when the scheduler becomes disconnected from the master, e.g.
-      the master fails and another is taking over.
-    """
-
-  def resourceOffers(self, driver, offers):
-    """
-      Invoked when resources have been offered to this framework. A single
-      offer will only contain resources from a single slave.  Resources
-      associated with an offer will not be re-offered to _this_ framework
-      until either (a) this framework has rejected those resources (see
-      SchedulerDriver.launchTasks) or (b) those resources have been
-      rescinded (see Scheduler.offerRescinded).  Note that resources may be
-      concurrently offered to more than one framework at a time (depending
-      on the allocator being used).  In that case, the first framework to
-      launch tasks using those resources will be able to use them while the
-      other frameworks will have those resources rescinded (or if a
-      framework has already launched tasks with those resources then those
-      tasks will fail with a TASK_LOST status and a message saying as much).
-    """
-
-  def offerRescinded(self, driver, offerId):
-    """
-      Invoked when an offer is no longer valid (e.g., the slave was lost or
-      another framework used resources in the offer.) If for whatever reason
-      an offer is never rescinded (e.g., dropped message, failing over
-      framework, etc.), a framwork that attempts to launch tasks using an
-      invalid offer will receive TASK_LOST status updats for those tasks
-      (see Scheduler.resourceOffers).
-    """
-
-  def statusUpdate(self, driver, status):
-    """
-      Invoked when the status of a task has changed (e.g., a slave is lost
-      and so the task is lost, a task finishes and an executor sends a
-      status update saying so, etc.) Note that returning from this callback
-      acknowledges receipt of this status update.  If for whatever reason
-      the scheduler aborts during this callback (or the process exits)
-      another status update will be delivered.  Note, however, that this is
-      currently not true if the slave sending the status update is lost or
-      fails during that time.
-    """
-
-  def frameworkMessage(self, driver, executorId, slaveId, message):
-    """
-      Invoked when an executor sends a message. These messages are best
-      effort; do not expect a framework message to be retransmitted in any
-      reliable fashion.
-    """
-
-  def slaveLost(self, driver, slaveId):
-    """
-      Invoked when a slave has been determined unreachable (e.g., machine
-      failure, network partition.) Most frameworks will need to reschedule
-      any tasks launched on this slave on a new slave.
-    """
-
-  def executorLost(self, driver, executorId, slaveId, status):
-    """
-      Invoked when an executor has exited/terminated. Note that any tasks
-      running will have TASK_LOST status updates automatically generated.
-    """
-
-  def error(self, driver, message):
-    """
-      Invoked when there is an unrecoverable error in the scheduler or
-      scheduler driver.  The driver will be aborted BEFORE invoking this
-      callback.
-    """
-    print("Error from Mesos: %s " % message, file=sys.stderr)
-
-
-class SchedulerDriver(object):
-  """
-    Interface for Mesos scheduler drivers. Users may wish to implement this
-    class in mock objects for tests.
-  """
-  def start(self):
-    """
-      Starts the scheduler driver.  This needs to be called before any other
-      driver calls are made.
-    """
-
-  def stop(self, failover=False):
-    """
-      Stops the scheduler driver. If the 'failover' flag is set to
-      false then it is expected that this framework will never
-      reconnect to Mesos. So Mesos will unregister the framework
-      and shutdown all its tasks and executors. If 'failover' is true,
-      all executors and tasks will remain running (for some framework
-      specific failover timeout) allowing the scheduler to reconnect
-      (possibly in the same process, or from a different process, for
-      example, on a different machine).
-    """
-
-  def abort(self):
-    """
-      Aborts the driver so that no more callbacks can be made to the
-      scheduler.  The semantics of abort and stop have deliberately been
-      separated so that code can detect an aborted driver (i.e., via the
-      return status of SchedulerDriver.join), and instantiate and start
-      another driver if desired (from within the same process.)
-    """
-
-  def join(self):
-    """
-      Waits for the driver to be stopped or aborted, possibly blocking the
-      current thread indefinitely.  The return status of this function can
-      be used to determine if the driver was aborted (see mesos.proto for a
-      description of Status).
-    """
-
-  def run(self):
-    """
-      Starts and immediately joins (i.e., blocks on) the driver.
-    """
-
-  def requestResources(self, requests):
-    """
-      Requests resources from Mesos (see mesos.proto for a description of
-      Request and how, for example, to request resources from specific
-      slaves.)  Any resources available are offered to the framework via
-      Scheduler.resourceOffers callback, asynchronously.
-    """
-
-  def launchTasks(self, offerIds, tasks, filters=None):
-    """
-      Launches the given set of tasks. Any resources remaining (i.e., not
-      used by the tasks or their executors) will be considered declined.
-      The specified filters are applied on all unused resources (see
-      mesos.proto for a description of Filters.) Invoking this function with
-      an empty collection of tasks declines the offers in entirety (see
-      Scheduler.declineOffer). Note that passing a single offer is also
-      supported.
-    """
-
-  def killTask(self, taskId):
-    """
-      Kills the specified task. Note that attempting to kill a task is
-      currently not reliable.  If, for example, a scheduler fails over while
-      it was attempting to kill a task it will need to retry in the future.
-      Likewise, if unregistered / disconnected, the request will be dropped
-      dropped (these semantics may be changed in the future).
-    """
-
-  def declineOffer(self, offerId, filters=None):
-    """
-      Declines an offer in its entirety and applies the specified
-      filters on the resources (see mesos.proto for a description of
-      Filters). Note that this can be done at any time, it is not
-      necessary to do this within the Scheduler::resourceOffers
-      callback.
-    """
-
-  def reviveOffers(self):
-    """
-      Removes all filters previously set by the framework (via
-      launchTasks()).  This enables the framework to receive offers from
-      those filtered slaves.
-    """
-
-  def sendFrameworkMessage(self, executorId, slaveId, data):
-    """
-      Sends a message from the framework to one of its executors. These
-      messages are best effort; do not expect a framework message to be
-      retransmitted in any reliable fashion.
-    """
-
-  # TODO(bmahler): Add reconcileTasks!
-
-class Executor(object):
-  """
-    Base class for Mesos executors. Users' executors should extend this
-    class to get default implementations of methods they don't override.
-  """
-
-  def registered(self, driver, executorInfo, frameworkInfo, slaveInfo):
-    """
-      Invoked once the executor driver has been able to successfully connect
-      with Mesos.  In particular, a scheduler can pass some data to its
-      executors through the FrameworkInfo.ExecutorInfo's data field.
-    """
-
-  def reregistered(self, driver, slaveInfo):
-    """
-      Invoked when the executor re-registers with a restarted slave.
-    """
-
-  def disconnected(self, driver):
-    """
-      Invoked when the executor becomes "disconnected" from the slave (e.g.,
-      the slave is being restarted due to an upgrade).
-    """
-
-  def launchTask(self, driver, task):
-    """
-      Invoked when a task has been launched on this executor (initiated via
-      Scheduler.launchTasks).  Note that this task can be realized with a
-      thread, a process, or some simple computation, however, no other
-      callbacks will be invoked on this executor until this callback has
-      returned.
-    """
-
-  def killTask(self, driver, taskId):
-    """
-      Invoked when a task running within this executor has been killed (via
-      SchedulerDriver.killTask).  Note that no status update will be sent on
-      behalf of the executor, the executor is responsible for creating a new
-      TaskStatus (i.e., with TASK_KILLED) and invoking ExecutorDriver's
-      sendStatusUpdate.
-    """
-
-  def frameworkMessage(self, driver, message):
-    """
-      Invoked when a framework message has arrived for this executor.  These
-      messages are best effort; do not expect a framework message to be
-      retransmitted in any reliable fashion.
-    """
-
-  def shutdown(self, driver):
-    """
-      Invoked when the executor should terminate all of its currently
-      running tasks.  Note that after Mesos has determined that an executor
-      has terminated any tasks that the executor did not send terminal
-      status updates for (e.g., TASK_KILLED, TASK_FINISHED, TASK_FAILED,
-      etc) a TASK_LOST status update will be created.
-    """
-
-  def error(self, driver, message):
-    """
-      Invoked when a fatal error has occured with the executor and/or
-      executor driver.  The driver will be aborted BEFORE invoking this
-      callback.
-    """
-    print("Error from Mesos: %s" % message, file=sys.stderr)
-
-
-
-class ExecutorDriver(object):
-  """
-    Interface for Mesos executor drivers. Users may wish to extend this
-    class in mock objects for tests.
-  """
-  def start(self):
-    """
-      Starts the executor driver. This needs to be called before any other
-      driver calls are made.
-    """
-
-  def stop(self):
-    """
-      Stops the executor driver.
-    """
-
-  def abort(self):
-    """
-      Aborts the driver so that no more callbacks can be made to the
-      executor.  The semantics of abort and stop have deliberately been
-      separated so that code can detect an aborted driver (i.e., via the
-      return status of ExecutorDriver.join), and instantiate and start
-      another driver if desired (from within the same process, although this
-      functionality is currently not supported for executors).
-    """
-
-  def join(self):
-    """
-      Waits for the driver to be stopped or aborted, possibly blocking the
-      current thread indefinitely.  The return status of this function can
-      be used to determine if the driver was aborted (see mesos.proto for a
-      description of Status).
-    """
-
-  def run(self):
-    """
-      Starts and immediately joins (i.e., blocks on) the driver.
-    """
-
-  def sendStatusUpdate(self, status):
-    """
-      Sends a status update to the framework scheduler, retrying as
-      necessary until an acknowledgement has been received or the executor
-      is terminated (in which case, a TASK_LOST status update will be sent).
-      See Scheduler.statusUpdate for more information about status update
-      acknowledgements.
-    """
-
-  def sendFrameworkMessage(self, data):
-    """
-      Sends a message to the framework scheduler. These messages are best
-      effort; do not expect a framework message to be retransmitted in any
-      reliable fashion.
-    """

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/src/mesos/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/src/mesos/__init__.py b/src/python/src/mesos/__init__.py
new file mode 100644
index 0000000..f48ad10
--- /dev/null
+++ b/src/python/src/mesos/__init__.py
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)


[2/3] Refactored the python bindings into multiple modules.

Posted by be...@apache.org.
http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/module.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/module.cpp b/src/python/native/module.cpp
deleted file mode 100644
index f523c1f..0000000
--- a/src/python/native/module.cpp
+++ /dev/null
@@ -1,102 +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(void)
-{
-  // 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_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/c5a68be1/src/python/native/module.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/module.hpp b/src/python/native/module.hpp
deleted file mode 100644
index 1c35e2e..0000000
--- a/src/python/native/module.hpp
+++ /dev/null
@@ -1,138 +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/c5a68be1/src/python/native/proxy_executor.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/proxy_executor.cpp b/src/python/native/proxy_executor.cpp
deleted file mode 100644
index 5e8637e..0000000
--- a/src/python/native/proxy_executor.cpp
+++ /dev/null
@@ -1,275 +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/c5a68be1/src/python/native/proxy_executor.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/proxy_executor.hpp b/src/python/native/proxy_executor.hpp
deleted file mode 100644
index eeefc5e..0000000
--- a/src/python/native/proxy_executor.hpp
+++ /dev/null
@@ -1,66 +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/c5a68be1/src/python/native/proxy_scheduler.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/proxy_scheduler.cpp b/src/python/native/proxy_scheduler.cpp
deleted file mode 100644
index 95b09cf..0000000
--- a/src/python/native/proxy_scheduler.cpp
+++ /dev/null
@@ -1,386 +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/c5a68be1/src/python/native/proxy_scheduler.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/proxy_scheduler.hpp b/src/python/native/proxy_scheduler.hpp
deleted file mode 100644
index 501c574..0000000
--- a/src/python/native/proxy_scheduler.hpp
+++ /dev/null
@@ -1,74 +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/c5a68be1/src/python/native/setup.py.in
----------------------------------------------------------------------
diff --git a/src/python/native/setup.py.in b/src/python/native/setup.py.in
new file mode 100644
index 0000000..9fc9ad2
--- /dev/null
+++ b/src/python/native/setup.py.in
@@ -0,0 +1,38 @@
+# 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.native',
+    'version': '@PACKAGE_VERSION@',
+    'description': 'Mesos native driver implementation',
+    'author': 'Apache Mesos',
+    'author_email': 'dev@mesos.apache.org',
+    'url': 'http://pypi.python.org/pypi/mesos.native',
+    'namespace_packages': [ 'mesos' ],
+    'packages': [ 'mesos', 'mesos.native' ],
+    'package_dir': { '': 'src' },
+    'install_requires': [ 'mesos.interface == @PACKAGE_VERSION@' ],
+    'license': 'Apache 2.0',
+    'keywords': 'mesos',
+    'classifiers': [ ],
+    'ext_modules': [ ext_modules.mesos_module ]
+}
+
+from setuptools import setup
+
+setup(**config)

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/src/mesos/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/__init__.py b/src/python/native/src/mesos/__init__.py
new file mode 100644
index 0000000..f48ad10
--- /dev/null
+++ b/src/python/native/src/mesos/__init__.py
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+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/c5a68be1/src/python/native/src/mesos/native/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/__init__.py b/src/python/native/src/mesos/native/__init__.py
new file mode 100644
index 0000000..226f943
--- /dev/null
+++ b/src/python/native/src/mesos/native/__init__.py
@@ -0,0 +1,21 @@
+# 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 ._mesos import MesosExecutorDriverImpl
+from ._mesos import MesosSchedulerDriverImpl
+
+MesosExecutorDriver = MesosExecutorDriverImpl
+MesosSchedulerDriver = MesosSchedulerDriverImpl

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/src/mesos/native/mesos_executor_driver_impl.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/mesos_executor_driver_impl.cpp b/src/python/native/src/mesos/native/mesos_executor_driver_impl.cpp
new file mode 100644
index 0000000..16b9bc1
--- /dev/null
+++ b/src/python/native/src/mesos/native/mesos_executor_driver_impl.cpp
@@ -0,0 +1,349 @@
+/**
+ * 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 "mesos_executor_driver_impl.hpp"
+#include "module.hpp"
+#include "proxy_executor.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 MesosExecutorDriverImpl.
+ */
+PyTypeObject MesosExecutorDriverImplType = {
+  PyObject_HEAD_INIT(NULL)
+  0,                                               /* ob_size */
+  "_mesos.MesosExecutorDriverImpl",                /* tp_name */
+  sizeof(MesosExecutorDriverImpl),                 /* tp_basicsize */
+  0,                                               /* tp_itemsize */
+  (destructor) MesosExecutorDriverImpl_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 MesosExecutorDriver implementation",    /* tp_doc */
+  (traverseproc) MesosExecutorDriverImpl_traverse, /* tp_traverse */
+  (inquiry) MesosExecutorDriverImpl_clear,         /* tp_clear */
+  0,                                               /* tp_richcompare */
+  0,                                               /* tp_weaklistoffset */
+  0,                                               /* tp_iter */
+  0,                                               /* tp_iternext */
+  MesosExecutorDriverImpl_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) MesosExecutorDriverImpl_init,         /* tp_init */
+  0,                                               /* tp_alloc */
+  MesosExecutorDriverImpl_new,                     /* tp_new */
+};
+
+
+/**
+ * List of Python methods in MesosExecutorDriverImpl.
+ */
+PyMethodDef MesosExecutorDriverImpl_methods[] = {
+  { "start",
+    (PyCFunction) MesosExecutorDriverImpl_start,
+    METH_NOARGS,
+    "Start the driver to connect to Mesos"
+  },
+  { "stop",
+    (PyCFunction) MesosExecutorDriverImpl_stop,
+    METH_NOARGS,
+    "Stop the driver, disconnecting from Mesos"
+  },
+  { "abort",
+    (PyCFunction) MesosExecutorDriverImpl_abort,
+    METH_NOARGS,
+    "Abort the driver, disallowing calls from and to the driver"
+  },
+  { "join",
+    (PyCFunction) MesosExecutorDriverImpl_join,
+    METH_NOARGS,
+    "Wait for a running driver to disconnect from Mesos"
+  },
+  { "run",
+    (PyCFunction) MesosExecutorDriverImpl_run,
+    METH_NOARGS,
+    "Start a driver and run it, returning when it disconnects from Mesos"
+  },
+  { "sendStatusUpdate",
+    (PyCFunction) MesosExecutorDriverImpl_sendStatusUpdate,
+    METH_VARARGS,
+    "Send a status update for a task"
+  },
+  { "sendFrameworkMessage",
+    (PyCFunction) MesosExecutorDriverImpl_sendFrameworkMessage,
+    METH_VARARGS,
+    "Send a FrameworkMessage to a slave"
+  },
+  { NULL }  /* Sentinel */
+};
+
+
+/**
+ * Create, but don't initialize, a new MesosExecutorDriverImpl
+ * (called by Python before init method).
+ */
+PyObject* MesosExecutorDriverImpl_new(PyTypeObject *type,
+                                       PyObject *args,
+                                       PyObject *kwds)
+{
+  MesosExecutorDriverImpl *self;
+  self = (MesosExecutorDriverImpl *) type->tp_alloc(type, 0);
+  if (self != NULL) {
+    self->driver = NULL;
+    self->proxyExecutor = NULL;
+    self->pythonExecutor = NULL;
+  }
+  return (PyObject*) self;
+}
+
+
+/**
+ * Initialize a MesosExecutorDriverImpl with constructor arguments.
+ */
+int MesosExecutorDriverImpl_init(MesosExecutorDriverImpl *self,
+                                  PyObject *args,
+                                  PyObject *kwds)
+{
+  PyObject *pythonExecutor = NULL;
+
+  if (!PyArg_ParseTuple(args, "O", &pythonExecutor)) {
+    return -1;
+  }
+
+  if (pythonExecutor != NULL) {
+    PyObject* tmp = self->pythonExecutor;
+    Py_INCREF(pythonExecutor);
+    self->pythonExecutor = pythonExecutor;
+    Py_XDECREF(tmp);
+  }
+
+  if (self->driver != NULL) {
+    delete self->driver;
+    self->driver = NULL;
+  }
+
+  if (self->proxyExecutor != NULL) {
+    delete self->proxyExecutor;
+    self->proxyExecutor = NULL;
+  }
+
+  self->proxyExecutor = new ProxyExecutor(self);
+  self->driver = new MesosExecutorDriver(self->proxyExecutor);
+
+  return 0;
+}
+
+
+/**
+ * Free a MesosExecutorDriverImpl.
+ */
+void MesosExecutorDriverImpl_dealloc(MesosExecutorDriverImpl* self)
+{
+  if (self->driver != NULL) {
+    // We need to wrap the driver destructor in an "allow threads"
+    // macro since the MesosExecutorDriver destructor waits for the
+    // ExecutorProcess to terminate and there might be a thread that
+    // is trying to acquire the GIL to call through the
+    // ProxyExecutor. It will only be after this thread executes that
+    // the ExecutorProcess might actually get a terminate.
+    Py_BEGIN_ALLOW_THREADS
+    delete self->driver;
+    Py_END_ALLOW_THREADS
+    self->driver = NULL;
+  }
+
+  if (self->proxyExecutor != NULL) {
+    delete self->proxyExecutor;
+    self->proxyExecutor = NULL;
+  }
+
+  MesosExecutorDriverImpl_clear(self);
+  self->ob_type->tp_free((PyObject*) self);
+}
+
+
+/**
+ * Traverse fields of a MesosExecutorDriverImpl on a cyclic GC search.
+ * See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosExecutorDriverImpl_traverse(MesosExecutorDriverImpl* self,
+                                      visitproc visit,
+                                      void* arg)
+{
+  Py_VISIT(self->pythonExecutor);
+  return 0;
+}
+
+
+/**
+ * Clear fields of a MesosExecutorDriverImpl that can participate in
+ * GC cycles. See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosExecutorDriverImpl_clear(MesosExecutorDriverImpl* self)
+{
+  Py_CLEAR(self->pythonExecutor);
+  return 0;
+}
+
+
+PyObject* MesosExecutorDriverImpl_start(MesosExecutorDriverImpl* self)
+{
+  if (self->driver == NULL) {
+    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
+    return NULL;
+  }
+
+  Status status = self->driver->start();
+  return PyInt_FromLong(status); // Sets an exception if creating the int fails
+}
+
+
+PyObject* MesosExecutorDriverImpl_stop(MesosExecutorDriverImpl* self)
+{
+  if (self->driver == NULL) {
+    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
+    return NULL;
+  }
+
+  Status status = self->driver->stop();
+  return PyInt_FromLong(status); // Sets an exception if creating the int fails
+}
+
+
+PyObject* MesosExecutorDriverImpl_abort(MesosExecutorDriverImpl* self)
+{
+  if (self->driver == NULL) {
+    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
+    return NULL;
+  }
+
+  Status status = self->driver->abort();
+  return PyInt_FromLong(status); // Sets an exception if creating the int fails
+}
+
+
+PyObject* MesosExecutorDriverImpl_join(MesosExecutorDriverImpl* self)
+{
+  if (self->driver == NULL) {
+    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
+    return NULL;
+  }
+
+  Status status;
+  Py_BEGIN_ALLOW_THREADS
+  status = self->driver->join();
+  Py_END_ALLOW_THREADS
+  return PyInt_FromLong(status); // Sets an exception if creating the int fails
+}
+
+
+PyObject* MesosExecutorDriverImpl_run(MesosExecutorDriverImpl* self)
+{
+  if (self->driver == NULL) {
+    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
+    return NULL;
+  }
+
+  Status status;
+  Py_BEGIN_ALLOW_THREADS
+  status = self->driver->run();
+  Py_END_ALLOW_THREADS
+  return PyInt_FromLong(status); // Sets an exception if creating the int fails
+}
+
+
+PyObject* MesosExecutorDriverImpl_sendStatusUpdate(
+    MesosExecutorDriverImpl* self,
+    PyObject* args)
+{
+  if (self->driver == NULL) {
+    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
+    return NULL;
+  }
+
+  PyObject* statusObj = NULL;
+  TaskStatus taskStatus;
+  if (!PyArg_ParseTuple(args, "O", &statusObj)) {
+    return NULL;
+  }
+  if (!readPythonProtobuf(statusObj, &taskStatus)) {
+    PyErr_Format(PyExc_Exception,
+                 "Could not deserialize Python TaskStatus");
+    return NULL;
+  }
+
+  Status status = self->driver->sendStatusUpdate(taskStatus);
+  return PyInt_FromLong(status); // Sets an exception if creating the int fails
+}
+
+
+PyObject* MesosExecutorDriverImpl_sendFrameworkMessage(
+    MesosExecutorDriverImpl* self,
+    PyObject* args)
+{
+  if (self->driver == NULL) {
+    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
+    return NULL;
+  }
+
+  const char* data;
+  int length;
+  if (!PyArg_ParseTuple(args, "s#", &data, &length)) {
+    return NULL;
+  }
+
+  Status status = self->driver->sendFrameworkMessage(string(data, length));
+  return PyInt_FromLong(status); // Sets an exception if creating the int fails
+}
+
+} // namespace python {
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/src/mesos/native/mesos_executor_driver_impl.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/mesos_executor_driver_impl.hpp b/src/python/native/src/mesos/native/mesos_executor_driver_impl.hpp
new file mode 100644
index 0000000..7245414
--- /dev/null
+++ b/src/python/native/src/mesos/native/mesos_executor_driver_impl.hpp
@@ -0,0 +1,105 @@
+/**
+ * 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_EXECUTOR_DRIVER_IMPL_HPP
+#define MESOS_EXECUTOR_DRIVER_IMPL_HPP
+
+#include <mesos/executor.hpp>
+
+
+namespace mesos { namespace python {
+
+class ProxyExecutor;
+
+/**
+ * Python object structure for MesosExecutorDriverImpl objects.
+ */
+struct MesosExecutorDriverImpl {
+    PyObject_HEAD
+    /* Type-specific fields go here. */
+    MesosExecutorDriver* driver;
+    ProxyExecutor* proxyExecutor;
+    PyObject* pythonExecutor;
+};
+
+/**
+ * Python type object for MesosExecutorDriverImpl.
+ */
+extern PyTypeObject MesosExecutorDriverImplType;
+
+/**
+ * List of Python methods in MesosExecutorDriverImpl.
+ */
+extern PyMethodDef MesosExecutorDriverImpl_methods[];
+
+/**
+ * Create, but don't initialize, a new MesosExecutorDriverImpl
+ * (called by Python before init method).
+ */
+PyObject* MesosExecutorDriverImpl_new(PyTypeObject *type,
+                                      PyObject *args,
+                                      PyObject *kwds);
+
+/**
+ * Initialize a MesosExecutorDriverImpl with constructor arguments.
+ */
+int MesosExecutorDriverImpl_init(MesosExecutorDriverImpl *self,
+                                 PyObject *args,
+                                 PyObject *kwds);
+
+/**
+ * Free a MesosExecutorDriverImpl.
+ */
+void MesosExecutorDriverImpl_dealloc(MesosExecutorDriverImpl* self);
+
+/**
+ * Traverse fields of a MesosExecutorDriverImpl on a cyclic GC search.
+ * See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosExecutorDriverImpl_traverse(MesosExecutorDriverImpl* self,
+                                     visitproc visit,
+                                     void* arg);
+/**
+ * Clear fields of a MesosExecutorDriverImpl that can participate in
+ * GC cycles. See http://docs.python.org/extending/newtypes.html.
+ */
+int MesosExecutorDriverImpl_clear(MesosExecutorDriverImpl* self);
+
+// MesosExecutorDriverImpl methods
+PyObject* MesosExecutorDriverImpl_start(MesosExecutorDriverImpl* self);
+
+PyObject* MesosExecutorDriverImpl_stop(MesosExecutorDriverImpl* self);
+
+PyObject* MesosExecutorDriverImpl_abort(MesosExecutorDriverImpl* self);
+
+PyObject* MesosExecutorDriverImpl_join(MesosExecutorDriverImpl* self);
+
+PyObject* MesosExecutorDriverImpl_run(MesosExecutorDriverImpl* self);
+
+PyObject* MesosExecutorDriverImpl_sendStatusUpdate(
+    MesosExecutorDriverImpl* self,
+    PyObject* args);
+
+PyObject* MesosExecutorDriverImpl_sendFrameworkMessage(
+    MesosExecutorDriverImpl* self,
+    PyObject* args);
+
+} // namespace python {
+} // namespace mesos {
+
+#endif /* MESOS_EXECUTOR_DRIVER_IMPL_HPP */

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.cpp b/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.cpp
new file mode 100644
index 0000000..e014eed
--- /dev/null
+++ b/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.cpp
@@ -0,0 +1,634 @@
+/**
+ * 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 "mesos_scheduler_driver_impl.hpp"
+#include "module.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"
+  },
+  { "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"
+  },
+  { "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)
+{
+  PyObject* schedulerObj = NULL;
+  PyObject* frameworkObj = NULL;
+  const char* master;
+  PyObject* credentialObj = NULL;
+
+  if (!PyArg_ParseTuple(
+      args, "OOs|O", &schedulerObj, &frameworkObj, &master, &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, credential);
+  } else {
+    self->driver = new MesosSchedulerDriver(
+        self->proxyScheduler, framework, master);
+  }
+
+  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_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_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/c5a68be1/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
new file mode 100644
index 0000000..8c285ae
--- /dev/null
+++ b/src/python/native/src/mesos/native/mesos_scheduler_driver_impl.hpp
@@ -0,0 +1,125 @@
+/**
+ * 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_declineOffer(
+    MesosSchedulerDriverImpl* self,
+    PyObject* args);
+
+PyObject* MesosSchedulerDriverImpl_reviveOffers(MesosSchedulerDriverImpl* self);
+
+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/c5a68be1/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
new file mode 100644
index 0000000..6d0de5f
--- /dev/null
+++ b/src/python/native/src/mesos/native/module.cpp
@@ -0,0 +1,102 @@
+/**
+ * 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(void)
+{
+  // 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/c5a68be1/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
new file mode 100644
index 0000000..1c35e2e
--- /dev/null
+++ b/src/python/native/src/mesos/native/module.hpp
@@ -0,0 +1,138 @@
+/**
+ * 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 */


[3/3] git commit: Refactored the python bindings into multiple modules.

Posted by be...@apache.org.
Refactored the python bindings into multiple modules.

The existing module has been split into two separate ones:

- mesos.interface - This contains the stub implementations for the
                    Executor/Scheduler as well as the protobufs.
- mesos.native - The old _mesos module.

There is also a base metapackage `mesos` that allows a potential `pip
install mesos` to correctly install everything required. While
mesos.interface can now be uploaded to the cheeseshop, mesos.native
has not changed and will need some more work first.

Review: https://reviews.apache.org/r/23224


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/c5a68be1
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/c5a68be1
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/c5a68be1

Branch: refs/heads/master
Commit: c5a68be12a68cba407d9e3364f6f8f405cbe7d79
Parents: 3047bbe
Author: Thomas Rampelberg <th...@saunter.org>
Authored: Thu Jul 31 21:11:26 2014 -0700
Committer: Benjamin Hindman <be...@gmail.com>
Committed: Thu Jul 31 22:45:26 2014 -0700

----------------------------------------------------------------------
 Makefile.am                                     |   8 +-
 configure.ac                                    |  28 +
 docs/upgrades.md                                |   5 +
 mpi/mpiexec-mesos.in                            |  24 +-
 mpi/mpiexec-mesos.py                            |   9 +-
 src/Makefile.am                                 |  98 +--
 src/examples/python/test-containerizer.in       |  25 +-
 src/examples/python/test-executor.in            |  25 +-
 src/examples/python/test-framework.in           |  25 +-
 src/examples/python/test_containerizer.py       |   5 +-
 src/examples/python/test_executor.py            |  13 +-
 src/examples/python/test_framework.py           |  11 +-
 src/python/interface/setup.py.in                |  35 +
 src/python/interface/src/mesos/__init__.py      |   6 +
 .../interface/src/mesos/interface/__init__.py   | 347 ++++++++++
 src/python/native/ext_modules.py.in             | 131 ++++
 .../native/mesos_executor_driver_impl.cpp       | 349 ----------
 .../native/mesos_executor_driver_impl.hpp       | 105 ---
 .../native/mesos_scheduler_driver_impl.cpp      | 634 -------------------
 .../native/mesos_scheduler_driver_impl.hpp      | 125 ----
 src/python/native/module.cpp                    | 102 ---
 src/python/native/module.hpp                    | 138 ----
 src/python/native/proxy_executor.cpp            | 275 --------
 src/python/native/proxy_executor.hpp            |  66 --
 src/python/native/proxy_scheduler.cpp           | 386 -----------
 src/python/native/proxy_scheduler.hpp           |  74 ---
 src/python/native/setup.py.in                   |  38 ++
 src/python/native/src/mesos/__init__.py         |   6 +
 src/python/native/src/mesos/native/__init__.py  |  21 +
 .../mesos/native/mesos_executor_driver_impl.cpp | 349 ++++++++++
 .../mesos/native/mesos_executor_driver_impl.hpp | 105 +++
 .../native/mesos_scheduler_driver_impl.cpp      | 634 +++++++++++++++++++
 .../native/mesos_scheduler_driver_impl.hpp      | 125 ++++
 src/python/native/src/mesos/native/module.cpp   | 102 +++
 src/python/native/src/mesos/native/module.hpp   | 138 ++++
 .../native/src/mesos/native/proxy_executor.cpp  | 275 ++++++++
 .../native/src/mesos/native/proxy_executor.hpp  |  66 ++
 .../native/src/mesos/native/proxy_scheduler.cpp | 386 +++++++++++
 .../native/src/mesos/native/proxy_scheduler.hpp |  74 +++
 src/python/protocol/setup.py.in                 |  35 +
 src/python/protocol/src/mesos/__init__.py       |   6 +
 .../protocol/src/mesos/protocol/__init__.py     |  15 +
 src/python/setup.py.in                          | 186 ++----
 src/python/src/mesos.py                         | 361 -----------
 src/python/src/mesos/__init__.py                |   6 +
 45 files changed, 3123 insertions(+), 2854 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/Makefile.am
----------------------------------------------------------------------
diff --git a/Makefile.am b/Makefile.am
index b91d8cf..e4ffa35 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,12 +27,14 @@ PHONY_TARGETS =
 
 # Since we generate several files in src/ with config.status, make
 # sure they're regenerated before we recurse into the src directory.
-all-recursive: src/python/setup.py src/java/mesos.pom
-
+all-recursive: src/python/setup.py			\
+	src/python/interface/setup.py			\
+	src/python/native/setup.py			\
+	src/java/mesos.pom
 
 # Standard stuff.
 EXTRA_DIST += bootstrap LICENSE NOTICE README.md	\
-  support/atexit.sh support/colors.sh
+	support/atexit.sh support/colors.sh
 
 
 # MPI framework.

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/configure.ac
----------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index e747208..a9cc6df 100644
--- a/configure.ac
+++ b/configure.ac
@@ -822,6 +822,31 @@ There are two possible workarounds for this issue:
 -------------------------------------------------------------------])])
         ])
 
+  AC_MSG_CHECKING([for an old installation of the Mesos egg (before 0.20.0)])
+
+  $PYTHON -c "import mesos; mesos._mesos" &> /dev/null
+
+  if test $? = 0; then
+    pymodulelocation=`python -c \
+      "import mesos; import os; print os.path.dirname(mesos.__path__[[0]])" \
+      2> /dev/null`
+  fi
+
+  AS_IF([test -z "$pymodulelocation"],
+        [AC_MSG_RESULT([no])],
+        [AC_MSG_ERROR([yes
+-------------------------------------------------------------------
+It appears that you currently have a native Python egg installed
+from a version before 0.20.0. This conflicts with the egg in this
+version.
+
+There are two possible workarounds for this issue:
+    1. Disable Python bindings by configuring with --disable-python.
+    2. Uninstall the legacy egg from your Python installation. This
+       might require you doing:
+         rm -rf $pymodulelocation
+-------------------------------------------------------------------])])
+
   # Determine how the generated Python egg's will get named, used in
   # the Makefile to keep the targets from being rerun.
   PYTHON_EGG_POSTFIX=`$PYTHON -c \
@@ -841,6 +866,9 @@ There are two possible workarounds for this issue:
   AC_CONFIG_FILES([src/examples/python/test-containerizer],
                   [chmod +x src/examples/python/test-containerizer])
   AC_CONFIG_FILES([src/python/setup.py])
+  AC_CONFIG_FILES([src/python/interface/setup.py])
+  AC_CONFIG_FILES([src/python/native/ext_modules.py])
+  AC_CONFIG_FILES([src/python/native/setup.py])
 
   # When clang is being used, make sure that the distutils python-
   # config cflags extraction does not cause build errors (MESOS-1079).

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/docs/upgrades.md
----------------------------------------------------------------------
diff --git a/docs/upgrades.md b/docs/upgrades.md
index 919f010..2d518be 100644
--- a/docs/upgrades.md
+++ b/docs/upgrades.md
@@ -5,6 +5,11 @@ layout: documentation
 # Upgrading Mesos
 This document serves as a guide for users who wish to upgrade an existing mesos cluster. Some versions require particular upgrade techniques when upgrading a running cluster. Some upgrades will have incompatible changes.
 
+## Upgrading from 0.19.x to 0.20.x.
+
+* Python bindings have changed their structure. There are now sub-modules which allow you to use either the interfaces and/or the native driver.
+    - `import mesos.native` for the native drivers
+    - `import mesos.interface` for the stub implementations and protobufs
 
 ## Upgrading from 0.18.x to 0.19.x.
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/mpi/mpiexec-mesos.in
----------------------------------------------------------------------
diff --git a/mpi/mpiexec-mesos.in b/mpi/mpiexec-mesos.in
index da0733f..8812ee2 100644
--- a/mpi/mpiexec-mesos.in
+++ b/mpi/mpiexec-mesos.in
@@ -29,11 +29,25 @@ test ! -e ${PROTOBUF_EGG} && \
   echo "${RED}Failed to find ${PROTOBUF_EGG}${NORMAL}" && \
   exit 1
 
-MESOS_EGG=`echo ${MESOS_BUILD_DIR}/src/python/dist/mesos*.egg`
+MESOS_EGGS=""
+for egg in interface native; do
+  base_dir="${MESOS_BUILD_DIR}/src/python/${egg}/dist/"
+  egg_path="${base_dir}mesos.${egg}-@PACKAGE_VERSION@"
 
-test ! -e ${MESOS_EGG} && \
-  echo "${RED}Failed to find ${MESOS_EGG}${NORMAL}" && \
-  exit 1
+  if [[ ${egg} == "native" ]]; then
+    egg_path+="@PYTHON_EGG_POSTFIX@"
+  else
+    egg_path+="@PYTHON_EGG_PUREPY_POSTFIX@"
+  fi
+
+  egg_path+=".egg"
+
+  test ! -e ${egg_path} && \
+    echo "${RED}Failed to find ${egg_path}${NORMAL}" && \
+    exit 1
+
+  MESOS_EGGS+="${egg_path}:"
+done
 
 SCRIPT=${MESOS_SOURCE_DIR}/mpi/mpiexec-mesos.py
 
@@ -41,5 +55,5 @@ test ! -e ${SCRIPT} && \
   echo "${RED}Failed to find ${SCRIPT}${NORMAL}" && \
   exit 1
 
-PYTHONPATH="${DISTRIBUTE_EGG}:${MESOS_EGG}:${PROTOBUF_EGG}" \
+PYTHONPATH="${DISTRIBUTE_EGG}:${PROTOBUF_EGG}:${MESOS_EGGS}" \
   exec ${PYTHON} ${SCRIPT} "${@}"

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/mpi/mpiexec-mesos.py
----------------------------------------------------------------------
diff --git a/mpi/mpiexec-mesos.py b/mpi/mpiexec-mesos.py
index 0ab5016..d86c85b 100755
--- a/mpi/mpiexec-mesos.py
+++ b/mpi/mpiexec-mesos.py
@@ -1,7 +1,8 @@
 #!/usr/bin/env python
 
-import mesos
-import mesos_pb2
+import mesos.interface
+import mesos.native
+from mesos.interface import mesos_pb2
 import os
 import sys
 import time
@@ -36,7 +37,7 @@ def mpiexec():
   call([MPICH2PATH + 'mpdallexit', MPD_PID])
 
 
-class MPIScheduler(mesos.Scheduler):
+class MPIScheduler(mesos.interface.Scheduler):
 
   def __init__(self, options, ip, port):
     self.mpdsLaunched = 0
@@ -209,7 +210,7 @@ if __name__ == "__main__":
   else:
     framework.name = "MPI: %s" % MPI_PROGRAM[0]
 
-  driver = mesos.MesosSchedulerDriver(
+  driver = mesos.native.MesosSchedulerDriver(
     scheduler,
     framework,
     args[0])

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index b660d91..c7ed168 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -135,8 +135,8 @@ JAVA_PROTOS =								\
   java/generated/org/apache/mesos/containerizer/Protos.java
 
 PYTHON_PROTOS =								\
-  python/src/mesos_pb2.py						\
-  python/src/containerizer_pb2.py
+  python/interface/src/mesos/interface/mesos_pb2.py			\
+  python/interface/src/mesos/interface/containerizer_pb2.py
 
 BUILT_SOURCES += $(CXX_PROTOS) $(JAVA_PROTOS) $(PYTHON_PROTOS)
 CLEANFILES += $(CXX_PROTOS) $(JAVA_PROTOS) $(PYTHON_PROTOS)
@@ -198,19 +198,19 @@ java/generated/org/apache/mesos/scheduler/Protos.java: $(SCHEDULER_PROTO)
 	$(MKDIR_P)  $(@D)
 	$(PROTOC) $(PROTOCFLAGS) --java_out=java/generated $^
 
-python/src/mesos_pb2.py: $(MESOS_PROTO)
+python/interface/src/mesos/interface/mesos_pb2.py: $(MESOS_PROTO)
 	$(MKDIR_P) $(@D)
-	$(PROTOC) $(PROTOCFLAGS) --python_out=python/src $^
+	$(PROTOC) $(PROTOCFLAGS) --python_out=python/interface/src/mesos/interface $^
 
-python/src/containerizer_pb2.py: $(CONTAINERIZER_PROTO)
+python/interface/src/mesos/interface/containerizer_pb2.py: $(CONTAINERIZER_PROTO)
 	$(MKDIR_P) $(@D)
 	$(PROTOC) -I$(top_srcdir)/include/mesos/containerizer		\
-		$(PROTOCFLAGS) --python_out=python/src $^
+		$(PROTOCFLAGS) --python_out=python/interface/src/mesos/interface $^
 
-python/src/scheduler_pb2.py: $(SCHEDULER_PROTO)
+python/interface/src/mesos/interface/scheduler_pb2.py: $(SCHEDULER_PROTO)
 	$(MKDIR_P) $(@D)
 	$(PROTOC) -I$(top_srcdir)/include/mesos/scheduler		\
-		$(PROTOCFLAGS) --python_out=python/src $^
+		$(PROTOCFLAGS) --python_out=python/interface/src/mesos/interface $^
 
 # We even use a convenience library for most of Mesos so that we can
 # exclude third party libraries so setuptools/distribute can build a
@@ -892,16 +892,24 @@ PHONY_TARGETS += clean-java
 
 # Python files listed outside HAS_PYTHON so they are included with the
 # distribution unconditionally.
-EXTRA_DIST += python/src/mesos.py					\
-	      python/native/mesos_executor_driver_impl.cpp		\
-	      python/native/mesos_executor_driver_impl.hpp		\
-	      python/native/mesos_scheduler_driver_impl.cpp		\
-	      python/native/mesos_scheduler_driver_impl.hpp		\
-	      python/native/module.cpp python/native/module.hpp		\
-	      python/native/proxy_executor.cpp				\
-	      python/native/proxy_executor.hpp				\
-	      python/native/proxy_scheduler.cpp				\
-	      python/native/proxy_scheduler.hpp
+PYTHON_SOURCE =									\
+	python/src/mesos/__init__.py						\
+	python/interface/src/mesos/__init__.py					\
+	python/interface/src/mesos/interface/__init__.py			\
+	python/native/src/mesos/__init__.py					\
+	python/native/src/mesos/native/__init__.py				\
+	python/native/src/mesos/native/mesos_executor_driver_impl.cpp		\
+	python/native/src/mesos/native/mesos_executor_driver_impl.hpp		\
+	python/native/src/mesos/native/mesos_scheduler_driver_impl.cpp		\
+	python/native/src/mesos/native/mesos_scheduler_driver_impl.hpp		\
+	python/native/src/mesos/native/module.cpp				\
+	python/native/src/mesos/native/module.hpp				\
+	python/native/src/mesos/native/proxy_executor.cpp			\
+	python/native/src/mesos/native/proxy_executor.hpp			\
+	python/native/src/mesos/native/proxy_scheduler.cpp			\
+	python/native/src/mesos/native/proxy_scheduler.hpp
+
+EXTRA_DIST += $(PYTHON_SOURCE)
 
 if HAS_PYTHON
 # Used for building Python eggs.
@@ -921,7 +929,7 @@ $(PROTOBUF_EGG):
 
 CLEANFILES += $(PROTOBUF_EGG)
 
-# This builds a Python egg against libmesos_no_3rdparty.a that is
+# This builds the mesos.native egg against libmesos_no_3rdparty.a that is
 # self-contained. It currently depends on the libraries in 3rdparty
 # being built as .a's. (If this is changed, the setup.py will need to
 # be edited).
@@ -936,44 +944,40 @@ CLEANFILES += $(PROTOBUF_EGG)
 # system versions of our dependencies (since we won't be able to
 # create a standalone egg anyways).
 
-MESOS_EGG = python/dist/mesos-$(PACKAGE_VERSION)$(PYTHON_EGG_POSTFIX).egg
+PHONY_TARGETS += $(PYTHON_SOURCE)
 
-$(MESOS_EGG): python/setup.py $(srcdir)/python/src/mesos.py		\
-              $(PYTHON_PROTOS) libmesos_no_3rdparty.la			\
-              $(PROTOBUF_EGG)
-	@echo "Building Mesos Python egg ..."
-	@if test "$(top_srcdir)" != "$(top_builddir)"; then		\
-	  $(MKDIR_P) python/src;					\
-	  cp -pf $(srcdir)/python/src/mesos.py python/src;		\
-	fi
-	@LIBS="$(LIBS)" CC="$(CC)" CXX="$(CXX)"				\
-	CPPFLAGS="$(PYTHON_CPPFLAGS)" CFLAGS="$(PYTHON_CFLAGS)"		\
-	LDFLAGS="$(PYTHON_LDFLAGS)"					\
-	PYTHONPATH=$(DISTRIBUTE_EGG) $(PYTHON) python/setup.py bdist_egg
+$(PYTHON_SOURCE):
+	test "$(top_srcdir)" = "$(top_builddir)" ||				\
+		($(MKDIR_P) $(@D) && cp -pf $(srcdir)/$@ $@)
 
-CLEANFILES += $(MESOS_EGG) python/build/temp.*/native/*.o python/build/lib.*/*
+MESOS_EGGS =										\
+	python/dist/mesos-$(PACKAGE_VERSION)$(PYTHON_EGG_PUREPY_POSTFIX).egg		\
+	python/interface/dist/mesos.interface-$(PACKAGE_VERSION)$(PYTHON_EGG_PUREPY_POSTFIX).egg	\
+	python/native/dist/mesos.native-$(PACKAGE_VERSION)$(PYTHON_EGG_POSTFIX).egg
+
+$(MESOS_EGGS):									\
+		$(PYTHON_PROTOS)						\
+		$(PYTHON_SOURCE)						\
+		libmesos_no_3rdparty.la						\
+		$(PROTOBUF_EGG)
+	@cd `echo $@ | awk -F"dist" '{print $$1}'` &&				\
+	LIBS="$(LIBS)" CC="$(CC)" CXX="$(CXX)"					\
+	CFLAGS="$(PYTHON_CFLAGS)" CPPFLAGS="$(PYTHON_CPPFLAGS)"			\
+	LDFLAGS="$(PYTHON_LDFLAGS)"						\
+	PYTHONPATH=$(DISTRIBUTE_EGG) $(PYTHON) setup.py bdist_egg
+
+CLEANFILES += $(MESOS_EGGS) python/*/build python/*/dist $(PYTHON_SOURCE)
 
 # Make sure the egg gets built via 'make all'.
-all-local: $(MESOS_EGG)
+all-local: $(MESOS_EGGS)
 endif # HAS_PYTHON
 
-# Note that to clean up the copied Python files we have to 'chmod u+w
-# python/native' because creating a distribution can eliminate write
-# permissions for the owner which are conserved even after we 'cp -p'
-# so we won't be able to delete the files until we update permissions.
-#
-# We remove mesos-*.egg here to make sure any older versions of the
-# egg or versions for different architectures are removed.
 clean-python:
-	test "$(top_srcdir)" = "$(top_builddir)" ||			\
-	  (chmod -R u+w python/native;					\
-	   rm -rf python/src/mesos.py python/native)
-	-rm -rf python/src/mesos.egg-info python/build
-	-rm -f python/dist/mesos-*.egg
+	find python -name "build" -o -name "dist" -o -name "*.pyc"		\
+		-o -name "*.egg-info" | xargs rm -rf
 
 PHONY_TARGETS += clean-python
 
-
 # Test (make check) binaries.
 check_PROGRAMS += low-level-scheduler-libprocess
 low_level_scheduler_libprocess_SOURCES = examples/low_level_scheduler_libprocess.cpp

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/examples/python/test-containerizer.in
----------------------------------------------------------------------
diff --git a/src/examples/python/test-containerizer.in b/src/examples/python/test-containerizer.in
index 569519b..f71828d 100644
--- a/src/examples/python/test-containerizer.in
+++ b/src/examples/python/test-containerizer.in
@@ -30,12 +30,25 @@ test ! -e ${PROTOBUF_EGG} && \
   echo "${RED}Failed to find ${PROTOBUF_EGG}${NORMAL}" && \
   exit 1
 
-MESOS_EGG=${MESOS_BUILD_DIR}/src/python/dist/
-MESOS_EGG+=mesos-@PACKAGE_VERSION@@PYTHON_EGG_POSTFIX@.egg
+MESOS_EGGS=""
+for egg in interface native; do
+  base_dir="${MESOS_BUILD_DIR}/src/python/${egg}/dist/"
+  egg_path="${base_dir}mesos.${egg}-@PACKAGE_VERSION@"
 
-test ! -e ${MESOS_EGG} && \
-  echo "${RED}Failed to find ${MESOS_EGG}${NORMAL}" && \
-  exit 1
+  if [[ ${egg} == "native" ]]; then
+    egg_path+="@PYTHON_EGG_POSTFIX@"
+  else
+    egg_path+="@PYTHON_EGG_PUREPY_POSTFIX@"
+  fi
+
+  egg_path+=".egg"
+
+  test ! -e ${egg_path} && \
+    echo "${RED}Failed to find ${egg_path}${NORMAL}" && \
+    exit 1
+
+  MESOS_EGGS+="${egg_path}:"
+done
 
 SCRIPT=${MESOS_SOURCE_DIR}/src/examples/python/test_containerizer.py
 
@@ -43,5 +56,5 @@ test ! -e ${SCRIPT} && \
   echo "${RED}Failed to find ${SCRIPT}${NORMAL}" && \
   exit 1
 
-PYTHONPATH="${DISTRIBUTE_EGG}:${MESOS_EGG}:${PROTOBUF_EGG}" \
+PYTHONPATH="${DISTRIBUTE_EGG}:${PROTOBUF_EGG}:${MESOS_EGGS}" \
   exec ${PYTHON} ${SCRIPT} "${@}"

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/examples/python/test-executor.in
----------------------------------------------------------------------
diff --git a/src/examples/python/test-executor.in b/src/examples/python/test-executor.in
index 7e8875f..b22e7a7 100644
--- a/src/examples/python/test-executor.in
+++ b/src/examples/python/test-executor.in
@@ -30,12 +30,25 @@ test ! -e ${PROTOBUF_EGG} && \
   echo "${RED}Failed to find ${PROTOBUF_EGG}${NORMAL}" && \
   exit 1
 
-MESOS_EGG=${MESOS_BUILD_DIR}/src/python/dist/
-MESOS_EGG+=mesos-@PACKAGE_VERSION@@PYTHON_EGG_POSTFIX@.egg
+MESOS_EGGS=""
+for egg in interface native; do
+  base_dir="${MESOS_BUILD_DIR}/src/python/${egg}/dist/"
+  egg_path="${base_dir}mesos.${egg}-@PACKAGE_VERSION@"
 
-test ! -e ${MESOS_EGG} && \
-  echo "${RED}Failed to find ${MESOS_EGG}${NORMAL}" && \
-  exit 1
+  if [[ ${egg} == "native" ]]; then
+    egg_path+="@PYTHON_EGG_POSTFIX@"
+  else
+    egg_path+="@PYTHON_EGG_PUREPY_POSTFIX@"
+  fi
+
+  egg_path+=".egg"
+
+  test ! -e ${egg_path} && \
+    echo "${RED}Failed to find ${egg_path}${NORMAL}" && \
+    exit 1
+
+  MESOS_EGGS+="${egg_path}:"
+done
 
 SCRIPT=${MESOS_SOURCE_DIR}/src/examples/python/test_executor.py
 
@@ -43,5 +56,5 @@ test ! -e ${SCRIPT} && \
   echo "${RED}Failed to find ${SCRIPT}${NORMAL}" && \
   exit 1
 
-PYTHONPATH="${DISTRIBUTE_EGG}:${MESOS_EGG}:${PROTOBUF_EGG}" \
+PYTHONPATH="${DISTRIBUTE_EGG}:${PROTOBUF_EGG}:${MESOS_EGGS}" \
   exec ${PYTHON} ${SCRIPT} "${@}"

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/examples/python/test-framework.in
----------------------------------------------------------------------
diff --git a/src/examples/python/test-framework.in b/src/examples/python/test-framework.in
index c4683b9..64fb1dd 100644
--- a/src/examples/python/test-framework.in
+++ b/src/examples/python/test-framework.in
@@ -30,12 +30,25 @@ test ! -e ${PROTOBUF_EGG} && \
   echo "${RED}Failed to find ${PROTOBUF_EGG}${NORMAL}" && \
   exit 1
 
-MESOS_EGG=${MESOS_BUILD_DIR}/src/python/dist/
-MESOS_EGG+=mesos-@PACKAGE_VERSION@@PYTHON_EGG_POSTFIX@.egg
+MESOS_EGGS=""
+for egg in interface native; do
+  base_dir="${MESOS_BUILD_DIR}/src/python/${egg}/dist/"
+  egg_path="${base_dir}mesos.${egg}-@PACKAGE_VERSION@"
 
-test ! -e ${MESOS_EGG} && \
-  echo "${RED}Failed to find ${MESOS_EGG}${NORMAL}" && \
-  exit 1
+  if [[ ${egg} == "native" ]]; then
+    egg_path+="@PYTHON_EGG_POSTFIX@"
+  else
+    egg_path+="@PYTHON_EGG_PUREPY_POSTFIX@"
+  fi
+
+  egg_path+=".egg"
+
+  test ! -e ${egg_path} && \
+    echo "${RED}Failed to find ${egg_path}${NORMAL}" && \
+    exit 1
+
+  MESOS_EGGS+="${egg_path}:"
+done
 
 SCRIPT=${MESOS_SOURCE_DIR}/src/examples/python/test_framework.py
 
@@ -47,5 +60,5 @@ test ! -e ${SCRIPT} && \
 # framework is able to find the executor.
 cd `dirname ${0}`
 
-PYTHONPATH="${DISTRIBUTE_EGG}:${MESOS_EGG}:${PROTOBUF_EGG}" \
+PYTHONPATH="${DISTRIBUTE_EGG}:${PROTOBUF_EGG}:${MESOS_EGGS}" \
   exec ${PYTHON} ${SCRIPT} "${@}"

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/examples/python/test_containerizer.py
----------------------------------------------------------------------
diff --git a/src/examples/python/test_containerizer.py b/src/examples/python/test_containerizer.py
index c65d891..8e154b0 100644
--- a/src/examples/python/test_containerizer.py
+++ b/src/examples/python/test_containerizer.py
@@ -40,10 +40,9 @@ import sys
 import struct
 import time
 import google
-import mesos
-import mesos_pb2
-import containerizer_pb2
 
+from mesos.interface import containerizer_pb2
+from mesos.interface import mesos_pb2
 
 # Render a string describing how to use this script.
 def use(argv0, methods):

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/examples/python/test_executor.py
----------------------------------------------------------------------
diff --git a/src/examples/python/test_executor.py b/src/examples/python/test_executor.py
index 065b50a..f29da95 100755
--- a/src/examples/python/test_executor.py
+++ b/src/examples/python/test_executor.py
@@ -7,9 +7,9 @@
 # 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.
@@ -20,10 +20,11 @@ import sys
 import threading
 import time
 
-import mesos
-import mesos_pb2
+import mesos.interface
+from mesos.interface import mesos_pb2
+import mesos.native
 
-class MyExecutor(mesos.Executor):
+class MyExecutor(mesos.interface.Executor):
     def launchTask(self, driver, task):
         # Create a thread to run the task. Tasks should always be run in new
         # threads or processes, rather than inside launchTask itself.
@@ -54,5 +55,5 @@ class MyExecutor(mesos.Executor):
 
 if __name__ == "__main__":
     print "Starting executor"
-    driver = mesos.MesosExecutorDriver(MyExecutor())
+    driver = mesos.native.MesosExecutorDriver(MyExecutor())
     sys.exit(0 if driver.run() == mesos_pb2.DRIVER_STOPPED else 1)

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/examples/python/test_framework.py
----------------------------------------------------------------------
diff --git a/src/examples/python/test_framework.py b/src/examples/python/test_framework.py
index fce090f..75ca509 100755
--- a/src/examples/python/test_framework.py
+++ b/src/examples/python/test_framework.py
@@ -20,15 +20,16 @@ import os
 import sys
 import time
 
-import mesos
-import mesos_pb2
+import mesos.interface
+from mesos.interface import mesos_pb2
+import mesos.native
 
 TOTAL_TASKS = 5
 
 TASK_CPUS = 1
 TASK_MEM = 32
 
-class TestScheduler(mesos.Scheduler):
+class TestScheduler(mesos.interface.Scheduler):
     def __init__(self, executor):
         self.executor = executor
         self.taskData = {}
@@ -153,7 +154,7 @@ if __name__ == "__main__":
 
         framework.principal = os.getenv("DEFAULT_PRINCIPAL")
 
-        driver = mesos.MesosSchedulerDriver(
+        driver = mesos.native.MesosSchedulerDriver(
             TestScheduler(executor),
             framework,
             sys.argv[1],
@@ -161,7 +162,7 @@ if __name__ == "__main__":
     else:
         framework.principal = "test-framework-python"
 
-        driver = mesos.MesosSchedulerDriver(
+        driver = mesos.native.MesosSchedulerDriver(
             TestScheduler(executor),
             framework,
             sys.argv[1])

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/interface/setup.py.in
----------------------------------------------------------------------
diff --git a/src/python/interface/setup.py.in b/src/python/interface/setup.py.in
new file mode 100644
index 0000000..afcaf7a
--- /dev/null
+++ b/src/python/interface/setup.py.in
@@ -0,0 +1,35 @@
+# 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.
+
+config = {
+    'name': 'mesos.interface',
+    'version': '@PACKAGE_VERSION@',
+    'description': 'Mesos interfaces',
+    'author': 'Apache Mesos',
+    'author_email': 'dev@mesos.apache.org',
+    'url': 'http://pypi.python.org/pypi/mesos.interface',
+    'namespace_packages': [ 'mesos' ],
+    'packages': [ 'mesos', 'mesos.interface' ],
+    'package_dir': { '': 'src' },
+    'install_requires': [ 'protobuf>=2.5.0,<3' ],
+    'license': 'Apache 2.0',
+    'keywords': 'mesos',
+    'classifiers': [ ]
+}
+
+from setuptools import setup
+
+setup(**config)

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/interface/src/mesos/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/interface/src/mesos/__init__.py b/src/python/interface/src/mesos/__init__.py
new file mode 100644
index 0000000..f48ad10
--- /dev/null
+++ b/src/python/interface/src/mesos/__init__.py
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+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/c5a68be1/src/python/interface/src/mesos/interface/__init__.py
----------------------------------------------------------------------
diff --git a/src/python/interface/src/mesos/interface/__init__.py b/src/python/interface/src/mesos/interface/__init__.py
new file mode 100644
index 0000000..818f41b
--- /dev/null
+++ b/src/python/interface/src/mesos/interface/__init__.py
@@ -0,0 +1,347 @@
+# 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.
+
+# See include/mesos/scheduler.hpp, include/mesos/executor.hpp and
+# include/mesos/mesos.proto for more information documenting this
+# interface.
+
+"""Python bindings for Mesos."""
+
+from __future__ import print_function
+
+import sys
+
+__all__ = (
+  'Executor',
+  'ExecutorDriver'
+  'Scheduler',
+  'SchedulerDriver',
+)
+
+class Scheduler(object):
+  """
+    Base class for Mesos schedulers. Users' schedulers should extend this
+    class to get default implementations of methods they don't override.
+  """
+
+  def registered(self, driver, frameworkId, masterInfo):
+    """
+      Invoked when the scheduler successfully registers with a Mesos master.
+      It is called with the frameworkId, a unique ID generated by the
+      master, and the masterInfo which is information about the master
+      itself.
+    """
+
+  def reregistered(self, driver, masterInfo):
+    """
+      Invoked when the scheduler re-registers with a newly elected Mesos
+      master.  This is only called when the scheduler has previously been
+      registered.  masterInfo contains information about the newly elected
+      master.
+    """
+
+  def disconnected(self, driver):
+    """
+      Invoked when the scheduler becomes disconnected from the master, e.g.
+      the master fails and another is taking over.
+    """
+
+  def resourceOffers(self, driver, offers):
+    """
+      Invoked when resources have been offered to this framework. A single
+      offer will only contain resources from a single slave.  Resources
+      associated with an offer will not be re-offered to _this_ framework
+      until either (a) this framework has rejected those resources (see
+      SchedulerDriver.launchTasks) or (b) those resources have been
+      rescinded (see Scheduler.offerRescinded).  Note that resources may be
+      concurrently offered to more than one framework at a time (depending
+      on the allocator being used).  In that case, the first framework to
+      launch tasks using those resources will be able to use them while the
+      other frameworks will have those resources rescinded (or if a
+      framework has already launched tasks with those resources then those
+      tasks will fail with a TASK_LOST status and a message saying as much).
+    """
+
+  def offerRescinded(self, driver, offerId):
+    """
+      Invoked when an offer is no longer valid (e.g., the slave was lost or
+      another framework used resources in the offer.) If for whatever reason
+      an offer is never rescinded (e.g., dropped message, failing over
+      framework, etc.), a framwork that attempts to launch tasks using an
+      invalid offer will receive TASK_LOST status updats for those tasks
+      (see Scheduler.resourceOffers).
+    """
+
+  def statusUpdate(self, driver, status):
+    """
+      Invoked when the status of a task has changed (e.g., a slave is lost
+      and so the task is lost, a task finishes and an executor sends a
+      status update saying so, etc.) Note that returning from this callback
+      acknowledges receipt of this status update.  If for whatever reason
+      the scheduler aborts during this callback (or the process exits)
+      another status update will be delivered.  Note, however, that this is
+      currently not true if the slave sending the status update is lost or
+      fails during that time.
+    """
+
+  def frameworkMessage(self, driver, executorId, slaveId, message):
+    """
+      Invoked when an executor sends a message. These messages are best
+      effort; do not expect a framework message to be retransmitted in any
+      reliable fashion.
+    """
+
+  def slaveLost(self, driver, slaveId):
+    """
+      Invoked when a slave has been determined unreachable (e.g., machine
+      failure, network partition.) Most frameworks will need to reschedule
+      any tasks launched on this slave on a new slave.
+    """
+
+  def executorLost(self, driver, executorId, slaveId, status):
+    """
+      Invoked when an executor has exited/terminated. Note that any tasks
+      running will have TASK_LOST status updates automatically generated.
+    """
+
+  def error(self, driver, message):
+    """
+      Invoked when there is an unrecoverable error in the scheduler or
+      scheduler driver.  The driver will be aborted BEFORE invoking this
+      callback.
+    """
+    print("Error from Mesos: %s " % message, file=sys.stderr)
+
+
+class SchedulerDriver(object):
+  """
+    Interface for Mesos scheduler drivers. Users may wish to implement this
+    class in mock objects for tests.
+  """
+  def start(self):
+    """
+      Starts the scheduler driver.  This needs to be called before any other
+      driver calls are made.
+    """
+
+  def stop(self, failover=False):
+    """
+      Stops the scheduler driver. If the 'failover' flag is set to False
+      then it is expected that this framework will never reconnect to Mesos
+      and all of its executors and tasks can be terminated.  Otherwise, all
+      executors and tasks will remain running (for some framework specific
+      failover timeout) allowing the scheduler to reconnect (possibly in the
+      same process, or from a different process, for example, on a different
+      machine.)
+    """
+
+  def abort(self):
+    """
+      Aborts the driver so that no more callbacks can be made to the
+      scheduler.  The semantics of abort and stop have deliberately been
+      separated so that code can detect an aborted driver (i.e., via the
+      return status of SchedulerDriver.join), and instantiate and start
+      another driver if desired (from within the same process.)
+    """
+
+  def join(self):
+    """
+      Waits for the driver to be stopped or aborted, possibly blocking the
+      current thread indefinitely.  The return status of this function can
+      be used to determine if the driver was aborted (see mesos.proto for a
+      description of Status).
+    """
+
+  def run(self):
+    """
+      Starts and immediately joins (i.e., blocks on) the driver.
+    """
+
+  def requestResources(self, requests):
+    """
+      Requests resources from Mesos (see mesos.proto for a description of
+      Request and how, for example, to request resources from specific
+      slaves.)  Any resources available are offered to the framework via
+      Scheduler.resourceOffers callback, asynchronously.
+    """
+
+  def launchTasks(self, offerIds, tasks, filters=None):
+    """
+      Launches the given set of tasks. Any resources remaining (i.e., not
+      used by the tasks or their executors) will be considered declined.
+      The specified filters are applied on all unused resources (see
+      mesos.proto for a description of Filters.) Invoking this function with
+      an empty collection of tasks declines the offers in entirety (see
+      Scheduler.declineOffer). Note that passing a single offer is also
+      supported.
+    """
+
+  def killTask(self, taskId):
+    """
+      Kills the specified task. Note that attempting to kill a task is
+      currently not reliable.  If, for example, a scheduler fails over while
+      it was attempting to kill a task it will need to retry in the future.
+      Likewise, if unregistered / disconnected, the request will be dropped
+      dropped (these semantics may be changed in the future).
+    """
+
+  def declineOffer(self, offerId, filters=None):
+    """
+      Declines an offer in its entirety and applies the specified
+      filters on the resources (see mesos.proto for a description of
+      Filters). Note that this can be done at any time, it is not
+      necessary to do this within the Scheduler::resourceOffers
+      callback.
+    """
+
+  def reviveOffers(self):
+    """
+      Removes all filters previously set by the framework (via
+      launchTasks()).  This enables the framework to receive offers from
+      those filtered slaves.
+    """
+
+  def sendFrameworkMessage(self, executorId, slaveId, data):
+    """
+      Sends a message from the framework to one of its executors. These
+      messages are best effort; do not expect a framework message to be
+      retransmitted in any reliable fashion.
+    """
+
+  # TODO(bmahler): Add reconcileTasks!
+
+class Executor(object):
+  """
+    Base class for Mesos executors. Users' executors should extend this
+    class to get default implementations of methods they don't override.
+  """
+
+  def registered(self, driver, executorInfo, frameworkInfo, slaveInfo):
+    """
+      Invoked once the executor driver has been able to successfully connect
+      with Mesos.  In particular, a scheduler can pass some data to its
+      executors through the FrameworkInfo.ExecutorInfo's data field.
+    """
+
+  def reregistered(self, driver, slaveInfo):
+    """
+      Invoked when the executor re-registers with a restarted slave.
+    """
+
+  def disconnected(self, driver):
+    """
+      Invoked when the executor becomes "disconnected" from the slave (e.g.,
+      the slave is being restarted due to an upgrade).
+    """
+
+  def launchTask(self, driver, task):
+    """
+      Invoked when a task has been launched on this executor (initiated via
+      Scheduler.launchTasks).  Note that this task can be realized with a
+      thread, a process, or some simple computation, however, no other
+      callbacks will be invoked on this executor until this callback has
+      returned.
+    """
+
+  def killTask(self, driver, taskId):
+    """
+      Invoked when a task running within this executor has been killed (via
+      SchedulerDriver.killTask).  Note that no status update will be sent on
+      behalf of the executor, the executor is responsible for creating a new
+      TaskStatus (i.e., with TASK_KILLED) and invoking ExecutorDriver's
+      sendStatusUpdate.
+    """
+
+  def frameworkMessage(self, driver, message):
+    """
+      Invoked when a framework message has arrived for this executor.  These
+      messages are best effort; do not expect a framework message to be
+      retransmitted in any reliable fashion.
+    """
+
+  def shutdown(self, driver):
+    """
+      Invoked when the executor should terminate all of its currently
+      running tasks.  Note that after Mesos has determined that an executor
+      has terminated any tasks that the executor did not send terminal
+      status updates for (e.g., TASK_KILLED, TASK_FINISHED, TASK_FAILED,
+      etc) a TASK_LOST status update will be created.
+    """
+
+  def error(self, driver, message):
+    """
+      Invoked when a fatal error has occured with the executor and/or
+      executor driver.  The driver will be aborted BEFORE invoking this
+      callback.
+    """
+    print("Error from Mesos: %s" % message, file=sys.stderr)
+
+
+
+class ExecutorDriver(object):
+  """
+    Interface for Mesos executor drivers. Users may wish to extend this
+    class in mock objects for tests.
+  """
+  def start(self):
+    """
+      Starts the executor driver. This needs to be called before any other
+      driver calls are made.
+    """
+
+  def stop(self):
+    """
+      Stops the executor driver.
+    """
+
+  def abort(self):
+    """
+      Aborts the driver so that no more callbacks can be made to the
+      executor.  The semantics of abort and stop have deliberately been
+      separated so that code can detect an aborted driver (i.e., via the
+      return status of ExecutorDriver.join), and instantiate and start
+      another driver if desired (from within the same process, although this
+      functionality is currently not supported for executors).
+    """
+
+  def join(self):
+    """
+      Waits for the driver to be stopped or aborted, possibly blocking the
+      current thread indefinitely.  The return status of this function can
+      be used to determine if the driver was aborted (see mesos.proto for a
+      description of Status).
+    """
+
+  def run(self):
+    """
+      Starts and immediately joins (i.e., blocks on) the driver.
+    """
+
+  def sendStatusUpdate(self, status):
+    """
+      Sends a status update to the framework scheduler, retrying as
+      necessary until an acknowledgement has been received or the executor
+      is terminated (in which case, a TASK_LOST status update will be sent).
+      See Scheduler.statusUpdate for more information about status update
+      acknowledgements.
+    """
+
+  def sendFrameworkMessage(self, data):
+    """
+      Sends a message to the framework scheduler. These messages are best
+      effort; do not expect a framework message to be retransmitted in any
+      reliable fashion.
+    """

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/ext_modules.py.in
----------------------------------------------------------------------
diff --git a/src/python/native/ext_modules.py.in b/src/python/native/ext_modules.py.in
new file mode 100644
index 0000000..a0f74b2
--- /dev/null
+++ b/src/python/native/ext_modules.py.in
@@ -0,0 +1,131 @@
+# 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
+
+abs_top_srcdir = '@abs_top_srcdir@'
+abs_top_builddir = '@abs_top_builddir@'
+
+src_python_native = os.path.join(
+    'src', 'python', 'native', 'src', 'mesos', 'native')
+
+leveldb = os.path.join('3rdparty', 'leveldb')
+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')
+libev = os.path.join(libprocess, '3rdparty', 'libev-4.15')
+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', 'native', file)
+        for file in os.listdir(os.path.join(abs_top_srcdir, src_python_native))
+            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, src_python_native),
+    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, protobuf, 'src', '.libs', 'libprotobuf.a'),
+    os.path.join(abs_top_builddir, libprocess, '.libs', 'libprocess.a'),
+    os.path.join(abs_top_builddir, glog, '.libs', 'libglog.a')
+]
+
+# For leveldb, we need to check for the presence of libleveldb.a, since
+# it is possible to disable leveldb inside mesos.
+libev = os.path.join(abs_top_builddir, libev, '.libs', 'libev.a')
+libleveldb = os.path.join(abs_top_builddir, leveldb, 'libleveldb.a')
+libzookeeper = os.path.join(
+    abs_top_builddir, zookeeper, '.libs', 'libzookeeper_mt.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(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 = []
+
+# 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)
+
+DEPENDS = [
+    os.path.join(abs_top_srcdir, 'src', 'python', source)
+        for source in SOURCES
+]
+
+# 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.native._mesos',
+              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++',
+              )

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/mesos_executor_driver_impl.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/mesos_executor_driver_impl.cpp b/src/python/native/mesos_executor_driver_impl.cpp
deleted file mode 100644
index 16b9bc1..0000000
--- a/src/python/native/mesos_executor_driver_impl.cpp
+++ /dev/null
@@ -1,349 +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 <string>
-
-#include "mesos_executor_driver_impl.hpp"
-#include "module.hpp"
-#include "proxy_executor.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 MesosExecutorDriverImpl.
- */
-PyTypeObject MesosExecutorDriverImplType = {
-  PyObject_HEAD_INIT(NULL)
-  0,                                               /* ob_size */
-  "_mesos.MesosExecutorDriverImpl",                /* tp_name */
-  sizeof(MesosExecutorDriverImpl),                 /* tp_basicsize */
-  0,                                               /* tp_itemsize */
-  (destructor) MesosExecutorDriverImpl_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 MesosExecutorDriver implementation",    /* tp_doc */
-  (traverseproc) MesosExecutorDriverImpl_traverse, /* tp_traverse */
-  (inquiry) MesosExecutorDriverImpl_clear,         /* tp_clear */
-  0,                                               /* tp_richcompare */
-  0,                                               /* tp_weaklistoffset */
-  0,                                               /* tp_iter */
-  0,                                               /* tp_iternext */
-  MesosExecutorDriverImpl_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) MesosExecutorDriverImpl_init,         /* tp_init */
-  0,                                               /* tp_alloc */
-  MesosExecutorDriverImpl_new,                     /* tp_new */
-};
-
-
-/**
- * List of Python methods in MesosExecutorDriverImpl.
- */
-PyMethodDef MesosExecutorDriverImpl_methods[] = {
-  { "start",
-    (PyCFunction) MesosExecutorDriverImpl_start,
-    METH_NOARGS,
-    "Start the driver to connect to Mesos"
-  },
-  { "stop",
-    (PyCFunction) MesosExecutorDriverImpl_stop,
-    METH_NOARGS,
-    "Stop the driver, disconnecting from Mesos"
-  },
-  { "abort",
-    (PyCFunction) MesosExecutorDriverImpl_abort,
-    METH_NOARGS,
-    "Abort the driver, disallowing calls from and to the driver"
-  },
-  { "join",
-    (PyCFunction) MesosExecutorDriverImpl_join,
-    METH_NOARGS,
-    "Wait for a running driver to disconnect from Mesos"
-  },
-  { "run",
-    (PyCFunction) MesosExecutorDriverImpl_run,
-    METH_NOARGS,
-    "Start a driver and run it, returning when it disconnects from Mesos"
-  },
-  { "sendStatusUpdate",
-    (PyCFunction) MesosExecutorDriverImpl_sendStatusUpdate,
-    METH_VARARGS,
-    "Send a status update for a task"
-  },
-  { "sendFrameworkMessage",
-    (PyCFunction) MesosExecutorDriverImpl_sendFrameworkMessage,
-    METH_VARARGS,
-    "Send a FrameworkMessage to a slave"
-  },
-  { NULL }  /* Sentinel */
-};
-
-
-/**
- * Create, but don't initialize, a new MesosExecutorDriverImpl
- * (called by Python before init method).
- */
-PyObject* MesosExecutorDriverImpl_new(PyTypeObject *type,
-                                       PyObject *args,
-                                       PyObject *kwds)
-{
-  MesosExecutorDriverImpl *self;
-  self = (MesosExecutorDriverImpl *) type->tp_alloc(type, 0);
-  if (self != NULL) {
-    self->driver = NULL;
-    self->proxyExecutor = NULL;
-    self->pythonExecutor = NULL;
-  }
-  return (PyObject*) self;
-}
-
-
-/**
- * Initialize a MesosExecutorDriverImpl with constructor arguments.
- */
-int MesosExecutorDriverImpl_init(MesosExecutorDriverImpl *self,
-                                  PyObject *args,
-                                  PyObject *kwds)
-{
-  PyObject *pythonExecutor = NULL;
-
-  if (!PyArg_ParseTuple(args, "O", &pythonExecutor)) {
-    return -1;
-  }
-
-  if (pythonExecutor != NULL) {
-    PyObject* tmp = self->pythonExecutor;
-    Py_INCREF(pythonExecutor);
-    self->pythonExecutor = pythonExecutor;
-    Py_XDECREF(tmp);
-  }
-
-  if (self->driver != NULL) {
-    delete self->driver;
-    self->driver = NULL;
-  }
-
-  if (self->proxyExecutor != NULL) {
-    delete self->proxyExecutor;
-    self->proxyExecutor = NULL;
-  }
-
-  self->proxyExecutor = new ProxyExecutor(self);
-  self->driver = new MesosExecutorDriver(self->proxyExecutor);
-
-  return 0;
-}
-
-
-/**
- * Free a MesosExecutorDriverImpl.
- */
-void MesosExecutorDriverImpl_dealloc(MesosExecutorDriverImpl* self)
-{
-  if (self->driver != NULL) {
-    // We need to wrap the driver destructor in an "allow threads"
-    // macro since the MesosExecutorDriver destructor waits for the
-    // ExecutorProcess to terminate and there might be a thread that
-    // is trying to acquire the GIL to call through the
-    // ProxyExecutor. It will only be after this thread executes that
-    // the ExecutorProcess might actually get a terminate.
-    Py_BEGIN_ALLOW_THREADS
-    delete self->driver;
-    Py_END_ALLOW_THREADS
-    self->driver = NULL;
-  }
-
-  if (self->proxyExecutor != NULL) {
-    delete self->proxyExecutor;
-    self->proxyExecutor = NULL;
-  }
-
-  MesosExecutorDriverImpl_clear(self);
-  self->ob_type->tp_free((PyObject*) self);
-}
-
-
-/**
- * Traverse fields of a MesosExecutorDriverImpl on a cyclic GC search.
- * See http://docs.python.org/extending/newtypes.html.
- */
-int MesosExecutorDriverImpl_traverse(MesosExecutorDriverImpl* self,
-                                      visitproc visit,
-                                      void* arg)
-{
-  Py_VISIT(self->pythonExecutor);
-  return 0;
-}
-
-
-/**
- * Clear fields of a MesosExecutorDriverImpl that can participate in
- * GC cycles. See http://docs.python.org/extending/newtypes.html.
- */
-int MesosExecutorDriverImpl_clear(MesosExecutorDriverImpl* self)
-{
-  Py_CLEAR(self->pythonExecutor);
-  return 0;
-}
-
-
-PyObject* MesosExecutorDriverImpl_start(MesosExecutorDriverImpl* self)
-{
-  if (self->driver == NULL) {
-    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
-    return NULL;
-  }
-
-  Status status = self->driver->start();
-  return PyInt_FromLong(status); // Sets an exception if creating the int fails
-}
-
-
-PyObject* MesosExecutorDriverImpl_stop(MesosExecutorDriverImpl* self)
-{
-  if (self->driver == NULL) {
-    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
-    return NULL;
-  }
-
-  Status status = self->driver->stop();
-  return PyInt_FromLong(status); // Sets an exception if creating the int fails
-}
-
-
-PyObject* MesosExecutorDriverImpl_abort(MesosExecutorDriverImpl* self)
-{
-  if (self->driver == NULL) {
-    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
-    return NULL;
-  }
-
-  Status status = self->driver->abort();
-  return PyInt_FromLong(status); // Sets an exception if creating the int fails
-}
-
-
-PyObject* MesosExecutorDriverImpl_join(MesosExecutorDriverImpl* self)
-{
-  if (self->driver == NULL) {
-    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
-    return NULL;
-  }
-
-  Status status;
-  Py_BEGIN_ALLOW_THREADS
-  status = self->driver->join();
-  Py_END_ALLOW_THREADS
-  return PyInt_FromLong(status); // Sets an exception if creating the int fails
-}
-
-
-PyObject* MesosExecutorDriverImpl_run(MesosExecutorDriverImpl* self)
-{
-  if (self->driver == NULL) {
-    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
-    return NULL;
-  }
-
-  Status status;
-  Py_BEGIN_ALLOW_THREADS
-  status = self->driver->run();
-  Py_END_ALLOW_THREADS
-  return PyInt_FromLong(status); // Sets an exception if creating the int fails
-}
-
-
-PyObject* MesosExecutorDriverImpl_sendStatusUpdate(
-    MesosExecutorDriverImpl* self,
-    PyObject* args)
-{
-  if (self->driver == NULL) {
-    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
-    return NULL;
-  }
-
-  PyObject* statusObj = NULL;
-  TaskStatus taskStatus;
-  if (!PyArg_ParseTuple(args, "O", &statusObj)) {
-    return NULL;
-  }
-  if (!readPythonProtobuf(statusObj, &taskStatus)) {
-    PyErr_Format(PyExc_Exception,
-                 "Could not deserialize Python TaskStatus");
-    return NULL;
-  }
-
-  Status status = self->driver->sendStatusUpdate(taskStatus);
-  return PyInt_FromLong(status); // Sets an exception if creating the int fails
-}
-
-
-PyObject* MesosExecutorDriverImpl_sendFrameworkMessage(
-    MesosExecutorDriverImpl* self,
-    PyObject* args)
-{
-  if (self->driver == NULL) {
-    PyErr_Format(PyExc_Exception, "MesosExecutorDriverImpl.driver is NULL");
-    return NULL;
-  }
-
-  const char* data;
-  int length;
-  if (!PyArg_ParseTuple(args, "s#", &data, &length)) {
-    return NULL;
-  }
-
-  Status status = self->driver->sendFrameworkMessage(string(data, length));
-  return PyInt_FromLong(status); // Sets an exception if creating the int fails
-}
-
-} // namespace python {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/mesos_executor_driver_impl.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/mesos_executor_driver_impl.hpp b/src/python/native/mesos_executor_driver_impl.hpp
deleted file mode 100644
index 7245414..0000000
--- a/src/python/native/mesos_executor_driver_impl.hpp
+++ /dev/null
@@ -1,105 +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_EXECUTOR_DRIVER_IMPL_HPP
-#define MESOS_EXECUTOR_DRIVER_IMPL_HPP
-
-#include <mesos/executor.hpp>
-
-
-namespace mesos { namespace python {
-
-class ProxyExecutor;
-
-/**
- * Python object structure for MesosExecutorDriverImpl objects.
- */
-struct MesosExecutorDriverImpl {
-    PyObject_HEAD
-    /* Type-specific fields go here. */
-    MesosExecutorDriver* driver;
-    ProxyExecutor* proxyExecutor;
-    PyObject* pythonExecutor;
-};
-
-/**
- * Python type object for MesosExecutorDriverImpl.
- */
-extern PyTypeObject MesosExecutorDriverImplType;
-
-/**
- * List of Python methods in MesosExecutorDriverImpl.
- */
-extern PyMethodDef MesosExecutorDriverImpl_methods[];
-
-/**
- * Create, but don't initialize, a new MesosExecutorDriverImpl
- * (called by Python before init method).
- */
-PyObject* MesosExecutorDriverImpl_new(PyTypeObject *type,
-                                      PyObject *args,
-                                      PyObject *kwds);
-
-/**
- * Initialize a MesosExecutorDriverImpl with constructor arguments.
- */
-int MesosExecutorDriverImpl_init(MesosExecutorDriverImpl *self,
-                                 PyObject *args,
-                                 PyObject *kwds);
-
-/**
- * Free a MesosExecutorDriverImpl.
- */
-void MesosExecutorDriverImpl_dealloc(MesosExecutorDriverImpl* self);
-
-/**
- * Traverse fields of a MesosExecutorDriverImpl on a cyclic GC search.
- * See http://docs.python.org/extending/newtypes.html.
- */
-int MesosExecutorDriverImpl_traverse(MesosExecutorDriverImpl* self,
-                                     visitproc visit,
-                                     void* arg);
-/**
- * Clear fields of a MesosExecutorDriverImpl that can participate in
- * GC cycles. See http://docs.python.org/extending/newtypes.html.
- */
-int MesosExecutorDriverImpl_clear(MesosExecutorDriverImpl* self);
-
-// MesosExecutorDriverImpl methods
-PyObject* MesosExecutorDriverImpl_start(MesosExecutorDriverImpl* self);
-
-PyObject* MesosExecutorDriverImpl_stop(MesosExecutorDriverImpl* self);
-
-PyObject* MesosExecutorDriverImpl_abort(MesosExecutorDriverImpl* self);
-
-PyObject* MesosExecutorDriverImpl_join(MesosExecutorDriverImpl* self);
-
-PyObject* MesosExecutorDriverImpl_run(MesosExecutorDriverImpl* self);
-
-PyObject* MesosExecutorDriverImpl_sendStatusUpdate(
-    MesosExecutorDriverImpl* self,
-    PyObject* args);
-
-PyObject* MesosExecutorDriverImpl_sendFrameworkMessage(
-    MesosExecutorDriverImpl* self,
-    PyObject* args);
-
-} // namespace python {
-} // namespace mesos {
-
-#endif /* MESOS_EXECUTOR_DRIVER_IMPL_HPP */

http://git-wip-us.apache.org/repos/asf/mesos/blob/c5a68be1/src/python/native/mesos_scheduler_driver_impl.cpp
----------------------------------------------------------------------
diff --git a/src/python/native/mesos_scheduler_driver_impl.cpp b/src/python/native/mesos_scheduler_driver_impl.cpp
deleted file mode 100644
index e014eed..0000000
--- a/src/python/native/mesos_scheduler_driver_impl.cpp
+++ /dev/null
@@ -1,634 +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 <string>
-
-#include "mesos_scheduler_driver_impl.hpp"
-#include "module.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"
-  },
-  { "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"
-  },
-  { "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)
-{
-  PyObject* schedulerObj = NULL;
-  PyObject* frameworkObj = NULL;
-  const char* master;
-  PyObject* credentialObj = NULL;
-
-  if (!PyArg_ParseTuple(
-      args, "OOs|O", &schedulerObj, &frameworkObj, &master, &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, credential);
-  } else {
-    self->driver = new MesosSchedulerDriver(
-        self->proxyScheduler, framework, master);
-  }
-
-  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_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_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/c5a68be1/src/python/native/mesos_scheduler_driver_impl.hpp
----------------------------------------------------------------------
diff --git a/src/python/native/mesos_scheduler_driver_impl.hpp b/src/python/native/mesos_scheduler_driver_impl.hpp
deleted file mode 100644
index 8c285ae..0000000
--- a/src/python/native/mesos_scheduler_driver_impl.hpp
+++ /dev/null
@@ -1,125 +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_declineOffer(
-    MesosSchedulerDriverImpl* self,
-    PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_reviveOffers(MesosSchedulerDriverImpl* self);
-
-PyObject* MesosSchedulerDriverImpl_sendFrameworkMessage(
-    MesosSchedulerDriverImpl* self,
-    PyObject* args);
-
-PyObject* MesosSchedulerDriverImpl_reconcileTasks(
-    MesosSchedulerDriverImpl* self,
-    PyObject* args);
-
-} // namespace python {
-} // namespace mesos {
-
-#endif /* MESOS_SCHEDULER_DRIVER_IMPL_HPP */