Status API: Return live hosts and services
Change-Id: I97ccadfa06387924a368a5ac2fb27ba374b7f03f
This commit is contained in:
parent
26efcedf6b
commit
fa47ae8302
@ -17,7 +17,7 @@ Hosts
|
||||
.. rest-controller:: surveil.api.controllers.v2.status.hosts:HostController
|
||||
:webprefix: /v2/status/hosts/
|
||||
|
||||
.. rest-controller:: surveil.api.controllers.v2.status.hosts.config:ConfigController
|
||||
.. rest-controller:: surveil.api.controllers.v2.status.hosts:ConfigController
|
||||
:webprefix: /v2/status/hosts/(host_name)/config
|
||||
|
||||
.. rest-controller:: surveil.api.controllers.v2.status.metrics:MetricsController
|
||||
@ -38,6 +38,13 @@ Hosts
|
||||
.. rest-controller:: surveil.api.controllers.v2.logs.notifications:NotificationsController
|
||||
:webprefix: /v2/status/hosts/(host_name)/events/notifications
|
||||
|
||||
Services
|
||||
========
|
||||
|
||||
.. rest-controller:: surveil.api.controllers.v2.status.services:ServicesController
|
||||
:webprefix: /v2/status/services
|
||||
|
||||
|
||||
Metrics
|
||||
=======
|
||||
|
||||
@ -46,3 +53,15 @@ Metrics
|
||||
|
||||
.. rest-controller:: surveil.api.controllers.v2.status.metrics:MetricController
|
||||
:webprefix: /v2/status/metrics/
|
||||
|
||||
Types
|
||||
=====
|
||||
|
||||
.. autotype:: surveil.api.datamodel.status.live_service.LiveService
|
||||
:members:
|
||||
|
||||
.. autotype:: surveil.api.datamodel.status.live_host.LiveHost
|
||||
:members:
|
||||
|
||||
.. autotype:: surveil.api.datamodel.status.live_query.LiveQuery
|
||||
:members:
|
||||
|
@ -8,3 +8,4 @@ oslo.middleware
|
||||
oslo.policy>=0.3.0
|
||||
keystonemiddleware
|
||||
PasteDeploy
|
||||
influxdb==2.0.1
|
||||
|
@ -26,13 +26,15 @@ server = {
|
||||
# as long as is it in the same format.
|
||||
surveil_api_config = {
|
||||
"mongodb_uri": "mongodb://mongo:27017",
|
||||
"ws_arbiter_url": "http://shinken:7760"
|
||||
"ws_arbiter_url": "http://shinken:7760",
|
||||
"influxdb_uri": "influxdb://root:root@influxdb:8086/db"
|
||||
}
|
||||
|
||||
app_hooks = [
|
||||
hooks.DBHook(
|
||||
surveil_api_config['mongodb_uri'],
|
||||
surveil_api_config['ws_arbiter_url']
|
||||
surveil_api_config['ws_arbiter_url'],
|
||||
surveil_api_config['influxdb_uri']
|
||||
)
|
||||
]
|
||||
|
||||
|
@ -16,10 +16,11 @@ from pecan import rest
|
||||
|
||||
from surveil.api.controllers.v2.status import hosts as v2_hosts
|
||||
from surveil.api.controllers.v2.status import metrics
|
||||
from surveil.api.controllers.v2.status import services as v2_services
|
||||
|
||||
|
||||
class StatusController(rest.RestController):
|
||||
# events = EventsController()
|
||||
hosts = v2_hosts.HostsController()
|
||||
# services = ServicesController()
|
||||
services = v2_services.ServicesController()
|
||||
metrics = metrics.MetricsController()
|
||||
|
@ -14,18 +14,30 @@
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from surveil.api.controllers.v2 import logs
|
||||
from surveil.api.controllers.v2.status.hosts import config
|
||||
from surveil.api.controllers.v2.status import metrics
|
||||
from surveil.api.datamodel.status import live_host
|
||||
from surveil.api.datamodel.status import live_query
|
||||
from surveil.api.handlers.status import live_host_handler
|
||||
|
||||
|
||||
class HostsController(rest.RestController):
|
||||
|
||||
@pecan.expose()
|
||||
@wsme_pecan.wsexpose([live_host.LiveHost])
|
||||
def get_all(self):
|
||||
"""Returns all hosts."""
|
||||
return "ALLL HOSSSSSSSST"
|
||||
handler = live_host_handler.HostHandler(pecan.request)
|
||||
hosts = handler.get_all()
|
||||
return hosts
|
||||
|
||||
@wsme_pecan.wsexpose([live_host.LiveHost], body=live_query.LiveQuery)
|
||||
def post(self, query):
|
||||
"""Given a LiveQuery, returns all matching hosts."""
|
||||
handler = live_host_handler.HostHandler(pecan.request)
|
||||
hosts = handler.get_all(live_query=query)
|
||||
return hosts
|
||||
|
||||
@pecan.expose()
|
||||
def _lookup(self, host_name, *remainder):
|
||||
@ -37,7 +49,7 @@ class HostController(rest.RestController):
|
||||
# services = ServicesController()
|
||||
# See init for controller creation. We need host_name to instanciate it
|
||||
# externalcommands = ExternalCommandsController()
|
||||
config = config.ConfigController()
|
||||
# config = config.ConfigController()
|
||||
events = logs.LogsController()
|
||||
metrics = metrics.MetricsController()
|
||||
|
||||
@ -52,3 +64,11 @@ class HostController(rest.RestController):
|
||||
output = '{"host_name": "myhostname", "alias": %s}' % self._id
|
||||
|
||||
return output
|
||||
|
||||
|
||||
class ConfigController(rest.RestController):
|
||||
|
||||
@pecan.expose()
|
||||
def get_all(self):
|
||||
"""Returns config from a specific host."""
|
||||
return "Dump CONFIG"
|
@ -1,24 +0,0 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 pecan
|
||||
from pecan import rest
|
||||
|
||||
|
||||
class ConfigController(rest.RestController):
|
||||
|
||||
@pecan.expose()
|
||||
def get_all(self):
|
||||
"""Returns config from a specific host."""
|
||||
return "Dump CONFIG"
|
38
surveil/api/controllers/v2/status/services.py
Normal file
38
surveil/api/controllers/v2/status/services.py
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 pecan
|
||||
from pecan import rest
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from surveil.api.datamodel.status import live_query
|
||||
from surveil.api.datamodel.status import live_service
|
||||
from surveil.api.handlers.status import live_service_handler
|
||||
|
||||
|
||||
class ServicesController(rest.RestController):
|
||||
|
||||
@wsme_pecan.wsexpose([live_service.LiveService])
|
||||
def get_all(self):
|
||||
"""Returns all services."""
|
||||
handler = live_service_handler.ServiceHandler(pecan.request)
|
||||
services = handler.get_all()
|
||||
return services
|
||||
|
||||
@wsme_pecan.wsexpose([live_service.LiveService], body=live_query.LiveQuery)
|
||||
def post(self, query):
|
||||
"""Given a LiveQuery, returns all matching services."""
|
||||
handler = live_service_handler.ServiceHandler(pecan.request)
|
||||
services = handler.get_all(live_query=query)
|
||||
return services
|
0
surveil/api/datamodel/status/__init__.py
Normal file
0
surveil/api/datamodel/status/__init__.py
Normal file
49
surveil/api/datamodel/status/live_host.py
Normal file
49
surveil/api/datamodel/status/live_host.py
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 wsme
|
||||
import wsme.types as wtypes
|
||||
|
||||
from surveil.api.controllers.v1.datamodel import types
|
||||
|
||||
|
||||
class LiveHost(types.Base):
|
||||
host_name = wsme.wsattr(wtypes.text, mandatory=False)
|
||||
"""The name of the host"""
|
||||
|
||||
description = wsme.wsattr(wtypes.text, mandatory=False)
|
||||
"""The description of the host"""
|
||||
|
||||
state = wsme.wsattr(int, mandatory=False)
|
||||
"""The current state of the host"""
|
||||
|
||||
last_check = wsme.wsattr(int, mandatory=False)
|
||||
"""The last time the host was checked"""
|
||||
|
||||
last_state_change = wsme.wsattr(int, mandatory=False)
|
||||
"""The last time the state has changed"""
|
||||
|
||||
plugin_output = wsme.wsattr(wtypes.text, mandatory=False)
|
||||
"""Plugin output of the last check"""
|
||||
|
||||
@classmethod
|
||||
def sample(cls):
|
||||
return cls(
|
||||
host_name='CoolHost',
|
||||
description='Very Nice Host',
|
||||
state=0,
|
||||
last_check=1429220785,
|
||||
last_state_change=1429220785,
|
||||
plugin_output='PING OK - Packet loss = 0%, RTA = 0.02 ms'
|
||||
)
|
42
surveil/api/datamodel/status/live_query.py
Normal file
42
surveil/api/datamodel/status/live_query.py
Normal file
@ -0,0 +1,42 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 json
|
||||
|
||||
import wsme
|
||||
import wsme.types as wtypes
|
||||
|
||||
from surveil.api.controllers.v1.datamodel import types
|
||||
|
||||
|
||||
class LiveQuery(types.Base):
|
||||
"""Holds a sample query encoded in json."""
|
||||
|
||||
filters = wsme.wsattr(wtypes.text, mandatory=True)
|
||||
"The filter expression encoded in json."
|
||||
|
||||
fields = wsme.wsattr(wtypes.text, mandatory=True)
|
||||
"List of fields to include in the response."
|
||||
|
||||
@classmethod
|
||||
def sample(cls):
|
||||
return cls(
|
||||
fields=json.dumps(['host_name', 'last_check']),
|
||||
filters=json.dumps({
|
||||
"isnot": {
|
||||
"state": ["0", "1"],
|
||||
"host_state": ["2"]
|
||||
}
|
||||
})
|
||||
)
|
53
surveil/api/datamodel/status/live_service.py
Normal file
53
surveil/api/datamodel/status/live_service.py
Normal file
@ -0,0 +1,53 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 wsme
|
||||
import wsme.types as wtypes
|
||||
|
||||
from surveil.api.controllers.v1.datamodel import types
|
||||
|
||||
|
||||
class LiveService(types.Base):
|
||||
host_name = wsme.wsattr(wtypes.text, mandatory=False)
|
||||
"""The host for the service"""
|
||||
|
||||
service_description = wsme.wsattr(wtypes.text, mandatory=False)
|
||||
"""The name of the service"""
|
||||
|
||||
description = wsme.wsattr(wtypes.text, mandatory=False)
|
||||
"""The description of the sevice"""
|
||||
|
||||
state = wsme.wsattr(int, mandatory=False)
|
||||
"""The current state of the service"""
|
||||
|
||||
last_check = wsme.wsattr(int, mandatory=False)
|
||||
"""The last time the service was checked"""
|
||||
|
||||
last_state_change = wsme.wsattr(int, mandatory=False)
|
||||
"""The last time the state has changed"""
|
||||
|
||||
plugin_output = wsme.wsattr(wtypes.text, mandatory=False)
|
||||
"""Plugin output of the last check"""
|
||||
|
||||
@classmethod
|
||||
def sample(cls):
|
||||
return cls(
|
||||
host_name='Webserver',
|
||||
service_name='Apache',
|
||||
description='Serves Stuff',
|
||||
state=0,
|
||||
last_check=1429220785,
|
||||
last_state_change=1429220785,
|
||||
plugin_output='HTTP OK - GOT NICE RESPONSE'
|
||||
)
|
0
surveil/api/handlers/status/__init__.py
Normal file
0
surveil/api/handlers/status/__init__.py
Normal file
52
surveil/api/handlers/status/liveQuery_filter.py
Normal file
52
surveil/api/handlers/status/liveQuery_filter.py
Normal file
@ -0,0 +1,52 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 json
|
||||
|
||||
|
||||
def filter_dict_list_with_live_query(item_list, live_query):
|
||||
filters = json.loads(live_query.filters)
|
||||
|
||||
matching_items = []
|
||||
|
||||
for item in item_list:
|
||||
matches = True
|
||||
|
||||
# Filters are, for example, 'isnot' or 'is'
|
||||
for filter in filters.items():
|
||||
|
||||
# Fields are, for example, 'STATE'
|
||||
for field in filter[1].items():
|
||||
|
||||
# Values are, for example, 0, 1, UP, Down...
|
||||
for value in field[1]:
|
||||
|
||||
if filter[0] == "isnot":
|
||||
if item[field[0]] == value:
|
||||
matches = False
|
||||
break
|
||||
elif filter[0] == "is":
|
||||
if item[field[0]] != value:
|
||||
matches = False
|
||||
break
|
||||
|
||||
if matches:
|
||||
fields = json.loads(live_query.fields)
|
||||
matching_item = {}
|
||||
for field in fields:
|
||||
matching_item[field] = item[field]
|
||||
|
||||
matching_items.append(matching_item)
|
||||
|
||||
return matching_items
|
58
surveil/api/handlers/status/live_host_handler.py
Normal file
58
surveil/api/handlers/status/live_host_handler.py
Normal file
@ -0,0 +1,58 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 __future__ import print_function
|
||||
|
||||
from surveil.api.datamodel.status import live_host
|
||||
from surveil.api.handlers import handler
|
||||
from surveil.api.handlers.status import liveQuery_filter as query_filter
|
||||
|
||||
|
||||
class HostHandler(handler.Handler):
|
||||
"""Fulfills a request on the live hosts."""
|
||||
|
||||
def get_all(self, live_query=None):
|
||||
"""Return all live hosts."""
|
||||
cli = self.request.influxdb_client
|
||||
query = "SELECT * from HOST_STATE GROUP BY host_name LIMIT 1"
|
||||
response = cli.query(query)
|
||||
|
||||
host_dicts = []
|
||||
|
||||
for item in response.items():
|
||||
first_entry = next(item[1])
|
||||
|
||||
host_dict = {
|
||||
"host_name": item[0][1]['host_name'],
|
||||
"description": item[0][1]['host_name'],
|
||||
"state": first_entry['state'],
|
||||
"last_check": int(first_entry['last_check']),
|
||||
"last_state_change": int(first_entry['last_state_change']),
|
||||
"plugin_output": first_entry['output']
|
||||
}
|
||||
|
||||
host_dicts.append(host_dict)
|
||||
|
||||
if live_query:
|
||||
host_dicts = query_filter.filter_dict_list_with_live_query(
|
||||
host_dicts,
|
||||
live_query
|
||||
)
|
||||
|
||||
hosts = []
|
||||
for host_dict in host_dicts:
|
||||
host = live_host.LiveHost(**host_dict)
|
||||
hosts.append(host)
|
||||
|
||||
return hosts
|
64
surveil/api/handlers/status/live_service_handler.py
Normal file
64
surveil/api/handlers/status/live_service_handler.py
Normal file
@ -0,0 +1,64 @@
|
||||
# Copyright 2014 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 __future__ import print_function
|
||||
|
||||
from surveil.api.datamodel.status import live_service
|
||||
from surveil.api.handlers import handler
|
||||
from surveil.api.handlers.status import liveQuery_filter as query_filter
|
||||
|
||||
|
||||
class ServiceHandler(handler.Handler):
|
||||
"""Fulfills a request on live services."""
|
||||
|
||||
def get_all(self, live_query=None):
|
||||
"""Return all live services."""
|
||||
cli = self.request.influxdb_client
|
||||
query = (
|
||||
"SELECT * from SERVICE_STATE "
|
||||
"GROUP BY host_name, service_description "
|
||||
"LIMIT 1"
|
||||
)
|
||||
|
||||
response = cli.query(query)
|
||||
|
||||
service_dicts = []
|
||||
|
||||
for item in response.items():
|
||||
first_entry = next(item[1])
|
||||
|
||||
service_dict = {
|
||||
"service_description": item[0][1]['service_description'],
|
||||
"host_name": item[0][1]['host_name'],
|
||||
"description": item[0][1]['service_description'],
|
||||
"state": first_entry['state'],
|
||||
"last_check": int(first_entry['last_check']),
|
||||
"last_state_change": int(first_entry['last_state_change']),
|
||||
"plugin_output": first_entry['output']
|
||||
}
|
||||
|
||||
service_dicts.append(service_dict)
|
||||
|
||||
if live_query:
|
||||
service_dicts = query_filter.filter_dict_list_with_live_query(
|
||||
service_dicts,
|
||||
live_query
|
||||
)
|
||||
|
||||
services = []
|
||||
for service_dict in service_dicts:
|
||||
service = live_service.LiveService(**service_dict)
|
||||
services.append(service)
|
||||
|
||||
return services
|
@ -12,21 +12,26 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import influxdb
|
||||
from pecan import hooks
|
||||
import pymongo
|
||||
|
||||
|
||||
class DBHook(hooks.PecanHook):
|
||||
|
||||
def __init__(self, mongo_url, ws_arbiter_url):
|
||||
def __init__(self, mongo_url, ws_arbiter_url, influxdb_url):
|
||||
self.mongo_url = mongo_url
|
||||
self.ws_arbiter_url = ws_arbiter_url
|
||||
self.influxdb_url = influxdb_url
|
||||
|
||||
def before(self, state):
|
||||
self.mongoclient = pymongo.MongoClient(self.mongo_url)
|
||||
|
||||
state.request.mongo_connection = self.mongoclient
|
||||
state.request.ws_arbiter_url = self.ws_arbiter_url
|
||||
state.request.influxdb_client = influxdb.InfluxDBClient.from_DSN(
|
||||
self.influxdb_url
|
||||
)
|
||||
|
||||
def after(self, state):
|
||||
self.mongoclient.close()
|
||||
|
0
surveil/tests/api/controllers/v2/status/__init__.py
Normal file
0
surveil/tests/api/controllers/v2/status/__init__.py
Normal file
93
surveil/tests/api/controllers/v2/status/test_hosts.py
Normal file
93
surveil/tests/api/controllers/v2/status/test_hosts.py
Normal file
@ -0,0 +1,93 @@
|
||||
# Copyright 2015 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 json
|
||||
|
||||
import httpretty
|
||||
|
||||
from surveil.tests.api import functionalTest
|
||||
|
||||
|
||||
class TestStatusHosts(functionalTest.FunctionalTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestStatusHosts, self).setUp()
|
||||
self.influxdb_response = (
|
||||
'{"results":[{"series":[{"name":"HOST_STATE","tags":{"host_nam'
|
||||
'e":"localhost"},"columns":["time","last_check","last_state_chan'
|
||||
'ge","output","state","state_type"],"values":[["201'
|
||||
'5-04-19T01:09:24Z",1.429405764e+09,1.429405765316929e+09,"OK '
|
||||
'- localhost: rta 0.033ms, lost 0%",0,"HARD"]]},{"name":"'
|
||||
'HOST_STATE","tags":{"host_name":"test_keystone"},"columns":["'
|
||||
'time","last_check","last_state_change","output","state",'
|
||||
'"state_type"],"values":[["2015-04-19T01:09:23Z",1.4294057'
|
||||
'63e+09,1.429405765317144e+09,"OK - 127.0.0.1: rta 0.032ms, lo'
|
||||
'st 0%",0,"HARD"]]},{"name":"HOST_STATE","tags":{"host_na'
|
||||
'me":"ws-arbiter"},"columns":["time","last_check","last_state_ch'
|
||||
'ange","output","state","state_type"],"values":[["2'
|
||||
'015-04-19T01:09:24Z",1.429405764e+09,1.429405765317063e+09,"O'
|
||||
'K - localhost: rta 0.030ms, lost 0%",0,"HARD"]]}]}]}'
|
||||
)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_all_hosts(self):
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
"http://influxdb:8086/query",
|
||||
body=self.influxdb_response)
|
||||
|
||||
response = self.app.get("/v2/status/hosts")
|
||||
|
||||
expected = [
|
||||
{"description": "localhost",
|
||||
"last_state_change": 1429405765,
|
||||
"plugin_output": "OK - localhost: rta 0.033ms, lost 0%",
|
||||
"last_check": 1429405764,
|
||||
"state": 0,
|
||||
"host_name": "localhost"},
|
||||
{"description": "test_keystone",
|
||||
"last_state_change": 1429405765,
|
||||
"plugin_output": "OK - 127.0.0.1: rta 0.032ms, lost 0%",
|
||||
"last_check": 1429405763,
|
||||
"state": 0,
|
||||
"host_name": "test_keystone"},
|
||||
{"description": "ws-arbiter",
|
||||
"last_state_change": 1429405765,
|
||||
"plugin_output": "OK - localhost: rta 0.030ms, lost 0%",
|
||||
"last_check": 1429405764,
|
||||
"state": 0,
|
||||
"host_name": "ws-arbiter"}]
|
||||
|
||||
self.assertEqual(json.loads(response.body), expected)
|
||||
|
||||
@httpretty.activate
|
||||
def test_query_hosts(self):
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
"http://influxdb:8086/query",
|
||||
body=self.influxdb_response)
|
||||
|
||||
query = {
|
||||
'fields': json.dumps(['host_name', 'last_check']),
|
||||
'filters': json.dumps({
|
||||
"isnot": {
|
||||
"host_name": ['localhost'],
|
||||
"description": ["test_keystone"]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
response = self.app.post_json("/v2/status/hosts", params=query)
|
||||
|
||||
expected = [{"host_name": "ws-arbiter", "last_check": 1429405764}]
|
||||
|
||||
self.assertEqual(json.loads(response.body), expected)
|
94
surveil/tests/api/controllers/v2/status/test_services.py
Normal file
94
surveil/tests/api/controllers/v2/status/test_services.py
Normal file
@ -0,0 +1,94 @@
|
||||
# Copyright 2015 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 json
|
||||
|
||||
import httpretty
|
||||
|
||||
from surveil.tests.api import functionalTest
|
||||
|
||||
|
||||
class TestStatusServices(functionalTest.FunctionalTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestStatusServices, self).setUp()
|
||||
self.influxdb_response = (
|
||||
'{"results":[{"series":[{"name":"SERVICE_STATE","tags":{"host_nam'
|
||||
'e":"test_keystone","service_description":"Check KeyStone service'
|
||||
'."},"columns":["time","last_check","last_state_change","output",'
|
||||
'"state","state_type"],"values":[["2015-04-19T18:20:34Z",1.429467'
|
||||
'634e+09,1.429467636632134e+09,"There was no suitable authenticat'
|
||||
'ion url for this request",3,"SOFT"]]},{"name":"SERVICE_STATE","t'
|
||||
'ags":{"host_name":"ws-arbiter","service_description":"check-ws-a'
|
||||
'rbiter"},"columns":["time","last_check","last_state_change","out'
|
||||
'put","state","state_type"],"values":[["2015-04-19T18:20:33Z",1.4'
|
||||
'29467633e+09,1.429467635629833e+09,"TCP OK - 0.000 second respon'
|
||||
'se time on port 7760",0,"HARD"]]}]}]}'
|
||||
)
|
||||
|
||||
@httpretty.activate
|
||||
def test_get_all_services(self):
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
"http://influxdb:8086/query",
|
||||
body=self.influxdb_response)
|
||||
|
||||
response = self.app.get("/v2/status/services")
|
||||
|
||||
expected = [
|
||||
{'description': 'Check KeyStone service.',
|
||||
'last_state_change': 1429467636,
|
||||
'plugin_output':
|
||||
'There was no suitable authentication url for this request',
|
||||
'last_check': 1429467634,
|
||||
'state': 3,
|
||||
'host_name': 'test_keystone',
|
||||
'service_description': 'Check KeyStone service.'},
|
||||
{'description': 'check-ws-arbiter',
|
||||
'last_state_change': 1429467635,
|
||||
'plugin_output':
|
||||
'TCP OK - 0.000 second response time on port 7760',
|
||||
'last_check': 1429467633,
|
||||
'state': 0,
|
||||
'host_name': 'ws-arbiter',
|
||||
'service_description': 'check-ws-arbiter'}
|
||||
]
|
||||
|
||||
self.assertEqual(json.loads(response.body), expected)
|
||||
|
||||
@httpretty.activate
|
||||
def test_query_services(self):
|
||||
httpretty.register_uri(httpretty.GET,
|
||||
"http://influxdb:8086/query",
|
||||
body=self.influxdb_response)
|
||||
|
||||
query = {
|
||||
'fields': json.dumps(['host_name', 'service_description']),
|
||||
'filters': json.dumps({
|
||||
"isnot": {
|
||||
"host_name": ['ws-arbiter'],
|
||||
},
|
||||
"is": {
|
||||
"service_description": ["Check KeyStone service."]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
response = self.app.post_json("/v2/status/services", params=query)
|
||||
|
||||
expected = [
|
||||
{'host_name': 'test_keystone',
|
||||
'service_description': 'Check KeyStone service.'}
|
||||
]
|
||||
|
||||
self.assertEqual(json.loads(response.body), expected)
|
@ -14,6 +14,7 @@
|
||||
|
||||
import os
|
||||
|
||||
import influxdb
|
||||
import mongomock
|
||||
from oslo_config import cfg
|
||||
import pecan
|
||||
@ -37,20 +38,26 @@ class FunctionalTest(base.BaseTestCase):
|
||||
|
||||
self.mongoconnection = mongomock.Connection()
|
||||
self.ws_arbiter_url = "http://localhost:7760"
|
||||
self.influxdb_client = influxdb.InfluxDBClient.from_DSN(
|
||||
'influxdb://root:root@influxdb:8086/db'
|
||||
)
|
||||
|
||||
class TestHook(hooks.PecanHook):
|
||||
def __init__(self, mongoclient, wsarbiterurl):
|
||||
def __init__(self, mongoclient, wsarbiterurl, influxdb_client):
|
||||
self.mongoclient = mongoclient
|
||||
self.ws_arbiter_url = wsarbiterurl
|
||||
self.influxdb_client = influxdb_client
|
||||
|
||||
def before(self, state):
|
||||
state.request.mongo_connection = self.mongoclient
|
||||
state.request.ws_arbiter_url = self.ws_arbiter_url
|
||||
state.request.influxdb_client = self.influxdb_client
|
||||
|
||||
app_hooks = [
|
||||
TestHook(
|
||||
self.mongoconnection,
|
||||
self.ws_arbiter_url
|
||||
self.ws_arbiter_url,
|
||||
self.influxdb_client
|
||||
)
|
||||
]
|
||||
|
||||
|
0
surveil/tests/api/handlers/__init__.py
Normal file
0
surveil/tests/api/handlers/__init__.py
Normal file
0
surveil/tests/api/handlers/live/__init__.py
Normal file
0
surveil/tests/api/handlers/live/__init__.py
Normal file
86
surveil/tests/api/handlers/live/test_liveQuery_filter.py
Normal file
86
surveil/tests/api/handlers/live/test_liveQuery_filter.py
Normal file
@ -0,0 +1,86 @@
|
||||
# Copyright 2015 - Savoir-Faire Linux inc.
|
||||
#
|
||||
# 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 json
|
||||
|
||||
from surveil.api.datamodel.status import live_query
|
||||
from surveil.api.handlers.status import liveQuery_filter as query_filter
|
||||
from surveil.tests import base
|
||||
|
||||
|
||||
class LiveQueryFilterTest(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.items = [
|
||||
{"description": "localhost",
|
||||
"last_state_change": 1429400991,
|
||||
"plugin_output": "OK - localhost: rta 0.047ms, lost 0%",
|
||||
"last_check": 1429400990,
|
||||
"state": 0,
|
||||
"host_name": "localhost"},
|
||||
{"description": "test_keystone",
|
||||
"last_state_change": 1429400986,
|
||||
"plugin_output": "OK - 127.0.0.1: rta 0.045ms, lost 0%",
|
||||
"last_check": 1429400984, "state": 2,
|
||||
"host_name": "test_keystone"},
|
||||
{"description": "ws-arbiter",
|
||||
"last_state_change": 1429400991,
|
||||
"plugin_output": "OK - localhost: rta 0.042ms, lost 0%",
|
||||
"last_check": 1429400990,
|
||||
"state": 2,
|
||||
"host_name": "ws-arbiter"}
|
||||
]
|
||||
|
||||
def test_query_builder_filter_isnot(self):
|
||||
query = live_query.LiveQuery(
|
||||
fields=json.dumps(['host_name', 'last_check']),
|
||||
filters=json.dumps({
|
||||
"isnot": {
|
||||
"state": [0, 1],
|
||||
"description": ["test_keystone"]
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
result = query_filter.filter_dict_list_with_live_query(
|
||||
self.items,
|
||||
query
|
||||
)
|
||||
|
||||
expected = [{"last_check": 1429400990, "host_name": "ws-arbiter"}]
|
||||
|
||||
self.assertItemsEqual(result, expected)
|
||||
|
||||
def test_query_builder_filter_is(self):
|
||||
query = live_query.LiveQuery(
|
||||
fields=json.dumps(['host_name']),
|
||||
filters=json.dumps({
|
||||
"is": {
|
||||
"state": [0],
|
||||
"description": ["localhost"]
|
||||
},
|
||||
"isnot": {
|
||||
"state": [1]
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
result = query_filter.filter_dict_list_with_live_query(
|
||||
self.items,
|
||||
query
|
||||
)
|
||||
|
||||
expected = [{"host_name": "localhost"}]
|
||||
|
||||
self.assertItemsEqual(result, expected)
|
Loading…
Reference in New Issue
Block a user