Merge "Refactored meta collector API"

This commit is contained in:
Jenkins 2015-07-30 12:32:47 +00:00 committed by Gerrit Code Review
commit e5310d4fb0
8 changed files with 280 additions and 47 deletions

View File

@ -17,6 +17,7 @@
#
import pecan
from pecan import rest
import six
from wsme import types as wtypes
import wsmeext.pecan as wsme_pecan
@ -31,15 +32,6 @@ class MappingController(rest.RestController):
def __init__(self):
self._db = db_api.get_instance().get_service_to_collector_mapping()
@wsme_pecan.wsexpose([wtypes.text])
def get_all(self):
"""Return the list of every services mapped.
:return: List of every services mapped.
"""
policy.enforce(pecan.request.context, 'collector:list_mappings', {})
return [mapping.service for mapping in self._db.list_services()]
@wsme_pecan.wsexpose(collector_models.ServiceToCollectorMapping,
wtypes.text)
def get_one(self, service):
@ -49,40 +41,105 @@ class MappingController(rest.RestController):
"""
policy.enforce(pecan.request.context, 'collector:get_mapping', {})
try:
return self._db.get_mapping(service)
mapping = self._db.get_mapping(service)
return collector_models.ServiceToCollectorMapping(
**mapping.as_dict())
except db_api.NoSuchMapping as e:
pecan.abort(400, str(e))
pecan.abort(400, six.str_type(e))
@wsme_pecan.wsexpose(collector_models.ServiceToCollectorMappingCollection,
wtypes.text,
wtypes.text)
def get_all(self, collector=None):
"""Return the list of every services mapped to a collector.
:param collector: Filter on the collector name.
:return: Service to collector mappings collection.
"""
policy.enforce(pecan.request.context, 'collector:list_mappings', {})
mappings = [collector_models.ServiceToCollectorMapping(
**mapping.as_dict())
for mapping in self._db.list_mappings(collector)]
return collector_models.ServiceToCollectorMappingCollection(
mappings=mappings)
@wsme_pecan.wsexpose(collector_models.ServiceToCollectorMapping,
wtypes.text,
wtypes.text)
def post(self, collector, service):
"""Create a service to collector mapping.
:param collector: Name of the collector to apply mapping on.
:param service: Name of the service to apply mapping on.
"""
policy.enforce(pecan.request.context, 'collector:manage_mapping', {})
new_mapping = self._db.set_mapping(service, collector)
return collector_models.ServiceToCollectorMapping(
service=new_mapping.service,
collector=new_mapping.collector)
@wsme_pecan.wsexpose(None,
wtypes.text,
wtypes.text,
status_code=204)
def delete(self, collector, service):
"""Delete a service to collector mapping.
:param collector: Name of the collector to filter on.
:param service: Name of the service to filter on.
"""
policy.enforce(pecan.request.context, 'collector:manage_mapping', {})
try:
self._db.delete_mapping(service)
except db_api.NoSuchMapping as e:
pecan.abort(400, six.str_type(e))
class CollectorStateController(rest.RestController):
"""REST Controller managing collector states."""
def __init__(self):
self._db = db_api.get_instance().get_module_info()
@wsme_pecan.wsexpose(collector_models.CollectorInfos, wtypes.text)
def get(self, name):
"""Query the enable state of a collector.
:param name: Name of the collector.
:return: State of the collector.
"""
policy.enforce(pecan.request.context, 'collector:get_state', {})
enabled = self._db.get_state('collector_{}'.format(name))
collector = collector_models.CollectorInfos(name=name,
enabled=enabled)
return collector
@wsme_pecan.wsexpose(collector_models.CollectorInfos,
wtypes.text,
body=collector_models.CollectorInfos)
def put(self, name, infos):
"""Set the enable state of a collector.
:param name: Name of the collector.
:param infos: New state informations of the collector.
:return: State of the collector.
"""
policy.enforce(pecan.request.context, 'collector:update_state', {})
enabled = self._db.set_state('collector_{}'.format(name),
infos.enabled)
collector = collector_models.CollectorInfos(name=name,
enabled=enabled)
return collector
class CollectorController(rest.RestController):
"""REST Controller managing collector modules."""
mapping = MappingController()
mappings = MappingController()
state = CollectorStateController()
_custom_actions = {
'state': ['GET', 'POST']
}
def __init__(self):
self._db = db_api.get_instance().get_module_enable_state()
@wsme_pecan.wsexpose(bool, wtypes.text)
def state(self, collector):
"""Query the enable state of a collector.
:param collector: Name of the collector.
:return: State of the collector.
"""
policy.enforce(pecan.request.context, 'collector:get_state', {})
return self._db.get_state('collector_{}'.format(collector))
@wsme_pecan.wsexpose(bool, wtypes.text, body=bool)
def post_state(self, collector, state):
"""Set the enable state of a collector.
:param collector: Name of the collector.
:param state: New state for the collector.
:return: State of the collector.
"""
policy.enforce(pecan.request.context, 'collector:update_state', {})
return self._db.set_state('collector_{}'.format(collector), state)
# FIXME(sheeprine): Stub function used to pass requests to subcontrollers
@wsme_pecan.wsexpose(None)
def get(self):
"Unused function, hack to let pecan route requests to subcontrollers."
return

View File

@ -18,6 +18,29 @@
from wsme import types as wtypes
class CollectorInfos(wtypes.Base):
"""Type describing a collector module.
"""
name = wtypes.wsattr(wtypes.text, mandatory=False)
"""Name of the collector."""
enabled = wtypes.wsattr(bool, mandatory=True)
"""State of the collector."""
def to_json(self):
res_dict = {'name': self.name,
'enabled': self.enabled}
return res_dict
@classmethod
def sample(cls):
sample = cls(name='ceilometer',
enabled=True)
return sample
class ServiceToCollectorMapping(wtypes.Base):
"""Type describing a service to collector mapping.
@ -30,8 +53,8 @@ class ServiceToCollectorMapping(wtypes.Base):
"""Name of the collector."""
def to_json(self):
res_dict = {}
res_dict[self.service] = self.collector
res_dict = {'service': self.service,
'collector': self.collector}
return res_dict
@classmethod
@ -39,3 +62,23 @@ class ServiceToCollectorMapping(wtypes.Base):
sample = cls(service='compute',
collector='ceilometer')
return sample
class ServiceToCollectorMappingCollection(wtypes.Base):
"""Type describing a service to collector mapping collection.
"""
mappings = [ServiceToCollectorMapping]
"""List of service to collector mappings."""
def to_json(self):
res_dict = {'mappings': self.mappings}
return res_dict
@classmethod
def sample(cls):
mapping = ServiceToCollectorMapping(service='compute',
collector='ceilometer')
sample = cls(mappings=[mapping])
return sample

View File

@ -117,7 +117,7 @@ class NoSuchMapping(Exception):
def __init__(self, service):
super(NoSuchMapping, self).__init__(
"No such mapping for service: %s" % service)
"No mapping for service: %s" % service)
self.service = service
@ -142,12 +142,21 @@ class ServiceToCollectorMapping(object):
"""
@abc.abstractmethod
def list_services(self):
def list_services(self, collector=None):
"""Retrieve the list of every services mapped.
:param collector: Filter on a collector name.
:return list(str): List of services' name.
"""
@abc.abstractmethod
def list_mappings(self, collector=None):
"""Retrieve the list of every mappings.
:param collector: Filter on a collector's name.
:return [tuple(str, str)]: List of mappings.
"""
@abc.abstractmethod
def delete_mapping(self, service):
"""Remove a mapping.

View File

@ -163,7 +163,7 @@ class ServiceToCollectorMapping(object):
q = utils.model_query(
models.ServiceToCollectorMapping,
session)
q.filter(
q = q.filter(
models.ServiceToCollectorMapping.service == service)
return q.one()
except sqlalchemy.orm.exc.NoResultFound:
@ -176,8 +176,8 @@ class ServiceToCollectorMapping(object):
q = utils.model_query(
models.ServiceToCollectorMapping,
session)
q = q.filter_by(
service=service)
q = q.filter(
models.ServiceToCollectorMapping.service == service)
q = q.with_lockmode('update')
db_mapping = q.one()
db_mapping.collector = collector
@ -188,15 +188,29 @@ class ServiceToCollectorMapping(object):
session.add(db_mapping)
return db_mapping
def list_services(self):
def list_services(self, collector=None):
session = db.get_session()
q = utils.model_query(
models.ServiceToCollectorMapping,
session)
if collector:
q = q.filter(
models.ServiceToCollectorMapping.collector == collector)
res = q.distinct().values(
models.ServiceToCollectorMapping.service)
return res
def list_mappings(self, collector=None):
session = db.get_session()
q = utils.model_query(
models.ServiceToCollectorMapping,
session)
if collector:
q = q.filter(
models.ServiceToCollectorMapping.collector == collector)
res = q.all()
return res
def delete_mapping(self, service):
session = db.get_session()
q = utils.model_query(

View File

@ -70,6 +70,12 @@ class ModuleStateInfo(Base, models.ModelBase):
name=self.name,
state=self.state)
def as_dict(self):
d = {}
for c in self.__table__.columns:
d[c.name] = self[c.name]
return d
class ServiceToCollectorMapping(Base, models.ModelBase):
"""Collector module state.
@ -88,3 +94,9 @@ class ServiceToCollectorMapping(Base, models.ModelBase):
'collector={collector}>').format(
service=self.service,
collector=self.collector)
def as_dict(self):
d = {}
for c in self.__table__.columns:
d[c.name] = self[c.name]
return d

View File

@ -0,0 +1,85 @@
#!/usr/bin/env bash
show_state()
{
echo ''
echo 'Show ceilometer state:'
echo "GET http://localhost:8888/v1/collector/ceilometer/state"
curl "http://localhost:8888/v1/collector/ceilometer/state"
echo ''
echo "GET http://localhost:8888/v1/collector/state/ceilometer"
curl "http://localhost:8888/v1/collector/state/ceilometer"
echo ''
}
set_state()
{
echo ''
echo 'Set ceilometer state:'
echo "PUT http://localhost:8888/v1/collector/ceilometer/state"
curl "http://localhost:8888/v1/collector/ceilometer/state" \
-X PUT -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"enabled": true}'
echo ''
echo "PUT http://localhost:8888/v1/collector/state/ceilometer"
curl "http://localhost:8888/v1/collector/state/ceilometer" \
-X PUT -H "Content-Type: application/json" -H "Accept: application/json" \
-d '{"enabled": false}'
echo ''
}
list_mappings()
{
echo ''
echo 'Get compute mapping:'
echo "GET http://localhost:8888/v1/collector/mappings/compute"
curl "http://localhost:8888/v1/collector/mappings/compute"
echo ''
echo 'List ceilometer mappings:'
echo "GET http://localhost:8888/v1/collector/ceilometer/mappings"
curl "http://localhost:8888/v1/collector/ceilometer/mappings"
echo ''
}
set_mappings()
{
echo ''
echo 'Set compute to ceilometer mapping:'
echo "POST http://localhost:8888/v1/collector/ceilometer/mappings/compute"
curl "http://localhost:8888/v1/collector/ceilometer/mappings/compute" \
-X POST -H "Content-Type: application/json" -H "Accept: application/json" \
-d ''
echo ''
echo 'Set volume to ceilometer mapping:'
echo "POST http://localhost:8888/v1/collector/mappings?collector=ceilometer&service=volume"
curl "http://localhost:8888/v1/collector/mappings?collector=ceilometer&service=volume" \
-X POST -H "Content-Type: application/json" -H "Accept: application/json" \
-d ''
echo ''
}
del_mappings()
{
echo ''
echo 'Deleting compute to ceilometer mapping:'
echo "DELETE http://localhost:8888/v1/collector/ceilometer/mappings/compute"
curl "http://localhost:8888/v1/collector/ceilometer/mappings/compute" \
-X DELETE -H "Content-Type: application/json" -H "Accept: application/json" \
-d ''
test $? && echo 'OK'
echo 'Deleting volume to ceilometer mapping:'
echo "DELETE http://localhost:8888/v1/collector/mappings?collector=ceilometer&service=volume"
curl "http://localhost:8888/v1/collector/mappings?collector=ceilometer&service=volume" \
-X DELETE -H "Content-Type: application/json" -H "Accept: application/json" \
-d ''
test $? && echo 'OK'
}
show_state
set_state
list_mappings
set_mappings
list_mappings
del_mappings
list_mappings

View File

@ -11,6 +11,18 @@ Collector
.. rest-controller:: cloudkitty.api.v1.controllers.collector:MappingController
:webprefix: /v1/collector/mapping
.. rest-controller:: cloudkitty.api.v1.controllers.collector:CollectorStateController
:webprefix: /v1/collector/state
.. autotype:: cloudkitty.api.v1.datamodels.collector.CollectorInfos
:members:
.. autotype:: cloudkitty.api.v1.datamodels.collector.ServiceToCollectorMapping
:members:
.. autotype:: cloudkitty.api.v1.datamodels.collector.ServiceToCollectorMappingCollection
:members:
Rating
======

View File

@ -12,6 +12,7 @@
"collector:list_mappings": "role:admin",
"collector:get_mapping": "role:admin",
"collector:manage_mappings": "role:admin",
"collector:get_state": "role:admin",
"collector:update_state": "role:admin",