def revert(self, context, resource, result, **kwargs): if isinstance(result, ft.Failure): LOG.error(_LE("Error when deleting resource: %s"), resource.id) return resource.deleted_at = None resource.store(context)
def revert(self, context, resource, result, **kwargs): if isinstance(result, ft.Failure): LOG.error(_LE("Error when creating resource: %s"), resource.to_dict()) return resource.delete(context, soft_delete=False)
def ActionProc(context, action_id): '''Action process.''' action = Action.load(context, action_id=action_id) if action is None: LOG.error(_LE('Action "%s" could not be found.'), action_id) return False reason = 'Action completed' success = True try: result, reason = action.execute() except Exception as ex: result = action.RES_ERROR reason = six.text_type(ex) LOG.exception(_('Unexpected exception occurred during action ' '%(action)s (%(id)s) execution: %(reason)s'), {'action': action.action, 'id': action.id, 'reason': reason}) success = False finally: # NOTE: locks on action is eventually released here by status update action.set_status(result, reason) return success
def service_manage_report(self): admin_context = bilean_context.get_admin_context() try: db_api.service_update(admin_context, self.engine_id) except Exception as ex: LOG.error(_LE('Service %(id)s update failed: %(error)s'), {'id': self.engine_id, 'error': six.text_type(ex)})
def rule_create(self, cnxt, name, spec, metadata=None): if len(rule_base.Rule.load_all(cnxt, filters={'name': name})) > 0: msg = _("The rule (%(name)s) already exists." ) % {"name": name} raise exception.BileanBadRequest(msg=msg) type_name, version = schema.get_spec_version(spec) try: plugin = environment.global_env().get_rule(type_name) except exception.RuleTypeNotFound: msg = _("The specified rule type (%(type)s) is not supported." ) % {"type": type_name} raise exception.BileanBadRequest(msg=msg) LOG.info(_LI("Creating rule type: %(type)s, name: %(name)s."), {'type': type_name, 'name': name}) rule = plugin(name, spec, metadata=metadata) try: rule.validate() except exception.InvalidSpec as ex: msg = six.text_type(ex) LOG.error(_LE("Failed in creating rule: %s"), msg) raise exception.BileanBadRequest(msg=msg) rule.store(cnxt) LOG.info(_LI("Rule %(name)s is created: %(id)s."), {'name': name, 'id': rule.id}) return rule.to_dict()
def _create_auth_plugin(self): if self.auth_token_info: auth_ref = access.AccessInfo.factory(body=self.auth_token_info, auth_token=self.auth_token) return access_plugin.AccessInfoPlugin( auth_url=self.keystone_v3_endpoint, auth_ref=auth_ref) if self.auth_token: # FIXME(jamielennox): This is broken but consistent. If you # only have a token but don't load a service catalog then # url_for wont work. Stub with the keystone endpoint so at # least it might be right. return token_endpoint.Token(endpoint=self.keystone_v3_endpoint, token=self.auth_token) if self.password: return v3.Password(username=self.username, password=self.password, project_id=self.tenant_id, user_domain_id='default', auth_url=self.keystone_v3_endpoint) LOG.error( _LE("Keystone v3 API connection failed, no password " "trust or auth_token!")) raise exception.AuthorizationFailure()
def rule_create(self, cnxt, name, spec, metadata=None): if len(plugin_base.Rule.load_all(cnxt, filters={'name': name})) > 0: msg = _("The rule (%(name)s) already exists." ) % {"name": name} raise exception.BileanBadRequest(msg=msg) type_name, version = schema.get_spec_version(spec) try: plugin = environment.global_env().get_plugin(type_name) except exception.RuleTypeNotFound: msg = _("The specified rule type (%(type)s) is not supported." ) % {"type": type_name} raise exception.BileanBadRequest(msg=msg) LOG.info(_LI("Creating rule type: %(type)s, name: %(name)s."), {'type': type_name, 'name': name}) rule = plugin.RuleClass(name, spec, metadata=metadata) try: rule.validate() except exception.InvalidSpec as ex: msg = six.text_type(ex) LOG.error(_LE("Failed in creating rule: %s"), msg) raise exception.BileanBadRequest(msg=msg) rule.store(cnxt) LOG.info(_LI("Rule %(name)s is created: %(id)s."), {'name': name, 'id': rule.id}) return rule.to_dict()
def _create_auth_plugin(self): if self.auth_token_info: auth_ref = access.AccessInfo.factory(body=self.auth_token_info, auth_token=self.auth_token) return access_plugin.AccessInfoPlugin( auth_url=self.keystone_v3_endpoint, auth_ref=auth_ref) if self.auth_token: # FIXME(jamielennox): This is broken but consistent. If you # only have a token but don't load a service catalog then # url_for wont work. Stub with the keystone endpoint so at # least it might be right. return token_endpoint.Token(endpoint=self.keystone_v3_endpoint, token=self.auth_token) if self.password: return v3.Password(username=self.username, password=self.password, project_id=self.tenant_id, user_domain_id='default', auth_url=self.keystone_v3_endpoint) LOG.error(_LE("Keystone v3 API connection failed, no password " "trust or auth_token!")) raise exception.AuthorizationFailure()
def revert(self, context, resource, resource_bak, result, **kwargs): if isinstance(result, ft.Failure): LOG.error(_LE("Error when updating resource: %s"), resource.id) return # restore resource res = plugin_base.Resource.from_dict(resource_bak) res.store(context)
def kill_children(self, *args): """Kills the entire process group.""" LOG.error(_LE('SIGTERM received')) signal.signal(signal.SIGTERM, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN) self.running = False os.killpg(0, signal.SIGTERM)
def execute(self): """Wrapper of action execution.""" action_name = self.action.lower() method_name = "do_" + action_name method = getattr(self, method_name, None) if method is None: LOG.error(_LE('Unsupported action: %s.') % self.action) return None return method()
def revert(self, context, user_obj, user_bak, resource, result, *args, **kwargs): if isinstance(result, ft.Failure): LOG.error(_LE("Error when updating user: %s"), user_obj.id) return # Restore user user = user_mod.User.from_dict(user_bak) user.store(context)
def revert(self, context, resource, result, *args, **kwargs): if isinstance(result, ft.Failure): LOG.error(_LE("Error when storing consumption of resource: %s"), resource.id) return consumption = resource.consumption if consumption is not None: consumption.delete(context)
def revert(self, context, user_bak, result, **kwargs): if isinstance(result, ft.Failure): LOG.error(_LE("Error when settling account for user: %s"), user_bak.get('id')) return # Restore user user = user_mod.User.from_dict(user_bak) user.store(context)
def topics_and_exchanges(self): topics_exchanges = set() plugins = environment.global_env().get_plugins() for plugin in plugins: try: topic_exchanges = plugin.get_notification_topics_exchanges() for plugin_topic in topic_exchanges: if isinstance(plugin_topic, basestring): raise Exception( _LE("Plugin %s should return a list of topic " "exchange pairs") % plugin.__class__.__name__) topics_exchanges.add(plugin_topic) except Exception as e: LOG.error(_LE("Failed to retrieve notification topic(s) " "and exchanges from bilean plugin " "%(ext)s: %(e)s") % {'ext': plugin.__name__, 'e': e}) return topics_exchanges
def user_delete(self, cnxt, user_id): """Delete a specify user according to the notification.""" LOG.info(_LI('Deleging user: %s'), user_id) user = user_mod.User.load(cnxt, user_id=user_id) if user.status in [user.ACTIVE, user.WARNING]: LOG.error(_LE("User (%s) is in use, can not delete."), user_id) return user_mod.User.delete(cnxt, user_id=user_id) bilean_scheduler.notify(bilean_scheduler.DELETE_JOBS, user=user.to_dict())
def _stop_rpc_server(self): # Stop RPC connection to prevent new requests LOG.info(_LI("Stopping engine service...")) try: self._rpc_server.stop() self._rpc_server.wait() LOG.info(_LI('Engine service stopped successfully')) except Exception as ex: LOG.error(_LE('Failed to stop engine service: %s'), six.text_type(ex))
def do_settle_account(self): try: flow_engine = bilean_flow.get_settle_account_flow( self.context, self.target, task=self.inputs.get('task')) with bilean_flow.DynamicLogListener(flow_engine, logger=LOG): flow_engine.run() except Exception as ex: LOG.error(_LE("Faied to execute action(%(action_id)s), error: " "%(error_msg)s"), {"action_id": self.id, "error_msg": six.text_type(ex)}) return self.RES_ERROR, _('Settle account failed.') return self.RES_OK, _('Settle account successfully.')
def _verify_and_respawn_children(self, pid, status): if len(self.stale_children) == 0: LOG.debug('No stale children') if os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0: LOG.error(_LE('Not respawning child %d, cannot ' 'recover from termination'), pid) if not self.children and not self.stale_children: LOG.info(_LI('All workers have terminated. Exiting')) self.running = False else: if len(self.children) < self.conf.workers: self.run_child()
def error(context, entity, action, status=None, status_reason=None, timestamp=None): timestamp = timestamp or timeutils.utcnow() event = Event(timestamp, logging.ERROR, entity, action=action, status=status, status_reason=status_reason, user_id=context.project) event.store(context) LOG.error(_LE('%(name)s [%(id)s] %(action)s - %(status)s: %(reason)s'), {'name': event.obj_name, 'id': event.obj_id and event.obj_id[:8], 'action': action, 'status': status, 'reason': status_reason})
def user_lock_acquire(context, user_id, action_id, engine=None, forced=False): """Try to lock the specified user. :param context: the context used for DB operations; :param user_id: ID of the user to be locked. :param action_id: ID of the action that attempts to lock the user. :param engine: ID of the engine that attempts to lock the user. :param forced: set to True to cancel current action that owns the lock, if any. :returns: True if lock is acquired, or False otherwise. """ owner = db_api.user_lock_acquire(user_id, action_id) if action_id == owner: return True retries = cfg.CONF.lock_retry_times retry_interval = cfg.CONF.lock_retry_interval while retries > 0: sleep(retry_interval) LOG.debug(_('Acquire lock for user %s again'), user_id) owner = db_api.user_lock_acquire(user_id, action_id) if action_id == owner: return True retries = retries - 1 if forced: owner = db_api.user_lock_steal(user_id, action_id) return action_id == owner action = db_api.action_get(context, owner) if (action and action.owner and action.owner != engine and is_engine_dead(context, action.owner)): LOG.info(_LI('The user %(u)s is locked by dead action %(a)s, ' 'try to steal the lock.'), { 'u': user_id, 'a': owner }) reason = _('Engine died when executing this action.') db_api.action_mark_failed(context, action.id, time.time(), reason=reason) db_api.user_lock_steal(user_id, action_id) return True LOG.error(_LE('User is already locked by action %(old)s, ' 'action %(new)s failed grabbing the lock'), {'old': owner, 'new': action_id}) return False
def _verify_and_respawn_children(self, pid, status): if len(self.stale_children) == 0: LOG.debug('No stale children') if os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0: LOG.error( _LE('Not respawning child %d, cannot ' 'recover from termination'), pid) if not self.children and not self.stale_children: LOG.info(_LI('All workers have terminated. Exiting')) self.running = False else: if len(self.children) < self.conf.workers: self.run_child()
def do_delete_resource(self): try: resource_id = self.inputs.get('resource_id') resource = plugin_base.Resource.load( self.context, resource_id=resource_id) except exception.ResourceNotFound: LOG.error(_LE('The resource(%s) trying to delete not found.'), resource_id) return self.RES_ERROR, _('Resource not found.') try: flow_engine = bilean_flow.get_delete_resource_flow( self.context, self.target, resource) with bilean_flow.DynamicLogListener(flow_engine, logger=LOG): flow_engine.run() except Exception as ex: LOG.error(_LE("Faied to execute action(%(action_id)s), error: " "%(error_msg)s"), {"action_id": self.id, "error_msg": six.text_type(ex)}) return self.RES_ERROR, _('Resource deletion failed.') LOG.info(_LI('Successfully deleted resource: %s'), resource.id) return self.RES_OK, _('Resource deletion successfully.')
def do_create_resource(self): resource = plugin_base.Resource.from_dict(self.inputs) try: flow_engine = bilean_flow.get_create_resource_flow( self.context, self.target, resource) with bilean_flow.DynamicLogListener(flow_engine, logger=LOG): flow_engine.run() except Exception as ex: LOG.error(_LE("Faied to execute action(%(action_id)s), error: " "%(error_msg)s"), {"action_id": self.id, "error_msg": six.text_type(ex)}) return self.RES_ERROR, _('Resource creation failed.') return self.RES_OK, _('Resource creation successfully.')
def process_identity_notification(self, notification): """Convert notification to user.""" user_id = notification['payload'].get('resource_info') if not user_id: LOG.error(_LE("Cannot retrieve user_id from notification: %s"), notification) return oslo_messaging.NotificationResult.HANDLED action = self._get_action(notification['event_type']) if action: act = notify_action.UserAction(self.cnxt, action, user_id) LOG.info(_LI("Notify engine to %(action)s user: %(user)s") % {'action': action, 'user': user_id}) act.execute() return oslo_messaging.NotificationResult.HANDLED
def __init__(self, **kwargs): self.kwargs = kwargs try: self.message = self.msg_fmt % kwargs except KeyError: # exc_info = sys.exc_info() # if kwargs doesn't match a variable in the message # log the issue and the kwargs LOG.exception(_LE('Exception in string format operation')) for name, value in six.iteritems(kwargs): LOG.error("%s: %s" % (name, value)) # noqa if _FATAL_EXCEPTION_FORMAT_ERRORS: raise
def read_global_environment(self): '''Read and parse global environment files.''' cfg.CONF.import_opt('environment_dir', 'bilean.common.config') env_dir = cfg.CONF.environment_dir try: files = glob.glob(os.path.join(env_dir, '*')) except OSError as ex: LOG.error(_LE('Failed to read %s'), env_dir) LOG.exception(ex) return for fname in files: try: with open(fname) as f: LOG.info(_LI('Loading environment from %s'), fname) self.load(self.parse(f.read())) except ValueError as vex: LOG.error(_LE('Failed to parse %s'), fname) LOG.exception(six.text_type(vex)) except IOError as ioex: LOG.error(_LE('Failed to read %s'), fname) LOG.exception(six.text_type(ioex))
def do_delete(self, context, timestamp=None, ignore_missing=True, timeout=None): '''Delete resource from other services.''' # Delete resource from db and generate consumption self.delete(context, timestamp=timestamp) self.consumption.store(context) # Delete resource from cinder cinderclient = driver_base.BileanDriver().block_store() try: cinderclient.volume_delete(self.id, ignore_missing=ignore_missing) except Exception as ex: LOG.error(_LE('Error: %s'), six.text_type(ex)) return False return True
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 do_delete(self, context, timestamp=None, ignore_missing=True, timeout=None): '''Delete resource from other services.''' # Delete resource from db and generate consumption self.delete(context, timestamp=timestamp) self.consumption.store(context) # Delete resource from nova novaclient = driver_base.BileanDriver().compute() try: novaclient.server_delete(self.id, ignore_missing=ignore_missing) novaclient.wait_for_server_delete(self.id, timeout=timeout) except Exception as ex: LOG.error(_LE('Error: %s'), six.text_type(ex)) return False return True
def process_identity_notification(self, notification): """Convert notifcation to user.""" user_id = notification['payload'].get('resource_info', None) if not user_id: LOG.error(_LE("Cannot retrieve user_id from notification: %s"), notification) return oslo_messaging.NotificationResult.HANDLED action = self._get_action(notification['event_type']) if action: act = notify_action.UserAction(self.cnxt, action, user_id) LOG.info( _("Notify engine to %(action)s user: %(user)s") % { 'action': action, 'user': user_id }) act.execute() return oslo_messaging.NotificationResult.HANDLED
def execute(self, **kwargs): """Interface function for action execution. :param dict kwargs: Parameters provided to the action, if any. :returns: A tuple containing the result and the related reason. """ try: res = bilean_lock.user_lock_acquire(self.context, self.target, self.id, self.owner) if not res: LOG.error(_LE('Failed grabbing the lock for user: %s'), self.target) res = self.RES_ERROR reason = _('Failed in locking user') else: res, reason = self._execute() finally: bilean_lock.user_lock_release(self.target, self.id) return res, reason
def log_exception(err, exc_info): args = {'exc_info': exc_info} if cfg.CONF.verbose or cfg.CONF.debug else {} LOG.error(_LE("Unexpected error occurred serving API: %s"), err, **args)
def hup(self, *args): """Reloads configuration files with zero down time.""" LOG.error(_LE('SIGHUP received')) signal.signal(signal.SIGHUP, signal.SIG_IGN) raise exception.SIGHUPInterrupt
def __call__(self, request): """WSGI method that controls (de)serialization and method dispatch.""" action_args = self.get_action_args(request.environ) action = action_args.pop('action', None) status_code = action_args.pop('success', None) try: deserialized_request = self.dispatch(self.deserializer, action, request) action_args.update(deserialized_request) LOG.debug(('Calling %(controller)s : %(action)s'), {'controller': self.controller, 'action': action}) action_result = self.dispatch(self.controller, action, request, **action_args) except TypeError as err: LOG.error(_LE('Exception handling resource: %s') % err) msg = _('The server could not comply with the request since ' 'it is either malformed or otherwise incorrect.') err = webob.exc.HTTPBadRequest(msg) http_exc = translate_exception(err, request.best_match_language()) # NOTE(luisg): We disguise HTTP exceptions, otherwise they will be # treated by wsgi as responses ready to be sent back and they # won't make it into the pipeline app that serializes errors raise exception.HTTPExceptionDisguise(http_exc) except webob.exc.HTTPException as err: if not isinstance(err, webob.exc.HTTPError): # Some HTTPException are actually not errors, they are # responses ready to be sent back to the users, so we don't # create error log, but disguise and translate them to meet # openstacksdk's need. http_exc = translate_exception(err, request.best_match_language()) raise exception.HTTPExceptionDisguise(http_exc) if isinstance(err, webob.exc.HTTPServerError): LOG.error( _LE("Returning %(code)s to user: %(explanation)s"), {'code': err.code, 'explanation': err.explanation}) http_exc = translate_exception(err, request.best_match_language()) raise exception.HTTPExceptionDisguise(http_exc) except exception.BileanException as err: raise translate_exception(err, request.best_match_language()) except Exception as err: log_exception(err, sys.exc_info()) raise translate_exception(err, request.best_match_language()) serializer = self.serializer or serializers.JSONResponseSerializer() try: response = webob.Response(request=request) # Customize status code if default (200) should be overridden if status_code is not None: response.status_code = int(status_code) # Customize 'location' header if provided if action_result and isinstance(action_result, dict): location = action_result.pop('location', None) if location: response.location = '/v1%s' % location if not action_result: action_result = None self.dispatch(serializer, action, response, action_result) return response # return unserializable result (typically an exception) except Exception: return action_result
def __call__(self, request): """WSGI method that controls (de)serialization and method dispatch.""" action_args = self.get_action_args(request.environ) action = action_args.pop('action', None) status_code = action_args.pop('success', None) try: deserialized_request = self.dispatch(self.deserializer, action, request) action_args.update(deserialized_request) LOG.debug(('Calling %(controller)s : %(action)s'), { 'controller': self.controller, 'action': action }) action_result = self.dispatch(self.controller, action, request, **action_args) except TypeError as err: LOG.error(_LE('Exception handling resource: %s') % err) msg = _('The server could not comply with the request since ' 'it is either malformed or otherwise incorrect.') err = webob.exc.HTTPBadRequest(msg) http_exc = translate_exception(err, request.best_match_language()) # NOTE(luisg): We disguise HTTP exceptions, otherwise they will be # treated by wsgi as responses ready to be sent back and they # won't make it into the pipeline app that serializes errors raise exception.HTTPExceptionDisguise(http_exc) except webob.exc.HTTPException as err: if not isinstance(err, webob.exc.HTTPError): # Some HTTPException are actually not errors, they are # responses ready to be sent back to the users, so we don't # create error log, but disguise and translate them to meet # openstacksdk's need. http_exc = translate_exception(err, request.best_match_language()) raise exception.HTTPExceptionDisguise(http_exc) if isinstance(err, webob.exc.HTTPServerError): LOG.error(_LE("Returning %(code)s to user: %(explanation)s"), { 'code': err.code, 'explanation': err.explanation }) http_exc = translate_exception(err, request.best_match_language()) raise exception.HTTPExceptionDisguise(http_exc) except exception.BileanException as err: raise translate_exception(err, request.best_match_language()) except Exception as err: log_exception(err, sys.exc_info()) raise translate_exception(err, request.best_match_language()) serializer = self.serializer or serializers.JSONResponseSerializer() try: response = webob.Response(request=request) # Customize status code if default (200) should be overridden if status_code is not None: response.status_code = int(status_code) # Customize 'location' header if provided if action_result and isinstance(action_result, dict): location = action_result.pop('location', None) if location: response.location = '/v1%s' % location if not action_result: action_result = None self.dispatch(serializer, action, response, action_result) return response # return unserializable result (typically an exception) except Exception: return action_result