summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Vobornik <pvoborni@redhat.com>2015-05-22 09:50:09 +0200
committerPetr Vobornik <pvoborni@redhat.com>2015-06-04 12:06:31 +0200
commitb189e66298816c3414e027c914b5e62f30512330 (patch)
tree891756fc8fb9702e31eb89ef83997156452c7f74
parentf87324df546055df1e7d038e63c04bb0d2250f55 (diff)
downloadfreeipa-b189e66298816c3414e027c914b5e62f30512330.tar.gz
freeipa-b189e66298816c3414e027c914b5e62f30512330.tar.xz
freeipa-b189e66298816c3414e027c914b5e62f30512330.zip
topology: ipa management commands
ipalib part of topology management Design: - http://www.freeipa.org/page/V4/Manage_replication_topology https://fedorahosted.org/freeipa/ticket/4302 Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
-rw-r--r--API.txt155
-rw-r--r--VERSION4
-rw-r--r--ipalib/constants.py1
-rw-r--r--ipalib/plugins/topology.py385
4 files changed, 543 insertions, 2 deletions
diff --git a/API.txt b/API.txt
index 7574bc900..c47d800b1 100644
--- a/API.txt
+++ b/API.txt
@@ -4560,6 +4560,161 @@ option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: PrimaryKey('value', None, None)
+command: topologysegment_add
+args: 2,13,3
+arg: Str('topologysuffixcn', cli_name='topologysuffix', multivalue=False, primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, primary_key=True, required=True)
+option: Str('addattr*', cli_name='addattr', exclude='webui')
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: StrEnum('iparepltoposegmentdirection', attribute=True, cli_name='direction', default=u'both', multivalue=False, required=True, values=(u'both', u'left-right', u'right-left', u'none'))
+option: Str('iparepltoposegmentleftnode', attribute=True, cli_name='leftnode', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$', required=True)
+option: Str('iparepltoposegmentrightnode', attribute=True, cli_name='rightnode', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$', required=True)
+option: StrEnum('nsds5replicaenabled', attribute=True, cli_name='enabled', multivalue=False, required=False, values=(u'on', u'off'))
+option: Str('nsds5replicastripattrs', attribute=True, cli_name='stripattrs', multivalue=False, required=False)
+option: Str('nsds5replicatedattributelist', attribute=True, cli_name='replattrs', multivalue=False, required=False)
+option: Str('nsds5replicatedattributelisttotal', attribute=True, cli_name='replattrstotal', multivalue=False, required=False)
+option: Int('nsds5replicatimeout', attribute=True, cli_name='timeout', minvalue=0, multivalue=False, required=False)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('setattr*', cli_name='setattr', exclude='webui')
+option: Str('version?', exclude='webui')
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: PrimaryKey('value', None, None)
+command: topologysegment_del
+args: 2,2,3
+arg: Str('topologysuffixcn', cli_name='topologysuffix', multivalue=False, primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=True, primary_key=True, query=True, required=True)
+option: Flag('continue', autofill=True, cli_name='continue', default=False)
+option: Str('version?', exclude='webui')
+output: Output('result', <type 'dict'>, None)
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: ListOfPrimaryKeys('value', None, None)
+command: topologysegment_find
+args: 2,15,4
+arg: Str('topologysuffixcn', cli_name='topologysuffix', multivalue=False, primary_key=True, query=True, required=True)
+arg: Str('criteria?', noextrawhitespace=False)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('cn', attribute=True, autofill=False, cli_name='name', maxlength=255, multivalue=False, primary_key=True, query=True, required=False)
+option: StrEnum('iparepltoposegmentdirection', attribute=True, autofill=False, cli_name='direction', default=u'both', multivalue=False, query=True, required=False, values=(u'both', u'left-right', u'right-left', u'none'))
+option: Str('iparepltoposegmentleftnode', attribute=True, autofill=False, cli_name='leftnode', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$', query=True, required=False)
+option: Str('iparepltoposegmentrightnode', attribute=True, autofill=False, cli_name='rightnode', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$', query=True, required=False)
+option: StrEnum('nsds5replicaenabled', attribute=True, autofill=False, cli_name='enabled', multivalue=False, query=True, required=False, values=(u'on', u'off'))
+option: Str('nsds5replicastripattrs', attribute=True, autofill=False, cli_name='stripattrs', multivalue=False, query=True, required=False)
+option: Str('nsds5replicatedattributelist', attribute=True, autofill=False, cli_name='replattrs', multivalue=False, query=True, required=False)
+option: Str('nsds5replicatedattributelisttotal', attribute=True, autofill=False, cli_name='replattrstotal', multivalue=False, query=True, required=False)
+option: Int('nsds5replicatimeout', attribute=True, autofill=False, cli_name='timeout', minvalue=0, multivalue=False, query=True, required=False)
+option: Flag('pkey_only?', autofill=True, default=False)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Int('sizelimit?', autofill=False, minvalue=0)
+option: Int('timelimit?', autofill=False, minvalue=0)
+option: Str('version?', exclude='webui')
+output: Output('count', <type 'int'>, None)
+output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: Output('truncated', <type 'bool'>, None)
+command: topologysegment_mod
+args: 2,15,3
+arg: Str('topologysuffixcn', cli_name='topologysuffix', multivalue=False, primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, primary_key=True, query=True, required=True)
+option: Str('addattr*', cli_name='addattr', exclude='webui')
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('delattr*', cli_name='delattr', exclude='webui')
+option: StrEnum('iparepltoposegmentdirection', attribute=True, autofill=False, cli_name='direction', default=u'both', multivalue=False, required=False, values=(u'both', u'left-right', u'right-left', u'none'))
+option: Str('iparepltoposegmentleftnode', attribute=True, autofill=False, cli_name='leftnode', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$', required=False)
+option: Str('iparepltoposegmentrightnode', attribute=True, autofill=False, cli_name='rightnode', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$', required=False)
+option: StrEnum('nsds5replicaenabled', attribute=True, autofill=False, cli_name='enabled', multivalue=False, required=False, values=(u'on', u'off'))
+option: Str('nsds5replicastripattrs', attribute=True, autofill=False, cli_name='stripattrs', multivalue=False, required=False)
+option: Str('nsds5replicatedattributelist', attribute=True, autofill=False, cli_name='replattrs', multivalue=False, required=False)
+option: Str('nsds5replicatedattributelisttotal', attribute=True, autofill=False, cli_name='replattrstotal', multivalue=False, required=False)
+option: Int('nsds5replicatimeout', attribute=True, autofill=False, cli_name='timeout', minvalue=0, multivalue=False, required=False)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Flag('rights', autofill=True, default=False)
+option: Str('setattr*', cli_name='setattr', exclude='webui')
+option: Str('version?', exclude='webui')
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: PrimaryKey('value', None, None)
+command: topologysegment_refresh
+args: 2,4,3
+arg: Str('topologysuffixcn', cli_name='topologysuffix', multivalue=False, primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, primary_key=True, query=True, required=True)
+option: Flag('left?', autofill=True, default=False)
+option: Flag('right?', autofill=True, default=False)
+option: Flag('stop?', autofill=True, default=False)
+option: Str('version?', exclude='webui')
+output: Output('result', <type 'bool'>, None)
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: PrimaryKey('value', None, None)
+command: topologysegment_show
+args: 2,4,3
+arg: Str('topologysuffixcn', cli_name='topologysuffix', multivalue=False, primary_key=True, query=True, required=True)
+arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, primary_key=True, query=True, required=True)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Flag('rights', autofill=True, default=False)
+option: Str('version?', exclude='webui')
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: PrimaryKey('value', None, None)
+command: topologysuffix_add
+args: 1,6,3
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True)
+option: Str('addattr*', cli_name='addattr', exclude='webui')
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('iparepltopoconfroot', attribute=True, cli_name='suffix', maxlength=255, multivalue=False, required=True)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Str('setattr*', cli_name='setattr', exclude='webui')
+option: Str('version?', exclude='webui')
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: PrimaryKey('value', None, None)
+command: topologysuffix_del
+args: 1,2,3
+arg: Str('cn', attribute=True, cli_name='name', multivalue=True, primary_key=True, query=True, required=True)
+option: Flag('continue', autofill=True, cli_name='continue', default=False)
+option: Str('version?', exclude='webui')
+output: Output('result', <type 'dict'>, None)
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: ListOfPrimaryKeys('value', None, None)
+command: topologysuffix_find
+args: 1,8,4
+arg: Str('criteria?', noextrawhitespace=False)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, primary_key=True, query=True, required=False)
+option: Str('iparepltopoconfroot', attribute=True, autofill=False, cli_name='suffix', maxlength=255, multivalue=False, query=True, required=False)
+option: Flag('pkey_only?', autofill=True, default=False)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Int('sizelimit?', autofill=False, minvalue=0)
+option: Int('timelimit?', autofill=False, minvalue=0)
+option: Str('version?', exclude='webui')
+output: Output('count', <type 'int'>, None)
+output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: Output('truncated', <type 'bool'>, None)
+command: topologysuffix_mod
+args: 1,8,3
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
+option: Str('addattr*', cli_name='addattr', exclude='webui')
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Str('delattr*', cli_name='delattr', exclude='webui')
+option: Str('iparepltopoconfroot', attribute=True, autofill=False, cli_name='suffix', maxlength=255, multivalue=False, required=False)
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Flag('rights', autofill=True, default=False)
+option: Str('setattr*', cli_name='setattr', exclude='webui')
+option: Str('version?', exclude='webui')
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: PrimaryKey('value', None, None)
+command: topologysuffix_show
+args: 1,4,3
+arg: Str('cn', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True)
+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
+option: Flag('rights', autofill=True, default=False)
+option: Str('version?', exclude='webui')
+output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
+output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
+output: PrimaryKey('value', None, None)
command: trust_add
args: 1,13,3
arg: Str('cn', attribute=True, cli_name='realm', multivalue=False, primary_key=True, required=True)
diff --git a/VERSION b/VERSION
index 2ad382792..6f6e363eb 100644
--- a/VERSION
+++ b/VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
# #
########################################################
IPA_API_VERSION_MAJOR=2
-IPA_API_VERSION_MINOR=123
-# Last change: rcritten - added service constraint delegation plugin
+IPA_API_VERSION_MINOR=124
+# Last change: pvoborni - added topology management commands
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 96396a236..93d7aaa7b 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -119,6 +119,7 @@ DEFAULT_CONFIG = (
('container_views', DN(('cn', 'views'), ('cn', 'accounts'))),
('container_masters', DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'))),
('container_certprofile', DN(('cn', 'certprofiles'), ('cn', 'ca'))),
+ ('container_topology', DN(('cn', 'topology'), ('cn', 'ipa'), ('cn', 'etc'))),
# Ports, hosts, and URIs:
('xmlrpc_uri', 'http://localhost:8888/ipa/xml'),
diff --git a/ipalib/plugins/topology.py b/ipalib/plugins/topology.py
new file mode 100644
index 000000000..ba99133b4
--- /dev/null
+++ b/ipalib/plugins/topology.py
@@ -0,0 +1,385 @@
+#
+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
+#
+
+from ipalib import api, errors
+from ipalib import Int, Str, Bool, StrEnum, Flag
+from ipalib.plugable import Registry
+from ipalib.plugins.baseldap import (
+ LDAPObject, LDAPSearch, LDAPCreate, LDAPDelete, LDAPUpdate, LDAPQuery,
+ LDAPRetrieve)
+from ipalib import _, ngettext
+from ipalib import output
+from ipapython.dn import DN
+
+
+__doc__ = _("""
+Topology
+
+Management of a replication topology.
+
+Requires minimum domain level 1.
+""")
+
+register = Registry()
+
+MINIMUM_DOMAIN_LEVEL = 1
+
+
+def validate_domain_level(api):
+ current = int(api.Command.domainlevel_get()['result'])
+ if current < MINIMUM_DOMAIN_LEVEL:
+ raise errors.InvalidDomainLevelError(
+ _('Topology management requires minimum domain level {0} '
+ .format(MINIMUM_DOMAIN_LEVEL))
+ )
+
+
+@register()
+class topologysegment(LDAPObject):
+ """
+ Topology segment.
+ """
+ parent_object = 'topologysuffix'
+ container_dn = api.env.container_topology
+ object_name = _('segment')
+ object_name_plural = _('segments')
+ object_class = ['iparepltoposegment']
+ default_attributes = [
+ 'cn',
+ 'ipaReplTopoSegmentdirection', 'ipaReplTopoSegmentrightNode',
+ 'ipaReplTopoSegmentLeftNode', 'nsds5replicastripattrs',
+ 'nsds5replicatedattributelist', 'nsds5replicatedattributelisttotal',
+ 'nsds5replicatimeout', 'nsds5replicaenabled'
+ ]
+ search_display_attributes = [
+ 'cn', 'ipaReplTopoSegmentdirection', 'ipaReplTopoSegmentrightNode',
+ 'ipaReplTopoSegmentLeftNode'
+ ]
+
+ label = _('Topology Segments')
+ label_singular = _('Topology Segment')
+
+ takes_params = (
+ Str(
+ 'cn',
+ maxlength=255,
+ cli_name='name',
+ primary_key=True,
+ label=_('Segment name'),
+ default_from=lambda iparepltoposegmentleftnode, iparepltoposegmentrightnode:
+ '%s-%s' % (iparepltoposegmentleftnode, iparepltoposegmentrightnode),
+ normalizer=lambda value: value.lower(),
+ doc=_('Arbitrary string identifying the segment'),
+ ),
+ Str(
+ 'iparepltoposegmentleftnode',
+ pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$',
+ pattern_errmsg='may only include letters, numbers, -, . and $',
+ maxlength=255,
+ cli_name='leftnode',
+ label=_('Left node'),
+ normalizer=lambda value: value.lower(),
+ doc=_('Left replication node - an IPA server'),
+ ),
+ Str(
+ 'iparepltoposegmentrightnode',
+ pattern='^[a-zA-Z0-9.][a-zA-Z0-9.-]{0,252}[a-zA-Z0-9.$-]?$',
+ pattern_errmsg='may only include letters, numbers, -, . and $',
+ maxlength=255,
+ cli_name='rightnode',
+ label=_('Right node'),
+ normalizer=lambda value: value.lower(),
+ doc=_('Right replication node - an IPA server'),
+ ),
+ StrEnum(
+ 'iparepltoposegmentdirection',
+ cli_name='direction',
+ label=_('Connectivity'),
+ values=(u'both', u'left-right', u'right-left', u'none'),
+ default=u'both',
+ doc=_('Direction of replication between left and right replication '
+ 'node'),
+ ),
+ Str(
+ 'nsds5replicastripattrs?',
+ cli_name='stripattrs',
+ label=_('Attributes to strip'),
+ normalizer=lambda value: value.lower(),
+ doc=_('A space separated list of attributes which are removed from '
+ 'replication updates.')
+ ),
+ Str(
+ 'nsds5replicatedattributelist?',
+ cli_name='replattrs',
+ label='Attributes to replicate',
+ doc=_('Attributes that are not replicated to a consumer server '
+ 'during a fractional update. E.g., `(objectclass=*) '
+ '$ EXCLUDE accountlockout memberof'),
+ ),
+ Str(
+ 'nsds5replicatedattributelisttotal?',
+ cli_name='replattrstotal',
+ label=_('Attributes for total update'),
+ doc=_('Attributes that are not replicated to a consumer server '
+ 'during a total update. E.g. (objectclass=*) $ EXCLUDE '
+ 'accountlockout'),
+ ),
+ Int(
+ 'nsds5replicatimeout?',
+ cli_name='timeout',
+ label=_('Session timeout'),
+ minvalue=0,
+ doc=_('Number of seconds outbound LDAP operations waits for a '
+ 'response from the remote replica before timing out and '
+ 'failing'),
+ ),
+ StrEnum(
+ 'nsds5replicaenabled?',
+ cli_name='enabled',
+ label=_('Replication agreement enabled'),
+ doc=_('Whether a replication agreement is active, meaning whether '
+ 'replication is occurring per that agreement'),
+ values=(u'on', u'off'),
+ ),
+ )
+
+ def validate_nodes(self, ldap, dn, entry_attrs):
+ leftnode = entry_attrs.get('iparepltoposegmentleftnode')
+ rightnode = entry_attrs.get('iparepltoposegmentrightnode')
+
+ if not leftnode and not rightnode:
+ return # nothing to check
+
+ # check if nodes are IPA servers
+ masters = self.api.Command.server_find('', sizelimit=0)['result']
+ m_hostnames = [master['cn'][0].lower() for master in masters]
+
+ if leftnode and leftnode not in m_hostnames:
+ raise errors.ValidationError(
+ name='leftnode',
+ error=_('left node is not a topology node: %(leftnode)s') %
+ dict(leftnode=leftnode)
+ )
+
+ if rightnode and rightnode not in m_hostnames:
+ raise errors.ValidationError(
+ name='rightnode',
+ error=_('right node is not a topology node: %(rightnode)s') %
+ dict(rightnode=rightnode)
+ )
+
+ # prevent creation of reflexive relation
+ key = 'leftnode'
+ if not leftnode or not rightnode: # get missing end
+ _entry_attrs = ldap.get_entry(dn, ['*'])
+ if not leftnode:
+ key = 'rightnode'
+ leftnode = _entry_attrs['iparepltoposegmentleftnode'][0]
+ else:
+ rightnode = _entry_attrs['iparepltoposegmentrightnode'][0]
+
+ if leftnode == rightnode:
+ raise errors.ValidationError(
+ name=key,
+ error=_('left node and right node must not be the same')
+ )
+
+
+@register()
+class topologysegment_find(LDAPSearch):
+ __doc__ = _('Search for topology segments.')
+
+ msg_summary = ngettext(
+ '%(count)d segment matched',
+ '%(count)d segments matched', 0
+ )
+
+
+@register()
+class topologysegment_add(LDAPCreate):
+ __doc__ = _('Add a new segment.')
+
+ msg_summary = _('Added segment "%(value)s"')
+
+ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+ assert isinstance(dn, DN)
+ validate_domain_level(self.api)
+ self.obj.validate_nodes(ldap, dn, entry_attrs)
+ return dn
+
+
+@register()
+class topologysegment_del(LDAPDelete):
+ __doc__ = _('Delete a segment.')
+
+ msg_summary = _('Deleted segment "%(value)s"')
+
+ def pre_callback(self, ldap, dn, *keys, **options):
+ assert isinstance(dn, DN)
+ validate_domain_level(self.api)
+ return dn
+
+
+@register()
+class topologysegment_mod(LDAPUpdate):
+ __doc__ = _('Modify a segment.')
+
+ msg_summary = _('Modified segment "%(value)s"')
+
+ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+ assert isinstance(dn, DN)
+ validate_domain_level(self.api)
+ self.obj.validate_nodes(ldap, dn, entry_attrs)
+ return dn
+
+
+@register()
+class topologysegment_refresh(LDAPQuery):
+ __doc__ = _('Request a replication refresh of specified node.')
+
+ has_output = output.standard_value
+ msg_summary = _('%(value)s')
+
+ takes_options = (
+ Flag(
+ 'left?',
+ doc=_('Initialize left node'),
+ default=False,
+ ),
+ Flag(
+ 'right?',
+ doc=_('Initialize right node'),
+ default=False,
+ ),
+ Flag(
+ 'stop?',
+ doc=_('Stop already started refresh of chosen node(s)'),
+ default=False,
+ ),
+ )
+
+ def execute(self, *keys, **options):
+ dn = self.obj.get_dn(*keys, **options)
+ validate_domain_level(self.api)
+
+ entry = self.obj.backend.get_entry(
+ dn, [
+ 'nsds5beginreplicarefresh;left',
+ 'nsds5beginreplicarefresh;right'
+ ])
+
+ left = options.get('left')
+ right = options.get('right')
+ stop = options.get('stop')
+ action = u'start'
+ msg = _('Replication refresh for segment: "%(pkey)s" requested.')
+ if stop:
+ action = u'stop'
+ msg = _('Stopping of replication refresh for segment: "'
+ '%(pkey)s" requested.')
+
+ if not left and not right:
+ raise errors.OptionError(
+ _('at least one node has to be specified')
+ )
+
+ if left:
+ entry['nsds5beginreplicarefresh;left'] = [action]
+ if right:
+ entry['nsds5beginreplicarefresh;right'] = [action]
+
+ self.obj.backend.update_entry(entry)
+
+ msg = msg % {'pkey': keys[-1]}
+ return dict(
+ result=True,
+ value=msg,
+ )
+
+
+@register()
+class topologysegment_show(LDAPRetrieve):
+ __doc__ = _('Display a segment.')
+
+
+@register()
+class topologysuffix(LDAPObject):
+ """
+ Suffix managed by the topology plugin.
+ """
+ container_dn = api.env.container_topology
+ object_name = _('suffix')
+ object_name_plural = _('suffices')
+ object_class = ['iparepltopoconf']
+ default_attributes = ['cn', 'ipaReplTopoConfRoot']
+ search_display_attributes = ['cn', 'ipaReplTopoConfRoot']
+ label = _('Topology suffices')
+ label_singular = _('Topology suffix')
+
+ takes_params = (
+ Str(
+ 'cn',
+ cli_name='name',
+ primary_key=True,
+ label=_('Suffix name'),
+ ),
+ Str(
+ 'iparepltopoconfroot',
+ maxlength=255,
+ cli_name='suffix',
+ label=_('LDAP suffix to be managed'),
+ normalizer=lambda value: value.lower(),
+ ),
+ )
+
+
+@register()
+class topologysuffix_find(LDAPSearch):
+ __doc__ = _('Search for topology suffices.')
+
+ msg_summary = ngettext(
+ '%(count)d topology suffix matched',
+ '%(count)d topology suffices matched', 0
+ )
+
+
+@register()
+class topologysuffix_del(LDAPDelete):
+ __doc__ = _('Delete a topology suffix.')
+
+ msg_summary = _('Deleted topology suffix "%(value)s"')
+
+ def pre_callback(self, ldap, dn, *keys, **options):
+ assert isinstance(dn, DN)
+ validate_domain_level(self.api)
+ return dn
+
+
+@register()
+class topologysuffix_add(LDAPCreate):
+ __doc__ = _('Add a new topology suffix to be managed.')
+
+ msg_summary = _('Added topology suffix "%(value)s"')
+
+ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+ assert isinstance(dn, DN)
+ validate_domain_level(self.api)
+ return dn
+
+
+@register()
+class topologysuffix_mod(LDAPUpdate):
+ __doc__ = _('Modify a topology suffix.')
+
+ msg_summary = _('Modified topology suffix "%(value)s"')
+
+ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
+ assert isinstance(dn, DN)
+ validate_domain_level(self.api)
+ return dn
+
+
+@register()
+class topologysuffix_show(LDAPRetrieve):
+ __doc__ = _('Show managed suffix.')