예제 #1
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)
예제 #2
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)
예제 #3
0
    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
    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)
예제 #5
0
    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)
예제 #6
0
 def get_all(self, order_id=None, type=None, product_id=None):
     user_id = acl.get_limited_to_user(request.headers, 'subs:all')
     conn = pecan.request.db_conn
     subs = conn.get_subscriptions_by_order_id(request.context, order_id,
                                               user_id=user_id,
                                               type=type,
                                               product_id=product_id)
     return [models.Subscription.from_db_model(s) for s in subs]
예제 #7
0
 def get_all(self, order_id=None, type=None, product_id=None):
     user_id = acl.get_limited_to_user(request.headers, 'subs:all')
     conn = pecan.request.db_conn
     subs = conn.get_subscriptions_by_order_id(request.context,
                                               order_id,
                                               user_id=user_id,
                                               type=type,
                                               product_id=product_id)
     return [models.Subscription.from_db_model(s) for s in subs]
예제 #8
0
    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)
예제 #9
0
    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
    def invitees(self, limit=None, offset=None):
        """Get invitees of the inviter."""

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

        inviter = acl.get_limited_to_user(request.headers,
                                          'referees_get') or self._id

        self.conn = pecan.request.db_conn
        try:
            _invitees, total_count = self.conn.get_invitees(request.context,
                                                            inviter,
                                                            limit=limit,
                                                            offset=offset)
        except Exception as e:
            LOG.exception('Fail to get invitees')
            raise exception.DBError(reason=e)

        invitees = []
        for invitee in _invitees:
            user = keystone.get_uos_user(invitee.user_id)
            if user:
                user_name = user.get('real_name') or user['email'].split(
                    '@')[0]
                user_email = user['email']
            else:
                user_name = ""
                user_email = ""
            invitees.append(
                models.Invitee(user_id=invitee.user_id,
                               user_name=user_name,
                               user_email=user_email,
                               created_at=invitee.created_at,
                               charged=invitee.charged,
                               reward_value=invitee.reward_value))
        return models.Invitees(total_count=total_count, invitees=invitees)
예제 #11
0
    def invitees(self, limit=None, offset=None):
        """Get invitees of the inviter."""

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

        inviter = acl.get_limited_to_user(
            request.headers, 'referees_get') or self._id

        self.conn = pecan.request.db_conn
        try:
            _invitees, total_count = self.conn.get_invitees(request.context,
                                                            inviter,
                                                            limit=limit,
                                                            offset=offset)
        except Exception as e:
            LOG.exception('Fail to get invitees')
            raise exception.DBError(reason=e)

        invitees = []
        for invitee in _invitees:
            user = keystone.get_uos_user(invitee.user_id)
            if user:
                user_name = user.get(
                    'real_name') or user['email'].split('@')[0]
                user_email = user['email']
            else:
                user_name = ""
                user_email = ""
            invitees.append(models.Invitee(user_id=invitee.user_id,
                                           user_name=user_name,
                                           user_email=user_email,
                                           created_at=invitee.created_at,
                                           charged=invitee.charged,
                                           reward_value=invitee.reward_value))
        return models.Invitees(total_count=total_count,
                               invitees=invitees)
예제 #12
0
    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
예제 #13
0
    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
예제 #14
0
    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)
예제 #15
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
예제 #16
0
 def get(self):
     """Get this account."""
     user_id = acl.get_limited_to_user(
         request.headers, 'account_get') or self._id
     return models.UserAccount.from_db_model(self._account(user_id=user_id))
예제 #17
0
 def get(self):
     """Get this account."""
     user_id = acl.get_limited_to_user(request.headers,
                                       'account_get') or self._id
     return models.UserAccount.from_db_model(self._account(user_id=user_id))
예제 #18
0
    def get_all(self, output_format='xlsx', type=None, status=None,
                start_time=None, end_time=None, limit=None, offset=None,
                region_id=None, project_id=None, user_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.
        """
        limit_user_id = acl.get_limited_to_user(request.headers,
                                                'export_orders')

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

        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 and project_id in _project_ids:
                project_ids = [project_id]
            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))

        users = {}
        projects = {}

        def _get_user(user_id):
            user = users.get(user_id)
            if user:
                return user
            contact = keystone.get_uos_user(user_id)
            user_name = contact['name'] if contact else None
            users[user_id] = models.User(user_id=user_id,
                                         user_name=user_name)
            return users[user_id]

        def _get_project(project_id):
            project = projects.get(project_id)
            if project:
                return project
            project = keystone.get_project(project_id)
            project_name = project.name if project else None
            projects[project_id] = models.SimpleProject(
                project_id=project_id,
                project_name=project_name
            )
            return projects[project_id]

        MAP = [
            {"running": u"运行中",
             "stopped": u"暂停中",
             "deleted": u"被删除"},
            {"instance": u"虚拟机",
             "image": u"镜像",
             "snapshot": u"硬盘快照",
             "volume": u"云硬盘",
             "share": u"共享文件",
             "floatingip": u"公网IP",
             "listener": u"负载均衡监听器",
             "router": u"路由器",
             "alarm": u"监控报警"},
        ]

        headers = (u"资源ID", u"资源名称", u"资源类型",
                   u"资源状态", u"单价(元/小时)", u"金额(元)",
                   u"区域", u"用户ID", u"用户名称", u"项目ID",
                   u"项目名称", u"创建时间")
        data = []

        adata = (u"过滤条件: 资源类型: %s, 资源状态: %s,用户ID: %s, 项目ID: %s, 区域: %s, 起始时间: %s,  结束时间: %s" %
                 (type, status, user_id, project_id, region_id, start_time, end_time),
                 "", "", "", "", "", "", "", "", "", "", "")
        data.append(adata)

        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,
                                                 user_id=user_id,
                                                 project_ids=project_ids)
        for order in orders_db:
            price = self._get_order_price(order,
                                          start_time=start_time,
                                          end_time=end_time)
            user = _get_user(order.user_id)
            project = _get_project(order.project_id)
            order.created_at += datetime.timedelta(hours=8)
            created_at = \
                timeutils.strtime(order.created_at, fmt=OUTPUT_TIME_FORMAT)
            adata = (order.resource_id, order.resource_name,
                     MAP[1][order.type], MAP[0][order.status],
                     order.unit_price, price, order.region_id,
                     user.user_id, user.user_name,
                     project.project_id, project.project_name,
                     created_at)
            data.append(adata)

        data = tablib.Dataset(*data, headers=headers)

        response.content_type = "application/binary; charset=UTF-8"
        response.content_disposition = \
            "attachment; filename=orders.%s" % output_format
        content = getattr(data, output_format)
        if output_format == 'csv':
            content = content.decode("utf-8").encode("gb2312")
        response.write(content)
        return response
예제 #19
0
    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)
예제 #20
0
    def get_all(self, user_id=None, type=None, duration=None):
        """Get all projects."""
        user_id = acl.get_limited_to_user(request.headers,
                                          'projects_get') or user_id
        self.conn = pecan.request.db_conn
        result = []

        if not type or type.lower() == 'pay':
            # if admin call this api, limit to admin's user_id
            if not user_id:
                user_id = request.context.user_id

            try:
                user_projects = self.conn.get_user_projects(request.context,
                                                            user_id=user_id)
            except Exception as e:
                LOG.exception('Fail to get all projects')
                raise exception.DBError(reason=e)

            project_ids = [up.project_id for up in user_projects]

            if not project_ids:
                LOG.warn('User %s has no payed projects' % user_id)
                return []

            projects = self._list_keystone_projects()

            for u, p in itertools.product(user_projects, projects):
                if u.project_id == p['id']:
                    billing_owner = p['users']['billing_owner']
                    project_owner = p['users']['project_owner']
                    project_creator = p['users']['project_creator']
                    up = models.UserProject(
                        user_id=user_id,
                        project_id=u.project_id,
                        project_name=p['name'],
                        user_consumption=u.user_consumption,
                        project_consumption=u.project_consumption,
                        billing_owner=dict(user_id=billing_owner.get('id')
                                           if billing_owner else None,
                                           user_name=billing_owner.get('name')
                                           if billing_owner else None),
                        project_owner=dict(user_id=project_owner.get('id')
                                           if project_owner else None,
                                           user_name=project_owner.get('name')
                                           if project_owner else None),
                        project_creator=dict(
                            user_id=project_creator.get('id')
                            if project_creator else None,
                            user_name=project_creator.get('name')
                            if project_creator else None),
                        is_historical=u.is_historical,
                        created_at=timeutils.parse_isotime(p['created_at'])
                        if p['created_at'] else None)
                    result.append(up)
        elif type.lower() == 'all':
            # if admin call this api, limit to admin's user_id
            if not user_id:
                user_id = request.context.user_id

            k_projects = keystone.get_project_list(name=user_id)
            project_ids = [p['id'] for p in k_projects]

            if not project_ids:
                LOG.warn('User %s has no projects' % user_id)
                return []

            try:
                g_projects = self.conn.get_projects_by_project_ids(
                    request.context, project_ids)
            except Exception as e:
                LOG.exception('Fail to get all projects')
                raise exception.DBError(reason=e)
            for k, g in itertools.product(k_projects, g_projects):
                if k['id'] == g.project_id:
                    billing_owner = k['users']['billing_owner']
                    project_owner = k['users']['project_owner']
                    project_creator = k['users']['project_creator']
                    up = models.UserProject(
                        user_id=user_id,
                        project_id=g.project_id,
                        project_name=k['name'],
                        project_consumption=g.consumption,
                        billing_owner=dict(user_id=billing_owner.get('id')
                                           if billing_owner else None,
                                           user_name=billing_owner.get('name')
                                           if billing_owner else None),
                        project_owner=dict(user_id=project_owner.get('id')
                                           if project_owner else None,
                                           user_name=project_owner.get('name')
                                           if project_owner else None),
                        project_creator=dict(
                            user_id=project_creator.get('id')
                            if project_creator else None,
                            user_name=project_creator.get('name')
                            if project_creator else None),
                        is_historical=False,
                        created_at=timeutils.parse_isotime(k['created_at'])
                        if k['created_at'] else None)
                    result.append(up)

        elif type.lower() == 'simple':
            duration = gringutils.normalize_timedelta(duration)
            if duration:
                active_from = datetime.datetime.utcnow() - duration
            else:
                active_from = None
            g_projects = list(
                self.conn.get_projects(request.context,
                                       user_id=user_id,
                                       active_from=active_from))
            project_ids = [p.project_id for p in g_projects]

            if not project_ids:
                LOG.warn('User %s has no payed projects' % user_id)
                return []

            k_projects = self._list_keystone_projects()

            for k, g in itertools.product(k_projects, g_projects):
                if k.id == g.project_id:
                    up = models.UserProject(
                        project_id=g.project_id,
                        project_name=k.name,
                        domain_id=g.domain_id,
                        billing_owner=dict(user_id=g.user_id))
                    result.append(up)

        return result
예제 #21
0
    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
    def get_all(self,
                output_format='xlsx',
                type=None,
                status=None,
                start_time=None,
                end_time=None,
                limit=None,
                offset=None,
                region_id=None,
                project_id=None,
                user_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.
        """
        limit_user_id = acl.get_limited_to_user(request.headers,
                                                'export_orders')

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

        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 and project_id in _project_ids:
                project_ids = [project_id]
            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))

        users = {}
        projects = {}

        def _get_user(user_id):
            user = users.get(user_id)
            if user:
                return user
            contact = kunkka.get_uos_user(user_id)
            user_name = contact['name'] if contact else None
            users[user_id] = models.User(user_id=user_id, user_name=user_name)
            return users[user_id]

        def _get_project(project_id):
            project = projects.get(project_id)
            if project:
                return project
            try:
                project = keystone.get_project(project_id)
                project_name = project.name if project else None
                projects[project_id] = models.SimpleProject(
                    project_id=project_id, project_name=project_name)
                return projects[project_id]
            except Exception as e:
                # Note(chengkun): some project was deleted from keystone,
                # But the project's order still in the gringotts. so when
                # we get the order it will raise 404 project not found error
                LOG.error('error to get project: %s' % e)
                return None

        MAP = [
            {
                "running": u"运行中",
                "stopped": u"暂停中",
                "deleted": u"被删除"
            },
            {
                "instance": u"虚拟机",
                "image": u"镜像",
                "snapshot": u"硬盘快照",
                "volume": u"云硬盘",
                "share": u"共享文件",
                "floatingip": u"公网IP",
                "listener": u"负载均衡监听器",
                "router": u"路由器",
                "alarm": u"监控报警"
            },
        ]

        headers = (u"资源ID", u"资源名称", u"资源类型", u"资源状态", u"单价(元/小时)", u"金额(元)",
                   u"区域", u"用户ID", u"用户名称", u"项目ID", u"项目名称", u"创建时间")
        data = []

        adata = (
            u"过滤条件: 资源类型: %s, 资源状态: %s,用户ID: %s, 项目ID: %s, 区域: %s, 起始时间: %s,  结束时间: %s"
            % (type, status, user_id, project_id, region_id, start_time,
               end_time), "", "", "", "", "", "", "", "", "", "", "")
        data.append(adata)

        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,
                                                 user_id=user_id,
                                                 project_ids=project_ids)
        for order in orders_db:
            price = self._get_order_price(order,
                                          start_time=start_time,
                                          end_time=end_time)
            user = _get_user(order.user_id)
            project = _get_project(order.project_id)
            if project is None:
                continue
            order.created_at += datetime.timedelta(hours=8)
            created_at = \
                timeutils.strtime(order.created_at, fmt=OUTPUT_TIME_FORMAT)
            adata = (order.resource_id, order.resource_name,
                     MAP[1][order.type], MAP[0][order.status],
                     order.unit_price, price, order.region_id, user.user_id,
                     user.user_name, project.project_id, project.project_name,
                     created_at)
            data.append(adata)

        data = tablib.Dataset(*data, headers=headers)

        response.content_type = "application/binary; charset=UTF-8"
        response.content_disposition = \
            "attachment; filename=orders.%s" % output_format
        content = getattr(data, output_format)
        if output_format == 'csv':
            content = content.decode("utf-8").encode("gb2312")
        response.write(content)
        return response
예제 #23
0
    def get_all(self, user_id=None, type=None, duration=None):
        """Get all projects."""
        user_id = acl.get_limited_to_user(request.headers,
                                          'projects_get') or user_id
        self.conn = pecan.request.db_conn
        result = []

        if not type or type.lower() == 'pay':
            # if admin call this api, limit to admin's user_id
            if not user_id:
                user_id = request.context.user_id

            try:
                user_projects = self.conn.get_user_projects(request.context,
                                                            user_id=user_id)
            except Exception as e:
                LOG.exception('Fail to get all projects')
                raise exception.DBError(reason=e)

            project_ids = [up.project_id for up in user_projects]

            if not project_ids:
                LOG.warn('User %s has no payed projects' % user_id)
                return []

            projects = self._list_keystone_projects()

            for u, p in itertools.product(user_projects, projects):
                if u.project_id == p['id']:
                    billing_owner = p['users']['billing_owner']
                    project_owner = p['users']['project_owner']
                    project_creator = p['users']['project_creator']
                    up = models.UserProject(user_id=user_id,
                                            project_id=u.project_id,
                                            project_name=p['name'],
                                            user_consumption=u.user_consumption,
                                            project_consumption=u.project_consumption,
                                            billing_owner=dict(user_id=billing_owner.get('id') if billing_owner else None,
                                                               user_name=billing_owner.get('name') if billing_owner else None),
                                            project_owner=dict(user_id=project_owner.get('id') if project_owner else None,
                                                               user_name=project_owner.get('name') if project_owner else None),
                                            project_creator=dict(user_id=project_creator.get('id') if project_creator else None,
                                                                 user_name=project_creator.get('name') if project_creator else None),
                                            is_historical=u.is_historical,
                                            created_at=timeutils.parse_isotime(p['created_at']) if p['created_at'] else None)
                    result.append(up)
        elif type.lower() == 'all':
            # if admin call this api, limit to admin's user_id
            if not user_id:
                user_id = request.context.user_id

            k_projects = keystone.get_project_list(name=user_id)
            project_ids = [p['id'] for p in k_projects]

            if not project_ids:
                LOG.warn('User %s has no projects' % user_id)
                return []

            try:
                g_projects = self.conn.get_projects_by_project_ids(request.context,
                                                                   project_ids)
            except Exception as e:
                LOG.exception('Fail to get all projects')
                raise exception.DBError(reason=e)
            for k, g in itertools.product(k_projects, g_projects):
                if k['id'] == g.project_id:
                    billing_owner = k['users']['billing_owner']
                    project_owner = k['users']['project_owner']
                    project_creator = k['users']['project_creator']
                    up = models.UserProject(user_id=user_id,
                                            project_id=g.project_id,
                                            project_name=k['name'],
                                            project_consumption=g.consumption,
                                            billing_owner=dict(user_id=billing_owner.get('id') if billing_owner else None,
                                                               user_name=billing_owner.get('name') if billing_owner else None),
                                            project_owner=dict(user_id=project_owner.get('id') if project_owner else None,
                                                               user_name=project_owner.get('name') if project_owner else None),
                                            project_creator=dict(user_id=project_creator.get('id') if project_creator else None,
                                                                 user_name=project_creator.get('name') if project_creator else None),
                                            is_historical=False,
                                            created_at=timeutils.parse_isotime(k['created_at']) if k['created_at'] else None)
                    result.append(up)

        elif type.lower() == 'simple':
            duration = gringutils.normalize_timedelta(duration)
            if duration:
                active_from = datetime.datetime.utcnow() - duration
            else:
                active_from = None
            g_projects = list(self.conn.get_projects(request.context,
                                                     user_id=user_id,
                                                     active_from=active_from))
            project_ids = [p.project_id for p in g_projects]

            if not project_ids:
                LOG.warn('User %s has no payed projects' % user_id)
                return []

            k_projects = self._list_keystone_projects()

            for k, g in itertools.product(k_projects, g_projects):
                if k.id == g.project_id:
                    up = models.UserProject(project_id=g.project_id,
                                            project_name=k.name,
                                            domain_id=g.domain_id,
                                            billing_owner=dict(user_id=g.user_id))
                    result.append(up)

        return result
예제 #24
0
    def get(self,
            output_format='xlsx',
            user_id=None,
            start_time=None,
            end_time=None,
            limit=None,
            offset=None):
        """Export all charges of special user, output formats supported:
           * Excel (Sets + Books)
           * JSON (Sets + Books)
           * YAML (Sets + Books)
           * HTML (Sets)
           * TSV (Sets)
           * CSV (Sets)
        """
        if output_format.lower() not in ["xls", "xlsx", "csv", "json", "yaml"]:
            raise exception.InvalidOutputFormat(output_format=output_format)

        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,
                                                'export_charges')

        if limit_user_id:
            user_id = limit_user_id

        headers = (u"充值记录ID", u"充值对象用户名", u"充值对象ID", u"充值对象真实姓名", u"充值对象邮箱",
                   u"充值对象公司", u"充值金额", u"充值类型", u"充值来源", u"充值人员ID", u"充值人员用户名",
                   u"充值时间", u"状态")
        data = []

        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') or 'unknown'
            mobile = contact.get('phone') or 'unknown'
            company = contact.get('company') or 'unknown'
            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,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time)
        for charge in charges:
            charge.charge_time += datetime.timedelta(hours=8)
            acharge = models.Charge.from_db_model(charge)
            acharge.actor = _get_user(charge.operator)
            acharge.target = _get_user(charge.user_id)
            charge_time = \
                timeutils.strtime(charge.charge_time, fmt=OUTPUT_TIME_FORMAT)

            adata = (acharge.charge_id, acharge.target.user_name,
                     acharge.target.user_id, acharge.target.real_name,
                     acharge.target.email, acharge.target.company,
                     str(acharge.value), acharge.type, acharge.come_from,
                     acharge.actor.user_id, acharge.actor.user_name,
                     charge_time, u"正常")
            data.append(adata)

        data = tablib.Dataset(*data, headers=headers)

        response.content_type = "application/binary; charset=UTF-8"
        response.content_disposition = \
            "attachment; filename=charges.%s" % output_format
        content = getattr(data, output_format)
        if output_format == 'csv':
            content = content.decode("utf-8").encode("gb2312")
        response.write(content)
        return response
예제 #25
0
    def get(self, output_format='xlsx', user_id=None,
            start_time=None, end_time=None,
            limit=None, offset=None):
        """Export all charges of special user, output formats supported:
           * Excel (Sets + Books)
           * JSON (Sets + Books)
           * YAML (Sets + Books)
           * HTML (Sets)
           * TSV (Sets)
           * CSV (Sets)
        """
        if output_format.lower() not in ["xls", "xlsx", "csv", "json", "yaml"]:
            raise exception.InvalidOutputFormat(output_format=output_format)

        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,
                                                'export_charges')

        if limit_user_id:
            user_id = limit_user_id

        headers = (u"充值记录ID", u"充值对象用户名", u"充值对象ID", u"充值对象真实姓名",
                   u"充值对象邮箱", u"充值对象公司", u"充值金额", u"充值类型",
                   u"充值来源", u"充值人员ID", u"充值人员用户名", u"充值时间", u"状态")
        data = []

        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') or 'unknown'
            mobile = contact.get('mobile_number') or 'unknown'
            company = contact.get('company') or 'unknown'
            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,
                                        limit=limit,
                                        offset=offset,
                                        start_time=start_time,
                                        end_time=end_time)
        for charge in charges:
            charge.charge_time += datetime.timedelta(hours=8)
            acharge = models.Charge.from_db_model(charge)
            acharge.actor = _get_user(charge.operator)
            acharge.target = _get_user(charge.user_id)
            charge_time = \
                timeutils.strtime(charge.charge_time, fmt=OUTPUT_TIME_FORMAT)

            adata = (acharge.charge_id, acharge.target.user_name,
                     acharge.target.user_id, acharge.target.real_name,
                     acharge.target.email, acharge.target.company,
                     str(acharge.value), acharge.type, acharge.come_from,
                     acharge.actor.user_id, acharge.actor.user_name,
                     charge_time, u"正常")
            data.append(adata)

        data = tablib.Dataset(*data, headers=headers)

        response.content_type = "application/binary; charset=UTF-8"
        response.content_disposition = \
            "attachment; filename=charges.%s" % output_format
        content = getattr(data, output_format)
        if output_format == 'csv':
            content = content.decode("utf-8").encode("gb2312")
        response.write(content)
        return response
예제 #26
0
파일: bill.py 프로젝트: ShooterTT/gringotts
    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