def __init__(self, user_id, **kwargs): self.id = kwargs.get('id') self.user_id = user_id self.resource_id = kwargs.get('resource_id') self.resource_type = kwargs.get('resource_type') self.start_time = utils.make_decimal(kwargs.get('start_time', 0)) self.end_time = utils.make_decimal(kwargs.get('end_time', 0)) self.rate = utils.make_decimal(kwargs.get('rate', 0)) self.cost = utils.make_decimal(kwargs.get('cost', 0)) self.metadata = kwargs.get('metadata')
def execute(self, context, resource, values, resource_bak, **kwargs): old_rate = resource.rate resource.properties = values.get('properties') rule = plugin_base.Rule.load(context, rule_id=resource.rule_id) resource.rate = utils.make_decimal(rule.get_price(resource)) resource.delta_rate = resource.rate - old_rate resource.store(context)
def settle_account(self, context, task=None): '''Settle account for user.''' notifier = bilean_notifier.Notifier() timestamp = utils.make_decimal(wallclock()) self._settle_account(context, timestamp=timestamp) if task == 'notify' and self._notify_or_not(): self.status_reason = "The balance is almost used up" self.status = self.WARNING # Notify user msg = {'user': self.id, 'notification': self.status_reason} notifier.info('billing.notify', msg) elif task == 'freeze' and self.balance <= 0: reason = _("Balance overdraft") LOG.info(_LI("Freeze user %(user_id)s, reason: %(reason)s"), {'user_id': self.id, 'reason': reason}) resources = plugin_base.Resource.load_all( context, user_id=self.id, project_safe=False) for resource in resources: resource.do_delete(context, timestamp=timestamp) self.rate = 0 self.status = self.FREEZE self.status_reason = reason # Notify user msg = {'user': self.id, 'notification': self.status_reason} notifier.info('billing.notify', msg) self.store(context)
def do_recharge(self, context, value, recharge_type=None, timestamp=None, metadata=None): """Recharge for user and update status. param context: The request context. param value: Recharge value. param recharge_type: Rechage type, 'Recharge'|'System bonus'. param timestamp: Record when recharge action occurs. param metadata: Some other keyword. """ self.balance += utils.make_decimal(value) if self.status == self.INIT and self.balance > 0: self.status = self.FREE self.status_reason = "Recharged" elif self.status == self.FREEZE and self.balance > 0: reason = _("Status change from 'FREEZE' to 'FREE' because " "of recharge.") self.status = self.FREE self.status_reason = reason elif self.status == self.WARNING: if not self._notify_or_not(): reason = _("Status change from 'WARNING' to 'ACTIVE' because " "of recharge.") self.status = self.ACTIVE self.status_reason = reason self.store(context) # Create recharge record values = {'user_id': self.id, 'value': value, 'type': recharge_type, 'timestamp': timestamp, 'metadata': metadata} db_api.recharge_create(context, values)
def _notify_or_not(self): '''Check if user should be notified.''' cfg.CONF.import_opt('prior_notify_time', 'bilean.scheduler.cron_scheduler', group='scheduler') prior_notify_time = cfg.CONF.scheduler.prior_notify_time * 3600 rest_usage = utils.make_decimal(prior_notify_time) * self.rate return self.balance < rest_usage
def __init__(self, user_id, **kwargs): self.id = user_id self.name = kwargs.get('name') self.policy_id = kwargs.get('policy_id') self.balance = utils.make_decimal(kwargs.get('balance', 0)) self.rate = utils.make_decimal(kwargs.get('rate', 0)) self.credit = kwargs.get('credit', 0) self.last_bill = utils.make_decimal(kwargs.get('last_bill', 0)) self.status = kwargs.get('status', self.INIT) self.status_reason = kwargs.get('status_reason', 'Init user') self.created_at = kwargs.get('created_at') self.updated_at = kwargs.get('updated_at') self.deleted_at = kwargs.get('deleted_at') if self.name is None: self.name = self._retrieve_name(self.id)
def _settle_account(self, context, timestamp=None): if self.rate == 0: LOG.info(_LI("Ignore settlement action because user is in '%s' " "status."), self.status) return now = timestamp or utils.make_decimal(wallclock()) usage_seconds = now - self.last_bill cost = self.rate * usage_seconds self.balance -= cost self.last_bill = now
def __init__(self, target, action, context, **kwargs): # context will be persisted into database so that any worker thread # can pick the action up and execute it on behalf of the initiator self.id = kwargs.get('id', None) self.name = kwargs.get('name', '') self.context = context self.action = action self.target = target # Why this action is fired, it can be a UUID of another action self.cause = kwargs.get('cause', '') # Owner can be an UUID format ID for the worker that is currently # working on the action. It also serves as a lock. self.owner = kwargs.get('owner', None) self.start_time = utils.make_decimal(kwargs.get('start_time', 0)) self.end_time = utils.make_decimal(kwargs.get('end_time', 0)) # Timeout is a placeholder in case some actions may linger too long self.timeout = kwargs.get('timeout', cfg.CONF.default_action_timeout) # Return code, useful when action is not automatically deleted # after execution self.status = kwargs.get('status', self.INIT) self.status_reason = kwargs.get('status_reason', '') # All parameters are passed in using keyword arguments which is # a dictionary stored as JSON in DB self.inputs = kwargs.get('inputs', {}) self.outputs = kwargs.get('outputs', {}) self.created_at = kwargs.get('created_at', None) self.updated_at = kwargs.get('updated_at', None) self.data = kwargs.get('data', {})
def execute(self, context, resource, **kwargs): user = user_mod.User.load(context, user_id=resource.user_id) pid = user.policy_id try: if pid: policy = policy_mod.Policy.load(context, policy_id=pid) else: policy = policy_mod.Policy.load_default(context) except exception.PolicyNotFound as e: LOG.error(_LE("Error when find policy: %s"), e) if policy is not None: rule = policy.find_rule(context, resource.resource_type) # Update resource with rule_id and rate resource.rule_id = rule.id resource.rate = utils.make_decimal(rule.get_price(resource)) resource.store(context)
def load(cls, context, user_id=None, user=None, realtime=False, show_deleted=False, project_safe=True): '''Retrieve a user from database.''' if context.is_admin: project_safe = False if user is None: user = db_api.user_get(context, user_id, show_deleted=show_deleted, project_safe=project_safe) if user is None: raise exception.UserNotFound(user=user_id) u = cls._from_db_record(user) if not realtime: return u if u.rate > 0 and u.status != u.FREEZE: seconds = utils.make_decimal(wallclock()) - u.last_bill u.balance -= u.rate * seconds return u
def consumption_statistics(self, cnxt, user_id=None, filters=None, start_time=None, end_time=None, summary=False, project_safe=True): user_id = user_id or cnxt.project result = {} if start_time is None: start_time = 0 else: start_time = utils.format_time_to_seconds(start_time) start_time = utils.make_decimal(start_time) now_time = utils.format_time_to_seconds(timeutils.utcnow()) now_time = utils.make_decimal(now_time) if end_time is None: end_time = now_time else: end_time = utils.format_time_to_seconds(end_time) end_time = utils.make_decimal(end_time) consumptions = cons_mod.Consumption.load_all(cnxt, user_id=user_id, filters=filters, project_safe=project_safe) for cons in consumptions: if cons.start_time > end_time or cons.end_time < start_time: continue et = min(cons.end_time, end_time) st = max(cons.start_time, start_time) seconds = et - st cost = cons.rate * seconds if summary: if cons.resource_type not in result: result[cons.resource_type] = cost else: result[cons.resource_type] += cost else: if cons.resource_id not in result: tmp = {'resource_type': cons.resource_type, 'cost': cost} result[cons.resource_id] = tmp else: result[cons.resource_id]['cost'] += cost resources = plugin_base.Resource.load_all(cnxt, user_id=user_id, filters=filters, project_safe=project_safe) for res in resources: if res.last_bill > end_time or now_time < start_time: continue et = min(now_time, end_time) st = max(res.last_bill, start_time) seconds = et - st cost = res.rate * seconds if summary: if res.resource_type not in result: result[res.resource_type] = cost else: result[res.resource_type] += cost else: if res.id not in result: tmp = {'resource_type': res.resource_type, 'cost': cost} result[res.id] = tmp else: result[res.id]['cost'] += cost if summary: for key in six.iterkeys(result): result[key] = utils.dec2str(result[key]) return result else: consumptions = [] for key in six.iterkeys(result): consumption = cons_mod.Consumption( user_id, resource_id=key, resource_type=result[key]['resource_type'], cost=result[key]['cost'], start_time=start_time, end_time=end_time) consumptions.append(consumption.to_dict()) return consumptions