Ejemplo n.º 1
0
def renewal_event_is_fired_after_one_month(context):
    # after 1 month , AllocationSourceSnapshot is first updated.

    report_start_date = context.ts
    report_end_date = context.ts + timedelta(days=30)
    query = EventTable.objects.filter(name='allocation_source_renewed',
                                      payload__name__exact='DefaultAllocationSource')
    assert len(query) == 0
    source_snapshot = AllocationSourceSnapshot.objects.filter(allocation_source=context.allocation_source_2).order_by(
        'updated').last()
    assert total_usage(context.amit.user.username, report_start_date,
                       allocation_source_name=context.allocation_source_2.name,
                       end_date=report_end_date) == 72.0
    source_snapshot.compute_used = total_usage(context.amit.user.username, report_start_date,
                                               allocation_source_name=context.allocation_source_2.name,
                                               end_date=report_end_date)
    source_snapshot.updated = context.ts + timedelta(days=29)
    source_snapshot.save()

    assert AllocationSourceSnapshot.objects.filter(allocation_source=context.allocation_source_2).order_by(
        'updated').last().compute_used == 72.0

    # rules engine is explicitly run

    current_time = context.ts + timedelta(days=30)
    run_all(rule_list=cyverse_rules,
            defined_variables=CyverseTestRenewalVariables(context.allocation_source_2, current_time),
            defined_actions=CyverseTestRenewalActions(context.allocation_source_2, current_time),
            )

    query = EventTable.objects.filter(name='allocation_source_renewed', payload__name__exact='DefaultAllocationSource')
    assert len(query) == 1
Ejemplo n.º 2
0
def total_usage_is_five_hours(context):
    report_start_date = context.ts
    report_end_date = context.ts + timedelta(hours=4)
    tots = total_usage(context.julian.user.username, report_start_date,
                       allocation_source_name=context.allocation_source_1.name,
                       end_date=report_end_date) + total_usage(context.amit.user.username, report_start_date,
                                                               allocation_source_name=context.allocation_source_1.name,
                                                               end_date=report_end_date)
    assert tots == 5.0
Ejemplo n.º 3
0
def total_usage_is_zero(context):
    report_start_date = context.ts
    report_end_date = context.ts + timedelta(minutes=120)
    tots = total_usage(context.amit.user.username, report_start_date,
                       allocation_source_name=context.allocation_source_1.name,
                       end_date=report_end_date)
    print(tots)
    assert total_usage(context.amit.user.username, report_start_date,
                       allocation_source_name=context.allocation_source_1.name,
                       end_date=report_end_date) == 0.0
Ejemplo n.º 4
0
def step_impl(context):
    current_time = context.current_time
    for row in context.table:
        allocation_source = AllocationSource.objects.filter(
            name=context.allocation_sources_name[row['allocation_source_id']]).last()

        start_date = current_time if str(row['report start date']) == 'current' else parse(
            str(row['report start date']))
        end_date = start_date + timedelta(days=int(row['number of days']))
        celery_iterator = list(rrule(HOURLY, interval=12, dtstart=start_date, until=end_date))

        prev_time = ''

        for current_time in celery_iterator:
            # update AllocationSourceSnapshot with the current compute_used
            if prev_time:
                update_snapshot_cyverse(end_date=current_time)
            prev_time = current_time

        context.time_at_the_end_of_calculation_check = current_time

        compute_used_total = 0
        for user in allocation_source.all_users:
            compute_used_total += total_usage(user.username, start_date=start_date,
                                              end_date=end_date, allocation_source_name=context.allocation_sources_name[
                    row['allocation_source_id']])

        compute_allowed = AllocationSourceSnapshot.objects.filter(
            allocation_source=allocation_source).last().compute_allowed
        compute_used_from_snapshot = AllocationSourceSnapshot.objects.filter(
            allocation_source=allocation_source).last().compute_used
        assert float(row['total compute used']) == float(compute_used_from_snapshot)
        assert float(row['current compute used']) == float(compute_used_from_snapshot)
        assert float(row['current compute allowed']) == float(compute_allowed)
Ejemplo n.º 5
0
def get_compute_used(allocation_source, current_time, prev_time):
    compute_used = 0
    for user in allocation_source.all_users:
        compute_used += total_usage(user.username, start_date=prev_time,
                                    end_date=current_time, allocation_source_name=allocation_source.name)

    return compute_used
Ejemplo n.º 6
0
def calculate_allocations_used_by_allocation_source_after_certain_number_of_days(context):
    current_time = context.current_time
    for row in context.table:
        allocation_source = AllocationSource.objects.filter(
            name=context.allocation_sources_name[row['allocation_source_id']]).last()

        start_date = current_time if str(row['report start date']) == 'current' else parse(
            str(row['report start date']))
        end_date = start_date + timedelta(days=int(row['number of days']))
        celery_iterator = list(rrule(HOURLY, interval=12, dtstart=start_date, until=end_date))

        prev_time = ''

        for current_time in celery_iterator:
            # update AllocationSourceSnapshot with the current compute_used
            if prev_time:
                update_snapshot_cyverse(end_date=current_time)
            prev_time = current_time

        context.time_at_the_end_of_calculation_check = current_time

        compute_used_total = 0
        for user in allocation_source.all_users:
            compute_used_total += total_usage(user.username, start_date=start_date,
                                              end_date=end_date, allocation_source_name=context.allocation_sources_name[
                    row['allocation_source_id']])

        compute_allowed = AllocationSourceSnapshot.objects.filter(
            allocation_source=allocation_source).last().compute_allowed
        compute_used_from_snapshot = AllocationSourceSnapshot.objects.filter(
            allocation_source=allocation_source).last().compute_used
        assert float(row['total compute used']) == float(compute_used_from_snapshot)
        assert float(row['current compute used']) == float(compute_used_from_snapshot)
        assert float(row['current compute allowed']) == float(compute_allowed)
Ejemplo n.º 7
0
def get_compute_used(allocation_source, current_time, prev_time):
    compute_used = 0
    for user in allocation_source.all_users:
        compute_used += total_usage(user.username, start_date=prev_time,
                                    end_date=current_time, allocation_source_name=allocation_source.name)

    return compute_used
Ejemplo n.º 8
0
def step_impl(context):
    report_start_date = context.ts
    report_end_date = context.ts + timedelta(hours=4)
    assert total_usage(context.amit.user.username,
                       report_start_date,
                       allocation_source_name=context.allocation_source_1.name,
                       end_date=report_end_date) == 2.0
Ejemplo n.º 9
0
def update_snapshot_cyverse(start_date=None, end_date=None):
    logger.debug("update_snapshot_cyverse task started at %s." %
                 datetime.now())
    end_date = timezone.now().replace(
        microsecond=0) if not end_date else end_date

    for allocation_source in AllocationSource.objects.order_by('name'):
        # calculate and save snapshots here
        allocation_source_name = allocation_source.name
        last_renewal_event = EventTable.objects.filter(
            name='allocation_source_created_or_renewed',
            payload__allocation_source_name__exact=str(
                allocation_source_name)).order_by('timestamp')

        if not last_renewal_event:
            logger.info('Allocation Source %s Create/Renewal event missing',
                        allocation_source_name)
            continue

        start_date = last_renewal_event.last().timestamp.replace(
            microsecond=0) if not start_date else start_date

        total_compute_used = 0
        total_burn_rate = 0
        for user in allocation_source.all_users:
            compute_used, burn_rate = total_usage(
                user.username,
                start_date=start_date,
                end_date=end_date,
                allocation_source_name=allocation_source_name,
                burn_rate=True)

            UserAllocationSnapshot.objects.update_or_create(
                allocation_source=allocation_source,
                user=user,
                defaults={
                    'compute_used': compute_used,
                    'burn_rate': burn_rate
                })
            total_compute_used += compute_used
            total_burn_rate += burn_rate
        AllocationSourceSnapshot.objects.update_or_create(
            allocation_source=allocation_source,
            defaults={
                'compute_used': total_compute_used,
                'global_burn_rate': total_burn_rate
            })

        run_all(
            rule_list=cyverse_rules,
            defined_variables=CyverseTestRenewalVariables(
                allocation_source, end_date, start_date),
            defined_actions=CyverseTestRenewalActions(allocation_source,
                                                      end_date),
        )
    # At the end of the task, fire-off an allocation threshold check
    logger.debug("update_snapshot_cyverse task finished at %s." %
                 datetime.now())
    allocation_threshold_check.apply_async()
Ejemplo n.º 10
0
def update_snapshot(start_date=None, end_date=None):
    end_date = end_date or timezone.now()
    # TODO: Read this start_date from last 'reset event' for each allocation source
    start_date = start_date or '2016-09-01 00:00:00.0-05'

    tas_api_obj = TASAPIDriver()
    allocation_source_usage_from_tas = tas_api_obj.get_all_projects()

    for project in allocation_source_usage_from_tas:
        total_burn_rate = 0
        allocation_source_name = project['chargeCode']
        try:
            allocation_source = AllocationSource.objects.filter(
                name=allocation_source_name
            ).order_by('id').last()

            if not allocation_source:
                continue

            created_or_updated_event = EventTable.objects.filter(
                name='allocation_source_created_or_renewed',
                payload__allocation_source_name=allocation_source.name
            ).order_by('timestamp').last()

            if created_or_updated_event:
                # if renewed, change ignore old allocation usage
                start_date = created_or_updated_event.payload['start_date']

            for user in allocation_source.all_users:
                compute_used, burn_rate = total_usage(
                    user.username,
                    start_date,
                    allocation_source_name=allocation_source.name,
                    end_date=end_date,
                    burn_rate=True
                )
                total_burn_rate += burn_rate
                UserAllocationSnapshot.objects.update_or_create(
                    allocation_source_id=allocation_source.id,
                    user_id=user.id,
                    defaults={
                        'compute_used': compute_used,
                        'burn_rate': burn_rate
                    }
                )

        except KeyError:
            # This allocation source does not exist in our database yet. Create it? Skip for now.
            continue
        valid_allocation = select_valid_allocation(project['allocations'])
        compute_used = valid_allocation['computeUsed'] if valid_allocation else 0
        AllocationSourceSnapshot.objects.update_or_create(
            allocation_source_id=allocation_source.id,
            defaults={
                'compute_used': compute_used,
                'global_burn_rate': total_burn_rate
            }
        )
    return True
def total_user_is_two_hours(context):
    report_start_date = context.ts
    report_end_date = context.ts + timedelta(hours=4)
    assert total_usage(
        context.amit.user.username,
        report_start_date,
        allocation_source_name=context.allocation_source_1.name,
        end_date=report_end_date
    ) == 2.0
    def test_total_usage(self):

        ts = parse('2016-10-04T00:00+00:00')
        allocation_source = create_allocation_source(name='TestSource', compute_allowed=1000,timestamp=ts)

        # In this workflow the instance_allocation_source_changed event is fired before any instance status history is created. Hence the instance will report usage as 0.0 because
        # it thinks the allocation source is 'N/A'. A fix for this would be to decouple instance status histories and events completely in the allocation logic.

        workflow1 = UserWorkflow()
        workflow1.assign_allocation_source_to_user(allocation_source, timestamp=ts + timedelta(minutes=10))
        instance = workflow1.create_instance(start_date=ts+timedelta(minutes=30))
        workflow1.create_instance_status_history(instance,start_date=ts+timedelta(days=30),status='suspend')
        workflow1.assign_allocation_source_to_instance(allocation_source, instance,
                                                       timestamp=ts + timedelta(minutes=40))

        report_start_date = ts
        report_end_date=ts + timedelta(minutes=160)

        self.assertEqual(
            total_usage(workflow1.user.username,report_start_date,allocation_source_name=allocation_source.name,end_date=report_end_date),
            2.0)

        workflow2 = UserWorkflow()
        workflow2.assign_allocation_source_to_user(allocation_source, timestamp=ts + timedelta(minutes=10))
        instance = workflow2.create_instance(start_date=ts + timedelta(minutes=30))
        workflow2.assign_allocation_source_to_instance(allocation_source, instance,
                                                       timestamp=ts + timedelta(minutes=40))
        ish_start_date=ts+timedelta(minutes=120)
        workflow2.create_instance_status_history(instance, start_date=ish_start_date,status='suspended')

        report_start_date = ts
        report_end_date = ts+timedelta(minutes=120)

        self.assertEqual(
            total_usage(workflow2.user.username, report_start_date, allocation_source_name=allocation_source.name,
                        end_date=report_end_date),
            1.33)

        # check total allocation usage so far
        end_date = ts+timedelta(days=30)
        update_snapshot_cyverse_allocation(ts,end_date)
        self.assertEqual( float(allocation_source.compute_used) , 720.66 )
Ejemplo n.º 13
0
def update_snapshot():
    if not settings.USE_ALLOCATION_SOURCE:
        return False
    allocation_source_total_compute = {}
    allocation_source_total_burn_rate = {}
    end_date = timezone.now()
    for source in AllocationSource.objects.all():
        # iterate over user + allocation_source combo
        for user_allocation_source in UserAllocationSource.objects.filter(
                allocation_source__exact=source.id):
            user = user_allocation_source.user
            # determine end date and start date using last snapshot
            start_date = user.date_joined
            # calculate compute used and burn rate for the user and allocation source combo
            compute_used, burn_rate = total_usage(
                user.username,
                start_date,
                allocation_source_name=source.name,
                end_date=end_date,
                burn_rate=True)

            allocation_source_total_compute[
                source.name] = allocation_source_total_compute.get(
                    source.name, 0) + compute_used
            allocation_source_total_burn_rate[
                source.name] = allocation_source_total_burn_rate.get(
                    source.name, 0) + burn_rate

            payload_ubr = {
                "allocation_source_id": source.source_id,
                "username": user.username,
                "burn_rate": burn_rate,
                "compute_used": compute_used
            }
            EventTable.create_event("user_allocation_snapshot_changed",
                                    payload_ubr, user.username)

        payload_as = {
            "allocation_source_id":
            source.source_id,
            "compute_used":
            allocation_source_total_compute.get(source.name, 0),
            "global_burn_rate":
            allocation_source_total_burn_rate.get(source.name, 0)
        }
        EventTable.create_event("allocation_source_snapshot", payload_as,
                                source.name)
    return True
def _create_tas_report_for(user, tacc_username, tacc_project_name, end_date):
    """
    Create a new report
    """
    if not end_date:
        raise TASPluginException("Explicit end date required")
    if not user:
        raise TASPluginException("User missing")
    if not tacc_username:
        raise TASPluginException("TACC Username missing")
    if not tacc_project_name:
        raise TASPluginException("OpenStack/TACC Project missing")

    last_report = TASAllocationReport.objects.filter(
        project_name=tacc_project_name, user=user
    ).order_by('end_date').last()
    if not last_report:
        start_date = user.date_joined
    else:
        start_date = last_report.end_date

    compute_used = total_usage(
        user.username,
        start_date,
        allocation_source_name=tacc_project_name,
        end_date=end_date
    )

    if compute_used < 0:
        raise TASPluginException(
            "Compute usage was not accurately calculated for user:%s for start_date:%s and end_date:%s"
            % (user, start_date, end_date)
        )

    new_report = TASAllocationReport.objects.create(
        user=user,
        username=tacc_username,
        project_name=tacc_project_name,
        compute_used=compute_used,
        start_date=start_date,
        end_date=end_date,
        tacc_api=settings.TACC_API_URL
    )
    logger.info("Created New Report:%s" % new_report)
    return new_report
Ejemplo n.º 15
0
def _create_tas_report_for(user, tacc_username, tacc_project_name, end_date):
    """
    Create a new report
    """
    if not end_date:
        raise TASPluginException("Explicit end date required")
    if not user:
        raise TASPluginException("User missing")
    if not tacc_username:
        raise TASPluginException("TACC Username missing")
    if not tacc_project_name:
        raise TASPluginException("OpenStack/TACC Project missing")

    last_report = TASAllocationReport.objects.filter(
        project_name=tacc_project_name, user=user
    ).order_by('end_date').last()
    if not last_report:
        start_date = user.date_joined
    else:
        start_date = last_report.end_date

    compute_used = total_usage(
        user.username,
        start_date,
        allocation_source_name=tacc_project_name,
        end_date=end_date
    )

    if compute_used < 0:
        raise TASPluginException(
            "Compute usage was not accurately calculated for user:%s" % user
        )

    new_report = TASAllocationReport.objects.create(
        user=user,
        username=tacc_username,
        project_name=tacc_project_name,
        compute_used=compute_used,
        start_date=start_date,
        end_date=end_date,
        tacc_api=settings.TACC_API_URL
    )
    logger.info("Created New Report:%s" % new_report)
    return new_report
Ejemplo n.º 16
0
def update_snapshot_cyverse(start_date=None, end_date=None):
    logger.debug("update_snapshot_cyverse task started at %s." % datetime.now())
    end_date = timezone.now().replace(microsecond=0) if not end_date else end_date

    for allocation_source in AllocationSource.objects.order_by('name'):
        # calculate and save snapshots here
        allocation_source_name = allocation_source.name
        last_renewal_event = EventTable.objects.filter(
            name='allocation_source_created_or_renewed',
            payload__allocation_source_name__exact=str(allocation_source_name)).order_by('timestamp')

        if not last_renewal_event:
            logger.info('Allocation Source %s Create/Renewal event missing', allocation_source_name)
            continue

        start_date = last_renewal_event.last().timestamp.replace(microsecond=0) if not start_date else start_date

        total_compute_used = 0
        total_burn_rate = 0
        for user in allocation_source.all_users:
            compute_used, burn_rate = total_usage(user.username, start_date=start_date,
                                                  end_date=end_date, allocation_source_name=allocation_source_name,
                                                  burn_rate=True)

            UserAllocationSnapshot.objects.update_or_create(allocation_source=allocation_source, user=user,
                                                            defaults={'compute_used': compute_used,
                                                                      'burn_rate': burn_rate})
            total_compute_used += compute_used
            total_burn_rate += burn_rate
        AllocationSourceSnapshot.objects.update_or_create(allocation_source=allocation_source,
                                                          defaults={'compute_used': total_compute_used,
                                                                    'global_burn_rate': total_burn_rate})

        run_all(rule_list=cyverse_rules,
                defined_variables=CyverseTestRenewalVariables(allocation_source, current_time=end_date,
                                                              last_renewal_event_date=start_date),
                defined_actions=CyverseTestRenewalActions(allocation_source, current_time=end_date))
    # At the end of the task, fire-off an allocation threshold check
    logger.debug("update_snapshot_cyverse task finished at %s." % datetime.now())
    allocation_threshold_check.apply_async()
Ejemplo n.º 17
0
def renewal_event_is_fired_twice(context):
    # after another 14 days , AllocationSourceSnapshot is updated.

    report_start_date = context.ts + timedelta(days=30)
    report_end_date = report_start_date + timedelta(days=43)
    query = EventTable.objects.filter(name='allocation_source_renewed',
                                      payload__name__exact='DefaultAllocationSource')
    assert len(query) == 1
    source_snapshot = AllocationSourceSnapshot.objects.filter(allocation_source=context.allocation_source_2).order_by(
        'updated').last()

    amit_usage = total_usage(context.amit.user.username, report_start_date,
                             allocation_source_name=context.allocation_source_2.name,
                             end_date=report_end_date)

    julian_usage = total_usage(context.julian.user.username, report_start_date,
                               allocation_source_name=context.allocation_source_2.name,
                               end_date=report_end_date)

    assert amit_usage == 120.0
    assert julian_usage == 96.0

    source_snapshot.compute_used = amit_usage + julian_usage
    source_snapshot.updated = context.ts + timedelta(days=43)
    source_snapshot.save()

    assert AllocationSourceSnapshot.objects.filter(allocation_source=context.allocation_source_2).order_by(
        'updated').last().compute_used == 216.0

    # rules engine is explicitly run

    current_time = context.ts + timedelta(days=44)
    run_all(rule_list=cyverse_rules,
            defined_variables=CyverseTestRenewalVariables(context.allocation_source_2, current_time),
            defined_actions=CyverseTestRenewalActions(context.allocation_source_2, current_time),
            )

    assert EventTable.objects.filter(name='allocation_source_renewed') == 2

    # after another 14 days , AllocationSourceSnapshot is updated.

    report_start_date = context.ts + timedelta(days=44)
    report_end_date = report_start_date + timedelta(days=57)
    query = EventTable.objects.filter(name='allocation_source_renewed',
                                      payload__name__exact='DefaultAllocationSource')

    source_snapshot = AllocationSourceSnapshot.objects.filter(allocation_source=context.allocation_source_2).order_by(
        'updated').last()

    amit_usage = total_usage(context.amit.user.username, report_start_date,
                             allocation_source_name=context.allocation_source_2.name,
                             end_date=report_end_date)

    julian_usage = total_usage(context.julian.user.username, report_start_date,
                               allocation_source_name=context.allocation_source_2.name,
                               end_date=report_end_date)

    assert amit_usage == 0.0
    assert julian_usage == 192.0

    source_snapshot.compute_used = amit_usage + julian_usage
    source_snapshot.updated = context.ts + timedelta(days=57)
    source_snapshot.save()

    assert AllocationSourceSnapshot.objects.filter(allocation_source=context.allocation_source_2).order_by(
        'updated').last().compute_used == 192.0

    # rules engine is explicitly run

    current_time = context.ts + timedelta(days=58)
    run_all(rule_list=cyverse_rules,
            defined_variables=CyverseTestRenewalVariables(context.allocation_source_2, current_time),
            defined_actions=CyverseTestRenewalActions(context.allocation_source_2, current_time),
            )

    assert EventTable.objects.filter(name='allocation_source_renewed') == 3
Ejemplo n.º 18
0
    def test_total_usage(self):

        ts = parse('2016-10-04T00:00+00:00')
        allocation_source = create_allocation_source(name='TestSource',
                                                     compute_allowed=1000,
                                                     timestamp=ts)

        # In this workflow the instance_allocation_source_changed event is
        # fired before any instance status history is created. Hence the
        # instance will report usage as 0.0 because it thinks the allocation
        # source is 'N/A'. A fix for this would be to decouple instance status
        # histories and events completely in the allocation logic.

        workflow1 = UserWorkflow()
        workflow1.assign_allocation_source_to_user(allocation_source,
                                                   timestamp=ts +
                                                   timedelta(minutes=10))
        instance = workflow1.create_instance(start_date=ts +
                                             timedelta(minutes=30))
        workflow1.create_instance_status_history(instance,
                                                 start_date=ts +
                                                 timedelta(days=30),
                                                 status='suspend')
        workflow1.assign_allocation_source_to_instance(allocation_source,
                                                       instance,
                                                       timestamp=ts +
                                                       timedelta(minutes=40))

        report_start_date = ts
        report_end_date = ts + timedelta(minutes=160)

        self.assertEqual(
            total_usage(workflow1.user.username,
                        report_start_date,
                        allocation_source_name=allocation_source.name,
                        end_date=report_end_date), 2.0)

        workflow2 = UserWorkflow()
        workflow2.assign_allocation_source_to_user(allocation_source,
                                                   timestamp=ts +
                                                   timedelta(minutes=10))
        instance = workflow2.create_instance(start_date=ts +
                                             timedelta(minutes=30))
        workflow2.assign_allocation_source_to_instance(allocation_source,
                                                       instance,
                                                       timestamp=ts +
                                                       timedelta(minutes=40))
        ish_start_date = ts + timedelta(minutes=120)
        workflow2.create_instance_status_history(instance,
                                                 start_date=ish_start_date,
                                                 status='suspended')

        report_start_date = ts
        report_end_date = ts + timedelta(minutes=120)

        self.assertEqual(
            total_usage(workflow2.user.username,
                        report_start_date,
                        allocation_source_name=allocation_source.name,
                        end_date=report_end_date), 1.33)

        # check total allocation usage so far
        end_date = ts + timedelta(days=30)
        update_snapshot_cyverse_allocation(ts, end_date)
        self.assertEqual(float(allocation_source.compute_used), 720.66)