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 <[email protected]>
Authored: Thu Jul 31 21:11:26 2014 -0700
Committer: Benjamin Hindman <[email protected]>
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@@[email protected]
+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@@[email protected]
+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@@[email protected]
+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': '[email protected]',
+    '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 */

Reply via email to