1 // +------------------------------------------------------------------+
2 // | ____ _ _ __ __ _ __ |
3 // | / ___| |__ ___ ___| | __ | \/ | |/ / |
4 // | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
5 // | | |___| | | | __/ (__| < | | | | . \ |
6 // | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
7 // | |
8 // | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
9 // +------------------------------------------------------------------+
10 //
11 // This file is part of Check_MK.
12 // The official homepage is at http://mathias-kettner.de/check_mk.
13 //
14 // check_mk is free software; you can redistribute it and/or modify it
15 // under the terms of the GNU General Public License as published by
16 // the Free Software Foundation in version 2. check_mk is distributed
17 // in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
18 // out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 // PARTICULAR PURPOSE. See the GNU General Public License for more de-
20 // ails. You should have received a copy of the GNU General Public
21 // License along with GNU Make; see the file COPYING. If not, write
22 // to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 // Boston, MA 02110-1301 USA.
24
25 #include "TableDownComm.h"
26 #include "DowntimeOrComment.h"
27 #include "OffsetIntColumn.h"
28 #include "OffsetStringColumn.h"
29 #include "OffsetTimeColumn.h"
30 #include "Query.h"
31 #include "TableHosts.h"
32 #include "TableServices.h"
33 #include "auth.h"
34 #include "logger.h"
35
36 using std::make_pair;
37
38 // Todo: the dynamic data in this table must be
39 // locked with a mutex
40
TableDownComm(bool is_downtime)41 TableDownComm::TableDownComm(bool is_downtime) {
42 if (is_downtime) {
43 _name = "downtimes";
44 } else {
45 _name = "comments";
46 }
47 DowntimeOrComment *ref = nullptr;
48 addColumn(new OffsetStringColumn(
49 "author", is_downtime ? "The contact that scheduled the downtime"
50 : "The contact that entered the comment",
51 reinterpret_cast<char *>(&(ref->_author_name)) -
52 reinterpret_cast<char *>(ref)));
53 addColumn(
54 new OffsetStringColumn("comment", "A comment text",
55 reinterpret_cast<char *>(&(ref->_comment)) -
56 reinterpret_cast<char *>(ref)));
57 addColumn(new OffsetIntColumn(
58 "id", is_downtime ? "The id of the downtime" : "The id of the comment",
59 reinterpret_cast<char *>(&(ref->_id)) - reinterpret_cast<char *>(ref)));
60 addColumn(new OffsetTimeColumn(
61 "entry_time", "The time the entry was made as UNIX timestamp",
62 reinterpret_cast<char *>(&(ref->_entry_time)) -
63 reinterpret_cast<char *>(ref)));
64 addColumn(new OffsetIntColumn(
65 "type",
66 is_downtime
67 ? "The type of the downtime: 0 if it is active, 1 if it is pending"
68 : "The type of the comment: 1 is host, 2 is service",
69 reinterpret_cast<char *>(&(ref->_type)) -
70 reinterpret_cast<char *>(ref)));
71 addColumn(new OffsetIntColumn(
72 "is_service",
73 "0, if this entry is for a host, 1 if it is for a service",
74 reinterpret_cast<char *>(&(ref->_is_service)) -
75 reinterpret_cast<char *>(ref)));
76
77 if (is_downtime) {
78 Downtime *ref = nullptr;
79 addColumn(new OffsetTimeColumn(
80 "start_time", "The start time of the downtime as UNIX timestamp",
81 reinterpret_cast<char *>(&(ref->_start_time)) -
82 reinterpret_cast<char *>(ref)));
83 addColumn(new OffsetTimeColumn(
84 "end_time", "The end time of the downtime as UNIX timestamp",
85 reinterpret_cast<char *>(&(ref->_end_time)) -
86 reinterpret_cast<char *>(ref)));
87 addColumn(new OffsetIntColumn(
88 "fixed", "A 1 if the downtime is fixed, a 0 if it is flexible",
89 reinterpret_cast<char *>(&(ref->_fixed)) -
90 reinterpret_cast<char *>(ref)));
91 addColumn(new OffsetIntColumn(
92 "duration", "The duration of the downtime in seconds",
93 reinterpret_cast<char *>(&(ref->_duration)) -
94 reinterpret_cast<char *>(ref)));
95 addColumn(new OffsetIntColumn(
96 "triggered_by",
97 "The id of the downtime this downtime was triggered by or 0 if it "
98 "was not triggered by another downtime",
99 reinterpret_cast<char *>(&(ref->_triggered_by)) -
100 reinterpret_cast<char *>(ref)));
101 } else {
102 Comment *ref = nullptr;
103 addColumn(new OffsetIntColumn(
104 "persistent", "Whether this comment is persistent (0/1)",
105 reinterpret_cast<char *>(&(ref->_persistent)) -
106 reinterpret_cast<char *>(ref)));
107 addColumn(new OffsetIntColumn(
108 "source",
109 "The source of the comment (0 is internal and 1 is external)",
110 reinterpret_cast<char *>(&(ref->_source)) -
111 reinterpret_cast<char *>(ref)));
112 addColumn(
113 new OffsetIntColumn("entry_type",
114 "The type of the comment: 1 is user, 2 is "
115 "downtime, 3 is flap and 4 is acknowledgement",
116 reinterpret_cast<char *>(&(ref->_entry_type)) -
117 reinterpret_cast<char *>(ref)));
118 addColumn(
119 new OffsetIntColumn("expires", "Whether this comment expires",
120 reinterpret_cast<char *>(&(ref->_expires)) -
121 reinterpret_cast<char *>(ref)));
122 addColumn(new OffsetTimeColumn(
123 "expire_time",
124 "The time of expiry of this comment as a UNIX timestamp",
125 reinterpret_cast<char *>(&(ref->_expire_time)) -
126 reinterpret_cast<char *>(ref)));
127 }
128
129 TableHosts::addColumns(this, "host_",
130 reinterpret_cast<char *>(&(ref->_host)) -
131 reinterpret_cast<char *>(ref));
132 TableServices::addColumns(this, "service_",
133 reinterpret_cast<char *>(&(ref->_service)) -
134 reinterpret_cast<char *>(ref),
135 false /* no hosts table */);
136 }
137
~TableDownComm()138 TableDownComm::~TableDownComm() {
139 for (auto &entry : _entries) {
140 delete entry.second;
141 }
142 }
143
addComment(nebstruct_comment_data * data)144 void TableDownComm::addComment(nebstruct_comment_data *data) {
145 if (data->type == NEBTYPE_COMMENT_ADD ||
146 data->type == NEBTYPE_COMMENT_LOAD) {
147 add(new Comment(data));
148 } else if (data->type == NEBTYPE_COMMENT_DELETE) {
149 Comment comment(data);
150 remove(&comment);
151 }
152 }
153
addDowntime(nebstruct_downtime_data * data)154 void TableDownComm::addDowntime(nebstruct_downtime_data *data) {
155 if (data->type == NEBTYPE_DOWNTIME_ADD ||
156 data->type == NEBTYPE_DOWNTIME_LOAD) {
157 add(new Downtime(data));
158 } else if (data->type == NEBTYPE_DOWNTIME_DELETE) {
159 Downtime downtime(data);
160 remove(&downtime);
161 }
162 }
163
add(DowntimeOrComment * data)164 void TableDownComm::add(DowntimeOrComment *data) {
165 dc_key tmp_key = make_pair(data->_id, data->_service != nullptr);
166 auto it = _entries.find(tmp_key);
167
168 // might be update -> delete previous data set
169 if (it != _entries.end()) {
170 delete it->second;
171 _entries.erase(it);
172 }
173 _entries.insert(make_pair(tmp_key, data));
174 }
175
remove(DowntimeOrComment * data)176 void TableDownComm::remove(DowntimeOrComment *data) {
177 dc_key tmp_key = make_pair(data->_id, data->_service != nullptr);
178 auto it = _entries.find(tmp_key);
179 if (it == _entries.end()) {
180 logger(LG_INFO, "Cannot delete non-existing downtime/comment %lu",
181 data->_id);
182 } else {
183 delete it->second;
184 _entries.erase(it);
185 }
186 }
187
answerQuery(Query * query)188 void TableDownComm::answerQuery(Query *query) {
189 for (const auto &entry : _entries) {
190 if (!query->processDataset(entry.second)) {
191 break;
192 }
193 }
194 }
195
isAuthorized(contact * ctc,void * data)196 bool TableDownComm::isAuthorized(contact *ctc, void *data) {
197 DowntimeOrComment *dtc = static_cast<DowntimeOrComment *>(data);
198 return is_authorized_for(ctc, dtc->_host, dtc->_service) != 0;
199 }
200
findEntry(unsigned long id,bool is_service)201 DowntimeOrComment *TableDownComm::findEntry(unsigned long id, bool is_service) {
202 dc_key tmp_key = make_pair(id, is_service);
203 auto it = _entries.find(tmp_key);
204 if (it != _entries.end()) {
205 return it->second;
206 }
207 return nullptr;
208 }
209