From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mogw1233.ocn.ad.jp (mogw1233.ocn.ad.jp [153.149.235.34]) by dpdk.org (Postfix) with ESMTP id 081712BF2 for ; Tue, 6 Mar 2018 11:51:30 +0100 (CET) Received: from mf-smf-ucb019c3 (mf-smf-ucb019c3.ocn.ad.jp [153.153.66.132]) by mogw1233.ocn.ad.jp (Postfix) with ESMTP id C9C7A108023B; Tue, 6 Mar 2018 19:51:28 +0900 (JST) Received: from ntt.pod01.mv-mta-ucb026 ([153.149.142.100]) by mf-smf-ucb019c3 with ESMTP id tABsedMP8DyE1tABseHLZN; Tue, 06 Mar 2018 19:51:28 +0900 Received: from smtp.ocn.ne.jp ([153.149.227.165]) by ntt.pod01.mv-mta-ucb026 with id JarU1x0053akymp01arUGJ; Tue, 06 Mar 2018 10:51:28 +0000 Received: from localhost.localdomain (sp1-66-103-93.msc.spmode.ne.jp [1.66.103.93]) by smtp.ocn.ne.jp (Postfix) with ESMTPA; Tue, 6 Mar 2018 19:51:28 +0900 (JST) From: ogawa.yasufumi@lab.ntt.co.jp To: ferruh.yigit@intel.com, spp@dpdk.org Cc: Yasufumi Ogawa Date: Tue, 6 Mar 2018 19:50:53 +0900 Message-Id: <20180306105055.65210-12-ogawa.yasufumi@lab.ntt.co.jp> X-Mailer: git-send-email 2.13.1 In-Reply-To: <20180306105055.65210-1-ogawa.yasufumi@lab.ntt.co.jp> References: <20180306105055.65210-1-ogawa.yasufumi@lab.ntt.co.jp> Subject: [spp] [PATCH 11/13] controller: add topo_subgraph command X-BeenThere: spp@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Soft Patch Panel List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Mar 2018 10:51:30 -0000 From: Yasufumi Ogawa 'topo_subgraph' is for defining subgraph of resources in a network topology generated by 'topo'. Typically it is used for grouping vhost interfaces of each of VMs or containers to be more understandable the generated network topology. Usage: topo_subgraph [VERB] [LABEL] [SUBGRAPH] VERB: 'add' or 'del' If you assign vhost1 and vhost2 to VM1, define subgraph as following. spp > topo_subgraph add VM1 vhost1,vhost2 Or delete defined subgraph. spp > topo_subgraph del VM1 To show all of defined subgraphs, simply run without arguments. spp > topo_subgraph Signed-off-by: Yasufumi Ogawa --- src/controller/shell.py | 85 ++++++++++++++++++++++++++++++++++++++++++++++++- src/controller/topo.py | 43 +++++++++++++++++++++---- 2 files changed, 120 insertions(+), 8 deletions(-) diff --git a/src/controller/shell.py b/src/controller/shell.py index 8a0580a..8aae86d 100644 --- a/src/controller/shell.py +++ b/src/controller/shell.py @@ -30,6 +30,7 @@ class Shell(cmd.Cmd, object): BYE_CMDS = ['sec', 'all'] PLUGIN_DIR = 'command' + subgraphs = {} def default(self, line): """Define defualt behaviour @@ -483,6 +484,87 @@ class Shell(cmd.Cmd, object): if args == '': pprint(vars(self)) + def terms_topo_subgraph(self): + """Define terms of topo_subgraph command""" + + return ['add', 'del'] + + def do_topo_subgraph(self, args): + """Subgarph manager for topo + + Subgraph is a group of object defined in dot language. + For topo command, it is used for grouping resources of each + of VM or container to topology be more understandable. + + Add subgraph labeled 'vm1'. Resource name is capitalized and + both of them is OK. + spp > topo_subgraph add vm1 VHOST1;VHOST2 # upper case + spp > topo_subgraph add vm1 vhost1;vhost2 # lower case + + Delete subgraph 'vm1'. + spp > topo_subgraph del vm1 + + To show subgraphs, run topo_subgraph without args. + spp > topo_subgraph + {'vm1', 'VHOST1;VHOST2'} + """ + + args_cleaned = re.sub(r"\s+", ' ', args).strip() + # Show subgraphs if given no argments + if (args_cleaned == ''): + if len(self.subgraphs) == 0: + print("No subgraph.") + else: + for label, subg in self.subgraphs.items(): + print('label: %s\tsubgraph: "%s"' % (label, subg)) + else: # add or del + tokens = args_cleaned.split(' ') + # Add subgraph + if tokens[0] == 'add': + if len(tokens) == 3: + label = tokens[1] + subg = tokens[2].upper() + if ',' in subg: + subg = re.sub(r",", ";", subg) + + # TODO(yasufum) add validation for subgraph + self.subgraphs[label] = subg + print("Add subgraph '%s'" % label) + else: + print("Invalid syntax '%s'!" % args_cleaned) + # Delete subgraph + elif ((tokens[0] == 'del') or + (tokens[0] == 'delete') or + (tokens[0] == 'remove')): + del(self.subgraphs[tokens[1]]) + print("Delete subgraph '%s'" % tokens[1]) + + else: + print("Ivalid subcommand '%s'!" % tokens[0]) + + def complete_topo_subgraph(self, text, line, begidx, endidx): + terms = self.terms_topo_subgraph() + + tokens = re.sub(r"\s+", ' ', line).strip().split(' ') + if text == '': + if len(tokens) == 1: + return terms + elif len(tokens) == 2 and tokens[1] == 'del': + return self.subgraphs.keys() + elif text != '': + completions = [] + if len(tokens) == 3 and tokens[1] == 'del': + for t in self.subgraphs.keys(): + if t.startswith(tokens[2]): + completions.append(t) + elif len(tokens) == 2: + for t in terms: + if t.startswith(text): + completions.append(t) + return completions + else: + pass + def do_topo(self, args): """Output network topology @@ -506,7 +588,8 @@ class Shell(cmd.Cmd, object): tp = topo.Topo( spp_common.SECONDARY_LIST, spp_common.MAIN2SEC, - spp_common.SEC2MAIN) + spp_common.SEC2MAIN, + self.subgraphs) args_ary = args.split() if len(args_ary) == 0: print("Usage: topo dst [ftype]") diff --git a/src/controller/topo.py b/src/controller/topo.py index 30a9c1a..92d1634 100644 --- a/src/controller/topo.py +++ b/src/controller/topo.py @@ -20,11 +20,12 @@ class Topo(object): * text (dot, json, yaml) """ - def __init__(self, sec_ids, m2s_queues, s2m_queues): + def __init__(self, sec_ids, m2s_queues, s2m_queues, sub_graphs): logger.info("Topo initialized with sec IDs %s" % sec_ids) self.sec_ids = sec_ids self.m2s_queues = m2s_queues self.s2m_queues = s2m_queues + self.sub_graphs = sub_graphs def show(self, dtype): res_ary = [] @@ -153,26 +154,54 @@ class Topo(object): # rank output.append( '{rank=same; %s}' % ("; ".join(ring_labels))) + output.append( + '{rank=same; %s}' % ("; ".join(vhost_labels))) + if len(phys) > 0: output.append( '{rank=max; %s}' % ( phys[0]["iface"]["type"] + phys[0]["iface"]["id"])) - output.append( - '{rank=same; %s}' % ("; ".join(phy_labels))) + elif len(vhosts) > 0: + output.append( + '{rank=max; %s}' % ( + vhosts[0]["iface"]["type"] + vhosts[0]["iface"]["id"])) + + if len(phy_labels) > 0: + output.append( + '{rank=same; %s}' % ("; ".join(phy_labels))) + + # Add subgraph + ssgs = [] + if len(self.sub_graphs) > 0: + cnt = 1 + for label, val in self.sub_graphs.items(): + cluster_id = "cluster%d" % cnt + ssg_label = label + ssg_ports = val + ssg = 'subgraph %s {label="%s" %s}' % ( + cluster_id, ssg_label, ssg_ports) + ssgs.append(ssg) + cnt += 1 - # subgraph cluster_id = "cluster0" sg_label = "Host" sg_ports = "; ".join(phy_labels + ring_labels) - output.append( - 'subgraph %s {label="%s" %s}' % (cluster_id, sg_label, sg_ports)) + if len(ssgs) == 0: + output.append( + 'subgraph %s {label="%s" %s}' % ( + cluster_id, sg_label, sg_ports)) + else: + tmp = 'label="%s" %s' % (sg_label, sg_ports) + contents = [tmp] + ssgs + output.append( + 'subgraph %s {%s}' % (cluster_id, '; '.join(contents))) + # Add links for link in links: output.append(link) output.append("}") - # remove duplicated entries f = open(output_fname, "w+") f.write("\n".join(output)) f.close() -- 2.13.1