def notify_zaqar(self, action, message, headers=None): queue_info = urlparse.parse_qs(action.query) try: # NOTE(flwang): Try to get build a pre-signed client if user has # provide enough information about that. Otherwise, go to build # a client with service account and queue name for this alarm. conf, queue_name = self._get_presigned_client_conf(queue_info) if conf is not None: zaqar_client = self.get_zaqar_client(conf) if conf is None or queue_name is None or zaqar_client is None: zaqar_client = self.client # queue_name is a combination of <alarm-id>-<topic> queue_name = "%s-%s" % (message['body']['alarm_id'], queue_info.get('topic')[-1]) # create a queue in zaqar queue = zaqar_client.queue(queue_name) subscriber_list = queue_info.get('subscriber', []) ttl = int(queue_info.get('ttl', ['3600'])[-1]) for subscriber in subscriber_list: # add subscriber to the zaqar queue subscription_data = dict(subscriber=subscriber, ttl=ttl) zaqar_client.subscription(queue_name, **subscription_data) # post the message to the queue queue.post(message) except IndexError: LOG.error( _LE("Required query option missing in action %s"), action) except Exception: LOG.error( _LE("Unknown error occurred; Failed to post message to" " Zaqar queue"), exc_info=True)
def notify_zaqar(self, action, message): queue_info = urlparse.parse_qs(action.query) try: # queue_name is a combination of <alarm-id>-<topic> queue_name = "%s-%s" % (message['body']['alarm_id'], queue_info.get('topic')[-1]) # create a queue in zaqar queue = self.client.queue(queue_name, force_create=True) subscriber_list = queue_info.get('subscriber', []) ttl = queue_info.get('ttl', [3600])[-1] for subscriber in subscriber_list: # add subscriber to the zaqar queue subscription_data = dict(subscriber=subscriber, ttl=ttl) self.client.subscription(queue_name, **subscription_data) # post the message to the queue queue.post(message) except IndexError: LOG.error( _LE("Required topic query option missing in action %s") % action) except Exception: LOG.error(_LE("Unknown error occurred; Failed to post message to" " Zaqar queue"), exc_info=True)
def notify_zaqar(self, action, message, headers=None): queue_info = urlparse.parse_qs(action.query) try: # NOTE(flwang): Try to get build a pre-signed client if user has # provide enough information about that. Otherwise, go to build # a client with service account and queue name for this alarm. conf, queue_name = self._get_presigned_client_conf(queue_info) if conf is not None: zaqar_client = self.get_zaqar_client(conf) if conf is None or queue_name is None or zaqar_client is None: zaqar_client = self.client # queue_name is a combination of <alarm-id>-<topic> queue_name = "%s-%s" % (message['body']['alarm_id'], queue_info.get('topic')[-1]) # create a queue in zaqar queue = zaqar_client.queue(queue_name) subscriber_list = queue_info.get('subscriber', []) ttl = int(queue_info.get('ttl', ['3600'])[-1]) for subscriber in subscriber_list: # add subscriber to the zaqar queue subscription_data = dict(subscriber=subscriber, ttl=ttl) zaqar_client.subscription(queue_name, **subscription_data) # post the message to the queue queue.post(message) except IndexError: LOG.error(_LE("Required query option missing in action %s"), action) except Exception: LOG.error(_LE("Unknown error occurred; Failed to post message to" " Zaqar queue"), exc_info=True)
def notify_zaqar(self, action, message): queue_info = urlparse.parse_qs(action.query) try: # queue_name is a combination of <alarm-id>-<topic> queue_name = "%s-%s" % (message['body']['alarm_id'], queue_info.get('topic')[-1]) # create a queue in zaqar queue = self.client.queue(queue_name, force_create=True) subscriber_list = queue_info.get('subscriber', []) ttl = queue_info.get('ttl', [3600])[-1] for subscriber in subscriber_list: # add subscriber to the zaqar queue subscription_data = dict(subscriber=subscriber, ttl=ttl) self.client.subscription(queue_name, **subscription_data) # post the message to the queue queue.post(message) except IndexError: LOG.error(_LE("Required topic query option missing in action %s") % action) except Exception: LOG.error(_LE("Unknown error occurred; Failed to post message to" " Zaqar queue"), exc_info=True)
def _get_alarm_state(self, alarm_id): try: alarms = self._storage_conn.get_alarms(alarm_id=alarm_id) except Exception: LOG.exception(_LE('alarm %s retrieval failed'), alarm_id) return None if not alarms: LOG.error(_LE("alarm %s doesn't exists anymore"), alarm_id) return None return list(alarms)[0].state
def _get_alarm_state(self, alarm_id): try: alarms = self._storage_conn.get_alarms(alarm_id=alarm_id) except Exception: LOG.exception(_LE('alarm %s retrieval failed'), alarm_id) return None if not alarms: LOG.error(_LE("alarm %s doesn't exist anymore"), alarm_id) return None return list(alarms)[0].state
def _validate_conn_options(args): nosql_scheme = urlparse.urlparse(args.nosql_conn).scheme sql_scheme = urlparse.urlparse(args.sql_conn).scheme if nosql_scheme not in ('mongodb', 'hbase'): root_logger.error(_LE('Invalid source DB type %s, the source database ' 'connection should be one of: [mongodb, hbase]' ), nosql_scheme) sys.exit(1) if sql_scheme not in ('mysql', 'mysql+pymysql', 'postgresql', 'sqlite'): root_logger.error(_LE('Invalid destination DB type %s, the destination' ' database connection should be one of: ' '[mysql, postgresql, sqlite]'), sql_scheme) sys.exit(1)
def _refresh(self, alarm, state, reason, reason_data, always_record=False): """Refresh alarm state.""" try: previous = alarm.state alarm.state = state if previous != state or always_record: LOG.info(_LI('alarm %(id)s transitioning to %(state)s because ' '%(reason)s'), {'id': alarm.alarm_id, 'state': state, 'reason': reason}) try: self._storage_conn.update_alarm(alarm) except storage.AlarmNotFound: LOG.warning(_LW("Skip updating this alarm's state, the" "alarm: %s has been deleted"), alarm.alarm_id) else: self._record_change(alarm, reason) self.notifier.notify(alarm, previous, reason, reason_data) elif alarm.repeat_actions: self.notifier.notify(alarm, previous, reason, reason_data) except Exception: # retry will occur naturally on the next evaluation # cycle (unless alarm state reverts in the meantime) LOG.exception(_LE('alarm state update failed'))
def extract_my_subset(self, group_id, universal_set): """Filters an iterable, returning only objects assigned to this agent. We have a list of objects and get a list of active group members from `tooz`. We then hash all the objects into buckets and return only the ones that hashed into *our* bucket. """ if not group_id: return universal_set if group_id not in self._groups: self.join_group(group_id) try: members = self._get_members(group_id) LOG.debug('Members of group: %s, Me: %s', members, self._my_id) if self._my_id not in members: LOG.warning(_LW('Cannot extract tasks because agent failed to ' 'join group properly. Rejoining group.')) self.join_group(group_id) members = self._get_members(group_id) if self._my_id not in members: raise MemberNotInGroupError(group_id, members, self._my_id) LOG.debug('Members of group: %s, Me: %s', members, self._my_id) hr = HashRing(members) LOG.debug('Universal set: %s', universal_set) my_subset = [v for v in universal_set if hr.get_node(str(v)) == self._my_id] LOG.debug('My subset: %s', my_subset) return my_subset except tooz.coordination.ToozError: LOG.exception(_LE('Error getting group membership info from ' 'coordination backend.')) return []
def extract_my_subset(self, group_id, iterable): """Filters an iterable, returning only objects assigned to this agent. We have a list of objects and get a list of active group members from `tooz`. We then hash all the objects into buckets and return only the ones that hashed into *our* bucket. """ if not group_id: return iterable if group_id not in self._groups: self.join_group(group_id) try: members = self._get_members(group_id) LOG.debug('Members of group: %s', members) hr = HashRing(members) filtered = [ v for v in iterable if hr.get_node(str(v)) == self._my_id ] LOG.debug('My subset: %s', filtered) return filtered except tooz.coordination.ToozError: LOG.exception( _LE('Error getting group membership info from ' 'coordination backend.')) return []
def _validate(self): """Validate received event has mandatory parameters.""" if not self.obj: LOG.error(_LE('Received invalid event (empty or None)')) raise InvalidEvent() if not self.obj.get('event_type'): LOG.error(_LE('Failed to extract event_type from event = %s'), self.obj) raise InvalidEvent() if not self.obj.get('message_id'): LOG.error(_LE('Failed to extract message_id from event = %s'), self.obj) raise InvalidEvent()
def _refresh(self, alarm, state, reason, reason_data, always_record=False): """Refresh alarm state.""" try: previous = alarm.state alarm.state = state if previous != state or always_record: LOG.info( _LI('alarm %(id)s transitioning to %(state)s because ' '%(reason)s'), { 'id': alarm.alarm_id, 'state': state, 'reason': reason }) try: self._storage_conn.update_alarm(alarm) except storage.AlarmNotFound: LOG.warning( _LW("Skip updating this alarm's state, the" "alarm: %s has been deleted"), alarm.alarm_id) else: self._record_change(alarm, reason) self.notifier.notify(alarm, previous, reason, reason_data) elif alarm.repeat_actions: self.notifier.notify(alarm, previous, reason, reason_data) except Exception: # retry will occur naturally on the next evaluation # cycle (unless alarm state reverts in the meantime) LOG.exception(_LE('alarm state update failed'))
def evaluate_events(self, events): """Evaluate the events by referring related alarms.""" if not isinstance(events, list): events = [events] LOG.debug('Starting event alarm evaluation: #events = %d', len(events)) for e in events: LOG.debug('Evaluating event: event = %s', e) try: event = Event(e) except InvalidEvent: LOG.debug('Aborting evaluation of the event.') continue for id, alarm in six.iteritems( self._get_project_alarms(event.project)): try: self._evaluate_alarm(alarm, event) except Exception: LOG.exception( _LE('Failed to evaluate alarm (id=%(a)s) ' 'triggered by event = %(e)s.'), { 'a': id, 'e': e }) LOG.debug('Finished event alarm evaluation.')
def evaluate_events(self, events): """Evaluate the events by referring related alarms.""" if not isinstance(events, list): events = [events] LOG.debug('Starting event alarm evaluation: #events = %d', len(events)) for e in events: LOG.debug('Evaluating event: event = %s', e) try: event = Event(e) except InvalidEvent: LOG.debug('Aborting evaluation of the event.') continue for id, alarm in six.iteritems( self._get_project_alarms(event.project)): try: self._evaluate_alarm(alarm, event) except Exception: LOG.exception(_LE('Failed to evaluate alarm (id=%(a)s) ' 'triggered by event = %(e)s.'), {'a': id, 'e': e}) LOG.debug('Finished event alarm evaluation.')
def extract_my_subset(self, group_id, universal_set): """Filters an iterable, returning only objects assigned to this agent. We have a list of objects and get a list of active group members from `tooz`. We then hash all the objects into buckets and return only the ones that hashed into *our* bucket. """ if not group_id: return universal_set if group_id not in self._groups: self.join_group(group_id) try: members = self._get_members(group_id) LOG.debug('Members of group: %s, Me: %s', members, self._my_id) if self._my_id not in members: LOG.warning( _LW('Cannot extract tasks because agent failed to ' 'join group properly. Rejoining group.')) self.join_group(group_id) members = self._get_members(group_id) if self._my_id not in members: raise MemberNotInGroupError(group_id, members, self._my_id) LOG.debug('Members of group: %s, Me: %s', members, self._my_id) hr = HashRing(members) LOG.debug('Universal set: %s', universal_set) my_subset = [ v for v in universal_set if hr.get_node(str(v)) == self._my_id ] LOG.debug('My subset: %s', my_subset) return my_subset except tooz.coordination.ToozError: LOG.exception( _LE('Error getting group membership info from ' 'coordination backend.')) return []
def _handle_action(notifiers, action, alarm_id, alarm_name, severity, previous, current, reason, reason_data): """Process action on alarm :param notifiers: list of possible notifiers. :param action: The action that is being attended, as a parsed URL. :param alarm_id: The triggered alarm. :param alarm_name: The name of triggered alarm. :param severity: The level of triggered alarm :param previous: The previous state of the alarm. :param current: The current state of the alarm. :param reason: The reason the alarm changed its state. :param reason_data: A dict representation of the reason. """ try: action = netutils.urlsplit(action) except Exception: LOG.error( _LE("Unable to parse action %(action)s for alarm " "%(alarm_id)s"), { 'action': action, 'alarm_id': alarm_id }) return try: notifier = notifiers[action.scheme].obj except KeyError: scheme = action.scheme LOG.error( _LE("Action %(scheme)s for alarm %(alarm_id)s is unknown, " "cannot notify"), { 'scheme': scheme, 'alarm_id': alarm_id }) return try: LOG.debug("Notifying alarm %(id)s with action %(act)s", { 'id': alarm_id, 'act': action }) notifier.notify(action, alarm_id, alarm_name, severity, previous, current, reason, reason_data) except Exception: LOG.exception(_LE("Unable to notify alarm %s"), alarm_id)
def get_zaqar_client(self, conf): try: from zaqarclient.queues import client as zaqar_client return zaqar_client.Client( self._get_endpoint(), version=2, conf=conf) except Exception: LOG.error( _LE("Failed to connect to Zaqar service "), exc_info=True)
def __init__(self, group_id, members, my_id): super(MemberNotInGroupError, self).__init__( _LE('Group ID: %{group_id}s, Members: %{members}s, Me: %{me}s: ' 'Current agent is not part of group and cannot take tasks') % { 'group_id': group_id, 'members': members, 'me': my_id })
def _evaluate_assigned_alarms(self): try: alarms = self._assigned_alarms() LOG.info(_LI('initiating evaluation cycle on %d alarms'), len(alarms)) for alarm in alarms: self._evaluate_alarm(alarm) except Exception: LOG.exception(_LE('alarm evaluation cycle failed'))
def start(self): if self.backend_url: try: self._coordinator = tooz.coordination.get_coordinator( self.backend_url, self._my_id) self._coordinator.start() LOG.info(_LI('Coordination backend started successfully.')) except tooz.coordination.ToozError: LOG.exception(_LE('Error connecting to coordination backend.'))
def _convert_to_datetime(isotime): try: date_time = timeutils.parse_isotime(isotime) date_time = date_time.replace(tzinfo=None) return date_time except ValueError: LOG.exception(_LE("String %s is not a valid isotime"), isotime) msg = _('Failed to parse the timestamp value %s') % isotime raise base.ClientSideError(msg)
def get_zaqar_client(self, conf): try: from zaqarclient.queues import client as zaqar_client return zaqar_client.Client(self._get_endpoint(), version=2, conf=conf) except Exception: LOG.error(_LE("Failed to connect to Zaqar service "), exc_info=True)
def heartbeat(self): if self._coordinator: if not self._coordinator.is_started: # re-connect self.start() try: self._coordinator.heartbeat() except tooz.coordination.ToozError: LOG.exception(_LE('Error sending a heartbeat to coordination ' 'backend.'))
def notify_zaqar(self, action, message, headers): queue_info = urlparse.parse_qs(action.query) try: queue_name = queue_info.get('queue_name')[-1] except IndexError: LOG.error(_LE("Required 'queue_name' query option missing in" " action %s"), action) return try: conf = self._get_client_conf(headers['X-Auth-Token']) client = self.get_zaqar_client(conf) queue = client.queue(queue_name) queue.post(message) except Exception: LOG.error(_LE("Unknown error occurred; Failed to post message to" " Zaqar queue"), exc_info=True)
def notify_zaqar(self, action, message, headers): queue_info = urlparse.parse_qs(action.query) try: queue_name = queue_info.get('queue_name')[-1] except IndexError: LOG.error( _LE("Required 'queue_name' query option missing in" " action %s"), action) return try: conf = self._get_client_conf(headers['X-Auth-Token']) client = self.get_zaqar_client(conf) queue = client.queue(queue_name) queue.post(message) except Exception: LOG.error(_LE("Unknown error occurred; Failed to post message to" " Zaqar queue"), exc_info=True)
def _get_endpoint(self): try: ks_client = keystone_client.get_client(self.conf) return ks_client.service_catalog.url_for( service_type=cfg.CONF.service_types.zaqar, endpoint_type=self.conf.service_credentials.os_endpoint_type) except Exception: LOG.error(_LE("Aodh was configured to use zaqar:// action," " but Zaqar endpoint could not be found in Keystone" " service catalog."))
def post(self, data): """Create a new alarm. :param data: an alarm within the request body. """ rbac.enforce('create_alarm', pecan.request.headers, pecan.request.enforcer, {}) conn = pecan.request.storage now = timeutils.utcnow() data.alarm_id = uuidutils.generate_uuid() user_limit, project_limit = rbac.get_limited_to( pecan.request.headers, pecan.request.enforcer) def _set_ownership(aspect, owner_limitation, header): attr = '%s_id' % aspect requested_owner = getattr(data, attr) explicit_owner = requested_owner != wtypes.Unset caller = pecan.request.headers.get(header) if (owner_limitation and explicit_owner and requested_owner != caller): raise base.ProjectNotAuthorized(requested_owner, aspect) actual_owner = (owner_limitation or requested_owner if explicit_owner else caller) setattr(data, attr, actual_owner) _set_ownership('user', user_limit, 'X-User-Id') _set_ownership('project', project_limit, 'X-Project-Id') # Check if there's room for one more alarm if is_over_quota(conn, data.project_id, data.user_id): raise OverQuota(data) data.timestamp = now data.state_timestamp = now ALARMS_RULES[data.type].plugin.create_hook(data) change = data.as_dict(models.Alarm) data.update_actions() try: alarm_in = models.Alarm(**change) except Exception: LOG.exception(_LE("Error while posting alarm: %s"), change) raise base.ClientSideError(_("Alarm incorrect")) alarm = conn.create_alarm(alarm_in) self._record_creation(conn, change, alarm.alarm_id, now) v2_utils.set_resp_location_hdr("/alarms/" + alarm.alarm_id) return Alarm.from_db_model(alarm)
def post(self, data): """Create a new alarm. :param data: an alarm within the request body. """ rbac.enforce('create_alarm', pecan.request.headers, pecan.request.enforcer, {}) conn = pecan.request.storage now = timeutils.utcnow() data.alarm_id = str(uuid.uuid4()) user_limit, project_limit = rbac.get_limited_to(pecan.request.headers, pecan.request.enforcer) def _set_ownership(aspect, owner_limitation, header): attr = '%s_id' % aspect requested_owner = getattr(data, attr) explicit_owner = requested_owner != wtypes.Unset caller = pecan.request.headers.get(header) if (owner_limitation and explicit_owner and requested_owner != caller): raise base.ProjectNotAuthorized(requested_owner, aspect) actual_owner = (owner_limitation or requested_owner if explicit_owner else caller) setattr(data, attr, actual_owner) _set_ownership('user', user_limit, 'X-User-Id') _set_ownership('project', project_limit, 'X-Project-Id') # Check if there's room for one more alarm if is_over_quota(conn, data.project_id, data.user_id): raise OverQuota(data) data.timestamp = now data.state_timestamp = now ALARMS_RULES[data.type].plugin.create_hook(data) change = data.as_dict(models.Alarm) data.update_actions() try: alarm_in = models.Alarm(**change) except Exception: LOG.exception(_LE("Error while posting alarm: %s"), change) raise base.ClientSideError(_("Alarm incorrect")) alarm = conn.create_alarm(alarm_in) self._record_creation(conn, change, alarm.alarm_id, now) v2_utils.set_resp_location_hdr("/v2/alarms/" + alarm.alarm_id) return Alarm.from_db_model(alarm)
def _get_endpoint(self): try: ks_client = keystone_client.get_client(self.conf) return ks_client.service_catalog.url_for( service_type=cfg.CONF.service_types.zaqar, endpoint_type=self.conf.service_credentials.os_endpoint_type) except Exception: LOG.error( _LE("Aodh was configured to use zaqar:// action," " but Zaqar endpoint could not be found in Keystone" " service catalog."))
def _evaluate_alarm(self, alarm): """Evaluate the alarms assigned to this evaluator.""" if alarm.type not in self.evaluators: LOG.debug('skipping alarm %s: type unsupported', alarm.alarm_id) return LOG.debug('evaluating alarm %s', alarm.alarm_id) try: self.evaluators[alarm.type].obj.evaluate(alarm) except Exception: LOG.exception(_LE('Failed to evaluate alarm %s'), alarm.alarm_id)
def start(self): backend_url = cfg.CONF.coordination.backend_url if backend_url: try: self._coordinator = tooz.coordination.get_coordinator( backend_url, self._my_id) self._coordinator.start() self._started = True LOG.info(_LI('Coordination backend started successfully.')) except tooz.coordination.ToozError: self._started = False LOG.exception(_LE('Error connecting to coordination backend.'))
def _handle_action(notifiers, action, alarm_id, alarm_name, severity, previous, current, reason, reason_data): """Process action on alarm :param notifiers: list of possible notifiers. :param action: The action that is being attended, as a parsed URL. :param alarm_id: The triggered alarm. :param alarm_name: The name of triggered alarm. :param severity: The level of triggered alarm :param previous: The previous state of the alarm. :param current: The current state of the alarm. :param reason: The reason the alarm changed its state. :param reason_data: A dict representation of the reason. """ try: action = netutils.urlsplit(action) except Exception: LOG.error( _LE("Unable to parse action %(action)s for alarm " "%(alarm_id)s"), {'action': action, 'alarm_id': alarm_id}) return try: notifier = notifiers[action.scheme].obj except KeyError: scheme = action.scheme LOG.error( _LE("Action %(scheme)s for alarm %(alarm_id)s is unknown, " "cannot notify"), {'scheme': scheme, 'alarm_id': alarm_id}) return try: LOG.debug("Notifying alarm %(id)s with action %(act)s", {'id': alarm_id, 'act': action}) notifier.notify(action, alarm_id, alarm_name, severity, previous, current, reason, reason_data) except Exception: LOG.exception(_LE("Unable to notify alarm %s"), alarm_id)
def stop(self): if not self._coordinator: return for group in list(self._groups): self.leave_group(group) try: self._coordinator.stop() except tooz.coordination.ToozError: LOG.exception(_LE('Error connecting to coordination backend.')) finally: self._coordinator = None
def _get_endpoint(self): if self._zendpoint is None: try: ks_client = keystone_client.get_client(self.conf) z_srv = ks_client.services.find( type=self.conf.service_types.zaqar) endpoint_type = self.conf.service_credentials.interface z_endpoint = ks_client.endpoints.find(service_id=z_srv.id, interface=endpoint_type) self._zendpoint = z_endpoint.url except Exception: LOG.error(_LE("Aodh was configured to use zaqar:// action," " but Zaqar endpoint could not be found in" " Keystone service catalog.")) return self._zendpoint
def put(self, data): """Modify this alarm. :param data: an alarm within the request body. """ # Ensure alarm exists alarm_in = self._enforce_rbac('change_alarm') now = timeutils.utcnow() data.alarm_id = self._id user, project = rbac.get_limited_to(pecan.request.headers, pecan.request.enforcer) if user: data.user_id = user elif data.user_id == wtypes.Unset: data.user_id = alarm_in.user_id if project: data.project_id = project elif data.project_id == wtypes.Unset: data.project_id = alarm_in.project_id data.timestamp = now if alarm_in.state != data.state: data.state_timestamp = now else: data.state_timestamp = alarm_in.state_timestamp ALARMS_RULES[data.type].plugin.update_hook(data) old_data = Alarm.from_db_model(alarm_in) old_alarm = old_data.as_dict(models.Alarm) data.update_actions(old_data) updated_alarm = data.as_dict(models.Alarm) try: alarm_in = models.Alarm(**updated_alarm) except Exception: LOG.exception(_LE("Error while putting alarm: %s"), updated_alarm) raise base.ClientSideError(_("Alarm incorrect")) alarm = pecan.request.storage.update_alarm(alarm_in) change = dict( (k, v) for k, v in updated_alarm.items() if v != old_alarm[k] and k not in ['timestamp', 'state_timestamp']) self._record_change(change, now, on_behalf_of=alarm.project_id) return Alarm.from_db_model(alarm)
def put(self, data): """Modify this alarm. :param data: an alarm within the request body. """ # Ensure alarm exists alarm_in = self._enforce_rbac('change_alarm') now = timeutils.utcnow() data.alarm_id = self._id user, project = rbac.get_limited_to(pecan.request.headers, pecan.request.enforcer) if user: data.user_id = user elif data.user_id == wtypes.Unset: data.user_id = alarm_in.user_id if project: data.project_id = project elif data.project_id == wtypes.Unset: data.project_id = alarm_in.project_id data.timestamp = now if alarm_in.state != data.state: data.state_timestamp = now else: data.state_timestamp = alarm_in.state_timestamp ALARMS_RULES[data.type].plugin.update_hook(data) old_data = Alarm.from_db_model(alarm_in) old_alarm = old_data.as_dict(models.Alarm) data.update_actions(old_data) updated_alarm = data.as_dict(models.Alarm) try: alarm_in = models.Alarm(**updated_alarm) except Exception: LOG.exception(_LE("Error while putting alarm: %s"), updated_alarm) raise base.ClientSideError(_("Alarm incorrect")) alarm = pecan.request.storage.update_alarm(alarm_in) change = dict((k, v) for k, v in updated_alarm.items() if v != old_alarm[k] and k not in ['timestamp', 'state_timestamp']) self._record_change(change, now, on_behalf_of=alarm.project_id) return Alarm.from_db_model(alarm)
def _get_endpoint(self): if self._zendpoint is None: try: ks_client = keystone_client.get_client(self.conf) z_srv = ks_client.services.find( type=self.conf.service_types.zaqar) endpoint_type = self.conf.service_credentials.interface z_endpoint = ks_client.endpoints.find(service_id=z_srv.id, interface=endpoint_type) self._zendpoint = z_endpoint.url except Exception: LOG.error( _LE("Aodh was configured to use zaqar:// action," " but Zaqar endpoint could not be found in" " Keystone service catalog.")) return self._zendpoint
def _inner(): try: join_req = self._coordinator.join_group(group_id) join_req.get() LOG.info(_LI('Joined partitioning group %s'), group_id) except tooz.coordination.MemberAlreadyExist: return except tooz.coordination.GroupNotCreated: create_grp_req = self._coordinator.create_group(group_id) try: create_grp_req.get() except tooz.coordination.GroupAlreadyExist: pass raise ErrorJoiningPartitioningGroup() except tooz.coordination.ToozError: LOG.exception(_LE('Error joining partitioning group %s,' ' re-trying'), group_id) raise ErrorJoiningPartitioningGroup() self._groups.add(group_id)
def get_zaqar_client(self): conf = self.conf.service_credentials params = { "auth_opts": { "backend": "keystone", "options": { "os_username": conf.os_username, "os_password": conf.os_password, "os_project_name": conf.os_tenant_name, "os_auth_url": conf.os_auth_url, "insecure": "", }, } } try: from zaqarclient.queues import client as zaqar_client return zaqar_client.Client(self._get_endpoint(), version=1.1, conf=params) except Exception: LOG.error(_LE("Failed to connect to Zaqar service "), exc_info=True)
def get_zaqar_client(self): conf = self.conf.service_credentials params = { 'auth_opts': { 'backend': 'keystone', 'options': { 'os_username': conf.os_username, 'os_password': conf.os_password, 'os_project_name': conf.os_tenant_name, 'os_auth_url': conf.os_auth_url, 'insecure': '' } } } try: from zaqarclient.queues import client as zaqar_client return zaqar_client.Client(self._get_endpoint(), version=1.1, conf=params) except Exception: LOG.error(_LE("Failed to connect to Zaqar service "), exc_info=True)
def _process_alarm(notifiers, data): """Notify that alarm has been triggered. :param notifiers: list of possible notifiers :param data: (dict): alarm data """ actions = data.get('actions') if not actions: LOG.error(_LE("Unable to notify for an alarm with no action")) return for action in actions: AlarmEndpoint._handle_action(notifiers, action, data.get('alarm_id'), data.get('alarm_name'), data.get('severity'), data.get('previous'), data.get('current'), data.get('reason'), data.get('reason_data'))
def extract_my_subset(self, group_id, iterable): """Filters an iterable, returning only objects assigned to this agent. We have a list of objects and get a list of active group members from `tooz`. We then hash all the objects into buckets and return only the ones that hashed into *our* bucket. """ if not group_id: return iterable if group_id not in self._groups: self.join_group(group_id) try: members = self._get_members(group_id) LOG.debug('Members of group: %s', members) hr = utils.HashRing(members) filtered = [v for v in iterable if hr.get_node(str(v)) == self._my_id] LOG.debug('My subset: %s', filtered) return filtered except tooz.coordination.ToozError: LOG.exception(_LE('Error getting group membership info from ' 'coordination backend.')) return []
def __init__(self, group_id, members, my_id): super(MemberNotInGroupError, self).__init__(_LE( 'Group ID: %(group_id)s, Members: %(members)s, Me: %(me)s: ' 'Current agent is not part of group and cannot take tasks') % {'group_id': group_id, 'members': members, 'me': my_id})
def __init__(self): super(ErrorJoiningPartitioningGroup, self).__init__(_LE( 'Error occurred when joining partitioning group'))
def __call__(self, environ, start_response): # Request for this state, modified by replace_start_response() # and used when an error is being reported. state = {} def replacement_start_response(status, headers, exc_info=None): """Overrides the default response to make errors parsable.""" try: status_code = int(status.split(' ')[0]) state['status_code'] = status_code except (ValueError, TypeError): # pragma: nocover raise Exception(('ErrorDocumentMiddleware received an invalid ' 'status %s' % status)) else: if (state['status_code'] // 100) not in (2, 3): # Remove some headers so we can replace them later # when we have the full error message and can # compute the length. headers = [(h, v) for (h, v) in headers if h not in ('Content-Length', 'Content-Type')] # Save the headers in case we need to modify them. state['headers'] = headers return start_response(status, headers, exc_info) app_iter = self.app(environ, replacement_start_response) if (state['status_code'] // 100) not in (2, 3): req = webob.Request(environ) error = environ.get('translatable_error') user_locale = self.best_match_language(req.accept_language) if (req.accept.best_match(['application/json', 'application/xml' ]) == 'application/xml'): content_type = 'application/xml' try: # simple check xml is valid fault = etree.fromstring(b'\n'.join(app_iter)) # Add the translated error to the xml data if error is not None: for fault_string in fault.findall('faultstring'): fault_string.text = i18n.translate( error, user_locale) error_message = etree.tostring(fault) body = b''.join((b'<error_message>', error_message, b'</error_message>')) except etree.XMLSyntaxError as err: LOG.error(_LE('Error parsing HTTP response: %s'), err) error_message = state['status_code'] body = '<error_message>%s</error_message>' % error_message if six.PY3: body = body.encode('utf-8') else: content_type = 'application/json' app_data = b'\n'.join(app_iter) if six.PY3: app_data = app_data.decode('utf-8') try: fault = json.loads(app_data) if error is not None and 'faultstring' in fault: fault['faultstring'] = i18n.translate( error, user_locale) except ValueError as err: fault = app_data body = json.dumps({'error_message': fault}) if six.PY3: body = body.encode('utf-8') state['headers'].append(('Content-Length', str(len(body)))) state['headers'].append(('Content-Type', content_type)) body = [body] else: body = app_iter return body
def __init__(self): super(ErrorJoiningPartitioningGroup, self).__init__( _LE('Error occurred when joining partitioning group'))
def __call__(self, environ, start_response): # Request for this state, modified by replace_start_response() # and used when an error is being reported. state = {} def replacement_start_response(status, headers, exc_info=None): """Overrides the default response to make errors parsable.""" try: status_code = int(status.split(" ")[0]) state["status_code"] = status_code except (ValueError, TypeError): # pragma: nocover raise Exception(("ErrorDocumentMiddleware received an invalid " "status %s" % status)) else: if (state["status_code"] // 100) not in (2, 3): # Remove some headers so we can replace them later # when we have the full error message and can # compute the length. headers = [(h, v) for (h, v) in headers if h not in ("Content-Length", "Content-Type")] # Save the headers in case we need to modify them. state["headers"] = headers return start_response(status, headers, exc_info) app_iter = self.app(environ, replacement_start_response) if (state["status_code"] // 100) not in (2, 3): req = webob.Request(environ) error = environ.get("translatable_error") user_locale = self.best_match_language(req.accept_language) if req.accept.best_match(["application/json", "application/xml"]) == "application/xml": content_type = "application/xml" try: # simple check xml is valid fault = etree.fromstring(b"\n".join(app_iter)) # Add the translated error to the xml data if error is not None: for fault_string in fault.findall("faultstring"): fault_string.text = i18n.translate(error, user_locale) error_message = etree.tostring(fault) body = b"".join((b"<error_message>", error_message, b"</error_message>")) except etree.XMLSyntaxError as err: LOG.error(_LE("Error parsing HTTP response: %s"), err) error_message = state["status_code"] body = "<error_message>%s</error_message>" % error_message if six.PY3: body = body.encode("utf-8") else: content_type = "application/json" app_data = b"\n".join(app_iter) if six.PY3: app_data = app_data.decode("utf-8") try: fault = json.loads(app_data) if error is not None and "faultstring" in fault: fault["faultstring"] = i18n.translate(error, user_locale) except ValueError as err: fault = app_data body = json.dumps({"error_message": fault}) if six.PY3: body = body.encode("utf-8") state["headers"].append(("Content-Length", str(len(body)))) state["headers"].append(("Content-Type", content_type)) body = [body] else: body = app_iter return body