Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,14 @@ def create_listener(self, context, listener, service):
id = listener['id']
try:
mgr = resource_manager.ListenerManager(self.lbdriver)
# todo delete these 3 lines
# listener['redirect_up'] = True
# listener['redirect_protocol'] = 'HTTPS'
# listener['redirect_port'] = 444
# service["listeners"][0]["redirect_up"] = True
# service["listeners"][0]["redirect_port"] = 444
# service["listeners"][0]["redirect_protocol"] = 'HTTPS'

mgr.create(listener, service)
provision_status = constants_v2.F5_ACTIVE
operating_status = constants_v2.F5_ONLINE
Expand Down
171 changes: 171 additions & 0 deletions f5_openstack_agent/lbaasv2/drivers/bigip/resource_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,10 +756,42 @@ def _check_http2_changed(self, old_listener, listener):
return True
return False

def _check_redirect_changed(self, old_listener, listener):
LOG.debug(old_listener)
LOG.debug(listener)

if 'redirect_up' not in old_listener or 'redirect_up' not in listener:
return 'none'

old_redirect_up = old_listener.get('redirect_up')
new_redirect_up = listener.get('redirect_up')

if new_redirect_up and not old_redirect_up:
LOG.debug('enabling')
return 'enable'
elif old_redirect_up and not new_redirect_up:
LOG.debug('disabling')
return 'disable'
elif old_redirect_up and new_redirect_up:
old_num = old_listener.get('redirect_port')
new_num = listener.get('redirect_port')
LOG.debug('old_num:')
LOG.debug(old_num)
LOG.debug('new_num:')
LOG.debug(new_num)
if old_num != new_num:
LOG.debug('modifying')
return 'modify'

LOG.debug('nothing')
return 'none'

def _update_needed(self, payload, old_listener, listener):
if self._check_tls_changed(old_listener, listener) or \
self._check_customized_changed(old_listener, listener) or \
self._check_redirect_changed(old_listener, listener) != 'none' or \
self._check_http2_changed(old_listener, listener):
LOG.info('true here')
return True
return super(ListenerManager, self)._update_needed(
payload, old_listener, listener)
Expand Down Expand Up @@ -1098,6 +1130,22 @@ def _detach_profile(self, bigip, vs, profile):
LOG.debug("Profile %s is not attached to vs %s",
profile['name'], vs['name'])

def _create_redirect_irule_payload(self, vs, loadbalancer, listener):
# create the redirect irule
irule = {}
irule['partition'] = self.driver.service_adapter.\
get_folder_name(loadbalancer['tenant_id'])
irule['name'] = 'redirect_irule_' + listener['id']

redi_port = listener.get('redirect_port')
if redi_port is None:
LOG.error('redirect port is none, seems safe to neglect now')

irule['apiAnonymous'] = 'when HTTP_REQUEST {\n\
HTTP::redirect https://[getfield [HTTP::host] ":" 1]:' + \
str(redi_port) + '[HTTP::uri]\n}'
return irule

def _create_websocket_irule(self, bigip, vs):
# Websocket iRule is shared across all partitions. Needn't delete it.
irule = {
Expand All @@ -1120,6 +1168,36 @@ def _create_websocket_irule(self, bigip, vs):
bigip, irule, None, None, type="irule", helper=self.irule_helper)
vs['rules'].append("/Common/websocket_irule")

def try_create_redirect_irule(self, bigip, vs, loadbalancer, listener):
LOG.debug('vs here is:')
LOG.debug(vs)
the_payload = self._create_redirect_irule_payload(
vs, loadbalancer, listener
)
super(ListenerManager, self)._create(
bigip, the_payload, None, None, type="irule",
helper=self.irule_helper, overwrite=True
)

def try_del_redirect_irule(self, bigip, vs, loadbalancer, listener):
LOG.debug('inside try_del_redirect_irule')
LOG.debug('vs here:')
LOG.debug(vs)

LOG.debug('loadbalancer here:')
LOG.debug(loadbalancer)

LOG.debug('listener here:')
LOG.debug(listener)

payload = self._create_redirect_irule_payload(
vs, loadbalancer, listener
)
super(ListenerManager, self).\
_delete(bigip, payload, None, None,
type="irule",
helper=self.irule_helper)

def _create(self, bigip, vs, listener, service):
tls = self.driver.service_adapter.get_tls(service)
if tls:
Expand Down Expand Up @@ -1154,6 +1232,23 @@ def _create(self, bigip, vs, listener, service):
bwc_policy = LoadBalancerManager.get_bwc_policy_name(
self.driver.service_adapter, loadbalancer)
vs['bwcPolicy'] = bwc_policy

# redirect_up, redirect_protocol, redirect_port
if vs.get('redirect_up'):
LOG.debug('at redirect_up')
self.try_create_redirect_irule(
bigip, vs, loadbalancer, listener
)
# use full name
# redirect_irule_name = 'redirect_irule_' + listener['id']
redi_irule_full_name = self.get_redirect_irule_full_name(
self.driver.service_adapter,
loadbalancer, listener['id']
)
vs['rules'].append(redi_irule_full_name)

LOG.debug('vs details:')
LOG.debug(vs)
super(ListenerManager, self)._create(bigip, vs, listener, service)

def __get_profiles_from_bigip(self, bigip, vs):
Expand All @@ -1166,6 +1261,13 @@ def __get_profiles_from_bigip(self, bigip, vs):
profiles = v.profilesReference
return profiles

@staticmethod
def get_redirect_irule_full_name(adapter, loadbalancer, listener_id):
irule_name = '/' + adapter.\
get_folder_name(loadbalancer['tenant_id']) + '/redirect_irule_'\
+ listener_id
return irule_name

def _update(self, bigip, vs, old_listener, listener, service):
# Add conditions here for more update requests via vs['profiles']
extended_profile_updated = False
Expand Down Expand Up @@ -1222,7 +1324,74 @@ def _update(self, bigip, vs, old_listener, listener, service):
old_service = {"listener": old_listener}
self._delete_ssl_profiles(bigip, vs, old_service)

LOG.debug('checking redirect here')
# enable, disable, modify, none
redirect_ret = self._check_redirect_changed(old_listener, listener)
LOG.debug('redirect_ret here is:')
LOG.debug(redirect_ret)
loadbalancer = service.get('loadbalancer', dict())

# redirect_irule_name = 'redirect_irule_' + listener['id']
redi_irule_full_name = self.get_redirect_irule_full_name(
self.driver.service_adapter,
loadbalancer, listener['id']
)

the_vs_payload = self.driver.service_adapter.\
_init_virtual_name(loadbalancer, listener)
the_vs = self.resource_helper.load(
bigip, name=the_vs_payload['name'],
partition=the_vs_payload['partition']
)

the_vs_payload['rules'] = the_vs.rules

if redirect_ret == 'enable':
LOG.debug('to redirect')
self.try_create_redirect_irule(
bigip, the_vs_payload,
loadbalancer, listener
)
the_vs_payload['rules'].append(redi_irule_full_name)

elif redirect_ret == 'disable':
LOG.debug('to reverse redirect')
# not able to delete here because it is still in use by listener
# self.try_del_redirect_irule(bigip,vs,loadbalancer,old_listener)

if redi_irule_full_name in the_vs_payload['rules']:
LOG.debug('remove from rules')
LOG.debug(redi_irule_full_name)
the_vs_payload['rules'].remove(redi_irule_full_name)

elif redirect_ret == 'modify':
LOG.debug('to redirect elsewhere')
# self.try_del_redirect_irule(bigip, the_vs_payload,
# loadbalancer,old_listener)
LOG.debug('creating new:')
self.try_create_redirect_irule(
bigip, the_vs_payload, loadbalancer, listener
)

if redi_irule_full_name not in the_vs_payload['rules']:
LOG.info('add to rules')
the_vs_payload['rules'].append(redi_irule_full_name)
else:
LOG.debug('no redirect change here')

if redirect_ret in ('enable', 'disable', 'modify'):
LOG.debug('calling _update')
self.resource_helper.update(bigip, the_vs_payload)

if redirect_ret == 'disable':
LOG.debug('delete the irule here.')
self.try_del_redirect_irule(
bigip, the_vs_payload, loadbalancer, old_listener
)

def _delete(self, bigip, vs, listener, service):
loadbalancer = service.get("loadbalancer", None)

super(ListenerManager, self)._delete(bigip, vs, listener, service)
self._delete_persist_profile(bigip, vs)
self._delete_ssl_profiles(bigip, vs, service)
Expand All @@ -1231,6 +1400,8 @@ def _delete(self, bigip, vs, listener, service):
if ftp_enable:
self.ftp_helper.remove_profile(service, vs, bigip)

self.try_del_redirect_irule(bigip, vs, loadbalancer, listener)

@serialized('ListenerManager.create')
@log_helpers.log_method_call
def create(self, listener, service, **kwargs):
Expand Down
9 changes: 9 additions & 0 deletions f5_openstack_agent/lbaasv2/drivers/bigip/service_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def get_resource_description(self, resource):
return full_description

def get_virtual(self, service):
# whether need to pass redirect from driver side.
listener = service["listener"]
loadbalancer = service["loadbalancer"]

Expand Down Expand Up @@ -506,6 +507,14 @@ def _map_virtual(self, loadbalancer, listener,
self._add_vlan_and_snat(listener, vip)
self._add_profiles_session_persistence(listener, pool, vip)

if "redirect_up" in listener:
if listener["redirect_up"]:
vip["redirect_up"] = True
vip["redirect_port"] = listener["redirect_port"]
vip["redirect_protocol"] = listener["redirect_protocol"]
else:
vip["redirect_up"] = False

# Set bandwidth controller
if 'bwcPolicy' in listener:
vip['bwcPolicy'] = listener.get("bwcPolicy")
Expand Down