* [spp] [PATCH] controller: add multi-node support
@ 2018-12-17 3:32 ogawa.yasufumi
0 siblings, 0 replies; only message in thread
From: ogawa.yasufumi @ 2018-12-17 3:32 UTC (permalink / raw)
To: ferruh.yigit, spp, ogawa.yasufumi
From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
This update is to manage multiple nodes of SPP from SPP CLI.
To add several nodes, give several address of spp-ctl with `-b` option.
Default address is `127.0.0.1:7777` and it is able to be overwritten.
If port number is not given, default value `7777` is remained.
# Use two spp-ctl running on "192.168.1.101:7777" and
# "192.168.1.102:7777".
$ python src/spp.py -b 192.168.1.101 -b 192.168.1.102
`server` command is provided for switching spp-ctl under the management
of SPP CLI.
# Show all of spp-ctl nodes.
spp > server # or 'server list'
1: 192.168.1.101:7777 *
2: 192.168.1.102:7777
# Switch to second node.
spp > server 2
Switch spp-ctl to "2: 192.168.1.102:7777".
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/controller/commands/pri.py | 2 +-
src/controller/commands/server.py | 79 +++++++++++++++++++++++++++++++++++++++
src/controller/shell.py | 29 +++++++++++++-
src/controller/spp.py | 42 ++++++++++++++++-----
src/controller/spp_ctl_client.py | 5 ++-
5 files changed, 142 insertions(+), 15 deletions(-)
create mode 100644 src/controller/commands/server.py
diff --git a/src/controller/commands/pri.py b/src/controller/commands/pri.py
index 51da7ab..750d355 100644
--- a/src/controller/commands/pri.py
+++ b/src/controller/commands/pri.py
@@ -8,7 +8,7 @@ class SppPrimary(object):
SppPrimary class is intended to be used in Shell class as a delegator
for running 'pri' command.
- 'self.command()' is called from do_pri() and 'self.complete()' is called
+ 'self.run()' is called from do_pri() and 'self.complete()' is called
from complete_pri() of both of which is defined in Shell.
"""
diff --git a/src/controller/commands/server.py b/src/controller/commands/server.py
new file mode 100644
index 0000000..ca362ab
--- /dev/null
+++ b/src/controller/commands/server.py
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017-2018 Nippon Telegraph and Telephone Corporation
+
+import re
+from ..spp_common import logger
+
+
+class SppCtlServer(object):
+ """Execute server command for switching spp-ctl.
+
+ SppCtlServer class is intended to be used in Shell class as a delegator
+ for running 'server' command.
+
+ 'self.run()' is called from do_pri() and 'self.complete()' is called
+ from complete_pri() of both of which is defined in Shell.
+ """
+
+ SERVER_CMDS = ['list']
+
+ def __init__(self, spp_cli_objs):
+ self.spp_cli_objs = spp_cli_objs
+ self.current_idx = 0
+
+ def run(self, commands):
+ args = re.sub(r'\s+', ' ', commands).split(' ')
+ if '' in args:
+ args.remove('')
+
+ if len(args) == 0 or args[0] == 'list':
+ self._show_list()
+ else:
+ idx = int(args[0]) - 1
+ self._switch_to(idx)
+
+ def complete(self, text, line, begidx, endidx):
+ """Completion for server command.
+
+ Called from complete_server() to complete server command.
+ """
+
+ candidates = []
+ for i in range(len(self.spp_cli_objs)):
+ candidates.append(str(i))
+ candidates = candidates + self.SERVER_CMDS[:]
+
+ if not text:
+ completions = candidates
+ else:
+ completions = [p for p in candidates
+ if p.startswith(text)
+ ]
+
+ return completions
+
+ def get_current_server(self):
+ return self.spp_cli_objs[self.current_idx]
+
+ def _show_list(self):
+ cnt = 1
+ for cli_obj in self.spp_cli_objs:
+ # Put a mark to current server.
+ if cnt == self.current_idx + 1:
+ current = '*'
+ else:
+ current = ''
+
+ print(' %d: %s:%s %s' % (
+ cnt, cli_obj.ip_addr, cli_obj.port, current))
+ cnt += 1
+
+ def _switch_to(self, idx):
+ if len(self.spp_cli_objs) > idx:
+ self.current_idx = idx
+ cli_obj = self.spp_cli_objs[self.current_idx]
+ print('Switch spp-ctl to "%d: %s:%d"' %
+ (idx+1, cli_obj.ip_addr, cli_obj.port))
+ else:
+ print('Index should be less than %d!' %
+ (len(self.spp_cli_objs) + 1))
diff --git a/src/controller/shell.py b/src/controller/shell.py
index 615b9a1..6ce4dca 100644
--- a/src/controller/shell.py
+++ b/src/controller/shell.py
@@ -7,6 +7,7 @@ import cmd
from .commands import bye
from .commands import pri
from .commands import nfv
+from .commands import server
from .commands import topo
from .commands import vf
from .commands import mirror
@@ -38,9 +39,10 @@ class Shell(cmd.Cmd, object):
else:
readline.write_history_file(hist_file)
- def __init__(self, spp_ctl_cli, use_cache=False):
+ def __init__(self, spp_cli_objs, use_cache=False):
cmd.Cmd.__init__(self)
- self.spp_ctl_cli = spp_ctl_cli
+ self.spp_ctl_server = server.SppCtlServer(spp_cli_objs)
+ self.spp_ctl_cli = spp_cli_objs[0]
self.use_cache = use_cache
self.init_spp_procs()
self.spp_topo = topo.SppTopo(self.spp_ctl_cli, {}, self.topo_size)
@@ -128,6 +130,9 @@ class Shell(cmd.Cmd, object):
def print_status(self):
"""Display information about connected clients."""
+ print('- spp-ctl:')
+ print(' - address: %s:%s' % (self.spp_ctl_cli.ip_addr,
+ self.spp_ctl_cli.port))
res = self.spp_ctl_cli.get('processes')
if res is not None:
if res.status_code == 200:
@@ -252,6 +257,26 @@ class Shell(cmd.Cmd, object):
self.recorded_file.close()
self.recorded_file = None
+ def do_server(self, commands):
+ """Switch SPP REST API server.
+
+ spp > server # or 'server list'
+ 1: 192.168.1.101:7777 *
+ 2: 192.168.1.102:7777
+
+ spp > server 2
+ Switch spp-ctl to "2: 192.168.1.102:7777".
+ """
+
+ self.spp_ctl_server.run(commands)
+ self.spp_ctl_cli = self.spp_ctl_server.get_current_server()
+
+ def complete_server(self, text, line, begidx, endidx):
+ """Completion for server command."""
+
+ res = self.spp_ctl_server.complete(text, line, begidx, endidx)
+ return res
+
def do_status(self, _):
"""Display status info of SPP processes
diff --git a/src/controller/spp.py b/src/controller/spp.py
index 2e1c173..7b7316c 100644
--- a/src/controller/spp.py
+++ b/src/controller/spp.py
@@ -5,6 +5,7 @@
from __future__ import absolute_import
import argparse
+import re
from .shell import Shell
from . import spp_ctl_client
import sys
@@ -12,19 +13,40 @@ import sys
def main(argv):
+ # Default
+ api_ipaddr = '127.0.0.1'
+ api_port = 7777
+
parser = argparse.ArgumentParser(description="SPP Controller")
- parser.add_argument('-b', '--bind-addr', type=str, default='127.0.0.1',
- help='bind address, default=127.0.0.1')
- parser.add_argument('-a', '--api-port', type=int, default=7777,
- help='bind address, default=7777')
+ parser.add_argument('-b', '--bind-addr', action='append',
+ default=['%s:%s' % (api_ipaddr, api_port)],
+ help='bind address, default=127.0.0.1:7777')
args = parser.parse_args()
- spp_ctl_cli = spp_ctl_client.SppCtlClient(args.bind_addr,
- args.api_port)
- if spp_ctl_cli.is_server_running() is False:
- print('Is not spp-ctl running, nor correct IP address?')
- exit()
- shell = Shell(spp_ctl_cli)
+ if len(args.bind_addr) > 1:
+ args.bind_addr.pop(0)
+
+ spp_cli_objs = []
+ for addr in args.bind_addr:
+ if ':' in addr:
+ api_ipaddr, api_port = addr.split(':')
+ else:
+ api_ipaddr = addr
+
+ if not re.match(r'\d*\.\d*\.\d*\.\d*', addr):
+ print('Invalid address "%s"' % args.bind_addr)
+ exit()
+
+ spp_ctl_cli = spp_ctl_client.SppCtlClient(api_ipaddr, int(api_port))
+
+ if spp_ctl_cli.is_server_running() is False:
+ print('Is not spp-ctl running on %s, nor correct IP address?' %
+ api_ipaddr)
+ exit()
+
+ spp_cli_objs.append(spp_ctl_cli)
+
+ shell = Shell(spp_cli_objs)
shell.cmdloop()
shell = None
diff --git a/src/controller/spp_ctl_client.py b/src/controller/spp_ctl_client.py
index 3713326..f04173b 100644
--- a/src/controller/spp_ctl_client.py
+++ b/src/controller/spp_ctl_client.py
@@ -9,9 +9,10 @@ class SppCtlClient(object):
rest_common_error_codes = [400, 404, 500]
- def __init__(self, ip_addr='localhost', port=7777):
- api_ver = 'v1'
+ def __init__(self, ip_addr='localhost', port=7777, api_ver='v1'):
self.base_url = 'http://%s:%d/%s' % (ip_addr, port, api_ver)
+ self.ip_addr = ip_addr
+ self.port = port
def request_handler(func):
"""Request handler for spp-ctl.
--
2.7.4
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2018-12-17 3:34 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-17 3:32 [spp] [PATCH] controller: add multi-node support ogawa.yasufumi
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).