Esempio n. 1
0
    def setup_mt(self, suffix, bename, parent=None):
        """Setup a suffix with the given backend-name.

            @param suffix
            @param bename
            @param parent   - the parent suffix 
            @param verbose  - None 

            This method does not create the matching entry in the tree,
            nor the given backend. Both should be created apart.
            
            Ex. setup_mt(suffix='o=addressbook1', bename='addressbook1')
                creates:
                    - the mapping in "cn=mapping tree,cn=config"
                you have to create:
                    - the backend 
                    - the ldap entry "o=addressbook1" *after*
        """
        nsuffix = normalizeDN(suffix)
        #escapedn = escapeDNValue(nsuffix)
        if parent:
            nparent = normalizeDN(parent)
        else:
            nparent = ""
            
        filt = suffixfilt(suffix)
        # if suffix exists, return
        try:
            entry = self.conn.getEntry(
                DN_MAPPING_TREE, ldap.SCOPE_SUBTREE, filt)
            return entry
        except NoSuchEntryError:
            entry = None

        # fix me when we can actually used escaped DNs
        #dn = "cn=%s,cn=mapping tree,cn=config" % escapedn
        dn = ','.join(('cn="%s"' % nsuffix, DN_MAPPING_TREE))
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject', 'nsMappingTree'],
            'nsslapd-state': 'backend',
            # the value in the dn has to be DN escaped
            # internal code will add the quoted value - unquoted value is useful for searching
            'cn': nsuffix,
            'nsslapd-backend': bename
        })
        #entry.setValues('cn', [escapedn, nsuffix]) # the value in the dn has to be DN escaped
        # the other value can be the unescaped value
        if parent:
            entry.setValues('nsslapd-parent-suffix', nparent)
        try:
            self.log.debug("Creating entry: %r" % entry)
            self.conn.add_s(entry)
        except ldap.LDAPError, e:
            raise ldap.LDAPError("Error adding suffix entry " + dn, e)
Esempio n. 2
0
    def setup_mt(self, suffix, bename, parent=None):
        """Setup a suffix with the given backend-name.

            @param suffix
            @param bename
            @param parent   - the parent suffix 
            @param verbose  - None 

            This method does not create the matching entry in the tree,
            nor the given backend. Both should be created apart.
            
            Ex. setup_mt(suffix='o=addressbook1', bename='addressbook1')
                creates:
                    - the mapping in "cn=mapping tree,cn=config"
                you have to create:
                    - the backend 
                    - the ldap entry "o=addressbook1" *after*
        """
        nsuffix = normalizeDN(suffix)
        #escapedn = escapeDNValue(nsuffix)
        if parent:
            nparent = normalizeDN(parent)
        else:
            nparent = ""
            
        filt = suffixfilt(suffix)
        # if suffix exists, return
        try:
            entry = self.conn.getEntry(
                DN_MAPPING_TREE, ldap.SCOPE_SUBTREE, filt)
            return entry
        except NoSuchEntryError:
            entry = None

        # fix me when we can actually used escaped DNs
        #dn = "cn=%s,cn=mapping tree,cn=config" % escapedn
        dn = ','.join(('cn="%s"' % nsuffix, DN_MAPPING_TREE))
        entry = Entry(dn)
        entry.update({
            'objectclass': ['top', 'extensibleObject', 'nsMappingTree'],
            'nsslapd-state': 'backend',
            # the value in the dn has to be DN escaped
            # internal code will add the quoted value - unquoted value is useful for searching
            'cn': nsuffix,
            'nsslapd-backend': bename
        })
        #entry.setValues('cn', [escapedn, nsuffix]) # the value in the dn has to be DN escaped
        # the other value can be the unescaped value
        if parent:
            entry.setValues('nsslapd-parent-suffix', nparent)
        try:
            self.log.debug("Creating entry: %r" % entry)
            self.conn.add_s(entry)
        except ldap.LDAPError, e:
            raise ldap.LDAPError("Error adding suffix entry " + dn, e)
Esempio n. 3
0
    def ruv(self, suffix, tryrepl=False):
        """return a replica update vector for the given suffix.

            @param suffix - eg. 'o=netscapeRoot'

            @raises NoSuchEntryError if missing
        """
        uuid = "ffffffff-ffffffff-ffffffff-ffffffff"
        filt = "(&(nsUniqueID=%s)(objectclass=nsTombstone))" % uuid
        attrs = ['nsds50ruv', 'nsruvReplicaLastModified']
        ents = self.conn.search_s(suffix, ldap.SCOPE_SUBTREE, filt, attrs)
        ent = None
        if ents and (len(ents) > 0):
            ent = ents[0]
        elif tryrepl:
            self.log.warn("Could not get RUV from %r entry - trying cn=replica" % suffix)
            ensuffix = escapeDNValue(normalizeDN(suffix))
            dn = ','.join(("cn=replica", "cn=%s" % ensuffix, DN_MAPPING_TREE))
            ents = self.conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*", attrs)

        if ents and (len(ents) > 0):
            ent = ents[0]
            self.log.debug("RUV entry is %r" % ent)
            return RUV(ent)

        raise NoSuchEntryError("RUV not found: suffix: %r" % suffix)
Esempio n. 4
0
    def ruv(self, suffix, tryrepl=False):
        """return a replica update vector for the given suffix.

            @param suffix - eg. 'o=netscapeRoot'

            @raises NoSuchEntryError if missing
        """
        uuid = "ffffffff-ffffffff-ffffffff-ffffffff"
        filt = "(&(nsUniqueID=%s)(objectclass=nsTombstone))" % uuid
        attrs = ['nsds50ruv', 'nsruvReplicaLastModified']
        ents = self.conn.search_s(suffix, ldap.SCOPE_SUBTREE, filt, attrs)
        ent = None
        if ents and (len(ents) > 0):
            ent = ents[0]
        elif tryrepl:
            self.log.warn("Could not get RUV from %r entry - trying cn=replica" % suffix)
            ensuffix = escapeDNValue(normalizeDN(suffix))
            dn = ','.join(("cn=replica", "cn=%s" % ensuffix, DN_MAPPING_TREE))
            ents = self.conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*", attrs)

        if ents and (len(ents) > 0):
            ent = ents[0]
            self.log.debug("RUV entry is %r" % ent)
            return RUV(ent)

        raise NoSuchEntryError("RUV not found: suffix: %r" % suffix)
Esempio n. 5
0
 def handle(self, dn, entry):
     """
     Append single record to dictionary of all records.
     """
     if not dn:
         dn = ''
     newentry = Entry((dn, entry))
     self.dndict[normalizeDN(dn)] = newentry
     self.dnlist.append(newentry)
Esempio n. 6
0
 def handle(self, dn, entry):
     """
     Append single record to dictionary of all records.
     """
     if not dn:
         dn = ''
     newentry = Entry((dn, entry))
     self.dndict[normalizeDN(dn)] = newentry
     self.dnlist.append(newentry)
Esempio n. 7
0
 def _list_by_suffix(self, suffix, attrs=None):    
     if suffix:
         nsuffix = normalizeDN(suffix)
     else:
         suffix = nsuffix = '*'
         
     entries = self.conn.search_s("cn=plugins,cn=config", ldap.SCOPE_SUBTREE,
                             "(&(objectclass=nsBackendInstance)(|(nsslapd-suffix=%s)(nsslapd-suffix=%s)))" % (suffix, nsuffix),
                             attrs)
     return entries
Esempio n. 8
0
 def _list_by_suffix(self, suffix, attrs=None):    
     if suffix:
         nsuffix = normalizeDN(suffix)
     else:
         suffix = nsuffix = '*'
         
     entries = self.conn.search_s("cn=plugins,cn=config", ldap.SCOPE_SUBTREE,
                             "(&(objectclass=nsBackendInstance)(|(nsslapd-suffix=%s)(nsslapd-suffix=%s)))" % (suffix, nsuffix),
                             attrs)
     return entries
Esempio n. 9
0
    def add(self, suffix, binddn=None, bindpw=None, urls=None, attrvals=None, benamebase='localdb', setupmt=False, parent=None):
        """Setup a backend and return its dn. Blank on error XXX should RAISE!
            @param suffix
            @param benamebase   -   the backend common name
            @param setupmt  - eventually setup Mapping Tree entry
            @param urls - a string of ldapurl - create a chaining backend
            @oaram binddn   -   chaining proxy user
            @param bindpw   -   chaining proxy password
            @param attrvals: a dict with further params like
                for ldbm    {
                                'nsslapd-cachememsize': '1073741824',
                                'nsslapd-cachesize': '-1',
                            }
                for chain   {
                                'nsmaxresponsedelay': '60',
                                'nsslapd-sizelimit': '-1'
                            }
                            
            ex.
            benamebase="Isle0-0"
            urls=[ 
                "ldaps://f0-ldap-vip.example.it:636/",
                "ldaps://ldap-18.example.it:636/",
                "ldaps://ldap-19.example.it:636/"
                ]
            
            NOTE: The suffix attribute is a mere string for the backend.
                the following action will work nicely:
                c.backend.add(suffix="foo=example,dc=com",benamebase="db1")
                    
            TODO: rename benamebase with cn
            TODO: split CHAIN and LDBM ? eg. backend.add_chain
        """
        attrvals = attrvals or {}
        dnbase = ""

        # figure out what type of be based on args
        if binddn and bindpw and urls:  # its a chaining be
            dnbase = DN_CHAIN
        else:  # its a ldbm be
            dnbase = DN_LDBM

        nsuffix = normalizeDN(suffix)
        try:
            cn = benamebase 
            self.log.debug("create backend with cn: %s" % cn)
            dn = "cn=" + cn + "," + dnbase
            entry = Entry(dn)
            entry.update({
                'objectclass': ['top', 'extensibleObject', 'nsBackendInstance'],
                'cn': cn,
                'nsslapd-suffix': nsuffix
            })

            if binddn and bindpw and urls:  # its a chaining be
                entry.update({
                             'nsfarmserverurl': urls,
                             'nsmultiplexorbinddn': binddn,
                             'nsmultiplexorcredentials': bindpw
                             })

            # set attrvals (but not cn, because it's in dn)
            # TODO do it in Entry
            if attrvals:
                entry.update(attrvals)

            self.log.debug("adding entry: %r" % entry)
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS, e:
            self.log.error("Entry already exists: %r" % dn)
            raise ldap.ALREADY_EXISTS("%s : %r" % (e, dn))
Esempio n. 10
0
    def agreement_add(self, consumer, suffix=None, binddn=None, bindpw=None, cn_format=r'meTo_$host:$port', description_format=r'me to $host:$port', timeout=120, auto_init=False, bindmethod='simple', starttls=False, schedule=ALWAYS, args=None):
        """Create (and return) a replication agreement from self to consumer.
            - self is the supplier,

            @param consumer: one of the following (consumer can be a master)
                    * a DSAdmin object if chaining
                    * an object with attributes: host, port, sslport, __str__
            @param suffix    - eg. 'dc=babel,dc=it'
            @param binddn    - 
            @param bindpw    -
            @param cn_format - string.Template to format the agreement name
            @param timeout   - replica timeout in seconds
            @param auto_init - start replication immediately
            @param bindmethod-  'simple'
            @param starttls  - True or False
            @param schedule  - when to schedule the replication. default: ALWAYS 
            @param args      - further args dict. Allowed keys:
                    'fractional',
                    'stripattrs',
                    'winsync'
                    
            @raise NosuchEntryError    - if a replica doesn't exist for that suffix
            @raise ALREADY_EXISTS
            @raise UNWILLING_TO_PERFORM if the database was previously
                    in read-only state. To create new agreements you
                    need to *restart* the directory server
            
            NOTE: this method doesn't cache connection entries
            
            TODO: test winsync 
            TODO: test chain
            
        """
        import string
        assert binddn and bindpw and suffix
        args = args or {}

        othhost, othport, othsslport = (
            consumer.host, consumer.port, consumer.sslport)
        othport = othsslport or othport
        nsuffix = normalizeDN(suffix)

        # adding agreement to previously created replica
        replica_entries = self.list(suffix)
        if not replica_entries:
            raise NoSuchEntryError(
                "Error: no replica set up for suffix " + suffix)
        replica = replica_entries[0]

        # define agreement entry
        cn = string.Template(cn_format).substitute({'host': othhost, 'port': othport})
        dn_agreement = ','.join(["cn=%s" % cn, replica.dn])

        # This is probably unnecessary because
        # we can just raise ALREADY_EXISTS
        try:
            entry = self.conn.getEntry(dn_agreement, ldap.SCOPE_BASE)
            self.log.warn("Agreement exists: %r" % dn_agreement)
            raise ldap.ALREADY_EXISTS
        except ldap.NO_SUCH_OBJECT:
            entry = None

        # In a separate function in this scope?
        entry = Entry(dn_agreement)
        entry.update({
            'objectclass': ["top", "nsds5replicationagreement"],
            'cn': cn,
            'nsds5replicahost': consumer.host,
            'nsds5replicatimeout': str(timeout),
            'nsds5replicabinddn': binddn,
            'nsds5replicacredentials': bindpw,
            'nsds5replicabindmethod': bindmethod,
            'nsds5replicaroot': nsuffix,
            'description': string.Template(description_format).substitute({'host': othhost, 'port': othport})
        })
        if schedule:
            if not re.match(r'\d{4}-\d{4} [0-6]{1,7}', schedule): # TODO put the regexp in a separate variable
                raise ValueError("Bad schedule format %r" % schedule)
            entry.update({'nsds5replicaupdateschedule': schedule})
        if starttls:
            entry.setValues('nsds5replicatransportinfo', 'TLS')
            entry.setValues('nsds5replicaport', str(othport))
        elif othsslport:
            entry.setValues('nsds5replicatransportinfo', 'SSL')
            entry.setValues('nsds5replicaport', str(othsslport))
        else:
            entry.setValues('nsds5replicatransportinfo', 'LDAP')
            entry.setValues('nsds5replicaport', str(othport))
            
        if auto_init:
            entry.setValues('nsds5BeginReplicaRefresh', 'start')
            
        # further arguments
        if 'fractional' in args:
            entry.setValues('nsDS5ReplicatedAttributeList', args['fractional'])
        if 'stripattrs' in args:
            entry.setValues('nsds5ReplicaStripAttrs', args['stripattrs'])
        if 'winsync' in args:  # state it clearly!
            self.conn.setupWinSyncAgmt(args, entry)

        try:
            self.log.debug("Adding replica agreement: [%s]" % entry)
            self.conn.add_s(entry)
        except:
            #  FIXME check please!
            raise

        entry = self.conn.waitForEntry(dn_agreement)
        if entry:
            # More verbose but shows what's going on
            if 'chain' in args:
                chain_args = {
                    'suffix': suffix,
                    'binddn': binddn,
                    'bindpw': bindpw
                }
                # Work on `self` aka producer
                if replica.nsds5replicatype == MASTER_TYPE:
                    self.setupChainingFarm(**chain_args)
                # Work on `consumer`
                # TODO - is it really required?
                if replica.nsds5replicatype == LEAF_TYPE:
                    chain_args.update({
                        'isIntermediate': 0,
                        'urls': self.conn.toLDAPURL(),
                        'args': args['chainargs']
                    })
                    consumer.setupConsumerChainOnUpdate(**chain_args)
                elif replica.nsds5replicatype == HUB_TYPE:
                    chain_args.update({
                        'isIntermediate': 1,
                        'urls': self.conn.toLDAPURL(),
                        'args': args['chainargs']
                    })
                    consumer.setupConsumerChainOnUpdate(**chain_args)

        return dn_agreement
Esempio n. 11
0
    def add(self, suffix, binddn, bindpw, rtype=MASTER_TYPE, rid=None, tombstone_purgedelay=None, purgedelay=None, referrals=None, legacy=False):
        """Setup a replica entry on an existing suffix.
            @param suffix - dn of suffix
            @param binddn - the replication bind dn for this replica
                            can also be a list ["cn=r1,cn=config","cn=r2,cn=config"]
            @param bindpw - used to eventually provision the replication entry

            @param rtype - master, hub, leaf (see above for values) - default is master
            @param rid - replica id or - if not given - an internal sequence number will be assigned

            # further args
            @param legacy - true or false - for legacy consumer
            @param tombstone_purgedelay
            @param purgedelay - changelog expiration time in seconds
            @param referrals

            Ex. replica.add(**{
                    'suffix': "dc=example,dc=com",
                    'type'  : dsadmin.MASTER_TYPE,
                    'binddn': "cn=replication manager,cn=config"
              })
             binddn
            TODO: this method does not update replica type
        """
        # set default values
        if rtype == MASTER_TYPE:
            rtype = REPLICA_RDWR_TYPE
        else:
            rtype = REPLICA_RDONLY_TYPE

        if legacy:
            legacy = 'on'
        else:
            legacy = 'off'

        # create replica entry in mapping-tree
        nsuffix = normalizeDN(suffix)
        mtent = self.conn.getMTEntry(suffix)
        dn_replica = ','.join(("cn=replica", mtent.dn))
        try:
            entry = self.conn.getEntry(dn_replica, ldap.SCOPE_BASE)
            self.log.warn("Already setup replica for suffix %r" % suffix)
            rec = self.conn.suffixes.setdefault(nsuffix, {})
            rec.update({'dn': dn_replica, 'type': rtype})
            return rec
        except ldap.NO_SUCH_OBJECT:
            entry = None

        # If a replica does not exist
        binddnlist = []
        if hasattr(binddn, '__iter__'):
            binddnlist = binddn
        else:
            binddnlist.append(binddn)

        entry = Entry(dn_replica)
        entry.update({
            'objectclass': ("top", "nsds5replica", "extensibleobject"),
            'cn': "replica",
            'nsds5replicaroot': nsuffix,
            'nsds5replicaid': str(rid),
            'nsds5replicatype': str(rtype),
            'nsds5replicalegacyconsumer': legacy,
            'nsds5replicabinddn': binddnlist
        })
        if rtype != LEAF_TYPE:
            entry.setValues('nsds5flags', "1")

        # other args
        if tombstone_purgedelay is not None:
            entry.setValues(
                'nsds5replicatombstonepurgeinterval', str(tombstone_purgedelay))
        if purgedelay is not None:
            entry.setValues('nsds5ReplicaPurgeDelay', str(purgedelay))
        if referrals:
            entry.setValues('nsds5ReplicaReferral', referrals)

        self.conn.add_s(entry)

        # check if the entry exists TODO better to raise!
        self.conn._test_entry(dn_replica, ldap.SCOPE_BASE)

        self.conn.suffixes[nsuffix] = {'dn': dn_replica, 'type': rtype}
        return {'dn': dn_replica, 'type': rtype}
Esempio n. 12
0
 def get(self, dn):
     ndn = normalizeDN(dn)
     return self.dndict.get(ndn, Entry(None))
Esempio n. 13
0
    def add(self, suffix, binddn=None, bindpw=None, urls=None, attrvals=None, benamebase='localdb', setupmt=False, parent=None):
        """Setup a backend and return its dn. Blank on error XXX should RAISE!
            @param suffix
            @param benamebase   -   the backend common name
            @param setupmt  - eventually setup Mapping Tree entry
            @param urls - a string of ldapurl - create a chaining backend
            @oaram binddn   -   chaining proxy user
            @param bindpw   -   chaining proxy password
            @param attrvals: a dict with further params like
                for ldbm    {
                                'nsslapd-cachememsize': '1073741824',
                                'nsslapd-cachesize': '-1',
                            }
                for chain   {
                                'nsmaxresponsedelay': '60',
                                'nsslapd-sizelimit': '-1'
                            }
                            
            ex.
            benamebase="Isle0-0"
            urls=[ 
                "ldaps://f0-ldap-vip.example.it:636/",
                "ldaps://ldap-18.example.it:636/",
                "ldaps://ldap-19.example.it:636/"
                ]
            
            NOTE: The suffix attribute is a mere string for the backend.
                the following action will work nicely:
                c.backend.add(suffix="foo=example,dc=com",benamebase="db1")
                    
            TODO: rename benamebase with cn
            TODO: split CHAIN and LDBM ? eg. backend.add_chain
        """
        attrvals = attrvals or {}
        dnbase = ""

        # figure out what type of be based on args
        if binddn and bindpw and urls:  # its a chaining be
            dnbase = DN_CHAIN
        else:  # its a ldbm be
            dnbase = DN_LDBM

        nsuffix = normalizeDN(suffix)
        try:
            cn = benamebase 
            self.log.debug("create backend with cn: %s" % cn)
            dn = "cn=" + cn + "," + dnbase
            entry = Entry(dn)
            entry.update({
                'objectclass': ['top', 'extensibleObject', 'nsBackendInstance'],
                'cn': cn,
                'nsslapd-suffix': nsuffix
            })

            if binddn and bindpw and urls:  # its a chaining be
                entry.update({
                             'nsfarmserverurl': urls,
                             'nsmultiplexorbinddn': binddn,
                             'nsmultiplexorcredentials': bindpw
                             })

            # set attrvals (but not cn, because it's in dn)
            # TODO do it in Entry
            if attrvals:
                entry.update(attrvals)

            self.log.debug("adding entry: %r" % entry)
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS, e:
            self.log.error("Entry already exists: %r" % dn)
            raise ldap.ALREADY_EXISTS("%s : %r" % (e, dn))
Esempio n. 14
0
    def agreement_add(self, consumer, suffix=None, binddn=None, bindpw=None, cn_format=r'meTo_$host:$port', description_format=r'me to $host:$port', timeout=120, auto_init=False, bindmethod='simple', starttls=False, schedule=ALWAYS, args=None):
        """Create (and return) a replication agreement from self to consumer.
            - self is the supplier,

            @param consumer: one of the following (consumer can be a master)
                    * a DSAdmin object if chaining
                    * an object with attributes: host, port, sslport, __str__
            @param suffix    - eg. 'dc=babel,dc=it'
            @param binddn    - 
            @param bindpw    -
            @param cn_format - string.Template to format the agreement name
            @param timeout   - replica timeout in seconds
            @param auto_init - start replication immediately
            @param bindmethod-  'simple'
            @param starttls  - True or False
            @param schedule  - when to schedule the replication. default: ALWAYS 
            @param args      - further args dict. Allowed keys:
                    'fractional',
                    'stripattrs',
                    'winsync'
                    
            @raise NosuchEntryError    - if a replica doesn't exist for that suffix
            @raise ALREADY_EXISTS
            @raise UNWILLING_TO_PERFORM if the database was previously
                    in read-only state. To create new agreements you
                    need to *restart* the directory server
            
            NOTE: this method doesn't cache connection entries
            
            TODO: test winsync 
            TODO: test chain
            
        """
        import string
        assert binddn and bindpw and suffix
        args = args or {}

        othhost, othport, othsslport = (
            consumer.host, consumer.port, consumer.sslport)
        othport = othsslport or othport
        nsuffix = normalizeDN(suffix)

        # adding agreement to previously created replica
        replica_entries = self.list(suffix)
        if not replica_entries:
            raise NoSuchEntryError(
                "Error: no replica set up for suffix " + suffix)
        replica = replica_entries[0]

        # define agreement entry
        cn = string.Template(cn_format).substitute({'host': othhost, 'port': othport})
        dn_agreement = ','.join(["cn=%s" % cn, replica.dn])

        # This is probably unnecessary because
        # we can just raise ALREADY_EXISTS
        try:
            entry = self.conn.getEntry(dn_agreement, ldap.SCOPE_BASE)
            self.log.warn("Agreement exists: %r" % dn_agreement)
            raise ldap.ALREADY_EXISTS
        except ldap.NO_SUCH_OBJECT:
            entry = None

        # In a separate function in this scope?
        entry = Entry(dn_agreement)
        entry.update({
            'objectclass': ["top", "nsds5replicationagreement"],
            'cn': cn,
            'nsds5replicahost': consumer.host,
            'nsds5replicatimeout': str(timeout),
            'nsds5replicabinddn': binddn,
            'nsds5replicacredentials': bindpw,
            'nsds5replicabindmethod': bindmethod,
            'nsds5replicaroot': nsuffix,
            'description': string.Template(description_format).substitute({'host': othhost, 'port': othport})
        })
        if schedule:
            if not re.match(r'\d{4}-\d{4} [0-6]{1,7}', schedule): # TODO put the regexp in a separate variable
                raise ValueError("Bad schedule format %r" % schedule)
            entry.update({'nsds5replicaupdateschedule': schedule})
        if starttls:
            entry.setValues('nsds5replicatransportinfo', 'TLS')
            entry.setValues('nsds5replicaport', str(othport))
        elif othsslport:
            entry.setValues('nsds5replicatransportinfo', 'SSL')
            entry.setValues('nsds5replicaport', str(othsslport))
        else:
            entry.setValues('nsds5replicatransportinfo', 'LDAP')
            entry.setValues('nsds5replicaport', str(othport))
            
        if auto_init:
            entry.setValues('nsds5BeginReplicaRefresh', 'start')
            
        # further arguments
        if 'fractional' in args:
            entry.setValues('nsDS5ReplicatedAttributeList', args['fractional'])
        # use the specified fractional total - if not specified, use the
        # specified fractional - if not specified, skip
        frac_total = args.get('fractional_total', args.get('fractional', None))
        if frac_total:
            entry.setValues('nsDS5ReplicatedAttributeListTotal', frac_total)
        if 'stripattrs' in args:
            entry.setValues('nsds5ReplicaStripAttrs', args['stripattrs'])
        if 'winsync' in args:  # state it clearly!
            self.conn.setupWinSyncAgmt(args, entry)

        try:
            self.log.debug("Adding replica agreement: [%s]" % entry)
            self.conn.add_s(entry)
        except:
            #  FIXME check please!
            raise

        entry = self.conn.waitForEntry(dn_agreement)
        if entry:
            # More verbose but shows what's going on
            if 'chain' in args:
                chain_args = {
                    'suffix': suffix,
                    'binddn': binddn,
                    'bindpw': bindpw
                }
                # Work on `self` aka producer
                if replica.nsds5replicatype == MASTER_TYPE:
                    self.setupChainingFarm(**chain_args)
                # Work on `consumer`
                # TODO - is it really required?
                if replica.nsds5replicatype == LEAF_TYPE:
                    chain_args.update({
                        'isIntermediate': 0,
                        'urls': self.conn.toLDAPURL(),
                        'args': args['chainargs']
                    })
                    consumer.setupConsumerChainOnUpdate(**chain_args)
                elif replica.nsds5replicatype == HUB_TYPE:
                    chain_args.update({
                        'isIntermediate': 1,
                        'urls': self.conn.toLDAPURL(),
                        'args': args['chainargs']
                    })
                    consumer.setupConsumerChainOnUpdate(**chain_args)

        return dn_agreement
Esempio n. 15
0
    def add(self, suffix, binddn, bindpw, rtype=MASTER_TYPE, rid=None, tombstone_purgedelay=None, purgedelay=None, referrals=None, legacy=False):
        """Setup a replica entry on an existing suffix.
            @param suffix - dn of suffix
            @param binddn - the replication bind dn for this replica
                            can also be a list ["cn=r1,cn=config","cn=r2,cn=config"]
            @param bindpw - used to eventually provision the replication entry

            @param rtype - master, hub, leaf (see above for values) - default is master
            @param rid - replica id or - if not given - an internal sequence number will be assigned

            # further args
            @param legacy - true or false - for legacy consumer
            @param tombstone_purgedelay
            @param purgedelay - changelog expiration time in seconds
            @param referrals

            Ex. replica.add(**{
                    'suffix': "dc=example,dc=com",
                    'type'  : dsadmin.MASTER_TYPE,
                    'binddn': "cn=replication manager,cn=config"
              })
             binddn
            TODO: this method does not update replica type
        """
        # set default values
        if rtype == MASTER_TYPE:
            rtype = REPLICA_RDWR_TYPE
        else:
            rtype = REPLICA_RDONLY_TYPE

        if legacy:
            legacy = 'on'
        else:
            legacy = 'off'

        # create replica entry in mapping-tree
        nsuffix = normalizeDN(suffix)
        mtent = self.conn.getMTEntry(suffix)
        dn_replica = ','.join(("cn=replica", mtent.dn))
        try:
            entry = self.conn.getEntry(dn_replica, ldap.SCOPE_BASE)
            self.log.warn("Already setup replica for suffix %r" % suffix)
            rec = self.conn.suffixes.setdefault(nsuffix, {})
            rec.update({'dn': dn_replica, 'type': rtype})
            return rec
        except ldap.NO_SUCH_OBJECT:
            entry = None

        # If a replica does not exist
        binddnlist = []
        if hasattr(binddn, '__iter__'):
            binddnlist = binddn
        else:
            binddnlist.append(binddn)

        entry = Entry(dn_replica)
        entry.update({
            'objectclass': ("top", "nsds5replica", "extensibleobject"),
            'cn': "replica",
            'nsds5replicaroot': nsuffix,
            'nsds5replicaid': str(rid),
            'nsds5replicatype': str(rtype),
            'nsds5replicalegacyconsumer': legacy,
            'nsds5replicabinddn': binddnlist
        })
        if rtype != LEAF_TYPE:
            entry.setValues('nsds5flags', "1")

        # other args
        if tombstone_purgedelay is not None:
            entry.setValues(
                'nsds5replicatombstonepurgeinterval', str(tombstone_purgedelay))
        if purgedelay is not None:
            entry.setValues('nsds5ReplicaPurgeDelay', str(purgedelay))
        if referrals:
            entry.setValues('nsds5ReplicaReferral', referrals)

        self.conn.add_s(entry)

        # check if the entry exists TODO better to raise!
        self.conn._test_entry(dn_replica, ldap.SCOPE_BASE)

        self.conn.suffixes[nsuffix] = {'dn': dn_replica, 'type': rtype}
        return {'dn': dn_replica, 'type': rtype}
Esempio n. 16
0
 def get(self, dn):
     ndn = normalizeDN(dn)
     return self.dndict.get(ndn, Entry(None))