Skip to content

Commit d1ffd34

Browse files
committed
redirect feature
using irules
1 parent 4a7d368 commit d1ffd34

3 files changed

Lines changed: 188 additions & 0 deletions

File tree

f5_openstack_agent/lbaasv2/drivers/bigip/agent_manager_lite.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,14 @@ def create_listener(self, context, listener, service):
14541454
id = listener['id']
14551455
try:
14561456
mgr = resource_manager.ListenerManager(self.lbdriver)
1457+
# todo delete these 3 lines
1458+
# listener['redirect_up'] = True
1459+
# listener['redirect_protocol'] = 'HTTPS'
1460+
# listener['redirect_port'] = 444
1461+
# service["listeners"][0]["redirect_up"] = True
1462+
# service["listeners"][0]["redirect_port"] = 444
1463+
# service["listeners"][0]["redirect_protocol"] = 'HTTPS'
1464+
14571465
mgr.create(listener, service)
14581466
provision_status = constants_v2.F5_ACTIVE
14591467
operating_status = constants_v2.F5_ONLINE

f5_openstack_agent/lbaasv2/drivers/bigip/resource_manager.py

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,10 +756,42 @@ def _check_http2_changed(self, old_listener, listener):
756756
return True
757757
return False
758758

759+
def _check_redirect_changed(self, old_listener, listener):
760+
LOG.debug(old_listener)
761+
LOG.debug(listener)
762+
763+
if 'redirect_up' not in old_listener or 'redirect_up' not in listener:
764+
return 'none'
765+
766+
old_redirect_up = old_listener.get('redirect_up')
767+
new_redirect_up = listener.get('redirect_up')
768+
769+
if new_redirect_up and not old_redirect_up:
770+
LOG.debug('enabling')
771+
return 'enable'
772+
elif old_redirect_up and not new_redirect_up:
773+
LOG.debug('disabling')
774+
return 'disable'
775+
elif old_redirect_up and new_redirect_up:
776+
old_num = old_listener.get('redirect_port')
777+
new_num = listener.get('redirect_port')
778+
LOG.debug('old_num:')
779+
LOG.debug(old_num)
780+
LOG.debug('new_num:')
781+
LOG.debug(new_num)
782+
if old_num != new_num:
783+
LOG.debug('modifying')
784+
return 'modify'
785+
786+
LOG.debug('nothing')
787+
return 'none'
788+
759789
def _update_needed(self, payload, old_listener, listener):
760790
if self._check_tls_changed(old_listener, listener) or \
761791
self._check_customized_changed(old_listener, listener) or \
792+
self._check_redirect_changed(old_listener, listener) != 'none' or \
762793
self._check_http2_changed(old_listener, listener):
794+
LOG.info('true here')
763795
return True
764796
return super(ListenerManager, self)._update_needed(
765797
payload, old_listener, listener)
@@ -1098,6 +1130,22 @@ def _detach_profile(self, bigip, vs, profile):
10981130
LOG.debug("Profile %s is not attached to vs %s",
10991131
profile['name'], vs['name'])
11001132

1133+
def _create_redirect_irule_payload(self, vs, loadbalancer, listener):
1134+
# create the redirect irule
1135+
irule = {}
1136+
irule['partition'] = self.driver.service_adapter.\
1137+
get_folder_name(loadbalancer['tenant_id'])
1138+
irule['name'] = 'redirect_irule_' + listener['id']
1139+
1140+
redi_port = listener.get('redirect_port')
1141+
if redi_port is None:
1142+
LOG.error('redirect port is none, seems safe to neglect now')
1143+
1144+
irule['apiAnonymous'] = 'when HTTP_REQUEST {\n\
1145+
HTTP::redirect https://[getfield [HTTP::host] ":" 1]:' + \
1146+
str(redi_port) + '[HTTP::uri]\n}'
1147+
return irule
1148+
11011149
def _create_websocket_irule(self, bigip, vs):
11021150
# Websocket iRule is shared across all partitions. Needn't delete it.
11031151
irule = {
@@ -1120,6 +1168,36 @@ def _create_websocket_irule(self, bigip, vs):
11201168
bigip, irule, None, None, type="irule", helper=self.irule_helper)
11211169
vs['rules'].append("/Common/websocket_irule")
11221170

1171+
def try_create_redirect_irule(self, bigip, vs, loadbalancer, listener):
1172+
LOG.debug('vs here is:')
1173+
LOG.debug(vs)
1174+
the_payload = self._create_redirect_irule_payload(
1175+
vs, loadbalancer, listener
1176+
)
1177+
super(ListenerManager, self)._create(
1178+
bigip, the_payload, None, None, type="irule",
1179+
helper=self.irule_helper, overwrite=True
1180+
)
1181+
1182+
def try_del_redirect_irule(self, bigip, vs, loadbalancer, listener):
1183+
LOG.debug('inside try_del_redirect_irule')
1184+
LOG.debug('vs here:')
1185+
LOG.debug(vs)
1186+
1187+
LOG.debug('loadbalancer here:')
1188+
LOG.debug(loadbalancer)
1189+
1190+
LOG.debug('listener here:')
1191+
LOG.debug(listener)
1192+
1193+
payload = self._create_redirect_irule_payload(
1194+
vs, loadbalancer, listener
1195+
)
1196+
super(ListenerManager, self).\
1197+
_delete(bigip, payload, None, None,
1198+
type="irule",
1199+
helper=self.irule_helper)
1200+
11231201
def _create(self, bigip, vs, listener, service):
11241202
tls = self.driver.service_adapter.get_tls(service)
11251203
if tls:
@@ -1154,6 +1232,23 @@ def _create(self, bigip, vs, listener, service):
11541232
bwc_policy = LoadBalancerManager.get_bwc_policy_name(
11551233
self.driver.service_adapter, loadbalancer)
11561234
vs['bwcPolicy'] = bwc_policy
1235+
1236+
# redirect_up, redirect_protocol, redirect_port
1237+
if vs.get('redirect_up'):
1238+
LOG.debug('at redirect_up')
1239+
self.try_create_redirect_irule(
1240+
bigip, vs, loadbalancer, listener
1241+
)
1242+
# use full name
1243+
# redirect_irule_name = 'redirect_irule_' + listener['id']
1244+
redi_irule_full_name = self.get_redirect_irule_full_name(
1245+
self.driver.service_adapter,
1246+
loadbalancer, listener['id']
1247+
)
1248+
vs['rules'].append(redi_irule_full_name)
1249+
1250+
LOG.debug('vs details:')
1251+
LOG.debug(vs)
11571252
super(ListenerManager, self)._create(bigip, vs, listener, service)
11581253

11591254
def __get_profiles_from_bigip(self, bigip, vs):
@@ -1166,6 +1261,13 @@ def __get_profiles_from_bigip(self, bigip, vs):
11661261
profiles = v.profilesReference
11671262
return profiles
11681263

1264+
@staticmethod
1265+
def get_redirect_irule_full_name(adapter, loadbalancer, listener_id):
1266+
irule_name = '/' + adapter.\
1267+
get_folder_name(loadbalancer['tenant_id']) + '/redirect_irule_'\
1268+
+ listener_id
1269+
return irule_name
1270+
11691271
def _update(self, bigip, vs, old_listener, listener, service):
11701272
# Add conditions here for more update requests via vs['profiles']
11711273
extended_profile_updated = False
@@ -1222,7 +1324,74 @@ def _update(self, bigip, vs, old_listener, listener, service):
12221324
old_service = {"listener": old_listener}
12231325
self._delete_ssl_profiles(bigip, vs, old_service)
12241326

1327+
LOG.debug('checking redirect here')
1328+
# enable, disable, modify, none
1329+
redirect_ret = self._check_redirect_changed(old_listener, listener)
1330+
LOG.debug('redirect_ret here is:')
1331+
LOG.debug(redirect_ret)
1332+
loadbalancer = service.get('loadbalancer', dict())
1333+
1334+
# redirect_irule_name = 'redirect_irule_' + listener['id']
1335+
redi_irule_full_name = self.get_redirect_irule_full_name(
1336+
self.driver.service_adapter,
1337+
loadbalancer, listener['id']
1338+
)
1339+
1340+
the_vs_payload = self.driver.service_adapter.\
1341+
_init_virtual_name(loadbalancer, listener)
1342+
the_vs = self.resource_helper.load(
1343+
bigip, name=the_vs_payload['name'],
1344+
partition=the_vs_payload['partition']
1345+
)
1346+
1347+
the_vs_payload['rules'] = the_vs.rules
1348+
1349+
if redirect_ret == 'enable':
1350+
LOG.debug('to redirect')
1351+
self.try_create_redirect_irule(
1352+
bigip, the_vs_payload,
1353+
loadbalancer, listener
1354+
)
1355+
the_vs_payload['rules'].append(redi_irule_full_name)
1356+
1357+
elif redirect_ret == 'disable':
1358+
LOG.debug('to reverse redirect')
1359+
# not able to delete here because it is still in use by listener
1360+
# self.try_del_redirect_irule(bigip,vs,loadbalancer,old_listener)
1361+
1362+
if redi_irule_full_name in the_vs_payload['rules']:
1363+
LOG.debug('remove from rules')
1364+
LOG.debug(redi_irule_full_name)
1365+
the_vs_payload['rules'].remove(redi_irule_full_name)
1366+
1367+
elif redirect_ret == 'modify':
1368+
LOG.debug('to redirect elsewhere')
1369+
# self.try_del_redirect_irule(bigip, the_vs_payload,
1370+
# loadbalancer,old_listener)
1371+
LOG.debug('creating new:')
1372+
self.try_create_redirect_irule(
1373+
bigip, the_vs_payload, loadbalancer, listener
1374+
)
1375+
1376+
if redi_irule_full_name not in the_vs_payload['rules']:
1377+
LOG.info('add to rules')
1378+
the_vs_payload['rules'].append(redi_irule_full_name)
1379+
else:
1380+
LOG.debug('no redirect change here')
1381+
1382+
if redirect_ret in ('enable', 'disable', 'modify'):
1383+
LOG.debug('calling _update')
1384+
self.resource_helper.update(bigip, the_vs_payload)
1385+
1386+
if redirect_ret == 'disable':
1387+
LOG.debug('delete the irule here.')
1388+
self.try_del_redirect_irule(
1389+
bigip, the_vs_payload, loadbalancer, old_listener
1390+
)
1391+
12251392
def _delete(self, bigip, vs, listener, service):
1393+
loadbalancer = service.get("loadbalancer", None)
1394+
12261395
super(ListenerManager, self)._delete(bigip, vs, listener, service)
12271396
self._delete_persist_profile(bigip, vs)
12281397
self._delete_ssl_profiles(bigip, vs, service)
@@ -1231,6 +1400,8 @@ def _delete(self, bigip, vs, listener, service):
12311400
if ftp_enable:
12321401
self.ftp_helper.remove_profile(service, vs, bigip)
12331402

1403+
self.try_del_redirect_irule(bigip, vs, loadbalancer, listener)
1404+
12341405
@serialized('ListenerManager.create')
12351406
@log_helpers.log_method_call
12361407
def create(self, listener, service, **kwargs):

f5_openstack_agent/lbaasv2/drivers/bigip/service_adapter.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ def get_resource_description(self, resource):
111111
return full_description
112112

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

@@ -506,6 +507,14 @@ def _map_virtual(self, loadbalancer, listener,
506507
self._add_vlan_and_snat(listener, vip)
507508
self._add_profiles_session_persistence(listener, pool, vip)
508509

510+
if "redirect_up" in listener:
511+
if listener["redirect_up"]:
512+
vip["redirect_up"] = True
513+
vip["redirect_port"] = listener["redirect_port"]
514+
vip["redirect_protocol"] = listener["redirect_protocol"]
515+
else:
516+
vip["redirect_up"] = False
517+
509518
# Set bandwidth controller
510519
if 'bwcPolicy' in listener:
511520
vip['bwcPolicy'] = listener.get("bwcPolicy")

0 commit comments

Comments
 (0)