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\")")
+
#include "base/networkstream.h"
#include "base/application.h"
#include "base/context.h"
+#include <fstream>
using namespace icinga;
/* create the primary JSON-RPC listener */
if (!GetBindPort().IsEmpty())
AddListener(GetBindPort());
-
+
m_AgentTimer = make_shared<Timer>();
m_AgentTimer->OnTimerExpired.connect(boost::bind(&AgentListener::AgentTimerHandler, this));
m_AgentTimer->SetInterval(GetUpstreamInterval());
return m_SSLContext;
}
+String AgentListener::GetInventoryDir(void)
+{
+ return Application::GetLocalStateDir() + "/lib/icinga2/agent/inventory/";
+}
+
/**
* Creates a new JSON-RPC listener on the specified port.
*
void AgentListener::MessageHandler(const TlsStream::Ptr& sender, const String& identity, const Dictionary::Ptr& message)
{
CONTEXT("Processing agent message of type '" + message->Get("method") + "'");
-
+
String method = message->Get("method");
-
+
if (identity == GetUpstreamName()) {
if (method == "get_crs") {
Dictionary::Ptr services = make_shared<Dictionary>();
Host::Ptr host = Host::GetByName("localhost");
-
+
if (!host)
Log(LogWarning, "agent", "Agent doesn't have any services for 'localhost'.");
else {
services->Set(service->GetShortName(), Serialize(service->GetLastCheckResult()));
}
}
-
+
Dictionary::Ptr params = make_shared<Dictionary>();
params->Set("services", services);
params->Set("host", Serialize(host->GetLastCheckResult()));
-
+
Dictionary::Ptr request = make_shared<Dictionary>();
request->Set("method", "push_crs");
request->Set("params", params);
-
+
JsonRpc::SendMessage(sender, request);
}
}
-
+
if (method == "push_crs") {
Host::Ptr host = Host::GetByName(identity);
-
+
if (!host) {
Log(LogWarning, "agent", "Ignoring check results for host '" + identity + "'.");
return;
}
-
+
Dictionary::Ptr params = message->Get("params");
-
+
if (!params)
return;
Value hostcr = Deserialize(params->Get("host"), true);
-
+
if (!hostcr.IsObjectType<CheckResult>()) {
Log(LogWarning, "agent", "Ignoring invalid check result for host '" + identity + "'.");
} else {
}
Dictionary::Ptr services = params->Get("services");
-
+
if (!services)
return;
-
+
Dictionary::Pair kv;
-
+
BOOST_FOREACH(kv, services) {
Service::Ptr service = host->GetServiceByShortName(kv.first);
-
+
if (!service) {
Log(LogWarning, "agent", "Ignoring check result for service '" + kv.first + "' on host '" + identity + "'.");
continue;
}
-
+
Value servicecr = Deserialize(kv.second, true);
-
+
if (!servicecr.IsObjectType<CheckResult>()) {
Log(LogWarning, "agent", "Ignoring invalid check result for service '" + kv.first + "' on host '" + identity + "'.");
continue;
}
-
+
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));
+ }
}
}
if (host.IsEmpty() || port.IsEmpty())
return;
-
+
AddConnection(host, port);
}
void ListenerThreadProc(const Socket::Ptr& server);
void MessageHandler(const TlsStream::Ptr& sender, const String& identity, const Dictionary::Ptr& message);
-
+
+ static String GetInventoryDir(void);
+
friend class AgentCheckTask;
};
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
%{_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}
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
)
# 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]
-port = int(sys.argv[2])
+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"
break
nsp.feed(data)
+ssl_sock.close()
+
if len(nsp.results) != 1:
warning("Agent returned invalid response: ", repr(nsp.results))
sys.exit(1)
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)
--- /dev/null
+#!/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)
--- /dev/null
+#!/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)