diff options
Diffstat (limited to 'ipalib')
-rw-r--r-- | ipalib/capabilities.py | 50 | ||||
-rw-r--r-- | ipalib/frontend.py | 40 | ||||
-rw-r--r-- | ipalib/messages.py | 6 |
3 files changed, 88 insertions, 8 deletions
diff --git a/ipalib/capabilities.py b/ipalib/capabilities.py new file mode 100644 index 00000000..751b93e2 --- /dev/null +++ b/ipalib/capabilities.py @@ -0,0 +1,50 @@ +# Authors: +# Petr Viktorin <pviktori@redhat.com> +# +# Copyright (C) 2012 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +"""List of, and utilities for working with, client capabilities by API version + +The API version is given in ipapython.version.API_VERSION. + +This module defines a dict, ``capabilities``, that maps feature names to API +versions they were introduced in. +""" + +from distutils import version + +VERSION_WITHOUT_CAPABILITIES = u'2.51' + +capabilities = dict( + # messages: Server output may include an extra key, "messages", that + # contains a list of warnings and other messages. + # http://freeipa.org/page/V3/Messages + messages=u'2.52', + +) + + +def client_has_capability(client_version, capability): + """Determine whether the client has the given capability + + :param capability: Name of the capability to test + :param client_version: The API version string reported by the client + """ + + version_tuple = version.LooseVersion(client_version) + + return version_tuple >= version.LooseVersion(capabilities[capability]) diff --git a/ipalib/frontend.py b/ipalib/frontend.py index c27ff138..06259823 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -23,18 +23,19 @@ Base classes for all front-end plugins. import re import inspect +from distutils import version + +from ipapython.version import API_VERSION +from ipapython.ipa_log_manager import root_logger from base import lock, check_name, NameSpace from plugable import Plugin, is_production_mode from parameters import create_param, parse_param_spec, Param, Str, Flag, Password from output import Output, Entry, ListOfEntries from text import _, ngettext - from errors import (ZeroArgumentError, MaxArgumentError, OverlapError, - RequiresRoot, VersionError, RequirementError, OptionError) -from errors import InvocationError + RequiresRoot, VersionError, RequirementError, OptionError, InvocationError) from constants import TYPE_ERROR -from ipapython.version import API_VERSION -from distutils import version +from ipalib import messages RULE_FLAG = 'validation_rule' @@ -740,11 +741,17 @@ class Command(HasParam): performs is executed remotely. """ if self.api.env.in_server: - if 'version' in options: + version_provided = 'version' in options + if version_provided: self.verify_client_version(options['version']) else: options['version'] = API_VERSION - return self.execute(*args, **options) + result = self.execute(*args, **options) + if not version_provided: + messages.add_message( + API_VERSION, result, + messages.VersionMissing(server_version=API_VERSION)) + return result return self.forward(*args, **options) def execute(self, *args, **kw): @@ -914,7 +921,7 @@ class Command(HasParam): nice, dict, type(output), output) ) expected_set = set(self.output) - actual_set = set(output) + actual_set = set(output) - set(['messages']) if expected_set != actual_set: missing = expected_set - actual_set if missing: @@ -945,6 +952,21 @@ class Command(HasParam): continue yield param + def log_messages(self, output, logger): + logger_functions = dict( + debug=logger.debug, + info=logger.info, + warning=logger.warning, + error=logger.error, + ) + for message in output.get('messages', ()): + try: + function = logger_functions[message['type']] + except KeyError: + logger.error('Server sent a message with a wrong type') + function = logger.error + function(message.get('message')) + def output_for_cli(self, textui, output, *args, **options): """ Generic output method. Prints values the output argument according @@ -963,6 +985,8 @@ class Command(HasParam): rv = 0 + self.log_messages(output, root_logger) + order = [p.name for p in self.output_params()] if options.get('all', False): order.insert(0, 'dn') diff --git a/ipalib/messages.py b/ipalib/messages.py index 619e81d5..e5b76a52 100644 --- a/ipalib/messages.py +++ b/ipalib/messages.py @@ -35,6 +35,12 @@ from inspect import isclass from ipalib.constants import TYPE_ERROR from ipalib.text import _ as ugettext from ipalib.text import Gettext, NGettext +from ipalib.capabilities import client_has_capability + + +def add_message(version, result, message): + if client_has_capability(version, 'messages'): + result.setdefault('messages', []).append(message.to_dict()) def process_message_arguments(obj, format=None, message=None, **kw): |