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_boot_order_policy
16short_description: Boot Order policy configuration for Cisco Intersight
17description:
18  - Boot Order policy configuration for Cisco Intersight.
19  - Used to configure Boot Order servers and timezone settings 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 Boot Order 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  description:
44    description:
45      - The user-defined description of the Boot Order policy.
46      - Description can contain letters(a-z, A-Z), numbers(0-9), hyphen(-), period(.), colon(:), or an underscore(_).
47    aliases: [descr]
48  configured_boot_mode:
49    description:
50      - Sets the BIOS boot mode.
51      - UEFI uses the GUID Partition Table (GPT) whereas Legacy mode uses the Master Boot Record (MBR) partitioning scheme.
52    choices: [Legacy, Uefi]
53    default: Legacy
54  uefi_enable_secure_boot:
55    description:
56      - Secure boot enforces that device boots using only software that is trusted by the Original Equipment Manufacturer (OEM).
57      - Option is only used if configured_boot_mode is set to Uefi.
58    type: bool
59    default: false
60  boot_devices:
61    description:
62      - List of Boot Devices configured on the endpoint.
63    type: list
64    suboptions:
65      enabled:
66        description:
67          - Specifies if the boot device is enabled or disabled.
68        type: bool
69        default: true
70      device_type:
71        description:
72          - Device type used with this boot option.
73          - Choices are based on each device title in the API schema.
74        choices: [iSCSI, Local CDD, Local Disk, NVMe, PCH Storage, PXE, SAN, SD Card, UEFI Shell, USB, Virtual Media]
75        required: true
76      device_name:
77        description:
78          - A name that helps identify a boot device.
79          - It can be any string that adheres to the following constraints.
80          - It should start and end with an alphanumeric character.
81          - It can have underscores and hyphens.
82          - It cannot be more than 30 characters.
83        required: true
84      network_slot:
85        description:
86          - The slot id of the controller for the iscsi and pxe device.
87          - Option is used when device_type is iscsi and pxe.
88        choices: [1 - 255, MLOM, L, L1, L2, OCP]
89      port:
90        description:
91          - The port id of the controller for the iscsi and pxe device.
92          - Option is used when device_type is iscsi and pxe.
93          - The port id need to be an integer from 0 to 255.
94      controller_slot:
95        description:
96          - The slot id of the controller for the local disk device.
97          - Option is used when device_type is local_disk.
98        choices: [1-255, M, HBA, SAS, RAID, MRAID, MSTOR-RAID]
99      bootloader_name:
100        description:
101          - Details of the bootloader to be used during boot from local disk.
102          - Option is used when device_type is local_disk and configured_boot_mode is Uefi.
103      bootloader_description:
104        description:
105          - Details of the bootloader to be used during boot from local disk.
106          - Option is used when device_type is local_disk and configured_boot_mode is Uefi.
107      bootloader_path:
108        description:
109          - Details of the bootloader to be used during boot from local disk.
110          - Option is used when device_type is local_disk and configured_boot_mode is Uefi.
111      ip_type:
112        description:
113          - The IP Address family type to use during the PXE Boot process.
114          - Option is used when device_type is pxe.
115        chocies: [None, IPv4, IPv6]
116        default: None
117      interface_source:
118        description:
119          - Lists the supported Interface Source for PXE device.
120          - Option is used when device_type is pxe.
121        choices: [name, mac, port]
122        default: name
123      intefrace_name:
124        description:
125          - The name of the underlying virtual ethernet interface used by the PXE boot device.
126          - Option is used when device_type is pxe and interface_source is name.
127      mac_address:
128        description:
129          - The MAC Address of the underlying virtual ethernet interface used by the PXE boot device.
130          - Option is used when device_type is pxe and interface_source is mac.
131      sd_card_subtype:
132        description:
133          - The subtype for the selected device type.
134          - Option is used when device_type is sd_card.
135        choices: [None, flex-util, flex-flash, SDCARD]
136        default: None
137      lun:
138        description:
139          - The Logical Unit Number (LUN) of the device.
140          - Option is used when device_type is pch, san and sd_card.
141          - The LUN need to be an integer from 0 to 255.
142      usb_subtype:
143        description:
144          - The subtype for the selected device type.
145          - Option is used when device_type is usb.
146        choices: [None, usb-cd, usb-fdd, usb-hdd]
147        default: None
148      virtual_media_subtype:
149        description:
150          - The subtype for the selected device type.
151          - Option is used when device_type is virtual_media.
152        choices: [None, cimc-mapped-dvd, cimc-mapped-hdd, kvm-mapped-dvd, kvm-mapped-hdd, kvm-mapped-fdd]
153        default: None
154author:
155  - Tse Kai "Kevin" Chan (@BrightScale)
156version_added: '2.10'
157'''
158
159EXAMPLES = r'''
160- name: Configure Boot Order Policy
161  cisco.intersight.intersight_boot_order_policy:
162    api_private_key: "{{ api_private_key }}"
163    api_key_id: "{{ api_key_id }}"
164    organization: DevNet
165    name: COS-Boot
166    description: Boot Order policy for COS
167    tags:
168      - Key: Site
169        Value: RCDN
170    configured_boot_mode: legacy
171    boot_devices:
172      - device_type: Local Disk
173        device_name: Boot-Lun
174        controller_slot: MRAID
175
176- name: Delete Boot Order Policy
177  cisco.intersight.intersight_boot_policy:
178    api_private_key: "{{ api_private_key }}"
179    api_key_id: "{{ api_key_id }}"
180    organization: DevNet
181    name: COS-Boot
182    state: absent
183'''
184
185RETURN = r'''
186api_repsonse:
187  description: The API response output returned by the specified resource.
188  returned: always
189  type: dict
190  sample:
191    "api_response": {
192        "Name": "COS-Boot",
193        "ObjectType": "boot.Policy",
194        "Tags": [
195            {
196                "Key": "Site",
197                "Value": "RCDN"
198            }
199        ]
200    }
201'''
202
203
204from ansible.module_utils.basic import AnsibleModule
205from ansible_collections.cisco.intersight.plugins.module_utils.intersight import IntersightModule, intersight_argument_spec
206
207
208def main():
209    boot_device = dict(
210        enabled=dict(type='bool', default=True),
211        device_type=dict(
212            type='str',
213            choices=[
214                'iSCSI',
215                'Local CDD',
216                'Local Disk',
217                'NVMe',
218                'PCH Storage',
219                'PXE',
220                'SAN',
221                'SD Card',
222                'UEFI Shell',
223                'USB',
224                'Virtual Media',
225            ],
226            required=True,
227        ),
228        device_name=dict(type='str', required=True),
229        # iscsi and pxe options
230        network_slot=dict(type='str', default=''),
231        port=dict(type='int', default=0),
232        # local disk options
233        controller_slot=dict(type='str', default=''),
234        # bootloader options
235        bootloader_name=dict(type='str', default=''),
236        bootloader_description=dict(type='str', default=''),
237        bootloader_path=dict(type='str', default=''),
238        # pxe only options
239        ip_type=dict(
240            type='str',
241            choices=[
242                'None',
243                'IPv4',
244                'IPv6'
245            ],
246            default='None'
247        ),
248        interface_source=dict(
249            type='str',
250            choices=[
251                'name',
252                'mac',
253                'port'
254            ],
255            default='name'
256        ),
257        interface_name=dict(type='str', default=''),
258        mac_address=dict(type='str', defualt=''),
259        # sd card options
260        sd_card_subtype=dict(
261            type='str',
262            choices=[
263                'None',
264                'flex-util',
265                'flex-flash',
266                'SDCARD'
267            ],
268            default='None',
269        ),
270        # lun for pch, san, sd_card
271        lun=dict(type='int', default=0),
272        # usb options
273        usb_subtype=dict(
274            type='str',
275            choices=[
276                'None',
277                'usb-cd',
278                'usb-fdd',
279                'usb-hdd'
280            ],
281            default='None',
282        ),
283        # virtual media options
284        virtual_media_subtype=dict(
285            type='str',
286            choices=[
287                'None',
288                'cimc-mapped-dvd',
289                'cimc-mapped-hdd',
290                'kvm-mapped-dvd',
291                'kvm-mapped-hdd',
292                'kvm-mapped-fdd'
293            ],
294            default='None',
295        ),
296    )
297    argument_spec = intersight_argument_spec
298    argument_spec.update(
299        state=dict(type='str', choices=['present', 'absent'], default='present'),
300        organization=dict(type='str', default='default'),
301        name=dict(type='str', required=True),
302        description=dict(type='str', aliases=['descr'], default=''),
303        tags=dict(type='list', default=[]),
304        configured_boot_mode=dict(type='str', choices=['Legacy', 'Uefi'], default='Legacy'),
305        uefi_enable_secure_boot=dict(type='bool', default=False),
306        boot_devices=dict(type='list', elements='dict', options=boot_device),
307    )
308
309    module = AnsibleModule(
310        argument_spec,
311        supports_check_mode=True,
312    )
313
314    intersight = IntersightModule(module)
315    intersight.result['api_response'] = {}
316    intersight.result['trace_id'] = ''
317    #
318    # Argument spec above, resource path, and API body should be the only code changed in each policy module
319    #
320    # Resource path used to configure policy
321    resource_path = '/boot/PrecisionPolicies'
322    # Define API body used in compares or create
323    intersight.api_body = {
324        'Organization': {
325            'Name': intersight.module.params['organization'],
326        },
327        'Name': intersight.module.params['name'],
328        'Tags': intersight.module.params['tags'],
329        'Description': intersight.module.params['description'],
330        'ConfiguredBootMode': intersight.module.params['configured_boot_mode'],
331        "EnforceUefiSecureBoot": intersight.module.params['uefi_enable_secure_boot'],
332        'BootDevices': [],
333    }
334    if intersight.module.params.get('boot_devices'):
335        for device in intersight.module.params['boot_devices']:
336            if device['device_type'] == 'iSCSI':
337                intersight.api_body['BootDevices'].append(
338                    {
339                        "ClassId": "boot.Iscsi",
340                        "ObjectType": "boot.Iscsi",
341                        "Enabled": device['enabled'],
342                        "Name": device['device_name'],
343                        "Slot": device['network_slot'],
344                        "Port": device['port'],
345                    }
346                )
347            elif device['device_type'] == 'Local CDD':
348                intersight.api_body['BootDevices'].append(
349                    {
350                        "ClassId": "boot.LocalCDD",
351                        "ObjectType": "boot.LocalCDD",
352                        "Enabled": device['enabled'],
353                        "Name": device['device_name'],
354                    }
355                )
356            elif device['device_type'] == 'Local Disk':
357                intersight.api_body['BootDevices'].append(
358                    {
359                        "ClassId": "boot.LocalDisk",
360                        "ObjectType": "boot.LocalDisk",
361                        "Enabled": device['enabled'],
362                        "Name": device['device_name'],
363                        "Slot": device['controller_slot'],
364                        "Bootloader": {
365                            "ClassId": "boot.Bootloader",
366                            "ObjectType": "boot.Bootloader",
367                            "Description": device['bootloader_description'],
368                            "Name": device['bootloader_name'],
369                            "Path": device['bootloader_path'],
370                        },
371                    }
372                )
373            elif device['device_type'] == 'NVMe':
374                intersight.api_body['BootDevices'].append(
375                    {
376                        "ClassId": "boot.NVMe",
377                        "ObjectType": "boot.NVMe",
378                        "Enabled": device['enabled'],
379                        "Name": device['device_name'],
380                        "Bootloader": {
381                            "ClassId": "boot.Bootloader",
382                            "ObjectType": "boot.Bootloader",
383                            "Description": device['bootloader_description'],
384                            "Name": device['bootloader_name'],
385                            "Path": device['bootloader_path'],
386                        },
387                    }
388                )
389            elif device['device_type'] == 'PCH Storage':
390                intersight.api_body['BootDevices'].append(
391                    {
392                        "ClassId": "boot.PchStorage",
393                        "ObjectType": "boot.PchStorage",
394                        "Enabled": device['enabled'],
395                        "Name": device['device_name'],
396                        "Bootloader": {
397                            "ClassId": "boot.Bootloader",
398                            "ObjectType": "boot.Bootloader",
399                            "Description": device['bootloader_description'],
400                            "Name": device['bootloader_name'],
401                            "Path": device['bootloader_path'],
402                        },
403                        "Lun": device['lun'],
404                    }
405                )
406            elif device['device_type'] == 'PXE':
407                intersight.api_body['BootDevices'].append(
408                    {
409                        "ClassId": "boot.Pxe",
410                        "ObjectType": "boot.Pxe",
411                        "Enabled": device['enabled'],
412                        "Name": device['device_name'],
413                        "IpType": device['ip_type'],
414                        "InterfaceSource": device['interface_source'],
415                        "Slot": device['network_slot'],
416                        "InterfaceName": device['interface_name'],
417                        "Port": device['port'],
418                        "MacAddress": device['mac_address'],
419                    }
420                )
421            elif device['device_type'] == 'SAN':
422                intersight.api_body['BootDevices'].append(
423                    {
424                        "ClassId": "boot.San",
425                        "ObjectType": "boot.San",
426                        "Enabled": device['enabled'],
427                        "Name": device['device_name'],
428                        "Lun": device['lun'],
429                        "Slot": device['network_slot'],
430                        "Bootloader": {
431                            "ClassId": "boot.Bootloader",
432                            "ObjectType": "boot.Bootloader",
433                            "Description": device['bootloader_description'],
434                            "Name": device['bootloader_name'],
435                            "Path": device['bootloader_path'],
436                        },
437                    }
438                )
439            elif device['device_type'] == 'SD Card':
440                intersight.api_body['BootDevices'].append(
441                    {
442                        "ClassId": "boot.SdCard",
443                        "ObjectType": "boot.SdCard",
444                        "Enabled": device['enabled'],
445                        "Name": device['device_name'],
446                        "Lun": device['lun'],
447                        "SubType": device['sd_card_subtype'],
448                        "Bootloader": {
449                            "ClassId": "boot.Bootloader",
450                            "ObjectType": "boot.Bootloader",
451                            "Description": device['bootloader_description'],
452                            "Name": device['bootloader_name'],
453                            "Path": device['bootloader_path'],
454                        },
455                    }
456                )
457            elif device['device_type'] == 'UEFI Shell':
458                intersight.api_body['BootDevices'].append(
459                    {
460                        "ClassId": "boot.UefiShell",
461                        "ObjectType": "boot.UefiShell",
462                        "Enabled": device['enabled'],
463                        "Name": device['device_name'],
464                    }
465                )
466            elif device['device_type'] == 'USB':
467                intersight.api_body['BootDevices'].append(
468                    {
469                        "ClassId": "boot.Usb",
470                        "ObjectType": "boot.Usb",
471                        "Enabled": device['enabled'],
472                        "Name": device['device_name'],
473                        "SubType": device['usb_subtype'],
474                    }
475                )
476            elif device['device_type'] == 'Virtual Media':
477                intersight.api_body['BootDevices'].append(
478                    {
479                        "ClassId": "boot.VirtualMedia",
480                        "ObjectType": "boot.VirtualMedia",
481                        "Enabled": device['enabled'],
482                        "Name": device['device_name'],
483                        "SubType": device['virtual_media_subtype'],
484                    }
485                )
486    #
487    # Code below should be common across all policy modules
488    #
489    intersight.configure_policy_or_profile(resource_path=resource_path)
490
491    module.exit_json(**intersight.result)
492
493
494if __name__ == '__main__':
495    main()
496