diff --git a/ipa-server/ipa-install/updates/RFC2307bis.update b/ipa-server/ipa-install/updates/RFC2307bis.update index 6d08d5786..1ddebc1a2 100644 --- a/ipa-server/ipa-install/updates/RFC2307bis.update +++ b/ipa-server/ipa-install/updates/RFC2307bis.update @@ -16,7 +16,7 @@ add:attributeTypes: SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC2307bis' ) add:attributeTypes: - ( 1.3.6.1.4.1.1.1.1.12 SUP name NAME 'nisDomain' + ( 1.3.6.1.4.1.1.1.1.12 NAME 'nisDomain' DESC 'NIS domain' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 X-ORIGIN 'RFC2307bis' ) diff --git a/ipa-server/ipa-ldap-updater b/ipa-server/ipa-ldap-updater index 38ccf6670..90119950e 100755 --- a/ipa-server/ipa-ldap-updater +++ b/ipa-server/ipa-ldap-updater @@ -99,9 +99,12 @@ def main(): else: files = args - ld.update(files) + modified = ld.update(files) - return 0 + if modified and options.test: + return 2 + else: + return 0 try: if __name__ == "__main__": diff --git a/ipa-server/ipaserver/ldapupdate.py b/ipa-server/ipaserver/ldapupdate.py index 638cd9a09..f4c868383 100755 --- a/ipa-server/ipaserver/ldapupdate.py +++ b/ipa-server/ipaserver/ldapupdate.py @@ -53,6 +53,7 @@ class LDAPUpdate(): self.live_run = live_run self.dm_password = dm_password self.conn = None + self.modified = False krbctx = krbV.default_context() @@ -454,6 +455,31 @@ class LDAPUpdate(): logging.debug(a + ": ") for l in value: logging.debug("\t" + l) + def is_schema_updated(self, s): + """Compare the schema in 's' with the current schema in the DS to + see if anything has changed. This should account for syntax + differences (like added parens that make no difference but are + detected as a change by generateModList()). + + This doesn't handle re-ordering of attributes. They are still + detected as changes, so foo $ bar != bar $ foo. + + return True if the schema has changed + return False if it has not + """ + s = ldap.schema.SubSchema(s) + s = s.ldap_entry() + + # Get a fresh copy and convert into a SubSchema + n = self.__get_entry("cn=schema")[0] + n = dict(n.data) + n = ldap.schema.SubSchema(n) + n = n.ldap_entry() + + if s == n: + return False + else: + return True def __update_record(self, update): found = False @@ -498,19 +524,31 @@ class LDAPUpdate(): else: # Update LDAP try: - logging.debug("%s" % self.conn.generateModList(entry.origDataDict(), entry.toDict())) - if self.live_run: + updated = False + changes = self.conn.generateModList(entry.origDataDict(), entry.toDict()) + if (entry.dn == "cn=schema"): + updated = self.is_schema_updated(entry.toDict()) + else: + if len(changes) > 1: + updated = True + logging.debug("%s" % changes) + if self.live_run and updated: self.conn.updateEntry(entry.dn, entry.origDataDict(), entry.toDict()) logging.info("Done") except ipaerror.exception_for(ipaerror.LDAP_EMPTY_MODLIST), e: logging.info("Entry already up-to-date") + updated = False except ipaerror.exception_for(ipaerror.LDAP_DATABASE_ERROR), e: logging.error("Update failed: %s: %s", e, self.__detail_error(e.detail)) + updated = False if ("cn=index" in entry.dn and "cn=userRoot" in entry.dn): taskid = self.create_index_task(entry.cn) self.monitor_index_task(taskid) + + if updated: + self.modified = True return def get_all_files(self, root, recursive=False): @@ -526,6 +564,8 @@ class LDAPUpdate(): def update(self, files): """Execute the update. files is a list of the update files to use. + + returns True if anything was changed, otherwise False """ try: @@ -551,4 +591,4 @@ class LDAPUpdate(): finally: if self.conn: self.conn.unbind() - return + return self.modified diff --git a/ipa-server/man/ipa-ldap-updater.1 b/ipa-server/man/ipa-ldap-updater.1 index 4a1dd5cda..453ac758f 100644 --- a/ipa-server/man/ipa-ldap-updater.1 +++ b/ipa-server/man/ipa-ldap-updater.1 @@ -66,7 +66,7 @@ A few rules: Enable debug logging when more verbose output is needed .TP \fB\-t\fR, \fB\-\-test\fR -Run through the update without changing anything +Run through the update without changing anything. If changes are available then the command returns 2. If no updates are available it returns 0. .TP \fB\-y\fR File containing the Directory Manager password @@ -74,3 +74,5 @@ File containing the Directory Manager password 0 if the command was successful 1 if an error occurred + +2 if run with in test mode (\-t) and updates are available