Example #1
0
def update_sync_status_to_sync_now(mirror):
    """
    This will change the sync status to SYNC_NOW and set the retries remaining to one, if it is less
    than one.

    None will be returned in cases where this is not possible, such as if the mirror is in the
    SYNCING state.
    """

    if mirror.sync_status == RepoMirrorStatus.SYNCING:
        return None

    retries = max(mirror.sync_retries_remaining, 1)

    query = RepoMirrorConfig.update(
        sync_transaction_id=uuid_generator(),
        sync_status=RepoMirrorStatus.SYNC_NOW,
        sync_expiration_date=None,
        sync_retries_remaining=retries,
    ).where(
        RepoMirrorConfig.id == mirror.id,
        RepoMirrorConfig.sync_transaction_id == mirror.sync_transaction_id,
    )

    if query.execute():
        return RepoMirrorConfig.get_by_id(mirror.id)

    return None
Example #2
0
def update_sync_status_to_cancel(mirror):
    """
    If the mirror is SYNCING, it will be force-claimed (ignoring existing transaction id), and the
    state will set to NEVER_RUN.

    None will be returned in cases where this is not possible, such as if the mirror is not in the
    SYNCING state.
    """

    if (
        mirror.sync_status != RepoMirrorStatus.SYNCING
        and mirror.sync_status != RepoMirrorStatus.SYNC_NOW
    ):
        return None

    query = RepoMirrorConfig.update(
        sync_transaction_id=uuid_generator(),
        sync_status=RepoMirrorStatus.NEVER_RUN,
        sync_expiration_date=None,
    ).where(RepoMirrorConfig.id == mirror.id)

    if query.execute():
        return RepoMirrorConfig.get_by_id(mirror.id)

    return None
Example #3
0
def update_with_transaction(mirror, **kwargs):
    """
  Helper function which updates a Repository's RepoMirrorConfig while also rolling its
  sync_transaction_id for locking purposes.
  """

    # RepoMirrorConfig attributes which can be modified
    mutable_attributes = ('is_enabled', 'mirror_type', 'external_reference',
                          'external_registry_username',
                          'external_registry_password',
                          'external_registry_config', 'sync_interval',
                          'sync_start_date', 'sync_expiration_date',
                          'sync_retries_remaining', 'sync_status',
                          'sync_transaction_id')

    # Key-Value map of changes to make
    filtered_kwargs = {
        key: kwargs.pop(key)
        for key in mutable_attributes if key in kwargs
    }

    # Roll the sync_transaction_id to a new value
    filtered_kwargs['sync_transaction_id'] = uuid_generator()

    # Generate the query to perform the updates
    query = (RepoMirrorConfig.update(filtered_kwargs).where(
        RepoMirrorConfig.sync_transaction_id == mirror.sync_transaction_id,
        RepoMirrorConfig.id == mirror.id))

    # Apply the change(s) and return the object if successful
    if query.execute():
        return RepoMirrorConfig.get_by_id(mirror.id)
    else:
        return None
Example #4
0
def update_sync_status(mirror, sync_status):
    """
  Update the sync status
  """
    query = (RepoMirrorConfig.update(
        sync_transaction_id=uuid_generator(), sync_status=sync_status).where(
            RepoMirrorConfig.sync_transaction_id == mirror.sync_transaction_id,
            RepoMirrorConfig.id == mirror.id))
    if query.execute():
        return RepoMirrorConfig.get_by_id(mirror.id)

    return None
Example #5
0
def expire_mirror(mirror):
    """
  Set the mirror to synchronize ASAP and reset its failure count.
  """

    # Set the next-sync date to now
    # TODO: Verify the `where` conditions would not expire a currently syncing mirror.
    query = (RepoMirrorConfig.update(
        sync_transaction_id=uuid_generator(),
        sync_expiration_date=datetime.utcnow(),
        sync_retries_remaining=MAX_SYNC_RETRIES).where(
            RepoMirrorConfig.sync_transaction_id == mirror.sync_transaction_id,
            RepoMirrorConfig.id == mirror.id,
            RepoMirrorConfig.state != RepoMirrorStatus.SYNCING))

    # Fetch and return the latest updates
    if query.execute():
        return RepoMirrorConfig.get_by_id(mirror.id)

    # Unable to update expiration date. Perhaps another process has claimed it?
    return None  # TODO: Raise some Exception?
Example #6
0
def release_mirror(mirror, sync_status):
    """
  Return a mirror to the queue and update its status.

  Upon success, move next sync to be at the next interval in the future. Failures remain with
  current date to ensure they are picked up for repeat attempt. After MAX_SYNC_RETRIES,
  the next sync will be moved ahead as if it were a success. This is to allow a daily sync,
  for example, to retry the next day. Without this, users would need to manually run syncs
  to clear failure state.
  """
    if sync_status == RepoMirrorStatus.FAIL:
        retries = max(0, mirror.sync_retries_remaining - 1)

    if sync_status == RepoMirrorStatus.SUCCESS or retries < 1:
        now = datetime.utcnow()
        delta = now - mirror.sync_start_date
        delta_seconds = (delta.days * 24 * 60 * 60) + delta.seconds
        next_start_date = now + timedelta(
            seconds=mirror.sync_interval -
            (delta_seconds % mirror.sync_interval))
        retries = MAX_SYNC_RETRIES
    else:
        next_start_date = mirror.sync_start_date

    query = RepoMirrorConfig.update(
        sync_transaction_id=uuid_generator(),
        sync_status=sync_status,
        sync_start_date=next_start_date,
        sync_expiration_date=None,
        sync_retries_remaining=retries,
    ).where(
        RepoMirrorConfig.id == mirror.id,
        RepoMirrorConfig.sync_transaction_id == mirror.sync_transaction_id,
    )

    if query.execute():
        return RepoMirrorConfig.get_by_id(mirror.id)

    # Unable to release Mirror. Has it been claimed by another process?
    return None
Example #7
0
def claim_mirror(mirror):
    """
  Attempt to create an exclusive lock on the RepoMirrorConfig and return it.
  If unable to create the lock, `None` will be returned.
  """

    # Attempt to update the RepoMirrorConfig to mark it as "claimed"
    now = datetime.utcnow()
    expiration_date = now + timedelta(seconds=MAX_SYNC_DURATION)
    query = (RepoMirrorConfig.update(
        sync_status=RepoMirrorStatus.SYNCING,
        sync_expiration_date=expiration_date,
        sync_transaction_id=uuid_generator()).where(
            RepoMirrorConfig.id == mirror.id,
            RepoMirrorConfig.sync_transaction_id == mirror.sync_transaction_id)
             )

    # If the update was successful, then it was claimed. Return the updated instance.
    if query.execute():
        return RepoMirrorConfig.get_by_id(mirror.id)

    return None  # Another process must have claimed the mirror faster.