1#!/usr/bin/python
2
3# (c) 2018-2019, NetApp Inc.
4# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
5
6from __future__ import absolute_import, division, print_function
7
8__metaclass__ = type
9
10ANSIBLE_METADATA = {'metadata_version': '1.1',
11                    'status': ['preview'],
12                    'supported_by': 'certified'}
13
14DOCUMENTATION = '''
15module: na_ontap_vscan
16short_description: NetApp ONTAP Vscan enable/disable.
17extends_documentation_fragment:
18    - netapp.na_ontap
19version_added: '2.9'
20author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com>
21notes:
22- on demand task, on_access_policy and scanner_pools must be set up before running this module
23description:
24- Enable and Disable Vscan
25options:
26  enable:
27    description:
28    - Whether to enable to disable a Vscan
29    type: bool
30    default: True
31
32  vserver:
33    description:
34    - the name of the data vserver to use.
35    required: true
36    type: str
37'''
38
39EXAMPLES = """
40    - name: Enable Vscan
41      na_ontap_vscan:
42        enable: True
43        username: '{{ netapp_username }}'
44        password: '{{ netapp_password }}'
45        hostname: '{{ netapp_hostname }}'
46        vserver: trident_svm
47
48    - name: Disable Vscan
49      na_ontap_vscan:
50        enable: False
51        username: '{{ netapp_username }}'
52        password: '{{ netapp_password }}'
53        hostname: '{{ netapp_hostname }}'
54        vserver: trident_svm
55"""
56
57RETURN = """
58
59"""
60
61import traceback
62
63from ansible.module_utils.basic import AnsibleModule
64from ansible.module_utils._text import to_native
65import ansible.module_utils.netapp as netapp_utils
66from ansible.module_utils.netapp import OntapRestAPI
67from ansible.module_utils.netapp_module import NetAppModule
68
69HAS_NETAPP_LIB = netapp_utils.has_netapp_lib()
70
71
72class NetAppOntapVscan(object):
73    def __init__(self):
74        self.use_rest = False
75        self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
76        self.argument_spec.update(dict(
77            enable=dict(type='bool', default=True),
78            vserver=dict(required=True, type='str'),
79        ))
80        self.module = AnsibleModule(
81            argument_spec=self.argument_spec,
82            supports_check_mode=True
83        )
84        self.na_helper = NetAppModule()
85        self.parameters = self.na_helper.set_parameters(self.module.params)
86
87        # API should be used for ONTAP 9.6 or higher, Zapi for lower version
88        self.restApi = OntapRestAPI(self.module)
89        if self.restApi.is_rest():
90            self.use_rest = True
91        else:
92            if HAS_NETAPP_LIB is False:
93                self.module.fail_json(msg="the python NetApp-Lib module is required")
94            else:
95                self.server = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=self.parameters['vserver'])
96
97    def get_vscan(self):
98        if self.use_rest:
99            params = {'fields': 'svm,enabled',
100                      "svm.name": self.parameters['vserver']}
101            api = "protocols/vscan"
102            message, error = self.restApi.get(api, params)
103            if error:
104                self.module.fail_json(msg=error)
105            return message['records'][0]
106        else:
107            vscan_status_iter = netapp_utils.zapi.NaElement('vscan-status-get-iter')
108            vscan_status_info = netapp_utils.zapi.NaElement('vscan-status-info')
109            vscan_status_info.add_new_child('vserver', self.parameters['vserver'])
110            query = netapp_utils.zapi.NaElement('query')
111            query.add_child_elem(vscan_status_info)
112            vscan_status_iter.add_child_elem(query)
113            try:
114                result = self.server.invoke_successfully(vscan_status_iter, True)
115            except netapp_utils.zapi.NaApiError as error:
116                self.module.fail_json(msg='Error getting Vscan info for Vserver %s: %s' %
117                                          (self.parameters['vserver'], to_native(error)),
118                                      exception=traceback.format_exc())
119            if result.get_child_by_name('num-records') and int(result.get_child_content('num-records')) >= 1:
120                return result.get_child_by_name('attributes-list').get_child_by_name('vscan-status-info')
121
122    def enable_vscan(self, uuid=None):
123        if self.use_rest:
124            params = {"svm.name": self.parameters['vserver']}
125            data = {"enabled": self.parameters['enable']}
126            api = "protocols/vscan/" + uuid
127            message, error = self.restApi.patch(api, data, params)
128            if error is not None:
129                self.module.fail_json(msg=error)
130                # self.module.fail_json(msg=repr(self.restApi.errors), log=repr(self.restApi.debug_logs))
131        else:
132            vscan_status_obj = netapp_utils.zapi.NaElement("vscan-status-modify")
133            vscan_status_obj.add_new_child('is-vscan-enabled', str(self.parameters['enable']))
134            try:
135                self.server.invoke_successfully(vscan_status_obj, True)
136            except netapp_utils.zapi.NaApiError as error:
137                self.module.fail_json(msg="Error Enable/Disabling Vscan: %s" % to_native(error), exception=traceback.format_exc())
138
139    def asup_log(self):
140        if self.use_rest:
141            # TODO: logging for Rest
142            return
143        else:
144            # Either we are using ZAPI, or REST failed when it should not
145            try:
146                netapp_utils.ems_log_event("na_ontap_vscan", self.server)
147            except Exception:
148                # TODO: we may fail to connect to REST or ZAPI, the line below shows REST issues only
149                # self.module.fail_json(msg=repr(self.restApi.errors), log=repr(self.restApi.debug_logs))
150                pass
151
152    def apply(self):
153        changed = False
154        self.asup_log()
155        current = self.get_vscan()
156        if self.use_rest:
157            if current['enabled'] != self.parameters['enable']:
158                if not self.module.check_mode:
159                    self.enable_vscan(current['svm']['uuid'])
160                changed = True
161        else:
162            if current.get_child_content('is-vscan-enabled') != str(self.parameters['enable']).lower():
163                if not self.module.check_mode:
164                    self.enable_vscan()
165                changed = True
166        self.module.exit_json(changed=changed)
167
168
169def main():
170    """
171    Execute action from playbook
172    """
173    command = NetAppOntapVscan()
174    command.apply()
175
176
177if __name__ == '__main__':
178    main()
179