From ae9ab0545ff06b60df4b66c0ebccb7baa79b8898 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 25 Mar 2019 15:59:51 +0100 Subject: [PATCH] Improve config-show to show hidden servers config-show only used to show enabled servers. Now also show hidden servers on separate lines. Additionally include information about KRA and DNS servers. The augmented config-show output makes it easier to diagnose a cluster and simplifies sanity checks. Fixes: https://pagure.io/freeipa/issue/7892 Signed-off-by: Christian Heimes Reviewed-By: Thomas Woerner Reviewed-By: Francois Cami --- ipaserver/plugins/config.py | 56 +++++++++++++++++-- ipaserver/plugins/serverroles.py | 25 ++++++--- ipaserver/servroles.py | 6 ++ .../test_replica_promotion.py | 23 ++++++++ 4 files changed, 97 insertions(+), 13 deletions(-) diff --git a/ipaserver/plugins/config.py b/ipaserver/plugins/config.py index fff58ac656f4fad3491dfa9f95c22b7d54a6da56..58b48935c2c7471ff2ce0bb3f5ce92a9fb47a503 100644 --- a/ipaserver/plugins/config.py +++ b/ipaserver/plugins/config.py @@ -249,6 +249,18 @@ class config(LDAPObject): doc=_('List of all IPA masters'), flags={'virtual_attribute', 'no_create', 'no_update'} ), + Str( + 'ipa_master_hidden_server*', + label=_('Hidden IPA masters'), + doc=_('List of all hidden IPA masters'), + flags={'virtual_attribute', 'no_create', 'no_update'} + ), + Str( + 'pkinit_server_server*', + label=_('IPA master capable of PKINIT'), + doc=_('IPA master which can process PKINIT requests'), + flags={'virtual_attribute', 'no_create', 'no_update'} + ), Str( 'ca_server_server*', label=_('IPA CA servers'), @@ -261,6 +273,12 @@ class config(LDAPObject): doc=_('IPA servers with enabled NTP'), flags={'virtual_attribute', 'no_create', 'no_update'} ), + Str( + 'ca_server_hidden_server*', + label=_('Hidden IPA CA servers'), + doc=_('Hidden IPA servers configured as certificate authority'), + flags={'virtual_attribute', 'no_create', 'no_update'} + ), Str( 'ca_renewal_master_server?', label=_('IPA CA renewal master'), @@ -268,9 +286,15 @@ class config(LDAPObject): flags={'virtual_attribute', 'no_create'} ), Str( - 'pkinit_server_server*', - label=_('IPA master capable of PKINIT'), - doc=_('IPA master which can process PKINIT requests'), + 'kra_server_server*', + label=_('IPA KRA servers'), + doc=_('IPA servers configured as key recovery agent'), + flags={'virtual_attribute', 'no_create', 'no_update'} + ), + Str( + 'kra_server_hidden_server*', + label=_('Hidden IPA KRA servers'), + doc=_('Hidden IPA servers configured as key recovery agent'), flags={'virtual_attribute', 'no_create', 'no_update'} ), Str( @@ -279,7 +303,25 @@ class config(LDAPObject): label=_('Domain resolution order'), doc=_('colon-separated list of domains used for short name' ' qualification') - ) + ), + Str( + 'dns_server_server*', + label=_('IPA DNS servers'), + doc=_('IPA servers configured as domain name server'), + flags={'virtual_attribute', 'no_create', 'no_update'} + ), + Str( + 'dns_server_hidden_server*', + label=_('Hidden IPA DNS servers'), + doc=_('Hidden IPA servers configured as domain name server'), + flags={'virtual_attribute', 'no_create', 'no_update'} + ), + Str( + 'dnssec_key_master_server?', + label=_('IPA DNSSec key master'), + doc=_('DNSec key master'), + flags={'virtual_attribute', 'no_create', 'no_update'} + ), ) def get_dn(self, *keys, **kwargs): @@ -560,7 +602,8 @@ class config_mod(LDAPUpdate): def post_callback(self, ldap, dn, entry_attrs, *keys, **options): self.obj.show_servroles_attributes( - entry_attrs, "CA server", "IPA master", "NTP server", **options) + entry_attrs, "CA server", "KRA server", "IPA master", + "NTP server", "DNS server", **options) return dn @@ -570,5 +613,6 @@ class config_show(LDAPRetrieve): def post_callback(self, ldap, dn, entry_attrs, *keys, **options): self.obj.show_servroles_attributes( - entry_attrs, "CA server", "IPA master", "NTP server", **options) + entry_attrs, "CA server", "KRA server", "IPA master", + "NTP server", "DNS server", **options) return dn diff --git a/ipaserver/plugins/serverroles.py b/ipaserver/plugins/serverroles.py index 0abf48ae5295be5f622bf8c90d32e7adff5e6cf7..5bba84972a5828b6c7230d0d0d858e6683e5986b 100644 --- a/ipaserver/plugins/serverroles.py +++ b/ipaserver/plugins/serverroles.py @@ -45,7 +45,9 @@ import six from ipalib import errors, _ from ipalib.backend import Backend from ipalib.plugable import Registry -from ipaserver.servroles import (attribute_instances, ENABLED, role_instances) +from ipaserver.servroles import ( + attribute_instances, ENABLED, HIDDEN, role_instances +) from ipaserver.servroles import SingleValuedServerAttribute @@ -81,17 +83,26 @@ class serverroles(Backend): raise errors.NotFound( reason=_("{role}: role not found".format(role=role_name))) - def _get_enabled_masters(self, role_name): + def _get_masters(self, role_name, include_hidden): result = {} role = self._get_role(role_name) + role_states = role.status(self.api, server=None) enabled_masters = [ - r[u'server_server'] for r in role.status(self.api, server=None) if - r[u'status'] == ENABLED] - + r[u'server_server'] for r in role_states if + r[u'status'] == ENABLED + ] if enabled_masters: result.update({role.attr_name: enabled_masters}) + if include_hidden and role.attr_name_hidden is not None: + hidden_masters = [ + r[u'server_server'] for r in role_states if + r[u'status'] == HIDDEN + ] + if hidden_masters: + result.update({role.attr_name_hidden: hidden_masters}) + return result def _get_assoc_attributes(self, role_name): @@ -131,8 +142,8 @@ class serverroles(Backend): return self._get_role(role_servrole).status( self.api, server=server_server) - def config_retrieve(self, servrole): - result = self._get_enabled_masters(servrole) + def config_retrieve(self, servrole, include_hidden=True): + result = self._get_masters(servrole, include_hidden=include_hidden) try: assoc_attributes = self._get_assoc_attributes(servrole) diff --git a/ipaserver/servroles.py b/ipaserver/servroles.py index 9c963be53527bb955ebf2b8cec7960f0d90717a4..0988cbdd7eac599ef26c89a015523b2d92e9502f 100644 --- a/ipaserver/servroles.py +++ b/ipaserver/servroles.py @@ -104,6 +104,12 @@ class LDAPBasedProperty(object): def __init__(self, attr_name, name): self.attr_name = attr_name self.name = name + # for hidden services, insert hidden before '_server' suffix + if attr_name.endswith(u'_server'): + parts = attr_name.rsplit(u'_', 1) + self.attr_name_hidden = u'{}_hidden_server'.format(parts[0]) + else: + self.attr_name_hidden = None @six.add_metaclass(abc.ABCMeta) diff --git a/ipatests/test_integration/test_replica_promotion.py b/ipatests/test_integration/test_replica_promotion.py index a4f3e402ce5d6f74af4bd6fed9376f0f039f297a..3be2ea95fa2325edfc74cbb902ce0a5966aa82d7 100644 --- a/ipatests/test_integration/test_replica_promotion.py +++ b/ipatests/test_integration/test_replica_promotion.py @@ -851,11 +851,32 @@ class TestHiddenReplicaPromotion(IntegrationTest): expected = 'Role status: {}'.format(status) assert expected in result.stdout_text + def _check_config(self, enabled=(), hidden=()): + enabled = {host.hostname for host in enabled} + hidden = {host.hostname for host in hidden} + services = [ + 'IPA masters', 'IPA CA servers', 'IPA KRA servers', + 'IPA DNS servers' + ] + + result = self.master.run_command(['ipa', 'config-show']) + values = {} + for line in result.stdout_text.split('\n'): + if ':' not in line: + continue + k, v = line.split(':', 1) + values[k.strip()] = {item.strip() for item in v.split(',')} + + for service in services: + assert values[service] == enabled + assert values['Hidden {}'.format(service)] == hidden + def test_hidden_replica_install(self): # TODO: check that all services are running on hidden replica self._check_server_role(self.master, 'enabled') self._check_server_role(self.replicas[0], 'hidden') self._check_dnsrecords([self.master], [self.replicas[0]]) + self._check_config([self.master], [self.replicas[0]]) def test_hidden_replica_promote(self): self.replicas[0].run_command([ @@ -864,6 +885,8 @@ class TestHiddenReplicaPromotion(IntegrationTest): ]) self._check_server_role(self.replicas[0], 'enabled') self._check_dnsrecords([self.master, self.replicas[0]]) + self._check_config([self.master, self.replicas[0]]) + result = self.replicas[0].run_command([ 'ipa', 'server-state', self.replicas[0].hostname, '--state=enabled' -- 2.20.1