def test_polled_time(self):
        """
        Test a polled job with an interval.  Also test some exceptions
        """
        now = datetime.datetime.now()
        test_name = 'test_job'
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = PolledScheduler.interval(seconds=3)

        # Verify that triggered events work.
        job = self._scheduler.add_polled_job(self._callback, test_name, min_interval, max_interval)
        self.assertEqual(len(self._scheduler.get_jobs()), 1)
        self.assert_event_triggered(now+max_interval)

        # after a triggered event the min time should be extended.
        self.assertFalse(self._scheduler.run_polled_job(test_name))
        time.sleep(1)
        self.assertTrue(self._scheduler.run_polled_job(test_name))
        self.assert_event_triggered(now + min_interval + max_interval)

        # after a polled event the wait time should also be exited
        self.assert_event_triggered(now + min_interval + max_interval + max_interval)

        # Test exceptions. Job name doesn't exist
        with self.assertRaises(LookupError):
            self._scheduler.run_polled_job('foo')

        # Verify that an exception is raised if we try to add a job with the same name
        with self.assertRaises(ValueError):
            job = self._scheduler.add_polled_job(self._callback, test_name, min_interval, max_interval)
    def test_polled_job(self):
        """
        Test features of the specialized job class that we overloaded.
        """
        now = datetime.datetime.now()
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = PolledScheduler.interval(seconds=3)
        trigger = PolledIntervalTrigger(min_interval, max_interval, now)

        job = PolledIntervalJob(trigger,
                                self._callback, [], {},
                                1,
                                1,
                                name='test_job')
        self.assertIsNotNone(job)
        log.debug("H: %s" % repr(job))
        next_time = job.compute_next_run_time(now)
        self.assert_datetime_close(next_time, now + max_interval)
        self.assertEqual(job.name, 'test_job')

        self.assertTrue(job.ready_to_run())
        next_time = job.compute_next_run_time(now)
        self.assertFalse(job.ready_to_run())
        self.assert_datetime_close(next_time, now + max_interval)

        time.sleep(2)
        now = datetime.datetime.now()
        self.assertTrue(job.ready_to_run())

        next_time = job.compute_next_run_time(now)
        self.assertFalse(job.ready_to_run())
        self.assert_datetime_close(next_time, now + max_interval)
    def test_polled_job(self):
        """
        Test features of the specialized job class that we overloaded.
        """
        now = datetime.datetime.now()
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = PolledScheduler.interval(seconds=3)
        trigger = PolledIntervalTrigger(min_interval, max_interval, now)

        job = PolledIntervalJob(trigger, self._callback, [], {}, 1, 1, name='test_job')
        self.assertIsNotNone(job)
        log.debug("H: %s" % repr(job))
        next_time = job.compute_next_run_time(now)
        self.assert_datetime_close(next_time, now + max_interval)
        self.assertEqual(job.name, 'test_job')

        self.assertTrue(job.ready_to_run())
        next_time = job.compute_next_run_time(now)
        self.assertFalse(job.ready_to_run())
        self.assert_datetime_close(next_time, now + max_interval)

        time.sleep(2)
        now = datetime.datetime.now()
        self.assertTrue(job.ready_to_run())

        next_time = job.compute_next_run_time(now)
        self.assertFalse(job.ready_to_run())
        self.assert_datetime_close(next_time, now + max_interval)
    def test_polled_time(self):
        """
        Test a polled job with an interval.  Also test some exceptions
        """
        now = datetime.datetime.now()
        test_name = 'test_job'
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = PolledScheduler.interval(seconds=3)

        # Verify that triggered events work.
        job = self._scheduler.add_polled_job(self._callback, test_name,
                                             min_interval, max_interval)
        self.assertEqual(len(self._scheduler.get_jobs()), 1)
        self.assert_event_triggered(now + max_interval)

        # after a triggered event the min time should be extended.
        self.assertFalse(self._scheduler.run_polled_job(test_name))
        time.sleep(1)
        self.assertTrue(self._scheduler.run_polled_job(test_name))
        self.assert_event_triggered(now + min_interval + max_interval)

        # after a polled event the wait time should also be exited
        self.assert_event_triggered(now + min_interval + max_interval +
                                    max_interval)

        # Test exceptions. Job name doesn't exist
        with self.assertRaises(LookupError):
            self._scheduler.run_polled_job('foo')

        # Verify that an exception is raised if we try to add a job with the same name
        with self.assertRaises(ValueError):
            job = self._scheduler.add_polled_job(self._callback, test_name,
                                                 min_interval, max_interval)
    def test_trigger_string(self):
        """
        test the str and repr methods
        """
        now = datetime.datetime.now()
        trigger = PolledIntervalTrigger(
            PolledScheduler.interval(seconds=1),
            PolledScheduler.interval(seconds=3),
            now)

        self.assertEqual(str(trigger), "min_interval[0:00:01] max_interval[0:00:03]")
        self.assertEqual(repr(trigger), "<PolledIntervalTrigger (min_interval=datetime.timedelta(0, 1), max_interval=datetime.timedelta(0, 3))>")

        trigger = PolledIntervalTrigger(PolledScheduler.interval(seconds=1), None, now)
        self.assertEqual(str(trigger), "min_interval[0:00:01] max_interval[None]")
        self.assertEqual(repr(trigger), "<PolledIntervalTrigger (min_interval=datetime.timedelta(0, 1), max_interval=None)>")
    def test_polled_time_no_interval_not_started(self):
        """
        Try to setup some jobs with the scheduler before the scheduler has been started.
        Then try to startup and see if the job is setup properly.
        """
        now = datetime.datetime.now()
        test_name = 'test_job'
        min_interval = PolledScheduler.interval(seconds=1)

        self._scheduler = PolledScheduler()
        self.assertFalse(self._scheduler.running)

        # Verify that triggered events work.
        job = self._scheduler.add_polled_job(self._callback, test_name,
                                             min_interval)
        self.assertIsNotNone(job)
        self.assertEqual(len(self._scheduler.get_jobs()), 0)
        self.assertEqual(len(self._scheduler._pending_jobs), 1)

        self._scheduler.start()

        log.debug("JOBS: %s" % self._scheduler.get_jobs())
        self.assertEqual(len(self._scheduler.get_jobs()), 1)

        self.assertTrue(self._scheduler.run_polled_job(test_name))
        self.assertFalse(self._scheduler.run_polled_job(test_name))
        time.sleep(2)
        self.assertTrue(self._scheduler.run_polled_job(test_name))
    def test_polled_time_no_interval_not_started(self):
        """
        Try to setup some jobs with the scheduler before the scheduler has been started.
        Then try to startup and see if the job is setup properly.
        """
        now = datetime.datetime.now()
        test_name = 'test_job'
        min_interval = PolledScheduler.interval(seconds=1)

        self._scheduler = PolledScheduler()
        self.assertFalse(self._scheduler.running)

        # Verify that triggered events work.
        job = self._scheduler.add_polled_job(self._callback, test_name, min_interval)
        self.assertIsNotNone(job)
        self.assertEqual(len(self._scheduler.get_jobs()), 0)
        self.assertEqual(len(self._scheduler._pending_jobs), 1)

        self._scheduler.start()

        log.debug("JOBS: %s" % self._scheduler.get_jobs())
        self.assertEqual(len(self._scheduler.get_jobs()), 1)

        self.assertTrue(self._scheduler.run_polled_job(test_name))
        self.assertFalse(self._scheduler.run_polled_job(test_name))
        time.sleep(2)
        self.assertTrue(self._scheduler.run_polled_job(test_name))
    def test_elapse_time(self):
        """
        Test with elapse time.  Not an exhaustive test because it's implemented in the library
        not our code.
        """
        now = datetime.datetime.now()
        interval = PolledScheduler.interval(seconds=3)

        job = self._scheduler.add_interval_job(self._callback, seconds=3)
        self.assert_event_triggered(now + interval)
        self.assert_event_triggered(now + interval + interval)
        self.assert_event_triggered(now + interval + interval + interval)
    def test_trigger_string(self):
        """
        test the str and repr methods
        """
        now = datetime.datetime.now()
        trigger = PolledIntervalTrigger(PolledScheduler.interval(seconds=1),
                                        PolledScheduler.interval(seconds=3),
                                        now)

        self.assertEqual(str(trigger),
                         "min_interval[0:00:01] max_interval[0:00:03]")
        self.assertEqual(
            repr(trigger),
            "<PolledIntervalTrigger (min_interval=datetime.timedelta(0, 1), max_interval=datetime.timedelta(0, 3))>"
        )

        trigger = PolledIntervalTrigger(PolledScheduler.interval(seconds=1),
                                        None, now)
        self.assertEqual(str(trigger),
                         "min_interval[0:00:01] max_interval[None]")
        self.assertEqual(
            repr(trigger),
            "<PolledIntervalTrigger (min_interval=datetime.timedelta(0, 1), max_interval=None)>"
        )
    def test_polled_time_no_interval(self):
        """
        Test the scheduler with a polled job with no interval
        """
        now = datetime.datetime.now()
        test_name = 'test_job'
        min_interval = PolledScheduler.interval(seconds=1)

        # Verify that triggered events work.
        job = self._scheduler.add_polled_job(self._callback, test_name, min_interval)

        self.assertEqual(len(self._scheduler.get_jobs()), 1)

        self.assertTrue(self._scheduler.run_polled_job(test_name))
        self.assertFalse(self._scheduler.run_polled_job(test_name))
        time.sleep(2)
        self.assertTrue(self._scheduler.run_polled_job(test_name))
    def test_elapse_time(self):
        """
        Test with elapse time.  Not an exhaustive test because it's implemented in the library
        not our code.
        """
        now = datetime.datetime.now()
        interval = PolledScheduler.interval(seconds=3)

        job = self._scheduler.add_interval_job(self._callback, seconds=3)
        self.assert_event_triggered(now + interval)
        self.assert_event_triggered(now + interval + interval)
        self.assert_event_triggered(now + interval + interval + interval)

        # Now shutdown the scheduler and verify we aren't firing events
        self._scheduler.shutdown()
        self._triggered = []
        self.assert_event_not_triggered()
    def test_elapse_time(self):
        """
        Test with elapse time.  Not an exhaustive test because it's implemented in the library
        not our code.
        """
        now = datetime.datetime.now()
        interval = PolledScheduler.interval(seconds=3)

        job = self._scheduler.add_interval_job(self._callback, seconds=3)
        self.assert_event_triggered(now + interval)
        self.assert_event_triggered(now + interval + interval)
        self.assert_event_triggered(now + interval + interval + interval)

        # Now shutdown the scheduler and verify we aren't firing events
        self._scheduler.shutdown()
        self._triggered = []
        self.assert_event_not_triggered()
    def test_polled_time_no_interval(self):
        """
        Test the scheduler with a polled job with no interval
        """
        now = datetime.datetime.now()
        test_name = 'test_job'
        min_interval = PolledScheduler.interval(seconds=1)

        # Verify that triggered events work.
        job = self._scheduler.add_polled_job(self._callback, test_name,
                                             min_interval)

        self.assertEqual(len(self._scheduler.get_jobs()), 1)

        self.assertTrue(self._scheduler.run_polled_job(test_name))
        self.assertFalse(self._scheduler.run_polled_job(test_name))
        time.sleep(2)
        self.assertTrue(self._scheduler.run_polled_job(test_name))
class DriverScheduler(object):
    """
    Class to facilitate event scheduling in drivers.
    jobs.
    """

    def __init__(self, config = None):
        """
        config structure:
        {
            test_name: {
                trigger: {}
                callback: some_function
            }
        }
        @param config: job configuration structure.
        """
        self._scheduler = PolledScheduler()
        if(config):
            self.add_config(config)

    def shutdown(self):
        self._scheduler.shutdown()

    def run_job(self, name):
        """
        Try to run a polled job with the passed in name.  If it
        runs then return true, otherwise false.
        @param name: name of the job
        @raise LookupError if we fail to find the job
        """
        return self._scheduler.run_polled_job(name)

    def add_config(self, config):
        """
        Add new jobs to the scheduler using the passed in config
        config structure:
        {
            test_name: {
                trigger: {}
                callback: some_function
            }
        }
        @param config: job configuration structure.
        @raise SchedulerException if we fail to add the job
        """
        if(not isinstance(config, dict)):
            raise SchedulerException("scheduler config not a dict")

        if(len(config.keys()) == 0):
            raise SchedulerException("scheduler config empty")

        for (name, config) in config.items():
            try:
                self._add_job(name, config)
            except ValueError as e:
                raise SchedulerException("failed to schedule job: %s" % e)
            except TypeError as e:
                raise SchedulerException("failed to schedule job: %s" % e)

        if(not self._scheduler.running):
            self._scheduler.start()

    def remove_job(self, callback):
        self._scheduler.unschedule_func(callback)
    
    def _add_job(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        log.debug(" Config name: %s value: %s" % (name, config))

        if(config == None):
            raise SchedulerException("job config empty")

        if(not isinstance(config, dict)):
            raise SchedulerException("job config not a dict")

        trigger = self._get_trigger_from_config(config)

        trigger_type = trigger.get(DriverSchedulerConfigKey.TRIGGER_TYPE)
        if(trigger_type == None):
            raise SchedulerException("trigger type missing")

        if(trigger_type == TriggerType.ABSOLUTE):
            self._add_job_absolute(name, config)
        elif(trigger_type == TriggerType.CRON):
            self._add_job_cron(name, config)
        elif(trigger_type == TriggerType.INTERVAL):
            self._add_job_interval(name, config)
        elif(trigger_type == TriggerType.POLLED_INTERVAL):
            self._add_job_polled_interval(name, config)
        else:
            raise SchedulerException("unknown trigger type '%s'" % trigger_type)

    def _get_trigger_from_config(self, config):
        """
        get and validate the trigger dictionary from the config object.
        @param config: configuration object to inspect
        @return: dictionary from the config for the trigger config
        """
        trigger = config.get(DriverSchedulerConfigKey.TRIGGER)
        if(trigger == None):
            raise SchedulerException("trigger definition missing")
        if(not isinstance(trigger, dict)):
            raise SchedulerException("config missing trigger definition")

        return trigger

    def _get_callback_from_config(self, config):
        """
        get and verify the callback parameter from a job config.
        @param config: configuration object to inspect
        @return: callback method from the config for the trigger config
        """
        callback = config.get(DriverSchedulerConfigKey.CALLBACK)
        if(callback == None):
            raise SchedulerException("callback definition missing")
        if(not callable(callback)):
            raise SchedulerException("callback incorrect type: '%s'" % type(callback))

        return callback

    def _add_job_absolute(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if(not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        dt = trigger.get(DriverSchedulerConfigKey.DATE)
        if(dt == None):
            raise SchedulerException("trigger missing parameter: %s" % DriverSchedulerConfigKey.DATE)

        self._scheduler.add_date_job(callback, dt)

    def _add_job_cron(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if(not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        year = trigger.get(DriverSchedulerConfigKey.YEAR)
        month = trigger.get(DriverSchedulerConfigKey.MONTH)
        day = trigger.get(DriverSchedulerConfigKey.DAY)
        week = trigger.get(DriverSchedulerConfigKey.WEEK)
        day_of_week = trigger.get(DriverSchedulerConfigKey.DAY_OF_WEEK)
        hour = trigger.get(DriverSchedulerConfigKey.HOUR)
        minute = trigger.get(DriverSchedulerConfigKey.MINUTE)
        second = trigger.get(DriverSchedulerConfigKey.SECOND)

        if(year==None and month==None and day==None and week==None and
           day_of_week==None and hour==None and minute==None and second==None):
            raise SchedulerException("at least one cron parameter required!")

        self._scheduler.add_cron_job(callback, year=year, month=month, day=day, week=week,
                                     day_of_week=day_of_week, hour=hour, minute=minute, second=second)

    def _add_job_interval(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if(not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        weeks = trigger.get(DriverSchedulerConfigKey.WEEKS, 0)
        days = trigger.get(DriverSchedulerConfigKey.DAYS, 0)
        hours = trigger.get(DriverSchedulerConfigKey.HOURS, 0)
        minutes = trigger.get(DriverSchedulerConfigKey.MINUTES, 0)
        seconds = trigger.get(DriverSchedulerConfigKey.SECONDS, 0)

        if(not (weeks or days or hours or minutes or seconds)):
            raise SchedulerException("at least interval parameter required!")

        self._scheduler.add_interval_job(callback, weeks=weeks, days=days, hours=hours,
                                                   minutes=minutes, seconds=seconds)

    def _add_job_polled_interval(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if(not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        min_interval = trigger.get(DriverSchedulerConfigKey.MINIMAL_INTERVAL)
        max_interval = trigger.get(DriverSchedulerConfigKey.MAXIMUM_INTERVAL)

        if(min_interval == None):
            raise SchedulerException("%s missing from trigger configuration" % DriverSchedulerConfigKey.MINIMAL_INTERVAL)
        if(not isinstance(min_interval, dict)):
            raise SchedulerException("%s trigger configuration not a dict" % DriverSchedulerConfigKey.MINIMAL_INTERVAL)

        min_weeks = min_interval.get(DriverSchedulerConfigKey.WEEKS, 0)
        min_days = min_interval.get(DriverSchedulerConfigKey.DAYS, 0)
        min_hours = min_interval.get(DriverSchedulerConfigKey.HOURS, 0)
        min_minutes = min_interval.get(DriverSchedulerConfigKey.MINUTES, 0)
        min_seconds = min_interval.get(DriverSchedulerConfigKey.SECONDS, 0)

        if(not (min_weeks or min_days or min_hours or min_minutes or min_seconds)):
            raise SchedulerException("at least interval parameter required!")

        min_interval_obj = self._scheduler.interval(min_weeks, min_days, min_hours, min_minutes, min_seconds)

        max_interval_obj = None
        if(max_interval != None):
            if(not isinstance(max_interval, dict)):
                raise SchedulerException("%s trigger configuration not a dict" % DriverSchedulerConfigKey.MINIMAL_INTERVAL)

            max_weeks = max_interval.get(DriverSchedulerConfigKey.WEEKS, 0)
            max_days = max_interval.get(DriverSchedulerConfigKey.DAYS, 0)
            max_hours = max_interval.get(DriverSchedulerConfigKey.HOURS, 0)
            max_minutes = max_interval.get(DriverSchedulerConfigKey.MINUTES, 0)
            max_seconds = max_interval.get(DriverSchedulerConfigKey.SECONDS, 0)

            if(max_weeks or max_days or max_hours or max_minutes or max_seconds):
                max_interval_obj = self._scheduler.interval(max_weeks, max_days, max_hours, max_minutes, max_seconds)

        self._scheduler.add_polled_job(callback, name, min_interval_obj, max_interval_obj)
Beispiel #15
0
class DriverScheduler(object):
    """
    Class to facilitate event scheduling in drivers.
    jobs.
    """
    def __init__(self, config=None):
        """
        config structure:
        {
            test_name: {
                trigger: {}
                callback: some_function
            }
        }
        @param config: job configuration structure.
        """
        self._scheduler = PolledScheduler()
        if (config):
            self.add_config(config)

    def shutdown(self):
        self._scheduler.shutdown()

    def run_job(self, name):
        """
        Try to run a polled job with the passed in name.  If it
        runs then return true, otherwise false.
        @param name: name of the job
        @raise LookupError if we fail to find the job
        """
        return self._scheduler.run_polled_job(name)

    def add_config(self, config):
        """
        Add new jobs to the scheduler using the passed in config
        config structure:
        {
            test_name: {
                trigger: {}
                callback: some_function
            }
        }
        @param config: job configuration structure.
        @raise SchedulerException if we fail to add the job
        """
        if (not isinstance(config, dict)):
            raise SchedulerException("scheduler config not a dict")

        if (len(config.keys()) == 0):
            raise SchedulerException("scheduler config empty")

        for (name, config) in config.items():
            try:
                self._add_job(name, config)
            except ValueError as e:
                raise SchedulerException("failed to schedule job: %s" % e)
            except TypeError as e:
                raise SchedulerException("failed to schedule job: %s" % e)

        if (not self._scheduler.running):
            self._scheduler.start()

    def remove_job(self, callback):
        self._scheduler.unschedule_func(callback)

    def _add_job(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        log.debug(" Config name: %s value: %s" % (name, config))

        if (config == None):
            raise SchedulerException("job config empty")

        if (not isinstance(config, dict)):
            raise SchedulerException("job config not a dict")

        trigger = self._get_trigger_from_config(config)

        trigger_type = trigger.get(DriverSchedulerConfigKey.TRIGGER_TYPE)
        if (trigger_type == None):
            raise SchedulerException("trigger type missing")

        if (trigger_type == TriggerType.ABSOLUTE):
            self._add_job_absolute(name, config)
        elif (trigger_type == TriggerType.CRON):
            self._add_job_cron(name, config)
        elif (trigger_type == TriggerType.INTERVAL):
            self._add_job_interval(name, config)
        elif (trigger_type == TriggerType.POLLED_INTERVAL):
            self._add_job_polled_interval(name, config)
        else:
            raise SchedulerException("unknown trigger type '%s'" %
                                     trigger_type)

    def _get_trigger_from_config(self, config):
        """
        get and validate the trigger dictionary from the config object.
        @param config: configuration object to inspect
        @return: dictionary from the config for the trigger config
        """
        trigger = config.get(DriverSchedulerConfigKey.TRIGGER)
        if (trigger == None):
            raise SchedulerException("trigger definition missing")
        if (not isinstance(trigger, dict)):
            raise SchedulerException("config missing trigger definition")

        return trigger

    def _get_callback_from_config(self, config):
        """
        get and verify the callback parameter from a job config.
        @param config: configuration object to inspect
        @return: callback method from the config for the trigger config
        """
        callback = config.get(DriverSchedulerConfigKey.CALLBACK)
        if (callback == None):
            raise SchedulerException("callback definition missing")
        if (not callable(callback)):
            raise SchedulerException("callback incorrect type: '%s'" %
                                     type(callback))

        return callback

    def _add_job_absolute(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if (not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        dt = trigger.get(DriverSchedulerConfigKey.DATE)
        if (dt == None):
            raise SchedulerException("trigger missing parameter: %s" %
                                     DriverSchedulerConfigKey.DATE)

        self._scheduler.add_date_job(callback, dt)

    def _add_job_cron(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if (not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        year = trigger.get(DriverSchedulerConfigKey.YEAR)
        month = trigger.get(DriverSchedulerConfigKey.MONTH)
        day = trigger.get(DriverSchedulerConfigKey.DAY)
        week = trigger.get(DriverSchedulerConfigKey.WEEK)
        day_of_week = trigger.get(DriverSchedulerConfigKey.DAY_OF_WEEK)
        hour = trigger.get(DriverSchedulerConfigKey.HOUR)
        minute = trigger.get(DriverSchedulerConfigKey.MINUTE)
        second = trigger.get(DriverSchedulerConfigKey.SECOND)

        if (year == None and month == None and day == None and week == None
                and day_of_week == None and hour == None and minute == None
                and second == None):
            raise SchedulerException("at least one cron parameter required!")

        self._scheduler.add_cron_job(callback,
                                     year=year,
                                     month=month,
                                     day=day,
                                     week=week,
                                     day_of_week=day_of_week,
                                     hour=hour,
                                     minute=minute,
                                     second=second)

    def _add_job_interval(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if (not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        weeks = trigger.get(DriverSchedulerConfigKey.WEEKS, 0)
        days = trigger.get(DriverSchedulerConfigKey.DAYS, 0)
        hours = trigger.get(DriverSchedulerConfigKey.HOURS, 0)
        minutes = trigger.get(DriverSchedulerConfigKey.MINUTES, 0)
        seconds = trigger.get(DriverSchedulerConfigKey.SECONDS, 0)

        if (not (weeks or days or hours or minutes or seconds)):
            raise SchedulerException("at least interval parameter required!")

        self._scheduler.add_interval_job(callback,
                                         weeks=weeks,
                                         days=days,
                                         hours=hours,
                                         minutes=minutes,
                                         seconds=seconds)

    def _add_job_polled_interval(self, name, config):
        """
        Add a new job to the scheduler based on the trigger configuration
        @param name: name of the job
        @param config: job configuration
        @raise SchedulerError if we fail to add the job
        """
        if (not isinstance(config, dict)):
            raise SchedulerException("config not a dict")

        callback = self._get_callback_from_config(config)
        trigger = self._get_trigger_from_config(config)

        min_interval = trigger.get(DriverSchedulerConfigKey.MINIMAL_INTERVAL)
        max_interval = trigger.get(DriverSchedulerConfigKey.MAXIMUM_INTERVAL)

        if (min_interval == None):
            raise SchedulerException("%s missing from trigger configuration" %
                                     DriverSchedulerConfigKey.MINIMAL_INTERVAL)
        if (not isinstance(min_interval, dict)):
            raise SchedulerException("%s trigger configuration not a dict" %
                                     DriverSchedulerConfigKey.MINIMAL_INTERVAL)

        min_weeks = min_interval.get(DriverSchedulerConfigKey.WEEKS, 0)
        min_days = min_interval.get(DriverSchedulerConfigKey.DAYS, 0)
        min_hours = min_interval.get(DriverSchedulerConfigKey.HOURS, 0)
        min_minutes = min_interval.get(DriverSchedulerConfigKey.MINUTES, 0)
        min_seconds = min_interval.get(DriverSchedulerConfigKey.SECONDS, 0)

        if (not (min_weeks or min_days or min_hours or min_minutes
                 or min_seconds)):
            raise SchedulerException("at least interval parameter required!")

        min_interval_obj = self._scheduler.interval(min_weeks, min_days,
                                                    min_hours, min_minutes,
                                                    min_seconds)

        max_interval_obj = None
        if (max_interval != None):
            if (not isinstance(max_interval, dict)):
                raise SchedulerException(
                    "%s trigger configuration not a dict" %
                    DriverSchedulerConfigKey.MINIMAL_INTERVAL)

            max_weeks = max_interval.get(DriverSchedulerConfigKey.WEEKS, 0)
            max_days = max_interval.get(DriverSchedulerConfigKey.DAYS, 0)
            max_hours = max_interval.get(DriverSchedulerConfigKey.HOURS, 0)
            max_minutes = max_interval.get(DriverSchedulerConfigKey.MINUTES, 0)
            max_seconds = max_interval.get(DriverSchedulerConfigKey.SECONDS, 0)

            if (max_weeks or max_days or max_hours or max_minutes
                    or max_seconds):
                max_interval_obj = self._scheduler.interval(
                    max_weeks, max_days, max_hours, max_minutes, max_seconds)

        self._scheduler.add_polled_job(callback, name, min_interval_obj,
                                       max_interval_obj)
    def test_polled_interval_trigger(self):
        """
        test the trigger mechanism.
        """
        ###
        # Test all constructors and exceptions
        ###
        trigger = PolledIntervalTrigger(PolledScheduler.interval(seconds=1))
        self.assertEqual(trigger.min_interval_length, 1)
        self.assertIsNone(trigger.max_interval)
        self.assertIsNone(trigger.max_interval_length)
        self.assertIsInstance(trigger.next_min_date, datetime.datetime)
        self.assertIsNone(trigger.next_max_date)

        trigger = PolledIntervalTrigger(PolledScheduler.interval(seconds=1),
                                        PolledScheduler.interval(seconds=3))
        self.assertEqual(trigger.min_interval_length, 1)
        self.assertEqual(trigger.max_interval_length, 3)

        trigger = PolledIntervalTrigger(PolledScheduler.interval(seconds=1),
                                        PolledScheduler.interval(seconds=3),
                                        datetime.datetime.now())
        self.assertEqual(trigger.min_interval_length, 1)
        self.assertEqual(trigger.max_interval_length, 3)

        # Test Type Error Exception
        with self.assertRaises(TypeError):
            trigger = PolledIntervalTrigger('boom')

        with self.assertRaises(TypeError):
            trigger = PolledIntervalTrigger(
                PolledScheduler.interval(seconds=3), 'boom')

        # Test Value Error Exception
        with self.assertRaises(ValueError):
            trigger = PolledIntervalTrigger(
                PolledScheduler.interval(seconds=3),
                PolledScheduler.interval(seconds=1))

        ###
        # Verify min and max dates are incremented correctly.
        ###
        now = datetime.datetime.now()
        log.debug("Now: %s" % now)
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = PolledScheduler.interval(seconds=3)

        trigger = PolledIntervalTrigger(min_interval, max_interval, now)

        # Initialized correctly?
        self.assert_datetime_close(trigger.next_min_date, now)
        self.assert_datetime_close(trigger.next_max_date, now + max_interval)
        self.assert_datetime_close(trigger.get_next_fire_time(now),
                                   now + max_interval)

        # First call should be successful, but second should not.
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())

        self.assert_datetime_close(trigger.next_min_date, now + min_interval)
        self.assert_datetime_close(trigger.next_max_date, now + max_interval)
        self.assert_datetime_close(trigger.get_next_fire_time(now),
                                   now + max_interval)

        # Wait for the minimum interval and it should succeed again!
        time.sleep(2)
        now = datetime.datetime.now()
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())

        ###
        # Now do the same sequence, but with no max_interval
        ###
        now = datetime.datetime.now()
        log.debug("Now: %s" % now)
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = None

        trigger = PolledIntervalTrigger(min_interval, max_interval, now)

        # Initialized correctly?
        self.assert_datetime_close(trigger.next_min_date, now)
        self.assertIsNone(trigger.next_max_date)
        self.assertIsNone(trigger.get_next_fire_time(now))

        # First call should be successful, but second should not.
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())

        self.assert_datetime_close(trigger.next_min_date, now + min_interval)
        self.assertIsNone(trigger.next_max_date)
        self.assertIsNone(trigger.get_next_fire_time(now))

        # Wait for the minimum interval and it should succeed again!
        time.sleep(2)
        now = datetime.datetime.now()
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())
    def test_polled_interval_trigger(self):
        """
        test the trigger mechanism.
        """
        ###
        # Test all constructors and exceptions
        ###
        trigger = PolledIntervalTrigger(PolledScheduler.interval(seconds=1))
        self.assertEqual(trigger.min_interval_length, 1)
        self.assertIsNone(trigger.max_interval)
        self.assertIsNone(trigger.max_interval_length)
        self.assertIsInstance(trigger.next_min_date, datetime.datetime)
        self.assertIsNone(trigger.next_max_date)

        trigger = PolledIntervalTrigger(
            PolledScheduler.interval(seconds=1),
            PolledScheduler.interval(seconds=3)
        )
        self.assertEqual(trigger.min_interval_length, 1)
        self.assertEqual(trigger.max_interval_length, 3)

        trigger = PolledIntervalTrigger(
            PolledScheduler.interval(seconds=1),
            PolledScheduler.interval(seconds=3),
            datetime.datetime.now()
        )
        self.assertEqual(trigger.min_interval_length, 1)
        self.assertEqual(trigger.max_interval_length, 3)

        # Test Type Error Exception
        with self.assertRaises(TypeError):
            trigger = PolledIntervalTrigger('boom')

        with self.assertRaises(TypeError):
            trigger = PolledIntervalTrigger(
                PolledScheduler.interval(seconds=3),
                'boom'
            )

        # Test Value Error Exception
        with self.assertRaises(ValueError):
            trigger = PolledIntervalTrigger(
                PolledScheduler.interval(seconds=3),
                PolledScheduler.interval(seconds=1)
            )

        ###
        # Verify min and max dates are incremented correctly.
        ###
        now = datetime.datetime.now()
        log.debug("Now: %s" % now)
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = PolledScheduler.interval(seconds=3)

        trigger = PolledIntervalTrigger(min_interval, max_interval, now)

        # Initialized correctly?
        self.assert_datetime_close(trigger.next_min_date, now)
        self.assert_datetime_close(trigger.next_max_date, now + max_interval)
        self.assert_datetime_close(trigger.get_next_fire_time(now), now + max_interval)

        # First call should be successful, but second should not.
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())

        self.assert_datetime_close(trigger.next_min_date, now + min_interval)
        self.assert_datetime_close(trigger.next_max_date, now + max_interval)
        self.assert_datetime_close(trigger.get_next_fire_time(now), now + max_interval)

        # Wait for the minimum interval and it should succeed again!
        time.sleep(2)
        now = datetime.datetime.now()
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())

        ###
        # Now do the same sequence, but with no max_interval
        ###
        now = datetime.datetime.now()
        log.debug("Now: %s" % now)
        min_interval = PolledScheduler.interval(seconds=1)
        max_interval = None

        trigger = PolledIntervalTrigger(min_interval, max_interval, now)

        # Initialized correctly?
        self.assert_datetime_close(trigger.next_min_date, now)
        self.assertIsNone(trigger.next_max_date)
        self.assertIsNone(trigger.get_next_fire_time(now))

        # First call should be successful, but second should not.
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())

        self.assert_datetime_close(trigger.next_min_date, now + min_interval)
        self.assertIsNone(trigger.next_max_date)
        self.assertIsNone(trigger.get_next_fire_time(now))

        # Wait for the minimum interval and it should succeed again!
        time.sleep(2)
        now = datetime.datetime.now()
        self.assertTrue(trigger.pull_trigger())
        self.assertFalse(trigger.pull_trigger())