From ae9ab0545ff06b60df4b66c0ebccb7baa79b8898 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
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 <cheimes@redhat.com>
Reviewed-By: Thomas Woerner <twoerner@redhat.com>
Reviewed-By: Francois Cami <fcami@redhat.com>
---
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