1#!/usr/local/bin/python3.8 2 3# # Copyright 2020 Hewlett Packard Enterprise Development LP 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 6# file except in compliance with the License. You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software distributed 11# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 12# OF ANY KIND, either express or implied. See the License for the specific 13# language governing permissions and limitations under the License. 14 15# author Alok Ranjan (alok.ranjan2@hpe.com) 16 17from __future__ import absolute_import, division, print_function 18__metaclass__ = type 19 20DOCUMENTATION = r''' 21--- 22author: 23 - HPE Nimble Storage Ansible Team (@ar-india) <nimble-dcs-storage-automation-eng@hpe.com> 24description: Manage the users on an HPE Nimble Storage group. 25module: hpe_nimble_user 26options: 27 auth_password: 28 required: False 29 type: str 30 description: 31 - Authorization password for changing password. 32 change_name: 33 required: False 34 type: str 35 description: 36 - Change name of the existing user. 37 description: 38 required: False 39 type: str 40 description: 41 - Description of the user. 42 disabled: 43 required: False 44 type: bool 45 description: 46 - User is currently disabled. 47 email_addr: 48 required: False 49 type: str 50 description: 51 - Email address of the user. 52 full_name: 53 required: False 54 type: str 55 description: 56 - Fully qualified name of the user. 57 inactivity_timeout: 58 required: False 59 type: int 60 default: 0 61 description: 62 - The amount of time that the user session is inactive before timing out. A value of 0 indicates that the timeout is taken from the group setting. 63 name: 64 required: True 65 type: str 66 description: 67 - Name of the user. 68 user_password: 69 required: False 70 type: str 71 description: 72 - User's login password. 73 role: 74 required: False 75 choices: 76 - administrator 77 - poweruser 78 - operator 79 - guest 80 type: str 81 description: 82 - Role of the user. Default is 'guest'. 83 state: 84 required: True 85 choices: 86 - create 87 - present 88 - absent 89 type: str 90 description: 91 - The user operation. 92 unlock: 93 required: False 94 type: bool 95 description: 96 - Unlock the user. 97extends_documentation_fragment: hpe.nimble.hpe_nimble 98short_description: Manage the HPE Nimble Storage users 99version_added: "1.0.0" 100notes: 101 - This module does not support C(check_mode). 102''' 103 104EXAMPLES = r''' 105 106# if state is create, then create user, fails if it exist or cannot create 107# if state is present, then create user if not present, else success 108- name: Create user 109 hpe.nimble.hpe_nimble_user: 110 host: "{{ host }}" 111 username: "{{ username }}" 112 password: "{{ password }}" 113 name: "{{ name }}" 114 description: "{{ description }}" 115 state: "{{ state | default('present') }}" 116 117- name: Delete user 118 hpe.nimble.hpe_nimble_user: 119 host: "{{ host }}" 120 username: "{{ username }}" 121 password: "{{ password }}" 122 name: "{{ name }}" 123 state: "absent" 124 125- name: Unlock user 126 hpe.nimble.hpe_nimble_user: 127 host: "{{ host }}" 128 username: "{{ username }}" 129 password: "{{ password }}" 130 name: "{{ name }}" 131 state: "present" 132 unlock: true 133 134''' 135RETURN = r''' 136''' 137 138from ansible.module_utils.basic import AnsibleModule 139try: 140 from nimbleclient.v1 import client 141except ImportError: 142 client = None 143from ansible_collections.hpe.nimble.plugins.module_utils.hpe_nimble import __version__ as NIMBLE_ANSIBLE_VERSION 144import ansible_collections.hpe.nimble.plugins.module_utils.hpe_nimble as utils 145 146 147def create_user( 148 client_obj, 149 user_name, 150 password, 151 **kwargs): 152 153 if utils.is_null_or_empty(user_name): 154 return (False, False, "Create user failed as user is not present.", {}, {}) 155 if utils.is_null_or_empty(password): 156 return (False, False, "Create user failed as password is not present.", {}, {}) 157 158 try: 159 user_resp = client_obj.users.get(id=None, name=user_name) 160 if utils.is_null_or_empty(user_resp): 161 params = utils.remove_null_args(**kwargs) 162 user_resp = client_obj.users.create(name=user_name, password=password, **params) 163 return (True, True, f"User '{user_name}' created successfully.", {}, user_resp.attrs) 164 else: 165 return (False, False, f"User '{user_name}' cannot be created as it is already present in given state.", {}, {}) 166 except Exception as ex: 167 return (False, False, f"User creation failed | {ex}", {}, {}) 168 169 170def update_user( 171 client_obj, 172 user_name, 173 **kwargs): 174 175 if utils.is_null_or_empty(user_name): 176 return (False, False, "Update user failed as user is not present.", {}, {}) 177 178 try: 179 user_resp = client_obj.users.get(id=None, name=user_name) 180 if utils.is_null_or_empty(user_resp): 181 return (False, False, f"User '{user_name}' cannot be updated as it is not present.", {}, {}) 182 183 changed_attrs_dict, params = utils.remove_unchanged_or_null_args(user_resp, **kwargs) 184 if changed_attrs_dict.__len__() > 0: 185 user_resp = client_obj.users.update(id=user_resp.attrs.get("id"), **params) 186 return (True, True, f"User '{user_name}' already present. Modified the following attributes '{changed_attrs_dict}'", 187 changed_attrs_dict, user_resp.attrs) 188 else: 189 return (True, False, f"User '{user_resp.attrs.get('name')}' already present in given state.", {}, user_resp.attrs) 190 except Exception as ex: 191 return (False, False, f"User update failed | {ex}", {}, {}) 192 193 194def delete_user( 195 client_obj, 196 user_name): 197 198 if utils.is_null_or_empty(user_name): 199 return (False, False, "Delete user failed as user is not present.", {}) 200 201 try: 202 user_resp = client_obj.users.get(id=None, name=user_name) 203 if utils.is_null_or_empty(user_resp): 204 return (False, False, f"User '{user_name}' cannot be deleted as it is not present.", {}) 205 206 client_obj.users.delete(id=user_resp.attrs.get("id")) 207 return (True, True, f"Deleted user '{user_name}' successfully.", {}) 208 except Exception as ex: 209 return (False, False, f"Delete user failed | {ex}", {}) 210 211 212def unlock_user( 213 client_obj, 214 user_name): 215 216 if utils.is_null_or_empty(user_name): 217 return (False, False, "Unlock user failed as user name is not present.", {}) 218 219 try: 220 user_resp = client_obj.users.get(id=None, name=user_name) 221 if utils.is_null_or_empty(user_resp): 222 return (False, False, f"User '{user_name}' cannot be unlocked as it is not present.", {}) 223 224 client_obj.users.unlock(id=user_resp.attrs.get("id")) 225 return (True, True, f"Unlocked user '{user_name}' successfully.", {}) 226 except Exception as ex: 227 return (False, False, f"Unlock user failed | {ex}", {}) 228 229 230def main(): 231 232 fields = { 233 "state": { 234 "required": True, 235 "choices": ['create', 236 'present', 237 'absent' 238 ], 239 "type": "str" 240 }, 241 "change_name": { 242 "required": False, 243 "type": "str" 244 }, 245 "name": { 246 "required": True, 247 "type": "str" 248 }, 249 "description": { 250 "required": False, 251 "type": "str" 252 }, 253 "role": { 254 "required": False, 255 "choices": ['administrator', 256 'poweruser', 257 'operator', 258 'guest' 259 ], 260 "type": "str" 261 }, 262 "user_password": { 263 "required": False, 264 "type": "str", 265 "no_log": True 266 }, 267 "inactivity_timeout": { 268 "required": False, 269 "type": "int" 270 }, 271 "full_name": { 272 "required": False, 273 "type": "str" 274 }, 275 "email_addr": { 276 "required": False, 277 "type": "str" 278 }, 279 "disabled": { 280 "required": False, 281 "type": "bool" 282 }, 283 "auth_password": { 284 "required": False, 285 "type": "str", 286 "no_log": True 287 }, 288 "unlock": { 289 "required": False, 290 "type": "bool" 291 } 292 } 293 default_fields = utils.basic_auth_arg_fields() 294 fields.update(default_fields) 295 required_if = [('state', 'create', ['user_password'])] 296 297 module = AnsibleModule(argument_spec=fields, required_if=required_if) 298 if client is None: 299 module.fail_json(msg='Python nimble-sdk could not be found.') 300 301 hostname = module.params["host"] 302 username = module.params["username"] 303 password = module.params["password"] 304 state = module.params["state"] 305 user_name = module.params["name"] 306 change_name = module.params["change_name"] 307 description = module.params["description"] 308 role = module.params["role"] 309 user_password = module.params["user_password"] 310 inactivity_timeout = module.params["inactivity_timeout"] 311 full_name = module.params["full_name"] 312 email_addr = module.params["email_addr"] 313 disabled = module.params["disabled"] 314 auth_password = module.params["auth_password"] 315 unlock = module.params["unlock"] 316 317 if (username is None or password is None or hostname is None): 318 module.fail_json( 319 msg="Missing variables: hostname, username and password is mandatory.") 320 321 # defaults 322 return_status = changed = False 323 msg = "No task to run." 324 resp = None 325 try: 326 client_obj = client.NimOSClient( 327 hostname, 328 username, 329 password, 330 f"HPE Nimble Ansible Modules v{NIMBLE_ANSIBLE_VERSION}" 331 ) 332 333 # States 334 if ((unlock is None or unlock is False) and (state == "create" or state == "present")): 335 if not client_obj.users.get(id=None, name=user_name) or state == "create": 336 return_status, changed, msg, changed_attrs_dict, resp = create_user( 337 client_obj, 338 user_name, 339 user_password, 340 description=description, 341 role=role, 342 inactivity_timeout=inactivity_timeout, 343 full_name=full_name, 344 email_addr=email_addr, 345 disabled=disabled) 346 else: 347 # update op 348 return_status, changed, msg, changed_attrs_dict, resp = update_user( 349 client_obj, 350 user_name, 351 name=change_name, 352 password=user_password, 353 description=description, 354 role=role, 355 inactivity_timeout=inactivity_timeout, 356 full_name=full_name, 357 email_addr=email_addr, 358 disabled=disabled, 359 auth_password=auth_password) 360 361 elif state == "absent": 362 return_status, changed, msg, changed_attrs_dict = delete_user(client_obj, user_name) 363 364 elif state == "present" and unlock is True: 365 return_status, changed, msg, changed_attrs_dict = unlock_user(client_obj, user_name) 366 367 except Exception as ex: 368 # failed for some reason. 369 msg = str(ex) 370 371 if return_status: 372 if utils.is_null_or_empty(resp): 373 module.exit_json(return_status=return_status, changed=changed, msg=msg) 374 else: 375 module.exit_json(return_status=return_status, changed=changed, msg=msg, attrs=resp) 376 else: 377 module.fail_json(return_status=return_status, changed=changed, msg=msg) 378 379 380if __name__ == '__main__': 381 main() 382