Esempio n. 1
0
    def meter_sms_actions(self, project_id, receivers):
        ctxt = get_admin_context()
        local_receivers = [r for r in receivers if r.startswith("+82")]
        international_receivers = [
            r for r in receivers if not r.startswith("+82")
        ]

        self.api.put_metric_data(ctxt,
                                 project_id,
                                 namespace="SPCS/SYNAPS",
                                 metric_name="LocalSMSActionCount",
                                 dimensions={},
                                 value=len(local_receivers),
                                 unit="Count",
                                 timestamp=utils.strtime(utils.utcnow()),
                                 is_admin=True)

        self.api.put_metric_data(ctxt,
                                 project_id,
                                 namespace="SPCS/SYNAPS",
                                 metric_name="InternationalSMSActionCount",
                                 dimensions={},
                                 value=len(international_receivers),
                                 unit="Count",
                                 timestamp=utils.strtime(utils.utcnow()),
                                 is_admin=True)

        LOG.audit("Meter SMS: %s %s %s", project_id, len(receivers), receivers)
Esempio n. 2
0
 def parse_metric_data(metric):
     try:
         dimensions_ = metric.get('dimensions', {})
         dimensions = utils.extract_member_dict(dimensions_)
     except KeyError:
         err = "Unsuitable Dimensions Value - %s" % str(dimensions_)
         raise InvalidParameterValue(err)
     
     self.check_dimensions(dimensions)
 
     metric_name = metric.get('metric_name')
     unit = metric.get('unit', 'None')
     value = metric.get('value')
     req_timestamp = metric.get('timestamp')
     timestamp = req_timestamp if req_timestamp \
                 else utils.strtime(utils.utcnow())
     timebound = (datetime.datetime.utcnow() - 
                  datetime.timedelta(
                                 seconds=FLAGS.get('statistics_ttl')))
     
     if utils.parse_strtime(timestamp) < timebound:
         err = "Stale metric data - %s" % timestamp
         raise InvalidParameterValue(err)
     
     self.check_metric_name(metric_name)
     self.check_unit(unit)
     
     return metric_name, dimensions, value, unit, timestamp 
Esempio n. 3
0
    def put_metric_data(self,
                        context,
                        project_id,
                        namespace,
                        metric_name,
                        dimensions,
                        value,
                        unit,
                        timestamp=None,
                        is_admin=False):
        admin_namespace = FLAGS.get('admin_namespace')
        if namespace.startswith(admin_namespace) and not is_admin:
            raise AdminRequired()

        timestamp = timestamp or utils.strtime(utils.utcnow())

        message = {
            'project_id': project_id,
            'namespace': namespace,
            'metric_name': metric_name,
            'dimensions': dimensions,
            'value': value,
            'unit': unit,
            'timestamp': timestamp,
            'context': context.to_dict()
        }

        self.rpc.send_msg(rpc.PUT_METRIC_DATA_MSG_ID, message)
        LOG.info("PUT_METRIC_DATA_MSG sent")

        return {}
Esempio n. 4
0
 def meter_instance_actions(self, project_id, receivers):
     ctxt = get_admin_context()
     self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS",
                              metric_name="InstanceActionCount",
                              dimensions={}, value=len(receivers),
                              unit="Count",
                              timestamp=utils.strtime(utils.utcnow()),
                              is_admin=True)
     LOG.audit("Meter InstanceAction: %s %s %s", project_id, len(receivers),
               receivers)
Esempio n. 5
0
 def meter_instance_actions(self, project_id, receivers):
     ctxt = get_admin_context()
     self.api.put_metric_data(ctxt,
                              project_id,
                              namespace="SPCS/SYNAPS",
                              metric_name="InstanceActionCount",
                              dimensions={},
                              value=len(receivers),
                              unit="Count",
                              timestamp=utils.strtime(utils.utcnow()),
                              is_admin=True)
     LOG.audit("Meter InstanceAction: %s %s %s", project_id, len(receivers),
               receivers)
Esempio n. 6
0
 def to_dict(self):
     return {
         "user_id": self.user_id,
         "project_id": self.project_id,
         "is_admin": self.is_admin,
         "read_deleted": self.read_deleted,
         "roles": self.roles,
         "remote_address": self.remote_address,
         "timestamp": utils.strtime(self.timestamp),
         "request_id": self.request_id,
         "auth_token": self.auth_token,
         "strategy": self.strategy,
     }
Esempio n. 7
0
 def to_dict(self):
     return {
         'user_id': self.user_id,
         'project_id': self.project_id,
         'is_admin': self.is_admin,
         'read_deleted': self.read_deleted,
         'roles': self.roles,
         'remote_address': self.remote_address,
         'timestamp': utils.strtime(self.timestamp),
         'request_id': self.request_id,
         'auth_token': self.auth_token,
         'strategy': self.strategy
     }
Esempio n. 8
0
    def meter_sms_actions(self, project_id, receivers):
        ctxt = get_admin_context()
        local_receivers = [r for r in receivers if r.startswith("+82")]
        international_receivers = [r for r in receivers if not 
                                   r.startswith("+82")]
        
        self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS",
                                 metric_name="LocalSMSActionCount",
                                 dimensions={}, value=len(local_receivers),
                                 unit="Count",
                                 timestamp=utils.strtime(utils.utcnow()),
                                 is_admin=True)

        self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS",
                                 metric_name="InternationalSMSActionCount",
                                 dimensions={},
                                 value=len(international_receivers),
                                 unit="Count",
                                 timestamp=utils.strtime(utils.utcnow()),
                                 is_admin=True)
        
        LOG.audit("Meter SMS: %s %s %s", project_id, len(receivers), receivers)
Esempio n. 9
0
    def put_metric_data(self, context, project_id, namespace, metric_name,
                        dimensions, value, unit, timestamp=None,
                        is_admin=False):
        admin_namespace = FLAGS.get('admin_namespace')
        if namespace.startswith(admin_namespace) and not is_admin:
            raise AdminRequired()
        
        timestamp = timestamp or utils.strtime(utils.utcnow())
        
        message = {'project_id': project_id, 'namespace':namespace,
                   'metric_name': metric_name, 'dimensions': dimensions,
                   'value':value, 'unit':unit, 'timestamp':timestamp,
                   'context': context.to_dict()}
        
        self.rpc.send_msg(rpc.PUT_METRIC_DATA_MSG_ID, message)
        LOG.info("PUT_METRIC_DATA_MSG sent")

        return {}
Esempio n. 10
0
        def parse_metric_data(metric):
            try:
                dimensions_ = metric.get('dimensions', {})
                dimensions = utils.extract_member_dict(dimensions_)
            except KeyError:
                err = "Unsuitable Dimensions Value - %s" % str(dimensions_)
                raise InvalidParameterValue(err)
        
            metric_name = metric.get('metric_name')
            unit = metric.get('unit', 'None')
            value = metric.get('value')
            req_timestamp = metric.get('timestamp')
            timestamp = req_timestamp if req_timestamp \
                        else utils.strtime(utils.utcnow())

            self.check_metric_name(metric_name)
            self.check_unit(unit)
            
            return metric_name, dimensions, value, unit, timestamp 
Esempio n. 11
0
        def metricalarm_for_json(metricalarm):
            cut = metricalarm.get('alarm_configuration_updated_timestamp')

            alarm_for_json = {
                'actionEnabled':
                metricalarm.get('actions_enabled', False),
                'alarmActions':
                metricalarm.get('alarm_actions', []),
                'alarmArn':
                metricalarm.get('alarm_arn'),
                'alarmConfigurationUpdatedTimestamp':
                utils.strtime(cut),
                'alarmDescription':
                metricalarm.get('alarm_description'),
                'alarmName':
                metricalarm.get('alarm_name'),
                'comparisonOperator':
                metricalarm.get('comparison_operator'),
                'dimensions':
                metricalarm.get('dimensions'),
                'evaluationPeriods':
                metricalarm.get('evaluation_periods'),
                'insufficientDataActions':
                metricalarm.get('insufficient_data_actions', []),
                'metricName':
                metricalarm.get('metric_name'),
                'namespace':
                metricalarm.get('namespace'),
                'okactions':
                metricalarm.get('ok_actions', []),
                'statistic':
                metricalarm.get('statistic'),
                'threshold':
                metricalarm.get('threshold'),
                'unit':
                metricalarm.get('unit'),
            }
            return alarm_for_json
Esempio n. 12
0
 def metricalarm_for_json(metricalarm):
     cut = metricalarm.get('alarm_configuration_updated_timestamp')
     
     alarm_for_json = {
         'actionEnabled': metricalarm.get('actions_enabled', False),
         'alarmActions': metricalarm.get('alarm_actions', []),
         'alarmArn': metricalarm.get('alarm_arn'),
         'alarmConfigurationUpdatedTimestamp': utils.strtime(cut),
         'alarmDescription': metricalarm.get('alarm_description'),
         'alarmName': metricalarm.get('alarm_name'),
         'comparisonOperator': metricalarm.get('comparison_operator'),
         'dimensions': metricalarm.get('dimensions'),
         'evaluationPeriods': metricalarm.get('evaluation_periods'),
         'insufficientDataActions': 
             metricalarm.get('insufficient_data_actions', []),
         'metricName':metricalarm.get('metric_name'),
         'namespace':metricalarm.get('namespace'),
         'okactions':metricalarm.get('ok_actions', []),
         'statistic':metricalarm.get('statistic'),
         'threshold':metricalarm.get('threshold'),
         'unit':metricalarm.get('unit'),
     }
     return alarm_for_json
Esempio n. 13
0
    def _check_alarm(self, alarmkey, alarm):
        period = int(alarm["period"] / 60)
        evaluation_periods = alarm["evaluation_periods"]
        statistic = alarm["statistic"]
        threshold = alarm["threshold"]
        cmp_op = self.CMP_MAP[alarm["comparison_operator"]]
        unit = alarm["unit"]
        state_value = alarm["state_value"]

        now = utils.utcnow()
        end_idx = now.replace(second=0, microsecond=0) - datetools.Minute()
        start_idx = end_idx - (evaluation_periods - 1) * datetools.Minute()
        start_ana_idx = start_idx - datetools.Minute() * period

        func = self.ROLLING_FUNC_MAP[statistic]
        data = func(self.df[statistic].ix[start_ana_idx:end_idx], period, min_periods=0).ix[start_idx:end_idx]

        if statistic == "SampleCount":
            data = data.fillna(0)
        else:
            if unit:
                data = data / utils.UNIT_CONV_MAP[unit]
                threshold = threshold / utils.UNIT_CONV_MAP[unit]

            data = data.dropna()

        query_date = utils.strtime(now)
        reason_data = {
            "period": alarm["period"],
            "queryDate": query_date,
            "recentDatapoints": list(data),
            "startDate": utils.strtime(start_idx),
            "statistic": statistic,
            "threshold": threshold,
            "version": "1.0",
        }
        old_state = {
            "stateReason": alarm.get("reason", ""),
            "stateValue": alarm.get("state_value", "INSUFFICIENT_DATA"),
            "stateReasonData": json.loads(alarm.get("reason_data", "{}")),
        }
        json_reason_data = json.dumps(reason_data)

        if len(data) < evaluation_periods:
            if state_value != "INSUFFICIENT_DATA":
                template = _("Insufficient Data: %d datapoints were unknown.")
                reason = template % (evaluation_periods - len(data))
                new_state = {"stateReason": reason, "stateReasonData": reason_data, "stateValue": "INSUFFICIENT_DATA"}
                self.update_alarm_state(alarmkey, "INSUFFICIENT_DATA", reason, json_reason_data, now)
                self.cass.update_alarm_state(alarmkey, "INSUFFICIENT_DATA", reason, json_reason_data, now)
                self.alarm_history_state_update(alarmkey, alarm, new_state, old_state)
                self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date)
                storm.log("INSUFFICIENT_DATA alarm")
        else:
            crossed = reduce(operator.and_, cmp_op(data, threshold))
            com_op = alarm["comparison_operator"]

            if crossed:
                template = _(
                    "Threshold Crossed: %d datapoints were %s "
                    + "the threshold(%f). "
                    + "The most recent datapoints: %s."
                )
                reason = template % (len(data), self.CMP_STR_MAP[com_op], threshold, str(list(data)))
                if state_value != "ALARM":
                    new_state = {"stateReason": reason, "stateReasonData": reason_data, "stateValue": "ALARM"}

                    self.update_alarm_state(alarmkey, "ALARM", reason, json_reason_data, now)
                    self.cass.update_alarm_state(alarmkey, "ALARM", reason, json_reason_data, now)
                    self.alarm_history_state_update(alarmkey, alarm, new_state, old_state)
                    self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date)
                    storm.log("ALARM alarm")
            else:
                template = _(
                    "Threshold Crossed: %d datapoints were not %s "
                    + "the threshold(%f). "
                    + "The most recent datapoints: %s."
                )
                reason = template % (len(data), self.CMP_STR_MAP[com_op], threshold, str(list(data)))
                if state_value != "OK":
                    new_state = {"stateReason": reason, "stateReasonData": reason_data, "stateValue": "OK"}
                    self.update_alarm_state(alarmkey, "OK", reason, json_reason_data, now)
                    self.cass.update_alarm_state(alarmkey, "OK", reason, json_reason_data, now)
                    self.alarm_history_state_update(alarmkey, alarm, new_state, old_state)
                    self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date)
                    storm.log("OK alarm")
Esempio n. 14
0
    def _check_alarm(self, alarmkey, alarm, query_time=None):
        period = int(alarm['period'] / 60)
        evaluation_periods = alarm['evaluation_periods']
        statistic = alarm['statistic']
        threshold = alarm['threshold']
        alarm_name = alarm['alarm_name']
        cmp_op = self.CMP_MAP[alarm['comparison_operator']]
        unit = alarm['unit']
        state_value = alarm['state_value']
        
        query_time = query_time if query_time else utils.utcnow()
        
        for i in range(self.insufficient_buffer):
            end_idx = (query_time.replace(second=0, microsecond=0) - 
                       (i + 1) * datetools.Minute())
            try:
                end_datapoint = self.df[statistic].ix[end_idx]
            except KeyError:
                end_datapoint = None
            if not isnull(end_datapoint):
                break
            
        start_idx = (end_idx - (period * evaluation_periods) * 
                     datetools.Minute())
        start_ana_idx = start_idx - datetools.Minute() * period
        
        func = self.ROLLING_FUNC_MAP[statistic]
        data = func(self.df[statistic].ix[start_ana_idx:end_idx], period,
                    min_periods=0).ix[start_idx:end_idx:period][1:]
        recent_datapoints = list(data)

        if unit and statistic is not 'SampleCount':
            data = data / utils.UNIT_CONV_MAP[unit]
            threshold = threshold / utils.UNIT_CONV_MAP[unit]
                
        data = data.dropna()

        query_date = utils.strtime(query_time)
        reason_data = {
            "period":alarm['period'],
            "queryDate":query_date,
            "recentDatapoints": recent_datapoints,
            "startDate": utils.strtime(start_idx),
            "statistic":statistic,
            "threshold": threshold,
            "version":"1.0",
        }
        old_state = {'stateReason':alarm.get('reason', ""),
                     'stateValue':alarm.get('state_value',
                                            "INSUFFICIENT_DATA"),
                     'stateReasonData':
                        json.loads(alarm.get('reason_data', "{}"))}
        json_reason_data = json.dumps(reason_data)

        if len(data) == 0:
            if state_value != 'INSUFFICIENT_DATA':
                template = _("Insufficient Data: %d datapoints were unknown.")
                reason = template % (evaluation_periods - len(data))
                new_state = {'stateReason':reason,
                             'stateReasonData':reason_data,
                             'stateValue':'INSUFFICIENT_DATA'}
                self.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA', reason,
                                        json_reason_data, query_time)
                self.cass.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA',
                                             reason, json_reason_data,
                                             query_time)
                self.alarm_history_state_update(alarmkey, alarm,
                                                new_state, old_state)
                self.do_alarm_action(alarmkey, alarm, new_state, old_state,
                                     query_date)
                LOG.audit("Alarm %s status changed to INSUFFICIENT_DATA",
                          alarm_name)
        else:
            sufficient = len(data) >= evaluation_periods
            crossed = (sufficient and 
                       reduce(operator.and_, cmp_op(data, threshold)))
            com_op = alarm['comparison_operator']
            
            if crossed:
                template = _("Threshold Crossed: %d datapoints were %s " + 
                             "the threshold(%f). " + 
                             "The most recent datapoints: %s.")
                reason = template % (evaluation_periods,
                                     self.CMP_STR_MAP[com_op], threshold,
                                     recent_datapoints)
                if state_value != 'ALARM':
                    new_state = {'stateReason':reason,
                                 'stateReasonData':reason_data,
                                 'stateValue':'ALARM'}
                    
                    self.update_alarm_state(alarmkey, 'ALARM', reason,
                                            json_reason_data, query_time)
                    self.cass.update_alarm_state(alarmkey, 'ALARM', reason,
                                                 json_reason_data, query_time)
                    self.alarm_history_state_update(alarmkey, alarm,
                                                    new_state, old_state)
                    self.do_alarm_action(alarmkey, alarm, new_state, old_state,
                                         query_date)                    
                    LOG.audit("Alarm %s status changed to ALARM", alarm_name)
            else:
                template = _("Threshold Crossed: %d datapoints were not %s " + 
                             "the threshold(%f). " + 
                             "The most recent datapoints: %s.")
                reason = template % (evaluation_periods,
                                     self.CMP_STR_MAP[com_op], threshold,
                                     recent_datapoints)
                if state_value != 'OK':
                    new_state = {'stateReason':reason,
                                 'stateReasonData':reason_data,
                                 'stateValue':'OK'}                    
                    self.update_alarm_state(alarmkey, 'OK', reason,
                                            json_reason_data, query_time)
                    self.cass.update_alarm_state(alarmkey, 'OK', reason,
                                                 json_reason_data, query_time)
                    self.alarm_history_state_update(alarmkey, alarm,
                                                    new_state, old_state)
                    self.do_alarm_action(alarmkey, alarm, new_state, old_state,
                                         query_date)                            
                    LOG.audit("Alarm %s status changed to OK", alarm_name)
Esempio n. 15
0
    def put_metric_alarm(self, project_id, metricalarm):
        """
        알람을 DB에 넣고 값이 빈 dictionary 를 반환한다.
        메트릭 유무 확인
        알람 히스토리 발생.
        """
        def metricalarm_for_json(metricalarm):
            alarm_for_json = {
                'actionEnabled': metricalarm.get('actions_enabled', False),
                'alarmActions': metricalarm.get('alarm_actions', []),
                'alarmArn': metricalarm.get('alarm_arn'),
                'alarmConfigurationUpdatedTimestamp': 
                      metricalarm.get('alarm_configuration_updated_timestamp'),
                'alarmDescription': metricalarm.get('alarm_description'),
                'alarmName': metricalarm.get('alarm_name'),
                'comparisonOperator': metricalarm.get('comparison_operator'),
                'dimensions': metricalarm.get('dimensions'),
                'evaluationPeriods': metricalarm.get('evaluation_periods'),
                'insufficientDataActions': 
                    metricalarm.get('insufficient_data_actions', []),
                'metricName':metricalarm.get('metric_name'),
                'namespace':metricalarm.get('namespace'),
                'okactions':metricalarm.get('ok_actions', []),
                'statistic':metricalarm.get('statistic'),
                'threshold':metricalarm.get('threshold'),
                'unit':metricalarm.get('unit'),
            }
            return alarm_for_json

        now = utils.utcnow()
        metricalarm = metricalarm.to_columns()
        
        # 메트릭 유무 확인
        metric_key = self.cass.get_metric_key_or_create(
            project_id=project_id,
            namespace=metricalarm['namespace'],
            metric_name=metricalarm['metric_name'],
            dimensions=json.loads(metricalarm['dimensions']),
            unit=metricalarm['unit'],
        )
        
        metricalarm['project_id'] = project_id
        metricalarm['metric_key'] = metric_key
        metricalarm['alarm_arn'] = "arn:spcs:synaps:%s:alarm:%s" % (
            project_id, metricalarm['alarm_name']
        )
        metricalarm['alarm_configuration_updated_timestamp'] = now
        
        # 알람 유무 확인
        alarm_key = self.cass.get_metric_alarm_key(
            project_id=project_id, alarm_name=metricalarm['alarm_name']
        )
        
        
        if alarm_key:            
            history_type = 'Update'
            before_alarm = self.cass.get_metric_alarm(alarm_key)
            if before_alarm['metric_key'] != metricalarm['metric_key']:
                raise InvalidRequest("Metric cannot be changed.")
            
            metricalarm['state_updated_timestamp'] = \
                before_alarm['state_updated_timestamp']
            metricalarm['state_reason'] = before_alarm['state_reason']
            metricalarm['state_reason_data'] = \
                before_alarm['state_reason_data']
            metricalarm['state_value'] = before_alarm['state_value']
            
        else:            
            history_type = "Create"
            alarm_key = uuid.uuid4()
            metricalarm['state_updated_timestamp'] = utils.utcnow()
            metricalarm['state_reason'] = "Unchecked: Initial alarm creation"
            metricalarm['state_reason_data'] = json.dumps({})
            metricalarm['state_value'] = "INSUFFICIENT_DATA"
            
        
        # insert alarm into database
        self.cass.put_metric_alarm(alarm_key, metricalarm)
        LOG.debug("metric alarm inserted alarm key: %s" % (alarm_key))

        # to make json, convert datetime type into str        
        metricalarm['state_updated_timestamp'] = utils.strtime(
            metricalarm['state_updated_timestamp']
        )
        metricalarm['alarm_configuration_updated_timestamp'] = utils.strtime(
            metricalarm['alarm_configuration_updated_timestamp']
        )
        metricalarm['metric_key'] = str(metric_key)
        
        if history_type == "Update":
            history_data = json.dumps({
                'updatedAlarm':metricalarm_for_json(metricalarm),
                'type':history_type,
                'version': '1.0'
            })
            summary = "Alarm %s updated" % metricalarm['alarm_name']
        else:
            history_data = json.dumps({
                'createdAlarm': metricalarm_for_json(metricalarm),
                'type':history_type, 'version': '1.0'
            })
            summary = "Alarm %s created" % metricalarm['alarm_name']
        
        history_key = uuid.uuid4()
        history_column = {
            'project_id': project_id,
            'alarm_key': alarm_key,
            'alarm_name': metricalarm['alarm_name'],
            'history_data': history_data,
            'history_item_type': 'ConfigurationUpdate',
            'history_summary':summary,
            'timestamp': utils.utcnow()
        }
            
        self.cass.insert_alarm_history(history_key, history_column)
        
        message = {'project_id': project_id, 'metric_key': str(metric_key),
                   'metricalarm': metricalarm}
        self.rpc.send_msg(rpc.PUT_METRIC_ALARM_MSG_ID, message)
        LOG.info("PUT_METRIC_ALARM_MSG sent")

        return {}
Esempio n. 16
0
    def put_metric_alarm(self, context, project_id, metricalarm):
        """
        Send put metric alarm message to Storm 
        """
        def _validate_actions(alarm):
            for actions in (alarm.ok_actions, alarm.insufficient_data_actions,
                            alarm.alarm_actions):
                for action in actions:
                    if utils.validate_groupnotification_action(action):
                        group = utils.parse_groupnotification_action(action)
                        if not self.cass.get_notification_group(group):
                            raise InvalidNotificationGroup()

        now = utils.utcnow()
        _validate_actions(metricalarm)
        metricalarm = metricalarm.to_columns()
        alarm_name = metricalarm['alarm_name']
        namespace = metricalarm['namespace']
        metric_name = metricalarm['metric_name']
        dimensions = json.loads(metricalarm['dimensions'])

        # check if we have metric in database
        metric_key = self.cass.get_metric_key_or_create(
            project_id=project_id,
            namespace=namespace,
            metric_name=metric_name,
            dimensions=dimensions,
            unit=metricalarm['unit'])

        update_data = {
            'project_id': project_id,
            'metric_key': str(metric_key),
            'alarm_arn':
            "arn:spcs:synaps:%s:alarm:%s" % (project_id, alarm_name),
            'alarm_configuration_updated_timestamp': utils.strtime(now)
        }
        metricalarm.update(update_data)

        # check if metric is changed
        alarm_key = self.cass.get_metric_alarm_key(project_id=project_id,
                                                   alarm_name=alarm_name)

        if alarm_key:
            original_alarm = self.cass.get_metric_alarm(alarm_key)
            if (str(original_alarm['metric_key']) != str(
                    metricalarm['metric_key'])):
                raise InvalidRequest("Metric cannot be changed. "
                                     "Delete alarm and retry.")
        else:
            # If alarm is newly added, check quotas
            # check alarm quota per project
            project_quota = FLAGS.get('alarm_quota_per_project')
            alarms_in_project = self.cass.get_alarm_count(project_id)
            if alarms_in_project >= project_quota:
                LOG.info("Too many alarms(%d) in the project %s",
                         alarms_in_project, project_id)
                raise ProjectAlarmQuotaExceeded()

            # check alarm quota per metric
            metric_quota = FLAGS.get('alarm_quota_per_metric')
            alarms_per_metric = self.cass.get_alarms_per_metric_count(
                project_id, namespace, metric_name, dimensions)
            if alarms_per_metric >= metric_quota:
                LOG.info("Too many alarms(%d) for this metric",
                         alarms_per_metric)
                raise MetricAlarmQuotaExceeded()

        message = {
            'project_id': project_id,
            'metric_key': str(metric_key),
            'metricalarm': metricalarm,
            'context': context.to_dict()
        }
        self.rpc.send_msg(rpc.PUT_METRIC_ALARM_MSG_ID, message)
        LOG.info("PUT_METRIC_ALARM_MSG sent")

        return {}
Esempio n. 17
0
    def _check_alarm(self, alarmkey, alarm, query_time=None):
        period = int(alarm['period'] / 60)
        evaluation_periods = alarm['evaluation_periods']
        statistic = alarm['statistic']
        threshold = alarm['threshold']
        alarm_name = alarm['alarm_name']
        cmp_op = self.CMP_MAP[alarm['comparison_operator']]
        unit = alarm['unit']
        state_value = alarm['state_value']

        query_time = query_time if query_time else utils.utcnow()

        for i in range(self.insufficient_buffer):
            end_idx = (query_time.replace(second=0, microsecond=0) -
                       (i + 1) * datetools.Minute())
            try:
                end_datapoint = self.df[statistic].ix[end_idx]
            except KeyError:
                end_datapoint = None
            if not isnull(end_datapoint):
                break

        start_idx = (end_idx -
                     (period * evaluation_periods) * datetools.Minute())
        start_ana_idx = start_idx - datetools.Minute() * period

        func = self.ROLLING_FUNC_MAP[statistic]
        data = func(self.df[statistic].ix[start_ana_idx:end_idx],
                    period,
                    min_periods=0).ix[start_idx:end_idx:period][1:]
        recent_datapoints = list(data)

        if unit and statistic is not 'SampleCount':
            data = data / utils.UNIT_CONV_MAP[unit]
            threshold = threshold / utils.UNIT_CONV_MAP[unit]

        data = data.dropna()

        query_date = utils.strtime(query_time)
        reason_data = {
            "period": alarm['period'],
            "queryDate": query_date,
            "recentDatapoints": recent_datapoints,
            "startDate": utils.strtime(start_idx),
            "statistic": statistic,
            "threshold": threshold,
            "version": "1.0",
        }
        old_state = {
            'stateReason': alarm.get('reason', ""),
            'stateValue': alarm.get('state_value', "INSUFFICIENT_DATA"),
            'stateReasonData': json.loads(alarm.get('reason_data', "{}"))
        }
        json_reason_data = json.dumps(reason_data)

        if len(data) == 0:
            if state_value != 'INSUFFICIENT_DATA':
                template = _("Insufficient Data: %d datapoints were unknown.")
                reason = template % (evaluation_periods - len(data))
                new_state = {
                    'stateReason': reason,
                    'stateReasonData': reason_data,
                    'stateValue': 'INSUFFICIENT_DATA'
                }
                self.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA', reason,
                                        json_reason_data, query_time)
                self.cass.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA',
                                             reason, json_reason_data,
                                             query_time)
                self.alarm_history_state_update(alarmkey, alarm, new_state,
                                                old_state)
                self.do_alarm_action(alarmkey, alarm, new_state, old_state,
                                     query_date)
                LOG.audit("Alarm %s status changed to INSUFFICIENT_DATA",
                          alarm_name)
        else:
            sufficient = len(data) >= evaluation_periods
            crossed = (sufficient
                       and reduce(operator.and_, cmp_op(data, threshold)))
            com_op = alarm['comparison_operator']

            if crossed:
                template = _("Threshold Crossed: %d datapoints were %s " +
                             "the threshold(%f). " +
                             "The most recent datapoints: %s.")
                reason = template % (evaluation_periods,
                                     self.CMP_STR_MAP[com_op], threshold,
                                     recent_datapoints)
                if state_value != 'ALARM':
                    new_state = {
                        'stateReason': reason,
                        'stateReasonData': reason_data,
                        'stateValue': 'ALARM'
                    }

                    self.update_alarm_state(alarmkey, 'ALARM', reason,
                                            json_reason_data, query_time)
                    self.cass.update_alarm_state(alarmkey, 'ALARM', reason,
                                                 json_reason_data, query_time)
                    self.alarm_history_state_update(alarmkey, alarm, new_state,
                                                    old_state)
                    self.do_alarm_action(alarmkey, alarm, new_state, old_state,
                                         query_date)
                    LOG.audit("Alarm %s status changed to ALARM", alarm_name)
            else:
                template = _("Threshold Crossed: %d datapoints were not %s " +
                             "the threshold(%f). " +
                             "The most recent datapoints: %s.")
                reason = template % (evaluation_periods,
                                     self.CMP_STR_MAP[com_op], threshold,
                                     recent_datapoints)
                if state_value != 'OK':
                    new_state = {
                        'stateReason': reason,
                        'stateReasonData': reason_data,
                        'stateValue': 'OK'
                    }
                    self.update_alarm_state(alarmkey, 'OK', reason,
                                            json_reason_data, query_time)
                    self.cass.update_alarm_state(alarmkey, 'OK', reason,
                                                 json_reason_data, query_time)
                    self.alarm_history_state_update(alarmkey, alarm, new_state,
                                                    old_state)
                    self.do_alarm_action(alarmkey, alarm, new_state, old_state,
                                         query_date)
                    LOG.audit("Alarm %s status changed to OK", alarm_name)
Esempio n. 18
0
    def put_metric_alarm(self, context, project_id, metricalarm):
        """
        Send put metric alarm message to Storm 
        """
        def _validate_actions(alarm):
            for actions in (alarm.ok_actions, alarm.insufficient_data_actions, 
                            alarm.alarm_actions):
                for action in actions:
                    if utils.validate_groupnotification_action(action):
                        group = utils.parse_groupnotification_action(action)
                        if not self.cass.get_notification_group(group):
                            raise InvalidNotificationGroup()
                                            
        
        now = utils.utcnow()
        _validate_actions(metricalarm)
        metricalarm = metricalarm.to_columns()
        alarm_name = metricalarm['alarm_name']
        namespace = metricalarm['namespace']
        metric_name = metricalarm['metric_name']
        dimensions = json.loads(metricalarm['dimensions'])
        
        # check if we have metric in database
        metric_key = self.cass.get_metric_key_or_create(project_id=project_id,
            namespace=namespace, metric_name=metric_name,
            dimensions=dimensions, unit=metricalarm['unit'])
        
        update_data = {
            'project_id': project_id,
            'metric_key': str(metric_key),
            'alarm_arn': "arn:spcs:synaps:%s:alarm:%s" % (project_id,
                                                          alarm_name),
            'alarm_configuration_updated_timestamp': utils.strtime(now)
        }
        metricalarm.update(update_data)
        
        # check if metric is changed 
        alarm_key = self.cass.get_metric_alarm_key(project_id=project_id,
                                                   alarm_name=alarm_name)
        
        if alarm_key:            
            original_alarm = self.cass.get_metric_alarm(alarm_key)
            if (str(original_alarm['metric_key']) != 
                str(metricalarm['metric_key'])):
                raise InvalidRequest("Metric cannot be changed. "
                                     "Delete alarm and retry.")
        else:
            # If alarm is newly added, check quotas
            # check alarm quota per project
            project_quota = FLAGS.get('alarm_quota_per_project')
            alarms_in_project = self.cass.get_alarm_count(project_id)
            if alarms_in_project >= project_quota:
                LOG.info("Too many alarms(%d) in the project %s",
                         alarms_in_project, project_id)
                raise ProjectAlarmQuotaExceeded()
            
            # check alarm quota per metric  
            metric_quota = FLAGS.get('alarm_quota_per_metric')
            alarms_per_metric = self.cass.get_alarms_per_metric_count(
                            project_id, namespace, metric_name, dimensions)
            if alarms_per_metric >= metric_quota:
                LOG.info("Too many alarms(%d) for this metric",
                         alarms_per_metric)
                raise MetricAlarmQuotaExceeded()
        
        message = {'project_id': project_id, 'metric_key': str(metric_key),
                   'metricalarm': metricalarm, 'context': context.to_dict()}
        self.rpc.send_msg(rpc.PUT_METRIC_ALARM_MSG_ID, message)
        LOG.info("PUT_METRIC_ALARM_MSG sent")

        return {}