def get_statistics(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '/stats' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) return_stats = {} if response.status_code < 400: return_obj = json.loads(response.text) if 'entries' in return_obj: for stat in return_obj['entries']: name = stat if 'value' in return_obj['entries'][name]: value = return_obj['entries'][name]['value'] if 'description' in return_obj['entries'][name]: value = return_obj['entries'][name]['description'] (st, val) = self._get_icontrol_stat(name, value) if st: return_stats[st] = val elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return return_stats return None
def member_exists(self, name=None, ip_address=None, port=None, folder='Common'): folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '/members/' request_url += '~' + folder + '~' if ':' in ip_address: request_url += urllib.quote(ip_address) + '.' + str(port) else: request_url += urllib.quote(ip_address) + ':' + str(port) response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if 'address' in response_obj: return True else: return False elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return False
def get_service_down_action(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '?$select=serviceDownAction' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if not 'serviceDownAction' in response_obj: return 'NONE' else: if response_obj['serviceDownAction'] == 'drop': return 'DROP' if response_obj['serviceDownAction'] == 'reset': return 'RESET' if response_obj['serviceDownAction'] == 'reselect': return 'RESELECT' elif response.status_code == 404: Log.error( 'pool', 'tied to get AOSD for non-existant pool %s' % '/' + folder + '/' + name) raise exceptions.PoolQueryException(response.text) return None
def get_members_monitor_status(self, name=None, folder='Common', config_mode='object'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' if config_mode == 'iapp': request_url += '~' + folder + '~' + name + \ '.app~' + name else: request_url += '~' + folder + '~' + name request_url += '/members?$select=name,state' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) members = [] if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for member in return_obj['items']: (addr, port) = split_addr_port(member['name']) member_state = 'MONITOR_STATUS_' + \ member['state'].upper() members.append({ 'addr': addr, 'port': port, 'state': member_state }) else: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return members return None
def get_members_monitor_status(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '/members?$select=name,state' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) members = [] if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for member in return_obj['items']: name_parts = member['name'].split(":") member_state = 'MONITOR_STATUS_' + \ member['state'].upper() members.append( { 'addr': strip_domain_address(name_parts[0]), 'port': name_parts[1], 'state': member_state } ) else: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return members return None
def remove_monitor(self, name=None, monitor_name=None, folder='Common'): if not (name and monitor_name): return False folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '?$select=monitor' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if 'monitor' in response_obj: w_split = response_obj['monitor'].split() existing_monitors = [] for w in w_split: if w.startswith('/'): existing_monitors.append(w) fp_monitor = '/' + folder + '/' + monitor_name monitor_string = '' if fp_monitor in existing_monitors: existing_monitors.remove(fp_monitor) new_monitor_count = len(existing_monitors) if new_monitor_count > 0: if response_obj['monitor'].startswith('min'): min_count = w_split[1] if min_count > new_monitor_count: min_count = new_monitor_count monitor_string = 'min ' + min_count + ' of { ' for monitor in existing_monitors: monitor_string += monitor + ' ' monitor_string += '}' else: for i in range(new_monitor_count): if (i + 1) < new_monitor_count: monitor_string += \ existing_monitors[i] + ' and ' else: monitor_string += \ existing_monitors[i] + ' ' request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name payload = dict() payload['monitor'] = monitor_string response = self.bigip.icr_session.put( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True else: Log.error('pool', response.text) raise exceptions.PoolUpdateException(response.text) else: return True elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return False
def purge_orhpaned_pools(self, known_pools, delete_virtual_server=True): request_url = self.bigip.icr_url + '/ltm/pool' request_url += '?$select=name,partition' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) existing_pools = {} if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for pool in return_obj['items']: existing_pools[pool['name']] = pool['partition'] elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) Log.debug('pool', 'purging pools - existing : %s, known : %s' % (existing_pools.keys(), known_pools)) # remove all pools which are not managed # with this object prefix for pool in existing_pools: if not pool.startswith(self.OBJ_PREFIX): del(existing_pools[pool]) for pool in known_pools: decorated_pool = self.OBJ_PREFIX + pool if decorated_pool in existing_pools: del(existing_pools[decorated_pool]) # anything left should be purged for pool in existing_pools: vs_name = \ self.bigip.virtual_server.get_virtual_servers_by_pool_name( pool_name=pool, folder=existing_pools[pool]) if vs_name: try: self.bigip.virtual_server.delete(name=vs_name, folder=existing_pools[pool]) self.bigip.virtual_server.delete_persist_profile_like( match=vs_name, folder=existing_pools[pool]) self.bigip.rule.delete_like(match=vs_name, folder=existing_pools[pool]) self.bigip.virtual_server.delete_profile_like( match=vs_name, folder=existing_pools[pool]) except Exception as e: Log.error('purge_orphaned_pools', e.message) try: self.delete(name=pool, folder=existing_pools[pool]) except Exception as e: Log.error('purge_orphaned_pools', e.message)
def get_all_node_count(self): request_url = self.bigip.icr_url + '/ltm/node' request_url += '?$top=1&$select=totalItems' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if 'totalItems' in response_obj: return int(response_obj['totalItems']) elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return 0
def exists(self, name=None, folder='Common'): folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '?$select=name' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return False
def get_node_addresses(self, folder='Common'): folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/node' request_url += '?$select=address' request_url += '&$filter=partition eq ' + folder response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) node_addresses = [] if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for node in return_obj['items']: node_addresses.append(node['address'].split('%')[0]) elif response.status_code != 404: Log.error('node', response.text) raise exceptions.PoolQueryException(response.text) return node_addresses
def get_pools(self, folder='Common'): folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool' request_url += '?$select=name' request_url += '&$filter=partition eq ' + folder response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) pool_names = [] if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for pool in return_obj['items']: pool_names.append(strip_folder_and_prefix(pool['name'])) elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return pool_names
def get_lb_method(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '?$select=loadBalancingMode' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if not 'loadBalancingMode' in response_obj: return 'round-robin' else: if response_obj['loadBalancingMode'] == \ 'least-connections-member': return 'LEAST_CONNECTIONS' if response_obj['loadBalancingMode'] == \ 'ratio-least-connections-member': return 'RATIO_LEAST_CONNECTIONS' if response_obj['loadBalancingMode'] == \ 'least-connections-node': return 'SOURCE_IP' if response_obj['loadBalancingMode'] == \ 'observed-member': return 'OBSERVED_MEMBER' if response_obj['loadBalancingMode'] == \ 'predictive-member': return 'PREDICTIVE_MEMBER' if response_obj['loadBalancingMode'] == \ 'ratio-member': return 'RATIO' if response_obj['loadBalancingMode'] == \ 'round-robin': return 'ROUND_ROBIN' elif response.status_code == 404: Log.error( 'pool', 'tied to get lb_method for non-existant pool %s' % '/' + folder + '/' + name) else: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return None
def delete_all(self, folder='Common'): folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '?$select=name,selfLink' request_filter = 'partition eq ' + folder request_url += '&$filter=' + request_filter response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if 'items' in response_obj: for item in response_obj['items']: if item['name'].startswith(self.OBJ_PREFIX): if not self.delete(item['name'], folder): return False return True elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return False
def get_members(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '/members?$select=name' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) members = [] if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for member in return_obj['items']: (addr, port) = split_addr_port(member['name']) members.append({'addr': addr, 'port': int(port)}) elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return members return None
def get_monitors(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '?$select=monitor' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) monitors = [] if 'monitor' in response_obj: w_split = response_obj['monitor'].split() for w in w_split: if w.startswith('/'): monitors.append(strip_folder_and_prefix(w)) return monitors elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return []
def all_client_profile_names(self, name=None, folder='Common'): folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/profile/client-ssl/' request_url += '?$select=name,partition' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) profile_names = [] if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for profile in return_obj['items']: print("%s" % profile) profile_name = '/' + \ profile['partition'] + \ '/' + \ profile['name'] profile_names.append(profile_name) elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return profile_names
def get_description(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '?$select=description' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if not 'description' in response_obj: return None else: return response_obj['description'] elif response.status_code == 404: Log.error('pool', 'tied to get description for non-existant pool %s' % '/' + folder + '/' + name) else: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return None
def get_statistics(self, name=None, folder='Common', config_mode='object'): if not name: return None folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' if config_mode == 'iapp': request_url += '~' + folder + '~' + name + '.app~' + name else: request_url += '~' + folder + '~' + name request_url += '/stats' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) return_stats = {} if response.status_code < 400: return_obj = json.loads(response.text) if 'entries' in return_obj: stats = return_obj['entries'] for stat in stats: if 'nestedStats' in stats[stat]: stats = stats[stat]['nestedStats']['entries'] break for stat in stats: name = stat value = None if 'value' in stats[name]: value = stats[name]['value'] if 'description' in stats[name]: value = stats[name]['description'] if value is None: Log.error('poolstats', 'bad stats:' + response.text) continue (st, val) = self._get_icontrol_stat(name, value) if st: return_stats[st] = val elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return return_stats
def delete(self, name=None, folder='Common'): if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name node_addresses = [] # get a list of node addresses before we delete response = self.bigip.icr_session.get(request_url + '/members', timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for member in return_obj['items']: node_addresses.append(member['address']) else: Log.error('members', response.text) raise exceptions.PoolQueryException(response.text) # delete the pool response = self.bigip.icr_session.delete(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400 or response.status_code == 404: for node_address in node_addresses: node_url = self.bigip.icr_url + '/ltm/node/' node_url += '~' + folder + '~' + urllib.quote(node_address) node_res = self.bigip.icr_session.delete(node_url, timeout=const.CONNECTION_TIMEOUT) # we only care if this works. Otherwise node is likely # in use by another pool if node_res.status_code < 400: self._del_arp_and_fdb(node_address, folder) elif node_res.status_code == 400 and \ (node_res.text.find('is referenced') > 0): # same node can be in multiple pools pass else: raise exceptions.PoolDeleteException(node_res.text) return True return False
def purge_orphaned_pools(self, known_pools, delete_virtual_server=True): request_url = self.bigip.icr_url + '/ltm/pool' request_url += '?$select=name,partition' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) existing_pools = {} if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for pool in return_obj['items']: existing_pools[pool['name']] = pool['partition'] elif response.status_code != 404: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) Log.debug( 'pool', 'purging pools - existing : %s, known : %s' % (existing_pools.keys(), known_pools)) # we start with all pools and remove the ones that are # completely unrelated to the plugin or are OK to be there. cleanup_list = dict(existing_pools) # remove all pools which are not managed by this plugin for pool in existing_pools: if not pool.startswith(self.OBJ_PREFIX): del cleanup_list[pool] for pool in known_pools: decorated_pool = self.OBJ_PREFIX + pool Log.debug( 'pool', 'excluding %s from %s' % (str(decorated_pool), str(cleanup_list))) if decorated_pool in cleanup_list: del cleanup_list[decorated_pool] # Exclude known iapp pool decorated_pool += '_pool' Log.debug( 'pool', 'excluding %s from %s' % (str(decorated_pool), str(cleanup_list))) if decorated_pool in cleanup_list: del cleanup_list[decorated_pool] # anything left should be purged for pool in cleanup_list: Log.debug( 'purge_orphaned_pools', "Purging pool %s in folder %s" % (pool, cleanup_list[pool])) vs_name = \ self.bigip.virtual_server.get_virtual_servers_by_pool_name( pool_name=pool, folder=cleanup_list[pool]) if vs_name: try: self.bigip.virtual_server.delete(name=vs_name, folder=cleanup_list[pool]) self.bigip.virtual_server.delete_persist_profile_like( match=vs_name, folder=cleanup_list[pool]) self.bigip.rule.delete_like(match=vs_name, folder=cleanup_list[pool]) self.bigip.virtual_server.delete_profile_like( match=vs_name, folder=cleanup_list[pool]) except Exception as e: Log.error('purge_orphaned_pools', e.message) try: Log.debug( 'purge_orphaned_pools', "Deleting pool %s in folder %s" % (pool, cleanup_list[pool])) self.delete(name=pool, folder=cleanup_list[pool]) except Exception as e: Log.error('purge_orphaned_pools', e.message)