Rework task naming in LDAP updates to avoid conflicting names in certain cases

There are two problems in task naming in LDAP updates:

1. Randomness may be scarce in virtual machines
2. Random number is added to the time value rounded to a second

The second issue leads to values that may repeat themselves as time
only grows and random number is non-negative as well, so
t2+r2 can be equal to t1+t2 generated earlier.

Since task name is a DN, there is no strict requirement to use an integer value.
Instead, we generate an UUID and use its 60-bit time, 14-bit sequential number,
and attribute name.

https://fedorahosted.org/freeipa/ticket/2942
This commit is contained in:
Alexander Bokovoy 2012-07-24 12:07:23 +03:00 committed by Rob Crittenden
parent 1235739122
commit cc42d19e35

View File

@ -29,9 +29,11 @@ from ipaserver.install import installutils
from ipaserver.install import service
from ipaserver import ipaldap
from ipapython import entity, ipautil
import uuid
from ipalib import util
from ipalib import errors
from ipalib import api
from ipalib.dn import DN
import ldap
from ldap.dn import escape_dn_chars
from ipapython.ipa_log_manager import *
@ -328,16 +330,14 @@ class LDAPUpdate:
if self.live_run:
time.sleep(5)
r = random.SystemRandom()
cn_uuid = uuid.uuid1()
# cn_uuid.time is in nanoseconds, but other users of LDAPUpdate expect
# seconds in 'TIME' so scale the value down
self.sub_dict['TIME'] = int(cn_uuid.time/1e9)
cn = "indextask_%s_%s_%s" % (attribute, cn_uuid.time, cn_uuid.clock_seq)
dn = DN(('cn', cn), ('cn', 'index'), ('cn', 'tasks'), ('cn', 'config'))
# Refresh the time to make uniqueness more probable. Add on some
# randomness for good measure.
self.sub_dict['TIME'] = int(time.time()) + r.randint(0,10000)
cn = self._template_str("indextask_$TIME")
dn = "cn=%s, cn=index, cn=tasks, cn=config" % cn
e = ipaldap.Entry(dn)
e = ipaldap.Entry(str(dn))
e.setValues('objectClass', ['top', 'extensibleObject'])
e.setValue('cn', cn)