1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "icinga/compatutility.hpp"
4 #include "icinga/checkcommand.hpp"
5 #include "icinga/eventcommand.hpp"
6 #include "icinga/notificationcommand.hpp"
7 #include "icinga/pluginutility.hpp"
8 #include "icinga/service.hpp"
9 #include "base/utility.hpp"
10 #include "base/configtype.hpp"
11 #include "base/objectlock.hpp"
12 #include "base/convert.hpp"
13 #include <boost/algorithm/string/replace.hpp>
14 #include <boost/algorithm/string/join.hpp>
16 using namespace icinga;
18 /* Used in DB IDO, StatusDataWriter and Livestatus. */
19 String CompatUtility::GetCommandLine(const Command::Ptr& command)
21 Value commandLine = command->GetCommandLine();
24 if (commandLine.IsObjectType<Array>()) {
25 Array::Ptr args = commandLine;
27 ObjectLock olock(args);
28 for (const String& arg : args) {
29 // This is obviously incorrect for non-trivial cases.
30 result += " \"" + EscapeString(arg) + "\"";
32 } else if (!commandLine.IsEmpty()) {
33 result = EscapeString(Convert::ToString(commandLine));
35 result = "<internal>";
41 String CompatUtility::GetCommandNamePrefix(const Command::Ptr& command)
48 if (command->GetReflectionType() == CheckCommand::TypeInstance)
50 else if (command->GetReflectionType() == NotificationCommand::TypeInstance)
51 prefix = "notification_";
52 else if (command->GetReflectionType() == EventCommand::TypeInstance)
58 String CompatUtility::GetCommandName(const Command::Ptr& command)
59 /* Used in DB IDO, StatusDataWriter and Livestatus. */
64 return GetCommandNamePrefix(command) + command->GetName();
67 /* Used in DB IDO, StatusDataWriter and Livestatus. */
68 String CompatUtility::GetCheckableCommandArgs(const Checkable::Ptr& checkable)
70 CheckCommand::Ptr command = checkable->GetCheckCommand();
72 Dictionary::Ptr args = new Dictionary();
77 tie(host, service) = GetHostService(checkable);
78 String command_line = GetCommandLine(command);
80 Dictionary::Ptr command_vars = command->GetVars();
83 ObjectLock olock(command_vars);
84 for (const Dictionary::Pair& kv : command_vars) {
85 String macro = "$" + kv.first + "$"; // this is too simple
86 if (command_line.Contains(macro))
87 args->Set(kv.first, kv.second);
92 Dictionary::Ptr host_vars = host->GetVars();
95 ObjectLock olock(host_vars);
96 for (const Dictionary::Pair& kv : host_vars) {
97 String macro = "$" + kv.first + "$"; // this is too simple
98 if (command_line.Contains(macro))
99 args->Set(kv.first, kv.second);
100 macro = "$host.vars." + kv.first + "$";
101 if (command_line.Contains(macro))
102 args->Set(kv.first, kv.second);
107 Dictionary::Ptr service_vars = service->GetVars();
110 ObjectLock olock(service_vars);
111 for (const Dictionary::Pair& kv : service_vars) {
112 String macro = "$" + kv.first + "$"; // this is too simple
113 if (command_line.Contains(macro))
114 args->Set(kv.first, kv.second);
115 macro = "$service.vars." + kv.first + "$";
116 if (command_line.Contains(macro))
117 args->Set(kv.first, kv.second);
123 ObjectLock olock(args);
124 for (const Dictionary::Pair& kv : args) {
125 arg_string += Convert::ToString(kv.first) + "=" + Convert::ToString(kv.second) + "!";
133 /* Used in DB IDO, StatusDataWriter and Livestatus. */
134 int CompatUtility::GetCheckableNotificationLastNotification(const Checkable::Ptr& checkable)
136 double last_notification = 0.0;
137 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
138 if (notification->GetLastNotification() > last_notification)
139 last_notification = notification->GetLastNotification();
142 return static_cast<int>(last_notification);
145 /* Used in DB IDO, StatusDataWriter and Livestatus. */
146 int CompatUtility::GetCheckableNotificationNextNotification(const Checkable::Ptr& checkable)
148 double next_notification = 0.0;
149 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
150 if (next_notification == 0 || notification->GetNextNotification() < next_notification)
151 next_notification = notification->GetNextNotification();
154 return static_cast<int>(next_notification);
157 /* Used in DB IDO, StatusDataWriter and Livestatus. */
158 int CompatUtility::GetCheckableNotificationNotificationNumber(const Checkable::Ptr& checkable)
160 int notification_number = 0;
161 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
162 if (notification->GetNotificationNumber() > notification_number)
163 notification_number = notification->GetNotificationNumber();
166 return notification_number;
169 /* Used in DB IDO, StatusDataWriter and Livestatus. */
170 double CompatUtility::GetCheckableNotificationNotificationInterval(const Checkable::Ptr& checkable)
172 double notification_interval = -1;
174 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
175 if (notification_interval == -1 || notification->GetInterval() < notification_interval)
176 notification_interval = notification->GetInterval();
179 if (notification_interval == -1)
180 notification_interval = 60;
182 return notification_interval / 60.0;
186 int CompatUtility::GetCheckableNotificationTypeFilter(const Checkable::Ptr& checkable)
188 unsigned long notification_type_filter = 0;
190 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
191 ObjectLock olock(notification);
193 notification_type_filter |= notification->GetTypeFilter();
196 return notification_type_filter;
200 int CompatUtility::GetCheckableNotificationStateFilter(const Checkable::Ptr& checkable)
202 unsigned long notification_state_filter = 0;
204 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
205 ObjectLock olock(notification);
207 notification_state_filter |= notification->GetStateFilter();
210 return notification_state_filter;
213 /* Used in DB IDO, StatusDataWriter and Livestatus. */
214 std::set<User::Ptr> CompatUtility::GetCheckableNotificationUsers(const Checkable::Ptr& checkable)
216 /* Service -> Notifications -> (Users + UserGroups -> Users) */
217 std::set<User::Ptr> allUsers;
218 std::set<User::Ptr> users;
220 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
221 ObjectLock olock(notification);
223 users = notification->GetUsers();
225 std::copy(users.begin(), users.end(), std::inserter(allUsers, allUsers.begin()));
227 for (const UserGroup::Ptr& ug : notification->GetUserGroups()) {
228 std::set<User::Ptr> members = ug->GetMembers();
229 std::copy(members.begin(), members.end(), std::inserter(allUsers, allUsers.begin()));
236 /* Used in DB IDO, StatusDataWriter and Livestatus. */
237 std::set<UserGroup::Ptr> CompatUtility::GetCheckableNotificationUserGroups(const Checkable::Ptr& checkable)
239 std::set<UserGroup::Ptr> usergroups;
240 /* Service -> Notifications -> UserGroups */
241 for (const Notification::Ptr& notification : checkable->GetNotifications()) {
242 ObjectLock olock(notification);
244 for (const UserGroup::Ptr& ug : notification->GetUserGroups()) {
245 usergroups.insert(ug);
252 /* Used in DB IDO, StatusDataWriter, Livestatus, CompatLogger, GelfWriter. */
253 String CompatUtility::GetCheckResultOutput(const CheckResult::Ptr& cr)
260 String raw_output = cr->GetOutput();
262 size_t line_end = raw_output.Find("\n");
264 return raw_output.SubStr(0, line_end);
267 /* Used in DB IDO, StatusDataWriter and Livestatus. */
268 String CompatUtility::GetCheckResultLongOutput(const CheckResult::Ptr& cr)
276 String raw_output = cr->GetOutput();
278 size_t line_end = raw_output.Find("\n");
280 if (line_end > 0 && line_end != String::NPos) {
281 long_output = raw_output.SubStr(line_end+1, raw_output.GetLength());
282 return EscapeString(long_output);
288 /* Helper for DB IDO, StatusDataWriter and Livestatus. Used in StatusDataWriter. */
289 String CompatUtility::EscapeString(const String& str)
292 boost::algorithm::replace_all(result, "\n", "\\n");
296 /* Used in ExternalCommandListener and CheckResultReader. */
297 String CompatUtility::UnEscapeString(const String& str)
300 boost::algorithm::replace_all(result, "\\n", "\n");