[spp] [PATCH 09/13] controller: add do_topo to shell.py

ogawa.yasufumi at lab.ntt.co.jp ogawa.yasufumi at lab.ntt.co.jp
Tue Mar 6 11:50:51 CET 2018


From: Yasufumi Ogawa <ogawa.yasufumi at lab.ntt.co.jp>

'topo' is an experimental command for SPP controller to outptu topology
of network configuration. It enables to display a graphical image of
network configuration on terminal, or browser for which websocket
server is running with.

'topo' command supports four types of output. For multiple output
support, it uses graphviz, imagemagick and other external tools.
* terminal (but very few terminals supporting to display images)
* browser (websocket server is required)
* image file (jpg, png, bmp)
* text (dot, json, yaml)

Here is a list of required tools for 'topo'. Notice that SPP controller
and 'topo' command support MacOS on a remote host.
* graphviz
* imagemagick
* libsixel-bin (for Ubuntu) and terminal app supporting img2sixel
* iTerm2 and imgcat (for MacOS)

For terminal, only few terminal applications are supported. You can use
mlterm or xterm for which 'img2sixel' supports on linux
or iTerm on MacOS. If you use iTerm2, you have to get a shell script
'imgcat' from [1] and save it as
'spp/src/controller/3rd_party/imgcat.sh'.

[1] https://iterm2.com/documentation-images.html

For browser support, you are required to install websocket libraries and
use 'spp_ws' tool. 'spp_ws' is not released yet, but soon.

There are some example usecases.

(1) Display on terminal or browser.
spp > topo term
spp > topo http

(2) Output to a file.
spp > topo myconfig.jpg
spp > topo myconfig dot

This update is only for 'shell.py' and requires a module file 'topo.py'
in which methods for 'topo' command are implemented.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi at lab.ntt.co.jp>
---
 src/controller/shell.py | 85 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 84 insertions(+), 1 deletion(-)

diff --git a/src/controller/shell.py b/src/controller/shell.py
index c5ef82d..8a0580a 100644
--- a/src/controller/shell.py
+++ b/src/controller/shell.py
@@ -7,6 +7,7 @@ from shell_lib import common
 import spp_common
 from spp_common import logger
 import subprocess
+import topo
 
 
 class Shell(cmd.Cmd, object):
@@ -481,7 +482,89 @@ class Shell(cmd.Cmd, object):
         from pprint import pprint
         if args == '':
             pprint(vars(self))
-            pprint(self.__class__.__name__)
+
+    def do_topo(self, args):
+        """Output network topology
+
+        Support four types of output.
+        * terminal (but very few terminals supporting to display images)
+        * browser (websocket server is required)
+        * image file (jpg, png, bmp)
+        * text (dot, json, yaml)
+
+        spp > topo term  # terminal
+        spp > topo http  # browser
+        spp > topo network_conf.jpg  # image
+        spp > topo network_conf.dot  # text
+        """
+
+        if len(spp_common.SECONDARY_LIST) == 0:
+            message = "secondary not exist"
+            print(message)
+            self.response(self.CMD_NOTREADY, message)
+        else:
+            tp = topo.Topo(
+                spp_common.SECONDARY_LIST,
+                spp_common.MAIN2SEC,
+                spp_common.SEC2MAIN)
+            args_ary = args.split()
+            if len(args_ary) == 0:
+                print("Usage: topo dst [ftype]")
+                return False
+            elif (args_ary[0] == "term") or (args_ary[0] == "http"):
+                res_ary = tp.show(args_ary[0])
+            elif len(args_ary) == 1:
+                ftype = args_ary[0].split(".")[-1]
+                res_ary = tp.output(args_ary[0], ftype)
+            elif len(args_ary) == 2:
+                res_ary = tp.output(args_ary[0], args_ary[1])
+            else:
+                print("Usage: topo dst [ftype]")
+                return False
+            self.response(self.CMD_OK, json.dumps(res_ary))
+
+    def complete_topo(self, text, line, begidx, endidx):
+        """Complete topo command
+
+        If no token given, return 'term' and 'http'.
+        On the other hand, complete 'term' or 'http' if token starts
+        from it, or complete file name if is one of supported formats.
+        """
+
+        terms = ['term', 'http']
+        # Supported formats
+        img_exts = ['jpg', 'png', 'bmp']
+        txt_exts = ['dot', 'yml', 'js']
+
+        # Number of given tokens is expected as two. First one is
+        # 'topo'. If it is three or more, this methods returns nothing.
+        tokens = re.sub(r"\s+", " ", line).split(' ')
+        if (len(tokens) == 2):
+            if (text == ''):
+                completions = terms
+            else:
+                completions = []
+                # Check if 2nd token is a part of terms.
+                for t in terms:
+                    if t.startswith(tokens[1]):
+                        completions.append(t)
+                # Not a part of terms, so check for completion for
+                # output file name.
+                if len(completions) == 0:
+                    if tokens[1].endswith('.'):
+                        completions = img_exts + txt_exts
+                    elif ('.' in tokens[1]):
+                        fname = tokens[1].split('.')[0]
+                        token = tokens[1].split('.')[-1]
+                        for ext in img_exts:
+                            if ext.startswith(token):
+                                completions.append(fname + '.' + ext)
+                        for ext in txt_exts:
+                            if ext.startswith(token):
+                                completions.append(fname + '.' + ext)
+            return completions
+        else:  # do nothing for three or more tokens
+            pass
 
     def do_load_cmd(self, args):
         """Load command plugin
-- 
2.13.1



More information about the spp mailing list