from .config import LDAPMigrationConfiguration
-__version__ = '0.10.1'
+__version__ = '0.10.2'
LOG = logging.getLogger(__name__)
CFG_BASENAME = 'ldap-migration.ini'
re_token_split = re.compile(r'^\s*([a-z0-9]+)\s*=\s*(\S(?:.*\S)?)\s*$', re.IGNORECASE)
re_plus_in_cn = re.compile(r'(?P<before>\S)(?:\s+\+\s+|\s+\+|\+\s+)\s*(?P<after>\S)')
+ pattern_member_url = r'^\s*ldaps?:///(?P<base>[^\?]+)(?:\?[^\?]*\?'
+ pattern_member_url += r'(?P<scope>[^\?]+)(?:\?(?P<filter>.+))?)?'
+ re_member_url = re.compile(pattern_member_url)
+
rev_dn_samba_computers = 'o=isp:o=pixelpark:ou=Applications:ou=Unix NSS:ou=SambaComputers'
+ search_scope = {
+ 'base': BASE,
+ 'one': LEVEL,
+ 'sub': SUBTREE,
+ }
+
tz = get_localzone()
syntax = {
used_classes.add(tgt_oc_name)
if len(src_data['member_url']):
tgt_at_name = self.attribute_types.real_key('memberURL')
- target_entry[tgt_at_name] = src_data['member_url']
+ target_entry[tgt_at_name] = copy.copy(src_data['member_url'])
else:
tgt_oc_name = self.object_classes.real_key('groupOfUniqueNames')
used_classes.add(tgt_oc_name)
return (object_classes, target_entry)
# -------------------------------------------------------------------------
- def get_dyn_members(self, member_urls):
+ def get_dyn_members(self, member_urls, from_src=True):
members = CIStringSet()
+ urls = member_urls
+ if not is_sequence(member_urls):
+ urls = [member_urls]
+
+ for member_url in urls:
+ match = self.re_member_url.match(member_url)
+ if not match:
+ msg = "Could not evaluate memberURL {!r}.".format(member_url)
+ LOG.error(msg)
+ continue
+ base = match.group('base')
+ scope = 'base'
+ if match.group('scope'):
+ scope = match.group('scope').lower()
+ search_filter = None
+ if match.group('filter'):
+ search_filter = match.group('filter')
+
+ if scope not in self.search_scope:
+ msg = "Wrong search scope {scope!r} in memberURL {url!r}.".format(
+ scope=match.group('scope'), url=member_url)
+ LOG.error(msg)
+ continue
+ if self.verbose > 1:
+ target = 'target'
+ if from_src:
+ target = 'source'
+ msg = ("Searching members from {t} on search base {b!r}, scope {sc!r}, "
+ "filter {f!r} ...").format(t=target, b=base, sc=scope, f=search_filter)
+ LOG.debug(msg)
+ if from_src:
+ status, result, response, _ = self.source.search(
+ search_base=base, search_scope=self.search_scope[scope],
+ search_filter=search_filter, attributes=['dn'], time_limit=self.config.timeout)
+ else:
+ status, result, response, _ = self.target.search(
+ search_base=base, search_scope=self.search_scope[scope],
+ search_filter=search_filter, attributes=['dn'], time_limit=self.config.timeout)
+ for entry in response:
+ old_dn = entry['dn']
+ new_dn = old_dn
+ if from_src:
+ new_dn = self.mangle_dn(old_dn)
+ if self.verbose > 1:
+ LOG.debug("Found DN {!r}.".format(old_dn))
+ members.add(new_dn)
return members