Soft Patch Panel
 help / color / mirror / Atom feed
* [spp] [PATCH 1/5] Add SO_REUSEADDR option
@ 2017-07-18 18:57 ogawa.yasufumi
  2017-07-18 18:57 ` [spp] [PATCH 2/5] Remove unwanted spaces from the sec command ogawa.yasufumi
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: ogawa.yasufumi @ 2017-07-18 18:57 UTC (permalink / raw)
  To: spp; +Cc: ferruh.yigit, sy.jong.choi, Yasufumi Ogawa

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

spp.py cannot be launched if it is terminated for unexpected error
and try to restart because of 'port is already used'.
This patch is for avoiding the situation by releasing port
immediately when spp.py is treminated.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 src/spp.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/spp.py b/src/spp.py
index b937b5a..01aed23 100755
--- a/src/spp.py
+++ b/src/spp.py
@@ -394,6 +394,7 @@ def main(argv):
 
     #Creating primary socket object
     primary_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    primary_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
     #Binding primary socket to a address. bind() takes tuple of host and port.
     primary_sock.bind((host, primary_port))
@@ -408,6 +409,7 @@ def main(argv):
 
     #Creating secondary socket object
     secondary_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    secondary_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
     #Binding secondary socket to a address. bind() takes tuple of host and port.
     secondary_sock.bind((host, secondary_port))
-- 
2.13.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [spp] [PATCH 2/5] Remove unwanted spaces from the sec command
  2017-07-18 18:57 [spp] [PATCH 1/5] Add SO_REUSEADDR option ogawa.yasufumi
@ 2017-07-18 18:57 ` ogawa.yasufumi
  2017-07-18 18:57 ` [spp] [PATCH 3/5] Add management port ogawa.yasufumi
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: ogawa.yasufumi @ 2017-07-18 18:57 UTC (permalink / raw)
  To: spp; +Cc: ferruh.yigit, sy.jong.choi, Yasufumi Ogawa

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

spp controller returns invalid command error if "sec n;..." contains
unwanted space chars.
Remove unwanted spaces from the command to avoid error.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 src/spp.py | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/spp.py b/src/spp.py
index 01aed23..c383820 100755
--- a/src/spp.py
+++ b/src/spp.py
@@ -10,6 +10,8 @@ import getopt
 import select
 import socket
 import sys
+import re
+#import pdb; pdb.set_trace()
 
 class GrowingList(list):
     """GrowingList"""
@@ -309,7 +311,10 @@ class Shell(cmd.Cmd):
     def do_sec(self, arg):
         """Send command to secondary process"""
 
-        cmds = arg.split(';')
+        # remove unwanted space to avoid invalid command error
+        tmparg = re.sub(r'\s+', " ", arg)
+        tmparg = re.sub(r'\s?;\s?', ";", tmparg)
+        cmds = tmparg.split(';')
         if len(cmds) < 2:
             print ("error")
         elif str.isdigit(cmds[0]):
@@ -370,6 +375,7 @@ class Shell(cmd.Cmd):
             self.close()
             return True
 
+
 def main(argv):
     """main"""
 
@@ -381,6 +387,7 @@ def main(argv):
     except getopt.GetoptError:
         print ('spp.py -p <primary__port_number> -s <secondary_port_number>')
         sys.exit(2)
+
     for opt, arg in opts:
         if opt in ("-h", "--help"):
             print ('spp.py -p <primary__port_number> -s <secondary_port_number>')
@@ -429,5 +436,6 @@ def main(argv):
     secondary_sock.shutdown(socket.SHUT_RDWR)
     secondary_sock.close()
 
+
 if __name__ == "__main__":
     main(sys.argv[1:])
-- 
2.13.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [spp] [PATCH 3/5] Add management port
  2017-07-18 18:57 [spp] [PATCH 1/5] Add SO_REUSEADDR option ogawa.yasufumi
  2017-07-18 18:57 ` [spp] [PATCH 2/5] Remove unwanted spaces from the sec command ogawa.yasufumi
@ 2017-07-18 18:57 ` ogawa.yasufumi
  2017-07-18 18:57 ` [spp] [PATCH 4/5] Correct sec command completion ogawa.yasufumi
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: ogawa.yasufumi @ 2017-07-18 18:57 UTC (permalink / raw)
  To: spp; +Cc: ferruh.yigit, sy.jong.choi, Yasufumi Ogawa

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

- Management port is a TCP port for send/recv SPP commands from external
  functions.
- Replace args parser for getopts to argparse to be more understandable
  and easily maintained.
- Add descriptions in exception messages to find which the error is
  occured.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 src/spp.py | 211 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 168 insertions(+), 43 deletions(-)

diff --git a/src/spp.py b/src/spp.py
index c383820..99165ed 100755
--- a/src/spp.py
+++ b/src/spp.py
@@ -2,17 +2,67 @@
 """Soft Patch Panel"""
 
 from __future__ import print_function
-from Queue import Queue
+from Queue import Queue, Empty
 from thread import start_new_thread
 from threading import Thread
 import cmd
-import getopt
+import argparse
 import select
 import socket
 import sys
 import re
 #import pdb; pdb.set_trace()
 
+import SocketServer
+import readline
+import threading
+import json
+
+from logging import getLogger,StreamHandler,Formatter,DEBUG
+logger = getLogger(__name__)
+handler = StreamHandler()
+handler.setLevel(DEBUG)
+formatter = Formatter('%(asctime)s - [%(name)s] - [%(levelname)s] - %(message)s')
+handler.setFormatter(formatter)
+logger.setLevel(DEBUG)
+logger.addHandler(handler)
+
+
+CMD_OK = "OK"
+CMD_NG = "NG"
+CMD_NOTREADY = "NOTREADY"
+CMD_ERROR = "ERROR"
+
+RCMD_EXECUTE_QUEUE = Queue()
+RCMD_RESULT_QUEUE = Queue()
+REMOTE_COMMAND = "RCMD"
+
+class CmdRequestHandler(SocketServer.BaseRequestHandler):
+    """Request handler for getting message from remote entities"""
+
+    CMD = None  # contains a instance of Shell class
+
+    def handle(self):
+        self.data = self.request.recv(1024).strip()
+        cur_thread = threading.currentThread()
+        print(cur_thread.getName())
+        print(self.client_address[0])
+        print(self.data)
+        if CmdRequestHandler.CMD is not None:
+            RCMD_EXECUTE_QUEUE.put(REMOTE_COMMAND)
+            CmdRequestHandler.CMD.onecmd(self.data)
+            ret = RCMD_RESULT_QUEUE.get()
+            if (ret is not None):
+                logger.debug("ret:%s" % ret)
+                self.request.send(ret)
+            else:
+                logger.debug("ret is none")
+                self.request.send("")
+        else:
+            logger.debug("CMD is None")
+            self.request.send("")
+
+
 class GrowingList(list):
     """GrowingList"""
 
@@ -21,6 +71,7 @@ class GrowingList(list):
             self.extend([None]*(index + 1 - len(self)))
         list.__setitem__(self, index, value)
 
+# Maximum num of sock queues for secondaries
 MAX_SECONDARY = 16
 
 # init
@@ -55,19 +106,20 @@ def connectionthread(name, client_id, conn, m2s, s2m):
         except KeyError:
             break
         except Exception, excep:
-            print (str(excep))
+            print(excep, ",Error while sending msg in connectionthread()!")
             break
 
         #Receiving from secondary
         try:
             data = conn.recv(1024) # 1024 stands for bytes of data to be received
             if data:
-                s2m.put("recv:" + str(conn.fileno()) + ":" + "{" + data + "}")
+                #s2m.put("recv:" + str(conn.fileno()) + ":" + "{" + data + "}")
+                s2m.put("recv:%s:{%s}" % (str(conn.fileno()), data))
             else:
                 s2m.put("closing:" + str(conn))
                 break
         except Exception, excep:
-            print (str(excep))
+            print(excep, ",Error while receiving msg in connectionthread()!")
             break
 
     SECONDARY_LIST.remove(client_id)
@@ -146,7 +198,7 @@ def acceptthread(sock, main2sec, sec2main):
                               sec2main[client_id], ))
             SECONDARY_COUNT += 1
     except Exception, excep:
-        print (str(excep))
+        print(excep, ", Error in acceptthread()!")
         sock.close()
 
 def command_primary(command):
@@ -154,24 +206,42 @@ def command_primary(command):
 
     if PRIMARY:
         MAIN2PRIMARY.put(command)
-        print (PRIMARY2MAIN.get(True))
+        recv = PRIMARY2MAIN.get(True)
+        print (recv)
+        return CMD_OK, recv
     else:
-        print ("primary not started")
+        recv = "primary not started"
+        print (recv)
+        return CMD_NOTREADY, recv
 
 def command_secondary(sec_id, command):
     """Send command to secondary process with sec_id"""
 
     if sec_id in SECONDARY_LIST:
         MAIN2SEC[sec_id].put(command)
-        print (SEC2MAIN[sec_id].get(True))
+        recv = SEC2MAIN[sec_id].get(True)
+        print (recv)
+        return CMD_OK, recv
     else:
-        print ("secondary id %d not exist" % sec_id)
+        message = "secondary id %d not exist" % sec_id
+        print(message)
+        return CMD_NOTREADY, message
+
+def get_status():
+    secondary = []
+    for i in SECONDARY_LIST:
+        secondary.append("%d" % i)
+    stat = {
+        "primary": "%d" % PRIMARY,
+        "secondary": secondary
+        }
+    return stat
 
 def print_status():
     """Display information about connected clients"""
 
     print ("Soft Patch Panel Status :")
-    print ("primary: %d" % PRIMARY)
+    print ("primary: %d" % PRIMARY)  # "primary: 1" if PRIMA == True
     print ("secondary count: %d" % len(SECONDARY_LIST))
     for i in SECONDARY_LIST:
         print ("Connected secondary id: %d" % i)
@@ -201,7 +271,7 @@ def primarythread(sock, main2primary, primary2main):
             except KeyError:
                 break
             except Exception, excep:
-                print (str(excep))
+                print(excep, ", Error while sending msg in primarythread()!")
                 break
 
             #Receiving from primary
@@ -214,7 +284,7 @@ def primarythread(sock, main2primary, primary2main):
                     conn.close()
                     break
             except Exception, excep:
-                print (str(excep))
+                print(excep, ", Error while receiving msg in primarythread()!")
                 break
 
     print ("primary communication thread end")
@@ -268,6 +338,7 @@ class Shell(cmd.Cmd):
     prompt = 'spp > '
     recorded_file = None
 
+    # TODO define pri_commands and sec_commands if there are difference
     COMMANDS = ['status', 'add', 'patch', 'ring', 'vhost',
                 'reset', 'exit', 'forward', 'stop', 'clear']
 
@@ -295,42 +366,67 @@ class Shell(cmd.Cmd):
                           ]
         return completions
 
+    def response(self, result, message):
+        """Enqueue message from other than CLI"""
+        try:
+            rcmd = RCMD_EXECUTE_QUEUE.get(False)
+        except Empty:
+            return
+
+        if (rcmd == REMOTE_COMMAND):
+            param = result + '\n' + message
+            RCMD_RESULT_QUEUE.put(param)
+        else:
+            logger.debug("unknown remote command = %s" % rcmd)
+
     def do_status(self, _):
         """Display Soft Patch Panel Status"""
 
         print_status()
+        stat = get_status()
+        self.response(CMD_OK, json.dumps(stat))
 
     def do_pri(self, command):
         """Send command to primary process"""
 
         if command and command in self.COMMANDS:
-            command_primary(command)
+            result, message = command_primary(command)
+            self.response(result, message)
         else:
-            print ("primary invalid command")
+            message = "primary invalid command"
+            print(message)
+            self.response(CMD_ERROR, ret)
 
     def do_sec(self, arg):
         """Send command to secondary process"""
 
-        # remove unwanted space to avoid invalid command error
+        # remove unwanted spaces to avoid invalid command error
         tmparg = re.sub(r'\s+', " ", arg)
         tmparg = re.sub(r'\s?;\s?', ";", tmparg)
         cmds = tmparg.split(';')
         if len(cmds) < 2:
-            print ("error")
+            message = "error"
+            print(message)
+            self.response(CMD_ERROR, message)
         elif str.isdigit(cmds[0]):
             sec_id = int(cmds[0])
             if check_sec_cmds(cmds[1]):
-                command_secondary(sec_id, cmds[1])
+                result, message = command_secondary(sec_id, cmds[1])
+                self.response(result, message)
             else:
-                print ("invalid cmd")
+                message = "invalid cmd"
+                print(message)
+                self.response(CMD_ERROR, message)
         else:
             print (cmds[0])
             print ("first %s" % cmds[1])
+            self.response(CMD_ERROR, "invalid format")
 
     def do_record(self, arg):
         """Save future commands to filename:  RECORD filename.cmd"""
 
         self.recorded_file = open(arg, 'w')
+        self.response(CMD_OK, "record")
 
     def do_playback(self, arg):
         """Playback commands from a file:  PLAYBACK filename.cmd"""
@@ -344,8 +440,11 @@ class Shell(cmd.Cmd):
                         continue
                     lines.append(line)
                 self.cmdqueue.extend(lines)
+                self.response(CMD_OK, "playback")
         except IOError:
-            print ("Error: File does not exist.")
+            message = "Error: File does not exist."
+            print(message)
+            self.response(CMD_NG, message)
 
     def precmd(self, line):
         line = line.lower()
@@ -379,25 +478,34 @@ class Shell(cmd.Cmd):
 def main(argv):
     """main"""
 
-    # Defining server address and port
-    host = ''  #'localhost' or '127.0.0.1' or '' are all same
-
-    try:
-        opts, _ = getopt.getopt(argv, "p:s:h", ["help", "primary = ", "secondary"])
-    except getopt.GetoptError:
-        print ('spp.py -p <primary__port_number> -s <secondary_port_number>')
-        sys.exit(2)
-
-    for opt, arg in opts:
-        if opt in ("-h", "--help"):
-            print ('spp.py -p <primary__port_number> -s <secondary_port_number>')
-            sys.exit()
-        elif opt in ("-p", "--primary"):
-            primary_port = int(arg)
-            print ("primary port : %d" % primary_port)
-        elif opt in ("-s", "--secondary"):
-            secondary_port = int(arg)
-            print ('secondary port : %d' % secondary_port)
+    parser = argparse.ArgumentParser(description="SPP Controller")
+    
+    parser.add_argument(
+            "-p", "--pri-port",
+            type=int, default=5555,
+            help="primary port number")
+    parser.add_argument(
+            "-s", "--sec-port",
+            type=int, default=6666,
+            help="secondary port number")
+    parser.add_argument(
+            "-m", "--mng-port",
+            type=int, default=7777,
+            help="management port number")
+    parser.add_argument(
+            "-ip", "--ipaddr",
+            type=str, default='', #'localhost' or '127.0.0.1' or '' are all same
+            help="IP address")
+    args = parser.parse_args()
+
+    host = args.ipaddr
+    primary_port = args.pri_port
+    secondary_port = args.sec_port
+    management_port = args.mng_port
+
+    print("primary port : %d" % primary_port)
+    print('secondary port : %d' % secondary_port)
+    print('management port : %d' % management_port)
 
     #Creating primary socket object
     primary_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -428,13 +536,30 @@ def main(argv):
     start_new_thread(acceptthread, (secondary_sock, MAIN2SEC, SEC2MAIN))
 
     shell = Shell()
+
+    # Run request handler as a TCP server thread
+    SocketServer.ThreadingTCPServer.allow_reuse_address = True
+    CmdRequestHandler.CMD = shell
+    command_server = SocketServer.ThreadingTCPServer((host, management_port),CmdRequestHandler)
+            
+    t = threading.Thread(target=command_server.serve_forever)
+    t.setDaemon(True)
+    t.start()
+
     shell.cmdloop()
     shell = None
 
-    primary_sock.shutdown(socket.SHUT_RDWR)
-    primary_sock.close()
-    secondary_sock.shutdown(socket.SHUT_RDWR)
-    secondary_sock.close()
+    try:
+        primary_sock.shutdown(socket.SHUT_RDWR)
+        primary_sock.close()
+    except socket.error, excep:
+        print(excep, ", Error while closing primary_sock in main()!")
+
+    try:
+        secondary_sock.shutdown(socket.SHUT_RDWR)
+        secondary_sock.close()
+    except socket.error, excep:
+        print(excep, ", Error while closing primary_sock in main()!")
 
 
 if __name__ == "__main__":
-- 
2.13.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [spp] [PATCH 4/5] Correct sec command completion
  2017-07-18 18:57 [spp] [PATCH 1/5] Add SO_REUSEADDR option ogawa.yasufumi
  2017-07-18 18:57 ` [spp] [PATCH 2/5] Remove unwanted spaces from the sec command ogawa.yasufumi
  2017-07-18 18:57 ` [spp] [PATCH 3/5] Add management port ogawa.yasufumi
@ 2017-07-18 18:57 ` ogawa.yasufumi
  2017-07-18 18:57 ` [spp] [PATCH 5/5] Add completion for bye command ogawa.yasufumi
  2017-08-04 15:57 ` [spp] [PATCH 1/5] Add SO_REUSEADDR option Ferruh Yigit
  4 siblings, 0 replies; 6+ messages in thread
From: ogawa.yasufumi @ 2017-07-18 18:57 UTC (permalink / raw)
  To: spp; +Cc: ferruh.yigit, sy.jong.choi, Yasufumi Ogawa

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

sec command takes sub commands and options contextually, for example,
"sec 1;add ring 0" takes str and int for options or
"sec 1;patch 2 3" takes two ints.
This update is for supporting completion for each of subcommand.

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 src/spp.py | 80 +++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 61 insertions(+), 19 deletions(-)

diff --git a/src/spp.py b/src/spp.py
index 99165ed..0e9908a 100755
--- a/src/spp.py
+++ b/src/spp.py
@@ -278,7 +278,8 @@ def primarythread(sock, main2primary, primary2main):
             try:
                 data = conn.recv(1024) # 1024 stands for bytes of data to be received
                 if data:
-                    primary2main.put("recv:" + str(addr) + ":" + "{" + data + "}")
+                    #primary2main.put("recv:" + str(addr) + ":" + "{" + data + "}")
+                    primary2main.put("recv:%s:{%s}" % (str(addr), data))
                 else:
                     primary2main.put("closing:" + str(addr))
                     conn.close()
@@ -331,6 +332,14 @@ def check_sec_cmds(cmds):
 
     return valid
 
+def clean_sec_cmd(cmdstr):
+    """remove unwanted spaces to avoid invalid command error"""
+     
+    tmparg = re.sub(r'\s+', " ", cmdstr)
+    res = re.sub(r'\s?;\s?', ";", tmparg)
+    return res
+
+
 class Shell(cmd.Cmd):
     """SPP command prompt"""
 
@@ -338,18 +347,18 @@ class Shell(cmd.Cmd):
     prompt = 'spp > '
     recorded_file = None
 
-    # TODO define pri_commands and sec_commands if there are difference
-    COMMANDS = ['status', 'add', 'patch', 'ring', 'vhost',
-                'reset', 'exit', 'forward', 'stop', 'clear']
+    PRI_CMDS = ['status', 'exit', 'clear']
+    SEC_CMDS = ['status', 'exit', 'forward', 'stop', 'add', 'patch', 'del']
+    SEC_SUBCMDS = ['vhost', 'ring']
 
     def complete_pri(self, text, line, begidx, endidx):
         """Completion for primary process commands"""
 
         if not text:
-            completions = self.COMMANDS[:]
+            completions = self.PRI_CMDS[:]
         else:
             completions = [p
-                           for p in self.COMMANDS
+                           for p in self.PRI_CMDS
                            if p.startswith(text)
                           ]
         return completions
@@ -357,14 +366,48 @@ class Shell(cmd.Cmd):
     def complete_sec(self, text, line, begidx, endidx):
         """Completion for secondary process commands"""
 
-        if not text:
-            completions = self.COMMANDS[:]
-        else:
-            completions = [p
-                           for p in self.COMMANDS
-                           if p.startswith(text)
-                          ]
-        return completions
+        try:
+            cleaned_line = clean_sec_cmd(line)
+            if len(cleaned_line.split()) == 1:
+                completions = [str(i)+";" for i in SECONDARY_LIST]
+            elif len(cleaned_line.split()) == 2:
+                if not (";" in cleaned_line):
+                    tmplist = [str(i) for i in SECONDARY_LIST]
+                    completions = [p+";"
+                            for p in tmplist
+                            if p.startswith(text)
+                            ]
+                elif cleaned_line[-1] == ";":
+                    completions = self.SEC_CMDS[:]
+                else:
+                    seccmd = cleaned_line.split(";")[1]
+                    if cleaned_line[-1] != " ":
+                        completions = [p
+                                for p in self.SEC_CMDS
+                                if p.startswith(seccmd)
+                                ]
+                    elif ("add" in seccmd) or ("del" in seccmd):
+                        completions = self.SEC_SUBCMDS[:]
+                    else:
+                        completions = []
+            elif len(cleaned_line.split()) == 3:
+                subcmd = cleaned_line.split()[-1]
+                if ("add" == subcmd) or ("del" == subcmd):
+                    completions = self.SEC_SUBCMDS[:]
+                else:
+                    if cleaned_line[-1] == " ":
+                        completions = []
+                    else:
+                        completions = [p
+                                for p in self.SEC_SUBCMDS
+                                if p.startswith(subcmd)
+                                ]
+            else:
+                completions = []
+            return completions
+        except Exception, e:
+            print(len(cleaned_line.split()))
+            print(e)
 
     def response(self, result, message):
         """Enqueue message from other than CLI"""
@@ -389,20 +432,19 @@ class Shell(cmd.Cmd):
     def do_pri(self, command):
         """Send command to primary process"""
 
-        if command and command in self.COMMANDS:
+        if command and command in self.PRI_CMDS:
             result, message = command_primary(command)
             self.response(result, message)
         else:
             message = "primary invalid command"
             print(message)
-            self.response(CMD_ERROR, ret)
+            self.response(CMD_ERROR, message)
 
     def do_sec(self, arg):
         """Send command to secondary process"""
 
         # remove unwanted spaces to avoid invalid command error
-        tmparg = re.sub(r'\s+', " ", arg)
-        tmparg = re.sub(r'\s?;\s?', ";", tmparg)
+        tmparg = clean_sec_cmd(arg)
         cmds = tmparg.split(';')
         if len(cmds) < 2:
             message = "error"
@@ -559,7 +601,7 @@ def main(argv):
         secondary_sock.shutdown(socket.SHUT_RDWR)
         secondary_sock.close()
     except socket.error, excep:
-        print(excep, ", Error while closing primary_sock in main()!")
+        print(excep, ", Error while closing secondary_sock in main()!")
 
 
 if __name__ == "__main__":
-- 
2.13.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [spp] [PATCH 5/5] Add completion for bye command
  2017-07-18 18:57 [spp] [PATCH 1/5] Add SO_REUSEADDR option ogawa.yasufumi
                   ` (2 preceding siblings ...)
  2017-07-18 18:57 ` [spp] [PATCH 4/5] Correct sec command completion ogawa.yasufumi
@ 2017-07-18 18:57 ` ogawa.yasufumi
  2017-08-04 15:57 ` [spp] [PATCH 1/5] Add SO_REUSEADDR option Ferruh Yigit
  4 siblings, 0 replies; 6+ messages in thread
From: ogawa.yasufumi @ 2017-07-18 18:57 UTC (permalink / raw)
  To: spp; +Cc: ferruh.yigit, sy.jong.choi, Yasufumi Ogawa

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

Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
 src/spp.py | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/spp.py b/src/spp.py
index 0e9908a..68b3a3f 100755
--- a/src/spp.py
+++ b/src/spp.py
@@ -350,6 +350,7 @@ class Shell(cmd.Cmd):
     PRI_CMDS = ['status', 'exit', 'clear']
     SEC_CMDS = ['status', 'exit', 'forward', 'stop', 'add', 'patch', 'del']
     SEC_SUBCMDS = ['vhost', 'ring']
+    BYE_CMDS = ['sec', 'all']
 
     def complete_pri(self, text, line, begidx, endidx):
         """Completion for primary process commands"""
@@ -409,6 +410,18 @@ class Shell(cmd.Cmd):
             print(len(cleaned_line.split()))
             print(e)
 
+    def complete_bye(self, text, line, begidx, endidx):
+        """Completion for bye commands"""
+
+        if not text:
+            completions = self.BYE_CMDS[:]
+        else:
+            completions = [p
+                           for p in self.BYE_CMDS
+                           if p.startswith(text)
+                          ]
+        return completions
+
     def response(self, result, message):
         """Enqueue message from other than CLI"""
         try:
-- 
2.13.1

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [spp] [PATCH 1/5] Add SO_REUSEADDR option
  2017-07-18 18:57 [spp] [PATCH 1/5] Add SO_REUSEADDR option ogawa.yasufumi
                   ` (3 preceding siblings ...)
  2017-07-18 18:57 ` [spp] [PATCH 5/5] Add completion for bye command ogawa.yasufumi
@ 2017-08-04 15:57 ` Ferruh Yigit
  4 siblings, 0 replies; 6+ messages in thread
From: Ferruh Yigit @ 2017-08-04 15:57 UTC (permalink / raw)
  To: ogawa.yasufumi, spp; +Cc: sy.jong.choi

On 7/18/2017 7:57 PM, ogawa.yasufumi@lab.ntt.co.jp wrote:
> From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
> 
> spp.py cannot be launched if it is terminated for unexpected error
> and try to restart because of 'port is already used'.
> This patch is for avoiding the situation by releasing port
> immediately when spp.py is treminated.
> 
> Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>

Series applied, thanks for contribution.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-08-04 15:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-18 18:57 [spp] [PATCH 1/5] Add SO_REUSEADDR option ogawa.yasufumi
2017-07-18 18:57 ` [spp] [PATCH 2/5] Remove unwanted spaces from the sec command ogawa.yasufumi
2017-07-18 18:57 ` [spp] [PATCH 3/5] Add management port ogawa.yasufumi
2017-07-18 18:57 ` [spp] [PATCH 4/5] Correct sec command completion ogawa.yasufumi
2017-07-18 18:57 ` [spp] [PATCH 5/5] Add completion for bye command ogawa.yasufumi
2017-08-04 15:57 ` [spp] [PATCH 1/5] Add SO_REUSEADDR option Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).