diff options
| author | Paul C. Buetow <paul@buetow.org> | 2014-04-14 17:38:28 +0200 |
|---|---|---|
| committer | Paul C. Buetow <paul@buetow.org> | 2014-04-14 17:38:28 +0200 |
| commit | c09c4cb9723b298d84086aaf1493dbb1bea444db (patch) | |
| tree | 0cc1918ab3ecfff3849d31faba778686f28c717f /src | |
| parent | fe50297eb38dccbc0437751bf718df5f93cfcc4c (diff) | |
some enhancements
Diffstat (limited to 'src')
| -rwxr-xr-x | src/fapi.py | 289 |
1 files changed, 188 insertions, 101 deletions
diff --git a/src/fapi.py b/src/fapi.py index c33da9d..9f61a18 100755 --- a/src/fapi.py +++ b/src/fapi.py @@ -9,6 +9,7 @@ import getpass import pprint import socket import sys +import re from os.path import expanduser from inspect import isfunction @@ -16,24 +17,59 @@ from inspect import isfunction import ConfigParser __program__ = 'fapi' -__version__ = 'VERSION_DEVEL' # Replaced by a Makefile target +__version__ = 'VERSION_DEVEL' # Replaced by a Makefile tsubet __prompt__ = '>>>' # Default prompt + +def print_synopsis(): + ''' Prints the full Synopsis string ''' + + print "\n".join([ + 'This is %s version %s' % (__program__, __version__), + '', + 'Synopsis:', + ' fapi monitor', + ' fapi monitor MONITORNAME get desc|state', + ' fapi node', + ' fapi node NODENAME create|delete', + ' fapi node NODENAME get detail|status', + ' fapi pool', + ' fapi pool POOLNAME add member MEMBERNAME', + ' fapi pool POOLNAME add monitor MONITORNAME', + ' fapi pool POOLNAME create [LIST,OF,POOL,MEMBERS]', + ' fapi pool POOLNAME delete', + ' fapi pool POOLNAME del member MEMBERNAME', + ' fapi pool POOLNAME del monitors', + ' fapi pool POOLNAME get detail|lbmethod|members|monitor|status', + ' fapi pool POOLNAME set lbmethod LBMETHOD', + ' fapi vserver', + ' fapi vserver VSERVERNAME create [protocol] [profile] [poolname] [mask]', + ' fapi vserver VSERVERNAME delete', + ' fapi vserver VSERVERNAME get brief|detail|status', + ' fapi vserver VSERVERNAME set nat|pat disabled|enabled', + ' fapi vserver VSERVERNAME set pool POOLNAME', + ' fapi vserver VSERVERNAME set snat none', + ]) + + + class Fapi(object): ''' The main F5 API Tool Object ''' def __init__(self, args): ''' Initialize the config file, username and password ''' + self._args = args self._config = ConfigParser.ConfigParser() self._config.read(args.C) - self._args = args + self._partition = self._config.get('fapi', 'partition') def __login(self): ''' Logs into the F5 BigIP SOAP API and changes the partition''' c = self._config + a = self._args if c.has_option('fapi', 'username'): username = c.get('fapi', 'username') @@ -45,7 +81,6 @@ class Fapi(object): prompt = 'Enter API password for user %s: ' % username password = getpass.getpass(prompt) self.info('Login to BigIP API with user %s' % username) - self._partition = c.get('fapi', 'partition') # Try a comma separated lists of F5 boxes, use the first one err = None @@ -71,7 +106,7 @@ class Fapi(object): def info(self, message): ''' Prints an informational message to stderr ''' - print >> sys.stderr, '%s %s' % (__prompt__, message) + if self._args.v: print >> sys.stderr, '%s %s' % (__prompt__, message) def out(self, result): @@ -109,8 +144,8 @@ class Fapi(object): if not a.name: return lambda: f5().get_list() - if a.arg == 'get': - if a.arg2 == 'detail': + if a.sub == 'get': + if a.sub2 == 'detail': def detail(f5): d = {} d['connection_limit'] = f5().get_connection_limit([a.name]) @@ -126,10 +161,10 @@ class Fapi(object): d['session_status'] = f5().get_session_status([a.name]) return d return lambda: detail(f5) - if a.arg2 == 'status': + if a.sub2 == 'status': return lambda: f5().get_monitor_status([a.name]) - elif a.arg == 'create': + elif a.sub == 'create': try: data = socket.gethostbyname_ex(a.name) except Exception, e: @@ -138,7 +173,7 @@ class Fapi(object): fqdn, ip, _ = self.lookup(a.name) return lambda: f5().create([fqdn],[ip],[0]) - elif a.arg == 'delete': + elif a.sub == 'delete': return lambda: f5().delete_node_address([a.name]) @@ -150,11 +185,11 @@ class Fapi(object): if not a.name: return lambda: f5().get_template_list() - if a.arg == 'get': - monitorname = a.arg3 - if a.arg2 == 'desc': + if a.sub == 'get': + monitorname = a.sub3 + if a.sub2 == 'desc': return lambda: f5().get_description([monitorname]) - if a.arg2 == 'state': + if a.sub2 == 'state': return lambda: f5().get_template_state([monitorname]) @@ -166,8 +201,8 @@ class Fapi(object): if not a.name: return lambda: f5().get_list() - if a.arg == 'get': - if a.arg2 == 'detail': + if a.sub == 'get': + if a.sub2 == 'detail': def detail(f5): d = {} d['allow_nat_state'] = f5().get_allow_nat_state([a.name]) @@ -179,33 +214,40 @@ class Fapi(object): d['profile'] = f5().get_profile([a.name]) return d return lambda: detail(f5) - elif a.arg2 == 'monitor': + elif a.sub2 == 'lbmethod': + return lambda: f5().get_lb_method([a.name]) + elif a.sub2 == 'members': + return lambda: f5().get_member_v2([a.name]) + elif a.sub2 == 'monitor': return lambda: f5().get_monitor_instance([a.name]) - elif a.arg2 == 'status': + elif a.sub2 == 'status': return lambda: f5().get_object_status([a.name]) - elif a.arg2 == 'members': - return lambda: f5().get_member_v2([a.name]) - elif a.arg == 'create': + elif a.sub == 'set': + if a.sub2 == 'lbmethod': + lbmethod = a.sub3 + return lambda: f5().set_lb_method([a.name], [lbmethod]) + + elif a.sub == 'create': poolmembers = [] method = a.m - if a.arg3: - for x in a.arg3.split(','): + if a.sub3: + for x in a.sub3.split(','): fqdn, ip, port = self.lookup(x) pm = { 'address' : fqdn, 'port' : port } poolmembers.append(pm) return lambda: f5().create_v2([a.name],[method],[poolmembers]) - elif a.arg == 'delete': + elif a.sub == 'delete': return lambda: f5().delete_pool([a.name]) - elif a.arg == 'add': - if a.arg2 == 'member': - fqdn, _, port = self.lookup(a.arg3) + elif a.sub == 'add': + if a.sub2 == 'member': + fqdn, _, port = self.lookup(a.sub3) member = [{ 'address' : fqdn, 'port' : port }] return lambda: f5().add_member_v2([a.name], [member]) - elif a.arg2 == 'monitor': - monitorname = a.arg3 + elif a.sub2 == 'monitor': + monitorname = a.sub3 rule = { 'type': 'MONITOR_RULE_TYPE_SINGLE', 'quorum': long(0), @@ -214,12 +256,12 @@ class Fapi(object): association = { 'pool_name': a.name, 'monitor_rule': rule } return lambda: f5().set_monitor_association([association]) - elif a.arg == 'del': - if a.arg2 == 'member': - fqdn, _, port = self.lookup(a.arg3) + elif a.sub == 'del': + if a.sub2 == 'member': + fqdn, _, port = self.lookup(a.sub3) member = [{ 'address' : fqdn, 'port' : port }] return lambda: f5().remove_member_v2([a.name], [member]) - elif a.arg2 == 'monitors': + elif a.sub2 == 'monitors': # Removes all monitor associations, not just one return lambda: f5().remove_monitor_association([a.name]) @@ -232,71 +274,82 @@ class Fapi(object): if not a.name: return lambda: f5().get_list() - if a.arg == 'get': - if a.arg2 == 'detail': + # Check for Pattern like /partition/foo-bar.example.com_443 + m = re.match('^(.*)_(\d+)$', a.name) + if m: + fqdn = m.group(1) + port = m.group(2) + _, ip, _ = self.lookup(fqdn) + else: + fqdn, ip, port = self.lookup(a.name) + + name = fqdn + '_' + port + + if a.sub == 'get': + if a.sub2 == 'detail': def detail(f5): d = {} - d['actual_hardware_acceleration'] = f5().get_actual_hardware_acceleration([a.name]) - d['auto_lasthop'] = f5().get_auto_lasthop([a.name]) - d['bw_controller_policy'] = f5().get_bw_controller_policy([a.name]) - d['clone_pool'] = f5().get_clone_pool([a.name]) - d['connection_limit'] = f5().get_connection_limit([a.name]) - d['default_pool_name'] = f5().get_default_pool_name([a.name]) - d['description'] = f5().get_description([a.name]) - d['destination'] = f5().get_destination_v2([a.name]) - d['enabled_state'] = f5().get_enabled_state([a.name]) - d['fallback_persistence_profile'] = f5().get_fallback_persistence_profile([a.name]) - d['gtm_score'] = f5().get_gtm_score([a.name]) - d['last_hop_pool'] = f5().get_last_hop_pool([a.name]) - d['object_status'] = f5().get_object_status([a.name]) - d['persistence_profile'] = f5().get_persistence_profile([a.name]) - d['profile'] = f5().get_profile([a.name]) - d['protocol'] = f5().get_protocol([a.name]) - d['rule'] = f5().get_rule([a.name]) - d['snat_pool'] = f5().get_snat_pool([a.name]) - d['snat_type'] = f5().get_snat_type([a.name]) - d['source_address'] = f5().get_source_address([a.name]) - d['source_address_translation_lsn_pool'] = f5().get_source_address_translation_lsn_pool([a.name]) - d['source_address_translation_snat_pool'] = f5().get_source_address_translation_snat_pool([a.name]) - d['source_address_translation_type'] = f5().get_source_address_translation_type([a.name]) - d['source_port_behavior'] = f5().get_source_port_behavior([a.name]) - d['translate_address_state'] = f5().get_translate_address_state([a.name]) - d['translate_port_state'] = f5().get_translate_port_state([a.name]) - d['type'] = f5().get_type([a.name]) - d['vlan'] = f5().get_vlan([a.name]) + d['actual_hardware_acceleration'] = f5().get_actual_hardware_acceleration([name]) + d['auto_lasthop'] = f5().get_auto_lasthop([name]) + d['bw_controller_policy'] = f5().get_bw_controller_policy([name]) + d['clone_pool'] = f5().get_clone_pool([name]) + d['connection_limit'] = f5().get_connection_limit([name]) + d['default_pool_name'] = f5().get_default_pool_name([name]) + d['description'] = f5().get_description([name]) + d['destination'] = f5().get_destination_v2([name]) + d['enabled_state'] = f5().get_enabled_state([name]) + d['fallback_persistence_profile'] = f5().get_fallback_persistence_profile([name]) + d['gtm_score'] = f5().get_gtm_score([name]) + d['last_hop_pool'] = f5().get_last_hop_pool([name]) + d['object_status'] = f5().get_object_status([name]) + d['persistence_profile'] = f5().get_persistence_profile([name]) + d['profile'] = f5().get_profile([name]) + d['protocol'] = f5().get_protocol([name]) + d['rule'] = f5().get_rule([name]) + d['snat_pool'] = f5().get_snat_pool([name]) + d['snat_type'] = f5().get_snat_type([name]) + d['source_address'] = f5().get_source_address([name]) + d['source_address_translation_lsn_pool'] = f5().get_source_address_translation_lsn_pool([name]) + d['source_address_translation_snat_pool'] = f5().get_source_address_translation_snat_pool([name]) + d['source_address_translation_type'] = f5().get_source_address_translation_type([name]) + d['source_port_behavior'] = f5().get_source_port_behavior([name]) + d['translate_address_state'] = f5().get_translate_address_state([name]) + d['translate_port_state'] = f5().get_translate_port_state([name]) + d['type'] = f5().get_type([name]) + d['vlan'] = f5().get_vlan([name]) return d return lambda: detail(f5) - elif a.arg2 == 'brief': + elif a.sub2 == 'brief': def brief(f5): d = {} - d['actual_hardware_acceleration'] = f5().get_actual_hardware_acceleration([a.name]) - d['default_pool_name'] = f5().get_default_pool_name([a.name]) - d['destination'] = f5().get_destination_v2([a.name]) - d['enabled_state'] = f5().get_enabled_state([a.name]) - d['object_status'] = f5().get_object_status([a.name]) - d['profile'] = f5().get_profile([a.name]) - d['protocol'] = f5().get_protocol([a.name]) - d['translate_address_state'] = f5().get_translate_address_state([a.name]) - d['translate_port_state'] = f5().get_translate_port_state([a.name]) - d['type'] = f5().get_type([a.name]) + d['actual_hardware_acceleration'] = f5().get_actual_hardware_acceleration([name]) + d['default_pool_name'] = f5().get_default_pool_name([name]) + d['destination'] = f5().get_destination_v2([name]) + d['enabled_state'] = f5().get_enabled_state([name]) + d['object_status'] = f5().get_object_status([name]) + d['persistence_profile'] = f5().get_persistence_profile([name]) + d['profile'] = f5().get_profile([name]) + d['protocol'] = f5().get_protocol([name]) + d['translate_address_state'] = f5().get_translate_address_state([name]) + d['translate_port_state'] = f5().get_translate_port_state([name]) + d['type'] = f5().get_type([name]) return d return lambda: brief(f5) - elif a.arg2 == 'status': - return lambda: f5().get_object_status([a.name]) + elif a.sub2 == 'status': + return lambda: f5().get_object_status([name]) - elif a.arg == 'create': - fqdn, ip, port = self.lookup(a.name) - protocol = a.arg2 if a.arg2 else 'PROTOCOL_TCP' - netmask = a.arg3 if a.arg3 else '255.255.255.255' - if a.arg4: - profile = a.arg4 + elif a.sub == 'create': + protocol = a.sub2 if a.sub2 else 'PROTOCOL_TCP' + if a.sub3: + profile = a.sub3 elif protocol == 'PROTOCOL_UDP': profile = 'udp' else: profile = 'tcp' - poolname = a.arg5 + poolname = a.sub4 + netmask = a.sub5 if a.sub5 else '255.255.255.255' vserver = { - 'name': a.name, + 'name': name, 'address': ip, 'port': port, 'protocol': protocol, @@ -309,15 +362,35 @@ class Fapi(object): } self.info("vserver:%s netmask:%s resource:%s, profile:%s" % (vserver, netmask, resource, profile)) - return lambda: f5().create([vserver], [netmask], [resource], [[profile]]) - - elif a.arg == 'delete': - return lambda: f5().delete_virtual_server([a.name]) + def vserver_create(): + f5().create([vserver], [netmask], [resource], [[profile]]) + # Auto disable NAT and PAT if nPath + if profile['profile_name'] == 'nPath': + f5().set_translate_address_state([name], ['STATE_DISABLED']) + f5().set_translate_port_state([name], ['STATE_DISABLED']) + return lambda: vserver_create() + + elif a.sub == 'delete': + return lambda: f5().delete_virtual_server([name]) + + elif a.sub == 'set': + if a.sub2 == 'pool': + poolname = a.sub3 + return lambda: f5().set_default_pool_name([name], [poolname]) + elif a.sub2 == 'nat': + if a.sub3 == 'disabled': + return lambda: f5().set_translate_address_state([name], ['STATE_DISABLED']) + elif a.sub3 == 'enabled': + return lambda: f5().set_translate_address_state([name], ['STATE_ENABLED']) + elif a.sub2 == 'pat': + if a.sub3 == 'disabled': + return lambda: f5().set_translate_port_state([name], ['STATE_DISABLED']) + elif a.sub3 == 'enabled': + return lambda: f5().set_translate_port_state([name], ['STATE_ENABLED']) + elif a.sub2 == 'snat': + if a.sub3 == 'none': + return lambda: f5().set_source_address_translation_none([name]) - elif a.arg == 'set': - if a.arg2 == 'pool': - poolname = a.arg3 - return lambda: f5().set_default_pool_name([a.name], [poolname]) def run(self): @@ -329,6 +402,12 @@ class Fapi(object): a = self._args lazy = None + if a.name: + # Remove the /partition/ prefix, setting default partition after + # login instead + a.name = re.sub(self._partition, '', a.name) + a.name = re.sub('^/+', '', a.name) + if a.what == 'node': lazy = self.__do_node(lambda: self._f5.LocalLB.NodeAddressV2) elif a.what == 'monitor': @@ -343,32 +422,40 @@ class Fapi(object): self.__login() self.out(lazy()) else: + print_synopsis() sys.exit(1) + if __name__ == '__main__': ''' The main function, here we will have Popcorn for free! ''' - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser(add_help=False) + parser.add_argument('-h', action='store_true', help='Help') parser.add_argument('-v', action='store_true', help='Verbose') parser.add_argument('-V', action='store_true', help='Print version') - parser.add_argument('-m', action='store', help='The lb method', - default='LB_METHOD_RATIO_LEAST_CONNECTION_MEMBER') + parser.add_argument('-m', action='store', help='The default lbmethod', + default='LB_METHOD_ROUND_ROBIN') parser.add_argument('-C', action='store', help='Config file', default=expanduser('~') + '/.fapi.conf') - parser.add_argument('what', nargs='?', help='What') + parser.add_argument('what', nargs='?', help='node|pool|monitor|vserver|...') parser.add_argument('name', nargs='?', help='The object name to operate on') - parser.add_argument('arg', nargs='?', help='The first argument') - parser.add_argument('arg2', nargs='?', help='The second argument') - parser.add_argument('arg3', nargs='?', help='The third argument') - parser.add_argument('arg4', nargs='?', help='The fourth argument') - parser.add_argument('arg5', nargs='?', help='The fith argument') + parser.add_argument('sub', nargs='?', help='First sub command') + parser.add_argument('sub2', nargs='?', help='Second sub command') + parser.add_argument('sub3', nargs='?', help='Third sub command') + parser.add_argument('sub4', nargs='?', help='Fourth sub command') + parser.add_argument('sub5', nargs='?', help='Fith sub command') args = parser.parse_args() + if args.h: + parser.print_help() + print '' + print_synopsis() + sys.exit(0) + if args.V: - print 'This is %s version %s' % (__program__, __version__) sys.exit(0) fapi = Fapi(args) |
