Implement support for auto-discovering services for passive agents.

Fixes #6002
This commit is contained in:
Gunnar Beutner 2014-04-13 09:22:27 +02:00
parent a00fbca5f4
commit ca4fe71d69
9 changed files with 153 additions and 35 deletions

View File

@ -34,3 +34,6 @@ set_target_properties (
install(TARGETS agent RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/icinga2)
#install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/agent\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LOCALSTATEDIR}/lib/icinga2/agent/inventory\")")

View File

@ -27,6 +27,7 @@
#include "base/networkstream.h"
#include "base/application.h"
#include "base/context.h"
#include <fstream>
using namespace icinga;
@ -64,6 +65,11 @@ shared_ptr<SSL_CTX> AgentListener::GetSSLContext(void) const
return m_SSLContext;
}
String AgentListener::GetInventoryDir(void)
{
return Application::GetLocalStateDir() + "/lib/icinga2/agent/inventory/";
}
/**
* Creates a new JSON-RPC listener on the specified port.
*
@ -246,6 +252,28 @@ void AgentListener::MessageHandler(const TlsStream::Ptr& sender, const String& i
CheckResult::Ptr cr = servicecr;
service->ProcessCheckResult(cr);
}
Dictionary::Ptr inventoryDescr = make_shared<Dictionary>();
inventoryDescr->Set("identity", identity);
inventoryDescr->Set("crs", params);
String inventoryFile = GetInventoryDir() + SHA256(identity);
String inventoryTempFile = inventoryFile + ".tmp";
std::ofstream fp(inventoryTempFile.CStr(), std::ofstream::out | std::ostream::trunc);
fp << JsonSerialize(inventoryDescr);
fp.close();
#ifdef _WIN32
_unlink(inventoryFile.CStr());
#endif /* _WIN32 */
if (rename(inventoryTempFile.CStr(), inventoryFile.CStr()) < 0) {
BOOST_THROW_EXCEPTION(posix_error()
<< boost::errinfo_api_function("rename")
<< boost::errinfo_errno(errno)
<< boost::errinfo_file_name(inventoryTempFile));
}
}
}

View File

@ -62,6 +62,8 @@ private:
void MessageHandler(const TlsStream::Ptr& sender, const String& identity, const Dictionary::Ptr& message);
static String GetInventoryDir(void);
friend class AgentCheckTask;
};

View File

@ -5,4 +5,6 @@ usr/bin/icinga2-migrate-config
usr/sbin/icinga2-*-feature
usr/sbin/icinga2-setup-agent
usr/sbin/icinga2-discover-agent
usr/sbin/icinga2-forget-agent
usr/sbin/icinga2-list-agents
usr/share/icinga2

View File

@ -426,6 +426,8 @@ exit 0
%{_sbindir}/%{name}-disable-feature
%{_sbindir}/%{name}-setup-agent
%{_sbindir}/%{name}-discover-agent
%{_sbindir}/%{name}-forget-agent
%{_sbindir}/%{name}-list-agents
%exclude %{_libdir}/%{name}/libdb_ido_mysql*
%exclude %{_libdir}/%{name}/libdb_ido_pgsql*
%{_libdir}/%{name}

View File

@ -21,9 +21,12 @@ add_subdirectory(mkembedconfig)
if(UNIX OR CYGWIN)
configure_file(icinga2-enable-feature.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga2-enable-feature @ONLY)
configure_file(icinga2-discover-agent.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga2-discover-agent @ONLY)
configure_file(icinga2-forget-agent.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga2-forget-agent @ONLY)
configure_file(icinga2-list-agents.cmake ${CMAKE_CURRENT_BINARY_DIR}/icinga2-list-agents @ONLY)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/icinga2-enable-feature ${CMAKE_CURRENT_BINARY_DIR}/icinga2-discover-agent
${CMAKE_CURRENT_BINARY_DIR}/icinga2-forget-agent ${CMAKE_CURRENT_BINARY_DIR}/icinga2-list-agents
DESTINATION ${CMAKE_INSTALL_SBINDIR}
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)

View File

@ -109,17 +109,20 @@ class NetstringParser(object):
# along with this program; if not, write to the Free Software Foundation
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
import socket, ssl, pprint, sys, json, os
import socket, ssl, sys, json, os, hashlib
def warning(*objs):
print(*objs, file=sys.stderr)
if len(sys.argv) < 3:
warning("Syntax: %s <host> <port>" % (sys.argv[0]))
if len(sys.argv) < 2:
warning("Syntax: %s <host> [<port>]" % (sys.argv[0]))
sys.exit(1)
host = sys.argv[1]
if len(sys.argv) > 2:
port = int(sys.argv[2])
else:
port = 8483
agentpki = "@CMAKE_INSTALL_FULL_SYSCONFDIR@/icinga2/pki/agent"
keyfile = agentpki + "/agent.key"
@ -164,6 +167,8 @@ while True:
break
nsp.feed(data)
ssl_sock.close()
if len(nsp.results) != 1:
warning("Agent returned invalid response: ", repr(nsp.results))
sys.exit(1)
@ -177,14 +182,11 @@ if method != "push_crs":
params = response['params']
for service in params['services']:
print(\
"""apply Service "%s" {
import "agent-service"
inventory_file = "@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/lib/icinga2/agent/inventory/" + hashlib.sha256(cn).hexdigest()
fp = open(inventory_file, "w")
inventory_info = { "identity": cn, "crs": params }
json.dump(inventory_info, fp)
fp.close()
assign where host.name == "%s"
}
""" % (service, cn))
# note that closing the SSLSocket will also close the underlying socket
ssl_sock.close()
print("Inventory information has been updated for agent '%s'." % (cn))
sys.exit(0)

View File

@ -0,0 +1,40 @@
#!/usr/bin/env python
# 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 __future__ import print_function
import sys, os, hashlib
def warning(*objs):
print(*objs, file=sys.stderr)
if len(sys.argv) < 2:
warning("Syntax: %s <identity>" % (sys.argv[0]))
sys.exit(1)
cn = sys.argv[1]
inventory_file = "@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/lib/icinga2/agent/inventory/" + hashlib.sha256(cn).hexdigest()
if not os.path.isfile(inventory_file):
warning("There's no inventory file for agent '%s'.")
sys.exit(0)
os.unlink(inventory_file)
print("Inventory information has been removed for agent '%s'." % (cn))
sys.exit(0)

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
# 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 __future__ import print_function
import sys, os, json
def warning(*objs):
print(*objs, file=sys.stderr)
inventory_dir = "@CMAKE_INSTALL_FULL_LOCALSTATEDIR@/lib/icinga2/agent/inventory/"
inventory = {}
for root, dirs, files in os.walk(inventory_dir):
for file in files:
fp = open(root + file, "r")
inventory_info = json.load(fp)
inventory[inventory_info["identity"]] = inventory_info["crs"]["services"].keys()
json.dump(inventory, sys.stdout)
sys.exit(0)