1#!/usr/bin/python
2#
3# This file is part of Ansible
4#
5# Ansible is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Ansible is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17#
18
19ANSIBLE_METADATA = {'metadata_version': '1.1',
20                    'status': ['preview'],
21                    'supported_by': 'community'}
22
23DOCUMENTATION = '''
24---
25module: ce_snmp_target_host
26version_added: "2.4"
27short_description: Manages SNMP target host configuration on HUAWEI CloudEngine switches.
28description:
29    - Manages SNMP target host configurations on HUAWEI CloudEngine switches.
30author:
31    - wangdezhuang (@QijunPan)
32notes:
33    - This module requires the netconf system service be enabled on the remote device being managed.
34    - Recommended connection is C(netconf).
35    - This module also works with C(local) connections for legacy playbooks.
36options:
37    version:
38        description:
39            - Version(s) Supported by SNMP Engine.
40        choices: ['none', 'v1', 'v2c', 'v3', 'v1v2c', 'v1v3', 'v2cv3', 'all']
41    connect_port:
42        description:
43            - Udp port used by SNMP agent to connect the Network management.
44    host_name:
45        description:
46            - Unique name to identify target host entry.
47    address:
48        description:
49            - Network Address.
50    notify_type:
51        description:
52            - To configure notify type as trap or inform.
53        choices: ['trap','inform']
54    vpn_name:
55        description:
56            - VPN instance Name.
57    recv_port:
58        description:
59            - UDP Port number used by network management to receive alarm messages.
60    security_model:
61        description:
62            - Security Model.
63        choices: ['v1','v2c', 'v3']
64    security_name:
65        description:
66            - Security Name.
67    security_name_v3:
68        description:
69            - Security Name V3.
70    security_level:
71        description:
72            - Security level indicating whether to use authentication and encryption.
73        choices: ['noAuthNoPriv','authentication', 'privacy']
74    is_public_net:
75        description:
76            - To enable or disable Public Net-manager for target Host.
77        default: no_use
78        choices: ['no_use','true','false']
79    interface_name:
80        description:
81            - Name of the interface to send the trap message.
82'''
83
84EXAMPLES = '''
85
86- name: CloudEngine snmp target host test
87  hosts: cloudengine
88  connection: local
89  gather_facts: no
90  vars:
91    cli:
92      host: "{{ inventory_hostname }}"
93      port: "{{ ansible_ssh_port }}"
94      username: "{{ username }}"
95      password: "{{ password }}"
96      transport: cli
97
98  tasks:
99
100  - name: "Config SNMP version"
101    ce_snmp_target_host:
102      state: present
103      version: v2cv3
104      provider: "{{ cli }}"
105
106  - name: "Config SNMP target host"
107    ce_snmp_target_host:
108      state: present
109      host_name: test1
110      address: 1.1.1.1
111      notify_type: trap
112      vpn_name: js
113      security_model: v2c
114      security_name: wdz
115      provider: "{{ cli }}"
116'''
117
118RETURN = '''
119changed:
120    description: check to see if a change was made on the device
121    returned: always
122    type: bool
123    sample: true
124proposed:
125    description: k/v pairs of parameters passed into module
126    returned: always
127    type: dict
128    sample: {"address": "10.135.182.158", "host_name": "test2",
129             "notify_type": "trap", "security_level": "authentication",
130             "security_model": "v3", "security_name_v3": "wdz",
131             "state": "present", "vpn_name": "js"}
132existing:
133    description: k/v pairs of existing aaa server
134    returned: always
135    type: dict
136    sample: {}
137end_state:
138    description: k/v pairs of aaa params after module execution
139    returned: always
140    type: dict
141    sample: {"target host info": [{"address": "10.135.182.158", "domain": "snmpUDPDomain",
142                                   "nmsName": "test2", "notifyType": "trap",
143                                   "securityLevel": "authentication", "securityModel": "v3",
144                                   "securityNameV3": "wdz", "vpnInstanceName": "js"}]}
145updates:
146    description: command sent to the device
147    returned: always
148    type: list
149    sample: ["snmp-agent target-host host-name test2 trap address udp-domain 10.135.182.158 vpn-instance js params securityname wdz v3 authentication"]
150'''
151
152from xml.etree import ElementTree
153from ansible.module_utils.basic import AnsibleModule
154from ansible.module_utils.network.cloudengine.ce import get_nc_config, set_nc_config, \
155    ce_argument_spec, load_config, check_ip_addr
156
157# get snmp version
158CE_GET_SNMP_VERSION = """
159    <filter type="subtree">
160      <snmp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
161        <engine>
162          <version></version>
163        </engine>
164      </snmp>
165    </filter>
166"""
167# merge snmp version
168CE_MERGE_SNMP_VERSION = """
169    <config>
170      <snmp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
171        <engine operation="merge">
172          <version>%s</version>
173        </engine>
174      </snmp>
175    </config>
176"""
177
178# get snmp target host
179CE_GET_SNMP_TARGET_HOST_HEADER = """
180    <filter type="subtree">
181      <snmp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
182        <targetHosts>
183          <targetHost>
184            <nmsName></nmsName>
185"""
186CE_GET_SNMP_TARGET_HOST_TAIL = """
187          </targetHost>
188        </targetHosts>
189      </snmp>
190    </filter>
191"""
192
193# merge snmp target host
194CE_MERGE_SNMP_TARGET_HOST_HEADER = """
195    <config>
196      <snmp xmlns="http://www.huawei.com/netconf/vrp" format-version="1.0" content-version="1.0">
197        <targetHosts>
198          <targetHost operation="merge">
199            <nmsName>%s</nmsName>
200"""
201CE_MERGE_SNMP_TARGET_HOST_TAIL = """
202          </targetHost>
203        </targetHosts>
204      </snmp>
205    </config>
206"""
207
208# create snmp target host
209CE_CREATE_SNMP_TARGET_HOST_HEADER = """
210    <config>
211      <snmp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
212        <targetHosts>
213          <targetHost operation="create">
214            <nmsName>%s</nmsName>
215"""
216CE_CREATE_SNMP_TARGET_HOST_TAIL = """
217          </targetHost>
218        </targetHosts>
219      </snmp>
220    </config>
221"""
222
223# delete snmp target host
224CE_DELETE_SNMP_TARGET_HOST_HEADER = """
225    <config>
226      <snmp xmlns="http://www.huawei.com/netconf/vrp" format-version="1.0" content-version="1.0">
227        <targetHosts>
228          <targetHost operation="delete">
229            <nmsName>%s</nmsName>
230"""
231CE_DELETE_SNMP_TARGET_HOST_TAIL = """
232          </targetHost>
233        </targetHosts>
234      </snmp>
235    </config>
236"""
237
238# get snmp listen port
239CE_GET_SNMP_PORT = """
240    <filter type="subtree">
241      <snmp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
242        <systemCfg>
243          <snmpListenPort></snmpListenPort>
244        </systemCfg>
245      </snmp>
246    </filter>
247"""
248
249# merge snmp listen port
250CE_MERGE_SNMP_PORT = """
251    <config>
252      <snmp xmlns="http://www.huawei.com/netconf/vrp" content-version="1.0" format-version="1.0">
253        <systemCfg operation="merge">
254          <snmpListenPort>%s</snmpListenPort>
255        </systemCfg>
256      </snmp>
257    </config>
258"""
259
260
261INTERFACE_TYPE = ['ethernet', 'eth-trunk', 'tunnel', 'null', 'loopback',
262                  'vlanif', '100ge', '40ge', 'mtunnel', '10ge', 'ge', 'meth', 'vbdif', 'nve']
263
264
265class SnmpTargetHost(object):
266    """ Manages SNMP target host configuration """
267
268    def __init__(self, **kwargs):
269        """ Class init """
270
271        # module
272        argument_spec = kwargs["argument_spec"]
273        self.spec = argument_spec
274        required_together = [("address", "notify_type"), ("address", "notify_type")]
275        required_if = [
276            ["security_model", "v1", ["security_name"]],
277            ["security_model", "v2c", ["security_name"]],
278            ["security_model", "v3", ["security_name_v3"]]
279        ]
280        self.module = AnsibleModule(
281            argument_spec=argument_spec,
282            required_together=required_together,
283            required_if=required_if,
284            supports_check_mode=True
285        )
286
287        # module args
288        self.state = self.module.params['state']
289        self.version = self.module.params['version']
290        self.connect_port = self.module.params['connect_port']
291        self.host_name = self.module.params['host_name']
292        self.domain = "snmpUDPDomain"
293        self.address = self.module.params['address']
294        self.notify_type = self.module.params['notify_type']
295        self.vpn_name = self.module.params['vpn_name']
296        self.recv_port = self.module.params['recv_port']
297        self.security_model = self.module.params['security_model']
298        self.security_name = self.module.params['security_name']
299        self.security_name_v3 = self.module.params['security_name_v3']
300        self.security_level = self.module.params['security_level']
301        self.is_public_net = self.module.params['is_public_net']
302        self.interface_name = self.module.params['interface_name']
303
304        # config
305        self.cur_cli_cfg = dict()
306        self.cur_netconf_cfg = dict()
307        self.end_netconf_cfg = dict()
308
309        # state
310        self.changed = False
311        self.updates_cmd = list()
312        self.results = dict()
313        self.proposed = dict()
314        self.existing = dict()
315        self.end_state = dict()
316
317    def netconf_get_config(self, conf_str):
318        """ Get configure by netconf """
319
320        xml_str = get_nc_config(self.module, conf_str)
321
322        return xml_str
323
324    def netconf_set_config(self, conf_str):
325        """ Set configure by netconf """
326
327        xml_str = set_nc_config(self.module, conf_str)
328
329        return xml_str
330
331    def check_cli_args(self):
332        """ Check invalid cli args """
333
334        if self.connect_port:
335            if int(self.connect_port) != 161 and (int(self.connect_port) > 65535 or int(self.connect_port) < 1025):
336                self.module.fail_json(
337                    msg='Error: The value of connect_port %s is out of [161, 1025 - 65535].' % self.connect_port)
338
339    def check_netconf_args(self, result):
340        """ Check invalid netconf args """
341
342        need_cfg = True
343        same_flag = True
344        delete_flag = False
345        result["target_host_info"] = []
346
347        if self.host_name:
348
349            if len(self.host_name) > 32 or len(self.host_name) < 1:
350                self.module.fail_json(
351                    msg='Error: The len of host_name is out of [1 - 32].')
352
353            if self.vpn_name and self.is_public_net != 'no_use':
354                if self.is_public_net == "true":
355                    self.module.fail_json(
356                        msg='Error: Do not support vpn_name and is_public_net at the same time.')
357
358            conf_str = CE_GET_SNMP_TARGET_HOST_HEADER
359
360            if self.domain:
361                conf_str += "<domain></domain>"
362
363            if self.address:
364                if not check_ip_addr(ipaddr=self.address):
365                    self.module.fail_json(
366                        msg='Error: The host address [%s] is invalid.' % self.address)
367                conf_str += "<address></address>"
368
369            if self.notify_type:
370                conf_str += "<notifyType></notifyType>"
371
372            if self.vpn_name:
373                if len(self.vpn_name) > 31 or len(self.vpn_name) < 1:
374                    self.module.fail_json(
375                        msg='Error: The len of vpn_name is out of [1 - 31].')
376                conf_str += "<vpnInstanceName></vpnInstanceName>"
377
378            if self.recv_port:
379                if int(self.recv_port) > 65535 or int(self.recv_port) < 0:
380                    self.module.fail_json(
381                        msg='Error: The value of recv_port is out of [0 - 65535].')
382                conf_str += "<portNumber></portNumber>"
383
384            if self.security_model:
385                conf_str += "<securityModel></securityModel>"
386
387            if self.security_name:
388                if len(self.security_name) > 32 or len(self.security_name) < 1:
389                    self.module.fail_json(
390                        msg='Error: The len of security_name is out of [1 - 32].')
391                conf_str += "<securityName></securityName>"
392
393            if self.security_name_v3:
394                if len(self.security_name_v3) > 32 or len(self.security_name_v3) < 1:
395                    self.module.fail_json(
396                        msg='Error: The len of security_name_v3 is out of [1 - 32].')
397                conf_str += "<securityNameV3></securityNameV3>"
398
399            if self.security_level:
400                conf_str += "<securityLevel></securityLevel>"
401
402            if self.is_public_net != 'no_use':
403                conf_str += "<isPublicNet></isPublicNet>"
404
405            if self.interface_name:
406                if len(self.interface_name) > 63 or len(self.interface_name) < 1:
407                    self.module.fail_json(
408                        msg='Error: The len of interface_name is out of [1 - 63].')
409
410                find_flag = False
411                for item in INTERFACE_TYPE:
412                    if item in self.interface_name.lower():
413                        find_flag = True
414                        break
415                if not find_flag:
416                    self.module.fail_json(
417                        msg='Error: Please input full name of interface_name.')
418
419                conf_str += "<interface-name></interface-name>"
420
421            conf_str += CE_GET_SNMP_TARGET_HOST_TAIL
422            recv_xml = self.netconf_get_config(conf_str=conf_str)
423
424            if "<data/>" in recv_xml:
425                if self.state == "present":
426                    same_flag = False
427                else:
428                    delete_flag = False
429            else:
430                xml_str = recv_xml.replace('\r', '').replace('\n', '').\
431                    replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
432                    replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
433
434                root = ElementTree.fromstring(xml_str)
435                target_host_info = root.findall(
436                    "snmp/targetHosts/targetHost")
437                if target_host_info:
438                    for tmp in target_host_info:
439                        tmp_dict = dict()
440                        for site in tmp:
441                            if site.tag in ["nmsName", "domain", "address", "notifyType", "vpnInstanceName",
442                                            "portNumber", "securityModel", "securityName", "securityNameV3",
443                                            "securityLevel", "isPublicNet", "interface-name"]:
444                                tmp_dict[site.tag] = site.text
445
446                        result["target_host_info"].append(tmp_dict)
447
448                if result["target_host_info"]:
449                    for tmp in result["target_host_info"]:
450
451                        same_flag = True
452
453                        if "nmsName" in tmp.keys():
454                            if tmp["nmsName"] != self.host_name:
455                                same_flag = False
456                            else:
457                                delete_flag = True
458
459                        if "domain" in tmp.keys():
460                            if tmp["domain"] != self.domain:
461                                same_flag = False
462
463                        if "address" in tmp.keys():
464                            if tmp["address"] != self.address:
465                                same_flag = False
466
467                        if "notifyType" in tmp.keys():
468                            if tmp["notifyType"] != self.notify_type:
469                                same_flag = False
470
471                        if "vpnInstanceName" in tmp.keys():
472                            if tmp["vpnInstanceName"] != self.vpn_name:
473                                same_flag = False
474
475                        if "portNumber" in tmp.keys():
476                            if tmp["portNumber"] != self.recv_port:
477                                same_flag = False
478
479                        if "securityModel" in tmp.keys():
480                            if tmp["securityModel"] != self.security_model:
481                                same_flag = False
482
483                        if "securityName" in tmp.keys():
484                            if tmp["securityName"] != self.security_name:
485                                same_flag = False
486
487                        if "securityNameV3" in tmp.keys():
488                            if tmp["securityNameV3"] != self.security_name_v3:
489                                same_flag = False
490
491                        if "securityLevel" in tmp.keys():
492                            if tmp["securityLevel"] != self.security_level:
493                                same_flag = False
494
495                        if "isPublicNet" in tmp.keys():
496                            if tmp["isPublicNet"] != self.is_public_net:
497                                same_flag = False
498
499                        if "interface-name" in tmp.keys():
500                            if tmp.get("interface-name") is not None:
501                                if tmp["interface-name"].lower() != self.interface_name.lower():
502                                    same_flag = False
503                            else:
504                                same_flag = False
505
506                        if same_flag:
507                            break
508
509        if self.state == "present":
510            need_cfg = True
511            if same_flag:
512                need_cfg = False
513        else:
514            need_cfg = False
515            if delete_flag:
516                need_cfg = True
517
518        result["need_cfg"] = need_cfg
519
520    def cli_load_config(self, commands):
521        """ Load configure by cli """
522
523        if not self.module.check_mode:
524            load_config(self.module, commands)
525
526    def get_snmp_version(self):
527        """ Get snmp version """
528
529        version = None
530        conf_str = CE_GET_SNMP_VERSION
531        recv_xml = self.netconf_get_config(conf_str=conf_str)
532
533        if "<data/>" in recv_xml:
534            pass
535
536        else:
537            xml_str = recv_xml.replace('\r', '').replace('\n', '').\
538                replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
539                replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
540
541            root = ElementTree.fromstring(xml_str)
542            version_info = root.find("snmp/engine")
543            if version_info:
544                for site in version_info:
545                    if site.tag in ["version"]:
546                        version = site.text
547
548        return version
549
550    def xml_get_connect_port(self):
551        """ Get connect port by xml """
552        tmp_cfg = None
553        conf_str = CE_GET_SNMP_PORT
554        recv_xml = self.netconf_get_config(conf_str=conf_str)
555        if "<data/>" in recv_xml:
556            pass
557        else:
558            xml_str = recv_xml.replace('\r', '').replace('\n', '').\
559                replace('xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"', "").\
560                replace('xmlns="http://www.huawei.com/netconf/vrp"', "")
561
562            root = ElementTree.fromstring(xml_str)
563            snmp_port_info = root.findall("snmp/systemCfg/snmpListenPort")
564
565            if snmp_port_info:
566                tmp_cfg = snmp_port_info[0].text
567            return tmp_cfg
568
569    def get_proposed(self):
570        """ Get proposed state """
571
572        self.proposed["state"] = self.state
573
574        if self.version:
575            self.proposed["version"] = self.version
576        if self.connect_port:
577            self.proposed["connect_port"] = self.connect_port
578        if self.host_name:
579            self.proposed["host_name"] = self.host_name
580        if self.address:
581            self.proposed["address"] = self.address
582        if self.notify_type:
583            self.proposed["notify_type"] = self.notify_type
584        if self.vpn_name:
585            self.proposed["vpn_name"] = self.vpn_name
586        if self.recv_port:
587            self.proposed["recv_port"] = self.recv_port
588        if self.security_model:
589            self.proposed["security_model"] = self.security_model
590        if self.security_name:
591            self.proposed["security_name"] = "******"
592        if self.security_name_v3:
593            self.proposed["security_name_v3"] = self.security_name_v3
594        if self.security_level:
595            self.proposed["security_level"] = self.security_level
596        if self.is_public_net != 'no_use':
597            self.proposed["is_public_net"] = self.is_public_net
598        if self.interface_name:
599            self.proposed["interface_name"] = self.interface_name
600
601    def get_existing(self):
602        """ Get existing state """
603
604        if self.version:
605            version = self.get_snmp_version()
606            if version:
607                self.cur_cli_cfg["version"] = version
608                self.existing["version"] = version
609
610        if self.connect_port:
611            tmp_cfg = self.xml_get_connect_port()
612            if tmp_cfg:
613                self.cur_cli_cfg["connect port"] = tmp_cfg
614                self.existing["connect port"] = tmp_cfg
615
616        if self.host_name:
617            self.existing["target host info"] = self.cur_netconf_cfg[
618                "target_host_info"]
619
620    def get_end_state(self):
621        """ Get end state """
622
623        if self.version:
624            version = self.get_snmp_version()
625            if version:
626                self.end_state["version"] = version
627
628        if self.connect_port:
629            tmp_cfg = self.xml_get_connect_port()
630            if tmp_cfg:
631                self.end_state["connect port"] = tmp_cfg
632
633        if self.host_name:
634            self.end_state["target host info"] = self.end_netconf_cfg[
635                "target_host_info"]
636        if self.existing == self.end_state:
637            self.changed = False
638            self.updates_cmd = list()
639
640    def config_version_cli(self):
641        """ Config version by cli """
642
643        if "disable" in self.cur_cli_cfg["version"]:
644            cmd = "snmp-agent sys-info version %s" % self.version
645            self.updates_cmd.append(cmd)
646
647            cmds = list()
648            cmds.append(cmd)
649
650            self.cli_load_config(cmds)
651            self.changed = True
652
653        else:
654            if self.version != self.cur_cli_cfg["version"]:
655                cmd = "snmp-agent sys-info version  %s disable" % self.cur_cli_cfg[
656                    "version"]
657                self.updates_cmd.append(cmd)
658                cmd = "snmp-agent sys-info version  %s" % self.version
659                self.updates_cmd.append(cmd)
660
661                cmds = list()
662                cmds.append(cmd)
663
664                self.cli_load_config(cmds)
665                self.changed = True
666
667    def undo_config_version_cli(self):
668        """ Undo config version by cli """
669
670        if "disable" in self.cur_cli_cfg["version"]:
671            pass
672        else:
673            cmd = "snmp-agent sys-info version  %s disable" % self.cur_cli_cfg[
674                "version"]
675
676            cmds = list()
677            cmds.append(cmd)
678
679            self.updates_cmd.append(cmd)
680            self.cli_load_config(cmds)
681            self.changed = True
682
683    def config_connect_port_xml(self):
684        """ Config connect port by xml """
685
686        if "connect port" in self.cur_cli_cfg.keys():
687            if self.cur_cli_cfg["connect port"] == self.connect_port:
688                pass
689            else:
690                cmd = "snmp-agent udp-port %s" % self.connect_port
691
692                cmds = list()
693                cmds.append(cmd)
694
695                self.updates_cmd.append(cmd)
696                conf_str = CE_MERGE_SNMP_PORT % self.connect_port
697                self.netconf_set_config(conf_str=conf_str)
698                self.changed = True
699        else:
700            cmd = "snmp-agent udp-port %s" % self.connect_port
701
702            cmds = list()
703            cmds.append(cmd)
704
705            self.updates_cmd.append(cmd)
706            conf_str = CE_MERGE_SNMP_PORT % self.connect_port
707            self.netconf_set_config(conf_str=conf_str)
708            self.changed = True
709
710    def undo_config_connect_port_cli(self):
711        """ Undo config connect port by cli """
712
713        if "connect port" in self.cur_cli_cfg.keys():
714            if not self.cur_cli_cfg["connect port"]:
715                pass
716            else:
717                cmd = "undo snmp-agent udp-port"
718
719                cmds = list()
720                cmds.append(cmd)
721
722                self.updates_cmd.append(cmd)
723                connect_port = "161"
724                conf_str = CE_MERGE_SNMP_PORT % connect_port
725                self.netconf_set_config(conf_str=conf_str)
726                self.changed = True
727
728    def merge_snmp_target_host(self):
729        """ Merge snmp target host operation """
730
731        conf_str = CE_MERGE_SNMP_TARGET_HOST_HEADER % self.host_name
732
733        if self.domain:
734            conf_str += "<domain>%s</domain>" % self.domain
735        if self.address:
736            conf_str += "<address>%s</address>" % self.address
737        if self.notify_type:
738            conf_str += "<notifyType>%s</notifyType>" % self.notify_type
739        if self.vpn_name:
740            conf_str += "<vpnInstanceName>%s</vpnInstanceName>" % self.vpn_name
741        if self.recv_port:
742            conf_str += "<portNumber>%s</portNumber>" % self.recv_port
743        if self.security_model:
744            conf_str += "<securityModel>%s</securityModel>" % self.security_model
745        if self.security_name:
746            conf_str += "<securityName>%s</securityName>" % self.security_name
747        if self.security_name_v3:
748            conf_str += "<securityNameV3>%s</securityNameV3>" % self.security_name_v3
749        if self.security_level:
750            conf_str += "<securityLevel>%s</securityLevel>" % self.security_level
751        if self.is_public_net != 'no_use':
752            conf_str += "<isPublicNet>%s</isPublicNet>" % self.is_public_net
753        if self.interface_name:
754            conf_str += "<interface-name>%s</interface-name>" % self.interface_name
755
756        conf_str += CE_MERGE_SNMP_TARGET_HOST_TAIL
757
758        recv_xml = self.netconf_set_config(conf_str=conf_str)
759
760        if "<ok/>" not in recv_xml:
761            self.module.fail_json(msg='Error: Merge snmp target host failed.')
762
763        cmd = "snmp-agent target-host host-name %s " % self.host_name
764        cmd += "%s " % self.notify_type
765        cmd += "address udp-domain %s " % self.address
766
767        if self.recv_port:
768            cmd += "udp-port %s " % self.recv_port
769        if self.interface_name:
770            cmd += "source %s " % self.interface_name
771        if self.vpn_name:
772            cmd += "vpn-instance %s " % self.vpn_name
773        if self.is_public_net == "true":
774            cmd += "public-net "
775        if self.security_model in ["v1", "v2c"] and self.security_name:
776            cmd += "params securityname %s %s " % (
777                "******", self.security_model)
778        if self.security_model == "v3" and self.security_name_v3:
779            cmd += "params securityname %s %s " % (
780                self.security_name_v3, self.security_model)
781            if self.security_level and self.security_level in ["authentication", "privacy"]:
782                cmd += "%s" % self.security_level
783
784        self.changed = True
785        self.updates_cmd.append(cmd)
786
787    def delete_snmp_target_host(self):
788        """ Delete snmp target host operation """
789
790        conf_str = CE_DELETE_SNMP_TARGET_HOST_HEADER % self.host_name
791
792        if self.domain:
793            conf_str += "<domain>%s</domain>" % self.domain
794        if self.address:
795            conf_str += "<address>%s</address>" % self.address
796        if self.notify_type:
797            conf_str += "<notifyType>%s</notifyType>" % self.notify_type
798        if self.vpn_name:
799            conf_str += "<vpnInstanceName>%s</vpnInstanceName>" % self.vpn_name
800        if self.recv_port:
801            conf_str += "<portNumber>%s</portNumber>" % self.recv_port
802        if self.security_model:
803            conf_str += "<securityModel>%s</securityModel>" % self.security_model
804        if self.security_name:
805            conf_str += "<securityName>%s</securityName>" % self.security_name
806        if self.security_name_v3:
807            conf_str += "<securityNameV3>%s</securityNameV3>" % self.security_name_v3
808        if self.security_level:
809            conf_str += "<securityLevel>%s</securityLevel>" % self.security_level
810        if self.is_public_net != 'no_use':
811            conf_str += "<isPublicNet>%s</isPublicNet>" % self.is_public_net
812        if self.interface_name:
813            conf_str += "<interface-name>%s</interface-name>" % self.interface_name
814
815        conf_str += CE_DELETE_SNMP_TARGET_HOST_TAIL
816
817        recv_xml = self.netconf_set_config(conf_str=conf_str)
818
819        if "<ok/>" not in recv_xml:
820            self.module.fail_json(msg='Error: Delete snmp target host failed.')
821
822        if not self.address:
823            cmd = "undo snmp-agent target-host host-name %s " % self.host_name
824        else:
825            if self.notify_type == "trap":
826                cmd = "undo snmp-agent target-host trap address udp-domain %s " % self.address
827            else:
828                cmd = "undo snmp-agent target-host inform address udp-domain %s " % self.address
829            if self.recv_port:
830                cmd += "udp-port %s " % self.recv_port
831            if self.interface_name:
832                cmd += "source %s " % self.interface_name
833            if self.vpn_name:
834                cmd += "vpn-instance %s " % self.vpn_name
835            if self.is_public_net == "true":
836                cmd += "public-net "
837            if self.security_model in ["v1", "v2c"] and self.security_name:
838                cmd += "params securityname %s" % "******"
839            if self.security_model == "v3" and self.security_name_v3:
840                cmd += "params securityname %s" % self.security_name_v3
841
842        self.changed = True
843        self.updates_cmd.append(cmd)
844
845    def merge_snmp_version(self):
846        """ Merge snmp version operation """
847
848        conf_str = CE_MERGE_SNMP_VERSION % self.version
849        recv_xml = self.netconf_set_config(conf_str=conf_str)
850
851        if "<ok/>" not in recv_xml:
852            self.module.fail_json(msg='Error: Merge snmp version failed.')
853
854        if self.version == "none":
855            cmd = "snmp-agent sys-info version %s disable" % self.cur_cli_cfg[
856                "version"]
857            self.updates_cmd.append(cmd)
858        elif self.version == "v1v2c":
859            cmd = "snmp-agent sys-info version v1"
860            self.updates_cmd.append(cmd)
861            cmd = "snmp-agent sys-info version v2c"
862            self.updates_cmd.append(cmd)
863        elif self.version == "v1v3":
864            cmd = "snmp-agent sys-info version v1"
865            self.updates_cmd.append(cmd)
866            cmd = "snmp-agent sys-info version v3"
867            self.updates_cmd.append(cmd)
868        elif self.version == "v2cv3":
869            cmd = "snmp-agent sys-info version v2c"
870            self.updates_cmd.append(cmd)
871            cmd = "snmp-agent sys-info version v3"
872            self.updates_cmd.append(cmd)
873        else:
874            cmd = "snmp-agent sys-info version %s" % self.version
875            self.updates_cmd.append(cmd)
876
877        self.changed = True
878
879    def work(self):
880        """ Main work function """
881
882        self.check_cli_args()
883        self.check_netconf_args(self.cur_netconf_cfg)
884        self.get_proposed()
885        self.get_existing()
886
887        if self.state == "present":
888            if self.version:
889                if self.version != self.cur_cli_cfg["version"]:
890                    self.merge_snmp_version()
891            if self.connect_port:
892                self.config_connect_port_xml()
893            if self.cur_netconf_cfg["need_cfg"]:
894                self.merge_snmp_target_host()
895
896        else:
897            if self.connect_port:
898                self.undo_config_connect_port_cli()
899            if self.cur_netconf_cfg["need_cfg"]:
900                self.delete_snmp_target_host()
901
902        self.check_netconf_args(self.end_netconf_cfg)
903        self.get_end_state()
904
905        self.results['changed'] = self.changed
906        self.results['proposed'] = self.proposed
907        self.results['existing'] = self.existing
908        self.results['end_state'] = self.end_state
909        self.results['updates'] = self.updates_cmd
910
911        self.module.exit_json(**self.results)
912
913
914def main():
915    """ Module main """
916
917    argument_spec = dict(
918        state=dict(choices=['present', 'absent'], default='present'),
919        version=dict(choices=['none', 'v1', 'v2c', 'v3',
920                              'v1v2c', 'v1v3', 'v2cv3', 'all']),
921        connect_port=dict(type='str'),
922        host_name=dict(type='str'),
923        address=dict(type='str'),
924        notify_type=dict(choices=['trap', 'inform']),
925        vpn_name=dict(type='str'),
926        recv_port=dict(type='str'),
927        security_model=dict(choices=['v1', 'v2c', 'v3']),
928        security_name=dict(type='str', no_log=True),
929        security_name_v3=dict(type='str'),
930        security_level=dict(
931            choices=['noAuthNoPriv', 'authentication', 'privacy']),
932        is_public_net=dict(type='str', default='no_use', choices=['no_use', 'true', 'false']),
933        interface_name=dict(type='str')
934    )
935
936    argument_spec.update(ce_argument_spec)
937    module = SnmpTargetHost(argument_spec=argument_spec)
938    module.work()
939
940
941if __name__ == '__main__':
942    main()
943