diff --git a/.gitignore b/.gitignore index 693bd2a9f..84664978d 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ db/config.yml virtenv/* .vagrant AUTHORS + +*.sample diff --git a/AUTHORS b/AUTHORS index 9a87fb43e..9a9d0d0d2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,4 @@ +Adrian Czarnecki Andrea Adams Andreas Jaeger Angelo Mendonca @@ -29,6 +30,7 @@ Flávio Ramalho Ghanshyam Habeeb Mohammed Haiwei Xu +Hangdong Zhang Hironori Shiina Igor Natanael Jakub Wachowski @@ -52,6 +54,7 @@ Michael James Hoppal Michal Zielonka Monty Taylor Nam Nguyen Hoai +OpenStack Release Bot Pradeep Kumar Velusamy Rob Raymond Rodolfo Alonso Hernandez @@ -90,6 +93,7 @@ liu-sheng liyingjun loooosy melissaml +mhoppal oiskam1 pallavi raymondr diff --git a/config-generator/README.rst b/config-generator/README.rst new file mode 100644 index 000000000..ac3ebc9c2 --- /dev/null +++ b/config-generator/README.rst @@ -0,0 +1,7 @@ +================ +config-generator +================ + +To generate sample configuration file execute:: + + tox -e genconfig diff --git a/config-generator/__init__.py b/config-generator/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/config-generator/api-config.conf b/config-generator/api-config.conf new file mode 100644 index 000000000..8c1fbaddb --- /dev/null +++ b/config-generator/api-config.conf @@ -0,0 +1,8 @@ +[DEFAULT] +output_file = etc/api-config.conf.sample +wrap_width = 79 +format = ini +summarize = True +namespace = monasca_api +namespace = oslo.log +namespace = oslo.db diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 18ebaf9eb..1c91204f5 100755 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -789,28 +789,45 @@ function configure_monasca_api_python { sudo chmod 0775 /var/log/monasca/api + # create configuration files in target locations rm -rf $MONASCA_API_CONF $MONASCA_API_PASTE_INI $MONASCA_API_LOGGING_CONF + $MONASCA_API_BIN_DIR/oslo-config-generator \ + --config-file $MONASCA_API_DIR/config-generator/api-config.conf \ + --output-file /tmp/api.conf + + install -m 600 /tmp/api.conf $MONASCA_API_CONF && rm -rf /tmp/api.conf + install -m 600 $MONASCA_API_DIR/etc/api-logging.conf $MONASCA_API_LOGGING_CONF + install -m 600 $MONASCA_API_DIR/etc/api-config.ini $MONASCA_API_PASTE_INI + # create configuration files in target locations + local dbAlarmUrl local dbMetricDriver - if [[ "${MONASCA_METRICS_DB,,}" == 'cassandra' ]]; then dbMetricDriver="monasca_api.common.repositories.cassandra.metrics_repository:MetricsRepository" else dbMetricDriver="monasca_api.common.repositories.influxdb.metrics_repository:MetricsRepository" fi dbAlarmUrl=`database_connection_url mon` - if [[ "$MONASCA_API_CONF_DIR" != "$MONASCA_API_DIR/etc/monasca" ]]; then - install -m 600 $MONASCA_API_DIR/etc/api-config.conf $MONASCA_API_CONF - install -m 600 $MONASCA_API_DIR/etc/api-logging.conf $MONASCA_API_LOGGING_CONF - install -m 600 $MONASCA_API_DIR/etc/api-config.ini $MONASCA_API_PASTE_INI - fi + + # default settings + iniset "$MONASCA_API_CONF" DEFAULT region $REGION_NAME + iniset "$MONASCA_API_CONF" DEFAULT log_config_append $MONASCA_API_LOGGING_CONF + + # logging + iniset "$MONASCA_API_LOGGING_CONF" handler_file args "('$MONASCA_API_LOG_DIR/monasca-api.log', 'a', 104857600, 5)" + + # messaging + iniset "$MONASCA_API_CONF" messaging driver "monasca_api.common.messaging.kafka_publisher:KafkaPublisher" + iniset "$MONASCA_API_CONF" kafka uri "$SERVICE_HOST:9092" + + # databases iniset "$MONASCA_API_CONF" database connection $dbAlarmUrl iniset "$MONASCA_API_CONF" repositories metrics_driver $dbMetricDriver iniset "$MONASCA_API_CONF" cassandra cluster_ip_addresses $SERVICE_HOST iniset "$MONASCA_API_CONF" influxdb ip_address $SERVICE_HOST iniset "$MONASCA_API_CONF" influxdb port 8086 - iniset "$MONASCA_API_CONF" kafka uri "$SERVICE_HOST:9092" + # keystone & security configure_auth_token_middleware $MONASCA_API_CONF "admin" $MONASCA_API_CACHE_DIR iniset "$MONASCA_API_CONF" keystone_authtoken region_name $REGION_NAME iniset "$MONASCA_API_CONF" keystone_authtoken project_name "admin" @@ -818,12 +835,16 @@ function configure_monasca_api_python { iniset "$MONASCA_API_CONF" keystone_authtoken identity_uri "http://$SERVICE_HOST:35357" iniset "$MONASCA_API_CONF" keystone_authtoken auth_uri "http://$SERVICE_HOST:5000" + iniset "$MONASCA_API_CONF" security default_authorized_roles "user, domainuser, domainadmin, monasca-user" + iniset "$MONASCA_API_CONF" security agent_authorized_roles "monasca-agent" + iniset "$MONASCA_API_CONF" security read_only_authorized_roles "monasca-read-only-user" + iniset "$MONASCA_API_CONF" security delegate_authorized_roles "admin" + + # server setup iniset "$MONASCA_API_PASTE_INI" server:main host $MONASCA_API_SERVICE_HOST iniset "$MONASCA_API_PASTE_INI" server:main port $MONASCA_API_SERVICE_PORT iniset "$MONASCA_API_PASTE_INI" server:main workers $API_WORKERS - iniset "$MONASCA_API_LOGGING_CONF" handler_file args "('$MONASCA_API_LOG_DIR/monasca-api.log', 'a', 104857600, 5)" - # link configuration for the gate ln -sf $MONASCA_API_CONF $MON_API_GATE_CONFIGURATION_DIR ln -sf $MONASCA_API_PASTE_INI $MON_API_GATE_CONFIGURATION_DIR diff --git a/doc/source/conf.py b/doc/source/conf.py index c5f54e0c9..2b5a1a72f 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -36,9 +36,8 @@ extensions = [ 'sphinx.ext.graphviz', 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', - # TODO(trebskit) enable as soon as we get configgen in place - # 'oslo_config.sphinxconfiggen' - # 'oslo_config.sphinxext', + 'oslo_config.sphinxconfiggen', + 'oslo_config.sphinxext', 'openstackdocstheme', ] @@ -52,6 +51,11 @@ bug_tag = u'' copyright = u'2014-present, OpenStack Foundation' author = u'OpenStack Foundation' +# sample config +config_generator_config_file = [ + ('config-generator/api-config.conf', '_static/api-config') +] + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/doc/source/configuration/index.rst b/doc/source/configuration/index.rst index e5cda699e..91f38f6de 100644 --- a/doc/source/configuration/index.rst +++ b/doc/source/configuration/index.rst @@ -1,3 +1,10 @@ +.. _configuring: + ============= Configuration ============= + +.. toctree:: + :maxdepth: 1 + + sample diff --git a/doc/source/configuration/sample.rst b/doc/source/configuration/sample.rst new file mode 100644 index 000000000..77bda35a2 --- /dev/null +++ b/doc/source/configuration/sample.rst @@ -0,0 +1,40 @@ +.. _sample-configuration: + +------- +Samples +------- + +The following sections show sample configuration files for monasca-api and +related utilities. These are generated from the code +(apart from the samples for logging and paster) and reflect the current state +of code in the monasca-api repository. + + +.. _sample-configuration-api: + +Sample Configuration For Application +------------------------------------ + +This sample configuration can also be viewed in `api-config.conf.sample +<../_static/api-config.conf.sample>`_. + +.. literalinclude:: ../_static/api-config.conf.sample + +.. _sample-configuration-logging: + +Sample Configuration For Logging +-------------------------------- + +This sample configuration can also be viewed in `api-logging.conf +<../../../etc/api-logging.conf>`_. + +.. literalinclude:: ../../../etc/api-logging.conf + + +Sample Configuration For Paster +------------------------------- + +This sample configuration can also be viewed in `api-config.ini +<../../../etc/api-config.ini>`_. + +.. literalinclude:: ../../../etc/api-config.ini diff --git a/etc/api-config.conf b/etc/api-config.conf deleted file mode 100755 index e048780c6..000000000 --- a/etc/api-config.conf +++ /dev/null @@ -1,146 +0,0 @@ -[DEFAULT] -log_config_append=/etc/monasca/api-logging.conf - -# Identifies the region that the Monasca API is running in. -region = useast - -# Dispatchers to be loaded to serve restful APIs -[dispatcher] -versions = monasca_api.v2.reference.versions:Versions -version_2_0 = monasca_api.v2.reference.version_2_0:Version2 -metrics = monasca_api.v2.reference.metrics:Metrics -metrics_measurements = monasca_api.v2.reference.metrics:MetricsMeasurements -metrics_statistics = monasca_api.v2.reference.metrics:MetricsStatistics -metrics_names = monasca_api.v2.reference.metrics:MetricsNames -alarm_definitions = monasca_api.v2.reference.alarm_definitions:AlarmDefinitions -alarms = monasca_api.v2.reference.alarms:Alarms -alarms_count = monasca_api.v2.reference.alarms:AlarmsCount -alarms_state_history = monasca_api.v2.reference.alarms:AlarmsStateHistory -notification_methods = monasca_api.v2.reference.notifications:Notifications -dimension_values = monasca_api.v2.reference.metrics:DimensionValues -dimension_names = monasca_api.v2.reference.metrics:DimensionNames -notification_method_types = monasca_api.v2.reference.notificationstype:NotificationsType -healthchecks = monasca_api.healthchecks:HealthChecks - -[security] -# The roles that are allowed full access to the API. -default_authorized_roles = user, domainuser, domainadmin, monasca-user - -# The roles that are allowed to only POST metrics to the API. This role would be used by the Monasca Agent. -agent_authorized_roles = monasca-agent - -# The roles that are allowed to only GET metrics from the API. -read_only_authorized_roles = monasca-read-only-user - -# The roles that are allowed to access the API on behalf of another tenant. -# For example, a service can POST metrics to another tenant if they are a member of the "delegate" role. -delegate_authorized_roles = admin - -[messaging] -# The message queue driver to use -driver = monasca_api.common.messaging.kafka_publisher:KafkaPublisher - -[repositories] -# The driver to use for the metrics repository -# Switches depending on backend database in use. Influxdb or Cassandra. -metrics_driver = monasca_api.common.repositories.influxdb.metrics_repository:MetricsRepository -#metrics_driver = monasca_api.common.repositories.cassandra.metrics_repository:MetricsRepository - -# The driver to use for the alarm definitions repository -alarm_definitions_driver = monasca_api.common.repositories.sqla.alarm_definitions_repository:AlarmDefinitionsRepository - -# The driver to use for the alarms repository -alarms_driver = monasca_api.common.repositories.sqla.alarms_repository:AlarmsRepository - -# The driver to use for the notifications repository -notifications_driver = monasca_api.common.repositories.sqla.notifications_repository:NotificationsRepository - -# The driver to use for the notification method type repository -notification_method_type_driver = monasca_api.common.repositories.sqla.notification_method_type_repository:NotificationMethodTypeRepository - - -[dispatcher] -driver = v2_reference - -[kafka] -# The endpoint to the kafka server -uri = 192.168.10.4:9092 - -# The topic that metrics will be published too -metrics_topic = metrics - -# The topic that events will be published too -events_topic = events - -# The topic that alarm state will be published too -alarm_state_transitions_topic = alarm-state-transitions - -# consumer group name -group = api - -# how many times to try when error occurs -max_retry = 1 - -# wait time between tries when kafka goes down -wait_time = 1 - -# use synchronous or asynchronous connection to kafka -async = False - -# send messages in bulk or send messages one by one. -compact = False - -# How many partitions this connection should listen messages on, this -# parameter is for reading from kafka. If listens on multiple partitions, -# For example, if the client should listen on partitions 1 and 3, then the -# configuration should look like the following: -# partitions = 1 -# partitions = 3 -# default to listen on partition 0. -partitions = 0 - -[influxdb] -# Only needed if Influxdb database is used for backend. -# The IP address of the InfluxDB service. -ip_address = 192.168.10.4 - -# The port number that the InfluxDB service is listening on. -port = 8086 - -# The username to authenticate with. -user = mon_api - -# The password to authenticate with. -password = password - -# The name of the InfluxDB database to use. -database_name = mon - -[cassandra] -# Only needed if Cassandra database is used for backend. -# Comma separated list of Cassandra node IP addresses. No spaces. -cluster_ip_addresses: 192.168.10.6 -keyspace: monasca - -# Below is configuration for database. -[database] -connection = "mysql+pymysql://monapi:password@192.168.10.4/mon?charset=utf8mb4" -# backend = sqlalchemy -# host = 192.168.10.4 -# username = monapi -# password = password -# drivername = mysq+pymysql -# port = 3306 -# database = mon -# query = "" - -[keystone_authtoken] -identity_uri = http://192.168.10.5:35357 -auth_uri = http://192.168.10.5:5000 -admin_password = admin -admin_user = admin -admin_tenant_name = admin -cafile = -certfile = -keyfile = -insecure = false diff --git a/monasca_api/api/server.py b/monasca_api/api/server.py index 9bc121392..f76760437 100644 --- a/monasca_api/api/server.py +++ b/monasca_api/api/server.py @@ -23,63 +23,14 @@ from oslo_log import log import paste.deploy from monasca_api.api.core import request - -dispatcher_opts = [cfg.StrOpt('versions', default=None, - help='Versions'), - cfg.StrOpt('version_2_0', default=None, - help='Version 2.0'), - cfg.StrOpt('metrics', default=None, - help='Metrics'), - cfg.StrOpt('metrics_measurements', default=None, - help='Metrics measurements'), - cfg.StrOpt('metrics_statistics', default=None, - help='Metrics statistics'), - cfg.StrOpt('metrics_names', default=None, - help='Metrics names'), - cfg.StrOpt('alarm_definitions', default=None, - help='Alarm definitions'), - cfg.StrOpt('alarms', default=None, - help='Alarms'), - cfg.StrOpt('alarms_count', default=None, - help='Alarms Count'), - cfg.StrOpt('alarms_state_history', default=None, - help='Alarms state history'), - cfg.StrOpt('notification_methods', default=None, - help='Notification methods'), - cfg.StrOpt('dimension_values', default=None, - help='Dimension values'), - cfg.StrOpt('dimension_names', default=None, - help='Dimension names'), - cfg.StrOpt('notification_method_types', default=None, - help='notification_method_types methods'), - cfg.StrOpt('healthchecks', default=None, - help='Health checks endpoint')] - -dispatcher_group = cfg.OptGroup(name='dispatcher', title='dispatcher') -cfg.CONF.register_group(dispatcher_group) -cfg.CONF.register_opts(dispatcher_opts, dispatcher_group) +from monasca_api import config LOG = log.getLogger(__name__) - -_CONF_LOADED = False +CONF = config.CONF def launch(conf): - global _CONF_LOADED - if not _CONF_LOADED: - # use default, but try to access one passed from conf first - config_file = conf.get('config_file', "/etc/monasca/api-config.conf") - - log.register_options(cfg.CONF) - log.set_defaults() - cfg.CONF(args=[], - project='monasca_api', - default_config_files=[config_file]) - log.setup(cfg.CONF, 'monasca_api') - LOG.debug('Configuration loaded successfully') - _CONF_LOADED = True - else: - LOG.debug('Configuration has already been loaded') + config.parse_args() app = falcon.API(request_type=request.Request) diff --git a/monasca_api/common/repositories/cassandra/metrics_repository.py b/monasca_api/common/repositories/cassandra/metrics_repository.py index 0aee9a428..140e10fd6 100644 --- a/monasca_api/common/repositories/cassandra/metrics_repository.py +++ b/monasca_api/common/repositories/cassandra/metrics_repository.py @@ -38,13 +38,12 @@ class MetricsRepository(metrics_repository.AbstractMetricsRepository): try: self.conf = cfg.CONF - self._cassandra_cluster = Cluster( - self.conf.cassandra.cluster_ip_addresses.split(',')) - + self.conf.cassandra.cluster_ip_addresses + ) self.cassandra_session = self._cassandra_cluster.connect( - self.conf.cassandra.keyspace) - + self.conf.cassandra.keyspace + ) except Exception as ex: LOG.exception(ex) raise exceptions.RepositoryException(ex) diff --git a/monasca_api/conf/__init__.py b/monasca_api/conf/__init__.py new file mode 100644 index 000000000..1cac2a273 --- /dev/null +++ b/monasca_api/conf/__init__.py @@ -0,0 +1,82 @@ +# Copyright 2017 FUJITSU LIMITED +# +# 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 os +import pkgutil + +from oslo_config import cfg +from oslo_db import options as oslo_db_opts +from oslo_log import log +from oslo_utils import importutils + +CONF = cfg.CONF +LOG = log.getLogger(__name__) + + +def load_conf_modules(): + """Loads all modules that contain configuration. + + Method iterates over modules of :py:module:`monasca_api.conf` + and imports only those that contain following methods: + + - list_opts (required by oslo_config.genconfig) + - register_opts (required by :py:currentmodule:) + + """ + for modname in _list_module_names(): + mod = importutils.import_module('monasca_api.conf.' + modname) + required_funcs = ['register_opts', 'list_opts'] + for func in required_funcs: + if hasattr(mod, func): + yield mod + + +def _list_module_names(): + package_path = os.path.dirname(os.path.abspath(__file__)) + for _, modname, ispkg in pkgutil.iter_modules(path=[package_path]): + if not (modname == "opts" and ispkg): + yield modname + + +def register_opts(): + """Registers all conf modules opts. + + This method allows different modules to register + opts according to their needs. + + """ + _register_api_opts() + _register_db_opts() + + +def _register_api_opts(): + for mod in load_conf_modules(): + mod.register_opts(CONF) + + +def _register_db_opts(): + oslo_db_opts.set_defaults(CONF, connection='sqlite://', + max_pool_size=10, max_overflow=20, + pool_timeout=10) + + +def list_opts(): + """Lists all conf modules opts. + + Goes through all conf modules and yields their opts + + """ + for mod in load_conf_modules(): + mod_opts = mod.list_opts() + yield mod_opts[0], mod_opts[1] diff --git a/monasca_api/conf/cassandra.py b/monasca_api/conf/cassandra.py new file mode 100644 index 000000000..41e8f9258 --- /dev/null +++ b/monasca_api/conf/cassandra.py @@ -0,0 +1,42 @@ +# Copyright 2014 IBM Corp. +# Copyright 2016-2017 FUJITSU LIMITED +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# +# 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 oslo_config import cfg +from oslo_config import types + +cassandra_opts = [ + cfg.ListOpt('cluster_ip_addresses', + default=['127.0.0.1'], + item_type=types.HostAddress(), + help=''' +Comma separated list of Cassandra node IP addresses +'''), + cfg.StrOpt('keyspace', default='monasca', + help=''' +keyspace where metric are stored +''') +] + +cassandra_group = cfg.OptGroup(name='cassandra') + + +def register_opts(conf): + conf.register_group(cassandra_group) + conf.register_opts(cassandra_opts, cassandra_group) + + +def list_opts(): + return cassandra_group, cassandra_opts diff --git a/monasca_api/conf/database.py b/monasca_api/conf/database.py new file mode 100644 index 000000000..fff6dead0 --- /dev/null +++ b/monasca_api/conf/database.py @@ -0,0 +1,35 @@ +# Copyright 2017 FUJITSU LIMITED +# +# 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 oslo_config import cfg + +url_opt = cfg.StrOpt(name='url', + default='$database.connection', + help=''' +The SQLAlchemy connection string to use to connect to the database +''', + required=False, + deprecated_for_removal=True, + deprecated_since='1.6.0', + deprecated_reason='Please use database.connection option,' + 'database.url is scheduled for removal ' + 'in Pike release') + + +def register_opts(conf): + conf.register_opt(url_opt, 'database') + + +def list_opts(): + return 'database', [url_opt] diff --git a/monasca_api/conf/dispatcher.py b/monasca_api/conf/dispatcher.py new file mode 100644 index 000000000..deff274e3 --- /dev/null +++ b/monasca_api/conf/dispatcher.py @@ -0,0 +1,78 @@ +# Copyright 2014 IBM Corp +# (C) Copyright 2015,2016 Hewlett Packard Enterprise Development LP +# Copyright 2017 Fujitsu LIMITED +# +# 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 oslo_config import cfg + +dispatcher_opts = [ + cfg.StrOpt('versions', + default='monasca_api.v2.reference.versions:Versions', + help='Versions controller'), + cfg.StrOpt('version_2_0', + default='monasca_api.v2.reference.version_2_0:Version2', + help='Version 2.0 controller'), + cfg.StrOpt('metrics', + default='monasca_api.v2.reference.metrics:Metrics', + help='Metrics controller'), + cfg.StrOpt('metrics_measurements', + default='monasca_api.v2.reference.metrics:MetricsMeasurements', + help='Metrics measurements controller'), + cfg.StrOpt('metrics_statistics', + default='monasca_api.v2.reference.metrics:MetricsStatistics', + help='Metrics statistics controller'), + cfg.StrOpt('metrics_names', + default='monasca_api.v2.reference.metrics:MetricsNames', + help='Metrics names controller'), + cfg.StrOpt('alarm_definitions', + default='monasca_api.v2.reference.' + 'alarm_definitions:AlarmDefinitions', + help='Alarm definitions controller'), + cfg.StrOpt('alarms', + default='monasca_api.v2.reference.alarms:Alarms', + help='Alarms controller'), + cfg.StrOpt('alarms_count', + default='monasca_api.v2.reference.alarms:AlarmsCount', + help='Alarms Count controller'), + cfg.StrOpt('alarms_state_history', + default='monasca_api.v2.reference.alarms:AlarmsStateHistory', + help='Alarms state history controller'), + cfg.StrOpt('notification_methods', + default='monasca_api.v2.reference.notifications:Notifications', + help='Notification Methods controller'), + cfg.StrOpt('dimension_values', + default='monasca_api.v2.reference.metrics:DimensionValues', + help='Dimension Values controller'), + cfg.StrOpt('dimension_names', + default='monasca_api.v2.reference.metrics:DimensionNames', + help='Dimension Names controller'), + cfg.StrOpt('notification_method_types', + default='monasca_api.v2.reference.' + 'notificationstype:NotificationsType', + help='Notifications Type Methods controller'), + cfg.StrOpt('healthchecks', + default='monasca_api.healthchecks:HealthChecks', + help='Health checks endpoint controller') +] + +dispatcher_group = cfg.OptGroup(name='dispatcher', title='dispatcher') + + +def register_opts(conf): + conf.register_group(dispatcher_group) + conf.register_opts(dispatcher_opts, dispatcher_group) + + +def list_opts(): + return dispatcher_group, dispatcher_opts diff --git a/monasca_api/conf/global.py b/monasca_api/conf/global.py new file mode 100644 index 000000000..321d12b10 --- /dev/null +++ b/monasca_api/conf/global.py @@ -0,0 +1,39 @@ +# Copyright 2014 IBM Corp. +# Copyright 2016-2017 FUJITSU LIMITED +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# +# 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 oslo_config import cfg + +_DEFAULT_NOTIF_PERIODS = [0, 60] + +global_opts = [ + cfg.StrOpt('region', sample_default='RegionOne', + help=''' +Region that API is running in +'''), + cfg.ListOpt('valid_notification_periods', default=_DEFAULT_NOTIF_PERIODS, + item_type=int, + help=''' +Valid periods for notification methods +''') +] + + +def register_opts(conf): + conf.register_opts(global_opts) + + +def list_opts(): + return 'DEFAULT', global_opts diff --git a/monasca_api/conf/influxdb.py b/monasca_api/conf/influxdb.py new file mode 100644 index 000000000..540e99468 --- /dev/null +++ b/monasca_api/conf/influxdb.py @@ -0,0 +1,50 @@ +# Copyright 2014 IBM Corp. +# Copyright 2016-2017 FUJITSU LIMITED +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# +# 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 oslo_config import cfg + +influxdb_opts = [ + cfg.StrOpt('database_name', default='mon', + help=''' +Database name where metrics are stored +'''), + cfg.HostAddressOpt('ip_address', default='127.0.0.1', + help=''' +IP address to Influxdb server +'''), + cfg.PortOpt('port', default=8086, + help='Port to Influxdb server'), + cfg.StrOpt('user', required=True, + sample_default='monasca-api', help=''' +Influxdb user +'''), + cfg.StrOpt('password', secret=True, sample_default='password', + help=''' +Influxdb password +''') +] + +influxdb_group = cfg.OptGroup(name='influxdb', title='influxdb') + + +def register_opts(conf): + conf.register_group(influxdb_group) + conf.register_opts(influxdb_opts, influxdb_group) + + +def list_opts(): + return influxdb_group, influxdb_opts diff --git a/monasca_api/conf/kafka.py b/monasca_api/conf/kafka.py new file mode 100644 index 000000000..cea9c0bf4 --- /dev/null +++ b/monasca_api/conf/kafka.py @@ -0,0 +1,96 @@ +# Copyright 2014 IBM Corp. +# Copyright 2016-2017 FUJITSU LIMITED +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# +# 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 oslo_config import cfg + +from monasca_api.conf import types + +kafka_opts = [ + cfg.ListOpt('uri', + default=['127.0.0.1:9092'], + item_type=types.HostAddressPortType(), + help=''' +Comma separated list of Kafka broker host:port +'''), + cfg.StrOpt('metrics_topic', default='metrics', + help=''' +The topic that metrics will be published to +'''), + cfg.StrOpt('events_topic', default='events', + help=''' +The topic that events will be published too +'''), + cfg.StrOpt('alarm_state_transitions_topic', + default='alarm-state-transitions', + help=''' +The topic that alarm state will be published too +'''), + cfg.StrOpt('group', default='api', + help=''' +The group name that this service belongs to +'''), + cfg.IntOpt('wait_time', default=1, + advanced=True, min=1, + help=''' +The wait time when no messages on kafka queue +'''), + cfg.IntOpt('ack_time', default=20, + help=''' +The ack time back to kafka. +'''), + cfg.IntOpt('max_retry', default=3, + help=''' +The number of retry when there is a connection error +'''), + cfg.BoolOpt('auto_commit', default=False, + advanced=True, help=''' +Should messages be automatically committed +'''), + cfg.BoolOpt('async', default=True, + help=''' +The type of posting +'''), + cfg.BoolOpt('compact', default=True, + help=''' +Specify if the message received should be parsed. +If True, message will not be parsed, otherwise +messages will be parsed +'''), + cfg.ListOpt('partitions', item_type=int, + default=[0], help=''' +The partitions this connection should +listen for messages on. Currently does not +support multiple partitions. +Default is to listen on partition 0 +'''), + cfg.BoolOpt('drop_data', default=False, + help=''' +Specify if received data should be simply dropped. +This parameter is only for testing purposes +''') +] + +kafka_group = cfg.OptGroup(name='kafka', title='kafka') + + +def register_opts(conf): + conf.register_group(kafka_group) + conf.register_opts(kafka_opts, kafka_group) + + +def list_opts(): + return kafka_group, kafka_opts diff --git a/monasca_api/conf/messaging.py b/monasca_api/conf/messaging.py new file mode 100644 index 000000000..c6b95f94b --- /dev/null +++ b/monasca_api/conf/messaging.py @@ -0,0 +1,52 @@ +# Copyright 2014 IBM Corp. +# Copyright 2016-2017 FUJITSU LIMITED +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# +# 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 oslo_config import cfg + +messaging_opts = [ + cfg.StrOpt('driver', help=''' +The message queue driver to use +'''), + cfg.StrOpt('metrics_message_format', default='reference', + deprecated_for_removal=True, + deprecated_since="2.1.0", + deprecated_reason=''' +Option is not used anywhere in the codebase +''', + help=''' +The type of metrics message format to publish to the message queue +'''), + cfg.StrOpt('events_message_format', default='reference', + deprecated_for_removal=True, + deprecated_since='2.1.0', + deprecated_reason=''' +Option is not used anywhere in the codebase +''', + help=''' +The type of events message format to publish to the message queue +''') +] + +messaging_group = cfg.OptGroup(name='messaging', title='messaging') + + +def register_opts(conf): + conf.register_group(messaging_group) + conf.register_opts(messaging_opts, messaging_group) + + +def list_opts(): + return messaging_group, messaging_opts diff --git a/monasca_api/conf/repositories.py b/monasca_api/conf/repositories.py new file mode 100644 index 000000000..64da2ac04 --- /dev/null +++ b/monasca_api/conf/repositories.py @@ -0,0 +1,64 @@ +# Copyright 2014 IBM Corp. +# Copyright 2016-2017 FUJITSU LIMITED +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# +# 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 oslo_config import cfg + +BASE_SQL_PATH = 'monasca_api.common.repositories.sqla.' + +repositories_opts = [ + cfg.StrOpt('metrics_driver', + default='monasca_api.common.repositories.influxdb.metrics_repository:MetricsRepository', + advanced=True, + help=''' +The repository driver to use for metrics +'''), + cfg.StrOpt('alarm_definitions_driver', + default=BASE_SQL_PATH + 'alarm_definitions_repository:AlarmDefinitionsRepository', + advanced=True, + help=''' +The repository driver to use for alarm definitions +'''), + cfg.StrOpt('alarms_driver', + default=BASE_SQL_PATH + 'alarms_repository:AlarmsRepository', + advanced=True, + help=''' +The repository driver to use for alarms +'''), + cfg.StrOpt('notifications_driver', + default=BASE_SQL_PATH + 'notifications_repository:NotificationsRepository', + advanced=True, + help=''' +The repository driver to use for notifications +'''), + cfg.StrOpt('notification_method_type_driver', + default=BASE_SQL_PATH + 'notification_method_type_repository:NotificationMethodTypeRepository', + advanced=True, + help=''' +The repository driver to use for notifications +''') +] + +repositories_group = cfg.OptGroup(name='repositories', title='repositories') + + +def register_opts(conf): + conf.register_group(repositories_group) + conf.register_opts(repositories_opts, repositories_group) + + +def list_opts(): + return repositories_group, repositories_opts diff --git a/monasca_api/conf/security.py b/monasca_api/conf/security.py new file mode 100644 index 000000000..268f11f12 --- /dev/null +++ b/monasca_api/conf/security.py @@ -0,0 +1,49 @@ +# Copyright 2014 IBM Corp. +# Copyright 2016-2017 FUJITSU LIMITED +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# +# 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 oslo_config import cfg + +security_opts = [ + cfg.ListOpt('default_authorized_roles', default=['admin'], + help=''' +Roles that are allowed full access to the API +'''), + cfg.ListOpt('agent_authorized_roles', default=['agent'], + help=''' +Roles that are only allowed to POST to the API +'''), + cfg.ListOpt('read_only_authorized_roles', + default=['monasca-read-only-user'], + help=''' +Roles that are only allowed to GET from the API +'''), + cfg.ListOpt('delegate_authorized_roles', default=['admin'], + help=''' +Roles that are allowed to POST metrics on +behalf of another tenant +''') +] + +security_group = cfg.OptGroup(name='security', title='security') + + +def register_opts(conf): + conf.register_group(security_group) + conf.register_opts(security_opts, security_group) + + +def list_opts(): + return security_group, security_opts diff --git a/monasca_api/conf/types.py b/monasca_api/conf/types.py new file mode 100644 index 000000000..5edc56b75 --- /dev/null +++ b/monasca_api/conf/types.py @@ -0,0 +1,58 @@ +# Copyright 2017 FUJITSU LIMITED +# +# 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 oslo_config import cfg +from oslo_config import types + + +class HostAddressPortOpt(cfg.Opt): + """Option for HostAddressPortType. + + Accept hostname or ip address with TCP/IP port number. + """ + def __init__(self, name, **kwargs): + ip_port_type = HostAddressPortType() + super(HostAddressPortOpt, self).__init__(name, + type=ip_port_type, + **kwargs) + + +class HostAddressPortType(types.HostAddress): + """HostAddress with additional port.""" + + def __init__(self, version=None): + type_name = 'ip and port value' + super(HostAddressPortType, self).__init__(version, type_name=type_name) + + def __call__(self, value): + addr, port = value.split(':') + addr = self.validate_addr(addr) + port = self._validate_port(port) + if not addr and not port: + raise ValueError('%s is not valid ip with optional port') + return '%s:%d' % (addr, port) + + @staticmethod + def _validate_port(port): + return types.Port()(port) + + def validate_addr(self, addr): + try: + addr = self.ip_address(addr) + except ValueError: + try: + addr = self.hostname(addr) + except ValueError: + raise ValueError("%s is not a valid host address", addr) + return addr diff --git a/monasca_api/config.py b/monasca_api/config.py new file mode 100644 index 000000000..3870164dd --- /dev/null +++ b/monasca_api/config.py @@ -0,0 +1,87 @@ +# Copyright 2017 FUJITSU LIMITED +# +# 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 sys + +from oslo_config import cfg +from oslo_log import log + +from monasca_api import conf +from monasca_api import version + +CONF = conf.CONF +LOG = log.getLogger(__name__) + +_CONF_LOADED = False +_GUNICORN_MARKER = 'gunicorn' + + +def parse_args(argv=None, config_file=None): + """Loads application configuration. + + Loads entire application configuration just once. + + """ + global _CONF_LOADED + if _CONF_LOADED: + LOG.debug('Configuration has been already loaded') + return + + log.set_defaults() + log.register_options(CONF) + + argv = (argv if argv is not None else sys.argv[1:]) + args = ([] if _is_running_under_gunicorn() else argv or []) + config_file = (_get_deprecated_config_file() + if config_file is None else config_file) + + CONF(args=args, + prog='api', + project='monasca', + version=version.version_str, + default_config_files=[config_file] if config_file else None, + description='RESTful API for alarming in the cloud') + + log.setup(CONF, + product_name='monasca-api', + version=version.version_str) + conf.register_opts() + + _CONF_LOADED = True + + +def _is_running_under_gunicorn(): + """Evaluates if api runs under gunicorn.""" + content = filter(lambda x: x != sys.executable and _GUNICORN_MARKER in x, + sys.argv or []) + return len(list(content) if not isinstance(content, list) else content) > 0 + + +def _get_deprecated_config_file(): + """Get deprecated config file. + + Responsible for keeping backward compatibility with old name of + the configuration file i.e. api-config.conf. + New name is => api.conf as prog=api. + + Note: + Old configuration file name did not follow a convention + oslo_config expects. + + """ + old_files = cfg.find_config_files(project='monasca', prog='api-config') + if old_files is not None and len(old_files) > 0: + LOG.warning('Detected old location "/etc/monasca/api-config.conf" ' + 'of main configuration file') + return old_files[0] diff --git a/monasca_api/healthcheck/metrics_db_check.py b/monasca_api/healthcheck/metrics_db_check.py index e7cb2aed0..4839b9f60 100644 --- a/monasca_api/healthcheck/metrics_db_check.py +++ b/monasca_api/healthcheck/metrics_db_check.py @@ -88,7 +88,7 @@ class MetricsDbCheck(base.BaseHealthCheck): return False, "Cassandra driver not imported" try: cassandra = self._cluster.Cluster( - CONF.cassandra.cluster_ip_addresses.split(',') + CONF.cassandra.cluster_ip_addresses ) session = cassandra.connect(CONF.cassandra.keyspace) session.shutdown() diff --git a/monasca_api/tests/base.py b/monasca_api/tests/base.py index 51963b385..077b181ec 100644 --- a/monasca_api/tests/base.py +++ b/monasca_api/tests/base.py @@ -21,6 +21,8 @@ from oslo_context import fixture as oo_ctx from oslotest import base as oslotest_base from monasca_api.api.core import request +from monasca_api import conf +from monasca_api import config class MockedAPI(falcon.API): @@ -45,10 +47,21 @@ class ConfigFixture(oo_cfg.Config): """Mocks configuration""" def __init__(self): - super(ConfigFixture, self).__init__(cfg.CONF) + super(ConfigFixture, self).__init__(config.CONF) def setUp(self): super(ConfigFixture, self).setUp() + self.addCleanup(self._clean_config_loaded_flag) + conf.register_opts() + self._set_defaults() + config.parse_args(argv=[]) # prevent oslo from parsing test args + + @staticmethod + def _clean_config_loaded_flag(): + config._CONF_LOADED = False + + def _set_defaults(self): + self.conf.set_default('user', 'monasca', 'influxdb') class BaseTestCase(oslotest_base.BaseTestCase): diff --git a/monasca_api/tests/config.py b/monasca_api/tests/config.py new file mode 100644 index 000000000..01454b77a --- /dev/null +++ b/monasca_api/tests/config.py @@ -0,0 +1,40 @@ +# Copyright 2017 FUJITSU LIMITED +# +# 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 mock + +from monasca_api import config +from monasca_api.tests import base + + +class TestConfig(base.BaseTestCase): + + @mock.patch('monasca_log_api.config.sys') + def test_should_return_true_if_runs_under_gunicorn(self, sys_patch): + sys_patch.argv = [ + '/bin/gunicorn', + '--capture-output', + '--paste', + 'etc/monasca/log-api-paste.ini', + '--workers', + '1' + ] + sys_patch.executable = '/bin/python' + self.assertTrue(config._is_running_under_gunicorn()) + + @mock.patch('monasca_log_api.config.sys') + def test_should_return_false_if_runs_without_gunicorn(self, sys_patch): + sys_patch.argv = ['/bin/monasca-log-api'] + sys_patch.executable = '/bin/python' + self.assertFalse(config._is_running_under_gunicorn()) diff --git a/monasca_api/tests/test_alarms_db_health_check.py b/monasca_api/tests/test_alarms_db_health_check.py index d98c64450..ea5bed1cb 100644 --- a/monasca_api/tests/test_alarms_db_health_check.py +++ b/monasca_api/tests/test_alarms_db_health_check.py @@ -14,11 +14,11 @@ import mock +from monasca_api import config from monasca_api.healthcheck import alarms_db_check as rdc from monasca_api.tests import base -from monasca_api.v2.reference import cfg -CONF = cfg.CONF +CONF = config.CONF class TestMetricsDbHealthCheckLogic(base.BaseTestCase): diff --git a/monasca_api/tests/test_config_types.py b/monasca_api/tests/test_config_types.py new file mode 100644 index 000000000..a707b73a0 --- /dev/null +++ b/monasca_api/tests/test_config_types.py @@ -0,0 +1,45 @@ +# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP +# Copyright 2017 FUJITSU LIMITED +# +# 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 monasca_api.conf import types +from monasca_api.tests import base + + +class TestHostAddressPortType(base.BaseTestCase): + def setUp(self): + super(TestHostAddressPortType, self).setUp() + self.types = types.HostAddressPortType() + + def test_ip_address(self): + self.assertEqual('127.0.0.1:2121', self.types('127.0.0.1:2121')) + + def test_hostname(self): + self.assertEqual('localhost:2121', self.types('localhost:2121')) + + # failure scenario + def test_missing_port(self): + self.assertRaises(ValueError, self.types, '127.0.0.1') + + def test_missing_address(self): + self.assertRaises(ValueError, self.types, ':123') + + def test_incorrect_ip(self): + self.assertRaises(ValueError, self.types, '127.surprise.0.1:2121') + + def test_incorrect_port(self): + self.assertRaises(ValueError, self.types, '127.0.0.1:65536') + self.assertRaises(ValueError, self.types, '127.0.0.1:sample') diff --git a/monasca_api/tests/test_healthchecks.py b/monasca_api/tests/test_healthchecks.py index 60503c111..5589fb6a6 100644 --- a/monasca_api/tests/test_healthchecks.py +++ b/monasca_api/tests/test_healthchecks.py @@ -15,13 +15,13 @@ import falcon import mock +from monasca_api import config from monasca_api.healthcheck import base from monasca_api import healthchecks from monasca_api.tests import base as test_base -from monasca_api.v2.reference import cfg from monasca_common.rest import utils -CONF = cfg.CONF +CONF = config.CONF ENDPOINT = '/healthcheck' diff --git a/monasca_api/tests/test_kafka_health_check.py b/monasca_api/tests/test_kafka_health_check.py index a66c5eaaa..d8c421005 100644 --- a/monasca_api/tests/test_kafka_health_check.py +++ b/monasca_api/tests/test_kafka_health_check.py @@ -16,11 +16,11 @@ import mock from monasca_common.kafka_lib import client +from monasca_api import config from monasca_api.healthcheck import kafka_check as kc from monasca_api.tests import base -from monasca_api.v2.reference import cfg -CONF = cfg.CONF +CONF = config.CONF class TestKafkaHealthCheckLogic(base.BaseTestCase): diff --git a/monasca_api/tests/test_metrics_db_health_check.py b/monasca_api/tests/test_metrics_db_health_check.py index 8f2d2a552..e1ef69520 100644 --- a/monasca_api/tests/test_metrics_db_health_check.py +++ b/monasca_api/tests/test_metrics_db_health_check.py @@ -19,11 +19,11 @@ import requests import mock from monasca_api.common.repositories import exceptions +from monasca_api import config from monasca_api.healthcheck import metrics_db_check as tdc from monasca_api.tests import base -from monasca_api.v2.reference import cfg -CONF = cfg.CONF +CONF = config.CONF class TestMetricsDbHealthCheck(base.BaseTestCase): diff --git a/monasca_api/v2/reference/__init__.py b/monasca_api/v2/reference/__init__.py index 2f64fc203..e69de29bb 100644 --- a/monasca_api/v2/reference/__init__.py +++ b/monasca_api/v2/reference/__init__.py @@ -1,180 +0,0 @@ -# Copyright 2014 IBM Corp. -# Copyright 2016 FUJITSU LIMITED -# (C) Copyright 2016-2017 Hewlett Packard Enterprise Development LP -# -# 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 oslo_config import cfg -from oslo_config import types -from oslo_db import options - - -"""Configurations for reference implementation - -I think that these configuration parameters should have been split into -small groups and be set into each implementation where they get used. - -For example: kafka configuration should have been in the implementation -where kafka get used. It seems to me that the configuration for kafka gets -used in kafka_publisher, but the original settings were at the api/server.py -which I think is at the wrong place. I move these settings here for now, we -need to have a bit more re-engineering to get it right. -""" -global_opts = [cfg.StrOpt('region', help='Region that API is running in'), - cfg.ListOpt('valid_notification_periods', default=[0, 60], - item_type=int, - help='Valid periods for notification methods') - ] - -cfg.CONF.register_opts(global_opts) - -security_opts = [cfg.ListOpt('default_authorized_roles', default=['admin'], - help='Roles that are allowed full access to the ' - 'API'), - cfg.ListOpt('agent_authorized_roles', default=['agent'], - help='Roles that are only allowed to POST to ' - 'the API'), - cfg.ListOpt('read_only_authorized_roles', default=['monasca-read-only-user'], - help='Roles that are only allowed to GET from ' - 'the API'), - cfg.ListOpt('delegate_authorized_roles', default=['admin'], - help='Roles that are allowed to POST metrics on ' - 'behalf of another tenant')] - -security_group = cfg.OptGroup(name='security', title='security') -cfg.CONF.register_group(security_group) -cfg.CONF.register_opts(security_opts, security_group) - -messaging_opts = [cfg.StrOpt('driver', default='kafka', - help='The message queue driver to use'), - cfg.StrOpt('metrics_message_format', default='reference', - help='The type of metrics message format to ' - 'publish to the message queue'), - cfg.StrOpt('events_message_format', default='reference', - help='The type of events message format to ' - 'publish to the message queue')] - -messaging_group = cfg.OptGroup(name='messaging', title='messaging') -cfg.CONF.register_group(messaging_group) -cfg.CONF.register_opts(messaging_opts, messaging_group) - -base_sqla_path = 'monasca_api.common.repositories.sqla.' -repositories_opts = [ - cfg.StrOpt('metrics_driver', - default='monasca_api.common.repositories.influxdb.metrics_repository:MetricsRepository', - help='The repository driver to use for metrics'), - cfg.StrOpt('alarm_definitions_driver', - default=base_sqla_path + 'alarm_definitions_repository:AlarmDefinitionsRepository', - help='The repository driver to use for alarm definitions'), - cfg.StrOpt('alarms_driver', - default=base_sqla_path + 'alarms_repository:AlarmsRepository', - help='The repository driver to use for alarms'), - cfg.StrOpt('notifications_driver', - default=base_sqla_path + 'notifications_repository:NotificationsRepository', - help='The repository driver to use for notifications'), - cfg.StrOpt('notification_method_type_driver', - default=base_sqla_path + 'notification_method_type_repository:NotificationMethodTypeRepository', - help='The repository driver to use for notifications')] - -repositories_group = cfg.OptGroup(name='repositories', title='repositories') -cfg.CONF.register_group(repositories_group) -cfg.CONF.register_opts(repositories_opts, repositories_group) - - -kafka_opts = [cfg.StrOpt('uri', help='Address to kafka server. For example: ' - 'uri=192.168.1.191:9092'), - cfg.StrOpt('metrics_topic', default='metrics', - help='The topic that metrics will be published too.', - advanced=True), - cfg.StrOpt('events_topic', default='events', - help='The topic that events will be published too.', - advanced=True), - cfg.StrOpt('alarm_state_transitions_topic', default='alarm-state-transitions', - help='The topic that alarm state will be published too.', - advanced=True), - cfg.StrOpt('group', default='api', - help='The group name that this service belongs to.'), - cfg.IntOpt('wait_time', default=1, - help='The wait time when no messages on kafka ' - 'queue.'), cfg.IntOpt('ack_time', default=20, - help='The ack time back ' - 'to kafka.'), - cfg.IntOpt('max_retry', default=3, - help='The number of retry when there is a ' - 'connection error.'), - cfg.BoolOpt('auto_commit', default=False, - help='If automatically commmit when consume ' - 'messages.'), - cfg.BoolOpt('async', default=True, help='The type of posting.'), - cfg.BoolOpt('compact', default=True, help=( - 'Specify if the message received should be parsed.' - 'If True, message will not be parsed, otherwise ' - 'messages will be parsed.')), - cfg.MultiOpt('partitions', item_type=types.Integer(), - default=0, - help='The partitions this connection should ' - 'listen for messages on. Currently does not ' - 'support multiple partitions. ' - 'Default is to listen on partition 0.'), - cfg.BoolOpt('drop_data', default=False, help=( - 'Specify if received data should be simply dropped. ' - 'This parameter is only for testing purposes.')), ] - -kafka_group = cfg.OptGroup(name='kafka', title='title') -cfg.CONF.register_group(kafka_group) -cfg.CONF.register_opts(kafka_opts, kafka_group) - -influxdb_opts = [cfg.StrOpt('database_name'), cfg.StrOpt('ip_address'), - cfg.StrOpt('port'), cfg.StrOpt('user'), - cfg.StrOpt('password', secret=True)] - -influxdb_group = cfg.OptGroup(name='influxdb', title='influxdb') -cfg.CONF.register_group(influxdb_group) -cfg.CONF.register_opts(influxdb_opts, influxdb_group) - -cassandra_opts = [cfg.StrOpt('cluster_ip_addresses'), cfg.StrOpt('keyspace')] - -cassandra_group = cfg.OptGroup(name='cassandra', title='cassandra') -cfg.CONF.register_group(cassandra_group) -cfg.CONF.register_opts(cassandra_opts, cassandra_group) - - -def register_database_opts(): - # Update the default QueuePool parameters. These can be tweaked by the - # conf variables - max_pool_size, max_overflow and pool_timeout - - options.set_defaults(cfg.CONF, connection='sqlite://', - max_pool_size=10, max_overflow=20, - pool_timeout=10) - - # register old value - url_opt = cfg.StrOpt(name='url', - default=cfg.CONF.database.connection, - required=False, - deprecated_for_removal=True, - deprecated_since='1.6.0', - deprecated_reason=( - 'Please use database.connection option,' - 'database.url is scheduled for removal ' - 'in Pike release') - ) - - cfg.CONF.register_opts([url_opt], group='database') - cfg.CONF.set_override(name='connection', group='database', - override=cfg.CONF.database.url) - -register_database_opts() - - -# support URL as an option till Pike is released -# TODO(trebskit) remove in Pike release diff --git a/releasenotes/notes/config_gen-ead0282db82e6c0f.yaml b/releasenotes/notes/config_gen-ead0282db82e6c0f.yaml new file mode 100644 index 000000000..60fc7a6d2 --- /dev/null +++ b/releasenotes/notes/config_gen-ead0282db82e6c0f.yaml @@ -0,0 +1,6 @@ +--- +other: + - | + Removed maintaining the example of configuration file. The file was + removed from the tree, however it can be generated using oslo.config + generator feature. Devstack plugin has been also migrated to use it. \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index f97e57e93..c916f2c42 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,7 +24,6 @@ packages = data_files = /etc/monasca = - etc/api-config.conf etc/api-logging.conf etc/api-config.ini @@ -35,6 +34,9 @@ console_scripts = tempest.test_plugins = monasca_tests = monasca_tempest_tests.plugin:MonascaTempestPlugin +oslo.config.opts = + monasca_api = monasca_api.conf:list_opts + [build_sphinx] all_files = 1 build-dir = doc/build @@ -63,6 +65,7 @@ universal = 1 autodoc_index_modules = True autodoc_exclude_modules = monasca_api.api.wsgi* + monasca_api.conf.* monasca_api.tests.* monasca_tempest_tests.* api_doc_dir = contributor/api diff --git a/tox.ini b/tox.ini index d7724e48f..23cba4f3b 100644 --- a/tox.ini +++ b/tox.ini @@ -98,7 +98,7 @@ commands = [testenv:devdocs] description = Builds developer documentation commands = - rm -rf doc/build + rm -rf doc/build doc/source/contributor/api {[testenv:checkjson]commands} python setup.py build_sphinx @@ -107,6 +107,8 @@ skip_install = True usedevelop = False description = Validates (pep-like) documenation commands = + rm -rf {toxinidir}/doc/source/contributor/api {toxinidir}/doc/build \ + {toxinidir}/api-ref/build {toxinidir}/releasenotes/build doc8 --file-encoding utf-8 {toxinidir}/doc doc8 --file-encoding utf-8 {toxinidir}/api-ref doc8 --file-encoding utf-8 {toxinidir}/releasenotes @@ -123,6 +125,10 @@ commands = bash -c "! find doc/ -type f -name *.json | xargs grep -U -n $'\r'" bash -c '! find doc/ -type f -name *.json | xargs -t -n1 python -m json.tool 2>&1 > /dev/null | grep -B1 -v ^python' +[testenv:genconfig] +description = Generates sample configuration file for monasca-api +commands = oslo-config-generator --config-file=config-generator/api-config.conf + [testenv:venv] commands = {posargs}