Adds Doctor Driver

This is a new DataSource Driver for Doctor project in OPNFV.
The Driver is a subclass of PushDataSourceDriver.

Change-Id: Iab6418922564dcb950d4a36b5bceeecf68bb6905
This commit is contained in:
Masahito Muroi 2016-02-25 14:19:31 -07:00
parent d7f122db21
commit 069b38e539
2 changed files with 181 additions and 0 deletions

View File

@ -0,0 +1,112 @@
# Copyright (c) 2016 NTT All rights reserved.
#
# 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 __future__ import division
from __future__ import absolute_import
from oslo_log import log as logging
import six
from congress.datasources import datasource_driver
LOG = logging.getLogger(__name__)
def d6service(name, keys, inbox, datapath, args):
"""This method is called by d6cage to create a dataservice instance."""
return DoctorDriver(name, keys, inbox, datapath, args)
class DoctorDriver(datasource_driver.PushedDataSourceDriver):
"""A DataSource Driver for OPNFV Doctor project.
This driver has a table for Doctor project's Inspector. Please check
https://wiki.opnfv.org/display/doctor/Doctor+Home for the details
about OPNFV Doctor project.
To update the table, call Update row API.
PUT /v1/data-sources/<the driver id>/tables/<table id>/rows
For updating 'events' table, the request body should be following
style. The request will replace all rows in the table with the body,
which means if you update the table with [] it will clear the table.
One {} object in the list represents one row of the table.
request body:
[
{
"id": "0123-4567-89ab",
"time": "2016-02-22T11:48:55Z",
"type": "compute.host.down",
"details": {
"hostname": "compute1",
"status": "down",
"monitor": "zabbix1",
"monitor_event_id": "111"
}
},
.....
]
"""
value_trans = {'translation-type': 'VALUE'}
def safe_id(x):
if isinstance(x, six.string_types):
return x
try:
return x['id']
except Exception:
return str(x)
def flatten_events(row_events):
flatten = []
for event in row_events:
details = event.pop('details')
for k, v in details.items():
event[k] = v
flatten.append(event)
return flatten
events_translator = {
'translation-type': 'HDICT',
'table-name': 'events',
'selector-type': 'DICT_SELECTOR',
'objects-extract-fn': flatten_events,
'field-translators':
({'fieldname': 'id', 'translator': value_trans},
{'fieldname': 'time', 'translator': value_trans},
{'fieldname': 'type', 'translator': value_trans},
{'fieldname': 'hostname', 'translator': value_trans},
{'fieldname': 'status', 'translator': value_trans},
{'fieldname': 'monitor', 'translator': value_trans},
{'fieldname': 'monitor_event_id', 'translator': value_trans},)
}
TRANSLATORS = [events_translator]
def __init__(self, name='', keys='', inbox=None, datapath=None, args=None):
super(DoctorDriver, self).__init__(name, keys, inbox, datapath, args)
@staticmethod
def get_datasource_info():
result = {}
result['id'] = 'doctor'
result['description'] = ('Datasource driver that interfaces with '
'OpenStack Compute aka nova.')
result['config'] = {}
return result

View File

@ -0,0 +1,69 @@
# Copyright (c) 2016 NTT All rights reserved.
#
# 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 __future__ import division
from __future__ import absolute_import
import mock
from congress.datasources import doctor_driver
from congress.tests import base
class TestDoctorDriver(base.TestCase):
def setUp(self):
super(TestDoctorDriver, self).setUp()
self.doctor = doctor_driver.DoctorDriver('test-doctor')
def numbered_string(self, string, number):
return string + str(number)
def generate_events_objects(self, row_number):
objects = []
for i in range(0, row_number):
obj = {
"id": self.numbered_string('id', i),
"time": self.numbered_string('time', i),
"type": self.numbered_string('type', i),
"details": {
"hostname": self.numbered_string('hostname', i),
"status": self.numbered_string('status', i),
"monitor": self.numbered_string('monitor', i),
"monitor_event_id": self.numbered_string('event_id', i),
}
}
objects.append(obj)
return objects
@mock.patch.object(doctor_driver.DoctorDriver, 'publish')
def test_events_table(self, mocked_publish):
objs = self.generate_events_objects(3)
self.doctor.update_entire_data('events', objs)
self.assertEqual(3, len(self.doctor.state['events']))
# change elements in state['events'] set to list and sort by id
sorted_state = sorted(list(self.doctor.state['events']),
key=lambda x: x[0])
for i, row in enumerate(sorted_state):
self.assertEqual(self.numbered_string('id', i), row[0])
self.assertEqual(self.numbered_string('time', i), row[1])
self.assertEqual(self.numbered_string('type', i), row[2])
self.assertEqual(self.numbered_string('hostname', i), row[3])
self.assertEqual(self.numbered_string('status', i), row[4])
self.assertEqual(self.numbered_string('monitor', i), row[5])
self.assertEqual(self.numbered_string('event_id', i), row[6])