Soft Patch Panel
 help / color / mirror / Atom feed
* [spp] [PATCH 0/2] Add completion for forwarder in primary
@ 2019-10-17 12:58 yasufum.o
  2019-10-17 12:58 ` [spp] [PATCH 1/2] cli: add compl for new commands in spp_primary yasufum.o
  2019-10-17 12:58 ` [spp] [PATCH 2/2] cli: fix bug of completion in del command yasufum.o
  0 siblings, 2 replies; 3+ messages in thread
From: yasufum.o @ 2019-10-17 12:58 UTC (permalink / raw)
  To: spp, ferruh.yigit, yasufum.o

From: Yasufumi Ogawa <yasufum.o@gmail.com>

This update is to add completion for command for forwarding thread in
spp_primary.

Yasufumi Ogawa (2):
  cli: add compl for new commands in spp_primary
  cli: fix bug of completion in del command

 src/cli/commands/nfv.py |  38 +++----
 src/cli/commands/pri.py | 221 ++++++++++++++++++++++++++++++----------
 2 files changed, 187 insertions(+), 72 deletions(-)

-- 
2.17.1


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

* [spp] [PATCH 1/2] cli: add compl for new commands in spp_primary
  2019-10-17 12:58 [spp] [PATCH 0/2] Add completion for forwarder in primary yasufum.o
@ 2019-10-17 12:58 ` yasufum.o
  2019-10-17 12:58 ` [spp] [PATCH 2/2] cli: fix bug of completion in del command yasufum.o
  1 sibling, 0 replies; 3+ messages in thread
From: yasufum.o @ 2019-10-17 12:58 UTC (permalink / raw)
  To: spp, ferruh.yigit, yasufum.o

From: Yasufumi Ogawa <yasufum.o@gmail.com>

As `add`, `del` and `patch` are supported in spp_primary, add
completion for these commands. This update is also including misc
revises for maintenance.

Signed-off-by: Yasufumi Ogawa <yasufum.o@gmail.com>
---
 src/cli/commands/nfv.py |  19 ++--
 src/cli/commands/pri.py | 218 ++++++++++++++++++++++++++++++----------
 2 files changed, 173 insertions(+), 64 deletions(-)

diff --git a/src/cli/commands/nfv.py b/src/cli/commands/nfv.py
index 1144eca..3bf4148 100644
--- a/src/cli/commands/nfv.py
+++ b/src/cli/commands/nfv.py
@@ -28,7 +28,7 @@ class SppNfv(object):
         self.spp_ctl_cli = spp_ctl_cli
         self.sec_id = sec_id
         self.ports = []  # registered ports
-        self.patchs = []
+        self.patches = []
 
         # Call REST API each time of completion if it is True.
         self.use_cache = use_cache
@@ -129,13 +129,13 @@ class SppNfv(object):
                 print('Error: unknown response.')
 
     # TODO(yasufum) change name starts with '_' as private
-    def get_ports_and_patches(self):
-        """Get all of ports and patchs at once.
+    def _get_ports_and_patches(self):
+        """Get all of ports and patches at once.
 
         This method is to execute `get_ports()` and `get_patches()` at
         once to reduce request to spp-ctl. Returned value is a set of
         lists. You use this method as following.
-          ports, patches = get_ports_and_patches()
+          ports, patches = _get_ports_and_patches()
         """
 
         res = self.spp_ctl_cli.get('nfvs/%d' % self.sec_id)
@@ -150,8 +150,7 @@ class SppNfv(object):
             else:
                 print('Error: unknown response.')
 
-    # TODO(yasufum) change name starts with '_' as private
-    def get_patched_ports(self):
+    def _get_patched_ports(self):
         """Get all of patched ports as a list.
 
         This method is to get a list of patched ports instead of a dict.
@@ -234,10 +233,10 @@ class SppNfv(object):
             res = []
 
             if self.use_cache is False:
-                self.ports, self.patches = self.get_ports_and_patches()
+                self.ports, self.patches = self._get_ports_and_patches()
 
             # Patched ports should not be included in the candidate of del.
-            patched_ports = self.get_patched_ports()
+            patched_ports = self._get_patched_ports()
 
             # Remove ports already used from candidate.
             for kw in self.ports:
@@ -264,7 +263,7 @@ class SppNfv(object):
             res = []
 
             if self.use_cache is False:
-                self.ports, self.patches = self.get_ports_and_patches()
+                self.ports, self.patches = self._get_ports_and_patches()
 
             # Get patched ports of src and dst to be used for completion.
             src_ports = []
@@ -354,7 +353,7 @@ class SppNfv(object):
                 self.patches = self.get_patches()
 
             # Patched ports should not be deleted.
-            patched_ports = self.get_patched_ports()
+            patched_ports = self._get_patched_ports()
 
             if params[0] in patched_ports:
                 print("Cannot delete patched port '%s'." % params[0])
diff --git a/src/cli/commands/pri.py b/src/cli/commands/pri.py
index 32c632c..f4cda74 100644
--- a/src/cli/commands/pri.py
+++ b/src/cli/commands/pri.py
@@ -25,7 +25,7 @@ class SppPrimary(object):
         self.spp_ctl_cli = spp_ctl_cli
 
         self.ports = []  # registered ports
-        self.patchs = []
+        self.patches = []
 
         # Default args for `pri; launch`, used if given cli_config is invalid
 
@@ -248,7 +248,7 @@ class SppPrimary(object):
                 print('Error: unknown response for get_patches.')
 
     def _get_ports_and_patches(self):
-        """Get all of ports and patchs at once.
+        """Get all of ports and patches at once.
 
         This method is to execute `_get_ports()` and `_get_patches()` at
         once to reduce request to spp-ctl. Returned value is a set of
@@ -357,16 +357,16 @@ class SppPrimary(object):
 
         return sockets
 
-    def _setup_launch_opts(self, tokens, cli_config):
+    def _setup_launch_opts(self, sub_tokens, cli_config):
         """Make options for launch cmd from config params."""
 
         if 'max_secondary' in cli_config.keys():
             max_secondary = int(cli_config['max_secondary']['val'])
 
-            if (tokens[2] in spp_common.SEC_TYPES) and \
-                    (int(tokens[3])-1 in range(max_secondary)):
-                ptype = tokens[2]
-                sid = tokens[3]
+            if (sub_tokens[1] in spp_common.SEC_TYPES) and \
+                    (int(sub_tokens[2])-1 in range(max_secondary)):
+                ptype = sub_tokens[1]
+                sid = sub_tokens[2]
 
                 # Option of secondary ID is different between spp_nfv
                 # and others.
@@ -481,56 +481,166 @@ class SppPrimary(object):
         Called from complete_pri() to complete primary command.
         """
 
-        candidates = []
-        tokens = line.split(' ')
-
-        # Parse command line
-        if tokens[0].endswith(';'):
-
-            # 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 'max_secondary' in cli_config.keys():
-                    max_secondary = int(
-                            cli_config['max_secondary']['val'])
-
-                    if tokens[2] in spp_common.SEC_TYPES:
-                        used_sec_ids = [str(i) for i in self._get_sec_ids()]
-                        candidates = [
-                                str(i+1) for i in range(max_secondary)
-                                if str(i+1) not in used_sec_ids]
-                        logger.debug(candidates)
+        try:
+            candidates = []
+            tokens = line.split(' ')
+
+            # Parse command line
+            if tokens[0].endswith(';'):
+
+                # Show sub commands
+                if len(tokens) == 2:
+                    # Add sub commands
+                    candidates = candidates + self.PRI_CMDS[:]
+
                 else:
-                    logger.error(
-                            'Error: max_secondary is not defined in config')
-                    candidates = []
+                    # Show args of `launch` sub command.
+                    if tokens[1] == 'launch':
+                        candidates = self._compl_launch(tokens[1:], cli_config)
+                    elif tokens[1] == 'add':
+                        candidates = self._compl_add(tokens[1:])
+                    elif tokens[1] == 'del':
+                        candidates = self._compl_del(tokens[1:])
+                    elif tokens[1] == 'patch':
+                        candidates = self._compl_patch(tokens[1:])
+
+            if not text:
+                completions = candidates
+            else:
+                completions = [p for p in candidates
+                               if p.startswith(text)
+                               ]
 
-            elif len(tokens) == 5 and tokens[1] == 'launch':
-                # Do not show candidate if given sec ID is already used.
-                # Sec ID is contained as the third entry in tokens. Here is an
-                # example of tokens.
-                #   ['pri;', 'launch', 'nfv', '1', '']
-                used_sec_ids = [str(i) for i in self._get_sec_ids()]
-                if tokens[3] not in used_sec_ids:
-                    candidates = self._setup_launch_opts(
-                            tokens, cli_config)
-
-        if not text:
-            completions = candidates
-        else:
-            completions = [p for p in candidates
-                           if p.startswith(text)
-                           ]
+            return completions
+
+        except Exception as e:
+            print(e)
+
+    def _compl_launch(self, sub_tokens, cli_config):
+        candidates = []
+        if len(sub_tokens) == 2:
+            for pt in spp_common.SEC_TYPES:
+                candidates.append('{}'.format(pt))
+
+        elif len(sub_tokens) == 3:
+            if 'max_secondary' in cli_config.keys():
+                max_secondary = int(
+                        cli_config['max_secondary']['val'])
+
+                if sub_tokens[1] in spp_common.SEC_TYPES:
+                    used_sec_ids = [str(i) for i in self._get_sec_ids()]
+                    candidates = [
+                            str(i+1) for i in range(max_secondary)
+                            if str(i+1) not in used_sec_ids]
+                    logger.debug(candidates)
+            else:
+                logger.error(
+                        'Error: max_secondary is not defined in config')
+                candidates = []
+
+        elif len(sub_tokens) == 4:
+            # Do not show candidate if given sec ID is already used.
+            # Sec ID is contained as the 2nd entry in sub_tokens. Here is an
+            # example of sub_tokens.
+            #   ['launch', 'nfv', '1', '']
+            used_sec_ids = [str(i) for i in self._get_sec_ids()]
+            if sub_tokens[1] not in used_sec_ids:
+                candidates = self._setup_launch_opts(
+                        sub_tokens, cli_config)
+
+        return candidates
+
+    # TODO(yasufum): consider to merge nfv's.
+    def _compl_add(self, sub_tokens):
+        """Complete `add` command."""
+
+        if len(sub_tokens) < 3:
+            res = []
+
+            port_types = spp_common.PORT_TYPES[:]
+            port_types.remove('phy')
+
+            for kw in port_types:
+                if kw.startswith(sub_tokens[1]):
+                    res.append(kw + ':')
+            return res
+
+    # TODO(yasufum): consider to merge nfv's.
+    def _compl_del(self, sub_tokens):
+        """Complete `del` command."""
+
+        # Del command consists of two tokens max, for instance,
+        # `nfv 1; del ring:1`.
+        if len(sub_tokens) < 3:
+            res = []
+
+            self.ports, self.patches = self._get_ports_and_patches()
+
+            # Patched ports should not be included in the candidate of del.
+            patched_ports = self._get_patched_ports()
+
+            # Remove ports already used from candidate.
+            for kw in self.ports:
+                if not (kw in patched_ports):
+                    if kw.startswith(sub_tokens[1]):
+                        if ':' in sub_tokens[1]:  # exp, 'ring:' or 'ring:0'
+                            res.append(kw.split(':')[1])
+                        else:
+                            res.append(kw)
+
+            # Physical port cannot be removed.
+            for p in res:
+                if p.startswith('phy:'):
+                    res.remove(p)
+
+            return res
+
+    # TODO(yasufum): consider to merge nfv's.
+    def _compl_patch(self, sub_tokens):
+        """Complete `patch` command."""
+
+        # Patch command consists of three tokens max, for instance,
+        # `nfv 1; patch phy:0 ring:1`.
+        if len(sub_tokens) < 4:
+            res = []
+
+            self.ports, self.patches = self._get_ports_and_patches()
+
+            # Get patched ports of src and dst to be used for completion.
+            src_ports = []
+            dst_ports = []
+            for pt in self.patches:
+                src_ports.append(pt['src'])
+                dst_ports.append(pt['dst'])
+
+            # Remove patched ports from candidates.
+            target_idx = len(sub_tokens) - 1  # target is src or dst
+            tmp_ports = self.ports[:]  # candidates
+            if target_idx == 1:  # find src port
+                # If some of ports are patched, `reset` should be included.
+                if self.patches != []:
+                    tmp_ports.append('reset')
+                for pt in src_ports:
+                    tmp_ports.remove(pt)  # remove patched ports
+            else:  # find dst port
+                # If `reset` is given, no need to show dst ports.
+                if sub_tokens[target_idx - 1] == 'reset':
+                    tmp_ports = []
+                else:
+                    for pt in dst_ports:
+                        tmp_ports.remove(pt)
+
+            # Return candidates.
+            for kw in tmp_ports:
+                if kw.startswith(sub_tokens[target_idx]):
+                    # Completion does not work correctly if `:` is included in
+                    # tokens. Required to create keyword only after `:`.
+                    if ':' in sub_tokens[target_idx]:  # 'ring:' or 'ring:0'
+                        res.append(kw.split(':')[1])  # add only after `:`
+                    else:
+                        res.append(kw)
 
-        return completions
+            return res
 
     def _get_sec_ids(self):
         sec_ids = []
-- 
2.17.1


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

* [spp] [PATCH 2/2] cli: fix bug of completion in del command
  2019-10-17 12:58 [spp] [PATCH 0/2] Add completion for forwarder in primary yasufum.o
  2019-10-17 12:58 ` [spp] [PATCH 1/2] cli: add compl for new commands in spp_primary yasufum.o
@ 2019-10-17 12:58 ` yasufum.o
  1 sibling, 0 replies; 3+ messages in thread
From: yasufum.o @ 2019-10-17 12:58 UTC (permalink / raw)
  To: spp, ferruh.yigit, yasufum.o

From: Yasufumi Ogawa <yasufum.o@gmail.com>

In `pri` and `nfv` commands, `del` subcommand supports TAB completion
for candidate ports for deleting. However, inappropriate ports are
suggested because of bug for selecting the candidates. This update is
fix this issue.

Signed-off-by: Yasufumi Ogawa <yasufum.o@gmail.com>
---
 src/cli/commands/nfv.py | 19 +++++++++++--------
 src/cli/commands/pri.py | 19 +++++++++++--------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/src/cli/commands/nfv.py b/src/cli/commands/nfv.py
index 3bf4148..6349823 100644
--- a/src/cli/commands/nfv.py
+++ b/src/cli/commands/nfv.py
@@ -227,10 +227,11 @@ class SppNfv(object):
     def _compl_del(self, sub_tokens):
         """Complete `del` command."""
 
+        res = []
         # Del command consists of two tokens max, for instance,
         # `nfv 1; del ring:1`.
         if len(sub_tokens) < 3:
-            res = []
+            tmp_ary = []
 
             if self.use_cache is False:
                 self.ports, self.patches = self._get_ports_and_patches()
@@ -241,18 +242,20 @@ class SppNfv(object):
             # Remove ports already used from candidate.
             for kw in self.ports:
                 if not (kw in patched_ports):
-                    if kw.startswith(sub_tokens[1]):
+                    if sub_tokens[1] == '':
+                        tmp_ary.append(kw)
+                    elif kw.startswith(sub_tokens[1]):
                         if ':' in sub_tokens[1]:  # exp, 'ring:' or 'ring:0'
-                            res.append(kw.split(':')[1])
+                            tmp_ary.append(kw.split(':')[1])
                         else:
-                            res.append(kw)
+                            tmp_ary.append(kw)
 
             # Physical port cannot be removed.
-            for p in res:
-                if p.startswith('phy:'):
-                    res.remove(p)
+            for p in tmp_ary:
+                if not p.startswith('phy:'):
+                    res.append(p)
 
-            return res
+        return res
 
     def _compl_patch(self, sub_tokens):
         """Complete `patch` command."""
diff --git a/src/cli/commands/pri.py b/src/cli/commands/pri.py
index f4cda74..bee0d81 100644
--- a/src/cli/commands/pri.py
+++ b/src/cli/commands/pri.py
@@ -569,10 +569,11 @@ class SppPrimary(object):
     def _compl_del(self, sub_tokens):
         """Complete `del` command."""
 
+        res = []
         # Del command consists of two tokens max, for instance,
         # `nfv 1; del ring:1`.
         if len(sub_tokens) < 3:
-            res = []
+            tmp_ary = []
 
             self.ports, self.patches = self._get_ports_and_patches()
 
@@ -582,18 +583,20 @@ class SppPrimary(object):
             # Remove ports already used from candidate.
             for kw in self.ports:
                 if not (kw in patched_ports):
-                    if kw.startswith(sub_tokens[1]):
+                    if sub_tokens[1] == '':
+                        tmp_ary.append(kw)
+                    elif kw.startswith(sub_tokens[1]):
                         if ':' in sub_tokens[1]:  # exp, 'ring:' or 'ring:0'
-                            res.append(kw.split(':')[1])
+                            tmp_ary.append(kw.split(':')[1])
                         else:
-                            res.append(kw)
+                            tmp_ary.append(kw)
 
             # Physical port cannot be removed.
-            for p in res:
-                if p.startswith('phy:'):
-                    res.remove(p)
+            for p in tmp_ary:
+                if not p.startswith('phy:'):
+                    res.append(p)
 
-            return res
+        return res
 
     # TODO(yasufum): consider to merge nfv's.
     def _compl_patch(self, sub_tokens):
-- 
2.17.1


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

end of thread, other threads:[~2019-10-17 12:58 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-17 12:58 [spp] [PATCH 0/2] Add completion for forwarder in primary yasufum.o
2019-10-17 12:58 ` [spp] [PATCH 1/2] cli: add compl for new commands in spp_primary yasufum.o
2019-10-17 12:58 ` [spp] [PATCH 2/2] cli: fix bug of completion in del command yasufum.o

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).