samba-tool visualise: --xdot option for instant graphviz visualisation
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Thu, 8 Mar 2018 04:42:18 +0000 (17:42 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 30 May 2018 23:57:15 +0000 (01:57 +0200)
This is a convenience for people who have xdot (and X11).

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/netcmd/visualize.py
python/samba/tests/samba_tool/visualize.py

index 2b8c5fc..c9bc824 100644 (file)
@@ -22,6 +22,7 @@ from __future__ import print_function
 import os
 import sys
 from collections import defaultdict
+import subprocess
 
 import tempfile
 import samba
@@ -44,6 +45,8 @@ COMMON_OPTIONS = [
            type=str, metavar="FILE", default=None),
     Option("--dot", help="Graphviz dot output", dest='format',
            const='dot', action='store_const'),
+    Option("--xdot", help="attempt to call Graphviz xdot", dest='format',
+           const='xdot', action='store_const'),
     Option("--distance", help="Distance matrix graph output (default)",
            dest='format', const='distance', action='store_const'),
     Option("--utf8", help="Use utf-8 Unicode characters",
@@ -133,8 +136,21 @@ class GraphCommand(Command):
                 return 'dot'
             else:
                 return 'distance'
+
+        if format == 'xdot':
+            return 'dot'
+
         return format
 
+    def call_xdot(self, s, output):
+        if output is None:
+            fn = self.write(s, TEMP_FILE)
+        else:
+            fn = self.write(s, output)
+        xdot = os.environ.get('SAMBA_TOOL_XDOT_PATH', '/usr/bin/xdot')
+        subprocess.call([xdot, fn])
+        os.remove(fn)
+
     def calc_distance_color_scheme(self, color, color_scheme, output):
         """Heuristics to work out the colour scheme for distance matrices.
         Returning None means no colour, otherwise it sould be a colour
@@ -211,7 +227,7 @@ class cmd_reps(GraphCommand):
             key=True, talk_to_remote=False,
             sambaopts=None, credopts=None, versionopts=None,
             mode='self', partition=None, color=None, color_scheme=None,
-            utf8=None, format=None):
+            utf8=None, format=None, xdot=False):
         # We use the KCC libraries in readonly mode to get the
         # replication graph.
         lp = sambaopts.get_loadparm()
@@ -377,7 +393,10 @@ class cmd_reps(GraphCommand):
                       shorten_names=shorten_names,
                       key_items=key_items)
 
-        self.write(s, output)
+        if format == 'xdot':
+            self.call_xdot(s, output)
+        else:
+            self.write(s, output)
 
 
 class NTDSConn(object):
@@ -416,7 +435,8 @@ class cmd_ntdsconn(GraphCommand):
             key=True, talk_to_remote=False,
             sambaopts=None, credopts=None, versionopts=None,
             color=None, color_scheme=None,
-            utf8=None, format=None, importldif=None):
+            utf8=None, format=None, importldif=None,
+            xdot=False):
 
         lp = sambaopts.get_loadparm()
         if importldif is None:
@@ -630,7 +650,11 @@ class cmd_ntdsconn(GraphCommand):
                       edge_styles=edge_styles,
                       shorten_names=shorten_names,
                       key_items=key_items)
-        self.write(s, output)
+
+        if format == 'xdot':
+            self.call_xdot(s, output)
+        else:
+            self.write(s, output)
 
 
 class cmd_visualize(SuperCommand):
index 43757e7..abb6c49 100644 (file)
@@ -27,6 +27,7 @@ query.
 from __future__ import print_function
 import samba
 import os
+import tempfile
 import re
 from samba.tests.samba_tool.base import SambaToolCmdTest
 from samba.kcc import ldif_import_export
@@ -123,6 +124,50 @@ class SambaToolVisualizeLdif(SambaToolCmdTest):
 
             self.assertStringsEqual(monochrome, uncoloured, strip=True)
 
+    def test_import_ldif_xdot(self):
+        """We can't test actual xdot, but using the environment we can
+        persuade samba-tool that a script we write is xdot and ensure
+        it gets the right text.
+        """
+        result, expected, err = self.runsubcmd("visualize", "ntdsconn",
+                                               '-H', self.dburl,
+                                               '--color=no', '-S',
+                                               '--dot')
+        self.assertCmdSuccess(result, expected, err)
+
+        # not that we're expecting anything here
+        old_xdot_path = os.environ.get('SAMBA_TOOL_XDOT_PATH')
+
+        tmpdir = tempfile.mkdtemp()
+        fake_xdot = os.path.join(tmpdir, 'fake_xdot')
+        content = os.path.join(tmpdir, 'content')
+        f = open(fake_xdot, 'w')
+        print('#!/bin/sh', file=f)
+        print('cp $1 %s' % content, file=f)
+        f.close()
+        os.chmod(fake_xdot, 0o700)
+
+        os.environ['SAMBA_TOOL_XDOT_PATH'] = fake_xdot
+        result, empty, err = self.runsubcmd("visualize", "ntdsconn",
+                                            '--importldif', MULTISITE_LDIF,
+                                            '--color=no', '-S',
+                                            '--xdot')
+
+        f = open(content)
+        xdot = f.read()
+        f.close()
+        os.remove(fake_xdot)
+        os.remove(content)
+        os.rmdir(tmpdir)
+
+        if old_xdot_path is not None:
+            os.environ['SAMBA_TOOL_XDOT_PATH'] = old_xdot_path
+        else:
+            del os.environ['SAMBA_TOOL_XDOT_PATH']
+
+        self.assertCmdSuccess(result, xdot, err)
+        self.assertStringsEqual(expected, xdot, strip=True)
+
     def test_import_ldif(self):
         """Make sure the samba-tool visualize --importldif option gives the
         same output as using the externally generated db from the same