├── .gitignore ├── .gitreview ├── .stestr.conf ├── .zuul.yaml ├── CONTRIBUTING.rst ├── HACKING.rst ├── LICENSE ├── README.rst ├── api-ref └── source │ ├── _static │ ├── conf.py │ ├── index.rst │ ├── v1 │ ├── rating │ │ ├── hashmap.rst │ │ └── pyscripts.rst │ └── v1.rst │ └── v2 │ ├── api_samples │ ├── dataframes │ │ ├── dataframes_get.json │ │ └── dataframes_post.json │ ├── rating │ │ ├── module_get.json │ │ └── modules_list_get.json │ ├── scope │ │ └── scope_get.json │ └── summary │ │ ├── summary_get.json │ │ └── summary_get_groupby_time.json │ ├── dataframes │ ├── dataframes.inc │ ├── dataframes_parameters.yml │ └── http_status.yml │ ├── http_status.yml │ ├── index.rst │ ├── rating │ ├── http_status.yml │ ├── modules.inc │ └── modules_parameters.yml │ ├── scope │ ├── http_status.yml │ ├── scope.inc │ └── scope_parameters.yml │ ├── summary │ ├── summary.inc │ └── summary_parameters.yml │ └── task │ ├── reprocessing.inc │ └── reprocessing_parameters.yml ├── cloudkitty ├── __init__.py ├── api │ ├── __init__.py │ ├── app.py │ ├── app.wsgi │ ├── middleware.py │ ├── root.py │ ├── v1 │ │ ├── __init__.py │ │ ├── config.py │ │ ├── controllers │ │ │ ├── __init__.py │ │ │ ├── collector.py │ │ │ ├── info.py │ │ │ ├── rating.py │ │ │ ├── report.py │ │ │ └── storage.py │ │ ├── datamodels │ │ │ ├── __init__.py │ │ │ ├── collector.py │ │ │ ├── info.py │ │ │ ├── rating.py │ │ │ ├── report.py │ │ │ └── storage.py │ │ ├── hooks.py │ │ └── types.py │ └── v2 │ │ ├── __init__.py │ │ ├── base.py │ │ ├── dataframes │ │ ├── __init__.py │ │ └── dataframes.py │ │ ├── rating │ │ ├── __init__.py │ │ └── modules.py │ │ ├── scope │ │ ├── __init__.py │ │ └── state.py │ │ ├── summary │ │ ├── __init__.py │ │ └── summary.py │ │ ├── task │ │ ├── __init__.py │ │ └── reprocess.py │ │ └── utils.py ├── backend │ ├── __init__.py │ └── file.py ├── cli │ ├── __init__.py │ ├── dbsync.py │ ├── processor.py │ ├── status.py │ ├── storage.py │ └── writer.py ├── collector │ ├── __init__.py │ ├── exceptions.py │ ├── gnocchi.py │ └── prometheus.py ├── common │ ├── __init__.py │ ├── config.py │ ├── context.py │ ├── custom_session.py │ ├── db │ │ ├── __init__.py │ │ ├── alembic │ │ │ ├── __init__.py │ │ │ ├── alembic.ini │ │ │ ├── env.py │ │ │ └── migration.py │ │ └── models.py │ ├── defaults.py │ ├── policies │ │ ├── __init__.py │ │ ├── base.py │ │ ├── v1 │ │ │ ├── __init__.py │ │ │ ├── collector.py │ │ │ ├── info.py │ │ │ ├── rating.py │ │ │ ├── report.py │ │ │ └── storage.py │ │ └── v2 │ │ │ ├── __init__.py │ │ │ ├── dataframes.py │ │ │ ├── rating.py │ │ │ ├── scope.py │ │ │ ├── summary.py │ │ │ └── tasks.py │ ├── policy.py │ └── prometheus_client.py ├── config.py ├── dataframe.py ├── db │ ├── __init__.py │ ├── api.py │ └── sqlalchemy │ │ ├── __init__.py │ │ ├── alembic │ │ ├── __init__.py │ │ ├── env.py │ │ ├── script.py.mako │ │ └── versions │ │ │ ├── 2ac2217dcbd9_added_support_for_meta_collector.py │ │ │ ├── 385e33fef139_added_priority_to_modules_state.py │ │ │ └── 464e951dc3b8_initial_migration.py │ │ ├── api.py │ │ ├── migration.py │ │ └── models.py ├── extension_manager.py ├── fetcher │ ├── __init__.py │ ├── gnocchi.py │ ├── keystone.py │ ├── prometheus.py │ └── source.py ├── hacking │ ├── __init__.py │ └── checks.py ├── i18n.py ├── messaging.py ├── orchestrator.py ├── rating │ ├── __init__.py │ ├── hash │ │ ├── __init__.py │ │ ├── controllers │ │ │ ├── __init__.py │ │ │ ├── field.py │ │ │ ├── group.py │ │ │ ├── mapping.py │ │ │ ├── root.py │ │ │ ├── service.py │ │ │ └── threshold.py │ │ ├── datamodels │ │ │ ├── __init__.py │ │ │ ├── field.py │ │ │ ├── group.py │ │ │ ├── mapping.py │ │ │ ├── service.py │ │ │ └── threshold.py │ │ └── db │ │ │ ├── __init__.py │ │ │ ├── api.py │ │ │ └── sqlalchemy │ │ │ ├── __init__.py │ │ │ ├── alembic │ │ │ ├── __init__.py │ │ │ ├── env.py │ │ │ ├── models │ │ │ │ ├── __init__.py │ │ │ │ └── f8c799db4aa0_fix_unnamed_constraints.py │ │ │ ├── script.py.mako │ │ │ └── versions │ │ │ │ ├── 10d2738b67df_rename_mapping_table_to_hashmap_mappings.py │ │ │ │ ├── 3dd7e13527f3_initial_migration.py │ │ │ │ ├── 4da82e1c11c8_add_per_tenant_hashmap_support.py │ │ │ │ ├── 4e0232ce_increase_precision_for_cost_fields.py │ │ │ │ ├── 4fa888fd7eda_added_threshold_support.py │ │ │ │ ├── 54cc17accf2c_fixed_constraint_name.py │ │ │ │ ├── 644faa4491fd_update_tenant_id_type_from_uuid_to_text.py │ │ │ │ ├── Ifbf5b2515c7_increase_precision_for_cost_fields.py │ │ │ │ ├── c88a06b1cfce_clean_hashmap_fields_constraints.py │ │ │ │ └── f8c799db4aa0_fix_unnamed_constraints.py │ │ │ ├── api.py │ │ │ ├── migration.py │ │ │ └── models.py │ ├── noop.py │ └── pyscripts │ │ ├── __init__.py │ │ ├── controllers │ │ ├── __init__.py │ │ ├── root.py │ │ └── script.py │ │ ├── datamodels │ │ ├── __init__.py │ │ └── script.py │ │ └── db │ │ ├── __init__.py │ │ ├── api.py │ │ └── sqlalchemy │ │ ├── __init__.py │ │ ├── alembic │ │ ├── __init__.py │ │ ├── env.py │ │ ├── script.py.mako │ │ └── versions │ │ │ ├── 4f9efa4601c0_initial_migration.py │ │ │ └── 75c205f6f1a2_move_from_sha1_to_sha512.py │ │ ├── api.py │ │ ├── migration.py │ │ └── models.py ├── service.py ├── state.py ├── storage │ ├── __init__.py │ ├── v1 │ │ ├── __init__.py │ │ ├── hybrid │ │ │ ├── __init__.py │ │ │ ├── alembic │ │ │ │ ├── env.py │ │ │ │ ├── script.py.mako │ │ │ │ └── versions │ │ │ │ │ └── 03da4bb002b9_initial_revision.py │ │ │ ├── backends │ │ │ │ ├── __init__.py │ │ │ │ └── gnocchi.py │ │ │ ├── migration.py │ │ │ └── models.py │ │ └── sqlalchemy │ │ │ ├── __init__.py │ │ │ ├── alembic │ │ │ ├── __init__.py │ │ │ ├── env.py │ │ │ ├── script.py.mako │ │ │ └── versions │ │ │ │ ├── 17fd1b237aa3_initial_migration.py │ │ │ │ ├── 307430ab38bc_improve_qty_precision.py │ │ │ │ ├── 792b438b663_added_tenant_informations.py │ │ │ │ ├── c703a1bad612_improve_qty_digit.py │ │ │ │ └── d875621d0384_create_index_idx_tenantid_begin_end_on_.py │ │ │ ├── migration.py │ │ │ └── models.py │ └── v2 │ │ ├── __init__.py │ │ ├── elasticsearch │ │ ├── __init__.py │ │ ├── client.py │ │ └── exceptions.py │ │ ├── influx.py │ │ └── opensearch │ │ ├── __init__.py │ │ ├── client.py │ │ └── exceptions.py ├── storage_state │ ├── __init__.py │ ├── alembic │ │ ├── env.py │ │ ├── script.py.mako │ │ └── versions │ │ │ ├── 4d69395f_add_storage_scope_state_fields.py │ │ │ ├── 750d3050_create_last_processed_timestamp_column.py │ │ │ ├── 9feccd32_create_reprocessing_scheduler.py │ │ │ ├── c14eea9d3cc1_initial.py │ │ │ ├── c50ed2c19204_update_storage_state_constraint.py │ │ │ └── d9d103dd4dcf_add_state_management_columns.py │ ├── migration.py │ └── models.py ├── tests │ ├── __init__.py │ ├── api │ │ ├── __init__.py │ │ ├── v1 │ │ │ ├── __init__.py │ │ │ ├── test_summary.py │ │ │ └── test_types.py │ │ └── v2 │ │ │ ├── __init__.py │ │ │ ├── dataframes │ │ │ ├── __init__.py │ │ │ └── test_dataframes.py │ │ │ ├── summary │ │ │ ├── __init__.py │ │ │ └── test_summary.py │ │ │ ├── task │ │ │ ├── __init__.py │ │ │ └── test_reprocess.py │ │ │ └── test_utils.py │ ├── cli │ │ ├── __init__.py │ │ └── test_status.py │ ├── collectors │ │ ├── __init__.py │ │ ├── test_gnocchi.py │ │ ├── test_prometheus.py │ │ └── test_validation.py │ ├── common │ │ └── test_prometheus_client.py │ ├── fetchers │ │ ├── __init__.py │ │ ├── test_gnocchi.py │ │ └── test_prometheus.py │ ├── gabbi │ │ ├── __init__.py │ │ ├── fixtures.py │ │ ├── gabbi_paste.ini │ │ ├── gabbits │ │ │ ├── ks_middleware_auth.yaml │ │ │ ├── ks_middleware_cors.yaml │ │ │ ├── no_auth.yaml │ │ │ ├── root-v1-storage.yaml │ │ │ ├── root-v2-storage.yaml │ │ │ ├── v1-collector.yaml │ │ │ ├── v1-info.yaml │ │ │ ├── v1-rating.yaml │ │ │ ├── v1-report.yaml │ │ │ ├── v1-storage.yaml │ │ │ ├── v2-dataframes.yaml │ │ │ ├── v2-rating-modules.yaml │ │ │ ├── v2-scope-state.yaml │ │ │ └── v2-summary.yaml │ │ ├── handlers.py │ │ ├── rating │ │ │ ├── __init__.py │ │ │ ├── hash │ │ │ │ ├── __init__.py │ │ │ │ ├── fixtures.py │ │ │ │ ├── gabbits │ │ │ │ │ ├── hash-empty.yaml │ │ │ │ │ ├── hash-errors.yaml │ │ │ │ │ ├── hash-location.yaml │ │ │ │ │ └── hash.yaml │ │ │ │ └── test_gabbi.py │ │ │ └── pyscripts │ │ │ │ ├── __init__.py │ │ │ │ ├── fixtures.py │ │ │ │ ├── gabbits │ │ │ │ └── pyscripts.yaml │ │ │ │ └── test_gabbi.py │ │ └── test_gabbi.py │ ├── samples.py │ ├── storage │ │ ├── __init__.py │ │ ├── v1 │ │ │ ├── __init__.py │ │ │ ├── test_hybrid_storage.py │ │ │ └── test_storage.py │ │ └── v2 │ │ │ ├── __init__.py │ │ │ ├── elasticsearch │ │ │ ├── __init__.py │ │ │ └── test_client.py │ │ │ ├── es_utils.py │ │ │ ├── influx_utils.py │ │ │ ├── opensearch │ │ │ ├── __init__.py │ │ │ └── test_client.py │ │ │ ├── opensearch_utils.py │ │ │ ├── test_influxdb.py │ │ │ └── test_storage_unit.py │ ├── test_config.py │ ├── test_dataframe.py │ ├── test_hacking.py │ ├── test_hashmap.py │ ├── test_keystone_fetcher.py │ ├── test_orchestrator.py │ ├── test_policy.py │ ├── test_pyscripts.py │ ├── test_rating.py │ ├── test_state.py │ ├── test_storage_state.py │ ├── utils.py │ └── utils_tests │ │ ├── __init__.py │ │ ├── test_json.py │ │ ├── test_tz.py │ │ ├── test_utils.py │ │ └── test_validation.py ├── utils │ ├── __init__.py │ ├── json.py │ ├── tz.py │ └── validation.py ├── version.py ├── write_orchestrator.py ├── writer │ ├── __init__.py │ ├── csv_base.py │ ├── csv_map.py │ └── osrf.py └── wsgi │ ├── __init__.py │ └── api.py ├── contrib ├── ci │ └── csv_writer.py ├── cloudkitty.logrotate └── init │ ├── cloudkitty-api.service │ └── cloudkitty-processor.service ├── devstack ├── README.rst ├── apache-cloudkitty.template ├── files │ └── influxdb.conf ├── plugin.sh ├── settings └── upgrade │ ├── resources.sh │ ├── settings │ ├── shutdown.sh │ └── upgrade.sh ├── doc ├── .gitignore ├── Makefile ├── requirements.txt └── source │ ├── _static │ └── cloudkitty.policy.yaml.sample │ ├── admin │ ├── architecture.rst │ ├── cli │ │ ├── cloudkitty-status.rst │ │ └── index.rst │ ├── configuration │ │ ├── collector.rst │ │ ├── configuration.rst │ │ ├── fetcher.rst │ │ ├── index.rst │ │ ├── policy.rst │ │ ├── samples │ │ │ ├── cloudkitty-conf.rst │ │ │ └── policy-yaml.rst │ │ └── storage.rst │ ├── devstack.rst │ ├── index.rst │ └── install │ │ ├── index.rst │ │ ├── install-rdo.rst │ │ ├── install-source.rst │ │ ├── install-ubuntu.rst │ │ └── mod_wsgi.rst │ ├── api-reference │ ├── common-index.rst │ ├── concepts │ └── index.rst │ ├── conf.py │ ├── contributor │ └── contributing.rst │ ├── developer │ ├── api │ │ ├── index.rst │ │ ├── tutorial.rst │ │ └── utils.rst │ ├── collector.rst │ ├── fetcher.rst │ ├── index.rst │ ├── roadmap.rst │ └── storage.rst │ ├── images │ ├── cloudkitty-logo.png │ ├── cloudkitty_architecture.png │ └── cloudkitty_modules.png │ ├── index.rst │ ├── pdf-index.rst │ └── user │ ├── index.rst │ └── rating │ ├── graph │ └── hashmap.dot │ ├── hashmap.rst │ ├── index.rst │ └── pyscripts.rst ├── etc ├── apache2 │ └── cloudkitty ├── cloudkitty │ ├── api_paste.ini │ └── metrics.yml ├── oslo-config-generator │ └── cloudkitty.conf └── oslo-policy-generator │ └── cloudkitty.conf ├── releasenotes ├── notes │ ├── add-dataframe-datapoint-objects-a5a4ac3db5289cb6.yaml │ ├── add-dataframes-v2-api-endpoint-601825c344ba0e2d.yaml │ ├── add-description-option-to-rating-671430ac73c0315b.yaml │ ├── add-gnocchi-fetcher-b8a6e2ea49fcfec5.yaml │ ├── add-influx-storage-backend-3ace5b451e789e64.yaml │ ├── add-new-validation-to-not-allow-reprocessing-with-incompatible-timewindows-5a44802f20bce4f2.yaml │ ├── add-opensearch-as-v2-storage-backend-ff4080d6d32d8a2a.yaml │ ├── add-opensearch-elasticsearch-datastreams-support-28b7c1ce700d33c0.yaml │ ├── add-prometheus-fetcher-be6082f70f279f0e.yaml │ ├── add-re-aggregation-method-option-gnocchi-collector-249917a14c4fc721.yaml │ ├── add-scope-key-58135c2a5c6dae68.yaml │ ├── add-storage-state-v2-api-endpoint-45a29d0b44e177b8.yaml │ ├── add-storage-state-v2-api-endpoint-492d7092e85ed7b1.yaml │ ├── add-support-to-influxdb-v2-storage-backend-f94df79f9e5276a8.yaml │ ├── add-tempest-plugin-3584e1918f344fb2.yaml │ ├── add-v2-storage-driver-for-elasticsearch-ec41cbb7849e82d3.yaml │ ├── add_warning_regarding_gnocchi_version-99d5213c35950e39.yaml │ ├── added-forced-granularity-gnocchi-d52e988194197248.yaml │ ├── added-v2-api-1ef829355c2feea4.yaml │ ├── admin-or-owner-policy-c666346da4405d13.yaml │ ├── allow-multiple-ranting-types-for-same-metric-in-gnocchi-1011ba2d5d36c073.yaml │ ├── batch-delete-reprocessing-d46df15b078a42a5.yaml │ ├── change-metrology-organization-1e11900eb30780cc.yaml │ ├── check-duplicates-metadata-groupby-d5ee99941bb483fd.yaml │ ├── collector-monasca-f0871406513ff22c.yaml │ ├── create-use_all_entries_for_timespan-option-for-gnocchi-collector-39d29603b1f554e1.yaml │ ├── custom-gnocchi-query-a391f5e83d55d771.yaml │ ├── dataframes-get-v2-policy-check-6070fc047b2e1496.yaml │ ├── default-to-v2-storage-a5ecac7e73dafa6d.yaml │ ├── deprecate-ceilometer-collector-6d8f72c84b95662b.yaml │ ├── deprecate-collector-mappings-5a69b31c8037fc01.yaml │ ├── deprecate-elasticsearch-for-opensearch-a338965edff23509.yaml │ ├── deprecate-get-state-2932a4e6a74295ce.yaml │ ├── deprecate-info-services-endpoints-0c5018cb08a30d5f.yaml │ ├── deprecate-json-formatted-policy-file-01ceb65712fd0a39.yaml │ ├── deprecate-monasca-5526b823b227c6ef.yaml │ ├── deprecate-report-total-62544dce42bb19a6.yaml │ ├── deprecate-set-state-3eea30afd43647ab.yaml │ ├── deprecate_section_name-9f1ce1f84d09adf8.yaml │ ├── drop-py-2-7-fcf8c0613a7bffa8.yaml │ ├── drop-python38-5524bd07bca35743.yaml │ ├── fetch-metrics-concurrently-dffffe346bd4900e.yaml │ ├── fix-begin-end-validation-v2-summary-52401fb47ef9b5d6.yaml │ ├── fix-csv-usage-end-7bcf4cb5effc4461.yaml │ ├── fix-dataframe-filtering-282cae643457bb8b.yaml │ ├── fix-gnocchi-metadata-collection-74665e862483a383.yaml │ ├── fix-hashmap-mapping-value-match-56570510203ce3e5.yaml │ ├── fix-lock-release-74d112c8599c9a59.yaml │ ├── fix-opensearch-report-344508dd4e3d0ccc.yaml │ ├── fix-processor-killed-on-metric-collect-error-824897dc2252b504.yaml │ ├── fix-project-id-none-d40df33fc7b7db23.yaml │ ├── fix-quote-v1-api-7282f01b596f0f3b.yaml │ ├── fix-rating-rules-value-precision-40d1054f8ab494c3.yaml │ ├── fix-response-total-for-elastic-search-a3a9244380ed046f.yaml │ ├── fix-scope-state-reset-filters-0a1f5ea503bd32a1.yaml │ ├── fix-url-building-do-init-7c952afaf6d909cd.yaml │ ├── fix-v1-storage-groupby-e865d1315bd390cb.yaml │ ├── fix-v1-summary-and-total-with-es-os-backend-9540741b80819672.yaml │ ├── fix_py_scripts-fd9ab52c92263844.yaml │ ├── force-project-id-monasca-collector-cb30ed073d36d40e.yaml │ ├── get-dataframes-v2-api-endpoint-3a4625c6008a5fca.yaml │ ├── harden-dataframes-policy-7786286525e52dfb.yaml │ ├── ignore_disabled_tenants-and-ignore_rating_role-dfe542a0cafd412e.yaml │ ├── improve-metrics-configuration-271102366f8e6fe7.yaml │ ├── introduce-active-status-field-cdfecd27c2bb9a42.yaml │ ├── introduce-bandit-security-linter-592faa26f957a3dd.yaml │ ├── introduce-cloudkitty.utils-792b9080537405bf.yaml │ ├── introduce-reprocessing-api-822db3edc256507a.yaml │ ├── make-cloudkitty-timezone-aware-2b65edc42e913d6c.yaml │ ├── make-gnocchi-http-max-connections-pool-configurable-52c9f6617466ea30.yaml │ ├── make-processor-run-several-workers-02597b0f77687ef3.yaml │ ├── map-mutator-632b8629c0482e94.yaml │ ├── monasca-fetcher-2ea866f873ab5336.yaml │ ├── move-api-docs-to-api-ref-be71b864e557110e.yaml │ ├── multiple_values_filter_summary_get_v2_api-1110373a900fad0d.yaml │ ├── new-forcegranularity-default-b8aaf7d7823aef3b.yaml │ ├── notnumbool-mutator-ab056e86f2bc843d.yaml │ ├── optimize_gnochi-fetcher-41b502e7ca242cb1.yaml │ ├── optimize_gnochi-fetcher-runtime-3604026816.yaml │ ├── optimizing-sql-queries-939f48fff1805389.yaml │ ├── patch-use-all-revision-0325eeb0f7871c35.yaml │ ├── post-api-create-scope-739098144706a1cf.yaml │ ├── prometheus-collector-empty-meta-12402d8f0254c011.yaml │ ├── prometheus-collector-mutate-8da4748b4d1f0b59.yaml │ ├── prometheus-custom-query-ab2dc00e97b14be2.yaml │ ├── prometheus-error-8eab9f1793c2280c.yaml │ ├── raise-exception-on-invalid-config-0aece71caa0947fa.yaml │ ├── rating-modules-v2-7e4e7a3c5fa96331.yaml │ ├── refactor-storage-e5453296e477e594.yaml │ ├── register-keystone-opts-with-keystoneauth-functions-monasca-collector-1a539fc8c23e9dbc.yaml │ ├── remove-ceilometer-collector-b310bf6c5736c88a.yaml │ ├── remove-dateutil-tz-utc-usage-1350c00be3fadde7.yaml │ ├── remove-deprecated-api-endpoints-26606e322b8a225e.yaml │ ├── remove-deprecated-config-section-names-9a125b1af0932c08.yaml │ ├── remove-deprecated-storage-backends-158fbec099846ec7.yaml │ ├── remove-fake-fetcher-9c264520a3cec9d0.yaml │ ├── remove-fake-meta-collectors-5ed94ab1165e9661.yaml │ ├── remove-gnocchi-transformer-1dad750b9ba6c2e4.yaml │ ├── remove-monasca-429122691d0e5d52.yaml │ ├── remove-state-attribute-scope-28e48ae4ada5208d.yaml │ ├── remove-transformers-8d9949ed3088b055.yaml │ ├── remove-v2-gnocchi-storage-a83bd58008bfd92e.yaml │ ├── remove-wsgi-scripts-27d0da6926c2127c.yaml │ ├── replace-eventlet-with-futurist-60f1fe6474a5efcf.yaml │ ├── reprocess-get-fix-f2bd1f2f9e2d640e.yaml │ ├── reprocessing-concurrency-issues-2a71f4d86a93c507.yaml │ ├── response_format-v2-summary-api-270facdb01d9202b.yaml │ ├── rework-prometheus-collector-02bd6351d447e4fe.yaml │ ├── rework-prometheus-collector-f9f34a3792888dad.yaml │ ├── secure-rbac-defaults-5bb903323634a94c.yaml │ ├── skip-period-if-nonexistent-metric-ba56a671e68f5bf5.yaml │ ├── source-fetcher-43c4352508f7f944.yaml │ ├── status-upgrade-check-fdcf054643e071d8.yaml │ ├── support-cross-tenant-metric-submission-monasca-collector-508b495bc88910ca.yaml │ ├── support-group-by-timeframes-1247aa336916f3b6.yaml │ ├── support-groupby-time-v2-summary-48ff5ad671f8c7c5.yaml │ ├── undeprecate-elasticsearch-6f207824e439ede3.yaml │ └── use-interface-param-endpoint-discovery-monasca-collector-7477e86cd7e5acf4.yaml └── source │ ├── 2023.1.rst │ ├── 2023.2.rst │ ├── 2024.1.rst │ ├── 2024.2.rst │ ├── 2025.1.rst │ ├── _static │ └── .placeholder │ ├── _templates │ └── .placeholder │ ├── conf.py │ ├── index.rst │ ├── ocata.rst │ ├── pike.rst │ ├── queens.rst │ ├── rocky.rst │ ├── stein.rst │ ├── train.rst │ ├── unreleased.rst │ ├── ussuri.rst │ ├── victoria.rst │ ├── wallaby.rst │ ├── xena.rst │ ├── yoga.rst │ └── zed.rst ├── requirements.txt ├── setup.cfg ├── setup.py ├── test-requirements.txt └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | eggs/ 15 | lib/ 16 | lib64/ 17 | parts/ 18 | sdist/ 19 | var/ 20 | *.egg-info/ 21 | .installed.cfg 22 | *.egg 23 | cloudkitty.egg-info 24 | .idea/ 25 | .python-version 26 | 27 | # Configuration file 28 | etc/cloudkitty/cloudkitty.conf.sample 29 | etc/cloudkitty/policy.yaml.sample 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .stestr/ 39 | .coverage 40 | .cache 41 | coverage.xml 42 | cover 43 | 44 | # Translations 45 | *.mo 46 | *.pot 47 | 48 | # Django stuff: 49 | *.log 50 | 51 | # Sphinx documentation 52 | doc/build/ 53 | 54 | # Rope 55 | .ropeproject/ 56 | 57 | # Others 58 | *.sqlite 59 | *.swp 60 | *~ 61 | *.swn 62 | *.swo 63 | *.DS_Store 64 | 65 | # tox -e docs 66 | AUTHORS 67 | ChangeLog 68 | 69 | releasenotes/build 70 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=review.opendev.org 3 | port=29418 4 | project=openstack/cloudkitty.git 5 | -------------------------------------------------------------------------------- /.stestr.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | test_path=./cloudkitty/tests 3 | top_dir=./ 4 | group_regex=gabbi\.(suitemaker|driver)\.(test_[^_]+_[^_]+) 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | The source repository for this project can be found at: 2 | 3 | https://opendev.org/openstack/cloudkitty 4 | 5 | Pull requests submitted through GitHub are not monitored. 6 | 7 | To start contributing to OpenStack, follow the steps in the contribution guide 8 | to set up and use Gerrit: 9 | 10 | https://docs.openstack.org/contributors/code-and-documentation/quick-start.html 11 | 12 | Bugs should be filed on Storyboard: 13 | 14 | https://storyboard.openstack.org/#!/project/890 15 | 16 | For more specific information about contributing to this repository, see the 17 | Cloudkitty contributor guide: 18 | 19 | https://docs.openstack.org/cloudkitty/latest/contributor/contributing.html 20 | -------------------------------------------------------------------------------- /api-ref/source/_static: -------------------------------------------------------------------------------- 1 | ../../doc/source/_static -------------------------------------------------------------------------------- /api-ref/source/index.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | API Reference 3 | ############# 4 | 5 | This is a complete reference of Cloudkitty's API. 6 | 7 | API v1 8 | ====== 9 | 10 | .. toctree:: 11 | :glob: 12 | 13 | v1/* 14 | v1/rating/* 15 | 16 | .. only:: html 17 | 18 | API v2 19 | ====== 20 | 21 | 22 | .. toctree:: 23 | :maxdepth: 2 24 | :glob: 25 | 26 | v2/* 27 | -------------------------------------------------------------------------------- /api-ref/source/v1/rating/pyscripts.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | PyScripts Module REST API 3 | ========================= 4 | 5 | .. rest-controller:: cloudkitty.rating.pyscripts.controllers.root:PyScriptsConfigController 6 | :webprefix: /v1/rating/module_config/pyscripts 7 | 8 | .. rest-controller:: cloudkitty.rating.pyscripts.controllers.script:PyScriptsScriptsController 9 | :webprefix: /v1/rating/module_config/pyscripts/scripts 10 | 11 | .. autotype:: cloudkitty.rating.pyscripts.datamodels.script.Script 12 | :members: 13 | 14 | .. autotype:: cloudkitty.rating.pyscripts.datamodels.script.ScriptCollection 15 | :members: 16 | -------------------------------------------------------------------------------- /api-ref/source/v2/api_samples/rating/module_get.json: -------------------------------------------------------------------------------- 1 | { 2 | "module_id": "sample_id", 3 | "description": "Sample extension", 4 | "enabled": true, 5 | "hot-config": false, 6 | "priority": 2 7 | } 8 | -------------------------------------------------------------------------------- /api-ref/source/v2/api_samples/rating/modules_list_get.json: -------------------------------------------------------------------------------- 1 | { 2 | "modules": [ 3 | { 4 | "module_id": "noop" 5 | "description": "Dummy test module.", 6 | "enabled": true, 7 | "hot-config": false, 8 | "priority": 1 9 | }, 10 | { 11 | "module_id": "hashmap", 12 | "description": "HashMap rating module.", 13 | "enabled": false, 14 | "hot-config": true, 15 | "priority": 2 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /api-ref/source/v2/api_samples/scope/scope_get.json: -------------------------------------------------------------------------------- 1 | { 2 | "results": [ 3 | { 4 | "collector": "gnocchi", 5 | "fetcher": "keystone", 6 | "scope_id": "7a7e5183264644a7a79530eb56e59941", 7 | "scope_key": "project_id", 8 | "last_processed_timestamp": "2019-05-09 10:00:00", 9 | "active": true 10 | }, 11 | { 12 | "collector": "gnocchi", 13 | "fetcher": "keystone", 14 | "scope_id": "9084fadcbd46481788e0ad7405dcbf12", 15 | "scope_key": "project_id", 16 | "last_processed_timestamp": "2019-05-08 03:00:00", 17 | "active": true 18 | }, 19 | { 20 | "collector": "gnocchi", 21 | "fetcher": "keystone", 22 | "scope_id": "1f41d183fca5490ebda5c63fbaca026a", 23 | "scope_key": "project_id", 24 | "last_processed_timestamp": "2019-05-06 22:00:00", 25 | "active": true 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /api-ref/source/v2/api_samples/summary/summary_get.json: -------------------------------------------------------------------------------- 1 | { 2 | "columns": [ 3 | "begin", 4 | "end", 5 | "qty", 6 | "rate", 7 | "project_id", 8 | "type" 9 | ], 10 | "results": [ 11 | [ 12 | "2019-06-01T00:00:00Z", 13 | "2019-07-01T00:00:00Z", 14 | 2590.421676635742, 15 | 1295.210838317871, 16 | "fe9c35372db6420089883805b37a34af", 17 | "image.size" 18 | ], 19 | [ 20 | "2019-06-01T00:00:00Z", 21 | "2019-07-01T00:00:00Z", 22 | 1354, 23 | 3625, 24 | "fe9c35372db6420089883805b37a34af", 25 | "instance" 26 | ], 27 | [ 28 | "2019-06-01T00:00:00Z", 29 | "2019-07-01T00:00:00Z", 30 | 502, 31 | 502, 32 | "fe9c35372db6420089883805b37a34af", 33 | "ip.floating" 34 | ], 35 | [ 36 | "2019-06-01T00:00:00Z", 37 | "2019-07-01T00:00:00Z", 38 | 175.9, 39 | 351.8, 40 | "fe9c35372db6420089883805b37a34af", 41 | "volume.size" 42 | ] 43 | ], 44 | "total": 4 45 | } 46 | -------------------------------------------------------------------------------- /api-ref/source/v2/api_samples/summary/summary_get_groupby_time.json: -------------------------------------------------------------------------------- 1 | { 2 | "total": 232, 3 | "columns": [ 4 | "begin", 5 | "end", 6 | "qty", 7 | "rate", 8 | "project_id" 9 | ], 10 | "results": [ 11 | [ 12 | "2019-10-01T06:00:00+02:00", 13 | "2019-10-01T07:00:00+02:00", 14 | 3.5533905029296875, 15 | 1.7766952514648438, 16 | "84631866b2d84db49b29828052bdc287" 17 | ], 18 | [ 19 | "2019-10-01T07:00:00+02:00", 20 | "2019-10-01T08:00:00+02:00", 21 | 3.5533905029296875, 22 | 1.7766952514648438, 23 | "84631866b2d84db49b29828052bdc287" 24 | ], 25 | [ 26 | "2019-10-01T08:00:00+02:00", 27 | "2019-10-01T09:00:00+02:00", 28 | 3.5533905029296875, 29 | 1.7766952514648438, 30 | "84631866b2d84db49b29828052bdc287" 31 | ] 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /api-ref/source/v2/dataframes/dataframes_parameters.yml: -------------------------------------------------------------------------------- 1 | begin: 2 | in: query 3 | description: | 4 | Begin of the period for which the dataframes are required. 5 | type: iso8601 timestamp 6 | required: false 7 | 8 | end: 9 | in: query 10 | description: | 11 | End of the period for which the dataframes are required. 12 | type: iso8601 timestamp 13 | required: false 14 | 15 | filters: 16 | in: query 17 | description: | 18 | Optional filters. 19 | type: dict 20 | required: false 21 | 22 | limit: 23 | in: query 24 | description: | 25 | For pagination. The maximum number of results to return. 26 | type: int 27 | required: false 28 | 29 | offset: 30 | in: query 31 | description: | 32 | For pagination. The index of the first element that should be returned. 33 | type: int 34 | required: false 35 | 36 | dataframes_body: 37 | in: body 38 | description: | 39 | List of dataframes to add. 40 | type: list 41 | required: true 42 | 43 | dataframes_resp: 44 | in: body 45 | description: | 46 | List of dataframes matching the query parameters. 47 | type: list 48 | required: true 49 | 50 | total_resp: 51 | in: body 52 | description: | 53 | Total of datapoints matching the query parameters. 54 | type: int 55 | required: true 56 | -------------------------------------------------------------------------------- /api-ref/source/v2/dataframes/http_status.yml: -------------------------------------------------------------------------------- 1 | ../http_status.yml -------------------------------------------------------------------------------- /api-ref/source/v2/http_status.yml: -------------------------------------------------------------------------------- 1 | 200: 2 | default: Request was successful. 3 | 4 | 201: 5 | default: Resource was successfully created. 6 | 7 | 202: 8 | default: Request has been accepted for asynchronous processing. 9 | 10 | 204: 11 | default: Request was successful even though no content is to be returned. 12 | 13 | 400: 14 | default: Invalid request. 15 | 16 | 401: 17 | default: Unauthenticated user. 18 | 19 | 403: 20 | default: Forbidden operation for the authentified user. 21 | 22 | 404: 23 | default: Not found. 24 | 25 | 405: 26 | default: The method is not allowed for the requested URL. 27 | -------------------------------------------------------------------------------- /api-ref/source/v2/index.rst: -------------------------------------------------------------------------------- 1 | .. rest_expand_all:: 2 | 3 | .. include:: dataframes/dataframes.inc 4 | .. include:: scope/scope.inc 5 | .. include:: summary/summary.inc 6 | .. include:: task/reprocessing.inc 7 | .. include:: rating/modules.inc 8 | -------------------------------------------------------------------------------- /api-ref/source/v2/rating/http_status.yml: -------------------------------------------------------------------------------- 1 | ../http_status.yml -------------------------------------------------------------------------------- /api-ref/source/v2/rating/modules_parameters.yml: -------------------------------------------------------------------------------- 1 | description: 2 | in: body 3 | description: | 4 | A quick description of the module 5 | type: string 6 | required: true 7 | 8 | enabled: &enabled 9 | in: body 10 | description: | 11 | Boolean representing if the module is enabled 12 | type: bool 13 | required: true 14 | 15 | enabled_opt: 16 | <<: *enabled 17 | required: false 18 | 19 | hot_config: 20 | in: body 21 | description: | 22 | Boolean representing if the module supports hot-config 23 | type: bool 24 | required: true 25 | 26 | module_id: 27 | in: body 28 | description: | 29 | The id of the module 30 | type: string 31 | required: true 32 | 33 | modules_list: 34 | in: body 35 | description: | 36 | List of modules. 37 | type: list 38 | required: true 39 | 40 | priority: &priority 41 | in: body 42 | description: | 43 | Priority of the module, relative to other modules 44 | type: int 45 | required: true 46 | 47 | priority_opt: 48 | <<: *priority 49 | required: false 50 | -------------------------------------------------------------------------------- /api-ref/source/v2/scope/http_status.yml: -------------------------------------------------------------------------------- 1 | ../http_status.yml -------------------------------------------------------------------------------- /cloudkitty/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | import pbr.version 16 | 17 | 18 | __version__ = pbr.version.VersionInfo( 19 | 'cloudkitty').version_string() 20 | -------------------------------------------------------------------------------- /cloudkitty/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/api/__init__.py -------------------------------------------------------------------------------- /cloudkitty/api/app.wsgi: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | # 3 | # Copyright 2013 New Dream Network, LLC (DreamHost) 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | # not use this file except in compliance with the License. You may obtain 7 | # a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | # License for the specific language governing permissions and limitations 15 | # under the License. 16 | 17 | """Use this file for deploying the API under mod_wsgi. 18 | 19 | See http://pecan.readthedocs.org/en/latest/deployment.html for details. 20 | """ 21 | 22 | from cloudkitty.api import app 23 | 24 | application = app.build_wsgi_app(argv=[]) 25 | -------------------------------------------------------------------------------- /cloudkitty/api/v1/config.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | from cloudkitty import config # noqa 13 | 14 | 15 | # Pecan Application Configurations 16 | app = { 17 | 'root': 'cloudkitty.api.v1.controllers.V1Controller', 18 | 'modules': ['cloudkitty.api'], 19 | 'static_root': '%(confdir)s/public', 20 | 'template_path': '%(confdir)s/templates', 21 | 'debug': False, 22 | 'enable_acl': True, 23 | 'acl_public_routes': ['/', '/v1'], 24 | } 25 | -------------------------------------------------------------------------------- /cloudkitty/api/v1/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from pecan import rest 17 | 18 | from cloudkitty.api.v1.controllers import collector as collector_api 19 | from cloudkitty.api.v1.controllers import info as info_api 20 | from cloudkitty.api.v1.controllers import rating as rating_api 21 | from cloudkitty.api.v1.controllers import report as report_api 22 | from cloudkitty.api.v1.controllers import storage as storage_api 23 | 24 | 25 | class V1Controller(rest.RestController): 26 | """API version 1 controller. 27 | 28 | """ 29 | 30 | billing = rating_api.RatingController() 31 | collector = collector_api.CollectorController() 32 | rating = rating_api.RatingController() 33 | report = report_api.ReportController() 34 | storage = storage_api.StorageController() 35 | info = info_api.InfoController() 36 | -------------------------------------------------------------------------------- /cloudkitty/api/v1/datamodels/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/api/v1/datamodels/__init__.py -------------------------------------------------------------------------------- /cloudkitty/api/v1/hooks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from pecan import hooks 17 | 18 | from cloudkitty.common import context 19 | from cloudkitty import messaging 20 | 21 | 22 | class RPCHook(hooks.PecanHook): 23 | def __init__(self): 24 | self._rpc_client = messaging.get_client() 25 | 26 | def before(self, state): 27 | state.request.rpc_client = self._rpc_client 28 | 29 | 30 | class StorageHook(hooks.PecanHook): 31 | def __init__(self, storage_backend): 32 | self._storage_backend = storage_backend 33 | 34 | def before(self, state): 35 | state.request.storage_backend = self._storage_backend 36 | 37 | 38 | class ContextHook(hooks.PecanHook): 39 | def on_route(self, state): 40 | state.request.context = context.RequestContext.from_environ( 41 | state.request.environ) 42 | -------------------------------------------------------------------------------- /cloudkitty/api/v2/dataframes/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | from cloudkitty.api.v2 import utils as api_utils 16 | 17 | 18 | def init(app): 19 | api_utils.do_init(app, 'dataframes', [ 20 | { 21 | 'module': __name__ + '.' + 'dataframes', 22 | 'resource_class': 'DataFrameList', 23 | 'url': '', 24 | }, 25 | ]) 26 | return app 27 | -------------------------------------------------------------------------------- /cloudkitty/api/v2/rating/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | from cloudkitty.api.v2 import utils as api_utils 16 | 17 | 18 | def init(app): 19 | api_utils.do_init(app, 'rating', [ 20 | { 21 | 'module': __name__ + '.' + 'modules', 22 | 'resource_class': 'RatingModule', 23 | 'url': '/modules/', 24 | }, 25 | { 26 | 'module': __name__ + '.' + 'modules', 27 | 'resource_class': 'RatingModuleList', 28 | 'url': '/modules', 29 | }, 30 | ]) 31 | return app 32 | -------------------------------------------------------------------------------- /cloudkitty/api/v2/scope/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | from cloudkitty.api.v2 import utils as api_utils 16 | 17 | 18 | def init(app): 19 | api_utils.do_init(app, 'scope', [ 20 | { 21 | 'module': __name__ + '.' + 'state', 22 | 'resource_class': 'ScopeState', 23 | 'url': '', 24 | }, 25 | ]) 26 | return app 27 | -------------------------------------------------------------------------------- /cloudkitty/api/v2/summary/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | from cloudkitty.api.v2 import utils as api_utils 16 | 17 | 18 | def init(app): 19 | api_utils.do_init(app, 'summary', [ 20 | { 21 | 'module': __name__ + '.' + 'summary', 22 | 'resource_class': 'Summary', 23 | 'url': '', 24 | }, 25 | ]) 26 | return app 27 | -------------------------------------------------------------------------------- /cloudkitty/api/v2/task/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | # 14 | from cloudkitty.api.v2 import utils as api_utils 15 | 16 | 17 | def init(app): 18 | api_utils.do_init(app, 'task', [ 19 | { 20 | 'module': __name__ + '.' + 'reprocess', 21 | 'resource_class': 'ReprocessSchedulerPostApi', 22 | 'url': '/reprocesses', 23 | }, 24 | { 25 | 'module': __name__ + '.' + 'reprocess', 26 | 'resource_class': 'ReprocessSchedulerGetApi', 27 | 'url': '/reprocesses/', 28 | }, 29 | { 30 | 'module': __name__ + '.' + 'reprocess', 31 | 'resource_class': 'ReprocessesSchedulerGetApi', 32 | 'url': '/reprocesses', 33 | }, 34 | ]) 35 | return app 36 | -------------------------------------------------------------------------------- /cloudkitty/backend/file.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | 17 | 18 | class FileBackend(file): # noqa 19 | def __init__(self, path, mode='ab+'): 20 | try: 21 | super(FileBackend, self).__init__(path, mode) 22 | except IOError: 23 | # File not found 24 | super(FileBackend, self).__init__(path, 'wb+') 25 | -------------------------------------------------------------------------------- /cloudkitty/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/cli/__init__.py -------------------------------------------------------------------------------- /cloudkitty/cli/processor.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty import service 17 | 18 | 19 | def main(): 20 | service.prepare_service() 21 | 22 | # NOTE(mc): This import is done here to ensure that the prepare_service() 23 | # function is called before any cfg option. By importing the orchestrator 24 | # file, the utils one is imported too, and then some cfg options are read 25 | # before the prepare_service(), making cfg.CONF returning default values 26 | # systematically. 27 | from cloudkitty import orchestrator 28 | orchestrator.CloudKittyServiceManager().run() 29 | 30 | 31 | if __name__ == '__main__': 32 | main() 33 | -------------------------------------------------------------------------------- /cloudkitty/cli/storage.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty import service 17 | from cloudkitty import storage 18 | from cloudkitty import storage_state 19 | 20 | 21 | def init_storage_backend(): 22 | backend = storage.get_storage() 23 | backend.init() 24 | state_manager = storage_state.StateManager() 25 | state_manager.init() 26 | 27 | 28 | def main(): 29 | service.prepare_service() 30 | init_storage_backend() 31 | -------------------------------------------------------------------------------- /cloudkitty/collector/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | 17 | class CollectError(Exception): 18 | """Base exception for collect errors""" 19 | pass 20 | -------------------------------------------------------------------------------- /cloudkitty/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/common/__init__.py -------------------------------------------------------------------------------- /cloudkitty/common/context.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from oslo_context import context 17 | 18 | from cloudkitty.common import policy 19 | 20 | 21 | class RequestContext(context.RequestContext): 22 | 23 | def __init__(self, is_admin=None, **kwargs): 24 | super(RequestContext, self).__init__(is_admin=is_admin, **kwargs) 25 | if self.is_admin is None: 26 | self.is_admin = policy.check_is_admin(self) 27 | -------------------------------------------------------------------------------- /cloudkitty/common/custom_session.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | import logging 16 | import requests 17 | 18 | from keystoneauth1 import session as ks_session 19 | 20 | 21 | LOG = logging.getLogger(__name__) 22 | 23 | 24 | def create_custom_session(session_options, pool_size): 25 | LOG.debug("Using custom connection pool size: %s", pool_size) 26 | session = requests.Session() 27 | session.adapters['http://'] = ks_session.TCPKeepAliveAdapter( 28 | pool_maxsize=pool_size) 29 | session.adapters['https://'] = ks_session.TCPKeepAliveAdapter( 30 | pool_maxsize=pool_size) 31 | 32 | return ks_session.Session(session=session, **session_options) 33 | -------------------------------------------------------------------------------- /cloudkitty/common/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/common/db/__init__.py -------------------------------------------------------------------------------- /cloudkitty/common/db/alembic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/common/db/alembic/__init__.py -------------------------------------------------------------------------------- /cloudkitty/common/db/alembic/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # path to migration scripts 5 | script_location = alembic 6 | 7 | # template used to generate migration files 8 | # file_template = %%(rev)s_%%(slug)s 9 | 10 | # max length of characters to apply to the 11 | # "slug" field 12 | #truncate_slug_length = 40 13 | 14 | # set to 'true' to run the environment during 15 | # the 'revision' command, regardless of autogenerate 16 | # revision_environment = false 17 | 18 | # set to 'true' to allow .pyc and .pyo files without 19 | # a source .py file to be detected as revisions in the 20 | # versions/ directory 21 | # sourceless = false 22 | 23 | # sqlalchemy.url = driver://user:pass@localhost/dbname 24 | 25 | 26 | # Logging configuration 27 | [loggers] 28 | keys = root,sqlalchemy,alembic 29 | 30 | [handlers] 31 | keys = console 32 | 33 | [formatters] 34 | keys = generic 35 | 36 | [logger_root] 37 | level = WARN 38 | handlers = console 39 | qualname = 40 | 41 | [logger_sqlalchemy] 42 | level = WARN 43 | handlers = 44 | qualname = sqlalchemy.engine 45 | 46 | [logger_alembic] 47 | level = INFO 48 | handlers = 49 | qualname = alembic 50 | 51 | [handler_console] 52 | class = StreamHandler 53 | args = (sys.stderr,) 54 | level = NOTSET 55 | formatter = generic 56 | 57 | [formatter_generic] 58 | format = %(levelname)-5.5s [%(name)s] %(message)s 59 | datefmt = %H:%M:%S 60 | -------------------------------------------------------------------------------- /cloudkitty/common/db/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2016 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from sqlalchemy.ext import declarative 17 | 18 | NAMING_CONVENTION = { 19 | "ix": 'ix_%(column_0_label)s', 20 | "uq": "uq_%(table_name)s_%(column_0_name)s", 21 | "ck": "ck_%(table_name)s_%(constraint_name)s", 22 | "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", 23 | "pk": "pk_%(table_name)s"} 24 | 25 | 26 | def get_base(): 27 | base = declarative.declarative_base() 28 | base.metadata.naming_convention = NAMING_CONVENTION 29 | return base 30 | -------------------------------------------------------------------------------- /cloudkitty/common/policies/v1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/common/policies/v1/__init__.py -------------------------------------------------------------------------------- /cloudkitty/common/policies/v1/storage.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 GohighSec. 2 | # All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | 16 | from oslo_policy import policy 17 | 18 | from cloudkitty.common.policies import base 19 | 20 | storage_policies = [ 21 | policy.DocumentedRuleDefault( 22 | name='storage:list_data_frames', 23 | check_str=base.PROJECT_READER_OR_ADMIN, 24 | description='Return a list of rated resources for a time period ' 25 | 'and a tenant.', 26 | operations=[{'path': '/v1/storage/dataframes', 27 | 'method': 'GET'}], 28 | scope_types=['project']) 29 | ] 30 | 31 | 32 | def list_rules(): 33 | return storage_policies 34 | -------------------------------------------------------------------------------- /cloudkitty/common/policies/v2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/common/policies/v2/__init__.py -------------------------------------------------------------------------------- /cloudkitty/common/policies/v2/dataframes.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | from oslo_policy import policy 16 | 17 | from cloudkitty.common.policies import base 18 | 19 | 20 | dataframes_policies = [ 21 | policy.DocumentedRuleDefault( 22 | name='dataframes:add', 23 | check_str=base.ROLE_ADMIN, 24 | description='Add one or several DataFrames', 25 | operations=[{'path': '/v2/dataframes', 26 | 'method': 'POST'}], 27 | scope_types=['project']), 28 | policy.DocumentedRuleDefault( 29 | name='dataframes:get', 30 | check_str=base.PROJECT_READER_OR_ADMIN, 31 | description='Get DataFrames', 32 | operations=[{'path': '/v2/dataframes', 33 | 'method': 'GET'}], 34 | scope_types=['project']), 35 | ] 36 | 37 | 38 | def list_rules(): 39 | return dataframes_policies 40 | -------------------------------------------------------------------------------- /cloudkitty/common/policies/v2/summary.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | from oslo_policy import policy 16 | 17 | from cloudkitty.common.policies import base 18 | 19 | example_policies = [ 20 | policy.DocumentedRuleDefault( 21 | name='summary:get_summary', 22 | check_str=base.PROJECT_READER_OR_ADMIN, 23 | description='Get a rating summary', 24 | operations=[{'path': '/v2/summary', 25 | 'method': 'GET'}], 26 | scope_types=['project']), 27 | ] 28 | 29 | 30 | def list_rules(): 31 | return example_policies 32 | -------------------------------------------------------------------------------- /cloudkitty/common/policies/v2/tasks.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | # 14 | from oslo_policy import policy 15 | 16 | from cloudkitty.common.policies import base 17 | 18 | 19 | schedule_policies = [ 20 | policy.DocumentedRuleDefault( 21 | name='schedule:task_reprocesses', 22 | check_str=base.ROLE_ADMIN, 23 | description='Schedule a scope for reprocessing', 24 | operations=[{'path': '/v2/task/reprocesses', 25 | 'method': 'POST'}], 26 | scope_types=['project']), 27 | policy.DocumentedRuleDefault( 28 | name='schedule:get_task_reprocesses', 29 | check_str=base.ROLE_ADMIN, 30 | description='Get reprocessing schedule tasks for scopes.', 31 | operations=[{'path': '/v2/task/reprocesses', 32 | 'method': 'GET'}], 33 | scope_types=['project']), 34 | ] 35 | 36 | 37 | def list_rules(): 38 | return schedule_policies 39 | -------------------------------------------------------------------------------- /cloudkitty/db/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import threading 17 | 18 | from oslo_db.sqlalchemy import enginefacade 19 | 20 | _CONTEXT = threading.local() 21 | _FACADE = None 22 | 23 | 24 | def _create_facade_lazily(): 25 | global _FACADE 26 | if _FACADE is None: 27 | ctx = enginefacade.transaction_context() 28 | ctx.configure(sqlite_fk=True) 29 | _FACADE = ctx 30 | return _FACADE 31 | 32 | 33 | def session_for_read(): 34 | return _create_facade_lazily().reader.using(_CONTEXT) 35 | 36 | 37 | def session_for_write(): 38 | return _create_facade_lazily().writer.using(_CONTEXT) 39 | -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/db/sqlalchemy/__init__.py -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/alembic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/db/sqlalchemy/alembic/__init__.py -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/alembic/env.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty.common.db.alembic import env # noqa 17 | from cloudkitty.db.sqlalchemy import models 18 | 19 | target_metadata = models.Base.metadata 20 | version_table = 'cloudkitty_alembic' 21 | 22 | 23 | env.run_migrations_online(target_metadata, version_table) 24 | -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | # Copyright ${create_date.year} OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """${message} 17 | 18 | Revision ID: ${up_revision} 19 | Revises: ${down_revision} 20 | Create Date: ${create_date} 21 | 22 | """ 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = ${repr(up_revision)} 26 | down_revision = ${repr(down_revision)} 27 | 28 | from alembic import op 29 | import sqlalchemy as sa 30 | ${imports if imports else ""} 31 | 32 | def upgrade(): 33 | ${upgrades if upgrades else "pass"} 34 | -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/alembic/versions/2ac2217dcbd9_added_support_for_meta_collector.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """Added support for meta collector 15 | 16 | Revision ID: 2ac2217dcbd9 17 | Revises: 464e951dc3b8 18 | Create Date: 2014-09-25 12:41:28.585333 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '2ac2217dcbd9' 24 | down_revision = '464e951dc3b8' 25 | 26 | from alembic import op # noqa: E402 27 | import sqlalchemy as sa # noqa: E402 28 | 29 | 30 | def upgrade(): 31 | op.create_table( 32 | 'service_to_collector_mappings', 33 | sa.Column('service', sa.String(length=255), nullable=False), 34 | sa.Column('collector', sa.String(length=255), nullable=False), 35 | sa.PrimaryKeyConstraint('service')) 36 | -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/alembic/versions/385e33fef139_added_priority_to_modules_state.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """Added priority to modules_state. 15 | 16 | Revision ID: 385e33fef139 17 | Revises: 2ac2217dcbd9 18 | Create Date: 2015-03-17 17:50:15.229896 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '385e33fef139' 24 | down_revision = '2ac2217dcbd9' 25 | 26 | from alembic import op # noqa: E402 27 | import sqlalchemy as sa # noqa: E402 28 | 29 | 30 | def upgrade(): 31 | op.add_column( 32 | 'modules_state', 33 | sa.Column('priority', sa.Integer(), nullable=True)) 34 | -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/alembic/versions/464e951dc3b8_initial_migration.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """Initial migration 15 | 16 | Revision ID: 464e951dc3b8 17 | Revises: None 18 | Create Date: 2014-08-05 17:41:34.470183 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '464e951dc3b8' 24 | down_revision = None 25 | 26 | from alembic import op # noqa: E402 27 | import sqlalchemy as sa # noqa: E402 28 | 29 | 30 | def upgrade(): 31 | op.create_table( 32 | 'states', 33 | sa.Column('name', sa.String(length=255), nullable=False), 34 | sa.Column('state', sa.BigInteger(), nullable=False), 35 | sa.Column('s_metadata', sa.Text(), nullable=True), 36 | sa.PrimaryKeyConstraint('name')) 37 | op.create_table( 38 | 'modules_state', 39 | sa.Column('name', sa.String(length=255), nullable=False), 40 | sa.Column('state', sa.Boolean(), nullable=False), 41 | sa.PrimaryKeyConstraint('name')) 42 | -------------------------------------------------------------------------------- /cloudkitty/db/sqlalchemy/migration.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from cloudkitty.common.db.alembic import migration 19 | 20 | ALEMBIC_REPO = os.path.join(os.path.dirname(__file__), 'alembic') 21 | 22 | 23 | def upgrade(revision): 24 | config = migration.load_alembic_config(ALEMBIC_REPO) 25 | return migration.upgrade(config, revision) 26 | 27 | 28 | def version(): 29 | config = migration.load_alembic_config(ALEMBIC_REPO) 30 | return migration.version(config) 31 | 32 | 33 | def revision(message, autogenerate): 34 | config = migration.load_alembic_config(ALEMBIC_REPO) 35 | return migration.revision(config, message, autogenerate) 36 | 37 | 38 | def stamp(revision): 39 | config = migration.load_alembic_config(ALEMBIC_REPO) 40 | return migration.stamp(config, revision) 41 | -------------------------------------------------------------------------------- /cloudkitty/extension_manager.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from stevedore import enabled 17 | 18 | 19 | class EnabledExtensionManager(enabled.EnabledExtensionManager): 20 | """CloudKitty Rating processor manager 21 | 22 | Override default EnabledExtensionManager to check for an internal 23 | object property in the extension. 24 | """ 25 | 26 | def __init__(self, namespace, invoke_args=(), invoke_kwds={}): 27 | 28 | def check_enabled(ext): 29 | """Check if extension is enabled. 30 | 31 | """ 32 | return ext.obj.enabled 33 | 34 | super(EnabledExtensionManager, self).__init__( 35 | namespace=namespace, 36 | check_func=check_enabled, 37 | invoke_on_load=True, 38 | invoke_args=invoke_args, 39 | invoke_kwds=invoke_kwds, 40 | ) 41 | -------------------------------------------------------------------------------- /cloudkitty/fetcher/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import abc 17 | 18 | from oslo_config import cfg 19 | 20 | FETCHER_OPTS = 'fetcher' 21 | fetcher_opts = [ 22 | cfg.StrOpt('backend', 23 | default='keystone', 24 | help='Driver used to fetch the list of scopes to rate.'), 25 | ] 26 | cfg.CONF.register_opts(fetcher_opts, 'fetcher') 27 | 28 | 29 | class BaseFetcher(object, metaclass=abc.ABCMeta): 30 | """CloudKitty tenants fetcher. 31 | 32 | Provides Cloudkitty integration with a backend announcing ratable scopes. 33 | """ 34 | 35 | @abc.abstractmethod 36 | def get_tenants(self): 37 | """Retrieve a list of scopes to rate.""" 38 | -------------------------------------------------------------------------------- /cloudkitty/fetcher/source.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from oslo_config import cfg 17 | 18 | from cloudkitty import fetcher 19 | 20 | FETCHER_SOURCE_OPTS = 'fetcher_source' 21 | 22 | fetcher_source_opts = [ 23 | cfg.ListOpt( 24 | 'sources', 25 | default=list(), 26 | help='list of source identifiers', 27 | ), 28 | ] 29 | 30 | cfg.CONF.register_opts(fetcher_source_opts, FETCHER_SOURCE_OPTS) 31 | 32 | CONF = cfg.CONF 33 | 34 | 35 | class SourceFetcher(fetcher.BaseFetcher): 36 | """Source projects fetcher.""" 37 | 38 | name = 'source' 39 | 40 | def get_tenants(self): 41 | return CONF.fetcher_source.sources 42 | -------------------------------------------------------------------------------- /cloudkitty/hacking/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/hacking/__init__.py -------------------------------------------------------------------------------- /cloudkitty/i18n.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import oslo_i18n as i18n # noqa 17 | 18 | _translators = i18n.TranslatorFactory(domain='cloudkitty') 19 | 20 | _ = _translators.primary 21 | -------------------------------------------------------------------------------- /cloudkitty/rating/hash/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/hash/controllers/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/hash/datamodels/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/hash/datamodels/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/hash/datamodels/service.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from wsme import types as wtypes 17 | 18 | from cloudkitty.api.v1 import types as ck_types 19 | 20 | 21 | class Service(wtypes.Base): 22 | """Type describing a service. 23 | 24 | A service is directly mapped to the usage key, the collected service. 25 | """ 26 | 27 | service_id = wtypes.wsattr(ck_types.UuidType(), mandatory=False) 28 | """UUID of the service.""" 29 | 30 | name = wtypes.wsattr(wtypes.text, mandatory=True) 31 | """Name of the service.""" 32 | 33 | @classmethod 34 | def sample(cls): 35 | sample = cls(service_id='a733d0e1-1ec9-4800-8df8-671e4affd017', 36 | name='compute') 37 | return sample 38 | 39 | 40 | class ServiceCollection(wtypes.Base): 41 | """Type describing a list of services.""" 42 | 43 | services = [Service] 44 | """List of services.""" 45 | 46 | @classmethod 47 | def sample(cls): 48 | sample = Service.sample() 49 | return cls(services=[sample]) 50 | -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/hash/db/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/hash/db/sqlalchemy/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/alembic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/hash/db/sqlalchemy/alembic/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/alembic/env.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty.common.db.alembic import env # noqa 17 | from cloudkitty.rating.hash.db.sqlalchemy import models 18 | 19 | target_metadata = models.Base.metadata 20 | version_table = 'hashmap_alembic' 21 | 22 | 23 | env.run_migrations_online(target_metadata, version_table) 24 | -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/alembic/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/hash/db/sqlalchemy/alembic/models/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | # Copyright ${create_date.year} OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """${message} 17 | 18 | Revision ID: ${up_revision} 19 | Revises: ${down_revision} 20 | Create Date: ${create_date} 21 | 22 | """ 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = ${repr(up_revision)} 26 | down_revision = ${repr(down_revision)} 27 | 28 | from alembic import op 29 | import sqlalchemy as sa 30 | ${imports if imports else ""} 31 | 32 | def upgrade(): 33 | ${upgrades if upgrades else "pass"} 34 | -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/alembic/versions/10d2738b67df_rename_mapping_table_to_hashmap_mappings.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """Rename mapping table to hashmap_mappings. 15 | 16 | Revision ID: 10d2738b67df 17 | Revises: 54cc17accf2c 18 | Create Date: 2016-05-24 18:37:25.305430 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '10d2738b67df' 24 | down_revision = '54cc17accf2c' 25 | 26 | from alembic import op # noqa: E402 27 | 28 | 29 | def upgrade(): 30 | op.rename_table('hashmap_maps', 'hashmap_mappings') 31 | -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/alembic/versions/4e0232ce_increase_precision_for_cost_fields.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """Increase cost fields to 30 digits 17 | 18 | Revision ID: 4e0232ce 19 | Revises: Ifbf5b2515c7 20 | Create Date: 2022-04-06 08:00:00.000000 21 | 22 | """ 23 | 24 | from alembic import op 25 | import importlib 26 | 27 | import sqlalchemy as sa 28 | 29 | # revision identifiers, used by Alembic. 30 | revision = '4e0232ce' 31 | down_revision = 'Ifbf5b2515c7' 32 | 33 | 34 | def upgrade(): 35 | down_version_module = importlib.import_module( 36 | "cloudkitty.rating.hash.db.sqlalchemy.alembic.versions." 37 | "644faa4491fd_update_tenant_id_type_from_uuid_to_text") 38 | 39 | for table_name in ('hashmap_mappings', 'hashmap_thresholds'): 40 | with op.batch_alter_table( 41 | table_name, reflect_args=down_version_module.get_reflect( 42 | table_name)) as batch_op: 43 | 44 | batch_op.alter_column('cost', 45 | type_=sa.Numeric(precision=40, scale=28)) 46 | -------------------------------------------------------------------------------- /cloudkitty/rating/hash/db/sqlalchemy/migration.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from cloudkitty.common.db.alembic import migration 19 | 20 | ALEMBIC_REPO = os.path.join(os.path.dirname(__file__), 'alembic') 21 | 22 | 23 | def upgrade(revision): 24 | config = migration.load_alembic_config(ALEMBIC_REPO) 25 | return migration.upgrade(config, revision) 26 | 27 | 28 | def version(): 29 | config = migration.load_alembic_config(ALEMBIC_REPO) 30 | return migration.version(config) 31 | 32 | 33 | def revision(message, autogenerate): 34 | config = migration.load_alembic_config(ALEMBIC_REPO) 35 | return migration.revision(config, message, autogenerate) 36 | 37 | 38 | def stamp(revision): 39 | config = migration.load_alembic_config(ALEMBIC_REPO) 40 | return migration.stamp(config, revision) 41 | -------------------------------------------------------------------------------- /cloudkitty/rating/noop.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty import rating 17 | 18 | 19 | class Noop(rating.RatingProcessorBase): 20 | 21 | module_name = "noop" 22 | description = 'Dummy test module.' 23 | 24 | @property 25 | def enabled(self): 26 | """Check if the module is enabled 27 | 28 | :returns: bool if module is enabled 29 | """ 30 | return True 31 | 32 | @property 33 | def priority(self): 34 | return 1 35 | 36 | def reload_config(self): 37 | pass 38 | 39 | def process(self, data): 40 | return data 41 | -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/controllers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/pyscripts/controllers/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/controllers/root.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty import rating 17 | from cloudkitty.rating.pyscripts.controllers import script as script_api 18 | 19 | 20 | class PyScriptsConfigController(rating.RatingRestControllerBase): 21 | """Controller exposing all management sub controllers. 22 | 23 | """ 24 | 25 | scripts = script_api.PyScriptsScriptsController() 26 | -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/datamodels/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/pyscripts/datamodels/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/pyscripts/db/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/sqlalchemy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/pyscripts/db/sqlalchemy/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/sqlalchemy/alembic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/rating/pyscripts/db/sqlalchemy/alembic/__init__.py -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/sqlalchemy/alembic/env.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty.common.db.alembic import env # noqa 17 | from cloudkitty.rating.pyscripts.db.sqlalchemy import models 18 | 19 | target_metadata = models.Base.metadata 20 | version_table = 'pyscripts_alembic' 21 | 22 | 23 | env.run_migrations_online(target_metadata, version_table) 24 | -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/sqlalchemy/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | # Copyright ${create_date.year} OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """${message} 17 | 18 | Revision ID: ${up_revision} 19 | Revises: ${down_revision} 20 | Create Date: ${create_date} 21 | 22 | """ 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = ${repr(up_revision)} 26 | down_revision = ${repr(down_revision)} 27 | 28 | from alembic import op 29 | import sqlalchemy as sa 30 | ${imports if imports else ""} 31 | 32 | def upgrade(): 33 | ${upgrades if upgrades else "pass"} 34 | -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/sqlalchemy/alembic/versions/4f9efa4601c0_initial_migration.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """Initial migration. 15 | 16 | Revision ID: 4f9efa4601c0 17 | Revises: None 18 | Create Date: 2015-07-30 12:46:32.998770 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '4f9efa4601c0' 24 | down_revision = None 25 | 26 | from alembic import op # noqa: E402 27 | import sqlalchemy as sa # noqa: E402 28 | 29 | 30 | def upgrade(): 31 | op.create_table( 32 | 'pyscripts_scripts', 33 | sa.Column('id', sa.Integer(), nullable=False), 34 | sa.Column('script_id', sa.String(length=36), nullable=False), 35 | sa.Column('name', sa.String(length=255), nullable=False), 36 | sa.Column('data', sa.LargeBinary(), nullable=False), 37 | sa.Column('checksum', sa.String(length=40), nullable=False), 38 | sa.PrimaryKeyConstraint('id'), 39 | sa.UniqueConstraint('name'), 40 | sa.UniqueConstraint('script_id'), 41 | mysql_charset='utf8', 42 | mysql_engine='InnoDB') 43 | -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/sqlalchemy/alembic/versions/75c205f6f1a2_move_from_sha1_to_sha512.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """move from sha1 to sha512 17 | 18 | Revision ID: 75c205f6f1a2 19 | Revises: 4f9efa4601c0 20 | Create Date: 2019-03-25 13:53:23.398755 21 | 22 | """ 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = '75c205f6f1a2' 26 | down_revision = '4f9efa4601c0' 27 | 28 | from alembic import op # noqa: E402 29 | import sqlalchemy as sa # noqa: E402 30 | 31 | 32 | def upgrade(): 33 | with op.batch_alter_table('pyscripts_scripts') as batch_op: 34 | batch_op.alter_column('checksum', 35 | existing_type=sa.VARCHAR(length=40), 36 | type_=sa.String(length=128)) 37 | 38 | 39 | def downgrade(): 40 | with op.batch_alter_table('pyscripts_scripts') as batch_op: 41 | batch_op.alter_column('checksum', 42 | existing_type=sa.String(length=128), 43 | type_=sa.VARCHAR(length=40)) 44 | -------------------------------------------------------------------------------- /cloudkitty/rating/pyscripts/db/sqlalchemy/migration.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from cloudkitty.common.db.alembic import migration 19 | 20 | ALEMBIC_REPO = os.path.join(os.path.dirname(__file__), 'alembic') 21 | 22 | 23 | def upgrade(revision): 24 | config = migration.load_alembic_config(ALEMBIC_REPO) 25 | return migration.upgrade(config, revision) 26 | 27 | 28 | def version(): 29 | config = migration.load_alembic_config(ALEMBIC_REPO) 30 | return migration.version(config) 31 | 32 | 33 | def revision(message, autogenerate): 34 | config = migration.load_alembic_config(ALEMBIC_REPO) 35 | return migration.revision(config, message, autogenerate) 36 | 37 | 38 | def stamp(revision): 39 | config = migration.load_alembic_config(ALEMBIC_REPO) 40 | return migration.stamp(config, revision) 41 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/hybrid/alembic/env.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2017 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty.common.db.alembic import env # noqa 17 | from cloudkitty.storage.v1.hybrid import models 18 | 19 | target_metadata = models.Base.metadata 20 | version_table = 'storage_hybrid_alembic' 21 | 22 | 23 | env.run_migrations_online(target_metadata, version_table) 24 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/hybrid/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/hybrid/alembic/versions/03da4bb002b9_initial_revision.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2017 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | """initial revision 17 | 18 | Revision ID: 03da4bb002b9 19 | Revises: None 20 | Create Date: 2017-11-21 15:59:26.776639 21 | 22 | """ 23 | from alembic import op 24 | import sqlalchemy as sa 25 | 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = '03da4bb002b9' 29 | down_revision = None 30 | branch_labels = None 31 | depends_on = None 32 | 33 | 34 | def upgrade(): 35 | op.create_table( 36 | 'hybrid_storage_states', 37 | sa.Column('id', sa.Integer(), nullable=False), 38 | sa.Column('tenant_id', sa.String(length=32), nullable=False), 39 | sa.Column('state', sa.DateTime(), nullable=False), 40 | sa.PrimaryKeyConstraint('id'), 41 | mysql_charset='utf8', 42 | mysql_engine='InnoDB') 43 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/hybrid/migration.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from cloudkitty.common.db.alembic import migration 19 | 20 | ALEMBIC_REPO = os.path.join(os.path.dirname(__file__), 'alembic') 21 | 22 | 23 | def upgrade(revision): 24 | config = migration.load_alembic_config(ALEMBIC_REPO) 25 | return migration.upgrade(config, revision) 26 | 27 | 28 | def version(): 29 | config = migration.load_alembic_config(ALEMBIC_REPO) 30 | return migration.version(config) 31 | 32 | 33 | def revision(message, autogenerate): 34 | config = migration.load_alembic_config(ALEMBIC_REPO) 35 | return migration.revision(config, message, autogenerate) 36 | 37 | 38 | def stamp(revision): 39 | config = migration.load_alembic_config(ALEMBIC_REPO) 40 | return migration.stamp(config, revision) 41 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/hybrid/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2017 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from oslo_db.sqlalchemy import models 17 | import sqlalchemy 18 | from sqlalchemy.ext import declarative 19 | 20 | Base = declarative.declarative_base() 21 | 22 | 23 | class TenantState(Base, models.ModelBase): 24 | """A tenant state. 25 | 26 | """ 27 | __table_args__ = {'mysql_charset': "utf8", 28 | 'mysql_engine': "InnoDB"} 29 | __tablename__ = 'hybrid_storage_states' 30 | 31 | id = sqlalchemy.Column(sqlalchemy.Integer, 32 | primary_key=True) 33 | tenant_id = sqlalchemy.Column(sqlalchemy.String(32), 34 | nullable=False) 35 | state = sqlalchemy.Column(sqlalchemy.DateTime, 36 | nullable=False) 37 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/storage/v1/sqlalchemy/alembic/__init__.py -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/env.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty.common.db.alembic import env # noqa 17 | from cloudkitty.storage.v1.sqlalchemy import models 18 | 19 | target_metadata = models.Base.metadata 20 | version_table = 'storage_sqlalchemy_alembic' 21 | 22 | 23 | env.run_migrations_online(target_metadata, version_table) 24 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | # Copyright ${create_date.year} OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """${message} 17 | 18 | Revision ID: ${up_revision} 19 | Revises: ${down_revision} 20 | Create Date: ${create_date} 21 | 22 | """ 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = ${repr(up_revision)} 26 | down_revision = ${repr(down_revision)} 27 | 28 | from alembic import op 29 | import sqlalchemy as sa 30 | ${imports if imports else ""} 31 | 32 | def upgrade(): 33 | ${upgrades if upgrades else "pass"} 34 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/versions/17fd1b237aa3_initial_migration.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """Initial migration 15 | 16 | Revision ID: 17fd1b237aa3 17 | Revises: None 18 | Create Date: 2014-10-10 11:28:08.645122 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '17fd1b237aa3' 24 | down_revision = None 25 | 26 | from alembic import op # noqa: E402 27 | import sqlalchemy as sa # noqa: E402 28 | 29 | 30 | def upgrade(): 31 | op.create_table( 32 | 'rated_data_frames', 33 | sa.Column('id', sa.Integer(), nullable=False), 34 | sa.Column('begin', sa.DateTime(), nullable=False), 35 | sa.Column('end', sa.DateTime(), nullable=False), 36 | sa.Column('unit', sa.String(length=255), nullable=False), 37 | sa.Column('qty', sa.Numeric(), nullable=False), 38 | sa.Column('res_type', sa.String(length=255), nullable=False), 39 | sa.Column('rate', sa.Float(), nullable=False), 40 | sa.Column('desc', sa.Text(), nullable=False), 41 | sa.PrimaryKeyConstraint('id'), 42 | mysql_charset='utf8', 43 | mysql_engine='InnoDB') 44 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/versions/307430ab38bc_improve_qty_precision.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """improve qty precision 15 | 16 | Revision ID: 307430ab38bc 17 | Revises: 792b438b663 18 | Create Date: 2016-09-05 18:37:26.714065 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '307430ab38bc' 24 | down_revision = '792b438b663' 25 | 26 | 27 | from alembic import op # noqa: E402 28 | import sqlalchemy as sa # noqa: E402 29 | 30 | 31 | def upgrade(): 32 | with op.batch_alter_table('rated_data_frames') as batch_op: 33 | batch_op.alter_column( 34 | 'qty', 35 | type_=sa.Numeric(10, 5), 36 | existing_type=sa.Numeric()) 37 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/versions/792b438b663_added_tenant_informations.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | """added tenant informations 15 | 16 | Revision ID: 792b438b663 17 | Revises: 17fd1b237aa3 18 | Create Date: 2014-12-02 13:12:11.328534 19 | 20 | """ 21 | 22 | # revision identifiers, used by Alembic. 23 | revision = '792b438b663' 24 | down_revision = '17fd1b237aa3' 25 | 26 | from alembic import op # noqa: E402 27 | import sqlalchemy as sa # noqa: E402 28 | 29 | 30 | def upgrade(): 31 | op.add_column('rated_data_frames', 32 | sa.Column('tenant_id', sa.String(length=32), nullable=True)) 33 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/versions/c703a1bad612_improve_qty_digit.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 OpenStack Foundation 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | """improve_qty_digit 17 | 18 | Revision ID: c703a1bad612 19 | Revises: 307430ab38bc 20 | Create Date: 2017-04-01 09:33:41.434750 21 | 22 | """ 23 | 24 | # revision identifiers, used by Alembic. 25 | revision = 'c703a1bad612' 26 | down_revision = '307430ab38bc' 27 | 28 | from alembic import op # noqa: E402 29 | import sqlalchemy as sa # noqa: E402 30 | 31 | 32 | def upgrade(): 33 | with op.batch_alter_table('rated_data_frames') as batch_op: 34 | batch_op.alter_column( 35 | 'qty', 36 | type_=sa.Numeric(15, 5), 37 | existing_type=sa.Numeric()) 38 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/alembic/versions/d875621d0384_create_index_idx_tenantid_begin_end_on_.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 10 | # implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | 14 | """Creating indexes to allow SQL query optimizations 15 | Revision ID: d875621d0384 16 | Revises: c703a1bad612 17 | Create Date: 2022-11-23 15:36:05.331585 18 | 19 | """ 20 | from alembic import op 21 | 22 | 23 | # revision identifiers, used by Alembic. 24 | revision = 'd875621d0384' 25 | down_revision = 'c703a1bad612' 26 | branch_labels = None 27 | depends_on = None 28 | 29 | 30 | def upgrade(): 31 | op.create_index('idx_rated_data_frames_date', 'rated_data_frames', 32 | ['begin', 'end']) 33 | op.create_index('idx_tenantid_begin_end', 'rated_data_frames', 34 | ['tenant_id', 'begin', 'end']) 35 | 36 | 37 | def downgrade(): 38 | op.drop_index('idx_tenantid_begin_end', 'rated_data_frames') 39 | op.drop_index('idx_rated_data_frames_date', 'rated_data_frames') 40 | -------------------------------------------------------------------------------- /cloudkitty/storage/v1/sqlalchemy/migration.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from cloudkitty.common.db.alembic import migration 19 | 20 | ALEMBIC_REPO = os.path.join(os.path.dirname(__file__), 'alembic') 21 | 22 | 23 | def upgrade(revision): 24 | config = migration.load_alembic_config(ALEMBIC_REPO) 25 | return migration.upgrade(config, revision) 26 | 27 | 28 | def version(): 29 | config = migration.load_alembic_config(ALEMBIC_REPO) 30 | return migration.version(config) 31 | 32 | 33 | def revision(message, autogenerate): 34 | config = migration.load_alembic_config(ALEMBIC_REPO) 35 | return migration.revision(config, message, autogenerate) 36 | 37 | 38 | def stamp(revision): 39 | config = migration.load_alembic_config(ALEMBIC_REPO) 40 | return migration.stamp(config, revision) 41 | -------------------------------------------------------------------------------- /cloudkitty/storage/v2/elasticsearch/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | 17 | class BaseElasticsearchException(Exception): 18 | """Base exception raised by the Elasticsearch v2 storage driver""" 19 | 20 | 21 | class InvalidStatusCode(BaseElasticsearchException): 22 | def __init__(self, expected, actual, msg, query): 23 | super(InvalidStatusCode, self).__init__( 24 | "Expected {} status code, got {}: {}. Query was {}".format( 25 | expected, actual, msg, query)) 26 | 27 | 28 | class IndexDoesNotExist(BaseElasticsearchException): 29 | def __init__(self, index_name): 30 | super(IndexDoesNotExist, self).__init__( 31 | "Elasticsearch index {} does not exist".format(index_name) 32 | ) 33 | -------------------------------------------------------------------------------- /cloudkitty/storage/v2/opensearch/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | 16 | 17 | class BaseOpenSearchException(Exception): 18 | """Base exception raised by the OpenSearch v2 storage driver""" 19 | 20 | 21 | class InvalidStatusCode(BaseOpenSearchException): 22 | def __init__(self, expected, actual, msg, query): 23 | super(InvalidStatusCode, self).__init__( 24 | "Expected {} status code, got {}: {}. Query was {}".format( 25 | expected, actual, msg, query)) 26 | 27 | 28 | class IndexDoesNotExist(BaseOpenSearchException): 29 | def __init__(self, index_name): 30 | super(IndexDoesNotExist, self).__init__( 31 | "OpenSearch index {} does not exist".format(index_name) 32 | ) 33 | -------------------------------------------------------------------------------- /cloudkitty/storage_state/alembic/env.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2018 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty.common.db.alembic import env # noqa 17 | from cloudkitty.storage_state import models 18 | 19 | target_metadata = models.Base.metadata 20 | version_table = 'storage_states_alembic' 21 | 22 | 23 | env.run_migrations_online(target_metadata, version_table) 24 | -------------------------------------------------------------------------------- /cloudkitty/storage_state/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /cloudkitty/storage_state/alembic/versions/c14eea9d3cc1_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2018 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | """Initial 17 | 18 | Revision ID: c14eea9d3cc1 19 | Revises: 20 | Create Date: 2018-04-20 14:27:11.434366 21 | 22 | """ 23 | from alembic import op 24 | import sqlalchemy as sa 25 | 26 | 27 | # revision identifiers, used by Alembic. 28 | revision = 'c14eea9d3cc1' 29 | down_revision = None 30 | branch_labels = None 31 | depends_on = None 32 | 33 | 34 | def upgrade(): 35 | op.create_table( 36 | 'cloudkitty_storage_states', 37 | sa.Column('id', sa.Integer(), nullable=False), 38 | sa.Column('identifier', 39 | sa.String(length=40), 40 | nullable=False, 41 | unique=True), 42 | sa.Column('state', sa.DateTime(), nullable=False), 43 | sa.PrimaryKeyConstraint('id'), 44 | mysql_charset='utf8', 45 | mysql_engine='InnoDB' 46 | ) 47 | 48 | 49 | def downgrade(): 50 | op.drop_table('cloudkitty_storage_states') 51 | -------------------------------------------------------------------------------- /cloudkitty/storage_state/alembic/versions/d9d103dd4dcf_add_state_management_columns.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | """Add details to state management 16 | 17 | Revision ID: d9d103dd4dcf 18 | Revises: c14eea9d3cc1 19 | Create Date: 2019-02-07 13:59:39.294277 20 | 21 | """ 22 | from alembic import op 23 | import sqlalchemy as sa 24 | 25 | 26 | # revision identifiers, used by Alembic. 27 | revision = 'd9d103dd4dcf' 28 | down_revision = 'c14eea9d3cc1' 29 | branch_labels = None 30 | depends_on = None 31 | 32 | 33 | def upgrade(): 34 | for column_name in ('scope_key', 'collector', 'fetcher'): 35 | op.add_column( 36 | 'cloudkitty_storage_states', 37 | sa.Column(column_name, sa.String(length=40), nullable=True)) 38 | -------------------------------------------------------------------------------- /cloudkitty/storage_state/migration.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from cloudkitty.common.db.alembic import migration 19 | 20 | ALEMBIC_REPO = os.path.join(os.path.dirname(__file__), 'alembic') 21 | 22 | 23 | def upgrade(revision): 24 | config = migration.load_alembic_config(ALEMBIC_REPO) 25 | return migration.upgrade(config, revision) 26 | 27 | 28 | def version(): 29 | config = migration.load_alembic_config(ALEMBIC_REPO) 30 | return migration.version(config) 31 | 32 | 33 | def revision(message, autogenerate): 34 | config = migration.load_alembic_config(ALEMBIC_REPO) 35 | return migration.revision(config, message, autogenerate) 36 | 37 | 38 | def stamp(revision): 39 | config = migration.load_alembic_config(ALEMBIC_REPO) 40 | return migration.stamp(config, revision) 41 | -------------------------------------------------------------------------------- /cloudkitty/tests/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/api/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/api/v1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/api/v1/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/api/v1/test_summary.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2017 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | """Test SummaryModel objects.""" 17 | from oslotest import base 18 | 19 | from cloudkitty.api.v1.datamodels import report 20 | 21 | 22 | class TestSummary(base.BaseTestCase): 23 | 24 | def setUp(self): 25 | super(TestSummary, self).setUp() 26 | 27 | def test_nulls(self): 28 | s = report.SummaryModel(begin=None, 29 | end=None, 30 | tenant_id=None, 31 | res_type=None, 32 | rate=None) 33 | self.assertIsNone(s.begin) 34 | self.assertIsNone(s.end) 35 | self.assertEqual(s.tenant_id, "ALL") 36 | self.assertEqual(s.res_type, "ALL") 37 | self.assertEqual(s.rate, "0") 38 | -------------------------------------------------------------------------------- /cloudkitty/tests/api/v2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/api/v2/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/api/v2/dataframes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/api/v2/dataframes/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/api/v2/summary/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/api/v2/summary/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/api/v2/task/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/api/v2/task/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/cli/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/cli/test_status.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | from oslo_upgradecheck import upgradecheck 16 | 17 | from cloudkitty.cli import status 18 | from cloudkitty import tests 19 | 20 | 21 | class CloudKittyStatusCheckUpgradeTest(tests.TestCase): 22 | 23 | def setUp(self): 24 | super(CloudKittyStatusCheckUpgradeTest, self).setUp() 25 | self._checks = status.CloudkittyUpgradeChecks() 26 | 27 | def test_storage_version_with_v1(self): 28 | self.conf.set_override('version', 1, 'storage') 29 | self.assertEqual( 30 | upgradecheck.Code.WARNING, 31 | self._checks._storage_version().code, 32 | ) 33 | 34 | def test_storage_version_with_v2(self): 35 | self.conf.set_override('version', 2, 'storage') 36 | self.assertEqual( 37 | upgradecheck.Code.SUCCESS, 38 | self._checks._storage_version().code, 39 | ) 40 | -------------------------------------------------------------------------------- /cloudkitty/tests/collectors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/collectors/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/fetchers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/fetchers/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/gabbi/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/gabbi_paste.ini: -------------------------------------------------------------------------------- 1 | [pipeline:cloudkitty+noauth] 2 | pipeline = cors http_proxy_to_wsgi request_id ck_api_v1 3 | 4 | [pipeline:cloudkitty+keystone] 5 | pipeline = cors http_proxy_to_wsgi request_id authtoken ck_api_v1 6 | 7 | [app:ck_api_v1] 8 | paste.app_factory = cloudkitty.api.app:app_factory 9 | 10 | [filter:authtoken] 11 | acl_public_routes = /, /v1 12 | paste.filter_factory = cloudkitty.api.middleware:AuthTokenMiddleware.factory 13 | 14 | [filter:request_id] 15 | paste.filter_factory = oslo_middleware:RequestId.factory 16 | 17 | [filter:cors] 18 | paste.filter_factory = oslo_middleware.cors:filter_factory 19 | oslo_config_project = cloudkitty 20 | 21 | [filter:http_proxy_to_wsgi] 22 | paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory 23 | oslo_config_project = cloudkitty 24 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/gabbits/ks_middleware_auth.yaml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | - ConfigFixtureKeystoneAuth 3 | - StorageDataFixture 4 | - NowStorageDataFixture 5 | 6 | tests: 7 | - name: Can't query api without token 8 | GET: /v1/storage/dataframes 9 | status: 401 10 | 11 | - name: Can't query api with non valid token 12 | GET: /v1/storage/dataframes 13 | status: 401 14 | request_headers: 15 | X-Auth-Token: bf08a02dbd52406b94fcc2447bb3e266 16 | 17 | - name: Can query api with valid token 18 | GET: /v1/storage/dataframes 19 | status: 200 20 | request_headers: 21 | X-Auth-Token: c93e3e31342e4e32ba201fd3d70878b5 22 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/gabbits/ks_middleware_cors.yaml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | - ConfigFixture 3 | - CORSConfigFixture 4 | 5 | tests: 6 | 7 | - name: valid cors options 8 | OPTIONS: / 9 | status: 200 10 | request_headers: 11 | origin: http://valid.example.com 12 | access-control-request-method: GET 13 | response_headers: 14 | access-control-allow-origin: http://valid.example.com 15 | 16 | - name: invalid cors options 17 | OPTIONS: / 18 | status: 200 19 | request_headers: 20 | origin: http://invalid.example.com 21 | access-control-request-method: GET 22 | response_forbidden_headers: 23 | - access-control-allow-origin 24 | 25 | - name: valid cors get 26 | GET: / 27 | status: 200 28 | request_headers: 29 | origin: http://valid.example.com 30 | access-control-request-method: GET 31 | response_headers: 32 | access-control-allow-origin: http://valid.example.com 33 | 34 | - name: invalid cors get 35 | GET: / 36 | status: 200 37 | request_headers: 38 | origin: http://invalid.example.com 39 | response_forbidden_headers: 40 | - access-control-allow-origin 41 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/gabbits/no_auth.yaml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | - ConfigFixture 3 | - StorageDataFixture 4 | - NowStorageDataFixture 5 | 6 | tests: 7 | - name: Can query API without auth 8 | url: /v1/storage/dataframes 9 | status: 200 10 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/gabbits/root-v1-storage.yaml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | - ConfigFixture 3 | 4 | tests: 5 | - name: test if / is publicly available 6 | url: / 7 | status: 200 8 | 9 | - name: test if HEAD / is available 10 | url: / 11 | status: 200 12 | method: HEAD 13 | 14 | - name: test that only one APIs is available 15 | url: / 16 | status: 200 17 | response_json_paths: 18 | $.versions.`len`: 1 19 | $.versions[0].id: v1 20 | $.versions[0].status: CURRENT 21 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/gabbits/root-v2-storage.yaml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | - ConfigFixtureStorageV2 3 | 4 | tests: 5 | - name: test if / is publicly available 6 | url: / 7 | status: 200 8 | 9 | - name: test if HEAD / is available 10 | url: / 11 | status: 200 12 | method: HEAD 13 | 14 | - name: test if both APIs are available 15 | url: / 16 | status: 200 17 | response_json_paths: 18 | $.versions.`len`: 2 19 | $.versions[0].id: v1 20 | $.versions[1].id: v2 21 | $.versions[0].status: CURRENT 22 | $.versions[1].status: EXPERIMENTAL 23 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/gabbits/v1-info.yaml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | - ConfigFixture 3 | - MetricsConfFixture 4 | 5 | tests: 6 | - name: get config 7 | url: /v1/info/config 8 | status: 200 9 | response_json_paths: 10 | $.metrics.`len`: 7 11 | $.metrics['cpu'].unit: instance 12 | $.metrics['image.size'].unit: MiB 13 | $.metrics['volume.size'].unit: GiB 14 | $.metrics['network.incoming.bytes'].unit: MB 15 | $.metrics['network.outgoing.bytes'].unit: MB 16 | $.metrics['ip.floating'].unit: ip 17 | $.metrics['radosgw.objects.size'].unit: GiB 18 | 19 | - name: get metrics info 20 | url: /v1/info/metrics 21 | status: 200 22 | response_json_paths: 23 | $.metrics.`len`: 7 24 | $.metrics[/metric_id][0].metric_id: image.size 25 | $.metrics[/metric_id][0].unit: MiB 26 | $.metrics[/metric_id][1].metric_id: instance 27 | $.metrics[/metric_id][1].unit: instance 28 | $.metrics[/metric_id][2].metric_id: ip.floating 29 | $.metrics[/metric_id][2].unit: ip 30 | $.metrics[/metric_id][3].metric_id: network.incoming.bytes 31 | $.metrics[/metric_id][3].unit: MB 32 | $.metrics[/metric_id][4].metric_id: network.outgoing.bytes 33 | $.metrics[/metric_id][4].unit: MB 34 | $.metrics[/metric_id][5].metric_id: radosgw.objects.size 35 | $.metrics[/metric_id][5].unit: GiB 36 | $.metrics[/metric_id][6].metric_id: volume.size 37 | $.metrics[/metric_id][6].unit: GiB 38 | 39 | - name: get cpu metric info 40 | url: /v1/info/metrics/instance 41 | status: 200 42 | response_json_paths: 43 | $.metric_id: instance 44 | $.unit: instance 45 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/handlers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2016 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from gabbi.handlers import base 19 | 20 | 21 | class EnvironStoreHandler(base.ResponseHandler): 22 | """Hackish response handler used to store data in environment. 23 | 24 | Store data into an environment variable to implement some kind of variable 25 | use in gabbi. 26 | """ 27 | test_key_suffix = 'store_environ' 28 | test_key_value = {} 29 | 30 | def action(self, test, key, value=None): 31 | data = test.content_handlers[0].extract_json_path_value( 32 | test.response_data, value) 33 | os.environ[key] = test.replace_template(data) 34 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/gabbi/rating/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/hash/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/gabbi/rating/hash/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/hash/fixtures.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | 17 | from cloudkitty.tests.gabbi.fixtures import * # noqa 18 | from cloudkitty.rating.hash.db import api as hashmap_db 19 | 20 | 21 | class HashMapConfigFixture(ConfigFixture): # noqa: F405 22 | def start_fixture(self): 23 | super(HashMapConfigFixture, self).start_fixture() 24 | self.conn = hashmap_db.get_instance() 25 | migration = self.conn.get_migration() 26 | migration.upgrade('head') 27 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/hash/gabbits/hash-empty.yaml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | - HashMapConfigFixture 3 | 4 | tests: 5 | 6 | - name: list services (empty) 7 | url: /v1/rating/module_config/hashmap/services 8 | status: 200 9 | response_strings: 10 | - "[]" 11 | 12 | - name: list fields from invalid service (empty) 13 | url: /v1/rating/module_config/hashmap/fields?service_id=d28490b2-fb3c-11e5-988b-eb9539c935dc 14 | status: 200 15 | response_strings: 16 | - "[]" 17 | 18 | - name: list mappings from invalid service (empty) 19 | url: /v1/rating/module_config/hashmap/mappings?service_id=d28490b2-fb3c-11e5-988b-eb9539c935dc 20 | status: 200 21 | response_strings: 22 | - "[]" 23 | 24 | - name: list mappings from invalid field (empty) 25 | url: /v1/rating/module_config/hashmap/mappings?field_id=d28490b2-fb3c-11e5-988b-eb9539c935dc 26 | status: 200 27 | response_strings: 28 | - "[]" 29 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/hash/test_gabbi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from gabbi import driver 19 | 20 | from cloudkitty.tests.gabbi import fixtures 21 | from cloudkitty.tests.gabbi import handlers as cloudkitty_handlers 22 | from cloudkitty.tests.gabbi.rating.hash import fixtures as hash_fixtures 23 | 24 | TESTS_DIR = 'gabbits' 25 | 26 | 27 | def load_tests(loader, tests, pattern): 28 | test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR) 29 | return driver.build_tests(test_dir, 30 | loader, 31 | host=None, 32 | intercept=fixtures.setup_app, 33 | fixture_module=hash_fixtures, 34 | response_handlers=[ 35 | cloudkitty_handlers.EnvironStoreHandler]) 36 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/pyscripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/gabbi/rating/pyscripts/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/pyscripts/fixtures.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | 17 | from cloudkitty.tests.gabbi.fixtures import * # noqa 18 | from cloudkitty.rating.pyscripts.db import api as pyscripts_db 19 | 20 | 21 | class PyScriptsConfigFixture(ConfigFixture): # noqa: F405 22 | def start_fixture(self): 23 | super(PyScriptsConfigFixture, self).start_fixture() 24 | self.conn = pyscripts_db.get_instance() 25 | migration = self.conn.get_migration() 26 | migration.upgrade('head') 27 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/rating/pyscripts/test_gabbi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from gabbi import driver 19 | 20 | from cloudkitty.tests.gabbi import fixtures 21 | from cloudkitty.tests.gabbi.rating.pyscripts import fixtures as py_fixtures 22 | 23 | TESTS_DIR = 'gabbits' 24 | 25 | 26 | def load_tests(loader, tests, pattern): 27 | test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR) 28 | return driver.build_tests(test_dir, 29 | loader, 30 | host=None, 31 | intercept=fixtures.setup_app, 32 | fixture_module=py_fixtures) 33 | -------------------------------------------------------------------------------- /cloudkitty/tests/gabbi/test_gabbi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import os 17 | 18 | from gabbi import driver 19 | 20 | from cloudkitty.tests.gabbi import fixtures 21 | 22 | 23 | TESTS_DIR = 'gabbits' 24 | 25 | 26 | def load_tests(loader, tests, pattern): 27 | test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR) 28 | return driver.build_tests(test_dir, 29 | loader, 30 | host=None, 31 | intercept=fixtures.setup_app, 32 | fixture_module=fixtures) 33 | -------------------------------------------------------------------------------- /cloudkitty/tests/storage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/storage/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/storage/v1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/storage/v1/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/storage/v2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/storage/v2/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/storage/v2/elasticsearch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/storage/v2/elasticsearch/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/storage/v2/opensearch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/storage/v2/opensearch/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/test_config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2015 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | from cloudkitty.common import config as ck_config 17 | from cloudkitty import tests 18 | 19 | 20 | class ConfigTest(tests.TestCase): 21 | def test_config(self): 22 | ck_config.list_opts() 23 | -------------------------------------------------------------------------------- /cloudkitty/tests/test_state.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Copyright 2014 Objectif Libre 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | # not use this file except in compliance with the License. You may obtain 6 | # a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | # License for the specific language governing permissions and limitations 14 | # under the License. 15 | # 16 | import datetime 17 | 18 | from cloudkitty import state 19 | from cloudkitty import tests 20 | 21 | 22 | class DBStateManagerTest(tests.TestCase): 23 | def setUp(self): 24 | super(DBStateManagerTest, self).setUp() 25 | self.sm = state.DBStateManager('testuser', 'osrtf') 26 | 27 | def test_gen_name(self): 28 | name = self.sm._gen_name('testuser', 'osrtf') 29 | self.assertEqual(name, 'testuser_osrtf') 30 | 31 | def test_state_access(self): 32 | now = datetime.datetime.utcnow() 33 | self.sm.set_state(now) 34 | result = self.sm.get_state() 35 | self.assertEqual(result, str(now)) 36 | 37 | def test_metadata_access(self): 38 | metadata = {'foo': 'bar'} 39 | now = datetime.datetime.utcnow() 40 | self.sm.set_state(now) 41 | self.sm.set_metadata(metadata) 42 | result = self.sm.get_metadata() 43 | self.assertEqual(result, metadata) 44 | -------------------------------------------------------------------------------- /cloudkitty/tests/utils_tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/tests/utils_tests/__init__.py -------------------------------------------------------------------------------- /cloudkitty/tests/utils_tests/test_json.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | import datetime 16 | import decimal 17 | 18 | from dateutil import tz 19 | 20 | from cloudkitty import tests 21 | from cloudkitty.utils import json 22 | 23 | 24 | class JSONEncoderTest(tests.TestCase): 25 | 26 | def test_encode_decimal(self): 27 | obj = {'nb': decimal.Decimal(42)} 28 | self.assertEqual(json.dumps(obj), '{"nb": 42.0}') 29 | 30 | def test_encode_datetime(self): 31 | obj = {'date': datetime.datetime(2019, 1, 1, tzinfo=tz.tzutc())} 32 | self.assertEqual(json.dumps(obj), 33 | '{"date": "2019-01-01T00:00:00+00:00"}') 34 | -------------------------------------------------------------------------------- /cloudkitty/utils/json.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Objectif Libre 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | # 15 | import datetime 16 | import decimal 17 | import functools 18 | import json 19 | 20 | 21 | class CloudkittyJSONEncoder(json.JSONEncoder): 22 | """Cloudkitty custom json encoder.""" 23 | 24 | def default(self, obj): 25 | if isinstance(obj, decimal.Decimal): 26 | return float(obj) 27 | elif isinstance(obj, datetime.datetime): 28 | return obj.isoformat() 29 | return super(CloudkittyJSONEncoder, self).default(obj) 30 | 31 | 32 | dumps = functools.partial(json.dumps, cls=CloudkittyJSONEncoder) 33 | loads = json.loads 34 | -------------------------------------------------------------------------------- /cloudkitty/version.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | # not use this file except in compliance with the License. You may obtain 4 | # a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | # License for the specific language governing permissions and limitations 12 | # under the License. 13 | 14 | 15 | import pbr.version 16 | 17 | version_info = pbr.version.VersionInfo('cloudkitty') 18 | -------------------------------------------------------------------------------- /cloudkitty/wsgi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/cloudkitty/wsgi/__init__.py -------------------------------------------------------------------------------- /cloudkitty/wsgi/api.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | """WSGI application entry-point for the CloudKitty API.""" 14 | 15 | import threading 16 | 17 | from cloudkitty.api import app 18 | 19 | application = None 20 | 21 | lock = threading.Lock() 22 | with lock: 23 | if application is None: 24 | application = app.build_wsgi_app() 25 | -------------------------------------------------------------------------------- /contrib/cloudkitty.logrotate: -------------------------------------------------------------------------------- 1 | /var/log/cloudkitty/*.log { 2 | weekly 3 | rotate 4 4 | missingok 5 | compress 6 | minsize 100k 7 | } 8 | -------------------------------------------------------------------------------- /contrib/init/cloudkitty-api.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=CloudKitty API Service 3 | After=syslog.target network.target 4 | 5 | [Service] 6 | Type=simple 7 | User=cloudkitty 8 | ExecStart=/usr/bin/cloudkitty-api --logfile /var/log/cloudkitty/api.log --config-file /etc/cloudkitty/cloudkitty.conf 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /contrib/init/cloudkitty-processor.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=CloudKitty processor Service 3 | After=syslog.target network.target 4 | 5 | [Service] 6 | Type=simple 7 | User=cloudkitty 8 | ExecStart=/usr/bin/cloudkitty-processor --logfile /var/log/cloudkitty/processor.log --config-file /etc/cloudkitty/cloudkitty.conf 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /devstack/README.rst: -------------------------------------------------------------------------------- 1 | ==================================== 2 | Installing CloudKitty using DevStack 3 | ==================================== 4 | 5 | The ``devstack`` directory contains the required files to integrate CloudKitty 6 | with DevStack. 7 | 8 | Configure DevStack to run CloudKitty 9 | ==================================== 10 | 11 | .. code-block:: bash 12 | 13 | $ DEVSTACK_DIR=/path/to/devstack 14 | 15 | 1. Enable Ceilometer: 16 | 17 | .. code-block:: bash 18 | 19 | $ cd ${DEVSTACK_DIR} 20 | $ cat >> local.conf << EOF 21 | [[local|localrc]] 22 | # ceilometer 23 | enable_plugin ceilometer https://opendev.org/openstack/ceilometer.git master 24 | EOF 25 | 26 | 2. Enable CloudKitty: 27 | 28 | .. code-block:: bash 29 | 30 | $ cd ${DEVSTACK_DIR} 31 | cat >> local.conf << EOF 32 | # cloudkitty 33 | enable_plugin cloudkitty https://opendev.org/openstack/cloudkitty master 34 | enable_service ck-api, ck-proc 35 | EOF 36 | 37 | 3. Set CloudKitty collector to gnocchi: 38 | 39 | .. code-block:: bash 40 | 41 | $ cd ${DEVSTACK_DIR} 42 | cat >> local.conf << EOF 43 | CLOUDKITTY_COLLECTOR=gnocchi 44 | EOF 45 | 46 | Run devstack as usual: 47 | 48 | .. code-block:: bash 49 | 50 | $ ./stack.sh 51 | 52 | See the documentation_ if you want more details about how to configure the 53 | devstack plugin. 54 | 55 | .. _documentation: https://docs.openstack.org/cloudkitty/latest/devstack.html 56 | -------------------------------------------------------------------------------- /devstack/apache-cloudkitty.template: -------------------------------------------------------------------------------- 1 | Listen %PORT% 2 | 3 | 4 | WSGIDaemonProcess cloudkitty-api processes=2 threads=10 user=%USER% display-name=%{GROUP} python-home=%VIRTUALENV% 5 | WSGIProcessGroup cloudkitty-api 6 | WSGIScriptAlias / %WSGIAPP% 7 | WSGIApplicationGroup %{GLOBAL} 8 | = 2.4> 9 | ErrorLogFormat "%{cu}t %M" 10 | 11 | ErrorLog /var/log/%APACHE_NAME%/cloudkitty.log 12 | CustomLog /var/log/%APACHE_NAME%/cloudkitty_access.log combined 13 | 14 | 15 | WSGISocketPrefix /var/run/%APACHE_NAME% 16 | -------------------------------------------------------------------------------- /devstack/upgrade/settings: -------------------------------------------------------------------------------- 1 | register_project_for_upgrade cloudkitty 2 | register_db_to_save cloudkitty 3 | -------------------------------------------------------------------------------- /devstack/upgrade/shutdown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | set -o errexit 6 | 7 | source $GRENADE_DIR/grenaderc 8 | source $GRENADE_DIR/functions 9 | 10 | source $BASE_DEVSTACK_DIR/functions 11 | source $BASE_DEVSTACK_DIR/stackrc # needed for status directory 12 | source $BASE_DEVSTACK_DIR/lib/tls 13 | source $BASE_DEVSTACK_DIR/lib/apache 14 | 15 | # Locate the cloudkitty plugin and get its functions 16 | CLOUDKITTY_DEVSTACK_DIR=$(dirname $(dirname $0)) 17 | source $CLOUDKITTY_DEVSTACK_DIR/plugin.sh 18 | 19 | set -o xtrace 20 | 21 | stop_cloudkitty 22 | 23 | # ensure everything is stopped 24 | 25 | SERVICES_DOWN="ck-api ck-proc" 26 | 27 | ensure_services_stopped $SERVICES_DOWN 28 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | openstackdocstheme>=2.2.6 # Apache-2.0 2 | sphinxcontrib-httpdomain>=1.7.0 # BSD 3 | sphinxcontrib-pecanwsme>=0.10.0 # Apache-2.0 4 | reno>=3.2.0 # Apache-2.0 5 | Pygments>=2.7.2 # BSD license 6 | os-api-ref>=2.1.0 # Apache-2.0 7 | -------------------------------------------------------------------------------- /doc/source/admin/cli/index.rst: -------------------------------------------------------------------------------- 1 | Command-Line Interface Reference 2 | ================================ 3 | 4 | Information on the commands available through Cloudkitty's Command Line 5 | Interface (CLI) can be found in this section. 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | cloudkitty-status 11 | -------------------------------------------------------------------------------- /doc/source/admin/configuration/index.rst: -------------------------------------------------------------------------------- 1 | ################### 2 | Configuration Guide 3 | ################### 4 | 5 | .. toctree:: 6 | :glob: 7 | 8 | configuration 9 | fetcher 10 | collector 11 | storage 12 | samples/cloudkitty-conf 13 | policy 14 | -------------------------------------------------------------------------------- /doc/source/admin/configuration/policy.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Policy configuration 3 | ==================== 4 | 5 | Configuration 6 | ~~~~~~~~~~~~~ 7 | 8 | .. warning:: 9 | 10 | JSON formatted policy file is deprecated since Cloudkitty 14.0.0 (Wallaby). 11 | This `oslopolicy-convert-json-to-yaml`__ tool will migrate your existing 12 | JSON-formatted policy file to YAML in a backward-compatible way. 13 | 14 | .. __: https://docs.openstack.org/oslo.policy/latest/cli/oslopolicy-convert-json-to-yaml.html 15 | 16 | The following is an overview of all available policies in Cloudkitty. 17 | For a sample configuration file, refer to :doc:`samples/policy-yaml`. 18 | 19 | .. show-policy:: 20 | :config-file: ../../etc/oslo-policy-generator/cloudkitty.conf 21 | -------------------------------------------------------------------------------- /doc/source/admin/configuration/samples/cloudkitty-conf.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | cloudkitty.conf reference 3 | ========================= 4 | 5 | .. literalinclude:: ../../../_static/cloudkitty.conf.sample 6 | -------------------------------------------------------------------------------- /doc/source/admin/configuration/samples/policy-yaml.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | =========== 4 | policy.yaml 5 | =========== 6 | 7 | Use the ``policy.yaml`` file to define additional access controls that apply to 8 | the Rating service: 9 | 10 | .. literalinclude:: ../../../_static/cloudkitty.policy.yaml.sample 11 | -------------------------------------------------------------------------------- /doc/source/admin/devstack.rst: -------------------------------------------------------------------------------- 1 | DevStack installation 2 | ===================== 3 | 4 | Add the following lines in your ``local.conf`` file to enable CloudKitty, 5 | Ceilometer and Gnocchi. By default, the fetcher will be ``gnocchi`` 6 | (configurable via the ``CLOUDKITTY_FETCHER`` variable), the collector will be 7 | ``gnocchi`` (configurable via the ``CLOUDKITTY_COLLECTOR`` variable), and the 8 | storage backend will be ``influxdb`` (configurable via the 9 | ``CLOUDKITTY_STORAGE_BACKEND`` and ``CLOUDKITTY_STORAGE_VERSION`` variables). 10 | 11 | .. code-block:: ini 12 | 13 | [[local|localrc]] 14 | # ceilometer 15 | enable_plugin ceilometer https://opendev.org/openstack/ceilometer.git master 16 | 17 | # cloudkitty 18 | enable_plugin cloudkitty https://opendev.org/openstack/cloudkitty.git master 19 | enable_service ck-api,ck-proc 20 | 21 | Then start devstack: 22 | 23 | .. code-block:: console 24 | 25 | ./stack.sh 26 | -------------------------------------------------------------------------------- /doc/source/admin/index.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Administration Guide 3 | ==================== 4 | 5 | .. toctree:: 6 | :glob: 7 | :maxdepth: 2 8 | 9 | architecture 10 | devstack 11 | install/index 12 | configuration/index 13 | cli/index 14 | -------------------------------------------------------------------------------- /doc/source/admin/install/index.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | Installation Guide 3 | ================== 4 | 5 | .. toctree:: 6 | :glob: 7 | 8 | install-source 9 | install-ubuntu 10 | install-rdo 11 | mod_wsgi 12 | -------------------------------------------------------------------------------- /doc/source/admin/install/install-rdo.rst: -------------------------------------------------------------------------------- 1 | Install from package (RDO For RHEL/CentOS 7) 2 | ============================================ 3 | 4 | Packages for RHEL/CentOS 7 are available starting from the Mitaka release. 5 | 6 | #. Install the RDO repositories for your release:: 7 | 8 | yum install centos-release-openstack-RELEASE 9 | # RELEASE can be any supported release name like rocky 10 | 11 | #. Install the packages:: 12 | 13 | yum install openstack-cloudkitty-api openstack-cloudkitty-processor openstack-cloudkitty-ui 14 | -------------------------------------------------------------------------------- /doc/source/admin/install/install-ubuntu.rst: -------------------------------------------------------------------------------- 1 | Install from packages for Ubuntu (16.04) 2 | ======================================== 3 | 4 | Packages for Ubuntu 16.04 are available starting from the Newton release. 5 | 6 | #. Enable the OpenStack repository for the Newton or Ocata release:: 7 | 8 | apt install software-properties-common 9 | add-apt-repository ppa:objectif-libre/cloudkitty # Newton 10 | add-apt-repository ppa:objectif-libre/cloudkitty-ocata # Ocata 11 | 12 | #. Upgrade the packages on your host:: 13 | 14 | apt update && apt dist-upgrade 15 | 16 | #. Install the packages:: 17 | 18 | apt-get install cloudkitty-api cloudkitty-processor cloudkitty-dashboard 19 | -------------------------------------------------------------------------------- /doc/source/api-reference: -------------------------------------------------------------------------------- 1 | ../../api-ref/source -------------------------------------------------------------------------------- /doc/source/developer/api/index.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | API 3 | ===== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | tutorial 9 | utils 10 | -------------------------------------------------------------------------------- /doc/source/developer/api/utils.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Utils reference 3 | ================= 4 | 5 | .. note:: 6 | 7 | This section of the documentation is a reference of the 8 | ``cloudkitty.api.v2.utils`` module. It is generated from the docstrings 9 | of the functions. Please report any documentation bug you encounter on this 10 | page 11 | 12 | .. automodule:: cloudkitty.api.v2.utils 13 | :members: SingleQueryParam, add_input_schema, paginated, add_output_schema, do_init 14 | -------------------------------------------------------------------------------- /doc/source/developer/index.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | Developer Documentation 3 | ======================= 4 | 5 | .. toctree:: 6 | :glob: 7 | 8 | roadmap 9 | fetcher 10 | collector 11 | storage 12 | api/index 13 | -------------------------------------------------------------------------------- /doc/source/developer/storage.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Storage backend (v2) 3 | ==================== 4 | 5 | .. warning:: This backend is considered unstable and should be used for 6 | upstream development only. 7 | 8 | In order to implement a storage backend for cloudkitty, you'll have to 9 | implement the following abstract class: 10 | 11 | .. autoclass:: cloudkitty.storage.v2.BaseStorage 12 | :members: 13 | 14 | You'll then need to register an entrypoint corresponding to your storage 15 | backend in the ``cloudkitty.storage.v2.backends`` section of the ``setup.cfg`` 16 | file. 17 | -------------------------------------------------------------------------------- /doc/source/images/cloudkitty-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/doc/source/images/cloudkitty-logo.png -------------------------------------------------------------------------------- /doc/source/images/cloudkitty_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/doc/source/images/cloudkitty_architecture.png -------------------------------------------------------------------------------- /doc/source/images/cloudkitty_modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/doc/source/images/cloudkitty_modules.png -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | ====================================== 2 | Welcome to CloudKitty's documentation! 3 | ====================================== 4 | 5 | .. 6 | NOTE: This is the index for the rst version only. If you update this file 7 | please update pdf-index.rst accordingly 8 | 9 | .. include:: common-index.rst 10 | 11 | Documentation contents 12 | ====================== 13 | 14 | .. list-table:: 15 | :header-rows: 1 16 | 17 | * - Documentation type 18 | - Table of contents 19 | 20 | * - **Concepts** 21 | - .. toctree:: 22 | :maxdepth: 3 23 | 24 | concepts/index 25 | 26 | * - **End User** 27 | - .. toctree:: 28 | :maxdepth: 3 29 | 30 | user/index 31 | 32 | * - **Admin / Operator** 33 | - .. toctree:: 34 | :maxdepth: 2 35 | 36 | admin/index 37 | 38 | * - **Developer** 39 | - .. toctree:: 40 | :maxdepth: 2 41 | 42 | developer/index 43 | 44 | * - **Contributors** 45 | 46 | - .. toctree:: 47 | :maxdepth: 2 48 | 49 | contributor/contributing 50 | 51 | * - **API Reference** 52 | - .. toctree:: 53 | :maxdepth: 2 54 | 55 | api-reference/index 56 | -------------------------------------------------------------------------------- /doc/source/pdf-index.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | ====================================== 4 | Welcome to CloudKitty's documentation! 5 | ====================================== 6 | 7 | .. include:: common-index.rst 8 | 9 | Documentation contents 10 | ====================== 11 | 12 | End User 13 | -------- 14 | 15 | .. toctree:: 16 | :maxdepth: 3 17 | 18 | user/index 19 | 20 | Admin / Operator 21 | ---------------- 22 | 23 | .. toctree:: 24 | :maxdepth: 2 25 | 26 | admin/index 27 | 28 | Developer 29 | --------- 30 | 31 | .. toctree:: 32 | :maxdepth: 2 33 | 34 | developer/index 35 | 36 | Contributors 37 | ------------ 38 | 39 | .. toctree:: 40 | :maxdepth: 2 41 | 42 | contributor/contributing 43 | 44 | API Reference 45 | ------------- 46 | 47 | .. toctree:: 48 | :maxdepth: 2 49 | 50 | api-reference/index 51 | -------------------------------------------------------------------------------- /doc/source/user/index.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | User documentation 3 | ================== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | rating/index 9 | -------------------------------------------------------------------------------- /doc/source/user/rating/graph/hashmap.dot: -------------------------------------------------------------------------------- 1 | digraph "Hashmap's data structure" { 2 | 3 | label="HashMap module data structure"; 4 | compound=true; 5 | 6 | compute; 7 | network [label="network.floating_ip"]; 8 | volume; 9 | 10 | subgraph cluster_0 { 11 | label="services"; 12 | style=dashed; 13 | {rank=same; compute -> network -> volume [style=invis];} 14 | } 15 | 16 | compute -> flavor; 17 | 18 | subgraph cluster_1 { 19 | label="fields:\nAssociate to metadata"; 20 | style=dashed; 21 | flavor; 22 | } 23 | 24 | // Mappings 25 | micro [label="value=m1.micro\ntype=flat\ncost=0.1"]; 26 | tiny [label="value=m1.tiny\ntype=flat\ncost=0.2"]; 27 | small [label="value=m1.small\ntype=flat\ncost=0.4"]; 28 | 29 | floating [label="\ntype=flat\ncost=0.5"]; 30 | 31 | // Thresholds 32 | 1024 [label="level=1024\ntype=flat\ncost=0.1"]; 33 | 10240 [label="level=10240\ntype=flat\ncost=0.2"]; 34 | 35 | subgraph cluster_2 { 36 | label="mappings"; 37 | style=dashed; 38 | {rank=same; micro -> tiny -> small -> floating [style=invis];} 39 | } 40 | 41 | subgraph cluster_3 { 42 | label="thresholds"; 43 | style=dashed; 44 | {rank=same; 1024 -> 10240 [style=invis];} 45 | } 46 | 47 | flavor -> micro; 48 | flavor -> tiny; 49 | flavor -> small; 50 | network -> floating; 51 | volume -> 1024; 52 | volume -> 10240; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /etc/apache2/cloudkitty: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 New Dream Network, LLC (DreamHost) 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | # not use this file except in compliance with the License. You may obtain 5 | # a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | # License for the specific language governing permissions and limitations 13 | # under the License. 14 | 15 | # This is an example Apache2 configuration file for using the 16 | # cloudkitty API through mod_wsgi. 17 | 18 | # Note: If you are using a Debian-based system then the paths 19 | # "/var/log/httpd" and "/var/run/httpd" will use "apache2" instead 20 | # of "httpd". 21 | # 22 | # The number of processes and threads is an example only and should 23 | # be adjusted according to local requirements. 24 | 25 | Listen 8889 26 | 27 | 28 | WSGIDaemonProcess cloudkitty-api processes=2 threads=10 user=SOMEUSER display-name=%{GROUP} 29 | WSGIProcessGroup cloudkitty-api 30 | WSGIScriptAlias / /var/www/cloudkitty/app.wsgi 31 | WSGIApplicationGroup %{GLOBAL} 32 | = 2.4> 33 | ErrorLogFormat "%{cu}t %M" 34 | 35 | ErrorLog /var/log/httpd/cloudkitty_error.log 36 | CustomLog /var/log/httpd/cloudkitty_access.log combined 37 | 38 | 39 | WSGISocketPrefix /var/run/httpd 40 | -------------------------------------------------------------------------------- /etc/cloudkitty/api_paste.ini: -------------------------------------------------------------------------------- 1 | [pipeline:cloudkitty+noauth] 2 | pipeline = cors healthcheck http_proxy_to_wsgi request_id ck_api 3 | 4 | [pipeline:cloudkitty+keystone] 5 | pipeline = cors healthcheck http_proxy_to_wsgi request_id authtoken ck_api 6 | 7 | [app:ck_api] 8 | paste.app_factory = cloudkitty.api.app:app_factory 9 | 10 | [filter:authtoken] 11 | acl_public_routes = /, /v1, /v2, /healthcheck 12 | paste.filter_factory = cloudkitty.api.middleware:AuthTokenMiddleware.factory 13 | 14 | [filter:request_id] 15 | paste.filter_factory = oslo_middleware:RequestId.factory 16 | 17 | [filter:cors] 18 | paste.filter_factory = oslo_middleware.cors:filter_factory 19 | oslo_config_project = cloudkitty 20 | 21 | [filter:healthcheck] 22 | paste.filter_factory = oslo_middleware:Healthcheck.factory 23 | backends = disable_by_file 24 | disable_by_file_path = /etc/cloudkitty/healthcheck_disable 25 | 26 | [filter:http_proxy_to_wsgi] 27 | paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory 28 | oslo_config_project = cloudkitty 29 | -------------------------------------------------------------------------------- /etc/oslo-config-generator/cloudkitty.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | output_file = etc/cloudkitty/cloudkitty.conf.sample 3 | namespace = cloudkitty.common.config 4 | namespace = oslo.concurrency 5 | namespace = oslo.db 6 | namespace = oslo.log 7 | namespace = oslo.messaging 8 | namespace = oslo.middleware.http_proxy_to_wsgi 9 | namespace = oslo.middleware.cors 10 | namespace = oslo.policy 11 | namespace = keystonemiddleware.auth_token -------------------------------------------------------------------------------- /etc/oslo-policy-generator/cloudkitty.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | output_file = etc/cloudkitty/policy.yaml.sample 3 | namespace = cloudkitty 4 | -------------------------------------------------------------------------------- /releasenotes/notes/add-dataframe-datapoint-objects-a5a4ac3db5289cb6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Data frames/points are now internally represented as objects rather than 5 | dicts. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/add-dataframes-v2-api-endpoint-601825c344ba0e2d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Added a v2 API endpoint allowing to push dataframes into the CloudKitty 5 | storage. This endpoint is available via a ``POST`` request on 6 | ``/v2/dataframes``. Admin privileges are required to use this endpoint. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/add-description-option-to-rating-671430ac73c0315b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add description option to a rating metric definition, which 5 | can be used to create custom reports in the ``summary`` GET API. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/add-gnocchi-fetcher-b8a6e2ea49fcfec5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A fetcher for gnocchi has been added, allowing dynamic scope/project 5 | discovery. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/add-influx-storage-backend-3ace5b451e789e64.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | An InfluxDB v2 storage backend has been added. It will become the default 5 | backend of the v2 storage interface. 6 | 7 | The v1 storage interface will be deprecated in a future release. At that 8 | point, documentation about how to upgrade the storage backend will be made 9 | available, along with some helpers. 10 | -------------------------------------------------------------------------------- /releasenotes/notes/add-new-validation-to-not-allow-reprocessing-with-incompatible-timewindows-5a44802f20bce4f2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Add a validation to not allow users to schedule reprocesses via 5 | ``POST`` request on ``/v2/task/reprocesses`` using a time window not 6 | compatible with the configured ``period`` in the collector. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/add-opensearch-as-v2-storage-backend-ff4080d6d32d8a2a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | OpenSearch has been added as an alternative v2 storage backend. It is a 5 | duplicate of the ElasticSearch backend, with the naming changed where 6 | appropriate. This change is in support of the deprecation of ElasticSearch 7 | as a backend. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/add-opensearch-elasticsearch-datastreams-support-28b7c1ce700d33c0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds support to the OpenSearch and Elasticsearch v2 storage backends for 5 | using datastreams, rather than indices. These are useful when a cluster 6 | has multiple storage types, as data can be rotated from hot to cold storage 7 | when not in active use. The option ``use_datastream`` can be set under 8 | either ``[storage_elasticsearch]`` or ``[storage_opensearch]``. 9 | -------------------------------------------------------------------------------- /releasenotes/notes/add-prometheus-fetcher-be6082f70f279f0e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A Prometheus scope fetcher has been added in order to dynamically discover 5 | scopes from a Prometheus service using a user defined metric and a scope 6 | attribute. 7 | It can also filter out the response from Prometheus using metadata filters 8 | to have a more fine-grained control over scope discovery. 9 | It features HTTP basic auth capabilities and HTTPS configuration options 10 | similar to Prometheus collector. 11 | -------------------------------------------------------------------------------- /releasenotes/notes/add-re-aggregation-method-option-gnocchi-collector-249917a14c4fc721.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | It is now possible to differentiate the aggregation method from the 5 | aggregate type in the gnocchi collector, in case the retrieved aggregates 6 | need to be re-aggregated. This has been introduced with the 7 | ``re_aggregation_method`` option. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/add-scope-key-58135c2a5c6dae68.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The "scope_key" option is now defined in cloudkitty.conf and has been 5 | removed from the cloudkitty and monasca collector's extra_args 6 | -------------------------------------------------------------------------------- /releasenotes/notes/add-storage-state-v2-api-endpoint-45a29d0b44e177b8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Added a v2 API endpoint allowing to retrieve the state of several scopes. 5 | This endpoint is available via a ``GET`` request on ``/v2/scope`` and 6 | supports filters. Admin privileges are required to use this endpoint. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/add-storage-state-v2-api-endpoint-492d7092e85ed7b1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Added a v2 API endpoint allowing to reset the state of several scopes. 5 | This endpoint is available via a ``PUT`` request on ``/v2/scope`` and 6 | supports filters. Admin privileges are required to use this endpoint. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/add-support-to-influxdb-v2-storage-backend-f94df79f9e5276a8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add support to Influx v2 database as storage backend. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/add-tempest-plugin-3584e1918f344fb2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | A tempest plugin has been created for CloudKitty, and it is used 5 | for gate tests. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/add-v2-storage-driver-for-elasticsearch-ec41cbb7849e82d3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A v2 storage driver for Elasticsearch has been added. It is marked as 5 | ``EXPERIMENTAL`` for now. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/add_warning_regarding_gnocchi_version-99d5213c35950e39.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | CloudKitty will always use the correct metadata for the 5 | processing and reprocessing jobs. This means, we always use 6 | the metadata for the timestamp that we are collecting at 7 | Gnocchi backend.This is achieved with the use of 8 | ``use_history=true`` in Gnocchi, which was released under 9 | `version 4.5.0 `__. 10 | Before that release, the ``aggregates`` API would only return 11 | the latest metadata for the resource of the metric being handled. 12 | Therefore, for CloudKitty processing and reprocessing, we would 13 | always have the possibility of using the wrong attribute version 14 | to rate the computing resources. -------------------------------------------------------------------------------- /releasenotes/notes/added-forced-granularity-gnocchi-d52e988194197248.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A ``force_granularity`` option has been added to the gnocchi collector's 5 | ``extra_args``. It allows to force a granularity to use when doing metric 6 | aggregations. If not specified or set to 0, the lowest available 7 | granularity will be used. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/added-v2-api-1ef829355c2feea4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A v2 API has been bootstrapped. It is compatible with the v2 storage and 5 | will be the base for all upcoming API endpoints. It is marked as 6 | ``EXPERIMENTAL`` for now. 7 | 8 | upgrade: 9 | - | 10 | The v1 API is now marked as ``CURRENT``. The API root is now built with 11 | Flask instead of pecan 12 | -------------------------------------------------------------------------------- /releasenotes/notes/admin-or-owner-policy-c666346da4405d13.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix the definition of the ``admin_or_owner`` policy expression, which was 5 | preventing even admins from using the ``get_summary`` endpoint with 6 | ``all_tenants=True`` or ``tenant_id`` parameters. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/allow-multiple-ranting-types-for-same-metric-in-gnocchi-1011ba2d5d36c073.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Extends the Gnocchi collector to allow operators 5 | to create multiple rating types for the same metric in Gnocchi. 6 | The Gnocchi collector is now accepting a list of configs for each 7 | metric entry, instead of accepting only one configuration. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/batch-delete-reprocessing-d46df15b078a42a5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Optimized the reprocessing workflow to execute batch cleaning 5 | of data in the storage backend of CloudKitty. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/change-metrology-organization-1e11900eb30780cc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Cloudkitty now bases itself on metrics and no more on services for data 5 | valorization. The metrics.yml file information has been reorganized 6 | accordingly. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/check-duplicates-metadata-groupby-d5ee99941bb483fd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | When the config is loaded, there is now a verification for duplicates 5 | between ``groupby`` and ``metadata`` for each metric. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/collector-monasca-f0871406513ff22c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A collector for Monasca has been added. It works with telemetry metrics 5 | published to Monasca by Ceilometer agent through Ceilosca. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/create-use_all_entries_for_timespan-option-for-gnocchi-collector-39d29603b1f554e1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Create the option 'use_all_resource_revisions' for Gnocchi collector. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/custom-gnocchi-query-a391f5e83d55d771.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Enable using custom queries with the Gnocchi collector. This option enables 5 | operators to take full advantage of the operations that are available on 6 | Gnocchi such as any arithmetic operation, logical operation and many 7 | others. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/dataframes-get-v2-policy-check-6070fc047b2e1496.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes policy check when getting dataframes using the v2 API, causing the 5 | operation to fail when run by a non-admin user. See story 2009879 6 | `_ for more details. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/default-to-v2-storage-a5ecac7e73dafa6d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | CloudKitty's storage interface defaults to v2 from now on. v1 will be 5 | deprecated in a future release. Documentation about how to upgrade the 6 | storage backend along with some tools will be available at that point. New 7 | deployments should use the v2 storage interface. 8 | 9 | The default v2 backend is ``influxdb``. In order to keep using 10 | ``sqlalchemy``, specify "version = 1" and "backend = sqlalchemy" in the 11 | ``[storage]`` section of the configuration. 12 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-ceilometer-collector-6d8f72c84b95662b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The ceilometer collector has been deprecated. Gnocchi should be used by 5 | default. The collector will be removed during the Rocky development cycle. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-collector-mappings-5a69b31c8037fc01.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Collector mappings have been deprecated and should not be used anymore. They 5 | will be removed during OpenStack's S cycle. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-elasticsearch-for-opensearch-a338965edff23509.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Support for using Elasticsearch as a storage backend is being deprecated in 5 | the Antelope release in favour of OpenSearch. We will try to keep 6 | CloudKitty compatible with both solutions. However, we will only test with 7 | OpenSearch. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-get-state-2932a4e6a74295ce.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The ``storage_state.get_state`` method has been removed in favor of the 5 | ``storage_state.get_last_processed_timestamp`` method. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-info-services-endpoints-0c5018cb08a30d5f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The /v1/info/services and /v1/info/services/ endpoints have 5 | been deprecated. The /v1/info/metrics and /v1/info/metrics/ 6 | endpoints should be used instead. 7 | The whole /v1/info API part is currently being reworked, and some 8 | endpoints will also be deprecated and deleted in the future. 9 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-json-formatted-policy-file-01ceb65712fd0a39.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The default value of ``[oslo_policy] policy_file`` config option has 5 | been changed from ``policy.json`` to ``policy.yaml``. 6 | Operators who are utilizing customized or previously generated 7 | static policy JSON files (which are not needed by default), should 8 | generate new policy files or convert them in YAML format. Use the 9 | `oslopolicy-convert-json-to-yaml 10 | `_ 11 | tool to convert a JSON to YAML formatted policy file in 12 | backward compatible way. 13 | deprecations: 14 | - | 15 | Use of JSON policy files was deprecated by the ``oslo.policy`` library 16 | during the Victoria development cycle. As a result, this deprecation is 17 | being noted in the Wallaby cycle with an anticipated future removal of support 18 | by ``oslo.policy``. As such operators will need to convert to YAML policy 19 | files. Please see the upgrade notes for details on migration of any 20 | custom policy files. 21 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-monasca-5526b823b227c6ef.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Support for using Monasca as a fetcher and collector is being deprecated 5 | in the Antelope release. The complete removal is going to take place 6 | in B release. -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-report-total-62544dce42bb19a6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The /v1/report/total route has been deprecated. /v1/report/summary should 5 | be used instead. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate-set-state-3eea30afd43647ab.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The ``storage_state.set_state`` method has been removed in favor of the 5 | ``storage_state.set_last_processed_timestamp`` method. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/deprecate_section_name-9f1ce1f84d09adf8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The 'gnocchi_collector', 'hybrid_storage', 'keystone_fetcher' and 'source_fetcher' group names have been deprecated and will be removed 5 | in the future. Use the 'collector_gnocchi', 'storage_hybrid', 'fetcher_keystone' and 'fetcher_source' group names instead. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/drop-py-2-7-fcf8c0613a7bffa8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Python 2.7 support has been dropped. Last release of Cloudkitty 5 | to support python 2.7 is OpenStack Train. The minimum version of Python now 6 | supported by Cloudkitty is Python 3.6. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/drop-python38-5524bd07bca35743.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Python 3.8 support has been removed. The minimum python version 5 | supported is 3.9. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fetch-metrics-concurrently-dffffe346bd4900e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Metrics are now fetched concurrently with ``eventlet`` instead of one 5 | after another by the orchestrator, leading to a consequent performance 6 | improvement. The maximum number of greenthreads to use can be specified 7 | through the ``max_greenthreads`` option of the ``orchestrator`` section. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-begin-end-validation-v2-summary-52401fb47ef9b5d6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | A validation issue causing the ``GET /v2/summary`` endpoint to 5 | systematically return a 400 error if any of the ``begin`` or ``end`` 6 | parameters was specified has been fixed. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-csv-usage-end-7bcf4cb5effc4461.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The value of the UsageEnd field in CSV reports has been fixed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-dataframe-filtering-282cae643457bb8b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | security: 3 | - | 4 | Data filtering on the ``GET /v1/dataframes`` and ``GET /v2/dataframes`` 5 | endpoints has been fixed. It was previously possible for users to retrieve 6 | data from other scopes through these endpoints. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-gnocchi-metadata-collection-74665e862483a383.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Metadata collection failures in the gnocchi collector caused by resources 5 | having measures in periods where they are supposed to be deleted have 6 | been fixed. Metadata is now collected over a three-period window in the 7 | gnocchi collector. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-hashmap-mapping-value-match-56570510203ce3e5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | HashMap module field mapping matching has been fixed: Field mapping values 5 | are always stored as strings. However, metadatas to match can be floats or 6 | integers (eg vcpus or ram). Given that mappings were matched with ``==`` 7 | until now, integers or float metadatas did never match. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-lock-release-74d112c8599c9a59.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | cloudkitty-processor crashes which happened when using distributed 5 | tooz locks have been fixed. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-opensearch-report-344508dd4e3d0ccc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix some API report requests that were returning HTTP 500 errors when using 5 | the ``opensearch`` storage backend. This fixes failures to load the Horizon 6 | ``Rating`` panel. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-processor-killed-on-metric-collect-error-824897dc2252b504.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Changes the metric collector exception handling to raise an exception 5 | instead of killing the processor when an error happens in the metric 6 | collect, so the problematic scope will be skipped till next 7 | collection and the other scopes will be processed normally. -------------------------------------------------------------------------------- /releasenotes/notes/fix-project-id-none-d40df33fc7b7db23.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The 500 errors happening on some API endpoints when keystone authentication 5 | is enabled and the request context bears no ``project_id`` have been fixed. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-quote-v1-api-7282f01b596f0f3b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes the quote API method. See story 2009022 5 | `_ for more details. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-rating-rules-value-precision-40d1054f8ab494c3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Allow rating rules that have more than 2 digits in integer part. 5 | 6 | Currently, CloudKitty only allows creating rating rules as 7 | ``99.999999999999999999999999``. Therefore, for prices equal to or higher 8 | than 100, we would not be able to use them. This patch will enable 9 | operators to use any value between ``0`` and ``999999999999`` (in the 10 | integer part of the number), which will provide more flexibility. 11 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-response-total-for-elastic-search-a3a9244380ed046f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix response format ``total`` for v2 dataframes API. The response for v2 5 | dataframes is ``{"total": 3}``. However, for Elasticsearch search response, 6 | the ``"hits.total"`` in the response body is ``{"value": 3, "relation": 7 | "eq"}``, which does not match the API response schema. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-scope-state-reset-filters-0a1f5ea503bd32a1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | An issue causing data not to be deleted from the storage backend when 5 | resetting a scope's state through the API has been fixed. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-url-building-do-init-7c952afaf6d909cd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | It is not required anymore to prefix the url of a resource with a ``/`` 5 | when using ``cloudkitty.api.v2.utils.do_init``. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-v1-storage-groupby-e865d1315bd390cb.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | ``CompileError: Can't resolve label reference for ORDER BY / GROUP BY.`` 5 | errors that were sometimes raised by SQLAlchemy when using the v1 storage 6 | backend and grouping on ``tenant_id`` and ``res_type`` have been fixed. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/fix-v1-summary-and-total-with-es-os-backend-9540741b80819672.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed a bug where ``openstack rating summary get -s `` and 5 | ``openstack rating total get -s `` would fail when using the 6 | Elasticsearch or OpenSearch storage backends. See `story 2011128 7 | `_ for more details. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/fix_py_scripts-fd9ab52c92263844.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix failure to process rating using the PyScripts rating module. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/force-project-id-monasca-collector-cb30ed073d36d40e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | It is now possible to force a project_id to retrieve a specific metric 5 | from it with the monasca collector. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/get-dataframes-v2-api-endpoint-3a4625c6008a5fca.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Added a v2 API endpoint allowing to retrieve dataframes from 5 | the CloudKitty storage. This endpoint is available via a ``GET`` 6 | request on ``/v2/dataframes``. Being the owner of the scope or 7 | having admin privileges are required to use this endpoint. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/harden-dataframes-policy-7786286525e52dfb.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | security: 3 | - | 4 | The default policy for the ``/v1/storage/dataframes`` endpoint has been 5 | changed from ``unprotected`` (accessible by any unauthenticated used) to 6 | ``admin_or_owner`` (accessible only by admins or members of the project). 7 | -------------------------------------------------------------------------------- /releasenotes/notes/ignore_disabled_tenants-and-ignore_rating_role-dfe542a0cafd412e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Two new options ``ignore_disabled_tenants`` and ``ignore_rating_role`` 5 | were added in the ``fetcher_keystone`` section. ``ignore_disabled_tenants`` 6 | skips disabled tenants when doing the rating. ``ignore_rating_role`` 7 | rates everyone, without reading the rating role for each project, which 8 | can be resource consuming. 9 | -------------------------------------------------------------------------------- /releasenotes/notes/improve-metrics-configuration-271102366f8e6fe7.yaml: -------------------------------------------------------------------------------- 1 | features: 2 | - | 3 | The format of the 'metrics.yml' configuration file has been improved, 4 | and will be stable. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/introduce-active-status-field-cdfecd27c2bb9a42.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add active status option in the storage state table and API. -------------------------------------------------------------------------------- /releasenotes/notes/introduce-bandit-security-linter-592faa26f957a3dd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | security: 3 | - | 4 | Introduce bandit security checks and fix potential security issues detected 5 | by bandit linter. Remove unused option where host_ip was a binding to all 6 | interfaces. Using of insecure hash function, switch from sha1 to sha512. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/introduce-cloudkitty.utils-792b9080537405bf.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Cloudkitty's ``*_utils`` modules have been grouped into the 5 | new ``cloudkitty.utils`` module. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/introduce-reprocessing-api-822db3edc256507a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Introduce the reprocessing schedule API, which allows operators to 5 | schedule reprocessing tasks to reprocess scopes in given timeframes. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/make-cloudkitty-timezone-aware-2b65edc42e913d6c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | CloudKitty is now aware of timezones, and the API supports iso8601 5 | formatted timestamps. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/make-gnocchi-http-max-connections-pool-configurable-52c9f6617466ea30.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds a new configuration ``http_pool_maxsize`` that defines the maximum 5 | size of Gnocchi's fetcher and collector HTTP connection pools. 6 | 7 | The default value of this new configuration is defined by the ``requests`` 8 | library in the ``requests.adapters.DEFAULT_POOLSIZE`` global variable. 9 | -------------------------------------------------------------------------------- /releasenotes/notes/make-processor-run-several-workers-02597b0f77687ef3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The processor is now able to run several parallel workers. By default, one 5 | worker is spawned for each available CPU. Workers can be limited through the 6 | ``max_workers`` option of the ``orchestrator`` section. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/map-mutator-632b8629c0482e94.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds a ``MAP`` mutator to map arbitrary values to new values. This is 5 | useful with metrics reporting resource status as their value, but multiple 6 | statuses are billable. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/monasca-fetcher-2ea866f873ab5336.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds a Monasca fetcher retrieving scopes from Monasca dimensions. See the 5 | `fetcher documentation 6 | `__ 7 | for more details. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/move-api-docs-to-api-ref-be71b864e557110e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | API reference/docs have been moved to ``api-ref/source/`` and the original 5 | path now contains a symlink to this directory. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/multiple_values_filter_summary_get_v2_api-1110373a900fad0d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add support for multiple value filters in the summary GET V2 API. -------------------------------------------------------------------------------- /releasenotes/notes/new-forcegranularity-default-b8aaf7d7823aef3b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | A new directive ``force_granularity: 300`` was added to the default 5 | ``metrics.yml`` file for ``cpu`` and ``volume.size``, to match the defaults 6 | of ceilometer and avoid logging errors in ``cloudkitty-processor`` with the 7 | default setup. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/notnumbool-mutator-ab056e86f2bc843d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The new "NOTNUMBOOL" mutator has been added. This mutator is, essentially, 5 | an opposite of the "NUMBOOL" mutator as it returns 1.0 when quantity is 0 6 | and 0.0 otherwise. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/optimize_gnochi-fetcher-41b502e7ca242cb1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | issues: 3 | - | 4 | Optimize Gnocchi fetcher to avoid consuming too much RAM when CloudKitty 5 | runs in cloud environments with hundreds of thousands of resources. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/optimize_gnochi-fetcher-runtime-3604026816.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | issues: 3 | - | 4 | Optimize Gnocchi fetcher runtime to avoid taking too long to load scopes 5 | when CloudKitty runs in cloud environments with hundreds of thousands of 6 | resources. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/optimizing-sql-queries-939f48fff1805389.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Improve performance of SQL queries filtering on date fields. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/patch-use-all-revision-0325eeb0f7871c35.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes accounting of quantity values when ``use_all_resource_revisions`` 5 | option is used in the Gnocchi collector. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/post-api-create-scope-739098144706a1cf.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Introduce an API to create scopes with a POST request. This is useful for 5 | operators to register scopes before they are created as resources in the 6 | collected backend and disable their processing without waiting for the 7 | scopes to be discovered by CloudKitty. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/prometheus-collector-empty-meta-12402d8f0254c011.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | issues: 3 | - | 4 | Fixes exceptions in Prometheus collector when metadata defined in 5 | ``metrics.yml`` is not present on metrics retrieved from Prometheus. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/prometheus-collector-mutate-8da4748b4d1f0b59.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | issues: 3 | - | 4 | The Prometheus collector now applies quantity mutation on metrics. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/prometheus-custom-query-ab2dc00e97b14be2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds support for specifying optional prefix and/or suffix to add to 5 | Prometheus queries. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/prometheus-error-8eab9f1793c2280c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Raises a ``CollectError`` exception with error details when a Prometheus 5 | query returns an error status. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/raise-exception-on-invalid-config-0aece71caa0947fa.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The ``cloudkitty.utils.load_conf`` function does now raise an exception in 5 | case the ``metrics.yml`` file can't be read or has an invalid format. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/rating-modules-v2-7e4e7a3c5fa96331.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Add rating modules GET endpoints to v2 API. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/refactor-storage-e5453296e477e594.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The storage system is being refactored. 5 | A hybrid storage backend has been added. This backend handles states 6 | via SQLAlchemy and pure storage via another storage backend. Once 7 | this new storage is considered stable, it will become the default storage. 8 | This will ease the creation of storage backends (no more state handling). 9 | 10 | deprecations: 11 | - | 12 | All storage backends except sqlalchemy and the new hybrid storage 13 | have been deprecated. 14 | -------------------------------------------------------------------------------- /releasenotes/notes/register-keystone-opts-with-keystoneauth-functions-monasca-collector-1a539fc8c23e9dbc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Keystone authentication options are now registered with ``keystoneauth1`` in 5 | the monasca collector helper functions, which allows to use the 6 | ``auth_section`` option even when using the ``source`` fetcher. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-ceilometer-collector-b310bf6c5736c88a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The ceilometer collector and transformer have been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-dateutil-tz-utc-usage-1350c00be3fadde7.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The use of ``tz.UTC`` from the ``dateutil`` package was removed, bringing 5 | compatibility with the version available in RHEL and CentOS 8. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-deprecated-api-endpoints-26606e322b8a225e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The deprecated 'Billing' API endpoint has been removed, and its code has 5 | been deleted from the CloudKitty repository. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-deprecated-config-section-names-9a125b1af0932c08.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Section names that had been deprecated in cloudkitty 9.0.0 have been removed 5 | in 11.0.0. These include ``gnocchi_collector``, ``tenant_fetcher``, 6 | ``keystone_fetcher``, ``source_fetcher`` and ``hybrid_storage``. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-deprecated-storage-backends-158fbec099846ec7.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The gnocchi and gnocchihybrid storage backends have been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-fake-fetcher-9c264520a3cec9d0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The fake fetcher has been removed from CloudKitty's codebase. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-fake-meta-collectors-5ed94ab1165e9661.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The fake and meta collectors have been removed from CloudKitty's codebase. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-gnocchi-transformer-1dad750b9ba6c2e4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The gnocchi transformer has been removed from CloudKitty's codebase. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-monasca-429122691d0e5d52.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The Monasca collector and fetcher are removed due to the unmaintained 5 | state of Monasca. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-state-attribute-scope-28e48ae4ada5208d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The ``state`` field is removed from the scope API. 5 | Use ``last_processed_timestamp`` instead. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-transformers-8d9949ed3088b055.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Since data frames are now represented as objects internally, transformers 5 | are not used anymore and have been completely removed from the codebase. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-v2-gnocchi-storage-a83bd58008bfd92e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | The gnocchi v2 storage backend has been removed. Users wanting to use the 5 | v2 storage interface must use the InfluxDB backend. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/remove-wsgi-scripts-27d0da6926c2127c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A new module, ``cloudkitty.wsgi``, has been added as a place to gather WSGI 5 | ``application`` objects. This is intended to ease deployment by providing a 6 | consistent location for these objects. For example, if using uWSGI then 7 | instead of: 8 | 9 | .. code-block:: ini 10 | 11 | [uwsgi] 12 | wsgi-file = /bin/cloudkitty-api 13 | 14 | You can now use: 15 | 16 | .. code-block:: ini 17 | 18 | [uwsgi] 19 | module = cloudkitty.wsgi.api:application 20 | 21 | This also simplifies deployment with other WSGI servers that expect module 22 | paths such as gunicorn. 23 | upgrade: 24 | - | 25 | The WSGI script ``cloudkitty-api`` has been removed. Deployment tooling 26 | should instead reference the Python module path for the wsgi module in 27 | CloudKitty, ``cloudkitty.wsgi.api:application`` if their chosen WSGI server 28 | supports this (gunicorn, uWSGI, etc.) or implement a .wsgi script 29 | themselves if not (mod_wsgi). 30 | -------------------------------------------------------------------------------- /releasenotes/notes/replace-eventlet-with-futurist-60f1fe6474a5efcf.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Since ``eventlet`` has been replaced with ``futurist``, the 5 | ``[orchestrator]/max_greenthreads`` option has been deprecated and 6 | replaced with ``[orchestrator]/max_threads``. 7 | 8 | other: 9 | - | 10 | The ``eventlet`` library has been replaced with ``futurist``. 11 | -------------------------------------------------------------------------------- /releasenotes/notes/reprocess-get-fix-f2bd1f2f9e2d640e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fix retrieval of reprocessing tasks which was returning ``Internal Server 5 | Error``. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/reprocessing-concurrency-issues-2a71f4d86a93c507.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixed concurrency issues during reprocessing tasks. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/response_format-v2-summary-api-270facdb01d9202b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Introduce ``response_format`` option for the V2 summary API, which can 5 | facilitate parsing the response. -------------------------------------------------------------------------------- /releasenotes/notes/rework-prometheus-collector-02bd6351d447e4fe.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Prometheus collector now supports, under extra_args section, 5 | an aggregation_method option to decide which aggregation 6 | method is to be performed over collected metrics. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/rework-prometheus-collector-f9f34a3792888dad.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Prometheus collector now supports HTTPS with custom CA file, 5 | an insecure option to allow an untrusted certificate 6 | and basic HTTP authentication. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/secure-rbac-defaults-5bb903323634a94c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The CloudKitty policies implemented the scope concept and new default roles 5 | (``admin``, ``member``, and ``reader``) provided by keystone. 6 | upgrade: 7 | - | 8 | All the policies implement the ``scope_type`` and new defaults. 9 | 10 | * **Scope** 11 | 12 | Each policy is protected with ``project`` ``scope_type``. 13 | 14 | * **New Defaults (Admin, Member and Reader)** 15 | 16 | Policies are default to Admin, Member and Reader roles. Old roles are 17 | also supported. There is no change in the legacy admin access. 18 | -------------------------------------------------------------------------------- /releasenotes/notes/skip-period-if-nonexistent-metric-ba56a671e68f5bf5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The behaviour of the gnocchi collector has changed in case of a nonexistent 5 | metric. Given that a nonexistent metric is unlikely to exist in the next 6 | collection cycle, the metric is simply skipped. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/source-fetcher-43c4352508f7f944.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A Source Fetcher has been added, allowing to add new collectors to scrap 5 | metrics from non-OpenStack sources. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/status-upgrade-check-fdcf054643e071d8.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | A new ``cloudkitty-status upgrade check`` command has been added. It can be 5 | used to validate a deployment before upgrading it from release N-1 to N. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/support-cross-tenant-metric-submission-monasca-collector-508b495bc88910ca.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Cross-tenant metric submission is now supported in the monasca collector. 5 | In order to a fetch metric from the scope that is currently being processed, 6 | the ``forced_project_id`` option must be set to ``SCOPE_ID``. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/support-group-by-timeframes-1247aa336916f3b6.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Introduce new default groupby options: (i) time: to group data hourly. 5 | The actual group by process will depend on the ``period`` parameter. The 6 | default value is ``3600``, which represents one hour; (ii) time-d: to 7 | group data by day of the year; (iii) time-w: to group data by week of 8 | the year; (iv) time-m: to group data by month; and, (v) time-y: to group 9 | data by year. If you have old data in CloudKitty and you wish to use 10 | these group by methods, you will need to reprocess the desired timeframe. 11 | -------------------------------------------------------------------------------- /releasenotes/notes/support-groupby-time-v2-summary-48ff5ad671f8c7c5.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | It is now possible to group v2 summaries by timestamp. In order to do this, 5 | the ``time`` parameter must be specified in the ``groupby`` list: 6 | ``cloudkitty summary get -g time,type``. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/undeprecate-elasticsearch-6f207824e439ede3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Support for using Elasticsearch as a storage backend is not deprecated 5 | anymore. The Elasticsearch storage backend was deprecated in the 6 | Antelope release in favour of OpenSearch. The removal of the deprecation 7 | is made following licensing changes and demand from CloudKitty users. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/use-interface-param-endpoint-discovery-monasca-collector-7477e86cd7e5acf4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The ``interface`` parameter of the ``collector_monasca`` section is now 5 | also used for the discovery of the monasca endpoint. 6 | -------------------------------------------------------------------------------- /releasenotes/source/2023.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2023.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/2023.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/2023.2.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2023.2 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2023.2 7 | -------------------------------------------------------------------------------- /releasenotes/source/2024.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2024.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2024.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/2024.2.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2024.2 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2024.2 7 | -------------------------------------------------------------------------------- /releasenotes/source/2025.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2025.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2025.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/_static/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/releasenotes/source/_static/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/_templates/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/cloudkitty/2a29211052e74199278c42457243054465bc6c77/releasenotes/source/_templates/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Licensed under the Apache License, Version 2.0 (the "License"); you may 3 | not use this file except in compliance with the License. You may obtain 4 | a copy of the License at 5 | 6 | https://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 10 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 11 | License for the specific language governing permissions and limitations 12 | under the License. 13 | 14 | ================================================== 15 | Welcome to cloudkitty Release Notes documentation! 16 | ================================================== 17 | 18 | Contents 19 | ======== 20 | 21 | .. toctree:: 22 | :maxdepth: 2 23 | 24 | unreleased 25 | 2025.1 26 | 2024.2 27 | 2024.1 28 | 2023.2 29 | 2023.1 30 | zed 31 | yoga 32 | xena 33 | wallaby 34 | victoria 35 | ussuri 36 | train 37 | stein 38 | rocky 39 | queens 40 | pike 41 | ocata 42 | 43 | Indices and tables 44 | ================== 45 | 46 | * :ref:`genindex` 47 | * :ref:`search` 48 | -------------------------------------------------------------------------------- /releasenotes/source/ocata.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Ocata Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: origin/stable/ocata 7 | -------------------------------------------------------------------------------- /releasenotes/source/pike.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Pike Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/pike 7 | -------------------------------------------------------------------------------- /releasenotes/source/queens.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Queens Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/queens 7 | -------------------------------------------------------------------------------- /releasenotes/source/rocky.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Rocky Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/rocky 7 | -------------------------------------------------------------------------------- /releasenotes/source/stein.rst: -------------------------------------------------------------------------------- 1 | =================================== 2 | Stein Series Release Notes 3 | =================================== 4 | 5 | .. release-notes:: 6 | :branch: stable/stein 7 | -------------------------------------------------------------------------------- /releasenotes/source/train.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | Train Series Release Notes 3 | ========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/train 7 | -------------------------------------------------------------------------------- /releasenotes/source/unreleased.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | Current Series Release Notes 3 | ============================ 4 | 5 | .. release-notes:: 6 | -------------------------------------------------------------------------------- /releasenotes/source/ussuri.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Ussuri Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/ussuri 7 | -------------------------------------------------------------------------------- /releasenotes/source/victoria.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Victoria Series Release Notes 3 | ============================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/victoria 7 | -------------------------------------------------------------------------------- /releasenotes/source/wallaby.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | Wallaby Series Release Notes 3 | ============================ 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/wallaby 7 | -------------------------------------------------------------------------------- /releasenotes/source/xena.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | Xena Series Release Notes 3 | ========================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/xena 7 | -------------------------------------------------------------------------------- /releasenotes/source/yoga.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | Yoga Series Release Notes 3 | ========================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/yoga 7 | -------------------------------------------------------------------------------- /releasenotes/source/zed.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | Zed Series Release Notes 3 | ======================== 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/zed 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Requirements lower bounds listed here are our best effort to keep them up to 2 | # date but we do not test them so no guarantee of having them all correct. If 3 | # you find any incorrect lower bounds, let us know or propose a fix. 4 | 5 | pbr>=5.5.1 # Apache-2.0 6 | alembic>=1.4.3 # MIT 7 | keystonemiddleware>=9.1.0 # Apache-2.0 8 | gnocchiclient>=7.0.6 # Apache-2.0 9 | python-keystoneclient>=4.1.1 # Apache-2.0 10 | keystoneauth1>=4.2.1 # Apache-2.0 11 | iso8601>=0.1.13 # MIT 12 | PasteDeploy>=2.1.1 # MIT 13 | pecan>=1.3.3 # BSD 14 | WSME>=0.10.0 # MIT 15 | oslo.config>=8.3.3 # Apache-2.0 16 | oslo.context>=3.1.1 # Apache-2.0 17 | oslo.concurrency>=4.3.1 # Apache-2.0 18 | oslo.db>=8.4.0 # Apache-2.0 19 | oslo.i18n>=5.0.1 # Apache-2.0 20 | oslo.log>=4.4.0 # Apache-2.0 21 | oslo.messaging>=14.1.0 # Apache-2.0 22 | oslo.middleware>=4.1.1 # Apache-2.0 23 | oslo.policy>=4.5.0 # Apache-2.0 24 | oslo.utils>=4.7.0 # Apache-2.0 25 | oslo.upgradecheck>=1.3.0 # Apache-2.0 26 | python-dateutil>=2.8.0 # BSD 27 | SQLAlchemy>=1.3.20 # MIT 28 | stevedore>=3.2.2 # Apache-2.0 29 | tooz>=2.7.1 # Apache-2.0 30 | voluptuous>=0.12.0 # BSD License 31 | influxdb>=5.3.1 # MIT 32 | influxdb-client>=1.36.0 # MIT 33 | Flask>=2.0.0 # BSD 34 | Flask-RESTful>=0.3.9 # BSD 35 | cotyledon>=1.7.3 # Apache-2.0 36 | futurist>=2.3.0 # Apache-2.0 37 | datetimerange>=0.6.1 # MIT 38 | requests>=2.14.2 # Apache-2.0 39 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | # implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT 17 | import setuptools 18 | 19 | setuptools.setup( 20 | setup_requires=['pbr>=2.0.0'], 21 | pbr=True) 22 | -------------------------------------------------------------------------------- /test-requirements.txt: -------------------------------------------------------------------------------- 1 | hacking>=7.0.0,<7.1.0 # Apache-2.0 2 | coverage>=5.3 # Apache-2.0 3 | kombu>=5.0.2 # BSD 4 | ddt>=1.4.1 # MIT 5 | gabbi>=2.0.4 # Apache-2.0 6 | testscenarios>=0.5.0 # Apache-2.0/BSD 7 | stestr>=3.0.1 # Apache-2.0 8 | oslotest>=4.4.1 # Apache-2.0 9 | doc8>=0.8.1 # Apache-2.0 10 | bandit>=1.6.0 # Apache-2.0 11 | --------------------------------------------------------------------------------