diff options
-rw-r--r-- | install/share/replica-acis.ldif | 4 | ||||
-rwxr-xr-x | install/tools/ipa-replica-manage | 70 | ||||
-rw-r--r-- | ipaserver/install/service.py | 21 |
3 files changed, 65 insertions, 30 deletions
diff --git a/install/share/replica-acis.ldif b/install/share/replica-acis.ldif index feda1d9b7..9ff4ed1b9 100644 --- a/install/share/replica-acis.ldif +++ b/install/share/replica-acis.ldif @@ -15,3 +15,7 @@ changetype: modify add: aci aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement))")(version 3.0;acl "Remove Replication Agreements";allow (delete) groupdn = "ldap:///cn=removereplica,cn=permissions,cn=accounts,$SUFFIX";) +dn: cn=tasks,cn=config +changetype: modify +add: aci +aci: (targetattr=*)(version 3.0; acl "Run tasks after replica re-initialization"; allow (add) groupdn = "ldap:///cn=modifyreplica,cn=permissions,cn=accounts,$SUFFIX";) diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage index 9894d2ad4..524384efa 100755 --- a/install/tools/ipa-replica-manage +++ b/install/tools/ipa-replica-manage @@ -39,10 +39,8 @@ commands = { "must provide the name of the server to disconnect"), "del":(1, 1, "<master fqdn>", "must provide hostname of master to delete"), - "init":(1, 1, "<master fqdn>", - "hostname of master to initialize is required"), - "synch":(1, 1, "master fqdn>", - "must provide hostname of supplier to synchronize with") + "re-initialize":(0, 0, "", ""), + "force-sync":(0, 0, "", "") } def parse_options(): @@ -69,6 +67,7 @@ def parse_options(): help="DN of Windows subtree containing the users you want to sync (default cn=Users,<domain suffix)") parser.add_option("--passsync", dest="passsync", help="Password for the Windows PassSync user") + parser.add_option("--from", dest="fromhost", help="Host to get data from") options, args = parser.parse_args() @@ -340,27 +339,50 @@ def add_link(replica1, replica2, dirman_passwd, options): repl1.setup_replication(replica2, get_realm_name(), **other_args) print "Connected '%s' to '%s'" % (replica1, replica2) -def init_master(replman, dirman_passwd, hostname): - filter = "(&(nsDS5ReplicaHost=%s)(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement)))" % hostname - entry = replman.conn.search_s("cn=config", ldap.SCOPE_SUBTREE, filter) +def re_initialize(options): + + if not options.fromhost: + print "re-initialize requires the option --from <host name>" + sys.exit(1) + + repl = replication.ReplicationManager(options.fromhost, options.dirman_passwd) + repl.suffix = get_suffix() + + thishost = installutils.get_fqdn() + + filter = "(&(nsDS5ReplicaHost=%s)(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement)))" % thishost + entry = repl.conn.search_s("cn=config", ldap.SCOPE_SUBTREE, filter) if len(entry) == 0: - logging.error("Unable to find replication agreement for %s" % hostname) + logging.error("Unable to find %s -> %s replication agreement" % (options.fromhost, thishost)) sys.exit(1) if len(entry) > 1: - logging.error("Found multiple agreements for %s. Only initializing the first one returned: %s" % (hostname, entry[0].dn)) - replman.initialize_replication(entry[0].dn, replman.conn) - ds = dsinstance.DsInstance(realm_name = get_realm_name(), dm_password = dirman_passwd) + logging.error("Found multiple agreements for %s. Only initializing the first one returned: %s" % (thishost, entry[0].dn)) + + repl.initialize_replication(entry[0].dn, repl.conn) + repl.wait_for_repl_init(repl.conn, entry[0].dn) + + ds = dsinstance.DsInstance(realm_name = get_realm_name(), dm_password = options.dirman_passwd) ds.init_memberof() -def synch_master(replman, hostname): - filter = "(&(nsDS5ReplicaHost=%s)(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement)))" % hostname - entry = replman.conn.search_s("cn=config", ldap.SCOPE_SUBTREE, filter) +def force_sync(options): + + if not options.fromhost: + print "force-sync requires the option --from <host name>" + sys.exit(1) + + repl = replication.ReplicationManager(options.fromhost, options.dirman_passwd) + repl.suffix = get_suffix() + + thishost = installutils.get_fqdn() + + filter = "(&(nsDS5ReplicaHost=%s)(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement)))" % thishost + entry = repl.conn.search_s("cn=config", ldap.SCOPE_SUBTREE, filter) if len(entry) == 0: - logging.error("Unable to find replication agreement for %s" % hostname) + logging.error("Unable to find %s -> %s replication agreement" % (options.fromhost, thishost)) sys.exit(1) if len(entry) > 1: - logging.error("Found multiple agreements for %s. Only initializing the first one returned: %s" % (hostname, entry[0].dn)) - replman.force_synch(entry[0].dn, entry[0].nsds5replicaupdateschedule, replman.conn) + logging.error("Found multiple agreements for %s. Only initializing the first one returned: %s" % (thishost, entry[0].dn)) + repl.force_synch(entry[0].dn, entry[0].nsds5replicaupdateschedule, repl.conn) def main(): options, args = parse_options() @@ -375,9 +397,11 @@ def main(): if options.dirman_passwd: dirman_passwd = options.dirman_passwd else: - if (not test_connection(host)) or args[0] in ["connect", "init"]: + if not test_connection(host): dirman_passwd = getpass.getpass("Directory Manager password: ") + options.dirman_passwd = dirman_passwd + r = replication.ReplicationManager(host, dirman_passwd) r.suffix = get_suffix() @@ -388,10 +412,10 @@ def main(): list_masters(host, replica, dirman_passwd, options.verbose) elif args[0] == "del": del_master(r, args[1], options.force) - elif args[0] == "init": - init_master(r, dirman_passwd, args[1]) - elif args[0] == "synch": - synch_master(r, args[1]) + elif args[0] == "re-initialize": + re_initialize(options) + elif args[0] == "force-sync": + force_sync(options) elif args[0] == "connect": if len(args) == 3: replica1 = args[1] @@ -412,7 +436,7 @@ def main(): try: main() except KeyboardInterrupt: - sys.exit(1) + sys.exit(1) except SystemExit, e: sys.exit(e) except ldap.INVALID_CREDENTIALS: diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py index 6517b8905..b8d049fee 100644 --- a/ipaserver/install/service.py +++ b/ipaserver/install/service.py @@ -28,6 +28,7 @@ from ipaserver import ipaldap import base64 import time import datetime +from ipaserver.install import installutils SERVICE_LIST = { 'KDC':('krb5kdc', 10), @@ -105,22 +106,27 @@ class Service: self.sstore = sysrestore.StateFile('/var/lib/ipa/sysrestore') def _ldap_mod(self, ldif, sub_dict = None): - assert self.dm_password is not None + pw_name = None fd = None path = ipautil.SHARE_DIR + ldif + hostname = installutils.get_fqdn() if sub_dict is not None: txt = ipautil.template_file(path, sub_dict) fd = ipautil.write_tmp_file(txt) path = fd.name - [pw_fd, pw_name] = tempfile.mkstemp() - os.write(pw_fd, self.dm_password) - os.close(pw_fd) + if self.dm_password: + [pw_fd, pw_name] = tempfile.mkstemp() + os.write(pw_fd, self.dm_password) + os.close(pw_fd) + auth_parms = ["-x", "-D", "cn=Directory Manager", "-y", pw_name] + else: + auth_parms = ["-Y", "GSSAPI"] - args = ["/usr/bin/ldapmodify", "-h", "127.0.0.1", "-xv", - "-D", "cn=Directory Manager", "-y", pw_name, "-f", path] + args = ["/usr/bin/ldapmodify", "-h", hostname, "-v", "-f", path] + args += auth_parms try: try: @@ -128,7 +134,8 @@ class Service: except ipautil.CalledProcessError, e: logging.critical("Failed to load %s: %s" % (ldif, str(e))) finally: - os.remove(pw_name) + if pw_name: + os.remove(pw_name) if fd is not None: fd.close() |