remove gnocchi specific commands and set to v2
This commit is contained in:
parent
3c46e6b930
commit
026b43ba76
@ -1,54 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from gnocchiclient.v1 import base
|
||||
|
||||
|
||||
class ArchivePolicyManager(base.Manager):
|
||||
|
||||
url = "v1/archive_policy/"
|
||||
|
||||
def list(self):
|
||||
"""List archive policies
|
||||
|
||||
"""
|
||||
return self._get(self.url).json()
|
||||
|
||||
def get(self, name):
|
||||
"""Get an archive policy
|
||||
|
||||
:param name: Name of the archive policy
|
||||
:type name: str
|
||||
"""
|
||||
return self._get(self.url + name).json()
|
||||
|
||||
def create(self, archive_policy):
|
||||
"""Create an archive policy
|
||||
|
||||
:param archive_policy: the archive policy
|
||||
:type archive_policy: dict
|
||||
|
||||
"""
|
||||
return self._post(
|
||||
self.url, headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(archive_policy)).json()
|
||||
|
||||
def delete(self, name):
|
||||
"""Delete an archive policy
|
||||
|
||||
:param name: Name of the archive policy
|
||||
:type name: str
|
||||
"""
|
||||
self._delete(self.url + name)
|
@ -1,105 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cliff import command
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from gnocchiclient import utils
|
||||
|
||||
|
||||
class CliArchivePolicyList(lister.Lister):
|
||||
"""List archive policies"""
|
||||
|
||||
COLS = ('name',
|
||||
'back_window', 'definition', 'aggregation_methods')
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
policies = self.app.client.archive_policy.list()
|
||||
for ap in policies:
|
||||
utils.format_archive_policy(ap)
|
||||
return utils.list2cols(self.COLS, policies)
|
||||
|
||||
|
||||
class CliArchivePolicyShow(show.ShowOne):
|
||||
"""Show an archive policy"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliArchivePolicyShow, self).get_parser(prog_name)
|
||||
parser.add_argument("name",
|
||||
help="Name of the archive policy")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ap = self.app.client.archive_policy.get(
|
||||
name=parsed_args.name)
|
||||
utils.format_archive_policy(ap)
|
||||
return self.dict2columns(ap)
|
||||
|
||||
|
||||
def archive_policy_definition(string):
|
||||
parts = string.split(",")
|
||||
defs = {}
|
||||
for part in parts:
|
||||
attr, __, value = part.partition(":")
|
||||
if (attr not in ['granularity', 'points', 'timespan']
|
||||
or value is None):
|
||||
raise ValueError
|
||||
defs[attr] = value
|
||||
if len(defs) < 2:
|
||||
raise ValueError
|
||||
return defs
|
||||
|
||||
|
||||
class CliArchivePolicyCreate(show.ShowOne):
|
||||
"""Create an archive policy"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliArchivePolicyCreate, self).get_parser(prog_name)
|
||||
parser.add_argument("name", help=("name of the archive policy"))
|
||||
parser.add_argument("-b", "--back-window", dest="back_window",
|
||||
type=int,
|
||||
help=("back window of the archive policy"))
|
||||
parser.add_argument("-m", "--aggregation-method",
|
||||
action="append",
|
||||
dest="aggregation_methods",
|
||||
help=("aggregation method of the archive policy"))
|
||||
parser.add_argument("-d", "--definition", action='append',
|
||||
required=True, type=archive_policy_definition,
|
||||
metavar="<DEFINITION>",
|
||||
help=("two attributes (separated by ',') of an "
|
||||
"archive policy definition with its name "
|
||||
"and value separated with a ':'"))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
archive_policy = utils.dict_from_parsed_args(
|
||||
parsed_args, ['name', 'back_window', 'aggregation_methods',
|
||||
'definition'])
|
||||
ap = self.app.client.archive_policy.create(
|
||||
archive_policy=archive_policy)
|
||||
utils.format_archive_policy(ap)
|
||||
return self.dict2columns(ap)
|
||||
|
||||
|
||||
class CliArchivePolicyDelete(command.Command):
|
||||
"""Delete an archive policy"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliArchivePolicyDelete, self).get_parser(prog_name)
|
||||
parser.add_argument("name",
|
||||
help="Name of the archive policy")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.client.archive_policy.delete(name=parsed_args.name)
|
@ -1,50 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from gnocchiclient.v1 import base
|
||||
|
||||
|
||||
class ArchivePolicyRuleManager(base.Manager):
|
||||
url = "v1/archive_policy_rule/"
|
||||
|
||||
def list(self):
|
||||
"""List archive policy rules
|
||||
|
||||
"""
|
||||
return self._get(self.url).json()
|
||||
|
||||
def get(self, name):
|
||||
"""Get an archive policy rules
|
||||
|
||||
:param name: Name of the archive policy rule
|
||||
:type name: str
|
||||
"""
|
||||
return self._get(self.url + name).json()
|
||||
|
||||
def create(self, archive_policy_rule):
|
||||
"""Create an archive policy rule
|
||||
|
||||
"""
|
||||
return self._post(
|
||||
self.url, headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(archive_policy_rule)).json()
|
||||
|
||||
def delete(self, name):
|
||||
"""Delete an archive policy rule
|
||||
|
||||
:param name: Name of the archive policy rule
|
||||
:type name: str
|
||||
"""
|
||||
self._delete(self.url + name)
|
@ -1,79 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cliff import command
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from gnocchiclient import utils
|
||||
|
||||
|
||||
class CliArchivePolicyRuleList(lister.Lister):
|
||||
"""List archive policy rules"""
|
||||
|
||||
COLS = ('name', 'archive_policy_name', 'metric_pattern')
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ap_rules = self.app.client.archive_policy_rule.list()
|
||||
return utils.list2cols(self.COLS, ap_rules)
|
||||
|
||||
|
||||
class CliArchivePolicyRuleShow(show.ShowOne):
|
||||
"""Show an archive policy rule"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliArchivePolicyRuleShow, self).get_parser(prog_name)
|
||||
parser.add_argument("name",
|
||||
help="Name of the archive policy rule")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
ap_rule = self.app.client.archive_policy_rule.get(
|
||||
name=parsed_args.name)
|
||||
return self.dict2columns(ap_rule)
|
||||
|
||||
|
||||
class CliArchivePolicyRuleCreate(show.ShowOne):
|
||||
"""Create an archive policy rule"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliArchivePolicyRuleCreate, self).get_parser(prog_name)
|
||||
parser.add_argument("name",
|
||||
help=("Rule name"))
|
||||
parser.add_argument("-a", "--archive-policy-name",
|
||||
dest="archive_policy_name",
|
||||
required=True,
|
||||
help=("Archive policy name"))
|
||||
parser.add_argument("-m", "--metric-pattern",
|
||||
dest="metric_pattern", required=True,
|
||||
help=("Wildcard of metric name to match"))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
rule = utils.dict_from_parsed_args(
|
||||
parsed_args, ["name", "metric_pattern", "archive_policy_name"])
|
||||
policy = self.app.client.archive_policy_rule.create(rule)
|
||||
return self.dict2columns(policy)
|
||||
|
||||
|
||||
class CliArchivePolicyRuleDelete(command.Command):
|
||||
"""Delete an archive policy rule"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliArchivePolicyRuleDelete, self).get_parser(prog_name)
|
||||
parser.add_argument("name",
|
||||
help="Name of the archive policy rule")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.client.archive_policy_rule.delete(parsed_args.name)
|
@ -1,201 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from gnocchiclient import utils
|
||||
from gnocchiclient.v1 import base
|
||||
|
||||
|
||||
class MetricManager(base.Manager):
|
||||
metric_url = "v1/metric/"
|
||||
resource_url = "v1/resource/generic/%s/metric/"
|
||||
|
||||
def list(self):
|
||||
"""List archive metrics
|
||||
|
||||
"""
|
||||
return self._get(self.metric_url).json()
|
||||
|
||||
@staticmethod
|
||||
def _ensure_metric_is_uuid(metric, attribute="resource_id"):
|
||||
try:
|
||||
uuid.UUID(metric)
|
||||
except ValueError:
|
||||
raise TypeError("%s is required to get a metric by name" %
|
||||
attribute)
|
||||
|
||||
def get(self, metric, resource_id=None):
|
||||
"""Get an metric
|
||||
|
||||
:param metric: ID or Name of the metric
|
||||
:type metric: str
|
||||
:param resource_id: ID of the resource (required
|
||||
to get a metric by name)
|
||||
:type resource_id: str
|
||||
"""
|
||||
if resource_id is None:
|
||||
self._ensure_metric_is_uuid(metric)
|
||||
url = self.metric_url + metric
|
||||
else:
|
||||
url = (self.resource_url % resource_id) + metric
|
||||
return self._get(url).json()
|
||||
|
||||
# FIXME(jd): remove refetch_metric when LP#1497171 is fixed
|
||||
def create(self, metric, refetch_metric=True):
|
||||
"""Create an metric
|
||||
|
||||
:param metric: The metric
|
||||
:type metric: str
|
||||
"""
|
||||
resource_id = metric.get('resource_id')
|
||||
|
||||
if resource_id is None:
|
||||
metric = self._post(
|
||||
self.metric_url, headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(metric)).json()
|
||||
# FIXME(sileht): create and get have a
|
||||
# different output: LP#1497171
|
||||
if refetch_metric:
|
||||
return self.get(metric["id"])
|
||||
return metric
|
||||
|
||||
metric_name = metric.get('name')
|
||||
|
||||
if metric_name is None:
|
||||
raise TypeError("metric_name is required if resource_id is set")
|
||||
|
||||
del metric['resource_id']
|
||||
metric = {metric_name: metric}
|
||||
metric = self._post(
|
||||
self.resource_url % resource_id,
|
||||
headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(metric))
|
||||
return self.get(metric_name, resource_id)
|
||||
|
||||
def delete(self, metric, resource_id=None):
|
||||
"""Delete an metric
|
||||
|
||||
:param metric: ID or Name of the metric
|
||||
:type metric: str
|
||||
:param resource_id: ID of the resource (required
|
||||
to get a metric by name)
|
||||
:type resource_id: str
|
||||
"""
|
||||
if resource_id is None:
|
||||
self._ensure_metric_is_uuid(metric)
|
||||
url = self.metric_url + metric
|
||||
else:
|
||||
url = self.resource_url % resource_id + metric
|
||||
self._delete(url)
|
||||
|
||||
def add_measures(self, metric, measures, resource_id=None):
|
||||
"""Add measurements to a metric
|
||||
|
||||
:param metric: ID or Name of the metric
|
||||
:type metric: str
|
||||
:param resource_id: ID of the resource (required
|
||||
to get a metric by name)
|
||||
:type resource_id: str
|
||||
:param measures: measurements
|
||||
:type measures: list of dict(timestamp=timestamp, value=float)
|
||||
"""
|
||||
if resource_id is None:
|
||||
self._ensure_metric_is_uuid(metric)
|
||||
url = self.metric_url + metric + "/measures"
|
||||
else:
|
||||
url = self.resource_url % resource_id + metric + "/measures"
|
||||
return self._post(
|
||||
url, headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(measures))
|
||||
|
||||
def get_measures(self, metric, start=None, stop=None, aggregation=None,
|
||||
resource_id=None, **kwargs):
|
||||
"""Get measurements of a metric
|
||||
|
||||
:param metric: ID or Name of the metric
|
||||
:type metric: str
|
||||
:param start: beginning of the period
|
||||
:type start: timestamp
|
||||
:param stop: end of the period
|
||||
:type stop: timestamp
|
||||
:param aggregation: aggregation to retrieve
|
||||
:type aggregation: str
|
||||
:param resource_id: ID of the resource (required
|
||||
to get a metric by name)
|
||||
:type resource_id: str
|
||||
|
||||
All other arguments are arguments are dedicated to custom aggregation
|
||||
method passed as-is to the Gnocchi.
|
||||
"""
|
||||
|
||||
if isinstance(start, datetime.datetime):
|
||||
start = start.isoformat()
|
||||
if isinstance(stop, datetime.datetime):
|
||||
stop = stop.isoformat()
|
||||
|
||||
params = dict(start=start, stop=stop, aggregation=aggregation)
|
||||
params.update(kwargs)
|
||||
if resource_id is None:
|
||||
self._ensure_metric_is_uuid(metric)
|
||||
url = self.metric_url + metric + "/measures"
|
||||
else:
|
||||
url = self.resource_url % resource_id + metric + "/measures"
|
||||
return self._get(url, params=params).json()
|
||||
|
||||
def aggregation(self, metrics, query=None,
|
||||
start=None, stop=None, aggregation=None,
|
||||
needed_overlap=None, resource_type="generic"):
|
||||
"""Get measurements of a aggregated metrics
|
||||
|
||||
:param metrics: IDs of metric or metric name
|
||||
:type metric: list or str
|
||||
:param query: The query dictionary
|
||||
:type query: dict
|
||||
:param start: beginning of the period
|
||||
:type start: timestamp
|
||||
:param stop: end of the period
|
||||
:type stop: timestamp
|
||||
:param aggregation: aggregation to retrieve
|
||||
:type aggregation: str
|
||||
:param resource_type: type of resource for the query
|
||||
:type resource_type: str
|
||||
|
||||
See Gnocchi REST API documentation for the format
|
||||
of *query dictionary*
|
||||
http://docs.openstack.org/developer/gnocchi/rest.html#searching-for-resources
|
||||
"""
|
||||
|
||||
if isinstance(start, datetime.datetime):
|
||||
start = start.isoformat()
|
||||
if isinstance(stop, datetime.datetime):
|
||||
stop = stop.isoformat()
|
||||
|
||||
params = dict(start=start, stop=stop, aggregation=aggregation,
|
||||
needed_overlap=needed_overlap)
|
||||
if query is None:
|
||||
for metric in metrics:
|
||||
self._ensure_metric_is_uuid(metric)
|
||||
params['metric'] = metrics
|
||||
return self._get("v1/aggregation/metric",
|
||||
params=params).json()
|
||||
else:
|
||||
return self._post(
|
||||
"v1/aggregation/resource/%s/metric/%s?%s" % (
|
||||
resource_type, metrics,
|
||||
utils.dict_to_querystring(params)),
|
||||
headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(query)).json()
|
@ -1,207 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cliff import command
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from gnocchiclient import utils
|
||||
|
||||
|
||||
class CliMetricWithResourceID(command.Command):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMetricWithResourceID, self).get_parser(prog_name)
|
||||
parser.add_argument("--resource-id", "-r",
|
||||
help="ID of the resource")
|
||||
return parser
|
||||
|
||||
|
||||
class CliMetricList(lister.Lister):
|
||||
"""List metrics"""
|
||||
|
||||
COLS = ('id', 'archive_policy/name', 'name', 'resource_id')
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
metrics = self.app.client.metric.list()
|
||||
for metric in metrics:
|
||||
utils.format_archive_policy(metric["archive_policy"])
|
||||
utils.format_move_dict_to_root(metric, "archive_policy")
|
||||
return utils.list2cols(self.COLS, metrics)
|
||||
|
||||
|
||||
class CliMetricShow(CliMetricWithResourceID, show.ShowOne):
|
||||
"""Show a metric"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMetricShow, self).get_parser(prog_name)
|
||||
parser.add_argument("metric",
|
||||
help="ID or name of the metric")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
metric = self.app.client.metric.get(
|
||||
metric=parsed_args.metric,
|
||||
resource_id=parsed_args.resource_id)
|
||||
utils.format_archive_policy(metric["archive_policy"])
|
||||
utils.format_move_dict_to_root(metric, "archive_policy")
|
||||
return self.dict2columns(metric)
|
||||
|
||||
|
||||
class CliMetricCreateBase(show.ShowOne, CliMetricWithResourceID):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMetricCreateBase, self).get_parser(prog_name)
|
||||
parser.add_argument("--archive-policy-name", "-a",
|
||||
dest="archive_policy_name",
|
||||
help=("name of the archive policy"))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
metric = utils.dict_from_parsed_args(parsed_args,
|
||||
["archive_policy_name",
|
||||
"resource_id"])
|
||||
return self._take_action(metric, parsed_args)
|
||||
|
||||
|
||||
class CliMetricCreate(CliMetricCreateBase):
|
||||
"""Create a metric"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMetricCreate, self).get_parser(prog_name)
|
||||
parser.add_argument("name", nargs='?',
|
||||
metavar="METRIC_NAME",
|
||||
help="Name of the metric")
|
||||
return parser
|
||||
|
||||
def _take_action(self, metric, parsed_args):
|
||||
if parsed_args.name:
|
||||
metric['name'] = parsed_args.name
|
||||
metric = self.app.client.metric.create(metric)
|
||||
utils.format_archive_policy(metric["archive_policy"])
|
||||
utils.format_move_dict_to_root(metric, "archive_policy")
|
||||
return self.dict2columns(metric)
|
||||
|
||||
|
||||
class CliMetricDelete(CliMetricWithResourceID):
|
||||
"""Delete a metric"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMetricDelete, self).get_parser(prog_name)
|
||||
parser.add_argument("metric", nargs='+',
|
||||
help="IDs or names of the metric")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
for metric in parsed_args.metric:
|
||||
self.app.client.metric.delete(metric=metric,
|
||||
resource_id=parsed_args.resource_id)
|
||||
|
||||
|
||||
class CliMeasuresShow(CliMetricWithResourceID, lister.Lister):
|
||||
"""Get measurements of a metric"""
|
||||
|
||||
COLS = ('timestamp', 'granularity', 'value')
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMeasuresShow, self).get_parser(prog_name)
|
||||
parser.add_argument("metric",
|
||||
help="ID or name of the metric")
|
||||
parser.add_argument("--aggregation",
|
||||
help="aggregation to retrieve")
|
||||
parser.add_argument("--start",
|
||||
help="beginning of the period")
|
||||
parser.add_argument("--stop",
|
||||
help="end of the period")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
measures = self.app.client.metric.get_measures(
|
||||
metric=parsed_args.metric,
|
||||
resource_id=parsed_args.resource_id,
|
||||
aggregation=parsed_args.aggregation,
|
||||
start=parsed_args.start,
|
||||
stop=parsed_args.stop,
|
||||
)
|
||||
return self.COLS, measures
|
||||
|
||||
|
||||
class CliMeasuresAddBase(CliMetricWithResourceID):
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMeasuresAddBase, self).get_parser(prog_name)
|
||||
parser.add_argument("metric", help="ID or name of the metric")
|
||||
return parser
|
||||
|
||||
|
||||
class CliMeasuresAdd(CliMeasuresAddBase):
|
||||
"""Add measurements to a metric"""
|
||||
|
||||
def measure(self, measure):
|
||||
timestamp, __, value = measure.rpartition("@")
|
||||
return {'timestamp': timestamp, 'value': float(value)}
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMeasuresAdd, self).get_parser(prog_name)
|
||||
parser.add_argument("-m", "--measure", action='append',
|
||||
required=True, type=self.measure,
|
||||
help=("timestamp and value of a measure "
|
||||
"separated with a '@'"))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.client.metric.add_measures(
|
||||
metric=parsed_args.metric,
|
||||
resource_id=parsed_args.resource_id,
|
||||
measures=parsed_args.measure,
|
||||
)
|
||||
|
||||
|
||||
class CliMeasuresAggregation(lister.Lister):
|
||||
"""Get measurements of aggregated metrics"""
|
||||
|
||||
COLS = ('timestamp', 'granularity', 'value')
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliMeasuresAggregation, self).get_parser(prog_name)
|
||||
parser.add_argument("-m", "--metric", nargs='+', required=True,
|
||||
help="metrics IDs or metric name")
|
||||
parser.add_argument("--aggregation",
|
||||
help="aggregation to retrieve")
|
||||
parser.add_argument("--start",
|
||||
help="beginning of the period")
|
||||
parser.add_argument("--stop",
|
||||
help="end of the period")
|
||||
parser.add_argument("--needed-overlap", type=float,
|
||||
help=("percent of datapoints in each "
|
||||
"metrics required"))
|
||||
parser.add_argument("--query", help="Query"),
|
||||
parser.add_argument("--resource-type", default="generic",
|
||||
help="Resource type to query"),
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
metrics = parsed_args.metric
|
||||
query = None
|
||||
if parsed_args.query:
|
||||
query = utils.search_query_builder(parsed_args.query)
|
||||
if len(parsed_args.metric) != 1:
|
||||
raise ValueError("One metric is required if query is provied")
|
||||
metrics = parsed_args.metric[0]
|
||||
measures = self.app.client.metric.aggregation(
|
||||
metrics=metrics,
|
||||
query=query,
|
||||
aggregation=parsed_args.aggregation,
|
||||
start=parsed_args.start,
|
||||
stop=parsed_args.stop,
|
||||
needed_overlap=parsed_args.needed_overlap,
|
||||
resource_type=parsed_args.resource_type,
|
||||
)
|
||||
return self.COLS, measures
|
@ -1,167 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from six.moves.urllib import parse as urllib_parse
|
||||
|
||||
from gnocchiclient.v1 import base
|
||||
|
||||
|
||||
def _get_pagination_options(details=False, history=False,
|
||||
limit=None, marker=None, sorts=None):
|
||||
options = []
|
||||
if details:
|
||||
options.append("details=true")
|
||||
if history:
|
||||
options.append("history=true")
|
||||
if limit:
|
||||
options.append("limit=%d" % limit)
|
||||
if marker:
|
||||
options.append("marker=%s" % urllib_parse.quote(marker))
|
||||
for sort in sorts or []:
|
||||
options.append("sort=%s" % urllib_parse.quote(sort))
|
||||
if options:
|
||||
return "%s" % "&".join(options)
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
class ResourceManager(base.Manager):
|
||||
url = "v1/resource/"
|
||||
|
||||
def list(self, resource_type="generic", details=False, history=False,
|
||||
limit=None, marker=None, sorts=None):
|
||||
"""List resources
|
||||
|
||||
:param resource_type: Type of the resource
|
||||
:type resource_type: str
|
||||
:param details: Show all attributes of resources
|
||||
:type details: bool
|
||||
:param history: Show the history of resources
|
||||
:type history: bool
|
||||
:param limit: maximum number of resources to return
|
||||
:type limit: int
|
||||
:param marker: the last item of the previous page; we returns the next
|
||||
results after this value.
|
||||
:param sorts: list of resource attributes to order by. (example
|
||||
["user_id:desc-nullslast", "project_id:asc"]
|
||||
:type sorts: list of str
|
||||
"""
|
||||
qs = _get_pagination_options(details, history, limit, marker, sorts)
|
||||
url = "%s%s?%s" % (self.url, resource_type, qs)
|
||||
return self._get(url).json()
|
||||
|
||||
def get(self, resource_type, resource_id, history=False):
|
||||
"""Get a resource
|
||||
|
||||
:param resource_type: Type of the resource
|
||||
:type resource_type: str
|
||||
:param resource_id: ID of the resource
|
||||
:type resource_id: str
|
||||
:param history: Show the history of the resource
|
||||
:type history: bool
|
||||
"""
|
||||
history = "/history" if history else ""
|
||||
url = self.url + "%s/%s%s" % (resource_type, resource_id, history)
|
||||
return self._get(url).json()
|
||||
|
||||
def history(self, resource_type, resource_id, details=False,
|
||||
limit=None, marker=None, sorts=None):
|
||||
"""Get a resource
|
||||
|
||||
:param resource_type: Type of the resource
|
||||
:type resource_type: str
|
||||
:param resource_id: ID of the resource
|
||||
:type resource_id: str
|
||||
:param details: Show all attributes of resources
|
||||
:type details: bool
|
||||
:param limit: maximum number of resources to return
|
||||
:type limit: int
|
||||
:param marker: the last item of the previous page; we returns the next
|
||||
results after this value.
|
||||
:param sorts: list of resource attributes to order by. (example
|
||||
["user_id:desc-nullslast", "project_id:asc"]
|
||||
:type sorts: list of str
|
||||
"""
|
||||
qs = _get_pagination_options(details, False, limit, marker, sorts)
|
||||
url = "%s%s/%s/history?%s" % (self.url, resource_type, resource_id, qs)
|
||||
return self._get(url).json()
|
||||
|
||||
def create(self, resource_type, resource):
|
||||
"""Create a resource
|
||||
|
||||
:param resource_type: Type of the resource
|
||||
:type resource_type: str
|
||||
:param resource: Attribute of the resource
|
||||
:type resource: dict
|
||||
"""
|
||||
return self._post(
|
||||
self.url + resource_type,
|
||||
headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(resource)).json()
|
||||
|
||||
def update(self, resource_type, resource_id, resource):
|
||||
"""Update a resource
|
||||
|
||||
:param resource_type: Type of the resource
|
||||
:type resource_type: str
|
||||
:param resource_id: ID of the resource
|
||||
:type resource_id: str
|
||||
:param resource: Attribute of the resource
|
||||
:type resource: dict
|
||||
"""
|
||||
|
||||
return self._patch(
|
||||
self.url + resource_type + "/" + resource_id,
|
||||
headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(resource)).json()
|
||||
|
||||
def delete(self, resource_id):
|
||||
"""Delete a resource
|
||||
|
||||
:param resource_id: ID of the resource
|
||||
:type resource_id: str
|
||||
"""
|
||||
self._delete(self.url + "generic/" + resource_id)
|
||||
|
||||
def search(self, resource_type="generic", query=None, details=False,
|
||||
history=False, limit=None, marker=None, sorts=None):
|
||||
"""List resources
|
||||
|
||||
:param resource_type: Type of the resource
|
||||
:param resource_type: str
|
||||
:param query: The query dictionary
|
||||
:type query: dict
|
||||
:param details: Show all attributes of resources
|
||||
:type details: bool
|
||||
:param history: Show the history of resources
|
||||
:type history: bool
|
||||
:param limit: maximum number of resources to return
|
||||
:type limit: int
|
||||
:param marker: the last item of the previous page; we returns the next
|
||||
results after this value.
|
||||
:param sorts: list of resource attributes to order by. (example
|
||||
["user_id:desc-nullslast", "project_id:asc"]
|
||||
:type sorts: list of str
|
||||
|
||||
See Gnocchi REST API documentation for the format
|
||||
of *query dictionary*
|
||||
http://docs.openstack.org/developer/gnocchi/rest.html#searching-for-resources
|
||||
"""
|
||||
|
||||
query = query or {}
|
||||
qs = _get_pagination_options(details, history, limit, marker, sorts)
|
||||
url = "v1/search/resource/%s?%s" % (resource_type, qs)
|
||||
return self._post(
|
||||
url, headers={'Content-Type': "application/json"},
|
||||
data=jsonutils.dumps(query)).json()
|
@ -1,213 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from cliff import command
|
||||
from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from gnocchiclient import utils
|
||||
|
||||
|
||||
class CliResourceList(lister.Lister):
|
||||
"""List resources"""
|
||||
|
||||
COLS = ('id', 'type',
|
||||
'project_id', 'user_id',
|
||||
'started_at', 'ended_at',
|
||||
'revision_start', 'revision_end')
|
||||
|
||||
def get_parser(self, prog_name, history=True):
|
||||
parser = super(CliResourceList, self).get_parser(prog_name)
|
||||
parser.add_argument("--details", action='store_true',
|
||||
help="Show all attributes of generic resources"),
|
||||
if history:
|
||||
parser.add_argument("--history", action='store_true',
|
||||
help="Show history of the resources"),
|
||||
parser.add_argument("--limit", type=int, metavar="<LIMIT>",
|
||||
help="Number of resources to return "
|
||||
"(Default is server default)")
|
||||
parser.add_argument("--marker", metavar="<MARKER>",
|
||||
help="Last item of the previous listing. "
|
||||
"Return the next results after this value")
|
||||
parser.add_argument("--sort", action="append", metavar="<SORT>",
|
||||
help="Sort of resource attribute "
|
||||
"(example: user_id:desc-nullslast")
|
||||
parser.add_argument("--type", "-t", dest="resource_type",
|
||||
default="generic", help="Type of resource")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
resources = self.app.client.resource.list(
|
||||
resource_type=parsed_args.resource_type,
|
||||
**self._get_pagination_options(parsed_args))
|
||||
return utils.list2cols(self.COLS, resources)
|
||||
|
||||
@staticmethod
|
||||
def _get_pagination_options(parsed_args):
|
||||
options = dict(
|
||||
details=parsed_args.details,
|
||||
sorts=parsed_args.sort,
|
||||
limit=parsed_args.limit,
|
||||
marker=parsed_args.marker)
|
||||
|
||||
if hasattr(parsed_args, 'history'):
|
||||
options['history'] = parsed_args.history
|
||||
return options
|
||||
|
||||
|
||||
class CliResourceHistory(CliResourceList):
|
||||
"""Show the history of a resource"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliResourceHistory, self).get_parser(prog_name,
|
||||
history=False)
|
||||
parser.add_argument("resource_id",
|
||||
help="ID of a resource")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
resources = self.app.client.resource.history(
|
||||
resource_type=parsed_args.resource_type,
|
||||
resource_id=parsed_args.resource_id,
|
||||
**self._get_pagination_options(parsed_args))
|
||||
return utils.list2cols(self.COLS, resources)
|
||||
|
||||
|
||||
class CliResourceSearch(CliResourceList):
|
||||
"""Search resources with specified query rules"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliResourceSearch, self).get_parser(prog_name)
|
||||
parser.add_argument("--query", help="Query"),
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
resources = self.app.client.resource.search(
|
||||
resource_type=parsed_args.resource_type,
|
||||
query=utils.search_query_builder(parsed_args.query),
|
||||
**self._get_pagination_options(parsed_args))
|
||||
return utils.list2cols(self.COLS, resources)
|
||||
|
||||
|
||||
def normalize_metrics(res):
|
||||
res['metrics'] = "\n".join(sorted(
|
||||
["%s: %s" % (name, _id)
|
||||
for name, _id in res['metrics'].items()]))
|
||||
|
||||
|
||||
class CliResourceShow(show.ShowOne):
|
||||
"""Show a resource"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliResourceShow, self).get_parser(prog_name)
|
||||
parser.add_argument("--type", "-t", dest="resource_type",
|
||||
default="generic", help="Type of resource")
|
||||
parser.add_argument("resource_id",
|
||||
help="ID of a resource")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
res = self.app.client.resource.get(
|
||||
resource_type=parsed_args.resource_type,
|
||||
resource_id=parsed_args.resource_id)
|
||||
normalize_metrics(res)
|
||||
return self.dict2columns(res)
|
||||
|
||||
|
||||
class CliResourceCreate(show.ShowOne):
|
||||
"""Create a resource"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliResourceCreate, self).get_parser(prog_name)
|
||||
parser.add_argument("--type", "-t", dest="resource_type",
|
||||
default="generic", help="Type of resource")
|
||||
parser.add_argument("resource_id",
|
||||
help="ID of the resource")
|
||||
parser.add_argument("-a", "--attribute", action='append',
|
||||
default=[],
|
||||
help=("name and value of a attribute "
|
||||
"separated with a ':'"))
|
||||
parser.add_argument("-m", "--add-metric", action='append',
|
||||
default=[],
|
||||
help="name:id of a metric to add"),
|
||||
parser.add_argument(
|
||||
"-n", "--create-metric", action='append',
|
||||
help="name:archive_policy_name of a metric to create"),
|
||||
parser.add_argument("-d", "--delete-metric", action='append',
|
||||
default=[],
|
||||
help="Name of a metric to delete"),
|
||||
return parser
|
||||
|
||||
def _resource_from_args(self, parsed_args, update=False):
|
||||
resource = {}
|
||||
if not update:
|
||||
resource['id'] = parsed_args.resource_id
|
||||
if parsed_args.attribute:
|
||||
for attr in parsed_args.attribute:
|
||||
attr, __, value = attr.partition(":")
|
||||
resource[attr] = value
|
||||
if (parsed_args.add_metric
|
||||
or parsed_args.create_metric
|
||||
or parsed_args.delete_metric):
|
||||
if update:
|
||||
r = self.app.client.resource.get(parsed_args.resource_type,
|
||||
parsed_args.resource_id)
|
||||
default = r['metrics']
|
||||
else:
|
||||
default = {}
|
||||
resource['metrics'] = default
|
||||
for metric in parsed_args.add_metric:
|
||||
name, _, value = metric.partition(":")
|
||||
resource['metrics'][name] = value
|
||||
for metric in parsed_args.delete_metric:
|
||||
resource['metrics'].pop(name, None)
|
||||
for metric in parsed_args.create_metric:
|
||||
name, _, value = metric.partition(":")
|
||||
if value is "":
|
||||
resource['metrics'][name] = {}
|
||||
else:
|
||||
resource['metrics'][name] = {'archive_policy_name': value}
|
||||
|
||||
return resource
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
resource = self._resource_from_args(parsed_args)
|
||||
res = self.app.client.resource.create(
|
||||
resource_type=parsed_args.resource_type, resource=resource)
|
||||
normalize_metrics(res)
|
||||
return self.dict2columns(res)
|
||||
|
||||
|
||||
class CliResourceUpdate(CliResourceCreate):
|
||||
"""Update a resource"""
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
resource = self._resource_from_args(parsed_args, update=True)
|
||||
res = self.app.client.resource.update(
|
||||
resource_type=parsed_args.resource_type,
|
||||
resource_id=parsed_args.resource_id,
|
||||
resource=resource)
|
||||
normalize_metrics(res)
|
||||
return self.dict2columns(res)
|
||||
|
||||
|
||||
class CliResourceDelete(command.Command):
|
||||
"""Delete a resource"""
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliResourceDelete, self).get_parser(prog_name)
|
||||
parser.add_argument("resource_id",
|
||||
help="ID of the resource")
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.app.client.resource.delete(parsed_args.resource_id)
|
@ -1,21 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
from gnocchiclient.v1 import base
|
||||
|
||||
|
||||
class StatusManager(base.Manager):
|
||||
url = "v1/status"
|
||||
|
||||
def get(self):
|
||||
"""Get Gnocchi status."""
|
||||
return self._get(self.url).json()
|
@ -1,31 +0,0 @@
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from cliff import show
|
||||
|
||||
|
||||
class CliStatusShow(show.ShowOne):
|
||||
"""Show the status of measurements processing"""
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
status = self.app.client.status.get()
|
||||
|
||||
nb_metric = len(status['storage']['measures_to_process'])
|
||||
nb_measures = (
|
||||
sum(status['storage']['measures_to_process'].values())
|
||||
)
|
||||
|
||||
return self.dict2columns({
|
||||
"storage/total number of measures to process": nb_measures,
|
||||
"storage/number of metric having measures to process": nb_metric,
|
||||
})
|
@ -11,11 +11,11 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from gnocchiclient.v1 import base
|
||||
from aodhclient.v2 import base
|
||||
|
||||
|
||||
class CapabilitiesManager(base.Manager):
|
||||
cap_url = "v1/capabilities/"
|
||||
cap_url = "v2/capabilities/"
|
||||
|
||||
def list(self):
|
||||
"""List capabilities
|
Loading…
x
Reference in New Issue
Block a user