コード例 #1
0
ファイル: instance.py プロジェクト: gbraad/ustack-gringotts
    def process_notification(self, message, state=None):
        LOG.warn("Do action for event: %s, resource_id: %s", message["event_type"], message["payload"]["instance_id"])

        # Generate uuid of an order
        order_id = uuidutils.generate_uuid()

        unit_price = 0
        unit = "hour"

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            # disk extension is used when instance been stopped and been suspend
            if ext.name.startswith("stopped"):
                sub = ext.obj.create_subscription(message, order_id, type=const.STATE_STOPPED)
                if sub and state == const.STATE_STOPPED:
                    p = gringutils._quantize_decimal(sub["unit_price"])
                    unit_price += p * sub["quantity"]
            elif ext.name.startswith("running"):
                sub = ext.obj.create_subscription(message, order_id, type=const.STATE_RUNNING)
                if sub and (not state or state == const.STATE_RUNNING):
                    p = gringutils._quantize_decimal(sub["unit_price"])
                    unit_price += p * sub["quantity"]

        # Create an order for this instance
        self.create_order(order_id, unit_price, unit, message, state=state)

        # Notify master
        remarks = "Instance Has Been Created."
        action_time = message["timestamp"]
        if state:
            self.resource_created_again(order_id, action_time, remarks)
            if state == const.STATE_STOPPED:
                self.instance_stopped(order_id, action_time)
        else:
            self.resource_created(order_id, action_time, remarks)
コード例 #2
0
ファイル: image.py プロジェクト: xiaolihope/gringotts
    def process_notification(self, message, state=None):
        LOG.warn('Do action for event: %s, resource_id: %s',
                 message['event_type'], message['payload']['id'])

        # Generate uuid of an order
        order_id = uuidutils.generate_uuid()

        unit_price = 0
        unit = 'hour'

        # Create subscriptions for this order
        for ext in self.product_items.extensions:
            if ext.name.startswith('suspend'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_SUSPEND)
                if sub and state==const.STATE_SUSPEND:
                    p = gringutils._quantize_decimal(sub['unit_price'])
                    unit_price += p * sub['quantity']
            elif ext.name.startswith('running'):
                sub = ext.obj.create_subscription(message, order_id,
                                                  type=const.STATE_RUNNING)
                if sub and (not state or state==const.STATE_RUNNING):
                    p = gringutils._quantize_decimal(sub['unit_price'])
                    unit_price += p * sub['quantity']

        # Create an order for this instance
        self.create_order(order_id, unit_price, unit, message, state=state)

        # Notify master
        remarks = 'Image Has Been Created.'
        action_time = message['timestamp']
        if state:
            self.resource_created_again(order_id, action_time, remarks)
        else:
            self.resource_created(order_id, action_time, remarks)
コード例 #3
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def estimate_per_day(self):
        """Get the price per day and the remaining days that the
        balance can support.
        """
        self.conn = pecan.request.db_conn
        user_id = acl.get_limited_to_user(
            request.headers, 'account_estimate') or self._id

        account = self._account(user_id=user_id)
        orders = self.conn.get_active_orders(request.context,
                                             user_id=user_id,
                                             within_one_hour=True,
                                             bill_methods=['hour'])
        price_per_day = gringutils._quantize_decimal(0)
        remaining_day = -1
        if not orders:
            return models.Estimate(price_per_day=price_per_day,
                                   remaining_day=remaining_day)

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return models.Estimate(price_per_day=price_per_day,
                                   remaining_day=remaining_day)

        price_per_day = price_per_hour * 24
        remaining_day = int(account.balance / price_per_day)

        return models.Estimate(price_per_day=price_per_day,
                               remaining_day=remaining_day)
コード例 #4
0
ファイル: account.py プロジェクト: zhaozhilong1993/gringotts
    def _estimate_per_day(self, user_id, balance):
        """Get the price per day and the remaining days that the
        balance can support.
        """
        self.conn = pecan.request.db_conn

        orders = self.conn.get_active_orders(request.context,
                                             user_id=user_id,
                                             within_one_hour=True,
                                             bill_methods=['hour'])
        price_per_day = gringutils._quantize_decimal(0)
        remaining_day = -1
        if not orders:
            return (price_per_day, remaining_day)

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return (price_per_day, remaining_day)

        price_per_day = price_per_hour * 24
        remaining_day = int(balance / price_per_day)

        return (price_per_day, remaining_day)
コード例 #5
0
ファイル: account.py プロジェクト: zhaozhilong1993/gringotts
    def estimate_per_day(self):
        """Get the price per day and the remaining days that the
        balance can support.
        """
        self.conn = pecan.request.db_conn
        user_id = acl.get_limited_to_user(request.headers,
                                          'account_estimate') or self._id

        account = self._account(user_id=user_id)
        orders = self.conn.get_active_orders(request.context,
                                             user_id=user_id,
                                             within_one_hour=True,
                                             bill_methods=['hour'])
        price_per_day = gringutils._quantize_decimal(0)
        remaining_day = -1
        if not orders:
            return models.Estimate(price_per_day=price_per_day,
                                   remaining_day=remaining_day)

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return models.Estimate(price_per_day=price_per_day,
                                   remaining_day=remaining_day)

        price_per_day = price_per_hour * 24
        remaining_day = int(account.balance / price_per_day)

        return models.Estimate(price_per_day=price_per_day,
                               remaining_day=remaining_day)
コード例 #6
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def _estimate_per_day(self, user_id, balance):
        """Get the price per day and the remaining days that the
        balance can support.
        """
        self.conn = pecan.request.db_conn

        orders = self.conn.get_active_orders(request.context,
                                             user_id=user_id,
                                             within_one_hour=True,
                                             bill_methods=['hour'])
        price_per_day = gringutils._quantize_decimal(0)
        remaining_day = -1
        if not orders:
            return (price_per_day, remaining_day)

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return (price_per_day, remaining_day)

        price_per_day = price_per_hour * 24
        remaining_day = int(balance / price_per_day)

        return (price_per_day, remaining_day)
コード例 #7
0
ファイル: order.py プロジェクト: zhaozhilong1993/gringotts
    def get(self, start_time=None, end_time=None, region_id=None):
        """Get summary of all kinds of orders
        """
        # bad hack
        if not request.context.is_admin and not project_id:
            summaries = []
            for order_type in ORDER_TYPE:
                summaries.append(
                    models.Summary.transform(
                        total_count=0,
                        order_type=order_type,
                        total_price=gringutils._quantize_decimal(0)))
            return models.Summaries.transform(
                total_price=gringutils._quantize_decimal(0),
                total_count=0,
                summaries=summaries)

        conn = pecan.request.db_conn

        # Get all orders of this particular context one time
        orders_db = list(
            conn.get_orders(request.context,
                            start_time=start_time,
                            end_time=end_time,
                            region_id=region_id))

        total_price = gringutils._quantize_decimal(0)
        total_count = 0
        summaries = []

        # loop all order types
        for order_type in ORDER_TYPE:

            order_total_price = gringutils._quantize_decimal(0)
            order_total_count = 0

            # One user's order records will not be very large, so we can
            # traverse them directly
            for order in orders_db:
                if order.type != order_type:
                    continue
                price, count = self._get_order_price_and_count(
                    order, start_time=start_time, end_time=end_time)
                order_total_price += price
                order_total_count += count

            summaries.append(
                models.Summary.transform(total_count=order_total_count,
                                         order_type=order_type,
                                         total_price=order_total_price))
            total_price += order_total_price
            total_count += order_total_count

        return models.Summaries.transform(total_price=total_price,
                                          total_count=total_count,
                                          summaries=summaries)
コード例 #8
0
ファイル: order.py プロジェクト: ShooterTT/gringotts
    def get(self, start_time=None, end_time=None, region_id=None):
        """Get summary of all kinds of orders
        """
        # bad hack
        if not request.context.is_admin and not project_id:
            summaries = []
            for order_type in ORDER_TYPE:
                summaries.append(models.Summary.transform(total_count=0,
                                                          order_type=order_type,
                                                          total_price=gringutils._quantize_decimal(0)))
            return models.Summaries.transform(total_price=gringutils._quantize_decimal(0),
                                              total_count=0,
                                              summaries=summaries)

        conn = pecan.request.db_conn

        # Get all orders of this particular context one time
        orders_db = list(conn.get_orders(request.context,
                                         start_time=start_time,
                                         end_time=end_time,
                                         region_id=region_id))

        total_price = gringutils._quantize_decimal(0)
        total_count = 0
        summaries = []

        # loop all order types
        for order_type in ORDER_TYPE:

            order_total_price = gringutils._quantize_decimal(0)
            order_total_count = 0

            # One user's order records will not be very large, so we can
            # traverse them directly
            for order in orders_db:
                if order.type != order_type:
                    continue
                price, count = self._get_order_price_and_count(order,
                                                               start_time=start_time,
                                                               end_time=end_time)
                order_total_price += price
                order_total_count += count

            summaries.append(models.Summary.transform(total_count=order_total_count,
                                                      order_type=order_type,
                                                      total_price=order_total_price))
            total_price += order_total_price
            total_count += order_total_count

        return models.Summaries.transform(total_price=total_price,
                                          total_count=total_count,
                                          summaries=summaries)
コード例 #9
0
ファイル: project.py プロジェクト: zhaozhilong1993/gringotts
    def estimate(self, region_id=None):
        """Get estimation of specified project and region."""
        limit_user_id = acl.get_limited_to_user(request.headers,
                                                'project_estimate')

        if limit_user_id:  # normal user
            projects = keystone.get_projects_by_user(limit_user_id)
            _project_ids = [project['id'] for project in projects]
            project_ids = [self._id] if self._id in _project_ids else []
        else:  # accountant
            project_ids = [self._id]

        # good way to go
        conn = pecan.request.db_conn

        # Get all orders of this particular context one time
        orders_db = list(
            conn.get_orders(request.context,
                            project_ids=project_ids,
                            region_id=region_id,
                            read_deleted=False,
                            bill_methods=['hour']))

        total_price = gringutils._quantize_decimal(0)
        total_count = 0
        summaries = []

        # loop all order types
        for order_type in const.ORDER_TYPE:

            order_total_price = gringutils._quantize_decimal(0)
            order_total_count = 0

            # One user's order records will not be very large, so we can
            # traverse them directly
            for order in orders_db:
                if order.type != order_type:
                    continue
                order_total_price += order.unit_price * 24
                order_total_count += 1

            summaries.append(
                models.Summary.transform(total_count=order_total_count,
                                         order_type=order_type,
                                         total_price=order_total_price))
            total_price += order_total_price
            total_count += order_total_count

        return models.Summaries.transform(total_price=total_price,
                                          total_count=total_count,
                                          summaries=summaries)
コード例 #10
0
ファイル: project.py プロジェクト: scorpioxiatian/gringotts
    def estimate(self, region_id=None):
        """Get estimation of specified project and region."""
        limit_user_id = acl.get_limited_to_user(request.headers,
                                                'project_estimate')

        if limit_user_id: # normal user
            projects = keystone.get_projects_by_user(limit_user_id)
            _project_ids = [project['id'] for project in projects]
            project_ids = [self._id] if self._id in _project_ids else []
        else: # accountant
            project_ids = [self._id]

        # good way to go
        conn = pecan.request.db_conn

        # Get all orders of this particular context one time
        orders_db = list(conn.get_orders(request.context,
                                         project_ids=project_ids,
                                         region_id=region_id,
                                         read_deleted=False,
                                         bill_methods=['hour']))

        total_price = gringutils._quantize_decimal(0)
        total_count = 0
        summaries = []

        # loop all order types
        for order_type in const.ORDER_TYPE:

            order_total_price = gringutils._quantize_decimal(0)
            order_total_count = 0

            # One user's order records will not be very large, so we can
            # traverse them directly
            for order in orders_db:
                if order.type != order_type:
                    continue
                order_total_price += order.unit_price * 24
                order_total_count += 1

            summaries.append(models.Summary.transform(total_count=order_total_count,
                                                      order_type=order_type,
                                                      total_price=order_total_price))
            total_price += order_total_price
            total_count += order_total_count

        return models.Summaries.transform(total_price=total_price,
                                          total_count=total_count,
                                          summaries=summaries)
コード例 #11
0
ファイル: deduct.py プロジェクト: zhaozhilong1993/gringotts
    def put(self, data):

        check_policy(request.context, "deduct:account_pay")

        if data.reqId == wsme.Unset or data.money == wsme.Unset or \
                data.accountNum == wsme.Unset or data.extData == wsme.Unset or \
                data.extData.order_id == wsme.Unset:
            raise exception.InvalidDeductParameter()

        data.money = gringutils._quantize_decimal(data.money)
        self.conn = pecan.request.db_conn

        try:
            deduct = self.conn.deduct_account(request.context, data.accountNum,
                                              **data.as_dict())
        except db_exc.DBDuplicateEntry:
            LOG.exception('Duplicated deduct req_id: %s' % data.reqId)
            raise exception.DuplicatedDeduct(req_id=data.reqId)
        except exception.NotAuthorized:
            LOG.exception('Fail to deduct the account: %s' % data.accountNum)
            raise exception.NotAuthorized()
        except Exception:
            msg = "Fail to deduct the account: %s, charge value: %s" % (
                data.accountNum, data.money)
            LOG.exception(msg)
            raise exception.DBError(reason=msg)

        pay = models.Pay(transactionNum=deduct.deduct_id,
                         money=deduct.money,
                         createDate=deduct.created_at)

        return models.PayResponse(code="0",
                                  total="1",
                                  message="OK",
                                  data=[pay])
コード例 #12
0
ファイル: deduct.py プロジェクト: ShooterTT/gringotts
    def put(self, data):

        check_policy(request.context, "deduct:account_pay")

        if data.reqId == wsme.Unset or data.money == wsme.Unset or \
                data.accountNum == wsme.Unset or data.extData == wsme.Unset or \
                data.extData.order_id == wsme.Unset:
            raise exception.InvalidDeductParameter()

        data.money = gringutils._quantize_decimal(data.money)
        self.conn = pecan.request.db_conn

        try:
            deduct = self.conn.deduct_account(request.context,
                                              data.accountNum,
                                              **data.as_dict())
        except db_exception.DBDuplicateEntry:
            LOG.exception('Duplicated deduct req_id: %s' % data.reqId)
            raise exception.DuplicatedDeduct(req_id=data.reqId)
        except exception.NotAuthorized as e:
            LOG.exception('Fail to deduct the account: %s' % data.accountNum)
            raise exception.NotAuthorized()
        except Exception as e:
            msg = "Fail to deduct the account: %s, charge value: %s" % (data.accountNum, data.money)
            LOG.exception(msg)
            raise exception.DBError(reason=msg)

        pay = models.Pay(transactionNum=deduct.deduct_id,
                         money=deduct.money,
                         createDate=deduct.created_at)

        return models.PayResponse(code="0", total="1", message="OK", data=[pay])
コード例 #13
0
    def charges(self, type=None, start_time=None,
                end_time=None, limit=None, offset=None):
        """Get this account's charge records."""

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        user_id = acl.get_limited_to_user(
            request.headers, 'account_charge') or self._id

        self.conn = pecan.request.db_conn
        charges = self.conn.get_charges(request.context,
                                        user_id=user_id,
                                        type=type,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time)
        charges_list = []
        for charge in charges:
            charges_list.append(models.Charge.from_db_model(charge))

        total_price, total_count = self.conn.get_charges_price_and_count(
            request.context, user_id=user_id, type=type,
            start_time=start_time, end_time=end_time)
        total_price = gringutils._quantize_decimal(total_price)

        return models.Charges.transform(total_price=total_price,
                                        total_count=total_count,
                                        charges=charges_list)
コード例 #14
0
ファイル: bill.py プロジェクト: ShooterTT/gringotts
    def get_all(self, start_time=None, end_time=None, type=None,
                project_id=None, limit=None, offset=None):

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        conn = pecan.request.db_conn

        bills_db = list(conn.get_bills(pecan.request.context,
                                       project_id=project_id,
                                       start_time=start_time,
                                       end_time=end_time,
                                       type=type,
                                       limit=limit,
                                       offset=offset))
        total_count, total_price = conn.get_bills_count_and_sum(
            pecan.request.context,
            project_id=project_id,
            start_time=start_time,
            end_time=end_time,
            type=type)

        total_price = gringutils._quantize_decimal(total_price)

        bills = []
        for bill in bills_db:
            bills.append(models.Bill.from_db_model(bill))

        return models.Bills.transform(total_price=total_price,
                                      total_count=total_count,
                                      bills=bills)
コード例 #15
0
ファイル: bill.py プロジェクト: unitedstack/gringotts
    def get_all(self, start_time=None, end_time=None, type=None, project_id=None, limit=None, offset=None):

        conn = pecan.request.db_conn

        bills_db = list(
            conn.get_bills(
                request.context,
                project_id=project_id,
                start_time=start_time,
                end_time=end_time,
                type=type,
                limit=limit,
                offset=offset,
            )
        )
        total_count, total_price = conn.get_bills_count_and_sum(
            request.context, project_id=project_id, start_time=start_time, end_time=end_time, type=type
        )

        total_price = gringutils._quantize_decimal(total_price)

        bills = []
        for bill in bills_db:
            bills.append(models.Bill.from_db_model(bill))

        return models.Bills.transform(total_price=total_price, total_count=total_count, bills=bills)
コード例 #16
0
    def estimate(self):
        self.conn = pecan.request.db_conn

        if not cfg.CONF.enable_owe:
            return -1

        account = self._account()
        if account.balance < 0:
            return -2

        orders = self.conn.get_active_orders(request.context,
                                             project_id=self._id,
                                             within_one_hour=True)
        if not orders:
            return -1

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return -1

        price_per_day = price_per_hour * 24
        days_to_owe_d = float(account.balance / price_per_day)
        days_to_owe = round(days_to_owe_d)
        if days_to_owe < days_to_owe_d:
            days_to_owe = days_to_owe + 1
        if days_to_owe > 7:
            return -1
        return days_to_owe
コード例 #17
0
    def get_all(self, start_time=None, end_time=None, type=None,
                project_id=None, limit=None, offset=None):

        conn = pecan.request.db_conn

        bills_db = list(conn.get_bills(request.context,
                                       project_id=project_id,
                                       start_time=start_time,
                                       end_time=end_time,
                                       type=type,
                                       limit=limit,
                                       offset=offset))
        total_count, total_price = conn.get_bills_count_and_sum(
            request.context,
            project_id=project_id,
            start_time=start_time,
            end_time=end_time,
            type=type)

        total_price=gringutils._quantize_decimal(total_price)

        bills = []
        for bill in bills_db:
            bills.append(models.Bill.from_db_model(bill))

        return models.Bills.transform(total_price=total_price,
                                      total_count=total_count,
                                      bills=bills)
コード例 #18
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def estimate(self):
        self.conn = pecan.request.db_conn

        if not cfg.CONF.enable_owe:
            return -1

        account = self._account()
        if account.balance < 0:
            return -2

        orders = self.conn.get_active_orders(request.context,
                                             project_id=self._id,
                                             within_one_hour=True)
        if not orders:
            return -1

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return -1

        price_per_day = price_per_hour * 24
        days_to_owe_d = float(account.balance / price_per_day)
        days_to_owe = round(days_to_owe_d)
        if days_to_owe < days_to_owe_d:
            days_to_owe = days_to_owe + 1
        if days_to_owe > 7:
            return -1
        return days_to_owe
コード例 #19
0
 def _check_resource_to_order(self, resource, resource_to_order,
                              bad_resources, try_to_fix):
     try:
         order = resource_to_order[resource.id]
     except KeyError:
         # Situation 1: There may exist resources that have no orders
         # NOTE(suo): The resource billed by month/year may also has no
         # order, but for now, we couldn't know which billing type it is
         # only from the GET resource method, on this occasion, we take
         # this resource as the hourly billing type, then create the order
         # in auto-fix process
         if resource.status == const.STATE_ERROR:
             bad_resources.append(resource)
             return
         if not resource.is_bill:
             return
         try_to_fix['1'].append(resource)
     else:
         # Situation 2: There may exist resource whose status doesn't match
         # with its order's
         if resource.status == const.STATE_ERROR:
             bad_resources.append(resource)
         elif order['unit'] in ['month', 'year']:
             # if the order is billed by month or year, we don't check
             # it for now, just pass, and set it to checked later
             pass
         elif (resource.resource_type == const.RESOURCE_LISTENER
               and resource.admin_state != order['status']):
             # for loadbalancer listener
             action_time = utils.format_datetime(timeutils.strtime())
             try_to_fix['2'].append(
                 Situation2Item(order['order_id'], resource.resource_type,
                                action_time, resource.admin_state,
                                resource.project_id))
         elif (resource.resource_type != const.RESOURCE_LISTENER
               and resource.status != order['status']):
             action_time = utils.format_datetime(timeutils.strtime())
             try_to_fix['2'].append(
                 Situation2Item(order['order_id'], resource.resource_type,
                                action_time, resource.status,
                                resource.project_id))
         # Situation 3: Resource's order has been created, but its bill not
         # be created by master
         elif (not order['cron_time']
               and order['status'] != const.STATE_STOPPED):
             try_to_fix['3'].append(
                 Situation3Item(order['order_id'], resource.created_at,
                                resource.project_id))
         # Situation 5: The order's unit_price is different from the
         # resource's actual price
         else:
             unit_price = (
                 self.RESOURCE_CREATE_MAP[resource.resource_type].\
                 get_unit_price(resource, 'hour'))
             order_unit_price = utils._quantize_decimal(order['unit_price'])
             if unit_price is not None and unit_price != order_unit_price:
                 try_to_fix['5'].append(
                     Situation5Item(order['order_id'], resource, unit_price,
                                    resource.project_id))
         resource_to_order[resource.id]['checked'] = True
コード例 #20
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def charges(self, type=None, start_time=None,
                end_time=None, limit=None, offset=None):
        """Get this account's charge records."""

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        user_id = acl.get_limited_to_user(
            request.headers, 'account_charge') or self._id

        self.conn = pecan.request.db_conn
        charges = self.conn.get_charges(request.context,
                                        user_id=user_id,
                                        type=type,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time)
        charges_list = []
        for charge in charges:
            charges_list.append(models.Charge.from_db_model(charge))

        total_price, total_count = self.conn.get_charges_price_and_count(
            request.context, user_id=user_id, type=type,
            start_time=start_time, end_time=end_time)
        total_price = gringutils._quantize_decimal(total_price)

        return models.Charges.transform(total_price=total_price,
                                        total_count=total_count,
                                        charges=charges_list)
コード例 #21
0
ファイル: order.py プロジェクト: scorpioxiatian/gringotts
    def get_all(self, type=None, status=None, start_time=None, end_time=None,
                limit=None, offset=None, resource_id=None, region_id=None,
                project_id=None, user_id=None, owed=None, bill_methods=None):
        """Get queried orders
        If start_time and end_time is not None, will get orders that have bills
        during start_time and end_time, or return all orders directly.
        """
        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        limit_user_id = acl.get_limited_to_user(
            request.headers, 'orders_get')

        if limit_user_id:  # normal user
            user_id = None
            projects = keystone.get_project_list(user=limit_user_id)
            _project_ids = [project.id for project in projects]
            if project_id:
                project_ids = ([project_id]
                               if project_id in _project_ids
                               else _project_ids)
            else:
                project_ids = _project_ids
        else:  # accountant
            if project_id:  # look up specified project
                project_ids = [project_id]
            else:  # look up all projects
                project_ids = None

        if project_ids:
            project_ids = list(set(project_ids) - set(cfg.CONF.ignore_tenants))

        conn = pecan.request.db_conn
        orders_db, total_count = conn.get_orders(request.context,
                                                 type=type,
                                                 status=status,
                                                 start_time=start_time,
                                                 end_time=end_time,
                                                 owed=owed,
                                                 limit=limit,
                                                 offset=offset,
                                                 with_count=True,
                                                 resource_id=resource_id,
                                                 bill_methods=bill_methods,
                                                 region_id=region_id,
                                                 user_id=user_id,
                                                 project_ids=project_ids)
        orders = []
        for order in orders_db:
            price = self._get_order_price(order,
                                          start_time=start_time,
                                          end_time=end_time)
            order.total_price = gringutils._quantize_decimal(price)
            orders.append(models.Order.from_db_model(order))

        return models.Orders.transform(total_count=total_count,
                                       orders=orders)
コード例 #22
0
ファイル: bill.py プロジェクト: unitedstack/gringotts
 def get_all(self, start_time=None, end_time=None, type=None, project_id=None):
     """Get all bills, filter by type, start time, and end time
     """
     conn = pecan.request.db_conn
     total_price = conn.get_bills_sum(
         request.context, project_id=project_id, start_time=start_time, end_time=end_time, type=type
     )
     return models.Bills.transform(total_price=gringutils._quantize_decimal(total_price))
コード例 #23
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def get(self, user_id=None, type=None, start_time=None,
            end_time=None, limit=None, offset=None,
            sort_key='created_at', sort_dir='desc'):
        """Get all charges of all account."""

        check_policy(request.context, "charges:all")

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        users = {}

        def _get_user(user_id):
            user = users.get(user_id)
            if user:
                return user
            contact = keystone.get_uos_user(user_id) or {}
            user_name = contact.get('name')
            email = contact.get('email')
            real_name = contact.get('real_name')
            mobile = contact.get('mobile_number')
            company = contact.get('company')
            users[user_id] = models.User(user_id=user_id,
                                         user_name=user_name,
                                         email=email,
                                         real_name=real_name,
                                         mobile=mobile,
                                         company=company)
            return users[user_id]

        self.conn = pecan.request.db_conn
        charges = self.conn.get_charges(request.context,
                                        user_id=user_id,
                                        type=type,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time,
                                        sort_key=sort_key,
                                        sort_dir=sort_dir)
        charges_list = []
        for charge in charges:
            acharge = models.Charge.from_db_model(charge)
            acharge.actor = _get_user(charge.operator)
            acharge.target = _get_user(charge.user_id)
            charges_list.append(acharge)

        total_price, total_count = self.conn.get_charges_price_and_count(
            request.context, user_id=user_id, type=type,
            start_time=start_time, end_time=end_time)
        total_price = gringutils._quantize_decimal(total_price)

        return models.Charges.transform(total_price=total_price,
                                        total_count=total_count,
                                        charges=charges_list)
コード例 #24
0
    def get(self, user_id=None, type=None, start_time=None,
            end_time=None, limit=None, offset=None,
            sort_key='created_at', sort_dir='desc'):
        """Get all charges of all account."""

        check_policy(request.context, "charges:all")

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        users = {}

        def _get_user(user_id):
            user = users.get(user_id)
            if user:
                return user
            contact = kunkka.get_uos_user(user_id) or {}
            user_name = contact.get('name')
            email = contact.get('email')
            real_name = contact.get('real_name')
            mobile = contact.get('phone')
            company = contact.get('company')
            users[user_id] = models.User(user_id=user_id,
                                         user_name=user_name,
                                         email=email,
                                         real_name=real_name,
                                         mobile=mobile,
                                         company=company)
            return users[user_id]

        self.conn = pecan.request.db_conn
        charges = self.conn.get_charges(request.context,
                                        user_id=user_id,
                                        type=type,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time,
                                        sort_key=sort_key,
                                        sort_dir=sort_dir)
        charges_list = []
        for charge in charges:
            acharge = models.Charge.from_db_model(charge)
            acharge.actor = _get_user(charge.operator)
            acharge.target = _get_user(charge.user_id)
            charges_list.append(acharge)

        total_price, total_count = self.conn.get_charges_price_and_count(
            request.context, user_id=user_id, type=type,
            start_time=start_time, end_time=end_time)
        total_price = gringutils._quantize_decimal(total_price)

        return models.Charges.transform(total_price=total_price,
                                        total_count=total_count,
                                        charges=charges_list)
コード例 #25
0
 def get_all(self, start_time=None, end_time=None, type=None,
             project_id=None):
     """Get all bills, filter by type, start time, and end time
     """
     conn = pecan.request.db_conn
     total_price = conn.get_bills_sum(request.context,
                                      project_id=project_id,
                                      start_time=start_time,
                                      end_time=end_time,
                                      type=type)
     return models.Bills.transform(
         total_price=gringutils._quantize_decimal(total_price))
コード例 #26
0
ファイル: project.py プロジェクト: gbraad/ustack-gringotts
 def get(self):
     self.conn = pecan.request.db_conn
     account = self.conn.get_billing_owner(request.context,
                                                   self.project_id)
     try:
         if cfg.CONF.external_billing.enable:
             external_balance = self.external_client.get_external_balance(
                 account.user_id)['data'][0]['money']
             account.balance = gringutils._quantize_decimal(
                 external_balance)
     except Exception:
         LOG.exception("Fail to get external balance of the account: %s" % \
             account.user_id)
     return models.UserAccount.from_db_model(account)
コード例 #27
0
ファイル: product.py プロジェクト: gbraad/ustack-gringotts
    def get_all(self, purchases=[]):
        """Get price of a group of products
        """
        conn = pecan.request.db_conn

        unit_price = 0
        hourly_price = 0
        unit = None

        for p in purchases:
            if p.product_name and p.service and p.region_id and p.quantity:
                filters = dict(name=p.product_name,
                               service=p.service,
                               region_id=p.region_id)
                try:
                    product = list(conn.get_products(request.context,
                                                     filters=filters))[0]
                    hourly_price += product.unit_price * p.quantity
                    unit_price += product.unit_price
                    unit = product.unit
                except Exception as e:
                    LOG.error('Product %s not found' % p.product_name)
                    # NOTE(suo): Even through fail to find the product, we should't
                    # raise Exception, emit the price to zero.
                    #raise exception.ProductNameNotFound(product_name=p.product_name)
            else:
                raise exception.MissingRequiredParams()

        unit_price = gringutils._quantize_decimal(unit_price)
        hourly_price = gringutils._quantize_decimal(hourly_price)
        monthly_price = gringutils._quantize_decimal(hourly_price * 24 * 30)

        return models.Price.transform(unit_price=unit_price,
                                      hourly_price=hourly_price,
                                      monthly_price=monthly_price,
                                      unit=unit)
コード例 #28
0
    def get_all(self, purchases=[]):
        """Get price of a group of products
        """
        conn = pecan.request.db_conn

        unit_price = 0
        hourly_price = 0
        unit = None

        for p in purchases:
            if p.product_name and p.service and p.region_id and p.quantity:
                filters = dict(name=p.product_name,
                               service=p.service,
                               region_id=p.region_id)
                try:
                    product = list(
                        conn.get_products(request.context, filters=filters))[0]
                    hourly_price += product.unit_price * p.quantity
                    unit_price += product.unit_price
                    unit = product.unit
                except Exception as e:
                    LOG.error('Product %s not found' % p.product_name)
                    # NOTE(suo): Even through fail to find the product, we should't
                    # raise Exception, emit the price to zero.
                    #raise exception.ProductNameNotFound(product_name=p.product_name)
            else:
                raise exception.MissingRequiredParams()

        unit_price = gringutils._quantize_decimal(unit_price)
        hourly_price = gringutils._quantize_decimal(hourly_price)
        monthly_price = gringutils._quantize_decimal(hourly_price * 24 * 30)

        return models.Price.transform(unit_price=unit_price,
                                      hourly_price=hourly_price,
                                      monthly_price=monthly_price,
                                      unit=unit)
コード例 #29
0
ファイル: project.py プロジェクト: zhaozhilong1993/gringotts
    def get(self):
        self.conn = pecan.request.db_conn
        try:
            account = self.conn.get_billing_owner(request.context,
                                                  self.project_id)
        except exception.AccountNotFound:
            return None

        try:
            if cfg.CONF.external_billing.enable:
                external_balance = self.external_client.get_external_balance(
                    account.user_id)['data'][0]['money']
                account.balance = gringutils._quantize_decimal(
                    external_balance)
        except Exception:
            LOG.exception("Fail to get external balance of the account: %s" % \
                account.user_id)
        return models.UserAccount.from_db_model(account)
コード例 #30
0
    def post(self, data):
        """Create a new product
        """
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(quantity=0,
                                           deleted=False,
                                           **data.as_dict())
        except Exception as e:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check if there are duplicated name in the same region
        filters = {
            'name': data.name,
            'service': data.service,
            'region_id': data.region_id
        }

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception as e:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        product.unit_price = gringutils._quantize_decimal(product.unit_price)

        # DB model to API model
        return models.Product.from_db_model(product)
コード例 #31
0
    def estimate_per_day(self):
        self.conn = pecan.request.db_conn

        account = self._account()
        orders = self.conn.get_active_orders(request.context,
                                             project_id=self._id,
                                             within_one_hour=True)
        if not orders:
            return 0

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return 0

        price_per_day = price_per_hour * 24
        return round(float(price_per_day), 4)
コード例 #32
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def estimate_per_day(self):
        self.conn = pecan.request.db_conn

        account = self._account()
        orders = self.conn.get_active_orders(request.context,
                                             project_id=self._id,
                                             within_one_hour=True)
        if not orders:
            return 0

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return 0

        price_per_day = price_per_hour * 24
        return round(float(price_per_day), 4)
コード例 #33
0
ファイル: product.py プロジェクト: gbraad/ustack-gringotts
    def post(self, data):
        """Create a new product
        """
        data.product_id = uuidutils.generate_uuid()
        conn = pecan.request.db_conn

        # API model to DB model
        try:
            product_in = db_models.Product(quantity=0,
                                           deleted=False,
                                           **data.as_dict())
        except Exception as e:
            error = 'Error while turning product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.MissingRequiredParams(reason=error)

        # Check if there are duplicated name in the same region
        filters = {'name': data.name,
                   'service': data.service,
                   'region_id': data.region_id}

        products = list(conn.get_products(request.context, filters=filters))

        if len(products) > 0:
            error = "Product with name(%s) within service(%s) already "\
                    "exists in region_id(%s)" % \
                    (data.name, data.service, data.region_id)
            LOG.warning(error)
            raise exception.DuplicatedProduct(reason=error)

        # Write product model to DB
        try:
            product = conn.create_product(request.context, product_in)
        except Exception as e:
            error = 'Error while creating product: %s' % data.as_dict()
            LOG.exception(error)
            raise exception.DBError(reason=error)

        product.unit_price = gringutils._quantize_decimal(product.unit_price)

        # DB model to API model
        return models.Product.from_db_model(product)
コード例 #34
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
 def _account(self, user_id=None):
     self.conn = pecan.request.db_conn
     _id = user_id or self._id
     try:
         account = self.conn.get_account(request.context, _id)
         if cfg.CONF.external_billing.enable:
             external_balance = self.external_client.get_external_balance(
                 _id)['data'][0]['money']
             external_balance = gringutils._quantize_decimal(
                 external_balance)
             account.balance = external_balance
     except exception.AccountNotFound:
         LOG.error("Account %s not found" % _id)
         raise
     except exception.GetExternalBalanceFailed:
         raise
     except (Exception):
         LOG.error("Fail to get account %s" % _id)
         raise exception.AccountGetFailed(user_id=_id)
     return account
コード例 #35
0
ファイル: account.py プロジェクト: zhaozhilong1993/gringotts
 def _account(self, user_id=None):
     self.conn = pecan.request.db_conn
     _id = user_id or self._id
     try:
         account = self.conn.get_account(request.context, _id)
         if cfg.CONF.external_billing.enable:
             external_balance = self.external_client.get_external_balance(
                 _id)['data'][0]['money']
             external_balance = gringutils._quantize_decimal(
                 external_balance)
             account.balance = external_balance
     except exception.AccountNotFound:
         LOG.error("Account %s not found" % _id)
         raise
     except exception.GetExternalBalanceFailed:
         raise
     except (Exception):
         LOG.error("Fail to get account %s" % _id)
         raise exception.AccountGetFailed(user_id=_id)
     return account
コード例 #36
0
ファイル: order.py プロジェクト: zhaozhilong1993/gringotts
    def get_all(self,
                type=None,
                status=None,
                start_time=None,
                end_time=None,
                limit=None,
                offset=None,
                region_id=None,
                project_id=None,
                owed=None):
        """Get queried orders
        If start_time and end_time is not None, will get orders that have bills
        during start_time and end_time, or return all orders directly.
        """
        # bad hack
        if not request.context.is_admin and not project_id:
            return models.Orders.transform(total_count=0, orders=[])

        conn = pecan.request.db_conn
        orders_db, total_count = conn.get_orders(request.context,
                                                 type=type,
                                                 status=status,
                                                 start_time=start_time,
                                                 end_time=end_time,
                                                 owed=owed,
                                                 limit=limit,
                                                 offset=offset,
                                                 with_count=True,
                                                 region_id=region_id,
                                                 project_id=project_id)
        orders = []
        for order in orders_db:
            price = self._get_order_price(order,
                                          start_time=start_time,
                                          end_time=end_time)

            order.total_price = gringutils._quantize_decimal(price)

            orders.append(models.Order.from_db_model(order))

        return models.Orders.transform(total_count=total_count, orders=orders)
コード例 #37
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def charges(self, start_time=None, end_time=None, limit=None, offset=None):
        """Return this account's charge records
        """
        self.conn = pecan.request.db_conn
        charges = self.conn.get_charges(request.context,
                                        project_id=self._id,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time)
        charges_list = []
        for charge in charges:
            charges_list.append(models.Charge.from_db_model(charge))

        total_price, total_count = self.conn.get_charges_price_and_count(
            request.context, project_id=self._id,
            start_time=start_time, end_time=end_time)
        total_price = gringutils._quantize_decimal(total_price)

        return models.Charges.transform(total_price=total_price,
                                        total_count=total_count,
                                        charges=charges_list)
コード例 #38
0
    def get_all(self,
                start_time=None,
                end_time=None,
                type=None,
                project_id=None,
                limit=None,
                offset=None):

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        conn = pecan.request.db_conn

        bills_db = list(
            conn.get_bills(pecan.request.context,
                           project_id=project_id,
                           start_time=start_time,
                           end_time=end_time,
                           type=type,
                           limit=limit,
                           offset=offset))
        total_count, total_price = conn.get_bills_count_and_sum(
            pecan.request.context,
            project_id=project_id,
            start_time=start_time,
            end_time=end_time,
            type=type)

        total_price = gringutils._quantize_decimal(total_price)

        bills = []
        for bill in bills_db:
            bills.append(models.Bill.from_db_model(bill))

        return models.Bills.transform(total_price=total_price,
                                      total_count=total_count,
                                      bills=bills)
コード例 #39
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def estimate(self):
        """Estimate the hourly billing resources how many days to owed.
        """
        self.conn = pecan.request.db_conn

        if not cfg.CONF.enable_owe:
            return -1

        user_id = acl.get_limited_to_user(
            request.headers, 'account_estimate') or self._id

        account = self._account(user_id=user_id)
        if account.balance < 0:
            return -2

        orders = self.conn.get_active_orders(request.context,
                                             user_id=user_id,
                                             within_one_hour=True,
                                             bill_methods=['hour'])
        if not orders:
            return -1

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return -1

        price_per_day = price_per_hour * 24
        days_to_owe_d = float(account.balance / price_per_day)
        days_to_owe = round(days_to_owe_d)
        if days_to_owe < days_to_owe_d:
            days_to_owe = days_to_owe + 1
        if days_to_owe > 7:
            return -1
        return days_to_owe
コード例 #40
0
ファイル: account.py プロジェクト: zhaozhilong1993/gringotts
    def estimate(self):
        """Estimate the hourly billing resources how many days to owed.
        """
        self.conn = pecan.request.db_conn

        if not cfg.CONF.enable_owe:
            return -1

        user_id = acl.get_limited_to_user(request.headers,
                                          'account_estimate') or self._id

        account = self._account(user_id=user_id)
        if account.balance < 0:
            return -2

        orders = self.conn.get_active_orders(request.context,
                                             user_id=user_id,
                                             within_one_hour=True,
                                             bill_methods=['hour'])
        if not orders:
            return -1

        price_per_hour = 0
        for order in orders:
            price_per_hour += gringutils._quantize_decimal(order.unit_price)

        if price_per_hour == 0:
            return -1

        price_per_day = price_per_hour * 24
        days_to_owe_d = float(account.balance / price_per_day)
        days_to_owe = round(days_to_owe_d)
        if days_to_owe < days_to_owe_d:
            days_to_owe = days_to_owe + 1
        if days_to_owe > 7:
            return -1
        return days_to_owe
コード例 #41
0
    def charges(self, start_time=None, end_time=None, limit=None, offset=None):
        """Return this account's charge records
        """
        self.conn = pecan.request.db_conn
        charges = self.conn.get_charges(request.context,
                                        project_id=self._id,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time)
        charges_list = []
        for charge in charges:
            charges_list.append(models.Charge.from_db_model(charge))

        total_price, total_count = self.conn.get_charges_price_and_count(
            request.context,
            project_id=self._id,
            start_time=start_time,
            end_time=end_time)
        total_price = gringutils._quantize_decimal(total_price)

        return models.Charges.transform(total_price=total_price,
                                        total_count=total_count,
                                        charges=charges_list)
コード例 #42
0
ファイル: order.py プロジェクト: ShooterTT/gringotts
    def get_all(self, type=None, status=None, start_time=None, end_time=None,
                limit=None, offset=None, region_id=None, project_id=None,
                owed=None):
        """Get queried orders
        If start_time and end_time is not None, will get orders that have bills
        during start_time and end_time, or return all orders directly.
        """
        # bad hack
        if not request.context.is_admin and not project_id:
            return models.Orders.transform(total_count=0,
                                           orders=[])

        conn = pecan.request.db_conn
        orders_db, total_count = conn.get_orders(request.context,
                                                 type=type,
                                                 status=status,
                                                 start_time=start_time,
                                                 end_time=end_time,
                                                 owed=owed,
                                                 limit=limit,
                                                 offset=offset,
                                                 with_count=True,
                                                 region_id=region_id,
                                                 project_id=project_id)
        orders = []
        for order in orders_db:
            price = self._get_order_price(order,
                                          start_time=start_time,
                                          end_time=end_time)

            order.total_price = gringutils._quantize_decimal(price)

            orders.append(models.Order.from_db_model(order))

        return models.Orders.transform(total_count=total_count,
                                       orders=orders)
コード例 #43
0
ファイル: core.py プロジェクト: ShooterTT/gringotts
 def quantize(self, value):
     return gring_utils._quantize_decimal(value)
コード例 #44
0
ファイル: account.py プロジェクト: zhaozhilong1993/gringotts
    def get_all(self,
                user_id=None,
                owed=None,
                limit=None,
                offset=None,
                sort_key='created_at',
                sort_dir='desc'):
        check_policy(request.context, "account:all")

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        self.conn = pecan.request.db_conn

        try:
            accounts = self.conn.get_accounts(request.context,
                                              user_id=user_id,
                                              owed=owed,
                                              limit=limit,
                                              offset=offset,
                                              sort_key=sort_key,
                                              sort_dir=sort_dir)
            count = self.conn.get_accounts_count(request.context,
                                                 owed=owed,
                                                 user_id=user_id)
            pecan.response.headers['X-Total-Count'] = str(count)
        except exception.NotAuthorized as e:
            LOG.exception('Failed to get all accounts')
            raise exception.NotAuthorized()
        except Exception as e:
            LOG.exception('Failed to get all accounts')
            raise exception.DBError(reason=e)

        results = []
        user_ids = []
        for account in accounts:
            user_ids.append(account.user_id)
            if account.sales_id:
                user_ids.append(account.sales_id)

            if cfg.CONF.external_billing.enable:
                try:
                    external_balance = \
                        self.external_client.get_external_balance(
                            account.user_id)['data'][0]['money']
                    external_balance = \
                        gringutils._quantize_decimal(
                            external_balance)
                    account.balance = external_balance
                except exception.GetExternalBalanceFailed:
                    msg = _('Fail to get %s\'s external balance' %
                            (account.user_id))
                    LOG.warn(msg)

            price_per_day, remaining_day = \
                self._estimate_per_day(account.user_id,
                                       account.balance)

            result = models.AdminAccountInDetail(
                user=None,
                user_id=account.user_id,
                salesperson=None,
                sales_id=account.sales_id,
                balance=account.balance,
                consumption=account.consumption,
                level=account.level,
                project_id=account.project_id,
                domain_id=account.domain_id,
                owed=owed,
                inviter=account.inviter,
                created_at=account.created_at,
                price_per_day=price_per_day,
                remaining_day=remaining_day)
            results.append(result)

        users = keystone.get_users_by_user_ids(user_ids)
        for result in results:
            user = users.get(result.user_id)
            salesperson = users.get(result.sales_id)
            if user:
                result.user = models.UserInDetail(**user)
            if salesperson:
                result.salesperson = models.UserInDetail(**salesperson)

        return models.AdminAccountsInDetail(total_count=count,
                                            accounts=results)
コード例 #45
0
ファイル: order.py プロジェクト: scorpioxiatian/gringotts
    def get(self, start_time=None, end_time=None, region_id=None,
            user_id=None, project_id=None, read_deleted=None):
        """Get summary of all kinds of orders."""
        limit_user_id = acl.get_limited_to_user(
            request.headers, 'order_summary')

        if limit_user_id:  # normal user
            user_id = None
            projects = keystone.get_projects_by_user(limit_user_id)
            _project_ids = [project['id'] for project in projects]
            if project_id:
                project_ids = ([project_id]
                               if project_id in _project_ids
                               else _project_ids)
            else:
                project_ids = _project_ids
        else:  # accountant
            if project_id:  # look up specified project
                project_ids = [project_id]
            else:  # look up all projects
                project_ids = []

        if project_ids:
            project_ids = list(set(project_ids) - set(cfg.CONF.ignore_tenants))

        # good way to go
        conn = pecan.request.db_conn

        if read_deleted:
            if read_deleted.lower() == 'true':
                read_deleted = True
            elif read_deleted.lower() == 'false':
                read_deleted = False
            else:
                read_deleted = True
        else:
            read_deleted = True

        # Get all orders of this particular context at one time
        orders_db = list(conn.get_orders(request.context,
                                         start_time=start_time,
                                         end_time=end_time,
                                         user_id=user_id,
                                         project_ids=project_ids,
                                         region_id=region_id,
                                         read_deleted=read_deleted))

        total_price = gringutils._quantize_decimal(0)
        total_count = 0
        summaries = []

        # loop all order types
        for order_type in const.ORDER_TYPE:

            order_total_price = gringutils._quantize_decimal(0)
            order_total_count = 0

            # One user's order records will not be very large, so we can
            # traverse them directly
            for order in orders_db:
                if order.type != order_type:
                    if (order.type == const.RESOURCE_FLOATINGIPSET
                            and order_type == const.RESOURCE_FLOATINGIP):
                        # floatingipset consumption belongs to floatingip
                        pass
                    else:
                        continue
                price, count = self._get_order_price_and_count(
                    order, start_time=start_time, end_time=end_time)
                order_total_price += price
                order_total_count += count

            summaries.append(models.Summary.transform(
                total_count=order_total_count,
                order_type=order_type,
                total_price=order_total_price)
            )
            total_price += order_total_price
            total_count += order_total_count

        return models.Summaries.transform(total_price=total_price,
                                          total_count=total_count,
                                          summaries=summaries)
コード例 #46
0
    def check_owed_hour_resources_and_notify(self):  # noqa
        """Check owed hour-billing resources and notify them

        Get owed accounts, send them sms/email notifications.
        """
        try:
            accounts = self._assigned_accounts()
        except Exception:
            LOG.exception("Fail to get assigned accounts")
            accounts = []
        LOG.warn("[%s] Notifying owed accounts, assigned accounts number: %s",
                 self.member_id, len(accounts))

        bill_methods = [
            'hour',
        ]

        for account in accounts:
            try:
                if not isinstance(account, dict):
                    account = account.as_dict()

                if account['level'] == 9:
                    continue

                if account['owed']:
                    orders = list(
                        self.gclient.get_active_orders(
                            user_id=account['user_id'],
                            owed=True,
                            bill_methods=bill_methods))
                    if not orders:
                        continue

                    contact = keystone.get_user(account['user_id']).to_dict()
                    _projects = self.gclient.get_projects(
                        user_id=account['user_id'], type='simple')

                    orders_dict = {}
                    for project in _projects:
                        orders_dict[project['project_id']] = []

                    for order in orders:
                        # check if the resource exists
                        resource = self.RESOURCE_GET_MAP[order['type']](
                            order['resource_id'],
                            region_name=order['region_id'])
                        if not resource:
                            # NOTE(chengkun): just warning if the resource not exists
                            LOG.warn(
                                "[%s] The resource(%s|%s) has been "
                                "deleted", self.member_id, order['type'],
                                order['resource_id'])
                            continue

                        order_d = {}
                        order_d['order_id'] = order['order_id']
                        order_d['region_id'] = order['region_id']
                        order_d['resource_id'] = order['resource_id']
                        order_d['resource_name'] = order['resource_name']
                        order_d['type'] = order['type']

                        if isinstance(order['date_time'], basestring):
                            order['date_time'] = timeutils.parse_strtime(
                                order['date_time'],
                                fmt=ISO8601_UTC_TIME_FORMAT)

                        now = datetime.datetime.utcnow()
                        reserved_days = (order['date_time'] - now).days
                        if reserved_days < 0:
                            LOG.warn(
                                "[%s] The order %s reserved_days is "
                                "less than 0", self.member_id,
                                order['order_id'])
                            reserved_days = 0
                        order_d['reserved_days'] = reserved_days

                        order_d['date_time'] = timeutils.strtime(
                            order['date_time'], fmt=ISO8601_UTC_TIME_FORMAT)

                        orders_dict[order['project_id']].append(order_d)

                    projects = []
                    for project in _projects:
                        if orders_dict[project['project_id']]:
                            adict = {}
                            adict['project_id'] = project['project_id']
                            adict['project_name'] = project['project_name']
                            adict['orders'] = (
                                orders_dict[project['project_id']])
                            projects.append(adict)

                    if not projects:
                        continue

                    reserved_days = utils.cal_reserved_days(account['level'])
                    account['reserved_days'] = reserved_days
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    self.notifier.notify_has_owed(self.ctxt,
                                                  account,
                                                  contact,
                                                  projects,
                                                  language=language)
                else:
                    orders = self.gclient.get_active_orders(
                        user_id=account['user_id'], bill_methods=bill_methods)
                    if not orders:
                        continue

                    _projects = self.gclient.get_projects(
                        user_id=account['user_id'], type='simple')

                    estimation = {}
                    for project in _projects:
                        estimation[project['project_id']] = 0

                    price_per_hour = 0
                    for order in orders:
                        # check if the resource exists
                        resource = self.RESOURCE_GET_MAP[order['type']](
                            order['resource_id'],
                            region_name=order['region_id'])
                        if not resource:
                            # just warning the resource not exists
                            LOG.warn(
                                "[%s] The resource(%s|%s) may has been "
                                "deleted", self.member_id, order['type'],
                                order['resource_id'])
                            continue

                        price_per_hour += utils._quantize_decimal(
                            order['unit_price'])
                        estimation[order['project_id']] += \
                            utils._quantize_decimal(order['unit_price'])

                    price_per_day = price_per_hour * 24
                    account_balance = utils._quantize_decimal(
                        account['balance'])

                    if price_per_day == 0:
                        continue

                    days_to_owe_d = float(account_balance / price_per_day)
                    days_to_owe = round(days_to_owe_d)

                    if days_to_owe > cfg.CONF.checker.days_to_owe:
                        continue

                    # caculate projects
                    projects = []
                    for project in _projects:
                        adict = {}
                        adict['project_id'] = project['project_id']
                        adict['project_name'] = project['project_name']
                        adict['estimation'] = str(
                            estimation[project['project_id']] * 24)
                        projects.append(adict)

                    if not projects:
                        continue

                    contact = keystone.get_uos_user(account['user_id'])
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    self.notifier.notify_before_owed(self.ctxt,
                                                     account,
                                                     contact,
                                                     projects,
                                                     str(price_per_day),
                                                     days_to_owe,
                                                     language=language)
            except Exception:
                LOG.exception(
                    "Some exceptions occurred when checking owed "
                    "account: %s", account['user_id'])
コード例 #47
0
ファイル: precharge.py プロジェクト: gbraad/ustack-gringotts
    def used(self):
        conn = pecan.request.db_conn
        user_id = pecan.request.context.user_id
        project_id = pecan.request.context.project_id

        key = str("gring-precharge-limit-%s" % project_id)
        cache = _get_cache()
        count = cache.get(key)

        max_count, lock_time = self._parse_limit_rule(cfg.CONF.precharge_limit_rule)

        if count is None:
            cache.set(key, str(max_count), lock_time)
            count = max_count

        price = utils._quantize_decimal('0')
        ret_code = 0

        if int(count) > 0:
            try:
                precharge = conn.use_precharge(pecan.request.context,
                                               self.code,
                                               user_id=user_id,
                                               project_id=project_id)
                price = precharge.price
            except exception.PreChargeNotFound:
                LOG.error('The precharge %s not found' % self.code)
                ret_code = 1
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except exception.PreChargeHasUsed:
                LOG.error('The precharge %s has been used' % self.code)
                ret_code = 2
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except exception.PreChargeHasExpired:
                LOG.error('The precharge %s has been expired' % self.code)
                ret_code = 3
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except Exception as e:
                LOG.error('Fail to use precharge(%s), for reason: %s' % (self.code, e))
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
                raise exception.PreChargeException()
            else:
                cache.set(key, str(max_count), lock_time)

        left_count = int(cache.get(key))

        if left_count == 0:
            ret_code = 4

        return models.PreChargeSimple.transform(price=price,
                                                ret_code=ret_code,
                                                left_count=left_count,
                                                lock_time=lock_time/60)
コード例 #48
0
ファイル: service.py プロジェクト: unitedstack/gringotts
 def _check_resource_to_order(self, resource, resource_to_order,
                              bad_resources, try_to_fix):
     try:
         order = resource_to_order[resource.id]
     except KeyError:
         # Situation 1: There may exist resources that have no orders
         # NOTE(suo): The resource billed by month/year may also has no
         # order, but for now, we couldn't know which billing type it is
         # only from the GET resource method, on this occasion, we take
         # this resource as the hourly billing type, then create the order
         # in auto-fix process
         if resource.status == const.STATE_ERROR:
             bad_resources.append(resource)
             return
         if not resource.is_bill:
             return
         try_to_fix['1'].append(resource)
     else:
         # Situation 2: There may exist resource whose status doesn't match
         # with its order's
         if resource.status == const.STATE_ERROR:
             bad_resources.append(resource)
         elif order['unit'] in ['month', 'year']:
             # if the order is billed by month or year, we don't check
             # it for now, just pass, and set it to checked later
             pass
         elif (resource.resource_type == const.RESOURCE_LISTENER and
               resource.admin_state != order['status']):
             # for loadbalancer listener
             action_time = utils.format_datetime(timeutils.strtime())
             try_to_fix['2'].append(Situation2Item(order['order_id'],
                                                   resource.resource_type,
                                                   action_time,
                                                   resource.admin_state,
                                                   resource.project_id))
         elif (resource.resource_type != const.RESOURCE_LISTENER and
               resource.status != order['status']):
             action_time = utils.format_datetime(timeutils.strtime())
             try_to_fix['2'].append(Situation2Item(order['order_id'],
                                                   resource.resource_type,
                                                   action_time,
                                                   resource.status,
                                                   resource.project_id))
         # Situation 3: Resource's order has been created, but its bill not
         # be created by master
         elif (not order['cron_time'] and
               order['status'] != const.STATE_STOPPED):
             try_to_fix['3'].append(Situation3Item(order['order_id'],
                                                   resource.created_at,
                                                   resource.project_id))
         # Situation 5: The order's unit_price is different from the
         # resource's actual price
         else:
             unit_price = (
                 self.RESOURCE_CREATE_MAP[resource.resource_type].\
                 get_unit_price(resource, 'hour'))
             order_unit_price = utils._quantize_decimal(order['unit_price'])
             if unit_price is not None and unit_price != order_unit_price:
                 try_to_fix['5'].append(Situation5Item(order['order_id'],
                                                       resource,
                                                       unit_price,
                                                       resource.project_id))
         resource_to_order[resource.id]['checked'] = True
コード例 #49
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def get_all(self, user_id=None, owed=None, limit=None, offset=None,
                sort_key='created_at', sort_dir='desc'):
        check_policy(request.context, "account:all")

        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        self.conn = pecan.request.db_conn

        try:
            accounts = self.conn.get_accounts(request.context,
                                              user_id=user_id,
                                              owed=owed,
                                              limit=limit,
                                              offset=offset,
                                              sort_key=sort_key,
                                              sort_dir=sort_dir)
            count = self.conn.get_accounts_count(request.context,
                                                 owed=owed,
                                                 user_id=user_id)
            pecan.response.headers['X-Total-Count'] = str(count)
        except exception.NotAuthorized as e:
            LOG.exception('Failed to get all accounts')
            raise exception.NotAuthorized()
        except Exception as e:
            LOG.exception('Failed to get all accounts')
            raise exception.DBError(reason=e)

        results = []
        user_ids = []
        for account in accounts:
            user_ids.append(account.user_id)
            if account.sales_id:
                user_ids.append(account.sales_id)

            if cfg.CONF.external_billing.enable:
                try:
                    external_balance = \
                        self.external_client.get_external_balance(
                            account.user_id)['data'][0]['money']
                    external_balance = \
                        gringutils._quantize_decimal(
                            external_balance)
                    account.balance = external_balance
                except exception.GetExternalBalanceFailed:
                    msg = _('Fail to get %s\'s external balance' %
                            (account.user_id))
                    LOG.warn(msg)

            price_per_day, remaining_day = \
                self._estimate_per_day(account.user_id,
                                       account.balance)

            result = models.AdminAccountInDetail(
                user=None,
                user_id=account.user_id,
                salesperson=None,
                sales_id=account.sales_id,
                balance=account.balance,
                consumption=account.consumption,
                level=account.level,
                project_id=account.project_id,
                domain_id=account.domain_id,
                owed=owed,
                inviter=account.inviter,
                created_at=account.created_at,
                price_per_day=price_per_day,
                remaining_day=remaining_day
            )
            results.append(result)

        users = keystone.get_users_by_user_ids(user_ids)
        for result in results:
            user = users.get(result.user_id)
            salesperson = users.get(result.sales_id)
            if user:
                result.user = models.UserInDetail(**user)
            if salesperson:
                result.salesperson = models.UserInDetail(**salesperson)

        return models.AdminAccountsInDetail(total_count=count,
                                            accounts=results)
コード例 #50
0
ファイル: order.py プロジェクト: zhaozhilong1993/gringotts
    def get_all(self,
                type=None,
                status=None,
                start_time=None,
                end_time=None,
                limit=None,
                offset=None,
                resource_id=None,
                region_id=None,
                project_id=None,
                user_id=None,
                owed=None,
                bill_methods=None):
        """Get queried orders
        If start_time and end_time is not None, will get orders that have bills
        during start_time and end_time, or return all orders directly.
        """
        if limit and limit < 0:
            raise exception.InvalidParameterValue(err="Invalid limit")
        if offset and offset < 0:
            raise exception.InvalidParameterValue(err="Invalid offset")

        limit_user_id = acl.get_limited_to_user(request.headers, 'orders_get')

        if limit_user_id:  # normal user
            user_id = None
            projects = keystone.get_project_list(user=limit_user_id)
            _project_ids = [project.id for project in projects]
            if project_id:
                project_ids = ([project_id]
                               if project_id in _project_ids else _project_ids)
            else:
                project_ids = _project_ids
        else:  # accountant
            if project_id:  # look up specified project
                project_ids = [project_id]
            else:  # look up all projects
                project_ids = None

        if project_ids:
            project_ids = list(set(project_ids) - set(cfg.CONF.ignore_tenants))

        conn = pecan.request.db_conn
        orders_db, total_count = conn.get_orders(request.context,
                                                 type=type,
                                                 status=status,
                                                 start_time=start_time,
                                                 end_time=end_time,
                                                 owed=owed,
                                                 limit=limit,
                                                 offset=offset,
                                                 with_count=True,
                                                 resource_id=resource_id,
                                                 bill_methods=bill_methods,
                                                 region_id=region_id,
                                                 user_id=user_id,
                                                 project_ids=project_ids)
        orders = []
        for order in orders_db:
            price = self._get_order_price(order,
                                          start_time=start_time,
                                          end_time=end_time)
            order.total_price = gringutils._quantize_decimal(price)
            orders.append(models.Order.from_db_model(order))

        return models.Orders.transform(total_count=total_count, orders=orders)
コード例 #51
0
    def used(self):
        conn = pecan.request.db_conn
        user_id = pecan.request.context.user_id
        project_id = pecan.request.context.project_id

        key = str("gring-precharge-limit-%s" % project_id)
        cache = _get_cache()
        count = cache.get(key)

        max_count, lock_time = self._parse_limit_rule(cfg.CONF.precharge_limit_rule)

        if count is None:
            cache.set(key, str(max_count), lock_time)
            count = max_count

        price = utils._quantize_decimal('0')
        ret_code = 0

        if int(count) > 0:
            try:
                precharge = conn.use_precharge(pecan.request.context,
                                               self.code,
                                               user_id=user_id,
                                               project_id=project_id)
                price = precharge.price
            except exception.PreChargeNotFound:
                LOG.error('The precharge %s not found' % self.code)
                ret_code = 1
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except exception.PreChargeHasUsed:
                LOG.error('The precharge %s has been used' % self.code)
                ret_code = 2
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except exception.PreChargeHasExpired:
                LOG.error('The precharge %s has been expired' % self.code)
                ret_code = 3
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except Exception as e:
                LOG.error('Fail to use precharge(%s), for reason: %s' % (self.code, e))
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
                raise exception.PreChargeException()
            else:
                cache.set(key, str(max_count), lock_time)

        left_count = int(cache.get(key))

        if left_count == 0:
            ret_code = 4

        return models.PreChargeSimple.transform(price=price,
                                                ret_code=ret_code,
                                                left_count=left_count,
                                                lock_time=lock_time/60)
コード例 #52
0
ファイル: bill.py プロジェクト: unitedstack/gringotts
    def get(self, today=None, type=None, region_id=None):
        """Get summary of all kinds of orders in the latest 12 month or 12 day

        :param today: Client's today wee hour
        :param type: month, day
        """
        conn = pecan.request.db_conn
        trends = []
        periods = []

        if not type:
            type = "month"
        if not today:
            now = datetime.datetime.utcnow()
            today = datetime.datetime(now.year, now.month, now.day)

        # The latest 12 months
        if type == "month":
            if calendar.monthrange(today.year, today.month)[1] == today.day:
                latest_start = today
            else:
                latest_start = today - datetime.timedelta(days=today.day)
            next_month_days = gringutils.next_month_days(latest_start.year, latest_start.month)
            latest_end = latest_start + datetime.timedelta(days=next_month_days)
            periods = [(latest_start, latest_end)]

            for i in range(11):
                last = periods[-1][0]
                last_days = calendar.monthrange(last.year, last.month)[1]
                start_month = last - datetime.timedelta(days=last_days)
                periods.append((start_month, last))
            LOG.debug("Latest 12 months: %s" % periods)
        # The latest 12 days
        elif type == "day":
            latest_end = today + datetime.timedelta(days=1)
            periods = [(today, latest_end)]

            for i in range(11):
                start_day = today - datetime.timedelta(days=i + 1)
                end_day = start_day + datetime.timedelta(days=1)
                periods.append((start_day, end_day))
            LOG.debug("Latest 12 days: %s" % periods)

        # NOTE(suo): The latest period will not read cache
        for i in range(12):
            read_cache = True
            if i == 0:
                read_cache = False
            bills_sum = self._get_bills_sum(
                request.context,
                conn,
                region_id=region_id,
                start_time=periods[i][0],
                end_time=periods[i][1],
                read_cache=read_cache,
            )
            bills_sum = gringutils._quantize_decimal(bills_sum)

            trends.insert(
                0, models.Trend.transform(start_time=periods[i][0], end_time=periods[i][-1], consumption=bills_sum)
            )

        return trends
コード例 #53
0
ファイル: account.py プロジェクト: gbraad/ustack-gringotts
    def put(self, data):
        """Charge the account."""
        check_policy(request.context, "account:charge")

        # check uos_bill_account_charge_limited charge value
        if "uos_bill_account_charge_limited" in request.context.roles:
            lscv = int(cfg.CONF.limited_support_charge_value)
            if data.value < -lscv or data.value > lscv:
                raise exception.InvalidChargeValue(value=data.value)
        else:  # check accountant charge value
            lacv = int(cfg.CONF.limited_accountant_charge_value)
            if data.value < -lacv or data.value > lacv:
                raise exception.InvalidChargeValue(value=data.value)

        remarks = data.remarks if data.remarks != wsme.Unset else None
        operator = request.context.user_id

        self.conn = pecan.request.db_conn

        try:
            charge, is_first_charge = self.conn.update_account(
                request.context, self._id, operator=operator,
                **data.as_dict())
            has_bonus = False
            if cfg.CONF.enable_bonus and data['type'] != 'bonus':
                value = gringutils.calculate_bonus(data['value'])
                if value > 0:
                    bonus, _ = self.conn.update_account(request.context,
                                                        self._id,
                                                        type='bonus',
                                                        value=value,
                                                        come_from='system',
                                                        operator=operator,
                                                        remarks=remarks)
                    has_bonus = True

            if cfg.CONF.enable_invitation and is_first_charge:
                _account = self._account()
                min_charge_value = gringutils._quantize_decimal(
                    cfg.CONF.min_charge_value)
                reward_value = gringutils._quantize_decimal(
                    cfg.CONF.reward_value)

                if _account.inviter \
                        and data.value >= min_charge_value \
                        and reward_value > 0:
                    self.conn.update_account(
                        request.context, _account.inviter, type='bonus',
                        value=reward_value, come_from='system',
                        operator=operator,
                        remarks="reward because of invitation",
                        invitee=self._id)
                    if cfg.CONF.notify_account_charged:
                        inviter = self.conn.get_account(
                            request.context, _account.inviter).as_dict()
                        contact = keystone.get_uos_user(inviter['user_id'])
                        self.notifier = notifier.NotifierService(
                            cfg.CONF.checker.notifier_level)
                        self.notifier.notify_account_charged(
                            request.context, inviter, contact,
                            'bonus', reward_value, bonus=0,
                            operator=operator,
                            operator_name=request.context.user_name,
                            remarks="reward because of invitation")
            self.conn.set_charged_orders(request.context, self._id)
        except exception.NotAuthorized as e:
            LOG.exception('Fail to charge the account:%s '
                          'due to not authorization' % self._id)
            raise exception.NotAuthorized()
        except Exception as e:
            LOG.exception('Fail to charge the account:%s, '
                          'charge value: %s' % (self._id, data.value))
            raise exception.DBError(reason=e)
        else:
            # Notifier account
            if cfg.CONF.notify_account_charged:
                account = self.conn.get_account(
                    request.context, self._id).as_dict()
                contact = keystone.get_uos_user(account['user_id'])
                country_code = contact.get("country_code") or "86"
                language = "en_US" if country_code != '86' else "zh_CN"
                self.notifier = notifier.NotifierService(
                    cfg.CONF.checker.notifier_level)
                self.notifier.notify_account_charged(
                    request.context, account, contact,
                    data['type'], charge.value,
                    bonus=bonus.value if has_bonus else 0,
                    operator=operator,
                    operator_name=request.context.user_name,
                    remarks=remarks, language=language)
        return models.Charge.from_db_model(charge)
コード例 #54
0
ファイル: service.py プロジェクト: unitedstack/gringotts
    def check_owed_hour_resources_and_notify(self):  # noqa
        """Check owed hour-billing resources and notify them

        Get owed accounts, send them sms/email notifications.
        """
        try:
            accounts = self._assigned_accounts()
        except Exception:
            LOG.exception("Fail to get assigned accounts")
            accounts = []
        LOG.warn("[%s] Notifying owed accounts, assigned accounts number: %s",
                 self.member_id, len(accounts))

        bill_methods=['hour',]

        for account in accounts:
            try:
                if not isinstance(account, dict):
                    account = account.as_dict()

                if account['level'] == 9:
                    continue

                if account['owed']:
                    orders = list(
                        self.gclient.get_active_orders(
                            user_id=account['user_id'],
                            owed=True,
                            bill_methods=bill_methods)
                    )
                    if not orders:
                        continue

                    contact = keystone.get_user(account['user_id']).to_dict()
                    _projects = self.gclient.get_projects(
                        user_id=account['user_id'],
                        type='simple')

                    orders_dict = {}
                    for project in _projects:
                        orders_dict[project['project_id']] = []

                    for order in orders:
                        # check if the resource exists
                        resource = self.RESOURCE_GET_MAP[order['type']](
                            order['resource_id'],
                            region_name=order['region_id'])
                        if not resource:
                            # NOTE(chengkun): just warning if the resource not exists
                            LOG.warn("[%s] The resource(%s|%s) has been "
                                     "deleted",
                                     self.member_id,
                                     order['type'], order['resource_id'])
                            continue

                        order_d = {}
                        order_d['order_id'] = order['order_id']
                        order_d['region_id'] = order['region_id']
                        order_d['resource_id'] = order['resource_id']
                        order_d['resource_name'] = order['resource_name']
                        order_d['type'] = order['type']

                        if isinstance(order['date_time'], basestring):
                            order['date_time'] = timeutils.parse_strtime(
                                order['date_time'],
                                fmt=ISO8601_UTC_TIME_FORMAT)

                        now = datetime.datetime.utcnow()
                        reserved_days = (order['date_time'] - now).days
                        if reserved_days < 0:
                            LOG.warn("[%s] The order %s reserved_days is "
                                     "less than 0",
                                     self.member_id, order['order_id'])
                            reserved_days = 0
                        order_d['reserved_days'] = reserved_days

                        order_d['date_time'] = timeutils.strtime(
                            order['date_time'],
                            fmt=ISO8601_UTC_TIME_FORMAT)

                        orders_dict[order['project_id']].append(order_d)

                    projects = []
                    for project in _projects:
                        if orders_dict[project['project_id']]:
                            adict = {}
                            adict['project_id'] = project['project_id']
                            adict['project_name'] = project['project_name']
                            adict['orders'] = (orders_dict[
                                               project['project_id']])
                            projects.append(adict)

                    if not projects:
                        continue

                    reserved_days = utils.cal_reserved_days(account['level'])
                    account['reserved_days'] = reserved_days
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    self.notifier.notify_has_owed(self.ctxt, account, contact,
                                                  projects, language=language)
                else:
                    orders = self.gclient.get_active_orders(
                        user_id=account['user_id'],
                        bill_methods=bill_methods)
                    if not orders:
                        continue

                    _projects = self.gclient.get_projects(
                        user_id=account['user_id'], type='simple')

                    estimation = {}
                    for project in _projects:
                        estimation[project['project_id']] = 0

                    price_per_hour = 0
                    for order in orders:
                        # check if the resource exists
                        resource = self.RESOURCE_GET_MAP[order['type']](
                            order['resource_id'],
                            region_name=order['region_id'])
                        if not resource:
                            # just warning the resource not exists
                            LOG.warn("[%s] The resource(%s|%s) may has been "
                                     "deleted",
                                     self.member_id, order['type'],
                                     order['resource_id'])
                            continue

                        price_per_hour += utils._quantize_decimal(
                            order['unit_price'])
                        estimation[order['project_id']] += \
                            utils._quantize_decimal(order['unit_price'])

                    price_per_day = price_per_hour * 24
                    account_balance = utils._quantize_decimal(
                        account['balance'])

                    if price_per_day == 0:
                        continue

                    days_to_owe_d = float(account_balance / price_per_day)
                    days_to_owe = round(days_to_owe_d)

                    if days_to_owe > cfg.CONF.checker.days_to_owe:
                        continue

                    # caculate projects
                    projects = []
                    for project in _projects:
                        adict = {}
                        adict['project_id'] = project['project_id']
                        adict['project_name'] = project['project_name']
                        adict['estimation'] = str(
                            estimation[project['project_id']] * 24)
                        projects.append(adict)

                    if not projects:
                        continue

                    contact = keystone.get_uos_user(account['user_id'])
                    country_code = contact.get("country_code") or "86"
                    language = "en_US" if country_code != '86' else "zh_CN"
                    self.notifier.notify_before_owed(self.ctxt, account,
                                                     contact, projects,
                                                     str(price_per_day),
                                                     days_to_owe,
                                                     language=language)
            except Exception:
                LOG.exception("Some exceptions occurred when checking owed "
                              "account: %s", account['user_id'])
コード例 #55
0
ファイル: precharge.py プロジェクト: scorpioxiatian/gringotts
    def used(self):
        conn = pecan.request.db_conn
        context = pecan.request.context
        user_id = context.user_id
        project_id = context.project_id
        user_name = context.user_name

        key = str("gring-precharge-limit-%s" % user_id)
        cache = _get_cache()
        count = cache.get(key)

        max_count, lock_time = \
            self._parse_limit_rule(cfg.CONF.precharge_limit_rule)

        if count is None:
            cache.set(key, str(max_count), lock_time)
            count = max_count

        price = utils._quantize_decimal('0')
        ret_code = 0

        if int(count) > 0:
            try:
                precharge = conn.use_precharge(context,
                                               self.code,
                                               user_id=user_id,
                                               project_id=project_id)
                price = precharge.price
            except exception.PreChargeNotFound:
                LOG.error('The precharge %s not found' % self.code)
                ret_code = 1
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except exception.PreChargeHasUsed:
                LOG.error('The precharge %s has been used' % self.code)
                ret_code = 2
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except exception.PreChargeHasExpired:
                LOG.error('The precharge %s has been expired' % self.code)
                ret_code = 3
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
            except Exception as e:
                LOG.error('Fail to use precharge(%s), for reason: %s' %
                          (self.code, e))
                try:
                    cache.decr(key)
                except AttributeError:
                    cache.incr(key, delta=-1)
                raise exception.PreChargeException()
            else:
                cache.set(key, str(max_count), lock_time)
                # Notifier account
                if cfg.CONF.notify_account_charged:
                    account = conn.get_account(context, user_id).as_dict()
                    contact = kunkka.get_uos_user(user_id)
                    self.notifier = notifier.NotifierService(
                        cfg.CONF.checker.notifier_level)
                    self.notifier.notify_account_charged(
                        context,
                        account,
                        contact,
                        'coupon',
                        price,
                        bonus=0,
                        operator=user_id,
                        operator_name=user_name,
                        remarks='coupon')
        left_count = int(cache.get(key))

        if left_count == 0:
            ret_code = 4

        return models.PreChargeSimple.transform(price=price,
                                                ret_code=ret_code,
                                                left_count=left_count,
                                                lock_time=lock_time / 60)
コード例 #56
0
ファイル: account.py プロジェクト: zhaozhilong1993/gringotts
    def put(self, data):
        """Charge the account."""
        check_policy(request.context, "account:charge")

        # check uos_bill_account_charge_limited charge value
        if "uos_bill_account_charge_limited" in request.context.roles:
            lscv = int(cfg.CONF.limited_support_charge_value)
            if data.value < -lscv or data.value > lscv:
                raise exception.InvalidChargeValue(value=data.value)
        else:  # check accountant charge value
            lacv = int(cfg.CONF.limited_accountant_charge_value)
            if data.value < -lacv or data.value > lacv:
                raise exception.InvalidChargeValue(value=data.value)

        remarks = data.remarks if data.remarks != wsme.Unset else None
        operator = request.context.user_id

        self.conn = pecan.request.db_conn

        try:
            charge, is_first_charge = self.conn.update_account(
                request.context, self._id, operator=operator, **data.as_dict())
            has_bonus = False
            if cfg.CONF.enable_bonus and data['type'] != 'bonus':
                value = gringutils.calculate_bonus(data['value'])
                if value > 0:
                    bonus, _ = self.conn.update_account(request.context,
                                                        self._id,
                                                        type='bonus',
                                                        value=value,
                                                        come_from='system',
                                                        operator=operator,
                                                        remarks=remarks)
                    has_bonus = True

            if cfg.CONF.enable_invitation and is_first_charge:
                _account = self._account()
                min_charge_value = gringutils._quantize_decimal(
                    cfg.CONF.min_charge_value)
                reward_value = gringutils._quantize_decimal(
                    cfg.CONF.reward_value)

                if _account.inviter \
                        and data.value >= min_charge_value \
                        and reward_value > 0:
                    self.conn.update_account(
                        request.context,
                        _account.inviter,
                        type='bonus',
                        value=reward_value,
                        come_from='system',
                        operator=operator,
                        remarks="reward because of invitation",
                        invitee=self._id)
                    if cfg.CONF.notify_account_charged:
                        inviter = self.conn.get_account(
                            request.context, _account.inviter).as_dict()
                        contact = keystone.get_uos_user(inviter['user_id'])
                        self.notifier = notifier.NotifierService(
                            cfg.CONF.checker.notifier_level)
                        self.notifier.notify_account_charged(
                            request.context,
                            inviter,
                            contact,
                            'bonus',
                            reward_value,
                            bonus=0,
                            operator=operator,
                            operator_name=request.context.user_name,
                            remarks="reward because of invitation")
            self.conn.set_charged_orders(request.context, self._id)
        except exception.NotAuthorized as e:
            LOG.exception('Fail to charge the account:%s '
                          'due to not authorization' % self._id)
            raise exception.NotAuthorized()
        except Exception as e:
            LOG.exception('Fail to charge the account:%s, '
                          'charge value: %s' % (self._id, data.value))
            raise exception.DBError(reason=e)
        else:
            # Notifier account
            if cfg.CONF.notify_account_charged:
                account = self.conn.get_account(request.context,
                                                self._id).as_dict()
                contact = keystone.get_uos_user(account['user_id'])
                country_code = contact.get("country_code") or "86"
                language = "en_US" if country_code != '86' else "zh_CN"
                self.notifier = notifier.NotifierService(
                    cfg.CONF.checker.notifier_level)
                self.notifier.notify_account_charged(
                    request.context,
                    account,
                    contact,
                    data['type'],
                    charge.value,
                    bonus=bonus.value if has_bonus else 0,
                    operator=operator,
                    operator_name=request.context.user_name,
                    remarks=remarks,
                    language=language)
        return models.Charge.from_db_model(charge)
コード例 #57
0
ファイル: order.py プロジェクト: zhaozhilong1993/gringotts
    def get(self,
            start_time=None,
            end_time=None,
            region_id=None,
            user_id=None,
            project_id=None,
            read_deleted=None):
        """Get summary of all kinds of orders."""
        limit_user_id = acl.get_limited_to_user(request.headers,
                                                'order_summary')

        if limit_user_id:  # normal user
            user_id = None
            projects = keystone.get_projects_by_user(limit_user_id)
            _project_ids = [project['id'] for project in projects]
            if project_id:
                project_ids = ([project_id]
                               if project_id in _project_ids else _project_ids)
            else:
                project_ids = _project_ids
        else:  # accountant
            if project_id:  # look up specified project
                project_ids = [project_id]
            else:  # look up all projects
                project_ids = []

        if project_ids:
            project_ids = list(set(project_ids) - set(cfg.CONF.ignore_tenants))

        # good way to go
        conn = pecan.request.db_conn

        if read_deleted:
            if read_deleted.lower() == 'true':
                read_deleted = True
            elif read_deleted.lower() == 'false':
                read_deleted = False
            else:
                read_deleted = True
        else:
            read_deleted = True

        # Get all orders of this particular context at one time
        orders_db = list(
            conn.get_orders(request.context,
                            start_time=start_time,
                            end_time=end_time,
                            user_id=user_id,
                            project_ids=project_ids,
                            region_id=region_id,
                            read_deleted=read_deleted))

        total_price = gringutils._quantize_decimal(0)
        total_count = 0
        summaries = []

        # loop all order types
        for order_type in const.ORDER_TYPE:

            order_total_price = gringutils._quantize_decimal(0)
            order_total_count = 0

            # One user's order records will not be very large, so we can
            # traverse them directly
            for order in orders_db:
                if order.type != order_type:
                    if (order.type == const.RESOURCE_FLOATINGIPSET
                            and order_type == const.RESOURCE_FLOATINGIP):
                        # floatingipset consumption belongs to floatingip
                        pass
                    else:
                        continue
                price, count = self._get_order_price_and_count(
                    order, start_time=start_time, end_time=end_time)
                order_total_price += price
                order_total_count += count

            summaries.append(
                models.Summary.transform(total_count=order_total_count,
                                         order_type=order_type,
                                         total_price=order_total_price))
            total_price += order_total_price
            total_count += order_total_count

        return models.Summaries.transform(total_price=total_price,
                                          total_count=total_count,
                                          summaries=summaries)
コード例 #58
0
    def get(self,
            today=None,
            type=None,
            user_id=None,
            project_id=None,
            region_id=None):
        """Get summary of all kinds of orders in the latest 12 month or 12 day

        :param today: Client's today wee hour
        :param type: month, day
        """
        limit_user_id = acl.get_limited_to_user(pecan.request.headers,
                                                'trends_get')
        if limit_user_id:
            user_id = limit_user_id
        # accountant can look up any user, if not sepcify, look up itself
        elif not user_id:
            user_id = pecan.request.context.user_id

        conn = pecan.request.db_conn
        trends = []
        periods = []

        if not type:
            type = 'month'
        if not today:
            now = datetime.datetime.utcnow()
            today = datetime.datetime(now.year, now.month, now.day)

        # The latest 12 months
        if type == 'month':
            if calendar.monthrange(today.year, today.month)[1] == today.day:
                latest_start = today
            else:
                latest_start = today - datetime.timedelta(days=today.day)
            next_month_days = gringutils.next_month_days(
                latest_start.year, latest_start.month)
            latest_end = latest_start + datetime.timedelta(
                days=next_month_days)
            periods = [(latest_start, latest_end)]

            for i in range(11):
                last = periods[-1][0]
                last_days = calendar.monthrange(last.year, last.month)[1]
                start_month = last - datetime.timedelta(days=last_days)
                periods.append((start_month, last))
            LOG.debug('Latest 12 months: %s' % periods)
        # The latest 12 days
        elif type == 'day':
            latest_end = today + datetime.timedelta(days=1)
            periods = [(today, latest_end)]

            for i in range(11):
                start_day = today - datetime.timedelta(days=i + 1)
                end_day = start_day + datetime.timedelta(days=1)
                periods.append((start_day, end_day))
            LOG.debug('Latest 12 days: %s' % periods)

        # NOTE(suo): The latest period will not read cache
        for i in range(12):
            read_cache = True
            if i == 0:
                read_cache = False
            bills_sum = self._get_bills_sum(pecan.request.context,
                                            conn,
                                            user_id=user_id,
                                            project_id=project_id,
                                            region_id=region_id,
                                            start_time=periods[i][0],
                                            end_time=periods[i][1],
                                            read_cache=read_cache)
            bills_sum = gringutils._quantize_decimal(bills_sum)

            trends.insert(
                0,
                models.Trend.transform(start_time=periods[i][0],
                                       end_time=periods[i][-1],
                                       consumption=bills_sum))

        return trends