/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ #include "icinga/compatutility.hpp" #include "icinga/checkcommand.hpp" #include "icinga/eventcommand.hpp" #include "icinga/notificationcommand.hpp" #include "icinga/pluginutility.hpp" #include "icinga/service.hpp" #include "base/utility.hpp" #include "base/configtype.hpp" #include "base/objectlock.hpp" #include "base/convert.hpp" #include #include using namespace icinga; /* Used in DB IDO and Livestatus. */ String CompatUtility::GetCommandLine(const Command::Ptr& command) { Value commandLine = command->GetCommandLine(); String result; if (commandLine.IsObjectType()) { Array::Ptr args = commandLine; ObjectLock olock(args); for (const String& arg : args) { // This is obviously incorrect for non-trivial cases. result += " \"" + EscapeString(arg) + "\""; } } else if (!commandLine.IsEmpty()) { result = EscapeString(Convert::ToString(commandLine)); } else { result = ""; } return result; } String CompatUtility::GetCommandNamePrefix(const Command::Ptr& command) /* Helper. */ { if (!command) return Empty; String prefix; if (command->GetReflectionType() == CheckCommand::TypeInstance) prefix = "check_"; else if (command->GetReflectionType() == NotificationCommand::TypeInstance) prefix = "notification_"; else if (command->GetReflectionType() == EventCommand::TypeInstance) prefix = "event_"; return prefix; } String CompatUtility::GetCommandName(const Command::Ptr& command) /* Used in DB IDO and Livestatus. */ { if (!command) return Empty; return GetCommandNamePrefix(command) + command->GetName(); } /* Used in DB IDO and Livestatus. */ String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable) { CheckCommand::Ptr command = checkable->GetCheckCommand(); Dictionary::Ptr args = new Dictionary(); if (command) { Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); String command_line = GetCommandLine(command); Dictionary::Ptr command_vars = command->GetVars(); if (command_vars) { ObjectLock olock(command_vars); for (const Dictionary::Pair& kv : command_vars) { String macro = "$" + kv.first + "$"; // this is too simple if (command_line.Contains(macro)) args->Set(kv.first, kv.second); } } Dictionary::Ptr host_vars = host->GetVars(); if (host_vars) { ObjectLock olock(host_vars); for (const Dictionary::Pair& kv : host_vars) { String macro = "$" + kv.first + "$"; // this is too simple if (command_line.Contains(macro)) args->Set(kv.first, kv.second); macro = "$host.vars." + kv.first + "$"; if (command_line.Contains(macro)) args->Set(kv.first, kv.second); } } if (service) { Dictionary::Ptr service_vars = service->GetVars(); if (service_vars) { ObjectLock olock(service_vars); for (const Dictionary::Pair& kv : service_vars) { String macro = "$" + kv.first + "$"; // this is too simple if (command_line.Contains(macro)) args->Set(kv.first, kv.second); macro = "$service.vars." + kv.first + "$"; if (command_line.Contains(macro)) args->Set(kv.first, kv.second); } } } String arg_string; ObjectLock olock(args); for (const Dictionary::Pair& kv : args) { arg_string += Convert::ToString(kv.first) + "=" + Convert::ToString(kv.second) + "!"; } return arg_string; } return Empty; } /* Used in DB IDO and Livestatus. */ int CompatUtility::GetCheckableNotificationLastNotification(const Checkable::Ptr& checkable) { double last_notification = 0.0; for (const Notification::Ptr& notification : checkable->GetNotifications()) { if (notification->GetLastNotification() > last_notification) last_notification = notification->GetLastNotification(); } return static_cast(last_notification); } /* Used in DB IDO and Livestatus. */ int CompatUtility::GetCheckableNotificationNextNotification(const Checkable::Ptr& checkable) { double next_notification = 0.0; for (const Notification::Ptr& notification : checkable->GetNotifications()) { if (next_notification == 0 || notification->GetNextNotification() < next_notification) next_notification = notification->GetNextNotification(); } return static_cast(next_notification); } /* Used in DB IDO and Livestatus. */ int CompatUtility::GetCheckableNotificationNotificationNumber(const Checkable::Ptr& checkable) { int notification_number = 0; for (const Notification::Ptr& notification : checkable->GetNotifications()) { if (notification->GetNotificationNumber() > notification_number) notification_number = notification->GetNotificationNumber(); } return notification_number; } /* Used in DB IDO and Livestatus. */ double CompatUtility::GetCheckableNotificationNotificationInterval(const Checkable::Ptr& checkable) { double notification_interval = -1; for (const Notification::Ptr& notification : checkable->GetNotifications()) { if (notification_interval == -1 || notification->GetInterval() < notification_interval) notification_interval = notification->GetInterval(); } if (notification_interval == -1) notification_interval = 60; return notification_interval / 60.0; } /* Helper. */ int CompatUtility::GetCheckableNotificationTypeFilter(const Checkable::Ptr& checkable) { unsigned long notification_type_filter = 0; for (const Notification::Ptr& notification : checkable->GetNotifications()) { ObjectLock olock(notification); notification_type_filter |= notification->GetTypeFilter(); } return notification_type_filter; } /* Helper. */ int CompatUtility::GetCheckableNotificationStateFilter(const Checkable::Ptr& checkable) { unsigned long notification_state_filter = 0; for (const Notification::Ptr& notification : checkable->GetNotifications()) { ObjectLock olock(notification); notification_state_filter |= notification->GetStateFilter(); } return notification_state_filter; } /* Used in DB IDO and Livestatus. */ std::set CompatUtility::GetCheckableNotificationUsers(const Checkable::Ptr& checkable) { /* Service -> Notifications -> (Users + UserGroups -> Users) */ std::set allUsers; std::set users; for (const Notification::Ptr& notification : checkable->GetNotifications()) { ObjectLock olock(notification); users = notification->GetUsers(); std::copy(users.begin(), users.end(), std::inserter(allUsers, allUsers.begin())); for (const UserGroup::Ptr& ug : notification->GetUserGroups()) { std::set members = ug->GetMembers(); std::copy(members.begin(), members.end(), std::inserter(allUsers, allUsers.begin())); } } return allUsers; } /* Used in DB IDO and Livestatus. */ std::set CompatUtility::GetCheckableNotificationUserGroups(const Checkable::Ptr& checkable) { std::set usergroups; /* Service -> Notifications -> UserGroups */ for (const Notification::Ptr& notification : checkable->GetNotifications()) { ObjectLock olock(notification); for (const UserGroup::Ptr& ug : notification->GetUserGroups()) { usergroups.insert(ug); } } return usergroups; } /* Used in DB IDO, Livestatus, CompatLogger, GelfWriter, IcingaDB. */ String CompatUtility::GetCheckResultOutput(const CheckResult::Ptr& cr) { if (!cr) return Empty; String output; String raw_output = cr->GetOutput(); size_t line_end = raw_output.Find("\n"); return raw_output.SubStr(0, line_end); } /* Used in DB IDO, Livestatus and IcingaDB. */ String CompatUtility::GetCheckResultLongOutput(const CheckResult::Ptr& cr) { if (!cr) return Empty; String long_output; String output; String raw_output = cr->GetOutput(); size_t line_end = raw_output.Find("\n"); if (line_end > 0 && line_end != String::NPos) { long_output = raw_output.SubStr(line_end+1, raw_output.GetLength()); return EscapeString(long_output); } return Empty; } /* Helper for DB IDO and Livestatus. */ String CompatUtility::EscapeString(const String& str) { String result = str; boost::algorithm::replace_all(result, "\n", "\\n"); return result; } /* Used in ExternalCommandListener. */ String CompatUtility::UnEscapeString(const String& str) { String result = str; boost::algorithm::replace_all(result, "\\n", "\n"); return result; }