1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

KCC: write dot files in a deterministic, user specified place

We were using randomised tempfile names in /tmp, initially to avoid
overwriting previous runs so as to track progress. Now we hardly ever
care about the old versions, and a user-specified name will be handy
for testing.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Douglas Bagnall 2015-04-30 10:39:54 +12:00 committed by Andrew Bartlett
parent 169fcd7add
commit eba852cc98
4 changed files with 55 additions and 49 deletions

View File

@ -97,10 +97,10 @@ class KCC(object):
:param read_only: Don't write to the database.
:param verify: Check topological invariants for the generated graphs
:param debug: Write verbosely to stderr.
"param dot_files: write Graphviz files in /tmp showing topology
"param dot_file_dir: write diagnostic Graphviz files in this directory
"""
def __init__(self, unix_now, readonly=False,verify=False, debug=False,
dot_files=False):
def __init__(self, unix_now, readonly=False, verify=False, debug=False,
dot_file_dir=None):
"""Initializes the partitions class which can hold
our local DCs partitions or all the partitions in
the forest
@ -140,7 +140,7 @@ class KCC(object):
self.readonly = readonly
self.verify = verify
self.debug = debug
self.dot_files = dot_files
self.dot_file_dir = dot_file_dir
def load_all_transports(self):
"""Loads the inter-site transport objects for Sites
@ -1158,7 +1158,7 @@ class KCC(object):
g = setup_graph(part, self.site_table, self.transport_table,
self.sitelink_table, bridges_required)
if self.verify or self.dot_files:
if self.verify or self.dot_file_dir is not None:
dot_edges = []
for edge in g.edges:
for a, b in itertools.combinations(edge.vertices, 2):
@ -1168,7 +1168,7 @@ class KCC(object):
label=self.my_dsa_dnstr,
properties=verify_properties, debug=DEBUG,
verify=self.verify,
dot_files=self.dot_files)
dot_file_dir=self.dot_file_dir)
return g
@ -2238,7 +2238,7 @@ class KCC(object):
DEBUG('\n'.join(str((x.rep_dsa_guid, x.rep_dsa_dnstr))
for x in r_list))
do_dot_files = self.dot_files and self.debug
do_dot_files = self.dot_file_dir is not None and self.debug
if self.verify or do_dot_files:
dot_edges = []
dot_vertices = set()
@ -2255,7 +2255,8 @@ class KCC(object):
nc_x.nc_dnstr),
properties=verify_properties, debug=DEBUG,
verify=self.verify,
dot_files=do_dot_files, directed=True)
dot_file_dir=self.dot_file_dir,
directed=True)
# For each existing nTDSConnection object implying an edge
# from rj of R to ri such that j != i, an edge from rj to ri
@ -2333,7 +2334,8 @@ class KCC(object):
nc_x.nc_dnstr),
properties=verify_properties, debug=DEBUG,
verify=self.verify,
dot_files=do_dot_files, directed=True)
dot_file_dir=self.dot_file_dir,
directed=True)
def intrasite(self):
"""The head method for generating the intra-site KCC replica
@ -2457,8 +2459,7 @@ class KCC(object):
def plot_all_connections(self, basename, verify_properties=()):
verify = verify_properties and self.verify
plot = self.dot_files
if not (verify or plot):
if not verify and self.dot_file_dir is None:
return
dot_edges = []
@ -2481,7 +2482,7 @@ class KCC(object):
verify_and_dot(basename, dot_edges, vertices=dot_vertices,
label=self.my_dsa_dnstr, properties=verify_properties,
debug=DEBUG, verify=verify, dot_files=plot,
debug=DEBUG, verify=verify, dot_file_dir=self.dot_file_dir,
directed=True, edge_colors=edge_colours,
vertex_colors=vertex_colours)
@ -2516,7 +2517,7 @@ class KCC(object):
self.load_all_transports()
self.load_all_sitelinks()
if self.verify or self.dot_files:
if self.verify or self.dot_file_dir is not None:
guid_to_dnstr = {}
for site in self.site_table.values():
guid_to_dnstr.update((str(dsa.dsa_guid), dnstr)
@ -2534,7 +2535,7 @@ class KCC(object):
verify_and_dot('dsa_repsFrom_initial', dot_edges,
directed=True, label=self.my_dsa_dnstr,
properties=(), debug=DEBUG, verify=self.verify,
dot_files=self.dot_files)
dot_file_dir=self.dot_file_dir)
dot_edges = []
for site in self.site_table.values():
@ -2550,7 +2551,7 @@ class KCC(object):
verify_and_dot('dsa_repsFrom_initial_all', dot_edges,
directed=True, label=self.my_dsa_dnstr,
properties=(), debug=DEBUG, verify=self.verify,
dot_files=self.dot_files)
dot_file_dir=self.dot_file_dir)
dot_edges = []
for link in self.sitelink_table.values():
@ -2561,7 +2562,7 @@ class KCC(object):
directed=False,
label=self.my_dsa_dnstr, properties=properties,
debug=DEBUG, verify=self.verify,
dot_files=self.dot_files)
dot_file_dir=self.dot_file_dir)
if forget_local_links:
for dsa in self.my_site.dsa_table.values():
@ -2615,7 +2616,7 @@ class KCC(object):
# Step 7
self.update_rodc_connection()
if self.verify or self.dot_files:
if self.verify or self.dot_file_dir is not None:
self.plot_all_connections('dsa_final',
('connected', 'forest_of_rings'))
@ -2635,7 +2636,7 @@ class KCC(object):
verify_and_dot('dsa_repsFrom_final', dot_edges, directed=True,
label=self.my_dsa_dnstr,
properties=(), debug=DEBUG, verify=self.verify,
dot_files=self.dot_files,
dot_file_dir=self.dot_file_dir,
edge_colors=edge_colors)
dot_edges = []
@ -2652,7 +2653,7 @@ class KCC(object):
verify_and_dot('dsa_repsFrom_final_all', dot_edges,
directed=True, label=self.my_dsa_dnstr,
properties=(), debug=DEBUG, verify=self.verify,
dot_files=self.dot_files)
dot_file_dir=self.dot_file_dir)
except:
raise

View File

@ -95,7 +95,7 @@ def combine_repl_info(info_a, info_b, info_c):
def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
dot_files=False):
dot_file_dir=None):
# Phase 1: Run Dijkstra's to get a list of internal edges, which are
# just the shortest-paths connecting colored vertices
@ -112,7 +112,7 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
for v in e.vertices:
v.edges.append(e)
if verify or dot_files:
if verify or dot_file_dir is not None:
graph_edges = [(a.site.site_dnstr, b.site.site_dnstr)
for a, b in
itertools.chain(
@ -120,7 +120,7 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
for edge in e_set.edges))]
graph_nodes = [v.site.site_dnstr for v in graph.vertices]
if dot_files:
if dot_file_dir is not None:
write_dot_file('edgeset_%s' % (edgeType,), graph_edges,
vertices=graph_nodes, label=label)
@ -148,15 +148,14 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
setup_vertices(graph)
process_edge_set(graph, None, internal_edges)
if verify or dot_files:
if verify or dot_file_dir is not None:
graph_edges = [(e.v1.site.site_dnstr, e.v2.site.site_dnstr)
for e in internal_edges]
graph_nodes = [v.site.site_dnstr for v in graph.vertices]
verify_properties = ('multi_edge_forest',)
verify_and_dot('prekruskal', graph_edges, graph_nodes, label=label,
properties=verify_properties, debug=DEBUG,
verify=verify,
dot_files=dot_files)
verify=verify, dot_file_dir=dot_file_dir)
# Phase 2: Run Kruskal's on the internal edges
output_edges, components = kruskal(graph, internal_edges)
@ -172,7 +171,7 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
else:
v.dist_to_red = v.repl_info.cost
if verify or dot_files:
if verify or dot_file_dir is not None:
graph_edges = [(e.v1.site.site_dnstr, e.v2.site.site_dnstr)
for e in internal_edges]
graph_nodes = [v.site.site_dnstr for v in graph.vertices]
@ -180,7 +179,7 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
verify_and_dot('postkruskal', graph_edges, graph_nodes,
label=label, properties=verify_properties,
debug=DEBUG, verify=verify,
dot_files=dot_files)
dot_file_dir=dot_file_dir)
# Ensure only one-way connections for partial-replicas,
# and make sure they point the right way.
@ -198,7 +197,7 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
edge.vertices[:] = w, v
edge_list.append(edge)
if verify or dot_files:
if verify or dot_file_dir is not None:
graph_edges = [[x.site.site_dnstr for x in e.vertices]
for e in edge_list]
#add the reverse edge if not directed.
@ -211,7 +210,7 @@ def get_spanning_tree_edges(graph, my_site, label=None, verify=False,
label=label, properties=verify_properties,
debug=DEBUG, verify=verify,
directed=True,
dot_files=dot_files)
dot_file_dir=dot_file_dir)
# count the components
return edge_list, components

View File

@ -18,6 +18,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import itertools
from samba.kcc.debug import null_debug, PURPLE, MAGENTA, DARK_YELLOW, RED
@ -26,14 +27,15 @@ from samba.kcc.debug import DARK_GREEN, C_NORMAL, GREY
def write_dot_file(basename, edge_list, vertices=None, label=None,
destdir=None, reformat_labels=True, directed=False,
dot_file_dir=None, reformat_labels=True, directed=False,
debug=None, edge_colors=None, edge_labels=None,
vertex_colors=None):
from tempfile import NamedTemporaryFile
if label:
basename += '_' + label.translate(None, ', ') # fix DN, guid labels
f = NamedTemporaryFile(suffix='.dot', prefix=basename + '_', delete=False,
dir=destdir)
# sanitise DN and guid labels
basename += '_' + label.translate(None, ', ')
f = open(os.path.join(dot_file_dir, "%s.dot" % basename), 'w')
if debug is not None:
debug(f.name)
graphname = ''.join(x for x in basename if x.isalnum())
@ -341,19 +343,22 @@ def verify_graph(title, edges, vertices=None, directed=False, properties=(),
debug(C_NORMAL)
def verify_and_dot(basename, edges, vertices=None, label=None, destdir=None,
reformat_labels=True, directed=False, properties=(),
fatal=True, debug=None, verify=True, dot_files=False,
edge_colors=None, edge_labels=None, vertex_colors=None):
def verify_and_dot(basename, edges, vertices=None, label=None,
reformat_labels=True, directed=False,
properties=(), fatal=True, debug=None,
verify=True, dot_file_dir=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_files:
if dot_file_dir is not None:
write_dot_file(basename, edges, vertices=vertices, label=label,
destdir=destdir, reformat_labels=reformat_labels,
directed=directed, debug=debug, edge_colors=edge_colors,
dot_file_dir=dot_file_dir,
reformat_labels=reformat_labels, directed=directed,
debug=debug, edge_colors=edge_colors,
edge_labels=edge_labels, vertex_colors=vertex_colors)

View File

@ -55,7 +55,8 @@ from samba.kcc import KCC
def test_all_reps_from(lp, creds, unix_now, rng_seed=None):
# This implies readonly and attempt_live_connections
kcc = KCC(unix_now, readonly=True,
verify=opts.verify, debug=opts.debug, dot_files=opts.dot_files)
verify=opts.verify, debug=opts.debug,
dot_file_dir=opts.dot_file_dir)
kcc.load_samdb(opts.dburl, lp, creds)
dsas = kcc.list_dsas()
needed_parts = {}
@ -76,7 +77,7 @@ def test_all_reps_from(lp, creds, unix_now, rng_seed=None):
random.seed(rng_seed)
kcc = KCC(unix_now, readonly=True,
verify=opts.verify, debug=opts.debug,
dot_files=opts.dot_files)
dot_file_dir=opts.dot_file_dir)
kcc.run(opts.dburl, lp, creds, forced_local_dsa=dsa_dn,
forget_local_links=opts.forget_local_links,
forget_intersite_links=opts.forget_intersite_links,
@ -123,7 +124,8 @@ def test_all_reps_from(lp, creds, unix_now, rng_seed=None):
verify_and_dot('all-dsa-connections', dot_edges, vertices=dot_vertices,
label="all dsa NTDSConnections", properties=(),
debug=DEBUG, verify=opts.verify, dot_files=opts.dot_files,
debug=DEBUG, verify=opts.verify,
dot_file_dir=opts.dot_file_dir,
directed=True, edge_colors=colours,
vertex_colors=vertex_colours)
@ -133,7 +135,7 @@ def test_all_reps_from(lp, creds, unix_now, rng_seed=None):
verify_and_dot('all-repsFrom_%s__%s' % (name, part), edges,
directed=True, label=part,
properties=(), debug=DEBUG, verify=opts.verify,
dot_files=opts.dot_files)
dot_file_dir=opts.dot_file_dir)
##################################################
# samba_kcc entry point
@ -165,9 +167,8 @@ parser.add_option("--list-verify-tests",
"and do nothing else"),
action="store_true")
parser.add_option("--no-dot-files", dest='dot_files',
help="Don't write dot graph files in /tmp",
default=True, action="store_false")
parser.add_option("--dot-file-dir", default=None,
help="Write Graphviz .dot files to this directory")
parser.add_option("--seed",
help="random number seed",
@ -269,7 +270,7 @@ if opts.test_all_reps_from:
# Instantiate Knowledge Consistency Checker and perform run
kcc = KCC(unix_now, readonly=opts.readonly, verify=opts.verify,
debug=opts.debug, dot_files=opts.dot_files)
debug=opts.debug, dot_file_dir=opts.dot_file_dir)
if opts.exportldif: