[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Sun Jun 10 19:42:02 UTC 2018


The branch, master has been updated
       via  b9a323a python/drs_utils: fix repeated typo
       via  153252a python/join: fix a typo
       via  2d8cc50 sambatool visualize: add up-to-dateness visualization
       via  04a773f samba-tool visualize ntdsconn: properly sort/group vertices
       via  c3ad137 samba-tool visualize: fix wrong variable name in get_partition()
       via  d8bbe1d python/graph: don't crash colourer on bad link
       via  8792609 python/graph: use '>' for excessive numbers, not '+'
       via  02bca55 python/graph: add full_matrix graph function
       via  6813e1b python/graph: rework shorten_vertex_names to not need edges
       via  4f7638f python/samba/graph: use look up table for ascii-art charsets
       via  9353a58 samba-tool visualize: separate dot options from common options
       via  7e001b2 samba-tool visualise: helper for getting the partition
       via  3f25e0b python/graph: tweak colour schemes for distance charts
       via  50e3bfa samba-tool drs showrepl: add a --verbose flag
       via  99aabf4 samba-tool drs showrepl: generalise the way output mode is chosen
       via  92fff57 samba-tool drs showrepl tests: don't assert existence of DNS partitions
       via  f27a700 python/kcc/graph_utils: short-cut edge failure test without edges
       via  e5c0e6d lib/audit_logging fix flapping test
      from  81f7ecc dsdb: Use ldb_init() to make the ldb_context in dsdb audit tests

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


- Log -----------------------------------------------------------------
commit b9a323a27cff7cca09babdf6dea784e94e25dad7
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Jun 8 15:36:39 2018 +1200

    python/drs_utils: fix repeated typo
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Sun Jun 10 21:41:33 CEST 2018 on sn-devel-144

commit 153252a55e66533d5bdbb419f259c1682801ae53
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Jun 7 20:11:26 2018 +1200

    python/join: fix a typo
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2d8cc50d392c9434993e2084d4390ce7337cb1b8
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Jun 1 17:20:56 2018 +1200

    sambatool visualize: add up-to-dateness visualization
    
    Or more accurately, out-of-dateness visualization, which shows how far
    each DCs is from every other using the difference in the up-to-dateness
    vectors.
    
    An example usage is
    
    samba-tool visualize uptodateness -r -S -H ldap://somewhere \
          -UAdministrator --color=auto --partition=DOMAIN
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 04a773f30fdb7d03c0526ca1f73353ce5f0d29d5
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Jun 1 17:14:32 2018 +1200

    samba-tool visualize ntdsconn: properly sort/group vertices
    
    The vertex is now a tuple, with the RODC state added.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c3ad137eb6bdbdc99cc2cc615ca3378a19b6cfa9
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 7 11:40:00 2018 +1300

    samba-tool visualize: fix wrong variable name in get_partition()
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d8bbe1da93433cf7440d780c7cb4a627c3cbd635
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Jun 1 16:55:37 2018 +1200

    python/graph: don't crash colourer on bad link
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 87926094040621e46534a305a8eec9dc75551711
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Jun 1 16:51:19 2018 +1200

    python/graph: use '>' for excessive numbers, not '+'
    
    '+' already has another meaning in these graphs.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 02bca5590cf3cb647df8c9b188a0a2e678933d0c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Jun 1 16:48:34 2018 +1200

    python/graph: add full_matrix graph function
    
    This makes an ASCII/ANSI art picture like distance_matrix(), but from
    a full matrix, not a list of adjacencies as in the distance_matrix case.
    
    This will be used to visualise up-to-dateness vectors.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6813e1b3c28276721ba7ae49a97ccbdb60d583a7
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Jun 1 16:39:19 2018 +1200

    python/graph: rework shorten_vertex_names to not need edges
    
    This will be necessary for the forthcoming full_matrix function.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 4f7638f8aba737240352199cc253dbd286f7907c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Tue May 15 22:26:43 2018 +1200

    python/samba/graph: use look up table for ascii-art charsets
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9353a580f896c74f60f56d0af555c29fdf8df117
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu May 24 15:22:47 2018 +1200

    samba-tool visualize: separate dot options from common options
    
    because not all sub-commands make dot format
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7e001b27411ef04304fca3fd25c549a8725df34a
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 29 15:52:25 2018 +1300

    samba-tool visualise: helper for getting the partition
    
    Repeated code becomes a function.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3f25e0b2316f41be3695446f3e5ec9d92ac27440
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu May 24 14:42:37 2018 +1200

    python/graph: tweak colour schemes for distance charts
    
    This works a bit better in terminals with white text.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 50e3bfa4f57e74a1c123b71ab3a79004c83fd01c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Jun 7 14:35:38 2018 +1200

    samba-tool drs showrepl: add a --verbose flag
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 99aabf436d62eef990990e6edf95b117bebe0228
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Mar 9 16:16:23 2018 +1300

    samba-tool drs showrepl: generalise the way output mode is chosen
    
    We have a couple more output modes coming along, so it makes senses to
    untangle .run() into a number of independent sub-methods.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 92fff57f0c269ff154adc589f395d8328b210e88
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Sat Jun 9 20:35:30 2018 +1200

    samba-tool drs showrepl tests: don't assert existence of DNS partitions
    
    Because their existence is uncertain immediately after provision,
    when these tests will run under some circumstances.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f27a700e69974ccc3e1c722050cd8d72d904eeca
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Sat Jun 9 20:07:37 2018 +1200

    python/kcc/graph_utils: short-cut edge failure test without edges
    
    Otherwise we get an exception because itertools.combinations is asked
    to find combinations with negative size.
    
    Instead we assert the graph is connected as-is, which in this case is
    the same as asserting there are no vertices.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e5c0e6da6593fb77d5a16ece9aa85532d855d2be
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Sat Jun 9 14:58:51 2018 +0200

    lib/audit_logging fix flapping test
    
    Add an adjustment to the before and after values to cater for the
    occasional differences between the calculated times.
    
    The exact value of the time stamp is not important what is important is
    that is correctly formatted and that the value is reasonable i.e. it's
    close enough to the current time.
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 lib/audit_logging/tests/audit_logging_test.c       |   4 +
 python/samba/drs_utils.py                          |   4 +-
 python/samba/graph.py                              | 333 +++++++++++++----
 python/samba/join.py                               |   2 +-
 python/samba/kcc/graph_utils.py                    |   3 +
 python/samba/netcmd/drs.py                         |  60 +++-
 python/samba/netcmd/visualize.py                   | 185 +++++++++-
 python/samba/tests/samba_tool/visualize_drs.py     | 398 ++++++++++++++++++++-
 .../torture/drs/python/samba_tool_drs_showrepl.py  |   9 +-
 9 files changed, 880 insertions(+), 118 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/audit_logging/tests/audit_logging_test.c b/lib/audit_logging/tests/audit_logging_test.c
index 6be71f3..26875c9 100644
--- a/lib/audit_logging/tests/audit_logging_test.c
+++ b/lib/audit_logging/tests/audit_logging_test.c
@@ -219,6 +219,7 @@ static void test_json_add_timestamp(void **state)
 	time_t before;
 	time_t after;
 	time_t actual;
+	const int adjustment = 1;
 
 
 	object = json_new_object();
@@ -255,7 +256,10 @@ static void test_json_add_timestamp(void **state)
 
 	/*
 	 * The timestamp should be before <= actual <= after
+	 * but we adjust the times to cater for any precision issues.
 	 */
+	before -= adjustment;
+	after += adjustment;
 	assert_true(difftime(actual, before) >= 0);
 	assert_true(difftime(after, actual) >= 0);
 
diff --git a/python/samba/drs_utils.py b/python/samba/drs_utils.py
index 1940d2d..7fab480 100644
--- a/python/samba/drs_utils.py
+++ b/python/samba/drs_utils.py
@@ -65,7 +65,7 @@ def sendDsReplicaSync(drsuapiBind, drsuapi_handle, source_dsa_guid,
     """Send DS replica sync request.
 
     :param drsuapiBind: a drsuapi Bind object
-    :param drsuapi_handle: a drsuapi hanle on the drsuapi connection
+    :param drsuapi_handle: a drsuapi handle on the drsuapi connection
     :param source_dsa_guid: the guid of the source dsa for the replication
     :param naming_context: the DN of the naming context to replicate
     :param req_options: replication options for the DsReplicaSync call
@@ -91,7 +91,7 @@ def sendRemoveDsServer(drsuapiBind, drsuapi_handle, server_dsa_dn, domain):
     """Send RemoveDSServer request.
 
     :param drsuapiBind: a drsuapi Bind object
-    :param drsuapi_handle: a drsuapi hanle on the drsuapi connection
+    :param drsuapi_handle: a drsuapi handle on the drsuapi connection
     :param server_dsa_dn: a DN object of the server's dsa that we want to
         demote
     :param domain: a DN object of the server's domain
diff --git a/python/samba/graph.py b/python/samba/graph.py
index a36dc25..0c389a7 100644
--- a/python/samba/graph.py
+++ b/python/samba/graph.py
@@ -61,91 +61,82 @@ def quote_graph_label(s, reformat=False):
     return "%s" % s
 
 
-def shorten_vertex_names(edges, vertices, suffix=',...', aggressive=False):
+def shorten_vertex_names(vertices, suffix=',...', aggressive=False):
     """Replace the common suffix (in practice, the base DN) of a number of
     vertices with a short string (default ",..."). If this seems
     pointless because the replaced string is very short or the results
     seem strange, the original vertices are retained.
 
-    :param edges: a sequence of vertex pairs to shorten
     :param vertices: a sequence of vertices to shorten
     :param suffix: the replacement string [",..."]
+    :param aggressive: replace certain common non-suffix strings
 
-    :return: tuple of (edges, vertices, replacement)
+    :return: tuple of (rename map, replacements)
 
-    If no change is made, the returned edges and vertices will be the
-    original lists  and replacement will be None.
-
-    If a change is made, replacement will be a tuple (new, original)
-    indicating the new suffix that replaces the old.
+    The rename map is a dictionary mapping the old vertex names to
+    their shortened versions. If no changes are made, replacements
+    will be empty.
     """
-    vlist = list(set(x[0] for x in edges) |
-                 set(x[1] for x in edges) |
-                 set(vertices))
-
-    if len(vlist) < 2:
-        return edges, vertices, None
-
-    # walk backwards along all the strings until we meet a character
-    # that is not shared by all.
-    i = -1
-    try:
-        while True:
-            c = set(x[i] for x in vlist)
-            if len(c) > 1:
-                break
-            i -= 1
-    except IndexError:
-        # We have indexed beyond the start of a string, which should
-        # only happen if one node is a strict suffix of all others.
-        return edges, vertices, None
-
-    # add one to get to the last unanimous character.
-    i += 1
-
-    # now, we actually really want to split on a comma. So we walk
-    # back to a comma.
-    x = vlist[0]
-    while i < len(x) and x[i] != ',':
+    vmap = dict((v, v) for v in vertices)
+    replacements = []
+
+    if len(vmap) > 1:
+        # walk backwards along all the strings until we meet a character
+        # that is not shared by all.
+        i = -1
+        vlist = vmap.values()
+        try:
+            while True:
+                c = set(x[i] for x in vlist)
+                if len(c) > 1 or c == {'*'}:
+                    break
+                i -= 1
+        except IndexError:
+            # We have indexed beyond the start of a string, which should
+            # only happen if one node is a strict suffix of all others.
+            return vmap, replacements
+
+        # add one to get to the last unanimous character.
         i += 1
 
-    if i >= -len(suffix):
-        # there is nothing to gain here
-        return edges, vertices, None
+        # now, we actually really want to split on a comma. So we walk
+        # back to a comma.
+        x = vlist[0]
+        while i < len(x) and x[i] != ',':
+            i += 1
 
-    edges2 = []
-    vertices2 = []
+        if i >= -len(suffix):
+            # there is nothing to gain here
+            return vmap, replacements
 
-    for a, b in edges:
-        edges2.append((a[:i] + suffix, b[:i] + suffix))
-    for a in vertices:
-        vertices2.append(a[:i] + suffix)
+        replacements.append((suffix, x[i:]))
 
-    replacements = [(suffix, a[i:])]
+        for k, v in vmap.items():
+            vmap[k] = v[:i] + suffix
 
     if aggressive:
         # Remove known common annoying strings
-        map = dict((v, v) for v in vertices2)
-        for v in vertices2:
+        for v in vmap.values():
             if ',CN=Servers,' not in v:
                 break
         else:
-            map = dict((k, v.replace(',CN=Servers,', ',**,'))
-                       for k, v in map.items())
+            vmap = dict((k, v.replace(',CN=Servers,', ',**,', 1))
+                       for k, v in vmap.items())
             replacements.append(('**', 'CN=Servers'))
 
-        for v in vertices2:
+        for v in vmap.values():
             if not v.startswith('CN=NTDS Settings,'):
                 break
         else:
-            map = dict((k, v.replace('CN=NTDS Settings,', '*,'))
-                       for k, v in map.items())
+            vmap = dict((k, v.replace('CN=NTDS Settings,', '*,', 1))
+                       for k, v in vmap.items())
             replacements.append(('*', 'CN=NTDS Settings'))
 
-        edges2 = [(map.get(a, a), map.get(b, b)) for a, b in edges2]
-        vertices2 = [map.get(a, a) for a in vertices2]
+    return vmap, replacements
+
+
+
 
-    return edges2, vertices2, replacements
 
 
 def compile_graph_key(key_items, nodes_above=[], elisions=None,
@@ -292,7 +283,13 @@ def dot_graph(vertices, edges,
         vertices = set(x[0] for x in edges) | set(x[1] for x in edges)
 
     if shorten_names:
-        edges, vertices, elisions = shorten_vertex_names(edges, vertices)
+        vlist = list(set(x[0] for x in edges) |
+                     set(x[1] for x in edges) |
+                     set(vertices))
+        vmap, elisions = shorten_vertex_names(vlist)
+        vertices = [vmap[x] for x in vertices]
+        edges = [(vmap[a], vmap[b]) for a, b in edges]
+
     else:
         elisions = None
 
@@ -404,7 +401,7 @@ COLOUR_SETS = {
         'connected': colour.xterm_256_colour(112),
         'transitive': colour.xterm_256_colour(214),
         'transitive scale': (colour.xterm_256_colour(190),
-                             colour.xterm_256_colour(226),
+                             colour.xterm_256_colour(184),
                              colour.xterm_256_colour(220),
                              colour.xterm_256_colour(214),
                              colour.xterm_256_colour(208),
@@ -421,7 +418,7 @@ COLOUR_SETS = {
         'connected': colour.xterm_256_colour(112, bg=True),
         'transitive': colour.xterm_256_colour(214, bg=True),
         'transitive scale': (colour.xterm_256_colour(190, bg=True),
-                             colour.xterm_256_colour(226, bg=True),
+                             colour.xterm_256_colour(184, bg=True),
                              colour.xterm_256_colour(220, bg=True),
                              colour.xterm_256_colour(214, bg=True),
                              colour.xterm_256_colour(208, bg=True),
@@ -439,6 +436,27 @@ COLOUR_SETS = {
     }
 }
 
+CHARSETS = {
+    'utf8': {
+        'vertical': '│',
+        'horizontal': '─',
+        'corner': '╭',
+        #'diagonal': '╲',
+        'diagonal': '·',
+        #'missing': '🕱',
+        'missing': '-',
+        'right_arrow': '←',
+    },
+    'ascii': {
+        'vertical': '|',
+        'horizontal': '-',
+        'corner': ',',
+        'diagonal': '0',
+        'missing': '-',
+        'right_arrow': '<-',
+    }
+}
+
 
 def find_transitive_distance(vertices, edges):
     all_vertices = (set(vertices) |
@@ -499,6 +517,8 @@ def get_transitive_colourer(colours, n_vertices):
         n = 1 + int(n_vertices ** 0.5)
 
         def f(link):
+            if not isinstance(link, int):
+                return ''
             return scale[min(link * m // n, m - 1)]
 
     else:
@@ -518,18 +538,13 @@ def distance_matrix(vertices, edges,
     lines = []
     write = lines.append
 
-    if utf8:
-        vertical = '│'
-        horizontal = '─'
-        corner = '╭'
-        #diagonal = '╲'
-        diagonal = '·'
-        #missing = '🕱'
-        missing = '-'
-        right_arrow = '←'
-    else:
-        vertical, horizontal, corner, diagonal, missing = '|-,0-'
-        right_arrow = '<-'
+    charset = CHARSETS['utf8' if utf8 else 'ascii']
+    vertical = charset['vertical']
+    horizontal = charset['horizontal']
+    corner = charset['corner']
+    diagonal = charset['diagonal']
+    missing = charset['missing']
+    right_arrow = charset['right_arrow']
 
     colours = COLOUR_SETS[colour]
 
@@ -550,10 +565,14 @@ def distance_matrix(vertices, edges,
         colour_list = [next(colour_cycle) for v in vertices]
 
     if shorten_names:
-        edges, vertices, replacements = shorten_vertex_names(edges,
-                                                             vertices,
-                                                             '+',
-                                                             aggressive=True)
+        vlist = list(set(x[0] for x in edges) |
+                     set(x[1] for x in edges) |
+                     set(vertices))
+        vmap, replacements = shorten_vertex_names(vlist, '+',
+                                                  aggressive=True)
+        vertices = [vmap[x] for x in vertices]
+        edges = [(vmap[a], vmap[b]) for a, b in edges]
+
 
     vlen = max(6, max(len(v) for v in vertices))
 
@@ -607,7 +626,7 @@ def distance_matrix(vertices, edges,
             else:
                 ct = colour_transitive(link)
                 if link > 9:
-                    link = '+'
+                    link = '>'
                 row.append('%s%s%s' % (ct, link, c_reset))
 
         if row_comments is not None and row_comments[i]:
@@ -641,3 +660,165 @@ def distance_matrix(vertices, edges,
               (c_disconn, missing, c_reset))
 
     return '\n'.join(lines)
+
+
+def pad_char(char, digits, padding=' '):
+    if digits == 1:
+        padding = ''
+    return ' ' * (digits - 1) + char + padding
+
+
+def transpose_dict_matrix(m):
+    m2 = {}
+    for k1, row in m.items():
+        for k2, dist in row.items():
+            m2.setdefault(k2, {})[k1] = dist
+    return m2
+
+def full_matrix(rows,
+                utf8=False,
+                colour=None,
+                shorten_names=False,
+                generate_key=False,
+                grouping_function=None,
+                row_comments=None,
+                colour_scale=None,
+                digits=1,
+                ylabel='source',
+                xlabel='destination',
+                transpose=True):
+    lines = []
+    write = lines.append
+
+    if transpose:
+        rows = transpose_dict_matrix(rows)
+
+    use_padding = digits > 1
+
+    charset = CHARSETS['utf8' if utf8 else 'ascii']
+    vertical = pad_char(charset['vertical'], digits)
+    horizontal = charset['horizontal'] * (digits + use_padding)
+    corner = pad_char(charset['corner'], digits,
+                      charset['horizontal'])
+    diagonal = pad_char(charset['diagonal'], digits)
+    missing = pad_char(charset['missing'], digits)
+    toobig = pad_char('>', digits)
+    right_arrow = charset['right_arrow']
+    empty = pad_char(' ', digits)
+
+    colours = COLOUR_SETS[colour]
+
+    colour_cycle = cycle(colours.get('alternate rows', ('',)))
+    vertices = list(rows.keys())
+    if grouping_function is not None:
+        # we sort and colour according to the grouping function
+        # which can be used to e.g. alternate colours by site.
+        vertices.sort(key=grouping_function)
+        colour_list = []
+        for k, v in groupby(vertices, key=grouping_function):
+            c = colour_cycle.next()
+            colour_list.extend(c for x in v)
+    else:
+        colour_list = [colour_cycle.next() for v in vertices]
+
+    if shorten_names:
+        vmap, replacements = shorten_vertex_names(vertices, '+',
+                                                  aggressive=True)
+        rows2 = {}
+        for vert, r in rows.items():
+            rows2[vmap[vert]] = dict((vmap[k], v) for k, v in r.items())
+
+        rows = rows2
+        vertices = list(rows.keys())
+
+    vlen = max(6, len(xlabel), max(len(v) for v in vertices))
+
+    # first, the key for the columns
+    c_header = colours.get('header', '')
+    c_disconn = colours.get('disconnected', '')
+    c_conn = colours.get('connected', '')
+    c_reset = colours.get('reset', '')
+
+    if colour_scale is None:
+        colour_scale = len(rows)
+    colour_transitive = get_transitive_colourer(colours, colour_scale)
+
+    vspace = ' ' * vlen
+    verticals = ''
+    write("%s %s %s%s%s" % (vspace,
+                            empty * (len(rows) + 1),
+                            c_header,
+                            xlabel,
+                            c_reset))
+    for i, v in enumerate(vertices):
+        j = len(rows) - i
+        c = colour_list[i]
+        if j == 1:
+            start = '%s%s%s%s' % (vspace[:-len(ylabel)],
+                                  c_header,
+                                  ylabel,
+                                  c_reset)
+        else:
+            start = vspace
+        write('%s %s%s%s%s%s %s%s' % (start,
+                                      verticals,
+                                      c_reset,
+                                      c,
+                                      corner,
+                                      horizontal * j,
+                                      v,
+                                      c_reset
+        ))
+        verticals += '%s%s' % (c, vertical)
+
+    end_cell = '%s%s' % (' ' * use_padding, c_reset)
+    overflow = False
+    for i, v in enumerate(vertices):
+        links = rows[v]
+        c = colour_list[i]
+        row = []
+        for v2 in vertices:
+            if v2 not in links:
+                row.append('%s%s%s' % (c_disconn, missing, c_reset))
+            elif v == v2:
+                row.append('%s%s%s%s' % (c_reset, c, diagonal, c_reset))
+            else:
+                link = links[v2]
+                if link >= 10 ** digits:
+                    ct = colour_transitive(link)
+                    row.append('%s%s%s' % (ct, toobig, c_reset))
+                    overflow = True
+                    continue
+                if link == 0:
+                    ct = c_conn
+                else:
+                    ct = colour_transitive(link)
+                row.append('%s%*s%s' % (ct, digits, link, end_cell))
+
+        if row_comments is not None and row_comments[i]:
+            row.append('%s %s %s' % (c_reset, right_arrow, row_comments[i]))
+
+        write('%s%*s%s %s%s' % (c, vlen, v, c_reset,
+                                ''.join(row), c_reset))
+
+    if overflow or shorten_names:
+        write('')
+
+    if overflow:
+            write("'%s%s%s' means greater than %d " %
+                  (colour_transitive(10 ** digits),
+                   toobig,
+                   c_reset,
+                   10 ** digits - 1))
+
+    if shorten_names:
+        example_c = colour_cycle.next()
+        for substitute, original in reversed(replacements):
+            write("'%s%s%s' stands for '%s%s%s'" % (example_c,
+                                                    substitute,
+                                                    c_reset,
+                                                    example_c,
+                                                    original,
+                                                    c_reset))
+
+    return '\n'.join(lines)
diff --git a/python/samba/join.py b/python/samba/join.py
index dc6d234..30ecce7 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -239,7 +239,7 @@ class dc_join(object):
                    == res[0]["objectSID"][0]:
                     raise DCJoinException("Not removing account %s which "
                                        "looks like a Samba DC account "
-                                       "maching the password we already have.  "
+                                       "matching the password we already have.  "
                                        "To override, remove secrets.ldb and secrets.tdb"
                                     % ctx.samname)
 
diff --git a/python/samba/kcc/graph_utils.py b/python/samba/kcc/graph_utils.py
index 727b342..65f5ee6 100644
--- a/python/samba/kcc/graph_utils.py
+++ b/python/samba/kcc/graph_utils.py
@@ -93,6 +93,9 @@ def verify_graph_connected(edges, vertices, edge_vertices):
 
 def verify_graph_connected_under_edge_failures(edges, vertices, edge_vertices):
     """The graph stays connected when any single edge is removed."""
+    if len(edges) == 0:


-- 
Samba Shared Repository



More information about the samba-cvs mailing list