]> granicus.if.org Git - icinga2/blobdiff - lib/livestatus/servicestable.cpp
Move CompatUtility::GetCheckableInCheckPeriod() into Livestatus feature
[icinga2] / lib / livestatus / servicestable.cpp
index b4576c52743374a534b97e1135f16ba0d44a4e85..00b11616ca5abb4e3d628b7214e24df482d8d8f5 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  * Icinga 2                                                                   *
- * Copyright (C) 2012-2015 Icinga Development Team (http://www.icinga.org)    *
+ * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/)  *
  *                                                                            *
  * This program is free software; you can redistribute it and/or              *
  * modify it under the terms of the GNU General Public License                *
 #include "icinga/macroprocessor.hpp"
 #include "icinga/icingaapplication.hpp"
 #include "icinga/compatutility.hpp"
-#include "base/dynamictype.hpp"
+#include "icinga/pluginutility.hpp"
+#include "base/configtype.hpp"
 #include "base/objectlock.hpp"
 #include "base/json.hpp"
 #include "base/convert.hpp"
 #include "base/utility.hpp"
-#include <boost/foreach.hpp>
 #include <boost/tuple/tuple.hpp>
 #include <boost/algorithm/string/replace.hpp>
 
 using namespace icinga;
 
 ServicesTable::ServicesTable(LivestatusGroupByType type)
-    : Table(type)
+       : Table(type)
 {
        AddColumns(this);
 }
 
 
 void ServicesTable::AddColumns(Table *table, const String& prefix,
-    const Column::ObjectAccessor& objectAccessor)
+       const Column::ObjectAccessor& objectAccessor)
 {
        table->AddColumn(prefix + "description", Column(&ServicesTable::ShortNameAccessor, objectAccessor));
        table->AddColumn(prefix + "service_description", Column(&ServicesTable::ShortNameAccessor, objectAccessor)); //ugly compatibility hack
@@ -61,7 +61,7 @@ void ServicesTable::AddColumns(Table *table, const String& prefix,
        table->AddColumn(prefix + "plugin_output", Column(&ServicesTable::PluginOutputAccessor, objectAccessor));
        table->AddColumn(prefix + "long_plugin_output", Column(&ServicesTable::LongPluginOutputAccessor, objectAccessor));
        table->AddColumn(prefix + "perf_data", Column(&ServicesTable::PerfDataAccessor, objectAccessor));
-       table->AddColumn(prefix + "notification_period", Column(&ServicesTable::NotificationPeriodAccessor, objectAccessor));
+       table->AddColumn(prefix + "notification_period", Column(&Table::EmptyStringAccessor, objectAccessor));
        table->AddColumn(prefix + "check_period", Column(&ServicesTable::CheckPeriodAccessor, objectAccessor));
        table->AddColumn(prefix + "notes", Column(&ServicesTable::NotesAccessor, objectAccessor));
        table->AddColumn(prefix + "notes_expanded", Column(&ServicesTable::NotesExpandedAccessor, objectAccessor));
@@ -104,12 +104,12 @@ void ServicesTable::AddColumns(Table *table, const String& prefix,
        table->AddColumn(prefix + "process_performance_data", Column(&ServicesTable::ProcessPerformanceDataAccessor, objectAccessor));
        table->AddColumn(prefix + "is_executing", Column(&Table::ZeroAccessor, objectAccessor));
        table->AddColumn(prefix + "active_checks_enabled", Column(&ServicesTable::ActiveChecksEnabledAccessor, objectAccessor));
-       table->AddColumn(prefix + "check_options", Column(&ServicesTable::CheckOptionsAccessor, objectAccessor));
+       table->AddColumn(prefix + "check_options", Column(&Table::EmptyStringAccessor, objectAccessor));
        table->AddColumn(prefix + "flap_detection_enabled", Column(&ServicesTable::FlapDetectionEnabledAccessor, objectAccessor));
-       table->AddColumn(prefix + "check_freshness", Column(&ServicesTable::CheckFreshnessAccessor, objectAccessor));
+       table->AddColumn(prefix + "check_freshness", Column(&Table::OneAccessor, objectAccessor));
        table->AddColumn(prefix + "obsess_over_service", Column(&Table::ZeroAccessor, objectAccessor));
-       table->AddColumn(prefix + "modified_attributes", Column(&ServicesTable::ModifiedAttributesAccessor, objectAccessor));
-       table->AddColumn(prefix + "modified_attributes_list", Column(&ServicesTable::ModifiedAttributesListAccessor, objectAccessor));
+       table->AddColumn(prefix + "modified_attributes", Column(&Table::ZeroAccessor, objectAccessor));
+       table->AddColumn(prefix + "modified_attributes_list", Column(&Table::ZeroAccessor, objectAccessor));
        table->AddColumn(prefix + "pnpgraph_present", Column(&Table::ZeroAccessor, objectAccessor));
        table->AddColumn(prefix + "staleness", Column(&ServicesTable::StalenessAccessor, objectAccessor));
        table->AddColumn(prefix + "check_interval", Column(&ServicesTable::CheckIntervalAccessor, objectAccessor));
@@ -137,29 +137,30 @@ void ServicesTable::AddColumns(Table *table, const String& prefix,
        table->AddColumn(prefix + "check_source", Column(&ServicesTable::CheckSourceAccessor, objectAccessor));
        table->AddColumn(prefix + "is_reachable", Column(&ServicesTable::IsReachableAccessor, objectAccessor));
        table->AddColumn(prefix + "cv_is_json", Column(&ServicesTable::CVIsJsonAccessor, objectAccessor));
+       table->AddColumn(prefix + "original_attributes", Column(&ServicesTable::OriginalAttributesAccessor, objectAccessor));
 
-       HostsTable::AddColumns(table, "host_", boost::bind(&ServicesTable::HostAccessor, _1, objectAccessor));
+       HostsTable::AddColumns(table, "host_", std::bind(&ServicesTable::HostAccessor, _1, objectAccessor));
 
        /* add additional group by values received through the object accessor */
        if (table->GetGroupByType() == LivestatusGroupByServiceGroup) {
                /* _1 = row, _2 = groupByType, _3 = groupByObject */
                Log(LogDebug, "Livestatus")
-                   << "Processing services group by servicegroup table.";
-               ServiceGroupsTable::AddColumns(table, "servicegroup_", boost::bind(&ServicesTable::ServiceGroupAccessor, _1, _2, _3));
+                       << "Processing services group by servicegroup table.";
+               ServiceGroupsTable::AddColumns(table, "servicegroup_", std::bind(&ServicesTable::ServiceGroupAccessor, _1, _2, _3));
        } else if (table->GetGroupByType() == LivestatusGroupByHostGroup) {
                /* _1 = row, _2 = groupByType, _3 = groupByObject */
                Log(LogDebug, "Livestatus")
-                   << "Processing services group by hostgroup table.";
-               HostGroupsTable::AddColumns(table, "hostgroup_", boost::bind(&ServicesTable::HostGroupAccessor, _1, _2, _3));
+                       << "Processing services group by hostgroup table.";
+               HostGroupsTable::AddColumns(table, "hostgroup_", std::bind(&ServicesTable::HostGroupAccessor, _1, _2, _3));
        }
 }
 
-String ServicesTable::GetName(void) const
+String ServicesTable::GetName() const
 {
        return "services";
 }
 
-String ServicesTable::GetPrefix(void) const
+String ServicesTable::GetPrefix() const
 {
        return "service";
 }
@@ -167,26 +168,29 @@ String ServicesTable::GetPrefix(void) const
 void ServicesTable::FetchRows(const AddRowFunction& addRowFn)
 {
        if (GetGroupByType() == LivestatusGroupByServiceGroup) {
-               BOOST_FOREACH(const ServiceGroup::Ptr& sg, DynamicType::GetObjectsByType<ServiceGroup>()) {
-                       BOOST_FOREACH(const Service::Ptr& service, sg->GetMembers()) {
+               for (const ServiceGroup::Ptr& sg : ConfigType::GetObjectsByType<ServiceGroup>()) {
+                       for (const Service::Ptr& service : sg->GetMembers()) {
                                /* the caller must know which groupby type and value are set for this row */
-                               addRowFn(service, LivestatusGroupByServiceGroup, sg);
+                               if (!addRowFn(service, LivestatusGroupByServiceGroup, sg))
+                                       return;
                        }
                }
        } else if (GetGroupByType() == LivestatusGroupByHostGroup) {
-               BOOST_FOREACH(const HostGroup::Ptr& hg, DynamicType::GetObjectsByType<HostGroup>()) {
+               for (const HostGroup::Ptr& hg : ConfigType::GetObjectsByType<HostGroup>()) {
                        ObjectLock ylock(hg);
-                       BOOST_FOREACH(const Host::Ptr& host, hg->GetMembers()) {
+                       for (const Host::Ptr& host : hg->GetMembers()) {
                                ObjectLock ylock(host);
-                               BOOST_FOREACH(const Service::Ptr& service, host->GetServices()) {
+                               for (const Service::Ptr& service : host->GetServices()) {
                                        /* the caller must know which groupby type and value are set for this row */
-                                       addRowFn(service, LivestatusGroupByHostGroup, hg);
+                                       if (!addRowFn(service, LivestatusGroupByHostGroup, hg))
+                                               return;
                                }
                        }
                }
        } else {
-               BOOST_FOREACH(const Service::Ptr& service, DynamicType::GetObjectsByType<Service>()) {
-                       addRowFn(service, LivestatusGroupByNone, Empty);
+               for (const Service::Ptr& service : ConfigType::GetObjectsByType<Service>()) {
+                       if (!addRowFn(service, LivestatusGroupByNone, Empty))
+                               return;
                }
        }
 }
@@ -203,7 +207,7 @@ Object::Ptr ServicesTable::HostAccessor(const Value& row, const Column::ObjectAc
        Service::Ptr svc = static_cast<Service::Ptr>(service);
 
        if (!svc)
-               return Object::Ptr();
+               return nullptr;
 
        return svc->GetHost();
 }
@@ -217,7 +221,7 @@ Object::Ptr ServicesTable::ServiceGroupAccessor(const Value& row, LivestatusGrou
        if (groupByType == LivestatusGroupByServiceGroup)
                return groupByObject;
 
-       return Object::Ptr();
+       return nullptr;
 }
 
 Object::Ptr ServicesTable::HostGroupAccessor(const Value& row, LivestatusGroupByType groupByType, const Object::Ptr& groupByObject)
@@ -229,7 +233,7 @@ Object::Ptr ServicesTable::HostGroupAccessor(const Value& row, LivestatusGroupBy
        if (groupByType == LivestatusGroupByHostGroup)
                return groupByObject;
 
-       return Object::Ptr();
+       return nullptr;
 }
 
 Value ServicesTable::ShortNameAccessor(const Value& row)
@@ -339,20 +343,10 @@ Value ServicesTable::PerfDataAccessor(const Value& row)
        String perfdata;
        CheckResult::Ptr cr = service->GetLastCheckResult();
 
-       if (cr)
-               perfdata = CompatUtility::GetCheckResultPerfdata(cr);
-
-       return perfdata;
-}
-
-Value ServicesTable::NotificationPeriodAccessor(const Value& row)
-{
-       Service::Ptr service = static_cast<Service::Ptr>(row);
-
-       if (!service)
+       if (!cr)
                return Empty;
 
-       return CompatUtility::GetCheckableNotificationNotificationPeriod(service);
+       return PluginUtility::FormatPerfdata(cr->GetPerformanceData());
 }
 
 Value ServicesTable::CheckPeriodAccessor(const Value& row)
@@ -382,10 +376,11 @@ Value ServicesTable::NotesExpandedAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       MacroProcessor::ResolverList resolvers;
-       resolvers.push_back(std::make_pair("service", service));
-       resolvers.push_back(std::make_pair("host", service->GetHost()));
-       resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
+       MacroProcessor::ResolverList resolvers {
+               { "service", service },
+               { "host", service->GetHost() },
+               { "icinga", IcingaApplication::GetInstance() }
+       };
 
        return MacroProcessor::ResolveMacros(service->GetNotes(), resolvers);
 }
@@ -407,10 +402,11 @@ Value ServicesTable::NotesUrlExpandedAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       MacroProcessor::ResolverList resolvers;
-       resolvers.push_back(std::make_pair("service", service));
-       resolvers.push_back(std::make_pair("host", service->GetHost()));
-       resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
+       MacroProcessor::ResolverList resolvers {
+               { "service", service },
+               { "host", service->GetHost() },
+               { "icinga", IcingaApplication::GetInstance() }
+       };
 
        return MacroProcessor::ResolveMacros(service->GetNotesUrl(), resolvers);
 }
@@ -432,10 +428,11 @@ Value ServicesTable::ActionUrlExpandedAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       MacroProcessor::ResolverList resolvers;
-       resolvers.push_back(std::make_pair("service", service));
-       resolvers.push_back(std::make_pair("host", service->GetHost()));
-       resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
+       MacroProcessor::ResolverList resolvers {
+               { "service", service },
+               { "host", service->GetHost() },
+               { "icinga", IcingaApplication::GetInstance() }
+       };
 
        return MacroProcessor::ResolveMacros(service->GetActionUrl(), resolvers);
 }
@@ -457,10 +454,11 @@ Value ServicesTable::IconImageExpandedAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       MacroProcessor::ResolverList resolvers;
-       resolvers.push_back(std::make_pair("service", service));
-       resolvers.push_back(std::make_pair("host", service->GetHost()));
-       resolvers.push_back(std::make_pair("icinga", IcingaApplication::GetInstance()));
+       MacroProcessor::ResolverList resolvers {
+               { "service", service },
+               { "host", service->GetHost() },
+               { "icinga", IcingaApplication::GetInstance() }
+       };
 
        return MacroProcessor::ResolveMacros(service->GetIconImage(), resolvers);
 }
@@ -512,7 +510,7 @@ Value ServicesTable::HasBeenCheckedAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableHasBeenChecked(service);
+       return Convert::ToLong(service->HasBeenChecked());
 }
 
 Value ServicesTable::LastStateAccessor(const Value& row)
@@ -552,7 +550,7 @@ Value ServicesTable::CheckTypeAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableCheckType(service);
+       return (service->GetEnableActiveChecks() ? 0 : 1); /* 0 .. active, 1 .. passive */
 }
 
 Value ServicesTable::AcknowledgedAccessor(const Value& row)
@@ -563,7 +561,7 @@ Value ServicesTable::AcknowledgedAccessor(const Value& row)
                return Empty;
 
        ObjectLock olock(service);
-       return CompatUtility::GetCheckableIsAcknowledged(service);
+       return service->IsAcknowledged();
 }
 
 Value ServicesTable::AcknowledgementTypeAccessor(const Value& row)
@@ -574,7 +572,7 @@ Value ServicesTable::AcknowledgementTypeAccessor(const Value& row)
                return Empty;
 
        ObjectLock olock(service);
-       return CompatUtility::GetCheckableAcknowledgementType(service);
+       return service->GetAcknowledgement();
 }
 
 Value ServicesTable::NoMoreNotificationsAccessor(const Value& row)
@@ -724,7 +722,7 @@ Value ServicesTable::ChecksEnabledAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableActiveChecksEnabled(service);
+       return Convert::ToLong(service->GetEnableActiveChecks());
 }
 
 Value ServicesTable::AcceptPassiveChecksAccessor(const Value& row)
@@ -734,7 +732,7 @@ Value ServicesTable::AcceptPassiveChecksAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckablePassiveChecksEnabled(service);
+       return Convert::ToLong(service->GetEnablePassiveChecks());
 }
 
 Value ServicesTable::EventHandlerEnabledAccessor(const Value& row)
@@ -744,7 +742,7 @@ Value ServicesTable::EventHandlerEnabledAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableEventHandlerEnabled(service);
+       return Convert::ToLong(service->GetEnableEventHandler());
 }
 
 Value ServicesTable::NotificationsEnabledAccessor(const Value& row)
@@ -754,7 +752,7 @@ Value ServicesTable::NotificationsEnabledAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableNotificationsEnabled(service);
+       return Convert::ToLong(service->GetEnableNotifications());
 }
 
 Value ServicesTable::ProcessPerformanceDataAccessor(const Value& row)
@@ -764,7 +762,7 @@ Value ServicesTable::ProcessPerformanceDataAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableProcessPerformanceData(service);
+       return Convert::ToLong(service->GetEnablePerfdata());
 }
 
 Value ServicesTable::ActiveChecksEnabledAccessor(const Value& row)
@@ -774,13 +772,7 @@ Value ServicesTable::ActiveChecksEnabledAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableActiveChecksEnabled(service);
-}
-
-Value ServicesTable::CheckOptionsAccessor(const Value& row)
-{
-       /* TODO - forcexec, freshness, orphan, none */
-       return Empty;
+       return Convert::ToLong(service->GetEnableActiveChecks());
 }
 
 Value ServicesTable::FlapDetectionEnabledAccessor(const Value& row)
@@ -790,37 +782,7 @@ Value ServicesTable::FlapDetectionEnabledAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableFlapDetectionEnabled(service);
-}
-
-Value ServicesTable::CheckFreshnessAccessor(const Value& row)
-{
-       Service::Ptr service = static_cast<Service::Ptr>(row);
-
-       if (!service)
-               return Empty;
-
-       return CompatUtility::GetCheckableFreshnessChecksEnabled(service);
-}
-
-Value ServicesTable::ModifiedAttributesAccessor(const Value& row)
-{
-       Service::Ptr service = static_cast<Service::Ptr>(row);
-
-       if (!service)
-               return Empty;
-
-       return service->GetModifiedAttributes();
-}
-
-Value ServicesTable::ModifiedAttributesListAccessor(const Value& row)
-{
-       Service::Ptr service = static_cast<Service::Ptr>(row);
-
-       if (!service)
-               return Empty;
-
-       return CompatUtility::GetModifiedAttributesList(service);
+       return Convert::ToLong(service->GetEnableFlapping());
 }
 
 Value ServicesTable::StalenessAccessor(const Value& row)
@@ -830,7 +792,10 @@ Value ServicesTable::StalenessAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableStaleness(service);
+       if (service->HasBeenChecked() && service->GetLastCheck() > 0)
+               return (Utility::GetTime() - service->GetLastCheck()) / (service->GetCheckInterval() * 3600);
+
+       return 0.0;
 }
 
 Value ServicesTable::CheckIntervalAccessor(const Value& row)
@@ -870,7 +835,7 @@ Value ServicesTable::LowFlapThresholdAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableLowFlapThreshold(service);
+       return service->GetFlappingThresholdLow();
 }
 
 Value ServicesTable::HighFlapThresholdAccessor(const Value& row)
@@ -880,7 +845,7 @@ Value ServicesTable::HighFlapThresholdAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableHighFlapThreshold(service);
+       return service->GetFlappingThresholdHigh();
 }
 
 Value ServicesTable::LatencyAccessor(const Value& row)
@@ -890,7 +855,12 @@ Value ServicesTable::LatencyAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return (Service::CalculateLatency(service->GetLastCheckResult()));
+       CheckResult::Ptr cr = service->GetLastCheckResult();
+
+       if (!cr)
+               return Empty;
+
+       return cr->CalculateLatency();
 }
 
 Value ServicesTable::ExecutionTimeAccessor(const Value& row)
@@ -900,7 +870,12 @@ Value ServicesTable::ExecutionTimeAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return (Service::CalculateExecutionTime(service->GetLastCheckResult()));
+       CheckResult::Ptr cr = service->GetLastCheckResult();
+
+       if (!cr)
+               return Empty;
+
+       return cr->CalculateExecutionTime();
 }
 
 Value ServicesTable::PercentStateChangeAccessor(const Value& row)
@@ -910,7 +885,7 @@ Value ServicesTable::PercentStateChangeAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckablePercentStateChange(service);
+       return service->GetFlappingCurrent();
 }
 
 Value ServicesTable::InCheckPeriodAccessor(const Value& row)
@@ -920,7 +895,13 @@ Value ServicesTable::InCheckPeriodAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       return CompatUtility::GetCheckableInCheckPeriod(service);
+       TimePeriod::Ptr timeperiod = service->GetCheckPeriod();
+
+       /* none set means always checked */
+       if (!timeperiod)
+               return 1;
+
+       return Convert::ToLong(timeperiod->IsInside(Utility::GetTime()));
 }
 
 Value ServicesTable::InNotificationPeriodAccessor(const Value& row)
@@ -942,7 +923,7 @@ Value ServicesTable::ContactsAccessor(const Value& row)
 
        Array::Ptr contact_names = new Array();
 
-       BOOST_FOREACH(const User::Ptr& user, CompatUtility::GetCheckableNotificationUsers(service)) {
+       for (const User::Ptr& user : CompatUtility::GetCheckableNotificationUsers(service)) {
                contact_names->Add(user->GetName());
        }
 
@@ -956,26 +937,16 @@ Value ServicesTable::DowntimesAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       Dictionary::Ptr downtimes = service->GetDowntimes();
-
-       Array::Ptr ids = new Array();
-
-       ObjectLock olock(downtimes);
-
-       String id;
-       Downtime::Ptr downtime;
-       BOOST_FOREACH(tie(id, downtime), downtimes) {
-
-               if (!downtime)
-                       continue;
+       Array::Ptr results = new Array();
 
+       for (const Downtime::Ptr& downtime : service->GetDowntimes()) {
                if (downtime->IsExpired())
                        continue;
 
-               ids->Add(downtime->GetLegacyId());
+               results->Add(downtime->GetLegacyId());
        }
 
-       return ids;
+       return results;
 }
 
 Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
@@ -985,19 +956,9 @@ Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       Dictionary::Ptr downtimes = service->GetDowntimes();
-
-       Array::Ptr ids = new Array();
-
-       ObjectLock olock(downtimes);
-
-       String id;
-       Downtime::Ptr downtime;
-       BOOST_FOREACH(tie(id, downtime), downtimes) {
-
-               if (!downtime)
-                       continue;
+       Array::Ptr results = new Array();
 
+       for (const Downtime::Ptr& downtime : service->GetDowntimes()) {
                if (downtime->IsExpired())
                        continue;
 
@@ -1005,10 +966,10 @@ Value ServicesTable::DowntimesWithInfoAccessor(const Value& row)
                downtime_info->Add(downtime->GetLegacyId());
                downtime_info->Add(downtime->GetAuthor());
                downtime_info->Add(downtime->GetComment());
-               ids->Add(downtime_info);
+               results->Add(downtime_info);
        }
 
-       return ids;
+       return results;
 }
 
 Value ServicesTable::CommentsAccessor(const Value& row)
@@ -1018,26 +979,16 @@ Value ServicesTable::CommentsAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       Dictionary::Ptr comments = service->GetComments();
-
-       Array::Ptr ids = new Array();
-
-       ObjectLock olock(comments);
-
-       String id;
-       Comment::Ptr comment;
-       BOOST_FOREACH(tie(id, comment), comments) {
-
-               if (!comment)
-                       continue;
+       Array::Ptr results = new Array();
 
+       for (const Comment::Ptr& comment : service->GetComments()) {
                if (comment->IsExpired())
                        continue;
 
-               ids->Add(comment->GetLegacyId());
+               results->Add(comment->GetLegacyId());
        }
 
-       return ids;
+       return results;
 }
 
 Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
@@ -1047,19 +998,9 @@ Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       Dictionary::Ptr comments = service->GetComments();
-
-       Array::Ptr ids = new Array();
-
-       ObjectLock olock(comments);
-
-       String id;
-       Comment::Ptr comment;
-       BOOST_FOREACH(tie(id, comment), comments) {
-
-               if (!comment)
-                       continue;
+       Array::Ptr results = new Array();
 
+       for (const Comment::Ptr& comment : service->GetComments()) {
                if (comment->IsExpired())
                        continue;
 
@@ -1067,10 +1008,10 @@ Value ServicesTable::CommentsWithInfoAccessor(const Value& row)
                comment_info->Add(comment->GetLegacyId());
                comment_info->Add(comment->GetAuthor());
                comment_info->Add(comment->GetText());
-               ids->Add(comment_info);
+               results->Add(comment_info);
        }
 
-       return ids;
+       return results;
 }
 
 Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
@@ -1080,19 +1021,9 @@ Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
        if (!service)
                return Empty;
 
-       Dictionary::Ptr comments = service->GetComments();
-
-       Array::Ptr ids = new Array();
-
-       ObjectLock olock(comments);
-
-       String id;
-       Comment::Ptr comment;
-       BOOST_FOREACH(tie(id, comment), comments) {
-
-               if (!comment)
-                       continue;
+       Array::Ptr results = new Array();
 
+       for (const Comment::Ptr& comment : service->GetComments()) {
                if (comment->IsExpired())
                        continue;
 
@@ -1102,10 +1033,10 @@ Value ServicesTable::CommentsWithExtraInfoAccessor(const Value& row)
                comment_info->Add(comment->GetText());
                comment_info->Add(comment->GetEntryType());
                comment_info->Add(static_cast<int>(comment->GetEntryTime()));
-               ids->Add(comment_info);
+               results->Add(comment_info);
        }
 
-       return ids;
+       return results;
 }
 
 Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
@@ -1119,16 +1050,16 @@ Value ServicesTable::CustomVariableNamesAccessor(const Value& row)
 
        {
                ObjectLock olock(service);
-               vars = CompatUtility::GetCustomAttributeConfig(service);
+               vars = service->GetVars();
        }
 
-       if (!vars)
-               return Empty;
-
        Array::Ptr cv = new Array();
 
+       if (!vars)
+               return cv;
+
        ObjectLock olock(vars);
-       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+       for (const Dictionary::Pair& kv : vars) {
                cv->Add(kv.first);
        }
 
@@ -1146,16 +1077,16 @@ Value ServicesTable::CustomVariableValuesAccessor(const Value& row)
 
        {
                ObjectLock olock(service);
-               vars = CompatUtility::GetCustomAttributeConfig(service);
+               vars = service->GetVars();
        }
 
-       if (!vars)
-               return Empty;
-
        Array::Ptr cv = new Array();
 
+       if (!vars)
+               return cv;
+
        ObjectLock olock(vars);
-       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+       for (const Dictionary::Pair& kv : vars) {
                if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
                        cv->Add(JsonEncode(kv.second));
                else
@@ -1176,16 +1107,16 @@ Value ServicesTable::CustomVariablesAccessor(const Value& row)
 
        {
                ObjectLock olock(service);
-               vars = CompatUtility::GetCustomAttributeConfig(service);
+               vars = service->GetVars();
        }
 
-       if (!vars)
-               return Empty;
-
        Array::Ptr cv = new Array();
 
+       if (!vars)
+               return cv;
+
        ObjectLock olock(vars);
-       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+       for (const Dictionary::Pair& kv : vars) {
                Array::Ptr key_val = new Array();
                key_val->Add(kv.first);
 
@@ -1211,7 +1142,7 @@ Value ServicesTable::CVIsJsonAccessor(const Value& row)
 
        {
                ObjectLock olock(service);
-               vars = CompatUtility::GetCustomAttributeConfig(service);
+               vars = service->GetVars();
        }
 
        if (!vars)
@@ -1220,7 +1151,7 @@ Value ServicesTable::CVIsJsonAccessor(const Value& row)
        bool cv_is_json = false;
 
        ObjectLock olock(vars);
-       BOOST_FOREACH(const Dictionary::Pair& kv, vars) {
+       for (const Dictionary::Pair& kv : vars) {
                if (kv.second.IsObjectType<Array>() || kv.second.IsObjectType<Dictionary>())
                        cv_is_json = true;
        }
@@ -1252,7 +1183,7 @@ Value ServicesTable::ContactGroupsAccessor(const Value& row)
 
        Array::Ptr contactgroup_names = new Array();
 
-       BOOST_FOREACH(const UserGroup::Ptr& usergroup, CompatUtility::GetCheckableNotificationUserGroups(service)) {
+       for (const UserGroup::Ptr& usergroup : CompatUtility::GetCheckableNotificationUserGroups(service)) {
                contactgroup_names->Add(usergroup->GetName());
        }
 
@@ -1283,3 +1214,13 @@ Value ServicesTable::IsReachableAccessor(const Value& row)
 
        return service->IsReachable();
 }
+
+Value ServicesTable::OriginalAttributesAccessor(const Value& row)
+{
+       Service::Ptr service = static_cast<Service::Ptr>(row);
+
+       if (!service)
+               return Empty;
+
+       return JsonEncode(service->GetOriginalAttributes());
+}