示例#1
0
    def check_rule(alarm):
        if (not pecan.request.cfg.api.enable_combination_alarms
                and alarm.type == 'combination'):
            raise base.ClientSideError("Unavailable alarm type")

        rule = '%s_rule' % alarm.type
        if getattr(alarm, rule) in (wtypes.Unset, None):
            error = _("%(rule)s must be set for %(type)s"
                      " type alarm") % {
                          "rule": rule,
                          "type": alarm.type
                      }
            raise base.ClientSideError(error)

        rule_set = None
        for ext in ALARMS_RULES:
            name = "%s_rule" % ext.name
            if getattr(alarm, name):
                if rule_set is None:
                    rule_set = name
                else:
                    error = _("%(rule1)s and %(rule2)s cannot be set at the "
                              "same time") % {
                                  'rule1': rule_set,
                                  'rule2': name
                              }
                    raise base.ClientSideError(error)
示例#2
0
文件: alarms.py 项目: sileht/aodh
    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.alarm_storage_conn
        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()
        # make sure alarms are unique by name per project.
        alarms = list(conn.get_alarms(name=data.name, project=data.project_id))
        if alarms:
            raise base.ClientSideError(_("Alarm with name='%s' exists") %
                                       data.name,
                                       status_code=409)

        try:
            alarm_in = models.Alarm(**change)
        except Exception:
            LOG.exception(_("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)
示例#3
0
    def valid_composite_rule(rules):
        if isinstance(rules, dict) and len(rules) == 1:
            and_or_key = list(rules)[0]
            if and_or_key not in ('and', 'or'):
                raise base.ClientSideError(
                    _('Threshold rules should be combined with "and" or "or"'))
            if isinstance(rules[and_or_key], list):
                for sub_rule in rules[and_or_key]:
                    CompositeRule.valid_composite_rule(sub_rule)
            else:
                raise InvalidCompositeRule(rules)
        elif isinstance(rules, dict):
            rule_type = rules.pop('type', None)
            if not rule_type:
                raise base.ClientSideError(_('type must be set in every rule'))

            if rule_type not in CompositeRule.threshold_plugins:
                plugins = sorted(CompositeRule.threshold_plugins.names())
                err = _('Unsupported sub-rule type :%(rule)s in composite '
                        'rule, should be one of: %(plugins)s') % {
                            'rule': rule_type,
                            'plugins': plugins
                        }
                raise base.ClientSideError(err)
            plugin = CompositeRule.threshold_plugins[rule_type].plugin
            wjson.fromjson(plugin, rules)
            rule_dict = plugin(**rules).as_dict()
            rules.update(rule_dict)
            rules.update(type=rule_type)
        else:
            raise InvalidCompositeRule(rules)
示例#4
0
文件: alarms.py 项目: sileht/aodh
    def put(self, data):
        """Modify this alarm.

        :param data: an alarm within the request body.
        """

        rbac.enforce('change_alarm', pecan.request.headers,
                     pecan.request.enforcer)

        # Ensure alarm exists
        alarm_in = self._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

        # make sure alarms are unique by name per project.
        if alarm_in.name != data.name:
            alarms = list(
                self.conn.get_alarms(name=data.name, project=data.project_id))
            if alarms:
                raise base.ClientSideError(_("Alarm with name=%s exists") %
                                           data.name,
                                           status_code=409)

        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(_("Error while putting alarm: %s") % updated_alarm)
            raise base.ClientSideError(_("Alarm incorrect"))

        alarm = self.conn.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)
示例#5
0
    def _check_ceilometer_sample_api(cls):
        # Check it only once
        if cls.ceilometer_sample_api_is_supported is None:

            auth_config = pecan.request.cfg.service_credentials
            client = ceiloclient.get_client(
                version=2,
                session=keystone_client.get_session(pecan.request.cfg),
                # ceiloclient adapter options
                region_name=auth_config.region_name,
                interface=auth_config.interface,
            )
            try:
                client.statistics.list(
                    meter_name="idontthinkthatexistsbutwhatever")
            except Exception as e:
                if isinstance(e, ceiloexc.HTTPException):
                    if e.code == 410:
                        cls.ceilometer_sample_api_is_supported = False
                    elif e.code < 500:
                        cls.ceilometer_sample_api_is_supported = True
                    else:
                        raise
                else:
                    raise
            else:
                # I don't think this meter can exist but how known
                cls.ceilometer_sample_api_is_supported = True

        if cls.ceilometer_sample_api_is_supported is False:
            raise base.ClientSideError(
                "This telemetry installation is not configured to support"
                "alarm of type 'threshold")
示例#6
0
 def validate_alarm(cls, alarm):
     alarm_rule = getattr(alarm, "%s_rule" % alarm.type)
     aggregation_method = alarm_rule.aggregation_method
     if aggregation_method not in cls._get_aggregation_methods():
         raise base.ClientSideError(
             'aggregation_method should be in %s not %s' % (
                 cls._get_aggregation_methods(), aggregation_method))
示例#7
0
 def update_hook(alarm):
     # should check if there is any circle in the dependency, but for
     # efficiency reason, here only check alarm cannot depend on itself
     if alarm.alarm_id in alarm.combination_rule.alarm_ids:
         raise base.ClientSideError(
             _('Cannot specify alarm %s itself in combination rule') %
             alarm.alarm_id)
示例#8
0
 def validate(rule):
     rule.alarm_ids = sorted(set(rule.alarm_ids), key=rule.alarm_ids.index)
     if len(rule.alarm_ids) <= 1:
         raise base.ClientSideError(_('Alarm combination rule should '
                                      'contain at least two different '
                                      'alarm ids.'))
     return rule
示例#9
0
文件: alarms.py 项目: amar266/aodh
 def validate(tc):
     if tc.timezone:
         try:
             pytz.timezone(tc.timezone)
         except Exception:
             raise base.ClientSideError(
                 _("Timezone %s is not valid") % tc.timezone)
     return tc
示例#10
0
文件: event.py 项目: TequieroD/aodh
 def validate_alarm(cls, alarm):
     super(AlarmEventRule, cls).validate_alarm(alarm)
     for i in alarm.event_rule.query:
         i._get_value_as_type()
         try:
             _q_validator({"field": i.field, "op": i.op, "value": i.type})
         except voluptuous.MultipleInvalid as e:
             raise base.ClientSideError(
                 _("Query value or traits invalid: %s") % str(e))
示例#11
0
 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("String %s is not a valid isotime", isotime)
         msg = _('Failed to parse the timestamp value %s') % isotime
         raise base.ClientSideError(msg)
示例#12
0
 def validate(value):
     try:
         json.dumps(value)
     except TypeError:
         raise base.ClientSideError(
             _('%s is not JSON serializable') % value)
     else:
         CompositeRule.valid_composite_rule(value)
         return value
示例#13
0
    def validate_alarm(cls, alarm):
        super(AggregationMetricByResourcesLookupRule,
              cls).validate_alarm(alarm)

        rule = alarm.gnocchi_aggregation_by_resources_threshold_rule

        # check the query string is a valid json
        try:
            query = json.loads(rule.query)
        except ValueError:
            raise wsme.exc.InvalidInput('rule/query', rule.query)

        conf = pecan.request.cfg

        # Scope the alarm to the project id if needed
        auth_project = v2_utils.get_auth_project(alarm.project_id)
        if auth_project:

            perms_filter = {"=": {"created_by_project_id": auth_project}}

            external_project_owner = cls.get_external_project_owner()
            if external_project_owner:
                perms_filter = {"or": [
                    perms_filter,
                    {"and": [
                        {"=": {"created_by_project_id":
                               external_project_owner}},
                        {"=": {"project_id": auth_project}}]}
                ]}

            query = {"and": [perms_filter, query]}
            rule.query = json.dumps(query)

        gnocchi_client = client.Client(
            '1', keystone_client.get_session(conf),
            adapter_options={
                'interface': conf.service_credentials.interface,
                'region_name': conf.service_credentials.region_name})
        try:
            gnocchi_client.metric.aggregation(
                metrics=rule.metric,
                query=query,
                aggregation=rule.aggregation_method,
                needed_overlap=0,
                start="-1 day",
                stop="now",
                resource_type=rule.resource_type)
        except exceptions.ClientException as e:
            if e.code == 404:
                # NOTE(sileht): We are fine here, we just want to ensure the
                # 'query' payload is valid for Gnocchi If the metric
                # doesn't exists yet, it doesn't matter
                return
            raise base.ClientSideError(e.message, status_code=e.code)
        except Exception as e:
            raise GnocchiUnavailable(e)
示例#14
0
文件: alarms.py 项目: amar266/aodh
    def check_alarm_actions(alarm):
        max_actions = pecan.request.cfg.api.alarm_max_actions
        for state in state_kind:
            actions_name = state.replace(" ", "_") + '_actions'
            actions = getattr(alarm, actions_name)
            if not actions:
                continue

            action_set = set(actions)
            if len(actions) != len(action_set):
                LOG.info(
                    'duplicate actions are found: %s, '
                    'remove duplicate ones', actions)
                actions = list(action_set)
                setattr(alarm, actions_name, actions)

            if 0 < max_actions < len(actions):
                error = _('%(name)s count exceeds maximum value '
                          '%(maximum)d') % {
                              "name": actions_name,
                              "maximum": max_actions
                          }
                raise base.ClientSideError(error)

            limited = rbac.get_limited_to_project(pecan.request.headers,
                                                  pecan.request.enforcer)

            for action in actions:
                try:
                    url = netutils.urlsplit(action)
                except Exception:
                    error = _("Unable to parse action %s") % action
                    raise base.ClientSideError(error)
                if url.scheme not in ACTIONS_SCHEMA:
                    error = _("Unsupported action %s") % action
                    raise base.ClientSideError(error)
                if limited and url.scheme in ('log', 'test'):
                    error = _('You are not authorized to create '
                              'action: %s') % action
                    raise base.ClientSideError(error, status_code=401)
示例#15
0
    def _get_aggregation_methods():
        conf = pecan.request.cfg
        gnocchi_client = client.Client(
            '1', keystone_client.get_session(conf),
            interface=conf.service_credentials.interface,
            region_name=conf.service_credentials.region_name)

        try:
            return gnocchi_client.capabilities.list().get(
                'aggregation_methods', [])
        except exceptions.ClientException as e:
            raise base.ClientSideError(e.message, status_code=e.code)
        except Exception as e:
            raise GnocchiUnavailable(e)
示例#16
0
文件: alarms.py 项目: amar266/aodh
    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
            data.state_reason = ALARM_REASON_MANUAL
        else:
            data.state_timestamp = alarm_in.state_timestamp
            data.state_reason = alarm_in.state_reason

        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("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)
示例#17
0
    def validate(alarm):
        Alarm.check_rule(alarm)
        Alarm.check_alarm_actions(alarm)

        ALARMS_RULES[alarm.type].plugin.validate_alarm(alarm)

        if alarm.time_constraints:
            tc_names = [tc.name for tc in alarm.time_constraints]
            if len(tc_names) > len(set(tc_names)):
                error = _("Time constraint names must be "
                          "unique for a given alarm.")
                raise base.ClientSideError(error)

        return alarm
示例#18
0
文件: alarms.py 项目: amar266/aodh
    def check_rule(alarm):
        rule = '%s_rule' % alarm.type
        if getattr(alarm, rule) in (wtypes.Unset, None):
            error = _("%(rule)s must be set for %(type)s"
                      " type alarm") % {
                          "rule": rule,
                          "type": alarm.type
                      }
            raise base.ClientSideError(error)

        rule_set = None
        for ext in ALARMS_RULES:
            name = "%s_rule" % ext.name
            if getattr(alarm, name):
                if rule_set is None:
                    rule_set = name
                else:
                    error = _("%(rule1)s and %(rule2)s cannot be set at the "
                              "same time") % {
                                  'rule1': rule_set,
                                  'rule2': name
                              }
                    raise base.ClientSideError(error)
示例#19
0
    def validate(self, visibility_field):
        """Validates the query content and does the necessary conversions."""
        if self.original_query.filter is wtypes.Unset:
            self.filter_expr = None
        else:
            try:
                self.filter_expr = json.loads(self.original_query.filter)
                self._validate_filter(self.filter_expr)
            except (ValueError, jsonschema.exceptions.ValidationError) as e:
                raise base.ClientSideError(
                    _("Filter expression not valid: %s") % str(e))
            self._replace_isotime_with_datetime(self.filter_expr)
            self._convert_operator_to_lower_case(self.filter_expr)
            self._normalize_field_names_for_db_model(self.filter_expr)

        self._force_visibility(visibility_field)

        if self.original_query.orderby is wtypes.Unset:
            self.orderby = None
        else:
            try:
                self.orderby = json.loads(self.original_query.orderby)
                self._validate_orderby(self.orderby)
            except (ValueError, jsonschema.exceptions.ValidationError) as e:
                raise base.ClientSideError(
                    _("Order-by expression not valid: %s") % e)
            self._convert_orderby_to_lower_case(self.orderby)
            self._normalize_field_names_in_orderby(self.orderby)

        if self.original_query.limit is wtypes.Unset:
            self.limit = None
        else:
            self.limit = self.original_query.limit

        if self.limit is not None and self.limit <= 0:
            msg = _('Limit should be positive')
            raise base.ClientSideError(msg)
示例#20
0
文件: alarms.py 项目: yi-cloud/aodh
    def update_actions(self, old_alarm=None):
        trustor_user_id = pecan.request.headers.get('X-User-Id')
        trustor_project_id = pecan.request.headers.get('X-Project-Id')
        roles = pecan.request.headers.get('X-Roles', '')
        if roles:
            roles = roles.split(',')
        else:
            roles = []
        auth_plugin = pecan.request.environ.get('keystone.token_auth')

        if old_alarm:
            prev_trust_ids = set(old_alarm._get_existing_trust_ids())
        else:
            prev_trust_ids = set()
        trust_id = prev_trust_ids.pop() if prev_trust_ids else None
        trust_id_used = False

        for actions in (self.ok_actions, self.alarm_actions,
                        self.insufficient_data_actions):
            if actions is not None:
                for index, action in enumerate(actions[:]):
                    url = netutils.urlsplit(action)
                    if self._is_trust_url(url):
                        if '@' in url.netloc:
                            errmsg = _("trust URL cannot contain a trust ID.")
                            raise base.ClientSideError(errmsg)
                        if trust_id is None:
                            # We have a trust action without a trust ID,
                            # create it
                            trust_id = keystone_client.create_trust_id(
                                pecan.request.cfg, trustor_user_id,
                                trustor_project_id, roles, auth_plugin)
                        if trust_id_used:
                            pw = ''
                        else:
                            pw = ':delete'
                            trust_id_used = True
                        netloc = '%s%s@%s' % (trust_id, pw, url.netloc)
                        url = urlparse.SplitResult(url.scheme, netloc,
                                                   url.path, url.query,
                                                   url.fragment)
                        actions[index] = url.geturl()
        if trust_id is not None and not trust_id_used:
            prev_trust_ids.add(trust_id)
        for old_trust_id in prev_trust_ids:
            keystone_client.delete_trust_id(pecan.request.cfg, old_trust_id,
                                            auth_plugin)
示例#21
0
    def validate_alarm(cls, alarm):
        super(MetricOfResourceRule, cls).validate_alarm(alarm)

        conf = pecan.request.cfg
        gnocchi_client = client.Client(
            '1',
            keystone_client.get_session(conf),
            interface=conf.service_credentials.interface,
            region_name=conf.service_credentials.region_name)

        rule = alarm.gnocchi_resources_threshold_rule
        try:
            gnocchi_client.resource.get(rule.resource_type, rule.resource_id)
        except exceptions.ClientException as e:
            raise base.ClientSideError(e.message, status_code=e.code)
        except Exception as e:
            raise GnocchiUnavailable(e)
示例#22
0
    def validate_alarm(cls, alarm):
        super(AggregationMetricByResourcesLookupRule,
              cls).validate_alarm(alarm)

        rule = alarm.gnocchi_aggregation_by_resources_threshold_rule

        # check the query string is a valid json
        try:
            query = jsonutils.loads(rule.query)
        except ValueError:
            raise wsme.exc.InvalidInput('rule/query', rule.query)

        # Scope the alarm to the project id if needed
        auth_project = v2_utils.get_auth_project(alarm.project_id)
        if auth_project:
            query = {
                "and": [{
                    "=": {
                        "created_by_project_id": auth_project
                    }
                }, query]
            }
            rule.query = jsonutils.dumps(query)

        conf = pecan.request.cfg
        gnocchi_client = client.Client(
            '1',
            keystone_client.get_session(conf),
            interface=conf.service_credentials.interface,
            region_name=conf.service_credentials.region_name,
            endpoint_override=conf.gnocchi_url)

        try:
            gnocchi_client.metric.aggregation(
                metrics=rule.metric,
                query=query,
                aggregation=rule.aggregation_method,
                needed_overlap=0,
                resource_type=rule.resource_type)
        except exceptions.ClientException as e:
            raise base.ClientSideError(e.message, status_code=e.code)
        except Exception as e:
            raise GnocchiUnavailable(e)
示例#23
0
文件: alarms.py 项目: amar266/aodh
    def validate(alarm):
        if alarm.type == 'threshold':
            warnings.simplefilter("always")
            debtcollector.deprecate(
                "Ceilometer's API is deprecated as of Ocata. Therefore, "
                " threshold rule alarms are no longer supported.",
                version="5.0.0")

        Alarm.check_rule(alarm)
        Alarm.check_alarm_actions(alarm)

        ALARMS_RULES[alarm.type].plugin.validate_alarm(alarm)

        if alarm.time_constraints:
            tc_names = [tc.name for tc in alarm.time_constraints]
            if len(tc_names) > len(set(tc_names)):
                error = _("Time constraint names must be "
                          "unique for a given alarm.")
                raise base.ClientSideError(error)

        return alarm
示例#24
0
文件: gnocchi.py 项目: sileht/aodh
    def validate_alarm(cls, alarm):
        super(MetricOfResourceRule,
              cls).validate_alarm(alarm)

        rule = alarm.gnocchi_resources_threshold_rule
        ks_client = keystone_client.get_client(pecan.request.cfg)
        gnocchi_url = pecan.request.cfg.gnocchi_url
        headers = {'Content-Type': "application/json",
                   'X-Auth-Token': ks_client.auth_token}
        try:
            r = requests.get("%s/v1/resource/%s/%s" % (
                gnocchi_url, rule.resource_type,
                rule.resource_id),
                headers=headers)
        except requests.ConnectionError as e:
            raise GnocchiUnavailable(e)
        if r.status_code == 404:
            raise base.EntityNotFound('gnocchi resource',
                                      rule.resource_id)
        elif r.status_code // 200 != 1:
            raise base.ClientSideError(r.content, status_code=r.status_code)
示例#25
0
    def put_state(self, state):
        """Set the state of this alarm.

        :param state: an alarm state within the request body.
        """

        alarm = self._enforce_rbac('change_alarm_state')

        # note(sileht): body are not validated by wsme
        # Workaround for https://bugs.launchpad.net/wsme/+bug/1227229
        if state not in state_kind:
            raise base.ClientSideError(_("state invalid"))
        now = timeutils.utcnow()
        alarm.state = state
        alarm.state_timestamp = now
        alarm = pecan.request.storage.update_alarm(alarm)
        change = {'state': alarm.state}
        self._record_change(change,
                            now,
                            on_behalf_of=alarm.project_id,
                            type=models.AlarmChange.STATE_TRANSITION)
        return alarm.state
示例#26
0
文件: gnocchi.py 项目: sileht/aodh
    def validate_alarm(cls, alarm):
        super(AggregationMetricByResourcesLookupRule,
              cls).validate_alarm(alarm)

        rule = alarm.gnocchi_aggregation_by_resources_threshold_rule

        # check the query string is a valid json
        try:
            query = jsonutils.loads(rule.query)
        except ValueError:
            raise wsme.exc.InvalidInput('rule/query', rule.query)

        # Scope the alarm to the project id if needed
        auth_project = v2_utils.get_auth_project(alarm.project_id)
        if auth_project:
            rule.query = jsonutils.dumps({
                "and": [{"=": {"created_by_project_id": auth_project}},
                        query]})

        # Delegate the query validation to gnocchi
        ks_client = keystone_client.get_client(pecan.request.cfg)
        request = {
            'url': "%s/v1/aggregation/resource/%s/metric/%s" % (
                pecan.request.cfg.gnocchi_url,
                rule.resource_type,
                rule.metric),
            'headers': {'Content-Type': "application/json",
                        'X-Auth-Token': ks_client.auth_token},
            'params': {'aggregation': rule.aggregation_method},
            'data': rule.query,
        }

        try:
            r = requests.post(**request)
        except requests.ConnectionError as e:
            raise GnocchiUnavailable(e)
        if r.status_code // 200 != 1:
            raise base.ClientSideError(r.content, status_code=r.status_code)