This will allow us to install the rpc Python code and (later) the mhsh
shell as a single 'matahari' Python package.
---
matahari.spec.in | 19 ++++++++++++++++
src/CMakeLists.txt | 1 +
src/lib/rpc-python.c | 5 +++-
src/python/.gitignore | 2 ++
src/python/CMakeLists.txt | 30 +++++++++++++++++++++++++
src/python/matahari/__init__.py | 0
src/python/matahari/rpc_server.py | 45 +++++++++++++++++++++++++++++++++++++
src/rpc/.gitignore | 2 --
src/rpc/rpc.py | 45 -------------------------------------
9 files changed, 101 insertions(+), 48 deletions(-)
create mode 100644 src/python/.gitignore
create mode 100644 src/python/CMakeLists.txt
create mode 100644 src/python/matahari/__init__.py
create mode 100644 src/python/matahari/rpc_server.py
delete mode 100644 src/rpc/.gitignore
delete mode 100644 src/rpc/rpc.py
diff --git a/matahari.spec.in b/matahari.spec.in
index ada689e..81ce81e 100644
--- a/matahari.spec.in
+++ b/matahari.spec.in
@@ -57,6 +57,7 @@ BuildRequires: libcurl-devel
BuildRequires: nss-devel
BuildRequires: help2man
BuildRequires: augeas-devel >= 0.9.0
+BuildRequires: python2-devel
%if %{with qmf}
BuildRequires: qpid-cpp-client-devel > 0.7
@@ -157,6 +158,15 @@ Requires: kstart
%description agent-lib
C++ library containing the base class for Matahari agents
+%package python
+License: GPLv2+
+Summary: Matahari Python API
+Group: Applications/System
+Requires: python-qpid-qmf
+
+%description python
+Python libraries for Matahari
+
%package host
License: GPLv2+
Summary: QMF agent for remote hosts
@@ -195,6 +205,7 @@ Summary: QMF agent for RPC plugins
Group: Applications/System
Requires: %{name}-lib = %{version}-%{release}
Requires: %{name}-agent-lib = %{version}-%{release}
+Requires: %{name}-python = %{version}-%{release}
Requires(post): chkconfig
Requires(preun):chkconfig
Requires(preun):initscripts
@@ -511,6 +522,14 @@ test "x%{buildroot}" != "x" && rm -rf
%{buildroot}
%dir %attr(0770, root, qpidd) %{_localstatedir}/lib/%{name}
%endif
+%files python
+%defattr(644, root, root, 755)
+%doc AUTHORS COPYING
+%dir %{python_sitelib}/matahari/
+%{python_sitelib}/matahari/*.py
+%{python_sitelib}/matahari/*.pyc
+%{python_sitelib}/matahari/*.pyo
+
%files network
%defattr(644, root, root, 755)
%doc AUTHORS COPYING
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1aa486a..63f3ae8 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -185,6 +185,7 @@ endif(WITH-QMF)
### Subdirectories
add_subdirectory(broker)
+add_subdirectory(python)
add_subdirectory(lib)
add_subdirectory(host)
add_subdirectory(network)
diff --git a/src/lib/rpc-python.c b/src/lib/rpc-python.c
index d2388e9..73c65be 100644
--- a/src/lib/rpc-python.c
+++ b/src/lib/rpc-python.c
@@ -25,6 +25,9 @@
#include "matahari/errors.h"
+#define RPC_SERVER_MODULE "matahari.rpc_server"
+
+
struct mh_rpc_plugin_impl {
PyObject *plugin;
};
@@ -62,7 +65,7 @@ call_rpc_server_func(const char *funcname, PyObject *args)
{
PyObject *rpc_mod, *func, *result;
- rpc_mod = PyImport_ImportModule("rpc"); // TODO: move to matahari package
+ rpc_mod = PyImport_ImportModule(RPC_SERVER_MODULE);
if (!rpc_mod) {
mh_err("Error importing Matahari RPC Python module");
PyErr_Print();
diff --git a/src/python/.gitignore b/src/python/.gitignore
new file mode 100644
index 0000000..52e4e61
--- /dev/null
+++ b/src/python/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
diff --git a/src/python/CMakeLists.txt b/src/python/CMakeLists.txt
new file mode 100644
index 0000000..3dc1050
--- /dev/null
+++ b/src/python/CMakeLists.txt
@@ -0,0 +1,30 @@
+FIND_PACKAGE(PythonInterp)
+
+macro(py_module MODULE DIRECTORY)
+ # Copy the Python file to the Binary directory
+ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${DIRECTORY}/${MODULE}.py
+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${DIRECTORY})
+
+ # Compile .pyc and .pyo files
+ execute_process(COMMAND echo "PYTHON_EXECUTABLE = ${PYTHON_EXECUTABLE}")
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -m py_compile ${MODULE}.py
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${DIRECTORY})
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -O -m py_compile ${MODULE}.py
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${DIRECTORY})
+
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${DIRECTORY}/${MODULE}.py
+ ${CMAKE_CURRENT_BINARY_DIR}/${DIRECTORY}/${MODULE}.pyc
+ ${CMAKE_CURRENT_BINARY_DIR}/${DIRECTORY}/${MODULE}.pyo
+ DESTINATION ${PYTHON_SITE_PACKAGES}/${DIRECTORY})
+endmacro(py_module)
+
+if(WITH-QMF)
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import
get_python_lib; print get_python_lib()"
+ OUTPUT_VARIABLE PYTHON_SITE_PACKAGES
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ py_module(__init__ matahari)
+ py_module(rpc_server matahari)
+
+endif(WITH-QMF)
+
diff --git a/src/python/matahari/__init__.py b/src/python/matahari/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/python/matahari/rpc_server.py b/src/python/matahari/rpc_server.py
new file mode 100644
index 0000000..6cf2eea
--- /dev/null
+++ b/src/python/matahari/rpc_server.py
@@ -0,0 +1,45 @@
+import sys, os
+import json
+import traceback
+
+(PLUGIN_PATH,) = ('.',) # TODO: choose proper install path
+
+class Plugin(object):
+ def __init__(self, module):
+ self.module = module
+ self.name = self.module.__name__
+
+ def procedures(self):
+ isProcedure = lambda a: callable(getattr(self.module, a))
+ return [o for o in dir(self.module) if isProcedure(o) and
+ not o.startswith('_')]
+
+ def call(self, procedure, args_json=[], kwargs_json=[]):
+ func = getattr(self.module, procedure)
+ args = [json.loads(a) for a in args_json]
+ kwargs = dict((k, json.loads(v)) for k,v in kwargs_json)
+ result = func(*args, **kwargs)
+ return json.dumps(result)
+
+def formatException(exc_type, exc_val, exc_tb):
+ return exc_type.__name__, str(exc_val), ''.join(traceback.format_tb(exc_tb))
+
+def plugins(path=PLUGIN_PATH):
+ old_path = sys.path
+ try:
+ sys.path = [path] + old_path
+ filenames = [os.path.splitext(f) for f in os.listdir(path)]
+ modnames = [n for n, e in filenames if e == '.py']
+ def getPlugin(name):
+ try:
+ mod = __import__(name, {}, {}, [], -1)
+ return Plugin(mod)
+ except ImportError:
+ return None
+ return filter(lambda p: p is not None, map(getPlugin, modnames))
+ finally:
+ sys.path = old_path
+
+
+if __name__ == '__main__':
+ print [p.name for p in plugins('src/rpc/plugins')]
diff --git a/src/rpc/.gitignore b/src/rpc/.gitignore
deleted file mode 100644
index 52e4e61..0000000
--- a/src/rpc/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.pyc
-*.pyo
diff --git a/src/rpc/rpc.py b/src/rpc/rpc.py
deleted file mode 100644
index 6cf2eea..0000000
--- a/src/rpc/rpc.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import sys, os
-import json
-import traceback
-
-(PLUGIN_PATH,) = ('.',) # TODO: choose proper install path
-
-class Plugin(object):
- def __init__(self, module):
- self.module = module
- self.name = self.module.__name__
-
- def procedures(self):
- isProcedure = lambda a: callable(getattr(self.module, a))
- return [o for o in dir(self.module) if isProcedure(o) and
- not o.startswith('_')]
-
- def call(self, procedure, args_json=[], kwargs_json=[]):
- func = getattr(self.module, procedure)
- args = [json.loads(a) for a in args_json]
- kwargs = dict((k, json.loads(v)) for k,v in kwargs_json)
- result = func(*args, **kwargs)
- return json.dumps(result)
-
-def formatException(exc_type, exc_val, exc_tb):
- return exc_type.__name__, str(exc_val), ''.join(traceback.format_tb(exc_tb))
-
-def plugins(path=PLUGIN_PATH):
- old_path = sys.path
- try:
- sys.path = [path] + old_path
- filenames = [os.path.splitext(f) for f in os.listdir(path)]
- modnames = [n for n, e in filenames if e == '.py']
- def getPlugin(name):
- try:
- mod = __import__(name, {}, {}, [], -1)
- return Plugin(mod)
- except ImportError:
- return None
- return filter(lambda p: p is not None, map(getPlugin, modnames))
- finally:
- sys.path = old_path
-
-
-if __name__ == '__main__':
- print [p.name for p in plugins('src/rpc/plugins')]