def db2ldif(self, instance, backend, online=True): ''' Create a LDIF backup of the data in this instance. If executed online create a task and wait for it to complete. For SELinux reasons this writes out to the 389-ds backup location and we move it. ''' logger.info('Backing up %s in %s to LDIF', backend, instance) cn = time.strftime('export_%Y_%m_%d_%H_%M_%S') dn = DN(('cn', cn), ('cn', 'export'), ('cn', 'tasks'), ('cn', 'config')) ldifname = '%s-%s.ldif' % (instance, backend) ldiffile = os.path.join( paths.SLAPD_INSTANCE_LDIF_DIR_TEMPLATE % instance, ldifname) if online: conn = self.get_connection() ent = conn.make_entry( dn, { 'objectClass': ['top', 'extensibleObject'], 'cn': [cn], 'nsInstance': [backend], 'nsFilename': [ldiffile], 'nsUseOneFile': ['true'], 'nsExportReplica': ['true'], }) try: conn.add_entry(ent) except Exception as e: raise admintool.ScriptError('Unable to add LDIF task: %s' % e) logger.info("Waiting for LDIF to finish") wait_for_task(conn, dn) else: args = [ paths.DB2LDIF, '-Z', instance, '-r', '-n', backend, '-a', ldiffile ] result = run(args, raiseonerr=False) if result.returncode != 0: logger.critical('db2ldif failed: %s', result.error_log) # Move the LDIF backup to our location shutil.move(ldiffile, os.path.join(self.dir, ldifname))
def validate_options(self): super(OTPTokenImport, self).validate_options() # Parse the file. if len(self.args) < 1: raise admintool.ScriptError("Import file required!") self.doc = PSKCDocument(self.args[0]) # Get the output file. if len(self.args) < 2: raise admintool.ScriptError("Output file required!") self.output = self.args[1] if os.path.exists(self.output): raise admintool.ScriptError("Output file already exists!") # Verify a key is provided if one is needed. if self.doc.keyname is not None: if self.safe_options.keyfile is None: # pylint: disable=no-member raise admintool.ScriptError("Encryption key required: %s!" % self.doc.keyname) # Load the keyfile. keyfile = self.safe_options.keyfile # pylint: disable=no-member with open(keyfile) as f: self.doc.setKey(f.read())
def validate_options(self): options = self.options super(LDAPUpdater, self).validate_options(needs_root=True) self.files = self.args for filename in self.files: if not os.path.exists(filename): raise admintool.ScriptError("%s: file not found" % filename) try: installutils.check_server_configuration() except RuntimeError, e: print unicode(e) sys.exit(1)
def ask_for_options(self): options = self.options super(Restore, self).ask_for_options() # get the directory manager password self.dirman_password = options.password if not options.password: if not options.unattended: self.dirman_password = installutils.read_password( "Directory Manager (existing master)", confirm=False, validate=False) if self.dirman_password is None: raise admintool.ScriptError( "Directory Manager password required")
def run(self): super(LDAPUpdater_Upgrade, self).run() api.Backend.ldap2.connect() options = self.options realm = api.env.realm upgrade = IPAUpgrade(realm, self.files, schema_files=options.schema_files) try: upgrade.create_instance() except BadSyntax: raise admintool.ScriptError( 'Bad syntax detected in upgrade file(s).', 1) except RuntimeError: raise admintool.ScriptError('IPA upgrade failed.', 1) else: if upgrade.modified: logger.info('Update complete') else: logger.info('Update complete, no data were modified') api.Backend.ldap2.disconnect()
def resubmit_request(self, ca='dogtag-ipa-ca-renew-agent', profile=''): timeout = api.env.startup_timeout + 60 logger.debug("resubmitting certmonger request '%s'", self.request_id) certmonger.resubmit_request(self.request_id, ca=ca, profile=profile, is_ca=True) try: state = certmonger.wait_for_request(self.request_id, timeout) except RuntimeError: raise admintool.ScriptError( "Resubmitting certmonger request '%s' timed out, " "please check the request manually" % self.request_id) ca_error = certmonger.get_request_value(self.request_id, 'ca-error') if state != 'MONITORING' or ca_error: raise admintool.ScriptError( "Error resubmitting certmonger request '%s', " "please check the request manually" % self.request_id) logger.debug("modifying certmonger request '%s'", self.request_id) certmonger.modify(self.request_id, ca='dogtag-ipa-ca-renew-agent', profile='')
def decrypt_file(tmpdir, filename): source = filename (dest, ext) = os.path.splitext(filename) if ext != '.gpg': raise admintool.ScriptError('Trying to decrypt a non-gpg file') dest = os.path.basename(dest) dest = os.path.join(tmpdir, dest) args = [ paths.GPG2, '--batch', '--output', dest, '--decrypt', source, ] result = run(args, raiseonerr=False) if result.returncode != 0: raise admintool.ScriptError('gpg failed: %s' % result.error_log) return dest
def run(self): fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) if (not fstore.has_files() and not os.path.exists(paths.IPA_DEFAULT_CONF)): raise admintool.ScriptError( "IPA client is not configured on this system.") api.bootstrap(context='cli_installer') api.finalize() server = urlparse.urlsplit(api.env.jsonrpc_uri).hostname ldap = ipaldap.IPAdmin(server) tmpdir = tempfile.mkdtemp(prefix="tmp-") ccache_name = os.path.join(tmpdir, 'ccache') try: principal = str('host/%s@%s' % (api.env.host, api.env.realm)) ipautil.kinit_keytab(principal, paths.KRB5_KEYTAB, ccache_name) os.environ['KRB5CCNAME'] = ccache_name api.Backend.rpcclient.connect() try: result = api.Backend.rpcclient.forward( 'ca_is_enabled', version=u'2.107', ) ca_enabled = result['result'] except (errors.CommandError, errors.NetworkError): result = api.Backend.rpcclient.forward( 'env', server=True, version=u'2.0', ) ca_enabled = result['result']['enable_ra'] api.Backend.rpcclient.disconnect() ldap.do_sasl_gssapi_bind() certs = certstore.get_ca_certs(ldap, api.env.basedn, api.env.realm, ca_enabled) finally: shutil.rmtree(tmpdir) server_fstore = sysrestore.FileStore(paths.SYSRESTORE) if server_fstore.has_files(): self.update_server(certs) self.update_client(certs)
def ldap_connect(self): password = self.options.password if not password: try: api.Backend.ldap2.connect(ccache=os.environ.get('KRB5CCNAME')) except (gssapi.exceptions.GSSError, errors.ACIError): pass else: return password = installutils.read_password( "Directory Manager", confirm=False, validate=False) if password is None: raise admintool.ScriptError( "Directory Manager password required") api.Backend.ldap2.connect(bind_pw=password)
def get_connection(self): ''' Create an ldapi connection and bind to it using autobind as root. ''' if self._conn is not None: return self._conn self._conn = ipaldap.IPAdmin(host=api.env.host, ldapi=True, protocol='ldapi', realm=api.env.realm) try: pw_name = pwd.getpwuid(os.geteuid()).pw_name self._conn.do_external_bind(pw_name) except Exception, e: raise admintool.ScriptError('Unable to bind to LDAP server: %s' % e)
def ask_for_options(self): options = self.options super(Restore, self).ask_for_options() # no IPA config means we are reinstalling from nothing so # there is no need for the DM password if not os.path.exists(paths.IPA_DEFAULT_CONF): return # get the directory manager password self.dirman_password = options.password if not options.password: if not options.unattended: self.dirman_password = installutils.read_password( "Directory Manager (existing master)", confirm=False, validate=False) if self.dirman_password is None: raise admintool.ScriptError( "Directory Manager password required")
def finalize_backup(self, data_only=False, encrypt=False, keyring=None): ''' Create the final location of the backup files and move the files we've backed up there, optionally encrypting them. This is done in a couple of steps. We have a directory that contains the tarball of the files, a directory that contains the db2bak output and an LDIF. These, along with the header, are moved into a new subdirectory in /var/lib/ipa/backup. ''' if data_only: backup_dir = os.path.join(paths.IPA_BACKUP_DIR, time.strftime('ipa-data-%Y-%m-%d-%H-%M-%S')) filename = os.path.join(backup_dir, "ipa-data.tar") else: backup_dir = os.path.join(paths.IPA_BACKUP_DIR, time.strftime('ipa-full-%Y-%m-%d-%H-%M-%S')) filename = os.path.join(backup_dir, "ipa-full.tar") os.mkdir(backup_dir) os.chmod(backup_dir, 0o700) os.chdir(self.dir) args = ['tar', '--xattrs', '--selinux', '-czf', filename, '.' ] result = run(args, raiseonerr=False) if result.returncode != 0: raise admintool.ScriptError( 'tar returned non-zero code %s: %s' % (result.returncode, result.error_log)) if encrypt: logger.info('Encrypting %s', filename) filename = encrypt_file(filename) shutil.move(self.header, backup_dir) logger.info('Backed up to %s', backup_dir)
def bak2db(self, instance, backend, online=True): ''' Restore a BAK backup of the data and changelog in this instance. If backend is None then all backends are restored. If executed online create a task and wait for it to complete. instance here is a loaded term. It can mean either a separate 389-ds install instance or a separate 389-ds backend. We only need to treat PKI-IPA and ipaca specially. ''' if backend is not None: self.log.info('Restoring %s in %s' % (backend, instance)) else: self.log.info('Restoring %s' % instance) cn = time.strftime('restore_%Y_%m_%d_%H_%M_%S') dn = DN(('cn', cn), ('cn', 'restore'), ('cn', 'tasks'), ('cn', 'config')) if online: conn = self.get_connection() ent = conn.make_entry( dn, { 'objectClass': ['top', 'extensibleObject'], 'cn': [cn], 'nsArchiveDir': [os.path.join(self.dir, instance)], 'nsDatabaseType': ['ldbm database'], }) if backend is not None: ent['nsInstance'] = [backend] try: conn.add_entry(ent) except Exception, e: raise admintool.ScriptError( 'Unable to bind to LDAP server: %s' % e) self.log.info("Waiting for restore to finish") wait_for_task(conn, dn)
def _run(self): super(KRAInstaller, self).run() print dedent(self.INSTALLER_START_MESSAGE) subject = dsinstance.DsInstance().find_subject_base() if not self.installing_replica: kra = krainstance.KRAInstance( api.env.realm, dogtag_constants=dogtag.install_constants) kra.configure_instance(api.env.host, api.env.domain, self.options.password, self.options.password, subject_base=subject) else: replica_config = create_replica_config(self.options.password, self.replica_file, self.options) if not read_replica_info_kra_enabled(replica_config.dir): raise admintool.ScriptError( "Either KRA is not installed on the master system or " "your replica file is out of date") kra = krainstance.install_replica_kra(replica_config) service.print_msg("Restarting the directory server") ds = dsinstance.DsInstance() ds.restart() kra.enable_client_auth_to_db(kra.dogtag_constants.KRA_CS_CFG_PATH) # Restart apache for new proxy config file services.knownservices.httpd.restart(capture_output=True) # Update config file parser = RawConfigParser() parser.read(paths.IPA_DEFAULT_CONF) parser.set('global', 'enable_kra', 'True') with open(paths.IPA_DEFAULT_CONF, 'w') as f: parser.write(f)
def encrypt_file(filename, remove_original=True): source = filename dest = filename + '.gpg' args = [ paths.GPG2, '--batch', '--default-recipient-self', '--output', dest, '--encrypt', source, ] result = run(args, raiseonerr=False) if result.returncode != 0: raise admintool.ScriptError('gpg failed: %s' % result.error_log) if remove_original: os.unlink(source) return dest
def extract_backup(self, keyring=None): ''' Extract the contents of the tarball backup into a temporary location, decrypting if necessary. ''' encrypt = False filename = None if self.backup_type == 'FULL': filename = os.path.join(self.backup_dir, 'ipa-full.tar') else: filename = os.path.join(self.backup_dir, 'ipa-data.tar') if not os.path.exists(filename): if not os.path.exists(filename + '.gpg'): raise admintool.ScriptError('Unable to find backup file in %s' % self.backup_dir) else: filename = filename + '.gpg' encrypt = True if encrypt: logger.info('Decrypting %s', filename) filename = decrypt_file(self.dir, filename, keyring) os.chdir(self.dir) args = ['tar', '--xattrs', '--selinux', '-xzf', filename, '.' ] run(args) pent = pwd.getpwnam(constants.DS_USER) os.chown(self.top_dir, pent.pw_uid, pent.pw_gid) recursive_chown(self.dir, pent.pw_uid, pent.pw_gid) if encrypt: # We can remove the decoded tarball os.unlink(filename)
def run(self): super(EPN, self).run() if not is_ipa_client_configured(): logger.error("IPA client is not configured on this system.") raise admintool.ScriptError() # tasks required privileges self._get_krb5_ticket() self._read_configuration() self._validate_configuration() self._parse_configuration() self._get_connection() self._read_ipa_configuration() self._create_ssl_context() drop_privileges() if self.options.mailtest: self._gentestdata() else: if self.options.to_nbdays: self._build_cli_date_ranges() for date_range in self._date_ranges: self._fetch_data_from_ldap(date_range) self._parse_ldap_data() if self.options.dry_run: self._pretty_print_data() else: self._mailer = MailUserAgent( security_protocol=api.env.smtp_security, smtp_hostname=api.env.smtp_server, smtp_port=api.env.smtp_port, smtp_timeout=api.env.smtp_timeout, smtp_username=api.env.smtp_user, smtp_password=api.env.smtp_password, ssl_context=self._ssl_context, x_mailer=self.command_name, msg_subtype=api.env.msg_subtype, msg_charset=api.env.msg_charset, ) self._send_emails()
def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command): pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=pkcs12_passwd, key_nickname=self.options.cert_name, ca_cert_files=[paths.IPA_CA_CRT], host_name=api.env.host) dirname = os.path.normpath(dirname) cdb = certs.CertDB(api.env.realm, nssdir=dirname) # Check that the ca_cert is known and trusted self.check_chain(pkcs12_file.name, pin, cdb) try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: cdb.untrack_server_cert(old_cert) cdb.delete_cert(old_cert) prevs = cdb.find_server_certs() cdb.import_pkcs12(pkcs12_file.name, pin) news = cdb.find_server_certs() server_certs = [item for item in news if item not in prevs] server_cert = server_certs[0][0] if ca_enabled: # Start tracking only if the cert was issued by IPA CA # Retrieve IPA CA ipa_ca_cert = cdb.get_cert_from_db( get_ca_nickname(api.env.realm)) # And compare with the CA which signed this certificate if ca_cert == ipa_ca_cert: cdb.track_server_cert(server_cert, principal, cdb.passwd_fname, command) except RuntimeError as e: raise admintool.ScriptError(str(e)) return server_cert
def file_backup(self, options): def verify_directories(dirs): return [s for s in dirs if os.path.exists(s)] self.log.info("Backing up files") args = [ 'tar', '--exclude=/var/lib/ipa/backup', '--xattrs', '--selinux', '-czf', os.path.join(self.dir, 'files.tar') ] args.extend(verify_directories(self.dirs)) args.extend(verify_directories(self.files)) if options.logs: args.extend(verify_directories(self.logs)) (stdout, stderr, rc) = run(args, raiseonerr=False) if rc != 0: raise admintool.ScriptError('tar returned non-zero %d: %s' % (rc, stdout))
def init_api(self, **overrides): overrides.setdefault('confdir', paths.ETC_IPA) api.bootstrap(in_server=True, context='restore', **overrides) api.finalize() self.instances = [ipaldap.realm_to_serverid(api.env.realm)] self.backends = ['userRoot', 'ipaca'] # no IPA config means we are reinstalling from nothing so # there is nothing to test the DM password against. if os.path.exists(paths.IPA_DEFAULT_CONF): instance_name = ipapython.ipaldap.realm_to_serverid(api.env.realm) if not services.knownservices.dirsrv.is_running(instance_name): raise admintool.ScriptError( "directory server instance is not running") try: ReplicationManager(api.env.realm, api.env.host, self.dirman_password) except errors.ACIError: logger.error("Incorrect Directory Manager password provided") raise
def export_certdb(self, fname, passwd_fname): """Export a cert database :param fname: The file to export to (relative to the info directory) :param passwd_fname: File that holds the cert DB password """ hostname = self.replica_fqdn subject_base = self.subject_base ca_subject = ca.lookup_ca_subject(api, subject_base) nickname = "Server-Cert" try: db = certs.CertDB(api.env.realm, nssdir=self.dir, host_name=api.env.host, subject_base=subject_base, ca_subject=ca_subject) db.create_passwd_file() db.create_from_cacert() db.create_server_cert(nickname, hostname) pkcs12_fname = os.path.join(self.dir, fname + ".p12") try: db.export_pkcs12(pkcs12_fname, passwd_fname, nickname) except ipautil.CalledProcessError as e: logger.info("error exporting Server certificate: %s", e) installutils.remove_file(pkcs12_fname) installutils.remove_file(passwd_fname) self.remove_info_file("cert8.db") self.remove_info_file("key3.db") self.remove_info_file("secmod.db") self.remove_info_file("noise.txt") orig_filename = passwd_fname + ".orig" if ipautil.file_exists(orig_filename): installutils.remove_file(orig_filename) except errors.CertificateOperationError as e: raise admintool.ScriptError(str(e))
def db2bak(self, instance, online=True): ''' Create a BAK backup of the data and changelog in this instance. If executed online create a task and wait for it to complete. ''' logger.info('Backing up %s', instance) cn = time.strftime('backup_%Y_%m_%d_%H_%M_%S') dn = DN(('cn', cn), ('cn', 'backup'), ('cn', 'tasks'), ('cn', 'config')) bakdir = os.path.join(paths.SLAPD_INSTANCE_BACKUP_DIR_TEMPLATE % (instance, instance)) if online: conn = self.get_connection() ent = conn.make_entry( dn, { 'objectClass': ['top', 'extensibleObject'], 'cn': [cn], 'nsInstance': ['userRoot'], 'nsArchiveDir': [bakdir], 'nsDatabaseType': ['ldbm database'], }) try: conn.add_entry(ent) except Exception as e: raise admintool.ScriptError( 'Unable to to add backup task: %s' % e) logger.info("Waiting for BAK to finish") wait_for_task(conn, dn) else: args = [paths.DB2BAK, bakdir, '-Z', instance] result = run(args, raiseonerr=False) if result.returncode != 0: logger.critical('db2bak failed: %s', result.error_log) shutil.move(bakdir, self.dir)
def db2ldif(self, instance, backend, online=True): ''' Create a LDIF backup of the data in this instance. If executed online create a task and wait for it to complete. For SELinux reasons this writes out to the 389-ds backup location and we move it. ''' self.log.info('Backing up %s in %s to LDIF' % (backend, instance)) now = time.localtime() cn = time.strftime('export_%Y_%m_%d_%H_%M_%S') dn = DN(('cn', cn), ('cn', 'export'), ('cn', 'tasks'), ('cn', 'config')) ldifname = '%s-%s.ldif' % (instance, backend) ldiffile = os.path.join( paths.SLAPD_INSTANCE_LDIF_DIR_TEMPLATE % instance, ldifname) if online: conn = self.get_connection() ent = conn.make_entry( dn, { 'objectClass': ['top', 'extensibleObject'], 'cn': [cn], 'nsInstance': [backend], 'nsFilename': [ldiffile], 'nsUseOneFile': ['true'], 'nsExportReplica': ['true'], }) try: conn.add_entry(ent) except Exception, e: raise admintool.ScriptError('Unable to add LDIF task: %s' % e) self.log.info("Waiting for LDIF to finish") wait_for_task(conn, dn)
def replace_key_cert_files(self, cert, key, cert_fname, key_fname, ca_cert, passwd_fname=None, profile=None, cmgr_post_command=None): try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: certmonger.stop_tracking(certfile=cert_fname) pkey_passwd = None if passwd_fname is not None: with open(passwd_fname, 'rb') as f: pkey_passwd = f.read() x509.write_certificate(cert, cert_fname) x509.write_pem_private_key(key, key_fname, pkey_passwd) if ca_enabled: # Start tracking only if the cert was issued by IPA CA # Retrieve IPA CA cdb = certs.CertDB(api.env.realm, nssdir=paths.IPA_NSSDB_DIR) ipa_ca_cert = cdb.get_cert_from_db( get_ca_nickname(api.env.realm)) # And compare with the CA which signed this certificate if ca_cert == ipa_ca_cert: req_id = certmonger.start_tracking( (cert_fname, key_fname), pinfile=passwd_fname, storage='FILE', post_command=cmgr_post_command) return req_id except RuntimeError as e: raise admintool.ScriptError(str(e)) return None
def delete_winsync_agreement(self): """ Deletes the winsync agreement between the current master and the given AD server. """ try: self.manager.delete_agreement(self.options.server) self.manager.delete_referral(self.options.server) dn = DN(('cn', self.options.server), ('cn', 'replicas'), ('cn', 'ipa'), ('cn', 'etc'), realm_to_suffix(api.env.realm)) entries = self.manager.conn.get_entries(dn, self.ldap.SCOPE_SUBTREE) if entries: entries.sort(key=len, reverse=True) for entry in entries: self.ldap.delete_entry(entry) except Exception as e: raise admintool.ScriptError( "Deletion of the winsync agreement failed: %s" % str(e))
def ldap_connect(self): conn = ldap2() password = self.options.password if not password: try: ccache = krbV.default_context().default_ccache() conn.connect(ccache=ccache) except (krbV.Krb5Error, errors.ACIError): pass else: return conn password = installutils.read_password("Directory Manager", confirm=False, validate=False) if password is None: raise admintool.ScriptError( "Directory Manager password required") conn.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=password) return conn
def validate_options(self): options = self.options super(Backup, self).validate_options(needs_root=True) installutils.check_server_configuration() if options.gpg_keyring is not None: if not os.path.exists(options.gpg_keyring + '.pub'): raise admintool.ScriptError('No such key %s' % options.gpg_keyring) options.gpg = True if options.online and not options.data_only: self.option_parser.error("You cannot specify --online " "without --data") if options.gpg: tmpfd = write_tmp_file('encryptme') newfile = encrypt_file(tmpfd.name, options.gpg_keyring, False) os.unlink(newfile) if options.data_only and options.logs: self.option_parser.error("You cannot specify --data " "with --logs")
def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command): pkcs12_file, pin, ca_cert = installutils.load_pkcs12( cert_files=self.args, key_password=pkcs12_passwd, key_nickname=self.options.cert_name, ca_cert_files=[CACERT], host_name=api.env.host) cdb = certs.CertDB(api.env.realm, nssdir=dirname) try: ca_enabled = api.Command.ca_is_enabled()['result'] if ca_enabled: cdb.untrack_server_cert(old_cert) cdb.delete_cert(old_cert) cdb.import_pkcs12(pkcs12_file.name, pin) server_cert = cdb.find_server_certs()[0][0] if ca_enabled: cdb.track_server_cert(server_cert, principal, cdb.passwd_fname, command) except RuntimeError, e: raise admintool.ScriptError(str(e))
def encrypt_file(filename, keyring, remove_original=True): source = filename dest = filename + '.gpg' args = [paths.GPG, '--batch', '--default-recipient-self', '-o', dest] if keyring is not None: args.append('--no-default-keyring') args.append('--keyring') args.append(keyring + '.pub') args.append('--secret-keyring') args.append(keyring + '.sec') args.append('-e') args.append(source) result = run(args, raiseonerr=False) if result.returncode != 0: raise admintool.ScriptError('gpg failed: %s' % result.error_log) if remove_original: os.unlink(source) return dest
def disable_agreements(self): ''' Find all replication agreements on all masters and disable them. Warn very loudly about any agreements/masters we cannot contact. ''' try: conn = self.get_connection() except Exception as e: logger.error('Unable to get connection, skipping disabling ' 'agreements: %s', e) return masters = [] dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) try: entries = conn.get_entries(dn, conn.SCOPE_ONELEVEL) except Exception as e: raise admintool.ScriptError( "Failed to read master data: %s" % e) else: masters = [ent.single_value['cn'] for ent in entries] for master in masters: if master == api.env.host: continue try: repl = ReplicationManager(api.env.realm, master, self.dirman_password) except Exception as e: logger.critical("Unable to disable agreement on %s: %s", master, e) continue master_dn = DN(('cn', master), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) try: services = repl.conn.get_entries(master_dn, repl.conn.SCOPE_ONELEVEL) except errors.NotFound: continue services_cns = [s.single_value['cn'] for s in services] host_entries = repl.find_ipa_replication_agreements() hosts = [rep.single_value.get('nsds5replicahost') for rep in host_entries] for host in hosts: logger.info('Disabling replication agreement on %s to %s', master, host) repl.disable_agreement(host) if 'CA' in services_cns: try: repl = get_cs_replication_manager(api.env.realm, master, self.dirman_password) except Exception as e: logger.critical("Unable to disable agreement on %s: %s", master, e) continue host_entries = repl.find_ipa_replication_agreements() hosts = [rep.single_value.get('nsds5replicahost') for rep in host_entries] for host in hosts: logger.info('Disabling CA replication agreement on %s to ' '%s', master, host) repl.hostnames = [master, host] repl.disable_agreement(host)