[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu May 31 02:35:02 UTC 2018


The branch, master has been updated
       via  8426c42 sambatool: heuristics to decided whether colour is wanted
       via  e58719d python/colour: add colourizing and switch functions
       via  81167c0 samba-tool drs: remove 'server' arg from commands without --server
       via  408447c samba-tool drs showrepl: remove unused search
       via  78fbe1f samba-tool: be consistent in accepting -q for --quiet
       via  432719c samba-tool: add -v to drs --verbose
       via  a3cc5ee samba-tool: add -v to domain --verbose
       via  3f67fb5 samba-tool dns cleanup_record: add missing verbose/quiet options
       via  3a3929e python kcc/graph_utils: don't debug in colour
       via  105633d kcc graph verifiers: improve messages
       via  e62cc29 kcc graph verifier: use __doc__ description for error explanation
       via  03bd7c2 kcc graphs: site edges in colour, labeled with DNs
       via  cd23651 ndr_misc: read syntax_id using strict util_str_hex functions
       via  f930864 util_str_hex: use array syntax in guid functions to document usage
       via  2157e8d util/charset/iconv: use read_hex_bytes rather than sscanf
       via  c2cac44 dsdb/util: use parse_guid_string, not sscanf()
       via  e5d092ea kcc.graph_utils: shift debug noise out of verify()
       via  35ab60b samba-tool drs replicate: reformat drs_local_replicate method
       via  23001c2 samba-tool drs replicate: make pseudo-method a real method
       via  7f7e690 samba-tool visualise: --xdot option for instant graphviz visualisation
       via  9f52c19 samba-tool viusalize: mark RODCs in distance matrix
       via  bdc0681 samba-tool visualize ntdsconn: add --importldif option
       via  07302fe samba-tool visualize tests: reduce noise on stdout
       via  e646895 samba-tool visualize: group (and colour) DCs by site
      from  003f24e selftest: Fix resolv_wrapper config variables

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


- Log -----------------------------------------------------------------
commit 8426c428ba2e7cc880392d6cf0e4bae4f603be3f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Apr 19 14:15:25 2018 +1200

    sambatool: heuristics to decided whether colour is wanted
    
    The easy cases are --color=yes and --color=no.
    
    With --color=auto, we use color if it seems we're writing to a TTY.
    
    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): Thu May 31 04:34:52 CEST 2018 on sn-devel-144

commit e58719d13cbaa16c9fa454d5653b4a7dd6915777
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Apr 19 14:12:57 2018 +1200

    python/colour: add colourizing and switch functions
    
    When samba.colour is first imported, the function
    
    colour.c_BLUE("samba")
    
    will give you the string "\033[1;34msamba\033[0m", which will show up
    as blue on an ANSI terminal. If you then go:
    
    colour.switch_colour_off()
    colour.c_BLUE("samba")
    
    the c_BLUE call will return the uncoloured string "samba".
    
    This is so things like samba-tool can do this sort of thing:
    
        if not os.isatty(self.outf):
            switch_colour_off()
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 81167c0198146e333cac96ef863acc80afacfa55
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Mon Mar 12 12:45:25 2018 +1300

    samba-tool drs: remove 'server' arg from commands without --server
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 408447cc67204fcb06252e7711273a4dd65d3e09
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Mon Mar 12 11:50:41 2018 +1300

    samba-tool drs showrepl: remove unused search
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 78fbe1ff3206261063e64fed524fd4cef8b52b90
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Apr 19 17:17:28 2018 +1200

    samba-tool: be consistent in accepting -q for --quiet
    
    Not all commands accept --quiet, and not all of those that do use it.
    Some already accept -q, and it is not used anywhere for anything else.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 432719c6e5bc75557b305d481bb784e792dc807f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu May 24 17:03:22 2018 +1200

    samba-tool: add -v to drs --verbose
    
    Sometimes we accept -v for --verbose, sometimes we don't. Let's be a
    bit more consistent.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a3cc5ee85dd213b8a610eaaf2f6bc25316c7cbfa
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Apr 19 16:56:28 2018 +1200

    samba-tool: add -v to domain --verbose
    
    Sometimes we accept -v for --verbose, sometimes we don't. Let's be a
    bit more consistent.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3f67fb5e7e886fd62995b28d9566a59739c80da9
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Apr 19 16:43:50 2018 +1200

    samba-tool dns cleanup_record: add missing verbose/quiet options
    
    The code for using them is already there
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3a3929eee6de3c71647abc581d93e8722bbbbe7c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Apr 19 16:39:06 2018 +1200

    python kcc/graph_utils: don't debug in colour
    
    this was somewhat useful during the initial development, but is wrong for a library
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 105633d4e763d4574dca06cb8fc9cbdc7ede6e74
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed May 16 15:53:35 2018 +1200

    kcc graph verifiers: improve messages
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e62cc29b472e7b33d88ece1797eb142e995cfa5b
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Tue May 15 14:40:36 2018 +1200

    kcc graph verifier: use __doc__ description for error explanation
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 03bd7c20f0846d6b231573b310190d3e0a747f00
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Sun Jan 7 22:17:43 2018 +1300

    kcc graphs: site edges in colour, labeled with DNs
    
    This makes it easy to see where the site edges objects are, and
    what sites they refer too.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cd2365175f5e9d5b5e2725fecf07b3862d3923df
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 22 17:12:49 2018 +1300

    ndr_misc: read syntax_id using strict util_str_hex functions
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f9308648e9a675205ac57302aa6393a37723cddf
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 22 17:57:05 2018 +1300

    util_str_hex: use array syntax in guid functions to document usage
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2157e8d83e7d32e646e7054d969d6be59053378b
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 22 17:54:55 2018 +1300

    util/charset/iconv: use read_hex_bytes rather than sscanf
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c2cac449c89d34f50da98c6eb59442bf63b67477
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 22 16:49:29 2018 +1300

    dsdb/util: use parse_guid_string, not sscanf()
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e5d092ea54c0d1c45ba970ad6db96a89b0ade8ce
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 15 12:01:10 2018 +1300

    kcc.graph_utils: shift debug noise out of verify()
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 35ab60b82a32f9be18fa49f17a47781989f7cd66
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Mon Mar 12 12:33:01 2018 +1300

    samba-tool drs replicate: reformat drs_local_replicate method
    
    line length.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 23001c2835a3d7e127ce54ffe7a9ef69bcadbf91
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Mon Mar 12 12:29:28 2018 +1300

    samba-tool drs replicate: make pseudo-method a real method
    
    This function can't function without a cmd_drs_replicate class, so it might as well be inside
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7f7e6902313f1422102a4c68803369af013ff038
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 8 17:42:18 2018 +1300

    samba-tool visualise: --xdot option for instant graphviz visualisation
    
    This is a convenience for people who have xdot (and X11).
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 9f52c19b807e4961a76fa652aa5b7f660625e65e
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Thu Mar 8 14:29:40 2018 +1300

    samba-tool viusalize: mark RODCs in distance matrix
    
    RODCs should not be replicating out, which means they look alarming
    when they are working properly. We label them as RODCs to reminds users
    that no outbound replication is expected.
    
    This results in slightly rejigged output formatting.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit bdc0681eaebab7bc930206c2d2db68d7ca132ad3
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Wed Mar 7 13:55:08 2018 +1300

    samba-tool visualize ntdsconn: add --importldif option
    
    This visualizes the NTDSConnections in an LDIF file exported via
    `samba_kcc --exportldif`. This functionality is already available in a
    roundabout way -- you can use `samba_kcc --import_ldif`, and use the
    DB that generates. This just shortens the process.
    
    The ldif import/export feature is useful for analysing AD networks
    offsite without exposing too much sensitive data.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 07302fe03724b98e39f0beca5710b534bcb1582c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 23 11:12:53 2018 +1300

    samba-tool visualize tests: reduce noise on stdout
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e646895d2d9097644cc005de1af6e10e2772ebd0
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri Feb 23 11:11:27 2018 +1300

    samba-tool visualize: group (and colour) DCs by site
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 lib/util/charset/iconv.c                   |   9 +-
 lib/util/util_str_hex.c                    |   4 +-
 lib/util/util_str_hex.h                    |   4 +-
 librpc/ndr/ndr_misc.c                      |  33 +++++--
 python/samba/colour.py                     |  56 +++++++++--
 python/samba/graph.py                      |  35 +++++--
 python/samba/kcc/__init__.py               |   9 +-
 python/samba/kcc/graph.py                  |  13 ++-
 python/samba/kcc/graph_utils.py            |  74 +++++++--------
 python/samba/kcc/kcc_utils.py              |   9 +-
 python/samba/netcmd/__init__.py            |  24 +++++
 python/samba/netcmd/dbcheck.py             |   2 +-
 python/samba/netcmd/dns.py                 |   5 +
 python/samba/netcmd/domain.py              |  24 ++---
 python/samba/netcmd/drs.py                 | 145 +++++++++++++++--------------
 python/samba/netcmd/ntacl.py               |   2 +-
 python/samba/netcmd/visualize.py           | 112 +++++++++++++++++++---
 python/samba/tests/samba_tool/visualize.py |  73 +++++++++++++--
 source4/dsdb/common/util.c                 |  14 +--
 19 files changed, 455 insertions(+), 192 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/util/charset/iconv.c b/lib/util/charset/iconv.c
index 02c061c..a03ff20 100644
--- a/lib/util/charset/iconv.c
+++ b/lib/util/charset/iconv.c
@@ -25,6 +25,8 @@
 #include "lib/util/dlinklist.h"
 #include "lib/util/charset/charset.h"
 #include "lib/util/charset/charset_proto.h"
+#include "libcli/util/ntstatus.h"
+#include "lib/util/util_str_hex.h"
 
 #ifdef strcasecmp
 #undef strcasecmp
@@ -454,8 +456,8 @@ static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft,
 			 char **outbuf, size_t *outbytesleft)
 {
 	while (*inbytesleft >= 1 && *outbytesleft >= 2) {
-		unsigned int v;
-
+		uint64_t v;
+		NTSTATUS status;
 		if ((*inbuf)[0] != '@') {
 			/* seven bit ascii case */
 			(*outbuf)[0] = (*inbuf)[0];
@@ -471,8 +473,9 @@ static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft,
 			errno = EINVAL;
 			return -1;
 		}
+		status = read_hex_bytes(&(*inbuf)[1], 4, &v);
 
-		if (sscanf(&(*inbuf)[1], "%04x", &v) != 1) {
+		if (!NT_STATUS_IS_OK(status)) {
 			errno = EILSEQ;
 			return -1;
 		}
diff --git a/lib/util/util_str_hex.c b/lib/util/util_str_hex.c
index 148735b..792b4e8 100644
--- a/lib/util/util_str_hex.c
+++ b/lib/util/util_str_hex.c
@@ -38,8 +38,8 @@ NTSTATUS parse_guid_string(const char *s,
 			   uint32_t *time_low,
 			   uint32_t *time_mid,
 			   uint32_t *time_hi_and_version,
-			   uint32_t *clock_seq,
-			   uint32_t *node)
+			   uint32_t clock_seq[2],
+			   uint32_t node[6])
 {
 	uint64_t tmp;
 	NTSTATUS status;
diff --git a/lib/util/util_str_hex.h b/lib/util/util_str_hex.h
index 2d0ba65..d0d53e3 100644
--- a/lib/util/util_str_hex.h
+++ b/lib/util/util_str_hex.h
@@ -6,5 +6,5 @@ NTSTATUS parse_guid_string(const char *s,
 			   uint32_t *time_low,
 			   uint32_t *time_mid,
 			   uint32_t *time_hi_and_version,
-			   uint32_t *clock_seq,
-			   uint32_t *node);
+			   uint32_t clock_seq[2],
+			   uint32_t node[6]);
diff --git a/librpc/ndr/ndr_misc.c b/librpc/ndr/ndr_misc.c
index fa643c8..155ab8f 100644
--- a/librpc/ndr/ndr_misc.c
+++ b/librpc/ndr/ndr_misc.c
@@ -23,6 +23,8 @@
 #include "includes.h"
 #include "system/network.h"
 #include "librpc/ndr/libndr.h"
+#include "libcli/util/ntstatus.h"
+#include "lib/util/util_str_hex.h"
 
 _PUBLIC_ void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid)
 {
@@ -52,21 +54,32 @@ _PUBLIC_ char *ndr_syntax_id_to_string(TALLOC_CTX *mem_ctx, const struct ndr_syn
 
 _PUBLIC_ bool ndr_syntax_id_from_string(const char *s, struct ndr_syntax_id *id)
 {
-	int ret;
 	size_t i;
 	uint32_t time_low;
 	uint32_t time_mid, time_hi_and_version;
 	uint32_t clock_seq[2];
 	uint32_t node[6];
-	uint32_t if_version;
+	uint64_t if_version;
+	NTSTATUS status;
 
-	ret = sscanf(s,
-		     "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x/0x%08x",
-		     &time_low, &time_mid, &time_hi_and_version,
-		     &clock_seq[0], &clock_seq[1],
-		     &node[0], &node[1], &node[2], &node[3], &node[4], &node[5],
-		     &if_version);
-	if (ret != 12) {
+	status =  parse_guid_string(s,
+				    &time_low,
+				    &time_mid,
+				    &time_hi_and_version,
+				    clock_seq,
+				    node);
+
+	if (!NT_STATUS_IS_OK(status)) {
+		return false;
+	}
+
+	if (strncmp(s + 36, "/0x", 3) != 0) {
+		return false;
+	}
+
+	status = read_hex_bytes(s + 39, 8, &if_version);
+
+	if (!NT_STATUS_IS_OK(status)) {
 		return false;
 	}
 
@@ -78,7 +91,7 @@ _PUBLIC_ bool ndr_syntax_id_from_string(const char *s, struct ndr_syntax_id *id)
 	for (i=0; i<6; i++) {
 		id->uuid.node[i] = node[i];
 	}
-	id->if_version = if_version;
+	id->if_version = (uint32_t)if_version;
 
 	return true;
 }
diff --git a/python/samba/colour.py b/python/samba/colour.py
index b3d9a71..92af2fd 100644
--- a/python/samba/colour.py
+++ b/python/samba/colour.py
@@ -18,15 +18,13 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 # The 4 bit colours are available as global variables with names like
-# RED, DARK_RED, REV_RED (for red background), and REV_DARK_RED.
+# RED, DARK_RED, REV_RED (for red background), and REV_DARK_RED. If
+# switch_colour_off() is called, these names will all point to the
+# empty string. switch_colour_on() restores the default values.
 #
 # The 256-colour codes are obtained using xterm_256_color(n), where n
 # is the number of the desired colour.
 
-# C_NORMAL resets to normal, whatever that is
-C_NORMAL = "\033[0m"
-
-UNDERLINE = "\033[4m"
 
 def _gen_ansi_colours():
     g = globals()
@@ -37,11 +35,53 @@ def _gen_ansi_colours():
         g['REV_' + name] = "\033[1;4%dm" % i
         g['REV_DARK_' + name] = "\033[4%dm" % i
 
+    # kcc.debug uses these aliases (which make visual sense)
+    g['PURPLE'] = DARK_MAGENTA
+    g['GREY'] = DARK_WHITE
+
+    # C_NORMAL resets to normal, whatever that is
+    g['C_NORMAL'] = "\033[0m"
+
+    # Non-colour ANSI codes.
+    g['UNDERLINE'] = "\033[4m"
+
+
 _gen_ansi_colours()
 
-# kcc.debug uses these aliases (which make visual sense)
-PURPLE = DARK_MAGENTA
-GREY = DARK_WHITE
+# Generate functions that colour a string. The functions look like
+# this:
+#
+#    c_BLUE("hello")  # "\033[1;34mhello\033[0m" -> blue text
+#    c_DARK_RED(3)    # 3 will be stringified and coloured
+#
+# but if colour is switched off, no colour codes are added.
+#
+#    c_BLUE("hello")  # "hello"
+#
+# The definition of the functions looks a little odd, because we want
+# to bake in the name of the colour but not its actual value.
+
+for _k in list(globals().keys()):
+    if _k.isupper():
+        def _f(s, name=_k):
+            return "%s%s%s" % (globals()[name], s, C_NORMAL)
+        globals()['c_%s' % _k] = _f
+
+del _k, _f
+
+
+def switch_colour_off():
+    """Convert all the ANSI colour codes into empty strings."""
+    g = globals()
+    for k, v in list(g.items()):
+        if k.isupper() and isinstance(v, str) and v.startswith('\033'):
+            g[k] = ''
+
+
+def switch_colour_on():
+    """Regenerate all the ANSI colour codes."""
+    _gen_ansi_colours()
+
 
 def xterm_256_colour(n, bg=False, bold=False):
     weight = '01;' if bold else ''
diff --git a/python/samba/graph.py b/python/samba/graph.py
index 7dfc190..a36dc25 100644
--- a/python/samba/graph.py
+++ b/python/samba/graph.py
@@ -22,6 +22,7 @@ from __future__ import print_function
 from __future__ import division
 from samba import colour
 import sys
+from itertools import cycle, groupby
 
 FONT_SIZE = 10
 
@@ -511,7 +512,9 @@ def distance_matrix(vertices, edges,
                     utf8=False,
                     colour=None,
                     shorten_names=False,
-                    generate_key=False):
+                    generate_key=False,
+                    grouping_function=None,
+                    row_comments=None):
     lines = []
     write = lines.append
 
@@ -523,14 +526,29 @@ def distance_matrix(vertices, edges,
         diagonal = '·'
         #missing = '🕱'
         missing = '-'
+        right_arrow = '←'
     else:
         vertical, horizontal, corner, diagonal, missing = '|-,0-'
+        right_arrow = '<-'
 
     colours = COLOUR_SETS[colour]
 
+    colour_cycle = cycle(colours.get('alternate rows', ('',)))
+
     if vertices is None:
         vertices = sorted(set(x[0] for x in edges) | set(x[1] for x in edges))
 
+    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 = sorted(vertices, key=grouping_function)
+        colour_list = []
+        for k, v in groupby(vertices, key=grouping_function):
+            c = next(colour_cycle)
+            colour_list.extend(c for x in v)
+    else:
+        colour_list = [next(colour_cycle) for v in vertices]
+
     if shorten_names:
         edges, vertices, replacements = shorten_vertex_names(edges,
                                                              vertices,
@@ -540,7 +558,6 @@ def distance_matrix(vertices, edges,
     vlen = max(6, max(len(v) for v in vertices))
 
     # first, the key for the columns
-    colour_cycle = colours.get('alternate rows', ('',))
     c_header = colours.get('header', '')
     c_disconn = colours.get('disconnected', '')
     c_conn = colours.get('connected', '')
@@ -556,7 +573,7 @@ def distance_matrix(vertices, edges,
                                        c_reset))
     for i, v in enumerate(vertices):
         j = len(vertices) - i
-        c = colour_cycle[i % len(colour_cycle)]
+        c = colour_list[i]
         if j == 1:
             start = '%s%ssource%s' % (vspace[:-6], c_header, c_reset)
         else:
@@ -575,7 +592,7 @@ def distance_matrix(vertices, edges,
     connections = find_transitive_distance(vertices, edges)
 
     for i, v in enumerate(vertices):
-        c = colour_cycle[i % len(colour_cycle)]
+        c = colour_list[i]
         links = connections[v]
         row = []
         for v2 in vertices:
@@ -593,16 +610,20 @@ def distance_matrix(vertices, edges,
                     link = '+'
                 row.append('%s%s%s' % (ct, link, c_reset))
 
+        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))
 
+    example_c = next(colour_cycle)
     if shorten_names:
         write('')
         for substitute, original in reversed(replacements):
-            write("'%s%s%s' stands for '%s%s%s'" % (colour_cycle[0],
+            write("'%s%s%s' stands for '%s%s%s'" % (example_c,
                                                     substitute,
                                                     c_reset,
-                                                    colour_cycle[0],
+                                                    example_c,
                                                     original,
                                                     c_reset))
     if generate_key:
@@ -611,7 +632,7 @@ def distance_matrix(vertices, edges,
               "indicated number of steps." % (c_header, c_reset,
                                               c_header, c_reset))
         write("%s%s%s means zero steps (it is the same DC)" %
-              (colour_cycle[0], diagonal, c_reset))
+              (example_c, diagonal, c_reset))
         write("%s1%s means a direct link" % (c_conn, c_reset))
         write("%s2%s means a transitive link involving two steps "
               "(i.e. one intermediate DC)" %
diff --git a/python/samba/kcc/__init__.py b/python/samba/kcc/__init__.py
index fae9dbd..1b22bf7 100644
--- a/python/samba/kcc/__init__.py
+++ b/python/samba/kcc/__init__.py
@@ -2583,15 +2583,20 @@ class KCC(object):
                                dot_file_dir=self.dot_file_dir)
 
                 dot_edges = []
+                dot_colours = []
                 for link in self.sitelink_table.values():
+                    from hashlib import md5
+                    colour = '#' + md5(link.dnstr).hexdigest()[:6]
                     for a, b in itertools.combinations(link.site_list, 2):
-                        dot_edges.append((str(a), str(b)))
+                        dot_edges.append((a[1], b[1]))
+                        dot_colours.append(colour)
                 properties = ('connected',)
                 verify_and_dot('dsa_sitelink_initial', dot_edges,
                                directed=False,
                                label=self.my_dsa_dnstr, properties=properties,
                                debug=DEBUG, verify=self.verify,
-                               dot_file_dir=self.dot_file_dir)
+                               dot_file_dir=self.dot_file_dir,
+                               edge_colors=dot_colours)
 
             if forget_local_links:
                 for dsa in self.my_site.dsa_table.values():
diff --git a/python/samba/kcc/graph.py b/python/samba/kcc/graph.py
index fb3ca0c..d87530d 100644
--- a/python/samba/kcc/graph.py
+++ b/python/samba/kcc/graph.py
@@ -184,10 +184,13 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
                                vertices=graph_nodes, label=label)
 
             if verify:
-                verify_graph('spanning tree edge set %s' % edgeType,
-                             graph_edges, vertices=graph_nodes,
-                             properties=('complete', 'connected'),
-                             debug=DEBUG)
+                errors = verify_graph(graph_edges, vertices=graph_nodes,
+                                      properties=('complete', 'connected'))
+                if errors:
+                    DEBUG('spanning tree edge set %s FAILED' % edgeType)
+                    for p, e, doc in errors:
+                        DEBUG("%18s: %s" % (p, e))
+                    raise KCCError("spanning tree failed")
 
         # Run dijkstra's algorithm with just the red vertices as seeds
         # Seed from the full replicas
@@ -290,7 +293,7 @@ def create_edge(con_type, site_link, guid_to_vertex):
     e = MultiEdge()
     e.site_link = site_link
     e.vertices = []
-    for site_guid in site_link.site_list:
+    for site_guid, site_dn in site_link.site_list:
         if str(site_guid) in guid_to_vertex:
             e.vertices.extend(guid_to_vertex.get(str(site_guid)))
     e.repl_info.cost = site_link.cost
diff --git a/python/samba/kcc/graph_utils.py b/python/samba/kcc/graph_utils.py
index 086b651..727b342 100644
--- a/python/samba/kcc/graph_utils.py
+++ b/python/samba/kcc/graph_utils.py
@@ -22,8 +22,6 @@ from __future__ import print_function
 import os
 import itertools
 
-from samba.kcc.debug import null_debug, PURPLE, MAGENTA, DARK_YELLOW, RED
-from samba.kcc.debug import DARK_GREEN, C_NORMAL, GREY
 from samba.graph import dot_graph
 
 
@@ -65,9 +63,8 @@ def verify_graph_connected(edges, vertices, edge_vertices):
     if not edges:
         if len(vertices) <= 1:
             return
-        raise GraphError("disconnected vertices were found:\n"
-                         "vertices: %s\n edges: %s" %
-                         (sorted(vertices), sorted(edges)))
+        raise GraphError("all vertices are disconnected because "
+                         "there are no edges:")
 
     remaining_edges = list(edges)
     reached = set(remaining_edges.pop())
@@ -87,16 +84,23 @@ def verify_graph_connected(edges, vertices, edge_vertices):
             del remaining_edges[i]
 
     if remaining_edges or reached != set(vertices):
-        raise GraphError("graph is not connected:\n vertices: %s\n edges: %s\n"
-                         " reached: %s\n remaining edges: %s" %
-                         (sorted(vertices), sorted(edges),
-                          sorted(reached), sorted(remaining_edges)))
+        s = ("the graph is not connected, "
+             "as the following vertices are unreachable:\n ")
+        s += '\n '.join(v for v in sorted(vertices)
+                        if v not in reached)
+        raise GraphError(s)
 
 
 def verify_graph_connected_under_edge_failures(edges, vertices, edge_vertices):
     """The graph stays connected when any single edge is removed."""
     for subset in itertools.combinations(edges, len(edges) - 1):
-        verify_graph_connected(subset, vertices, edge_vertices)
+        try:
+            verify_graph_connected(subset, vertices, edge_vertices)
+        except GraphError as e:
+            for edge in edges:
+                if edge not in subset:
+                    raise GraphError("The graph will be disconnected when the "
+                                     "connection from %s to %s fails" % edge)
 
 
 def verify_graph_connected_under_vertex_failures(edges, vertices,
@@ -109,8 +113,7 @@ def verify_graph_connected_under_vertex_failures(edges, vertices,
 
 
 def verify_graph_forest(edges, vertices, edge_vertices):
-    """The graph contains no loops. A forest that is also connected is a
-    tree."""
+    """The graph contains no loops."""
     trees = [set(e) for e in edges]
     while True:
         for a, b in itertools.combinations(trees, 2):
@@ -274,12 +277,8 @@ def verify_graph_directed_double_ring_or_small(edges, vertices, edge_vertices):
     return verify_graph_directed_double_ring(edges, vertices, edge_vertices)
 
 
-def verify_graph(title, edges, vertices=None, directed=False, properties=(),
-                 fatal=True, debug=null_debug):
+def verify_graph(edges, vertices=None, directed=False, properties=()):
     errors = []
-    debug("%sStarting verify_graph for %s%s%s" % (PURPLE, MAGENTA, title,
-                                                  C_NORMAL))
-
     properties = [x.replace(' ', '_') for x in properties]
 
     edge_vertices = set()
@@ -291,31 +290,16 @@ def verify_graph(title, edges, vertices=None, directed=False, properties=(),
         vertices = edge_vertices
     else:
         vertices = set(vertices)
-        if vertices != edge_vertices:
-            debug("vertices in edges don't match given vertices:\n %s != %s" %
-                  (sorted(edge_vertices), sorted(vertices)))
 
     for p in properties:
         fn = 'verify_graph_%s' % p
-        try:
-            f = globals()[fn]
-        except KeyError:
-            errors.append((p, "There is no verification check for '%s'" % p))
+        f = globals()[fn]
         try:
             f(edges, vertices, edge_vertices)
-            debug(" %s%18s:%s verified!" % (DARK_GREEN, p, C_NORMAL))
         except GraphError as e:
-            errors.append((p, e))
+            errors.append((p, e, f.__doc__))
 
-    if errors:
-        if fatal:
-            raise GraphError("The '%s' graph lacks the following properties:"
-                             "\n%s" %
-                             (title, '\n'.join('%s: %s' % x for x in errors)))
-        debug(("%s%s%s FAILED:" % (MAGENTA, title, RED)))
-        for p, e in errors:
-            debug(" %18s: %s%s%s" % (p, DARK_YELLOW, e, RED))
-        debug(C_NORMAL)
+    return errors
 
 
 def verify_and_dot(basename, edges, vertices=None, label=None,
@@ -325,10 +309,6 @@ def verify_and_dot(basename, edges, vertices=None, label=None,
                    edge_colors=None, edge_labels=None,
                    vertex_colors=None):
 
-    title = '%s %s' % (basename, label or '')
-    if verify:
-        verify_graph(title, edges, vertices, properties=properties,
-                     fatal=fatal, debug=debug)
     if dot_file_dir is not None:
         write_dot_file(basename, edges, vertices=vertices, label=label,
                        dot_file_dir=dot_file_dir,
@@ -336,12 +316,26 @@ def verify_and_dot(basename, edges, vertices=None, label=None,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list