[SCM] Samba Shared Repository - branch master updated
Karolin Seeger
kseeger at samba.org
Sat Jan 13 21:02:02 UTC 2018
The branch, master has been updated
via 08651a0 samba_kcc: do not commit new nTDSConnection, if we are rodc
via a00312d samba_kcc: simplify NCReplica.set_instantiated_flags()
via 81484f3 samba_kcc: simplify NCReplica constructor
via 315f445 samba_kcc: clarify readonly logging, removing now unused function
via d3f4429 samba_kcc: remove unused functions
via d3c5420 samba_kcc: fix dot_file_dir documentation
via a090d7e samba_kcc: remove an unused function
via c6294c3 samba-tool visualize for understanding AD DC behaviour
via ba2306f samba_kcc: use new graph module for writing dot files
via cebad22 python/graph: module for generating ASCII and graphviz visualisations
via b4a90a6 samba_kcc: respect kcc.read_only flag on RODC
via e579d5b samba_kcc: kcc.debug module defers to samba.colour
via a46c4a3 python: module containing ANSI colour sequences
via f2762d0 python tests: assert string equality, with diff
via 3f2762d samba_kcc: documentation fix
via 6678f33 s4:torture/samba_tool_drs: demote the test dc at the end of test_samba_tool_replicate_local()
from 4b17d36 WHATSNEW: document some more new options
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 08651a08ac10d472a8b170c2f33496192d7faa66
Author: Andrej Gessel <Andrej.Gessel at janztec.com>
Date: Mon Nov 13 11:07:43 2017 +0100
samba_kcc: do not commit new nTDSConnection, if we are rodc
Traceback (most recent call last):
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/sbin/samba_kcc", line 337, in <module>
/usr/local/samba/sbin/samba_kcc: attempt_live_connections=opts.attempt_live_connections)
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/lib/python2.7/site-packages/samba/kcc/__init__.py", line 2644, in run
/usr/local/samba/sbin/samba_kcc: all_connected = self.intersite(ping)
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/lib/python2.7/site-packages/samba/kcc/__init__.py", line 1883, in intersite
/usr/local/samba/sbin/samba_kcc: all_connected = self.create_intersite_connections()
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/lib/python2.7/site-packages/samba/kcc/__init__.py", line 1817, in create_intersite_connections
/usr/local/samba/sbin/samba_kcc: part, True)
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/lib/python2.7/site-packages/samba/kcc/__init__.py", line 1769, in create_connections
/usr/local/samba/sbin/samba_kcc: partial_ok, detect_failed)
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/lib/python2.7/site-packages/samba/kcc/__init__.py", line 1594, in create_connection
/usr/local/samba/sbin/samba_kcc: lbh.commit_connections(self.samdb)
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/lib/python2.7/site-packages/samba/kcc/kcc_utils.py", line 827, in commit_connections
/usr/local/samba/sbin/samba_kcc: connect.commit_added(samdb, ro)
/usr/local/samba/sbin/samba_kcc: File "/usr/local/samba/lib/python2.7/site-packages/samba/kcc/kcc_utils.py", line 1123, in commit_added
/usr/local/samba/sbin/samba_kcc: (self.dnstr, estr))
/usr/local/samba/sbin/samba_kcc: samba.kcc.kcc_utils.KCCError: Could not add nTDSConnection for (CN=862f0429-c72c-4a81-ae9a-96820bb2f96d,CN=NTDS Settings,
CN=BUILDHOST,CN=Servers,CN=Testsite,CN=Sites,CN=Configuration,DC=samdom,DC=com) - (Invalid LDB reply type 1)
../source4/dsdb/kcc/kcc_periodic.c:693: Failed samba_kcc - NT_STATUS_ACCESS_DENIED
Signed-off-by: Andrej Gessel <Andrej.Gessel at janztec.com>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Autobuild-User(master): Karolin Seeger <kseeger at samba.org>
Autobuild-Date(master): Sat Jan 13 22:01:49 CET 2018 on sn-devel-144
commit a00312df7d5a9a2394b41111608c4d988ff4e3f2
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Fri Dec 15 15:58:46 2017 +1300
samba_kcc: simplify NCReplica.set_instantiated_flags()
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 81484f32f4dfe4aeb5624430575fe791a9063246
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Wed Dec 13 17:50:56 2017 +1300
samba_kcc: simplify NCReplica constructor
There is nothing to be gained from setting the dn and guid separately
except subtle bugs.
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 315f445a0256b0b63a344286debb6a27053c4d69
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Wed Dec 13 17:35:29 2017 +1300
samba_kcc: clarify readonly logging, removing now unused function
The unused function was somewhat misnamed.
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit d3f4429cd6e8a58926753651c015e683b92995ae
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Wed Dec 13 16:04:19 2017 +1300
samba_kcc: remove unused functions
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit d3c542051fb19559c5699001da8d9da6c7e66712
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Thu Nov 30 09:24:05 2017 +1300
samba_kcc: fix dot_file_dir documentation
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit a090d7ef52cfd2bbc8bdf7028db0e2237def1f3e
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Thu Nov 16 16:47:32 2017 +1300
samba_kcc: remove an unused function
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit c6294c3c7b6c97f15daad7d463bda267726245c7
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Thu Aug 10 11:57:24 2017 +1200
samba-tool visualize for understanding AD DC behaviour
To work out what is happening in a replication graph, it is sometimes
helpful to use visualisations. We introduce a samba-tool subcommand to
write Graphviz dot output and generate text-based heatmaps of the
distance in hops between DCs.
There are two subcommands, two graphical modes, and (roughly) two modes of
operation with respect to the location of authority.
`samba-tool visualize ntdsconn` looks at NTDS Connections.
`samba-tool visualize reps` looks at repsTo and repsFrom objects.
In '--distance' mode (default), the distances between DCs are shown in
a matrix in the terminal. With '--color=yes', this is depicted as a
heatmap. With '--utf8' it is a lttle prettier.
In '--dot' mode, Graphviz dot output is generated. When viewed using
dot or xdot, this shows the network as a graph with DCs as vertices
and connections edges. Certain types of degenerate edges are shown in
different colours or line-styles.
Normally samba-tool talks to one database; with the '-r' (a.k.a.
'--talk-to-remote') option attempts are made to contact all the DCs
known to the first database. This is necessary to get sensible results
from `samba-tool visualize reps` because the repsFrom/To objects are
not replicated, and it can reveal replication issues in other modes.
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit ba2306f00d32d2fc55685b388e03e28fd7d97fd7
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Thu Aug 10 15:29:43 2017 +1200
samba_kcc: use new graph module for writing dot files
We avoid changing the (annoying) signature of write_dot_file().
Using samba_kcc to write dot files may be deprecated.
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit cebad22ce021ce9051fbe664bc699677796e0fb3
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Wed Jan 10 15:25:22 2018 +1300
python/graph: module for generating ASCII and graphviz visualisations
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit b4a90a650e969cd65b5104d37e9c57275909b336
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Thu Jan 11 21:56:40 2018 +1300
samba_kcc: respect kcc.read_only flag on RODC
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit e579d5bd48dfc7bc93ecc126d42fd4389ded0e28
Author: Douglas Bagnall <douglas at halo.gen.nz>
Date: Wed Jan 3 09:20:09 2018 +1300
samba_kcc: kcc.debug module defers to samba.colour
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit a46c4a39c4d3be88f76c295b0719c025a1c39c3b
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Sun Jan 7 23:17:38 2018 +1300
python: module containing ANSI colour sequences
This is going to be used by `samba-tool visualize` and samba_kcc.
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit f2762d088001408a706e88e0fe6f46181c01fc3f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Fri Jan 5 16:45:37 2018 +1300
python tests: assert string equality, with diff
In the success case this works just like self.assertEqual(),
but when things fail you get a better representation of where it went
wrong (a unified diff).
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 3f2762d0b716e8a440cefeb1867caa303e21af40
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Fri Jan 12 07:32:59 2018 +1300
samba_kcc: documentation fix
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
commit 6678f33274d4f1784635cd11fc63d9d32a9f9b16
Author: Stefan Metzmacher <metze at samba.org>
Date: Fri Jan 12 14:52:45 2018 +0100
s4:torture/samba_tool_drs: demote the test dc at the end of test_samba_tool_replicate_local()
Otherwise this taints other tests which might follow.
Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
-----------------------------------------------------------------------
Summary of changes:
python/samba/colour.py | 50 ++
python/samba/graph.py | 621 +++++++++++++++++++++++++
python/samba/kcc/__init__.py | 21 +-
python/samba/kcc/debug.py | 24 +-
python/samba/kcc/graph_utils.py | 37 +-
python/samba/kcc/kcc_utils.py | 39 +-
python/samba/netcmd/main.py | 1 +
python/samba/netcmd/visualize.py | 574 +++++++++++++++++++++++
python/samba/tests/__init__.py | 23 +
python/samba/tests/graph.py | 152 ++++++
python/samba/tests/samba_tool/visualize.py | 466 +++++++++++++++++++
python/samba/tests/samba_tool/visualize_drs.py | 110 +++++
selftest/tests.py | 1 +
source4/selftest/tests.py | 6 +-
source4/torture/drs/python/samba_tool_drs.py | 3 +
15 files changed, 2037 insertions(+), 91 deletions(-)
create mode 100644 python/samba/colour.py
create mode 100644 python/samba/graph.py
create mode 100644 python/samba/netcmd/visualize.py
create mode 100644 python/samba/tests/graph.py
create mode 100644 python/samba/tests/samba_tool/visualize.py
create mode 100644 python/samba/tests/samba_tool/visualize_drs.py
Changeset truncated at 500 lines:
diff --git a/python/samba/colour.py b/python/samba/colour.py
new file mode 100644
index 0000000..b3d9a71
--- /dev/null
+++ b/python/samba/colour.py
@@ -0,0 +1,50 @@
+# ANSI codes for 4 bit and xterm-256color
+#
+# Copyright (C) Andrew Bartlett 2018
+#
+# Originally written by Douglas Bagnall
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# 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.
+#
+# 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()
+ for i, name in enumerate(('BLACK', 'RED', 'GREEN', 'YELLOW', 'BLUE',
+ 'MAGENTA', 'CYAN', 'WHITE')):
+ g[name] = "\033[1;3%dm" % i
+ g['DARK_' + name] = "\033[3%dm" % i
+ g['REV_' + name] = "\033[1;4%dm" % i
+ g['REV_DARK_' + name] = "\033[4%dm" % i
+
+_gen_ansi_colours()
+
+# kcc.debug uses these aliases (which make visual sense)
+PURPLE = DARK_MAGENTA
+GREY = DARK_WHITE
+
+def xterm_256_colour(n, bg=False, bold=False):
+ weight = '01;' if bold else ''
+ target = '48' if bg else '38'
+
+ return "\033[%s%s;5;%dm" % (weight, target, int(n))
diff --git a/python/samba/graph.py b/python/samba/graph.py
new file mode 100644
index 0000000..f626287
--- /dev/null
+++ b/python/samba/graph.py
@@ -0,0 +1,621 @@
+# -*- coding: utf-8 -*-
+# Graph topology utilities and dot file generation
+#
+# Copyright (C) Andrew Bartlett 2018.
+#
+# Written by Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import print_function
+from samba import colour
+import sys
+
+FONT_SIZE = 10
+
+
+def reformat_graph_label(s):
+ """Break DNs over multiple lines, for better shaped and arguably more
+ readable nodes. We try to split after commas, and if necessary
+ after hyphens or failing that in arbitrary places."""
+ if len(s) < 12:
+ return s
+
+ s = s.replace(',', ',\n')
+ pieces = []
+ for p in s.split('\n'):
+ while len(p) > 20:
+ if '-' in p[2:20]:
+ q, p = p.split('-', 1)
+ else:
+ n = len(p) / 12
+ b = len(p) / n
+ q, p = p[:b], p[b:]
+ pieces.append(q + '-')
+ if p:
+ pieces.append(p)
+
+ return '\\n'.join(pieces)
+
+
+def quote_graph_label(s, reformat=False):
+ """Escape a string as graphvis requires."""
+ # escaping inside quotes is simple in dot, because only " is escaped.
+ # there is no need to count backslashes in sequences like \\\\"
+ s = s.replace('"', '\"')
+ if reformat:
+ s = reformat_graph_label(s)
+ return "%s" % s
+
+
+def shorten_vertex_names(edges, 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 [",..."]
+
+ :return: tuple of (edges, vertices, replacement)
+
+ 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.
+ """
+ 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] != ',':
+ i += 1
+
+ if i >= -len(suffix):
+ # there is nothing to gain here
+ return edges, vertices, None
+
+ edges2 = []
+ vertices2 = []
+
+ for a, b in edges:
+ edges2.append((a[:i] + suffix, b[:i] + suffix))
+ for a in vertices:
+ vertices2.append(a[:i] + suffix)
+
+ replacements = [(suffix, a[i:])]
+
+ if aggressive:
+ # Remove known common annoying strings
+ map = dict((v, v) for v in vertices2)
+ for v in vertices2:
+ if ',CN=Servers,' not in v:
+ break
+ else:
+ map = dict((k, v.replace(',CN=Servers,', ',**,'))
+ for k, v in map.iteritems())
+ replacements.append(('**', 'CN=Servers'))
+
+ for v in vertices2:
+ if not v.startswith('CN=NTDS Settings,'):
+ break
+ else:
+ map = dict((k, v.replace('CN=NTDS Settings,', '*,'))
+ for k, v in map.iteritems())
+ 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 edges2, vertices2, replacements
+
+
+def compile_graph_key(key_items, nodes_above=[], elisions=None,
+ prefix='key_', width=2):
+ """Generate a dot file snippet that acts as a legend for a graph.
+
+ :param key_items: sequence of items (is_vertex, style, label)
+ :param nodes_above: list of vertices (pushes key into right position)
+ :param elision: tuple (short, full) indicating suffix replacement
+ :param prefix: string used to generate key node names ["key_"]
+ :param width: default width of node lines
+
+ Each item in key_items is a tuple of (is_vertex, style, label).
+ is_vertex is a boolean indicating whether the item is a vertex
+ (True) or edge (False). Style is a dot style string for the edge
+ or vertex. label is the text associated with the key item.
+ """
+ edge_lines = []
+ edge_names = []
+ vertex_lines = []
+ vertex_names = []
+ order_lines = []
+ for i, item in enumerate(key_items):
+ is_vertex, style, label = item
+ tag = '%s%d_' % (prefix, i)
+ label = quote_graph_label(label)
+ name = '%s_label' % tag
+
+ if is_vertex:
+ order_lines.append(name)
+ vertex_names.append(name)
+ vertex_lines.append('%s[label="%s"; %s]' %
+ (name, label, style))
+ else:
+ edge_names.append(name)
+ e1 = '%se1' % tag
+ e2 = '%se2' % tag
+ order_lines.append(name)
+ edge_lines.append('subgraph cluster_%s {' % tag)
+ edge_lines.append('%s[label=src; color="#000000"; group="%s_g"]' %
+ (e1, tag))
+ edge_lines.append('%s[label=dest; color="#000000"; group="%s_g"]' %
+ (e2, tag))
+ edge_lines.append('%s -> %s [constraint = false; %s]' % (e1, e2,
+ style))
+ edge_lines.append(('%s[shape=plaintext; style=solid; width=%f; '
+ 'label="%s\\r"]') %
+ (name, width, label))
+ edge_lines.append('}')
+
+ elision_str = ''
+ if elisions:
+ for i, elision in enumerate(reversed(elisions)):
+ order_lines.append('elision%d' % i)
+ short, long = elision
+ if short[0] == ',' and long[0] == ',':
+ short = short[1:]
+ long = long[1:]
+ elision_str += ('\nelision%d[shape=plaintext; style=solid; '
+ 'label="\ā%sā means ā%sā\\r"]\n'
+ % ((i, short, long)))
+
+ above_lines = []
+ if order_lines:
+ for n in nodes_above:
+ above_lines.append('"%s" -> %s [style=invis]' %
+ (n, order_lines[0]))
+
+ s = ('subgraph cluster_key {\n'
+ 'label="Key";\n'
+ 'subgraph cluster_key_nodes {\n'
+ 'label="";\n'
+ 'color = "invis";\n'
+ '%s\n'
+ '}\n'
+ 'subgraph cluster_key_edges {\n'
+ 'label="";\n'
+ 'color = "invis";\n'
+ '%s\n'
+ '{%s}\n'
+ '}\n'
+ '%s\n'
+ '}\n'
+ '%s\n'
+ '%s [style=invis; weight=9]'
+ '\n'
+ % (';\n'.join(vertex_lines),
+ '\n'.join(edge_lines),
+ ' '.join(edge_names),
+ elision_str,
+ ';\n'.join(above_lines),
+ ' -> '.join(order_lines),
+ ))
+
+ return s
+
+
+def dot_graph(vertices, edges,
+ directed=False,
+ title=None,
+ reformat_labels=True,
+ vertex_colors=None,
+ edge_colors=None,
+ edge_labels=None,
+ vertex_styles=None,
+ edge_styles=None,
+ graph_name=None,
+ shorten_names=False,
+ key_items=None,
+ vertex_clusters=None):
+ """Generate a Graphviz representation of a list of vertices and edges.
+
+ :param vertices: list of vertex names (optional).
+ :param edges: list of (vertex, vertex) pairs
+ :param directed: bool: whether the graph is directed
+ :param title: optional title for the graph
+ :param reformat_labels: whether to wrap long vertex labels
+ :param vertex_colors: if not None, a sequence of colours for the vertices
+ :param edge_colors: if not None, colours for the edges
+ :param edge_labels: if not None, labels for the edges
+ :param vertex_styles: if not None, DOT style strings for vertices
+ :param edge_styles: if not None, DOT style strings for edges
+ :param graph_name: if not None, name of graph
+ :param shorten_names: if True, remove common DN suffixes
+ :param key: (is_vertex, style, description) tuples
+ :param vertex_clusters: list of subgraph cluster names
+
+ Colour, style, and label lists must be the same length as the
+ corresponding list of edges or vertices (or None).
+
+ Colours can be HTML RGB strings ("#FF0000") or common names
+ ("red"), or some other formats you don't want to think about.
+
+ If `vertices` is None, only the vertices mentioned in the edges
+ are shown, and their appearance can be modified using the
+ vertex_colors and vertex_styles arguments. Vertices appearing in
+ the edges but not in the `vertices` list will be shown but their
+ styles can not be modified.
+ """
+ out = []
+ write = out.append
+
+ if vertices is None:
+ 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)
+ else:
+ elisions = None
+
+ if graph_name is None:
+ graph_name = 'A_samba_tool_production'
+
+ if directed:
+ graph_type = 'digraph'
+ connector = '->'
+ else:
+ graph_type = 'graph'
+ connector = '--'
+
+ write('/* generated by samba */')
+ write('%s %s {' % (graph_type, graph_name))
+ if title is not None:
+ write('label="%s";' % (title,))
+ write('fontsize=%s;\n' % (FONT_SIZE))
+ write('node[fontname=Helvetica; fontsize=%s];\n' % (FONT_SIZE))
+
+ prev_cluster = None
+ cluster_n = 0
+ quoted_vertices = []
+ for i, v in enumerate(vertices):
+ v = quote_graph_label(v, reformat_labels)
+ quoted_vertices.append(v)
+ attrs = []
+ if vertex_clusters and vertex_clusters[i]:
+ cluster = vertex_clusters[i]
+ if cluster != prev_cluster:
+ if prev_cluster is not None:
+ write("}")
+ prev_cluster = cluster
+ n = quote_graph_label(cluster)
+ if cluster:
+ write('subgraph cluster_%d {' % cluster_n)
+ cluster_n += 1
+ write('style = "rounded,dotted";')
+ write('node [style="filled"; fillcolor=white];')
+ write('label = "%s";' % n)
+
+ if vertex_styles and vertex_styles[i]:
+ attrs.append(vertex_styles[i])
+ if vertex_colors and vertex_colors[i]:
+ attrs.append('color="%s"' % quote_graph_label(vertex_colors[i]))
+ if attrs:
+ write('"%s" [%s];' % (v, ', '.join(attrs)))
+ else:
+ write('"%s";' % (v,))
+
+ if prev_cluster:
+ write("}")
+
+ for i, edge in enumerate(edges):
+ a, b = edge
+ if a is None:
+ a = "Missing source value"
+ if b is None:
+ b = "Missing destination value"
+
+ a = quote_graph_label(a, reformat_labels)
+ b = quote_graph_label(b, reformat_labels)
+
+ attrs = []
+ if edge_labels:
+ label = quote_graph_label(edge_labels[i])
+ attrs.append('label="%s"' % label)
+ if edge_colors:
+ attrs.append('color="%s"' % quote_graph_label(edge_colors[i]))
+ if edge_styles:
+ attrs.append(edge_styles[i]) # no quoting
+ if attrs:
+ write('"%s" %s "%s" [%s];' % (a, connector, b, ', '.join(attrs)))
+ else:
+ write('"%s" %s "%s";' % (a, connector, b))
+
+ if key_items:
+ key = compile_graph_key(key_items, nodes_above=quoted_vertices,
+ elisions=elisions)
+ write(key)
+
+ write('}\n')
+ return '\n'.join(out)
+
+
+COLOUR_SETS = {
+ 'ansi': {
+ 'alternate rows': (colour.DARK_WHITE, colour.BLACK),
+ 'disconnected': colour.RED,
+ 'connected': colour.GREEN,
+ 'transitive': colour.DARK_YELLOW,
+ 'header': colour.UNDERLINE,
+ 'reset': colour.C_NORMAL,
+ },
+ 'ansi-heatmap': {
+ 'alternate rows': (colour.DARK_WHITE, colour.BLACK),
+ 'disconnected': colour.REV_RED,
+ 'connected': colour.REV_GREEN,
+ 'transitive': colour.REV_DARK_YELLOW,
+ 'header': colour.UNDERLINE,
+ 'reset': colour.C_NORMAL,
+ },
+ 'xterm-256color': {
+ 'alternate rows': (colour.xterm_256_colour(39),
+ colour.xterm_256_colour(45)),
+ #'alternate rows': (colour.xterm_256_colour(246),
+ # colour.xterm_256_colour(247)),
+ 'disconnected': colour.xterm_256_colour(124, bg=True),
+ '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(220),
+ colour.xterm_256_colour(214),
+ colour.xterm_256_colour(208),
+ ),
+ 'header': colour.UNDERLINE,
+ 'reset': colour.C_NORMAL,
+ },
+ 'xterm-256color-heatmap': {
+ 'alternate rows': (colour.xterm_256_colour(171),
+ colour.xterm_256_colour(207)),
+ #'alternate rows': (colour.xterm_256_colour(246),
+ # colour.xterm_256_colour(247)),
+ 'disconnected': colour.xterm_256_colour(124, bg=True),
+ '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(220, bg=True),
+ colour.xterm_256_colour(214, bg=True),
+ colour.xterm_256_colour(208, bg=True),
+ ),
+ 'header': colour.UNDERLINE,
+ 'reset': colour.C_NORMAL,
+ },
+ None: {
+ 'alternate rows': ('',),
+ 'disconnected': '',
+ 'connected': '',
+ 'transitive': '',
+ 'header': '',
+ 'reset': '',
+ }
+}
--
Samba Shared Repository
More information about the samba-cvs
mailing list