8 import xml.etree.ElementTree as ET
13 <configuration name="test_cli">
17 <description>GRE Tunnel</description>
20 <gre-port>gre1</gre-port>
21 <local-endpoint>1.1.1.1</local-endpoint>
22 <remote-endpoint>1.1.1.2</remote-endpoint>
28 <description>GRE Tunnel</description>
31 <gre-port>gre2</gre-port>
32 <local-endpoint>2.2.2.1</local-endpoint>
33 <remote-endpoint>2.2.2.2</remote-endpoint>
41 xmlconf = ET.XML(default_conf)
45 # from http://stackoverflow.com/questions/749796/pretty-printing-xml-in-python
46 def xml_indent(elem, level=0):
49 if not elem.text or not elem.text.strip():
51 if not elem.tail or not elem.tail.strip():
54 xml_indent(elem, level+1)
55 if not elem.tail or not elem.tail.strip():
58 if level and (not elem.tail or not elem.tail.strip()):
61 def text_indent(s, indent = 0, end = "\n"):
62 return " " * indent + s + end
64 def help_callback(cmdline, kvargs):
65 cmd_wr = textwrap.TextWrapper(initial_indent=" ",
66 subsequent_indent=" ")
67 token_wr = textwrap.TextWrapper(initial_indent=" ",
68 subsequent_indent=" ")
70 for c in cmdline.context:
71 s += "%s\n"%(c.to_expr())
72 lines = c.get_help().split("\n")
73 # first line is the command + its help
74 s += ("\n".join(cmd_wr.wrap(lines[0]))) + "\n"
76 s += ("\n".join(token_wr.wrap(l))) + "\n"
79 # used in main and gre context
80 help_cmd = CmdBuilder(
83 "help": TextCliCmd("help", help_str = "Show the help."),
86 help_str = "help for command toto"
89 def get_interface_text_conf(conf, indent = 0):
91 local = conf.find("encapsulation/gre-tunnel/local-endpoint")
92 remote = conf.find("encapsulation/gre-tunnel/remote-endpoint")
93 if local != None and remote != None:
94 bind_str = "bind %s %s"%(local.text, remote.text)
95 vrfid = conf.find("encapsulation/gre-tunnel/link-vrf-id")
97 bind_str += " link-vrfid %s"%(vrfid.text)
98 s += text_indent(bind_str, indent)
99 key = conf.find("encapsulation/gre-tunnel/key")
102 s += text_indent("key enable", indent)
104 s += text_indent("key %s"%(key.text), indent)
105 checksum = conf.find("encapsulation/gre-tunnel/checksum")
107 s += text_indent("checksum enable", indent)
110 def get_main_text_conf(conf, indent = 0):
111 s = text_indent("# GRE", indent)
112 for node in xmlconf.findall("interfaces/interface"):
113 s += text_indent(node.find("name").text, indent)
114 s += get_interface_text_conf(node, indent=(indent + 4))
117 def display_cb(cmdline, kvargs):
119 xml_indent(cur_xmlconf)
120 s = ET.tostring(cur_xmlconf, method="xml", encoding="unicode")
122 if cmdline.context == main_ctx:
123 s = get_main_text_conf(cur_xmlconf)
125 s = get_interface_text_conf(cur_xmlconf)
128 # used in main and gre context
129 display_cmd = CmdBuilder(
130 expr = "display [xml]",
132 "display": TextCliCmd("display", help_str = "Display the " +
133 "current configuration."),
134 "xml": TextCliCmd("xml", help_str = "If present, dump in XML format."),
137 help_str = "Display the current configuration."
140 def bind_cb(cmdline, kvargs):
141 tunnel = cur_xmlconf.find("encapsulation/gre-tunnel")
142 local = tunnel.find("local-endpoint")
144 local = ET.XML("<local-endpoint/>")
146 local.text = kvargs["<local-ip>"]
147 remote = tunnel.find("remote-endpoint")
149 remote = ET.XML("<remote-endpoint/>")
150 tunnel.append(remote)
151 remote.text = kvargs["<remote-ip>"]
152 vrfid = tunnel.find("link-vrf-id")
155 if "<vrfid>" in kvargs:
156 vrfid = ET.XML("<link-vrf-id/>")
158 vrfid.text = str(kvargs["<vrfid>"])
160 def key_cb(cmdline, kvargs):
161 tunnel = cur_xmlconf.find("encapsulation/gre-tunnel")
162 key = tunnel.find("key")
165 if "disable" in kvargs:
167 key = ET.XML("<key/>")
169 if "<key>" in kvargs:
170 key.text = str(kvargs["<key>"])
172 def checksum_cb(cmdline, kvargs):
173 # XXX handle input/output
174 tunnel = cur_xmlconf.find("encapsulation/gre-tunnel")
175 checksum = tunnel.find("checksum")
177 tunnel.remove(checksum)
178 if "disable" in kvargs:
180 checksum = ET.XML("<checksum/>")
181 tunnel.append(checksum)
183 def exit_cb(cmdline, kvargs):
184 global cur_xmlconf, xmlconf
185 cmdline.set_context("main")
186 cmdline.set_prompt("router{} ")
187 cur_xmlconf = xmlconf
189 gre_ctx = PycolContext([
191 expr = "bind <local-ip> <remote-ip> [link-vrfid <vrfid>]",
193 "bind": TextCliCmd("bind", help_str = "Bind the tunnel."),
194 "<local-ip>": IPv4CliCmd(help_str = "The local IPv4 address (A.B.C.D)."),
195 "<remote-ip>": IPv4CliCmd(help_str = "The remote IPv4 address (A.B.C.D)."),
196 "link-vrfid": TextCliCmd("link-vrfid", help_str = ""),
197 "<vrfid>": IntCliCmd(help_str = "Link vrfid."),
200 help_str = "Bind the GRE tunnel on local and remote addresses."
203 expr = "checksum|checksum-input|checksum-output enable|disable",
205 "checksum": TextCliCmd("checksum", help_str = ""),
206 "checksum-input": TextCliCmd("checksum-input", help_str = ""),
207 "checksum-output": TextCliCmd("checksum-output", help_str = ""),
208 "enable": TextCliCmd("enable", help_str = ""),
209 "disable": TextCliCmd("disable", help_str = ""),
212 help_str = "Enable or disable GRE checksum."
215 expr = "key <key>|enable|disable",
217 "key": TextCliCmd("key", help_str = ""),
218 "<key>": IntCliCmd(val_min = 0, val_max = (1<<32) - 1,
219 help_str = "The GRE key."),
220 "enable": TextCliCmd("enable", help_str = ""),
221 "disable": TextCliCmd("disable", help_str = ""),
224 help_str = "Enable or disable GRE checksum."
229 "exit": TextCliCmd("exit", help_str = "Exit from GRE context."),
232 help_str = "Exit from GRE context."
239 return [ node.text for node in \
240 xmlconf.findall("interfaces/interface/encapsulation/gre-tunnel/gre-port") ]
242 def enter_gre(ifname):
243 global xmlconf, cur_xmlconf
244 for node in xmlconf.findall("interfaces/interface"):
245 if node.find("name").text == ifname:
248 cmdline.set_prompt("router{%s} "%(ifname))
249 cmdline.set_context("gre")
251 def enter_gre_cb(cmdline, kvargs):
252 ifname = kvargs["<gre-ctx>"]
253 return enter_gre(ifname)
255 def create_gre_cb(cmdline, kvargs):
256 global xmlconf, cur_xmlconf
258 # create the context first
259 ifname = kvargs["<new-gre-ctx>"]
263 <description>GRE Tunnel</description>
266 <gre-port>{name}</gre-port>
270 """.format(name = ifname)
271 node = ET.XML(xml_str)
272 xmlconf.find("interfaces").append(node)
273 return enter_gre(ifname)
275 def delete_gre(cmdline, kvargs):
276 interfaces = xmlconf.find("interfaces")
277 for interface in interfaces.findall("interface"):
278 if interface.find("name").text == kvargs["<gre-ctx>"]:
279 interfaces.remove(interface)
282 main_ctx = PycolContext([
286 "<gre-ctx>": ChoiceCliCmd(choice = list_gre_ctx,
287 help_str = "An existing gre context."),
290 help_str = "Enter an existing GRE context."
293 expr = "<new-gre-ctx>",
295 "<new-gre-ctx>": RegexpCliCmd("gre[0-9]+",
296 help_str = "A new gre context (format " +
300 help_str = "Create and enter a new GRE context."
303 expr = "delete <gre-ctx>",
305 "delete": TextCliCmd("delete", help_str = ""),
306 "<gre-ctx>": ChoiceCliCmd(choice = list_gre_ctx,
307 help_str = "An existing gre context."),
310 help_str = "Delete a GRE context."
317 cmdline = pycol.Cmdline()
318 cmdline.add_context("main", main_ctx)
319 cmdline.add_context("gre", gre_ctx)
320 cmdline.set_context("main")
321 cmdline.set_prompt("router{} ")