1#!/usr/local/bin/python3.8 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__metaclass__ = type 8 9 10ANSIBLE_METADATA = {'metadata_version': '1.1', 11 'status': ['preview'], 12 'supported_by': 'certified'} 13 14 15DOCUMENTATION = ''' 16 17module: na_ontap_user_role 18 19short_description: NetApp ONTAP user role configuration and management 20extends_documentation_fragment: 21 - netapp.ontap.netapp.na_ontap 22version_added: 2.6.0 23author: NetApp Ansible Team (@carchi8py) <ng-ansibleteam@netapp.com> 24 25description: 26- Create or destroy user roles 27 28options: 29 30 state: 31 description: 32 - Whether the specified user should exist or not. 33 choices: ['present', 'absent'] 34 type: str 35 default: present 36 37 name: 38 description: 39 - The name of the role to manage. 40 required: true 41 type: str 42 43 command_directory_name: 44 description: 45 - The command or command directory to which the role has an access. 46 required: true 47 type: str 48 49 access_level: 50 description: 51 - The name of the role to manage. 52 choices: ['none', 'readonly', 'all'] 53 type: str 54 default: all 55 56 query: 57 description: 58 - A query for the role. The query must apply to the specified command or directory name. 59 - Use double quotes "" for modifying a existing query to none. 60 type: str 61 version_added: 2.8.0 62 63 vserver: 64 description: 65 - The name of the vserver to use. 66 type: str 67 required: true 68 69''' 70 71EXAMPLES = """ 72 73 - name: Create User Role 74 na_ontap_user_role: 75 state: present 76 name: ansibleRole 77 command_directory_name: volume 78 access_level: none 79 query: show 80 vserver: ansibleVServer 81 hostname: "{{ netapp_hostname }}" 82 username: "{{ netapp_username }}" 83 password: "{{ netapp_password }}" 84 85 - name: Modify User Role 86 na_ontap_user_role: 87 state: present 88 name: ansibleRole 89 command_directory_name: volume 90 access_level: none 91 query: "" 92 vserver: ansibleVServer 93 hostname: "{{ netapp_hostname }}" 94 username: "{{ netapp_username }}" 95 password: "{{ netapp_password }}" 96 97""" 98 99RETURN = """ 100 101""" 102import traceback 103 104from ansible.module_utils.basic import AnsibleModule 105from ansible.module_utils._text import to_native 106from ansible_collections.netapp.ontap.plugins.module_utils.netapp_module import NetAppModule 107import ansible_collections.netapp.ontap.plugins.module_utils.netapp as netapp_utils 108 109 110HAS_NETAPP_LIB = netapp_utils.has_netapp_lib() 111 112 113class NetAppOntapUserRole(object): 114 115 def __init__(self): 116 self.argument_spec = netapp_utils.na_ontap_host_argument_spec() 117 self.argument_spec.update(dict( 118 state=dict(required=False, type='str', choices=['present', 'absent'], default='present'), 119 name=dict(required=True, type='str'), 120 command_directory_name=dict(required=True, type='str'), 121 access_level=dict(required=False, type='str', default='all', 122 choices=['none', 'readonly', 'all']), 123 vserver=dict(required=True, type='str'), 124 query=dict(required=False, type='str') 125 )) 126 127 self.module = AnsibleModule( 128 argument_spec=self.argument_spec, 129 supports_check_mode=True 130 ) 131 self.na_helper = NetAppModule() 132 self.parameters = self.na_helper.set_parameters(self.module.params) 133 134 if HAS_NETAPP_LIB is False: 135 self.module.fail_json(msg="the python NetApp-Lib module is required") 136 else: 137 self.server = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=self.parameters['vserver']) 138 139 def get_role(self): 140 """ 141 Checks if the role exists for specific command-directory-name. 142 143 :return: 144 True if role found 145 False if role is not found 146 :rtype: bool 147 """ 148 options = {'vserver': self.parameters['vserver'], 149 'role-name': self.parameters['name'], 150 'command-directory-name': self.parameters['command_directory_name']} 151 152 security_login_role_get_iter = netapp_utils.zapi.NaElement( 153 'security-login-role-get-iter') 154 query_details = netapp_utils.zapi.NaElement.create_node_with_children( 155 'security-login-role-info', **options) 156 query = netapp_utils.zapi.NaElement('query') 157 query.add_child_elem(query_details) 158 security_login_role_get_iter.add_child_elem(query) 159 160 try: 161 result = self.server.invoke_successfully( 162 security_login_role_get_iter, enable_tunneling=False) 163 except netapp_utils.zapi.NaApiError as e: 164 # Error 16031 denotes a role not being found. 165 if to_native(e.code) == "16031": 166 return None 167 # Error 16039 denotes command directory not found. 168 elif to_native(e.code) == "16039": 169 return None 170 else: 171 self.module.fail_json(msg='Error getting role %s: %s' % (self.name, to_native(e)), 172 exception=traceback.format_exc()) 173 if (result.get_child_by_name('num-records') and 174 int(result.get_child_content('num-records')) >= 1): 175 role_info = result.get_child_by_name('attributes-list').get_child_by_name('security-login-role-info') 176 result = { 177 'name': role_info['role-name'], 178 'access_level': role_info['access-level'], 179 'command_directory_name': role_info['command-directory-name'], 180 'query': role_info['role-query'] 181 } 182 return result 183 184 return None 185 186 def create_role(self): 187 options = {'vserver': self.parameters['vserver'], 188 'role-name': self.parameters['name'], 189 'command-directory-name': self.parameters['command_directory_name'], 190 'access-level': self.parameters['access_level']} 191 if self.parameters.get('query'): 192 options['role-query'] = self.parameters['query'] 193 role_create = netapp_utils.zapi.NaElement.create_node_with_children('security-login-role-create', **options) 194 195 try: 196 self.server.invoke_successfully(role_create, 197 enable_tunneling=False) 198 except netapp_utils.zapi.NaApiError as error: 199 self.module.fail_json(msg='Error creating role %s: %s' % (self.parameters['name'], to_native(error)), 200 exception=traceback.format_exc()) 201 202 def delete_role(self): 203 role_delete = netapp_utils.zapi.NaElement.create_node_with_children( 204 'security-login-role-delete', **{'vserver': self.parameters['vserver'], 205 'role-name': self.parameters['name'], 206 'command-directory-name': 207 self.parameters['command_directory_name']}) 208 209 try: 210 self.server.invoke_successfully(role_delete, 211 enable_tunneling=False) 212 except netapp_utils.zapi.NaApiError as error: 213 self.module.fail_json(msg='Error removing role %s: %s' % (self.parameters['name'], to_native(error)), 214 exception=traceback.format_exc()) 215 216 def modify_role(self, modify): 217 options = {'vserver': self.parameters['vserver'], 218 'role-name': self.parameters['name'], 219 'command-directory-name': self.parameters['command_directory_name']} 220 if 'access_level' in modify.keys(): 221 options['access-level'] = self.parameters['access_level'] 222 if 'query' in modify.keys(): 223 options['role-query'] = self.parameters['query'] 224 225 role_modify = netapp_utils.zapi.NaElement.create_node_with_children('security-login-role-modify', **options) 226 227 try: 228 self.server.invoke_successfully(role_modify, 229 enable_tunneling=False) 230 except netapp_utils.zapi.NaApiError as error: 231 self.module.fail_json(msg='Error modifying role %s: %s' % (self.parameters['name'], to_native(error)), 232 exception=traceback.format_exc()) 233 234 def apply(self): 235 self.asup_log_for_cserver('na_ontap_user_role') 236 current = self.get_role() 237 cd_action = self.na_helper.get_cd_action(current, self.parameters) 238 239 # if desired state specify empty quote query and current query is None, set desired query to None. 240 # otherwise na_helper.get_modified_attributes will detect a change. 241 if self.parameters.get('query') == '' and current is not None: 242 if current['query'] is None: 243 self.parameters['query'] = None 244 245 modify = self.na_helper.get_modified_attributes(current, self.parameters) 246 if self.na_helper.changed: 247 if self.module.check_mode: 248 pass 249 else: 250 if cd_action == 'create': 251 self.create_role() 252 elif cd_action == 'delete': 253 self.delete_role() 254 elif modify: 255 self.modify_role(modify) 256 self.module.exit_json(changed=self.na_helper.changed) 257 258 def asup_log_for_cserver(self, event_name): 259 """ 260 Fetch admin vserver for the given cluster 261 Create and Autosupport log event with the given module name 262 :param event_name: Name of the event log 263 :return: None 264 """ 265 netapp_utils.ems_log_event(event_name, self.server) 266 267 268def main(): 269 obj = NetAppOntapUserRole() 270 obj.apply() 271 272 273if __name__ == '__main__': 274 main() 275