Rework old init and synch commands and use better names.

These commands can now be run exclusively o the replica that needs to be
resynced or reinitialized and the --from command must be used to tell from
which other replica it can will pull data.

Fixes: https://fedorahosted.org/freeipa/ticket/626
This commit is contained in:
Simo Sorce
2010-12-20 23:34:00 -05:00
parent 91f3e79d81
commit 613f5feb0e
3 changed files with 65 additions and 30 deletions

View File

@@ -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";)

View File

@@ -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:

View File

@@ -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()