Fix timeperiod handling

Unfortunately, a lot of the more complex timeperiod tests were
downright wrong, leading us to use buggy code in the timeperiod
handling.

This patch fixes them. Future commits will fix the broken tests
in a series of patches reworking them completely.

Manually going through the ~400 relevant testcases was *not* fun,
so please be really careful when adding more tests and make sure
the expected output is actually correct.

Signed-off-by: Andreas Ericsson <ae@op5.se>
test-config: Add more timeperiods for testing

Signed-off-by: Andreas Ericsson <ae@op5.se>
test_timeperiods: Revamp and fix timeperiod testing

Earlier timeperiod tests tested only the high level functions
and had very little debug output for when things went wrong.

With this patch, we add some convenient macros that explain what
we got and what we expected.

We also add tests for get_matching_timerange, which is at the
heart of all other timeperiod stuff.

Since a lot of tests failed, I've also gone through all of them
to make sure all tests are actually sane, and the ones that were
previously broken have been fixed so the input actually matches
the expected output.

Since there are a *lot* of tests, I've only updated the broken
ones to use the new macros, since I needed the debug output from
them while fixing them.

Signed-off-by: Andreas Ericsson <ae@op5.se>
Add macro for calculating next check time

The signature is next_check_time(o), where o is either a host or a
service. It yields the next check time (surprise!) by choosing the
correct interval based on the state of the object and the last_check
variable of the object, so those two have to be set.

The interesting part about this is that we can now get scheduling
retention exceptionally cheaply, by simply using the next_check logic
we can (and should; Patch to follow) the whole swamp of fiddling
with checks that are already scheduled but have had their intervals
changed since restart when initially scheduling checks.

Assuming we take into account the fact that checks can be scheduled
to run in the past if they were supposed to run while we were shut
down, we now have an excellent oneline tool to handle scheduling
data retention with zero-exception code.

Signed-off-by: Andreas Ericsson <ae@op5.se>
Stop being so damn stupid when initially scheduling checks

The previous code had a number of problems with it. Not least of
which was the fact that scheduling would take forever if a lot of
checks use a checkperiod that excludes a timeperiod with exceptions
far in the future.

There's also the fact that we had to do special exception handling
for when checks were already scheduled but the check_interval had
changed between restarts.

With this change, we randomize checks into anywhere between now
and now+check_window(obj), which should allow for a pretty decent
distribution.

This fixes the slow-to-start issue reported as issue 82 by
julianbrost on github.

Reported-by: Julian Brost
Signed-off-by: Andreas Ericsson <ae@op5.se>
Use next_check_time(o) when scheduling checks after commands

If one doesn't take the last_check parameter into account, it's
possible to have the checks run way too close together, as could
happen when one disables and then quickly re-enables checks for
a host or a service (as could happen with a misclick, for example).

Since next_check_time() already takes the last_check into account,
this is a prime spot for us to use it.

It's ok if the check gets scheduled at a time where we can't run
it, as we'll just push it forward when we encounter it if that
happens.

Signed-off-by: Andreas Ericsson <ae@op5.se>
Use next_check_time() when rescheduling checks

We used to do the equivalent of next_check_time() in case we
failed to find a suitable time for the check to run, so this
was always the fallback. Since the only downside of using it
as the primary scheduling mechanism is that "next_check" will
sometimes point to a time where the check won't actually be
run, but rather when we'll inspect it again (and that already
happened for checks where we couldn't determine a good next
time to run the check), we gladly take that tradeoff for the
accuracy in checking this provides.

This also means that checks scheduled to run, say, between
08:00-17:00 every weekday won't all be scheduled to run at
08:00 exactly, and we'll keep the checkspread. With a 5 min
interval, a check that last ran at 16:57 will end up running
at 08:02 instead of 08:00, which makes for smoother load on
the monitoring system.

It also lets us avoid the buggy get_next_valid_time() and
its counterpart get_next_invalid_time(), which have some
buggy tests that hide their sometimes inaccurate behaviour.

Signed-off-by: Andreas Ericsson <ae@op5.se>
Avoid updating our checked-in retention data file when testing

This unfortunately removes one test from the commands, but since
it only tests if Naemon receives the commands and not how well
it actually saves the state information, it's quite a useless
test anyway.

This removes the constant annoyance of not being able to run
"git bisect run", since the tests no longer modify checked in
files.

Signed-off-by: Andreas Ericsson <ae@op5.se>
.gitignore naemon.log

Tests create it but we don't want it.

Signed-off-by: Andreas Ericsson <ae@op5.se>