Server IP : 85.214.239.14 / Your IP : 3.149.24.9 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /usr/lib/python3/dist-packages/ansible_collections/dellemc/openmanage/plugins/modules/ |
Upload File : |
#!/usr/bin/python # -*- coding: utf-8 -*- # # Dell EMC OpenManage Ansible Modules # Version 5.0.1 # Copyright (C) 2021-2022 Dell Inc. or its subsidiaries. All Rights Reserved. # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) # from __future__ import (absolute_import, division, print_function) __metaclass__ = type DOCUMENTATION = """ --- module: ome_groups short_description: Manages static device groups on OpenManage Enterprise description: This module allows to create, modify, and delete static device groups on OpenManage Enterprise. version_added: "3.5.0" author: - Jagadeesh N V(@jagadeeshnv) extends_documentation_fragment: - dellemc.openmanage.oment_auth_options options: state: type: str description: - C(present) allows to create or modify a device group. - C(absent) allows to delete a device group. choices: [present, absent] default: present name: type: list elements: str description: - Name of the device group to be created, modified, or deleted. - If I(state) is absent, multiple names can be provided. - This option is case insensitive. - This option is mutually exclusive with I(group_id). group_id: type: list elements: int description: - ID of the device group to be created, modified, or deleted. - If I(state) is absent, multiple IDs can be provided. - This option is mutually exclusive with I(name). new_name: type: str description: - New name for the existing device group. - This is applicable only when I(state) is C(present). description: type: str description: - Description for the device group. - This is applicable only when I(state) is C(present). parent_group_name: type: str default: "Static Groups" description: - Name of the parent device group under which the device group to be created or modified. - This is applicable only when I(state) is C(present). - C(NOTE) If device group with such a name does not exist, device group with I(parent_group_name) is created. - This option is case insensitive. - This option is mutually exclusive with I(parent_group_id). parent_group_id: type: int description: - ID of the parent device group under which the device group to be created or modified. - This is applicable only when I(state) is C(present). - This option is mutually exclusive with I(parent_group_name). requirements: - "python >= 3.8.6" notes: - This module manages only static device groups on Dell EMC OpenManage Enterprise. - If a device group with the name I(parent_group_name) does not exist, a new device group with the same name is created. - Make sure the entered parent group is not the descendant of the provided group. - Run this module from a system that has direct access to Dell EMC OpenManage Enterprise. - This module supports C(check_mode). """ EXAMPLES = """ --- - name: Create a new device group dellemc.openmanage.ome_groups: hostname: "192.168.0.1" username: "username" password: "password" ca_path: "/path/to/ca_cert.pem" name: "group 1" description: "Group 1 description" parent_group_name: "group parent 1" - name: Modify a device group using the group ID dellemc.openmanage.ome_groups: hostname: "192.168.0.1" username: "username" password: "password" ca_path: "/path/to/ca_cert.pem" group_id: 1234 description: "Group description updated" parent_group_name: "group parent 2" - name: Delete a device group using the device group name dellemc.openmanage.ome_groups: hostname: "192.168.0.1" username: "username" password: "password" ca_path: "/path/to/ca_cert.pem" state: absent name: "group 1" - name: Delete multiple device groups using the group IDs dellemc.openmanage.ome_groups: hostname: "192.168.0.1" username: "username" password: "password" ca_path: "/path/to/ca_cert.pem" state: absent group_id: - 1234 - 5678 """ RETURN = """ --- msg: type: str description: Overall status of the device group operation. returned: always sample: "Successfully deleted the device group(s)." group_status: description: Details of the device group operation status. returned: success type: dict sample: { "Description": "my group description", "Id": 12123, "MembershipTypeId": 12, "Name": "group 1", "ParentId": 12345, "TypeId": 3000, "IdOwner": 30, "CreatedBy": "admin", "CreationTime": "2021-01-01 10:10:10.100", "DefinitionDescription": "UserDefined", "DefinitionId": 400, "GlobalStatus": 5000, "HasAttributes": false, "UpdatedBy": "", "UpdatedTime": "2021-01-01 11:11:10.100", "Visible": true } group_ids: type: list elements: int description: List of the deleted device group IDs. returned: when I(state) is C(absent) sample: [1234, 5678] invalid_groups: type: list elements: str description: List of the invalid device group IDs or names. returned: when I(state) is C(absent) sample: [1234, 5678] error_info: description: Details of the HTTP Error. returned: on HTTP error type: dict sample: { "error": { "code": "Base.1.0.GeneralError", "message": "A general error has occurred. See ExtendedInfo for more information.", "@Message.ExtendedInfo": [ { "MessageId": "CGRP9013", "RelatedProperties": [], "Message": "Unable to update group 12345 with the provided parent 54321 because a group/parent relationship already exists.", "MessageArgs": [ "12345", "54321" ], "Severity": "Warning", "Resolution": "Make sure the entered parent ID does not create a bidirectional relationship and retry the operation." } ] } } """ import json import time from ssl import SSLError from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six.moves.urllib.error import URLError, HTTPError from ansible.module_utils.urls import ConnectionError from ansible_collections.dellemc.openmanage.plugins.module_utils.ome import RestOME, ome_auth_params GROUP_URI = "GroupService/Groups" OP_URI = "GroupService/Actions/GroupService.{op}Group" # GROUPS_HIERARCHY = "GroupService/AllGroupsHierarchy" MULTIPLE_GROUPS_MSG = "Provide only one unique device group when state is present." NONEXIST_GROUP_ID = "A device group with the provided ID does not exist." NONEXIST_PARENT_ID = "A parent device group with the provided ID does not exist." INVALID_PARENT = "The provided parent device group is not a valid user-defined static device group." INVALID_GROUPS_DELETE = "Provide valid static device group(s) for deletion." INVALID_GROUPS_MODIFY = "Provide valid static device group for modification." PARENT_CREATION_FAILED = "Unable to create a parent device group with the name {pname}." CREATE_SUCCESS = "Successfully {op}d the device group." GROUP_PARENT_SAME = "Provided parent and the device group cannot be the same." GROUP_NAME_EXISTS = "Unable to rename the group because a group with the provided name '{gname}' already exists." DELETE_SUCCESS = "Successfully deleted the device group(s)." NO_CHANGES_MSG = "No changes found to be applied." CHANGES_FOUND = "Changes found to be applied." STATIC_ROOT = 'Static Groups' SETTLING_TIME = 2 def get_valid_groups(module, rest_obj, group_arg, group_set): parent = {} static_root = {} group_dict = {} group_resp = rest_obj.get_all_items_with_pagination(GROUP_URI) if module.params.get('state') == 'absent': group_dict = dict([(str(g[group_arg]).lower(), g) for g in group_resp.get("value") if str(g[group_arg]).lower() in group_set]) else: parg = module.params.get('parent_group_id') if parg: # Checking id first as name has a default value pkey = 'Id' else: pkey = 'Name' parg = module.params.get('parent_group_name') count = 0 for g in group_resp.get("value"): if str(g[group_arg]).lower() in group_set: group_dict = g count = count + 1 if str(g[pkey]).lower() == str(parg).lower(): parent = g count = count + 1 if g['Name'] == STATIC_ROOT: static_root = g count = count + 1 if count == 3: break return group_dict, parent, static_root def is_valid_static_group(grp): if grp['TypeId'] == 3000 and grp['MembershipTypeId'] == 12: return True return False def create_parent(rest_obj, module, static_root): try: prt = static_root payload = {} payload['MembershipTypeId'] = 12 # Static members payload['Name'] = module.params.get('parent_group_name') payload['ParentId'] = prt['Id'] prt_resp = rest_obj.invoke_request('POST', OP_URI.format(op='Create'), data={"GroupModel": payload}) return int(prt_resp.json_data) except Exception: return static_root['Id'] def get_parent_id(rest_obj, module, parent, static_root): parent_id = module.params.get("parent_group_id") if parent_id: # Checking id first as name has a default value if not parent: module.fail_json(msg=NONEXIST_PARENT_ID) if parent['Name'] != STATIC_ROOT: if not is_valid_static_group(parent): module.fail_json(msg=INVALID_PARENT) return parent['Id'] else: if parent: if parent['Name'] != STATIC_ROOT: if not is_valid_static_group(parent): module.fail_json(msg=INVALID_PARENT) return parent['Id'] else: if module.check_mode: return 0 else: prtid = create_parent(rest_obj, module, static_root) time.sleep(SETTLING_TIME) return prtid return static_root['Id'] def get_ome_group_by_name(rest_obj, name): grp = {} try: resp = rest_obj.invoke_request("GET", GROUP_URI, query_param={"$filter": "Name eq '{0}'".format(name)}) group_resp = resp.json_data.get('value') if group_resp: grp = group_resp[0] except Exception: grp = {} return grp def get_ome_group_by_id(rest_obj, id): grp = {} try: resp = rest_obj.invoke_request('GET', GROUP_URI + "({0})".format(id)) grp = resp.json_data except Exception: grp = {} return grp def exit_group_operation(module, rest_obj, payload, operation): group_resp = rest_obj.invoke_request('POST', OP_URI.format(op=operation), data={"GroupModel": payload}) cid = int(group_resp.json_data) time.sleep(SETTLING_TIME) try: grp = get_ome_group_by_id(rest_obj, cid) group = rest_obj.strip_substr_dict(grp) except Exception: payload['Id'] = cid group = payload module.exit_json(changed=True, msg=CREATE_SUCCESS.format(op=operation.lower()), group_status=group) def create_group(rest_obj, module, parent, static_root): payload = {} payload['MembershipTypeId'] = 12 # Static members mparams = module.params payload['Name'] = mparams.get('name')[0] if mparams.get('parent_group_name').lower() == payload['Name'].lower(): module.fail_json(msg=GROUP_PARENT_SAME) parent_id = get_parent_id(rest_obj, module, parent, static_root) payload['ParentId'] = parent_id if mparams.get('description'): payload['Description'] = mparams.get('description') if module.check_mode: module.exit_json(changed=True, msg=CHANGES_FOUND) exit_group_operation(module, rest_obj, payload, 'Create') def modify_group(rest_obj, module, valid_group_dict, parent, static_root): if not is_valid_static_group(valid_group_dict): module.fail_json(msg=INVALID_GROUPS_MODIFY) grp = valid_group_dict diff = 0 payload = dict([(k, grp.get(k)) for k in ["Name", "Description", "MembershipTypeId", "ParentId", "Id"]]) new_name = module.params.get('new_name') if new_name: if new_name != payload['Name']: dup_grp = get_ome_group_by_name(rest_obj, new_name) if dup_grp: module.fail_json(msg=GROUP_NAME_EXISTS.format(gname=new_name)) payload['Name'] = new_name diff += 1 desc = module.params.get('description') if desc: if desc != payload['Description']: payload['Description'] = desc diff += 1 parent_id = get_parent_id(rest_obj, module, parent, static_root) if parent_id == payload['Id']: module.fail_json(msg=GROUP_PARENT_SAME) if parent_id != payload['ParentId']: payload['ParentId'] = parent_id diff += 1 if diff == 0: gs = rest_obj.strip_substr_dict(grp) module.exit_json(msg=NO_CHANGES_MSG, group_status=gs) if module.check_mode: module.exit_json(changed=True, msg=CHANGES_FOUND) exit_group_operation(module, rest_obj, payload, 'Update') def delete_groups(rest_obj, module, group_set, group_dict): deletables = [] invalids = [] for g in group_set: grp = group_dict.get(str(g).lower()) if grp: if is_valid_static_group(grp): # For Query Groups MembershipTypeId = 24 deletables.append(grp['Id']) else: invalids.append(g) if invalids: module.fail_json(msg=INVALID_GROUPS_DELETE, invalid_groups=invalids) if module.check_mode: module.exit_json(changed=True, msg=CHANGES_FOUND, group_ids=deletables) rest_obj.invoke_request("POST", OP_URI.format(op='Delete'), data={"GroupIds": deletables}) module.exit_json(changed=True, msg=DELETE_SUCCESS, group_ids=deletables) def main(): specs = { "name": {"type": "list", "elements": 'str'}, "group_id": {"type": "list", "elements": 'int'}, "state": {"type": "str", "choices": ["present", "absent"], "default": "present"}, "description": {"type": "str"}, "new_name": {"type": "str"}, "parent_group_name": {"type": "str", "default": STATIC_ROOT}, "parent_group_id": {"type": "int"}, } specs.update(ome_auth_params) module = AnsibleModule( argument_spec=specs, required_if=[ ["state", "present", ("new_name", "description", "parent_group_name", "parent_group_id"), True], ], mutually_exclusive=[ ("name", "group_id"), ("parent_group_name", "parent_group_id"), ], required_one_of=[("name", "group_id")], supports_check_mode=True ) try: if module.params.get('name'): group_arg = 'Name' group_set = set(v.lower() for v in module.params.get('name')) else: group_arg = 'Id' group_set = set(str(v).lower() for v in module.params.get('group_id')) if len(group_set) != 1 and module.params['state'] == 'present': module.fail_json(msg=MULTIPLE_GROUPS_MSG) with RestOME(module.params, req_session=True) as rest_obj: valid_group_dict, parent, static_root = get_valid_groups(module, rest_obj, group_arg, group_set) if module.params["state"] == "absent": if valid_group_dict: delete_groups(rest_obj, module, group_set, valid_group_dict) module.exit_json(msg=NO_CHANGES_MSG) else: if valid_group_dict: modify_group(rest_obj, module, valid_group_dict, parent, static_root) elif group_arg == 'Id': module.fail_json(msg=NONEXIST_GROUP_ID) create_group(rest_obj, module, parent, static_root) except HTTPError as err: module.fail_json(msg=str(err), error_info=json.load(err)) except URLError as err: module.exit_json(msg=str(err), unreachable=True) except (IOError, ValueError, SSLError, TypeError, ConnectionError, AttributeError, IndexError, KeyError, OSError) as err: module.fail_json(msg=str(err)) if __name__ == '__main__': main()