From 4ef0eb329c1df888eaf5b4018f9a6e84f70d8163 Mon Sep 17 00:00:00 2001 From: Marek Isalski Date: Sat, 15 Aug 2020 17:31:26 +0100 Subject: [PATCH] can now provision an IP address/subnet --- automonty | 93 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/automonty b/automonty index 9384e9c..c655ee5 100755 --- a/automonty +++ b/automonty @@ -2,12 +2,12 @@ import argparse import librouteros -import progress.bar import ssl import os import yaml import re import dns.resolver, dns.reversename +import ipaddress # comment format: # hostname.example.com [aM flag1 flag2 key1=value1 key2=option3:value3,option4:value4] selector.example.com @@ -94,15 +94,13 @@ def router_in_groups( options, groups ): def connect_routers( config, args ): routers = config.get( 'router', {} ) rval = {} - with progress.bar.PixelBar( 'Connecting', max = len( routers ) ) as bar: - for ( name, options ) in routers.items(): - if ( not args.only_router and not args.only_group ) or ( name in args.only_router ) or router_in_groups( options, args.only_group ): - kwargs = {} - kwargs.update( options.get( 'connection', {} ) ) - if 'host' not in kwargs: - kwargs[ 'host' ] = name - rval[ name ] = connection( **kwargs ) - bar.next() + for ( name, options ) in routers.items(): + if ( not args.only_router and not args.only_group ) or ( name in args.only_router ) or router_in_groups( options, args.only_group ): + kwargs = {} + kwargs.update( options.get( 'connection', {} ) ) + if 'host' not in kwargs: + kwargs[ 'host' ] = name + rval[ name ] = connection( **kwargs ) return rval def monty_check( config, args, routers ): @@ -179,6 +177,69 @@ def monty_fixup( config, args, routers ): print( name, ":", item[ 'interface' ], new_comment ) ipv6_address.update( **{ 'comment': new_comment, '.id': item[ '.id' ] } ) +def monty_provision( config, args, routers ): + reverse = {} + statics = {} + print() + for ( name, api ) in routers.items(): + if args.dry_run: + print( '#' * ( len( name ) + 2 ) ) + print( '#', name ) + print() + vlans = api.path( 'interface', 'vlan' ) + ip_address = api.path( 'ip', 'address' ) + ipv6_address = api.path( 'ipv6', 'address' ) + for vlan in vlans: + if vlan[ 'vlan-id' ] == args.vlan: + rval = {} + if args.static: + rval[ 'static' ] = True + disabled = 'no' + elif name in args.home: + rval[ 'home' ] = True + disabled = 'no' + else: + disabled = 'yes' + comment = make_comment( args.selector, rval, args.hostname ) + if args.dry_run: + if args.ipv4.network.prefixlen == 32: + print( '/ip address add interface="%s" address="%s" network="%s" disabled=%s comment="%s"' % ( vlan[ 'name' ], config[ 'default_ipv4_loopback' ], args.ipv4.network.network_address, disabled, comment ) ) + else: + print( '/ip address add interface="%s" address="%s" disabled=%s comment="%s"' % ( vlan[ 'name' ], args.ipv4, disabled, comment ) ) + if args.ipv6: + if args.static: + print( '/ipv6 address add interface="%s" address="%s" disabled=%s comment="%s" advertise=no' % ( vlan[ 'name' ], args.ipv6, disabled, comment ) ) + else: + print( '/ipv6 address add interface="%s" address="%s" disabled=%s comment="%s" eui-64=yes advertise=yes' % ( vlan[ 'name' ], args.ipv6.network, disabled, comment ) ) + + else: + v4addr = { 'interface': vlan[ 'name' ], + 'disabled': disabled, + 'comment': comment, + } + if args.ipv4.network.prefixlen == 32: + v4addr[ 'address' ] = config[ 'default_ipv4_loopback' ] + v4addr[ 'network' ] = str( args.ipv4.network.network_address ) + else: + v4addr[ 'address' ] = str( args.ipv4 ) + ip_address.add( **v4addr ) + + if args.ipv6: + v6addr = { 'interface': vlan[ 'name' ], + 'disabled': disabled, + 'comment': comment, + } + if args.static: + v6addr[ 'address' ] = str( args.ipv6 ) + else: + v6addr[ 'address' ] = str( args.ipv6.network ) + v6addr[ 'eui-64' ] = 'yes' + v6addr[ 'advertise' ] = 'yes' + ipv6_address.add( **v6addr ) + + if args.dry_run: + print() + def load_configuration(): try: config = open( os.path.expanduser( '~/.automonty.yaml' ), 'r' ) @@ -196,7 +257,7 @@ def main(): parser.add_argument( '--only-router', action = 'append', default = [] ) parser.add_argument( '--only-group', action = 'append', default = [] ) - parser.add_argument( '-n', '--dry-run', action = 'store_true' ) + parser.add_argument( '-n', '--dry-run', action = 'store_true', default = False ) parser_check = subparsers.add_parser( 'check' ) parser_check.add_argument( 'addr', nargs = "*" ) @@ -205,6 +266,16 @@ def main(): parser_fixup = subparsers.add_parser( 'fixup' ) parser_fixup.set_defaults( func = monty_fixup ) + parser_provision = subparsers.add_parser( 'provision' ) + parser_provision.add_argument( '--home', action = 'append', default = [] ) + parser_provision.add_argument( '-s', '--static', action = 'store_true', default = False ) + parser_provision.add_argument( '--selector', type = str, default = None ) + parser_provision.add_argument( 'hostname' ) + parser_provision.add_argument( 'vlan', type = int ) + parser_provision.add_argument( 'ipv4', type = ipaddress.IPv4Interface ) + parser_provision.add_argument( 'ipv6', type = ipaddress.IPv6Interface, nargs = "?" ) + parser_provision.set_defaults( func = monty_provision ) + args = parser.parse_args() routers = connect_routers( config, args ) args.func( config, args, routers )