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 */