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