host.cc 19.5 KB
Newer Older
1
/*
2
** Copyright 2011-2019 Centreon
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
**
** This file is part of Centreon Engine.
**
** Centreon Engine is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Engine is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Engine. If not, see
** <http://www.gnu.org/licenses/>.
*/
19

20
#include "com/centreon/engine/configuration/applier/host.hh"
21

22
#include <algorithm>
23

Dorian Guillois's avatar
Dorian Guillois committed
24
#include "com/centreon/engine/broker.hh"
Dorian Guillois's avatar
Dorian Guillois committed
25
#include "com/centreon/engine/common.hh"
26
#include "com/centreon/engine/config.hh"
27
#include "com/centreon/engine/configuration/applier/scheduler.hh"
Dorian Guillois's avatar
Dorian Guillois committed
28
#include "com/centreon/engine/configuration/applier/state.hh"
29
#include "com/centreon/engine/downtimes/downtime_manager.hh"
David Boucher's avatar
David Boucher committed
30
#include "com/centreon/engine/exceptions/error.hh"
31
32
#include "com/centreon/engine/globals.hh"

33
34
using namespace com::centreon;
using namespace com::centreon::engine;
35
36
37
using namespace com::centreon::engine::configuration;

/**
38
 *  Default constructor.
39
 */
40
applier::host::host() {}
41
42

/**
43
 *  Destructor.
44
 */
45
applier::host::~host() throw() {}
46
47
48
49

/**
 *  Add new host.
 *
50
 *  @param[in] obj  The new host to add into the monitoring engine.
51
 */
52
void applier::host::add_object(configuration::host const& obj) {
Dorian Guillois's avatar
Dorian Guillois committed
53
54
  // Logging.
  logger(logging::dbg_config, logging::more)
55
      << "Creating new host '" << obj.host_name() << "'.";
56
57
58

  // Add host to the global configuration set.
  config->hosts().insert(obj);
59

60
  // Create host.
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
  std::shared_ptr<com::centreon::engine::host> h{new engine::host(
      obj.host_id(), obj.host_name(), obj.display_name(), obj.alias(),
      obj.address(), obj.check_period(),
      static_cast<engine::host::host_state>(obj.initial_state()),
      obj.check_interval(), obj.retry_interval(), obj.max_check_attempts(),
      static_cast<bool>(obj.notification_options() & configuration::host::up),
      static_cast<bool>(obj.notification_options() & configuration::host::down),
      static_cast<bool>(obj.notification_options() &
                        configuration::host::unreachable),
      static_cast<bool>(obj.notification_options() &
                        configuration::host::flapping),
      static_cast<bool>(obj.notification_options() &
                        configuration::host::downtime),
      obj.notification_interval(), obj.first_notification_delay(),
      obj.recovery_notification_delay(), obj.notification_period(),
      obj.notifications_enabled(), obj.check_command(), obj.checks_active(),
      obj.checks_passive(), obj.event_handler(), obj.event_handler_enabled(),
      obj.flap_detection_enabled(), obj.low_flap_threshold(),
      obj.high_flap_threshold(),
      static_cast<bool>(obj.flap_detection_options() & configuration::host::up),
      static_cast<bool>(obj.flap_detection_options() &
                        configuration::host::down),
      static_cast<bool>(obj.flap_detection_options() &
                        configuration::host::unreachable),
      static_cast<bool>(obj.stalking_options() & configuration::host::up),
      static_cast<bool>(obj.stalking_options() & configuration::host::down),
      static_cast<bool>(obj.stalking_options() &
                        configuration::host::unreachable),
      obj.process_perf_data(), obj.check_freshness(), obj.freshness_threshold(),
      obj.notes(), obj.notes_url(), obj.action_url(), obj.icon_image(),
      obj.icon_image_alt(), obj.vrml_image(), obj.statusmap_image(),
      obj.coords_2d().x(), obj.coords_2d().y(), obj.have_coords_2d(),
      obj.coords_3d().x(), obj.coords_3d().y(), obj.coords_3d().z(),
      obj.have_coords_3d(),
      true,  // should_be_drawn, enabled by Nagios
      obj.retain_status_information(), obj.retain_nonstatus_information(),
      obj.obsess_over_host(), obj.timezone())};
98

Sylvestre Gallon's avatar
Sylvestre Gallon committed
99
100
101
  engine::host::hosts.insert({h->get_name(), h});
  engine::host::hosts_by_id.insert({obj.host_id(), h});

David Boucher's avatar
David Boucher committed
102
  h->set_initial_notif_time(0);
Sylvestre Gallon's avatar
Sylvestre Gallon committed
103
104
  h->set_should_reschedule_current_check(false);
  h->set_host_id(obj.host_id());
David Boucher's avatar
David Boucher committed
105
106
107
  h->set_acknowledgement_timeout(obj.get_acknowledgement_timeout() *
                                 config->interval_length());
  h->set_last_acknowledgement(0);
108

David Boucher's avatar
David Boucher committed
109
  // Contacts
110
111
112
  for (set_string::const_iterator it(obj.contacts().begin()),
       end(obj.contacts().end());
       it != end; ++it)
David Boucher's avatar
David Boucher committed
113
    h->get_contacts().insert({*it, nullptr});
114
115

  // Contact groups.
116
117
118
  for (set_string::const_iterator it(obj.contactgroups().begin()),
       end(obj.contactgroups().end());
       it != end; ++it)
David Boucher's avatar
David Boucher committed
119
    h->get_contactgroups().insert({*it, nullptr});
120
121

  // Custom variables.
122
123
124
  for (map_customvar::const_iterator it(obj.customvariables().begin()),
       end(obj.customvariables().end());
       it != end; ++it) {
125
126
127
128
129
130
131
132
133
    h->custom_variables[it->first] = it->second;

    if (it->second.is_sent()) {
      timeval tv(get_broker_timestamp(nullptr));
      broker_custom_variable(NEBTYPE_HOSTCUSTOMVARIABLE_ADD, NEBFLAG_NONE,
                             NEBATTR_NONE, h.get(), it->first.c_str(),
                             it->second.get_value().c_str(), &tv);
    }
  }
134
135

  // Parents.
136
137
138
  for (set_string::const_iterator it(obj.parents().begin()),
       end(obj.parents().end());
       it != end; ++it)
139
    h->add_parent_host(*it);
140

141
  // Notify event broker.
142
  timeval tv(get_broker_timestamp(nullptr));
143
144
  broker_adaptive_host_data(NEBTYPE_HOST_ADD, NEBFLAG_NONE, NEBATTR_NONE,
                            h.get(), CMD_NONE, MODATTR_ALL, MODATTR_ALL, &tv);
145
146
}

147
148
149
150
151
152
153
154
/**
 *  @brief Expand a host.
 *
 *  During expansion, the host will be added to its host groups. These
 *  will be modified in the state.
 *
 *  @param[int,out] s   Configuration state.
 */
155
156
void applier::host::expand_objects(configuration::state& s) {
  // Browse all hosts.
157
158
159
  for (configuration::set_host::iterator it_host(s.hosts().begin()),
       end_host(s.hosts().end());
       it_host != end_host; ++it_host) {
160
    // Should custom variables be sent to broker ?
161
    for (map_customvar::iterator
162
163
164
165
166
             it(const_cast<map_customvar&>(it_host->customvariables()).begin()),
         end(const_cast<map_customvar&>(it_host->customvariables()).end());
         it != end; ++it) {
      if (!s.enable_macros_filter() ||
          s.macros_filter().find(it->first) != s.macros_filter().end()) {
167
        it->second.set_sent(true);
168
169
170
      }
    }

171
    // Browse current host's groups.
172
173
174
    for (set_string::const_iterator it_group(it_host->hostgroups().begin()),
         end_group(it_host->hostgroups().end());
         it_group != end_group; ++it_group) {
175
      // Find host group.
176
177
      configuration::set_hostgroup::iterator group(
          s.hostgroups_find(*it_group));
178
      if (group == s.hostgroups().end())
179
180
181
        throw(engine_error()
              << "Could not add host '" << it_host->host_name()
              << "' to non-existing host group '" << *it_group << "'");
182
183
184
185
186
187

      // Remove host group from state.
      configuration::hostgroup backup(*group);
      s.hostgroups().erase(group);

      // Add host to group members.
188
      backup.members().insert(it_host->host_name());
189
190
191
192

      // Reinsert host group.
      s.hostgroups().insert(backup);
    }
193
  }
194
195
}

196
197
198
/**
 *  Modified host.
 *
199
 *  @param[in] obj  The new host to modify into the monitoring engine.
200
 */
201
void applier::host::modify_object(configuration::host const& obj) {
Dorian Guillois's avatar
Dorian Guillois committed
202
203
  // Logging.
  logger(logging::dbg_config, logging::more)
204
      << "Modifying host '" << obj.host_name() << "'.";
205

206
  // Find the configuration object.
207
  set_host::iterator it_cfg(config->hosts_find(obj.key()));
208
  if (it_cfg == config->hosts().end())
209
    throw engine_error() << "Cannot modify non-existing host '"
210
                         << obj.host_name() << "'";
211

Dorian Guillois's avatar
Dorian Guillois committed
212
  // Find host object.
Sylvestre Gallon's avatar
Sylvestre Gallon committed
213
214
  host_id_map::iterator it_obj(engine::host::hosts_by_id.find(obj.key()));
  if (it_obj == engine::host::hosts_by_id.end())
215
    throw engine_error() << "Could not modify non-existing "
216
                         << "host object '" << obj.host_name() << "'";
Dorian Guillois's avatar
Dorian Guillois committed
217

218
  // Update the global configuration set.
219
  configuration::host obj_old(*it_cfg);
220
  config->hosts().erase(it_cfg);
Dorian Guillois's avatar
Dorian Guillois committed
221
  config->hosts().insert(obj);
222

Dorian Guillois's avatar
Dorian Guillois committed
223
  // Modify properties.
224
  if (it_obj->second->get_name() != obj.host_name()) {
Sylvestre Gallon's avatar
Sylvestre Gallon committed
225
226
227
228
229
230
    engine::host::hosts.erase(it_obj->second->get_name());
    engine::host::hosts.insert({obj.host_name(), it_obj->second});
  }

  it_obj->second->set_name(obj.host_name());
  it_obj->second->set_display_name(obj.display_name());
231
  if (!obj.alias().empty())
Sylvestre Gallon's avatar
Sylvestre Gallon committed
232
    it_obj->second->set_alias(obj.alias());
233
  else
Sylvestre Gallon's avatar
Sylvestre Gallon committed
234
235
    it_obj->second->set_alias(obj.host_name());
  it_obj->second->set_address(obj.address());
236
  if (obj.check_period().empty())
Sylvestre Gallon's avatar
Sylvestre Gallon committed
237
    it_obj->second->set_check_period(obj.check_period());
238
239
  it_obj->second->set_initial_state(
      static_cast<engine::host::host_state>(obj.initial_state()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
240
241
242
  it_obj->second->set_check_interval(static_cast<double>(obj.check_interval()));
  it_obj->second->set_retry_interval(static_cast<double>(obj.retry_interval()));
  it_obj->second->set_max_attempts(static_cast<int>(obj.max_check_attempts()));
David Boucher's avatar
David Boucher committed
243
  it_obj->second->set_notify_on(
244
      (obj.notification_options() & configuration::host::up ? notifier::up
David Boucher's avatar
David Boucher committed
245
246
247
248
249
250
251
252
253
254
255
256
257
258
                                                            : notifier::none) |
      (obj.notification_options() & configuration::host::down
           ? notifier::down
           : notifier::none) |
      (obj.notification_options() & configuration::host::unreachable
           ? notifier::unreachable
           : notifier::none) |
      (obj.notification_options() & configuration::host::flapping
           ? (notifier::flappingstart | notifier::flappingstop |
              notifier::flappingdisabled)
           : notifier::none) |
      (obj.notification_options() & configuration::host::downtime
           ? notifier::downtime
           : notifier::none));
259
260
261
262
  it_obj->second->set_notification_interval(
      static_cast<double>(obj.notification_interval()));
  it_obj->second->set_first_notification_delay(
      static_cast<double>(obj.first_notification_delay()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
263
  it_obj->second->set_notification_period(obj.notification_period());
264
265
  it_obj->second->set_notifications_enabled(
      static_cast<int>(obj.notifications_enabled()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
266
267
  it_obj->second->set_check_command(obj.check_command());
  it_obj->second->set_checks_enabled(static_cast<int>(obj.checks_active()));
268
269
  it_obj->second->set_accept_passive_checks(
      static_cast<int>(obj.checks_passive()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
270
  it_obj->second->set_event_handler(obj.event_handler());
271
272
  it_obj->second->set_event_handler_enabled(
      static_cast<int>(obj.event_handler_enabled()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
273
274
275
  it_obj->second->set_flap_detection_enabled(obj.flap_detection_enabled());
  it_obj->second->set_low_flap_threshold(obj.low_flap_threshold());
  it_obj->second->set_high_flap_threshold(obj.high_flap_threshold());
Sylvestre Gallon's avatar
Sylvestre Gallon committed
276
  it_obj->second->set_flap_detection_on(notifier::none);
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
  it_obj->second->add_flap_detection_on(
      obj.flap_detection_options() & configuration::host::up ? notifier::up
                                                             : notifier::none);
  it_obj->second->add_flap_detection_on(obj.flap_detection_options() &
                                                configuration::host::down
                                            ? notifier::down
                                            : notifier::none);
  it_obj->second->add_flap_detection_on(obj.flap_detection_options() &
                                                configuration::host::unreachable
                                            ? notifier::unreachable
                                            : notifier::none);
  it_obj->second->add_stalk_on(obj.stalking_options() & configuration::host::up
                                   ? notifier::up
                                   : notifier::none);
  it_obj->second->add_stalk_on(
      obj.stalking_options() & configuration::host::down ? notifier::down
                                                         : notifier::none);
  it_obj->second->add_stalk_on(obj.stalking_options() &
                                       configuration::host::unreachable
                                   ? notifier::unreachable
                                   : notifier::none);
  it_obj->second->set_process_performance_data(
      static_cast<int>(obj.process_perf_data()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
300
  it_obj->second->set_check_freshness(static_cast<int>(obj.check_freshness()));
301
302
  it_obj->second->set_freshness_threshold(
      static_cast<int>(obj.freshness_threshold()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
303
304
305
306
307
308
309
310
311
312
313
314
315
316
  it_obj->second->set_notes(obj.notes());
  it_obj->second->set_notes_url(obj.notes_url());
  it_obj->second->set_action_url(obj.action_url());
  it_obj->second->set_icon_image(obj.icon_image());
  it_obj->second->set_icon_image_alt(obj.icon_image_alt());
  it_obj->second->set_vrml_image(obj.vrml_image());
  it_obj->second->set_statusmap_image(obj.statusmap_image());
  it_obj->second->set_x_2d(obj.coords_2d().x());
  it_obj->second->set_y_2d(obj.coords_2d().y());
  it_obj->second->set_have_2d_coords(static_cast<int>(obj.have_coords_2d()));
  it_obj->second->set_x_3d(obj.coords_3d().x());
  it_obj->second->set_y_3d(obj.coords_3d().y());
  it_obj->second->set_z_3d(obj.coords_3d().z());
  it_obj->second->set_have_3d_coords(static_cast<int>(obj.have_coords_3d()));
317
318
319
320
  it_obj->second->set_retain_status_information(
      static_cast<int>(obj.retain_status_information()));
  it_obj->second->set_retain_nonstatus_information(
      static_cast<int>(obj.retain_nonstatus_information()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
321
322
323
  it_obj->second->set_obsess_over(obj.obsess_over_host());
  it_obj->second->set_timezone(obj.timezone());
  it_obj->second->set_host_id(obj.host_id());
324
325
326
327
  it_obj->second->set_acknowledgement_timeout(
      obj.get_acknowledgement_timeout() * config->interval_length());
  it_obj->second->set_recovery_notification_delay(
      obj.recovery_notification_delay());
328

329
  // Contacts.
330
  if (obj.contacts() != obj_old.contacts()) {
331
    // Delete old contacts.
David Boucher's avatar
David Boucher committed
332
    it_obj->second->get_contacts().clear();
333
334

    // Add contacts to host.
335
336
337
    for (set_string::const_iterator it(obj.contacts().begin()),
         end(obj.contacts().end());
         it != end; ++it)
David Boucher's avatar
David Boucher committed
338
      it_obj->second->get_contacts().insert({*it, nullptr});
339
340
341
  }

  // Contact groups.
342
  if (obj.contactgroups() != obj_old.contactgroups()) {
343
    // Delete old contact groups.
David Boucher's avatar
David Boucher committed
344
    it_obj->second->get_contactgroups().clear();
345
346

    // Add contact groups to host.
347
348
349
    for (set_string::const_iterator it(obj.contactgroups().begin()),
         end(obj.contactgroups().end());
         it != end; ++it)
David Boucher's avatar
David Boucher committed
350
      it_obj->second->get_contactgroups().insert({*it, nullptr});
351
352
353
  }

  // Custom variables.
354
355
356
357
358
359
360
361
362
363
  if (obj.customvariables() != obj_old.customvariables()) {
    for (auto& c : it_obj->second->custom_variables) {
      if (c.second.is_sent()) {
        timeval tv(get_broker_timestamp(nullptr));
        broker_custom_variable(NEBTYPE_HOSTCUSTOMVARIABLE_DELETE, NEBFLAG_NONE,
                               NEBATTR_NONE, it_obj->second.get(),
                               c.first.c_str(), c.second.get_value().c_str(),
                               &tv);
      }
    }
364
    it_obj->second->custom_variables.clear();
365

366
    for (auto& c : obj.customvariables()) {
367
368
369
370
371
372
373
374
375
376
377
      it_obj->second->custom_variables[c.first] = c.second;

      if (c.second.is_sent()) {
        timeval tv(get_broker_timestamp(nullptr));
        broker_custom_variable(NEBTYPE_HOSTCUSTOMVARIABLE_ADD, NEBFLAG_NONE,
                               NEBATTR_NONE, it_obj->second.get(),
                               c.first.c_str(), c.second.get_value().c_str(),
                               &tv);
      }
    }
  }
378
379

  // Parents.
380
  if (obj.parents() != obj_old.parents()) {
381
    // Delete old parents.
382
    {
383
      timeval tv(get_broker_timestamp(nullptr));
384
385
386
387
388
389
      for (host_map_unsafe::iterator it(it_obj->second->parent_hosts.begin()),
           end(it_obj->second->parent_hosts.end());
           it != end; it++)
        broker_relation_data(NEBTYPE_PARENT_DELETE, NEBFLAG_NONE, NEBATTR_NONE,
                             it->second, nullptr, it_obj->second.get(), nullptr,
                             &tv);
390
    }
Sylvestre Gallon's avatar
Sylvestre Gallon committed
391
    it_obj->second->parent_hosts.clear();
392
393

    // Create parents.
394
395
396
    for (set_string::const_iterator it(obj.parents().begin()),
         end(obj.parents().end());
         it != end; ++it)
Sylvestre Gallon's avatar
Sylvestre Gallon committed
397
      it_obj->second->add_parent_host(*it);
398
399
  }

400
  // Notify event broker.
401
  timeval tv(get_broker_timestamp(nullptr));
402
403
404
  broker_adaptive_host_data(NEBTYPE_HOST_UPDATE, NEBFLAG_NONE, NEBATTR_NONE,
                            it_obj->second.get(), CMD_NONE, MODATTR_ALL,
                            MODATTR_ALL, &tv);
405
406
407
408
409
410
411
}

/**
 *  Remove old host.
 *
 *  @param[in] obj The new host to remove from the monitoring engine.
 */
412
void applier::host::remove_object(configuration::host const& obj) {
Dorian Guillois's avatar
Dorian Guillois committed
413
414
  // Logging.
  logger(logging::dbg_config, logging::more)
415
      << "Removing host '" << obj.host_name() << "'.";
Dorian Guillois's avatar
Dorian Guillois committed
416

417
  // Find host.
Sylvestre Gallon's avatar
Sylvestre Gallon committed
418
419
  host_id_map::iterator it(engine::host::hosts_by_id.find(obj.key()));
  if (it != engine::host::hosts_by_id.end()) {
420
    // Remove host comments.
David Boucher's avatar
David Boucher committed
421
    comment::delete_host_comments(obj.host_id());
422
423

    // Remove host downtimes.
424
425
426
    downtimes::downtime_manager::instance()
        .delete_downtime_by_hostname_service_description_start_time_comment(
            obj.host_name(), "", (time_t)0, "");
427

428
    // Remove events related to this host.
David Boucher's avatar
David Boucher committed
429
    applier::scheduler::instance().remove_host(obj.key());
430

431
432
    // remove host from hostgroup->members
    for (auto& it_h : it->second->get_parent_groups())
David Boucher's avatar
David Boucher committed
433
434
      it_h->members.erase(it->second->get_name());

Dorian Guillois's avatar
Dorian Guillois committed
435
    // Notify event broker.
436
    timeval tv(get_broker_timestamp(nullptr));
437
438
439
440
441
442
443

    for (auto it_s = it->second->services.begin();
         it_s != it->second->services.end(); ++it_s)
      broker_adaptive_service_data(NEBTYPE_SERVICE_DELETE, NEBFLAG_NONE,
                                   NEBATTR_NONE, it_s->second, CMD_NONE,
                                   MODATTR_ALL, MODATTR_ALL, &tv);

444
445
446
    broker_adaptive_host_data(NEBTYPE_HOST_DELETE, NEBFLAG_NONE, NEBATTR_NONE,
                              it->second.get(), CMD_NONE, MODATTR_ALL,
                              MODATTR_ALL, &tv);
447
448

    // Erase host object (will effectively delete the object).
449
    engine::host::hosts.erase(it->second->get_name());
Sylvestre Gallon's avatar
Sylvestre Gallon committed
450
    engine::host::hosts_by_id.erase(it);
451
  }
452
453
454

  // Remove host from the global configuration set.
  config->hosts().erase(obj);
455
456
457
458
459
}

/**
 *  Resolve a host.
 *
460
 *  @param[in] obj  Host object.
461
 */
462
void applier::host::resolve_object(configuration::host const& obj) {
463
464
  // Logging.
  logger(logging::dbg_config, logging::more)
465
      << "Resolving host '" << obj.host_name() << "'.";
466

467
468
469
470
471
  // If it is the very first host to be resolved,
  // remove all the child backlinks of all the hosts.
  // It is necessary to do it only once to prevent the removal
  // of valid child backlinks.
  if (obj == *config->hosts().begin()) {
472
473
474
    for (host_map::iterator it(engine::host::hosts.begin()),
         end(engine::host::hosts.end());
         it != end; ++it)
475
      it->second->child_hosts.clear();
476
477
  }

478
  // Find host.
479
  host_id_map::iterator it(engine::host::hosts_by_id.find(obj.key()));
Sylvestre Gallon's avatar
Sylvestre Gallon committed
480
  if (engine::host::hosts_by_id.end() == it)
481
482
    throw(engine_error() << "Cannot resolve non-existing host '"
                         << obj.host_name() << "'");
483

484
  // Remove service backlinks.
David Boucher's avatar
David Boucher committed
485
  it->second->services.clear();
486
487

  // Remove host group links.
David Boucher's avatar
David Boucher committed
488
  it->second->get_parent_groups().clear();
489
490

  // Reset host counters.
491
492
  it->second->set_total_services(0);
  it->second->set_total_service_check_interval(0);
493

494
  // Resolve host.
David Boucher's avatar
David Boucher committed
495
  it->second->resolve(config_warnings, config_errors);
496
}