Skip to content

Commit 1b3f9a6

Browse files
author
Shiva Shankar Vaddepally
committed
NSNETAUTO-1005 supporting dynamic routing protocols
Signed-off-by: Shiva Shankar Vaddepally <[email protected]>
1 parent 700874f commit 1b3f9a6

17 files changed

Lines changed: 820 additions & 49 deletions

Makefile

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
fmt:
2-
autoflake plugins/modules/*.py
3-
autoflake plugins/module_utils/*.py
4-
autoflake --recursive tests/
5-
autoflake tools/migrationtool/*py
2+
autoflake plugins/modules/*.py
3+
autoflake plugins/module_utils/*.py
4+
autoflake --recursive tests/
5+
autoflake tools/migrationtool/*.py
66

7-
black plugins/modules/*.py
8-
black plugins/module_utils/*.py
9-
black tests/
10-
black tools/migrationtool/*.py
7+
black plugins/modules/*.py
8+
black plugins/module_utils/*.py
9+
black tests/
10+
black tools/migrationtool/*.py
1111

12-
isort plugins/modules/*.py
13-
isort plugins/module_utils/*.py
14-
isort tests/
15-
isort tools/migrationtool/*.py
12+
isort plugins/modules/*.py
13+
isort plugins/module_utils/*.py
14+
isort tests/
15+
isort tools/migrationtool/*.py
1616

17-
yamlfmt $(shell find . -name '*.yml' -o -name '*.yaml')
17+
yamlfmt $(shell find . -name '*.yml' -o -name '*.yaml')
1818

1919
install:
2020
ansible-galaxy collection install . --force
@@ -63,7 +63,7 @@ galaxy_importer: build
6363
# skip the playbook which contains "password" in the file name
6464
run_examples:
6565
@for playbook in examples/*.yaml; do \
66-
if [[ $$playbook == *"password"* || $$playbook == *"login"* || $$playbook == *"logout"* || $$playbook == *"route"* || $$playbook == locationfile.yaml || $$playbook == nsip6.yaml || $$playbook == hanode.yaml ]]; then \
66+
if [[ $$playbook == *"password"* || $$playbook == *"login"* || $$playbook == *"logout"* || $$playbook == *"route"* || $$playbook == *"locationfile.yaml"* || $$playbook == *"nsip6.yaml"* || $$playbook == *"hanode.yaml"* ]]; then \
6767
continue; \
6868
fi; \
6969
echo "Running $$playbook"; \

examples/accesslist.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
- name: Configure accessslist
3+
hosts: localhost
4+
tasks:
5+
- name: Create accesslist
6+
delegate_to: localhost
7+
netscaler.adc.accesslist:
8+
state: present
9+
id: 1
10+
remark: "Allow all traffic"
11+
rules:
12+
- action: permit
13+
address: 2.1.1.21
14+
wildcard: "0.0.0.255"

examples/bfdinterface.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
- name: Configure bfdinterface
3+
hosts: localhost
4+
tasks:
5+
- name: Create bfdinterface
6+
delegate_to: localhost
7+
netscaler.adc.bfdinterface:
8+
state: present
9+
name: vlan0
10+
passive: true
11+
interval: 752
12+
minrx: 501
13+
multiplier: 3

examples/iproute.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
- name: Configure bfdinterface
3+
hosts: localhost
4+
tasks:
5+
- name: Create bfdinterface
6+
delegate_to: localhost
7+
netscaler.adc.iproute:
8+
state: present
9+
addressFamily: ipv4
10+
prefix: 33.1.1.0
11+
prefixLength: 24
12+
nextHop: 10.106.210.24

examples/location.yaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
---
22
- name: Sample location playbook
3-
hosts: demo_netscalers
3+
hosts: localhost
44
gather_facts: false
55
tasks:
66
- name: Configure location
77
delegate_to: localhost
88
netscaler.adc.location:
99
state: present
10-
ipfrom: 1.1.1.1
11-
ipto: 2.2.2.2
12-
preferredlocation: '*.US.*'
10+
nsip: 10.106.210.21
11+
nitro_user: nsroot
12+
nitro_pass: notnsroot
13+
nitro_protocol: http
14+
validate_certs: false
15+
ipfrom: "170.173.217.0"
16+
ipto: "170.173.222.255"
17+
preferredlocation: "prov.WA.sdc.*.*.*"

meta/runtime.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,3 +981,6 @@ action_groups:
981981
- sslechconfig.py
982982
- sslhpkekey.py
983983
- sslprofile_sslechconfig_binding.py
984+
- accesslist
985+
- bfdinterface
986+
- iproute

plugins/module_utils/client.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
from ansible.module_utils.six.moves.urllib.parse import quote
1616
from ansible.module_utils.urls import fetch_url
1717

18-
from .constants import HTTP_SUCCESS_CODES
18+
from .constants import (
19+
DYNAMIC_PROTOCOLS,
20+
DYNAMIC_PROTOCOLS_ALIAS,
21+
HTTP_SUCCESS_CODES,
22+
)
1923
from .decorators import trace
2024
from .logger import log
2125

@@ -98,6 +102,9 @@ def url_builder(
98102
filter = filter if filter is not None else {}
99103

100104
# Construct basic URL
105+
if resource in DYNAMIC_PROTOCOLS:
106+
resource = "routerDynamicRouting/" + DYNAMIC_PROTOCOLS_ALIAS[resource]
107+
101108
url = "%s://%s/%s/%s" % (
102109
self._module.params["nitro_protocol"],
103110
self._module.params["nsip"],
@@ -235,6 +242,7 @@ def post(self, post_data, resource, action=None):
235242
def put(self, put_data, resource=None, id=None):
236243
url = self.url_builder(resource, id=id)
237244
data = self._module.jsonify(put_data)
245+
238246
return self.send("PUT", url, data)
239247

240248
@trace

plugins/module_utils/common.py

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import re
1111

1212
from .constants import (
13+
DYNAMIC_PROTOCOLS,
14+
DYNAMIC_PROTOCOLS_ALIAS,
1315
GLOBAL_BINDING_ARG_LIST,
1416
HTTP_RESOURCE_ALREADY_EXISTS,
1517
HTTP_RESOURCE_NOT_FOUND,
@@ -94,16 +96,29 @@ def get_resource(client, resource_name, resource_id=None, resource_module_params
9496
args=get_args,
9597
)
9698
else:
97-
status_code, response_body = client.get(
98-
resource=resource_name,
99-
id=resource_id,
100-
args=get_args,
101-
)
99+
if resource_name in DYNAMIC_PROTOCOLS:
100+
new_resource_name = (
101+
"routerDynamicRouting/" + DYNAMIC_PROTOCOLS_ALIAS[resource_name]
102+
)
103+
status_code, response_body = client.get(
104+
resource=new_resource_name,
105+
id=resource_id,
106+
args=get_args,
107+
)
108+
else:
109+
status_code, response_body = client.get(
110+
resource=resource_name,
111+
id=resource_id,
112+
args=get_args,
113+
)
102114
if status_code in {HTTP_RESOURCE_NOT_FOUND}:
103115
return False, []
104116
if status_code in HTTP_SUCCESS_CODES:
105117
# for zero bindings and some resources, the response_body will be {'errorcode': 0, 'message': 'Done', 'severity': 'NONE'}
106-
if resource_name not in response_body:
118+
if (
119+
resource_name not in response_body
120+
and resource_name not in DYNAMIC_PROTOCOLS
121+
):
107122
if resource_name == "sslcipher":
108123
resource_primary_key = NITRO_RESOURCE_MAP[resource_name]["primary_key"]
109124
return True, [
@@ -112,7 +127,12 @@ def get_resource(client, resource_name, resource_id=None, resource_module_params
112127

113128
return False, []
114129
# `update-only` resources return a dict instead of a list.
115-
return_response = response_body[resource_name]
130+
if resource_name in DYNAMIC_PROTOCOLS:
131+
return_response = response_body.get("routerDynamicRouting", {}).get(
132+
DYNAMIC_PROTOCOLS_ALIAS[resource_name], {}
133+
)
134+
else:
135+
return_response = response_body[resource_name]
116136
# FIXME: NITRO-BUG: for some resources like `policypatset_pattern_binding`, NITRO returns keys with uppercase. eg: `String` for `string`.
117137
# So, we are converting the keys to lowercase.
118138
# except for `ping` and `traceroute`, all the othe resources returns a keys with lowercase.
@@ -242,7 +262,6 @@ def _check_create_resource_params(resource_name, resource_module_params, action=
242262
key, resource_name, action.upper()
243263
)
244264
)
245-
246265
return True, None, post_data
247266

248267

@@ -281,7 +300,11 @@ def create_resource(client, resource_name, resource_module_params, action=None):
281300
if not ok:
282301
return False, err
283302

284-
post_data = {resource_name: post_data}
303+
if resource_name in DYNAMIC_PROTOCOLS:
304+
post_data = {DYNAMIC_PROTOCOLS_ALIAS[resource_name]: post_data}
305+
post_data = {"routerDynamicRouting": post_data}
306+
else:
307+
post_data = {resource_name: post_data}
285308
status_code, response_body = client.post(
286309
post_data=post_data,
287310
resource=resource_name,
@@ -355,7 +378,11 @@ def update_resource(client, resource_name, resource_module_params):
355378
if not ok:
356379
return False, err
357380

358-
put_data = {resource_name: put_payload}
381+
if resource_name in DYNAMIC_PROTOCOLS:
382+
put_data = {DYNAMIC_PROTOCOLS_ALIAS[resource_name]: put_payload}
383+
put_data = {"routerDynamicRouting": put_data}
384+
else:
385+
put_data = {resource_name: put_payload}
359386

360387
status_code, response_body = client.put(
361388
put_data=put_data,

plugins/module_utils/constants.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,22 @@
151151
"sslkeyfile",
152152
"systementitydata",
153153
]
154+
155+
# Dynamic Protocol list
156+
DYNAMIC_PROTOCOLS = [
157+
"accesslist",
158+
"bfdinterface",
159+
"iproute",
160+
"ospf6interface",
161+
]
162+
163+
DYNAMIC_PROTOCOLS_ALIAS = {
164+
"accesslist": "accessList",
165+
"accessList": "accesslist",
166+
"bfdinterface": "bfdInterface",
167+
"bfdInterface": "bfdinterface",
168+
"iproute": "ipRoute",
169+
"ipRoute": "iproute",
170+
"ospf6interface": "ospf6Interface",
171+
"ospf6Interface": "ospf6interface",
172+
}

plugins/module_utils/module_executor.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ def create_or_update(self):
500500
errorcode = None
501501
message = None
502502
err_str = str(err)
503-
regex_string = re.search(r'status_code:\s*(\d+)', err_str)
503+
regex_string = re.search(r"status_code:\s*(\d+)", err_str)
504504
if regex_string:
505505
status_code = int(regex_string.group(1))
506506
regex_string = re.search(r"'errorcode':\s*(\d+)", err_str)
@@ -510,9 +510,9 @@ def create_or_update(self):
510510
if regex_string:
511511
message = regex_string.group(1)
512512
if not (
513-
status_code == 599 and
514-
errorcode == 1065 and
515-
message == "Internal error while adding HSM key."
513+
status_code == 599
514+
and errorcode == 1065
515+
and message == "Internal error while adding HSM key."
516516
):
517517
self.return_failure(err)
518518

@@ -580,15 +580,21 @@ def create_or_update(self):
580580
"INFO: Resource %s:%s exists and is different. Will be REMOVED and ADDED."
581581
% (self.resource_name, self.resource_id)
582582
)
583-
if self.resource_name == "systemfile":
584-
# If the systemfile is present, we will delete it and add it again
585-
self.delete()
586-
ok, err = create_resource(
587-
self.client, self.resource_name, self.resource_module_params
588-
)
589-
if not ok:
590-
self.return_failure(err)
591-
583+
# If the systemfile is present, we will delete it and add it again
584+
self.delete()
585+
ok, err = create_resource(
586+
self.client, self.resource_name, self.resource_module_params
587+
)
588+
if not ok:
589+
self.return_failure(err)
590+
elif self.resource_name == "location":
591+
# TODO: primary composite key needs to be added.
592+
# location resource has composite primary key. 1.ipfrom 2.ipto
593+
ok, err = create_resource(
594+
self.client, self.resource_name, self.resource_module_params
595+
)
596+
if not ok:
597+
self.return_failure(err)
592598
elif self.resource_name.endswith("_binding"):
593599
# Generally bindings are not updated. They are removed and added again.
594600
log(
@@ -707,7 +713,7 @@ def delete(self):
707713
errorcode = None
708714
message = None
709715
err_str = str(err)
710-
regex_string = re.search(r'status_code:\s*(\d+)', err_str)
716+
regex_string = re.search(r"status_code:\s*(\d+)", err_str)
711717
if regex_string:
712718
status_code = int(regex_string.group(1))
713719
regex_string = re.search(r"'errorcode':\s*(\d+)", err_str)
@@ -717,9 +723,9 @@ def delete(self):
717723
if regex_string:
718724
message = regex_string.group(1)
719725
if not (
720-
status_code == 599 and
721-
errorcode == 1065 and
722-
message == "Internal error while adding HSM key."
726+
status_code == 599
727+
and errorcode == 1065
728+
and message == "Internal error while adding HSM key."
723729
):
724730
self.return_failure(err)
725731
else:

0 commit comments

Comments
 (0)