1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3 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 9ANSIBLE_METADATA = {'metadata_version': '1.1', 10 'status': ['preview'], 11 'supported_by': 'community'} 12 13DOCUMENTATION = r''' 14--- 15module: intersight_virtual_media_policy 16short_description: Virtual Media policy configuration for Cisco Intersight 17description: 18 - Virtual Media policy configuration for Cisco Intersight. 19 - Used to configure Virtual Media image mappings on Cisco Intersight managed devices. 20 - For more information see L(Cisco Intersight,https://intersight.com/apidocs). 21extends_documentation_fragment: intersight 22options: 23 state: 24 description: 25 - If C(present), will verify the resource is present and will create if needed. 26 - If C(absent), will verify the resource is absent and will delete if needed. 27 choices: [present, absent] 28 default: present 29 organization: 30 description: 31 - The name of the Organization this resource is assigned to. 32 - Profiles and Policies that are created within a Custom Organization are applicable only to devices in the same Organization. 33 default: default 34 name: 35 description: 36 - The name assigned to the NTP policy. 37 - The name must be between 1 and 62 alphanumeric characters, allowing special characters :-_. 38 required: true 39 tags: 40 description: 41 - List of tags in Key:<user-defined key> Value:<user-defined value> format. 42 type: list 43 descrption: 44 description: 45 - The user-defined description of the NTP policy. 46 - Description can contain letters(a-z, A-Z), numbers(0-9), hyphen(-), period(.), colon(:), or an underscore(_). 47 aliases: [descr] 48 enable: 49 description: 50 - Enable or disable virtual media. 51 type: bool 52 default: true 53 encryption: 54 description: 55 - If enabled, allows encryption of all Virtual Media communications 56 type: bool 57 default: false 58 low_power_usb: 59 description: 60 - If enabled, the virtual drives appear on the boot selection menu after mapping the image and rebooting the host. 61 type: bool 62 default: true 63 cdd_virtual_media: 64 description: 65 - CDD Virtual Media image mapping options. 66 suboptions: 67 enable: 68 description: 69 - Enable or disable CDD image mapping. 70 type: bool 71 default: true 72 mount_type: 73 description: 74 - Type (protocol) of network share used by the remote_hostname. 75 - Ensure that the remote_hostname's communication port for the mount type that you choose is accessible from the managed endpoint. 76 - For CIFS as your mount type, ensure port 445 (which is its communication port) on the remote_hostname is accessible. 77 - For HTTP, ensure port 80 is accessible. 78 - For HTTPS, ensure port 443 is accessible. 79 - For NFS, ensure port 2049 is accessible. 80 choices: [nfs,cifs,http,https] 81 required: true 82 volume: 83 description: 84 - A user defined name of the image mounted for mapping. 85 required: true 86 remote_hostname: 87 description: 88 - Hostname or IP address of the server hosting the virtual media image. 89 required: true 90 remote_path: 91 description: 92 - Filepath (not including the filename) of the remote image. 93 - Ex. mnt/SHARE/ISOS 94 required: true 95 remote_file: 96 description: 97 - Filename of the remote image. 98 - Ex. custom_image.iso 99 required: true 100 username: 101 description: 102 - The username for the specified Mount Type, if required. 103 password: 104 description: 105 - The password for the selected username, if required. 106 hdd_virtual_media: 107 description: 108 - HDD Virtual Media image mapping options. 109 suboptions: 110 enable: 111 description: 112 - Enable or disable HDD image mapping. 113 type: bool 114 default: false 115 mount_type: 116 description: 117 - Type (protocol) of network share used by the remote_hostname. 118 - Ensure that the remote_hostname's communication port for the mount type that you choose is accessible from the managed endpoint. 119 - For CIFS as your mount type, ensure port 445 (which is its communication port) on the remote_hostname is accessible. 120 - For HTTP, ensure port 80 is accessible. 121 - For HTTPS, ensure port 443 is accessible. 122 - For NFS, ensure port 2049 is accessible. 123 choices: [nfs,cifs,http,https] 124 required: true 125 volume: 126 description: 127 - A user defined name of the image mounted for mapping. 128 required: true 129 remote_hostname: 130 description: 131 - Hostname or IP address of the server hosting the virtual media image. 132 required: true 133 remote_path: 134 description: 135 - Filepath (not including the filename) of the remote image. 136 - Ex. mnt/SHARE/ISOS 137 required: true 138 remote_file: 139 description: 140 - Filename of the remote image. 141 - Ex. custom_image.iso 142 required: true 143 username: 144 description: 145 - The username for the specified Mount Type, if required. 146 password: 147 description: 148 - The password for the selected username, if required. 149 mount_options: 150 description: 151 - Mount options for the Virtual Media mapping. 152 - For NFS, supported options are ro, rw, nolock, noexec, soft, port=VALUE, timeo=VALUE, retry=VALUE 153 - For CIFS, supported options are soft, nounix, noserverino, guest 154 required: false 155 authentication_protocol: 156 description: 157 - Authentication Protocol for CIFS Mount Type 158 required: false 159author: 160 - David Soper (@dsoper2) 161 - Sid Nath (@SidNath21) 162version_added: '2.10' 163''' 164 165EXAMPLES = r''' 166- name: Configure Virtual Media Policy 167 cisco.intersight.intersight_virtual_media_policy: 168 api_private_key: "{{ api_private_key }}" 169 api_key_id: "{{ api_key_id }}" 170 organization: DevNet 171 name: lab-vmedia 172 description: Virutal Media policy for lab use 173 tags: 174 - Key: Site 175 Value: RCDN 176 cdd_virtual_media: 177 mount_type: nfs 178 volume: nfs-cdd 179 remote_hostname: 172.28.224.77 180 remote_path: mnt/SHARE/ISOS/CENTOS 181 remote_file: CentOS7.iso 182 hdd_virtual_media: 183 mount_type: nfs 184 volume: nfs-hdd 185 remote_hostname: 172.28.224.77 186 remote_path: mnt/SHARE/ISOS/CENTOS 187 remote_file: CentOS7.iso 188 189- name: Delete Virtual Media Policy 190 cisco.intersight.intersight_virtual_media_policy: 191 api_private_key: "{{ api_private_key }}" 192 api_key_id: "{{ api_key_id }}" 193 organization: DevNet 194 name: lab-vmedia 195 state: absent 196''' 197 198RETURN = r''' 199api_repsonse: 200 description: The API response output returned by the specified resource. 201 returned: always 202 type: dict 203 sample: 204 "api_response": { 205 "Name": "lab-ntp", 206 "ObjectType": "ntp.Policy", 207 "Tags": [ 208 { 209 "Key": "Site", 210 "Value": "RCDN" 211 } 212 ] 213 } 214''' 215 216 217from ansible.module_utils.basic import AnsibleModule 218from ansible_collections.cisco.intersight.plugins.module_utils.intersight import IntersightModule, intersight_argument_spec, compare_values 219 220 221def main(): 222 path = '/vmedia/Policies' 223 virtual_media_mapping = dict( 224 enable=dict(type='bool', default=True), 225 mount_type=dict(type='str', choices=['nfs', 'cifs', 'http', 'https'], required=True), 226 volume=dict(type='str', required=True), 227 remote_hostname=dict(type='str', required=True), 228 remote_path=dict(type='str', required=True), 229 remote_file=dict(type='str', required=True), 230 mount_options=dict(type='str', default=''), 231 username=dict(type='str', default=''), 232 password=dict(type='str', default='', no_log=True), 233 authentication_protocol=dict(type='str', default='none'), 234 ) 235 argument_spec = intersight_argument_spec 236 argument_spec.update( 237 state=dict(type='str', choices=['present', 'absent'], default='present'), 238 organization=dict(type='str', default='default'), 239 name=dict(type='str', required=True), 240 description=dict(type='str', aliases=['descr'], default=''), 241 tags=dict(type='list', default=[]), 242 enable=dict(type='bool', default=True), 243 encryption=dict(type='bool', default=False), 244 low_power_usb=dict(type='bool', default=True), 245 cdd_virtual_media=dict(type='dict', options=virtual_media_mapping), 246 hdd_virtual_media=dict(type='dict', options=virtual_media_mapping), 247 ) 248 249 module = AnsibleModule( 250 argument_spec, 251 supports_check_mode=True, 252 ) 253 254 intersight = IntersightModule(module) 255 intersight.result['api_response'] = {} 256 intersight.result['trace_id'] = '' 257 # Defined API body used in compares or create 258 intersight.api_body = { 259 'Organization': { 260 'Name': intersight.module.params['organization'], 261 }, 262 'Name': intersight.module.params['name'], 263 'Tags': intersight.module.params['tags'], 264 'Description': intersight.module.params['description'], 265 'Enabled': intersight.module.params['enable'], 266 "Encryption": intersight.module.params['encryption'], 267 "LowPowerUsb": intersight.module.params['low_power_usb'], 268 'Mappings': [], 269 } 270 271 if intersight.module.params.get('cdd_virtual_media'): 272 intersight.api_body['Mappings'].append( 273 { 274 "ClassId": "vmedia.Mapping", 275 "ObjectType": "vmedia.Mapping", 276 "AuthenticationProtocol": intersight.module.params['cdd_virtual_media']['authentication_protocol'], 277 "DeviceType": "cdd", 278 "HostName": intersight.module.params['cdd_virtual_media']['remote_hostname'], 279 "Password": intersight.module.params['cdd_virtual_media']['password'], 280 "IsPasswordSet": intersight.module.params['cdd_virtual_media']['password'] != '', 281 "MountOptions": intersight.module.params['cdd_virtual_media']['mount_options'], 282 "MountProtocol": intersight.module.params['cdd_virtual_media']['mount_type'], 283 "RemoteFile": intersight.module.params['cdd_virtual_media']['remote_file'], 284 "RemotePath": intersight.module.params['cdd_virtual_media']['remote_path'], 285 "Username": intersight.module.params['cdd_virtual_media']['username'], 286 "VolumeName": intersight.module.params['cdd_virtual_media']['volume'], 287 } 288 ) 289 if intersight.module.params.get('hdd_virtual_media'): 290 intersight.api_body['Mappings'].append( 291 { 292 "ClassId": "vmedia.Mapping", 293 "ObjectType": "vmedia.Mapping", 294 "AuthenticationProtocol": intersight.module.params['hdd_virtual_media']['authentication_protocol'], 295 "DeviceType": "hdd", 296 "HostName": intersight.module.params['hdd_virtual_media']['remote_hostname'], 297 "Password": intersight.module.params['hdd_virtual_media']['password'], 298 "IsPasswordSet": intersight.module.params['hdd_virtual_media']['password'] != '', 299 "MountOptions": intersight.module.params['hdd_virtual_media']['mount_options'], 300 "MountProtocol": intersight.module.params['hdd_virtual_media']['mount_type'], 301 "RemoteFile": intersight.module.params['hdd_virtual_media']['remote_file'], 302 "RemotePath": intersight.module.params['hdd_virtual_media']['remote_path'], 303 "Username": intersight.module.params['hdd_virtual_media']['username'], 304 "VolumeName": intersight.module.params['hdd_virtual_media']['volume'], 305 } 306 ) 307 308 organization_moid = None 309 # GET Organization Moid 310 intersight.get_resource( 311 resource_path='/organization/Organizations', 312 query_params={ 313 '$filter': "Name eq '" + intersight.module.params['organization'] + "'", 314 '$select': 'Moid', 315 }, 316 ) 317 if intersight.result['api_response'].get('Moid'): 318 # resource exists and moid was returned 319 organization_moid = intersight.result['api_response']['Moid'] 320 321 intersight.result['api_response'] = {} 322 # get the current state of the resource 323 filter_str = "Name eq '" + intersight.module.params['name'] + "'" 324 filter_str += "and Organization.Moid eq '" + organization_moid + "'" 325 intersight.get_resource( 326 resource_path=path, 327 query_params={ 328 '$filter': filter_str, 329 '$expand': 'Organization', 330 }, 331 ) 332 333 moid = None 334 resource_values_match = False 335 if intersight.result['api_response'].get('Moid'): 336 # resource exists and moid was returned 337 moid = intersight.result['api_response']['Moid'] 338 if module.params['state'] == 'present': 339 resource_values_match = compare_values(intersight.api_body, intersight.result['api_response']) 340 else: # state == 'absent' 341 intersight.delete_resource( 342 moid=moid, 343 resource_path=path, 344 ) 345 moid = None 346 347 if module.params['state'] == 'present' and not resource_values_match: 348 # remove read-only Organization key 349 intersight.api_body.pop('Organization') 350 if not moid: 351 # Organization must be set, but can't be changed after initial POST 352 intersight.api_body['Organization'] = { 353 'Moid': organization_moid, 354 } 355 intersight.configure_resource( 356 moid=moid, 357 resource_path=path, 358 body=intersight.api_body, 359 query_params={ 360 '$filter': filter_str, 361 }, 362 ) 363 364 module.exit_json(**intersight.result) 365 366 367if __name__ == '__main__': 368 main() 369