From 3b7b843eb50c9bcf176936aa54809d01f64f197f Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Mon, 17 Apr 2017 19:39:10 +0200 Subject: [PATCH] Retire repo This repo was created by accident, use deb-python-oslo.reports instead. Needed-By: I1ac1a06931c8b6dd7c2e73620a0302c29e605f03 Change-Id: I81894aea69b9d09b0977039623c26781093a397a --- .coveragerc | 8 - .gitignore | 54 -- .gitreview | 4 - .mailmap | 3 - .testr.conf | 7 - CONTRIBUTING.rst | 17 - HACKING.rst | 4 - LICENSE | 176 ---- README.rst | 51 -- README.txt | 13 + babel.cfg | 2 - doc/source/conf.py | 79 -- doc/source/contributing.rst | 5 - doc/source/history.rst | 1 - doc/source/index.rst | 40 - doc/source/installation.rst | 7 - doc/source/opts.rst | 8 - doc/source/report.txt | 755 ------------------ doc/source/usage.rst | 35 - oslo_reports/__init__.py | 25 - oslo_reports/_i18n.py | 35 - oslo_reports/_utils.py | 27 - oslo_reports/generators/__init__.py | 21 - oslo_reports/generators/conf.py | 44 - oslo_reports/generators/process.py | 38 - oslo_reports/generators/threading.py | 104 --- oslo_reports/generators/version.py | 60 -- oslo_reports/guru_meditation_report.py | 299 ------- .../locale/en_GB/LC_MESSAGES/oslo_reports.po | 18 - oslo_reports/models/__init__.py | 20 - oslo_reports/models/base.py | 162 ---- oslo_reports/models/conf.py | 66 -- oslo_reports/models/process.py | 73 -- oslo_reports/models/threading.py | 100 --- oslo_reports/models/version.py | 44 - oslo_reports/models/with_default_views.py | 81 -- oslo_reports/opts.py | 71 -- oslo_reports/report.py | 189 ----- oslo_reports/tests/__init__.py | 0 oslo_reports/tests/test_base_report.py | 144 ---- .../tests/test_guru_meditation_report.py | 249 ------ .../tests/test_openstack_generators.py | 141 ---- oslo_reports/tests/test_views.py | 426 ---------- oslo_reports/views/__init__.py | 22 - oslo_reports/views/jinja_view.py | 137 ---- oslo_reports/views/json/__init__.py | 19 - oslo_reports/views/json/generic.py | 66 -- oslo_reports/views/text/__init__.py | 19 - oslo_reports/views/text/generic.py | 203 ----- oslo_reports/views/text/header.py | 53 -- oslo_reports/views/text/process.py | 38 - oslo_reports/views/text/threading.py | 80 -- oslo_reports/views/xml/__init__.py | 19 - oslo_reports/views/xml/generic.py | 87 -- requirements.txt | 11 - setup.cfg | 61 -- setup.py | 29 - test-requirements.txt | 17 - tox.ini | 38 - 59 files changed, 13 insertions(+), 4592 deletions(-) delete mode 100644 .coveragerc delete mode 100644 .gitignore delete mode 100644 .gitreview delete mode 100644 .mailmap delete mode 100644 .testr.conf delete mode 100644 CONTRIBUTING.rst delete mode 100644 HACKING.rst delete mode 100644 LICENSE delete mode 100644 README.rst create mode 100644 README.txt delete mode 100644 babel.cfg delete mode 100755 doc/source/conf.py delete mode 100644 doc/source/contributing.rst delete mode 100644 doc/source/history.rst delete mode 100644 doc/source/index.rst delete mode 100644 doc/source/installation.rst delete mode 100644 doc/source/opts.rst delete mode 100644 doc/source/report.txt delete mode 100644 doc/source/usage.rst delete mode 100644 oslo_reports/__init__.py delete mode 100644 oslo_reports/_i18n.py delete mode 100644 oslo_reports/_utils.py delete mode 100644 oslo_reports/generators/__init__.py delete mode 100644 oslo_reports/generators/conf.py delete mode 100644 oslo_reports/generators/process.py delete mode 100644 oslo_reports/generators/threading.py delete mode 100644 oslo_reports/generators/version.py delete mode 100644 oslo_reports/guru_meditation_report.py delete mode 100644 oslo_reports/locale/en_GB/LC_MESSAGES/oslo_reports.po delete mode 100644 oslo_reports/models/__init__.py delete mode 100644 oslo_reports/models/base.py delete mode 100644 oslo_reports/models/conf.py delete mode 100644 oslo_reports/models/process.py delete mode 100644 oslo_reports/models/threading.py delete mode 100644 oslo_reports/models/version.py delete mode 100644 oslo_reports/models/with_default_views.py delete mode 100644 oslo_reports/opts.py delete mode 100644 oslo_reports/report.py delete mode 100644 oslo_reports/tests/__init__.py delete mode 100644 oslo_reports/tests/test_base_report.py delete mode 100644 oslo_reports/tests/test_guru_meditation_report.py delete mode 100644 oslo_reports/tests/test_openstack_generators.py delete mode 100644 oslo_reports/tests/test_views.py delete mode 100644 oslo_reports/views/__init__.py delete mode 100644 oslo_reports/views/jinja_view.py delete mode 100644 oslo_reports/views/json/__init__.py delete mode 100644 oslo_reports/views/json/generic.py delete mode 100644 oslo_reports/views/text/__init__.py delete mode 100644 oslo_reports/views/text/generic.py delete mode 100644 oslo_reports/views/text/header.py delete mode 100644 oslo_reports/views/text/process.py delete mode 100644 oslo_reports/views/text/threading.py delete mode 100644 oslo_reports/views/xml/__init__.py delete mode 100644 oslo_reports/views/xml/generic.py delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 test-requirements.txt delete mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index f60e8fa..0000000 --- a/.coveragerc +++ /dev/null @@ -1,8 +0,0 @@ -[run] -branch = True -source = oslo_reports -omit = oslo_reports/tests/* - -[report] -ignore_errors = True -precision = 2 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 5fc5a62..0000000 --- a/.gitignore +++ /dev/null @@ -1,54 +0,0 @@ -*.py[cod] - -# C extensions -*.so - -# Packages -*.egg -*.eggs -*.egg-info -dist -build -eggs -parts -bin -var -sdist -develop-eggs -.installed.cfg -lib -lib64 - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -cover -.tox -nosetests.xml -.testrepository - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Complexity -output/*.html -output/*/index.html - -# Sphinx -doc/build - -# pbr generates these -AUTHORS -ChangeLog -/doc/source/api/ - -# Editors -*~ -.*.swp diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 504e72f..0000000 --- a/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=openstack/oslo.reports.git diff --git a/.mailmap b/.mailmap deleted file mode 100644 index 516ae6f..0000000 --- a/.mailmap +++ /dev/null @@ -1,3 +0,0 @@ -# Format is: -# -# diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index bafdfe5..0000000 --- a/.testr.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ ./oslo_reports $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst deleted file mode 100644 index 044fc64..0000000 --- a/CONTRIBUTING.rst +++ /dev/null @@ -1,17 +0,0 @@ -If you would like to contribute to the development of OpenStack, you must -follow the steps in this page: - - http://docs.openstack.org/infra/manual/developers.html - -If you already have a good understanding of how the system works and your -OpenStack accounts are set up, you can skip to the development workflow -section of this documentation to learn how changes to OpenStack should be -submitted for review via the Gerrit tool: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/oslo.reports diff --git a/HACKING.rst b/HACKING.rst deleted file mode 100644 index 9ddcced..0000000 --- a/HACKING.rst +++ /dev/null @@ -1,4 +0,0 @@ -oslo.reports Style Commandments -====================================================== - -Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 68c771a..0000000 --- a/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/README.rst b/README.rst deleted file mode 100644 index 856e38e..0000000 --- a/README.rst +++ /dev/null @@ -1,51 +0,0 @@ -=================================== -oslo.reports -=================================== - -.. image:: https://img.shields.io/pypi/v/oslo.reports.svg - :target: https://pypi.python.org/pypi/oslo.reports/ - :alt: Latest Version - -.. image:: https://img.shields.io/pypi/dm/oslo.reports.svg - :target: https://pypi.python.org/pypi/oslo.reports/ - :alt: Downloads - -When things go wrong in (production) deployments of OpenStack collecting debug -data is a key first step in the process of triaging & ultimately resolving the -problem. Projects like Nova has extensively used logging capabilities which -produce a vast amount of data. This does not, however, enable an admin to -obtain an accurate view on the current live state of the system. For example, -what threads are running, what config parameters are in effect, and more. - -The project oslo.reports hosts a general purpose error report generation -framework, known as the "guru meditation report" -(cf http://en.wikipedia.org/wiki/Guru_Meditation) to address the issues -described above. - -Models: These classes define structured data for a variety of interesting -pieces of state. For example, stack traces, threads, config parameters, -package version info, etc. They are capable of being serialized to XML / JSON -or a plain text representation - -Generators: These classes are used to populate the model classes with the -current runtime state of the system - -Views: views serialize models into say JSON, text or xml. There is also -a predefined view that utilizes Jinja templating system. - -There will be a number of standard models / generators available for all -OpenStack services - -StackTraceModel: a base class for any model which includes a stack trace -ThreadModel: a class for information about a thread -ExceptionModel: a class for information about a caught exception -ConfigModel: a class for information about configuration file settings -PackageModel: a class for information about vendor/product/version/package information - -Each OpenStack project will have the ability to register further generator -classes to provide custom project specific data. - -* Free software: Apache license -* Documentation: http://docs.openstack.org/developer/oslo.reports -* Source: http://git.openstack.org/cgit/openstack/oslo.reports -* Bugs: http://bugs.launchpad.net/oslo.reports diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..bba33a6 --- /dev/null +++ b/README.txt @@ -0,0 +1,13 @@ +This project is no longer maintained. + +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". + +Use instead the project deb-python-oslo.reports at +http://git.openstack.org/cgit/openstack/deb-python-oslo.reports . + +For any further questions, please email +openstack-dev@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/babel.cfg b/babel.cfg deleted file mode 100644 index 15cd6cb..0000000 --- a/babel.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[python: **.py] - diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100755 index 49987f2..0000000 --- a/doc/source/conf.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -sys.path.insert(0, os.path.abspath('../..')) -# -- General configuration ---------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [ - 'sphinx.ext.autodoc', - #'sphinx.ext.intersphinx', - 'oslosphinx', - 'oslo_config.sphinxext', -] - -# autodoc generation is a bit aggressive and a nuisance when doing heavy -# text edit cycles. -# execute "export SPHINX_DEBUG=1" in your terminal to disable - -# The suffix of source filenames. -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'oslo.reports' -copyright = u'2014, OpenStack Foundation' - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = True - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -modindex_common_prefix = ['oslo_reports.'] - -# -- Options for HTML output -------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -# html_theme_path = ["."] -# html_theme = '_theme' -# html_static_path = ['static'] - -# Output file base name for HTML help builder. -htmlhelp_basename = '%sdoc' % project - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', - '%s.tex' % project, - u'%s Documentation' % project, - u'OpenStack Foundation', 'manual'), -] - -# Example configuration for intersphinx: refer to the Python standard library. -#intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/doc/source/contributing.rst b/doc/source/contributing.rst deleted file mode 100644 index 2ca75d1..0000000 --- a/doc/source/contributing.rst +++ /dev/null @@ -1,5 +0,0 @@ -============== - Contributing -============== - -.. include:: ../../CONTRIBUTING.rst diff --git a/doc/source/history.rst b/doc/source/history.rst deleted file mode 100644 index 69ed4fe..0000000 --- a/doc/source/history.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../ChangeLog diff --git a/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index a5e66c3..0000000 --- a/doc/source/index.rst +++ /dev/null @@ -1,40 +0,0 @@ -============== - oslo.reports -============== - -oslo.reports library - -Contents -======== - -.. toctree:: - :maxdepth: 2 - - installation - usage - opts - contributing - -API -=== - -.. toctree:: - :maxdepth: 2 - - api/autoindex - -Release Notes -============= - -.. toctree:: - :maxdepth: 1 - - history - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/doc/source/installation.rst b/doc/source/installation.rst deleted file mode 100644 index 042f75c..0000000 --- a/doc/source/installation.rst +++ /dev/null @@ -1,7 +0,0 @@ -============== - Installation -============== - -At the command line:: - - $ pip install oslo.reports diff --git a/doc/source/opts.rst b/doc/source/opts.rst deleted file mode 100644 index 205e30d..0000000 --- a/doc/source/opts.rst +++ /dev/null @@ -1,8 +0,0 @@ -======================= - Configuration Options -======================= - -oslo.reports uses oslo.config to define and manage configuration options -to allow the deployer to control where the GMR reports should be generated. - -.. show-options:: oslo.reports diff --git a/doc/source/report.txt b/doc/source/report.txt deleted file mode 100644 index 8f3c446..0000000 --- a/doc/source/report.txt +++ /dev/null @@ -1,755 +0,0 @@ -======================================================================== -==== Guru Meditation ==== -======================================================================== -|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| - - -======================================================================== -==== Package ==== -======================================================================== -product = OpenStack Nova -vendor = OpenStack Foundation -version = 13.0.0 -======================================================================== -==== Threads ==== -======================================================================== ------- Thread #140417215547200 ------ - -/usr/local/lib/python2.7/dist-packages/eventlet/hubs/hub.py:346 in run - `self.wait(sleep_time)` - -/usr/local/lib/python2.7/dist-packages/eventlet/hubs/poll.py:82 in wait - `sleep(seconds)` - -======================================================================== -==== Green Threads ==== -======================================================================== ------- Green Thread ------ - -/usr/local/bin/nova-api:10 in - `sys.exit(main())` - -/opt/stack/nova/nova/cmd/api.py:57 in main - `launcher.wait()` - -/usr/local/lib/python2.7/dist-packages/oslo_service/service.py:511 in wait - `self._respawn_children()` - -/usr/local/lib/python2.7/dist-packages/oslo_service/service.py:495 in _respawn_children - `eventlet.greenthread.sleep(self.wait_interval)` - -/usr/local/lib/python2.7/dist-packages/eventlet/greenthread.py:34 in sleep - `hub.switch()` - -/usr/local/lib/python2.7/dist-packages/eventlet/hubs/hub.py:294 in switch - `return self.greenlet.switch()` - ------- Green Thread ------ - -No Traceback! - -======================================================================== -==== Processes ==== -======================================================================== -Process 14756 (under 1) [ run by: stack (1001), state: running ] - Process 14770 (under 14756) [ run by: stack (1001), state: sleeping ] - Process 14771 (under 14756) [ run by: stack (1001), state: sleeping ] - Process 14776 (under 14756) [ run by: stack (1001), state: sleeping ] - Process 14777 (under 14756) [ run by: stack (1001), state: sleeping ] - Process 14784 (under 14756) [ run by: stack (1001), state: sleeping ] - Process 14785 (under 14756) [ run by: stack (1001), state: sleeping ] - -======================================================================== -==== Configuration ==== -======================================================================== - -api_database: - connection = *** - connection_debug = 0 - connection_trace = False - idle_timeout = 3600 - max_overflow = None - max_pool_size = None - max_retries = 10 - mysql_sql_mode = TRADITIONAL - pool_timeout = None - retry_interval = 10 - slave_connection = *** - sqlite_synchronous = True - -cells: - bandwidth_update_interval = 600 - call_timeout = 60 - capabilities = - hypervisor=xenserver;kvm - os=linux;windows - cell_type = compute - enable = False - instance_update_sync_database_limit = 100 - manager = nova.cells.manager.CellsManager - mute_child_interval = 300 - name = nova - reserve_percent = 10.0 - topic = cells - -cinder: - cafile = None - catalog_info = volumev2:cinderv2:publicURL - certfile = None - cross_az_attach = True - endpoint_template = None - http_retries = 3 - insecure = False - keyfile = None - os_region_name = RegionOne - timeout = None - -conductor: - manager = nova.conductor.manager.ConductorManager - topic = conductor - use_local = False - workers = 2 - -database: - backend = sqlalchemy - connection = *** - connection_debug = 0 - connection_trace = False - db_inc_retry_interval = True - db_max_retries = 20 - db_max_retry_interval = 10 - db_retry_interval = 1 - idle_timeout = 3600 - max_overflow = None - max_pool_size = None - max_retries = 10 - min_pool_size = 1 - mysql_sql_mode = TRADITIONAL - pool_timeout = None - retry_interval = 10 - slave_connection = *** - sqlite_db = nova.sqlite - sqlite_synchronous = True - use_db_reconnect = False - use_tpool = False - -default: - allow_instance_snapshots = True - allow_resize_to_same_host = True - allow_same_net_traffic = True - api_paste_config = /etc/nova/api-paste.ini - api_rate_limit = False - auth_strategy = keystone - auto_assign_floating_ip = False - bandwidth_poll_interval = 600 - bindir = /usr/local/bin - block_device_allocate_retries = 60 - block_device_allocate_retries_interval = 3 - boot_script_template = /opt/stack/nova/nova/cloudpipe/bootscript.template - ca_file = cacert.pem - ca_path = /opt/stack/data/nova/CA - cert_manager = nova.cert.manager.CertManager - cert_topic = cert - client_socket_timeout = 900 - cnt_vpn_clients = 0 - compute_available_monitors = None - compute_driver = libvirt.LibvirtDriver - compute_manager = nova.compute.manager.ComputeManager - compute_monitors = - compute_resources = - vcpu - compute_stats_class = nova.compute.stats.Stats - compute_topic = compute - config-dir = None - config-file = - /etc/nova/nova.conf - config_drive_format = iso9660 - config_drive_skip_versions = 1.0 2007-01-19 2007-03-01 2007-08-29 2007-10-10 2007-12-15 2008-02-01 2008-09-01 - console_host = dims-ubuntu - console_manager = nova.console.manager.ConsoleProxyManager - console_topic = console - consoleauth_manager = nova.consoleauth.manager.ConsoleAuthManager - consoleauth_topic = consoleauth - control_exchange = nova - cpu_allocation_ratio = 0.0 - create_unique_mac_address_attempts = 5 - crl_file = crl.pem - db_driver = nova.db - debug = True - default_access_ip_network_name = None - default_availability_zone = nova - default_ephemeral_format = ext4 - default_flavor = m1.small - default_floating_pool = public - default_log_levels = - amqp=WARN - amqplib=WARN - boto=WARN - glanceclient=WARN - iso8601=WARN - keystonemiddleware=WARN - oslo_messaging=INFO - qpid=WARN - requests.packages.urllib3.connectionpool=WARN - routes.middleware=WARN - sqlalchemy=WARN - stevedore=WARN - suds=INFO - urllib3.connectionpool=WARN - websocket=WARN - default_notification_level = INFO - default_publisher_id = None - default_schedule_zone = None - defer_iptables_apply = False - dhcp_domain = novalocal - dhcp_lease_time = 86400 - dhcpbridge = /usr/local/bin/nova-dhcpbridge - dhcpbridge_flagfile = - /etc/nova/nova.conf - dmz_cidr = - dmz_mask = 255.255.255.0 - dmz_net = 10.0.0.0 - dns_server = - dns_update_periodic_interval = -1 - dnsmasq_config_file = - ebtables_exec_attempts = 3 - ebtables_retry_interval = 1.0 - ec2_dmz_host = 10.0.0.9 - ec2_host = 10.0.0.9 - ec2_listen = 0.0.0.0 - ec2_listen_port = 8773 - ec2_path = / - ec2_port = 8773 - ec2_private_dns_show_ip = False - ec2_scheme = http - ec2_strict_validation = True - ec2_timestamp_expiry = 300 - ec2_workers = 2 - enable_instance_password = True - enable_network_quota = False - enable_new_services = True - enabled_apis = - ec2 - metadata - osapi_compute - enabled_ssl_apis = - fake_call = False - fake_network = False - fatal_deprecations = False - fatal_exception_format_errors = False - firewall_driver = nova.virt.firewall.NoopFirewallDriver - fixed_ip_disassociate_timeout = 600 - fixed_range_v6 = fd00::/48 - flat_injected = False - flat_interface = None - flat_network_bridge = None - flat_network_dns = 8.8.4.4 - floating_ip_dns_manager = nova.network.noop_dns_driver.NoopDNSDriver - force_config_drive = True - force_dhcp_release = True - force_raw_images = True - force_snat_range = - forward_bridge_interface = - all - fping_path = /usr/sbin/fping - gateway = None - gateway_v6 = None - heal_instance_info_cache_interval = 60 - host = dims-ubuntu - image_cache_manager_interval = 2400 - image_cache_subdirectory_name = _base - image_decryption_dir = /tmp - injected_network_template = /opt/stack/nova/nova/virt/interfaces.template - instance_build_timeout = 0 - instance_delete_interval = 300 - instance_dns_domain = - instance_dns_manager = nova.network.noop_dns_driver.NoopDNSDriver - instance_format = [instance: %(uuid)s] - instance_name_template = instance-%08x - instance_usage_audit = False - instance_usage_audit_period = month - instance_uuid_format = [instance: %(uuid)s] - instances_path = /opt/stack/data/nova/instances - internal_service_availability_zone = internal - iptables_bottom_regex = - iptables_drop_action = DROP - iptables_top_regex = - ipv6_backend = rfc2462 - key_file = private/cakey.pem - keys_path = /opt/stack/data/nova/keys - keystone_ec2_insecure = False - keystone_ec2_url = http://10.0.0.9:5000/v2.0/ec2tokens - l3_lib = nova.network.l3.LinuxNetL3 - linuxnet_interface_driver = - linuxnet_ovs_integration_bridge = br-int - live_migration_retry_count = 30 - lockout_attempts = 5 - lockout_minutes = 15 - lockout_window = 15 - log-config-append = None - log-date-format = %Y-%m-%d %H:%M:%S - log-dir = None - log-file = None - log-format = None - log_options = True - logging_context_format_string = %(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s%(color)s] %(instance)s%(color)s%(message)s - logging_debug_format_suffix = from (pid=%(process)d) %(funcName)s %(pathname)s:%(lineno)d - logging_default_format_string = %(asctime)s.%(msecs)03d %(color)s%(levelname)s %(name)s [-%(color)s] %(instance)s%(color)s%(message)s - logging_exception_prefix = %(color)s%(asctime)s.%(msecs)03d TRACE %(name)s %(instance)s - max_age = 0 - max_concurrent_builds = 10 - max_concurrent_live_migrations = 1 - max_header_line = 16384 - max_local_block_devices = 3 - maximum_instance_delete_attempts = 5 - memcached_servers = None - metadata_cache_expiration = 15 - metadata_host = 10.0.0.9 - metadata_listen = 0.0.0.0 - metadata_listen_port = 8775 - metadata_manager = nova.api.manager.MetadataManager - metadata_port = 8775 - metadata_workers = 2 - migrate_max_retries = -1 - mkisofs_cmd = genisoimage - monkey_patch = False - monkey_patch_modules = - nova.api.ec2.cloud:nova.notifications.notify_decorator - nova.compute.api:nova.notifications.notify_decorator - multi_host = False - multi_instance_display_name_template = %(name)s-%(count)d - my_block_storage_ip = 10.0.0.9 - my_ip = 10.0.0.9 - network_allocate_retries = 0 - network_api_class = nova.network.neutronv2.api.API - network_device_mtu = None - network_driver = nova.network.linux_net - network_manager = nova.network.manager.VlanManager - network_size = 256 - network_topic = network - networks_path = /opt/stack/data/nova/networks - neutron_default_tenant_id = default - non_inheritable_image_properties = - bittorrent - cache_in_nova - notification_driver = - notification_topics = - notifications - notify_api_faults = False - notify_on_state_change = None - null_kernel = nokernel - num_networks = 1 - osapi_compute_ext_list = - osapi_compute_extension = - nova.api.openstack.compute.legacy_v2.contrib.standard_extensions - osapi_compute_link_prefix = None - osapi_compute_listen = 0.0.0.0 - osapi_compute_listen_port = 8774 - osapi_compute_unique_server_name_scope = - osapi_compute_workers = 2 - osapi_glance_link_prefix = None - osapi_hide_server_address_states = - building - osapi_max_limit = 1000 - ovs_vsctl_timeout = 120 - password_length = 12 - pci_alias = - pci_passthrough_whitelist = - periodic_enable = True - periodic_fuzzy_delay = 60 - policy_default_rule = default - policy_dirs = - policy.d - policy_file = policy.json - preallocate_images = none - project_cert_subject = /C=US/ST=California/O=OpenStack/OU=NovaDev/CN=project-ca-%.16s-%s - public_interface = eth0 - publish_errors = False - pybasedir = /opt/stack/nova - quota_cores = 20 - quota_driver = nova.quota.DbQuotaDriver - quota_fixed_ips = -1 - quota_floating_ips = 10 - quota_injected_file_content_bytes = 10240 - quota_injected_file_path_length = 255 - quota_injected_files = 5 - quota_instances = 10 - quota_key_pairs = 100 - quota_metadata_items = 128 - quota_networks = 3 - quota_ram = 51200 - quota_security_group_rules = 20 - quota_security_groups = 10 - quota_server_group_members = 10 - quota_server_groups = 10 - ram_allocation_ratio = 0.0 - reboot_timeout = 0 - reclaim_instance_interval = 0 - region_list = - remove_unused_base_images = True - remove_unused_original_minimum_age_seconds = 86400 - report_interval = 10 - rescue_timeout = 0 - reservation_expire = 86400 - reserved_host_disk_mb = 0 - reserved_host_memory_mb = 512 - resize_confirm_window = 0 - resize_fs_using_block_device = False - resume_guests_state_on_host_boot = False - rootwrap_config = /etc/nova/rootwrap.conf - routing_source_ip = 10.0.0.9 - rpc_backend = rabbit - rpc_response_timeout = 60 - run_external_periodic_tasks = True - running_deleted_instance_action = reap - running_deleted_instance_poll_interval = 1800 - running_deleted_instance_timeout = 0 - s3_access_key = notchecked - s3_affix_tenant = False - s3_host = 10.0.0.9 - s3_port = 3333 - s3_secret_key = notchecked - s3_use_ssl = False - scheduler_available_filters = - nova.scheduler.filters.all_filters - scheduler_default_filters = - AvailabilityZoneFilter - ComputeCapabilitiesFilter - ComputeFilter - DiskFilter - ImagePropertiesFilter - RamFilter - RetryFilter - ServerGroupAffinityFilter - ServerGroupAntiAffinityFilter - scheduler_instance_sync_interval = 120 - scheduler_manager = nova.scheduler.manager.SchedulerManager - scheduler_max_attempts = 3 - scheduler_topic = scheduler - scheduler_tracks_instance_changes = True - scheduler_weight_classes = - nova.scheduler.weights.all_weighers - secure_proxy_ssl_header = None - security_group_api = neutron - send_arp_for_ha = False - send_arp_for_ha_count = 3 - service_down_time = 60 - servicegroup_driver = db - share_dhcp_address = False - shelved_offload_time = 0 - shelved_poll_interval = 3600 - shutdown_timeout = 60 - snapshot_name_template = snapshot-%s - ssl_ca_file = None - ssl_cert_file = None - ssl_key_file = None - state_path = /opt/stack/data/nova - sync_power_state_interval = 600 - syslog-log-facility = LOG_USER - tcp_keepidle = 600 - teardown_unused_network_gateway = False - tempdir = None - transport_url = None - until_refresh = 0 - update_dns_entries = False - update_resources_interval = 0 - use-syslog = False - use-syslog-rfc-format = True - use_cow_images = True - use_forwarded_for = False - use_ipv6 = False - use_network_dns_servers = False - use_neutron_default_nets = False - use_project_ca = False - use_rootwrap_daemon = False - use_single_default_gateway = False - use_stderr = True - user_cert_subject = /C=US/ST=California/O=OpenStack/OU=NovaDev/CN=%.16s-%.16s-%s - vcpu_pin_set = None - vendordata_driver = nova.api.metadata.vendordata_json.JsonFileVendorData - verbose = True - vif_plugging_is_fatal = True - vif_plugging_timeout = 300 - virt_mkfs = - vlan_interface = None - vlan_start = 100 - volume_api_class = nova.volume.cinder.API - volume_usage_poll_interval = 0 - vpn_flavor = m1.tiny - vpn_image_id = 0 - vpn_ip = 10.0.0.9 - vpn_key_suffix = -vpn - vpn_start = 1000 - wsgi_default_pool_size = 1000 - wsgi_keep_alive = True - wsgi_log_format = %(client_ip)s "%(request_line)s" status: %(status_code)s len: %(body_length)s time: %(wall_seconds).7f - -ephemeral_storage_encryption: - cipher = aes-xts-plain64 - enabled = False - key_size = 512 - -glance: - allowed_direct_url_schemes = - api_insecure = False - api_servers = - http://10.0.0.9:9292 - host = 10.0.0.9 - num_retries = 0 - port = 9292 - protocol = http - -guestfs: - debug = False - -image_file_url: - filesystems = - -ironic: - admin_auth_token = *** - admin_password = *** - admin_tenant_name = None - admin_url = None - admin_username = None - api_endpoint = None - api_max_retries = 60 - api_retry_interval = 2 - api_version = 1 - client_log_level = None - -keymgr: - api_class = nova.keymgr.conf_key_mgr.ConfKeyManager - -keystone_authtoken: - admin_password = *** - admin_tenant_name = admin - admin_token = *** - admin_user = None - auth-url = http://10.0.0.9:35357 - auth_admin_prefix = - auth_host = 127.0.0.1 - auth_plugin = password - auth_port = 35357 - auth_protocol = https - auth_section = None - auth_uri = http://10.0.0.9:5000 - auth_version = None - cache = None - cafile = /opt/stack/data/ca-bundle.pem - certfile = None - check_revocations_for_cached = False - delay_auth_decision = False - domain-id = None - domain-name = None - enforce_token_bind = permissive - hash_algorithms = - md5 - http_connect_timeout = None - http_request_max_retries = 3 - identity_uri = None - include_service_catalog = True - insecure = False - keyfile = None - memcache_pool_conn_get_timeout = 10 - memcache_pool_dead_retry = 300 - memcache_pool_maxsize = 10 - memcache_pool_socket_timeout = 3 - memcache_pool_unused_timeout = 60 - memcache_secret_key = *** - memcache_security_strategy = None - memcache_use_advanced_pool = False - memcached_servers = None - password = password - project-domain-id = default - project-domain-name = None - project-id = None - project-name = service - region_name = None - revocation_cache_time = 10 - signing_dir = /var/cache/nova - tenant-id = None - tenant-name = None - token_cache_time = 300 - trust-id = None - user-domain-id = default - user-domain-name = None - user-id = None - user-name = nova - -libvirt: - block_migration_flag = VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE, VIR_MIGRATE_TUNNELLED, VIR_MIGRATE_NON_SHARED_INC - checksum_base_images = False - checksum_interval_seconds = 3600 - connection_uri = - cpu_mode = none - cpu_model = None - disk_cachemodes = - disk_prefix = None - gid_maps = - hw_disk_discard = None - hw_machine_type = None - image_info_filename_pattern = /opt/stack/data/nova/instances/_base/%(image)s.info - images_rbd_ceph_conf = - images_rbd_pool = rbd - images_type = default - images_volume_group = None - inject_key = False - inject_partition = -2 - inject_password = False - iscsi_iface = None - iscsi_use_multipath = False - live_migration_bandwidth = 0 - live_migration_completion_timeout = 800 - live_migration_downtime = 500 - live_migration_downtime_delay = 75 - live_migration_downtime_steps = 10 - live_migration_flag = VIR_MIGRATE_UNDEFINE_SOURCE, VIR_MIGRATE_PEER2PEER, VIR_MIGRATE_LIVE, VIR_MIGRATE_TUNNELLED - live_migration_progress_timeout = 150 - live_migration_uri = qemu+ssh://stack@%s/system - mem_stats_period_seconds = 10 - num_iscsi_scan_tries = 5 - qemu_allowed_storage_drivers = - rbd_secret_uuid = None - rbd_user = None - remote_filesystem_transport = ssh - remove_unused_kernels = True - remove_unused_resized_minimum_age_seconds = 3600 - rescue_image_id = None - rescue_kernel_id = None - rescue_ramdisk_id = None - rng_dev_path = None - snapshot_compression = False - snapshot_image_format = None - snapshots_directory = /opt/stack/data/nova/instances/snapshots - sparse_logical_volumes = False - sysinfo_serial = auto - uid_maps = - use_usb_tablet = False - use_virtio_for_bridges = True - virt_type = kvm - volume_clear = zero - volume_clear_size = 0 - wait_soft_reboot_seconds = 120 - xen_hvmloader_path = /usr/lib/xen/boot/hvmloader - -mks: - enabled = False - mksproxy_base_url = http://127.0.0.1:6090/ - -neutron: - admin_auth_url = http://10.0.0.9:35357/v2.0 - admin_password = *** - admin_tenant_id = None - admin_tenant_name = service - admin_user_id = None - admin_username = neutron - auth_plugin = None - auth_section = None - auth_strategy = keystone - cafile = None - certfile = None - extension_sync_interval = 600 - insecure = False - keyfile = None - metadata_proxy_shared_secret = *** - ovs_bridge = br-int - region_name = RegionOne - service_metadata_proxy = True - timeout = None - url = http://10.0.0.9:9696 - -osapi_v21: - enabled = True - extensions_blacklist = - extensions_whitelist = - -oslo_concurrency: - disable_process_locking = False - lock_path = /opt/stack/data/nova - -oslo_messaging_rabbit: - amqp_auto_delete = False - amqp_durable_queues = False - fake_rabbit = False - heartbeat_rate = 2 - heartbeat_timeout_threshold = 60 - kombu_reconnect_delay = 1.0 - kombu_reconnect_timeout = 60 - kombu_ssl_ca_certs = - kombu_ssl_certfile = - kombu_ssl_keyfile = - kombu_ssl_version = - rabbit_ha_queues = False - rabbit_host = localhost - rabbit_hosts = - 10.0.0.9 - rabbit_login_method = AMQPLAIN - rabbit_max_retries = 0 - rabbit_password = *** - rabbit_port = 5672 - rabbit_retry_backoff = 2 - rabbit_retry_interval = 1 - rabbit_use_ssl = False - rabbit_userid = stackrabbit - rabbit_virtual_host = / - rpc_conn_pool_size = 30 - send_single_reply = False - -oslo_middleware: - max_request_body_size = 114688 - -oslo_versionedobjects: - fatal_exception_format_errors = False - -rdp: - enabled = False - html5_proxy_base_url = http://127.0.0.1:6083/ - -remote_debug: - host = None - port = None - -serial_console: - base_url = ws://127.0.0.1:6083/ - enabled = False - listen = 127.0.0.1 - port_range = 10000:20000 - proxyclient_address = 127.0.0.1 - -spice: - agent_enabled = True - enabled = False - html5proxy_base_url = http://10.0.0.9:6082/spice_auto.html - keymap = en-us - server_listen = 127.0.0.1 - server_proxyclient_address = 127.0.0.1 - -ssl: - ca_file = None - cert_file = None - key_file = None - -upgrade_levels: - baseapi = None - cells = None - cert = None - compute = None - conductor = None - console = None - consoleauth = None - network = None - scheduler = None - -vnc: - enabled = False - keymap = en-us - novncproxy_base_url = http://10.0.0.9:6080/vnc_auto.html - vncserver_listen = 127.0.0.1 - vncserver_proxyclient_address = 127.0.0.1 - xvpvncproxy_base_url = http://10.0.0.9:6081/console - -workarounds: - destroy_after_evacuate = True - disable_libvirt_livesnapshot = True - disable_rootwrap = False - handle_virt_lifecycle_events = True \ No newline at end of file diff --git a/doc/source/usage.rst b/doc/source/usage.rst deleted file mode 100644 index b1c1790..0000000 --- a/doc/source/usage.rst +++ /dev/null @@ -1,35 +0,0 @@ -======= - Usage -======= - -Every long running service process should have a call to install a -signal handler which will trigger the guru meditation framework upon -receipt of SIGUSR1/SIGUSR2. This will result in the process dumping a -complete report of its current state to stderr. - -For RPC listeners, it may also be desirable to install some kind of hook in -the RPC request dispatcher that will save a guru meditation report whenever -the processing of a request results in an uncaught exception. It could save -these reports to a well known directory -(/var/log/openstack///) for later analysis by the sysadmin -or automated bug analysis tools. - -To use oslo.reports in a project, you need to add the following call to -:py:func:`~oslo_reports.TextGuruMeditation.setup_autorun` somewhere really -early in the startup sequence of the process:: - - from oslo_reports import guru_meditation_report as gmr - - gmr.TextGuruMeditation.setup_autorun(version='13.0.0') - -Note that the version parameter is the version of the component itself. - -To trigger the report to be generated:: - - kill -SIGUSR2 - - -Here is a sample report: - -.. include:: report.txt - :literal: diff --git a/oslo_reports/__init__.py b/oslo_reports/__init__.py deleted file mode 100644 index 100171b..0000000 --- a/oslo_reports/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides a way to generate serializable reports - -This package/module provides mechanisms for defining reports -which may then be serialized into various data types. Each -report ( :class:`oslo_reports.report.BasicReport` ) -is composed of one or more report sections -( :class:`oslo_reports.report.BasicSection` ), -which contain generators which generate data models -( :class:`oslo_reports.models.base.ReportModels` ), -which are then serialized by views. -""" diff --git a/oslo_reports/_i18n.py b/oslo_reports/_i18n.py deleted file mode 100644 index 8db1970..0000000 --- a/oslo_reports/_i18n.py +++ /dev/null @@ -1,35 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""oslo.i18n integration module. - -See http://docs.openstack.org/developer/oslo.i18n/usage.html . - -""" - -import oslo_i18n - - -_translators = oslo_i18n.TranslatorFactory(domain='oslo_reports') - -# The primary translation function using the well-known name "_" -_ = _translators.primary - -# Translators for log levels. -# -# The abbreviated names are meant to reflect the usual use of a short -# name like '_'. The "L" is for "log" and the other letter comes from -# the level. -_LI = _translators.log_info -_LW = _translators.log_warning -_LE = _translators.log_error -_LC = _translators.log_critical diff --git a/oslo_reports/_utils.py b/oslo_reports/_utils.py deleted file mode 100644 index 149aef7..0000000 --- a/oslo_reports/_utils.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Various utilities for report generation - -This module includes various utilities -used in generating reports. -""" - -import six - - -class StringWithAttrs(six.text_type): - """A String that can have arbitrary attributes""" - - pass diff --git a/oslo_reports/generators/__init__.py b/oslo_reports/generators/__init__.py deleted file mode 100644 index 4daf75e..0000000 --- a/oslo_reports/generators/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides Data Model Generators - -This module defines classes for generating data models -( :class:`oslo_reports.models.base.ReportModel` ). -A generator is any object which is callable with no parameters -and returns a data model. -""" diff --git a/oslo_reports/generators/conf.py b/oslo_reports/generators/conf.py deleted file mode 100644 index cdb8c43..0000000 --- a/oslo_reports/generators/conf.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides OpenStack config generators - -This module defines a class for configuration -generators for generating the model in -:mod:`oslo_reports.models.conf`. -""" - -from oslo_config import cfg - -from oslo_reports.models import conf as cm - - -class ConfigReportGenerator(object): - """A Configuration Data Generator - - This generator returns - :class:`oslo_reports.models.conf.ConfigModel`, - by default using the configuration options stored - in :attr:`oslo_config.cfg.CONF`, which is where - OpenStack stores everything. - - :param cnf: the configuration option object - :type cnf: :class:`oslo_config.cfg.ConfigOpts` - """ - - def __init__(self, cnf=cfg.CONF): - self.conf_obj = cnf - - def __call__(self): - return cm.ConfigModel(self.conf_obj) diff --git a/oslo_reports/generators/process.py b/oslo_reports/generators/process.py deleted file mode 100644 index 2749ff2..0000000 --- a/oslo_reports/generators/process.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides process-data generators - -This modules defines a class for generating -process data by way of the psutil package. -""" - -import os - -import psutil - -from oslo_reports.models import process as pm - - -class ProcessReportGenerator(object): - """A Process Data Generator - - This generator returns a - :class:`oslo_reports.models.process.ProcessModel` - based on the current process (which will also include - all subprocesses, recursively) using the :class:`psutil.Process` class`. - """ - - def __call__(self): - return pm.ProcessModel(psutil.Process(os.getpid())) diff --git a/oslo_reports/generators/threading.py b/oslo_reports/generators/threading.py deleted file mode 100644 index 9d68f90..0000000 --- a/oslo_reports/generators/threading.py +++ /dev/null @@ -1,104 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides thread-related generators - -This module defines classes for threading-related -generators for generating the models in -:mod:`oslo_reports.models.threading`. -""" - -from __future__ import absolute_import - -import gc -import sys -import threading - -from oslo_reports.models import threading as tm -from oslo_reports.models import with_default_views as mwdv -from oslo_reports.views.text import generic as text_views - - -def _find_objects(t): - """Find Objects in the GC State - - This horribly hackish method locates objects of a - given class in the current python instance's garbage - collection state. In case you couldn't tell, this is - horribly hackish, but is necessary for locating all - green threads, since they don't keep track of themselves - like normal threads do in python. - - :param class t: the class of object to locate - :rtype: list - :returns: a list of objects of the given type - """ - - return [o for o in gc.get_objects() if isinstance(o, t)] - - -class ThreadReportGenerator(object): - """A Thread Data Generator - - This generator returns a collection of - :class:`oslo_reports.models.threading.ThreadModel` - objects by introspecting the current python state using - :func:`sys._current_frames()` . Its constructor may optionally - be passed a frame object. This frame object will be interpreted - as the actual stack trace for the current thread, and, come generation - time, will be used to replace the stack trace of the thread in which - this code is running. - """ - - def __init__(self, curr_thread_traceback=None): - self.traceback = curr_thread_traceback - - def __call__(self): - threadModels = dict( - (thread_id, tm.ThreadModel(thread_id, stack)) - for thread_id, stack in sys._current_frames().items() - ) - - if self.traceback is not None: - curr_thread_id = threading.current_thread().ident - threadModels[curr_thread_id] = tm.ThreadModel(curr_thread_id, - self.traceback) - - return mwdv.ModelWithDefaultViews(threadModels, - text_view=text_views.MultiView()) - - -class GreenThreadReportGenerator(object): - """A Green Thread Data Generator - - This generator returns a collection of - :class:`oslo_reports.models.threading.GreenThreadModel` - objects by introspecting the current python garbage collection - state, and sifting through for :class:`greenlet.greenlet` objects. - - .. seealso:: - - Function :func:`_find_objects` - """ - - def __call__(self): - import greenlet - - threadModels = [ - tm.GreenThreadModel(gr.gr_frame) - for gr in _find_objects(greenlet.greenlet) - ] - - return mwdv.ModelWithDefaultViews(threadModels, - text_view=text_views.MultiView()) diff --git a/oslo_reports/generators/version.py b/oslo_reports/generators/version.py deleted file mode 100644 index 97f6e4f..0000000 --- a/oslo_reports/generators/version.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides OpenStack version generators - -This module defines a class for OpenStack -version and package information -generators for generating the model in -:mod:`oslo_reports.models.version`. -""" - -from oslo_reports.models import version as vm - - -class PackageReportGenerator(object): - """A Package Information Data Generator - - This generator returns - :class:`oslo_reports.models.version.PackageModel`, - extracting data from the given version object, which should follow - the general format defined in Nova's version information (i.e. it - should contain the methods vendor_string, product_string, and - version_string_with_package). - - :param version_object: the version information object - """ - - def __init__(self, version_obj): - self.version_obj = version_obj - - def __call__(self): - if hasattr(self.version_obj, "vendor_string"): - vendor_string = self.version_obj.vendor_string() - else: - vendor_string = None - - if hasattr(self.version_obj, "product_string"): - product_string = self.version_obj.product_string() - else: - product_string = None - - if hasattr(self.version_obj, "version_string_with_package"): - version_string_with_package = self.version_obj.\ - version_string_with_package() - else: - version_string_with_package = None - - return vm.PackageModel(vendor_string, product_string, - version_string_with_package) diff --git a/oslo_reports/guru_meditation_report.py b/oslo_reports/guru_meditation_report.py deleted file mode 100644 index 3ff497d..0000000 --- a/oslo_reports/guru_meditation_report.py +++ /dev/null @@ -1,299 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides Guru Meditation Report - -This module defines the actual OpenStack Guru Meditation -Report class. - -This can be used in the OpenStack command definition files. -For example, in a nova command module (under nova/cmd): - -.. code-block:: python - :emphasize-lines: 8,9,10 - - from oslo_config import cfg - from oslo_log import log as oslo_logging - from oslo_reports import opts as gmr_opts - from oslo_reports import guru_meditation_report as gmr - - CONF = cfg.CONF - # maybe import some options here... - - def main(): - oslo_logging.register_options(CONF) - gmr_opts.set_defaults(CONF) - - CONF(sys.argv[1:], default_config_files=['myapp.conf']) - oslo_logging.setup(CONF, 'myapp') - - gmr.TextGuruMeditation.register_section('Some Special Section', - special_section_generator) - gmr.TextGuruMeditation.setup_autorun(version_object, conf=CONF) - - server = service.Service.create(binary='some-service', - topic=CONF.some_service_topic) - service.serve(server) - service.wait() - -Then, you can do - -.. code-block:: bash - - $ kill -USR2 $SERVICE_PID - -and get a Guru Meditation Report in the file or terminal -where stderr is logged for that given service. -""" - -from __future__ import print_function - -import inspect -import logging -import os -import signal -import stat -import sys -import threading -import time -import traceback - -from oslo_utils import timeutils - -from oslo_reports._i18n import _LE -from oslo_reports._i18n import _LW -from oslo_reports.generators import conf as cgen -from oslo_reports.generators import process as prgen -from oslo_reports.generators import threading as tgen -from oslo_reports.generators import version as pgen -from oslo_reports import report - - -LOG = logging.getLogger(__name__) - - -class GuruMeditation(object): - """A Guru Meditation Report Mixin/Base Class - - This class is a base class for Guru Meditation Reports. - It provides facilities for registering sections and - setting up functionality to auto-run the report on - a certain signal or use file modification events. - - This class should always be used in conjunction with - a Report class via multiple inheritance. It should - always come first in the class list to ensure the - MRO is correct. - """ - - timestamp_fmt = "%Y%m%d%H%M%S" - - def __init__(self, version_obj, sig_handler_tb=None, *args, **kwargs): - self.version_obj = version_obj - self.traceback = sig_handler_tb - - super(GuruMeditation, self).__init__(*args, **kwargs) - self.start_section_index = len(self.sections) - - @classmethod - def register_section(cls, section_title, generator): - """Register a New Section - - This method registers a persistent section for the current - class. - - :param str section_title: the title of the section - :param generator: the generator for the section - """ - - try: - cls.persistent_sections.append([section_title, generator]) - except AttributeError: - cls.persistent_sections = [[section_title, generator]] - - @classmethod - def setup_autorun(cls, version, service_name=None, - log_dir=None, signum=None, conf=None): - """Set Up Auto-Run - - This method sets up the Guru Meditation Report to automatically - get dumped to stderr or a file in a given dir when the given signal - is received. It can also use file modification events instead of - signals. - - :param version: the version object for the current product - :param service_name: this program name used to construct logfile name - :param logdir: path to a log directory where to create a file - :param signum: the signal to associate with running the report - :param conf: Configuration object, managed by the caller. - """ - - if log_dir is None and conf is not None: - log_dir = conf.oslo_reports.log_dir - - if signum: - cls._setup_signal(signum, version, service_name, log_dir) - return - - if conf and conf.oslo_reports.file_event_handler: - cls._setup_file_watcher( - conf.oslo_reports.file_event_handler, - conf.oslo_reports.file_event_handler_interval, - version, service_name, log_dir) - else: - if hasattr(signal, 'SIGUSR1'): - # TODO(dims) We need to remove this in the "O" release cycle - LOG.warning(_LW("Guru meditation now registers SIGUSR1 and " - "SIGUSR2 by default for backward " - "compatibility. SIGUSR1 will no longer be " - "registered in a future release, so please " - "use SIGUSR2 to generate reports.")) - cls._setup_signal(signal.SIGUSR1, - version, service_name, log_dir) - if hasattr(signal, 'SIGUSR2'): - cls._setup_signal(signal.SIGUSR2, - version, service_name, log_dir) - - @classmethod - def _setup_file_watcher(cls, filepath, interval, version, service_name, - log_dir): - - st = os.stat(filepath) - if not bool(st.st_mode & stat.S_IRGRP): - LOG.error(_LE("Guru Meditation Report does not have read " - "permissions to '%s' file."), filepath) - - def _handler(): - mtime = time.time() - while True: - try: - stat = os.stat(filepath) - if stat.st_mtime > mtime: - cls.handle_signal(version, service_name, log_dir, None) - mtime = stat.st_mtime - except OSError: - msg = ("Guru Meditation Report cannot read " + - "'{0}' file".format(filepath)) - raise IOError(msg) - finally: - time.sleep(interval) - - th = threading.Thread(target=_handler) - th.daemon = True - th.start() - - @classmethod - def _setup_signal(cls, signum, version, service_name, log_dir): - signal.signal(signum, - lambda sn, f: cls.handle_signal( - version, service_name, log_dir, f)) - - @classmethod - def handle_signal(cls, version, service_name, log_dir, frame): - """The Signal Handler - - This method (indirectly) handles receiving a registered signal and - dumping the Guru Meditation Report to stderr or a file in a given dir. - If service name and log dir are not None, the report will be dumped to - a file named $service_name_gurumeditation_$current_time in the log_dir - directory. - This method is designed to be curried into a proper signal handler by - currying out the version - parameter. - - :param version: the version object for the current product - :param service_name: this program name used to construct logfile name - :param logdir: path to a log directory where to create a file - :param frame: the frame object provided to the signal handler - """ - - try: - res = cls(version, frame).run() - except Exception: - traceback.print_exc(file=sys.stderr) - print("Unable to run Guru Meditation Report!", - file=sys.stderr) - else: - if log_dir: - service_name = service_name or os.path.basename( - inspect.stack()[-1][1]) - filename = "%s_gurumeditation_%s" % ( - service_name, timeutils.utcnow().strftime( - cls.timestamp_fmt)) - filepath = os.path.join(log_dir, filename) - try: - with open(filepath, "w") as dumpfile: - dumpfile.write(res) - except Exception: - print("Unable to dump Guru Meditation Report to file %s" % - (filepath,), file=sys.stderr) - else: - print(res, file=sys.stderr) - - def _readd_sections(self): - del self.sections[self.start_section_index:] - - self.add_section('Package', - pgen.PackageReportGenerator(self.version_obj)) - - self.add_section('Threads', - tgen.ThreadReportGenerator(self.traceback)) - - self.add_section('Green Threads', - tgen.GreenThreadReportGenerator()) - - self.add_section('Processes', - prgen.ProcessReportGenerator()) - - self.add_section('Configuration', - cgen.ConfigReportGenerator()) - - try: - for section_title, generator in self.persistent_sections: - self.add_section(section_title, generator) - except AttributeError: - pass - - def run(self): - self._readd_sections() - return super(GuruMeditation, self).run() - - -# GuruMeditation must come first to get the correct MRO -class TextGuruMeditation(GuruMeditation, report.TextReport): - """A Text Guru Meditation Report - - This report is the basic human-readable Guru Meditation Report - - It contains the following sections by default - (in addition to any registered persistent sections): - - - Package Information - - - Threads List - - - Green Threads List - - - Process List - - - Configuration Options - - :param version_obj: the version object for the current product - :param traceback: an (optional) frame object providing the actual - traceback for the current thread - """ - - def __init__(self, version_obj, traceback=None): - super(TextGuruMeditation, self).__init__(version_obj, traceback, - 'Guru Meditation') diff --git a/oslo_reports/locale/en_GB/LC_MESSAGES/oslo_reports.po b/oslo_reports/locale/en_GB/LC_MESSAGES/oslo_reports.po deleted file mode 100644 index d4a0452..0000000 --- a/oslo_reports/locale/en_GB/LC_MESSAGES/oslo_reports.po +++ /dev/null @@ -1,18 +0,0 @@ -# Andi Chandler , 2016. #zanata -msgid "" -msgstr "" -"Project-Id-Version: oslo.reports 1.9.1.dev1\n" -"Report-Msgid-Bugs-To: https://bugs.launchpad.net/openstack-i18n/\n" -"POT-Creation-Date: 2016-06-10 16:23+0000\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2016-06-09 11:13+0000\n" -"Last-Translator: Andi Chandler \n" -"Language-Team: English (United Kingdom)\n" -"Language: en-GB\n" -"X-Generator: Zanata 3.7.3\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" - -msgid "Path to a log directory where to create a file" -msgstr "Path to a log directory where to create a file" diff --git a/oslo_reports/models/__init__.py b/oslo_reports/models/__init__.py deleted file mode 100644 index 7bfed3d..0000000 --- a/oslo_reports/models/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides data models - -This module provides both the base data model, -as well as several predefined specific data models -to be used in reports. -""" diff --git a/oslo_reports/models/base.py b/oslo_reports/models/base.py deleted file mode 100644 index 5c121d0..0000000 --- a/oslo_reports/models/base.py +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides the base report model - -This module defines a class representing the basic report -data model from which all data models should inherit (or -at least implement similar functionality). Data models -store unserialized data generated by generators during -the report serialization process. -""" - -import collections as col -import copy - -import six - - -class ReportModel(col.MutableMapping): - """A Report Data Model - - A report data model contains data generated by some - generator method or class. Data may be read or written - using dictionary-style access, and may be read (but not - written) using object-member-style access. Additionally, - a data model may have an associated view. This view is - used to serialize the model when str() is called on the - model. An appropriate object for a view is callable with - a single parameter: the model to be serialized. - - If present, the object passed in as data will be transformed - into a standard python dict. For mappings, this is fairly - straightforward. For sequences, the indices become keys - and the items become values. - - :param data: a sequence or mapping of data to associate with the model - :param attached_view: a view object to attach to this model - """ - - def __init__(self, data=None, attached_view=None): - self.attached_view = attached_view - - if data is not None: - if isinstance(data, col.Mapping): - self.data = dict(data) - elif isinstance(data, col.Sequence): - # convert a list [a, b, c] to a dict {0: a, 1: b, 2: c} - self.data = dict(enumerate(data)) - else: - raise TypeError('Data for the model must be a sequence ' - 'or mapping.') - else: - self.data = {} - - def __str__(self): - self_cpy = copy.deepcopy(self) - for key in self_cpy: - if getattr(self_cpy[key], 'attached_view', None) is not None: - self_cpy[key] = six.text_type(self_cpy[key]) - - if self.attached_view is not None: - return self.attached_view(self_cpy) - else: - raise Exception("Cannot stringify model: no attached view") - - def __repr__(self): - if self.attached_view is not None: - return ("").format(cl=type(self), - dt=self.data, - vw=type(self.attached_view)) - else: - return ("").format(cl=type(self), - dt=self.data) - - def __getitem__(self, attrname): - return self.data[attrname] - - def __setitem__(self, attrname, attrval): - self.data[attrname] = attrval - - def __delitem__(self, attrname): - del self.data[attrname] - - def __contains__(self, key): - return self.data.__contains__(key) - - def __getattr__(self, attrname): - # Needed for deepcopy in Python3. That will avoid an infinite loop - # in __getattr__ . - if 'data' not in self.__dict__: - self.data = {} - - try: - return self.data[attrname] - except KeyError: - # we don't have that key in data, and the - # model class doesn't have that attribute - raise AttributeError( - "'{cl}' object has no attribute '{an}'".format( - cl=type(self).__name__, an=attrname - ) - ) - - def __len__(self): - return len(self.data) - - def __iter__(self): - return self.data.__iter__() - - def set_current_view_type(self, tp, visited=None): - """Set the current view type - - This method attempts to set the current view - type for this model and all submodels by calling - itself recursively on all values, traversing - intervening sequences and mappings when possible, - and ignoring all other objects. - - :param tp: the type of the view ('text', 'json', 'xml', etc) - :param visited: a set of object ids for which the corresponding objects - have already had their view type set - """ - - if visited is None: - visited = set() - - def traverse_obj(obj): - oid = id(obj) - - # don't die on recursive structures, - # and don't treat strings like sequences - if oid in visited or isinstance(obj, six.string_types): - return - - visited.add(oid) - - if hasattr(obj, 'set_current_view_type'): - obj.set_current_view_type(tp, visited=visited) - - if isinstance(obj, col.Sequence): - for item in obj: - traverse_obj(item) - - elif isinstance(obj, col.Mapping): - for val in six.itervalues(obj): - traverse_obj(val) - - traverse_obj(self) diff --git a/oslo_reports/models/conf.py b/oslo_reports/models/conf.py deleted file mode 100644 index e56a5cd..0000000 --- a/oslo_reports/models/conf.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides OpenStack Configuration Model - -This module defines a class representing the data -model for :mod:`oslo_config` configuration options -""" - -from oslo_reports.models import with_default_views as mwdv -from oslo_reports.views.text import generic as generic_text_views - - -class ConfigModel(mwdv.ModelWithDefaultViews): - """A Configuration Options Model - - This model holds data about a set of configuration options - from :mod:`oslo_config`. It supports both the default group - of options and named option groups. - - :param conf_obj: a configuration object - :type conf_obj: :class:`oslo_config.cfg.ConfigOpts` - """ - - def __init__(self, conf_obj): - kv_view = generic_text_views.KeyValueView(dict_sep=": ", - before_dict='') - super(ConfigModel, self).__init__(text_view=kv_view) - - def opt_title(optname, co): - return co._opts[optname]['opt'].name - - def opt_value(opt_obj, value): - if opt_obj['opt'].secret: - return '***' - else: - return value - - self['default'] = dict( - (opt_title(optname, conf_obj), - opt_value(conf_obj._opts[optname], conf_obj[optname])) - for optname in conf_obj._opts - ) - - groups = {} - for groupname in conf_obj._groups: - group_obj = conf_obj._groups[groupname] - curr_group_opts = dict( - (opt_title(optname, group_obj), - opt_value(group_obj._opts[optname], - conf_obj[groupname][optname])) - for optname in group_obj._opts) - groups[group_obj.name] = curr_group_opts - - self.update(groups) diff --git a/oslo_reports/models/process.py b/oslo_reports/models/process.py deleted file mode 100644 index 40af0a1..0000000 --- a/oslo_reports/models/process.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides a process model - -This module defines a class representing a process, -potentially with subprocesses. -""" - -import psutil - -import oslo_reports.models.with_default_views as mwdv -import oslo_reports.views.text.process as text_views - -PS1 = psutil.version_info[0] == 1 - - -class ProcessModel(mwdv.ModelWithDefaultViews): - """A Process Model - - This model holds data about a process, - including references to any subprocesses - - :param process: a :class:`psutil.Process` object - """ - - def __init__(self, process): - super(ProcessModel, self).__init__( - text_view=text_views.ProcessView()) - - self['pid'] = process.pid - self['parent_pid'] = (process.ppid if PS1 else process.ppid()) - if hasattr(process, 'uids'): - self['uids'] = { - 'real': (process.uids.real if PS1 else process.uids().real), - 'effective': (process.uids.effective if PS1 - else process.uids().effective), - 'saved': (process.uids.saved if PS1 else process.uids().saved) - } - else: - self['uids'] = {'real': None, - 'effective': None, - 'saved': None} - - if hasattr(process, 'gids'): - self['gids'] = { - 'real': (process.gids.real if PS1 else process.gids().real), - 'effective': (process.gids.effective if PS1 - else process.gids().effective), - 'saved': (process.gids.saved if PS1 else process.gids().saved) - } - else: - self['gids'] = {'real': None, - 'effective': None, - 'saved': None} - - self['username'] = process.username if PS1 else process.username() - self['command'] = process.cmdline if PS1 else process.cmdline() - self['state'] = process.status if PS1 else process.status() - - children = process.get_children() if PS1 else process.children() - self['children'] = [ProcessModel(pr) for pr in children] diff --git a/oslo_reports/models/threading.py b/oslo_reports/models/threading.py deleted file mode 100644 index 5caca3c..0000000 --- a/oslo_reports/models/threading.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides threading and stack-trace models - -This module defines classes representing thread, green -thread, and stack trace data models -""" - -import traceback - -from oslo_reports.models import with_default_views as mwdv -from oslo_reports.views.text import threading as text_views - - -class StackTraceModel(mwdv.ModelWithDefaultViews): - """A Stack Trace Model - - This model holds data from a python stack trace, - commonly extracted from running thread information - - :param stack_state: the python stack_state object - """ - - def __init__(self, stack_state): - super(StackTraceModel, self).__init__( - text_view=text_views.StackTraceView()) - - if (stack_state is not None): - self['lines'] = [ - {'filename': fn, 'line': ln, 'name': nm, 'code': cd} - for fn, ln, nm, cd in traceback.extract_stack(stack_state) - ] - # FIXME(flepied): under Python3 f_exc_type doesn't exist - # anymore so we lose information about exceptions - if getattr(stack_state, 'f_exc_type', None) is not None: - self['root_exception'] = { - 'type': stack_state.f_exc_type, - 'value': stack_state.f_exc_value} - else: - self['root_exception'] = None - else: - self['lines'] = [] - self['root_exception'] = None - - -class ThreadModel(mwdv.ModelWithDefaultViews): - """A Thread Model - - This model holds data for information about an - individual thread. It holds both a thread id, - as well as a stack trace for the thread - - .. seealso:: - - Class :class:`StackTraceModel` - - :param int thread_id: the id of the thread - :param stack: the python stack state for the current thread - """ - - # threadId, stack in sys._current_frams().items() - def __init__(self, thread_id, stack): - super(ThreadModel, self).__init__(text_view=text_views.ThreadView()) - - self['thread_id'] = thread_id - self['stack_trace'] = StackTraceModel(stack) - - -class GreenThreadModel(mwdv.ModelWithDefaultViews): - """A Green Thread Model - - This model holds data for information about an - individual thread. Unlike the thread model, - it holds just a stack trace, since green threads - do not have thread ids. - - .. seealso:: - - Class :class:`StackTraceModel` - - :param stack: the python stack state for the green thread - """ - - # gr in greenpool.coroutines_running --> gr.gr_frame - def __init__(self, stack): - super(GreenThreadModel, self).__init__( - {'stack_trace': StackTraceModel(stack)}, - text_view=text_views.GreenThreadView()) diff --git a/oslo_reports/models/version.py b/oslo_reports/models/version.py deleted file mode 100644 index 50d2f6c..0000000 --- a/oslo_reports/models/version.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides OpenStack Version Info Model - -This module defines a class representing the data -model for OpenStack package and version information -""" - -from oslo_reports.models import with_default_views as mwdv -from oslo_reports.views.text import generic as generic_text_views - - -class PackageModel(mwdv.ModelWithDefaultViews): - """A Package Information Model - - This model holds information about the current - package. It contains vendor, product, and version - information. - - :param str vendor: the product vendor - :param str product: the product name - :param str version: the product version - """ - - def __init__(self, vendor, product, version): - super(PackageModel, self).__init__( - text_view=generic_text_views.KeyValueView() - ) - - self['vendor'] = vendor - self['product'] = product - self['version'] = version diff --git a/oslo_reports/models/with_default_views.py b/oslo_reports/models/with_default_views.py deleted file mode 100644 index cce9d88..0000000 --- a/oslo_reports/models/with_default_views.py +++ /dev/null @@ -1,81 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -from oslo_reports.models import base as base_model -from oslo_reports.views.json import generic as jsonviews -from oslo_reports.views.text import generic as textviews -from oslo_reports.views.xml import generic as xmlviews - - -class ModelWithDefaultViews(base_model.ReportModel): - """A Model With Default Views of Various Types - - A model with default views has several predefined views, - each associated with a given type. This is often used for - when a submodel should have an attached view, but the view - differs depending on the serialization format - - Parameters are as the superclass, except for any - parameters ending in '_view': these parameters - get stored as default views. - - The default 'default views' are - - text - :class:`oslo_reports.views.text.generic.KeyValueView` - xml - :class:`oslo_reports.views.xml.generic.KeyValueView` - json - :class:`oslo_reports.views.json.generic.KeyValueView` - - .. function:: to_type() - - ('type' is one of the 'default views' defined for this model) - Serializes this model using the default view for 'type' - - :rtype: str - :returns: this model serialized as 'type' - """ - - def __init__(self, *args, **kwargs): - self.views = { - 'text': textviews.KeyValueView(), - 'json': jsonviews.KeyValueView(), - 'xml': xmlviews.KeyValueView() - } - - newargs = copy.copy(kwargs) - for k in kwargs: - if k.endswith('_view'): - self.views[k[:-5]] = kwargs[k] - del newargs[k] - super(ModelWithDefaultViews, self).__init__(*args, **newargs) - - def set_current_view_type(self, tp, visited=None): - self.attached_view = self.views[tp] - super(ModelWithDefaultViews, self).set_current_view_type(tp, visited) - - def __getattr__(self, attrname): - if attrname[:3] == 'to_': - if self.views[attrname[3:]] is not None: - return lambda: self.views[attrname[3:]](self) - else: - raise NotImplementedError(( - "Model {cn.__module__}.{cn.__name__} does not have" + - " a default view for " - "{tp}").format(cn=type(self), tp=attrname[3:])) - else: - return super(ModelWithDefaultViews, self).__getattr__(attrname) diff --git a/oslo_reports/opts.py b/oslo_reports/opts.py deleted file mode 100644 index 324b7f1..0000000 --- a/oslo_reports/opts.py +++ /dev/null @@ -1,71 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -__all__ = [ - 'list_opts', - 'set_defaults', -] - -import copy - -from oslo_config import cfg - -from oslo_reports._i18n import _ - - -_option_group = 'oslo_reports' - -_options = [ - cfg.StrOpt('log_dir', - help=_('Path to a log directory where to create a file')), - cfg.StrOpt('file_event_handler', - help=_('The path to a file to watch for changes to trigger ' - 'the reports, instead of signals. Setting this option ' - 'disables the signal trigger for the reports. If ' - 'application is running as a WSGI application it is ' - 'recommended to use this instead of signals.')), - cfg.IntOpt('file_event_handler_interval', - default=1, - help=_('How many seconds to wait between polls when ' - 'file_event_handler is set')) -] - - -def list_opts(): - """Return a list of oslo.config options available in the library. - - The returned list includes all oslo.config options which may be registered - at runtime by the library. - Each element of the list is a tuple. The first element is the name of the - group under which the list of elements in the second element will be - registered. A group name of None corresponds to the [DEFAULT] group in - config files. - This function is also discoverable via the 'oslo_messaging' entry point - under the 'oslo.config.opts' namespace. - The purpose of this is to allow tools like the Oslo sample config file - generator to discover the options exposed to users by this library. - - :returns: a list of (group_name, opts) tuples - """ - - return [(_option_group, copy.deepcopy(_options))] - - -def set_defaults(conf): - """Set defaults for configuration variables. - - Overrides default options values. - - :param conf: Configuration object, managed by the caller. - :type conf: oslo.config.cfg.ConfigOpts - """ - conf.register_opts(_options, group=_option_group) diff --git a/oslo_reports/report.py b/oslo_reports/report.py deleted file mode 100644 index fa8c07b..0000000 --- a/oslo_reports/report.py +++ /dev/null @@ -1,189 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides Report classes - -This module defines various classes representing reports and report sections. -All reports take the form of a report class containing various report -sections. -""" - -import six - -from oslo_reports.views.text import header as header_views - - -class BasicReport(object): - """A Basic Report - - A Basic Report consists of a collection of :class:`ReportSection` - objects, each of which contains a top-level model and generator. - It collects these sections into a cohesive report which may then - be serialized by calling :func:`run`. - """ - - def __init__(self): - self.sections = [] - self._state = 0 - - def add_section(self, view, generator, index=None): - """Add a section to the report - - This method adds a section with the given view and - generator to the report. An index may be specified to - insert the section at a given location in the list; - If no index is specified, the section is appended to the - list. The view is called on the model which results from - the generator when the report is run. A generator is simply - a method or callable object which takes no arguments and - returns a :class:`oslo_reports.models.base.ReportModel` - or similar object. - - :param view: the top-level view for the section - :param generator: the method or class which generates the model - :param index: the index at which to insert the section - (or None to append it) - :type index: int or None - """ - - if index is None: - self.sections.append(ReportSection(view, generator)) - else: - self.sections.insert(index, ReportSection(view, generator)) - - def run(self): - """Run the report - - This method runs the report, having each section generate - its data and serialize itself before joining the sections - together. The BasicReport accomplishes the joining - by joining the serialized sections together with newlines. - - :rtype: str - :returns: the serialized report - """ - - return "\n".join(six.text_type(sect) for sect in self.sections) - - -class ReportSection(object): - """A Report Section - - A report section contains a generator and a top-level view. When something - attempts to serialize the section by calling str() or unicode() on it, the - section runs the generator and calls the view on the resulting model. - - .. seealso:: - - Class :class:`BasicReport` - :func:`BasicReport.add_section` - - :param view: the top-level view for this section - :param generator: the generator for this section - (any callable object which takes no parameters and returns a data model) - """ - - def __init__(self, view, generator): - self.view = view - self.generator = generator - - def __str__(self): - return self.view(self.generator()) - - -class ReportOfType(BasicReport): - """A Report of a Certain Type - - A ReportOfType has a predefined type associated with it. - This type is automatically propagated down to the each of - the sections upon serialization by wrapping the generator - for each section. - - .. seealso:: - - Class :class:`oslo_reports.models.with_default_view.ModelWithDefaultView` # noqa - (the entire class) - - Class :class:`oslo_reports.models.base.ReportModel` - :func:`oslo_reports.models.base.ReportModel.set_current_view_type` # noqa - - :param str tp: the type of the report - """ - - def __init__(self, tp): - self.output_type = tp - super(ReportOfType, self).__init__() - - def add_section(self, view, generator, index=None): - def with_type(gen): - def newgen(): - res = gen() - try: - res.set_current_view_type(self.output_type) - except AttributeError: - pass - - return res - return newgen - - super(ReportOfType, self).add_section( - view, - with_type(generator), - index - ) - - -class TextReport(ReportOfType): - """A Human-Readable Text Report - - This class defines a report that is designed to be read by a human - being. It has nice section headers, and a formatted title. - - :param str name: the title of the report - """ - - def __init__(self, name): - super(TextReport, self).__init__('text') - self.name = name - # add a title with a generator that creates an empty result model - self.add_section(name, lambda: ('|' * 72) + "\n\n") - - def add_section(self, heading, generator, index=None): - """Add a section to the report - - This method adds a section with the given title, and - generator to the report. An index may be specified to - insert the section at a given location in the list; - If no index is specified, the section is appended to the - list. The view is called on the model which results from - the generator when the report is run. A generator is simply - a method or callable object which takes no arguments and - returns a :class:`oslo_reports.models.base.ReportModel` - or similar object. - - The model is told to serialize as text (if possible) at serialization - time by wrapping the generator. The view model's attached view - (if any) is wrapped in a - :class:`oslo_reports.views.text.header.TitledView` - - :param str heading: the title for the section - :param generator: the method or class which generates the model - :param index: the index at which to insert the section - (or None to append) - :type index: int or None - """ - - super(TextReport, self).add_section(header_views.TitledView(heading), - generator, - index) diff --git a/oslo_reports/tests/__init__.py b/oslo_reports/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/oslo_reports/tests/test_base_report.py b/oslo_reports/tests/test_base_report.py deleted file mode 100644 index 7097a24..0000000 --- a/oslo_reports/tests/test_base_report.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import collections as col -import re - -from oslotest import base -import six - -from oslo_reports.models import base as base_model -from oslo_reports import report - - -class BasicView(object): - def __call__(self, model): - res = "" - for k in sorted(model.keys()): - res += six.text_type(k) + ": " + six.text_type(model[k]) + ";" - return res - - -def basic_generator(): - return base_model.ReportModel(data={'string': 'value', 'int': 1}) - - -class TestBasicReport(base.BaseTestCase): - def setUp(self): - super(TestBasicReport, self).setUp() - - self.report = report.BasicReport() - - def test_add_section(self): - self.report.add_section(BasicView(), basic_generator) - self.assertEqual(len(self.report.sections), 1) - - def test_append_section(self): - self.report.add_section(BasicView(), lambda: {'a': 1}) - self.report.add_section(BasicView(), basic_generator) - - self.assertEqual(len(self.report.sections), 2) - self.assertEqual(self.report.sections[1].generator, basic_generator) - - def test_insert_section(self): - self.report.add_section(BasicView(), lambda: {'a': 1}) - self.report.add_section(BasicView(), basic_generator, 0) - - self.assertEqual(len(self.report.sections), 2) - self.assertEqual(self.report.sections[0].generator, basic_generator) - - def test_basic_render(self): - self.report.add_section(BasicView(), basic_generator) - self.assertEqual(self.report.run(), "int: 1;string: value;") - - -class TestBaseModel(base.BaseTestCase): - def test_submodel_attached_view(self): - class TmpView(object): - def __call__(self, model): - return '{len: ' + six.text_type(len(model.c)) + '}' - - def generate_model_with_submodel(): - base_m = basic_generator() - tv = TmpView() - base_m['submodel'] = base_model.ReportModel(data={'c': [1, 2, 3]}, - attached_view=tv) - return base_m - - self.assertEqual(BasicView()(generate_model_with_submodel()), - 'int: 1;string: value;submodel: {len: 3};') - - def test_str_throws_error_with_no_attached_view(self): - model = base_model.ReportModel(data={'c': [1, 2, 3]}) - self.assertRaisesRegex(Exception, - 'Cannot stringify model: no attached view', - six.text_type, model) - - def test_str_returns_string_with_attached_view(self): - model = base_model.ReportModel(data={'a': 1, 'b': 2}, - attached_view=BasicView()) - - self.assertEqual(six.text_type(model), 'a: 1;b: 2;') - - def test_model_repr(self): - model1 = base_model.ReportModel(data={'a': 1, 'b': 2}, - attached_view=BasicView()) - - model2 = base_model.ReportModel(data={'a': 1, 'b': 2}) - - base_re = r"" - without_view_re = base_re + r"no view>" - - self.assertTrue(re.match(with_view_re, repr(model1))) - self.assertTrue(re.match(without_view_re, repr(model2))) - - def test_getattr(self): - model = base_model.ReportModel(data={'a': 1}) - - self.assertEqual(model.a, 1) - - self.assertRaises(AttributeError, getattr, model, 'b') - - def test_data_as_sequence_is_handled_properly(self): - model = base_model.ReportModel(data=['a', 'b']) - model.attached_view = BasicView() - - # if we don't handle lists properly, we'll get a TypeError here - self.assertEqual('0: a;1: b;', six.text_type(model)) - - def test_immutable_mappings_produce_mutable_models(self): - class SomeImmutableMapping(col.Mapping): - def __init__(self): - self.data = {'a': 2, 'b': 4, 'c': 8} - - def __getitem__(self, key): - return self.data[key] - - def __len__(self): - return len(self.data) - - def __iter__(self): - return iter(self.data) - - mp = SomeImmutableMapping() - model = base_model.ReportModel(data=mp) - model.attached_view = BasicView() - - self.assertEqual('a: 2;b: 4;c: 8;', six.text_type(model)) - - model['d'] = 16 - - self.assertEqual('a: 2;b: 4;c: 8;d: 16;', six.text_type(model)) - self.assertEqual({'a': 2, 'b': 4, 'c': 8}, mp.data) diff --git a/oslo_reports/tests/test_guru_meditation_report.py b/oslo_reports/tests/test_guru_meditation_report.py deleted file mode 100644 index b86bcf3..0000000 --- a/oslo_reports/tests/test_guru_meditation_report.py +++ /dev/null @@ -1,249 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from __future__ import print_function - -import datetime -import os -import re -import signal -import sys -import threading - -# needed to get greenthreads -import fixtures -import greenlet -import mock -from oslotest import base -import six - -import oslo_config -from oslo_config import fixture -from oslo_reports import guru_meditation_report as gmr -from oslo_reports.models import with_default_views as mwdv -from oslo_reports import opts - - -CONF = oslo_config.cfg.CONF -opts.set_defaults(CONF) - - -class FakeVersionObj(object): - def vendor_string(self): - return 'Cheese Shoppe' - - def product_string(self): - return 'Sharp Cheddar' - - def version_string_with_package(self): - return '1.0.0' - - -def skip_body_lines(start_line, report_lines): - curr_line = start_line - while (len(report_lines[curr_line]) == 0 - or report_lines[curr_line][0] != '='): - curr_line += 1 - - return curr_line - - -class GmrConfigFixture(fixture.Config): - def setUp(self): - super(GmrConfigFixture, self).setUp() - - self.conf.set_override( - 'file_event_handler', - '/tmp/file', - group='oslo_reports') - self.conf.set_override( - 'file_event_handler_interval', - 10, - group='oslo_reports') - self.conf.set_override( - 'log_dir', - '/var/fake_log', - group='oslo_reports') - - -class TestGuruMeditationReport(base.BaseTestCase): - def setUp(self): - super(TestGuruMeditationReport, self).setUp() - - self.curr_g = greenlet.getcurrent() - - self.report = gmr.TextGuruMeditation(FakeVersionObj()) - - self.old_stderr = None - - self.CONF = self.useFixture(GmrConfigFixture(CONF)).conf - - def test_basic_report(self): - report_lines = self.report.run().split('\n') - - target_str_header = ['========================================================================', # noqa - '==== Guru Meditation ====', # noqa - '========================================================================', # noqa - '||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||', # noqa - '', - '', - '========================================================================', # noqa - '==== Package ====', # noqa - '========================================================================', # noqa - 'product = Sharp Cheddar', - 'vendor = Cheese Shoppe', - 'version = 1.0.0', - '========================================================================', # noqa - '==== Threads ====', # noqa - '========================================================================'] # noqa - - # first the header and version info... - self.assertEqual(target_str_header, - report_lines[0:len(target_str_header)]) - - # followed by at least one thread... - # NOTE(zqfan): add an optional '-' because sys._current_frames() - # may return a negative thread id on 32 bit operating system. - self.assertTrue(re.match(r'------(\s+)Thread #-?\d+\1\s?------', - report_lines[len(target_str_header)])) - self.assertEqual('', report_lines[len(target_str_header) + 1]) - - # followed by more thread stuff stuff... - curr_line = skip_body_lines(len(target_str_header) + 2, report_lines) - - # followed by at least one green thread - target_str_gt = ['========================================================================', # noqa - '==== Green Threads ====', # noqa - '========================================================================', # noqa - '------ Green Thread ------', # noqa - ''] - end_bound = curr_line + len(target_str_gt) - self.assertEqual(target_str_gt, - report_lines[curr_line:end_bound]) - - # followed by some more green thread stuff - curr_line = skip_body_lines(curr_line + len(target_str_gt), - report_lines) - - # followed by the processes header - target_str_p_head = ['========================================================================', # noqa - '==== Processes ====', # noqa - '========================================================================'] # noqa - end_bound = curr_line + len(target_str_p_head) - self.assertEqual(target_str_p_head, - report_lines[curr_line:end_bound]) - - curr_line += len(target_str_p_head) - - # followed by at least one process - self.assertTrue(re.match("Process \d+ \(under \d+\)", - report_lines[curr_line])) - - # followed by some more process stuff - curr_line = skip_body_lines(curr_line + 1, report_lines) - - # followed finally by the configuration - target_str_config = ['========================================================================', # noqa - '==== Configuration ====', # noqa - '========================================================================', # noqa - ''] - end_bound = curr_line + len(target_str_config) - self.assertEqual(target_str_config, - report_lines[curr_line:end_bound]) - - def test_reg_persistent_section(self): - def fake_gen(): - fake_data = {'cheddar': ['sharp', 'mild'], - 'swiss': ['with holes', 'with lots of holes'], - 'american': ['orange', 'yellow']} - - return mwdv.ModelWithDefaultViews(data=fake_data) - - gmr.TextGuruMeditation.register_section('Cheese Types', fake_gen) - - report_lines = self.report.run() - target_lst = ['========================================================================', # noqa - '==== Cheese Types ====', # noqa - '========================================================================', # noqa - 'american = ', - ' orange', - ' yellow', - 'cheddar = ', - ' mild', - ' sharp', - 'swiss = ', - ' with holes', - ' with lots of holes'] - target_str = '\n'.join(target_lst) - self.assertIn(target_str, report_lines) - - def test_register_autorun(self): - gmr.TextGuruMeditation.setup_autorun(FakeVersionObj()) - self.old_stderr = sys.stderr - sys.stderr = six.StringIO() - - os.kill(os.getpid(), signal.SIGUSR2) - self.assertIn('Guru Meditation', sys.stderr.getvalue()) - - @mock.patch.object(gmr.TextGuruMeditation, '_setup_file_watcher') - def test_register_autorun_without_signals(self, mock_setup_fh): - version = FakeVersionObj() - gmr.TextGuruMeditation.setup_autorun(version, conf=self.CONF) - mock_setup_fh.assert_called_once_with( - '/tmp/file', 10, version, None, '/var/fake_log') - - @mock.patch('os.stat') - @mock.patch('time.sleep') - @mock.patch.object(threading.Thread, 'start') - def test_setup_file_watcher(self, mock_thread, mock_sleep, mock_stat): - version = FakeVersionObj() - mock_stat.return_value.st_mtime = 3 - - gmr.TextGuruMeditation._setup_file_watcher( - self.CONF.oslo_reports.file_event_handler, - self.CONF.oslo_reports.file_event_handler_interval, - version, None, self.CONF.oslo_reports.log_dir) - - mock_stat.assert_called_once_with('/tmp/file') - self.assertEqual(1, mock_thread.called) - - @mock.patch('oslo_utils.timeutils.utcnow', - return_value=datetime.datetime(2014, 1, 1, 12, 0, 0)) - def test_register_autorun_log_dir(self, mock_strtime): - log_dir = self.useFixture(fixtures.TempDir()).path - gmr.TextGuruMeditation.setup_autorun( - FakeVersionObj(), "fake-service", log_dir) - - os.kill(os.getpid(), signal.SIGUSR2) - with open(os.path.join( - log_dir, "fake-service_gurumeditation_20140101120000")) as df: - self.assertIn('Guru Meditation', df.read()) - - @mock.patch.object(gmr.TextGuruMeditation, 'run') - def test_fail_prints_traceback(self, run_mock): - class RunFail(Exception): - pass - - run_mock.side_effect = RunFail() - gmr.TextGuruMeditation.setup_autorun(FakeVersionObj()) - self.old_stderr = sys.stderr - sys.stderr = six.StringIO() - - os.kill(os.getpid(), signal.SIGUSR2) - self.assertIn('RunFail', sys.stderr.getvalue()) - - def tearDown(self): - super(TestGuruMeditationReport, self).tearDown() - if self.old_stderr is not None: - sys.stderr = self.old_stderr diff --git a/oslo_reports/tests/test_openstack_generators.py b/oslo_reports/tests/test_openstack_generators.py deleted file mode 100644 index f5b1cda..0000000 --- a/oslo_reports/tests/test_openstack_generators.py +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2011 OpenStack Foundation. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import threading - -import greenlet -import mock -from oslo_config import cfg -from oslotest import base -import six - -from oslo_reports.generators import conf as os_cgen -from oslo_reports.generators import threading as os_tgen -from oslo_reports.generators import version as os_pgen -from oslo_reports.models import threading as os_tmod - - -class TestOpenstackGenerators(base.BaseTestCase): - def test_thread_generator(self): - model = os_tgen.ThreadReportGenerator()() - # self.assertGreaterEqual(len(model.keys()), 1) - self.assertTrue(len(model.keys()) >= 1) - was_ok = False - for val in model.values(): - self.assertIsInstance(val, os_tmod.ThreadModel) - self.assertIsNotNone(val.stack_trace) - if val.thread_id == threading.current_thread().ident: - was_ok = True - break - - self.assertTrue(was_ok) - - model.set_current_view_type('text') - self.assertIsNotNone(six.text_type(model)) - - def test_thread_generator_tb(self): - class FakeModel(object): - def __init__(self, thread_id, tb): - self.traceback = tb - - with mock.patch('oslo_reports.models' - '.threading.ThreadModel', FakeModel): - model = os_tgen.ThreadReportGenerator("fake traceback")() - curr_thread = model.get(threading.current_thread().ident, None) - self.assertIsNotNone(curr_thread, None) - self.assertEqual("fake traceback", curr_thread.traceback) - - def test_green_thread_generator(self): - curr_g = greenlet.getcurrent() - - model = os_tgen.GreenThreadReportGenerator()() - - # self.assertGreaterEqual(len(model.keys()), 1) - self.assertTrue(len(model.keys()) >= 1) - - was_ok = False - for tm in model.values(): - if tm.stack_trace == os_tmod.StackTraceModel(curr_g.gr_frame): - was_ok = True - break - self.assertTrue(was_ok) - - model.set_current_view_type('text') - self.assertIsNotNone(six.text_type(model)) - - def test_config_model(self): - conf = cfg.ConfigOpts() - conf.register_opt(cfg.StrOpt('crackers', default='triscuit')) - conf.register_opt(cfg.StrOpt('secrets', secret=True, - default='should not show')) - conf.register_group(cfg.OptGroup('cheese', title='Cheese Info')) - conf.register_opt(cfg.IntOpt('sharpness', default=1), - group='cheese') - conf.register_opt(cfg.StrOpt('name', default='cheddar'), - group='cheese') - conf.register_opt(cfg.BoolOpt('from_cow', default=True), - group='cheese') - conf.register_opt(cfg.StrOpt('group_secrets', secret=True, - default='should not show'), - group='cheese') - - model = os_cgen.ConfigReportGenerator(conf)() - model.set_current_view_type('text') - - target_str = ('\ncheese: \n' - ' from_cow = True\n' - ' group_secrets = ***\n' - ' name = cheddar\n' - ' sharpness = 1\n' - '\n' - 'default: \n' - ' crackers = triscuit\n' - ' secrets = ***') - self.assertEqual(target_str, six.text_type(model)) - - def test_package_report_generator(self): - class VersionObj(object): - def vendor_string(self): - return 'Cheese Shoppe' - - def product_string(self): - return 'Sharp Cheddar' - - def version_string_with_package(self): - return '1.0.0' - - model = os_pgen.PackageReportGenerator(VersionObj())() - model.set_current_view_type('text') - - target_str = ('product = Sharp Cheddar\n' - 'vendor = Cheese Shoppe\n' - 'version = 1.0.0') - self.assertEqual(target_str, six.text_type(model)) - - def test_package_report_generator_without_vendor_string(self): - class VersionObj(object): - def product_string(self): - return 'Sharp Cheddar' - - def version_string_with_package(self): - return '1.0.0' - - model = os_pgen.PackageReportGenerator(VersionObj())() - model.set_current_view_type('text') - - target_str = ('product = Sharp Cheddar\n' - 'vendor = None\n' - 'version = 1.0.0') - self.assertEqual(target_str, six.text_type(model)) diff --git a/oslo_reports/tests/test_views.py b/oslo_reports/tests/test_views.py deleted file mode 100644 index 7161ef9..0000000 --- a/oslo_reports/tests/test_views.py +++ /dev/null @@ -1,426 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -import mock -from oslotest import base -import six - -from oslo_reports.models import base as base_model -from oslo_reports.models import with_default_views as mwdv -from oslo_reports import report -from oslo_reports.views import jinja_view as jv -from oslo_reports.views.json import generic as json_generic -from oslo_reports.views.text import generic as text_generic - - -def mwdv_generator(): - return mwdv.ModelWithDefaultViews(data={'string': 'value', 'int': 1}) - - -class TestModelReportType(base.BaseTestCase): - def test_model_with_default_views(self): - model = mwdv_generator() - - model.set_current_view_type('text') - self.assertEqual('int = 1\nstring = value', six.text_type(model)) - - model.set_current_view_type('json') - self.assertEqual('{"int": 1, "string": "value"}', six.text_type(model)) - - model.set_current_view_type('xml') - - self.assertEqual('1value', - six.text_type(model)) - - def test_recursive_type_propagation_with_nested_models(self): - model = mwdv_generator() - model['submodel'] = mwdv_generator() - - model.set_current_view_type('json') - - self.assertEqual(model.submodel.views['json'], - model.submodel.attached_view) - - def test_recursive_type_propagation_with_nested_dicts(self): - nested_model = mwdv.ModelWithDefaultViews(json_view='abc') - data = {'a': 1, 'b': {'c': nested_model}} - top_model = base_model.ReportModel(data=data) - - top_model.set_current_view_type('json') - self.assertEqual(nested_model.attached_view, - nested_model.views['json']) - - def test_recursive_type_propagation_with_nested_lists(self): - nested_model = mwdv_generator() - data = {'a': 1, 'b': [nested_model]} - top_model = base_model.ReportModel(data=data) - - top_model.set_current_view_type('json') - self.assertEqual(nested_model.attached_view, - nested_model.views['json']) - - def test_recursive_type_propogation_on_recursive_structures(self): - nested_model = mwdv_generator() - data = {'a': 1, 'b': [nested_model]} - nested_model['c'] = data - top_model = base_model.ReportModel(data=data) - - top_model.set_current_view_type('json') - self.assertEqual(nested_model.attached_view, - nested_model.views['json']) - del nested_model['c'] - - def test_report_of_type(self): - rep = report.ReportOfType('json') - rep.add_section(lambda x: six.text_type(x), mwdv_generator) - - self.assertEqual('{"int": 1, "string": "value"}', rep.run()) - - # NOTE: this also tests views.text.header - def test_text_report(self): - rep = report.TextReport('Test Report') - rep.add_section('An Important Section', mwdv_generator) - rep.add_section('Another Important Section', mwdv_generator) - - target_str = ('========================================================================\n' # noqa - '==== Test Report ====\n' # noqa - '========================================================================\n' # noqa - '||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n' # noqa - '\n' # noqa - '\n' # noqa - '========================================================================\n' # noqa - '==== An Important Section ====\n' # noqa - '========================================================================\n' # noqa - 'int = 1\n' # noqa - 'string = value\n' # noqa - '========================================================================\n' # noqa - '==== Another Important Section ====\n' # noqa - '========================================================================\n' # noqa - 'int = 1\n' # noqa - 'string = value') # noqa - self.assertEqual(target_str, rep.run()) - - def test_to_type(self): - model = mwdv_generator() - - self.assertEqual('1value', - model.to_xml()) - - -class TestGenericXMLView(base.BaseTestCase): - def setUp(self): - super(TestGenericXMLView, self).setUp() - - self.model = mwdv_generator() - self.model.set_current_view_type('xml') - - def test_dict_serialization(self): - self.model['dt'] = {'a': 1, 'b': 2} - - target_str = ('' - '
12
' - '1' - 'value
') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_list_serialization(self): - self.model['lt'] = ['a', 'b'] - - target_str = ('' - '1' - 'ab' - 'value') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_list_in_dict_serialization(self): - self.model['dt'] = {'a': 1, 'b': [2, 3]} - - target_str = ('' - '
1' - '23
' - '1' - 'value
') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_dict_in_list_serialization(self): - self.model['lt'] = [1, {'b': 2, 'c': 3}] - - target_str = ('' - '1' - '1' - '23' - 'value') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_submodel_serialization(self): - sm = mwdv_generator() - sm.set_current_view_type('xml') - - self.model['submodel'] = sm - - target_str = ('' - '1' - 'value' - '' - '1value' - '' - '') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_wrapper_name(self): - self.model.attached_view.wrapper_name = 'cheese' - - target_str = ('' - '1' - 'value' - '') - self.assertEqual(target_str, six.text_type(self.model)) - - -class TestGenericJSONViews(base.BaseTestCase): - def setUp(self): - super(TestGenericJSONViews, self).setUp() - - self.model = mwdv_generator() - self.model.set_current_view_type('json') - - def test_basic_kv_view(self): - attached_view = json_generic.BasicKeyValueView() - self.model = base_model.ReportModel(data={'string': 'value', 'int': 1}, - attached_view=attached_view) - - self.assertEqual('{"int": 1, "string": "value"}', - six.text_type(self.model)) - - def test_dict_serialization(self): - self.model['dt'] = {'a': 1, 'b': 2} - - target_str = ('{' - '"dt": {"a": 1, "b": 2}, ' - '"int": 1, ' - '"string": "value"' - '}') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_list_serialization(self): - self.model['lt'] = ['a', 'b'] - - target_str = ('{' - '"int": 1, ' - '"lt": ["a", "b"], ' - '"string": "value"' - '}') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_list_in_dict_serialization(self): - self.model['dt'] = {'a': 1, 'b': [2, 3]} - - target_str = ('{' - '"dt": {"a": 1, "b": [2, 3]}, ' - '"int": 1, ' - '"string": "value"' - '}') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_dict_in_list_serialization(self): - self.model['lt'] = [1, {'b': 2, 'c': 3}] - - target_str = ('{' - '"int": 1, ' - '"lt": [1, {"b": 2, "c": 3}], ' - '"string": "value"' - '}') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_submodel_serialization(self): - sm = mwdv_generator() - sm.set_current_view_type('json') - - self.model['submodel'] = sm - - target_str = ('{' - '"int": 1, ' - '"string": "value", ' - '"submodel": {"int": 1, "string": "value"}' - '}') - self.assertEqual(target_str, six.text_type(self.model)) - - -class TestGenericTextViews(base.BaseTestCase): - def setUp(self): - super(TestGenericTextViews, self).setUp() - - self.model = mwdv_generator() - self.model.set_current_view_type('text') - - def test_multi_view(self): - attached_view = text_generic.MultiView() - self.model = base_model.ReportModel(data={}, - attached_view=attached_view) - - self.model['1'] = mwdv_generator() - self.model['2'] = mwdv_generator() - self.model['2']['int'] = 2 - self.model.set_current_view_type('text') - - target_str = ('int = 1\n' - 'string = value\n' - 'int = 2\n' - 'string = value') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_basic_kv_view(self): - attached_view = text_generic.BasicKeyValueView() - self.model = base_model.ReportModel(data={'string': 'value', 'int': 1}, - attached_view=attached_view) - - self.assertEqual('int = 1\nstring = value\n', - six.text_type(self.model)) - - def test_table_view(self): - column_names = ['Column A', 'Column B'] - column_values = ['a', 'b'] - attached_view = text_generic.TableView(column_names, column_values, - 'table') - self.model = base_model.ReportModel(data={}, - attached_view=attached_view) - - self.model['table'] = [{'a': 1, 'b': 2}, {'a': 3, 'b': 4}] - - target_str = (' Column A | Column B \n' # noqa - '------------------------------------------------------------------------\n' # noqa - ' 1 | 2 \n' # noqa - ' 3 | 4 \n') # noqa - - self.assertEqual(target_str, six.text_type(self.model)) - - def test_dict_serialization(self): - self.model['dt'] = {'a': 1, 'b': 2} - - target_str = ('dt = \n' - ' a = 1\n' - ' b = 2\n' - 'int = 1\n' - 'string = value') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_list_serialization(self): - self.model['lt'] = ['a', 'b'] - - target_str = ('int = 1\n' - 'lt = \n' - ' a\n' - ' b\n' - 'string = value') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_list_in_dict_serialization(self): - self.model['dt'] = {'a': 1, 'b': [2, 3]} - - target_str = ('dt = \n' - ' a = 1\n' - ' b = \n' - ' 2\n' - ' 3\n' - 'int = 1\n' - 'string = value') - - self.assertEqual(target_str, six.text_type(self.model)) - - def test_dict_in_list_serialization(self): - self.model['lt'] = [1, {'b': 2, 'c': 3}] - - target_str = ('int = 1\n' - 'lt = \n' - ' 1\n' - ' [dict]\n' - ' b = 2\n' - ' c = 3\n' - 'string = value') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_submodel_serialization(self): - sm = mwdv_generator() - sm.set_current_view_type('text') - - self.model['submodel'] = sm - - target_str = ('int = 1\n' - 'string = value\n' - 'submodel = \n' - ' int = 1\n' - ' string = value') - self.assertEqual(target_str, six.text_type(self.model)) - - def test_custom_indent_string(self): - view = text_generic.KeyValueView(indent_str='~~') - - self.model['lt'] = ['a', 'b'] - self.model.attached_view = view - - target_str = ('int = 1\n' - 'lt = \n' - '~~a\n' - '~~b\n' - 'string = value') - self.assertEqual(target_str, six.text_type(self.model)) - - -def get_open_mocks(rv): - file_mock = mock.MagicMock(name='file_obj') - file_mock.read.return_value = rv - open_mock = mock.MagicMock(name='open') - open_mock().__enter__.return_value = file_mock - return (open_mock, file_mock) - - -class TestJinjaView(base.BaseTestCase): - - TEMPL_STR = "int is {{ int }}, string is {{ string }}" - MM_OPEN, MM_FILE = get_open_mocks(TEMPL_STR) - - def setUp(self): - super(TestJinjaView, self).setUp() - self.model = base_model.ReportModel(data={'int': 1, 'string': 'value'}) - - @mock.mock_open(MM_OPEN) - def test_load_from_file(self): - self.model.attached_view = jv.JinjaView(path='a/b/c/d.jinja.txt') - - self.assertEqual('int is 1, string is value', - six.text_type(self.model)) - self.MM_FILE.assert_called_with_once('a/b/c/d.jinja.txt') - - def test_direct_pass(self): - self.model.attached_view = jv.JinjaView(text=self.TEMPL_STR) - - self.assertEqual('int is 1, string is value', - six.text_type(self.model)) - - def test_load_from_class(self): - class TmpJinjaView(jv.JinjaView): - VIEW_TEXT = TestJinjaView.TEMPL_STR - - self.model.attached_view = TmpJinjaView() - - self.assertEqual('int is 1, string is value', - six.text_type(self.model)) - - def test_is_deepcopiable(self): - view_orig = jv.JinjaView(text=self.TEMPL_STR) - view_cpy = copy.deepcopy(view_orig) - - self.assertIsNot(view_orig, view_cpy) diff --git a/oslo_reports/views/__init__.py b/oslo_reports/views/__init__.py deleted file mode 100644 index 612959b..0000000 --- a/oslo_reports/views/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides predefined views - -This module provides a collection of predefined views -for use in reports. It is separated by type (xml, json, or text). -Each type contains a submodule called 'generic' containing -several basic, universal views for that type. There is also -a predefined view that utilizes Jinja. -""" diff --git a/oslo_reports/views/jinja_view.py b/oslo_reports/views/jinja_view.py deleted file mode 100644 index 5f57dc3..0000000 --- a/oslo_reports/views/jinja_view.py +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides Jinja Views - -This module provides views that utilize the Jinja templating -system for serialization. For more information on Jinja, please -see http://jinja.pocoo.org/ . -""" - -import copy - -import jinja2 - - -class JinjaView(object): - """A Jinja View - - This view renders the given model using the provided Jinja - template. The template can be given in various ways. - If the `VIEw_TEXT` property is defined, that is used as template. - Othewise, if a `path` parameter is passed to the constructor, that - is used to load a file containing the template. If the `path` - parameter is None, the `text` parameter is used as the template. - - The leading newline character and trailing newline character are stripped - from the template (provided they exist). Baseline indentation is - also stripped from each line. The baseline indentation is determined by - checking the indentation of the first line, after stripping off the leading - newline (if any). - - :param str path: the path to the Jinja template - :param str text: the text of the Jinja template - """ - - def __init__(self, path=None, text=None): - try: - self._text = self.VIEW_TEXT - except AttributeError: - if path is not None: - with open(path, 'r') as f: - self._text = f.read() - elif text is not None: - self._text = text - else: - self._text = "" - - if self._text[0] == "\n": - self._text = self._text[1:] - - newtext = self._text.lstrip() - amt = len(self._text) - len(newtext) - if (amt > 0): - base_indent = self._text[0:amt] - lines = self._text.splitlines() - newlines = [] - for line in lines: - if line.startswith(base_indent): - newlines.append(line[amt:]) - else: - newlines.append(line) - self._text = "\n".join(newlines) - - if self._text[-1] == "\n": - self._text = self._text[:-1] - - self._regentemplate = True - self._templatecache = None - - def __call__(self, model): - return self.template.render(**model) - - def __deepcopy__(self, memodict): - res = object.__new__(JinjaView) - res._text = copy.deepcopy(self._text, memodict) - - # regenerate the template on a deepcopy - res._regentemplate = True - res._templatecache = None - - return res - - @property - def template(self): - """Get the Compiled Template - - Gets the compiled template, using a cached copy if possible - (stored in attr:`_templatecache`) or otherwise recompiling - the template if the compiled template is not present or is - invalid (due to attr:`_regentemplate` being set to True). - - :returns: the compiled Jinja template - :rtype: :class:`jinja2.Template` - """ - - if self._templatecache is None or self._regentemplate: - self._templatecache = jinja2.Template(self._text) - self._regentemplate = False - - return self._templatecache - - def _gettext(self): - """Get the Template Text - - Gets the text of the current template - - :returns: the text of the Jinja template - :rtype: str - """ - - return self._text - - def _settext(self, textval): - """Set the Template Text - - Sets the text of the current template, marking it - for recompilation next time the compiled template - is retrived via attr:`template` . - - :param str textval: the new text of the Jinja template - """ - - self._text = textval - self.regentemplate = True - - text = property(_gettext, _settext) diff --git a/oslo_reports/views/json/__init__.py b/oslo_reports/views/json/__init__.py deleted file mode 100644 index 47bd33b..0000000 --- a/oslo_reports/views/json/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides basic JSON views - -This module provides several basic views which serialize -models into JSON. -""" diff --git a/oslo_reports/views/json/generic.py b/oslo_reports/views/json/generic.py deleted file mode 100644 index 5580ba1..0000000 --- a/oslo_reports/views/json/generic.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides generic JSON views - -This modules defines several basic views for serializing -data to JSON. Submodels that have already been serialized -as JSON may have their string values marked with `__is_json__ -= True` using :class:`oslo_reports._utils.StringWithAttrs` -(each of the classes within this module does this automatically, -and non-naive serializers check for this attribute and handle -such strings specially) -""" - -import copy - -from oslo_serialization import jsonutils as json - -from oslo_reports import _utils as utils - - -class BasicKeyValueView(object): - """A Basic Key-Value JSON View - - This view performs a naive serialization of a model - into JSON by simply calling :func:`json.dumps` on the model - """ - - def __call__(self, model): - res = utils.StringWithAttrs(json.dumps(model.data, sort_keys=True)) - res.__is_json__ = True - return res - - -class KeyValueView(object): - """A Key-Value JSON View - - This view performs advanced serialization to a model - into JSON. It does so by first checking all values to - see if they are marked as JSON. If so, they are deserialized - using :func:`json.loads`. Then, the copy of the model with all - JSON deserialized is reserialized into proper nested JSON using - :func:`json.dumps`. - """ - - def __call__(self, model): - # this part deals with subviews that were already serialized - cpy = copy.deepcopy(model) - for key in model.keys(): - if getattr(model[key], '__is_json__', False): - cpy[key] = json.loads(model[key]) - - res = utils.StringWithAttrs(json.dumps(cpy.data, sort_keys=True)) - res.__is_json__ = True - return res diff --git a/oslo_reports/views/text/__init__.py b/oslo_reports/views/text/__init__.py deleted file mode 100644 index c097484..0000000 --- a/oslo_reports/views/text/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides basic text views - -This module provides several basic views which serialize -models into human-readable text. -""" diff --git a/oslo_reports/views/text/generic.py b/oslo_reports/views/text/generic.py deleted file mode 100644 index 5240a87..0000000 --- a/oslo_reports/views/text/generic.py +++ /dev/null @@ -1,203 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides generic text views - -This modules provides several generic views for -serializing models into human-readable text. -""" - -import collections as col - -import six - - -class MultiView(object): - """A Text View Containing Multiple Views - - This view simply serializes each - value in the data model, and then - joins them with newlines (ignoring - the key values altogether). This is - useful for serializing lists of models - (as array-like dicts). - """ - - def __call__(self, model): - res = sorted([six.text_type(model[key]) for key in model]) - return "\n".join(res) - - -class BasicKeyValueView(object): - """A Basic Key-Value Text View - - This view performs a naive serialization of a model into - text using a basic key-value method, where each - key-value pair is rendered as "key = str(value)" - """ - - def __call__(self, model): - res = "" - for key in sorted(model): - res += "{key} = {value}\n".format(key=key, value=model[key]) - - return res - - -class KeyValueView(object): - """A Key-Value Text View - - This view performs an advanced serialization of a model - into text by following the following set of rules: - - key : text - key = text - - rootkey : Mapping - :: - - rootkey = - serialize(key, value) - - key : Sequence - :: - - key = - serialize(item) - - :param str indent_str: the string used to represent one "indent" - :param str key_sep: the separator to use between keys and values - :param str dict_sep: the separator to use after a dictionary root key - :param str list_sep: the separator to use after a list root key - :param str anon_dict: the "key" to use when there is a dict in a list - (does not automatically use the dict separator) - :param before_dict: content to place on the line(s) before the a dict - root key (use None to avoid inserting an extra line) - :type before_dict: str or None - :param before_list: content to place on the line(s) before the a list - root key (use None to avoid inserting an extra line) - :type before_list: str or None - """ - - def __init__(self, - indent_str=' ', - key_sep=' = ', - dict_sep=' = ', - list_sep=' = ', - anon_dict='[dict]', - before_dict=None, - before_list=None): - self.indent_str = indent_str - self.key_sep = key_sep - self.dict_sep = dict_sep - self.list_sep = list_sep - self.anon_dict = anon_dict - self.before_dict = before_dict - self.before_list = before_list - - def __call__(self, model): - def serialize(root, rootkey, indent): - res = [] - if rootkey is not None: - res.append((self.indent_str * indent) + rootkey) - - if isinstance(root, col.Mapping): - if rootkey is None and indent > 0: - res.append((self.indent_str * indent) + self.anon_dict) - elif rootkey is not None: - res[0] += self.dict_sep - if self.before_dict is not None: - res.insert(0, self.before_dict) - - for key in sorted(root): - res.extend(serialize(root[key], key, indent + 1)) - elif (isinstance(root, col.Sequence) and - not isinstance(root, six.string_types)): - if rootkey is not None: - res[0] += self.list_sep - if self.before_list is not None: - res.insert(0, self.before_list) - - for val in sorted(root, key=str): - res.extend(serialize(val, None, indent + 1)) - else: - str_root = six.text_type(root) - if '\n' in str_root: - # we are in a submodel - if rootkey is not None: - res[0] += self.dict_sep - - list_root = [(self.indent_str * (indent + 1)) + line - for line in str_root.split('\n')] - res.extend(list_root) - else: - # just a normal key or list entry - try: - res[0] += self.key_sep + str_root - except IndexError: - res = [(self.indent_str * indent) + str_root] - - return res - - return "\n".join(serialize(model, None, -1)) - - -class TableView(object): - """A Basic Table Text View - - This view performs serialization of data into a basic table with - predefined column names and mappings. Column width is auto-calculated - evenly, column values are automatically truncated accordingly. Values - are centered in the columns. - - :param [str] column_names: the headers for each of the columns - :param [str] column_values: the item name to match each column to in - each row - :param str table_prop_name: the name of the property within the model - containing the row models - """ - - def __init__(self, column_names, column_values, table_prop_name): - self.table_prop_name = table_prop_name - self.column_names = column_names - self.column_values = column_values - self.column_width = (72 - len(column_names) + 1) // len(column_names) - - column_headers = "|".join( - "{{ch[{n}]: ^{width}}}".format(n=n, width=self.column_width) - for n in range(len(column_names)) - ) - - # correct for float-to-int roundoff error - test_fmt = column_headers.format(ch=column_names) - if len(test_fmt) < 72: - column_headers += ' ' * (72 - len(test_fmt)) - - vert_divider = '-' * 72 - self.header_fmt_str = column_headers + "\n" + vert_divider + "\n" - - self.row_fmt_str = "|".join( - "{{cv[{n}]: ^{width}}}".format(n=n, width=self.column_width) - for n in range(len(column_values)) - ) - - def __call__(self, model): - res = self.header_fmt_str.format(ch=self.column_names) - for raw_row in model[self.table_prop_name]: - row = [six.text_type(raw_row[prop_name]) - for prop_name in self.column_values] - # double format is in case we have roundoff error - res += '{0: <72}\n'.format(self.row_fmt_str.format(cv=row)) - - return res diff --git a/oslo_reports/views/text/header.py b/oslo_reports/views/text/header.py deleted file mode 100644 index 30d3700..0000000 --- a/oslo_reports/views/text/header.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Text Views With Headers - -This package defines several text views with headers -""" - -import six - - -class HeaderView(object): - """A Text View With a Header - - This view simply serializes the model and places the given - header on top. - - :param header: the header (can be anything on which str() can be called) - """ - - def __init__(self, header): - self.header = header - - def __call__(self, model): - return six.text_type(self.header) + "\n" + six.text_type(model) - - -class TitledView(HeaderView): - """A Text View With a Title - - This view simply serializes the model, and places - a preformatted header containing the given title - text on top. The title text can be up to 64 characters - long. - - :param str title: the title of the view - """ - - FORMAT_STR = ('=' * 72) + "\n===={0: ^64}====\n" + ('=' * 72) - - def __init__(self, title): - super(TitledView, self).__init__(self.FORMAT_STR.format(title)) diff --git a/oslo_reports/views/text/process.py b/oslo_reports/views/text/process.py deleted file mode 100644 index 26572bb..0000000 --- a/oslo_reports/views/text/process.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2014 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides process view - -This module provides a view for -visualizing processes in human-readable form -""" - -import oslo_reports.views.jinja_view as jv - - -class ProcessView(jv.JinjaView): - """A Process View - - This view displays process models defined by - :class:`oslo_reports.models.process.ProcessModel` - """ - - VIEW_TEXT = ( - "Process {{ pid }} (under {{ parent_pid }}) " - "[ run by: {{ username }} ({{ uids.real|default('unknown uid') }})," - " state: {{ state }} ]\n" - "{% for child in children %}" - " {{ child }}" - "{% endfor %}" - ) diff --git a/oslo_reports/views/text/threading.py b/oslo_reports/views/text/threading.py deleted file mode 100644 index 5b84f30..0000000 --- a/oslo_reports/views/text/threading.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides thread and stack-trace views - -This module provides a collection of views for -visualizing threads, green threads, and stack traces -in human-readable form. -""" - -from oslo_reports.views import jinja_view as jv - - -class StackTraceView(jv.JinjaView): - """A Stack Trace View - - This view displays stack trace models defined by - :class:`oslo_reports.models.threading.StackTraceModel` - """ - - VIEW_TEXT = ( - "{% if root_exception is not none %}" - "Exception: {{ root_exception }}\n" - "------------------------------------\n" - "\n" - "{% endif %}" - "{% for line in lines %}\n" - "{{ line.filename }}:{{ line.line }} in {{ line.name }}\n" - " {% if line.code is not none %}" - "`{{ line.code }}`" - "{% else %}" - "(source not found)" - "{% endif %}\n" - "{% else %}\n" - "No Traceback!\n" - "{% endfor %}" - ) - - -class GreenThreadView(object): - """A Green Thread View - - This view displays a green thread provided by the data - model :class:`oslo_reports.models.threading.GreenThreadModel` - """ - - FORMAT_STR = "------{thread_str: ^60}------" + "\n" + "{stack_trace}" - - def __call__(self, model): - return self.FORMAT_STR.format( - thread_str=" Green Thread ", - stack_trace=model.stack_trace - ) - - -class ThreadView(object): - """A Thread Collection View - - This view displays a python thread provided by the data - model :class:`oslo_reports.models.threading.ThreadModel` # noqa - """ - - FORMAT_STR = "------{thread_str: ^60}------" + "\n" + "{stack_trace}" - - def __call__(self, model): - return self.FORMAT_STR.format( - thread_str=" Thread #{0} ".format(model.thread_id), - stack_trace=model.stack_trace - ) diff --git a/oslo_reports/views/xml/__init__.py b/oslo_reports/views/xml/__init__.py deleted file mode 100644 index a40fec9..0000000 --- a/oslo_reports/views/xml/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides basic XML views - -This module provides several basic views which serialize -models into XML. -""" diff --git a/oslo_reports/views/xml/generic.py b/oslo_reports/views/xml/generic.py deleted file mode 100644 index 21cac78..0000000 --- a/oslo_reports/views/xml/generic.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2013 Red Hat, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""Provides generic XML views - -This modules defines several basic views for serializing -data to XML. Submodels that have already been serialized -as XML may have their string values marked with `__is_xml__ -= True` using :class:`oslo_reports._utils.StringWithAttrs` -(each of the classes within this module does this automatically, -and non-naive serializers check for this attribute and handle -such strings specially) -""" - -import collections as col -import copy -import xml.etree.ElementTree as ET - -import six - -from oslo_reports import _utils as utils - - -class KeyValueView(object): - """A Key-Value XML View - - This view performs advanced serialization of a data model - into XML. It first deserializes any values marked as XML so - that they can be properly reserialized later. It then follows - the following rules to perform serialization: - - key : text/xml - The tag name is the key name, and the contents are the text or xml - key : Sequence - A wrapper tag is created with the key name, and each item is placed - in an 'item' tag - key : Mapping - A wrapper tag is created with the key name, and the serialize is called - on each key-value pair (such that each key gets its own tag) - - :param str wrapper_name: the name of the top-level element - """ - - def __init__(self, wrapper_name="model"): - self.wrapper_name = wrapper_name - - def __call__(self, model): - # this part deals with subviews that were already serialized - cpy = copy.deepcopy(model) - for key, valstr in model.items(): - if getattr(valstr, '__is_xml__', False): - cpy[key] = ET.fromstring(valstr) - - def serialize(rootmodel, rootkeyname): - res = ET.Element(rootkeyname) - - if isinstance(rootmodel, col.Mapping): - for key in sorted(rootmodel): - res.append(serialize(rootmodel[key], key)) - elif (isinstance(rootmodel, col.Sequence) - and not isinstance(rootmodel, six.string_types)): - for val in sorted(rootmodel, key=str): - res.append(serialize(val, 'item')) - elif ET.iselement(rootmodel): - res.append(rootmodel) - else: - res.text = six.text_type(rootmodel) - - return res - - str_ = ET.tostring(serialize(cpy, - self.wrapper_name), - encoding="utf-8").decode("utf-8") - res = utils.StringWithAttrs(str_) - res.__is_xml__ = True - return res diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 56641ec..0000000 --- a/requirements.txt +++ /dev/null @@ -1,11 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -pbr>=1.6 # Apache-2.0 -Jinja2>=2.8 # BSD License (3 clause) -oslo.serialization>=1.10.0 # Apache-2.0 -psutil<2.0.0,>=1.1.1 # BSD -six>=1.9.0 # MIT -oslo.i18n>=2.1.0 # Apache-2.0 -oslo.utils>=3.16.0 # Apache-2.0 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index a37e5db..0000000 --- a/setup.cfg +++ /dev/null @@ -1,61 +0,0 @@ -[metadata] -name = oslo.reports -summary = oslo.reports library -description-file = - README.rst -author = OpenStack -author-email = openstack-dev@lists.openstack.org -home-page = http://launchpad.net/oslo -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.4 - Programming Language :: Python :: 3.5 - -[files] -packages = - oslo_reports - -[pbr] -warnerrors = true -autodoc_index_modules = true -autodoc_exclude_modules = - oslo_reports._i18n - oslo_reports._utils - oslo_reports.tests.* - -[entry_points] -oslo.config.opts = - oslo.reports = oslo_reports.opts:list_opts - -[build_sphinx] -source-dir = doc/source -build-dir = doc/build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/build/html - -[compile_catalog] -directory = oslo_reports/locale -domain = oslo_reports - -[update_catalog] -domain = oslo_reports -output_dir = oslo_reports/locale -input_file = oslo_reports/locale/oslo_reports.pot - -[extract_messages] -keywords = _ gettext ngettext l_ lazy_gettext -mapping_file = babel.cfg -output_file = oslo_reports/locale/oslo_reports.pot - -[wheel] -universal = true diff --git a/setup.py b/setup.py deleted file mode 100644 index 782bb21..0000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT -import setuptools - -# In python < 2.7.4, a lazy loading of package `pbr` will break -# setuptools if some other modules registered functions in `atexit`. -# solution from: http://bugs.python.org/issue15881#msg170215 -try: - import multiprocessing # noqa -except ImportError: - pass - -setuptools.setup( - setup_requires=['pbr>=1.8'], - pbr=True) diff --git a/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index a27784d..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,17 +0,0 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. - -hacking<0.11,>=0.10.0 -oslotest>=1.10.0 # Apache-2.0 - -# These are needed for docs generation -oslosphinx!=3.4.0,>=2.5.0 # Apache-2.0 -sphinx!=1.3b1,<1.3,>=1.2.1 # BSD - -# for testing optional parts -oslo.config>=3.14.0 # Apache-2.0 -eventlet!=0.18.3,>=0.18.2 # MIT -greenlet>=0.3.2 # MIT - -coverage>=3.6 # Apache-2.0 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 83c6ced..0000000 --- a/tox.ini +++ /dev/null @@ -1,38 +0,0 @@ -[tox] -minversion = 1.6 -envlist = py35,py34,py27,pypy,pep8 - -[testenv] -deps = -r{toxinidir}/test-requirements.txt -commands = python setup.py testr --slowest --testr-args='{posargs}' - -[testenv:pep8] -commands = flake8 - -[testenv:venv] -commands = {posargs} - -[testenv:docs] -commands = python setup.py build_sphinx - -[testenv:cover] -commands = python setup.py test --coverage --coverage-package-name=oslo_reports --testr-args='{posargs}' - -[flake8] -# E123, E125 skipped as they are invalid PEP-8. - -show-source = True -ignore = E123,E125 -builtins = _ -exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build - -[hacking] -import_exceptions = - -[testenv:pip-missing-reqs] -# do not install test-requirements as that will pollute the virtualenv for -# determining missing packages -# this also means that pip-missing-reqs must be installed separately, outside -# of the requirements.txt files -deps = pip_missing_reqs -commands = pip-missing-reqs -d --ignore-module=oslo_reports* --ignore-module=pkg_resources --ignore-file=oslo_reports/test.py --ignore-file=oslo_reports/tests/* oslo_reports