Value ServicesTable::CustomVariablesAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; Dictionary::Ptr vars = service->GetVars(); ArrayData result; if (vars) { ObjectLock olock(vars); for (const Dictionary::Pair& kv : vars) { Value val; if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>()) val = JsonEncode(kv.second); else val = kv.second; result.push_back(new Array({ kv.first, val })); } } return new Array(std::move(result)); }
void ElasticsearchWriter::NotificationSentToAllUsersHandlerInternal(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const std::set<User::Ptr>& users, NotificationType type, const CheckResult::Ptr& cr, const String& author, const String& text) { AssertOnWorkQueue(); CONTEXT("Elasticwriter processing notification to all users '" + checkable->GetName() + "'"); Log(LogDebug, "ElasticsearchWriter") << "Processing notification for '" << checkable->GetName() << "'"; Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); String notificationTypeString = Notification::NotificationTypeToString(type); Dictionary::Ptr fields = new Dictionary(); if (service) { fields->Set("service", service->GetShortName()); fields->Set("state", service->GetState()); fields->Set("last_state", service->GetLastState()); fields->Set("last_hard_state", service->GetLastHardState()); } else { fields->Set("state", host->GetState()); fields->Set("last_state", host->GetLastState()); fields->Set("last_hard_state", host->GetLastHardState()); } fields->Set("host", host->GetName()); ArrayData userNames; for (const User::Ptr& user : users) { userNames.push_back(user->GetName()); } fields->Set("users", new Array(std::move(userNames))); fields->Set("notification_type", notificationTypeString); fields->Set("author", author); fields->Set("text", text); CheckCommand::Ptr commandObj = checkable->GetCheckCommand(); if (commandObj) fields->Set("check_command", commandObj->GetName()); double ts = Utility::GetTime(); if (cr) { AddCheckResult(fields, checkable, cr); ts = cr->GetExecutionEnd(); } Enqueue(checkable, "notification", fields, ts); }
Value ServicesTable::ContactsAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; ArrayData result; for (const User::Ptr& user : CompatUtility::GetCheckableNotificationUsers(service)) { result.push_back(user->GetName()); } return new Array(std::move(result)); }
Value ServiceGroupsTable::MembersAccessor(const Value& row) { ServiceGroup::Ptr sg = static_cast<ServiceGroup::Ptr>(row); if (!sg) return Empty; ArrayData result; for (const Service::Ptr& service : sg->GetMembers()) { result.push_back(new Array({ service->GetHost()->GetName(), service->GetShortName() })); } return new Array(std::move(result)); }
Value ServicesTable::CommentsAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; ArrayData result; for (const Comment::Ptr& comment : service->GetComments()) { if (comment->IsExpired()) continue; result.push_back(comment->GetLegacyId()); } return new Array(std::move(result)); }
void ClusterEvents::NotificationSentToAllUsersHandler(const Notification::Ptr& notification, const Checkable::Ptr& checkable, const std::set<User::Ptr>& users, NotificationType notificationType, const CheckResult::Ptr& cr, const String& author, const String& commentText, const MessageOrigin::Ptr& origin) { ApiListener::Ptr listener = ApiListener::GetInstance(); if (!listener) return; Host::Ptr host; Service::Ptr service; tie(host, service) = GetHostService(checkable); Dictionary::Ptr params = new Dictionary(); params->Set("host", host->GetName()); if (service) params->Set("service", service->GetShortName()); params->Set("notification", notification->GetName()); ArrayData ausers; for (const User::Ptr& user : users) { ausers.push_back(user->GetName()); } params->Set("users", new Array(std::move(ausers))); params->Set("type", notificationType); params->Set("cr", Serialize(cr)); params->Set("author", author); params->Set("text", commentText); params->Set("last_notification", notification->GetLastNotification()); params->Set("next_notification", notification->GetNextNotification()); params->Set("notification_number", notification->GetNotificationNumber()); params->Set("last_problem_notification", notification->GetLastProblemNotification()); params->Set("no_more_notifications", notification->GetNoMoreNotifications()); Dictionary::Ptr message = new Dictionary(); message->Set("jsonrpc", "2.0"); message->Set("method", "event::NotificationSentToAllUsers"); message->Set("params", params); listener->RelayMessage(origin, nullptr, message, true); }
Value ServicesTable::CustomVariableNamesAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; Dictionary::Ptr vars = service->GetVars(); ArrayData result; if (vars) { ObjectLock olock(vars); for (const Dictionary::Pair& kv : vars) { result.push_back(kv.first); } } return new Array(std::move(result)); }
Value CommandsTable::CustomVariableValuesAccessor(const Value& row) { Command::Ptr command = static_cast<Command::Ptr>(row); if (!command) return Empty; Dictionary::Ptr vars = command->GetVars(); ArrayData keys; if (vars) { ObjectLock xlock(vars); for (const auto& kv : vars) { keys.push_back(kv.second); } } return new Array(std::move(keys)); }
Value ServicesTable::DowntimesWithInfoAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; ArrayData result; for (const Downtime::Ptr& downtime : service->GetDowntimes()) { if (downtime->IsExpired()) continue; result.push_back(new Array({ downtime->GetLegacyId(), downtime->GetAuthor(), downtime->GetComment() })); } return new Array(std::move(result)); }
Value CommandsTable::CustomVariablesAccessor(const Value& row) { Command::Ptr command = static_cast<Command::Ptr>(row); if (!command) return Empty; Dictionary::Ptr vars = command->GetVars(); ArrayData result; if (vars) { ObjectLock xlock(vars); for (const auto& kv : vars) { result.push_back(new Array({ kv.first, kv.second })); } } return new Array(std::move(result)); }
Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row) { Service::Ptr service = static_cast<Service::Ptr>(row); if (!service) return Empty; ArrayData result; for (const Comment::Ptr& comment : service->GetComments()) { if (comment->IsExpired()) continue; result.push_back(new Array({ comment->GetLegacyId(), comment->GetAuthor(), comment->GetText(), comment->GetEntryType(), static_cast<int>(comment->GetEntryTime()) })); } return new Array(std::move(result)); }
bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response, const Dictionary::Ptr& params) { if (request.RequestUrl->GetPath().size() < 3 || request.RequestUrl->GetPath().size() > 4) return false; if (request.RequestMethod != "GET") return false; Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[2]); if (!type) { HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); return true; } QueryDescription qd; qd.Types.insert(type->GetName()); qd.Permission = "objects/query/" + type->GetName(); Array::Ptr uattrs, ujoins, umetas; try { uattrs = params->Get("attrs"); } catch (const std::exception&) { HttpUtility::SendJsonError(response, params, 400, "Invalid type for 'attrs' attribute specified. Array type is required."); return true; } try { ujoins = params->Get("joins"); } catch (const std::exception&) { HttpUtility::SendJsonError(response, params, 400, "Invalid type for 'joins' attribute specified. Array type is required."); return true; } try { umetas = params->Get("meta"); } catch (const std::exception&) { HttpUtility::SendJsonError(response, params, 400, "Invalid type for 'meta' attribute specified. Array type is required."); return true; } bool allJoins = HttpUtility::GetLastParameter(params, "all_joins"); params->Set("type", type->GetName()); if (request.RequestUrl->GetPath().size() >= 4) { String attr = type->GetName(); boost::algorithm::to_lower(attr); params->Set(attr, request.RequestUrl->GetPath()[3]); } std::vector<Value> objs; try { objs = FilterUtility::GetFilterTargets(qd, params, user); } catch (const std::exception& ex) { HttpUtility::SendJsonError(response, params, 404, "No objects found.", DiagnosticInformation(ex)); return true; } ArrayData results; results.reserve(objs.size()); std::set<String> joinAttrs; std::set<String> userJoinAttrs; if (ujoins) { ObjectLock olock(ujoins); for (const String& ujoin : ujoins) { userJoinAttrs.insert(ujoin.SubStr(0, ujoin.FindFirstOf("."))); } } for (int fid = 0; fid < type->GetFieldCount(); fid++) { Field field = type->GetFieldInfo(fid); if (!(field.Attributes & FANavigation)) continue; if (!allJoins && userJoinAttrs.find(field.NavigationName) == userJoinAttrs.end()) continue; joinAttrs.insert(field.Name); } for (const ConfigObject::Ptr& obj : objs) { DictionaryData result1{ { "name", obj->GetName() }, { "type", obj->GetReflectionType()->GetName() } }; DictionaryData metaAttrs; if (umetas) { ObjectLock olock(umetas); for (const String& meta : umetas) { if (meta == "used_by") { Array::Ptr used_by = new Array(); metaAttrs.emplace_back("used_by", used_by); for (const Object::Ptr& pobj : DependencyGraph::GetParents((obj))) { ConfigObject::Ptr configObj = dynamic_pointer_cast<ConfigObject>(pobj); if (!configObj) continue; used_by->Add(new Dictionary({ { "type", configObj->GetReflectionType()->GetName() }, { "name", configObj->GetName() } })); } } else if (meta == "location") { metaAttrs.emplace_back("location", obj->GetSourceLocation()); } else { HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for meta: " + meta); return true; } } } result1.emplace_back("meta", new Dictionary(std::move(metaAttrs))); try { result1.emplace_back("attrs", SerializeObjectAttrs(obj, String(), uattrs, false, false)); } catch (const ScriptError& ex) { HttpUtility::SendJsonError(response, params, 400, ex.what()); return true; } DictionaryData joins; for (const String& joinAttr : joinAttrs) { Object::Ptr joinedObj; int fid = type->GetFieldId(joinAttr); if (fid < 0) { HttpUtility::SendJsonError(response, params, 400, "Invalid field specified for join: " + joinAttr); return true; } Field field = type->GetFieldInfo(fid); if (!(field.Attributes & FANavigation)) { HttpUtility::SendJsonError(response, params, 400, "Not a joinable field: " + joinAttr); return true; } joinedObj = obj->NavigateField(fid); if (!joinedObj) continue; String prefix = field.NavigationName; try { joins.emplace_back(prefix, SerializeObjectAttrs(joinedObj, prefix, ujoins, true, allJoins)); } catch (const ScriptError& ex) { HttpUtility::SendJsonError(response, params, 400, ex.what()); return true; } } result1.emplace_back("joins", new Dictionary(std::move(joins))); results.push_back(new Dictionary(std::move(result1))); } Dictionary::Ptr result = new Dictionary({ { "results", new Array(std::move(results)) } }); response.SetStatus(200, "OK"); HttpUtility::SendJsonBody(response, params, result); return true; }
Value ClusterEvents::CheckResultAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); if (!endpoint) { Log(LogNotice, "ClusterEvents") << "Discarding 'check result' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; return Empty; } CheckResult::Ptr cr; Array::Ptr vperf; if (params->Contains("cr")) { cr = new CheckResult(); Dictionary::Ptr vcr = params->Get("cr"); if (vcr && vcr->Contains("performance_data")) { vperf = vcr->Get("performance_data"); if (vperf) vcr->Remove("performance_data"); Deserialize(cr, vcr, true); } } if (!cr) return Empty; ArrayData rperf; if (vperf) { ObjectLock olock(vperf); for (const Value& vp : vperf) { Value p; if (vp.IsObjectType<Dictionary>()) { PerfdataValue::Ptr val = new PerfdataValue(); Deserialize(val, vp, true); rperf.push_back(val); } else rperf.push_back(vp); } } cr->SetPerformanceData(new Array(std::move(rperf))); Host::Ptr host = Host::GetByName(params->Get("host")); if (!host) return Empty; Checkable::Ptr checkable; if (params->Contains("service")) checkable = host->GetServiceByShortName(params->Get("service")); else checkable = host; if (!checkable) return Empty; if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable) && endpoint != checkable->GetCommandEndpoint()) { Log(LogNotice, "ClusterEvents") << "Discarding 'check result' message for checkable '" << checkable->GetName() << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; return Empty; } if (!checkable->IsPaused() && Zone::GetLocalZone() == checkable->GetZone() && endpoint == checkable->GetCommandEndpoint()) checkable->ProcessCheckResult(cr); else checkable->ProcessCheckResult(cr, origin); return Empty; }
Value ClusterEvents::NotificationSentToAllUsersAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); if (!endpoint) { Log(LogNotice, "ClusterEvents") << "Discarding 'sent notification to all users' message from '" << origin->FromClient->GetIdentity() << "': Invalid endpoint origin (client not allowed)."; return Empty; } Host::Ptr host = Host::GetByName(params->Get("host")); if (!host) return Empty; Checkable::Ptr checkable; if (params->Contains("service")) checkable = host->GetServiceByShortName(params->Get("service")); else checkable = host; if (!checkable) return Empty; if (origin->FromZone && origin->FromZone != Zone::GetLocalZone()) { Log(LogNotice, "ClusterEvents") << "Discarding 'sent notification to all users' message for checkable '" << checkable->GetName() << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; return Empty; } CheckResult::Ptr cr; Array::Ptr vperf; if (params->Contains("cr")) { cr = new CheckResult(); Dictionary::Ptr vcr = params->Get("cr"); if (vcr && vcr->Contains("performance_data")) { vperf = vcr->Get("performance_data"); if (vperf) vcr->Remove("performance_data"); Deserialize(cr, vcr, true); } } NotificationType type = static_cast<NotificationType>(static_cast<int>(params->Get("type"))); String author = params->Get("author"); String text = params->Get("text"); Notification::Ptr notification = Notification::GetByName(params->Get("notification")); if (!notification) return Empty; Array::Ptr ausers = params->Get("users"); if (!ausers) return Empty; std::set<User::Ptr> users; { ObjectLock olock(ausers); for (const String& auser : ausers) { User::Ptr user = User::GetByName(auser); if (!user) continue; users.insert(user); } } notification->SetLastNotification(params->Get("last_notification")); notification->SetNextNotification(params->Get("next_notification")); notification->SetNotificationNumber(params->Get("notification_number")); notification->SetLastProblemNotification(params->Get("last_problem_notification")); notification->SetNoMoreNotifications(params->Get("no_more_notifications")); ArrayData notifiedProblemUsers; for (const User::Ptr& user : users) { notifiedProblemUsers.push_back(user->GetName()); } notification->SetNotifiedProblemUsers(new Array(std::move(notifiedProblemUsers))); Checkable::OnNotificationSentToAllUsers(notification, checkable, users, type, cr, author, text, origin); return Empty; }