def estimate(self): """Get the price per day and the remaining days.""" policy.check_policy(HOOK.context, "account:estimate", action="account:estimate") _gnocchi_fetcher = fetcher.GnocchiFetcher() user_id = self._id account = self._account(user_id=user_id) price_per_hour = _gnocchi_fetcher.get_current_consume( HOOK.context.project_id) def _estimate(balance, price_per_hour, remaining_day): return models.Estimate(balance=round(balance, 2), price_per_hour=round(price_per_hour, 2), remaining_day=remaining_day) if price_per_hour == 0: if account['balance'] < 0: return _estimate(account['balance'], price_per_hour, -2) else: return _estimate(account['balance'], price_per_hour, -1) elif price_per_hour > 0: if account['balance'] < 0: return _estimate(account['balance'], price_per_hour, -2) else: price_per_day = price_per_hour * 24 remaining_day = int(account['balance'] / price_per_day) return _estimate(account['balance'], price_per_hour, remaining_day)
def get(self, user_id=None, type=None, start_time=None, end_time=None, limit=None, offset=None, sort_key='created_at', sort_dir='desc'): """Get all charges of all account.""" policy.check_policy(HOOK.context, "charges:all", action="charges:all") if limit and limit < 0: raise exception.InvalidParameterValue(err="Invalid limit") if offset and offset < 0: raise exception.InvalidParameterValue(err="Invalid offset") users = {} def _get_user(user_id): user = users.get(user_id) if user: return user contact = ks_client.get_user(user_id) or {} user_name = contact.get('name') email = contact.get('email') users[user_id] = models.User(user_id=user_id, user_name=user_name, email=email) return users[user_id] charges = HOOK.conductor_rpcapi.get_charges(HOOK.context, user_id=user_id, type=type, limit=limit, offset=offset, start_time=start_time, end_time=end_time, sort_key=sort_key, sort_dir=sort_dir) charges_list = [] for charge in charges: acharge = models.Charge.from_db_model(charge) acharge.target = _get_user(charge['user_id']) charges_list.append(acharge) total_price, total_count = ( HOOK.conductor_rpcapi.get_charges_price_and_count( HOOK.context, user_id=user_id, type=type, start_time=start_time, end_time=end_time)) return models.Charges.transform(total_price=total_price, total_count=total_count, charges=charges_list)
def post(self, data): """Create a new project.""" policy.check_policy(HOOK.context, "project:post") try: project = data.as_dict() return HOOK.conductor_rpcapi.create_project(HOOK.context, project) except Exception: LOG.exception('Fail to create project: %s' % project) raise exception.ProjectCreateFailed(project_id=data.project_id, user_id=data.user_id)
def delete(self): """Delete the account including the projects that belong to it.""" policy.check_policy(HOOK.context, "account:delete", action="account:delete") try: HOOK.conductor_rpcapi.delete_account(HOOK.context, self._id) except exception.NotFound: LOG.Warning('Could not find account whose user_id is %s' % self._id) except Exception as e: LOG.error('Fail to delete the account: %s' % self._id) raise exception.DBError(reason=e)
def post(self, data): """Create a new account.""" policy.check_policy(HOOK.context, "account:post", action="account:post") try: account = data.as_dict() response = HOOK.conductor_rpcapi.create_account( HOOK.context, account) return response except Exception as e: LOG.error('Fail to create account: %s' % data.as_dict()) raise exception.DBError(reason=e)
def summary(self, project_id=None, all_get=False): gnocchi_client = fetcher.GnocchiFetcher() policy.check_policy(HOOK.context, "order:summary", action="order:summary") if not project_id and not all_get: project_id = HOOK.headers.get("X-Project-Id") if all_get and acl.context_is_admin(HOOK.headers): project_id = None try: result = gnocchi_client.get_summary( project_id) except Exception as e: LOG.error('Exception reason: %s' % e) raise return result
def bills(self, resource_type, project_id=None, limit=None, marker=None, all_get=False): gnocchi_client = fetcher.GnocchiFetcher() policy.check_policy(HOOK.context, "order:bills", action="order:bills") if not project_id and not all_get: project_id = HOOK.headers.get("X-Project-Id") if all_get and acl.context_is_admin(HOOK.headers): project_id = None try: resources = gnocchi_client.get_bills( resource_type, project_id, limit, marker) except Exception as e: LOG.error('Exception reason: %s' % e) raise return resources
def level(self, level): """Update the account's level.""" policy.check_policy(HOOK.context, "account:level", action="account:level") if not isinstance(level, int) or level < 0 or level > 9: raise exception.InvalidParameterValue(err="Invalid Level") try: account = HOOK.conductor_rpcapi.change_account_level( HOOK.context, self._id, level) except Exception as e: LOG.error('Fail to change the account level of: %s' % self._id) raise exception.DBError(reason=e) return models.UserAccount(**account)
def charges(self, type=None, start_time=None, end_time=None, limit=None, offset=None): """Get this account's charge records.""" policy.check_policy(HOOK.context, "charges:get", action="account:charges") 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(HOOK.headers, 'account:charge') or self._id charges = HOOK.conductor_rpcapi.get_charges(HOOK.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(**charge)) total_price, total_count = ( HOOK.conductor_rpcapi.get_charges_price_and_count( HOOK.context, user_id=user_id, type=type, start_time=start_time, end_time=end_time)) return models.Charges.transform(total_price=total_price, total_count=total_count, charges=charges_list)
def put(self, data): """Charge the account.""" policy.check_policy(HOOK.context, "account:charge", action="account:charge") # check accountant charge value lacv = int(CONF.limited_accountant_charge_value) if data.value > lacv: raise exception.InvalidChargeValue(value=data.value) try: charge = HOOK.conductor_rpcapi.charge_account( HOOK.context, self._id, **data.as_dict()) except exception.NotAuthorized as e: LOG.error('Fail to charge the account:%s' 'due to not authorization' % self._id) raise exception.NotAuthorized() except Exception as e: LOG.error('Fail to charge the account:%s,' 'charge value: %s' % (self._id, data.value)) raise exception.DBError(reason=e) return models.Charge.from_db_model(charge)
def get_all(self, owed=None, limit=None, offset=None, duration=None): """Get this account.""" policy.check_policy(HOOK.context, "account:all", action="account:all") owed = False if limit and limit < 0: raise exception.InvalidParameterValue(err="Invalid limit") if offset and offset < 0: raise exception.InvalidParameterValue(err="Invalid offset") duration = timeutils.normalize_timedelta(duration) if duration: active_from = timeutils.utcnow() - duration else: active_from = None try: accounts = HOOK.conductor_rpcapi.get_accounts( HOOK.context, owed=owed, limit=limit, offset=offset, active_from=active_from) count = len(accounts) except exception.NotAuthorized as e: LOG.error('Failed to get all accounts') raise exception.NotAuthorized() except Exception as e: LOG.error('Failed to get all accounts') raise exception.DBError(reason=e) accounts = [ models.AdminAccount.transform(**account) for account in accounts ] return models.AdminAccounts.transform(total_count=count, accounts=accounts)
def get(self, output_format='xlsx', user_id=None, start_time=None, end_time=None, limit=None, offset=None, all_get=False): """Export all charges of special user, output formats supported: * Excel (Sets + Books) * YAML (Sets + Books) * HTML (Sets) * TSV (Sets) * CSV (Sets) * JSON (Sets) """ policy.check_policy(HOOK.context, "charges:export", action="charges:export") tablib.formats.json.json = json if output_format.lower() not in ["xls", "xlsx", "csv", "yaml", "json"]: 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") policy.check_policy(HOOK.context, "charges:export", action="charges:export") if all_get and acl.context_is_admin(HOOK.headers): user_id = None headers = (u"充值记录ID", u"充值对象用户名", u"充值对象ID", u"充值对象邮箱", u"充值金额", u"充值类型", u"充值来源", u"充值人员ID", u"充值人员用户名", u"充值时间", u"状态") data = [] users = {} def _get_user(user_id): if not user_id: return models.User(user_id=None, user_name=None, email=None) user = users.get(user_id) if user: return user contact = ks_client.get_user(user_id) or {} user_name = contact.get('name') email = contact.get('email') users[user_id] = models.User(user_id=user_id, user_name=user_name, email=email) return users[user_id] charges = HOOK.conductor_rpcapi.get_charges( HOOK.context, user_id=user_id, limit=limit, offset=offset, start_time=start_time, end_time=end_time) for charge in charges: charge_st = timeutils.str2ts(charge['charge_time']) + (3600 * 8) charge['charge_time'] = timeutils.ts2str(charge_st) acharge = models.Charge.from_db_model(charge) acharge.actor = _get_user(charge['operator']) acharge.target = _get_user(charge['user_id']) charge_time = charge['charge_time'] adata = (acharge.charge_id, acharge.target.user_name, acharge.target.user_id, acharge.target.email, 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) content = data.export(output_format) response.write(content) return response
def get_all(self, output_format='xlsx', type=None, status=None, start_time=None, end_time=None, limit=None, marker=None, project_id=None, user_id=None, owed=None, all_get=False): """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. """ policy.check_policy(HOOK.context, "charges:export", action="charges:export") tablib.formats.json.json = json _gnocchi_fetcher = fetcher.GnocchiFetcher() if limit and limit < 0: raise exception.InvalidParameterValue(err="Invalid limit") policy.check_policy(HOOK.context, "charges:export", action="charges:export") if all_get and acl.context_is_admin(HOOK.headers): user_id = None MAP = {"instance": u"虚拟机", "volume": u"云硬盘", "image": u"镜像", "ratelimit": u"限速", "network_lbaas_loadbalancer": u"负载均衡"} headers = (u"资源ID", u"资源名称", u"资源类型", u"金额(元)", u"用户ID", u"项目ID", u"创建时间") data = [] adata = (u"过滤条件: 资源类型: %s, 用户ID: %s, " u"项目ID: %s, 起始时间: %s, 结束时间: %s" % (type, user_id, project_id, start_time, end_time), "", "", "", "", "", "") data.append(adata) resources = [] for service in MAP: resources += _gnocchi_fetcher.get_resources(project_id, service) for resource in resources: if 'total.cost' in resource['metrics']: price = _gnocchi_fetcher.get_resource_price( resource['metrics']['total.cost'], start_time, end_time) adata = (resource['id'], resource['display_name'], MAP[resource['type']], price, resource['user_id'], resource['project_id'], resource['started_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) response.write(content) return response
def get(self): """Get this account.""" policy.check_policy(HOOK.context, "account:get", action="account:get") user_id = self._id return models.AdminAccount(**self._account(user_id=user_id))