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.bagn...@catalyst.net.nz> Date: Fri Jun 8 15:36:39 2018 +1200 python/drs_utils: fix repeated typo Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Sun Jun 10 21:41:33 CEST 2018 on sn-devel-144 commit 153252a55e66533d5bdbb419f259c1682801ae53 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Jun 7 20:11:26 2018 +1200 python/join: fix a typo Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 2d8cc50d392c9434993e2084d4390ce7337cb1b8 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 04a773f30fdb7d03c0526ca1f73353ce5f0d29d5 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c3ad137eb6bdbdc99cc2cc615ca3378a19b6cfa9 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d8bbe1da93433cf7440d780c7cb4a627c3cbd635 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 87926094040621e46534a305a8eec9dc75551711 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 02bca5590cf3cb647df8c9b188a0a2e678933d0c Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6813e1b3c28276721ba7ae49a97ccbdb60d583a7 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 4f7638f8aba737240352199cc253dbd286f7907c Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 9353a580f896c74f60f56d0af555c29fdf8df117 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7e001b27411ef04304fca3fd25c549a8725df34a Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3f25e0b2316f41be3695446f3e5ec9d92ac27440 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 50e3bfa4f57e74a1c123b71ab3a79004c83fd01c Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 99aabf436d62eef990990e6edf95b117bebe0228 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 92fff57f0c269ff154adc589f395d8328b210e88 Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f27a700e69974ccc3e1c722050cd8d72d904eeca Author: Douglas Bagnall <douglas.bagn...@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.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit e5c0e6da6593fb77d5a16ece9aa85532d855d2be Author: Gary Lockyer <g...@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 <g...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@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