summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/capabilities.py50
-rw-r--r--ipalib/frontend.py40
-rw-r--r--ipalib/messages.py6
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):