]> granicus.if.org Git - icinga2/commitdiff
Add Python module for the icinga2.debug file
authorGunnar Beutner <gunnar.beutner@netways.de>
Fri, 15 Aug 2014 13:39:00 +0000 (15:39 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Sat, 16 Aug 2014 18:22:43 +0000 (20:22 +0200)
refs #6702

20 files changed:
CMakeLists.txt
INSTALL
debian/control
debian/icinga2-common.install
debian/python-icinga2.install [new file with mode: 0644]
debian/rules
icinga2.spec
python/CMakeLists.txt [new file with mode: 0644]
python/icinga2/CMakeLists.txt [new file with mode: 0644]
python/icinga2/__init__.py [new file with mode: 0644]
python/icinga2/commands/CMakeLists.txt [new file with mode: 0644]
python/icinga2/commands/__init__.py [new file with mode: 0644]
python/icinga2/commands/list_objects.py [new file with mode: 0644]
python/icinga2/config.py.cmake [new file with mode: 0644]
python/icinga2/utils/CMakeLists.txt [new file with mode: 0644]
python/icinga2/utils/__init__.py [new file with mode: 0644]
python/icinga2/utils/debug.py [new file with mode: 0644]
python/icinga2/utils/netstring.py [new file with mode: 0644]
python/setup.py.cmake [new file with mode: 0644]
third-party/cmake/PythonSetup.cmake [new file with mode: 0644]

index d15aef4f0f965f99ba617de8be7a8e055a512ea1..19518eba1b7dc14cab30077215480adc9909f8e5 100644 (file)
@@ -147,6 +147,7 @@ add_subdirectory(doc)
 add_subdirectory(test)
 add_subdirectory(pki)
 add_subdirectory(contrib)
+add_subdirectory(python)
 
 set(CPACK_PACKAGE_NAME "Icinga2")
 set(CPACK_PACKAGE_VENDOR "Icinga Development Team")
diff --git a/INSTALL b/INSTALL
index 3f9b3246c76ece17fca4bb2dde16da6ec7a20251..451e0cec85f185b48a34da3e4db5161621cae747 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -27,9 +27,9 @@ parentheses):
                                   on Debian)
 * GNU bison (bison)
 * GNU flex (flex) >= 2.5.35
+* Python (python-devel on RHEL, python-dev on Debian)
 * recommended: libexecinfo on FreeBSD
 * optional: MySQL (mysql-devel on RHEL, libmysqlclient-dev on Debian)
-* optional: Python (python-devel on RHEL, python-dev on Debian)
 
 Note: RHEL5 ships an ancient flex version. Updated packages are available for
 example from the repoforge buildtools repository.
index e924f6278a82fbb6edd0935f86977288572ce9a9..7a7c94a7b700c62ead0ba783685ffdbadbbb9023 100644 (file)
@@ -19,7 +19,9 @@ Build-Depends: bison,
                libpq-dev,
                libssl-dev,
                make (>= 3.81),
-               po-debconf
+               po-debconf,
+               python-setuptools,
+               python-all
 Standards-Version: 3.9.5
 Homepage: http://www.icinga.org
 
@@ -51,7 +53,7 @@ Description: host and network monitoring system
 
 Package: icinga2-common
 Architecture: all
-Depends: adduser, lsb-release, ${misc:Depends}
+Depends: python-icinga2 (= ${source:Version}), adduser, lsb-release, ${misc:Depends}
 Description: host and network monitoring system - common files
  Icinga 2 is a general-purpose monitoring application and the next generation
  after Icinga 1.x - which was a Nagios fork. It should fit the needs of a small
@@ -235,3 +237,29 @@ Description: host and network monitoring system - debug symbols
   * Native support for Livestatus and Graphite
  .
  This package provides debug symbols for Icinga 2.
+
+Package: python-icinga2
+Architecture: all
+Section: python
+Priority: extra
+Depends: ${misc:Depends}, ${python:Depends}
+Description: host and network monitoring system - debug symbols
+ Icinga 2 is a general-purpose monitoring application and the next generation
+ after Icinga 1.x - which was a Nagios fork. It should fit the needs of a small
+ environment as well as big installations.
+ .
+ Rewritten from scratch in C++, with multi-threading and cluster support.
+ .
+ Features:
+  * All common features of Icinga and Nagios
+  * Much faster and more scalable than Icinga 1 and Nagios
+  * New configuration format, more intuitive and template based
+  * Monitoring several services by executing checks (see nagios-plugins*)
+    for example ICMP/ping, SMTP, POP3, HTTP, NNTP, or other TCP port
+  * Any small script can be used as a check plugin, when following the Nagios
+    plugin API
+  * Notifications about alerts with any custom script, or shipped examples
+  * Native support for Livestatus and Graphite
+ .
+ This package provides the Python module for Icinga 2.
+
index a97e0a8357216e2fa17585b885a5dea6755b8df9..f4f8e2622b3b5d60086d7d1b8c2a78c9d80cdc51 100644 (file)
@@ -5,4 +5,5 @@ tools/syntax/*                usr/share/icinga2-common/syntax
 usr/bin/icinga2-build*
 usr/bin/icinga2-sign-key
 usr/sbin/icinga2-*-feature
+usr/sbin/icinga2-list-objects
 usr/share/icinga2
diff --git a/debian/python-icinga2.install b/debian/python-icinga2.install
new file mode 100644 (file)
index 0000000..2453ce7
--- /dev/null
@@ -0,0 +1 @@
+usr/lib/python*/
index 49dd1bd535aa1ec813362b0db8f2b34fc94901b2..d445ce24316726d392b127c946e24f561314a18e 100755 (executable)
@@ -3,7 +3,7 @@
 export DH_VERBOSE=1
 
 %:
-       dh $@
+       dh $@ --with python2
 
 override_dh_auto_clean:
 ifeq ($(shell test -d .git && echo "git"),git) # verify we are in a GIT repo
index cb6130cd3cbedd4531a2696652f7b7926cdded34..aaa1a326af7b63e083999a8850c1c3280a72dbb4 100644 (file)
 %endif
 %endif
 
+%{!?__python2: %global __python2 /usr/bin/python2}
+%{!?python2_sitelib: %global python2_sitelib %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")}
+%{!?python2_sitearch: %global python2_sitearch %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
+
 %define icinga_user icinga
 %define icinga_group icinga
 %define icingacmd_group icingacmd
@@ -63,7 +67,6 @@ Group: Applications/System
 Source: https://github.com/Icinga/%{name}/archive/v%{version}.tar.gz
 URL: http://www.icinga.org/
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-
 Requires: %{name}-bin = %{version}
 #Requires: %{name}-ido-mysql = %{version}
 #Requires: %{icingaweb2name} >= %{icingaweb2version}
@@ -75,6 +78,7 @@ Meta package for Icinga 2 Core, DB IDO and Web.
 Summary:      Icinga 2 binaries and libraries
 Group:        Applications/System
 
+Requires: python-%{name} = %{version}
 %if "%{_vendor}" == "suse"
 PreReq: permissions
 %endif
@@ -168,6 +172,17 @@ Icinga 1.x Classic UI Standalone configuration with locations
 for Icinga 2.
 
 
+%package -n python-icinga2
+Summary:      Python module for Icinga 2
+Group:        Application/System
+BuildRequires: python
+BuildRequires: python-devel
+BuildRequires: python-setuptools
+Requires:     python-setuptools
+
+%description -n python-icinga2
+Python module for Icinga 2.
+
 %prep
 %setup -q -n %{name}-%{version}
 
@@ -207,7 +222,6 @@ cmake $CMAKE_OPTS .
 
 make %{?_smp_mflags}
 
-rm -f components/db_ido_*sql/schema/upgrade/.gitignore
 
 %install
 [ "%{buildroot}" != "/" ] && [ -d "%{buildroot}" ] && rm -rf %{buildroot}
@@ -448,6 +462,7 @@ exit 0
 %{_bindir}/%{name}-build-ca
 %{_bindir}/%{name}-build-key
 %{_bindir}/%{name}-sign-key
+%{_sbindir}/%{name}-list-objects
 %{_sbindir}/%{name}-enable-feature
 %{_sbindir}/%{name}-disable-feature
 %{_sbindir}/%{name}-prepare-dirs
@@ -506,5 +521,8 @@ exit 0
 %config(noreplace) %{apacheconfdir}/icinga.conf
 %config(noreplace) %attr(0640,root,%{apachegroup}) %{icingaclassicconfdir}/passwd
 
+%files -n python-icinga2
+%{python2_sitelib}/icinga2*
+
 
 %changelog
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
new file mode 100644 (file)
index 0000000..dda939d
--- /dev/null
@@ -0,0 +1,43 @@
+# Icinga 2
+# Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+find_package(PythonInterp REQUIRED)
+
+add_subdirectory(icinga2)
+
+configure_file(setup.py.cmake ${CMAKE_CURRENT_BINARY_DIR}/setup.py @ONLY)
+
+install(CODE "
+  execute_process(
+   COMMAND ${CMAKE_COMMAND}
+     -DSETUP_PY=${CMAKE_CURRENT_BINARY_DIR}/setup.py
+     -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
+     -DPREFIX=${CMAKE_INSTALL_PREFIX}
+     -DWDIR=${CMAKE_CURRENT_BINARY_DIR}
+     -P ${PROJECT_SOURCE_DIR}/third-party/cmake/PythonSetup.cmake
+  )
+
+  configure_file(
+      \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/icinga2-list-objects
+      \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_SBINDIR}/icinga2-list-objects COPYONLY}
+  )
+
+  file(
+    REMOVE
+      \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/icinga2-list-objects
+  )"
+)
diff --git a/python/icinga2/CMakeLists.txt b/python/icinga2/CMakeLists.txt
new file mode 100644 (file)
index 0000000..846637f
--- /dev/null
@@ -0,0 +1,23 @@
+# Icinga 2
+# Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+add_subdirectory(commands)
+add_subdirectory(utils)
+
+configure_file(config.py.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.py @ONLY)
+configure_file(__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py COPYONLY)
+
diff --git a/python/icinga2/__init__.py b/python/icinga2/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/python/icinga2/commands/CMakeLists.txt b/python/icinga2/commands/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b31292d
--- /dev/null
@@ -0,0 +1,20 @@
+# Icinga 2
+# Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+configure_file(__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py COPYONLY)
+configure_file(list_objects.py ${CMAKE_CURRENT_BINARY_DIR}/list_objects.py COPYONLY)
+
diff --git a/python/icinga2/commands/__init__.py b/python/icinga2/commands/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/python/icinga2/commands/list_objects.py b/python/icinga2/commands/list_objects.py
new file mode 100644 (file)
index 0000000..ebcaead
--- /dev/null
@@ -0,0 +1,25 @@
+# Icinga 2
+# Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+from icinga2.utils.debug import ObjectsFile
+from icinga2.config import LocalStateDir
+
+def main():
+    fp = open(LocalStateDir + "/cache/icinga2/icinga2.debug")
+    of = ObjectsFile(fp)
+    for obj in of:
+        print obj
diff --git a/python/icinga2/config.py.cmake b/python/icinga2/config.py.cmake
new file mode 100644 (file)
index 0000000..9596450
--- /dev/null
@@ -0,0 +1,24 @@
+# Icinga 2
+# Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+Prefix = '@CMAKE_INSTALL_PREFIX@'
+SysconfDir = '@CMAKE_INSTALL_FULL_SYSCONFDIR@'
+RunDir = '@ICINGA2_RUNDIR@'
+LocalStateDir = '@CMAKE_INSTALL_FULL_LOCALSTATEDIR@'
+PkgDataDir = '@CMAKE_INSTALL_FULL_DATADIR@/icinga2'
+IncludeConfDir = '@CMAKE_INSTALL_FULL_DATADIR@/icinga2/include'
+
diff --git a/python/icinga2/utils/CMakeLists.txt b/python/icinga2/utils/CMakeLists.txt
new file mode 100644 (file)
index 0000000..7aaabe7
--- /dev/null
@@ -0,0 +1,21 @@
+# Icinga 2
+# Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+configure_file(__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py COPYONLY)
+configure_file(debug.py ${CMAKE_CURRENT_BINARY_DIR}/debug.py COPYONLY)
+configure_file(netstring.py ${CMAKE_CURRENT_BINARY_DIR}/netstring.py COPYONLY)
+
diff --git a/python/icinga2/utils/__init__.py b/python/icinga2/utils/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/python/icinga2/utils/debug.py b/python/icinga2/utils/debug.py
new file mode 100644 (file)
index 0000000..81b314e
--- /dev/null
@@ -0,0 +1,115 @@
+# Icinga 2
+# Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+from icinga2.utils import netstring
+import subprocess
+
+try:
+    import json
+except ImportError:
+    import simplejson as json
+
+class ConsoleColors(object):
+    @staticmethod
+    def _exec(args):
+        return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
+
+    def __init__(self):
+        self.RESET = ConsoleColors._exec(['tput', 'sgr0'])
+        self.GREEN = ConsoleColors._exec(['tput', 'setaf', '2'])
+        self.CYAN = ConsoleColors._exec(['tput', 'setaf', '6'])
+
+_colors = ConsoleColors()
+
+class DebugObject(object):
+    def __init__(self, obj):
+        self._obj = obj
+
+    def __str__(self):
+        return self.format_object()
+
+    def format_object(self):
+        if self._obj["abstract"]:
+            result = "Template '"
+        else:
+            result = "Object '"
+        result += self._obj["properties"]["__name"] + "' of type '" + self._obj["type"] + "':\n"
+        result += self.format_properties(2)
+        return result
+
+    @staticmethod
+    def format_value(value):
+        if isinstance(value, list):
+            result = ""
+            for avalue in value:
+                if result != "":
+                    result += ", "
+                result += DebugObject.format_value(avalue)
+            return "[%s]" % (result)
+        elif isinstance(value, basestring):
+            return "'%s'" % (str(value))
+        else:
+            return str(value)
+
+    def format_properties(self, indent=0, path=[]):
+        props = self._obj["properties"]
+        for component in path:
+            props = props[component]
+
+        result = ""
+        for key, value in props.items():
+            path.append(key)
+            result += ' ' * indent + "* %s%s%s" % (_colors.GREEN, key, _colors.RESET)
+            hints = self.format_hints(self, indent + 2, path)
+            if isinstance(value, dict):
+                result += "\n" + hints
+                result += self.format_properties(indent + 2, path)
+            else:
+                result += " = %s\n" % (DebugObject.format_value(value))
+                result += hints
+            path.pop()
+        return result
+
+    def format_hints(self, dhints, indent=0, path=[]):
+        dhints = self._obj["debug_hints"]
+        try:
+            for component in path:
+                dhints = dhints["properties"][component]
+        except KeyError:
+            return ""
+
+        result = ""
+        for message in dhints["messages"]:
+            result += ' ' * indent + "%% %smodified in %s, lines %s:%s-%s:%s%s\n" % (_colors.CYAN,
+              message[1], message[2], message[3], message[4], message[5], _colors.RESET)
+        return result
+
+class ObjectsFile(object):
+    def __init__(self, file):
+        self._file = file
+
+    def __iter__(self):
+        fr = netstring.FileReader(self._file)
+
+        while True:
+            try:
+                json_data = fr.readskip()
+            except EOFError:
+                break
+            if json_data == "":
+                break
+            yield DebugObject(json.loads(json_data))
diff --git a/python/icinga2/utils/netstring.py b/python/icinga2/utils/netstring.py
new file mode 100644 (file)
index 0000000..704c66f
--- /dev/null
@@ -0,0 +1,305 @@
+#!/usr/bin/python
+# netstring.py - Netstring encoding/decoding routines.
+# Version 1.1 - July 2003
+# http://www.dlitz.net/software/python-netstring/
+#
+# Copyright (c) 2003 Dwayne C. Litzenberger <dlitz@dlitz.net>
+# 
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# HISTORY:
+#
+# Changes between 1.0 and 1.1:
+# - Renamed Reader to BaseReader.  Use FileReader and StringReader instead.
+# - Added BaseReader.readskip()
+# - Switched to saner stream reading semantics.  Now the stream is not read
+#   until information is requested which requires it to be read.
+# - Added split()
+#
+
+from __future__ import generators
+import StringIO
+
+"""Conversions to/from netstring format.
+
+The netstring format is defined in http://cr.yp.to/proto/netstrings.txt
+(or http://www.dlitz.net/proto/netstrings-abnf.txt if you prefer ABNF)
+
+Classes:
+
+    BaseReader (not to be used directly)
+    FileReader
+    StringReader
+
+Functions:
+
+    dump
+    dumps
+    load
+    loads
+    split
+
+Misc variables:
+
+    maxintlen       - Maximum number of digits when reading integers
+
+"""
+
+__all__ = ['BaseReader', 'FileReader', 'StringReader',
+           'dump', 'dumps', 'load', 'loads', 'split']
+
+maxintlen = 999     # Maximum number of digits when reading integers
+                    # This allows numbers up to 10**1000 - 1, which should
+                    # be large enough for most applications. :-)
+
+
+def dump(s, file):
+    """dump(s, file) -> None
+
+Writes the string s as a netstring to file.
+"""
+    file.write(dumps(s))
+
+
+def dumps(s):
+    """dumps(s) -> string
+
+Encodes the string s as a netstring, and returns the result.
+"""
+    return str(len(s)) + ":" + s + ","
+
+
+def load(file, maxlen=None):
+    """load(file, maxlen=None) -> string
+
+Read a netstring from a file, and return the extracted netstring.
+
+If the parsed string would be longer than maxlen, OverflowError is raised.
+"""
+    n = _readlen(file)
+    if maxlen is not None and n > maxlen:
+        raise OverflowError
+    retval = file.read(n)
+    #assert(len(retval) == n)
+    ch = file.read(1)
+    if ch == "":
+        raise EOFError
+    elif ch != ",":
+        raise ValueError
+    return retval
+
+
+def loads(s, maxlen=None, returnUnparsed=False):
+    """loads(s, maxlen=None, returnUnparsed=False) -> string or (string,
+    string)
+
+Extract a netstring from a string.  If returnUnparsed is false, return the
+decoded netstring, otherwise return a tuple (parsed, unparsed) containing both
+the parsed string and the remaining unparsed part of s.
+
+If the parsed string would be longer than maxlen, OverflowError is raised.
+"""
+    f = StringIO.StringIO(s)
+    parsed = load(f, maxlen=maxlen)
+    if not returnUnparsed:
+        return parsed
+    unparsed = f.read()
+    return parsed, unparsed
+
+
+def _readlen(file):
+    """_readlen(file) -> integer
+
+Read the initial "[length]:" of a netstring from file, and return the length.
+"""
+    i = 0
+    n = ""
+    ch = file.read(1)
+    while ch != ":":
+        if ch == "":
+            raise EOFError
+        elif not ch in "0123456789":
+            raise ValueError
+        n += ch
+        i += 1
+        if i > maxintlen:
+            raise OverflowError
+        ch = file.read(1)
+    #assert(ch == ":")
+    return long(n)
+
+
+def split(s):
+    """split(s) -> list of strings
+
+Return a list of the decoded netstrings in s.
+"""
+    if s == "":
+       raise EOFError
+    retval = []
+    unparsed = s
+    while unparsed != "":
+        parsed, unparsed = loads(unparsed, returnUnparsed=True)
+        retval.append(parsed)
+    return retval
+
+
+class BaseReader:
+    """BaseReader(file, maxlen=None, blocksize=1024) -> BaseReader object
+
+Return a new BaseReader object.  BaseReader allows reading a
+netstring in blocks, instead of reading an netstring into memory at once.
+
+If BaseReader encounters a netstring which is larger than maxlen, it will return
+OverflowError.  BaseReader will also return ValueError if it encounters bad
+formatting, or EOFError if an unexpected attempt is made to read beyond the
+end of file.
+
+The state of BaseReader is undefined once any exception other than StopIteration
+is raised.
+
+blocksize is the size of blocks to use when iterating over the BaseReader class.
+You should not use BaseReader except when subclassing.  Use FileReader or one
+of the other *Reader classes instead.
+"""
+
+    def __init__(self, file, maxlen=None, blocksize=1024):
+        self._file = file
+        self._length = None
+        self._bytesleft = 0L
+        self._maxlen = maxlen
+        self._blocksize = blocksize
+
+    def _readlen(self):
+        if self._length is None:
+            self._length = _readlen(self._file)
+            self._bytesleft = self._length
+            if self._maxlen is not None and self._length > self._maxlen:
+                raise OverflowError
+            # Handle the 0-byte case
+            if self._length == 0:
+                ch = self._file.read(1)
+                if ch == "":
+                    raise EOFError
+                elif ch != ",":
+                    raise ValueError
+
+    def read(self, size=None):
+        """x.read([size]) -> string
+
+Works like <fileobject>.read.
+"""
+        self._readlen()
+        if size is None or size > self._bytesleft:
+            size = self._bytesleft
+        if size == 0:
+            return ""
+        retval = self._file.read(size)
+        self._bytesleft -= len(retval)
+        if self._bytesleft == 0:
+            ch = self._file.read(1)
+            if ch == "":
+                raise EOFError
+            elif ch != ",":
+                raise ValueError
+        return retval
+
+    def length(self):
+        """x.length() -> long
+
+Return the total length of the decoded string.
+"""
+        self._readlen()
+        return self._length
+
+    def bytesremaining(self):
+        """x.bytesremaining() -> long
+
+Return the number of decoded string bytes remaining to be read from the file.
+"""
+        self._readlen()
+        return self._bytesleft
+
+    def skip(self):
+        """x.skip() -> None
+
+Skip to the next netstring.
+"""
+        self._readlen()
+        if self._bytesleft:
+            self._file.seek(self._bytesleft, 1)
+            ch = self._file.read(1)
+            if ch == "":
+                raise EOFError
+            elif ch != ",":
+                raise ValueError
+        self._bytesleft = 0L
+        self._length = None
+
+    def readskip(self, size=None):
+        """x.readskip([size]) -> string
+
+Equivalent to x.read([size]); x.skip().  Returns whatever is returned by
+x.read().
+"""
+        retval = self.read(size)
+        self.skip()
+        return retval
+
+    def __iter__(self):
+        """x.__iter__() -> iterator
+
+Return a block of the decoded netstring.
+"""
+        block = self.read(self._blocksize)
+        while block != "":
+            yield block
+            block = self.read(self._blocksize)
+
+    def __len__(self):
+        """x.__len__() -> integer
+
+Return the total length of the decoded string.
+
+Note that this is limited to the maximum integer value.  Use x.length()
+wherever possible.
+"""
+        return int(self.length())
+
+
+class FileReader(BaseReader):
+    """FileReader(file, ...) -> FileReader object
+
+Takes a file as input.  See BaseReader.__doc__ for more information.
+"""
+    pass
+
+
+class StringReader(BaseReader):
+    """StringReader(s, ...) -> StringReader object
+
+Takes a string as input.  See BaseReader.__doc__ for more information.
+"""
+    def __init__(self, s, *args, **kwargs):    
+        file = StringIO.StringIO(s)
+        return BaseReader.__init__(self, file, *args, **kwargs)
+
+
+# vim:set tw=78 sw=4 ts=4 expandtab:
diff --git a/python/setup.py.cmake b/python/setup.py.cmake
new file mode 100644 (file)
index 0000000..ce8e1e0
--- /dev/null
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+import os, re
+from setuptools import setup, find_packages
+
+def get_icinga2_version():
+    spec = open(os.path.join('@PROJECT_SOURCE_DIR@', 'icinga2.spec')).read()
+    m = re.search('^Version: (.*)$', spec, re.MULTILINE)
+    if not m:
+        return None
+    return m.group(1)
+
+setup(
+    name = 'icinga2',
+    version = get_icinga2_version(),
+    packages = find_packages(),
+    entry_points = {
+        'console_scripts': [ 'icinga2-list-objects=icinga2.commands.list_objects:main' ]
+    }
+)
+
diff --git a/third-party/cmake/PythonSetup.cmake b/third-party/cmake/PythonSetup.cmake
new file mode 100644 (file)
index 0000000..9042eae
--- /dev/null
@@ -0,0 +1,215 @@
+# Copyright: 2004 Martin F. Krafft <madduck@debian.org>
+#            2008 Martin Schreiber <schreiberx@gmail.com>
+#            2012-2013 Sebastian Ramacher <sramacher@debian.org>
+# License: Artistic-2.0
+# 
+# License: Artistic-2.0
+#  Copyright (c) 2000-2006, The Perl Foundation.
+#  http://www.perlfoundation.org/artistic_license_2_0
+#  .
+#  Everyone is permitted to copy and distribute verbatim copies of this
+#  license document, but changing it is not allowed.
+#  .
+#  Preamble
+#  .
+#  This license establishes the terms under which a given free software
+#  Package may be copied, modified, distributed, and/or redistributed.
+#  The intent is that the Copyright Holder maintains some artistic
+#  control over the development of that Package while still keeping the
+#  Package available as open source and free software.
+#  .
+#  You are always permitted to make arrangements wholly outside of this
+#  license directly with the Copyright Holder of a given Package. If the
+#  terms of this license do not permit the full use that you propose to
+#  make of the Package, you should contact the Copyright Holder and seek
+#  a different licensing arrangement.
+#  .
+#  Definitions
+#  .
+#  "Copyright Holder" means the individual(s) or organization(s) named in
+#  the copyright notice for the entire Package.
+#  .
+#  "Contributor" means any party that has contributed code or other
+#  material to the Package, in accordance with the Copyright Holder's
+#  procedures.
+#  .
+#  "You" and "your" means any person who would like to copy, distribute,
+#  or modify the Package.
+#  .
+#  "Package" means the collection of files distributed by the Copyright
+#  Holder, and derivatives of that collection and/or of those files. A
+#  given Package may consist of either the Standard Version, or a
+#  Modified Version.
+#  .
+#  "Distribute" means providing a copy of the Package or making it
+#  accessible to anyone else, or in the case of a company or
+#  organization, to others outside of your company or organization.
+#  .
+#  "Distributor Fee" means any fee that you charge for Distributing this
+#  Package or providing support for this Package to another party. It
+#  does not mean licensing fees.
+#  .
+#  "Standard Version" refers to the Package if it has not been modified,
+#  or has been modified only in ways explicitly requested by the
+#  Copyright Holder.
+#  .
+#  "Modified Version" means the Package, if it has been changed, and such
+#  changes were not explicitly requested by the Copyright Holder.
+#  .
+#  "Original License" means this Artistic License as Distributed with the
+#  Standard Version of the Package, in its current version or as it may
+#  be modified by The Perl Foundation in the future.
+#  .
+#  "Source" form means the source code, documentation source, and
+#  configuration files for the Package.
+#  .
+#  "Compiled" form means the compiled bytecode, object code, binary, or
+#  any other form resulting from mechanical transformation or translation
+#  of the Source form.
+#  .
+#  Permission for Use and Modification Without Distribution
+#  .
+#  (1) You are permitted to use the Standard Version and create and use
+#  Modified Versions for any purpose without restriction, provided that
+#  you do not Distribute the Modified Version.
+#  .
+#  Permissions for Redistribution of the Standard Version
+#  .
+#  (2) You may Distribute verbatim copies of the Source form of the
+#  Standard Version of this Package in any medium without restriction,
+#  either gratis or for a Distributor Fee, provided that you duplicate
+#  all of the original copyright notices and associated disclaimers. At
+#  your discretion, such verbatim copies may or may not include a
+#  Compiled form of the Package.
+#  .
+#  (3) You may apply any bug fixes, portability changes, and other
+#  modifications made available from the Copyright Holder. The resulting
+#  Package will still be considered the Standard Version, and as such
+#  will be subject to the Original License.
+#  .
+#  Distribution of Modified Versions of the Package as Source
+#  .
+#  (4) You may Distribute your Modified Version as Source (either gratis
+#  or for a Distributor Fee, and with or without a Compiled form of the
+#  Modified Version) provided that you clearly document how it differs
+#  from the Standard Version, including, but not limited to, documenting
+#  any non-standard features, executables, or modules, and provided that
+#  you do at least ONE of the following:
+#  .
+#  (a) make the Modified Version available to the Copyright Holder of the
+#  Standard Version, under the Original License, so that the Copyright
+#  Holder may include your modifications in the Standard Version. (b)
+#  ensure that installation of your Modified Version does not prevent the
+#  user installing or running the Standard Version. In addition, the
+#  Modified Version must bear a name that is different from the name of
+#  the Standard Version. (c) allow anyone who receives a copy of the
+#  Modified Version to make the Source form of the Modified Version
+#  available to others under (i) the Original License or (ii) a license
+#  that permits the licensee to freely copy, modify and redistribute the
+#  Modified Version using the same licensing terms that apply to the copy
+#  that the licensee received, and requires that the Source form of the
+#  Modified Version, and of any works derived from it, be made freely
+#  available in that license fees are prohibited but Distributor Fees are
+#  allowed.
+#  .
+#  Distribution of Compiled Forms of the Standard Version or Modified
+#  Versions without the Source
+#  .
+#  (5) You may Distribute Compiled forms of the Standard Version without
+#  the Source, provided that you include complete instructions on how to
+#  get the Source of the Standard Version. Such instructions must be
+#  valid at the time of your distribution. If these instructions, at any
+#  time while you are carrying out such distribution, become invalid, you
+#  must provide new instructions on demand or cease further distribution.
+#  If you provide valid instructions or cease distribution within thirty
+#  days after you become aware that the instructions are invalid, then
+#  you do not forfeit any of your rights under this license.
+#  .
+#  (6) You may Distribute a Modified Version in Compiled form without the
+#  Source, provided that you comply with Section 4 with respect to the
+#  Source of the Modified Version.
+#  .
+#  Aggregating or Linking the Package
+#  .
+#  (7) You may aggregate the Package (either the Standard Version or
+#  Modified Version) with other packages and Distribute the resulting
+#  aggregation provided that you do not charge a licensing fee for the
+#  Package. Distributor Fees are permitted, and licensing fees for other
+#  components in the aggregation are permitted. The terms of this license
+#  apply to the use and Distribution of the Standard or Modified Versions
+#  as included in the aggregation.
+#  .
+#  (8) You are permitted to link Modified and Standard Versions with
+#  other works, to embed the Package in a larger work of your own, or to
+#  build stand-alone binary or bytecode versions of applications that
+#  include the Package, and Distribute the result without restriction,
+#  provided the result does not expose a direct interface to the Package.
+#  .
+#  Items That are Not Considered Part of a Modified Version
+#  .
+#  (9) Works (including, but not limited to, modules and scripts) that
+#  merely extend or make use of the Package, do not, by themselves, cause
+#  the Package to be a Modified Version. In addition, such works are not
+#  considered parts of the Package itself, and are not subject to the
+#  terms of this license.
+#  .
+#  General Provisions
+#  .
+#  (10) Any use, modification, and distribution of the Standard or
+#  Modified Versions is governed by this Artistic License. By using,
+#  modifying or distributing the Package, you accept this license. Do not
+#  use, modify, or distribute the Package, if you do not accept this
+#  license.
+#  .
+#  (11) If your Modified Version has been derived from a Modified Version
+#  made by someone other than you, you are nevertheless required to
+#  ensure that your Modified Version complies with the requirements of
+#  this license.
+#  .
+#  (12) This license does not grant you the right to use any trademark,
+#  service mark, tradename, or logo of the Copyright Holder.
+#  .
+#  (13) This license includes the non-exclusive, worldwide,
+#  free-of-charge patent license to make, have made, use, offer to sell,
+#  sell, import and otherwise transfer the Package with respect to any
+#  patent claims licensable by the Copyright Holder that are necessarily
+#  infringed by the Package. If you institute patent litigation
+#  (including a cross-claim or counterclaim) against any party alleging
+#  that the Package constitutes direct or contributory patent
+#  infringement, then this Artistic License to you shall terminate on the
+#  date that such litigation is filed.
+#  .
+#  (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT
+#  HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED
+#  WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+#  PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT
+#  PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT
+#  HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT,
+#  INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
+#  OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This is a ugly workaround to be able to pass DESTDIR as --root to setup.py.
+# cmake expands any occurence of $ENV{foo} with the value of foo while runing
+# cmake and not while running make afterwards.
+
+SET(PYTHON_EXECUTABLE "" CACHE FORCE "Python executable")
+SET(PREFIX ${CMAKE_INSTALL_PREFIX} CACHE FORCE "cmake install prefix")
+SET(WDIR "" CACHE FORCE "working directory")
+SET(SETUP_PY "" CACHE FORCE "setup.py path")
+SET(EXTRA_ARGS $ENV{SETUP_PY_EXTRA_ARGS} CACHE FORCE "extra arguments for setup.py")
+
+SET(INSTALL_ROOT $ENV{DESTDIR})
+IF(INSTALL_ROOT)
+  SET(INSTALL_ROOT_ARGS "--root=$ENV{DESTDIR}")
+ELSE(INSTALL_ROOT)
+  SET(INSTALL_ROOT_ARGS "")
+ENDIF(INSTALL_ROOT)
+
+EXECUTE_PROCESS(
+  COMMAND ${PYTHON_EXECUTABLE}
+    ${SETUP_PY}
+    install
+    --prefix=${PREFIX}
+    ${INSTALL_ROOT_ARGS}
+    ${EXTRA_ARGS}
+  WORKING_DIRECTORY ${WDIR})