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)
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)
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)
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)
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]
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)
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)
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)
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)
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
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
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)
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
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))
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))
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
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)
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
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)
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
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
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
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
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