[SCM] Samba Shared Repository - branch master updated

Douglas Bagnall dbagnall at samba.org
Wed Mar 21 08:26:02 UTC 2018


The branch, master has been updated
       via  9312a1c samba-tool visualize: fix python2.6 incompatibility
       via  bddf66c samba-tool ldapcmp: remove duplicate takes_optiongroups attribute
       via  2b87bf8 samba_dnsupdate: Introduce automatic site coverage
       via  79b640f tests/samba_dnsupdate: Add a trivial test of automatic site coverage
       via  b71f897 tests/kcc_util: Add unit tests for automatic site coverage
       via  ecf503c kcc_utils: Use lower name in automatic sites covered
       via  f342d7e kcc_utils: Prevent multiple sites attached to a sitelink covering a site
       via  96340e1 kcc_utils: Keep a count of the DCs in each site
       via  32a5431 kcc_utils: Add a routine for automatic site coverage
       via  245e179 join.py: Add missing NTSTATUSError import
      from  e9d42e5 s3:registry: Fix size types and length calculations

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 9312a1cdafbd5a0140d72502487c4e478dc578d2
Author: Björn Baumbach <bb at sernet.de>
Date:   Tue Mar 20 12:15:22 2018 +0100

    samba-tool visualize: fix python2.6 incompatibility
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13337
    
    Signed-off-by: Björn Baumbach <bb at sernet.de>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    
    Autobuild-User(master): Douglas Bagnall <dbagnall at samba.org>
    Autobuild-Date(master): Wed Mar 21 09:25:51 CET 2018 on sn-devel-144

commit bddf66c460241378fb9248d630cf66f0e7740ed2
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Mar 9 16:13:01 2018 +1300

    samba-tool ldapcmp: remove duplicate takes_optiongroups attribute
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2b87bf8c0984df65f7d0396f40442432c8b57c4b
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Mon Mar 12 14:45:48 2018 +1300

    samba_dnsupdate: Introduce automatic site coverage
    
    This uses the underlying function in kcc_utils.py which already has
    tests.
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 79b640f84e32ccd548d78e427b1cbdad1df21669
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Mon Mar 19 16:50:36 2018 +1300

    tests/samba_dnsupdate: Add a trivial test of automatic site coverage
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit b71f897b4feba0b6cae6c6c3d9c3122ebc640e38
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Wed Mar 14 16:53:13 2018 +1300

    tests/kcc_util: Add unit tests for automatic site coverage
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit ecf503ce76cd241e0e095279642820f72c8a7fba
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Wed Mar 14 16:52:58 2018 +1300

    kcc_utils: Use lower name in automatic sites covered
    
    This allows easier testing, as well as some consistency in the DNS
    record creation.
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit f342d7e0256eda8f6702c0f2c7752fbcf459ba8f
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Tue Mar 13 14:41:23 2018 +1300

    kcc_utils: Prevent multiple sites attached to a sitelink covering a site
    
    This avoids trivial duplicates in a similar manner as mentioned in:
    
    https://blogs.technet.microsoft.com/askds/2011/04/29/sites-sites-everywhere/
    
    It prefers the largest sites then the earliest alphabetically, so that
    only a single site ever covers an uncovered site (within a site link).
    Note that this isn't applicable over multiple site links (like Windows
    presumably) and is only a simple mechanism to avoid excessive
    registering.  DCs within the site will also still register for each.
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 96340e1ad2b15ab513e20e5a4317b90811c06bba
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Tue Mar 13 14:11:14 2018 +1300

    kcc_utils: Keep a count of the DCs in each site
    
    This is useful for ranking which sites are preferable within the same
    site link.
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 32a543198769c0e50f2039325d2e6eafdd877ba4
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Tue Mar 13 13:04:12 2018 +1300

    kcc_utils: Add a routine for automatic site coverage
    
    This allows double-coverage if two links exist with the same cost.
    Administrators should only connect an DC-less site via a single site
    link.
    
    This also allows unnecessary coverage by all sites in the adjoining site
    link (to be resolved in the later patches).
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 245e179340bd870e486957f0a4b82be23ebc9f5a
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Mon Mar 12 14:44:58 2018 +1300

    join.py: Add missing NTSTATUSError import
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

-----------------------------------------------------------------------

Summary of changes:
 python/samba/join.py                           |   2 +-
 python/samba/kcc/kcc_utils.py                  | 112 ++++++++
 python/samba/netcmd/ldapcmp.py                 |   6 -
 python/samba/netcmd/visualize.py               |   6 +-
 python/samba/tests/blackbox/samba_dnsupdate.py |  54 ++++
 python/samba/tests/kcc/kcc_utils.py            | 352 +++++++++++++++++++++++++
 selftest/tests.py                              |   1 -
 source4/scripting/bin/samba_dnsupdate          |  27 ++
 source4/selftest/tests.py                      |   2 +
 9 files changed, 553 insertions(+), 9 deletions(-)


Changeset truncated at 500 lines:

diff --git a/python/samba/join.py b/python/samba/join.py
index 22deff0..4eaf05c 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -35,7 +35,7 @@ from samba.provision.sambadns import setup_bind9_dns
 from samba import read_and_sub_file
 from samba import werror
 from base64 import b64encode
-from samba import WERRORError
+from samba import WERRORError, NTSTATUSError
 from samba.dnsserver import ARecord, AAAARecord, PTRRecord, CNameRecord, NSRecord, MXRecord, SOARecord, SRVRecord, TXTRecord
 from samba import sd_utils
 import logging
diff --git a/python/samba/kcc/kcc_utils.py b/python/samba/kcc/kcc_utils.py
index 7c292a6..a4870a3 100644
--- a/python/samba/kcc/kcc_utils.py
+++ b/python/samba/kcc/kcc_utils.py
@@ -31,6 +31,7 @@ from samba.dcerpc import (
     )
 from samba.common import dsdb_Dn
 from samba.ndr import ndr_unpack, ndr_pack
+from collections import Counter
 
 
 class KCCError(Exception):
@@ -2252,3 +2253,114 @@ def new_connection_schedule():
 
     schedule.dataArray = [data]
     return schedule
+
+
+##################################################
+# DNS related calls
+##################################################
+
+def uncovered_sites_to_cover(samdb, site_name):
+    """
+    Discover which sites have no DCs and whose lowest single-hop cost
+    distance for any link attached to that site is linked to the site supplied.
+
+    We compare the lowest cost of your single-hop link to this site to all of
+    those available (if it exists). This means that a lower ranked siteLink
+    with only the uncovered site can trump any available links (but this can
+    only be done with specific, poorly enacted user configuration).
+
+    If the site is connected to more than one other site with the same
+    siteLink, only the largest site (failing that sorted alphabetically)
+    creates the DNS records.
+
+    :param samdb database
+    :param site_name origin site (with a DC)
+
+    :return a list of sites this site should be covering (for DNS)
+    """
+    sites_to_cover = []
+
+    server_res = samdb.search(base=samdb.get_config_basedn(),
+                              scope=ldb.SCOPE_SUBTREE,
+                              expression="(&(objectClass=server)"
+                              "(serverReference=*))")
+
+    site_res = samdb.search(base=samdb.get_config_basedn(),
+                            scope=ldb.SCOPE_SUBTREE,
+                            expression="(objectClass=site)")
+
+    sites_in_use = Counter()
+    dc_count = 0
+
+    # Assume server is of form DC,Servers,Site-ABCD because of schema
+    for msg in server_res:
+        site_dn = msg.dn.parent().parent()
+        sites_in_use[site_dn.canonical_str()] += 1
+
+        if site_dn.get_rdn_value().lower() == site_name.lower():
+            dc_count += 1
+
+    if len(sites_in_use) != len(site_res):
+        # There is a possible uncovered site
+        sites_uncovered = []
+
+        for msg in site_res:
+            if msg.dn.canonical_str() not in sites_in_use:
+                sites_uncovered.append(msg)
+
+        own_site_dn = "CN={},CN=Sites,{}".format(
+            ldb.binary_encode(site_name),
+            ldb.binary_encode(str(samdb.get_config_basedn()))
+        )
+
+        for site in sites_uncovered:
+            encoded_dn = ldb.binary_encode(str(site.dn))
+
+            # Get a sorted list of all siteLinks featuring the uncovered site
+            link_res1 = samdb.search(base=samdb.get_config_basedn(),
+                                     scope=ldb.SCOPE_SUBTREE, attrs=["cost"],
+                                     expression="(&(objectClass=siteLink)"
+                                     "(siteList={}))".format(encoded_dn),
+                                     controls=["server_sort:1:0:cost"])
+
+            # Get a sorted list of all siteLinks connecting this an the
+            # uncovered site
+            link_res2 = samdb.search(base=samdb.get_config_basedn(),
+                                     scope=ldb.SCOPE_SUBTREE,
+                                     attrs=["cost", "siteList"],
+                                     expression="(&(objectClass=siteLink)"
+                                     "(siteList={})(siteList={}))".format(
+                                         own_site_dn,
+                                         encoded_dn),
+                                     controls=["server_sort:1:0:cost"])
+
+            # Add to list if your link is equal in cost to lowest cost link
+            if len(link_res1) > 0 and len(link_res2) > 0:
+                cost1 = int(link_res1[0]['cost'][0])
+                cost2 = int(link_res2[0]['cost'][0])
+
+                # Own siteLink must match the lowest cost link
+                if cost1 != cost2:
+                    continue
+
+                # In a siteLink with more than 2 sites attached, only pick the
+                # largest site, and if there are multiple, the earliest
+                # alphabetically.
+                to_cover = True
+                for site_val in link_res2[0]['siteList']:
+                    site_dn = ldb.Dn(samdb, str(site_val))
+                    site_dn_str = site_dn.canonical_str()
+                    site_rdn = site_dn.get_rdn_value().lower()
+                    if sites_in_use[site_dn_str] > dc_count:
+                        to_cover = False
+                        break
+                    elif (sites_in_use[site_dn_str] == dc_count and
+                          site_rdn < site_name.lower()):
+                        to_cover = False
+                        break
+
+                if to_cover:
+                    site_cover_rdn = site.dn.get_rdn_value()
+                    sites_to_cover.append(site_cover_rdn.lower())
+
+    return sites_to_cover
diff --git a/python/samba/netcmd/ldapcmp.py b/python/samba/netcmd/ldapcmp.py
index 87d4531..4e5abad 100644
--- a/python/samba/netcmd/ldapcmp.py
+++ b/python/samba/netcmd/ldapcmp.py
@@ -889,12 +889,6 @@ class cmd_ldapcmp(Command):
         "credopts": options.CredentialsOptionsDouble,
     }
 
-    takes_optiongroups = {
-        "sambaopts": options.SambaOptions,
-        "versionopts": options.VersionOptions,
-        "credopts": options.CredentialsOptionsDouble,
-    }
-
     takes_args = ["URL1", "URL2", "context1?", "context2?", "context3?", "context4?", "context5?"]
 
     takes_options = [
diff --git a/python/samba/netcmd/visualize.py b/python/samba/netcmd/visualize.py
index 473872a..3e5b950 100644
--- a/python/samba/netcmd/visualize.py
+++ b/python/samba/netcmd/visualize.py
@@ -176,7 +176,11 @@ def get_partition_maps(samdb):
         "DNSDOMAIN": "DC=DomainDnsZones,%s" % base_dn,
         "DNSFOREST": "DC=ForestDnsZones,%s" % base_dn
     }
-    long_to_short = {v: k for k, v in short_to_long.iteritems()}
+
+    long_to_short = {}
+    for s, l in short_to_long.iteritems():
+        long_to_short[l] = s
+
     return short_to_long, long_to_short
 
 
diff --git a/python/samba/tests/blackbox/samba_dnsupdate.py b/python/samba/tests/blackbox/samba_dnsupdate.py
index 7ddaab7..e6cad3b 100644
--- a/python/samba/tests/blackbox/samba_dnsupdate.py
+++ b/python/samba/tests/blackbox/samba_dnsupdate.py
@@ -17,6 +17,12 @@
 #
 
 import samba.tests
+from StringIO import StringIO
+from samba.netcmd.main import cmd_sambatool
+from samba.credentials import Credentials
+from samba.auth import system_session
+from samba.samdb import SamDB
+import ldb
 
 class SambaDnsUpdateTests(samba.tests.BlackboxTestCase):
     """Blackbox test case for samba_dnsupdate."""
@@ -57,3 +63,51 @@ class SambaDnsUpdateTests(samba.tests.BlackboxTestCase):
         self.assertTrue(" DNS deletes needed" in rpc_out, rpc_out)
         out = self.check_output("samba_dnsupdate --verbose")
         self.assertTrue("No DNS updates needed" in out, out + rpc_out)
+
+    def test_add_new_uncovered_site(self):
+        name = 'sites'
+        cmd = cmd_sambatool.subcommands[name]
+        cmd.outf = StringIO()
+        cmd.errf = StringIO()
+
+        site_name = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+        # Clear out any existing site
+        cmd._run("samba-tool %s" % name, 'remove', site_name)
+
+        result = cmd._run("samba-tool %s" % name, 'create', site_name)
+        if result is not None:
+            self.fail("Error creating new site")
+
+        self.lp = samba.tests.env_loadparm()
+        self.creds = Credentials()
+        self.creds.guess(self.lp)
+        self.session = system_session()
+
+        self.samdb = SamDB(session_info=self.session,
+                           credentials=self.creds,
+                           lp=self.lp)
+
+        m = ldb.Message()
+        m.dn = ldb.Dn(self.samdb, 'CN=DEFAULTIPSITELINK,CN=IP,'
+                      'CN=Inter-Site Transports,CN=Sites,{}'.format(
+                          self.samdb.get_config_basedn()))
+        m['siteList'] = ldb.MessageElement("CN={},CN=Sites,{}".format(
+            site_name,
+            self.samdb.get_config_basedn()),
+            ldb.FLAG_MOD_ADD, "siteList")
+
+        out = self.check_output("samba_dnsupdate --verbose")
+        self.assertTrue("No DNS updates needed" in out, out)
+
+        self.samdb.modify(m)
+
+        out = self.check_output("samba_dnsupdate --verbose --use-samba-tool"
+                                " --rpc-server-ip={}".format(self.server_ip))
+
+        self.assertFalse("No DNS updates needed" in out, out)
+        self.assertTrue(site_name.lower() in out, out)
+
+        result = cmd._run("samba-tool %s" % name, 'remove', site_name)
+        if result is not None:
+            self.fail("Error deleting site")
diff --git a/python/samba/tests/kcc/kcc_utils.py b/python/samba/tests/kcc/kcc_utils.py
index ac59bee..ae0aee3 100644
--- a/python/samba/tests/kcc/kcc_utils.py
+++ b/python/samba/tests/kcc/kcc_utils.py
@@ -21,6 +21,10 @@
 import samba
 import samba.tests
 from samba.kcc.kcc_utils import *
+from samba.credentials import Credentials
+from samba.auth import system_session
+from samba.samdb import SamDB
+from samba.tests import delete_force
 
 
 class ScheduleTests(samba.tests.TestCase):
@@ -35,3 +39,351 @@ class ScheduleTests(samba.tests.TestCase):
 # OK, this is pathetic, but the rest of it looks really hard, with the
 # classes all intertwingled with each other and the samdb. That is to say:
 # XXX later.
+
+class SiteCoverageTests(samba.tests.TestCase):
+
+    def setUp(self):
+        self.prefix = "kcc_"
+        self.lp = samba.tests.env_loadparm()
+
+        self.sites = {}
+        self.site_links = {}
+
+        self.creds = Credentials()
+        self.creds.guess(self.lp)
+        self.session = system_session()
+
+        self.samdb = SamDB(session_info=self.session,
+                           credentials=self.creds,
+                           lp=self.lp)
+
+    def tearDown(self):
+        self.samdb.transaction_start()
+
+        for site in self.sites:
+            delete_force(self.samdb, site, controls=['tree_delete:1'])
+
+        for site_link in self.site_links:
+            delete_force(self.samdb, site_link)
+
+        self.samdb.transaction_commit()
+
+    def _add_server(self, name, site):
+        dn = "CN={},CN=Servers,{}".format(name, site)
+        self.samdb.add({
+            "dn": dn,
+            "objectClass": "server",
+            "serverReference": self.samdb.domain_dn()
+        })
+        return dn
+
+    def _add_site(self, name):
+        dn = "CN={},CN=Sites,{}".format(
+            name, self.samdb.get_config_basedn()
+        )
+        self.samdb.add({
+            "dn": dn,
+            "objectClass": "site"
+        })
+        self.samdb.add({
+            "dn": "CN=Servers," + dn,
+            "objectClass": ["serversContainer"]
+        })
+
+        self.sites[dn] = name
+        return dn, name.lower()
+
+    def _add_site_link(self, name, links=[], cost=100):
+        dn = "CN={},CN=IP,CN=Inter-Site Transports,CN=Sites,{}".format(
+            name, self.samdb.get_config_basedn()
+        )
+        self.samdb.add({
+            "dn": dn,
+            "objectClass": "siteLink",
+            "cost": str(cost),
+            "siteList": links
+        })
+        self.site_links[dn] = name
+        return dn
+
+    def test_single_site_link_same_dc_count(self):
+        self.samdb.transaction_start()
+        site1, name1 = self._add_site(self.prefix + "ABCD")
+        site2, name2 = self._add_site(self.prefix + "BCDE")
+
+        uncovered_dn, uncovered = self._add_site(self.prefix + "uncovered")
+
+        self._add_server(self.prefix + "ABCD" + '1', site1)
+        self._add_server(self.prefix + "BCDE" + '1', site2)
+
+        self._add_site_link(self.prefix + "link",
+                            [site1, site2, uncovered_dn])
+        self.samdb.transaction_commit()
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name1)
+        to_cover.sort()
+
+        self.assertEqual([uncovered], to_cover)
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name2)
+        to_cover.sort()
+
+        self.assertEqual([], to_cover)
+
+    def test_single_site_link_different_dc_count(self):
+        self.samdb.transaction_start()
+        site1, name1 = self._add_site(self.prefix + "ABCD")
+        site2, name2 = self._add_site(self.prefix + "BCDE")
+
+        uncovered_dn, uncovered = self._add_site(self.prefix + "uncovered")
+
+        self._add_server(self.prefix + "ABCD" + '1', site1)
+        self._add_server(self.prefix + "ABCD" + '2', site1)
+        self._add_server(self.prefix + "BCDE" + '1', site2)
+        self._add_server(self.prefix + "BCDE" + '2', site2)
+        self._add_server(self.prefix + "BCDE" + '3', site2)
+
+        self._add_site_link(self.prefix + "link",
+                            [site1, site2, uncovered_dn])
+        self.samdb.transaction_commit()
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name1)
+        to_cover.sort()
+
+        self.assertEqual([], to_cover)
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name2)
+        to_cover.sort()
+
+        self.assertEqual([uncovered], to_cover)
+
+    def test_two_site_links_same_cost(self):
+        self.samdb.transaction_start()
+        site1, name1 = self._add_site(self.prefix + "ABCD")
+        site2, name2 = self._add_site(self.prefix + "BCDE")
+
+        uncovered_dn, uncovered = self._add_site(self.prefix + "uncovered")
+
+        self._add_server(self.prefix + "ABCD" + '1', site1)
+        self._add_server(self.prefix + "ABCD" + '2', site1)
+        self._add_server(self.prefix + "BCDE" + '1', site2)
+        self._add_server(self.prefix + "BCDE" + '2', site2)
+        self._add_server(self.prefix + "BCDE" + '3', site2)
+
+        self._add_site_link(self.prefix + "link1",
+                            [site1, uncovered_dn])
+        self._add_site_link(self.prefix + "link2",
+                            [site2, uncovered_dn])
+        self.samdb.transaction_commit()
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name1)
+        to_cover.sort()
+
+        self.assertEqual([uncovered], to_cover)
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name2)
+        to_cover.sort()
+
+        self.assertEqual([uncovered], to_cover)
+
+    def test_two_site_links_different_costs(self):
+        self.samdb.transaction_start()
+        site1, name1 = self._add_site(self.prefix + "ABCD")
+        site2, name2 = self._add_site(self.prefix + "BCDE")
+
+        uncovered_dn, uncovered = self._add_site(self.prefix + "uncovered")
+
+        self._add_server(self.prefix + "ABCD" + '1', site1)
+        self._add_server(self.prefix + "BCDE" + '1', site2)
+        self._add_server(self.prefix + "BCDE" + '2', site2)
+
+        self._add_site_link(self.prefix + "link1",
+                            [site1, uncovered_dn],
+                            cost=50)
+        self._add_site_link(self.prefix + "link2",
+                            [site2, uncovered_dn],
+                            cost=75)
+        self.samdb.transaction_commit()
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name1)
+        to_cover.sort()
+
+        self.assertEqual([uncovered], to_cover)
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name2)
+        to_cover.sort()
+
+        self.assertEqual([], to_cover)
+
+    def test_three_site_links_different_costs(self):
+        self.samdb.transaction_start()
+        site1, name1 = self._add_site(self.prefix + "ABCD")
+        site2, name2 = self._add_site(self.prefix + "BCDE")
+        site3, name3 = self._add_site(self.prefix + "CDEF")
+
+        uncovered_dn, uncovered = self._add_site(self.prefix + "uncovered")
+
+        self._add_server(self.prefix + "ABCD" + '1', site1)
+        self._add_server(self.prefix + "BCDE" + '1', site2)
+        self._add_server(self.prefix + "CDEF" + '1', site3)
+        self._add_server(self.prefix + "CDEF" + '2', site3)
+
+        self._add_site_link(self.prefix + "link1",
+                            [site1, uncovered_dn],
+                            cost=50)
+        self._add_site_link(self.prefix + "link2",
+                            [site2, uncovered_dn],
+                            cost=75)
+        self._add_site_link(self.prefix + "link3",
+                            [site3, uncovered_dn],
+                            cost=60)
+        self.samdb.transaction_commit()
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name1)
+        to_cover.sort()
+
+        self.assertEqual([uncovered], to_cover)
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name2)
+        to_cover.sort()
+
+        self.assertEqual([], to_cover)
+
+        to_cover = uncovered_sites_to_cover(self.samdb, name3)
+        to_cover.sort()
+
+        self.assertEqual([], to_cover)
+
+    def test_three_site_links_different_costs(self):
+        self.samdb.transaction_start()
+        site1, name1 = self._add_site(self.prefix + "ABCD")
+        site2, name2 = self._add_site(self.prefix + "BCDE")
+        site3, name3 = self._add_site(self.prefix + "CDEF")
+
+        uncovered_dn, uncovered = self._add_site(self.prefix + "uncovered")
+
+        self._add_server(self.prefix + "ABCD" + '1', site1)
+        self._add_server(self.prefix + "BCDE" + '1', site2)
+        self._add_server(self.prefix + "CDEF" + '1', site3)
+        self._add_server(self.prefix + "CDEF" + '2', site3)
+
+        self._add_site_link(self.prefix + "link1",
+                            [site1, uncovered_dn],
+                            cost=50)
+        self._add_site_link(self.prefix + "link2",
+                            [site2, uncovered_dn],
+                            cost=75)
+        self._add_site_link(self.prefix + "link3",
+                            [site3, uncovered_dn],
+                            cost=50)
+        self.samdb.transaction_commit()


-- 
Samba Shared Repository



More information about the samba-cvs mailing list