| 
									
										
										
										
											2014-10-09 16:02:46 -07:00
										 |  |  | #!/usr/bin/python | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import re | 
					
						
							|  |  |  | import argparse | 
					
						
							|  |  |  | from collections import OrderedDict | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lockfile="/run/network/.lock" | 
					
						
							|  |  |  | modules_configfile='/var/lib/ifupdownaddons/addons.conf' | 
					
						
							|  |  |  | modules_dir='/usr/share/ifupdownaddons' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | addon_config = OrderedDict([('pre-up', []), | 
					
						
							|  |  |  |                             ('up', []), | 
					
						
							|  |  |  |                             ('post-up', []), | 
					
						
							|  |  |  |                             ('pre-down', []), | 
					
						
							|  |  |  |                             ('down', []), | 
					
						
							|  |  |  |                             ('post-down', [])]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def read_modules_config(): | 
					
						
							|  |  |  |     with open(modules_configfile, 'r') as f: | 
					
						
							|  |  |  |         lines = f.readlines() | 
					
						
							|  |  |  |         for l in lines: | 
					
						
							|  |  |  |             litems = l.rstrip(' \n').split(',') | 
					
						
							|  |  |  |             operation = litems[0] | 
					
						
							|  |  |  |             mname = litems[1] | 
					
						
							|  |  |  |             addon_config[operation].append(mname) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def man_rst_header(): | 
					
						
							|  |  |  |     print '==========================' | 
					
						
							|  |  |  |     print 'ifupdown-addons-interfaces' | 
					
						
							|  |  |  |     print '==========================' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print '---------------------------------------------------------' | 
					
						
							|  |  |  |     print 'ifupdown2 addon modules interface configuration' | 
					
						
							|  |  |  |     print '---------------------------------------------------------' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print ':Author: roopa@cumulusnetworks.com' | 
					
						
							|  |  |  |     print ':Date:   2013-09-25' | 
					
						
							|  |  |  |     print ':Copyright: Copyright 2013 Cumulus Networks, Inc.  All rights reserved.' | 
					
						
							|  |  |  |     print ':Version: 0.1' | 
					
						
							|  |  |  |     print ':Manual section: 5' | 
					
						
							|  |  |  |     print '\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def man_rst_body(): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print 'DESCRIPTION' | 
					
						
							|  |  |  |     print '===========' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print ('''    ifupdown2 addon modules add incremental functionality to | 
					
						
							|  |  |  |     core ifupdown2 tool. | 
					
						
							|  |  |  |             | 
					
						
							|  |  |  |     All installed addon modules are executed on every interface | 
					
						
							|  |  |  |     listed in the interfaces file. Addon modules are installed under | 
					
						
							|  |  |  |     /usr/share/ifupdownaddons. To see the list of active addon | 
					
						
							|  |  |  |     modules, see ifaddon(8). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Addon modules add new attributes to the interfaces(5) file. | 
					
						
							|  |  |  |     Below is a list of attribute options provided by each module. | 
					
						
							|  |  |  |     These can be listed under each iface section in the interfaces(5) | 
					
						
							|  |  |  |     file.  ''') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     print '\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_addon_modinfo(modules_dir): | 
					
						
							|  |  |  |     """ load python modules from modules_dir | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Default modules_dir is /usr/share/ifupdownmodules | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """ | 
					
						
							|  |  |  |     if not modules_dir in sys.path: | 
					
						
							|  |  |  |         sys.path.append(modules_dir) | 
					
						
							|  |  |  |     read_modules_config() | 
					
						
							|  |  |  |     modinfo = {} | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         for op, mlist in addon_config.items(): | 
					
						
							|  |  |  |             for mname in mlist: | 
					
						
							|  |  |  |                 if mname in modinfo.keys(): continue | 
					
						
							|  |  |  |                 mpath = modules_dir + '/' + mname + '.py' | 
					
						
							|  |  |  |                 if os.path.exists(mpath): | 
					
						
							|  |  |  |                     try: | 
					
						
							|  |  |  |                         m = __import__(mname) | 
					
						
							|  |  |  |                         mclass = getattr(m, mname) | 
					
						
							|  |  |  |                     except: | 
					
						
							|  |  |  |                         pass | 
					
						
							|  |  |  |                         continue | 
					
						
							|  |  |  |                     minstance = mclass() | 
					
						
							|  |  |  |                     if hasattr(minstance, 'get_modinfo'): | 
					
						
							|  |  |  |                        modinfo[mname] = minstance.get_modinfo() | 
					
						
							|  |  |  |     except:  | 
					
						
							|  |  |  |         raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return modinfo | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def print_long_string(indent, strarg): | 
					
						
							|  |  |  |     slen = 70 - len(indent) | 
					
						
							|  |  |  |     tmphelpstr = strarg | 
					
						
							|  |  |  |     l = len(strarg) | 
					
						
							|  |  |  |     while l > 0: | 
					
						
							|  |  |  |         rem = slen if l >= slen else l | 
					
						
							|  |  |  |         print('%s%s' %(indent, tmphelpstr[:rem])) | 
					
						
							|  |  |  |         tmphelpstr = tmphelpstr[rem:].strip() | 
					
						
							|  |  |  |         l -= rem | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def man_rst_examples(): | 
					
						
							|  |  |  |     print 'EXAMPLES' | 
					
						
							|  |  |  |     print '========' | 
					
						
							|  |  |  |     print '''    Listed below are addon modules and their supported attributes. | 
					
						
							|  |  |  |     The attributes if applicable go under the iface section in the | 
					
						
							|  |  |  |     interfaces(5) file.\n''' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     indent = '    ' | 
					
						
							|  |  |  |     modinfo = get_addon_modinfo(modules_dir) | 
					
						
							|  |  |  |     for m, mdict in modinfo.items(): | 
					
						
							|  |  |  |         aindent = indent + '  ' | 
					
						
							|  |  |  |         aindentplus = aindent + '  ' | 
					
						
							|  |  |  |         if not mdict: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         print_long_string(indent, '**%s**: %s' %(m, mdict.get('mhelp', ''))) | 
					
						
							|  |  |  |         attrdict = mdict.get('attrs') | 
					
						
							|  |  |  |         if not attrdict: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         print '\n' | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             for attrname, attrvaldict in attrdict.items(): | 
					
						
							|  |  |  |                 if attrvaldict.get('compat', False): | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 print('%s**%s**\n' %(aindent, attrname)) | 
					
						
							|  |  |  |                 print_long_string(aindentplus, '**help**: %s' | 
					
						
							|  |  |  |                         %(attrvaldict.get('help', ''))) | 
					
						
							|  |  |  |                 print '\n' | 
					
						
							|  |  |  |                 print('%s**required**: %s\n' %(aindentplus, | 
					
						
							|  |  |  |                             attrvaldict.get('required', False))) | 
					
						
							|  |  |  |                 default = attrvaldict.get('default') | 
					
						
							|  |  |  |                 if default: | 
					
						
							|  |  |  |                     print('%s**default**: %s\n' %(aindentplus, default)) | 
					
						
							|  |  |  |                 validrange = attrvaldict.get('validrange') | 
					
						
							|  |  |  |                 if validrange: | 
					
						
							|  |  |  |                     print('%svalidrange: %s\n' | 
					
						
							|  |  |  |                           %(aindentplus, '-'.join(validrange))) | 
					
						
							|  |  |  |                 validvals = attrvaldict.get('validvals') | 
					
						
							|  |  |  |                 if validvals: | 
					
						
							|  |  |  |                     print('%s**validvals**: %s\n' | 
					
						
							|  |  |  |                               %(aindentplus, ','.join(validvals))) | 
					
						
							|  |  |  |                 examples = attrvaldict.get('example') | 
					
						
							|  |  |  |                 if not examples: | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 print '%s**example**:' %(aindentplus) | 
					
						
							|  |  |  |                 for e in examples: | 
					
						
							|  |  |  |                     print '%s%s\n' %(aindentplus + indent, e) | 
					
						
							|  |  |  |                 print '' | 
					
						
							|  |  |  |         except Exception, e: | 
					
						
							|  |  |  |             print "Roopa: m = %s, str(e) = %s\n"  %(m, str(e)) | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         print '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def man_rst_see_also(): | 
					
						
							|  |  |  |     print 'SEE ALSO' | 
					
						
							|  |  |  |     print '========' | 
					
						
							|  |  |  |     print '''    interfaces(5), | 
					
						
							|  |  |  |     ifup(8), | 
					
						
							|  |  |  |     ip(8), | 
					
						
							|  |  |  |     mstpctl(8), | 
					
						
							|  |  |  |     brctl(8), | 
					
						
							| 
									
										
										
										
											2014-12-28 07:07:47 -08:00
										 |  |  |     ethtool(8), | 
					
						
							|  |  |  |     clagctl(8)''' | 
					
						
							| 
									
										
										
										
											2014-10-09 16:02:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | def show_man_rst(): | 
					
						
							|  |  |  |     man_rst_header() | 
					
						
							|  |  |  |     man_rst_body() | 
					
						
							|  |  |  |     man_rst_examples() | 
					
						
							|  |  |  |     man_rst_see_also() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def show(): | 
					
						
							|  |  |  |     for operation, mlist in addon_config.items(): | 
					
						
							|  |  |  |         postion = 1 | 
					
						
							|  |  |  |         for m in mlist: | 
					
						
							|  |  |  |             print '%d. %s' %(postion, m) | 
					
						
							|  |  |  |             postion += 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def write_modules_config(): | 
					
						
							|  |  |  |     with open(modules_configfile, 'w') as f: | 
					
						
							|  |  |  |         for op, mlist in addon_config.items(): | 
					
						
							|  |  |  |             [f.write('%s,%s\n' %(op, m)) for m in mlist] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def process_add_cmd(args): | 
					
						
							|  |  |  |     op = args.operation | 
					
						
							|  |  |  |     module = args.module | 
					
						
							|  |  |  |     position = args.position | 
					
						
							|  |  |  |     if not op: | 
					
						
							|  |  |  |         for k, vlist in addon_config.items(): | 
					
						
							|  |  |  |             if module not in vlist: | 
					
						
							|  |  |  |                 addon_config[k].append(module) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 print '%s: module %s already present' %(k, module) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if module in addon_config.get(op): | 
					
						
							|  |  |  |         print 'module already present' | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if position: | 
					
						
							|  |  |  |        try: | 
					
						
							|  |  |  |             addon_config[op].insert(position, module) | 
					
						
							|  |  |  |        except Exception, e: | 
					
						
							|  |  |  |            print ('error inserting module %s at postion %s (%s)' | 
					
						
							|  |  |  |                     %(module, position, str(e))) | 
					
						
							|  |  |  |            raise | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |        addon_config[op].append(module) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def process_del_cmd(args): | 
					
						
							|  |  |  |     op = args.operation | 
					
						
							|  |  |  |     module = args.module | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if op: | 
					
						
							|  |  |  |         del addon_config[op] | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |        try: | 
					
						
							|  |  |  |             [addon_config[op].remove(module) for op in addon_config.keys()] | 
					
						
							|  |  |  |        except ValueError: | 
					
						
							|  |  |  |            pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def process_move_cmd(args): | 
					
						
							|  |  |  |     op = args.operation | 
					
						
							|  |  |  |     module = args.module | 
					
						
							|  |  |  |     pos = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         pos = int(args.position) | 
					
						
							|  |  |  |         if pos < 0 or pos > len(addon_config.get(op)): | 
					
						
							|  |  |  |             raise Exception('invalid value for position') | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         raise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if addon_config[op].index(module) == pos: | 
					
						
							|  |  |  |         print '%s module %s already at location %d' %(op, module, pos) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addon_config[op].remove(module) | 
					
						
							|  |  |  |     addon_config[op].insert(pos, module) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def print_mlist(mlist, indent): | 
					
						
							|  |  |  |     for idx, val in enumerate(mlist): | 
					
						
							|  |  |  |         print '%s%d. %s' %(indent, idx, val) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def process_show_cmd(args): | 
					
						
							|  |  |  |     indent = '   ' | 
					
						
							|  |  |  |     op = args.operation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if args.man: | 
					
						
							|  |  |  |         show_man_rst() | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if op: | 
					
						
							|  |  |  |         mlist = addon_config[op] | 
					
						
							|  |  |  |         print '%s:' %op | 
					
						
							|  |  |  |         print_mlist(mlist, indent) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         for op, mlist in addon_config.items(): | 
					
						
							|  |  |  |             print '%s:' %op | 
					
						
							|  |  |  |             print_mlist(mlist, indent) | 
					
						
							|  |  |  |             print '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | cmdhandlers = {'add' : process_add_cmd, | 
					
						
							|  |  |  |                'del' : process_del_cmd, | 
					
						
							|  |  |  |                'move' : process_move_cmd, | 
					
						
							|  |  |  |                'show' : process_show_cmd} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def update_subparser_add(subparser): | 
					
						
							|  |  |  |     subparser.add_argument('module', metavar='MODULE', help='module name') | 
					
						
							|  |  |  |     subparser.add_argument('operation', metavar='OPERATION', | 
					
						
							|  |  |  |                            choices=['pre-up', 'up', 'post-up', | 
					
						
							|  |  |  |                                     'pre-down', 'down', 'post-down'], | 
					
						
							|  |  |  |                                     help='operations', nargs='?') | 
					
						
							|  |  |  |     subparser.add_argument('position', metavar='POSITION', nargs='?', | 
					
						
							|  |  |  |                            help='position') | 
					
						
							|  |  |  |     subparser.set_defaults(func=process_add_cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def update_subparser_del(subparser): | 
					
						
							|  |  |  |     subparser.add_argument('module', metavar='MODULE', help='module name') | 
					
						
							|  |  |  |     subparser.add_argument('operation', metavar='OPERATION', | 
					
						
							|  |  |  |                            choices=['pre-up', 'up', 'post-up', | 
					
						
							|  |  |  |                                     'pre-down', 'down', 'post-down'], | 
					
						
							|  |  |  |                                     help='operations', nargs='?') | 
					
						
							|  |  |  |     subparser.add_argument('position', metavar='POSITION', nargs='?', | 
					
						
							|  |  |  |                            help='position') | 
					
						
							|  |  |  |     subparser.set_defaults(func=process_del_cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def update_subparser_move(subparser): | 
					
						
							|  |  |  |     subparser.add_argument('module', metavar='MODULE', help='module name') | 
					
						
							|  |  |  |     subparser.add_argument('operation', metavar='OPERATION', | 
					
						
							|  |  |  |                            choices=['pre-up', 'up', 'post-up', | 
					
						
							|  |  |  |                                     'pre-down', 'down', 'post-down'], | 
					
						
							|  |  |  |                                     help='operations') | 
					
						
							|  |  |  |     subparser.add_argument('position', metavar='POSITION', | 
					
						
							|  |  |  |                            help='position') | 
					
						
							|  |  |  |     subparser.set_defaults(func=process_move_cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def update_subparser_show(subparser): | 
					
						
							|  |  |  |     subparser.add_argument('--man', action='store_true', | 
					
						
							|  |  |  |                            help=argparse.SUPPRESS) | 
					
						
							|  |  |  |     subparser.add_argument('operation', metavar='OPERATION', | 
					
						
							|  |  |  |                            choices=addon_config.keys(), | 
					
						
							|  |  |  |                            help='operations %s' %str(addon_config.keys()), | 
					
						
							|  |  |  |                            nargs='?') | 
					
						
							|  |  |  |     subparser.set_defaults(func=process_show_cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def update_argparser(argparser): | 
					
						
							|  |  |  |     subparsers = argparser.add_subparsers(help='sub-command help') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parser_add = subparsers.add_parser('add') | 
					
						
							|  |  |  |     update_subparser_add(parser_add) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parser_del = subparsers.add_parser('del', help='del help') | 
					
						
							|  |  |  |     update_subparser_del(parser_del) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parser_move = subparsers.add_parser('move', help='move help') | 
					
						
							|  |  |  |     update_subparser_move(parser_move) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parser_show = subparsers.add_parser('show', help='show help') | 
					
						
							|  |  |  |     update_subparser_show(parser_show) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def parse_args(argsv): | 
					
						
							|  |  |  |     descr = 'ifupdown addon modules management command.\n \ | 
					
						
							|  |  |  |             This command helps add/del/display/reorder modules \n \ | 
					
						
							|  |  |  |             in all ifupdown module categories' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     argparser = argparse.ArgumentParser(description=descr) | 
					
						
							|  |  |  |     update_argparser(argparser) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     args = argparser.parse_args(argsv) | 
					
						
							|  |  |  |     return args | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(argv): | 
					
						
							|  |  |  |     """ main function """ | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         # Command line arg parser | 
					
						
							|  |  |  |         args = parse_args(argv[1:]) | 
					
						
							|  |  |  |         read_modules_config() | 
					
						
							|  |  |  |         args.func(args) | 
					
						
							|  |  |  |         write_modules_config() | 
					
						
							|  |  |  |     except Exception, e: | 
					
						
							|  |  |  |         print 'error processing command (%s)' %str(e) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     if not os.geteuid() == 0: | 
					
						
							|  |  |  |         print 'Error: Must be root to run this command' | 
					
						
							|  |  |  |         exit(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     main(sys.argv) |