From daddcf6ec68f536fe647cb7155a85778597d90aa Mon Sep 17 00:00:00 2001 From: Mark Reynolds Date: Dec 01 2020 07:45:07 +0000 Subject: Accept 389-ds JSON replication status messages 389-ds now stores a replication agreement status message in a JSON string in a new attribute: replicaLastInitStatusJSON replicaLastUpdateStatusJSON The original status attributes' values are not changing at this time, but there are plans to do so eventually as the old status format is confusing. http://www.port389.org/docs/389ds/design/repl-agmt-status-design.html Fixes: https://pagure.io/freeipa/issue/7975 Signed-off-by: Mark Reynolds Reviewed-By: Alexander Bokovoy Reviewed-By: Rob Crittenden --- diff --git a/install/ui/test/data/ipa_init_objects.json b/install/ui/test/data/ipa_init_objects.json index 6f9b13e..9051449 100644 --- a/install/ui/test/data/ipa_init_objects.json +++ b/install/ui/test/data/ipa_init_objects.json @@ -11160,9 +11160,11 @@ "nsds5replicalastinitend", "nsds5replicalastinitstart", "nsds5replicalastinitstatus", + "nsds5replicalastinitstatusjson", "nsds5replicalastupdateend", "nsds5replicalastupdatestart", "nsds5replicalastupdatestatus", + "nsds5replicalastupdatestatusjson", "nsds5replicalegacyconsumer", "nsds5replicaname", "nsds5replicaport", diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update index c1e72b1..a168bb9 100644 --- a/install/updates/20-aci.update +++ b/install/updates/20-aci.update @@ -84,6 +84,7 @@ add:aci:(targetattr="*")(version 3.0; acl "Admin can read all tasks"; allow (rea dn: cn=mapping tree,cn=config add:aci: (target = "ldap:///cn=meTo($$dn),cn=*,cn=mapping tree,cn=config")(targetattr = "objectclass || cn")(version 3.0; acl "Allow hosts to read their replication agreements"; allow(read, search, compare) userdn = "ldap:///fqdn=($$dn),cn=computers,cn=accounts,$SUFFIX";) +remove: aci: (targetattr = "cn || createtimestamp || description || entryusn || modifytimestamp || nsds50ruv || nsds5beginreplicarefresh || nsds5debugreplicatimeout || nsds5flags || nsds5replicaabortcleanruv || nsds5replicaautoreferral || nsds5replicabackoffmax || nsds5replicabackoffmin || nsds5replicabinddn || nsds5replicabindmethod || nsds5replicabusywaittime || nsds5replicachangecount || nsds5replicachangessentsincestartup || nsds5replicacleanruv || nsds5replicacleanruvnotified || nsds5replicacredentials || nsds5replicaenabled || nsds5replicahost || nsds5replicaid || nsds5replicalastinitend || nsds5replicalastinitstart || nsds5replicalastinitstatus || nsds5replicalastupdateend || nsds5replicalastupdatestart || nsds5replicalastupdatestatus || nsds5replicalegacyconsumer || nsds5replicaname || nsds5replicaport || nsds5replicaprotocoltimeout || nsds5replicapurgedelay || nsds5replicareferral || nsds5replicaroot || nsds5replicasessionpausetime || nsds5replicastripattrs || nsds5replicatedattributelist || nsds5replicatedattributelisttotal || nsds5replicatimeout || nsds5replicatombstonepurgeinterval || nsds5replicatransportinfo || nsds5replicatype || nsds5replicaupdateinprogress || nsds5replicaupdateschedule || nsds5task || nsds7directoryreplicasubtree || nsds7dirsynccookie || nsds7newwingroupsyncenabled || nsds7newwinusersyncenabled || nsds7windowsdomain || nsds7windowsreplicasubtree || nsruvreplicalastmodified || nsstate || objectclass || onewaysync || winsyncdirectoryfilter || winsyncinterval || winsyncmoveaction || winsyncsubtreepair || winsyncwindowsfilter")(targetfilter = "(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0;acl "permission:Read Replication Agreements";allow (compare,read,search) groupdn = "ldap:///cn=Read Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";) # replication ACIs should reside in cn=mapping tree,cn=config and be common for both suffixes dn: cn=mapping tree,cn=config @@ -93,7 +94,7 @@ remove:aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5replicationagreemen add:aci: (targetattr = "*")(version 3.0;acl "permission:Add Replication Agreements";allow (add) groupdn = "ldap:///cn=Add Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";) add:aci: (targetattr = "*")(targetfilter="(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0; acl "permission:Modify Replication Agreements"; allow (read, write, search) groupdn = "ldap:///cn=Modify Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";) add:aci: (targetattr = "*")(targetfilter="(|(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement))")(version 3.0;acl "permission:Remove Replication Agreements";allow (delete) groupdn = "ldap:///cn=Remove Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";) -add: aci: (targetattr = "cn || createtimestamp || description || entryusn || modifytimestamp || nsds50ruv || nsds5beginreplicarefresh || nsds5debugreplicatimeout || nsds5flags || nsds5replicaabortcleanruv || nsds5replicaautoreferral || nsds5replicabackoffmax || nsds5replicabackoffmin || nsds5replicabinddn || nsds5replicabindmethod || nsds5replicabusywaittime || nsds5replicachangecount || nsds5replicachangessentsincestartup || nsds5replicacleanruv || nsds5replicacleanruvnotified || nsds5replicacredentials || nsds5replicaenabled || nsds5replicahost || nsds5replicaid || nsds5replicalastinitend || nsds5replicalastinitstart || nsds5replicalastinitstatus || nsds5replicalastupdateend || nsds5replicalastupdatestart || nsds5replicalastupdatestatus || nsds5replicalegacyconsumer || nsds5replicaname || nsds5replicaport || nsds5replicaprotocoltimeout || nsds5replicapurgedelay || nsds5replicareferral || nsds5replicaroot || nsds5replicasessionpausetime || nsds5replicastripattrs || nsds5replicatedattributelist || nsds5replicatedattributelisttotal || nsds5replicatimeout || nsds5replicatombstonepurgeinterval || nsds5replicatransportinfo || nsds5replicatype || nsds5replicaupdateinprogress || nsds5replicaupdateschedule || nsds5task || nsds7directoryreplicasubtree || nsds7dirsynccookie || nsds7newwingroupsyncenabled || nsds7newwinusersyncenabled || nsds7windowsdomain || nsds7windowsreplicasubtree || nsruvreplicalastmodified || nsstate || objectclass || onewaysync || winsyncdirectoryfilter || winsyncinterval || winsyncmoveaction || winsyncsubtreepair || winsyncwindowsfilter")(targetfilter = "(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0;acl "permission:Read Replication Agreements";allow (compare,read,search) groupdn = "ldap:///cn=Read Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";) +add: aci: (targetattr = "cn || createtimestamp || description || entryusn || modifytimestamp || nsds50ruv || nsds5beginreplicarefresh || nsds5debugreplicatimeout || nsds5flags || nsds5replicaabortcleanruv || nsds5replicaautoreferral || nsds5replicabackoffmax || nsds5replicabackoffmin || nsds5replicabinddn || nsds5replicabindmethod || nsds5replicabusywaittime || nsds5replicachangecount || nsds5replicachangessentsincestartup || nsds5replicacleanruv || nsds5replicacleanruvnotified || nsds5replicacredentials || nsds5replicaenabled || nsds5replicahost || nsds5replicaid || nsds5replicalastinitend || nsds5replicalastinitstart || nsds5replicalastinitstatus || nsds5replicalastinitstatusjson || nsds5replicalastupdateend || nsds5replicalastupdatestart || nsds5replicalastupdatestatus || nsds5replicalastupdatestatusjson || nsds5replicalegacyconsumer || nsds5replicaname || nsds5replicaport || nsds5replicaprotocoltimeout || nsds5replicapurgedelay || nsds5replicareferral || nsds5replicaroot || nsds5replicasessionpausetime || nsds5replicastripattrs || nsds5replicatedattributelist || nsds5replicatedattributelisttotal || nsds5replicatimeout || nsds5replicatombstonepurgeinterval || nsds5replicatransportinfo || nsds5replicatype || nsds5replicaupdateinprogress || nsds5replicaupdateschedule || nsds5task || nsds7directoryreplicasubtree || nsds7dirsynccookie || nsds7newwingroupsyncenabled || nsds7newwinusersyncenabled || nsds7windowsdomain || nsds7windowsreplicasubtree || nsruvreplicalastmodified || nsstate || objectclass || onewaysync || winsyncdirectoryfilter || winsyncinterval || winsyncmoveaction || winsyncsubtreepair || winsyncwindowsfilter")(targetfilter = "(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0;acl "permission:Read Replication Agreements";allow (compare,read,search) groupdn = "ldap:///cn=Read Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";) dn: cn="$SUFFIX",cn=mapping tree,cn=config diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py index e8407f3..6d4b30a 100644 --- a/ipaserver/install/replication.py +++ b/ipaserver/install/replication.py @@ -28,6 +28,7 @@ import time import datetime import sys import os +import json from random import randint import ldap @@ -1058,6 +1059,7 @@ class ReplicationManager: attrlist = ['cn', 'nsds5BeginReplicaRefresh', 'nsds5replicaUpdateInProgress', 'nsds5ReplicaLastInitStatus', + 'nsds5ReplicaLastInitStatusJSON', 'nsds5ReplicaLastInitStart', 'nsds5ReplicaLastInitEnd'] entry = conn.get_entry(agmtdn, attrlist) @@ -1068,7 +1070,14 @@ class ReplicationManager: refresh = entry.single_value.get('nsds5BeginReplicaRefresh') inprogress = entry.single_value.get('nsds5replicaUpdateInProgress') status = entry.single_value.get('nsds5ReplicaLastInitStatus') - if not refresh: # done - check status + json_status = \ + entry.single_value.get('nsds5ReplicaLastInitStatusJSON') + if not refresh: # done - check status + if json_status: + # Just reset status with the JSON 'message' + status_obj = json.loads(json_status) + status = status_obj['message'] + if not status: print("No status yet") elif status.find("replica busy") > -1: @@ -1099,8 +1108,11 @@ class ReplicationManager: done = False hasError = 0 error_message = '' - attrlist = ['cn', 'nsds5replicaUpdateInProgress', - 'nsds5ReplicaLastUpdateStatus', 'nsds5ReplicaLastUpdateStart', + attrlist = ['cn', + 'nsds5replicaUpdateInProgress', + 'nsds5ReplicaLastUpdateStatus', + 'nsds5ReplicaLastUpdateStatusjson', + 'nsds5ReplicaLastUpdateStart', 'nsds5ReplicaLastUpdateEnd'] entry = conn.get_entry(agmtdn, attrlist) if not entry: @@ -1109,6 +1121,8 @@ class ReplicationManager: else: inprogress = entry.single_value.get('nsds5replicaUpdateInProgress') status = entry.single_value.get('nsds5ReplicaLastUpdateStatus') + json_status = \ + entry.single_value.get('nsds5ReplicaLastUpdateStatusjson') try: # nsds5ReplicaLastUpdateStart is either a GMT time # ending with Z or 0 (see 389-ds ticket 47836) @@ -1134,7 +1148,15 @@ class ReplicationManager: logger.info("Replication Update in progress: %s: status: %s: " "start: %d: end: %d", inprogress, status, start, end) - if status: # always check for errors + if json_status: + # In 389-ds-base 1.4.1.4 we have the status message available + # to us in a json object + status_obj = json.loads(json_status) + if status_obj['state'] != 'green': + hasError = 1 + error_message = status_obj['message'] + done = True + elif status: # always check for errors # status will usually be a number followed by a string # number != 0 means error # Since 389-ds-base 1.3.5 it is 'Error (%d) %s'