Esempio n. 1
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") % 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)

        self.limit = (None if self.original_query.limit is wtypes.Unset else
                      self.original_query.limit)

        self.limit = v2_utils.enforce_limit(self.limit)
Esempio n. 2
0
def _event_query_to_event_filter(q):
    evt_model_filter = {
        'event_type': None,
        'message_id': None,
        'start_timestamp': None,
        'end_timestamp': None
    }
    filters = _build_rbac_query_filters()
    traits_filter = filters['t_filter']
    admin_proj = filters['admin_proj']

    for i in q:
        if not i.op:
            i.op = 'eq'
        elif i.op not in base.operation_kind:
            error = (_('Operator %(operator)s is not supported. The supported'
                       ' operators are: %(supported)s') %
                     {'operator': i.op, 'supported': base.operation_kind})
            raise base.ClientSideError(error)
        if i.field in evt_model_filter:
            if i.op != 'eq':
                error = (_('Operator %(operator)s is not supported. Only'
                           ' equality operator is available for field'
                           ' %(field)s') %
                         {'operator': i.op, 'field': i.field})
                raise base.ClientSideError(error)
            evt_model_filter[i.field] = i.value
        else:
            trait_type = i.type or 'string'
            traits_filter.append({"key": i.field,
                                  trait_type: i._get_value_as_type(),
                                  "op": i.op})
    return storage.EventFilter(traits_filter=traits_filter,
                               admin_proj=admin_proj, **evt_model_filter)
Esempio n. 3
0
    def post(self, data):
        """Create a new alarm.

        :param data: an alarm within the request body.
        """
        rbac.enforce('create_alarm', pecan.request)

        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)

        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)

        data.update_actions()
        change = data.as_dict(alarm_models.Alarm)

        # 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 = alarm_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)
        return Alarm.from_db_model(alarm)
Esempio n. 4
0
    def put(self, data):
        """Modify this alarm.

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

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

        # Ensure alarm exists
        alarm_in = self._alarm()

        now = timeutils.utcnow()

        data.alarm_id = self._id

        user, project = rbac.get_limited_to(pecan.request.headers)
        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

        alarm_in.severity = data.severity

        # 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_alarm = Alarm.from_db_model(alarm_in).as_dict(alarm_models.Alarm)
        updated_alarm = data.as_dict(alarm_models.Alarm)
        try:
            alarm_in = alarm_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)
Esempio n. 5
0
    def statistics(self, q=None, groupby=None, period=None, aggregate=None):
        """Computes the statistics of the samples in the time range given.

        :param q: Filter rules for the data to be returned.
        :param groupby: Fields for group by aggregation
        :param period: Returned result will be an array of statistics for a
                       period long of that number of seconds.
        :param aggregate: The selectable aggregation functions to be applied.
        """

        rbac.enforce('compute_statistics', pecan.request)

        q = q or []
        groupby = groupby or []
        aggregate = aggregate or []

        if period and period < 0:
            raise base.ClientSideError(_("Period must be positive."))

        kwargs = v2_utils.query_to_kwargs(q, storage.SampleFilter.__init__)
        kwargs['meter'] = self.meter_name
        f = storage.SampleFilter(**kwargs)
        g = _validate_groupby_fields(groupby)

        aggregate = utils.uniq(aggregate, ['func', 'param'])
        # Find the original timestamp in the query to use for clamping
        # the duration returned in the statistics.
        start = end = None
        for i in q:
            if i.field == 'timestamp' and i.op in ('lt', 'le'):
                end = timeutils.parse_isotime(i.value).replace(tzinfo=None)
            elif i.field == 'timestamp' and i.op in ('gt', 'ge'):
                start = timeutils.parse_isotime(i.value).replace(tzinfo=None)

        try:
            computed = pecan.request.storage_conn.get_meter_statistics(
                f, period, g, aggregate)
            LOG.debug(_('computed value coming from %r'),
                      pecan.request.storage_conn)

            return [
                Statistics(start_timestamp=start,
                           end_timestamp=end,
                           **c.as_dict()) for c in computed
            ]
        except OverflowError as e:
            params = dict(period=period, err=e)
            raise base.ClientSideError(
                _("Invalid period %(period)s: %(err)s") % params)
Esempio n. 6
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)
Esempio n. 7
0
def _event_query_to_event_filter(q):
    evt_model_filter = {
        'event_type': None,
        'message_id': None,
        'start_timestamp': None,
        'end_timestamp': None
    }
    traits_filter = []

    for i in q:
        if not i.op:
            i.op = 'eq'
        elif i.op not in base.operation_kind:
            error = _("operator {} is incorrect").format(i.op)
            raise base.ClientSideError(error)
        if i.field in evt_model_filter:
            evt_model_filter[i.field] = i.value
        else:
            trait_type = i.type or 'string'
            traits_filter.append({
                "key": i.field,
                trait_type: i._get_value_as_type(),
                "op": i.op
            })
    return storage.EventFilter(traits_filter=traits_filter, **evt_model_filter)
Esempio n. 8
0
def _event_query_to_event_filter(q):
    evt_model_filter = {
        'event_type': None,
        'message_id': None,
        'start_timestamp': None,
        'end_timestamp': None
    }
    traits_filter = []

    for i in q:
        if not i.op:
            i.op = 'eq'
        elif i.op not in base.operation_kind:
            error = (_('operator %(operator)s is not supported. the supported'
                       ' operators are: %(supported)s') % {
                           'operator': i.op,
                           'supported': base.operation_kind
                       })
            raise base.ClientSideError(error)
        if i.field in evt_model_filter:
            evt_model_filter[i.field] = i.value
        else:
            trait_type = i.type or 'string'
            traits_filter.append({
                "key": i.field,
                trait_type: i._get_value_as_type(),
                "op": i.op
            })
    return storage.EventFilter(traits_filter=traits_filter, **evt_model_filter)
Esempio n. 9
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
Esempio n. 10
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))
Esempio n. 11
0
    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)
Esempio n. 12
0
 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
Esempio n. 13
0
    def check_alarm_actions(alarm):
        actions_schema = ceilometer_alarm.NOTIFIER_SCHEMAS
        for state in state_kind:
            actions_name = state.replace(" ", "_") + '_actions'
            actions = getattr(alarm, actions_name)
            if not actions:
                continue

            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)
Esempio n. 14
0
 def validate(aggregate):
     valid_agg = (storage_base.Connection.CAPABILITIES.get(
         'statistics', {}).get('aggregation', {}).get('selectable',
                                                      {}).keys())
     if aggregate.func not in valid_agg:
         msg = _('Invalid aggregation function: %s') % aggregate.func
         raise base.ClientSideError(msg)
     return aggregate
Esempio n. 15
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)
Esempio n. 16
0
def enforce_limit(limit):
    """Ensure limit is defined and is valid. if not, set a default."""
    if limit is None:
        limit = pecan.request.cfg.api.default_api_return_limit
        LOG.info('No limit value provided, result set will be'
                 ' limited to %(limit)d.', {'limit': limit})
    if not limit or limit <= 0:
        raise base.ClientSideError(_("Limit must be positive"))
    return limit
Esempio n. 17
0
def enforce_limit(limit):
    """Ensure limit is defined and is valid. if not, set a default."""
    if limit is None:
        limit = cfg.CONF.api.default_api_return_limit
        LOG.info(
            _LI('No limit value provided, result set will be'
                'limited to %(limit)d.'), {limit: limit})
    if limit and limit < 0:
        raise base.ClientSideError(_("Limit must be positive"))
    return limit
Esempio n. 18
0
    def check_alarm_actions(alarm):
        actions_schema = ceilometer_alarm.NOTIFIER_SCHEMAS
        max_actions = cfg.CONF.alarm.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(
                    _LI('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)

            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)
Esempio n. 19
0
    def get_all(self,
                q=None,
                meter=None,
                groupby=None,
                period=None,
                aggregate=None):
        """Retrieve all statistics for all meters

        :param q: Filter rules for the statistics to be returned.
        """
        rbac.enforce('compute_statistics', pecan.request)

        q = q or []
        meter = meter or []
        groupby = groupby or []
        aggregate = aggregate or []

        if period and period < 0:
            raise base.ClientSideError(_("Period must be positive."))

        g = meters._validate_groupby_fields(groupby)

        # TO DO:  break out the meter names and invoke multiple calls
        kwargs = v2_utils.query_to_kwargs(q, storage.SampleFilter.__init__)

        aggregate = utils.uniq(aggregate, ['func', 'param'])
        # Find the original timestamp in the query to use for clamping
        # the duration returned in the statistics.
        start = end = None
        for i in q:
            if i.field == 'timestamp' and i.op in ('lt', 'le'):
                end = timeutils.parse_isotime(i.value).replace(tzinfo=None)
            elif i.field == 'timestamp' and i.op in ('gt', 'ge'):
                start = timeutils.parse_isotime(i.value).replace(tzinfo=None)
        ret = []

        kwargs['meter'] = meter
        f = storage.SampleFilter(**kwargs)
        try:
            computed = pecan.request.storage_conn.get_meter_statistics(
                f, period, g, aggregate)
            dbStats = [
                ScopedStatistics(start_timestamp=start,
                                 end_timestamp=end,
                                 **c.as_dict()) for c in computed
            ]
            ret += dbStats
        except OverflowError:
            LOG.exception("Problem processing meters %s" % meter)

        return ret
Esempio n. 20
0
    def validate(alarm):

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

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

        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
Esempio n. 21
0
    def get_all(self, q=None, limit=None):
        """Return all known samples, based on the data recorded so far.

        :param q: Filter rules for the samples to be returned.
        :param limit: Maximum number of samples to be returned.
        """

        rbac.enforce('get_samples', pecan.request)

        q = q or []

        if limit and limit < 0:
            raise base.ClientSideError(_("Limit must be positive"))
        kwargs = utils.query_to_kwargs(q, storage.SampleFilter.__init__)
        f = storage.SampleFilter(**kwargs)
        return map(Sample.from_db_model,
                   pecan.request.storage_conn.get_samples(f, limit=limit))
Esempio n. 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:
            rule.query = jsonutils.dumps({
                "and": [{
                    "=": {
                        "created_by_project_id": auth_project
                    }
                }, query]
            })

        # Delegate the query validation to gnocchi
        ks_client = keystone_client.get_client()
        request = {
            'url':
            "%s/v1/aggregation/resource/%s/metric/%s" %
            (cfg.CONF.alarms.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)
Esempio n. 23
0
    def get_all(self, q=None, limit=None):
        """Return samples for the meter.

        :param q: Filter rules for the data to be returned.
        :param limit: Maximum number of samples to return.
        """

        rbac.enforce('get_samples', pecan.request)

        q = q or []
        if limit and limit < 0:
            raise base.ClientSideError(_("Limit must be positive"))
        kwargs = v2_utils.query_to_kwargs(q, storage.SampleFilter.__init__)
        kwargs['meter'] = self.meter_name
        f = storage.SampleFilter(**kwargs)
        return [
            OldSample.from_db_model(e)
            for e in pecan.request.storage_conn.get_samples(f, limit=limit)
        ]
Esempio n. 24
0
    def put_state(self, state):
        """Set the state of this alarm.

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

        rbac.enforce('change_alarm_state', pecan.request)

        # 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 = self._alarm()
        alarm.state = state
        alarm.state_timestamp = now
        alarm = self.conn.update_alarm(alarm)
        change = {'state': alarm.state}
        self._record_change(change, now, on_behalf_of=alarm.project_id,
                            type=alarm_models.AlarmChange.STATE_TRANSITION)
        return alarm.state
Esempio n. 25
0
    def validate_alarm(cls, alarm):
        super(MetricOfResourceRule, cls).validate_alarm(alarm)

        rule = alarm.gnocchi_resources_threshold_rule
        ks_client = keystone_client.get_client()
        gnocchi_url = cfg.CONF.alarms.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)
Esempio n. 26
0
    def post(self, direct='', samples=None):
        """Post a list of new Samples to Telemetry.

        :param direct: a flag indicates whether the samples will be posted
                       directly to storage or not.
        :param samples: a list of samples within the request body.
        """
        rbac.enforce('create_samples', pecan.request)

        direct = strutils.bool_from_string(direct)
        if not samples:
            msg = _('Samples should be included in request body')
            raise base.ClientSideError(msg)

        now = timeutils.utcnow()
        auth_project = rbac.get_limited_to_project(pecan.request.headers)
        def_source = pecan.request.cfg.sample_source
        def_project_id = pecan.request.headers.get('X-Project-Id')
        def_user_id = pecan.request.headers.get('X-User-Id')

        published_samples = []
        for s in samples:
            if self.meter_name != s.counter_name:
                raise wsme.exc.InvalidInput('counter_name', s.counter_name,
                                            'should be %s' % self.meter_name)

            if s.message_id:
                raise wsme.exc.InvalidInput('message_id', s.message_id,
                                            'The message_id must not be set')

            if s.counter_type not in sample.TYPES:
                raise wsme.exc.InvalidInput(
                    'counter_type', s.counter_type,
                    'The counter type must be: ' + ', '.join(sample.TYPES))

            s.user_id = (s.user_id or def_user_id)
            s.project_id = (s.project_id or def_project_id)
            s.source = '%s:%s' % (s.project_id, (s.source or def_source))
            s.timestamp = (s.timestamp or now)

            if auth_project and auth_project != s.project_id:
                # non admin user trying to cross post to another project_id
                auth_msg = 'can not post samples to other projects'
                raise wsme.exc.InvalidInput('project_id', s.project_id,
                                            auth_msg)

            published_sample = sample.Sample(
                name=s.counter_name,
                type=s.counter_type,
                unit=s.counter_unit,
                volume=s.counter_volume,
                user_id=s.user_id,
                project_id=s.project_id,
                resource_id=s.resource_id,
                timestamp=s.timestamp.isoformat(),
                resource_metadata=utils.restore_nesting(s.resource_metadata,
                                                        separator='.'),
                source=s.source)
            s.message_id = published_sample.id

            sample_dict = publisher_utils.meter_message_from_counter(
                published_sample, cfg.CONF.publisher.telemetry_secret)
            if direct:
                ts = timeutils.parse_isotime(sample_dict['timestamp'])
                sample_dict['timestamp'] = timeutils.normalize_time(ts)
                pecan.request.storage_conn.record_metering_data(sample_dict)
            else:
                published_samples.append(sample_dict)
        if not direct:
            pecan.request.notifier.sample(
                {
                    'user': def_user_id,
                    'tenant': def_project_id,
                    'is_admin': True
                }, 'telemetry.api', {'samples': published_samples})

        return samples
Esempio n. 27
0
    def post(self, samples):
        """Post a list of new Samples to Telemetry.

        :param samples: a list of samples within the request body.
        """

        rbac.enforce('create_samples', pecan.request)

        now = timeutils.utcnow()
        auth_project = rbac.get_limited_to_project(pecan.request.headers)
        def_source = pecan.request.cfg.sample_source
        def_project_id = pecan.request.headers.get('X-Project-Id')
        def_user_id = pecan.request.headers.get('X-User-Id')

        published_samples = []
        for s in samples:
            for p in pecan.request.pipeline_manager.pipelines:
                if p.support_meter(s.counter_name):
                    break
            else:
                message = _("The metric %s is not supported by metering "
                            "pipeline configuration.") % s.counter_name
                raise base.ClientSideError(message, status_code=409)

            if self.meter_name != s.counter_name:
                raise wsme.exc.InvalidInput('counter_name', s.counter_name,
                                            'should be %s' % self.meter_name)

            if s.message_id:
                raise wsme.exc.InvalidInput('message_id', s.message_id,
                                            'The message_id must not be set')

            if s.counter_type not in sample.TYPES:
                raise wsme.exc.InvalidInput(
                    'counter_type', s.counter_type,
                    'The counter type must be: ' + ', '.join(sample.TYPES))

            s.user_id = (s.user_id or def_user_id)
            s.project_id = (s.project_id or def_project_id)
            s.source = '%s:%s' % (s.project_id, (s.source or def_source))
            s.timestamp = (s.timestamp or now)

            if auth_project and auth_project != s.project_id:
                # non admin user trying to cross post to another project_id
                auth_msg = 'can not post samples to other projects'
                raise wsme.exc.InvalidInput('project_id', s.project_id,
                                            auth_msg)

            published_sample = sample.Sample(
                name=s.counter_name,
                type=s.counter_type,
                unit=s.counter_unit,
                volume=s.counter_volume,
                user_id=s.user_id,
                project_id=s.project_id,
                resource_id=s.resource_id,
                timestamp=s.timestamp.isoformat(),
                resource_metadata=utils.restore_nesting(s.resource_metadata,
                                                        separator='.'),
                source=s.source)
            published_samples.append(published_sample)

            s.message_id = published_sample.id

        with pecan.request.pipeline_manager.publisher(
                context.get_admin_context()) as publisher:
            publisher(published_samples)

        return samples