├── .gitignore ├── README.rst ├── ansible.cfg ├── backup.yaml ├── backup_and_restore.yaml ├── file_system_deployment.yaml ├── library └── commvault.py └── update_subclient_description.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Ansible Commvault module 2 | ======================== 3 | 4 | `Ansible `_ is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs. 5 | 6 | `How Ansible Works | Ansible.com `_ 7 | 8 | `Getting started with Ansible `_ 9 | 10 | `Getting started with playbooks `_ 11 | 12 | Introduction 13 | ------------ 14 | 15 | Ansible Commvault module can be used in playbooks to automate commvault operations 16 | 17 | 18 | 19 | 20 | Commvault module uses `CVPySDK `_ to perform operations 21 | 22 | All agents supported by CVPySDK are supported by commvault ansible module 23 | 24 | CVPySDK, in turn, uses Commvault REST API to perform operations on a Commcell via WebConsole. 25 | 26 | 27 | Requirements 28 | ------------ 29 | 30 | - Ansible 31 | - Python 3 or above 32 | - `CVPySDK `_ 33 | - Commvault Software v11 SP16 or later release with WebConsole installed 34 | 35 | Installing CVPySDK 36 | ------------------ 37 | 38 | CVPySDK can be installed directly from PyPI using pip: 39 | 40 | >>> pip install cvpysdk 41 | 42 | 43 | CVPySDK is available on GitHub `here `_ 44 | 45 | It can also be installed from source. 46 | 47 | After downloading, from within the ``cvpysdk`` directory, execute: 48 | 49 | >>> python setup.py install 50 | 51 | Installing Ansible 52 | ------------------ 53 | 54 | - `Installation guide | Ansible.com `_ 55 | 56 | 57 | Using Ansible commvault module 58 | ------------------------------ 59 | 60 | **Login to Commcell:** 61 | :: 62 | 63 | --- 64 | - name: Commvault Ansible 65 | gather_facts: no 66 | hosts: localhost 67 | connection: local 68 | 69 | vars: 70 | webconsole_hostname: 'webconsole_hostname' 71 | commcell_username: 'commcell_username' 72 | commcell_password: 'commcell_password' 73 | 74 | tasks: 75 | - name: Login 76 | commvault: 77 | operation: login 78 | entity: { 79 | webconsole_hostname: "{{ webconsole_hostname }}", 80 | commcell_username: "{{ commcell_username }}", 81 | commcell_password: "{{ commcell_password }}" 82 | } 83 | register: commcell 84 | 85 | **Force HTTPS login using self-signed certificate** 86 | :: 87 | 88 | - name: Login 89 | commvault: 90 | operation: login 91 | entity: { 92 | webconsole_hostname: "{{ webconsole_hostname }}", 93 | commcell_username: "{{ commcell_username }}", 94 | commcell_password: "{{ commcell_password }}", 95 | force_https: True, 96 | certificate_path: '/tmp/certificates' 97 | } 98 | register: commcell 99 | 100 | 101 | **Run backup for a subclient:** 102 | :: 103 | 104 | - name: Backup 105 | commvault: 106 | operation: "backup" 107 | entity_type: subclient 108 | commcell: "{{ commcell }}" 109 | entity: { 110 | client: "client name", 111 | agent: "file system", 112 | backupset: "defaultbackupset", 113 | subclient: "default" 114 | } 115 | register: backup_job 116 | 117 | **Run restore in place job for a subclient:** 118 | :: 119 | 120 | - name: Restore 121 | commvault: 122 | operation: "restore_in_place" 123 | entity_type: subclient 124 | commcell: "{{ commcell }}" 125 | entity: { 126 | client: "client name", 127 | agent: "file system", 128 | backupset: "defaultbackupset", 129 | subclient: "default" 130 | } 131 | args: { 132 | paths: ['path'] 133 | } 134 | register: restore_job 135 | 136 | **Wait for the restore job to complete:** 137 | :: 138 | 139 | - name: wait for restore job to complete 140 | commvault: 141 | operation: "wait_for_completion" 142 | entity_type: "job" 143 | commcell: "{{ commcell }}" 144 | entity: { 145 | job_id: "{{ restore_job.output }}" 146 | } 147 | register: restore_status 148 | 149 | **Get storage pool properties:** 150 | :: 151 | 152 | - name: "get storage pool properties" 153 | commvault: 154 | operation: "storage_pool_properties" 155 | entity_type: storagepool 156 | commcell: "{{ commcell }}" 157 | entity: { 158 | "storage_pool": "dedicated cl2" 159 | } 160 | register: storage_pool_props 161 | 162 | 163 | Explanation: 164 | ------------ 165 | 166 | **operation** corresponds to a method name in CVPySDK modules, example "restore_in_place" method is in subclient.py module 167 | 168 | **entity_type** corresponds to baisc CVPySDK class, available options are 169 | 170 | - Commcell 171 | - Clients 172 | - Client 173 | - Clientgroups 174 | - Clientgroup 175 | - Agents 176 | - Agent 177 | - Instances 178 | - Instance 179 | - Backupsets 180 | - Backupset 181 | - Subclients 182 | - Subclient 183 | - Job 184 | - MediaAgents 185 | - MediaAgent 186 | - StoragePools 187 | - StoragePool 188 | - DiskLibraries 189 | - DiskLibrary 190 | 191 | **commcell** is mandatory to perform any tasks, when performing login operation commcell is registered and can later be used in other tasks 192 | 193 | **entity** will contain basic CVPySDK inputs, available options are 194 | 195 | - client 196 | - clientgroup 197 | - agent 198 | - instance 199 | - backupset 200 | - subclient 201 | - job_id 202 | - media_agent 203 | - storage_pool 204 | - disk_library 205 | 206 | **args** contains the arguments to be passed to the method 207 | 208 | Contribution Guidelines 209 | ----------------------- 210 | 211 | #. We welcome all the enhancements from everyone although we request the developer to follow some guidelines while interacting with the ``Ansible commvault module`` codebase. 212 | 213 | #. Before adding any enhancements/bug-fixes, we request you to open an Issue first. 214 | 215 | #. The core team will go over the Issue and notify if it is required or already been worked on. 216 | 217 | #. If the Issue is approved, the contributor can then make the changes to their fork and open a pull request. 218 | 219 | Coding Considerations 220 | ********************* 221 | 222 | - All python code should be **PEP8** compliant. 223 | - All changes should be consistent with the design of the SDK. 224 | - The code should be formatted using **autopep8** with line-length set to **119** instead of default **79**. 225 | - All changes and any new methods/classes should be properly documented. 226 | - The docstrings should be of the same format as existing docs. 227 | 228 | Questions/Comments/Suggestions 229 | -------------- 230 | If you have any questions or comments, please contact us `here `_. 231 | Also Check out our community for `Automation `_ incase of queries. 232 | 233 | Code of Conduct 234 | *************** 235 | 236 | Everyone interacting in the **Ansible commvault module** project's codebases, issue trackers, 237 | chat rooms, and mailing lists is expected to follow the 238 | `PyPA Code of Conduct`_. 239 | 240 | .. _PyPA Code of Conduct: https://www.pypa.io/en/latest/code-of-conduct/ 241 | 242 | License 243 | ------- 244 | **CVPySDK** and **Commvault ansible module** are licensed under `Apache 2.0 `_ 245 | 246 | About Commvault 247 | --------------- 248 | .. image:: https://commvault.github.io/cvpysdk/logo.png 249 | :align: center 250 | 251 | | 252 | 253 | `Commvault `_ 254 | (NASDAQ: CVLT) is a publicly-traded data protection and information management software company headquartered in Tinton Falls, New Jersey. 255 | 256 | It was formed in 1988 as a development group in Bell Labs, and later became a business unit of AT&T Network Systems. It was incorporated in 1996. 257 | 258 | Commvault software assists organizations with data backup and recovery, cloud and infrastructure management, and retention and compliance. 259 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | -------------------------------------------------------------------------------- /backup.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Commvault Ansible 3 | gather_facts: no 4 | hosts: localhost 5 | connection: local 6 | 7 | vars: 8 | webconsole_hostname: 'hostname' 9 | commcell_username: 'username' 10 | commcell_password: 'password' 11 | client: 'sample client' 12 | 13 | tasks: 14 | - name: Commvault commcell initialization 15 | block: 16 | - name: Login 17 | commvault: 18 | operation: LOGIN 19 | entity: { 20 | webconsole_hostname: "{{ webconsole_hostname }}", 21 | commcell_username: "{{ commcell_username }}", 22 | commcell_password: "{{ commcell_password }}" 23 | } 24 | register: commcell 25 | - debug: 26 | msg: "Login is done successfully" 27 | rescue: 28 | - debug: 29 | msg: 'Login failed' 30 | 31 | - name: performing backup 32 | commvault: 33 | operation: "backup" 34 | entity_type: subclient 35 | commcell: "{{ commcell }}" 36 | entity: { 37 | client: "{{ client }}", 38 | agent: "file system", 39 | backupset: "defaultbackupset", 40 | subclient: "default" 41 | } 42 | register: backup_job 43 | 44 | - debug: 45 | msg: "Successfully started backup job: {{ backup_job.output }}" 46 | 47 | ... -------------------------------------------------------------------------------- /backup_and_restore.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Commvault Ansible 3 | gather_facts: no 4 | hosts: localhost 5 | connection: local 6 | 7 | vars: 8 | webconsole_hostname: 'hostname' 9 | commcell_username: 'username' 10 | commcell_password: 'password' 11 | client: 'sample client' 12 | 13 | tasks: 14 | - name: Commvault commcell initialization 15 | block: 16 | - name: Login 17 | commvault: 18 | operation: LOGIN 19 | entity: { 20 | webconsole_hostname: "{{ webconsole_hostname }}", 21 | commcell_username: "{{ commcell_username }}", 22 | commcell_password: "{{ commcell_password }}" 23 | } 24 | register: commcell 25 | - debug: 26 | msg: "Login is done successfully" 27 | rescue: 28 | - debug: 29 | msg: 'Login failed' 30 | 31 | - name: Backup 32 | block: 33 | - name: performing backup 34 | commvault: 35 | operation: "backup" 36 | entity_type: subclient 37 | commcell: "{{ commcell }}" 38 | entity: { 39 | client: "{{ client }}", 40 | agent: "file system", 41 | backupset: "defaultbackupset", 42 | subclient: "default" 43 | } 44 | register: backup_job 45 | - debug: 46 | msg: "Successfully started backup job: {{ backup_job.output }}" 47 | - name: wait for backup job to complete 48 | commvault: 49 | operation: "wait_for_completion" 50 | entity_type: "job" 51 | commcell: "{{ commcell }}" 52 | entity: { 53 | job_id: "{{ backup_job.output }}" 54 | } 55 | register: backup_status 56 | - name: Backup job failure reason 57 | when: backup_status.output == false 58 | commvault: 59 | operation: "delay_reason" 60 | entity_type: "job" 61 | commcell: "{{ commcell }}" 62 | entity: { 63 | job_id: "{{ backup_job.output }}" 64 | } 65 | register: failure_reason 66 | - debug: 67 | msg: "{{ failure_reason.output }}" 68 | when: backup_status.output == false 69 | ignore_errors: yes 70 | - debug: 71 | msg: "Backup job completed successfully" 72 | when: backup_status.output == true 73 | ignore_errors: yes 74 | rescue: 75 | - debug: 76 | msg: 'Backup failed' 77 | 78 | - name: Restore 79 | when: backup_status.output == true 80 | commvault: 81 | operation: "restore_in_place" 82 | entity_type: subclient 83 | commcell: "{{ commcell }}" 84 | entity: { 85 | client: "{{ client }}", 86 | agent: "file system", 87 | backupset: "defaultbackupset", 88 | subclient: "default" 89 | } 90 | args: { 91 | paths: ['C:\testing'] 92 | } 93 | register: restore_job 94 | 95 | - debug: 96 | msg: "Successfully started Restore job: {{ restore_job.output }}" 97 | 98 | - name: wait for restore job to complete 99 | when: restore_job is succeeded 100 | commvault: 101 | operation: "wait_for_completion" 102 | entity_type: "job" 103 | commcell: "{{ commcell }}" 104 | entity: { 105 | job_id: "{{ restore_job.output }}" 106 | } 107 | register: restore_status 108 | 109 | - name: Backup job failure reason 110 | when: restore_status.output == false 111 | commvault: 112 | operation: "delay_reason" 113 | entity_type: "job" 114 | commcell: "{{ commcell }}" 115 | entity: { 116 | job_id: "{{ restore_job.output }}" 117 | } 118 | register: failure_reason 119 | 120 | - debug: 121 | msg: "{{ failure_reason.output }}" 122 | when: restore_status.output == false 123 | ignore_errors: yes 124 | 125 | - debug: 126 | msg: "{{ Restore job completed successfully }}" 127 | when: restore_status.output == true 128 | ignore_errors: yes 129 | 130 | ... -------------------------------------------------------------------------------- /file_system_deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Commvault Ansible 3 | gather_facts: no 4 | hosts: localhost 5 | connection: local 6 | 7 | vars: 8 | webconsole_hostname: 'webconsole_hostname' 9 | commcell_username: 'commcell_username' 10 | commcell_password: 'commcell_password' 11 | 12 | tasks: 13 | - name: Commvault commcell initialization 14 | block: 15 | - name: Login 16 | commvault: 17 | operation: LOGIN 18 | entity: { 19 | webconsole_hostname: "{{ webconsole_hostname }}", 20 | commcell_username: "{{ commcell_username }}", 21 | commcell_password: "{{ commcell_password }}" 22 | } 23 | register: commcell 24 | - debug: 25 | msg: "Login is done successfully" 26 | rescue: 27 | - debug: 28 | msg: 'Login failed' 29 | 30 | 31 | # Either Unix or Windows clients_computers should be chosen and not both 32 | # windows packages - https://github.com/CommvaultEngg/cvpysdk/blob/master/cvpysdk/deployment/deploymentconstants.py#L79 33 | # Unix packages - https://github.com/CommvaultEngg/cvpysdk/blob/master/cvpysdk/deployment/deploymentconstants.py#L59 34 | # Install software method is available on commcell.py module in cvpysdk - https://github.com/CommvaultEngg/cvpysdk/blob/master/cvpysdk/commcell.py#L1684 35 | - name: Windows FS package installation 36 | commvault: 37 | operation: install_software 38 | entity_type: commcell 39 | commcell: "{{ commcell }}" 40 | args: { 41 | client_computers: ["client_name"], 42 | windows_features: [702], # 702 is File System 43 | username: "username", 44 | password: "password" 45 | } 46 | 47 | register: install_job 48 | 49 | - debug: 50 | msg: "Successfully started install job: {{ install_job.output }}" 51 | 52 | - name: wait for install job to complete 53 | when: install_job is succeeded 54 | commvault: 55 | operation: "wait_for_completion" 56 | entity_type: "job" 57 | commcell: "{{ commcell }}" 58 | entity: { 59 | job_id: "{{ install_job.output }}" 60 | } 61 | register: status 62 | 63 | - name: install job failure reason 64 | when: status.output == false 65 | commvault: 66 | operation: "delay_reason" 67 | entity_type: "job" 68 | commcell: "{{ commcell }}" 69 | entity: { 70 | job_id: "{{ install_job.output }}" 71 | } 72 | register: failure_reason 73 | 74 | - debug: 75 | msg: "{{ failure_reason.output }}" 76 | when: status.output == false 77 | ignore_errors: yes 78 | 79 | - debug: 80 | msg: "{{ install job completed successfully }}" 81 | when: status.output == true 82 | ignore_errors: yes 83 | 84 | ... -------------------------------------------------------------------------------- /library/commvault.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # -------------------------------------------------------------------------- 4 | # Copyright Commvault Systems, Inc. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # -------------------------------------------------------------------------- 18 | 19 | 20 | ANSIBLE_METADATA = { 21 | 'metadata_version': '11.28.0' 22 | } 23 | 24 | DOCUMENTATION = ''' 25 | 26 | module: commvault 27 | 28 | short_description: To perform commvault operations 29 | 30 | description: 31 | 32 | - Ansible Commvault module can be used in playbooks to perform commvault operations 33 | 34 | - Commvault module uses CVPySDK to perform operations 35 | 36 | - CVPySDK, in turn, uses Commvault REST API to perform operations on a Commcell via WebConsole. 37 | 38 | author: "Commvault Systems, Inc." 39 | 40 | options: 41 | 42 | operation: 43 | description: 44 | - operation to be performed 45 | - corresponds to method name in CVPySDK modules 46 | - example "restore_in_place" method is in subclient module 47 | 48 | required: true 49 | 50 | choices: 51 | - Login 52 | - CVPySDK methods like backup, restore_in_place 53 | 54 | type: str 55 | 56 | entity: 57 | description: 58 | - contain basic CVPySDK inputs 59 | 60 | required: false 61 | 62 | default: {} 63 | 64 | choices: 65 | - client 66 | - clientgroup 67 | - agent 68 | - instance 69 | - backupset 70 | - subclient 71 | - job_id 72 | - media_agent 73 | - storage_pool 74 | - disk_library 75 | 76 | type: dict 77 | 78 | commcell: 79 | description: 80 | - mandatory to perform any tasks, when performing login operation commcell is registered 81 | 82 | required: true 83 | 84 | entity_type: 85 | description: 86 | - corresponds to basic CVPySDK class 87 | 88 | required: false 89 | 90 | default: '' 91 | 92 | choices: 93 | - Commcell 94 | - Clients 95 | - Client 96 | - Clientgroups 97 | - Clientgroup 98 | - Agents 99 | - Agent 100 | - Instances 101 | - Instance 102 | - Backupsets 103 | - Backupset 104 | - Subclients 105 | - Subclient 106 | - Job 107 | - MediaAgents 108 | - MediaAgent 109 | - StoragePools 110 | - StoragePool 111 | - DiskLibraries 112 | - DiskLibrary 113 | 114 | type: str 115 | 116 | args: 117 | description: 118 | - arguments to be passed to the CVPySDK methods 119 | 120 | required: false 121 | 122 | default: {} 123 | 124 | type: dict 125 | 126 | requirements: 127 | 128 | - Ansible 129 | 130 | - Python 2.7 or above 131 | 132 | - CVPySDK 133 | 134 | - Commvault Software v11 SP16 or later release with WebConsole installed 135 | 136 | ''' 137 | 138 | EXAMPLES = ''' 139 | **Login to Commcell:** 140 | 141 | - name: Login 142 | commvault: 143 | operation: login 144 | entity: { 145 | webconsole_hostname: "{{ webconsole_hostname }}", 146 | commcell_username: "{{ commcell_username }}", 147 | commcell_password: "{{ commcell_password }}" 148 | } 149 | register: commcell 150 | 151 | **Force HTTPS login using self-signed certificate** 152 | 153 | - name: Login 154 | commvault: 155 | operation: login 156 | entity: { 157 | webconsole_hostname: "{{ webconsole_hostname }}", 158 | commcell_username: "{{ commcell_username }}", 159 | commcell_password: "{{ commcell_password }}", 160 | force_https: True, 161 | certificate_path: '/tmp/certificates' 162 | } 163 | register: commcell 164 | 165 | **Run backup for a subclient:** 166 | 167 | - name: Backup 168 | commvault: 169 | operation: "backup" 170 | entity_type: subclient 171 | commcell: "{{ commcell }}" 172 | entity: { 173 | client: "client name", 174 | agent: "file system", 175 | backupset: "defaultbackupset", 176 | subclient: "default" 177 | } 178 | register: backup_job 179 | 180 | **Run restore in place job for a subclient:** 181 | 182 | - name: Restore 183 | commvault: 184 | operation: "restore_in_place" 185 | entity_type: subclient 186 | commcell: "{{ commcell }}" 187 | entity: { 188 | client: "client name", 189 | agent: "file system", 190 | backupset: "defaultbackupset", 191 | subclient: "default" 192 | } 193 | args: { 194 | paths: ['path'] 195 | } 196 | register: restore_job 197 | 198 | **Wait for the restore job to complete:** 199 | 200 | - name: wait for restore job to complete 201 | commvault: 202 | operation: "wait_for_completion" 203 | entity_type: "job" 204 | commcell: "{{ commcell }}" 205 | entity: { 206 | job_id: "{{ restore_job.output }}" 207 | } 208 | register: restore_status 209 | 210 | **Get storage pool properties:** 211 | 212 | - name: "get storage pool properties" 213 | commvault: 214 | operation: "storage_pool_properties" 215 | entity_type: storagepool 216 | commcell: "{{ commcell }}" 217 | entity: { 218 | "storage_pool": "dedicated cl2" 219 | } 220 | register: storage_pool_props 221 | 222 | ''' 223 | 224 | RETURN = ''' 225 | 226 | return name: output 227 | 228 | returned: always 229 | 230 | sample: { 231 | output: "output of operation" 232 | } 233 | 234 | ''' 235 | 236 | from ansible.module_utils.basic import AnsibleModule 237 | from cvpysdk.commcell import Commcell 238 | from cvpysdk.job import Job 239 | 240 | 241 | commcell = client = clients = agent = agents = instance = instances = backupset = backupsets = subclient = subclients = None 242 | 243 | clientgroups = clientgroup = job = jobs = None 244 | 245 | mediaagents = mediaagent = storagepools = storagepool = disklibraries = disklibrary = None 246 | 247 | result = {} 248 | 249 | 250 | def login(module): 251 | """ 252 | sign in the user to the commcell with the credentials provided 253 | 254 | Args: 255 | module (dict) -- webconsole and authentication details 256 | 257 | """ 258 | global commcell_object 259 | 260 | if module.get('authtoken'): 261 | commcell_object = Commcell( 262 | module['webconsole_hostname'], 263 | authtoken=module['authtoken'], 264 | force_https=module.get('force_https', False), 265 | certificate_path=module.get('certificate_path') 266 | ) 267 | 268 | else: 269 | commcell_object = Commcell( 270 | webconsole_hostname=module['webconsole_hostname'], 271 | commcell_username=module['commcell_username'], 272 | commcell_password=module['commcell_password'], 273 | force_https=module.get('force_https', False), 274 | certificate_path=module.get('certificate_path') 275 | ) 276 | 277 | 278 | def create_object(entity): 279 | """ 280 | To create the basic commvault objects 281 | 282 | entity (dict) -- basic commvault object names 283 | 284 | Example: 285 | { 286 | client: "", 287 | agent: "", 288 | instance: "" 289 | backupset: "", 290 | subclient: "" 291 | } 292 | 293 | """ 294 | global commcell, client, clients, agent, agents, instance, instances, backupset, backupsets, subclient, subclients, result, clientgroup, clientgroups 295 | global job, jobs 296 | global mediaagents, mediaagent, storagepools, storagepool, disklibraries, disklibrary 297 | 298 | commcell = commcell_object 299 | clients = commcell_object.clients 300 | clientgroups = commcell_object.client_groups 301 | jobs = commcell_object.job_controller 302 | mediaagents = commcell_object.media_agents 303 | storagepools = commcell_object.storage_pools 304 | disklibraries = commcell_object.disk_libraries 305 | 306 | if 'client' in entity: 307 | 308 | client = clients.get(entity['client']) 309 | agents = client.agents 310 | 311 | if 'agent' in entity: 312 | agent = agents.get(entity['agent']) 313 | instances = agent.instances 314 | backupsets = agent.backupsets 315 | 316 | if 'instance' in entity: 317 | instance = instances.get(entity['instance']) 318 | subclients = instance.subclients 319 | 320 | if 'backupset' in entity: 321 | backupset = backupsets.get(entity['backupset']) 322 | subclients = backupset.subclients 323 | 324 | if subclients and 'subclient' in entity: 325 | subclient = subclients.get(entity['subclient']) 326 | 327 | if 'job_id' in entity: 328 | job = jobs.get(entity['job_id']) 329 | 330 | if 'clientgroup' in entity: 331 | clientgroup = clientgroups.get(entity['clientgroup']) 332 | 333 | if 'media_agent' in entity: 334 | mediaagent = mediaagents.get(entity['media_agent']) 335 | 336 | if 'storage_pool' in entity: 337 | storagepool = storagepools.get(entity['storage_pool']) 338 | 339 | if 'disk_library' in entity: 340 | disklibrary = disklibraries.get(entity['disk_library']) 341 | 342 | 343 | def main(): 344 | """Main method for this module""" 345 | module_args = dict( 346 | operation=dict(type='str', required=True), 347 | entity=dict(type="dict", default={}), 348 | entity_type=dict(type='str', default=''), 349 | commcell=dict(type='dict', default={}), 350 | args=dict(type='dict', default={}) 351 | ) 352 | 353 | module = AnsibleModule( 354 | argument_spec=module_args, 355 | supports_check_mode=True 356 | ) 357 | 358 | global result 359 | result = dict() 360 | if module.params['operation'].lower() == 'login': 361 | login(module.params['entity']) 362 | result['changed'] = True 363 | result['authtoken'] = commcell_object.auth_token 364 | result['webconsole_hostname'] = commcell_object.webconsole_hostname 365 | else: 366 | login(module.params['commcell']) 367 | create_object(module.params['entity']) 368 | # module.exit_json(**module.params['entity']) 369 | 370 | obj_name = module.params["entity_type"] 371 | obj = eval(obj_name) 372 | method = module.params["operation"] 373 | 374 | if not hasattr(obj, method): 375 | obj_name = '{}s'.format(module.params["entity_type"]) 376 | obj = eval(obj_name) 377 | 378 | statement = '{0}.{1}'.format(obj_name, method) 379 | attr = getattr(obj, method) 380 | 381 | if callable(attr): 382 | if module.params.get('args'): 383 | args = module.params["args"] 384 | statement = '{0}(**{1})'.format(statement, args) 385 | else: 386 | statement = '{0}()'.format(statement) 387 | 388 | else: 389 | if module.params.get('args'): 390 | statement = '{0} = list(module.params["args"].values())[0]'.format(statement) 391 | exec(statement) 392 | result['output'] = "Property set successfully" 393 | module.exit_json(**result) 394 | 395 | output = eval(statement) 396 | 397 | if type(output).__module__ in ['builtins', '__builtin__']: 398 | result['output'] = output 399 | elif isinstance(output, Job): 400 | result['output'] = output.job_id 401 | else: 402 | result['output'] = str(output) 403 | 404 | module.exit_json(**result) 405 | 406 | 407 | if __name__ == '__main__': 408 | main() 409 | -------------------------------------------------------------------------------- /update_subclient_description.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Commvault Ansible 3 | gather_facts: no 4 | hosts: localhost 5 | connection: local 6 | 7 | vars: 8 | webconsole_hostname: 'hostname' 9 | commcell_username: 'username' 10 | commcell_password: 'password' 11 | client: 'sample client' 12 | 13 | tasks: 14 | - name: Commvault commcell initialization 15 | block: 16 | - name: Login 17 | commvault: 18 | operation: LOGIN 19 | entity: { 20 | webconsole_hostname: "{{ webconsole_hostname }}", 21 | commcell_username: "{{ commcell_username }}", 22 | commcell_password: "{{ commcell_password }}" 23 | } 24 | register: commcell 25 | - debug: 26 | msg: "Login is done successfully" 27 | rescue: 28 | - debug: 29 | msg: 'Login failed' 30 | 31 | - name: changing subclient description 32 | commvault: 33 | operation: "description" 34 | entity_type: subclient 35 | commcell: "{{ commcell }}" 36 | entity: { 37 | client: "{{ client }}", 38 | agent: "file system", 39 | backupset: "defaultbackupset", 40 | subclient: "default" 41 | } 42 | args: { 43 | "value": "setting subclient description" 44 | } 45 | register: output 46 | 47 | - debug: 48 | msg: "Successful {{ output.output }}" 49 | 50 | ... --------------------------------------------------------------------------------