diff --git a/cinder/cmd/api.py b/cinder/cmd/api.py index 418bba98331..1fbaa055b86 100644 --- a/cinder/cmd/api.py +++ b/cinder/cmd/api.py @@ -29,13 +29,13 @@ warnings.simplefilter('once', DeprecationWarning) from oslo_config import cfg from oslo_log import log as logging +from oslo_reports import guru_meditation_report as gmr from cinder import i18n i18n.enable_lazy() # Need to register global_opts from cinder.common import config # noqa -from cinder.openstack.common.report import guru_meditation_report as gmr from cinder import rpc from cinder import service from cinder import utils diff --git a/cinder/cmd/backup.py b/cinder/cmd/backup.py index 455fda09cb7..888d858f687 100644 --- a/cinder/cmd/backup.py +++ b/cinder/cmd/backup.py @@ -25,6 +25,7 @@ warnings.simplefilter('once', DeprecationWarning) import eventlet from oslo_config import cfg from oslo_log import log as logging +from oslo_reports import guru_meditation_report as gmr eventlet.monkey_patch() @@ -34,7 +35,6 @@ i18n.enable_lazy() # Need to register global_opts from cinder.common import config # noqa from cinder import objects -from cinder.openstack.common.report import guru_meditation_report as gmr from cinder import service from cinder import utils from cinder import version diff --git a/cinder/cmd/scheduler.py b/cinder/cmd/scheduler.py index 53a82067256..8bbb6f7e49c 100644 --- a/cinder/cmd/scheduler.py +++ b/cinder/cmd/scheduler.py @@ -27,13 +27,13 @@ warnings.simplefilter('once', DeprecationWarning) from oslo_config import cfg from oslo_log import log as logging +from oslo_reports import guru_meditation_report as gmr from cinder import i18n i18n.enable_lazy() # Need to register global_opts from cinder.common import config # noqa -from cinder.openstack.common.report import guru_meditation_report as gmr from cinder import service from cinder import utils from cinder import version diff --git a/cinder/cmd/volume.py b/cinder/cmd/volume.py index 3c103fe15a8..3dc6db99028 100644 --- a/cinder/cmd/volume.py +++ b/cinder/cmd/volume.py @@ -37,6 +37,7 @@ warnings.simplefilter('once', DeprecationWarning) from oslo_config import cfg from oslo_log import log as logging +from oslo_reports import guru_meditation_report as gmr from cinder import i18n i18n.enable_lazy() @@ -44,7 +45,6 @@ i18n.enable_lazy() # Need to register global_opts from cinder.common import config # noqa from cinder.db import api as session -from cinder.openstack.common.report import guru_meditation_report as gmr from cinder import service from cinder import utils from cinder import version diff --git a/cinder/openstack/common/report/__init__.py b/cinder/openstack/common/report/__init__.py deleted file mode 100644 index 35390ecd392..00000000000 --- a/cinder/openstack/common/report/__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:`openstack.common.report.report.BasicReport` ) -is composed of one or more report sections -( :class:`openstack.common.report.report.BasicSection` ), -which contain generators which generate data models -( :class:`openstack.common.report.models.base.ReportModels` ), -which are then serialized by views. -""" diff --git a/cinder/openstack/common/report/generators/__init__.py b/cinder/openstack/common/report/generators/__init__.py deleted file mode 100644 index 68473f22d5a..00000000000 --- a/cinder/openstack/common/report/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:`openstack.common.report.models.base.ReportModel` ). -A generator is any object which is callable with no parameters -and returns a data model. -""" diff --git a/cinder/openstack/common/report/generators/conf.py b/cinder/openstack/common/report/generators/conf.py deleted file mode 100644 index c6a916bfee1..00000000000 --- a/cinder/openstack/common/report/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:`openstack.common.report.models.conf`. -""" - -from oslo_config import cfg - -from cinder.openstack.common.report.models import conf as cm - - -class ConfigReportGenerator(object): - """A Configuration Data Generator - - This generator returns - :class:`openstack.common.report.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/cinder/openstack/common/report/generators/process.py b/cinder/openstack/common/report/generators/process.py deleted file mode 100644 index 57afb7a69b2..00000000000 --- a/cinder/openstack/common/report/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 cinder.openstack.common.report.models import process as pm - - -class ProcessReportGenerator(object): - """A Process Data Generator - - This generator returns a - :class:`openstack.common.report.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/cinder/openstack/common/report/generators/threading.py b/cinder/openstack/common/report/generators/threading.py deleted file mode 100644 index 10c07503f95..00000000000 --- a/cinder/openstack/common/report/generators/threading.py +++ /dev/null @@ -1,86 +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:`openstack.common.report.models.threading`. -""" - -from __future__ import absolute_import - -import sys -import threading - -import greenlet - -from cinder.openstack.common.report.models import threading as tm -from cinder.openstack.common.report.models import with_default_views as mwdv -from cinder.openstack.common.report import utils as rutils -from cinder.openstack.common.report.views.text import generic as text_views - - -class ThreadReportGenerator(object): - """A Thread Data Generator - - This generator returns a collection of - :class:`openstack.common.report.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:`openstack.common.report.models.threading.GreenThreadModel` - objects by introspecting the current python garbage collection - state, and sifting through for :class:`greenlet.greenlet` objects. - - .. seealso:: - - Function :func:`openstack.common.report.utils._find_objects` - """ - - def __call__(self): - threadModels = [ - tm.GreenThreadModel(gr.gr_frame) - for gr in rutils._find_objects(greenlet.greenlet) - ] - - return mwdv.ModelWithDefaultViews(threadModels, - text_view=text_views.MultiView()) diff --git a/cinder/openstack/common/report/generators/version.py b/cinder/openstack/common/report/generators/version.py deleted file mode 100644 index 77e1b3b807d..00000000000 --- a/cinder/openstack/common/report/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:`openstack.common.report.models.version`. -""" - -from cinder.openstack.common.report.models import version as vm - - -class PackageReportGenerator(object): - """A Package Information Data Generator - - This generator returns - :class:`openstack.common.report.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/cinder/openstack/common/report/guru_meditation_report.py b/cinder/openstack/common/report/guru_meditation_report.py deleted file mode 100644 index dd8af3924eb..00000000000 --- a/cinder/openstack/common/report/guru_meditation_report.py +++ /dev/null @@ -1,227 +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 - - CONF = cfg.CONF - # maybe import some options here... - - def main(): - config.parse_args(sys.argv) - logging.setup('blah') - - TextGuruMeditation.register_section('Some Special Section', - special_section_generator) - TextGuruMeditation.setup_autorun(version_object) - - 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 -USR1 $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 os -import signal -import sys - -from oslo_utils import timeutils - -from cinder.openstack.common.report.generators import conf as cgen -from cinder.openstack.common.report.generators import process as prgen -from cinder.openstack.common.report.generators import threading as tgen -from cinder.openstack.common.report.generators import version as pgen -from cinder.openstack.common.report import report - - -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. - - 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): - """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. - - :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 - """ - - if not signum and hasattr(signal, 'SIGUSR1'): - # SIGUSR1 is not supported on all platforms - signum = signal.SIGUSR1 - - if signum: - signal.signal(signum, - lambda sn, tb: cls.handle_signal( - version, service_name, log_dir, tb)) - - @classmethod - def handle_signal(cls, version, service_name, log_dir, traceback): - """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 traceback: the traceback provided to the signal handler - """ - - try: - res = cls(version, traceback).run() - except Exception: - 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/cinder/openstack/common/report/models/__init__.py b/cinder/openstack/common/report/models/__init__.py deleted file mode 100644 index 7bfed3d882b..00000000000 --- a/cinder/openstack/common/report/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/cinder/openstack/common/report/models/base.py b/cinder/openstack/common/report/models/base.py deleted file mode 100644 index d840c5b514b..00000000000 --- a/cinder/openstack/common/report/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] = str(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/cinder/openstack/common/report/models/conf.py b/cinder/openstack/common/report/models/conf.py deleted file mode 100644 index f692d3c76f6..00000000000 --- a/cinder/openstack/common/report/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 cinder.openstack.common.report.models import with_default_views as mwdv -from cinder.openstack.common.report.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/cinder/openstack/common/report/models/process.py b/cinder/openstack/common/report/models/process.py deleted file mode 100644 index 22d1e98f790..00000000000 --- a/cinder/openstack/common/report/models/process.py +++ /dev/null @@ -1,62 +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 cinder.openstack.common.report.models.with_default_views as mwdv -import cinder.openstack.common.report.views.text.process as text_views - - -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 hasattr(process, 'uids'): - self['uids'] = {'real': process.uids.real, - 'effective': process.uids.effective, - 'saved': process.uids.saved} - else: - self['uids'] = {'real': None, - 'effective': None, - 'saved': None} - - if hasattr(process, 'gids'): - self['gids'] = {'real': process.gids.real, - 'effective': process.gids.effective, - 'saved': process.gids.saved} - else: - self['gids'] = {'real': None, - 'effective': None, - 'saved': None} - - self['username'] = process.username - self['command'] = process.cmdline - self['state'] = process.status - - self['children'] = [ProcessModel(pr) for pr in process.get_children()] diff --git a/cinder/openstack/common/report/models/threading.py b/cinder/openstack/common/report/models/threading.py deleted file mode 100644 index 94ccfcd987d..00000000000 --- a/cinder/openstack/common/report/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 cinder.openstack.common.report.models import with_default_views as mwdv -from cinder.openstack.common.report.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/cinder/openstack/common/report/models/version.py b/cinder/openstack/common/report/models/version.py deleted file mode 100644 index 7602ce2a296..00000000000 --- a/cinder/openstack/common/report/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 cinder.openstack.common.report.models import with_default_views as mwdv -from cinder.openstack.common.report.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/cinder/openstack/common/report/models/with_default_views.py b/cinder/openstack/common/report/models/with_default_views.py deleted file mode 100644 index 43f6cbe8bde..00000000000 --- a/cinder/openstack/common/report/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 cinder.openstack.common.report.models import base as base_model -from cinder.openstack.common.report.views.json import generic as jsonviews -from cinder.openstack.common.report.views.text import generic as textviews -from cinder.openstack.common.report.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:`openstack.common.report.views.text.generic.KeyValueView` - xml - :class:`openstack.common.report.views.xml.generic.KeyValueView` - json - :class:`openstack.common.report.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/cinder/openstack/common/report/report.py b/cinder/openstack/common/report/report.py deleted file mode 100644 index 96b070afdd5..00000000000 --- a/cinder/openstack/common/report/report.py +++ /dev/null @@ -1,187 +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. -""" - -from cinder.openstack.common.report.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:`openstack.common.report.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(str(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() 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:`openstack.common.report.models.with_default_view.ModelWithDefaultView` # noqa - (the entire class) - - Class :class:`openstack.common.report.models.base.ReportModel` - :func:`openstack.common.report.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:`openstack.common.report.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:`openstack.common.report.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/cinder/openstack/common/report/utils.py b/cinder/openstack/common/report/utils.py deleted file mode 100644 index fb71e36ae91..00000000000 --- a/cinder/openstack/common/report/utils.py +++ /dev/null @@ -1,46 +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 gc - - -class StringWithAttrs(str): - """A String that can have arbitrary attributes - """ - - pass - - -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)] diff --git a/cinder/openstack/common/report/views/__init__.py b/cinder/openstack/common/report/views/__init__.py deleted file mode 100644 index 612959b2e0e..00000000000 --- a/cinder/openstack/common/report/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/cinder/openstack/common/report/views/jinja_view.py b/cinder/openstack/common/report/views/jinja_view.py deleted file mode 100644 index 5f57dc34ab8..00000000000 --- a/cinder/openstack/common/report/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/cinder/openstack/common/report/views/json/__init__.py b/cinder/openstack/common/report/views/json/__init__.py deleted file mode 100644 index 47bd33b6f98..00000000000 --- a/cinder/openstack/common/report/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/cinder/openstack/common/report/views/json/generic.py b/cinder/openstack/common/report/views/json/generic.py deleted file mode 100644 index f2769e31c53..00000000000 --- a/cinder/openstack/common/report/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:`openstack.common.report.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 cinder.openstack.common.report 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)) - 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/cinder/openstack/common/report/views/text/__init__.py b/cinder/openstack/common/report/views/text/__init__.py deleted file mode 100644 index c0974844365..00000000000 --- a/cinder/openstack/common/report/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/cinder/openstack/common/report/views/text/generic.py b/cinder/openstack/common/report/views/text/generic.py deleted file mode 100644 index 3b30a07079c..00000000000 --- a/cinder/openstack/common/report/views/text/generic.py +++ /dev/null @@ -1,202 +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 = [str(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 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 = str(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[" + str(n) + "]: ^" + str(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[" + str(n) + "]: ^" + str(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 = [str(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/cinder/openstack/common/report/views/text/header.py b/cinder/openstack/common/report/views/text/header.py deleted file mode 100644 index 58d06c0d3ef..00000000000 --- a/cinder/openstack/common/report/views/text/header.py +++ /dev/null @@ -1,51 +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 -""" - - -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 str(self.header) + "\n" + str(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/cinder/openstack/common/report/views/text/process.py b/cinder/openstack/common/report/views/text/process.py deleted file mode 100644 index c7d7f12d66f..00000000000 --- a/cinder/openstack/common/report/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 formm -""" - -import cinder.openstack.common.report.views.jinja_view as jv - - -class ProcessView(jv.JinjaView): - """A Process View - - This view displays process models defined by - :class:`openstack.common.report.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/cinder/openstack/common/report/views/text/threading.py b/cinder/openstack/common/report/views/text/threading.py deleted file mode 100644 index c4a11c07997..00000000000 --- a/cinder/openstack/common/report/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 cinder.openstack.common.report.views import jinja_view as jv - - -class StackTraceView(jv.JinjaView): - """A Stack Trace View - - This view displays stack trace models defined by - :class:`openstack.common.report.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:`openstack.common.report.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:`openstack.common.report.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/cinder/openstack/common/report/views/xml/__init__.py b/cinder/openstack/common/report/views/xml/__init__.py deleted file mode 100644 index a40fec984d3..00000000000 --- a/cinder/openstack/common/report/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/cinder/openstack/common/report/views/xml/generic.py b/cinder/openstack/common/report/views/xml/generic.py deleted file mode 100644 index 59c3f486107..00000000000 --- a/cinder/openstack/common/report/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:`openstack.common.report.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 cinder.openstack.common.report 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 = str(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/doc/source/devref/gmr.rst b/doc/source/devref/gmr.rst index 3b098d9f1f3..3d0db39832a 100644 --- a/doc/source/devref/gmr.rst +++ b/doc/source/devref/gmr.rst @@ -64,7 +64,7 @@ Cinder version module: .. code-block:: python - from cinder.openstack.common.report import guru_meditation_report as gmr + from oslo_reports import guru_meditation_report as gmr from cinder import version Then, register any additional sections (optional): @@ -87,4 +87,5 @@ Extending the GMR As mentioned above, additional sections can be added to the GMR for a particular executable. For more information, see the inline documentation -under :mod:`cinder.openstack.common.report` \ No newline at end of file +about oslo.reports: +`oslo.reports `_ \ No newline at end of file diff --git a/openstack-common.conf b/openstack-common.conf index 0764cfef9a9..9749b729d9b 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -10,13 +10,6 @@ module=install_venv_common module=scheduler module=scheduler.filters module=scheduler.weights -module=report -module=report.generators -module=report.models -module=report.views -module=report.views.json -module=report.views.text -module=report.views.xml # The base module to hold the copy of openstack.common base=cinder diff --git a/requirements.txt b/requirements.txt index 19e6a448b38..7ad05b34883 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,6 @@ Babel>=1.3 eventlet>=0.17.4 greenlet>=0.3.2 iso8601>=0.1.9 -Jinja2>=2.6 # BSD License (3 clause) keystonemiddleware>=1.5.0 kombu>=3.0.7 lxml>=2.3 @@ -21,6 +20,7 @@ oslo.log>=1.2.0 # Apache-2.0 oslo.messaging!=1.12.0,>=1.8.0 # Apache-2.0 oslo.middleware!=2.0.0,>=1.2.0 # Apache-2.0 oslo.policy>=0.5.0 # Apache-2.0 +oslo.reports>=0.1.0 # Apache-2.0 oslo.rootwrap>=2.0.0 # Apache-2.0 oslo.serialization>=1.4.0 # Apache-2.0 oslo.service>=0.1.0 # Apache-2.0 @@ -30,7 +30,6 @@ osprofiler>=0.3.0 # Apache-2.0 paramiko>=1.13.0 Paste PasteDeploy>=1.5.0 -psutil<2.0.0,>=1.1.1 pycrypto>=2.6 pyparsing>=2.0.1 python-barbicanclient>=3.0.1