mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 16:26:10 +00:00
tools: added alias_destroyer.py
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
This commit is contained in:
parent
c0c053fa13
commit
c66bbd697d
269
tools/alias_destroyer.py
Executable file
269
tools/alias_destroyer.py
Executable file
@ -0,0 +1,269 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from pprint import pformat, pprint
|
||||
|
||||
|
||||
class DEFUN(object):
|
||||
|
||||
def __init__(self, lines):
|
||||
# name, name_cmd, command_string, help_strings, guts):
|
||||
self.name = None
|
||||
self.name_cmd = None
|
||||
self.command_string = None
|
||||
self.help_strings = []
|
||||
self.guts = []
|
||||
self.aliases = []
|
||||
|
||||
'''
|
||||
DEFUN (no_bgp_maxmed_onstartup,
|
||||
no_bgp_maxmed_onstartup_cmd,
|
||||
"no bgp max-med on-startup",
|
||||
NO_STR
|
||||
BGP_STR
|
||||
"Advertise routes with max-med\n"
|
||||
"Effective on a startup\n")
|
||||
|
||||
'''
|
||||
state = 'HEADER'
|
||||
for (line_number, line) in enumerate(lines):
|
||||
|
||||
if state == 'HEADER':
|
||||
if line_number == 0:
|
||||
re_name = re.search('DEFUN \((.*),', line.strip())
|
||||
self.name = re_name.group(1)
|
||||
|
||||
elif line_number == 1:
|
||||
self.name_cmd = line.strip()[0:-1] # chop the trailing comma
|
||||
|
||||
elif line_number == 2:
|
||||
self.command_string = line
|
||||
state = 'HELP'
|
||||
|
||||
elif state == 'HELP':
|
||||
if line.strip() == '{':
|
||||
self.guts.append(line)
|
||||
state = 'BODY'
|
||||
else:
|
||||
self.help_strings.append(line)
|
||||
|
||||
elif state == 'BODY':
|
||||
if line.rstrip() == '}':
|
||||
self.guts.append(line)
|
||||
state = None
|
||||
else:
|
||||
self.guts.append(line)
|
||||
|
||||
else:
|
||||
raise Exception("invalid state %s" % state)
|
||||
|
||||
# print "%d %7s: %s" % (line_number, state, line.rstrip())
|
||||
|
||||
assert self.command_string, "No command string for\n%s" % pformat(lines)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def dump(self):
|
||||
lines = []
|
||||
|
||||
if self.aliases:
|
||||
lines.append("/*\n")
|
||||
lines.append(" * CHECK ME - The following ALIASes need to be implemented in this DEFUN\n")
|
||||
|
||||
for alias in self.aliases:
|
||||
lines.append(" * %s\n" % alias.command_string.strip())
|
||||
for line in alias.help_strings:
|
||||
lines.append(" * %s\n" % line)
|
||||
lines.append(" *\n")
|
||||
|
||||
lines.append(" */\n")
|
||||
|
||||
lines.append("DEFUN (%s,\n" % self.name)
|
||||
lines.append(" %s,\n" % self.name_cmd)
|
||||
lines.append(self.command_string)
|
||||
lines.extend(self.help_strings)
|
||||
lines.extend(self.guts)
|
||||
return ''.join(lines)
|
||||
|
||||
|
||||
class ALIAS(object):
|
||||
|
||||
def __init__(self, lines):
|
||||
self.name = None
|
||||
self.name_cmd = None
|
||||
self.command_string = None
|
||||
self.help_strings = []
|
||||
|
||||
'''
|
||||
ALIAS (no_bgp_maxmed_onstartup,
|
||||
no_bgp_maxmed_onstartup_period_cmd,
|
||||
"no bgp max-med on-startup <5-86400>",
|
||||
NO_STR
|
||||
BGP_STR
|
||||
"Advertise routes with max-med\n"
|
||||
"Effective on a startup\n"
|
||||
"Time (seconds) period for max-med\n")
|
||||
'''
|
||||
state = 'HEADER'
|
||||
for (line_number, line) in enumerate(lines):
|
||||
|
||||
if state == 'HEADER':
|
||||
if line_number == 0:
|
||||
re_name = re.search('ALIAS \((.*),', line)
|
||||
|
||||
try:
|
||||
self.name = re_name.group(1)
|
||||
except AttributeError:
|
||||
pprint(lines)
|
||||
raise
|
||||
|
||||
elif line_number == 1:
|
||||
self.name_cmd = line.strip()[0:-1] # chop the trailing comma
|
||||
|
||||
elif line_number == 2:
|
||||
self.command_string = line
|
||||
state = 'HELP'
|
||||
|
||||
elif state == 'HELP':
|
||||
if line.strip() == '{':
|
||||
raise Exception("should not see { in an ALIAS")
|
||||
else:
|
||||
line = line.strip()
|
||||
if line.endswith(')'):
|
||||
line = line[0:-1] # strip the trailing )
|
||||
self.help_strings.append(line)
|
||||
|
||||
else:
|
||||
raise Exception("invalid state %s" % state)
|
||||
|
||||
assert self.command_string, "No command string for\n%s" % pformat(lines)
|
||||
|
||||
def __str__(self):
|
||||
return self.name_cmd
|
||||
|
||||
|
||||
def alias_destroy(filename):
|
||||
lines = []
|
||||
defuns = {}
|
||||
aliases = {}
|
||||
|
||||
with open(filename, 'r') as fh:
|
||||
state = None
|
||||
defun_lines = []
|
||||
alias_lines = []
|
||||
|
||||
for (line_number, line) in enumerate(fh.readlines()):
|
||||
|
||||
if state is None:
|
||||
if line.startswith('DEFUN ('):
|
||||
assert line.count(',') == 1, "%d: Too many commas in\n%s" % (line_number, line)
|
||||
defun_lines.append(line)
|
||||
state = 'DEFUN_HEADER'
|
||||
|
||||
elif line.startswith('ALIAS ('):
|
||||
assert line.count(',') == 1, "%d: Too many commas in\n%s" % (line_number, line)
|
||||
alias_lines.append(line)
|
||||
state = 'ALIAS_HEADER'
|
||||
|
||||
elif state == 'DEFUN_HEADER':
|
||||
defun_lines.append(line)
|
||||
|
||||
if line.startswith('DEFUN'):
|
||||
raise Exception("ERROR on line %d, found DEFUN inside DEFUN" % line_number)
|
||||
|
||||
elif line.startswith('ALIAS'):
|
||||
raise Exception("ERROR on line %d, found ALIAS inside DEFUN" % line_number)
|
||||
|
||||
elif line.strip() == '{':
|
||||
state = 'DEFUN_BODY'
|
||||
|
||||
elif state == 'ALIAS_HEADER':
|
||||
alias_lines.append(line)
|
||||
|
||||
if line.startswith('ALIAS'):
|
||||
raise Exception("ERROR on line %d, found ALIAS inside ALIAS" % line_number)
|
||||
|
||||
elif line.startswith('DEFUN'):
|
||||
raise Exception("ERROR on line %d, found DEFUN inside ALIAS" % line_number)
|
||||
|
||||
if line.rstrip().endswith(')'):
|
||||
new_alias = ALIAS(alias_lines)
|
||||
aliases[new_alias.name_cmd] = new_alias
|
||||
state = None
|
||||
alias_lines = []
|
||||
|
||||
elif state == 'DEFUN_BODY':
|
||||
defun_lines.append(line)
|
||||
|
||||
if line.rstrip() == '}':
|
||||
new_defun = DEFUN(defun_lines)
|
||||
defuns[new_defun.name] = new_defun
|
||||
state = None
|
||||
defun_lines = []
|
||||
|
||||
# uncomment to debug state machine
|
||||
print "%5d %12s: %s" % (line_number, state, line.rstrip())
|
||||
|
||||
lines.append(line)
|
||||
|
||||
|
||||
# At this point we know all of the aliases and all of the tokens
|
||||
# Assign each ALIAS to its parent DEFUN
|
||||
for alias in aliases.itervalues():
|
||||
defun = defuns.get(alias.name)
|
||||
assert defun, "Could not find DEFUN for %s" % alias
|
||||
defun.aliases.append(alias)
|
||||
|
||||
# Now write the file but:
|
||||
# - do not write any ALIASes
|
||||
# - do not write the install_element for any ALIASes
|
||||
# - when you write the DEFUN include a comment that contains the ALIAS command strings it needs to cover
|
||||
with open(filename, 'w') as fh:
|
||||
state = None
|
||||
|
||||
for line in lines:
|
||||
|
||||
if state is None:
|
||||
if line.startswith('DEFUN ('):
|
||||
state = 'DEFUN_HEADER'
|
||||
re_name = re.search('DEFUN \((.*),', line.strip())
|
||||
name = re_name.group(1)
|
||||
defun = defuns.get(name)
|
||||
fh.write(defun.dump())
|
||||
|
||||
elif line.startswith('ALIAS ('):
|
||||
state = 'ALIAS_HEADER'
|
||||
|
||||
else:
|
||||
if 'install_element' in line:
|
||||
# install_element (CONFIG_NODE, &ip_community_list_name_standard_cmd);
|
||||
re_install_element = re.search('install_element\s*\(\w+,\s*&(.*)\s*\)', line.strip())
|
||||
cmd = re_install_element.group(1)
|
||||
if cmd not in aliases:
|
||||
fh.write(line)
|
||||
else:
|
||||
fh.write(line)
|
||||
|
||||
elif state == 'DEFUN_HEADER':
|
||||
if line.strip() == '{':
|
||||
state = 'DEFUN_BODY'
|
||||
|
||||
elif state == 'ALIAS_HEADER':
|
||||
if line.rstrip().endswith(')'):
|
||||
state = None
|
||||
|
||||
elif state == 'DEFUN_BODY':
|
||||
if line.rstrip() == '}':
|
||||
state = None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
filename = sys.argv[1]
|
||||
if os.path.exists(filename):
|
||||
alias_destroy(filename)
|
||||
else:
|
||||
print "ERROR: could not find file %s" % filename
|
Loading…
Reference in New Issue
Block a user