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 create(self, name=None, mon_type=None, interval=5, timeout=16, send_text=None, recv_text=None, folder="Common"): folder = str(folder).replace("/", "") self.bigip.system.set_rest_folder(folder) mon_type = self._get_monitor_rest_type(mon_type) payload = dict() payload["name"] = name payload["partition"] = folder parent = mon_type.replace("-", "_") payload["defaultsFrom"] = "/Common/" + parent payload["timeout"] = timeout payload["interval"] = interval if send_text: payload["send"] = send_text if recv_text: payload["recv"] = recv_text request_url = self.bigip.icr_url + "/ltm/monitor/" + mon_type response = self.bigip.icr_session.post(request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 409: return True else: Log.error("monitor", response.text) raise exceptions.MonitorCreationException(response.text) return False
def remove_member(self, name=None, ip_address=None, port=None, folder='Common'): if name and ip_address and port: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '/members/' request_url += '~' + folder + '~' request_url += urllib.quote(ip_address) + ':' + str(port) response = self.bigip.icr_session.delete(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400 or response.status_code == 404: # delete nodes node_req = self.bigip.icr_url + '/ltm/node/' node_req += '~' + folder + '~' + urllib.quote(ip_address) response = self.bigip.icr_session.delete(node_req, timeout=const.CONNECTION_TIMEOUT) if response.status_code == 400 and \ (response.text.find('is referenced') > 0): # Node address is part of multiple pools pass elif response.status_code > 399 and \ (not response.status_code == 404): Log.error('node', response.text) raise exceptions.PoolDeleteException(response.text) else: self._del_arp_and_fdb(ip_address, folder) else: Log.error('pool', response.text) raise exceptions.PoolDeleteException(response.text) return False
def _in_use(self, name=None, folder=None): """ Is tunnel used by selfip? """ if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/net/self?$select=vlan' if folder: request_filter = 'partition eq ' + folder request_url += '&$filter=' + request_filter else: folder = 'Common' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for selfip in return_obj['items']: vlan_name = os.path.basename(selfip['vlan']) if vlan_name == name: return True if vlan_name == \ strip_folder_and_prefix(name): return True elif response.status_code != 404: Log.error('self', response.text) raise exceptions.VXLANQueryException(response.text) return False
def delete_all(self, folder='Common'): """ Delete all ARP entries """ try: self.net_arp.delete_all_static_entries() except Exception as exc: Log.error('ARP', 'delete exception: ' + exc.message) raise exceptions.StaticARPDeleteException(exc.message)
def create_multipoint_tunnel(self, name=None, profile_name=None, self_ip_address=None, vxlanid=0, description=None, folder='Common', route_domain_id=0): """ Create vxlan multipoint tunnel """ if not self.tunnel_exists(name=name, folder=folder): folder = str(folder).replace('/', '') # check partition is okay to create in payload = dict() payload['name'] = name payload['partition'] = folder payload['profile'] = profile_name payload['key'] = vxlanid payload['localAddress'] = self_ip_address payload['remoteAddress'] = '0.0.0.0' if description: payload['description'] = description request_url = self.bigip.icr_url + '/net/tunnels/tunnel/' response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: if not folder == 'Common': self.bigip.route.add_vlan_to_domain_by_id( name=name, folder=folder, route_domain_id=route_domain_id) return True else: Log.error('VXLAN', response.text) raise exceptions.VXLANCreationException(response.text) else: return False
def set_member_ratio(self, name=None, ip_address=None, port=None, ratio=1, folder='Common', no_checks=False): if name and ip_address and port: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '/members/' request_url += '~' + folder + '~' request_url += urllib.quote(ip_address) + ':' + str(port) payload = dict() payload['ratio'] = ratio response = self.bigip.icr_session.put(request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 404: Log.error('pool', 'tried to set ratio on non-existant member %s on pool %s.' % (ip_address + ':' + str(port), '/' + folder + '/' + name)) return False else: Log.error('pool', response.text) raise exceptions.PoolUpdateException(response.text) return False
def delete_all(self, folder='Common'): """ Delete vxlan multipoint tunnels """ folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/net/tunnels/tunnel/' 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): self.delete_all_fdb_entries(item['name'], folder) response = self.bigip.icr_session.delete( self.bigip.icr_link(item['selfLink']), timeout=const.CONNECTION_TIMEOUT) if response.status_code > 400 and \ response.status_code != 404: Log.error('VXLAN', response.text) raise exceptions.VXLANDeleteException( response.text) elif response.status_code != 404: Log.error('VXLAN', response.text) raise exceptions.VXLANQueryException(response.text) return True
def get_metadata(self, name=None): if not name: name = self.get_device_name() request_url = self.bigip.icr_url + '/cm/device/~Common~' request_url += name + '?$select=name,description' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) str_comment = None if response.status_code < 400: response_obj = json.loads(response.text) if response_obj['name'] == name: if 'description' in response_obj: str_comment = response_obj['description'] elif response.status_code != 404: Log.error('device', response.text) raise exceptions.DeviceQueryException(response.text) if str_comment: try: return json.loads(base64.decodestring(str_comment)) except: try: return base64.decodestring(str_comment) except: return str_comment return None
def set_failover_address(self, ip_address=None, folder='/Common'): dev_name = self.get_device_name() dev_ip = self.get_mgmt_addr() request_url = self.bigip.icr_url + '/cm/device/' request_url += '~Common~' + dev_name payload = dict() unicast_addresses = [] if ip_address: unicast_addresses.append({'effectiveIp': dev_ip, 'effectivePort': 1026, 'ip': dev_ip, 'port': 1026}) unicast_addresses.append({'effectiveIp': ip_address, 'effectivePort': 1026, 'ip': ip_address, 'port': 1026}) payload['unicastAddress'] = unicast_addresses 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('device', response.text) raise exceptions.DeviceUpdateException(response.text) return False
def create(self, name=None, mon_type=None, interval=5, timeout=16, send_text=None, recv_text=None, folder='Common'): """ Create monitor """ folder = str(folder).replace('/', '') mon_type = self._get_monitor_rest_type(mon_type) payload = dict() payload['name'] = name payload['partition'] = folder parent = mon_type.replace('-', '_') payload['defaultsFrom'] = '/Common/' + parent payload['timeout'] = timeout payload['interval'] = interval if send_text: payload['send'] = send_text if recv_text: payload['recv'] = recv_text request_url = self.bigip.icr_url + '/ltm/monitor/' + mon_type response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 409: return True else: Log.error('monitor', response.text) raise exceptions.MonitorCreationException(response.text) return False
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 delete_by_subnet(self, subnet=None, mask=None, folder='Common'): """ Delete ARP static entries on subnet """ if subnet: mask_div = subnet.find('/') if mask_div > 0: try: rd_div = subnet.find(':') if rd_div > -1: network = netaddr.IPNetwork( subnet[0:mask_div][0:rd_div] + subnet[mask_div:]) else: network = netaddr.IPNetwork(subnet) except Exception as exc: Log.error('ARP', exc.message) return [] elif not mask: return [] else: try: rd_div = subnet.find(':') if rd_div > -1: network = netaddr.IPNetwork( subnet[0:rd_div] + '/' + mask) else: network = netaddr.IPNetwork(subnet + '/' + mask) except Exception as exc: Log.error('ARP', exc.message) return [] return self._delete_by_network(folder, network)
def get_vlans_in_domain(self, folder="Common"): """ Get VLANs in Domain """ folder = str(folder).replace("/", "") request_url = self.bigip.icr_url + "/net/route-domain?$select=name,partition,vlans" if folder: 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: vlans = [] folder = str(folder).replace("/", "") for route_domain in response_obj["items"]: if route_domain["name"] == folder: if "vlans" in route_domain: for vlan in route_domain["vlans"]: vlans.append(vlan) return vlans return [] else: if response.status_code != 404: Log.error("route-domain", response.text) raise exceptions.RouteQueryException(response.text) return []
def create_domain(self, folder="Common", strict_route_isolation=False, is_aux=False): """ Create route domain. is_aux: whether it is an auxiliary route domain beyond the main route domain for the folder """ folder = str(folder).replace("/", "") if not folder == "Common": payload = dict() payload["partition"] = "/" + folder payload["id"] = self._get_next_domain_id() payload["name"] = folder if is_aux: payload["name"] += "_aux_" + str(payload["id"]) if strict_route_isolation: payload["strict"] = "enabled" else: payload["strict"] = "disabled" payload["parent"] = "/Common/0" request_url = self.bigip.icr_url + "/net/route-domain/" response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT ) if response.status_code < 400: return payload["id"] elif response.status_code == 409: return True else: Log.error("route-domain", response.text) raise exceptions.RouteCreationException(response.text) return False return False
def add_to_pool(self, name=None, member_name=None, folder="Common"): """ Add to SNAT pool """ folder = str(folder).replace("/", "") sa_path = "/" + folder + "/" + member_name request_url = self.bigip.icr_url + "/ltm/snatpool" request_url += "/~" + folder + "~" + name request_url += "?$select=members" response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if "members" in response_obj: if sa_path not in response_obj["members"]: members = response["members"] members.append(sa_path) else: return True else: members = [sa_path] else: Log.error("snatpool", response.text) raise exceptions.SNATQueryException(response.text) payload = dict() payload["members"] = members request_url += "/~" + folder + "~" + name 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("snatpool", response.text) raise exceptions.SNATUpdateException(response.text) return False
def add_member(self, name=None, ip_address=None, port=None, folder='Common', no_checks=False): if name and ip_address and port: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name request_url += '/members' payload = dict() payload['name'] = ip_address + ':' + str(port) payload['partition'] = folder payload['address'] = ip_address response = self.bigip.icr_session.post(request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 404: Log.error('pool', 'tried to add member %s to non-existant pool %s.' % (payload['name'], '/' + folder + '/' + name)) return False elif response.status_code == 409: return True else: Log.error('pool', response.text) raise exceptions.PoolCreationException(response.text) return False
def delete_snatpool(self, name=None, folder="Common"): """ Delete SNAT pool """ if name: folder = str(folder).replace("/", "") request_url = self.bigip.icr_url + "/ltm/snatpool/" 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"] == name: response = self.bigip.icr_session.delete( self.bigip.icr_link(item["selfLink"]), timeout=const.CONNECTION_TIMEOUT ) if response.status_code > 400 and response.status_code != 404: Log.error("snatpool", response.text) raise exceptions.SNATDeleteException(response.text) return True elif response.status_code != 404: Log.error("snatpool", response.text) raise exceptions.SNATQueryException(response.text) return False
def create_multipoint_tunnel(self, name=None, profile_name=None, self_ip_address=None, greid=0, description=None, folder='Common'): """ Create multipoint tunnel """ if not self.tunnel_exists(name=name, folder=folder): folder = str(folder).replace('/', '') payload = dict() payload['name'] = name payload['partition'] = folder payload['profile'] = profile_name payload['key'] = greid payload['localAddress'] = self_ip_address payload['remoteAddress'] = '0.0.0.0' if description: payload['description'] = description request_url = self.bigip.icr_url + '/net/tunnels/tunnel/' Log.info('L2GRE', 'creating tunnel with %s' % json.dumps(payload)) response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: if not folder == 'Common': self.bigip.route.add_vlan_to_domain( name=name, folder=folder) return True else: Log.error('L2GRE', response.text) raise exceptions.L2GRETunnelCreationException(response.text) return False
def get_fdb_entry(self, tunnel_name=None, mac=None, folder='Common'): """ Add fdb entry for a tunnel """ folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/net/fdb/tunnel/' request_url += '~' + folder + '~' + tunnel_name response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if 'records' in response_obj: if not mac: return_fdbs = [] for fdb in response_obj['records']: fdb['endpoint'] = strip_domain_address(fdb['endpoint']) return_fdbs.append(fdb) return return_fdbs else: for record in response_obj['records']: if record['name'] == mac: record['endpoint'] = strip_domain_address( record['endpoint']) return record elif response.status_code != 404: Log.error('L2GRE', response.text) raise exceptions.L2GRETunnelQueryException(response.text) return []
def get_type(self, name=None, folder="Common"): folder = str(folder).replace("/", "") request_url = self.bigip.icr_url + "/ltm/monitor" 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: return_obj = json.loads(response.text) monitor_types = [] if "items" in return_obj: for monitor_type in return_obj["items"]: ref = monitor_type["reference"]["link"] monitor_types.append(ref.replace("https://localhost/mgmt/tm", "").split("?")[0]) for monitor in monitor_types: mon_req = self.bigip.icr_url + monitor mon_req += "?$select=name,defaultsFrom" if folder: mon_req += "&$filter=" + request_filter mon_resp = self.bigip.icr_session.get(mon_req, timeout=const.CONNECTION_TIMEOUT) if mon_resp.status_code < 400: mon_resp_obj = json.loads(mon_resp.text) if "items" in mon_resp_obj: for mon_def in mon_resp_obj["items"]: if mon_def["name"] == name: mon_type = mon_def["defaultsFrom"].replace("/Common/", "") return self._get_monitor_type_from_parent(mon_type) else: Log.error("monitor", mon_resp.text) raise exceptions.MonitorQueryException(mon_resp.text) else: Log.error("monitor", response.text) raise exceptions.MonitorQueryException(response.text) return None
def add_to_pool(self, name=None, member_name=None, folder='Common'): """ Add to SNAT pool """ folder = str(folder).replace('/', '') sa_path = '/' + folder + '/' + member_name request_url = self.bigip.icr_url + '/ltm/snatpool' request_url += '/~' + folder + '~' + name request_url += '?$select=members' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if 'members' in response_obj: if not sa_path in response_obj['members']: members = response['members'] members.append(sa_path) else: return True else: members = [sa_path] else: Log.error('snatpool', response.text) raise exceptions.SNATQueryException(response.text) payload = dict() payload['members'] = members request_url += '/~' + folder + '~' + name 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('snatpool', response.text) raise exceptions.SNATUpdateException(response.text) return False
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 delete_all_snatpools(self, folder='Common'): """ Delete SNAT pools """ folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/snatpool/' 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): response = self.bigip.icr_session.delete( self.bigip.icr_link(item['selfLink']), timeout=const.CONNECTION_TIMEOUT) if response.status_code > 400 and \ response.status_code != 404: Log.error('snatpool', response.text) raise exceptions.SNATDeleteException(response.text) return True elif response.status_code != 404: Log.error('snatpool', response.text) raise exceptions.SNATQueryException(response.text) return False
def get_description(self, name=None, folder='Common'): """ Get vlan description """ if name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + \ '/net/vlan?$select=name,description' if folder: request_filter = 'partition eq ' + folder request_url += '&$filter=' + request_filter else: folder = 'Common' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: for vlan in return_obj['items']: vlan_name = os.path.basename(vlan['name']) if vlan_name == name: if 'description' in vlan: return vlan['description'] if vlan_name == \ strip_folder_and_prefix(name): if 'description' in vlan: return vlan['description'] elif response.status_code != 404: Log.error('VLAN', response.text) raise exceptions.VLANQueryException(response.text) return None
def delete_like(self, match=None, folder='Common'): if match: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/rule/' 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'].find(match) > -1: response = self.bigip.icr_session.delete( self.bigip.icr_link(item['selfLink']), timeout=const.CONNECTION_TIMEOUT) if response.status_code > 400 and \ response.status_code != 404: Log.error('rule', response.text) raise exceptions.RuleDeleteException( response.text) return True elif response.status_code != 404: Log.error('rule', response.text) raise exceptions.RuleQueryException(response.text) return False
def create(self, name=None, ip_address=None, netmask=None, vlan_name=None, floating=False, traffic_group=None, folder='Common'): if not self.exists(name=name, folder=folder): enabled_state = self.net_self.typefactory.create( 'Common.EnabledState').STATE_ENABLED if not traffic_group: traffic_group = const.SHARED_CONFIG_DEFAULT_TRAFFIC_GROUP if floating: traffic_group = \ const.SHARED_CONFIG_DEFAULT_FLOATING_TRAFFIC_GROUP try: self.net_self.create([name], [vlan_name], [ip_address], [netmask], [traffic_group], [enabled_state]) return True except WebFault as wf: if "already exists in partition" in str(wf.message): Log.error('SelfIP', 'tried to create a SelfIP when exists') return False else: raise wf else: return False
def create(self, name=None, vlanid=None, interface=None, folder="Common", description=None): if name: folder = str(folder).replace("/", "") self.bigip.system.set_rest_folder(folder) payload = dict() payload["name"] = name payload["partition"] = folder if vlanid: payload["tag"] = vlanid payload["interfaces"] = [{"name": interface, "tagged": True}] else: payload["tag"] = 0 payload["interfaces"] = [{"name": interface, "untagged": True}] if description: payload["description"] = description request_url = self.bigip.icr_url + "/net/vlan/" response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT ) if response.status_code < 400: if not folder == "Common": self.bigip.route.add_vlan_to_domain(name=name, folder=folder) return True elif response.status_code == 409: return True else: Log.error("VLAN", response.text) raise exceptions.VLANCreationException(response.text) return False
def get_description(self, name=None, folder="Common"): if name: folder = str(folder).replace("/", "") request_url = self.bigip.icr_url + "/net/vlan?$select=name,description" if folder: request_filter = "partition eq " + folder request_url += "&$filter=" + request_filter else: folder = "Common" response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return_obj = json.loads(response.text) if "items" in return_obj: for vlan in return_obj["items"]: vlan_name = os.path.basename(vlan["name"]) if vlan_name == name: if "description" in vlan: return vlan["description"] if vlan_name == strip_folder_and_prefix(name): if "description" in vlan: return vlan["description"] elif response.status_code != 404: Log.error("VLAN", response.text) raise exceptions.VLANQueryException(response.text) return None
def delete_all(self, folder="Common"): request_url = self.bigip.icr_url + "/ltm/monitor" folder = str(folder).replace("/", "") 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: return_obj = json.loads(response.text) monitor_types = [] if "items" in return_obj: for monitor_type in return_obj["items"]: ref = monitor_type["reference"]["link"] monitor_types.append(self.bigip.icr_link(ref).split("?")[0]) for monitor in monitor_types: mon_req = monitor mon_req += "?$select=name,selfLink" if folder: mon_req += "&$filter=" + request_filter mon_resp = self.bigip.icr_session.get(mon_req, timeout=const.CONNECTION_TIMEOUT) if mon_resp.status_code < 400: mon_resp_obj = json.loads(mon_resp.text) if "items" in mon_resp_obj: for mon_def in mon_resp_obj["items"]: if mon_def["name"].startswith(self.OBJ_PREFIX): response = self.bigip.icr_session.delete( self.bigip.icr_link(mon_def["selfLink"]), timeout=const.CONNECTION_TIMEOUT ) if response.status_code > 400 and response.status_code != 404: Log.error("monitor", response.text) raise exceptions.MonitorDeleteException(response.text) return True elif response.status_code != 404: Log.error("monitor", response.text) raise exceptions.MonitorQueryException(response.text) return False
def get_tunnels(self, folder='Common'): """ Get tunnels """ folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/net/tunnels/tunnel' if folder: 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: tunnel_list = [] return_obj = json.loads(response.text) if 'items' in return_obj: for tunnel in return_obj['items']: if tunnel['profile'].find('vxlan') > 0: tunnel_list.append( strip_folder_and_prefix(tunnel['name'])) return tunnel_list else: return None elif response.status_code != 404: Log.error('VXLAN', response.text) exceptions.VXLANQueryException(response.text) return None
def create(self, name=None, ip_address=None, orig_ip_address=None, traffic_group=None, vlan_name=None, folder='Common'): """ Create NAT """ folder = str(folder).replace('/', '') if not self.exists(name=name, folder=folder): payload = dict() payload['name'] = name payload['partition'] = folder payload['originatingAddress'] = orig_ip_address payload['translationAddress'] = ip_address payload['trafficGroup'] = traffic_group payload['vlans'] = [vlan_name] request_url = self.bigip.icr_url + '/ltm/nat' response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 409: return True else: Log.error('NAT', response.text) raise exceptions.NATCreationException(response.text) return False
def set_recv_string(self, name=None, mon_type=None, recv_text=None, folder='Common'): folder = str(folder).replace('/', '') payload = dict() if recv_text: payload['recv'] = recv_text else: payload['recv'] = '' mon_type = self._get_monitor_rest_type(mon_type) request_url = self.bigip.icr_url + '/ltm/monitor/' + mon_type + '/' request_url += '~' + folder + '~' + name 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('monitor', response.text) raise exceptions.MonitorQueryException(response.text) return False
def set_member_ratio(self, name=None, ip_address=None, port=None, ratio=1, folder='Common', no_checks=False): if name and ip_address and port: 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) payload = dict() payload['ratio'] = ratio response = self.bigip.icr_session.patch( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 404: Log.error( 'pool', 'tried to set ratio on non-existant member %s on pool %s.' % (ip_address + ':' + str(port), '/' + folder + '/' + name)) return False else: Log.error('pool', response.text) raise exceptions.PoolUpdateException(response.text) return False
def exists(self, name=None, folder='Common'): folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/net/self/' 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: request_url = self.bigip.icr_url + '/net/self/' request_url += '~' + folder + '~' + strip_folder_and_prefix(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('self', response.text) raise exceptions.SelfIPQueryException(response.text) else: Log.error('self', response.text) raise exceptions.SelfIPQueryException(response.text) return False
def create_multipoint_profile(self, name=None, folder='Common'): """ Create vxlan multipoint tunnel profile """ if not self.profile_exists(name=name, folder=folder): folder = str(folder).replace('/', '') payload = dict() payload['name'] = name payload['partition'] = folder payload['defaultsFrom'] = 'vxlan' payload['floodingType'] = 'multipoint' payload['port'] = const.VXLAN_UDP_PORT request_url = self.bigip.icr_url + '/net/tunnels/vxlan/' response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.staus_code == 409: return True else: Log.error('VXLAN', response.text) raise exceptions.VXLANCreationException(response.text) else: return False
def update_traffic_group(self, name=None, autofailback=False, failbacktimer=60, loadfactor=1, floating=True, ha_order=None): """ Update traffic group """ request_url = self.bigip.icr_url + '/cm/traffic-group/' request_url += '~Common~' + name response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code >= 400: Log.error('traffic-group', response.text) raise exceptions.ClusterUpdateException(response.text) payload = json.loads(response.text) payload['autoFailbackEnabled'] = autofailback payload['autoFailbackTime'] = failbacktimer payload['haLoadFactor'] = loadfactor payload['isFloating'] = floating if ha_order: ha_order_list = [] devices = self.bigip.device.get_all_device_names() for device in ha_order: dev_name = os.path.basename(device) if dev_name in devices: ha_order_list.append('/Common/' + dev_name) payload['haOrder'] = ha_order_list response = self.bigip.icr_session.put( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 409: return True else: Log.error('traffic-group', response.text) raise exceptions.ClusterUpdateException(response.text)
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 remove_from_pool(self, name=None, member_name=None, folder='Common'): """ Remove from SNAT pool """ folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/ltm/snatpool' request_url += '/~' + folder + '~' + name request_url += '?$select=members' response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) sa_to_remove = None for member in response_obj['members']: member_base_name = os.path.basename(member) if member_base_name == member_name: sa_to_remove = member if not sa_to_remove: return True else: members = response_obj['members'] if len(members) == 1: request_url = self.bigip.icr_url + '/ltm/snatpool' request_url += '/~' + folder + '~' + name response = self.bigip.icr_session.delete( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code: return True else: Log.error('snatpool', response.text) raise exceptions.SNATDeleteException(response.text) else: members.remove(sa_to_remove) payload = dict() payload['members'] = members request_url = self.bigip.icr_url request_url += '/ltm/snatpool' request_url += '/~' + folder + '~' + name 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('snatpool', response.text) raise exceptions.SNATUpdateException(response.text) elif response.status_code != 404: Log.error('snatpool', response.text) raise exceptions.SNATQueryException(response.text) return False
def delete_by_vlan_name(self, vlan_name=None, folder='Common'): """ Delete selfip by vlan name """ if vlan_name: folder = str(folder).replace('/', '') request_url = self.bigip.icr_url + '/net/self' request_url += '?$select=vlan,selfLink,floating' if folder: request_filter = 'partition eq ' + folder request_url += '&$filter=' + request_filter else: folder = 'Common' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return_obj = json.loads(response.text) if 'items' in return_obj: float_to_delete = [] nonfloat_to_delete = [] for selfip in return_obj['items']: name = os.path.basename(selfip['vlan']) if vlan_name == name or \ vlan_name == strip_folder_and_prefix(name): if selfip['floating'] == 'enabled': float_to_delete.append( self.bigip.icr_link(selfip['selfLink'])) else: nonfloat_to_delete.append( self.bigip.icr_link(selfip['selfLink'])) for selfip in float_to_delete: del_res = self.bigip.icr_session.delete( selfip, timeout=const.CONNECTION_TIMEOUT) if del_res.status_code > 399 and\ del_res.status_code != 404: Log.error('self', del_res.text) raise exceptions.SelfIPDeleteException( del_res.text) for selfip in nonfloat_to_delete: del_res = self.bigip.icr_session.delete( selfip, timeout=const.CONNECTION_TIMEOUT) if del_res.status_code > 399 and\ del_res.status_code != 404: Log.error('self', del_res.text) raise exceptions.SelfIPDeleteException( del_res.text) return True else: Log.error('selfip', response.text) raise exceptions.SelfIPQueryException(response.text) return False
def delete_tunnel(self, name=None, folder='Common'): """ Delete tunnel """ folder = str(folder).replace('/', '') # delete arp and fdb records for this tunnel first request_url = self.bigip.icr_url + '/net/fdb/tunnel/' request_url += '~' + folder + '~' + name response = self.bigip.icr_session.get(request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if const.FDB_POPULATE_STATIC_ARP: if 'records' in response_obj: for record in response_obj['records']: self.bigip.arp.delete_by_mac( mac_address=record['name'], folder=folder) payload = dict() payload['records'] = [] tunnel_link = self.bigip.icr_link(response_obj['selfLink']) response = self.bigip.icr_session.put( tunnel_link, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) response = self.bigip.icr_session.delete(tunnel_link) if response.status_code > 399: Log.error('fdb', response.text) raise exceptions.L2GRETunnelUpdateException(response.text) elif response.status_code != 404: Log.error('fdb', response.text) raise exceptions.L2GRETunnelQueryException(response.text) request_url = self.bigip.icr_url + '/net/tunnels/tunnel/' request_url += '~' + folder + '~' + name response = self.bigip.icr_session.delete( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 404: return True else: Log.error('L2GRE', response.text) raise exceptions.L2GRETunnelDeleteException(response.text) return False
def add_monitor(self, name=None, monitor_name=None, folder='Common'): if name and monitor_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) 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 not fp_monitor in existing_monitors: if response_obj['monitor'].startswith('min'): min_count = w_split[1] monitor_string = 'min ' + min_count + ' of { ' for monitor in existing_monitors: monitor_string += monitor + ' ' monitor_string += fp_monitor + ' ' monitor_string += '}' else: for monitor in existing_monitors: monitor_string += monitor + ' and ' monitor_string += fp_monitor 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 else: payload = dict() payload['monitor'] = monitor_name request_url = self.bigip.icr_url + '/ltm/pool/' request_url += '~' + folder + '~' + name 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: Log.error('pool', response.text) raise exceptions.PoolQueryException(response.text) return False
def delete_all(self, folder='Common'): try: self.net_arp.delete_all_static_entries() except Exception as e: Log.error('ARP', 'delete exception: ' + e.message) raise exceptions.StaticARPDeleteException(e.message)
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)
def create(self, name=None, ip_address=None, traffic_group=None, snat_pool_name=None, folder='Common', snat_pool_folder=None): """ Create SNAT """ if not traffic_group: traffic_group = const.SHARED_CONFIG_DEFAULT_TRAFFIC_GROUP if name: folder = str(folder).replace('/', '') # create snat address payload = dict() payload['name'] = name payload['partition'] = folder payload['address'] = ip_address payload['trafficGroup'] = traffic_group request_url = self.bigip.icr_url + '/ltm/snat-translation' response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if not (response.status_code < 400 or response.status_code == 409): Log.error('snat-translation', response.text) raise exceptions.SNATCreationException(response.text) if snat_pool_name: if not snat_pool_folder: snat_pool_folder = folder # create snat pool with member sa_path = '/' + folder + '/' + name payload = dict() payload['name'] = snat_pool_name payload['partition'] = snat_pool_folder payload['members'] = [sa_path] request_url = self.bigip.icr_url + '/ltm/snatpool' response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code == 409: # get existing members request_url += '/~' + snat_pool_folder request_url += '~' + snat_pool_name request_url += '?$select=members' response = self.bigip.icr_session.get( request_url, timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: response_obj = json.loads(response.text) if 'members' in response_obj: if sa_path not in response_obj['members']: members = response_obj['members'] members.append(sa_path) else: return True else: members = [sa_path] elif response.status_code != 404: Log.error('snatpool', response.text) raise exceptions.SNATQueryException(response.text) payload = dict() payload['members'] = members request_url = self.bigip.icr_url + '/ltm/snatpool' request_url += '/~' + snat_pool_folder request_url += '~' + snat_pool_name response = self.bigip.icr_session.put( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) elif response.status_code < 400: return True else: Log.error('snatpool', response.text) raise exceptions.SNATCreationException(response.text) return False
def create(self, name=None, ip_address=None, netmask=None, vlan_name=None, floating=False, traffic_group=None, folder='Common', preserve_vlan_name=False): if name: folder = str(folder).replace('/', '') if not traffic_group: if floating: traffic_group = \ const.SHARED_CONFIG_DEFAULT_FLOATING_TRAFFIC_GROUP else: traffic_group = const.SHARED_CONFIG_DEFAULT_TRAFFIC_GROUP self.bigip.system.set_rest_folder(folder) payload = dict() payload['name'] = name payload['partition'] = folder if not netmask: netmask = '32' payload['address'] = ip_address + '/' + str(netmask) else: net = netaddr.IPNetwork('1.1.1.1/' + str(netmask)) payload['address'] = ip_address + '/' + str(net.prefixlen) if floating: payload['floating'] = 'enabled' else: payload['floating'] = 'disabled' payload['trafficGroup'] = traffic_group if not vlan_name.startswith('/Common'): payload['vlan'] = '/' + folder + '/' + vlan_name else: payload['vlan'] = vlan_name request_url = self.bigip.icr_url + '/net/self/' response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 409: return True elif response.status_code == 400 and \ response.text.find( "must be one of the vlans in the associated route domain") > 0: self.bigip.route.add_vlan_to_domain(name=vlan_name, folder=folder) Log.error('self', 'bridge creation was halted before ' + \ 'it was added to route domain.' + \ 'attempting to add to route domain ' + \ 'and retrying SelfIP creation.') response = self.bigip.icr_session.post( request_url, data=json.dumps(payload), timeout=const.CONNECTION_TIMEOUT) if response.status_code < 400: return True elif response.status_code == 409: return True else: Log.error('self', response.text) raise exceptions.SelfIPCreationException(response.text) else: Log.error('self', response.text) raise exceptions.SelfIPCreationException(response.text) return False