From: ogawa.yasufumi@lab.ntt.co.jp
To: ferruh.yigit@intel.com, spp@dpdk.org, ogawa.yasufumi@lab.ntt.co.jp
Subject: [spp] [PATCH 4/8] controller: add launch sub command in pri
Date: Tue, 29 Jan 2019 21:21:57 +0900 [thread overview]
Message-ID: <1548764521-2827-5-git-send-email-ogawa.yasufumi@lab.ntt.co.jp> (raw)
In-Reply-To: <1548764521-2827-1-git-send-email-ogawa.yasufumi@lab.ntt.co.jp>
From: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
As launch is supported in spp_primary and spp-ctl, add `launch` in
`pri` command. It takes type of secondary process, ID and arguments
of launching the process. Here is an example.
spp > pri; launch nfv 1 -l 1,2 -m 512 -- -n 1 -s 192.168.1.100:7777
You notice that secondary ID is used two times. The reason is it is used
for completion. If you specify secondary ID, it completes typical
arguments. You just correct a few params of command line.
spp > pri; launch # press TAB
mirror nfv pcap nfv
spp > pri; launch nfv # press TAB
1 10 11 12 2 3 4 ...
spp > pri; launch nfv 1 # press TAB and correct some params
spp > pri; launch nfv 1 -l 1,2 -m 512 -- -n 1 -s 192.168.1.100:7777
Signed-off-by: Yasufumi Ogawa <ogawa.yasufumi@lab.ntt.co.jp>
---
src/controller/commands/pri.py | 190 +++++++++++++++++++++++++++++++++++--
src/controller/commands/server.py | 4 +
src/controller/shell.py | 3 +
src/controller/shell_lib/common.py | 8 +-
src/controller/spp_common.py | 4 +
5 files changed, 201 insertions(+), 8 deletions(-)
diff --git a/src/controller/commands/pri.py b/src/controller/commands/pri.py
index 750d355..577952c 100644
--- a/src/controller/commands/pri.py
+++ b/src/controller/commands/pri.py
@@ -1,6 +1,10 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2018 Nippon Telegraph and Telephone Corporation
+from __future__ import absolute_import
+
+from .. import spp_common
+from ..shell_lib import common
class SppPrimary(object):
"""Exec SPP primary command.
@@ -13,7 +17,7 @@ class SppPrimary(object):
"""
# All of primary commands used for validation and completion.
- PRI_CMDS = ['status', 'clear']
+ PRI_CMDS = ['status', 'launch', 'clear']
def __init__(self, spp_ctl_cli):
self.spp_ctl_cli = spp_ctl_cli
@@ -21,11 +25,15 @@ class SppPrimary(object):
def run(self, cmd):
"""Called from do_pri() to Send command to primary process."""
- if not (cmd in self.PRI_CMDS):
- print("Invalid pri command: '%s'" % cmd)
+ tmpary = cmd.split(' ')
+ subcmd = tmpary[0]
+ params = tmpary[1:]
+
+ if not (subcmd in self.PRI_CMDS):
+ print("Invalid pri command: '%s'" % subcmd)
return None
- if cmd == 'status':
+ if subcmd == 'status':
res = self.spp_ctl_cli.get('primary/status')
if res is not None:
if res.status_code == 200:
@@ -36,7 +44,10 @@ class SppPrimary(object):
else:
print('Error: unknown response.')
- elif cmd == 'clear':
+ elif subcmd == 'launch':
+ self._run_launch(params)
+
+ elif subcmd == 'clear':
res = self.spp_ctl_cli.delete('primary/status')
if res is not None:
if res.status_code == 204:
@@ -122,10 +133,175 @@ class SppPrimary(object):
Called from complete_pri() to complete primary command.
"""
+ candidates = []
+ tokens = line.split(' ')
+
+ mytemplate = "-l 1,2 -m 512 -- -n {} -s {}"
+
+ # Show sub commands
+ if len(tokens) == 2:
+ # Add sub commands
+ candidates = candidates + self.PRI_CMDS[:]
+
+ # Show args of `launch` sub command.
+ elif len(tokens) == 3 and tokens[1] == 'launch':
+ for pt in spp_common.SEC_TYPES:
+ candidates.append('{}'.format(pt))
+
+ elif len(tokens) == 4 and tokens[1] == 'launch':
+ if tokens[2] in spp_common.SEC_TYPES:
+ candidates = [
+ str(i+1) for i in range(spp_common.MAX_SECONDARY)]
+
+ elif len(tokens) == 5 and tokens[1] == 'launch':
+ if (tokens[2] in spp_common.SEC_TYPES) and \
+ (int(tokens[3])-1 in range(spp_common.MAX_SECONDARY)):
+ sid = tokens[3]
+ candidates = [mytemplate.format(sid, common.current_server_addr())]
+
if not text:
- completions = self.PRI_CMDS[:]
+ completions = candidates
else:
- completions = [p for p in self.PRI_CMDS
+ completions = [p for p in candidates
if p.startswith(text)
]
+
+ #completions.append("nof_tokens:{}".format(len(tokens)))
+
return completions
+
+ def _get_sec_ids(self):
+ sec_ids = []
+ res = self.spp_ctl_cli.get('processes')
+ if res is not None:
+ if res.status_code == 200:
+ for proc in res.json():
+ if proc['type'] != 'primary':
+ sec_ids.append(proc['client-id'])
+ elif res.status_code in self.rest_common_error_codes:
+ # Print default error message
+ pass
+ else:
+ print('Error: unknown response.')
+ return sec_ids
+
+ def _setup_opts_dict(self, opts_list):
+ """Setup options for sending to spp-ctl as a request body.
+
+ Options is setup from given list. If option has no value, None is
+ assgined for the value. For example,
+ ['-l', '1-2', --no-pci, '-m', '512', ...]
+ => {'-l':'1-2', '--no-pci':None, '-m':'512', ...}
+ """
+ prekey = None
+ opts_dict = {}
+ for opt in opts_list:
+ if opt.startswith('-'):
+ opts_dict[opt] = None
+ prekey = opt
+ else:
+ if prekey is not None:
+ opts_dict[prekey] = opt
+ prekey = None
+ return opts_dict
+
+ def _run_launch(self, params):
+ """Launch secondary process.
+
+ Parse `launch` command and send request to spp-ctl. Params of the
+ consists of proc type, sec ID and arguments. It allows to skip some
+ params which are completed. All of examples here are same.
+
+ spp > lanuch nfv -l 1-2 ... -- -n 1 ... # sec ID '1' is skipped
+ spp > lanuch spp_nfv -l 1-2 ... -- -n 1 ... # use 'spp_nfv' insteads
+ """
+
+ # Check params
+ if len(params) < 2:
+ print('Invalid syntax! Proc type, ID and options are required.')
+ print('E.g. "nfv 1 -l 1-2 -m 512 -- -n 1 -s 192.168.1.100:6666"')
+ return None
+
+ proc_type = params[0]
+ if params[1].startswith('-'):
+ sec_id = None # should be found later, or failed
+ args = params[1:]
+ else:
+ sec_id = params[1]
+ args = params[2:]
+
+ if proc_type.startswith('spp_') is not True:
+ proc_name = 'spp_' + proc_type
+ else:
+ proc_name = proc_type
+ proc_type = proc_name[len('spp_'):]
+
+ if proc_type not in spp_common.SEC_TYPES:
+ print("'{}' is not supported in launch cmd.".format(proc_type))
+ return None
+
+ if '--' not in args:
+ print('Arguments should include separator "--".')
+ return None
+
+ # Setup options of JSON sent to spp-ctl. Here is an example for
+ # launching spp_nfv.
+ # {
+ # 'client_id': '1',
+ # 'proc_name': 'spp_nfv',
+ # 'eal': {'-l': '1-2', '-m': '1024', ...},
+ # 'app': {'-n': '1', '-s': '192.168.1.100:6666'}
+ # }
+ idx_separator = args.index('--')
+ eal_opts = args[:idx_separator]
+ app_opts = args[(idx_separator+1):]
+
+ if '--proc-type' not in args:
+ eal_opts.append('--proc-type')
+ eal_opts.append('secondary')
+
+ opts = {'proc_name': proc_name}
+ opts['eal'] = self._setup_opts_dict(eal_opts)
+ opts['app'] = self._setup_opts_dict(app_opts)
+
+ # Try to find sec_id from app options.
+ if sec_id is None:
+ if (proc_type == 'nfv') and ('-n' in opts['app']):
+ sec_id = opts['app']['-n']
+ elif ('--client-id' in opts['app']): # vf, mirror or pcap
+ sec_id = opts['app']['--client-id']
+ else:
+ print('Secondary ID is required!')
+ return None
+
+ if sec_id in self._get_sec_ids():
+ print("Cannot add '{}' already used.".format(sec_id))
+ return None
+
+ opts['client_id'] = sec_id
+
+ # Complete or correct sec_id.
+ if proc_name == 'spp_nfv':
+ if '-n' in opts['app'].keys():
+ if (opts['app']['-n'] != sec_id):
+ opts['app']['-n'] = sec_id
+ else:
+ opts['app']['-n'] = sec_id
+ else: # vf, mirror or pcap
+ if '--client-id' in opts['app'].keys():
+ if (opts['app']['--client-id'] != sec_id):
+ opts['app']['--client-id'] = sec_id
+ else:
+ opts['app']['--client-id'] = sec_id
+
+ # Send request for launch secondary.
+ res = self.spp_ctl_cli.put('primary/launch', opts)
+ if res is not None:
+ error_codes = self.spp_ctl_cli.rest_common_error_codes
+ if res.status_code == 204:
+ print('Succeeded to launch {}:{}.'.format(
+ proc_type, sec_id))
+ elif res.status_code in error_codes:
+ pass
+ else:
+ print('Error: unknown response.')
diff --git a/src/controller/commands/server.py b/src/controller/commands/server.py
index eece1f6..c2bda9d 100644
--- a/src/controller/commands/server.py
+++ b/src/controller/commands/server.py
@@ -123,6 +123,10 @@ class SppCtlServer(object):
if len(self.spp_cli_objs) > idx:
self.current_idx = idx
cli_obj = self.spp_cli_objs[self.current_idx]
+
+ common.set_current_server_addr(
+ cli_obj.ip_addr, cli_obj.port)
+
print('Switch spp-ctl to "{}: {}:{}".'.format(
idx+1, cli_obj.ip_addr, cli_obj.port))
else:
diff --git a/src/controller/shell.py b/src/controller/shell.py
index 6dc6514..1fb9867 100644
--- a/src/controller/shell.py
+++ b/src/controller/shell.py
@@ -47,6 +47,9 @@ class Shell(cmd.Cmd, object):
self.init_spp_procs()
self.spp_topo = topo.SppTopo(self.spp_ctl_cli, {}, self.topo_size)
+ common.set_current_server_addr(
+ self.spp_ctl_cli.ip_addr, self.spp_ctl_cli.port)
+
def init_spp_procs(self):
"""Initialize delegators of SPP processes.
diff --git a/src/controller/shell_lib/common.py b/src/controller/shell_lib/common.py
index 3c59cca..87263d0 100644
--- a/src/controller/shell_lib/common.py
+++ b/src/controller/shell_lib/common.py
@@ -3,7 +3,7 @@
# Copyright(c) 2017-2018 Nippon Telegraph and Telephone Corporation
import os
-
+from .. import spp_common
def decorate_dir(curdir, filelist):
"""Add '/' the end of dirname for path completion
@@ -122,3 +122,9 @@ def is_valid_port(port_num):
return False
return True
+
+def current_server_addr():
+ return spp_common.cur_server_addr
+
+def set_current_server_addr(ipaddr, port):
+ spp_common.cur_server_addr = '{}:{}'.format(ipaddr, port)
diff --git a/src/controller/spp_common.py b/src/controller/spp_common.py
index 1a15bcc..c94d175 100644
--- a/src/controller/spp_common.py
+++ b/src/controller/spp_common.py
@@ -7,6 +7,10 @@ import os
PORT_TYPES = ['phy', 'ring', 'vhost', 'pcap', 'nullpmd']
+SEC_TYPES = ['nfv', 'vf', 'mirror', 'pcap']
+
+cur_server_addr = None
+
# Maximum num of sock queues for secondaries
MAX_SECONDARY = 16
--
2.7.4
next prev parent reply other threads:[~2019-01-29 12:24 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-29 12:21 [spp] [PATCH 0/8] Add launch command to spp_primary ogawa.yasufumi
2019-01-29 12:21 ` [spp] [PATCH 1/8] shared: add func for getting dirname of secondary ogawa.yasufumi
2019-01-29 12:21 ` [spp] [PATCH 2/8] spp_priamry: add launch command ogawa.yasufumi
2019-01-29 12:21 ` [spp] [PATCH 3/8] spp-ctl: add launch command support for REST API ogawa.yasufumi
2019-01-29 12:21 ` ogawa.yasufumi [this message]
2019-01-29 12:21 ` [spp] [PATCH 5/8] spp_primary: change launching sec to use python ogawa.yasufumi
2019-01-29 12:21 ` [spp] [PATCH 6/8] tools/helpers: add sec launcher script ogawa.yasufumi
2019-01-29 12:22 ` [spp] [PATCH 7/8] controller: revise completion of launch command ogawa.yasufumi
2019-01-29 12:22 ` [spp] [PATCH 8/8] tools/helpers: move cpu_layout script to helpers ogawa.yasufumi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1548764521-2827-5-git-send-email-ogawa.yasufumi@lab.ntt.co.jp \
--to=ogawa.yasufumi@lab.ntt.co.jp \
--cc=ferruh.yigit@intel.com \
--cc=spp@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).