# -*- coding: utf-8 -*-
import itertools
import logging
import bigsuds
from ..base import BasePlugin
from networkapi.plugins import exceptions as base_exceptions
from networkapi.plugins.F5 import monitor
from networkapi.plugins.F5 import node
from networkapi.plugins.F5 import pool
from networkapi.plugins.F5 import poolmember
from networkapi.plugins.F5 import rule
from networkapi.plugins.F5 import util
from networkapi.plugins.F5 import virtualserver
from networkapi.plugins.F5.util import logger
log = logging.getLogger(__name__)
[docs]class Generic(BasePlugin):
#######################################
# VIP
#######################################
[docs] @logger
def get_name_eqpt(self, obj, port):
address = obj.ipv4.ip_formated \
if obj.ipv4 else obj.ipv6.ip_formated
name_vip = 'VIP%s_%s_%s' % (obj.id, address, port)
name_vip = str.replace(str(name_vip), ':', '.')
return name_vip
[docs] @logger
@util.connection
def delete_vip(self, vips, cleanup=False):
tratado = util.trata_param_vip(vips)
dict_vip = {
'vips': tratado.get('vips_filter'),
'vips_cache': tratado.get('vips_cache_filter'),
'pool_created': tratado.get('pool_filter_created')
}
if cleanup:
self._cleanup_vip(dict_vip)
return []
else:
pools_del = self._delete_vip(dict_vip)
return pools_del
@logger
def _delete_vip(self, tratado):
pools_del = list()
vts = virtualserver.VirtualServer(self._lb)
try:
self._lb._channel.System.Session.start_transaction()
if tratado.get('vips'):
vps_names = [vp['name'] for vp in tratado.get('vips')]
vts.delete(vps_names=vps_names)
rule_l7 = ['{}_RULE_L7'.format(vp['name'])
for vp in tratado.get('vips') if vp.get('pool_l7')]
if rule_l7:
rl = rule.Rule(self._lb)
rl.delete(rule_names=rule_l7)
# CACHE
if tratado.get('vips_cache'):
vps_names = [vp['name'] for vp in tratado.get('vips_cache')]
vts.delete(vps_names=vps_names)
except Exception, e:
self._lb._channel.System.Session.rollback_transaction()
log.error(e)
raise e
else:
self._lb._channel.System.Session.submit_transaction()
if tratado.get('pool_created'):
for server_pool in tratado.get('pool_created'):
if self._delete_pool_by_pass(server_pool):
pools_del.append(server_pool.get('id'))
return pools_del
@logger
def _cleanup_vip(self, tratado):
pools_del = list()
vts = virtualserver.VirtualServer(self._lb)
if tratado.get('vips'):
for vip in tratado.get('vips'):
try:
vts.delete(vps_names=[vip['name']])
except:
pass
try:
if vip.get('pool_l7'):
rl = rule.Rule(self._lb)
rl.delete(rule_names='{}_RULE_L7'.format(vip['name']))
except:
pass
# CACHE
if tratado.get('vips_cache'):
for vip in tratado.get('vips_cache'):
vts.delete(vps_names=[vip['name']])
[docs] @logger
@util.connection
def create_vip(self, vips):
tratado = util.trata_param_vip(vips)
dict_vip = {
'vips_cache': tratado.get('vips_cache_filter'),
'vips': tratado.get('vips_filter'),
'pool': tratado.get('pool_filter')
}
pools_ins = self._create_vip(dict_vip)
return pools_ins
@logger
def _create_vip(self, tratado):
pools_ins = list()
vts = virtualserver.VirtualServer(self._lb)
# vip create
if tratado.get('pool'):
self.__create_pool({'pools': tratado.get('pool')})
pools_ins = [server_pool.get('id')
for server_pool in tratado.get('pool')]
try:
if tratado.get('vips'):
vts.create(vips=tratado.get('vips'))
except Exception, e:
if tratado.get('pool'):
self._delete_pool({'pools': tratado.get('pool')})
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
# cache layer
try:
if tratado.get('vips_cache'):
vts.create(vips=tratado.get('vips_cache'))
except Exception, e:
# rollback vip create
try:
if tratado.get('vips'):
vps_names = [vp['name'] for vp in tratado.get('vips')]
vts.delete(vps_names=vps_names)
except Exception, e:
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
if tratado.get('pool'):
self._delete_pool({'pools': tratado.get('pool')})
log.error(e)
raise base_exceptions.CommandErrorException(e)
return pools_ins
[docs] @logger
@util.connection
def update_vip(self, vips):
pools_ins = list()
pools_del = list()
tratado = util.trata_param_vip(vips)
vts = virtualserver.VirtualServer(self._lb)
dict_create_vip = {
'vips_cache': tratado.get('vips_cache_filter_to_insert'),
'vips': tratado.get('vips_filter_to_insert'),
'pool': tratado.get('pool_filter_to_insert')
}
dict_delete_vip = {
'vips_cache': tratado.get('vips_cache_filter_to_delete'),
'vips': tratado.get('vips_filter_to_delete'),
'pool_created': list()
}
# delete ports
try:
log.info('try delete ports')
pools_del = self._delete_vip(dict_delete_vip)
vts = virtualserver.VirtualServer(self._lb)
except Exception, e:
# rollback delete of ports
log.info('rollback delete of ports')
pools_del = self._delete_vip(dict_create_vip)
log.error('error to delete ports')
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
log.info('delete ports with success')
# create new ports
# create new pools(of new ports and old ports)
try:
log.info('try create ports')
pools_ins = self._create_vip(dict_create_vip)
except Exception, e:
log.error('error to create new ports and new pools')
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
log.info('success create ports')
# update vips(old ports)
try:
log.info('try update vips')
if tratado.get('vips_filter'):
vts.update(vips=tratado.get('vips_filter'))
except Exception, e:
# rollback create port
log.info('rollback create port')
self._create_vip(dict_delete_vip)
# rollback delete port
log.info('rollback delete port')
self._delete_vip(dict_create_vip)
log.info('error update vips')
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
# delete pools that not were deleted in first call
if tratado.get('pool_filter_to_delete'):
log.info('try delete pools that not were deleted in first call')
for server_pool in tratado.get('pool_filter_to_delete'):
if self._delete_pool_by_pass(server_pool):
pools_del.append(server_pool.get('id'))
log.info('update vips with success')
return pools_ins, pools_del
[docs] @logger
@util.connection
def partial_update_vip(self, vips):
tratado = util.trata_param_vip(vips)
vts = virtualserver.VirtualServer(self._lb)
try:
log.info('try update vips')
if tratado.get('vips_filter'):
vts.partial_update(vips=tratado.get('vips_filter'))
except Exception, e:
log.info('error update vips')
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
log.info('update vips with success')
return [], []
@logger
def _delete_pool_by_pass(self, server_pool):
try:
self._delete_pool({'pools': [server_pool]})
except Exception, e:
if 'cannot be deleted because it is in use by a Virtual Server' in str(e.message):
log.warning(
'Pool cannot be deleted because it is in use by a Virtual Server')
pass
elif 'is referenced by one or more virtual servers' in str(e.message):
log.warning(
'Pool cannot be deleted because it is referenced by one or more virtual servers')
pass
elif 'is referenced by one or more rules' in str(e.message):
log.warning(
'Pool cannot be deleted because is referenced by one or more rules')
pass
else:
log.error(e)
raise e
return False
return True
#######################################
# POOLMEMBER
#######################################
[docs] @logger
@util.transation
def set_state_member(self, pools):
pls = util.trata_param_pool(pools)
plm = poolmember.PoolMember(self._lb)
plm.set_states(
names=pls['pools_names'],
members=pls['pools_members']['members'],
monitor_state=pls['pools_members']['monitor'],
session_state=pls['pools_members']['session'])
[docs] @logger
@util.transation
def set_connection_limit_member(self, pools):
pls = util.trata_param_pool(pools)
plm = poolmember.PoolMember(self._lb)
plm.setConnectionLimit(
names=pls['pools_names'],
members=pls['pools_members']['members'],
connection_limit=pls['pools_members']['limit'])
[docs] @logger
@util.transation
def set_priority_member(self, pools):
pls = util.trata_param_pool(pools)
plm = poolmember.PoolMember(self._lb)
plm.setPriority(
names=pls['pools_names'],
members=pls['pools_members']['members'],
priority=pls['pools_members']['priority'])
[docs] @logger
@util.connection_simple
def get_state_member(self, pools):
pls = util.trata_param_pool(pools)
plm = poolmember.PoolMember(self._lb)
return plm.get_states(
names=pls['pools_names'],
members=pls['pools_members']['members'])
[docs] @logger
@util.transation
def create_member(self, pools):
pls = util.trata_param_pool(pools)
plm = poolmember.PoolMember(self._lb)
return plm.create(
names=pls['pools_names'],
members=pls['pools_members']['members'])
[docs] @logger
@util.transation
def remove_member(self, pools):
pls = util.trata_param_pool(pools)
plm = poolmember.PoolMember(self._lb)
return plm.remove(
names=pls['pools_names'],
members=pls['pools_members']['members'])
#######################################
# POOL
#######################################
[docs] @logger
@util.connection
def create_pool(self, pools):
self.__create_pool(pools)
@logger
def __create_pool(self, pools):
monitor_associations = []
pls = util.trata_param_pool(pools)
mon = monitor.Monitor(self._lb)
monitor_associations, monitor_associations_nodes, templates_extra = mon.prepare_template(
names=pls['pools_names'],
members=pls['pools_members']['members'],
healthcheck=pls['pools_healthcheck']
)
mon.create_template(templates_extra=templates_extra)
try:
self._lb._channel.System.Session.start_transaction()
pl = pool.Pool(self._lb)
pl.create(
names=pls['pools_names'],
lbmethod=pls['pools_lbmethod'],
members=pls['pools_members']['members'])
pl.set_monitor_association(
monitor_associations=monitor_associations)
pl.set_service_down_action(
names=pls['pools_names'],
actions=pls['pools_actions'])
pl.set_minimum_active_member(
names=pls['pools_names'])
plm = poolmember.PoolMember(self._lb)
plm.set_connection_limit(
names=pls['pools_names'],
members=pls['pools_members']['members'],
connection_limit=pls['pools_members']['limit'])
plm.set_priority(
names=pls['pools_names'],
members=pls['pools_members']['members'],
priority=pls['pools_members']['priority'])
# plm.set_member_description(
# names=pls['pools_names'],
# members=pls['pools_members']['members'],
# description=pls['pools_members']['description'])
plm.set_states(
names=pls['pools_names'],
members=pls['pools_members']['members'],
monitor_state=pls['pools_members']['monitor'],
session_state=pls['pools_members']['session'])
except Exception, e:
self._lb._channel.System.Session.rollback_transaction()
template_names = [m for m in list(itertools.chain(
*[m['monitor_rule']['monitor_templates'] for m in monitor_associations])) if 'MONITOR' in m]
if template_names != []:
mon.delete_template(
template_names=template_names
)
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
self._lb._channel.System.Session.submit_transaction()
try:
if monitor_associations_nodes.get('nodes'):
nd = node.Node(self._lb)
nd.set_monitor_rule(
monitor_associations=monitor_associations_nodes)
except bigsuds.OperationFailed:
pass
[docs] @logger
@util.connection
def update_pool(self, pools):
self.__update_pool(pools)
@logger
def __update_pool(self, pools):
monitor_associations = []
pls = util.trata_param_pool(pools)
pl = pool.Pool(self._lb)
mon = monitor.Monitor(self._lb)
# get template currents
monitor_associations_old = pl.get_monitor_association(
names=pls['pools_names'])
# creates templates
monitor_associations, monitor_associations_nodes, templates_extra = mon.prepare_template(
names=pls['pools_names'],
members=pls['pools_members']['members'],
healthcheck=pls['pools_healthcheck']
)
mon.create_template(templates_extra=templates_extra)
try:
self._lb._channel.System.Session.start_transaction()
pl.set_monitor_association(
monitor_associations=monitor_associations)
pl.set_lb_method(
names=pls['pools_names'],
lbmethod=pls['pools_lbmethod'])
pl.set_service_down_action(
names=pls['pools_names'],
actions=pls['pools_actions'])
plm = poolmember.PoolMember(self._lb)
if pls['pools_members']['members_remove']:
plm.remove(
names=pls['pools_names'],
members=pls['pools_members']['members_remove'])
if pls['pools_members']['members_new']:
plm.create(
names=pls['pools_names'],
members=pls['pools_members']['members_new'])
plm.set_connection_limit(
names=pls['pools_names'],
members=pls['pools_members']['members'],
connection_limit=pls['pools_members']['limit'])
plm.set_priority(
names=pls['pools_names'],
members=pls['pools_members']['members'],
priority=pls['pools_members']['priority'])
plm.set_ratio(
names=pls['pools_names'],
members=pls['pools_members']['members'],
ratio=pls['pools_members']['weight'])
# plm.set_member_description(
# names=pls['pools_names'],
# members=pls['pools_members']['members'],
# description=pls['pools_members']['description'])
plm.set_states(
names=pls['pools_names'],
members=pls['pools_members']['members'],
monitor_state=pls['pools_members']['monitor'],
session_state=pls['pools_members']['session'])
except Exception, e:
self._lb._channel.System.Session.rollback_transaction()
# delete templates created
template_names = [m for m in list(
itertools.chain(
*[m['monitor_rule']['monitor_templates'] for m in monitor_associations])
) if 'MONITOR' in m]
if template_names:
mon.delete_template(
template_names=template_names
)
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
self._lb._channel.System.Session.submit_transaction()
try:
if monitor_associations_nodes.get('nodes'):
nd = node.Node(self._lb)
nd.set_monitor_rule(
monitor_associations=monitor_associations_nodes)
if pls['pools_confirm']['pools_names']:
plm.set_member_monitor_state(
names=pls['pools_confirm']['pools_names'],
members=pls['pools_confirm']['members'],
monitor_state=pls['pools_confirm']['monitor'])
except bigsuds.OperationFailed:
pass
# delete templates old
try:
template_names = [m for m in list(
itertools.chain(*[m['monitor_rule']['monitor_templates'] for m in monitor_associations_old])) if 'MONITOR' in m]
if template_names:
mon.delete_template(template_names=template_names)
except bigsuds.OperationFailed:
pass
[docs] @logger
@util.connection
def delete_pool(self, pools, cleanup=False):
if cleanup:
return self._cleanup_pool(pools)
else:
self._delete_pool(pools)
@logger
def _delete_pool(self, pools):
pls = util.trata_param_pool(pools)
pl = pool.Pool(self._lb)
mon = monitor.Monitor(self._lb)
try:
monitor_associations = pl.get_monitor_association(
names=pls['pools_names'])
except Exception, e:
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
try:
self._lb._channel.System.Session.start_transaction()
pl.delete(names=pls['pools_names'])
except Exception, e:
self._lb._channel.System.Session.rollback_transaction()
log.error(e)
raise base_exceptions.CommandErrorException(e)
else:
self._lb._channel.System.Session.submit_transaction()
try:
template_names = [m for m in list(
itertools.chain(
*[m['monitor_rule']['monitor_templates'] for m in monitor_associations])) if 'MONITOR' in m]
if template_names:
mon.delete_template(template_names=template_names)
except bigsuds.OperationFailed:
pass
@logger
def _cleanup_pool(self, pools):
pls = util.trata_param_pool(pools)
pl = pool.Pool(self._lb)
mon = monitor.Monitor(self._lb)
ids = list()
for idx, pool_name in enumerate(pls['pools_names']):
try:
monitor_associations = pl.get_monitor_association(
names=[pool_name])
except:
pass
can_delete = True
try:
pl.delete(names=[pool_name])
except Exception, e:
can_delete = False
if 'cannot be deleted because it is in use by a Virtual Server' in str(e.message):
log.warning(
'Pool cannot be deleted because it is in use by a Virtual Server')
pass
elif 'is referenced by one or more virtual servers' in str(e.message):
log.warning(
'Pool cannot be deleted because it is referenced by one or more virtual servers')
pass
elif 'is referenced by one or more rules' in str(e.message):
log.warning(
'Pool cannot be deleted because is referenced by one or more rules')
pass
elif 'was not found.' in str(e.message):
log.warning('Pool already deleted')
can_delete = True
pass
else:
log.error(e)
raise e
if can_delete:
ids.append(pools['pools'][idx]['id'])
try:
template_names = [m for m in list(
itertools.chain(
*[m['monitor_rule']['monitor_templates'] for m in monitor_associations])) if 'MONITOR' in m]
if template_names:
mon.delete_template(template_names=template_names)
except:
pass
return ids