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