Example #1
0
    def test_pass_in_schedule(self):
        schedule = pickle.dumps(CelerySchedule(60))

        call = ScheduledCall('PT1M',
                             'pulp.tasks.dosomething',
                             schedule=schedule)

        self.assertEqual(call.schedule, schedule)
Example #2
0
def update(schedule_id, delta):
    """
    Updates the schedule with unique ID schedule_id. This only allows updating
    of fields in ScheduledCall.USER_UPDATE_FIELDS.

    :param schedule_id: a unique ID for a schedule
    :type  schedule_id: basestring
    :param delta:       a dictionary of keys with values that should be modified
                        on the schedule.
    :type  delta:       dict

    :return:    instance of ScheduledCall representing the post-update state
    :rtype      ScheduledCall

    :raise  exceptions.UnsupportedValue
    :raise  exceptions.MissingResource
    """
    unknown_keys = set(delta.keys()) - ScheduledCall.USER_UPDATE_FIELDS
    if unknown_keys:
        raise exceptions.UnsupportedValue(list(unknown_keys))

    delta['last_updated'] = time.time()

    # bz 1139703 - if we update iso_schedule, update the pickled object as well
    if 'iso_schedule' in delta:
        interval, start_time, occurrences = dateutils.parse_iso8601_interval(
            delta['iso_schedule'])
        delta['schedule'] = pickle.dumps(CelerySchedule(interval))

        # set first_run and next_run so that the schedule update will take effect
        new_schedule_call = ScheduledCall(delta['iso_schedule'],
                                          'dummytaskname')
        delta['first_run'] = new_schedule_call.first_run
        delta['next_run'] = new_schedule_call.next_run

    try:
        spec = {'_id': ObjectId(schedule_id)}
    except InvalidId:
        # During schedule update, MissingResource should be raised even if
        # schedule_id is invalid object_id.
        raise exceptions.MissingResource(schedule_id=schedule_id)
    schedule = ScheduledCall.get_collection().find_and_modify(
        query=spec, update={'$set': delta}, safe=True, new=True)
    if schedule is None:
        raise exceptions.MissingResource(schedule_id=schedule_id)
    return ScheduledCall.from_db(schedule)
Example #3
0
    def __init__(self,
                 iso_schedule,
                 task,
                 total_run_count=0,
                 next_run=None,
                 schedule=None,
                 args=None,
                 kwargs=None,
                 principal=None,
                 last_updated=None,
                 consecutive_failures=0,
                 enabled=True,
                 failure_threshold=None,
                 last_run_at=None,
                 first_run=None,
                 remaining_runs=None,
                 id=None,
                 tags=None,
                 name=None,
                 options=None,
                 resource=None):
        """
        :param iso_schedule:        string representing the schedule in ISO8601 format
        :type  iso_schedule:        basestring
        :param task:                the task that should be run on a schedule. This
                                    can be an instance of a celery task or the name
                                    of the task, as taken from a task's "name" attribute
        :type  task:                basestring or celery.Task
        :param total_run_count:     total number of times this schedule has run
        :type  total_run_count:     int
        :param next_run:            ignored, because it is always re-calculated at instantiation
        :param schedule:            pickled instance of celery.schedules.schedule,
                                    representing the schedule that should be run.
                                    This is optional.
        :type  schedule:            basestring or None
        :param args:                list of arguments that should be passed to the
                                    task's apply_async function as its "args" argument
        :type  args:                list
        :param kwargs:              dict of keyword arguments that should be passed to the task's
                                    apply_async function as its "kwargs" argument
        :type  kwargs:              dict
        :param principal:           pickled instance of pulp.server.db.model.auth.User
                                    representing the pulp user who the task
                                    should be run as. This is optional.
        :type  principal:           basestring or None
        :param last_updated:        timestamp for the last time this schedule was updated in the
                                    database as seconds since the epoch
        :type  last_updated:        float
        :param consecutive_failures:    number of times this task has failed consecutively. This
                                        gets reset to zero if the task succeeds.
        :type  consecutive_failures:    int
        :param enabled:             boolean indicating whether this schedule should be actively run
                                    by the scheduler. If False, the schedule will be ignored.
        :type  enabled:             bool
        :param failure_threshold:   number of consecutive failures after which this task should be
                                    automatically disabled. Because these tasks run asynchronously,
                                    they may finish in a different order than they were queued in.
                                    Thus, it is possible that n consecutive failures will be
                                    reported by jobs that were not queued consecutively. So do not
                                    depend on the queuing order when using this feature. If this
                                    value is 0, no automatic disabling will occur.
        :type  failure_threshold:   int
        :param last_run_at:         ISO8601 string representing when this schedule last ran.
        :type  last_run_at:         basestring
        :param first_run:           ISO8601 string or datetime instance (in UTC timezone)
                                    representing when this schedule should run or should have been
                                    run for the first time. If the schedule has a specified date and
                                    time to start, this will be that value. If not, the value from
                                    the first time the schedule was actually run will be used.
        :type  first_run:           basestring or datetime.datetime or NoneType
        :param remaining_runs:      number of runs remaining until this schedule will be
                                    automatically disabled.
        :type  remaining_runs:      int or NoneType
        :param id:                  unique ID used by mongodb to identify this schedule
        :type  id:                  basestring
        :param tags:                ignored, but allowed to exist as historical
                                    data for now
        :param name:                ignored, because the "id" value is used for this now. The value
                                    is here for backward compatibility.
        :param options:             dictionary that should be passed to the apply_async function as
                                    its "options" argument.
        :type  options:             dict
        :param resource:            optional string indicating a unique resource that should be used
                                    to find this schedule. For example, to find all schedules for a
                                    given repository, a resource string will be derived for that
                                    repo, and this collection will be searched for that resource
                                    string.
        :type  resource:            basestring
        """
        if id is None:
            # this creates self._id and self.id
            super(ScheduledCall, self).__init__()
            self._new = True
        else:
            self.id = id
            self._id = ObjectId(id)
            self._new = False

        if hasattr(task, 'name'):
            task = task.name

        # generate this if it wasn't passed in
        if schedule is None:
            interval, start_time, occurrences = dateutils.parse_iso8601_interval(
                iso_schedule)
            schedule = pickle.dumps(CelerySchedule(interval))

        # generate this if it wasn't passed in
        principal = principal or factory.principal_manager().get_principal()

        self.args = args or []
        self.consecutive_failures = consecutive_failures
        self.enabled = enabled
        self.failure_threshold = failure_threshold
        self.iso_schedule = iso_schedule
        self.kwargs = kwargs or {}
        self.last_run_at = last_run_at
        self.last_updated = last_updated or time.time()
        self.name = id
        self.options = options or {}
        self.principal = principal
        self.resource = resource
        self.schedule = schedule
        self.task = task
        self.total_run_count = total_run_count

        if first_run is None:
            # get the date and time from the iso_schedule value, and if it does not have a date and
            # time, use the current date and time
            self.first_run = dateutils.format_iso8601_datetime(
                dateutils.parse_iso8601_interval(iso_schedule)[1]
                or datetime.utcnow().replace(tzinfo=isodate.UTC))
        elif isinstance(first_run, datetime):
            self.first_run = dateutils.format_iso8601_datetime(first_run)
        else:
            self.first_run = first_run
        if remaining_runs is None:
            self.remaining_runs = dateutils.parse_iso8601_interval(
                iso_schedule)[2]
        else:
            self.remaining_runs = remaining_runs

        self.next_run = self.calculate_next_run()