Remove class HttpDispatcher

Remove class HttpDispatcher and use http publisher instead

Change-Id: If4174431c9a09e237fb79c9643a54748afe797b0
This commit is contained in:
zhangxuanyuan 2017-09-12 17:10:36 +08:00
parent e86aa05112
commit 481e6151af
5 changed files with 1 additions and 409 deletions

View File

@ -1,175 +0,0 @@
# Copyright 2013 IBM Corp
#
# 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 debtcollector import removals
from oslo_config import cfg
from oslo_log import log
from oslo_utils import strutils
import requests
from ceilometer import dispatcher
LOG = log.getLogger(__name__)
http_dispatcher_opts = [
cfg.StrOpt('target',
default='',
help='The target where the http request will be sent. '
'If this is not set, no data will be posted. For '
'example: target = http://hostname:1234/path'),
cfg.StrOpt('event_target',
help='The target for event data where the http request '
'will be sent to. If this is not set, it will default '
'to same as Sample target.'),
cfg.IntOpt('timeout',
default=5,
help='The max time in seconds to wait for a request to '
'timeout.'),
cfg.StrOpt('verify_ssl',
help='The path to a server certificate or directory if the '
'system CAs are not used or if a self-signed certificate '
'is used. Set to False to ignore SSL cert verification.'),
cfg.BoolOpt('batch_mode',
default=False,
help='Indicates whether samples are published in a batch.'),
]
@removals.removed_class("HttpDispatcher", message="Use http publisher instead",
removal_version="9.0.0")
class HttpDispatcher(dispatcher.MeterDispatcherBase,
dispatcher.EventDispatcherBase):
"""Dispatcher class for posting metering/event data into a http target.
To enable this dispatcher, the following option needs to be present in
ceilometer.conf file::
[DEFAULT]
meter_dispatchers = http
event_dispatchers = http
Dispatcher specific options can be added as follows::
[dispatcher_http]
target = www.example.com
event_target = www.example.com
timeout = 2
# No SSL verification
#verify_ssl = False
# SSL verification with system-installed CAs
verify_ssl = True
# SSL verification with specific CA or directory of certs
#verify_ssl = /path/to/ca_certificate.crt
Instead of publishing events and meters as JSON objects in individual HTTP
requests, they can be batched up and published as JSON arrays of objects::
[dispatcher_http]
batch_mode = True
"""
def __init__(self, conf):
super(HttpDispatcher, self).__init__(conf)
self.headers = {'Content-type': 'application/json'}
self.timeout = self.conf.dispatcher_http.timeout
self.target = self.conf.dispatcher_http.target
self.event_target = (self.conf.dispatcher_http.event_target or
self.target)
if self.conf.dispatcher_http.batch_mode:
self.post_event_data = self.post_event
self.post_meter_data = self.post_meter
else:
self.post_event_data = self.post_individual_events
self.post_meter_data = self.post_individual_meters
try:
self.verify_ssl = strutils.bool_from_string(
self.conf.dispatcher_http.verify_ssl, strict=True)
except ValueError:
self.verify_ssl = self.conf.dispatcher_http.verify_ssl or True
def record_metering_data(self, data):
if self.target == '':
# if the target was not set, do not do anything
LOG.error('Dispatcher target was not set, no meter will '
'be posted. Set the target in the ceilometer.conf '
'file.')
return
# We may have receive only one counter on the wire
if not isinstance(data, list):
data = [data]
self.post_meter_data(data)
def post_individual_meters(self, meters):
for meter in meters:
self.post_meter(meter)
def post_meter(self, meter):
meter_json = json.dumps(meter)
res = None
try:
LOG.trace('Meter Message: %s', meter_json)
res = requests.post(self.target,
data=meter_json,
headers=self.headers,
verify=self.verify_ssl,
timeout=self.timeout)
LOG.debug('Meter message posting finished with status code '
'%d.', res.status_code)
res.raise_for_status()
except requests.exceptions.HTTPError:
LOG.exception('Status Code: %(code)s. '
'Failed to dispatch meter: %(meter)s' %
{'code': res.status_code, 'meter': meter_json})
def record_events(self, events):
if self.event_target == '':
# if the event target was not set, do not do anything
LOG.error('Dispatcher event target was not set, no event will '
'be posted. Set event_target in the ceilometer.conf '
'file.')
return
if not isinstance(events, list):
events = [events]
self.post_event_data(events)
def post_individual_events(self, events):
for event in events:
self.post_event(event)
def post_event(self, event):
res = None
try:
event_json = json.dumps(event)
LOG.trace('Event Message: %s', event_json)
res = requests.post(self.event_target,
data=event_json,
headers=self.headers,
verify=self.verify_ssl,
timeout=self.timeout)
LOG.debug('Event Message posting to %s: status code %d.',
self.event_target, res.status_code)
res.raise_for_status()
except requests.exceptions.HTTPError:
LOG.exception('Status Code: %(code)s. '
'Failed to dispatch event: %(event)s' %
{'code': res.status_code, 'event': event_json})

View File

@ -28,7 +28,6 @@ import ceilometer.compute.virt.vmware.inspector
import ceilometer.compute.virt.xenapi.inspector import ceilometer.compute.virt.xenapi.inspector
import ceilometer.dispatcher import ceilometer.dispatcher
import ceilometer.dispatcher.gnocchi_opts import ceilometer.dispatcher.gnocchi_opts
import ceilometer.dispatcher.http
import ceilometer.event.converter import ceilometer.event.converter
import ceilometer.exchange_control import ceilometer.exchange_control
import ceilometer.hardware.discovery import ceilometer.hardware.discovery
@ -111,7 +110,6 @@ def list_opts():
'membership has changed'), 'membership has changed'),
]), ]),
('database', ceilometer.storage.OPTS), ('database', ceilometer.storage.OPTS),
('dispatcher_http', ceilometer.dispatcher.http.http_dispatcher_opts),
('dispatcher_gnocchi', ('dispatcher_gnocchi',
ceilometer.dispatcher.gnocchi_opts.dispatcher_opts), ceilometer.dispatcher.gnocchi_opts.dispatcher_opts),
('event', ceilometer.event.converter.OPTS), ('event', ceilometer.event.converter.OPTS),

View File

@ -31,7 +31,7 @@ class DirectPublisher(publisher.ConfigPublisherBase):
are required. are required.
By default, the database dispatcher is used to select another one we By default, the database dispatcher is used to select another one we
can use direct://?dispatcher=gnocchi, direct://?dispatcher=http, ... can use direct://?dispatcher=gnocchi, ...
""" """
def __init__(self, conf, parsed_url): def __init__(self, conf, parsed_url):
super(DirectPublisher, self).__init__(conf, parsed_url) super(DirectPublisher, self).__init__(conf, parsed_url)

View File

@ -1,229 +0,0 @@
#
# Copyright 2013 IBM Corp
#
# 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
import mock
from oslotest import base
import requests
from ceilometer.dispatcher import http
from ceilometer.event.storage import models as event_models
from ceilometer.publisher import utils
from ceilometer import service
class TestDispatcherHttp(base.BaseTestCase):
"""Test sending meters with the http dispatcher"""
def setUp(self):
super(TestDispatcherHttp, self).setUp()
self.CONF = service.prepare_service([], [])
self.msg = {'counter_name': 'test',
'resource_id': self.id(),
'counter_volume': 1,
}
self.msg['message_signature'] = utils.compute_signature(
self.msg, self.CONF.publisher.telemetry_secret,
)
def test_http_dispatcher_config_options(self):
self.CONF.dispatcher_http.target = 'fake'
self.CONF.dispatcher_http.timeout = 2
dispatcher = http.HttpDispatcher(self.CONF)
self.assertEqual('fake', dispatcher.target)
self.assertEqual(2, dispatcher.timeout)
def test_http_dispatcher_with_no_target(self):
self.CONF.dispatcher_http.target = ''
dispatcher = http.HttpDispatcher(self.CONF)
# The target should be None
self.assertEqual('', dispatcher.target)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_metering_data(self.msg)
# Since the target is not set, no http post should occur, thus the
# call_count should be zero.
self.assertEqual(0, post.call_count)
def test_http_dispatcher_with_no_metadata(self):
self.CONF.dispatcher_http.target = 'fake'
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_metering_data(self.msg)
self.assertEqual(1, post.call_count)
def test_http_dispatcher_with_ssl_default(self):
self.CONF.dispatcher_http.target = 'https://example.com'
self.CONF.dispatcher_http.verify_ssl = ''
dispatcher = http.HttpDispatcher(self.CONF)
self.assertEqual(True, dispatcher.verify_ssl)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_metering_data(self.msg)
self.assertEqual(True, post.call_args[1]['verify'])
def test_http_dispatcher_with_ssl_true(self):
self.CONF.dispatcher_http.target = 'https://example.com'
self.CONF.dispatcher_http.verify_ssl = 'true'
dispatcher = http.HttpDispatcher(self.CONF)
self.assertEqual(True, dispatcher.verify_ssl)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_metering_data(self.msg)
self.assertEqual(True, post.call_args[1]['verify'])
def test_http_dispatcher_with_ssl_false(self):
self.CONF.dispatcher_http.target = 'https://example.com'
self.CONF.dispatcher_http.verify_ssl = 'false'
dispatcher = http.HttpDispatcher(self.CONF)
self.assertEqual(False, dispatcher.verify_ssl)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_metering_data(self.msg)
self.assertEqual(False, post.call_args[1]['verify'])
def test_http_dispatcher_with_ssl_path(self):
self.CONF.dispatcher_http.target = 'https://example.com'
self.CONF.dispatcher_http.verify_ssl = '/path/to/cert.crt'
dispatcher = http.HttpDispatcher(self.CONF)
self.assertEqual('/path/to/cert.crt', dispatcher.verify_ssl)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_metering_data(self.msg)
self.assertEqual('/path/to/cert.crt', post.call_args[1]['verify'])
def test_http_dispatcher_non_batch(self):
self.CONF.dispatcher_http.target = 'fake'
self.CONF.dispatcher_http.batch_mode = False
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch('requests.post') as post:
dispatcher.record_metering_data([self.msg, self.msg])
self.assertEqual(2, post.call_count)
def test_http_dispatcher_batch(self):
self.CONF.dispatcher_http.target = 'fake'
self.CONF.dispatcher_http.batch_mode = True
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch('requests.post') as post:
dispatcher.record_metering_data([self.msg, self.msg, self.msg])
self.assertEqual(1, post.call_count)
class TestEventDispatcherHttp(base.BaseTestCase):
"""Test sending events with the http dispatcher"""
def setUp(self):
super(TestEventDispatcherHttp, self).setUp()
self.CONF = service.prepare_service([], [])
# repr(uuid.uuid4()) is used in test event creation to avoid an
# exception being thrown when the uuid is serialized to JSON
event = event_models.Event(repr(uuid.uuid4()), 'test',
datetime.datetime(2012, 7, 2, 13, 53, 40),
[], {})
event = utils.message_from_event(event,
self.CONF.publisher.telemetry_secret)
self.event = event
def test_http_dispatcher(self):
self.CONF.dispatcher_http.event_target = 'fake'
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_events(self.event)
self.assertEqual(1, post.call_count)
def test_http_dispatcher_bad_server(self):
self.CONF.dispatcher_http.event_target = 'fake'
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch.object(requests, 'post') as post:
response = requests.Response()
response.status_code = 500
post.return_value = response
with mock.patch('ceilometer.dispatcher.http.LOG',
mock.MagicMock()) as LOG:
dispatcher.record_events(self.event)
self.assertTrue(LOG.exception.called)
def test_http_dispatcher_with_no_target(self):
self.CONF.dispatcher_http.event_target = ''
dispatcher = http.HttpDispatcher(self.CONF)
# The target should be None
self.assertEqual('', dispatcher.event_target)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_events(self.event)
# Since the target is not set, no http post should occur, thus the
# call_count should be zero.
self.assertEqual(0, post.call_count)
def test_http_dispatcher_share_target(self):
self.CONF.dispatcher_http.event_target = 'fake'
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_events(self.event)
self.assertEqual('fake', post.call_args[0][0])
def test_http_dispatcher_with_ssl_path(self):
self.CONF.dispatcher_http.event_target = 'https://example.com'
self.CONF.dispatcher_http.verify_ssl = '/path/to/cert.crt'
dispatcher = http.HttpDispatcher(self.CONF)
self.assertEqual('/path/to/cert.crt', dispatcher.verify_ssl)
with mock.patch.object(requests, 'post') as post:
dispatcher.record_events(self.event)
self.assertEqual('/path/to/cert.crt', post.call_args[1]['verify'])
def test_http_dispatcher_nonbatch_event(self):
self.CONF.dispatcher_http.event_target = 'fake'
self.CONF.dispatcher_http.batch_mode = False
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch('requests.post') as post:
dispatcher.record_events([self.event, self.event])
self.assertEqual(2, post.call_count)
def test_http_dispatcher_batch_event(self):
self.CONF.dispatcher_http.event_target = 'fake'
self.CONF.dispatcher_http.batch_mode = True
dispatcher = http.HttpDispatcher(self.CONF)
with mock.patch('requests.post') as post:
dispatcher.record_events([self.event, self.event])
self.assertEqual(1, post.call_count)

View File

@ -287,11 +287,9 @@ console_scripts =
ceilometer.dispatcher.meter = ceilometer.dispatcher.meter =
database = ceilometer.dispatcher.database:MeterDatabaseDispatcher database = ceilometer.dispatcher.database:MeterDatabaseDispatcher
http = ceilometer.dispatcher.http:HttpDispatcher
gnocchi = ceilometer.dispatcher.gnocchi:GnocchiDispatcher gnocchi = ceilometer.dispatcher.gnocchi:GnocchiDispatcher
ceilometer.dispatcher.event = ceilometer.dispatcher.event =
http = ceilometer.dispatcher.http:HttpDispatcher
gnocchi = ceilometer.dispatcher.gnocchi:GnocchiDispatcher gnocchi = ceilometer.dispatcher.gnocchi:GnocchiDispatcher
network.statistics.drivers = network.statistics.drivers =