asinspector工具怎么安装

Comparison of JungleScout vs ASINspector - side by side=== renamed file '.coveragerc' => '.coveragerc'
=== removed file '.gitignore'
--- debian/.gitignore
20:55:14 +0000
+++ ubuntu/.gitignore
00:00:00 +0000
@@ -1,17 +0,0 @@
-.coverage
-.testrepository
-ChangeLog
-doc/build
-doc/source/api/
-etc/ceilometer/ceilometer.conf
-subunit.log
-tools/lintstack.head.py
-tools/pylint_exceptions
=== removed file '.gitreview'
--- debian/.gitreview
20:55:14 +0000
+++ ubuntu/.gitreview
00:00:00 +0000
@@ -1,4 +0,0 @@
-host=review.openstack.org
-port=29418
-project=openstack/ceilometer.git
=== renamed file '.mailmap' => '.mailmap'
=== renamed directory '.pc' => '.pc'
=== modified file '.pc/applied-patches'
--- debian/.pc/applied-patches
13:37:36 +0000
+++ ubuntu/.pc/applied-patches
11:28:21 +0000
@@ -0,0 +1,4 @@
+skip-db-tests.patch
+skip-test.patch
+skip-gabbi.patch
+disable-kafka.patch
=== added directory '.pc/disable-kafka.patch'
=== added directory '.pc/disable-kafka.patch/ceilometer'
=== added directory '.pc/disable-kafka.patch/ceilometer/tests'
=== added directory '.pc/disable-kafka.patch/ceilometer/tests/unit'
=== added directory '.pc/disable-kafka.patch/ceilometer/tests/unit/publisher'
=== added file '.pc/disable-kafka.patch/ceilometer/tests/unit/publisher/test_kafka_broker_publisher.py'
--- debian/.pc/disable-kafka.patch/ceilometer/tests/unit/publisher/test_kafka_broker_publisher.py
00:00:00 +0000
+++ ubuntu/.pc/disable-kafka.patch/ceilometer/tests/unit/publisher/test_kafka_broker_publisher.py
15:48:26 +0000
@@ -0,0 +1,210 @@
+# Copyright 2015 Cisco 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.
+"""Tests for ceilometer/publisher/kafka_broker.py
+import datetime
+import uuid
+import mock
+from oslo_utils import netutils
+from ceilometer.event.storage import models as event
+from ceilometer.publisher import kafka_broker as kafka
+from ceilometer.publisher import messaging as msg_publisher
+from ceilometer import sample
+from ceilometer.tests import base as tests_base
+@mock.patch('ceilometer.publisher.kafka_broker.LOG', mock.Mock())
+@mock.patch('ceilometer.publisher.kafka_broker.kafka.KafkaClient',
mock.Mock())
+class TestKafkaPublisher(tests_base.BaseTestCase):
test_event_data = [
event.Event(message_id=uuid.uuid4(),
event_type='event_%d' % i,
generated=datetime.datetime.utcnow(),
traits=[], raw={})
for i in range(0, 5)
test_data = [
sample.Sample(
name='test',
type=sample.TYPE_CUMULATIVE,
user_id='test',
project_id='test',
resource_id='test_run_tasks',
timestamp=datetime.datetime.utcnow().isoformat(),
resource_metadata={'name': 'TestPublish'},
sample.Sample(
name='test',
type=sample.TYPE_CUMULATIVE,
user_id='test',
project_id='test',
resource_id='test_run_tasks',
timestamp=datetime.datetime.utcnow().isoformat(),
resource_metadata={'name': 'TestPublish'},
sample.Sample(
name='test2',
type=sample.TYPE_CUMULATIVE,
user_id='test',
project_id='test',
resource_id='test_run_tasks',
timestamp=datetime.datetime.utcnow().isoformat(),
resource_metadata={'name': 'TestPublish'},
sample.Sample(
name='test2',
type=sample.TYPE_CUMULATIVE,
user_id='test',
project_id='test',
resource_id='test_run_tasks',
timestamp=datetime.datetime.utcnow().isoformat(),
resource_metadata={'name': 'TestPublish'},
sample.Sample(
name='test3',
type=sample.TYPE_CUMULATIVE,
user_id='test',
project_id='test',
resource_id='test_run_tasks',
timestamp=datetime.datetime.utcnow().isoformat(),
resource_metadata={'name': 'TestPublish'},
def test_publish(self):
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer'))
with mock.patch.object(publisher, '_producer') as fake_producer:
publisher.publish_samples(mock.MagicMock(), self.test_data)
self.assertEqual(5, len(fake_producer.send_messages.mock_calls))
self.assertEqual(0, len(publisher.local_queue))
def test_publish_without_options(self):
publisher = kafka.KafkaBrokerPublisher(
netutils.urlsplit('kafka://127.0.0.1:9092'))
with mock.patch.object(publisher, '_producer') as fake_producer:
publisher.publish_samples(mock.MagicMock(), self.test_data)
self.assertEqual(5, len(fake_producer.send_messages.mock_calls))
self.assertEqual(0, len(publisher.local_queue))
def test_publish_to_host_without_policy(self):
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer'))
self.assertEqual('default', publisher.policy)
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer&policy=test'))
self.assertEqual('default', publisher.policy)
def test_publish_to_host_with_default_policy(self):
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer&policy=default'))
with mock.patch.object(publisher, '_producer') as fake_producer:
fake_producer.send_messages.side_effect = TypeError
self.assertRaises(msg_publisher.DeliveryFailure,
publisher.publish_samples,
mock.MagicMock(), self.test_data)
self.assertEqual(100, len(fake_producer.send_messages.mock_calls))
self.assertEqual(0, len(publisher.local_queue))
def test_publish_to_host_with_drop_policy(self):
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer&policy=drop'))
with mock.patch.object(publisher, '_producer') as fake_producer:
fake_producer.send_messages.side_effect = Exception("test")
publisher.publish_samples(mock.MagicMock(), self.test_data)
self.assertEqual(1, len(fake_producer.send_messages.mock_calls))
self.assertEqual(0, len(publisher.local_queue))
def test_publish_to_host_with_queue_policy(self):
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer&policy=queue'))
with mock.patch.object(publisher, '_producer') as fake_producer:
fake_producer.send_messages.side_effect = Exception("test")
publisher.publish_samples(mock.MagicMock(), self.test_data)
self.assertEqual(1, len(fake_producer.send_messages.mock_calls))
self.assertEqual(1, len(publisher.local_queue))
def test_publish_to_down_host_with_default_queue_size(self):
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer&policy=queue'))
with mock.patch.object(publisher, '_producer') as fake_producer:
fake_producer.send_messages.side_effect = Exception("test")
for i in range(0, 2000):
for s in self.test_data:
s.name = 'test-%d' % i
publisher.publish_samples(mock.MagicMock(), self.test_data)
self.assertEqual(1024, len(publisher.local_queue))
self.assertEqual('test-976',
publisher.local_queue[0][2][0]['counter_name'])
self.assertEqual('test-1999',
publisher.local_queue[]['counter_name'])
def test_publish_to_host_from_down_to_up_with_queue(self):
publisher = kafka.KafkaBrokerPublisher(netutils.urlsplit(
'kafka://127.0.0.1:9092?topic=ceilometer&policy=queue'))
with mock.patch.object(publisher, '_producer') as fake_producer:
fake_producer.send_messages.side_effect = Exception("test")
for i in range(0, 16):
for s in self.test_data:
s.name = 'test-%d' % i
publisher.publish_samples(mock.MagicMock(), self.test_data)
self.assertEqual(16, len(publisher.local_queue))
fake_producer.send_messages.side_effect = None
for s in self.test_data:
s.name = 'test-%d' % 16
publisher.publish_samples(mock.MagicMock(), self.test_data)
self.assertEqual(0, len(publisher.local_queue))
def test_publish_event_with_default_policy(self):
publisher = kafka.KafkaBrokerPublisher(
netutils.urlsplit('kafka://127.0.0.1:9092?topic=ceilometer'))
with mock.patch.object(publisher, '_producer') as fake_producer:
publisher.publish_events(mock.MagicMock(), self.test_event_data)
self.assertEqual(5, len(fake_producer.send_messages.mock_calls))
with mock.patch.object(publisher, '_producer') as fake_producer:
fake_producer.send_messages.side_effect = Exception("test")
self.assertRaises(msg_publisher.DeliveryFailure,
publisher.publish_events,
mock.MagicMock(), self.test_event_data)
self.assertEqual(100, len(fake_producer.send_messages.mock_calls))
self.assertEqual(0, len(publisher.local_queue))
=== added file '.pc/disable-kafka.patch/requirements.txt'
--- debian/.pc/disable-kafka.patch/requirements.txt
00:00:00 +0000
+++ ubuntu/.pc/disable-kafka.patch/requirements.txt
17:02:38 +0000
@@ -0,0 +1,48 @@
+# The order of packages is significant, because pip processes them in the order
+# of appearance. Changing the order has an impact on the overall integration
+# process, which may cause wedges in the gate later.
+retrying!=1.3.0,>=1.2.3 # Apache-2.0
+croniter>=0.3.4 # MIT License
+eventlet>=0.17.4
+jsonpath-rw-ext>=0.1.7
+jsonschema!=2.5.0,=2.0.0
+kafka-python>=0.9.2 # Apache-2.0
+keystonemiddleware>=2.0.0
+lxml>=2.3
+msgpack-python>=0.4.0
+oslo.context>=0.2.0 # Apache-2.0
+oslo.db>=2.4.1 # Apache-2.0
+oslo.concurrency>=2.3.0 # Apache-2.0
+oslo.config>=2.3.0 # Apache-2.0
+oslo.i18n>=1.5.0 # Apache-2.0
+oslo.log>=1.8.0 # Apache-2.0
+oslo.policy>=0.5.0 # Apache-2.0
+oslo.reports>=0.1.0 # Apache-2.0
+oslo.rootwrap>=2.0.0 # Apache-2.0
+oslo.service>=0.7.0 # Apache-2.0
+PasteDeploy>=1.5.0
+pecan>=1.0.0
+oslo.messaging!=1.17.0,!=1.17.1,>=1.16.0 # Apache-2.0
+oslo.middleware>=2.8.0 # Apache-2.0
+oslo.serialization>=1.4.0 # Apache-2.0
+oslo.utils>=2.0.0 # Apache-2.0
+pysnmp=4.2.1
+python-ceilometerclient>=1.5.0
+python-glanceclient>=0.18.0
+python-keystoneclient>=1.6.0
+python-neutronclient>=2.6.0
+python-novaclient>=2.28.1
+python-swiftclient>=2.2.0
+pytz>=2013.6
+PyYAML>=3.1.0
+requests>=2.5.2
+six>=1.9.0
+SQLAlchemy=0.9.9
+sqlalchemy-migrate>=0.9.6
+stevedore>=1.5.0 # Apache-2.0
+tooz>=1.19.0 # Apache-2.0
+Werkzeug>=0.7 # BSD License
+WebOb>=1.2.3
+WSME>=0.7
=== added directory '.pc/skip-db-tests.patch'
=== added directory '.pc/skip-db-tests.patch/ceilometer'
=== added directory '.pc/skip-db-tests.patch/ceilometer/tests'
=== added file '.pc/skip-db-tests.patch/ceilometer/tests/db.py'
--- debian/.pc/skip-db-tests.patch/ceilometer/tests/db.py
00:00:00 +0000
+++ ubuntu/.pc/skip-db-tests.patch/ceilometer/tests/db.py
11:28:21 +0000
@@ -0,0 +1,310 @@
+# Copyright 2012 New Dream Network, LLC (DreamHost)
+# Copyright 2013 eNovance
+# 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.
+"""Base classes for API tests."""
+import os
+import uuid
+import warnings
+import fixtures
+import mock
+from oslo_config import fixture as fixture_config
+from oslotest import mockpatch
+import six
+from six.moves.urllib import parse as urlparse
+import sqlalchemy
+import testscenarios.testcase
+from testtools import testcase
+from ceilometer import storage
+from ceilometer.tests import base as test_base
from ceilometer.tests import mocks
+except ImportError:
mocks = None
# happybase module is not Python 3 compatible yet
+class MongoDbManager(fixtures.Fixture):
def __init__(self, url):
self._url = url
def setUp(self):
super(MongoDbManager, self).setUp()
with warnings.catch_warnings():
warnings.filterwarnings(
action='ignore',
message='.*you must provide a username and password.*')
self.connection = storage.get_connection(
self.url, 'ceilometer.metering.storage')
self.alarm_connection = storage.get_connection(
self.url, 'ceilometer.alarm.storage')
self.event_connection = storage.get_connection(
self.url, 'ceilometer.event.storage')
except storage.StorageBadVersion as e:
raise testcase.TestSkipped(six.text_type(e))
def url(self):
return '%(url)s_%(db)s' % {
'url': self._url,
'db': uuid.uuid4().hex
+class SQLManager(fixtures.Fixture):
def setUp(self):
super(SQLManager, self).setUp()
self.connection = storage.get_connection(
self.url, 'ceilometer.metering.storage')
self.alarm_connection = storage.get_connection(
self.url, 'ceilometer.alarm.storage')
self.event_connection = storage.get_connection(
self.url, 'ceilometer.event.storage')
def url(self):
return self._url.replace('template1', self._db_name)
+class PgSQLManager(SQLManager):
def __init__(self, url):
self._url = url
self._db_name = 'ceilometer_%s' % uuid.uuid4().hex
self._engine = sqlalchemy.create_engine(self._url)
self._conn = self._engine.connect()
self._conn.connection.set_isolation_level(0)
self._conn.execute(
'CREATE DATABASE %s WITH TEMPLATE template0;' % self._db_name)
self._conn.connection.set_isolation_level(1)
self._conn.close()
self._engine.dispose()
+class MySQLManager(SQLManager):
def __init__(self, url):
self._url = url
self._db_name = 'ceilometer_%s' % uuid.uuid4().hex
self._engine = sqlalchemy.create_engine(
self._url.replace('template1', ''))
self._conn = self._engine.connect()
self._conn.execute('CREATE DATABASE %s;' % self._db_name)
self._conn.close()
self._engine.dispose()
+class ElasticSearchManager(fixtures.Fixture):
def __init__(self, url):
self.url = url
def setUp(self):
super(ElasticSearchManager, self).setUp()
self.connection = storage.get_connection(
'sqlite://', 'ceilometer.metering.storage')
self.alarm_connection = storage.get_connection(
'sqlite://', 'ceilometer.alarm.storage')
self.event_connection = storage.get_connection(
self.url, 'ceilometer.event.storage')
# prefix each test with unique index name
self.event_connection.index_name = 'events_%s' % uuid.uuid4().hex
# force index on write so data is queryable right away
self.event_connection._refresh_on_write = True
+class HBaseManager(fixtures.Fixture):
def __init__(self, url):
self._url = url
def setUp(self):
super(HBaseManager, self).setUp()
self.connection = storage.get_connection(
self.url, 'ceilometer.metering.storage')
self.alarm_connection = storage.get_connection(
self.url, 'ceilometer.alarm.storage')
self.event_connection = storage.get_connection(
self.url, 'ceilometer.event.storage')
# Unique prefix for each test to keep data is distinguished because
# all test data is stored in one table
data_prefix = str(uuid.uuid4().hex)
def table(conn, name):
return mocks.MockHBaseTable(name, conn, data_prefix)
# Mock only real HBase connection, MConnection "table" method
# stays origin.
mock.patch('happybase.Connection.table', new=table).start()
# We shouldn't delete data and tables after each test,
# because it last for too long.
# All tests tables will be deleted in setup-test-env.sh
mock.patch("happybase.Connection.disable_table",
new=mock.MagicMock()).start()
mock.patch("happybase.Connection.delete_table",
new=mock.MagicMock()).start()
mock.patch("happybase.Connection.create_table",
new=mock.MagicMock()).start()
def url(self):
return '%s?table_prefix=%s' % (
self._url,
os.getenv("CEILOMETER_TEST_HBASE_TABLE_PREFIX", "test")
+class SQLiteManager(fixtures.Fixture):
def __init__(self, url):
self.url = url
def setUp(self):
super(SQLiteManager, self).setUp()
self.connection = storage.get_connection(
self.url, 'ceilometer.metering.storage')
self.alarm_connection = storage.get_connection(
self.url, 'ceilometer.alarm.storage')
self.event_connection = storage.get_connection(
self.url, 'ceilometer.event.storage')
+class TestBase(testscenarios.testcase.WithScenarios, test_base.BaseTestCase):
DRIVER_MANAGERS = {
'mongodb': MongoDbManager,
'mysql': MySQLManager,
'postgresql': PgSQLManager,
'db2': MongoDbManager,
'sqlite': SQLiteManager,
'es': ElasticSearchManager,
if mocks is not None:
DRIVER_MANAGERS['hbase'] = HBaseManager
db_url = 'sqlite://'
# NOTE(Alexei_987) Set default db url
def setUp(self):
super(TestBase, self).setUp()
engine = urlparse.urlparse(self.db_url).scheme
# NOTE(Alexei_987) Shortcut to skip expensive db setUp
test_method = self._get_test_method()
if (hasattr(test_method, '_run_with')
and engine not in test_method._run_with):
raise testcase.TestSkipped(
'Test is not applicable for %s' % engine)
self.CONF = self.useFixture(fixture_config.Config()).conf
self.CONF([], project='ceilometer', validate_default_values=True)
self.db_manager = self._get_driver_manager(engine)(self.db_url)
except ValueError as exc:
self.skipTest("missing driver manager: %s" % exc)
self.useFixture(self.db_manager)
self.conn = self.db_manager.connection
self.conn.upgrade()
self.alarm_conn = self.db_manager.alarm_connection
self.alarm_conn.upgrade()
self.event_conn = self.db_manager.event_connection
self.event_conn.upgrade()
self.useFixture(mockpatch.Patch('ceilometer.storage.get_connection',
side_effect=self._get_connection))
# Set a default location for the pipeline config file so the
# tests work even if ceilometer is not installed globally on
# the system.
self.CONF.import_opt('pipeline_cfg_file', 'ceilometer.pipeline')
self.CONF.set_override(
'pipeline_cfg_file',
self.path_get('etc/ceilometer/pipeline.yaml')
def tearDown(self):
self.event_conn.clear()
self.event_conn = None
self.alarm_conn.clear()
self.alarm_conn = None
self.conn.clear()
self.conn = None
super(TestBase, self).tearDown()
def _get_connection(self, url, namespace):
if namespace == "ceilometer.alarm.storage":
return self.alarm_conn
elif namespace == "ceilometer.event.storage":
return self.event_conn
return self.conn
def _get_driver_manager(self, engine):
manager = self.DRIVER_MANAGERS.get(engine)
if not manager:
raise ValueError('No manager available for %s' % engine)
return manager
+def run_with(*drivers):
"""Used to mark tests that are only applicable for certain db driver.
Skips test if driver is not available.
def decorator(test):
if isinstance(test, type) and issubclass(test, TestBase):
# Decorate all test methods
for attr in dir(test):
value = getattr(test, attr)
if callable(value) and attr.startswith('test_'):
if six.PY3:
value._run_with = drivers
value.__func__._run_with = drivers
test._run_with = drivers
return test
return decorator
+@six.add_metaclass(test_base.SkipNotImplementedMeta)
+class MixinTestsWithBackendScenarios(object):
scenarios = [
('sqlite', {'db_url': 'sqlite://'}),
for db in ('MONGODB', 'MYSQL', 'PGSQL', 'HBASE', 'DB2', 'ES'):
if os.environ.get('CEILOMETER_TEST_%s_URL' % db):
scenarios.append(
(db.lower(), {'db_url': os.environ.get(
'CEILOMETER_TEST_%s_URL' % db)}))
scenarios_db = [db for db, _ in scenarios]
# Insert default value for hbase test
if 'hbase' not in scenarios_db:
scenarios.append(
('hbase', {'db_url': 'hbase://__test__'}))
# Insert default value for db2 test
if 'mongodb' in scenarios_db and 'db2' not in scenarios_db:
scenarios.append(
('db2', {'db_url': os.environ.get('CEILOMETER_TEST_MONGODB_URL',
'').replace('mongodb://',
'db2://')}))
=== added directory '.pc/skip-gabbi.patch'
=== added directory '.pc/skip-gabbi.patch/ceilometer'
=== added directory '.pc/skip-gabbi.patch/ceilometer/tests'
=== added directory '.pc/skip-gabbi.patch/ceilometer/tests/functional'
=== added directory '.pc/skip-gabbi.patch/ceilometer/tests/functional/gabbi'
=== added file '.pc/skip-gabbi.patch/ceilometer/tests/functional/gabbi/test_gabbi.py'
--- debian/.pc/skip-gabbi.patch/ceilometer/tests/functional/gabbi/test_gabbi.py
00:00:00 +0000
+++ ubuntu/.pc/skip-gabbi.patch/ceilometer/tests/functional/gabbi/test_gabbi.py
15:48:26 +0000
@@ -0,0 +1,36 @@
+# Copyright 2015 Red Hat. 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.
+"""A test module to exercise the Ceilometer API with gabbi
+For the sake of exploratory development.
+import os
+from gabbi import driver
+from ceilometer.api import app
+from ceilometer.tests.functional.gabbi import fixtures as fixture_module
+TESTS_DIR = 'gabbits'
+def load_tests(loader, tests, pattern):
"""Provide a TestSuite to the discovery process."""
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
return driver.build_tests(test_dir, loader, host=None,
intercept=app.VersionSelectorApplication,
fixture_module=fixture_module)
=== added directory '.pc/skip-test.patch'
=== added directory '.pc/skip-test.patch/ceilometer'
=== added directory '.pc/skip-test.patch/ceilometer/tests'
=== added directory '.pc/skip-test.patch/ceilometer/tests/functional'
=== added directory '.pc/skip-test.patch/ceilometer/tests/functional/api'
=== added directory '.pc/skip-test.patch/ceilometer/tests/functional/api/v2'
=== added file '.pc/skip-test.patch/ceilometer/tests/functional/api/v2/test_event_scenarios.py'
--- debian/.pc/skip-test.patch/ceilometer/tests/functional/api/v2/test_event_scenarios.py
00:00:00 +0000
+++ ubuntu/.pc/skip-test.patch/ceilometer/tests/functional/api/v2/test_event_scenarios.py
11:09:35 +0000
@@ -0,0 +1,650 @@
+# Copyright 2013 Hewlett-Packard Development Company, L.P.
+# 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.
+"""Test event, event_type and trait retrieval."""
+import datetime
+import uuid
+import webtest.app
+from ceilometer.event.storage import models
+from ceilometer.tests import db as tests_db
+from ceilometer.tests.functional.api import v2
+USER_ID = uuid.uuid4().hex
+PROJ_ID = uuid.uuid4().hex
+HEADERS = {"X-Roles": "admin",
"X-User-Id": USER_ID,
"X-Project-Id": PROJ_ID}
+class EventTestBase(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(EventTestBase, self).setUp()
self._generate_models()
def _generate_models(self):
event_models = []
self.s_time = datetime.datetime(, 5, 0)
self.trait_time = datetime.datetime(, 5, 0)
for event_type in ['Foo', 'Bar', 'Zoo']:
trait_models = [models.Trait(name, type, value)
for name, type, value in [
('trait_A', models.Trait.TEXT_TYPE,
"my_%s_text" % event_type),
('trait_B', models.Trait.INT_TYPE,
base + 1),
('trait_C', models.Trait.FLOAT_TYPE,
float(base) + 0.123456),
('trait_D', models.Trait.DATETIME_TYPE,
self.trait_time)]]
# Message ID for test will be 'base'. So, message ID for the first
# event will be '0', the second '100', and so on.
# trait_time in first event will be equal to self.trait_time
# (datetime.datetime(, 5, 0)), next will add 1 day, so
# second will be (datetime.datetime(, 5, 0)) and so on.
event_models.append(
models.Event(message_id=str(base),
event_type=event_type,
generated=self.trait_time,
traits=trait_models,
raw={'status': {'nested': 'started'}}))
base += 100
self.trait_time += datetime.timedelta(days=1)
self.event_conn.record_events(event_models)
+class TestEventTypeAPI(EventTestBase):
PATH = '/event_types'
def test_event_types(self):
data = self.get_json(self.PATH, headers=HEADERS)
for event_type in ['Foo', 'Bar', 'Zoo']:
self.assertIn(event_type, data)
+class TestTraitAPI(EventTestBase):
PATH = '/event_types/%s/traits'
def test_get_traits_for_event(self):
path = self.PATH % "Foo"
data = self.get_json(path, headers=HEADERS)
self.assertEqual(4, len(data))
def test_get_event_invalid_path(self):
data = self.get_json('/event_types/trait_A/', headers=HEADERS,
expect_errors=True)
self.assertEqual(404, data.status_int)
def test_get_traits_for_non_existent_event(self):
path = self.PATH % "NO_SUCH_EVENT_TYPE"
data = self.get_json(path, headers=HEADERS)
self.assertEqual([], data)
def test_get_trait_data_for_event(self):
path = (self.PATH % "Foo") + "/trait_A"
data = self.get_json(path, headers=HEADERS)
self.assertEqual(1, len(data))
self.assertEqual("trait_A", data[0]['name'])
path = (self.PATH % "Foo") + "/trait_B"
data = self.get_json(path, headers=HEADERS)
self.assertEqual(1, len(data))
self.assertEqual("trait_B", data[0]['name'])
self.assertEqual("1", data[0]['value'])
path = (self.PATH % "Foo") + "/trait_D"
data = self.get_json(path, headers=HEADERS)
self.assertEqual(1, len(data))
self.assertEqual("trait_D", data[0]['name'])
self.assertEqual((self.trait_time - datetime.timedelta(days=3)).
isoformat(), data[0]['value'])
def test_get_trait_data_for_non_existent_event(self):
path = (self.PATH % "NO_SUCH_EVENT") + "/trait_A"
data = self.get_json(path, headers=HEADERS)
self.assertEqual([], data)
def test_get_trait_data_for_non_existent_trait(self):
path = (self.PATH % "Foo") + "/no_such_trait"
data = self.get_json(path, headers=HEADERS)
self.assertEqual([], data)
+class TestEventAPI(EventTestBase):
PATH = '/events'
def test_get_events(self):
data = self.get_json(self.PATH, headers=HEADERS)
self.assertEqual(3, len(data))
# We expect to get native UTC generated time back
trait_time = self.s_time
for event in data:
expected_generated = trait_time.isoformat()
self.assertIn(event['event_type'], ['Foo', 'Bar', 'Zoo'])
self.assertEqual(4, len(event['traits']))
self.assertEqual({'status': {'nested': 'started'}}, event['raw']),
self.assertEqual(expected_generated, event['generated'])
for trait_name in ['trait_A', 'trait_B',
'trait_C', 'trait_D']:
self.assertIn(trait_name, map(lambda x: x['name'],
event['traits']))
trait_time += datetime.timedelta(days=1)
def test_get_event_by_message_id(self):
event = self.get_json(self.PATH + "/100", headers=HEADERS)
expected_traits = [{'name': 'trait_A',
'type': 'string',
'value': 'my_Bar_text'},
{'name': 'trait_B',
'type': 'integer',
'value': '101'},
{'name': 'trait_C',
'type': 'float',
'value': '100.123456'},
{'name': 'trait_D',
'type': 'datetime',
'value': 'T05:00:00'}]
self.assertEqual('100', event['message_id'])
self.assertEqual('Bar', event['event_type'])
self.assertEqual('T05:00:00', event['generated'])
self.assertEqual(expected_traits, event['traits'])
def test_get_event_by_message_id_no_such_id(self):
data = self.get_json(self.PATH + "/DNE", headers=HEADERS,
expect_errors=True)
self.assertEqual(404, data.status_int)
def test_get_events_filter_event_type(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'event_type',
'value': 'Foo'}])
self.assertEqual(1, len(data))
def test_get_events_filter_trait_no_type(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text'}])
self.assertEqual(1, len(data))
self.assertEqual('Foo', data[0]['event_type'])
def test_get_events_filter_trait_empty_type(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text',
'type': ''}])
self.assertEqual(1, len(data))
self.assertEqual('Foo', data[0]['event_type'])
def test_get_events_filter_trait_invalid_type(self):
resp = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text',
'type': 'whats-up'}],
expect_errors=True)
self.assertEqual(400, resp.status_code)
self.assertEqual("The data type whats-up is not supported. The "
"supported data type list is: [\'integer\', "
"\'float\', \'string\', \'datetime\']",
resp.json['error_message']['faultstring'])
def test_get_events_filter_operator_invalid_type(self):
resp = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text',
'op': 'whats-up'}],
expect_errors=True)
self.assertEqual(400, resp.status_code)
self.assertEqual("operator whats-up is not supported. the "
"supported operators are: (\'lt\', \'le\', "
"\'eq\', \'ne\', \'ge\', \'gt\')",
resp.json['error_message']['faultstring'])
def test_get_events_filter_text_trait(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text',
'type': 'string'}])
self.assertEqual(1, len(data))
self.assertEqual('Foo', data[0]['event_type'])
def test_get_events_filter_int_trait(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '101',
'type': 'integer'}])
self.assertEqual(1, len(data))
self.assertEqual('Bar', data[0]['event_type'])
traits = [x for x in data[0]['traits'] if x['name'] == 'trait_B']
self.assertEqual(1, len(traits))
self.assertEqual('integer', traits[0]['type'])
self.assertEqual('101', traits[0]['value'])
def test_get_events_filter_float_trait(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_C',
'value': '200.123456',
'type': 'float'}])
self.assertEqual(1, len(data))
self.assertEqual('Zoo', data[0]['event_type'])
traits = [x for x in data[0]['traits'] if x['name'] == 'trait_C']
self.assertEqual(1, len(traits))
self.assertEqual('float', traits[0]['type'])
self.assertEqual('200.123456', traits[0]['value'])
def test_get_events_filter_datetime_trait(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_D',
'value': 'T05:00:00',
'type': 'datetime'}])
self.assertEqual(1, len(data))
traits = [x for x in data[0]['traits'] if x['name'] == 'trait_D']
self.assertEqual(1, len(traits))
self.assertEqual('datetime', traits[0]['type'])
self.assertEqual('T05:00:00', traits[0]['value'])
def test_get_events_multiple_filters(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '1',
'type': 'integer'},
{'field': 'trait_A',
'value': 'my_Foo_text',
'type': 'string'}])
self.assertEqual(1, len(data))
self.assertEqual('Foo', data[0]['event_type'])
def test_get_events_multiple_filters_no_matches(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '101',
'type': 'integer'},
{'field': 'trait_A',
'value': 'my_Foo_text',
'type': 'string'}])
self.assertEqual(0, len(data))
def test_get_events_multiple_filters_same_field_different_values(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text',
'type': 'string'},
{'field': 'trait_A',
'value': 'my_Bar_text',
'type': 'string'}])
self.assertEqual(0, len(data))
def test_get_events_not_filters(self):
data = self.get_json(self.PATH, headers=HEADERS,
self.assertEqual(3, len(data))
def test_get_events_filter_op_string(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text',
'type': 'string',
'op': 'eq'}])
self.assertEqual(1, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Bar_text',
'type': 'string',
'op': 'lt'}])
self.assertEqual(0, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Zoo_text',
'type': 'string',
'op': 'le'}])
self.assertEqual(3, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Foo_text',
'type': 'string',
'op': 'ne'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Bar_text',
'type': 'string',
'op': 'gt'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_A',
'value': 'my_Zoo_text',
'type': 'string',
'op': 'ge'}])
self.assertEqual(1, len(data))
def test_get_events_filter_op_integer(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '101',
'type': 'integer',
'op': 'eq'}])
self.assertEqual(1, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '201',
'type': 'integer',
'op': 'lt'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '1',
'type': 'integer',
'op': 'le'}])
self.assertEqual(1, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '101',
'type': 'integer',
'op': 'ne'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '201',
'type': 'integer',
'op': 'gt'}])
self.assertEqual(0, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '1',
'type': 'integer',
'op': 'ge'}])
self.assertEqual(3, len(data))
def test_get_events_filter_op_float(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_C',
'value': '100.123456',
'type': 'float',
'op': 'eq'}])
self.assertEqual(1, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_C',
'value': '200.123456',
'type': 'float',
'op': 'lt'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_C',
'value': '0.123456',
'type': 'float',
'op': 'le'}])
self.assertEqual(1, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_C',
'value': '100.123456',
'type': 'float',
'op': 'ne'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_C',
'value': '200.123456',
'type': 'float',
'op': 'gt'}])
self.assertEqual(0, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_C',
'value': '0.123456',
'type': 'float',
'op': 'ge'}])
self.assertEqual(3, len(data))
def test_get_events_filter_op_datatime(self):
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_D',
'value': 'T05:00:00',
'type': 'datetime',
'op': 'eq'}])
self.assertEqual(1, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_D',
'value': 'T05:00:00',
'type': 'datetime',
'op': 'lt'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_D',
'value': 'T05:00:00',
'type': 'datetime',
'op': 'le'}])
self.assertEqual(1, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_D',
'value': 'T05:00:00',
'type': 'datetime',
'op': 'ne'}])
self.assertEqual(2, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_D',
'value': 'T05:00:00',
'type': 'datetime',
'op': 'gt'}])
self.assertEqual(0, len(data))
data = self.get_json(self.PATH, headers=HEADERS,
q=[{'field': 'trait_D',
'value': 'T05:00:00',
'type': 'datetime',
'op': 'ge'}])
self.assertEqual(3, len(data))
def test_get_events_filter_wrong_op(self):
self.assertRaises(webtest.app.AppError,
self.get_json, self.PATH, headers=HEADERS,
q=[{'field': 'trait_B',
'value': '1',
'type': 'integer',
'op': 'el'}])
+class AclRestrictedEventTestBase(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(AclRestrictedEventTestBase, self).setUp()
self.admin_user_id = uuid.uuid4().hex
self.admin_proj_id = uuid.uuid4().hex
self.user_id = uuid.uuid4().hex
self.proj_id = uuid.uuid4().hex
self._generate_models()
def _generate_models(self):
event_models = []
self.s_time = datetime.datetime(, 5, 0)
event_models.append(
models.Event(message_id='1',
event_type='empty_ev',
generated=self.s_time,
traits=[models.Trait('random',
models.Trait.TEXT_TYPE,
event_models.append(
models.Event(message_id='2',
event_type='admin_ev',
generated=self.s_time,
traits=[models.Trait('project_id',
models.Trait.TEXT_TYPE,
self.admin_proj_id),
models.Trait('user_id',
models.Trait.TEXT_TYPE,
self.admin_user_id)],
event_models.append(
models.Event(message_id='3',
event_type='user_ev',
generated=self.s_time,
traits=[models.Trait('project_id',
models.Trait.TEXT_TYPE,
self.proj_id),
models.Trait('user_id',
models.Trait.TEXT_TYPE,
self.user_id)],
self.event_conn.record_events(event_models)
def test_non_admin_access(self):
a_headers = {"X-Roles": "member",
"X-User-Id": self.user_id,
"X-Project-Id": self.proj_id}
data = self.get_json('/events', headers=a_headers)
self.assertEqual(1, len(data))
self.assertEqual('user_ev', data[0]['event_type'])
def test_non_admin_access_single(self):
a_headers = {"X-Roles": "member",
"X-User-Id": self.user_id,
"X-Project-Id": self.proj_id}
data = self.get_json('/events/3', headers=a_headers)
self.assertEqual('user_ev', data['event_type'])
def test_non_admin_access_incorrect_user(self):
a_headers = {"X-Roles": "member",
"X-User-Id": 'blah',
"X-Project-Id": self.proj_id}
data = self.get_json('/events', headers=a_headers)
self.assertEqual(0, len(data))
def test_non_admin_access_incorrect_proj(self):
a_headers = {"X-Roles": "member",
"X-User-Id": self.user_id,
"X-Project-Id": 'blah'}
data = self.get_json('/events', headers=a_headers)
self.assertEqual(0, len(data))
def test_non_admin_access_single_invalid(self):
a_headers = {"X-Roles": "member",
"X-User-Id": self.user_id,
"X-Project-Id": self.proj_id}
data = self.get_json('/events/1', headers=a_headers,
expect_errors=True)
self.assertEqual(404, data.status_int)
@tests_db.run_with('sqlite', 'mysql', 'pgsql', 'mongodb', 'es', 'db2')
def test_admin_access(self):
a_headers = {"X-Roles": "admin",
"X-User-Id": self.admin_user_id,
"X-Project-Id": self.admin_proj_id}
data = self.get_json('/events', headers=a_headers)
self.assertEqual(2, len(data))
self.assertEqual(set(['empty_ev', 'admin_ev']),
set(ev['event_type'] for ev in data))
@tests_db.run_with('sqlite', 'mysql', 'pgsql', 'mongodb', 'es', 'db2')
def test_admin_access_trait_filter(self):
a_headers = {"X-Roles": "admin",
"X-User-Id": self.admin_user_id,
"X-Project-Id": self.admin_proj_id}
data = self.get_json('/events', headers=a_headers,
q=[{'field': 'random',
'value': 'blah',
'type': 'string',
'op': 'eq'}])
self.assertEqual(1, len(data))
self.assertEqual('empty_ev', data[0]['event_type'])
@tests_db.run_with('sqlite', 'mysql', 'pgsql', 'mongodb', 'es', 'db2')
def test_admin_access_single(self):
a_headers = {"X-Roles": "admin",
"X-User-Id": self.admin_user_id,
"X-Project-Id": self.admin_proj_id}
data = self.get_json('/events/1', headers=a_headers)
self.assertEqual('empty_ev', data['event_type'])
data = self.get_json('/events/2', headers=a_headers)
self.assertEqual('admin_ev', data['event_type'])
@tests_db.run_with('sqlite', 'mysql', 'pgsql', 'mongodb', 'es', 'db2')
def test_admin_access_trait_filter_no_access(self):
a_headers = {"X-Roles": "admin",
"X-User-Id": self.admin_user_id,
"X-Project-Id": self.admin_proj_id}
data = self.get_json('/events', headers=a_headers,
q=[{'field': 'user_id',
'value': self.user_id,
'type': 'string',
'op': 'eq'}])
self.assertEqual(0, len(data))
+class EventRestrictionTestBase(v2.FunctionalTest,
tests_db.MixinTestsWithBackendScenarios):
def setUp(self):
super(EventRestrictionTestBase, self).setUp()
self.CONF.set_override('default_api_return_limit', 10, group='api')
self._generate_models()
def _generate_models(self):
event_models = []
self.s_time = datetime.datetime(, 5, 0)
self.trait_time = datetime.datetime(, 5, 0)
for i in range(20):
trait_models = [models.Trait(name, type, value)
for name, type, value in [
('trait_A', models.Trait.TEXT_TYPE,
"my_text"),
('trait_B', models.Trait.INT_TYPE,
base + 1),
('trait_C', models.Trait.FLOAT_TYPE,
float(base) + 0.123456),
('trait_D', models.Trait.DATETIME_TYPE,
self.trait_time)]]
event_models.append(
models.Event(message_id=str(uuid.uuid4()),
event_type='foo.bar',
generated=self.trait_time,
traits=trait_models,
raw={'status': {'nested': 'started'}}))
self.trait_time += datetime.timedelta(seconds=1)
self.event_conn.record_events(event_models)
+class TestEventRestriction(EventRestrictionTestBase):
def test_get_limit(self):
data = self.get_json('/events?limit=1', headers=HEADERS)
self.assertEqual(1, len(data))
def test_get_limit_negative(self):
self.assertRaises(webtest.app.AppError,
self.get_json, '/events?limit=-2', headers=HEADERS)
def test_get_limit_bigger(self):
data = self.get_json('/events?limit=100', headers=HEADERS)
self.assertEqual(20, len(data))
def test_get_default_limit(self):
data = self.get_json('/events', headers=HEADERS)
self.assertEqual(10, len(data))
=== renamed file '.testr.conf' => '.testr.conf'
=== added file 'AUTHORS'
--- debian/AUTHORS
00:00:00 +0000
+++ ubuntu/AUTHORS
17:02:38 +0000
@@ -0,0 +1,270 @@
+Abhishek Chanda
+Abhishek Lekshmanan
+Abhishek Lekshmanan
+Adelina Tuvenie
+Ajaya Agrawal
+Akhil Hingane
+Ala Rezmerita
+Alessandro Pilotti
+Alex Holden
+Alexei Kornienko
+Ana Malagon
+Andreas Jaeger
+Andrew Hutchings
+Andrew Melton
+Angus Lees
+Angus Salkeld
+Ann Kamyshnikova
+Artur Svechnikov
+Ashwin Agate
+Balazs Gibizer
+Bartosz Górski
+Ben Nemec
+Ben Nemec
+Boris Pavlovic
+Brad Pokorny
+Brant Knudson
+Brian Cline
+Brian Moss
+Brooklyn Chen
+Can ZHANG
+Cedric Soulas
+Chad Lung
+Chandan Kumar
+ChangBo Guo(gcb)
+ChenZheng
+Chinmaya Bharadwaj
+Chmouel Boudjnah
+Chris Dent
+Christian Berendt
+Christian Martinez
+Christian Schwede
+Chuck Short
+Clark Boylan
+Claudiu Belu
+Cyril Roelandt
+Damian Van Vuuren
+Dan Florea
+Dan Prince
+Darren Birkett
+Davanum Srinivas
+David Peraza
+Debo~ Dutta
+Dina Belova
+Dirk Mueller
+Doug Hellmann
+Drew Thorstensen
+Edwin Zhai
+Endre Karlson
+Eoghan Glynn
+Eoghan Glynn
+Eric Brown
+Fabio Giannetti
+Fei Long Wang
+Feng Xi Yan
+Fengqian Gao
+Flavio Percoco
+Fran?ois Charlier
+Fran?ois Rossigneux
+Frederic FAURE
+Gangyi Luo
+Gauvain Pocentek
+Gerard Garcia
+Gordon Chung
+Graham Binns
+Guangyu Suo
+Haomeng, Wang
+Harri H?m?l?inen
+Hisashi Osanai
+Hongbin Lu
+Igor Degtiarov
+Ihar Hrachyshka
+Ildiko Vancsa
+Ilya Sviridov
+Ilya Tyaptin
+Ionu? Ar??ri?i
+James E. Blair
+Jason Myers
+Jason Zhang
+Jay Pipes
+Jeremy Stanley
+Jim Rollenhagen
+Joanna H. Huang
+Joe Gordon
+Joe H. Rahme
+John H. Tran
+John Herndon
+Julien Danjou
+Justin SB
+KIYOHIRO ADACHI
+Kamil Rykowski
+Keith Byrne
+Ken Pepple
+Ken'ichi Ohmichi
+Kishore Juigil
+Koert van der Veer
+Komei Shimamura
+Ladislav Smola
+Lan Qi song
+Lena Novokshonova
+Lianhao Lu
+LinuxJedi
+Luis A. Garcia
+Maho Koshiya
+Mark McClain
+Mark McLoughlin
+Martin Geisler
+Martin Kletzander
+Mathew Odden
+Mathieu Gagne?
+Matt Riedemann
+Mehdi Abaakouk
+Mehdi Abaakouk
+Michael Still
+Micha? Jastrz?bski
+Miguel Grinberg
+Mike Spreitzer
+Monsyne Dragon
+Monty Taylor
+Nadya Privalova
+Nadya Shakhat
+Nejc Saje
+Nick Barcet
+Nicolas Barcet (nijaba)
+Noorul Islam K M
+Octavian Ciuhandu
+Patrick East
+Paul Belanger
+Peter Portante
+Phil Neal
+Piyush Masrani
+Pradeep Kilambi
+Pradeep Kilambi
+Pradeep Kumar Singh
+Pradyumna Sampath
+Pádraig Brady
+Qiaowei Ren
+Rafael Rivero
+Rich Bowen
+Rikimaru Honjo
+Rob Raymond
+Robert Collins
+Robert Mizielski
+Rohit Jaiswal
+Romain Soufflet
+Roman Bogorodskiy
+Rosario Di Somma
+Ruslan Aliev
+Russell Bryant
+Ryan Petrello
+Ryota MIBU
+Saba Ahmed
+Sam Morrison
+Samuel Merritt
+Sandy Walsh
+Sanja Nosan
+Sascha Peilicke
+Sean Dague
+Sergey Lukjanov
+Sergey Vilgelm
+Shane Wang
+Shengjie Min
+Shilla Saebi
+Shuangtai Tian
+Shubham Chitranshi
+Simona Iuliana Toader
+Sofer Athlan-Guyot
+Srinivas Sakhamuri
+Stas Maksimov
+Stephen Balukoff
+Stephen Gran
+Steve Lewis
+Steve Martinelli
+Steven Berler
+Surya Prabhakar
+Svetlana Shturm
+Swami Reddy
+Swann Croiset
+Sylvain Afchain
+Takashi NATSUME
+Tatsuro Makita
+Thierry Carrez
+Thomas Bechtold
+Thomas Herve
+Thomas Herve
+Thomas Maddox
+Victor Stinner
+Victor Stinner
+Vitalii Lebedynskyi
+Vitaly Gridnev
+Vladislav Kuzmin
+Wu Wenxiang
+Yaguang Tang
+Yanyan Hu
+Yassine Lamgarchal
+Yathiraj Udupi
+You Yamagata
+Yunhong, Jiang
+Zhi Kun Liu
+Zhi Yan Liu
+ZhiQiang Fan
+Zhongyue Luo
+annegentle
+fujioka yuuichi
+gord chung
+guillaume pernot
+kiwik-chenrui
+lianghuifei
+lizheming
+lvdongbing
+nellysmitt
+shengjie min
+srsakhamuri
+venkatamahesh
+vivek.nandavanam
+vivek.nandavanam
+xiangjun li
+zhang-jinnan
=== renamed file 'CONTRIBUTING.rst' => 'CONTRIBUTING.rst'
=== added file 'ChangeLog'
--- debian/ChangeLog
00:00:00 +0000
+++ ubuntu/ChangeLog
12:33:10 +0000
@@ -0,0 +1,2590 @@
+* Imported Translations from Zanata
+* SQL: Fix event-list with multiple trait query filters
+* Fix the deprecation note in meter.yaml
+5.0.0.0rc1
+----------
+* gnocchi: Don't raise NotImplementedError
+* Add missing meter and exchange opts
+* Imported Translations from Zanata
+* Add test to cover history rule change
+* Workaround requests/urllib connection leaks
+* integration tests: additional debugging infos
+* Coordinator handles ToozError when joining group
+* Don't create neutron client at loadtime
+* Delete its corresponding history data when deleting an alarm
+* update event filter test to validate multiple trait args
+* Fix variable typos
+* Updated from global requirements
+* Change ignore-errors to ignore_errors
+* Fix reconnecting to libvirt
+* remove batch processing requirement from arithmetic transformer
+* Cleanup empty dirs from tests
+* retain existing listeners on refresh
+* Override dispatcher option for test_alarm_redirect_keystone
+* [ceilometer] Update links to Cloud Admin Guide
+* Adds support for dynamic event pipeline
+* Updated from global requirements
+* Imported Translations from Zanata
+* pollster/api now publish to sample queue
+* tox: generate config file on test run
+* tox: Allow to pass some OS_* variables
+* Refactor keystone handling in discovery manager
+* Use make_sample_from_instance for net-pollster
+* apply limit constraint on storage base interface
+* gnocchi: add two new resources
+* Fixed tox -egenconfig Error
+* Add declarative meters to developer docs
+* add delta transfomer support
+* do not recreate main queue listeners on partitioning
+* Validate required fields in meter definition
+* deprecate cadf_only http dispatcher
+* Fix the heavy time cost of event-list
+* Update API Doc to deprecate the alarming part
+* Deprecate config options of the old alarming functionality
+* update architecture documentation
+* Add attribute 'state' to meter metadata when source is polling
+* Remove useless base class
+* Split out image non-meters
+* Make the gabbi tox target work with modern tox
+* Avoid 500 errors when duplicating limit queries
+* Correct test_list_meters_meter_id to work with py3
+* Updated from global requirements
+* Update event_definitions for Cinder Image Cache
+* Update install docs
+* Use b64encode to replace of encodestring
+* Prevent ceilometer expirer from causing deadlocks
+* remove duplicate log exception message
+* Spelling mistake of comment in api/controllers/v2/query.py
+* Fix typos in gnocchi.py and converter.py
+* Updated from global requirements
+* Updated from global requirements
+* Add a py34-functional tox target
+* doc: update notification_driver
+* polling: remove deprecated agents
+* Fix string in limit warning
+* Typo fixing
+* missed entrypoint for nova_notifier removal
+* Imported Translations from Transifex
+* Fix links in README.rst
+* integration: Add debugging information
+* deprecate db2 nosql driver
+* devstack: add new option to support event-alarm
+* Sync devstack plugin with devstack:lib/ceilometer
+* Updated from global requirements
+* remove old nova_notifier processing code
+5.0.0.0b3
+---------
+* restrict admin event access
+* Migrate the old snmp pollsters to new declarative pollster
+* Support to load pollsters extensions at runtime
+* Added snmp declarative hardware pollster
+* Requeuing event with workload_partitioning on publish failure
+* Event filtering for non-admin users
+* integration: fix typo
+* gnocchi: cleanup instance resource definition
+* Updated from global requirements
+* Adding pradk to MAINTAINERS
+* Adding liusheng to MAINTAINERS
+* Add index to metadata_hash column of resource table
+* Incorrect Links are updated
+* Removing unused dependency: discover
+* Use new location of subunit2html
+* Change tox default targets for quick use
+* Fixed identity trust event types
+* gnocchi: quote the resource_id in url
+* fix metadata for compute cpu notifications
+* support custom metadata
+* Move profiler meters to yaml
+* Control Events RBAC from policy.json
+* Events RBAC needs scoped token
+* make telemetry sample payloads dictionaries
+* Fix requeue process on event handling error
+* allow configurable pipeline partitioning
+* Keep the instance_type meta from polling and notification consistent
+* Add user_id,project_id traits to audit events
+* Change json path's to start with $. for consistency
+* Add validation tests for arithmetic, string and prefix expressions
+* Fix description for "Inapt spelling of 'MongoDB'"
+* Create conf directory during devstack install phase
+* support custom timestamp
+* Add cpu meters to yaml
+* Fix description for "Incorrect spelling of a word"
+* integration: add some new tests
+* Fix disable_non_metric_meters referencing
+* Update tests to reflect WSME 0.8 fixes
+* remove jsonpath-rw requirement
+* Do not use system config file for test
+* gnocchi: move to jsonpath_rw_ext
+* Updated from global requirements
+* Allow to run debug tox job for functional tests
+* Use jsonpath_rw_ext for meter/event definitions
+* preload jsonpath_rw parsers
+* integration test: adjusts timeout
+* integration test: failfast
+* Updated from global requirements
+* Avoid recording whole instance info in log
+* Fix dependency for doc build
+* Mark record_type in PaaS Event Format doc as optional
+* full multi-meter support
+* add flexible grouping key
+* Corrected test_fallback_meter_path test case
+* Add hypervisor inspector sanity check
+* handle list payloads in notifications
+* xenapi: support the session to "unix://local"
+* Introduce Guru Meditation Reports into Ceilometer
+* Use start status of coodinator in tooz
+* Fixed event requeuing/ack on publisher failure
+* Implement consuming metrics from Magnum
+* Avoid from storing samples with empty or not numerical volumes
+* use union all when building trait query
+* Fixed spelling error, retreive -> retrieve
+* Use min and max on IntOpt option types
+* Update install docs with gnocchi dispatcher info
+* Make it possible to run postgresql functional job
+* Revert "Remove version from os_auth_url in service_credentials"
+* Updated from global requirements
+* integration: chown ceilometer directory properly
+* add mandatory limit value to complex query list
+* add test to validate jsonpath
+* Remove version from os_auth_url in service_credentials
+* do not translate debug logs
+* Updated from global requirements
+* Grenade plugin using devstack plugin for ceilometer
+* remove alembic requirement
+* Convert instance, bandwidth and SwiftMiddleware meters
+* Change and move the workers options to corresponding service section
+* Drop the downgrade function of migration scripts
+* start rpc deprecation
+* support multiple-meter payloads
+* add poll history to avoid duplicate samples
+* Add Kilo release note reference
+* initialise opencontrail client in tests
+* Make ConnectionRetryTest more reliable
+* Correct thread handling in TranslationHook
+* Updated from global requirements
+* Correctly intialized olso config fixture for TestClientHTTPBasicAuth
+* Don't start up mongodb for unit test coverage
+* disable non-metric meter definitions
+* Cast Int64 values to float
+* Convert identity, sahara and volume to meters yaml
+* Enable entry points for new declarative meters
+* Fix for rgw still throwing errors
+* group pollsters by interval
+* Revert "Revert "remove instance: meter""
+* api: fix alarm deletion and update
+* Fixes the kafka publisher
+* Sync devstack plugin with devstack:lib/ceilometer
+* integration: use the right user in gate
+* Imported Translations from Transifex
+* Initial separating unit and functional tests
+* Stop mon from keystoneclient
+* minimise scope of hmac mocking
+* Updated from global requirements
+* gnocchi: retry with a new token on 401
+* Fix some gabbi tests
+* Improve comments in notification.py
+* mongo: fix last python3 bugs
+* postgres isolation level produces inconsistent reads
+* Masks messaging_urls in logs during debug mode
+* Corrected unit of snmp based harware disk and memory meters
+* Provide base method for inspect_memory_resident
+* Fix Python 3 issue in opendaylight client
+* Fix more tests on Python 3
+* Remove the compute inspector choice restriction
+* [MongoDB] Refactor indexes for meter and resources
+* tests: add an integration test
+* Fix WSGI replacement_start_response() on Python 3
+* gnocchi: reduce the number of patch to gnocchi API
+* Make the partition coordinator log more readable
+* Drop out-of-time-sequence rate of change samples
+5.0.0.0b2
+---------
+* [MongoDB] Use a aggregate pipeline in statistics
+* Instance Cache in Node Discovery Pollster
+* Instance Caching
+* Imported Translations from Transifex
+* fix gnocchi resources yaml
+* Import the api opt group in gabbi fixture
+* Add a batch_polled_samples configuration item
+* Remove redundant comma
+* storage: deprecates mongodb_replica_set option
+* Improves send_test_data tools
+* Replace isotime() with utcnow() and isoformat()
+* distributed coordinated notifications
+* Imported Translations from Transifex
+* Close and dispose test database setup connections
+* Updated from global requirements
+* api: Redirect request to aodh if available
+* api: return 410 if only Gnocchi is enabled
+* Fix broken IPMI agent
+* add mandatory limit value to meter list
+* add mandatory limit value to resource list
+* add mandatory limit value to event list
+* Move gnocchi resources definition in yaml file
+* Send a notification per sample, do not batch
+* Handles dns.domain.exists event in Ceilometer
+* Pollsters now send notifications without doing transforms
+* Imported Translations from Transifex
+* Switch to the oslo_utils.fileutils
+* Updated from global requirements
+* Use choices for hypervisor_inspector option
+* The product name Vsphere should be vSphere
+* Add necessary executable permission
+* Store and restore the xtrace option in devstack plugin
+* gnocchi: Remove useless resources patching
+* add Trove(DBaaS) events
+* Set conf.gnocchi_dispatcher.url explicitly in tests
+* Declarative meters support
+* Stop the tests if backend hasn't started
+* Delay the start of the collector until after apache restart
+* Clean the re-implemented serializers in Ceilometer
+* monkey_patch thread in tests
+* make notifier default event publisher
+* Fix gnocchi DispatcherTest tests
+* Sort metric data before grouping and processing
+* Namespace functions in devstack plugin
+* Added valid values of operator to response body
+* gnocchi: fixes the instance flavor type
+* gnocchi dispatcher: fix typo in stevedore endpoint
+* Imported Translations from Transifex
+* Tolerate alarm actions set to None
+* Make ceilometer work correctly when hosted with a SCRIPT_NAME
+* Implementation of dynamically reloadable pipeline
+* fix log msg typo in api utils
+* Updated from global requirements
+* Add documentation about the usage of api-no-pipline
+* drop deprecated pipeline
+* Improve doc strings after changing method for index creation
+* set default limit to meter/sample queries
+* collector: fix test raising error
+* Remove test-requirements-py3.txt
+* remove unused event query
+* Create a devstack plugin for ceilometer
+* Add support for posting samples to notification-agent via API
+* restore long uuid data type
+* Revert "Add support for posting samples to notification-agent via API"
+* Update alarm history only if change in alarm property
+* test error log - catch dummy error
+* fix kafka tests from flooding logs
+* catch warnings from error tests
+* remove unused notifier
+* Add support for posting samples to notification-agent via API
+* Stop dropping deprecated tables while upgrade in mongodb and db2
+* Add handler of sample creation notification
+* Remove the unused get_targets method of plugin base
+* Replaces methods deprecated in pymongo3.0
+* add oslo.service options
+* Restricts pipeline to have unique source names
+* drop use of oslo.db private attribute
+* Fix oslo.service configuration options building
+* Add fileutils to openstack-common.conf
+* disable non-metric meters
+5.0.0.0b1
+---------
+* Remove unnecessary executable permission
+* Imported Translations from Transifex
+* Switch to oslo.service
+* Remove unnecessary wrapping of transformer ExtentionManager
+* Port test_complex_query to Python 3
+* Fix expected error message on Python 3
+* Fix usage of iterator/list on Python 3
+* Replaces ensure_index for create_index
+* pip has its own download cache by default
+* For sake of future python3 encode FakeMemcache hashes
+* Make acl_scenarios tests' keystonemiddleware cache work flexibly
+* Update version for Liberty
+* Gnocchi Dispatcher support in Ceilometer
+* Updated from global requirements
+* Fix alarm rest notifier logging to include severity
+* Remove useless execute bit on rst file
+* Fix unicode/bytes issues in API v2 tests
+* Fix script name in tox.ini for Elasticsearch
+* Fix the meter unit types to be consistent
+* tests: use policy_file in group oslo_policy
+* Fix publisher test_udp on Python 3
+* Fix Ceph object store tests on Python 3
+* Port IPMI to Python 3
+* Port middleware to Python 3
+* [elasticsearch] default trait type to string
+* Updated from global requirements
+* Lower down the range for columns which are being used as uuid
+* Sync with latest oslo-incubator
+* Fix testing of agent manager with tooz
+* Remove deprecated Swift middleware
+* add DNS events
+* Handle database failures on api startup
+* Fix more tests on Python 3
+* Switch to using pbr's autodoc capability
+* Remove old oslo.messaging aliases
+* Remove useless versioninfo and clean ceilometer.conf git exclusion
+* Register oslo_log options before using them
+* Add running functional scripts for defined backend
+* Remove snapshot.update events as they are not sent
+* WSME version >=0.7 correctly returns a 405
+* TraitText value restricted to max length 255
+* Cause gabbi to skip on no storage sooner
+* Updated from global requirements
+* Move eventlet using commands into own directory
+* adjust alarm post ut code to adapt to upstream wsme
+* Disable rgw pollster when aws module not found
+* Fixes DiskInfoPollster AttributeError exception
+* remove useless log message
+* use oslo.log instead of oslo-incubator code
+* Port test_inspector to Python 3
+* Fix usage of dictionary methods on Python 3
+* Imported Translations from Transifex
+* Add oslo.vmware to Python 3 test dependencies
+* Optionally create trust for alarm actions
+* Remove iso8601 dependency
+* Enable test_swift_middleware on Python 3
+* Enable more tests on Python 3
+* Skip hbase tests on Python 3
+* Clear useless exclude from flake8 ignore in tox
+* Remove pagination code
+* Stop importing print_function
+* Remove useless release script in tools
+* Remove useless dependency on posix_ipc
+* Remove exceute bit on HTTP dispatcher
+* Remove oslo.messaging compat from Havana
+* Fixing event types pattern for Role Noti. handler
+* Mask database.event_connection details in logs
+* Switch from MySQL-python to PyMySQL
+* Python 3: replace long with int
+* Python 3: Replace unicode with six.text_type
+* Python 3: generalize the usage of the six module
+* Update Python 3 requirements
+* Python 3: set __bool__() method on Namespace
+* Python 3: encode to UTF-8 when needed
+* Python 3: sort tables by their full name
+* Python 3: replace sys.maxint with sys.maxsize
+* Initial commit for functional tests
+* Update a test to properly anticipate HTTP 405 for RestController
+* proposal to add Chris Dent to Ceilometer core
+* rebuild event model only for database writes
+* cleanup problem events logic in event db storage
+* fix incorrect docstring for dispatcher
+* Imported Translations from Transifex
+* api: record severity change in alarm history
+* VMware: verify vCenter server certificate
+* Add hardware memory buffer and cache metrics
+* Make interval optional in pipeline
+* Improve ceilometer-api install documentation
+* empty non-string values are returned as string traits
+* Trait_* models have incorrect type for key
+* small change to development.rst file
+* Drop use of 'oslo' namespace package
+* [unittests] Increase agent module unittests coverage
+* stop mocking os.path in test_setup_events_default_config
+* Remove py33 tox target
+* made change to mod_wsgi.rst file
+* ensure collections created on upgrade
+* Fix raise error when run "tox -egenconfig"
+* Updated from global requirements
+* Fix None TypeError in neutron process notifications
+* Have eventlet monkeypatch the time module
+* Have eventlet monkeypatch the time module
+* Add the function of deleting alarm history
+* Updated from global requirements
+* Fix valueerror when ceilometer-api start
+* Override gnocchi_url configuration in test
+* Move ceilometer/cli.py to ceilometer/cmd/sample.py
+* Fix valueerror when ceilometer-api start
+* remove deprecated partitioned alarm service
+* use message id to generate hbase unique key
+* gnocchi: fix typo in the aggregation endpoint
+* Release Import of Translations from Transifex
+* Fix Copyright date in docs
+* Replace 'metrics' with 'meters' in option and doc
+* use message id to generate hbase unique key
+* update .gitreview for stable/kilo
+* gnocchi: fix typo in the aggregation endpoint
+* broadcast data to relevant queues only
+* Imported Translations from Transifex
+* fix combination alarm with operator == 'or'
+* Updated from global requirements
+-----------
+* proposal to add ZhiQiang Fan to Ceilometer core
+* Open Liberty development
+* Fix a samples xfail test that now succeeds
+* Cosmetic changes for system architecture docs
+* Fix a issue for kafka-publisher and refactor the test code
+* pymongo 3.0 breaks ci gate
+* use oslo.messaging dispatch filter
+* Further mock adjustments to deal with intermittent failure
+* Adds support for default rule in ceilometer policy.json
+* Updated from global requirements
+* limit alarm actions
+* Use oslo_vmware instead of deprecated oslo.vmware
+* Remove 'samples:groupby' from the Capabilities list
+* Use old name of 'hardware.ipmi.node.temperature'
+* Revert "remove instance: meter"
+* Tweak authenticate event definition
+* Add project and domain ID to event definition for identity CRUD
+* Fix the event type for trusts
+* reset croniter to avoid cur time shift
+* Imported Translations from Transifex
+* Avoid a error when py27 and py-mysql tests run in sequence
+* Stop using PYTHONHASHSEED=0 in ceilometer tests
+* remove instance: meter
+* Added ipv6 support for udp publisher
+* Remove the unnecessary dependency to netaddr
+* Optimize the flow of getting pollster resources
+* support ability to skip message signing
+* Avoid conflict with existing gnocchi_url conf value
+* Using oslo.db retry decorator for sample create
+* alarm: Use new gnocchi aggregation API
+* collector: enable the service to listen on IPv6
+* minimise the use of hmac
+* Typo in pylintrc
+* Ceilometer retrieve all images by 'all-tenants'
+* fix incorrect key check in swift notifications
+* support disabling profiler and http meters
+* ensure collections created on upgrade
+* Fix common misspellings
+* Updated from global requirements
+* refuse to post sample which is not supported
+* Enable collector to requeue samples when enabled
+* drop deprecated novaclient.v1_1
+* exclude precise metaquery in query field
+----------
+* Imported Translations from Transifex
+* remove log message when process notification
+* Add gabbi tests for resources
+* Fix typos and format in docstrings in http dispatcher
+* add ability to dispatch events to http target
+* doc: fix class name
+* add ability to publish to multiple topics
+* make field and value attributes mandatory in API Query
+* Fix db2 upgrade in multi-thread run issue
+* Add memory.resident libvirt meter for Ceilometer
+* Update reference
+* Check the namespaces duplication for ceilometer-polling
+* Add gabbi tests to explore the Meter and MetersControllers
+* Imported Translations from Transifex
+* mysql doesn't understand intersect
+* order traits returned within events
+* add network, kv-store, and http events
+* Add support for additional identity events
+* Add a Kafka publisher as a Ceilometer publisher
+* Fix response POST /v2/meters/(meter_name) to 201 status
+* Attempt to set user_id for identity events
+* Switch to oslo.policy 0.3.0
+* normalise timestamp in query
+* Add more power and thermal data
+* Updated from global requirements
+* Fix formatting error in licence
+* Added option to allow sample expiration more frequently
+* add option to store raw notification
+* use mongodb distinct
+* remove event_types ordering assumption
+* Add gabbi tests to cover the SamplesController
+* api: fix alarm creation if time_constraint is null
+* fix log message format in event.storage.impl_sqlalchemy
+* Remove duplications from docco
+* Tidy up clean-samples.yaml
+* Fix a few typos in the docs
+* use default trait type in event list query
+* fix wrong string format in libvirt inspector
+* create a developer section and refactor
+* Do not default pecan_debug to CONF.debug
+* Adding Gabbi Tests to Events API
+* fix config opts in objectstore.rgw
+* Updated from global requirements
+* support time to live on event database for sql backend
+* add an option to disable non-metric meters
+* add missing objectstore entry points
+* Initial gabbi testing for alarms
+* reorganise architecture page
+* Add ceph object storage meters
+* Use oslo_config choices suppo

我要回帖

更多关于 node inspector 安装 的文章

 

随机推荐