#!/usr/bin/env python
# Copyright (C) 2009-2014:
#    Gabes Jean, naparuba@gmail.com
#    Gerhard Lausser, Gerhard.Lausser@consol.de
#
# This file is part of Shinken.
#
# Shinken is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Shinken 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Shinken.  If not, see <http://www.gnu.org/licenses/>.

#
# This file is used to test host- and service-downtimes.
#

from shinken_test import *

#time.time = original_time_time
#time.sleep = original_time_sleep

class TestDowntime(ShinkenTest):

    def test_schedule_fixed_svc_downtime(self):
        self.print_header()
        # schedule a 2-minute downtime
        # downtime must be active
        # consume a good result, sleep for a minute
        # downtime must be active
        # consume a bad result
        # downtime must be active
        # no notification must be found in broks
        duration = 600
        now = time.time()
        # downtime valid for the next 2 minutes
        cmd = "[%lu] SCHEDULE_SVC_DOWNTIME;test_host_0;test_ok_0;%d;%d;1;0;%d;lausser;blablub" % (now, now, now + duration, duration)
        self.sched.run_external_command(cmd)
        svc = self.sched.services.find_srv_by_name_and_hostname("test_host_0", "test_ok_0")
        svc.checks_in_progress = []
        svc.act_depend_of = []  # no hostchecks on critical checkresults
        time.sleep(20)
        self.scheduler_loop(1, [[svc, 0, 'OK']])

        print "downtime was scheduled. check its activity and the comment"
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
        self.assertIn(svc.downtimes[0], self.sched.downtimes.values())
        self.assertTrue(svc.downtimes[0].fixed)
        self.assertTrue(svc.downtimes[0].is_in_effect)
        self.assertFalse(svc.downtimes[0].can_be_deleted)
        self.assertEqual(1, len(self.sched.comments))
        self.assertEqual(1, len(svc.comments))
        self.assertIn(svc.comments[0], self.sched.comments.values())
        self.assertEqual(svc.comments[0].id, svc.downtimes[0].comment_id)

        self.scheduler_loop(1, [[svc, 0, 'OK']])

        print "good check was launched, downtime must be active"
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
        self.assertIn(svc.downtimes[0], self.sched.downtimes.values())
        self.assertTrue(svc.in_scheduled_downtime)
        self.assertTrue(svc.downtimes[0].fixed)
        self.assertTrue(svc.downtimes[0].is_in_effect)
        self.assertFalse(svc.downtimes[0].can_be_deleted)

        self.scheduler_loop(1, [[svc, 2, 'BAD']])

        print "bad check was launched (SOFT;1), downtime must be active"
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
        self.assertIn(svc.downtimes[0], self.sched.downtimes.values())
        self.assertTrue(svc.in_scheduled_downtime)
        self.assertTrue(svc.downtimes[0].fixed)
        self.assertTrue(svc.downtimes[0].is_in_effect)
        self.assertFalse(svc.downtimes[0].can_be_deleted)

        # now the state changes to hard
        self.scheduler_loop(1, [[svc, 2, 'BAD']])

        print "bad check was launched (HARD;2), downtime must be active"
        print svc.downtimes[0]
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
  
      s
elf.assertIn(svc.downtimes[0], self.sched.downtimes.values())
        self.assertTrue(svc.in_scheduled_downtime)
        self.assertTrue(svc.downtimes[0].fixed)
        self.assertTrue(svc.downtimes[0].is_in_effect)
        self.assertFalse(svc.downtimes[0].can_be_deleted)

        scheduled_downtime_depth = svc.scheduled_downtime_depth
        cmd = "[%lu] DEL_SVC_DOWNTIME;%d" % (now, svc.downtimes[0].id)
        self.sched.run_external_command(cmd)
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
        self.assertFalse(svc.in_scheduled_downtime)
        self.assertLess(svc.scheduled_downtime_depth, scheduled_downtime_depth)
        self.assertTrue(svc.downtimes[0].fixed)
        self.assertFalse(svc.downtimes[0].is_in_effect)
        self.assertTrue(svc.downtimes[0].can_be_deleted)
        self.assertEqual(1, len(self.sched.comments))
        self.assertEqual(1, len(svc.comments))

        # now a notification must be sent
        self.scheduler_loop(1, [[svc, 2, 'BAD']])
        # downtimes must have been deleted now
        self.assertEqual(0, len(self.sched.downtimes))
        self.assertEqual(0, len(svc.downtimes))
        self.assertEqual(0, len(self.sched.comments))
        self.assertEqual(0, len(svc.comments))

    def test_schedule_flexible_svc_downtime(self):
        self.print_header()
        #----------------------------------------------------------------
        # schedule a flexible downtime of 3 minutes for the host
        #----------------------------------------------------------------
        duration = 180
        now = time.time()
        cmd = "[%lu] SCHEDULE_SVC_DOWNTIME;test_host_0;test_ok_0;%d;%d;0;0;%d;lausser;blablub" % (now, now, now + duration, duration)
        self.sched.run_external_command(cmd)
        svc = self.sched.services.find_srv_by_name_and_hostname("test_host_0", "test_ok_0")
        svc.checks_in_progress = []
        svc.act_depend_of = []  # no hostchecks on critical checkresults
        time.sleep(20)
        #----------------------------------------------------------------
        # check if a downtime object exists (scheduler and service)
        # check if the downtime is still inactive
        #----------------------------------------------------------------
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
        self.assertIn(svc.downtimes[0], self.sched.downtimes.values())
        self.assertFalse(svc.downtimes[0].fixed)
        self.assertFalse(svc.downtimes[0].is_in_effect)
        self.assertFalse(svc.downtimes[0].can_be_deleted)
        self.assertEqual(1, len(self.sched.comments))
        self.assertEqual(1, len(svc.comments))
        self.assertIn(svc.comments[0], self.sched.comments.values())
        self.assertEqual(svc.comments[0].id, svc.downtimes[0].comment_id)
        #----------------------------------------------------------------
        # run the service and return an OK status
        # check if the downtime is still inactive
        #----------------------------------------------------------------
        self.scheduler_loop(1, [[svc, 0, 'OK']])
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
        self.assertIn(svc.downtimes[0], self.sched.downtimes.values())
        self.assertFalse(svc.in_scheduled_downtime)
        self.assertFalse(svc.downtimes[0].fixed)
        self.assertFalse(svc.downtimes[0].is_in_effect)
        self.assertFalse(svc.downtimes[0].can_be_deleted)
        time.sleep(61)
        #----------------------------------------------------------------
        # run the service twice to get a soft critical status
        # check if the downtime is still inactive
        #----------------------------------------------------------------
        self.scheduler_loop(1, [[svc, 2, 'BAD']])
        self.assertEqual(1, len(self.sched.downtimes))
        self.assertEqual(1, len(svc.downtimes))
        self.assertIn(svc.downtimes[0], self.sched.downtimes.values())
        self.assertFalse(svc.in_scheduled_downtime)
        self.assertFalse(svc.downtimes[0].fixed)
        self.assertFalse(svc.downtimes[0].is_in_effect)
        self.assertFalse(svc.downtimes[0].can_be_deleted)
        t