Skip to content

Commit 4cc1e60

Browse files
committed
feat: add snmp module
1 parent baf5807 commit 4cc1e60

File tree

1 file changed

+299
-0
lines changed

1 file changed

+299
-0
lines changed

plugins/modules/pfsense_snmp.py

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
#!/usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright: (c) 2018, Frederic Bor <frederic.bor@wanadoo.fr>
5+
# Copyright: (c) 2021, Jan Wenzel <jan.wenzel@gonicus.de>
6+
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7+
8+
from __future__ import absolute_import, division, print_function
9+
__metaclass__ = type
10+
11+
12+
ANSIBLE_METADATA = {'metadata_version': '1.1',
13+
'status': ['preview'],
14+
'supported_by': 'community'}
15+
16+
DOCUMENTATION = """
17+
---
18+
module: pfsense_snmp
19+
version_added: "0.4.2"
20+
author: Jan Wenzel (@coffeelover)
21+
short_description: Manage pfSense snmp settings
22+
description:
23+
- Manage pfSense snmp settings
24+
notes:
25+
options:
26+
enable:
27+
description: Enable SNMP Service
28+
required: false
29+
type: bool
30+
pollport:
31+
description: SNMP Service Port
32+
required: false
33+
type: int
34+
default: 161
35+
syslocation:
36+
description: System Location
37+
required: false
38+
type: str
39+
syscontact:
40+
description: System Contact
41+
required: false
42+
type: str
43+
rocommunity:
44+
description: Read Community String
45+
required: false
46+
type: str
47+
default: public
48+
trapenable:
49+
description: Enable SNMP Trap
50+
required: false
51+
type: bool
52+
trapserver:
53+
description: SNMP Trap Target Server
54+
required: false
55+
type: str
56+
trapserverport:
57+
description: SNMP Trap Target Port
58+
required: false
59+
type: int
60+
trapstring:
61+
description: SNMP Trap String
62+
required: false
63+
type: str
64+
mibii:
65+
description: Enable SNMP MibII Module
66+
required: false
67+
type: bool
68+
netgraph:
69+
description: Enable SNMP Netgraph Module
70+
required: false
71+
type: bool
72+
pf:
73+
description: Enable SNMP PF Module
74+
required: false
75+
type: bool
76+
hostres:
77+
description: Enable SNMP Host Resources Module
78+
required: false
79+
type: bool
80+
ucd:
81+
description: Enable SNMP UCD Module
82+
required: false
83+
type: bool
84+
regex:
85+
description: Enable SNMP Regex Module
86+
required: false
87+
type: bool
88+
bindip:
89+
description: Bind Interfaces
90+
required: false
91+
type: list
92+
elements: str
93+
"""
94+
95+
EXAMPLES = """
96+
pfsensible.core.pfsense_snmp:
97+
enable: true
98+
syslocation: "Some Datacenter"
99+
bindip:
100+
- "lan"
101+
- "lo0"
102+
"""
103+
104+
RETURN = """
105+
description: the set of commands that would be pushed to the remote device (if pfSense had a CLI)
106+
returned: always
107+
type: list
108+
sample: [
109+
"update snmp snmp set enable=True, syslocation='Some Datacenter', bindip='lan,lo0'"
110+
]
111+
"""
112+
113+
import re
114+
from copy import deepcopy
115+
from ansible.module_utils.basic import AnsibleModule
116+
from ansible_collections.pfsensible.core.plugins.module_utils.module_base import PFSenseModuleBase
117+
118+
SNMP_ARGUMENT_SPEC = dict(
119+
enable=dict(required=False, type='bool'),
120+
pollport=dict(required=False, type='int'),
121+
syslocation=dict(required=False, type='str'),
122+
syscontact=dict(required=False, type='str'),
123+
rocommunity=dict(required=False, type='str', default='public'),
124+
trapenable=dict(required=False, type='bool'),
125+
trapserver=dict(required=False, type='str'),
126+
trapserverport=dict(required=False, type='int', default=162),
127+
trapstring=dict(required=False, type='str'),
128+
mibii=dict(required=False, type='bool', default=True),
129+
netgraph=dict(required=False, type='bool', default=True),
130+
pf=dict(required=False, type='bool', default=True),
131+
hostres=dict(required=False, type='bool', default=True),
132+
ucd=dict(required=False, type='bool', default=True),
133+
regex=dict(required=False, type='bool', default=True),
134+
bindip=dict(required=False, type='list', elements='str', default=['all']),
135+
)
136+
137+
modules = ['mibii', 'netgraph', 'pf', 'hostres', 'ucd', 'regex']
138+
139+
140+
class PFSenseSnmpModule(PFSenseModuleBase):
141+
""" module managing pfsense snmp settings """
142+
143+
@staticmethod
144+
def get_argument_spec():
145+
""" return argument spec """
146+
return SNMP_ARGUMENT_SPEC
147+
148+
##############################
149+
# init
150+
#
151+
def __init__(self, module, pfsense=None):
152+
super(PFSenseSnmpModule, self).__init__(module, pfsense)
153+
self.name = "snmp"
154+
self.root_elt = self.pfsense.get_element('snmpd')
155+
self.target_elt = self.root_elt
156+
self.params = dict()
157+
self.obj = dict()
158+
self.before = None
159+
self.before_elt = None
160+
self.route_cmds = list()
161+
self.params_to_delete = list()
162+
163+
##############################
164+
# params processing
165+
#
166+
def _params_to_obj(self):
167+
""" return a dict from module params """
168+
params = self.params
169+
170+
obj = self.pfsense.element_to_dict(self.root_elt)
171+
self.before = deepcopy(obj)
172+
self.before_elt = deepcopy(self.root_elt)
173+
modules = obj['modules']
174+
175+
def _set_param(target, param):
176+
if params.get(param) is not None:
177+
if isinstance(params[param], str):
178+
target[param] = params[param]
179+
else:
180+
target[param] = str(params[param])
181+
182+
def _set_param_bool(target, param):
183+
if params.get(param) is not None:
184+
value = params.get(param)
185+
if value is True and param not in target:
186+
target[param] = ''
187+
elif value is False and param in target:
188+
del target[param]
189+
190+
def _set_param_list(target, param):
191+
if params.get(param) is not None:
192+
target[param] = ','.join(params[param])
193+
194+
_set_param_bool(obj, 'enable')
195+
_set_param(obj, 'pollport')
196+
_set_param(obj, 'syslocation')
197+
_set_param(obj, 'syscontact')
198+
_set_param(obj, 'rocommunity')
199+
_set_param_bool(obj, 'trapenable')
200+
_set_param(obj, 'trapserver')
201+
_set_param(obj, 'trapserverport')
202+
_set_param(obj, 'trapstring')
203+
_set_param_bool(modules, 'mibii')
204+
_set_param_bool(modules, 'netgraph')
205+
_set_param_bool(modules, 'pf')
206+
_set_param_bool(modules, 'hostres')
207+
_set_param_bool(modules, 'ucd')
208+
_set_param_bool(modules, 'regex')
209+
_set_param_list(obj, 'bindip')
210+
211+
return obj
212+
213+
214+
def _validate_params(self):
215+
""" do some extra checks on input parameters """
216+
pass
217+
218+
##############################
219+
# XML processing
220+
#
221+
def _remove_deleted_params(self):
222+
""" Remove from target_elt a few deleted params """
223+
changed = False
224+
for param in SNMP_ARGUMENT_SPEC:
225+
if SNMP_ARGUMENT_SPEC[param]['type'] == 'bool':
226+
if param in modules:
227+
continue
228+
if self.pfsense.remove_deleted_param_from_elt(self.target_elt, param, self.obj):
229+
changed = True
230+
231+
modules_elt = self.target_elt.find('modules')
232+
_modules = self.obj['modules']
233+
for param in modules:
234+
if self.pfsense.remove_deleted_param_from_elt(modules_elt, param, _modules):
235+
changed = True
236+
237+
return changed
238+
239+
##############################
240+
# run
241+
#
242+
def run(self, params):
243+
""" process input params to add/update/delete """
244+
self.params = params
245+
self.target_elt = self.root_elt
246+
self._validate_params()
247+
self.obj = self._params_to_obj()
248+
self._add()
249+
250+
def _update(self):
251+
""" make the target pfsense reload """
252+
for cmd in self.route_cmds:
253+
self.module.run_command(cmd)
254+
255+
cmd = '''
256+
require_once("functions.inc");
257+
$retval = 0;
258+
$retval |= services_snmpd_configure();'''
259+
260+
return self.pfsense.phpshell(cmd)
261+
262+
##############################
263+
# Logging
264+
#
265+
@staticmethod
266+
def _get_obj_name():
267+
""" return obj's name """
268+
return "snmp"
269+
270+
def _log_fields(self, before=None):
271+
""" generate pseudo-CLI command fields parameters to create an obj """
272+
values = ''
273+
274+
for param in SNMP_ARGUMENT_SPEC:
275+
if param in modules:
276+
continue
277+
if SNMP_ARGUMENT_SPEC[param]['type'] == 'bool':
278+
values += self.format_updated_cli_field(self.obj, self.before, param, fvalue=self.fvalue_bool, add_comma=(values), log_none=False)
279+
else:
280+
values += self.format_updated_cli_field(self.obj, self.before, param, add_comma=(values), log_none=False)
281+
282+
for param in modules:
283+
values += self.format_updated_cli_field(self.obj['modules'], self.before['modules'], param, fvalue=self.fvalue_bool, add_comma=(values), log_none=False)
284+
285+
return values
286+
287+
288+
def main():
289+
module = AnsibleModule(
290+
argument_spec=SNMP_ARGUMENT_SPEC,
291+
supports_check_mode=True)
292+
293+
pfmodule = PFSenseSnmpModule(module)
294+
pfmodule.run(module.params)
295+
pfmodule.commit_changes()
296+
297+
298+
if __name__ == '__main__':
299+
main()

0 commit comments

Comments
 (0)