Exemplo n.º 1
0
 def filters(self, **kwargs):
     # type: (Dict[str, Any]) -> Dict[str, Any]
     query = Query()
     if self.limit:
         query = query.limit(self.limit)
     for key, val in kwargs.items():
         if isinstance(val, (list, tuple)):
             query = query.in_(key, val)
         else:
             query = query.equal(key, val)
     return query
Exemplo n.º 2
0
    def process_request(self, request):
        """Generate UsageFile for each active Asset"""

        # store each processed request for debug
        self.usages.append(request)

        today = datetime.utcnow() - timedelta(minutes=10)
        name_format = 'Report for {asset} {date}'

        project = self.get_project(request)
        if not project:
            return

        stop_report_time = self.get_stop_report_time(request, project)
        start_report_time = self.get_start_report_time(request, project)
        self.logger.info("Start report time: %s, stop report time: %s",
                         start_report_time, stop_report_time)
        if request.status in ['suspended', 'terminated'
                              ] and not stop_report_time:
            self.logger.info(
                "%s-%s: asset usage reporting was stopped without stop report time label",
                request.id, project.id)
            return

        last_report_time, confirmed = self.get_last_report_time(
            request, project)
        report_time = last_report_time + timedelta(days=1)
        report_time = report_time.replace(hour=0,
                                          minute=0,
                                          second=0,
                                          microsecond=0)
        self.logger.info(
            "Last report time: %s, report time: %s, confirmed: %s",
            last_report_time, report_time, confirmed)

        if self.project_id is not None and self.project_id != project.id:
            self.logger.info(
                "project_id=%s is not the same as project.id=%s, skip it",
                self.project_id, project.id)
            return

        # check that previous report has passed validation
        if confirmed is False:
            usage_files = UsageFileAutomation()
            try:
                report_date = last_report_time.strftime('%Y-%m-%d')
                report_name = name_format.format(asset=request.id,
                                                 date=report_date)

                filters = Query().equal('name', report_name).limit(10)
                if self.config.products:
                    filters.in_('product_id', self.config.products)
                found = usage_files.list(filters)

                found = [f for f in found or [] if f.status != 'deleted']
                self.logger.debug("Found usage files: %s", found)

                if found:
                    if len(found) > 2:
                        raise Exception("Found multiple reports with name %s" %
                                        report_name)

                    report = found[0]

                    if report.status in ('processing', 'draft', 'uploading'):
                        self.logger.info(
                            "%s-%s: usage report '%s' is being processed",
                            request.id, project.id, report_name)
                        return

                    if report.status in ('invalid', 'rejected'):
                        # we have to wait when user remove invalid report
                        self.logger.error(
                            "%s-%s: failed usage report '%s' found",
                            request.id, project.id, report_name)
                        return

                    self.update_last_report_time(project,
                                                 last_report_time,
                                                 confirmed=True)
                else:
                    report_time = last_report_time

            except ServerError:
                # this section is useless but left for future development
                raise

        if request.status in ['suspended', 'terminated']:
            if stop_report_time and last_report_time < stop_report_time <= report_time:
                self.logger.info("%s-%s: sending last report (%s)", request.id,
                                 project.id, request.status)
                report_time = stop_report_time

        if start_report_time and last_report_time < start_report_time < report_time:
            last_report_time = start_report_time

        if report_time > today and self.project_id is None:
            self.logger.info("%s-%s: usage is already reported", request.id,
                             project.id)
            return

        usage_file = UsageFile(
            name=name_format.format(asset=request.id,
                                    date=report_time.strftime('%Y-%m-%d')),
            product=Product(id=request.product.id),
            contract=Contract(id=request.contract.id),
            description=name_format.format(
                asset=request.id, date=report_time.strftime('%Y-%m-%d')),
        )

        # report for each day since last report date
        self.logger.info("%s-%s: creating report from %s to %s", request.id,
                         project.id, last_report_time, report_time)
        items = {item.mpn: item for item in request.items}
        usage_records = self.collect_usage_records(items, project,
                                                   last_report_time,
                                                   report_time)
        self.submit_usage(usage_file=usage_file, usage_records=usage_records)

        if report_time > today:
            # when project id is specified we allow to send usage for today
            # but don't update last report time
            return

        self.update_last_report_time(project, report_time)