File ardana-cobbler-9.0+git.1660747489.119efcd.obscpio of Package ardana-cobbler

07070100000000000081A400000000000000000000000162FCFEE10000000B000000000000000000000000000000000000003B00000000ardana-cobbler-9.0+git.1660747489.119efcd/.copyrightignore.gitignore
07070100000001000081A400000000000000000000000162FCFEE100000007000000000000000000000000000000000000003500000000ardana-cobbler-9.0+git.1660747489.119efcd/.gitignore.*.swp
07070100000002000081A400000000000000000000000162FCFEE10000007A000000000000000000000000000000000000003500000000ardana-cobbler-9.0+git.1660747489.119efcd/.gitreview[gerrit]
host=gerrit.prv.suse.net
port=29418
project=ardana/cobbler-ansible.git
defaultremote=ardana
defaultbranch=master
07070100000003000081A400000000000000000000000162FCFEE10000279F000000000000000000000000000000000000003200000000ardana-cobbler-9.0+git.1660747489.119efcd/LICENSE
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

07070100000004000081A400000000000000000000000162FCFEE100000A8D000000000000000000000000000000000000003400000000ardana-cobbler-9.0+git.1660747489.119efcd/README.md(c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
(c) Copyright 2017-2018 SUSE LLC

Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.


README
======

This repo contains the following roles:
- COBBLER: Cobbler server role

The verbs:
- configure
- install
- start
- populate

The operations:
- deploy

Repo structure:

```
├── bm-reimage.yml
├── cobbler-bm-verify.yml
├── cobbler-deploy.yml
├── cobbler-power-down.yml
├── cobbler-power-status.yml
├── cobbler-power-up.yml
├── cobbler-provision.yml
├── cobbler-set-diskboot-all.yml
├── cobbler-set-pxeboot-all.yml
├── cobbler-wait-for-shutdown.yml
├── cobbler-wait-for-ssh.yml
├── library
│   ├── bmconfig
│   └── ipmi
├── README.md
└── roles
    └── cobbler
        ├── defaults
        │   └── main.yml
        ├── files
        │   ├── cobbler.conf
        │   ├── configure_network.sh
        │   ├── fence_ipmitool.template
        │   └── validate_yaml
        ├── tasks
        │   ├── check-ipmi-connectivity.yml
        │   ├── configure.yml
        │   ├── get-nodelist.yml
        │   ├── install.yml
        │   ├── populate.yml
        │   ├── power-cycle-all.yml
        │   ├── power-down-all.yml
        │   ├── power-up-all.yml
        │   ├── set-diskboot-all.yml
        │   ├── set-pxeboot-all.yml
        │   ├── set-vars.yml
        │   ├── start.yml
        │   ├── verify-bm-install.yml
        │   ├── wait-for-shutdown.yml
        │   └── wait-for-ssh.yml
        ├── templates
        │   ├── cobbler.dhcp.template.j2
        │   ├── dhcpd.conf.j2
        │   ├── dhcpd-start-limit.conf.j2
        │   ├── grub.cfg.j2
        │   ├── hlinux-server-vm.preseed.j2
        │   ├── isc-dhcp-server.j2
        │   ├── rhel73-anaconda-ks.cfg.j2
        │   └── settings.j2
        └── vars
            └── main.yml
```
07070100000005000081ED00000000000000000000000162FCFEE100000C95000000000000000000000000000000000000003B00000000ardana-cobbler-9.0+git.1660747489.119efcd/ardanaencrypt.py#!/usr/bin/env python
#
# A utility to encrypt passwords for auxiliary Ardana OpenStack
# systems like IPMI.
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import os
from subprocess import PIPE, Popen

encryption_env = 'ARDANA_USER_PASSWORD_ENCRYPT_KEY'
legacy_encryption_env = 'HOS_USER_PASSWORD_ENCRYPT_KEY'


class aes256:
    prefix = '@ardana_aes256@'
    legacy_prefix = '@hos_aes256@'

    def __init__(self, key):
        pass

    def encrypt(self, raw):
        return ""

    def decrypt(self, cooked):
        return ""


class openssl:
    prefix = '@ardana@'
    legacy_prefix = '@hos@'

    def __init__(self, key=None):
        pass

    def _get_env_key_name(self):
        if encryption_env in os.environ and os.environ[encryption_env]:
            return encryption_env
        elif (legacy_encryption_env in os.environ and
              os.environ[legacy_encryption_env]):
            return legacy_encryption_env
        else:
            return encryption_env

    def delegate(self, cmd, value):
        # Note that I'm passing the environment variable's name to the
        # subprocess, not its value.
        argv = ('/usr/bin/openssl', 'aes-256-cbc', '-a',
                cmd, '-pass', 'env:%s' % self._get_env_key_name())
        p = Popen(argv, close_fds=True, stdin=PIPE, stdout=PIPE, stderr=PIPE)
        result = p.communicate(input=value)
        if p.returncode != 0:
            errmsg = result[1].strip()
            if errmsg.startswith('bad decrypt'):
                errmsg = 'incorrect encryption key'
            elif (errmsg.startswith('error reading input file') or
                  errmsg.startswith('bad magic number')):
                errmsg = 'bad input data'
            raise OSError('openssl: %s' % errmsg)
        return result[0].strip()

    def encrypt(self, raw):
        return self.delegate('-salt', raw)

    def decrypt(self, cooked):
        # openssl expects a newline at the end of the string.
        if cooked[-1] != '\n':
            cooked += '\n'
        return self.delegate('-d', cooked)


def main():
    import getpass
    import sys

    obj = openssl()
    if len(sys.argv) > 1 and sys.argv[1] == '-d':
        value = getpass.getpass('encrypted value? ')
        if value.startswith(obj.prefix):
            value = value[len(obj.prefix):]
        elif value.startswith(obj.legacy_prefix):
            value = value[len(obj.legacy_prefix):]
        x = obj.decrypt(value)
        print x
    else:
        value = getpass.getpass('unencrypted value? ')
        x = obj.encrypt(value)
        print obj.prefix + x


if __name__ == '__main__':
    main()
07070100000006000081A400000000000000000000000162FCFEE1000003AD000000000000000000000000000000000000004500000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-assert-power-is-off.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-all-nodes.yml
  when: dynamic_targets_created is undefined

- hosts: dynamic_targets
  max_fail_percentage: 100
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/assert-power-is-off.yml
    - include: roles/cobbler/tasks/assert-nodes-are-not-pingable.yml
07070100000007000081A400000000000000000000000162FCFEE1000004D9000000000000000000000000000000000000003A00000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-diskboot.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-no-default.yml
  when: dynamic_targets_created is undefined

# Tasks that can safely be done in parallel.
- hosts: dynamic_targets
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/set-diskboot.yml
      when: set_bootdev

# Tasks that can't.
- hosts: dynamic_targets
  serial: 1
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/netboot-off.yml
      when: set_bootdev

- include: bm-power-up.yml

- hosts: localhost
  tasks:
    - name: The nodes have been instructed to boot from disk
      pause: minutes=1

- include: bm-wait-for-ssh.yml
07070100000008000081A400000000000000000000000162FCFEE10000034E000000000000000000000000000000000000003D00000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-power-cycle.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-no-default.yml
  when: dynamic_targets_created is undefined

- hosts: dynamic_targets
  serial: 10
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/power-cycle.yml
07070100000009000081A400000000000000000000000162FCFEE10000036D000000000000000000000000000000000000003C00000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-power-down.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-no-default.yml
  when: dynamic_targets_created is undefined

- hosts: dynamic_targets
  max_fail_percentage: 100
  serial: 10
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/power-down.yml
0707010000000A000081A400000000000000000000000162FCFEE100000409000000000000000000000000000000000000003E00000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-power-status.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: pbstart.yml
  vars:
    playbook_name: "bm-power-status.yml"

- include: bm-target-all-nodes.yml
  when: dynamic_targets_created is undefined

- hosts: dynamic_targets
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/get-power-status.yml
    - debug: msg="{{ ipmi_connectivity.power }}"

- include: pbfinish.yml
  vars:
    playbook_name: "bm-power-status.yml"
0707010000000B000081A400000000000000000000000162FCFEE10000034B000000000000000000000000000000000000003A00000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-power-up.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-no-default.yml
  when: dynamic_targets_created is undefined

- hosts: dynamic_targets
  serial: 10
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/power-up.yml
0707010000000C000081A400000000000000000000000162FCFEE100000643000000000000000000000000000000000000003B00000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-provision.yml#
# (c) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-netboot-nodes.yml
  when: dynamic_targets_created is undefined

- hosts: localhost
  become: yes
  roles:
    - cobbler
  tasks:
    - shell: date +%Y%m%d%H%M%S > {{ local_timestamp_file }}

# Cobbler cli is not thread safe so have to do these one at a time.
- hosts: dynamic_targets
  serial: 1
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/netboot-on.yml
      when: set_bootdev

- hosts: dynamic_targets
  serial: "{{ bm_batch_size | default(20) }}"
  roles:
    - cobbler
  tasks:
    - name: "Starting reimage batch"
      pause:
        seconds: 10
    - include: roles/cobbler/tasks/set-pxeboot.yml
      when: set_bootdev
    - include: roles/cobbler/tasks/power-cycle.yml
    - name: "These nodes have been instructed to install over PXE"
      pause:
        minutes: 3
    - include: roles/cobbler/tasks/wait-for-shutdown.yml
    - include: roles/cobbler/tasks/set-diskboot.yml
      when: set_bootdev
0707010000000D000081A400000000000000000000000162FCFEE100000512000000000000000000000000000000000000003900000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-reimage.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: pbstart.yml
  vars:
    playbook_name: "bm-reimage.yml"

- include: bm-target-netboot-nodes.yml
  when: dynamic_targets_created is undefined

- hosts: localhost
  tasks:
    - name: The nodes listed above will be reimaged
      pause: minutes=1

- include: bm-power-down.yml

- hosts: localhost
  tasks:
    - name: Waiting for the nodes to power off
      pause: minutes=4
- include: bm-assert-power-is-off.yml

- include: bm-provision.yml

- hosts: localhost
  tasks:
    - name: Pausing to allow nodes to fully shut down
      pause: minutes=1

- include: bm-diskboot.yml

- include: pbfinish.yml
  vars:
    playbook_name: "bm-reimage.yml"
0707010000000E000081A400000000000000000000000162FCFEE1000002EF000000000000000000000000000000000000004200000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-target-all-nodes.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- hosts: localhost
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/target-all-nodes.yml
0707010000000F000081A400000000000000000000000162FCFEE1000002F2000000000000000000000000000000000000004600000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-target-netboot-nodes.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- hosts: localhost
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/target-netboot-nodes.yml
07070100000010000081A400000000000000000000000162FCFEE10000036B000000000000000000000000000000000000004300000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-target-no-default.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- hosts: localhost
  roles:
    - cobbler
  tasks:
    # There's no default set of nodes for this command; needs to be
    # set by the caller, or on the command line by the user.
    - include: roles/cobbler/tasks/get-nodelist.yml
07070100000011000081A400000000000000000000000162FCFEE10000037D000000000000000000000000000000000000003800000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-verify.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Playbook used by vagrant to help provision virtual machines
# You should not need to run this manually!
---

- include: ardana-ssh-keyscan.yml

- hosts: resources
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/verify-bm-install.yml
07070100000012000081A400000000000000000000000162FCFEE100000346000000000000000000000000000000000000004300000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-wait-for-shutdown.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-all-nodes.yml
  when: dynamic_targets_created is undefined

- hosts: dynamic_targets
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/wait-for-shutdown.yml
07070100000013000081A400000000000000000000000162FCFEE100000341000000000000000000000000000000000000003E00000000ardana-cobbler-9.0+git.1660747489.119efcd/bm-wait-for-ssh.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: bm-target-all-nodes.yml
  when: dynamic_targets_created is undefined

- hosts: dynamic_targets
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/wait-for-ssh.yml
07070100000014000081A400000000000000000000000162FCFEE100000600000000000000000000000000000000000000003D00000000ardana-cobbler-9.0+git.1660747489.119efcd/cobbler-deploy.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- include: pbstart.yml
  vars:
    playbook_name: "cobbler-deploy.yml"

- hosts: localhost
  roles:
    - cobbler
    - deployer-setup
  vars_prompt:
    - name: ardanauser_password
      prompt: "Enter the password that will be used to access provisioned nodes"
      private: yes
      confirm: yes
      when: ardanauser_password is not defined
  tasks:
    - include: roles/cobbler/tasks/set-vars.yml
    - include: roles/cobbler/tasks/install.yml
    - include: roles/cobbler/tasks/update-signatures.yml
    - include: roles/cobbler/tasks/configure.yml
    - include: roles/cobbler/tasks/start.yml
    - include: roles/cobbler/tasks/get-baremetal-info.yml
    - include: roles/cobbler/tasks/populate-rhel.yml
    - include: roles/cobbler/tasks/populate-sles.yml
    - include: roles/cobbler/tasks/populate.yml

- include: pbfinish.yml
  vars:
    playbook_name: "cobbler-deploy.yml"
07070100000015000081A400000000000000000000000162FCFEE10000031C000000000000000000000000000000000000004200000000ardana-cobbler-9.0+git.1660747489.119efcd/cobbler-reconfigure.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- hosts: localhost
  roles:
    - cobbler
  tasks:
    - include: roles/cobbler/tasks/set-vars.yml
    - include: roles/cobbler/tasks/reconfig-dhcp.yml
07070100000016000041ED00000000000000000000000262FCFEE100000000000000000000000000000000000000000000003200000000ardana-cobbler-9.0+git.1660747489.119efcd/library07070100000017000081A400000000000000000000000162FCFEE1000019BC000000000000000000000000000000000000003B00000000ardana-cobbler-9.0+git.1660747489.119efcd/library/bmconfig#!/usr/bin/env python
#
# An Ansible module to parse baremetalConfig.yml (or json)
#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

DOCUMENTATION = '''
---
module: bmconfig
author: Joe Fegan
short_description: Returns baremetal information from servers.yml
description:
    - Isolates parsing of baremetal information from the playbooks that consume it.
    - By default this module returns a struct containing all information available.
options:
    field:
        required: false
        description:
            - Returns just the value of this field, on stdout.
    node:
        required: false
        description:
            - Used with "field", returns just the value for this specific node.
'''

EXAMPLES = '''
- bmconfig: file={{ baremetal_config }}
- bmconfig: file={{ baremetal_config }} field=id
- bmconfig: file={{ baremetal_config }} field=role node=ccn-0001
'''

from netaddr import  IPNetwork
import yaml


class BmConfig(object):
    name = 'bmconfig'

    # The field that contains the node name.
    idfield = 'id'
    # The field that contains the primary IP of the node.
    ipaddrfield = 'ip_addr'
    # If this field is not present the node will be ignored.
    # Intended as a means of identifying nodes in the model
    # that we don't control e.g. pre-built VMs or the like.
    ignorefield = 'ilo_ip'

    # Old field names and their modern equivalents.
    fieldmap = {
        'node_name': 'id',
        'node_type': 'role',
        'pxe_ip_addr': 'ip_addr',
        'pxe_mac_addr': 'mac_addr',
        'kopts_extra': 'kopt_extras' }

    def __init__(self, module):
        self.module = module

        try:
            self.fname = module.params["file"]
            self.field = module.params["field"]
            self.node = module.params["node"]
            self.default_distro_id = module.params["default_distro_id"]
            self.data = None
            self.network = None
            self.localips = None
        except ValueError as e:
            self.fail(msg="%s: bad value %s" % (self.name, str(e)))

    def fail(self, **kwargs):
        return self.module.fail_json(**kwargs)

    def succeed(self, **kwargs):
        return self.module.exit_json(**kwargs)

    def execv(self, cmd, **kwargs):
        return self.module.run_command(cmd, **kwargs)

    # This doesn't do much yet, but in time it will handle more complex
    # data file locations and varying content.
    def load_data(self):
        y = yaml.safe_load(file(self.fname))
        if 'servers' in y:
            key = 'servers'
        elif 'baremetal_servers' in y:
            # Backward compatibility
            key = 'baremetal_servers'
        else:
            raise AttributeError('no servers info found in %s' % self.fname)
        self.data = [self.map_fields(item) for item in y[key]]

        if 'baremetal' in y:
            key = 'baremetal'
        elif 'baremetal_network' in y:
            # Backward compatibility
            key = 'baremetal_network'
        else:
            raise AttributeError('no network info found in %s' % self.fname)
        self.network = self.map_fields(y[key])
        if 'cidr' in self.network:
            if 'subnet' in self.network or 'netmask' in self.network:
                raise KeyError('cannot specify both cidr and subnet/netmask')
            ip = IPNetwork(self.network['cidr'])
            self.network['subnet'] = str(ip.network)
            self.network['netmask'] = str(ip.netmask)
        else:
            ip = IPNetwork('/'.join([self.network['subnet'], self.network['netmask']]))
            self.network['cidr']= str(ip.cidr)
        cmd = ['/bin/bash', '-c', 'ip a | awk \'/inet / {sub("/.*","",$2) ; print $2}\'']
        rc, out, err = self.execv(cmd, check_rc=True)
        self.localips = out.strip().split('\n')

    # Handle backward compatibility of field names.
    def map_fields(self, srv):
        result = dict()
        for (key, value) in srv.iteritems():
            try:
                result[self.fieldmap[key]] = value
            except KeyError:
                # Ansible doesn't accept - in variable names.
                result[key.replace('-','_')] = value
        return result

    def action_field(self):
        lst = list()
        for srv in self.data:
            if self.node is None or srv[self.idfield] == self.node:
                lst.append(srv[self.field])
        result = dict(stdout="\n".join(lst))
        self.succeed(**result)

    def action_struct(self):
        lst = list()
        svrids = list()
        whoami = 'localhost'
        for srv in self.data:
            if self.ignorefield not in srv:
                continue
            lst.append(srv)
            svrids.append(srv[self.idfield])
            if srv[self.ipaddrfield] in self.localips:
                whoami = srv[self.idfield]
        facts = {'bminfo': dict(servers=lst,network=self.network,server_ids=svrids,whoami=whoami)}
        result = dict(ansible_facts=facts)
        self.succeed(**result)

    def add_default(self):
        for srv in self.data:
            if "boot_from_san" not in srv:
                srv["boot_from_san"] = False
            if "fcoe_interfaces" not in srv:
                srv["fcoe_interfaces"] = []
            if "persistent_interfaces" not in srv:
                srv["persistent_interfaces"] = []
            if "distro_id" not in srv:
                srv["distro_id"] = self.default_distro_id

    def execute(self):
        self.load_data()

        self.add_default()

        if self.field:
            return self.action_field()
        else:
            return self.action_struct()


def main():
    module = AnsibleModule(
        argument_spec=dict(
            file=dict(required=True),
            field=dict(required=False),
            node=dict(required=False),
            default_distro_id=dict(required=False)
        )
    )

    mod = BmConfig(module)
    return mod.execute()


from ansible.module_utils.basic import *
main()
07070100000018000081A400000000000000000000000162FCFEE100001628000000000000000000000000000000000000003800000000ardana-cobbler-9.0+git.1660747489.119efcd/library/hpilo#!/usr/bin/env python
#
# (c) Copyright 2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# An Ansible module to allow playbooks to communicate with
# HP ILO devices using SMASH CLP commands.

DOCUMENTATION = '''
---
module: hpiLO
author: Wayne Okuma
short_description: Issue a SMASH CLP command to HP-ILO hosts
description:
    - Issue SMASH CLP commands to an HP ILO server.
    - HPILO credentials and network addresses can be specified in a JSON or
      YAML file, or can be retrieved from Cobbler.
options:
    name:
        required: true
        description:
            - Name of the node to manage.
    credsfile:
        required: false
        description:
            - The Credentals file which contains the HP ILO user, password and
              IP-Address of the HP ILO server by the name specified (e.g., the
              servers.yml file).
    command:
        required: true
        description:
            - the SMASH CLP command to issue to the server.
'''

EXAMPLES = '''
- hpilo: name=compute2 command="show /system1/bootconfig1 oemhp_bootmode"
- hpilo: name=compute2 credsfile="/tmp/nodeinfo.yml" \
         command="set /system1/bootconfig1/oemhp_uefibootsource4 bootorder=1"
'''

import os
import pexpect
import re
import time
import yaml

# Load the local module
import imp
ardanaencrypt = imp.load_source('ardanaencrypt', './ardanaencrypt.py')

openssl_prefix = ardanaencrypt.openssl.prefix

def decrypt(value):
    if value.startswith(openssl_prefix):
        decrypter = hosencrypt.openssl
    else:
        return value
    obj = decrypter()
    return obj.decrypt(value[len(obj.prefix):])

def parse_command_result_status(command_result):
    for line in command_result.strip().splitlines():
        if line.find("status=") != -1:
            return line.strip("status=")
    return("-1")

class HPilo(object):
    def __init__(self, module):
        self.module = module

        try:
            self.node = module.params["name"]
            self.credsfile = module.params["credsfile"]
            self.command = module.params["command"]
        except ValueError as e:
            self.module.fail_json(msg="hpilo: " + str(e))

    def cobbler_creds(self, node):
        cmd = ["sudo", "cobbler", "system", "dumpvars", "--name=%s" % node]
        rc, out, err = self.execv(cmd, check_rc=True)
        creds = dict()
        translation = {"power_address": "ip", "power_user": "user", "power_pass": "password"}
        for line in out.splitlines():
            key, value = line.split(" : ")
            if key in translation:
                if value == "":
                    break
                creds[translation[key]] = value
        if len(translation) != len(creds):
            self.fail(msg="hpilo: missing creds for %s in cobbler" % node)
        return creds

    def file_creds(self, fname):
        data = yaml.safe_load(file(fname))
        creds = dict()
        if "servers" in data:
            field = "servers"
            ident = "id"
            iloip = "ilo-ip"
            ilouser = "ilo-user"
            ilopassword = "ilo-password"
        else:
            # Backward compatibility
            field = "baremetal_servers"
            ident = "node_name"
            iloip = "ilo_ip"
            ilouser = "ilo_user"
            ilopassword = "ilo_password"

        for srv in data[field]:
            if srv[ident] == self.node:
                creds["ip"] = srv[iloip]
                creds["user"] = srv[ilouser]
                creds["password"] = decrypt(srv[ilopassword])
                break
        return creds

    def get_creds(self, node):
        if self.credsfile:
            return self.file_creds(self.credsfile)
        else:
            return self.cobbler_creds(node)

    def execute(self):
        ssh_disable_host_key = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '
        try:
            creds = self.get_creds(self.node)

            child = pexpect.spawn('ssh ' + ssh_disable_host_key + creds["user"] + '@' + creds["ip"])
            child.expect('password')
            child.sendline(creds["password"])
            child.expect('</>hpiLO->')
            child.sendline(self.command)
            child.expect('</>hpiLO->')
            command_result = child.before
            child.sendline('exit')

            result = dict(
                changed=False,
                stdout=command_result,
                stderr=''
            )
            print(command_result)
            rc = parse_command_result_status(command_result)
            if rc == '0':
               result['changed']=True
               self.module.exit_json(**result)
            else:
               self.module.fail_json(msg='command failed', **result)
        except Exception as e:
            self.module.fail_json(msg='hpilo: processing failed ' + str(e))


def main():
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            command=dict(required=True),
            credsfile=dict(required=False),
        )
    )

    hpilo = HPilo(module)
    return hpilo.execute()


from ansible.module_utils.basic import *
main()
07070100000019000081ED00000000000000000000000162FCFEE100004AB8000000000000000000000000000000000000004000000000ardana-cobbler-9.0+git.1660747489.119efcd/library/hpilosetup.py#!/usr/bin/env python
#
# Copyright 2014 Hewlett-Packard Development Company, L.P.
# Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from __future__ import print_function
import argparse
import json
import sys
# Need six > 1.3.0 (1.8.0 works)
import six
import urllib3
try:
    urllib3.disable_warnings(urllib3.exceptions.InsecurePlatformWarning)
except:
    pass

from proliantutils.ilo import ribcl

from httplib import HTTPSConnection
from base64 import b64encode


def do_raw_cmd(cmd, hostname, path, headers, data=None):
    conn = HTTPSConnection(host=hostname, strict=True)
    conn.request(cmd, path, headers=headers, body=data)
    resp = conn.getresponse().read()
    return resp


def do_raw_get(hostname, path, headers):
    return do_raw_cmd('GET', hostname, path, headers)


def do_raw_patch(hostname, path, headers, data):
    return do_raw_cmd('PATCH', hostname, path, headers, data)


def set_propagate_time(ilo_client, val='N'):
    """
       Set PROPAGATE_TIME_TO_HOST configuration item
       If this is set, then the iLO can set the time on the host
       on powerup, and, if the iLO is misconfigured, the host can
       encounter time jumps that cause issues with other apps,
       including at installation time.
    """
    import xml.etree.ElementTree as etree
    xml = ilo_client._create_dynamic_xml('MOD_GLOBAL_SETTINGS',
                                         'RIB_INFO', 'write')
    if six.PY2:
        child_iterator = xml.getiterator()
    else:
        child_iterator = xml.iter()
    for child in child_iterator:
        if child.tag == 'MOD_GLOBAL_SETTINGS':
            etree.SubElement(child, 'PROPAGATE_TIME_TO_HOST', VALUE=val)
    d = ilo_client._request_ilo(xml)
    data = ilo_client._parse_output(d)
    return data


def get_propagate_time(ilo_client):
    """
       Get PROPAGATE_TIME_TO_HOST configuration item
    """
    info = ilo_client._execute_command('GET_GLOBAL_SETTINGS',
                                       'RIB_INFO', 'read')
    res = info['GET_GLOBAL_SETTINGS']['PROPAGATE_TIME_TO_HOST']
    return res['VALUE']


def set_tz(ilo_client, val):
    """
       Set TIMEZONE configuration item
    """
    import xml.etree.ElementTree as etree
    xml = ilo_client._create_dynamic_xml('MOD_NETWORK_SETTINGS',
                                         'RIB_INFO', 'write')
    if six.PY2:
        child_iterator = xml.getiterator()
    else:
        child_iterator = xml.iter()
    for child in child_iterator:
        if child.tag == 'MOD_NETWORK_SETTINGS':
            etree.SubElement(child, 'TIMEZONE', VALUE=val)
    d = ilo_client._request_ilo(xml)
    data = ilo_client._parse_output(d)
    return data


def error(msg):
    print(msg, file=sys.stderr)


def verbose(msg):
    print(msg, file=sys.stderr)


def output(msg):
    print(msg, file=sys.stderr)


def setup_ilo(user, password, host, tz=None,
              bootmode=None, check_privs=True,
              check_propagate=True,
              boot_from_dev=None,
              do_verbose=True, debug=False):
    """
        Connect to a host to valdiate its iLO settings.
        If the host doesnt support ilo/ribcl return 1
        else
            report on firmware settings
            optionally check the privileges
            optionally set the timezone
            check NTP propagate setting
            check bootmode and optionally set it
    """
    # Make a connection
    try:
        if (do_verbose):
            verbose('Connecting to %s' % host)
        ilo_client = ribcl.IloClient(host, user, password)
        # if we cant get at least power status we stop.
        ilo_client.get_host_power_status()
    except ribcl.IloConnectionError as e:
        error('Error(%s) connecting to %s: %s' % (type(e), host, e))
        return 1
    except Exception as e:
        error('Error(%s) connecting to %s: %s' % (type(e), host, e))
        return 1

    auth = 'BASIC ' + b64encode(user + ':' + password)
    headers = {'Authorization': auth, 'Content-Type': 'application/json'}

    mp = None
    try:
        if (do_verbose):
            verbose('Getting f/w version')
        info = ilo_client._execute_command('GET_FW_VERSION',
                                           'RIB_INFO',
                                           'read')
        if (debug):
            verbose(info.keys())
        for key in info['GET_FW_VERSION'].keys():
            output("%s: %s" % (key, info['GET_FW_VERSION'][key]))
        # e.g.: 'iLO3' or 'iLO4'
        mp = info['GET_FW_VERSION'].get('MANAGEMENT_PROCESSOR')
    except Exception as e:
        error('Error(%s) getting f/w version from %s: %s' %
              (type(e), host, e))

    # Get the user privileges - fail if the check was requested and
    # if the required privileges arent present.
    # Its useful to fail early if you get a user without Administrator privs
    if check_privs:
        try:
            if (do_verbose):
                verbose('Getting user info')
            user_dict = {'USER_LOGIN': user}
            info = ilo_client._execute_command('GET_USER',
                                               'USER_INFO',
                                               'read',
                                               user_dict)
            if ('CONFIG_ILO_PRIV' in info['GET_USER']):
                if (info['GET_USER']['CONFIG_ILO_PRIV'] != 'Y'):
                    error('Insufficient privs: CONFIG_ILO_PRIV is required')
                    for key in info['GET_USER'].keys():
                        verbose("%s: %s" % (key, info['GET_USER'][key]))
                    return 1
            else:
                # Maybe its an older iLO?
                pass
        except Exception as e:
            error('Error(%s) getting user info from %s: %s' %
                  (type(e), host, e))

    # Get the timezone - dont fail if it cant be read.
    # UTC is NOT a valid timezone for iLO. Africa/Accra?
    if (do_verbose):
        verbose('Getting network settings')
    try:
        info = ilo_client._execute_command('GET_NETWORK_SETTINGS',
                                           'RIB_INFO',
                                           'read')
        now_tz = info['GET_NETWORK_SETTINGS']['TIMEZONE']['VALUE']
        verbose('Current timezone is: %s' % tz)
        if (tz and now_tz != tz):
            if (do_verbose):
                verbose('Setting timezone=%s' % tz)
            try:
                set_tz(ilo_client, tz)
            except Exception as e:
                error('Error(%s) setting tz %s for %s: %s' %
                      (type(e), args.tz, args.host, e))
    except Exception as e:
        error('Error(%s) getting tz for %s: %s' %
              (type(e), host, e))

    # Get the propagate flag - dont fail if it cant be read.
    if (do_verbose):
        verbose('Getting global settings')
    try:
        propagate = get_propagate_time(ilo_client)
        verbose('Current time propagate setting is: %s' % propagate)

        if check_propagate and propagate != 'N':
            if (do_verbose):
                verbose('Setting time propagate OFF')
            try:
                set_propagate_time(ilo_client, 'N')
            except Exception as e:
                error('Error(%s) setting time propagate %s for %s: %s' %
                      (type(e), host, e))
            propagate = get_propagate_time(ilo_client)
            if propagate != 'N':
                verbose('Failed setting time propagate OFF')
    except Exception as e:
        error('Error(%s) getting time propagate for %s: %s' %
              (type(e), host, e))

    # bootmode = 'LEGACY'
    current_mode = None
    pending_mode = None
    if mp and mp == 'iLO4':
        try:
            # GET_SUPPORTED_BOOT_MODE = LEGACY_ONLY, UEFI_ONLY,
            #                           LEGACY_UEFI, UNKNOWN
            supported_modes = ilo_client.get_supported_boot_mode()
            if (do_verbose):
                verbose("Supported modes are: %s" % supported_modes)
            # Possible return values are LEGACY, UEFI, or UNKNOWN
            current_mode = ilo_client.get_current_boot_mode()
            pending_mode = ilo_client.get_pending_boot_mode()
            if (do_verbose):
                verbose("Current boot mode is: %s" % current_mode)
                verbose("Pending boot mode is: %s" % pending_mode)
            if bootmode is not None:
                if pending_mode != bootmode:
                    try:
                        if (do_verbose):
                            verbose("Setting *next* boot mode as: %s" %
                                    bootmode)
                        ilo_client.set_pending_boot_mode(bootmode)
                    except Exception as e:
                        error('Error(%s) setting boot_mode to %s for %s: %s' %
                              (type(e), bootmode, host, e))
        except ribcl.IloError as e:
            if 'Feature not supported' in repr(e):
                error(e)
        except Exception as e:
            error('Error(%s) getting current boot mode for %s: %s' %
                  (type(e), host, e))

    _process_bootmode(ilo_client, host, headers, boot_from_dev,
                      current_mode, pending_mode, do_verbose, debug)

    return 0


def _update_boot_order(ilo_client, host, headers, boot_order,
                       boot_from_dev, current_mode):
    if current_mode == 'UEFI':
        offset = 0
        for item in boot_order:
            if item == boot_from_dev:
                break
            offset += 1
        if offset < len(boot_order) and offset != 0:
            tosend = {'PersistentBootConfigOrder':
                      boot_order}
            master = tosend['PersistentBootConfigOrder'][offset]
            del tosend['PersistentBootConfigOrder'][offset]
            tosend['PersistentBootConfigOrder'].insert(0, master)
            resp = do_raw_patch(host,
                                '/rest/v1/Systems/1/BIOS/Boot/Settings',
                                headers,
                                json.dumps(tosend))
            result = json.loads(resp)
            if 'Messages' in result:
                for message in result['Messages']:
                    if "MessageID" in message:
                        verbose('Boot order update completed with status: %s'
                                % message["MessageID"])
            else:
                error('Unexpected status received while setting boot order')
            # expect this response
            # {"Messages":[{"MessageID":"iLO.0.10.SystemResetRequired"}],
            #               "Name":"Extended Error Information",
            #               "Type":"ExtendedError.0.9.5"}
            #
            # and so no point in trying to GET the current value after setting
            # to check as the system must be reset.
        else:
            verbose("boot_from_dev value (%s) is invalid" % boot_from_dev)
    else:
        offset = 0
        for item in boot_order:
            if item['value'] == boot_from_dev:
                break
            offset += 1
        if offset < len(boot_order) and offset != 0:
            master = boot_order[offset]
            del boot_order[offset]
            boot_order.insert(0, master)
            resp = ilo_client._get_persistent_boot()
            # ilo_client.update_persistent_boot will fail on 'USB', so use _set
            resp = ilo_client._set_persistent_boot(
                [item['value'] for item in boot_order
                 if item['value'] != 'Unknown'])
        else:
            verbose("boot_from_dev value is either invalid or the default")


def _list_uefi_boot_order(host, headers, do_verbose=True, debug=True):
    try:
        # Use the HP Rest interface to get and set boot order
        newbios = json.loads(do_raw_get(host,
                                        '/rest/v1/Systems/1/BIOS/Boot',
                                        headers))
        if debug:
            verbose(newbios)
        for source in newbios['PersistentBootConfigOrder']:
            verbose("\t%s" % (source))
        verbose('Valid boot sources are:')
        for source in newbios['BootSources']:
            verbose('\t%s: \"%s\"' % (source['StructuredBootString'],
                                      source['BootString']))
        return newbios['PersistentBootConfigOrder']
    except:
        pass


def _list_legacy_boot_order(ilo_client, current_mode,
                            do_verbose=True, debug=True):
    try:
        info = ilo_client._execute_command('GET_PERSISTENT_BOOT',
                                           'SERVER_INFO', 'read')
        boot_order = info['PERSISTENT_BOOT']['DEVICE']

        # boot_order is an ordered list of dicts with key 'value'
        # if 'DESCRIPTION' in boot_order[0]: then its a UEFI list
        if debug:
            verbose(json.dumps(boot_order, indent=2))
        for item in boot_order:
            if current_mode == 'UEFI' and 'DESCRIPTION' in item:
                verbose("\t%s: %s" % (item['value'],
                                      item['DESCRIPTION']))
            else:
                verbose("\t%s" % (item['value']))
        return boot_order
    except:
        pass


def _process_bootmode(ilo_client, host, headers, boot_from_dev,
                      current_mode, pending_mode, do_verbose, debug):
    # Note on boot settings:
    #    LEGACY BIOS and UEFI BIOS treat boot order separately and differently
    #
    #    LEGACY BIOS:
    #        The boot order can be set via ilo to a list
    #              e.g. CDROM USB HDD NETWORK
    #        The relative order of the network devices can be set using
    #        a POST to a json interface
    #              NETWORK1 NETWORK2 NETWORK3 ...
    #              **not implemented**
    #              allowable values are CDROM USB HDD NETWORK
    #        It is NOT possible in LEGACY BIOS to *programmatically*
    #              list devices
    #              determine what device is NETWORK1,2 etc
    #              enable a device for network boot
    #              determine what devices have links connected
    #
    #    UEFI
    #        The boot order can be found via ilo api call GET_PERSISTENT_BOOT
    #        The boot order can be found via json api call /json/boot_order
    #        The boot order can be set via ilo api call
    #        The boot order can be set explictly using POST to a json interface
    #              Boot000A, etc ...
    #              HD.Emb.1.3 NIC.FlexLOM.1.1.IPv4 NIC.LOM.1.1.IPv4
    #              These names can be mapped to devices via GET_PERSISTENT_BOOT
    #        It is NOT possible in UEFI mode to *programmatically*
    #              enable a device for network boot
    #              determine what devices have links connected
    #

    # This request can be used to list all network devices, BUT doesnt return
    # link status, or if network boot enabled, just port, location and mac addr
    resp = ilo_client.get_host_health_data()
    nic_info = resp['GET_EMBEDDED_HEALTH_DATA'].get('NIC_INFORMATION', None)
    if nic_info:
        nics = nic_info['NIC']
    else:
        nics = []
        verbose('No NIC information for this host')
    if debug:
        verbose(json.dumps(nics, indent=2))

    if len(nics) > 0:
        verbose('Found NICs on system')
    for item in nics:
        verbose('\tMAC: %s LOCATION: %s PORT: %s' %
                (item['MAC_ADDRESS']['VALUE'],
                 item['LOCATION']['VALUE'],
                 item['NETWORK_PORT']['VALUE']))

    if boot_from_dev:
        try:
            if (do_verbose):
                verbose('Listing persistent boot order:')
            if current_mode == 'UEFI':
                boot_order = _list_uefi_boot_order(host, headers,
                                                   do_verbose, debug)
            else:
                boot_order = _list_legacy_boot_order(ilo_client, current_mode,
                                                     do_verbose, debug)
            if boot_from_dev != '?':
                if (do_verbose):
                    verbose('Updating boot device')
                if pending_mode != current_mode:
                    error("Changing boot order when pending boot mode (%s) is "
                          "not the same as current mode (%s) is not possible" %
                          (pending_mode, current_mode))
                else:
                    _update_boot_order(ilo_client, host, headers,
                                       boot_order, boot_from_dev, current_mode)
        except Exception as e:
            error('Error(%s) getting persistent boot for %s: %s' %
                  (type(e), host, e))

    return 0


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Utility to setup HP iLO')
    parser.add_argument('-U', '--user', required=True, help='Username')
    parser.add_argument('-P', '--password', required=True, help='Password')
    parser.add_argument('-H', '--host', required=True, help='Host')
    parser.add_argument('-c', '--check_privs', action='store_true',
                        help='Check iLO privs')
    parser.add_argument('-t', '--check_propagate_time', action='store_true',
                        help='Check iLO propagate time to BIOS setting is OFF')
    parser.add_argument('-z', '--tz', default=None, help='TimeZone')
    parser.add_argument('-m', '--bootmode', default=None, help='iLO4 bootmode')
    parser.add_argument('-d', '--debug', action='store_true', help='Debug')
    parser.add_argument('-v', '--verbose', action='store_true', help='Verbose')
    parser.add_argument('-n', '--boot_from_dev', default=None,
                        help="""Device from which to boot.
    For LEGACY systems the allowable values are CDROM HDD USB NETWORK.
    This utility cannot determine the Nic names associated with NETWORK,
    or the order of the NETWORK (PXE-enabled) Nics.
    For UEFI systems the allowable values can be determined from the system
    by running this command with a value for this argument of ?
    For example: 'NIC.FlexLOM.1.1.IPv4'""")
    parser.add_argument('--boot-from-dev', dest='boot_from_dev')

    args = parser.parse_args()

    if (args.debug):
        # Need six > 1.3.0 (1.8.0 works)
        verbose(six.__version__)

    setup_ilo(args.user, args.password, args.host,
              args.tz, args.bootmode, args.check_privs,
              args.check_propagate_time,
              args.boot_from_dev,
              args.verbose, args.debug)

    sys.exit(0)
0707010000001A000081A400000000000000000000000162FCFEE100002DE8000000000000000000000000000000000000003700000000ardana-cobbler-9.0+git.1660747489.119efcd/library/ipmi#!/usr/bin/env python
#
# An Ansible module to allow playbooks to communicate with
# remote devices using IPMI.
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

DOCUMENTATION = '''
---
module: ipmi
author: Joe Fegan
short_description: Issue IPMI commands to network targets
description:
    - Issue IPMI commands to systems that are accessible over the network from this node.
    - IPMI credentials and network addresses can be specified in a JSON or YAML file, or
      can be retrieved from Cobbler.
options:
    name:
        required: true
        description:
            - Name of the node to manage.
    retry_interval:
        required: false
        default: 5
        description:
            - Interval in seconds between retries.
    retry_max:
        required: false
        default: 12
        description:
            - Max number of retries.
    power:
        required: false
        description:
            - An IPMI power command to be sent to the target.
        choices: [ "on", "off", "status" ]
    bootdev:
        required: false
        description:
            - A bootdev command to be sent to the target.
            - For example to boot from PXE first, disk first, etc.
    options:
        required: false
        description:
            - Options for the bootdev command.
    passthru:
        required: false
        description:
            - Any artibrary IPMI command to be sent to the target.
            - This is a fallback for obscure commands. Any that you use regularly
              should be wrapped up in a proper handler like power and bootdev.
'''

EXAMPLES = '''
- ipmi: name=cpn-0001 power=off
- ipmi: name=cpn-0001 bootdev=pxe options=persistent
- ipmi: name=cpn-0001 credsfile="/tmp/nodeinfo.yml" passthru="mc reset warm"
'''

import os
import re
import time
import yaml

# Load the local module
import imp
ardanaencrypt = imp.load_source('ardanaencrypt', './ardanaencrypt.py')

openssl_prefix = ardanaencrypt.openssl.prefix
legacy_prefix = ardanaencrypt.openssl.legacy_prefix

def decrypt(value):
    prefix = None
    if value.startswith(openssl_prefix):
        decrypter = ardanaencrypt.openssl
        prefix = openssl_prefix
    elif value.startswith(legacy_prefix):
        decrypter = ardanaencrypt.openssl
        prefix = legacy_prefix
    else:
        return value
    obj = decrypter()
    return obj.decrypt(value[len(prefix):])

# Take something like "Chassis Power Control: Up/On" and return
# the last word. The exact format of the input varies a lot.
def parse_power_status(raw_status):
    return raw_status.split()[-1].split("/")[-1].lower()

# Something like "Set Boot Device to disk".
def parse_bootdev(raw_status):
    return raw_status.split()[-1].lower()

# Take an HP Moonshot server locator like c12n4 and return a list containing
# the extra IPMI addressing flags needed to send commands to that node.
def parse_moonshot(locator):
    r = re.compile('^c([0-9]+)n([0-9]+)$')
    m = r.match(locator.strip().lower())
    if not m:
        raise ValueError('unable to parse Moonshot id "%s"' % locator)
    (cartridge, node) = m.groups()
    transit = 0x80 + (int(cartridge) * 2)
    target = 0x70 + (int(node) * 2)
    return ['-B0', '-b7', '-T%#02x' % transit, '-t%#02x' % target]

class Ipmi(object):
    def __init__(self, module):
        self.module = module
        self.target = None

        try:
            self.node = module.params["name"]
            self.credsfile = module.params["credsfile"]
            self.bootdev = module.params["bootdev"]
            self.options = module.params["options"]
            self.power = module.params["power"]
            self.passthru = module.params["passthru"]
            self.retry_interval = int(module.params["retry_interval"])
            self.retry_max = int(module.params["retry_max"])
            self.retries = int(module.params["retries"])
            self.delay = int(module.params["delay"])
            secs = module.params["sleep"]
            if not secs:
                self.sleep = None
            elif secs[-1] == "m":
                self.sleep = 60.0 * float(secs[:-1])
            elif secs[-1] == "s":
                self.sleep = float(secs[:-1])
            else:
                self.sleep = float(secs)
        except ValueError as e:
            self.fail(msg="ipmi: " + str(e))

    def fail(self, **kwargs):
        return self.module.fail_json(**kwargs)

    def succeed(self, **kwargs):
        if self.sleep:
            time.sleep(self.sleep)
        return self.module.exit_json(**kwargs)

    def execv(self, cmd, **kwargs):
        return self.module.run_command(cmd, **kwargs)

    def cobbler_creds(self, node):
        cmd = ["sudo", "cobbler", "system", "dumpvars", "--name=%s" % node]
        rc, out, err = self.execv(cmd, check_rc=True)
        creds = dict()
        translation = {"power_address": "ip", "power_user": "user", "power_pass": "password"}
        for line in out.splitlines():
            key, value = line.split(" : ")
            if key in translation:
                if value == "":
                    break
                creds[translation[key]] = value
        if len(translation) != len(creds):
            self.fail(msg="ipmi: missing creds for %s in cobbler" % node)
        return creds

    def file_creds(self, fname):
        data = yaml.safe_load(file(fname))
        creds = dict()
        if "servers" in data:
            field = "servers"
            ident = "id"
            iloip = "ilo-ip"
            ilouser = "ilo-user"
            ilopassword = "ilo-password"
            iloextras = "ilo-extras"
        else:
            # Backward compatibility
            field = "baremetal_servers"
            ident = "node_name"
            iloip = "ilo_ip"
            ilouser = "ilo_user"
            ilopassword = "ilo_password"
            iloextras = "ilo_extras"
        for srv in data[field]:
            if srv[ident] == self.node:
                creds["ip"] = srv[iloip]
                creds["user"] = srv[ilouser]
                creds["password"] = decrypt(srv[ilopassword])
                if "moonshot" in srv:
                    creds["moonshot"] = parse_moonshot(srv["moonshot"])
                if iloextras in srv:
                    creds["extras"] = srv[iloextras].split(" ")

                break
        return creds

    def get_creds(self, node):
        if self.credsfile:
            return self.file_creds(self.credsfile)
        else:
            return self.cobbler_creds(node)

    def set_target(self, node):
        creds = self.get_creds(node)
        # we're in a subprocess, so our environment should be private.
        os.environ["IPMI_PASSWORD"] = creds["password"]
        self.ip = creds["ip"]
        self.target = ["ipmitool", "-I", "lanplus", "-E",
                       "-N", str(self.retry_interval),
                       "-R", str(self.retry_max),
                       "-U", creds["user"],
                       "-H", self.ip]
        if "moonshot" in creds:
            self.target += creds["moonshot"]
        if "extras" in creds:
            self.target += creds["extras"]

    # This will send any ipmi command you like to the target and return its
    # stdout and stderr. I thought twice about providing this, because the
    # proper thing to do is to create custom handlers for specific actions
    # (like action_power below), but in the end passthru is pragmatic for
    # rarely used commands. It can't populate the Ansible "changed" field
    # because it has no idea what the command was.
    def action_passthru(self, action):
        cmd = self.target + action.split()
        rc, out, err = self.execv(cmd, check_rc=True)
        result = dict(rc=rc, stdout=out, stderr=err)
        self.succeed(**result)

    # This sends ipmi "power" commands to the target and returns a proper
    # "changed" status to Ansible by inspecting the before and after state.
    # It also parses stdout of the reply and returns a simple "on" or "off"
    # value, which is much easier to cope with in a playbook.
    def action_power(self, action):
        attempts = 0
        rc = -1
        cmd = self.target + ["power", "status"]
        while rc != 0 and attempts <= self.retries:
            attempts = attempts + 1
            if attempts > 1:
                time.sleep(self.delay)
            rc, out, err = self.execv(cmd, check_rc=False)
        if rc != 0:
            self.fail(msg="%s (%d attempts) %s" % (self.ip, attempts, err))
        before = parse_power_status(out)

        desired = action.strip().lower()
        if desired == "status" or desired == before:
            after = before
        else:
            cmd = self.target + ["power", action]
            rc, out, err = self.execv(cmd, check_rc=True)
            after = parse_power_status(out)

        if attempts > 1:
            out = "%s: success after %d attempts" % (self.ip, attempts)
        else:
            out = ""
        result = dict(stdout=out, power=after, changed=(before != after))
        self.succeed(**result)

    # This sends ipmi "bootdev" commands to the target. It also parses stdout
    # of the reply and returns a simple value, which is much easier to cope
    # with in a playbook. I can't find a way to query the current bootdev
    # through IPMI so can't return a proper "changed" status to Ansible.
    def action_bootdev(self, action):
        cmd = self.target + ["chassis", "bootdev", action]
        if self.options:
            cmd.append("options=%s" % self.options)
        rc, out, err = self.execv(cmd, check_rc=True)
        dev = parse_bootdev(out)
        if len(dev) == 0:
            self.fail(msg="ipmi: can't parse bootdev response", stdout=out, stderr=err)
        result = dict(bootdev=dev, options=self.options, changed=True)
        self.succeed(**result)

    def execute(self):
        try:
            self.set_target(self.node)

            action = self.bootdev
            if action:
                return self.action_bootdev(action)

            action = self.power
            if action:
                return self.action_power(action)

            action = self.passthru
            if action:
                return self.action_passthru(action)

            self.fail(msg="usage: ipmi name=<node> <action>")
        except Exception as e:
            self.fail(msg="ipmi: " + str(e))


def main():
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            credsfile=dict(required=False),
            bootdev=dict(required=False, default=None),
            options=dict(required=False, default=None),
            power=dict(required=False, default=None),
            passthru=dict(required=False, default=None),
            sleep=dict(required=False, default=None),
            retry_interval=dict(required=False, default=5),
            retry_max=dict(required=False, default=12),
            retries=dict(required=False, default=0),
            delay=dict(required=False, default=0)
        )
    )

    ipmi = Ipmi(module)
    return ipmi.execute()


from ansible.module_utils.basic import *
main()
0707010000001B000081A400000000000000000000000162FCFEE100000E29000000000000000000000000000000000000003D00000000ardana-cobbler-9.0+git.1660747489.119efcd/library/match-cidr#!/usr/bin/env python
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

DOCUMENTATION = '''
---
module: matchcidr
author: Joe Fegan
short_description: Find a nic matching the given search creteria
description:
    - Searches the output of "ip a" for nics matching the given search criteria
options:
    cidr:
        required: true
        description:
            - Find nics that have addresses on this cidr.
    ips:
        required: true
        description:
            - List of candidate interfaces and ips, newline separated.
'''

EXAMPLES = '''
- matchcidr: cidr="10.1.11.0/24" ips="eth0 10.1.11.56/24\neth1 192.168.24.54/16\n"
'''

from socket import inet_aton

class MatchCidr(object):
    name = 'matchcidr'

    def __init__(self, module):
        self.module = module
        self.ips = module.params['ips']
        self.cidr = module.params['cidr']

    def fail(self, **kwargs):
        return self.module.fail_json(**kwargs)

    def succeed(self, **kwargs):
        return self.module.exit_json(**kwargs)

    def mkint(self, ipstr):
        binstr = inet_aton(ipstr)
        value = ((ord(binstr[0]) & 0xff) << 24) | \
                ((ord(binstr[1]) & 0xff) << 16) | \
                ((ord(binstr[2]) & 0xff) << 8) | \
                (ord(binstr[3]) & 0xff)
        return value

    def cidrmatch(self, cidr):
        ip, width = cidr.split('/')
        if int(width) < self.width:
            return False
        if self.mkint(ip) & self.mask != self.subnet:
            return False
        return True

    def execute(self):
        try:
            # convert mask etc to integers.
            subnet, width = self.cidr.split('/')
            self.width = int(width)
            shift = 32 - self.width
            self.mask = 0xffffffff >> shift << shift
            self.subnet = self.mkint(subnet) & self.mask
            # look for nics matching this.
            result = None
            for candidate in self.ips.split('\n'):
                nic, thiscidr = candidate.split(' ')
                if self.cidrmatch(thiscidr):
                    if result:
                        if result['stdout'] == nic:
                            continue
                        self.fail(msg='%s: multiple nics matching %s\n%s' % (self.name, self.cidr, self.ips))
                    ip, width = thiscidr.split('/')
                    result = dict(stdout=nic, ip=ip, cidr=self.cidr,
                                  subnet=hex(self.subnet), mask=hex(self.mask))
            if result:
                self.succeed(**result)
            else:
                self.fail(msg='%s: no nic matching %s\n%s' % (self.name, self.cidr, self.ips))
        except Exception as e:
            self.fail(msg='%s: %s %s' % (self.name, str(type(e)), str(e)))


def main():
    module = AnsibleModule(
        argument_spec=dict(
            cidr=dict(required=True),
            ips=dict(required=True)
        )
    )

    mod = MatchCidr(module)
    return mod.execute()


from ansible.module_utils.basic import *
main()
0707010000001C000081A400000000000000000000000162FCFEE100000EAE000000000000000000000000000000000000004500000000ardana-cobbler-9.0+git.1660747489.119efcd/library/netaddr-match-cidr#!/usr/bin/env python
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

DOCUMENTATION = '''
---
module: netaddr-match-cidr
author: Adolfo Duarte
short_description: Find a nic matching the given search creteria
description:
    - Searches the output of "ip a" for nics matching the given search criteria
    - returns a dictionary containing:
      return_dict.ip=nicip
      return_dict.output=nicname
      return_dict.cidr=cidr
      return_dict.subnet=hex(cidr_subnet)
      return_dict.mask=hex(cidr_mask)
options:
    cidr:
        required: true
        description:
            - CIDR to be used for search. Format "x/y"
    ips:
        required: true
        description:
            - List of candidate interfaces and ips, newline separated.
'''

EXAMPLES = '''
- matchcidr: cidr="10.1.11.0/24" ips="eth0 10.1.11.56/24\neth1 192.168.24.54/16\n"
- matchcidr: cidr="ffff:0001::0/64" ips="eth0 ffff:0001::1/64\neth1 ffff:0002::1/64\n
'''

from netaddr import IPNetwork

class NetaddrMatchCidr(object):
    name = 'matchcidr'

    def __init__(self, module):
        self.module = module
        self.niccidrcombos = module.params['ips'].split('\n')
        self.ipnetwork = IPNetwork(module.params['cidr'])

    def fail(self, **kwargs):
        return self.module.fail_json(**kwargs)

    def succeed(self, **kwargs):
        return self.module.exit_json(**kwargs)

    def execute(self):
        try:
            # We want to look through all the nic/cidr combos
            # and find a matching nic.
            # if more than one nic match, then we return error
            result = None
            for candidate in self.niccidrcombos:
                nic, niccidr = candidate.split(' ')
                nicipnetwork = IPNetwork(niccidr)
                if nicipnetwork.cidr == self.ipnetwork.cidr:
                    if result:
                        # we fail if more than one nic is found to match cidr
                        if result['stdout'] == nic:
                            continue
                        self.fail(msg='%s: multiple nics matching %s\n%s' % (
                            self.name, self.ipnetwork.cidr,
                            self.niccidrcombos))
                    result = dict(stdout=str(nic),
                                  ip=str(nicipnetwork.ip),
                                  cidr=str(self.ipnetwork.cidr),
                                  subnet=hex(self.ipnetwork.network),
                                  mask=hex(self.ipnetwork.netmask))
            if result:
                self.succeed(**result)
            else:
                self.fail(msg='%s: no nic matching %s\n%s' % (
                    self.name,
                    self.ipnetwork.cidr,
                    self.niccidrcombos)
                          )
        except Exception as e:
            self.fail(msg='%s: %s %s' % (self.name, str(type(e)), str(e)))


def main():
    module = AnsibleModule(
        argument_spec=dict(
            cidr=dict(required=True),
            ips=dict(required=True)
        )
    )

    mod = NetaddrMatchCidr(module)
    return mod.execute()


from ansible.module_utils.basic import *
main()
0707010000001D000081A400000000000000000000000162FCFEE100000335000000000000000000000000000000000000004100000000ardana-cobbler-9.0+git.1660747489.119efcd/prepare-rhel-grub2.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- hosts: localhost
  roles:
   - cobbler

  tasks:
    - include: roles/cobbler/tasks/set-vars.yml

    - include: roles/cobbler/tasks/create-rhel-grub2.yml node={{ nodelist }}
0707010000001E000081A400000000000000000000000162FCFEE1000003C5000000000000000000000000000000000000004200000000ardana-cobbler-9.0+git.1660747489.119efcd/prepare-rhel-loader.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- hosts: localhost
  roles:
    - cobbler

  tasks:

    - include: roles/cobbler/tasks/set-vars.yml

    - include: roles/cobbler/tasks/get-rhel-loader-file.yml
      vars:
        filepath: "{{ file }}"
      when: file is defined

    - include: roles/cobbler/tasks/get-rhel-loader.yml
      when: file is not defined
0707010000001F000081A400000000000000000000000162FCFEE1000000DD000000000000000000000000000000000000004100000000ardana-cobbler-9.0+git.1660747489.119efcd/prepare-sles-grub2.yml#
# (c) Copyright 2017,2018 SUSE LLC
#
---

- hosts: localhost
  roles:
   - cobbler

  tasks:
    - include: roles/cobbler/tasks/set-vars.yml

    - include: roles/cobbler/tasks/create-sles-grub2.yml node={{ nodelist }}
07070100000020000081A400000000000000000000000162FCFEE1000001B6000000000000000000000000000000000000004200000000ardana-cobbler-9.0+git.1660747489.119efcd/prepare-sles-loader.yml#
# (c) Copyright 2017,2018 SUSE LLC
#
---
- hosts: localhost
  roles:
    - cobbler

  tasks:

    - include: roles/cobbler/tasks/set-vars.yml

    - include: roles/cobbler/tasks/get-sles-loader-file.yml
      vars:
        filepath: "{{ file }}"
      when: file is defined and (ansible_os_family  == 'Debian')

    - include: roles/cobbler/tasks/get-sles-loader.yml
      when: file is not defined and (ansible_os_family  == 'Debian')
07070100000021000041ED00000000000000000000000362FCFEE100000000000000000000000000000000000000000000003000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles07070100000022000041ED00000000000000000000000762FCFEE100000000000000000000000000000000000000000000003800000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler07070100000023000041ED00000000000000000000000262FCFEE100000000000000000000000000000000000000000000004100000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/defaults07070100000024000081A400000000000000000000000162FCFEE100000942000000000000000000000000000000000000004A00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/defaults/main.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Variables for getting to the apt servers
---

hlinux_distro: "cattleprod"

remote_distros:
  - name: sles12sp4
    arch: x86_64
    kickstart: sles12sp4-autoyast.xml
    managed_by: sles
  - name: sles12sp3
    arch: x86_64
    kickstart: sles12sp3-autoyast.xml
    managed_by: sles
  - name: rhel75
    arch: x86_64
    kickstart: rhel75-anaconda-ks.cfg
    managed_by: rhel
    entry_name: 'RHEL 7.5'
    grub2_efi_rpm: "grub2-efi-x64-[0-9]*.rpm"
    rhel_shim_rpm: "shim-x64-[0-9]*rpm"

rhel_iso_location: "{{ ardanauser_deployer_home }}/rhel7.iso"


grubx64_location: "boot/efi/EFI/*/grubx64.efi"
rhel_shim_location: "boot/efi/EFI/*/shim.efi"

# SLES Profile Variables
sles_version_name: "sles12sp4"
sles_iso_location: "{{ ardanauser_deployer_home }}/{{ sles_version_name }}.iso"

# SLES UEFI Variables
sles_grub2_efi_rpm: "grub2-x86_64-efi-[0-9]*.rpm"
sles_shim_rpm: "shim-[0-9]*rpm"

sles_grubx64_location: "usr/lib/grub2/x86_64-efi/grub.efi"
sles_regexp_location: "usr/lib/grub2/x86_64-efi/regexp.mod"
sles_shim_location: "usr/lib64/efi/shim-sles.efi"

sles_expected_media_repos:
  sles12sp4:
    - alias: PTF
      name: PTF
    - alias: SLES12-SP4-Pool
      name: SLES12-SP4-Pool
    - alias: SLES12-SP4-Updates
      name:  SLES12-SP4-Updates
  sles12sp3:
    - alias: PTF
      name: PTF
    - alias: SLES12-SP3-Pool
      name: SLES12-SP3-Pool
    - alias: SLES12-SP3-Updates
      name:  SLES12-SP3-Updates

# Variable to hold list of repos configured on deployer
sles_configured_media_repos:
  sles12sp4: []
  sles12sp3: []

sles_dhcpd_start_limit_interval: 30
sles_dhcpd_start_limit_burst: 25

distro_signatures_files:
  - /etc/cobbler/distro_signatures.json
  - /var/lib/cobbler/distro_signatures.json
07070100000025000041ED00000000000000000000000262FCFEE100000000000000000000000000000000000000000000003E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files07070100000026000081A400000000000000000000000162FCFEE1000000A5000000000000000000000000000000000000004500000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/atftpdUSE_INETD=false
OPTIONS="--tftpd-timeout 300 --retry-timeout 5 --mcast-port 1758 --mcast-addr 239.239.239.0-255 --mcast-ttl 1 --maxthread 100 --verbose=5 /srv/tftp"
07070100000027000081A400000000000000000000000162FCFEE10000001C000000000000000000000000000000000000004900000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/bnx2x.confoptions bnx2x disable_tpa=1
07070100000028000081A400000000000000000000000162FCFEE100000084000000000000000000000000000000000000004E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/configure_kdump#!/bin/bash
sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="crashkernel=384M-2G:64M,2G-:256M"/g' /etc/default/grub
update-grub

07070100000029000081A400000000000000000000000162FCFEE1000000A8000000000000000000000000000000000000005500000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/configure_partitioningif [ -e /sys/firmware/efi ]
then
    wget -O ./partition_scheme http://$1/preseed/partition-uefi
else
    wget -O ./partition_scheme http://$1/preseed/partition-pxe
fi
0707010000002A000081A400000000000000000000000162FCFEE100000063000000000000000000000000000000000000005600000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/fence_ipmitool.templateaction=$power_mode
ipaddr=$power_address
login=$power_user
passwd=$power_pass
lanplus
power_wait=4
0707010000002B000081A400000000000000000000000162FCFEE1000002A1000000000000000000000000000000000000004C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/partition-pxeardana-config ::
    1 1 1 free
    $bios_boot{ }
    method{ biosgrub }
.
    512 39000 512 free
    $primary{ }
    method{ keep }
.
    512 38000 512 ext3
      $primary{ }
      $bootable{ }
      method{ format }
      format{ }
      use_filesystem{ }
      filesystem{ ext3 }
      mountpoint{ /boot }
.
    32000 32000 32000 ext4
      $lvmok{ }
      lv_name{ root }
      method{ format }
      format{ }
      use_filesystem{ }
      filesystem{ ext4 }
      mountpoint{ / }
.
    3000 3000 100000 ext4
      $lvmok{ }
      lv_name{ unused }
      method{ format }
      format{ }
      use_filesystem{ }
      filesystem{ ext4 }
      mountpoint{ /unused }
.

0707010000002C000081A400000000000000000000000162FCFEE1000002C0000000000000000000000000000000000000004D00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/partition-uefiardana-config ::
    1 1 1 free
    $bios_boot{ }
    method{ biosgrub }
.
    512 39000 512 fat32
    $primary{ }
    method{ efi }
    format{ }
    $bootable{ }
.
    512 38000 512 ext3
      $primary{ }
      $bootable{ }
      method{ format }
      format{ }
      use_filesystem{ }
      filesystem{ ext3 }
      mountpoint{ /boot }
.
    32000 32000 32000 ext4
      $lvmok{ }
      lv_name{ root }
      method{ format }
      format{ }
      use_filesystem{ }
      filesystem{ ext4 }
      mountpoint{ / }
.
    3000 3000 100000 ext4
      $lvmok{ }
      lv_name{ unused }
      method{ format }
      format{ }
      use_filesystem{ }
      filesystem{ ext4 }
      mountpoint{ /unused }
.

0707010000002D000081A400000000000000000000000162FCFEE10000B2B7000000000000000000000000000000000000005200000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/update_fcoe_udev.py#!/usr/bin/env python
#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""update_fcoe_udev.py

Provides tooling that can be used to manage the persistent ordering of
network devices for use with FCOE deployments.

Usage:
    update_fcoe_udev.py [--prefix|-p <prefix>]

Where:
    --prefix, -p <prefix>
        specifies the path to prefix system file access with.

Example:
    When running during a preseed install, the installed system
hierarchy is mounted under /target, so invoke the command as follows:

    % update_fcoe_udev.py -p /target
"""


from argparse import ArgumentParser
from collections import OrderedDict
from glob import glob
from hashlib import md5 as hasher
from operator import attrgetter, itemgetter
import os
import re
import sys


class ArdanaSystemPathsError(RuntimeError):
    def __init__(self, *args, **kwargs):
        super(ArdanaSystemPathsError, self).__init__(*args, **kwargs)


class DictReplacerError(RuntimeError):
    def __init__(self, *args, **kwargs):
        super(DictReplacerError, self).__init__(*args, **kwargs)


class ConfFileError(RuntimeError):
    def __init__(self, *args, **kwargs):
        super(ConfFileError, self).__init__(*args, **kwargs)


class PhaseRenameError(ConfFileError):
    def __init__(self, *args, **kwargs):
        super(PhaseRenameError, self).__init__(*args, **kwargs)


class NetRulesError(RuntimeError):
    def __init__(self, *args, **kwargs):
        super(NetRulesError, self).__init__(*args, **kwargs)


class NotRuleError(NetRulesError):
    def __init__(self, *args, **kwargs):
        super(NotRuleError, self).__init__(*args, **kwargs)


class NotRule70Error(NetRulesError):
    def __init__(self, *args, **kwargs):
        super(NotRule70Error, self).__init__(*args, **kwargs)


class NotRule71Error(NetRulesError):
    def __init__(self, *args, **kwargs):
        super(NotRule71Error, self).__init__(*args, **kwargs)


class RenameError(NetRulesError):
    def __init__(self, *args, **kwargs):
        super(RenameError, self).__init__(*args, **kwargs)


class InvalidRuleError(NetRulesError):
    def __init__(self, *args, **kwargs):
        super(InvalidRuleError, self).__init__(*args, **kwargs)


class InvalidDeviceNameError(NetRulesError):
    def __init__(self, *args, **kwargs):
        super(InvalidDeviceNameError, self).__init__(*args, **kwargs)


class ArdanaSystemPaths(object):
    """Helper class for system path access.

    Implements a simple helper class used to manage access the important
    system paths, potentially accessed under a provided offset, e.g.
    during an install.
    """
    _default_path_prefix = "/"
    _default_flag_dir = "/etc/ardana"
    _default_flag_name = "udev_net_rules_updated"
    _rules_file_70 = "/etc/udev/rules.d/70-persistent-net.rules"
    _rules_file_71 = "/etc/udev/rules.d/71-persistent-net.rules"
    _fcoe_dir = "/etc/fcoe"
    _ifaces_file = "/etc/network/interfaces"
    _ifaces_dir = "/etc/network/interfaces.d"

    def __init__(self, prefix=None, sys_prefix=None, flag_dir=None,
                 flag_name=None):
        """Initialise instance settings.

        The prefix argument specifies an offset path for all path
        resolution, e.g. /target if invoked during preseed install.
        The flag_dir and flag_name combined specify a flag file, the
        presence of which indicates that the associated operations
        have already been performed.
        """
        if prefix is None:
            prefix = self._default_path_prefix
        if sys_prefix is None:
            sys_prefix = self._default_path_prefix
        if flag_dir is None:
            flag_dir = self._default_flag_dir
        if flag_name is None:
            flag_name = self._default_flag_name

        if not os.path.exists(prefix):
            raise ArdanaSystemPathsError("Prefix '%s' doesn't exist!" %
                                         prefix)
        self._path_prefix = prefix
        self._path_sys_prefix = sys_prefix
        self._flag_dir = flag_dir
        self._flag_name = flag_name

    @property
    def prefix(self):
        """Expose prefix path as readonly attr."""
        return self._path_prefix

    @prefix.setter
    def prefix(self, prefix):
        """Update the prefix path to a new value."""
        self._path_prefix = prefix

    def system_path(self, path):
        """Returns the actual path to use to access specified path."""
        return os.path.join(self.prefix, path.lstrip('/'))

    @property
    def sys_prefix(self):
        """Expose sys_prefix path as readonly attr."""
        return self._path_sys_prefix

    @sys_prefix.setter
    def sys_prefix(self, sys_prefix):
        """Update the sys_prefix path to a new value."""
        self._path_sys_prefix = sys_prefix

    def system_sys_path(self, *args):
        """Returns the actual path to use to access specified path."""
        return os.path.join(self.sys_prefix, "sys", *args)

    @property
    def rules_file_70(self):
        """System path to persistent udev rules file."""
        return self.system_path(self._rules_file_70)

    @property
    def rules_file_71(self):
        """System path to persistent udev rules file."""
        return self.system_path(self._rules_file_71)

    @property
    def fcoe_dir(self):
        """System path to FCOE config directory."""
        return self.system_path(self._fcoe_dir)

    @property
    def ifaces_file(self):
        """System path to network interfaces config file."""
        return self.system_path(self._ifaces_file)

    @property
    def ifaces_dir(self):
        """System path to network interfaces config directory."""
        return self.system_path(self._ifaces_dir)

    @property
    def flag_dir(self):
        """System path to directory holding flag files."""
        return self.system_path(self._flag_dir)

    @property
    def flag_name(self):
        """Expose flag name as readonly attr."""
        return self._flag_name

    @property
    def flag_file(self):
        """System path to specified flag file."""
        return os.path.join(self.flag_dir, self.flag_name)

    @property
    def flag_exists(self):
        """True if specified flag file exists."""
        return os.path.exists(self.flag_file)


class DictReplacer(object):
    """Manage text replacement based upon lookup table.

    Instances of this class can be used to manage updating contents
    of lines where the replacement value is dynamically looked up
    in a provided dictionary, based on the value to be replaced; if
    no value is found in provided dictionary then leave unchanged.
    """

    def __init__(self, replacer, lookup, field=1, skipper=None):
        """Initialise the instance settings.

        The replacer argument must include at least one group
        specifier identifying the value to be replaced.
        The lookup argument must be a dictionary line object that
        maps candidate values onto there replacements.
        The field argument specifies which group's value should be
        looked up in the lookup map when doing replacement.
        The skipper argument can optionally specify a pattern that
        can be used to skip processing, e.g. ignore comment or
        blank lines.
        NOTE: The replacer and skipper can be provided as either
        compiled pattern objects, or pattern strings which will be
        automatically compiled, and the compiled versions used.
        """
        if isinstance(replacer, str):
            replacer = re.compile(replacer)
        if isinstance(skipper, str):
            skipper = re.compile(skipper)

        if not replacer.groups:
            raise DictReplacerError("Invalid replacer pattern: no groups "
                                    "specified - '%s'" % replacer.pattern)

        self._replacer = replacer
        self._lookup = lookup
        self._field = field
        self._skipper = skipper

    @property
    def replacer(self):
        """Expose replacer as a readonly attr."""
        return self._replacer

    @property
    def lookup(self):
        """Expose lookup as a readonly attr."""
        return self._lookup

    @property
    def field(self):
        """Expose field as a readonly attr."""
        return self._field

    @property
    def skipper(self):
        """Expose skipper as a readonly attr."""
        return self._skipper

    def should_skip(self, text):
        """Check if we should skip processing of this text.

        Returns true if a skipper pattern has been provided, and
        the pattern matches the specified value.
        """
        return self.skipper and self.skipper.match(text)

    def _callback(self, matcher):
        """Callback handling lookup of the substitution value."""
        matched_field = matcher.group(self.field)
        replacement = self.lookup.get(matched_field)
        if not replacement:
            return matcher.group(0)

        fields = list(f or "" for f in matcher.groups())
        fields[self.field - 1] = replacement

        return "".join(fields)

    def replace(self, text):
        """Replace content in text based upon lookup table.

        Based upon the content of the associated lookup table,
        replace any occurrences of any matching keys with their
        associated values that may be found in the provided text.
        """
        if self.should_skip(text):
            return text
        return self.replacer.sub(self._callback, text)


class ConfEntry(object):
    """Basic Conf File Entry handler."""
    def __init__(self, line, lineno, syspaths):
        """Record line and line number."""
        self._line = line
        self._lineno = lineno
        self._orig_line = None
        self._syspaths = syspaths

    def __str__(self):
        """Return line as str() value."""
        return self._line

    @property
    def syspaths(self):
        """Syspaths object to use when resolving paths."""
        return self._syspaths

    @property
    def lineno(self):
        """Line number of this line in the file."""
        return self._lineno

    @property
    def orig_line(self):
        """Original line content."""
        if self._orig_line is None:
            return self._line
        return self._orig_line

    def _backup_line(self):
        """Backup line content if not previously done."""
        if self._orig_line is None:
            self._orig_line = self._line

    def update(self, new_line):
        """Update line with new content, backing up if needed."""
        if new_line == self._line:
            return

        self._backup_line()
        self._line = new_line

    @property
    def dirty(self):
        """True if line has in fact been modified."""
        return self._orig_line is not None


class UdevNetEntry(ConfEntry):
    """Manage Udev persistent network rule entry.

    Class used to manage a specific udev persistent net rules,
    allowing renaming of associated device and checking whether
    the device exists on the system, and whether the configured
    settings match the actual settings in use..
    """

    def __init__(self, line, lineno, syspaths):
        """Record line and line number, and parse fields from line."""
        super(UdevNetEntry, self).__init__(line, lineno, syspaths)
        self._orig_dev_name = None
        self._fields = self._parse_line()

    def _parse_line(self):
        """Parse line into fields, skipping comment and blank lines."""
        # check if line contains a rule or not
        stripped = self._line.strip()
        if not stripped or stripped.startswith("#"):
            return None

        # strip out double quotes from values, and simplify equals strings
        simplified = self._line.replace("==", "=").replace('"', '')

        # return a dictionary formed from the key=value pairs found in line
        return dict(f.strip().split("=", 1) for f in simplified.split(","))

    def _backup_dev_name(self):
        """Backup original device name if not previously done."""
        if self._orig_dev_name is None:
            self._orig_dev_name = self.dev_name

    @property
    def is_rule(self):
        """True if line represents a udev rule."""
        return self._fields is not None

    @property
    def mac(self):
        """Expose parsed MAC address as a readonly attr."""
        if not self.is_rule:
            raise NotRuleError("No 'ATTR{address}' field.")

        if "ATTR{address}" not in self._fields:
            raise NotRule70Error("No 'ATTR{address}' field.")

        return self._fields["ATTR{address}"]

    @property
    def dev_name(self):
        """Expose parsed device name as a readonly attr."""
        if not self.is_rule:
            raise NotRuleError("No 'NAME' field.")

        return self._fields["NAME"]

    _name_re = re.compile(r"^(\D+)(\d+)$")

    @property
    def is_dev_name_valid(self):
        """True if device name is valid format."""
        return self._name_re.match(self.dev_name) is not None

    @property
    def dev_name_prefix(self):
        """Device name prefix string.

        Expose the device name prefix string, e.g. eth for ethN,
        as a readonly attr.
        """
        match = self._name_re.match(self.dev_name)
        if not match:
            raise InvalidDeviceNameError("Not a valid device name: '%s'" %
                                         self.dev_name)

        return match.group(1)

    @property
    def orig_dev_name(self):
        """Expose original device name as a readonly attr."""
        if not self.is_rule:
            raise NotRuleError("No original name to find.")

        if self._orig_dev_name:
            return self._orig_dev_name

        return self.dev_name

    _dev_rename_re = re.compile(r'(\sNAME=")([^"]+)(")')

    def dev_rename(self, new_dev_name):
        """Rename device associated with rule.

        Rename the device associated with a given rule, if the
        name has in fact changed, and the device hasn't already
        been re-ordered.
        """
        if not self.is_rule:
            raise NotRuleError("Rename not possible.")

        if new_dev_name == self.dev_name:
            return

        if self.reordered:
            return

        self._backup_dev_name()

        repl_value = r'\1' + new_dev_name + r'\3'
        new_line, count = self._dev_rename_re.subn(repl_value,
                                                   self._line, 1)
        if not count:
            raise InvalidRuleError("Failed to update NAME field")

        self.update(new_line)
        self._fields["NAME"] = new_dev_name

    @property
    def sys_class_orig_path(self):
        """Expose path to original /sys/class/net entry as readonly attr."""
        if not self.is_rule:
            raise NotRuleError("Cannot determine /sys/class/net path")

        return self.syspaths.system_sys_path('class/net', self.orig_dev_name)

    @property
    def sys_class_path(self):
        """Expose path to current /sys/class/net entry as readonly attr."""
        if not self.is_rule:
            raise NotRuleError("Cannot determine /sys/class/net path")

        return self.syspaths.system_sys_path('class/net', self.dev_name)

    @property
    def sys_path_exists(self):
        """True if original /sys/class/net path exists."""
        return os.path.exists(self.sys_class_orig_path)

    @property
    def sys_dev_port(self):
        """The PCI device port of the device associated with this rule.

        Expose PCI Device port associated with original device name as
        readonly attr.
        """
        try:
            with open(os.path.join(self.sys_class_orig_path, "dev_port")) as f:
                dev_port = f.read().strip('\0').strip()
        except Exception:
            sys.stderr.write("Failed to read dev_port for entry: %s\n" %
                             (self._orig_line))
            raise

        return dev_port

    @property
    def dev_port(self):
        """The ATTR{dev_port} specified in this rule."""
        if not self.is_rule:
            raise NotRuleError("No 'ATTR{dev_port}' field.")

        if "ATTR{dev_port}" not in self._fields:
            raise NotRule71Error("No 'ATTR{dev_port}' field.")

        return self._fields["ATTR{dev_port}"]

    @property
    def devpath(self):
        """The DEVPATH specified in this rule."""
        if not self.is_rule:
            raise NotRuleError("No 'DEVPATH' field.")

        if "DEVPATH" not in self._fields:
            raise NotRule71Error("No 'DEVPATH' field.")

        return self._fields["DEVPATH"]

    @property
    def sys_mac(self):
        """The system MAC address associated with rules current device.

        Expose the MAC address associated with the current device name
        as a readonly attr. Used in determining if network devices have
        already been re-ordered.
        """
        try:
            with open(os.path.join(self.sys_class_path, "address")) as f:
                sys_mac = f.read().strip('\0').strip()
        except Exception:
            sys.stderr.write("Failed to read address for entry: %s\n" %
                             (self._orig_line))
            raise

        return sys_mac

    @property
    def pci_dev(self):
        """The PCI device ID associated with rules network device.

        Expose the PCI Device ID associated with the original device
        name as a readonly attr.
        """
        return os.path.realpath(self.sys_class_orig_path).split("/")[-3]

    @property
    def pci_order(self):
        """Returns constructed PCI ordering string for use in sorting."""
        return "%s:%s" % (self.pci_dev, self.sys_dev_port)

    @property
    def reordered(self):
        """Has this rule already been re-ordered.

        True if device associated with has already been reordered,
        either by us or a previous run.
        """
        if "ATTR{address}" in self._fields:
            return self.mac != self.sys_mac

        if "DEVPATH" in self._fields:
            return self.devpath != ("*/%s/*" % self.pci_dev)


class ConfFile(object):
    """Class used to manage on-disk config files"""

    def __init__(self, conf_file, syspaths, handler=None):
        """Initialise instance settings.

        If no handler specified, use default, i.e. ConfEntry.
        Track name changes for conf file via path list.
        """
        if handler is None:
            handler = ConfEntry

        self._path = [conf_file]
        self._rename_phase = 0
        self._handler = handler

        self._lines = []
        self._linemap = {}
        self._syspaths = syspaths

    @property
    def syspaths(self):
        """System paths manager to use when resolving paths."""
        return self._syspaths

    @property
    def path(self):
        """Current file path."""
        return self._path[-1]

    @path.setter
    def path(self, new_path):
        """Change file path to new name."""
        if new_path == self.path:
            return

        self._path.append(new_path)

    @property
    def paths(self):
        """Expose rename paths list as readonly attr."""
        return tuple(self._path)

    @property
    def orig_path(self):
        """Expose original file path as readonly attr."""
        return self._path[0]

    @property
    def rename_phases(self):
        """Total number of renames for this conf file."""
        return len(self._path) - 1

    @property
    def has_moved(self):
        """True if a file has been renamed."""
        return bool(self.rename_phases)

    @property
    def renames_remaining(self):
        """Number of outstanding rename operations.

        Remaining number of renames for this conf file that
        haven't yet been performed.
        """
        return self.rename_phases - self._rename_phase

    @property
    def rename_phase_src(self):
        """Source path for current rename phase."""
        return self._path[self._rename_phase]

    @property
    def rename_phase_dst(self):
        """Destination path for current rename phase."""
        if not self.renames_remaining:
            raise PhaseRenameError("File '%s' already fully renamed to '%s'"
                                   % (self.orig_path, self.path))
        return self._path[self._rename_phase + 1]

    def _load_file(self):
        """Load entries from on-disk file.

        Load the conf file lines each as an instance of provided
        handler, and record associated line number mapping.
        """
        try:
            with open(self.path) as f:
                conf_lines = f.readlines()
        except Exception:
            sys.stderr.write("open('%s') failed: %s\n" %
                             (self.path, sys.exc_info()[1]))
            raise

        for lineno, line in enumerate(conf_lines):
            entry = self._handler(line, lineno, self.syspaths)
            self._lines.append(entry)
            self._linemap[lineno] = entry

    @property
    def entries(self):
        """List of entries in the file.

        Expose list of entries in the conf file as a readonly attr,
        dynamically loading the file lines if necessary.
        """
        if not self._lines:
            self._load_file()

        return tuple(self._lines)

    @property
    def lines(self):
        """Expose text lines of conf file as readonly attr."""
        return tuple(str(e) for e in self.entries)

    @property
    def content(self):
        """Expose text content of conf file as readonly attr."""
        return "".join(self.lines)

    @property
    def ondisk_digest(self):
        """Generate hashed digest of on-disk file content.

        Returns hashed digest based upon on-disk file content for
        current file name; used in determining whether file has
        been modified.
        """
        with open(self.rename_phase_src) as f:
            return hasher(f.read()).hexdigest()

    @property
    def incore_digest(self):
        """Generate hashed digest of in-code file content.

        Returns hashed digest based upon in-core file content for
        conf file; used in determining whether file has been modified.
        """
        return hasher(self.content).hexdigest()

    @property
    def consistent(self):
        """True if in-core and on-disk content digests match."""
        return self.incore_digest == self.ondisk_digest

    def _update_ondisk(self):
        """Write out in-core file content to disk."""
        with open(self.orig_path, "w") as f:
            f.write(self.content)

    @property
    def dirty(self):
        """True if in-core and on-disk content differs."""
        return not self.consistent

    def replace(self, replacer):
        """Replace specific values based upon lookup table.

        Update file content via the provided DictReplacer instance,
        which will replace matching values based upon their current
        value, looked up in the replacer's lookup table.
        """
        for e in self.entries:
            e.update(replacer.replace(str(e)))

    def _rename_ondisk(self):
        """Perform an on-disk rename action.

        Perform the next on-disk rename of this conf file, if one is
        pending.
        """
        if not self.has_moved or not self.renames_remaining:
            return

        try:
            os.rename(self.rename_phase_src, self.rename_phase_dst)
        except Exception:
            sys.stderr.write("Failed to renamed '%s' to '%s'\n" %
                             (self.rename_phase_src,
                              self.rename_phase_dst))
            raise

        self._rename_phase += 1

    def commit(self, phases=1):
        """Commit pending changes for this conf file.

        Write any required changes to the conf file if it is dirty, and
        perform specified number of rename phases, where -1 means all
        remaining phases. The latter special value should only be used
        if we are certain that we are not trying to swap the names of
        two conf files.
        """
        if self.dirty:
            self._update_ondisk()

        if self.has_moved and self.renames_remaining:
            if phases == -1:
                phases = self.renames_remaining
            for phase in range(phases):
                self._rename_ondisk()


class UdevNetRulesFile(ConfFile):
    """Manage a udev net rules file.

    Provides common framework for managing net rules files.
    """

    def __init__(self, conf_file, syspaths):
        """Manage this conf file using the UdevNetEntry handler."""
        super(UdevNetRulesFile, self).__init__(conf_file, syspaths,
                                               UdevNetEntry)

    @property
    def rules(self):
        """Expose list of rules as readonly attr."""
        return tuple(e for e in self.entries if e.is_rule)

    @property
    def reordered_rules(self):
        """Expose list of re-ordered rules as readonly attr."""
        return tuple(r for r in self.rules if r.reordered)

    @property
    def reordered(self):
        """True if any rules have been re-ordered."""
        return bool(self.reordered_rules)

    @property
    def devices_exist(self):
        """Check that all rule network devices exist.

        Returns true only if all the /sys/class/net devices associated
        with all rules still exist.
        """
        return all(r.sys_path_exists for r in self.rules)


class UdevNetRulesFile70(UdevNetRulesFile):
    """Manage a udev 70-persistent-net.rules file.

    This class manages the contents of the udev persistent net
    rules file /etc/udev/rules.d/70-persistent-net.rules.
    """

    def __init__(self, syspaths):
        """Manage this conf file using the UdevNetEntry handler."""
        super(UdevNetRulesFile70, self).__init__(syspaths.rules_file_70,
                                                 syspaths)

    def reorder_rules(self):
        """Re-order the device names in the rules by PCI device.

        Sort rule devices according to the associated pci_order value,
        and rename device names based upon that ordering.
        """
        new_order = sorted(self.rules, key=attrgetter("pci_order"))
        for idx, r in enumerate(new_order):
            r.dev_rename("%s%s" % (r.dev_name_prefix, idx))


class UdevNetRulesFile71(UdevNetRulesFile):
    """Manage a udev 71-persistent-net.rules file.

    This class manages the contents of the udev persistent net
    rules file /etc/udev/rules.d/71-persistent-net.rules.
    """

    def __init__(self, syspaths):
        """Manage this conf file using the UdevNetEntry handler."""
        super(UdevNetRulesFile71, self).__init__(syspaths.rules_file_71,
                                                 syspaths)

    def reorder_rules(self):
        raise NetRulesError("Re-ordering not supported for "
                            "71-persistent-net.rules file.")


class UdevNetRulesManager(object):
    """Udev Net Rules Manager

    Class used to make the udev persistent net rules settings
    for a system. Generates a 71-persistent-net.rules file that
    orders network devices by PCI order, superceding any existing
    70-persistent-net.rules file.

    We will also update the 70-persistent-net.rules file to match
    the new order.
    """

    def __init__(self, syspaths):
        """Initialise instance settings.

        The syspaths object manages access to the system paths
        against which the operations should be performed.
        """
        self._syspaths = syspaths
        self._rules_70 = None
        self._rules_71 = None
        self._rules_71_created = False

    @property
    def syspaths(self):
        return self._syspaths

    @property
    def rules_70(self):
        if not self._rules_70:
            self._load_rules_70()

        return self._rules_70

    @property
    def rules_71(self):
        if not self._rules_71:
            self._load_rules_71()

        return self._rules_71

    @property
    def rules_71_created(self):
        return self._rules_71_created

    @property
    def rules_file_70_exists(self):
        return os.path.exists(self._syspaths.rules_file_70)

    @property
    def rules_file_71_exists(self):
        return os.path.exists(self._syspaths.rules_file_71)

    def _load_rules_70(self):
        if not self.rules_file_70_exists:
            return

        self._rules_70 = UdevNetRulesFile70(self.syspaths)

    def _load_rules_71(self):
        if not self.rules_file_71_exists:
            self._gen_rules_file_71()

        self._rules_71 = UdevNetRulesFile71(self.syspaths)

    @staticmethod
    def _get_net_dev_info(net_dev_path):
        dev_name = os.path.basename(net_dev_path)
        pci = os.path.realpath(net_dev_path).split('/')[-3]
        with file(os.path.join(net_dev_path, 'dev_port')) as fp:
            port = fp.read().strip('\0').strip()
        with file(os.path.join(net_dev_path, 'address')) as fp:
            address = fp.read().strip('\0').strip()
        return dict(dev_name=dev_name, pci=pci, port=port, address=address)

    @property
    def system_eth_devices(self):
        class_net = self.syspaths.system_sys_path('class', 'net')
        eth_dev_info = list(self._get_net_dev_info(e)
                            for e in glob(os.path.join(class_net, 'eth*')))
        return {e['dev_name']: e for e in eth_dev_info}

    @property
    def ordered_eth_devices(self):
        sys_devs = self.system_eth_devices

        pci_ordered = sorted(sys_devs.values(),
                             key=lambda x: '%s:%s' % (x['pci'], x['port']))
        ordered_devs = OrderedDict()
        for i, e in enumerate(pci_ordered):
            dev_name = 'eth%d' % i
            new_e = e.copy()
            new_e.update(dict(dev_name=dev_name))
            ordered_devs[dev_name] = new_e
        return ordered_devs

    @property
    def reordered(self):
        sys_devs = self.system_eth_devices
        ordered_devs = self.ordered_eth_devices
        return (sys_devs != ordered_devs)

    @property
    def reordered_devices(self):
        sys_devs = self.system_eth_devices
        sys_set = set("%s:%s#%s" % (e['pci'], e['port'], e['dev_name'])
                      for e in sys_devs.itervalues())

        ordered_devs = self.ordered_eth_devices
        ordered_set = set("%s:%s#%s" % (e['pci'], e['port'], e['dev_name'])
                          for e in ordered_devs.itervalues())

        set_diffs = sys_set.symmetric_difference(ordered_set)
        diff_map = {}
        for d in set_diffs:
            d_pci, d_name = d.split('#')
            if d_pci not in diff_map:
                diff_map[d_pci] = {}
            if d in sys_set:
                diff_map[d_pci]['from'] = d_name
            else:
                diff_map[d_pci]['to'] = d_name

        return sorted(diff_map.itervalues(), key=itemgetter('from'))

    @staticmethod
    def _gen_rules_71_entry(e):
        return ['',
                ('SUBSYSTEM=="net", ACTION=="add", DEVPATH=="*/%s/*", '
                 'ATTR{dev_port}=="%s", NAME="%s"' % (e['pci'], e['port'],
                                                      e['dev_name']))]

    def _gen_rules_file_71(self):
        ordered_devs = self.ordered_eth_devices
        content = ["# ARDANA-MANAGED - Managed by Ardana - Do not edit",
                   "# Generated by update_fcoe_udev during install/setup",
                   "#",
                   ("# udev rules to persistently map physical PCI devices "
                    "to ethX device names."),
                   ("# This is used to hard-wire specific ethX names to a "
                    "specific (PCI address,"),
                   ("# dev_port) pairings so that the names don't change "
                    "across reboots.")]

        for e in ordered_devs:
            content.extend(self._gen_rules_71_entry(ordered_devs[e]))

        rules_file = self.syspaths.rules_file_71
        with file(rules_file, "w") as fp:
            fp.write("\n".join(content))

        self._rules_71_created = True

    @property
    def dirty(self):
        if self.rules_71_created and self.reordered:
            return True

        if self.rules_70:
            if self.rules_70.dirty:
                return True

        return False

    @property
    def devices_exist(self):
        if not self.rules_71.devices_exist:
            return False

        if self.rules_71:
            if not self.rules_71.devices_exist:
                return False

        return True

    def reorder_rules(self):
        if self.rules_70:
            self.rules_70.reorder_rules()
        # We should never need to re-order the entries in rules_71

    def commit(self):
        if self.rules_70:
            self.rules_70.commit()


class NetworkDeviceManager(object):
    """Network Device Management Helper

    Class used to manage updating system configuration files as a
    result of reordering network devices in PCI device order.
    """

    def __init__(self, prefix, sys_prefix, syspaths=None):
        """Initialise instance settings.

        The arguments that we support are:
          * prefix - path
            The path under which to look for network configuration files.
          * sys_prefix - path
            The path under which to perform /sys lookups
        """
        if syspaths is None:
            syspaths = ArdanaSystemPaths(prefix, sys_prefix)

        self._syspaths = syspaths
        self._udev = UdevNetRulesManager(syspaths)
        self._fcoe_confs = []
        self._ifaces_confs = []
        self._remap_renamer = None

    @property
    def syspaths(self):
        """Expose syspaths as a readonly attr."""
        return self._syspaths

    @property
    def udev(self):
        """Expose udev as a readonly attr."""
        return self._udev

    @property
    def fcoe_confs(self):
        """Expose fcoe_confs as a readonly attr."""
        return tuple(self._fcoe_confs)

    @property
    def ifaces_confs(self):
        """Expose ifaces_confs as a readonly attr."""
        return tuple(self._ifaces_confs)

    @property
    def remap_renamer(self):
        """Renamer tool used to manage content updates.

        Dynamically creates a DictReplacer instance to be used for
        updating config files the first this is called after devices have
        been reordered, and thereafter returns that DictReplacer instance.
        """
        if self._remap_renamer is None and self.udev.reordered:
            # Construct a DictReplacer instance that can be used to
            # rename the device names within config files.
            reordered = self.udev.reordered_devices
            rename_map = dict(((r['from'], r['to'])
                               for r in reordered))
            self._remap_renamer = DictReplacer(r"(eth\d+)",
                                               rename_map)

        return self._remap_renamer

    _noreorder_flag = "fcoe_noreorder"

    @property
    def dont_run(self):
        """Returns true if flag found in /proc/cmdline."""
        cmdline_file = "/proc/cmdline"
        try:
            with open(cmdline_file) as f:
                cmdline = f.read()
        except Exception:
            sys.stderr.write("Failed to open '%s': %s\n" %
                             (cmdline_file, sys.exc_info()[1]))
            raise

        return self._noreorder_flag in cmdline

    @property
    def system_valid(self):
        """Check that system state is consistent and valid.

        Returns false if any of the network devices identified in
        ther persistent udev net rules doesn't exist.
        """
        return self.udev.devices_exist

    @property
    def already_processed(self):
        """Check if a system has already been processed.

        Should be called before doing anything to check if system
        has already been processed, and or needs a reboot.
        """
        # If the flag file has been created by a previous run
        # or if any of the rules have already been re-ordered
        # then we shouldn't make any more changes and instead
        # the system needs to be rebooted.
        return self.syspaths.flag_exists

    @property
    def needs_reboot(self):
        return self.udev.reordered

    def reorder_udev_rules(self):
        """Re-order network devcies in Udev persistent rules."""
        self.udev.reorder_rules()

    @property
    def fcoe_dirty(self):
        """True if any FCOE config changes pending."""
        return any(c.dirty or c.renames_remaining for c in self.fcoe_confs)

    @property
    def ifaces_dirty(self):
        """True if any network interface config changes pending."""
        return any(c.dirty or c.renames_remaining for c in self.ifaces_confs)

    @property
    def dirty(self):
        """True if any udev, FCOE or network config changes pending."""
        return self.udev.dirty or self.fcoe_dirty or self.ifaces_dirty

    def _process_candidate_conf_files(self, reordered_files):
        """Process specified conf files.

        Given a list of (rule, file) pairs, weed out those for which
        the conf file doesn't exist and then process the remaining
        conf files, updating their content as appropriate and then
        rename them in a 2 phase process; this allows us to safely
        swap files. Return the resulting list of ConfFile instances.
        """
        confs = []
        for r, f in reordered_files:
            if not os.path.exists(f):
                continue

            conf = ConfFile(f, self.syspaths)
            conf.replace(self.remap_renamer)
            temp_name = "%s...%s" % (r['from'], r['to'])
            conf.path = conf.path.replace(r['from'], temp_name)
            conf.path = conf.path.replace(temp_name, r['to'])
            confs.append(conf)

        return confs

    def update_fcoe_configs(self):
        """Update FCOE config based on re-ordered udev rules."""
        # Nothing to be done if no reordering has occurred.
        reordered = self.udev.reordered_devices
        if not reordered:
            return

        # Skip if we have already completed this stage
        if self.fcoe_confs:
            return

        # Generate candidate list of fcoe conf files, with
        # associated rule, that need to be processed
        reordered_files = tuple((r, os.path.join(self.syspaths.fcoe_dir,
                                                 "cfg-%s" % r['from']))
                                for r in reordered)

        # At this stage changes have been prepared but are not yet
        # committed to disk
        self._fcoe_confs = self._process_candidate_conf_files(reordered_files)

    def update_ifaces_configs(self):
        """Update network config based on re-ordered udev rules."""
        # Nothing to be done if no reordering has occurred.
        reordered = self.udev.reordered_devices
        if not reordered:
            return

        # Skip if we have already completed this stage
        if self.ifaces_confs:
            return

        # Generate candidate list of iface conf files, with
        # associated rule, that need to be processed.
        reordered_files = tuple((r, os.path.join(self.syspaths.ifaces_dir,
                                                 r['from']))
                                for r in reordered)

        ifaces_confs = self._process_candidate_conf_files(reordered_files)

        # Process the main interfaces file, and if it was modified, then
        # include it in the list of interface conf objects to be tracked
        conf = ConfFile(self.syspaths.ifaces_file, self.syspaths)
        conf.replace(self.remap_renamer)
        if conf.dirty:
            ifaces_confs.append(conf)

        # At this stage changes have been prepared but are not yet
        # committed to disk
        self._ifaces_confs = ifaces_confs

    @staticmethod
    def _gen_conf_changes_text(action, title, conf_list):
        """Generate change info text."""
        if not (conf_list and
                any(c.dirty or c.has_moved for c in conf_list)):
            return ""

        lines = ["%s %s Changes:" % (action, title)]

        if any(c.has_moved for c in conf_list):
            lines.append("  Reordering:")
            lines.extend(["    %s ==> %s" % (c.orig_path, c.path)
                          for c in conf_list if c.has_moved])
        if any(c.dirty for c in conf_list):
            lines.append("  Modifying:")
            lines.extend(["    %s" % c.path
                          for c in conf_list if c.has_moved])
        lines.append("")

        return "\n".join(lines)

    @staticmethod
    def _gen_udev_changes_text(action, reordered_list):
        """Generate device reorder change text."""
        if not reordered_list:
            return ""

        lines = ["%s Device Re-ordering:" % action]
        lines.extend(["  %6s ==> %s" % (r['from'], r['to'])
                      for r in reordered_list])
        lines.append("")

        return "\n".join(lines)

    def _gen_changes_text(self, action):
        reordered = self.udev.reordered_devices
        changes = [self._gen_udev_changes_text(action, reordered),
                   self._gen_conf_changes_text(action, "FCOE",
                                               self.fcoe_confs),
                   self._gen_conf_changes_text(action, "Network",
                                               self.ifaces_confs)]

        return "\n".join(c for c in changes if c)

    def _create_flag_file(self, content):
        """Create flag file with provided content."""
        if not os.path.exists(self.syspaths.flag_dir):
            try:
                os.makedirs(self.syspaths.flag_dir)
            except Exception:
                sys.stderr.write("Failed to create flag directory '%s': %s\n" %
                                 (self.syspaths.flag_dir, sys.exc_info()[1]))
                raise

        try:
            with open(self.syspaths.flag_file, "w") as f:
                f.write(content)
        except Exception:
            sys.stderr.write("Failed to create flag file '%s': %s\n" %
                             (self.syspaths.flag_file, sys.exc_info()[1]))
            raise

    def commit(self):
        """Commit any pending changes to disk."""
        changes = "No reordering required."
        msg = "No device reordering required on this system."

        if self.dirty:
            print(self._gen_changes_text("Proposed"))

            # Generate committed changes text before committing.
            changes = self._gen_changes_text("Committed")

            # If the rules have been updated commit those changes
            if self.udev.dirty:
                self.udev.commit()

            # If any of the fcoe or interfaces files have been
            # updated or renamed then commit those changes
            if self.fcoe_dirty or self.ifaces_dirty:
                conf_list = self.fcoe_confs + self.ifaces_confs
                rename_phases = max(c.renames_remaining
                                    for c in conf_list)

                # We want to iterate at least once, and up to max
                # number of rename operations outstanding.
                for i in range(max(1, rename_phases)):
                    for conf in conf_list:
                        # First time through will update file content, and
                        # peforms first rename if any; subsequent commits
                        # perform any remaining renames
                        conf.commit()

            msg = ("All device reordering changes committed to disk.\n"
                   "NOTE:\n"
                   "  Please ensure that the ramdisk is updated and the\n"
                   "  system is rebooted for these changes to take effect.")

        self._create_flag_file(changes)
        print(msg)

    def process_system(self):
        """Process the current system.

        Update the system by re-ordering the udev persistent network
        rules according to PCI device order, and then reflect those
        reordering changes in the system FCOE and network interfaces
        configurations, and then commit those changes to disk.
        """
        if self.already_processed or self.dont_run or not self.system_valid:
            return

        self.reorder_udev_rules()
        self.update_fcoe_configs()
        self.update_ifaces_configs()

        self.commit()


def main():
    """Main body for script."""
    parser = ArgumentParser(description="Update FCOE device udev persisted "
                                        "ordering.")
    parser.add_argument("--prefix", "-p", default="/target",
                        help="System files will be accessed under this "
                             "prefix")
    parser.add_argument("--sys-prefix", "-s", default="/",
                        help="The /sys file system files will be accessed "
                             "under this prefix")
    args = parser.parse_args()
    NetworkDeviceManager(args.prefix, args.sys_prefix).process_system()


if __name__ == '__main__':
    main()
0707010000002E000081ED00000000000000000000000162FCFEE10000020A000000000000000000000000000000000000004C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/files/validate_yaml#!/usr/bin/python

import json
import jsonschema
import sys
import yaml

with open(sys.argv[1], 'r') as schema:
    schema_yml = yaml.load(schema)
    schema_json = json.dumps(schema_yml)
    schema_contents = json.loads(schema_json)

with open(sys.argv[2], 'r') as data_file:
    data_yml = yaml.load(data_file)
    data_json = json.dumps(data_yml)
    data_contents = json.loads(data_json)

try:
    jsonschema.validate(data_contents, schema_contents)
except Exception as e:
    print "ERROR: " + str(e)
    sys.exit(1)
0707010000002F000041ED00000000000000000000000262FCFEE100000000000000000000000000000000000000000000003E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks07070100000030000081A400000000000000000000000162FCFEE1000003F5000000000000000000000000000000000000006000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/assert-nodes-are-not-pingable.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
---
- name: cobbler | assert-nodes-are-not-pingable | Derive node ips
  local_action: bmconfig file={{ baremetal_config }} node={{ inventory_hostname }} field=ip_addr
  register: cobbler_ip

- name: cobbler | assert-nodes-are-not-pingable | ping IPs
  become: yes
  shell: ping -c 3 "{{ cobbler_ip.stdout }}"
  register: ping
  failed_when: ping.rc == 0
  changed_when: false
07070100000031000081A400000000000000000000000162FCFEE10000035C000000000000000000000000000000000000005600000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/assert-power-is-off.yml# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | assert-power-is-off | Check node power status
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=status
  register: pstate
  failed_when: pstate | failed or pstate.power != "off"
07070100000032000081A400000000000000000000000162FCFEE10000057C000000000000000000000000000000000000005600000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/check-distro-exists.yml#
# (c) Copyright 2019 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# This task file expects 2 parameters:
#   check_distro: the name of the distro to check for (required)
#   check_delay: delay between retry attempts (optional, default=1)
# Results:
#   cobbler_distro_exists_result - registered result from cobbler command
---

- name: cobbler | check-distro-exists | Check {{ check_distro }} distro exists?
  become: yes
  command: >-
    cobbler distro report --name="{{ check_distro }}"
  register: cobbler_distro_exists_result
  failed_when: false
  changed_when: false
  retries: 5
  delay: "{{ check_delay | default(1) }}"
  until: >-
    "error(111, 'Connection refused')" not in cobbler_distro_exists_result.stderr

- name: cobbler | check-distro-exists | Report if multiple attempts required
  debug: var=cobbler_distro_exists_result
  when: cobbler_distro_exists_result.attempts > 0

07070100000033000081A400000000000000000000000162FCFEE1000006AB000000000000000000000000000000000000005300000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/check-sles-repos.yml#
# (c) Copyright 2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Task to check whether zypper repos are configured on deployer
# and repos URI has expected input uri pattern
# Check is done via using 'alias' attribute in input repos list
#
# Pass following variable to include file.
# vars:
#    _input_repos_list: "{{ sles_expected_media_repos }}"
#    _input_uri_pattern: "^dir:\\/\\/\\/srv\\/www\\/suse-12.3\\/"
#

- name: cobbler | check-sles-repos | Check repos configured on deployer
  delegate_to: "localhost"
  become: yes
  shell: >
     zypper lr -u | awk '$3 == "{{ item.alias }}" && $15 ~ /{{ _input_uri_pattern}}/ {print $3}'
  with_items: _input_repos_list
  register: _repos_found_result

- name: cobbler | check-sles-repos | Create configured repos list
  set_fact:
    sles_configured_media_repos: >
      {%- set _c = [] -%}
      {%- for _item in _input_repos_list -%}
      {%-   if _repos_found_result.results | selectattr('stdout', 'equalto', _item.alias) | list | count > 0 -%}
      {%-     set _ = _c.append(_item) -%}
      {%-   endif -%}
      {%- endfor -%}
      {{ _c }}
  when:
    - _repos_found_result is defined
    - _repos_found_result.results | length > 0
07070100000034000081A400000000000000000000000162FCFEE100001092000000000000000000000000000000000000004C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/configure.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | configure | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

# Cobbler deb package installs conf file into wrong folder /etc/apache2/conf.d
- name: cobbler | configure | Debian - symlink cobbler apache configuration
  become: yes
  file:
    src: /etc/apache2/conf.d/cobbler.conf
    dest: /etc/apache2/conf-available/cobbler.conf
    state: link
  when: not cobbler_is_sles

- name: cobbler | configure | Debian - enable cobbler apache configuration
  become: yes
  command: a2enconf cobbler
  when: not cobbler_is_sles

- name: cobbler | configure | Suse - create apache configuration for /srv
  become: yes
  template: src=srv.conf.j2 dest=/etc/apache2/conf.d/srv.conf
  when: cobbler_is_sles

- name: cobbler | configure | Debian - create apache configuration for /srv
  become: yes
  template: src=srv.conf.j2 dest=/etc/apache2/conf-available/srv.conf
  when: not cobbler_is_sles

- name: cobbler | configure | Debian - enable apache configuration for /srv
  become: yes
  command: a2enconf srv
  when: not cobbler_is_sles

- name: cobbler | configure | set default passwd
  set_fact: cobbler_default_passwd="{{ item }}"
  with_password: /tmp/cobbler_setup  encrypt=sha512_crypt

- name: cobbler | configure | rm temp file
  file:
    path: /tmp/cobbler_setup
    state: absent
    recurse: no

- name: cobbler | configure | Adding cobbler settings file
  become: yes
  template: src=settings.j2 dest=/etc/cobbler/settings

- name: cobbler | configure | Suse - fix cobbler tftpd template
  become: yes
  lineinfile:
    dest: /etc/cobbler/tftpd.template
    state: present
    regexp: '^\s*server_args\s*=.*'
    line: '        server_args             = -u tftp -B 1380 -vvvv -s $args'
  when: cobbler_is_sles

- name: cobbler | configure | Create directory for preseed content
  become: yes
  file:
    path: /srv/www/preseed
    state: directory
    mode: 0755

- name: cobbler | configure | Copy preseed content
  become: yes
  copy: src={{ item }} dest=/srv/www/preseed
  with_items:
     - partition-pxe
     - partition-uefi
     - configure_partitioning
     - configure_kdump
     - bnx2x.conf
     - update_fcoe_udev.py

- name: cobbler | configure | Add option to add gateway
  become: yes
  template:
      src: configure_network.sh.j2
      dest: /srv/www/preseed/configure_network.sh

- name: cobbler | configure | set timestamp for installs
  become: yes
  shell: date +%Y%m%d%H%M%S > {{ local_timestamp_file }}

# Temp until CI updated
- name: cobbler | configure | Set local stamp
  become: yes
  copy: src={{ local_timestamp_file }} dest=/etc/cobbler_ardana_installed

# Get syslinux bootloaders
- name: cobbler | configure | Create bootloader directory
  become: yes
  file:
    path: /var/lib/cobbler/loaders
    state: directory
    mode: 0755

# Copy module behaves weird with with_items
- name: cobbler | configure | Copy various loaders to cobbler loaders dir
  become: yes
  shell: cp -Lf {{ item.src }} /var/lib/cobbler/loaders/{{ item.filename }}
  with_items: cobbler_bootloader_sources

- name: cobbler | configure | Adding cobbler dhcp template
  become: yes
  template: src=cobbler.dhcp.template.j2 dest=/etc/cobbler/dhcp.template

- name: cobbler | configure | Enable apache modules
  become: yes
  command: "a2enmod {{ item }}"
  with_items:
    - proxy
    - proxy_http
    - access_compat

- name: cobbler | configure | Check SLES distro exists?
  include: check-distro-exists.yml
  vars:
    check_distro: "{{ sles_version_name }}-x86_64"
    check_delay: 5
07070100000035000081A400000000000000000000000162FCFEE1000004D9000000000000000000000000000000000000005400000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/create-rhel-grub2.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | create-rhel-grub2 | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

- name: cobbler | create-rhel-grub2 | Derive nodes mac address
  local_action: bmconfig file={{ baremetal_config }} node={{ item }} field=mac_addr
  with_items: "{{ node | split(',') }}"
  register: node_mac

- name: cobbler | create-rhel-grub2 | Create nodes grub2 files
  become: yes
  template:
    src: grub2.j2
    dest: '{{ cobbler_tftp_dir }}/grub/grub.cfg-01-{{ item.stdout | lower }}'
  with_items: "{{ node_mac.results }}"
07070100000036000081A400000000000000000000000162FCFEE1000004DE000000000000000000000000000000000000005400000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/create-sles-grub2.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | create-sles-grub2 | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

- name: cobbler | create-sles-grub2 | Derive nodes mac address
  local_action: bmconfig file={{ baremetal_config }} node={{ item }} field=mac_addr
  with_items: "{{ node | split(',') }}"
  register: node_mac

- name: cobbler | create-sles-grub2 | Create nodes grub2 files
  become: yes
  template:
    src: sles.grub2.j2
    dest: '{{ cobbler_tftp_dir }}/grub/grub.cfg-01-{{ item.stdout | lower }}'
  with_items: "{{ node_mac.results }}"
07070100000037000081A400000000000000000000000162FCFEE1000006BC000000000000000000000000000000000000005500000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/get-baremetal-info.yml#
# (c) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#

# This task runs a module on localhost that extracts networking information
# from the baremetal section of the model and returns it in a convenient struct
# that is consumed by various other plays. I'm using run_once because this task
# might get run against a bunch of nodes in parallel. That's not dangerous or
# anything, but they'd all get the same answer (because they're all working
# with the same source data from localhost) so it's pointless repetition.
# Run once, we don't even care on what node; the result will be the same.

- name: cobbler | get-baremetal-info | Get baremetal info
  local_action: bmconfig file={{ baremetal_config }} default_distro_id={{ sles_version_name }}-x86_64
- name: cobbler | check-ipmi-credentials-provided | Check at least one server has ipmi credentials
  fail:
    msg: >
      There were no servers found with ipmi credentials defined.
      If you want to use cobbler to deploy servers,
      you must include proper ipmi credentials for each server
      you want to deploy with cobbler.
  when: bminfo.servers | length == 0

07070100000038000081A400000000000000000000000162FCFEE10000066D000000000000000000000000000000000000004F00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/get-nodelist.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- include: get-baremetal-info.yml

# Allow the user to specify -e nodelist="ccn-0001,cpn-0003" on the
# command line to target a specific set of nodes.
- name: cobbler | get-nodelist | User-specified target list
  set_fact: target_nodes="{{ nodelist | split(',') }}"
  when: nodelist is defined and nodelist != "all"

# Allow the user to specify -e nodelist=all on the command line.
- name: cobbler | get-nodelist | Compute generic target list
  set_fact: target_nodes="{{ bminfo.server_ids }}"
  when: nodelist is defined and nodelist == "all"

- name: cobbler | get-nodelist | Check we have targets
  fail: msg="There is no default set of nodes for this command, use -e nodelist"
  when: target_nodes is undefined

- name: cobbler | get-nodelist | Create dynamic host group, minus myself
  add_host: name={{ item }} groups=dynamic_targets ansible_connection=local
  with_items: target_nodes
  when: dynamic_targets_created is undefined and bminfo.whoami != item

- set_fact: dynamic_targets_created=True
07070100000039000081A400000000000000000000000162FCFEE100000327000000000000000000000000000000000000005300000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/get-power-status.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | get-power-status | Get power status
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=status
  register: ipmi_connectivity
0707010000003A000081A400000000000000000000000162FCFEE100000544000000000000000000000000000000000000005700000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/get-rhel-loader-file.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | create-rhel-loader-file | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

- name: cobbler | get-rhel-loader-file | define grub file to load
  set_fact:
    dest_file: grubx64.efi
  when: filepath | basename == "grubx64.efi"

- name: cobbler | get-rhel-loader-file | define shim file to load
  set_fact:
    dest_file: shim.efi.signed
  when: filepath | basename == "shim.efi"

- name: cobbler | get-rhel-loader-file | Move loader into cobbler
  become: yes
  copy:
    src: "{{ filepath }}"
    dest: "{{ cobbler_tftp_dir }}/grub/{{ dest_file }}"
    owner: root
    group: root
  when: dest_file is defined
0707010000003B000081A400000000000000000000000162FCFEE100000C02000000000000000000000000000000000000005200000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/get-rhel-loader.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | get-rhel-loader | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

- name: cobbler | get-rhel-loader | Install rpm2cpio for debian host
  become: yes
  apt:
    name: rpm2cpio
    state: installed
  when: ansible_os_family | lower == 'debian'

- name: cobbler | get-rhel-loader | Mount iso on deployer
  become: yes
  mount:
    name: /mnt
    src: "{{ rhel_iso_location }}"
    fstype: iso9660
    opts: ro
    state: mounted

- name: cobbler | get-rhel-loader | Create tmp dir on deployer
  command: mktemp -dt ardana.XXXXXXXX
  register: uefi_deployer_tmp_dir_result

- name: cobbler | get-rhel-loader | Define deployer tmp dir fact
  set_fact:
    uefi_deployer_tmp_dir: "{{ uefi_deployer_tmp_dir_result.stdout }}"

- name: cobbler | get-rhel-loader | Extract shim/grub on deployer
  become: yes
  copy:
    src: "{{ item }}"
    dest: "{{ uefi_deployer_tmp_dir }}"
  with_fileglob:
    - /mnt/Packages/{{ rhel_shim_rpm }}
    - /mnt/Packages/{{ rhel_grub2_efi_rpm }}

- name: cobbler | get-rhel-loader | Unmount iso on deployer
  become: yes
  mount:
    name: /mnt
    src: "{{ rhel_iso_location }}"
    fstype: iso9660
    state: unmounted

- name: cobbler | get-rhel-loader | Execute rpm2cpio
  become: yes
  shell: rpm2cpio {{ item }} | cpio -dimv
  args:
    chdir: "{{ uefi_deployer_tmp_dir }}"
  with_fileglob:
    - "{{ uefi_deployer_tmp_dir }}/{{ rhel_shim_rpm }}"
    - "{{ uefi_deployer_tmp_dir }}/{{ rhel_grub2_efi_rpm }}"

- name: cobbler | get-rhel-loader | Move loader into cobbler
  become: yes
  shell: >
    mv {{ uefi_deployer_tmp_dir }}/{{ grubx64_location }} \
          "{{ cobbler_tftp_dir }}/grub"

- name: cobbler | get-rhel-loader | Move shim into cobbler
  become: yes
  shell: >
     mv {{ uefi_deployer_tmp_dir }}/{{ rhel_shim_location }} \
           "{{ cobbler_tftp_dir }}/grub/shim.efi.signed"


- name: cobbler | get-rhel-loader | root owns the loader
  become: yes
  file:
    path: "{{ cobbler_tftp_dir }}/grub/grubx64.efi"
    owner: root
    group: root
    mode: 0644

- name: cobbler | get-rhel-loader | root owns the shim
  become: yes
  file:
    path: "{{ cobbler_tftp_dir }}/grub/shim.efi.signed"
    owner: root
    group: root
    mode: 0644

- name: cobbler | get-rhel-loader | Cleanup deployer tmp dir
  become: yes
  file:
    path: "{{ uefi_deployer_tmp_dir }}"
    state: absent
0707010000003C000081A400000000000000000000000162FCFEE100000541000000000000000000000000000000000000005700000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/get-sles-loader-file.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | get-sles-loader-file | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

- name: cobbler | get-sles-loader-file | define grub file to load
  set_fact:
    dest_file: grubx64.efi
  when: filepath | basename == "grubx64.efi"

- name: cobbler | get-sles-loader-file | define shim file to load
  set_fact:
    dest_file: shim.efi.signed
  when: filepath | basename == "shim.efi"

- name: cobbler | get-sles-loader-file | Move loader into cobbler
  become: yes
  copy:
    src: "{{ filepath }}"
    dest: "{{ cobbler_tftp_dir }}/grub/{{ dest_file }}"
    owner: root
    group: root
  when: dest_file is defined
0707010000003D000081A400000000000000000000000162FCFEE100000D4C000000000000000000000000000000000000005200000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/get-sles-loader.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | get-sles-loader | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

- name: cobbler | get-sles-loader | Install rpm2cpio
  become: yes
  apt:
    name: rpm2cpio
    state: installed

- name: cobbler | get-sles-loader | Mount iso on deployer
  become: yes
  mount:
    name: /mnt
    src: "{{ sles_iso_location }}"
    fstype: iso9660
    opts: ro
    state: mounted

- name: cobbler | get-sles-loader | Create tmp dir on deployer
  command: mktemp -dt ardana.XXXXXXXX
  register: uefi_deployer_tmp_dir_result

- name: cobbler | get-sles-loader | Define deployer tmp dir fact
  set_fact:
    uefi_deployer_tmp_dir: "{{ uefi_deployer_tmp_dir_result.stdout }}"

- name: cobbler | get-sles-loader | Extract shim/grub on deployer
  become: yes
  copy:
    src: "{{ item }}"
    dest: "{{ uefi_deployer_tmp_dir }}"
  with_fileglob:
    - /mnt/suse/x86_64/{{ sles_shim_rpm }}
    - /mnt/suse/x86_64/{{ sles_grub2_efi_rpm }}

- name: cobbler | get-sles-loader | Unmount iso on deployer
  become: yes
  mount:
    name: /mnt
    src: "{{ sles_iso_location }}"
    fstype: iso9660
    state: unmounted

- name: cobbler | get-sles-loader | Execute rpm2cpio
  become: yes
  shell: rpm2cpio {{ item }} | cpio -dimv
  args:
    chdir: "{{ uefi_deployer_tmp_dir }}"
  with_fileglob:
    - "{{ uefi_deployer_tmp_dir }}/{{ sles_shim_rpm }}"
    - "{{ uefi_deployer_tmp_dir }}/{{ sles_grub2_efi_rpm }}"

- name: cobbler | get-sles-loader | Move loader into cobbler
  become: yes
  command: >
    mv "{{ uefi_deployer_tmp_dir }}/{{ sles_grubx64_location }} "
          "{{ cobbler_tftp_dir }}/grub/grub.efi"

- name: cobbler | get-sles-loader | Make x86_64-efi module directory
  become: yes
  command: >
    mkdir "{{ cobbler_tftp_dir }}/grub/x86_64-efi"

- name: cobbler | get-sles-loader | Move regexp module into cobbler
  become: yes
  command: >
    mv "{{ uefi_deployer_tmp_dir }}/{{ sles_regexp_location }}"
          "{{ cobbler_tftp_dir }}/grub/x86_64-efi/regexp.mod"

- name: cobbler | get-sles-loader | Move shim into cobbler
  become: yes
  command: >
     mv "{{ uefi_deployer_tmp_dir }}/{{ sles_shim_location }} "
           "{{ cobbler_tftp_dir }}/grub/shim.efi.signed"

- name: cobbler | get-sles-loader | root owns the loader
  become: yes
  file:
    path: "{{ cobbler_tftp_dir }}/grub/grub.efi"
    owner: root
    group: root
    mode: 0644

- name: cobbler | get-sles-loader | root owns the shim
  become: yes
  file:
    path: "{{ cobbler_tftp_dir }}/grub/shim.efi.signed"
    owner: root
    group: root
    mode: 0644

- name: cobbler | get-sles-loader | Cleanup deployer tmp dir
  become: yes
  file:
    path: "{{ uefi_deployer_tmp_dir }}"
    state: absent
0707010000003E000081A400000000000000000000000162FCFEE100001336000000000000000000000000000000000000004A00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/install.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Playbook for installing cobbler
---
- name: cobbler | install | Set vars dependent on target OS
  include_vars: "{{ ansible_os_family.split(' ')[0] | lower | replace('open','') }}.yml"

# Remove any old atftp (this also stops the service)
- name: cobbler | install | Remove conflicting packages
  become: yes
  package:
    name: "{{ item }}"
    state: absent
  with_items: cobbler_remove_packages

- name: cobbler | install | Install cobbler and dependencies
  become: yes
  package:
    name: "{{ item }}"
    state: present
  with_items: cobbler_install_packages

- name: cobbler | install | Comment contents of default log rotation script
  become: yes
  shell: sed -i -e 's/^/#/' $(grep -lv "#" /etc/logrotate.d/cobbler)
  failed_when: false

- name: cobbler | install | Create validate json script
  copy:
    src: validate_yaml
    dest: ~/
    mode: "u=rwx"

- name: cobbler | install | Set bm_schema_{base_dir,path} for nonlegacy layout
  set_fact:
      bm_schema_base_dir: "{{ lookup( 'pipe', '/usr/bin/python -c \"import ardana_configurationprocessor as acp; print(acp.__file__)\"' | quote) | quote | dirname  }}"
      bm_schema_path: '/data/Site/Schema/2.0/server.yml'

- name: cobbler | install | Validate json schema
  command: ~/validate_yaml {{ bm_schema_base_dir }}{{ bm_schema_path }} {{ baremetal_config }}

- name: cobbler | install | stop tftpd
  become: yes
  command: "systemctl stop {{ cobbler_tftp_service_name }}"

- name: cobbler | install | disable tftpd
  become: yes
  command: "systemctl disable {{ cobbler_tftp_service_name }}"

- name: cobbler install | Get interface name
  shell: netstat -ie | grep -B1 "{{ cobbler_server_ip_addr }}" | head -n1 | awk '{ print $1 }'
  register: interface_name
  changed_when: false

- name: check if interface matches baremetal file
  fail:
    msg: "Please update your baremetal file with the new interface name {{ interface_name.stdout }}"
  when: interface_name.stdout != cobbler_server_interface

# isc-dhcp-server will fail to install if dest=/etc/default/isc-dhcp-server is not present
# and containing the INTERFACES param
# TODO - Log bugzilla for this packaging issue
- name: cobbler | install | Create isc-dhcp-server conf file
  become: yes
  template:
    src: isc-dhcp-server.j2
    dest: /etc/default/isc-dhcp-server
  when: not cobbler_is_sles

- name: cobbler | install | Install isc-dhcp-server
  become: yes
  package:
    name: "{{ cobbler_dhcp_package_name }}"
    state: present

- name: cobbler | install | Create dhcp conf file
  become: yes
  template:
    src: dhcpd.conf.j2
    dest: "{{ cobbler_dhcp_config_file }}"

- name: cobbler | install | Populate isc-dhcp-server sysconfig file
  become: yes
  lineinfile:
    dest: /etc/sysconfig/dhcpd
    regexp: '^DHCPD_INTERFACE=.*'
    line: 'DHCPD_INTERFACE="{{ cobbler_server_interface }}"'
  when: cobbler_is_sles

- name: cobbler | install | Create dhcpd.service.d systemd path
  become: yes
  file:
    path: /etc/systemd/system/dhcpd.service.d
    state: directory
    mode: 0755
  when: cobbler_is_sles

- name: cobbler  | install | Create dhcpd.service.d/start-limit.conf
  become: yes
  template:
    src: dhcpd-start-limit.conf.j2
    dest: /etc/systemd/system/dhcpd.service.d/start-limit.conf
    mode: 0644
  register: _dhcpd_conf_result
  when: cobbler_is_sles

- name: cobbler | install | Reload systemd for dhcpd.service extension
  become: yes
  command: systemctl daemon-reload
  when:
    cobbler_is_sles and
    _dhcpd_conf_result | changed

- name: cobbler | install | Create ipmi lanplus power file
  become: yes
  copy:
    src: fence_ipmitool.template
    dest: /etc/cobbler/power/fence_ipmitool.template

- name: cobbler | install | Get deployer pub ssh key
  command: cat {{ ardanauser_deployer_home }}/.ssh/id_rsa.pub
  register: sshkeyoutput

- name: cobbler | install | Save deployer ssh key
  set_fact:
    deployer_ssh_pub_key: "{{ sshkeyoutput.stdout }}"

- name: cobbler | install | Install kickstarts
  become: yes
  template:
    src: "{{ item[0].kickstart }}.j2"
    dest: "/var/lib/cobbler/kickstarts/{{ item[0].kickstart }}-{{ item[1].id }}"
  when:
    "'{{ item[0].name }}-{{ item[0].arch }}' == '{{ item[1].distro_id }}'"
  with_nested:
      - remote_distros
      - bminfo.servers
0707010000003F000081A400000000000000000000000162FCFEE10000031C000000000000000000000000000000000000004E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/netboot-off.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | netboot-off | Disallow netboot in Cobbler
  become: yes
  command: cobbler system edit --name={{ inventory_hostname }} --netboot-enabled=0
07070100000040000081A400000000000000000000000162FCFEE100000318000000000000000000000000000000000000004D00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/netboot-on.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | netboot-on | Allow netboot in Cobbler
  become: yes
  command: cobbler system edit --name={{ inventory_hostname }} --netboot-enabled=1
07070100000041000081A400000000000000000000000162FCFEE100000DCD000000000000000000000000000000000000005C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/populate-rhel-per-profile.yml#
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- name: cobbler | populate-rhel-per-profile | Check RHEL distro exists?
  include: check-distro-exists.yml
  vars:
    check_distro: "{{ use_rhel_profile }}-x86_64"

- name: cobbler | populate-rhel-per-profile | Install RHEL kickstarts
  become: yes
  template:
    src: "{{ use_rhel_profile }}-anaconda-ks.cfg.j2"
    dest: "/var/lib/cobbler/kickstarts/{{ item }}"
    owner: "root"
    group: "root"
    mode: 0644
  with_items:
    - "{{ use_rhel_profile }}-anaconda-ks.cfg"
    - "{{ use_rhel_profile }}-anaconda-ks-multipath.cfg"

- name: cobbler | populate-rhel-per-profile | Customize multipath kickstart
  become: yes
  replace:
    dest: "/var/lib/cobbler/kickstarts/{{ use_rhel_profile }}-anaconda-ks-multipath.cfg"
    regexp: "{{ cobbler_root_device }}"
    replace: "{{ boot_from_san_root_device }}"

- name: cobbler | populate-rhel-per-profile | Test for RHEL7 ISO
  stat:
    path: "{{ ardanauser_deployer_home }}/{{ deployer_rhel7_iso }}"
    get_checksum: no
    get_md5: no
  register: _deployer_rhel7_iso_exists_result

- name: cobbler | populate-rhel-per-profile | Create temporary mount directory
  become: yes
  command: mktemp -d -p /srv
  register: _mount_tmpdir
  when: _deployer_rhel7_iso_exists_result.stat.exists and cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-rhel-per-profile | Mount RHEL ISO
  become: yes
  shell: |
    mount -o loop "{{ ardanauser_deployer_home }}/{{ deployer_rhel7_iso }}" "{{ _mount_tmpdir.stdout }}"
  when: _deployer_rhel7_iso_exists_result.stat.exists and cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-rhel-per-profile | Cobbler import
  become: yes
  shell: >
    cobbler import
    --path {{ _mount_tmpdir.stdout }}
    --name {{ use_rhel_profile }}
    --kickstart "/var/lib/cobbler/kickstarts/{{ use_rhel_profile }}-anaconda-ks.cfg"
  when: _deployer_rhel7_iso_exists_result.stat.exists and cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-rhel-per-profile | Create multipath profiles
  become: yes
  shell: >
    cobbler profile report --name "{{ item.distro_id }}-{{ item.id }}" ||
    cobbler profile add
    --name="{{ item.distro_id }}-{{ item.id }}"
    --distro="{{ use_rhel_profile }}-x86_64"
    --kickstart "/var/lib/cobbler/kickstarts/{{ use_rhel_profile }}-anaconda-ks-multipath.cfg"
  when:
    "'{{ item.distro_id }}' == '{{ use_rhel_profile }}-x86_64-multipath' and
    _deployer_rhel7_iso_exists_result.stat.exists"
  with_items:  bminfo.servers

- name: cobbler | populate-rhel-per-profile | Umount ISO
  become: yes
  shell: |
    umount {{ _mount_tmpdir.stdout }}
  when: _deployer_rhel7_iso_exists_result.stat.exists and cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-rhel-per-profile | Remove temporary mount directory
  become: yes
  file:
    path: "{{ _mount_tmpdir.stdout }}"
    state: absent
  when: _deployer_rhel7_iso_exists_result.stat.exists and cobbler_distro_exists_result.rc != 0
07070100000042000081A400000000000000000000000162FCFEE100000366000000000000000000000000000000000000005000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/populate-rhel.yml#
# (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- include_vars: ../../deployer-setup/defaults/ardana_tar_locations.yml

- include: populate-rhel-per-profile.yml
  vars:
    use_rhel_profile: "{{ rhel_profile_name }}"
  when: rhel_profile_name | default('') != ''

07070100000043000081A400000000000000000000000162FCFEE100000D28000000000000000000000000000000000000005000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/populate-sles.yml#
# (c) Copyright 2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- name: cobbler | populate-sles | Check SLES Distro
  include: check-distro-exists.yml
  vars:
    check_distro: "{{ sles_version_name }}-x86_64"

- name: cobbler | populate-sles | Install SLES kickstart (autoyast)
  become: yes
  template:
    src: "{{ sles_version_name }}-autoyast.xml.j2"
    dest: "/var/lib/cobbler/kickstarts/{{ sles_version_name }}-autoyast.xml"
    owner: "root"
    group: "root"
    mode: 0644

- name: cobbler | populate-sles | Test for SLES ISO file in home folder
  stat:
    path: "{{ sles_iso_location }}"
    get_checksum: no
    get_md5: no
  register: _deployer_sles_iso_exists_result

- name: cobbler | populate-sles | Test for SLES ISO mounted at /media/cdrom
  stat:
    path: "/media/cdrom/suse"
    get_checksum: no
    get_md5: no
  register: _deployer_sles_cdrom_exists_result

- name: cobbler | populate-sles | Create temporary mount directory
  become: yes
  command: mktemp -d -p /srv
  register: _mount_tmpdir
  when: (_deployer_sles_iso_exists_result.stat.exists or
         _deployer_sles_cdrom_exists_result.stat.exists) and
         cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-sles | Mount SLES ISO
  become: yes
  command: >
    mount -o ro,loop "{{ sles_iso_location }}" \
        "{{ _mount_tmpdir.stdout }}"
  when: _deployer_sles_iso_exists_result.stat.exists
        and cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-sles | Rsync SLES ISO to temporary folder
  become: yes
  synchronize:
    src: "/media/cdrom/"
    dest: "{{ _mount_tmpdir.stdout }}/"
    delete: true
    times: no
    rsync_opts:
      - "--exclude=ardana"
  when: _deployer_sles_cdrom_exists_result.stat.exists
        and not _deployer_sles_iso_exists_result.stat.exists
        and cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-sles | Cobbler import
  become: yes
  command: >
    cobbler import
    --path {{ _mount_tmpdir.stdout }}
    --name {{ sles_version_name }}
    --kickstart /var/lib/cobbler/kickstarts/{{ sles_version_name }}-autoyast.xml
  when: (_deployer_sles_iso_exists_result.stat.exists or
         _deployer_sles_cdrom_exists_result.stat.exists) and
         cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-sles | Umount ISO
  become: yes
  command: >
    umount {{ _mount_tmpdir.stdout }}
  when: _deployer_sles_iso_exists_result.stat.exists
        and cobbler_distro_exists_result.rc != 0

- name: cobbler | populate-sles | Remove temporary directory
  become: yes
  file:
    path: "{{ _mount_tmpdir.stdout }}"
    state: absent
  when: (_deployer_sles_iso_exists_result.stat.exists or
         _deployer_sles_cdrom_exists_result.stat.exists) and
         cobbler_distro_exists_result.rc != 0
07070100000044000081A400000000000000000000000162FCFEE100001A6B000000000000000000000000000000000000004B00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/populate.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
# Make path for isos
- name: cobbler | populate | Create directory for isos
  become: yes
  file:
    path: /srv/www/cobbler/iso
    state: directory
    mode: 0755

# Remote distros

- name: Compile distro in-use list
  set_fact:
    remote_distros_inuse: >
      {%- set distros = [] %}
      {%- for distro_id in bminfo.servers | map(attribute='distro_id') | unique %}
      {%-   for distro in remote_distros %}
      {%-     if [distro.name, distro.arch] | join('-') == distro_id %}
      {%-       set _ = distros.append(distro) %}
      {%-     endif %}
      {%-   endfor %}
      {%- endfor %}
      {{- distros -}}

- name: cobbler | populate | Check distro exists in cobbler
  become: yes
  with_items: remote_distros_inuse
  command: cobbler distro report --name={{ item.name }}-{{ item.arch }}
  register: distro_exists
  changed_when: false
  failed_when: false

- name: cobbler | populate | Fail if any managed distro(s) are missing
  fail:
    msg: "Cobbler distro {{ item.item.name }}-{{ item.item.arch }}, managed by '{{ item.item.managed_by }}', does not exist"
  when:
    item.rc != 0 and
    item.item.managed_by|default('') != ''
  with_items: distro_exists.results

- name: cobbler | populate | Create directory for net images
  become: yes
  file:
    path: "{{ item.item.file }}"
    state: directory
    mode: 0755
  when:
    item.rc != 0 and
    item.item.managed_by|default('') == ''
  with_items: distro_exists.results

- name: cobbler | populate | Get net kernel
  become: yes
  get_url:
    url: "{{ item.item.url }}/dists/{{ item.item.distro }}/{{ item.item.url_boot_path }}/{{ item.item.kernel }}"
    dest: "{{ item.item.file }}"
  when:
    item.item.managed_by|default('') == ''
  with_items: distro_exists.results

- name: cobbler | populate | Get net initrd
  become: yes
  get_url:
    url: "{{ item.item.url }}/dists/{{ item.item.distro }}/{{ item.item.url_boot_path }}/{{ item.item.initrd }}"
    dest: "{{ item.item.file }}"
  when:
    item.item.managed_by|default('') == ''
  with_items: distro_exists.results

- name: cobbler | populate | Add distro
  become: yes
  shell: >
    cobbler distro add
    --name="{{ item.item.name }}-{{ item.item.arch }}"
    --kernel="{{ item.item.file }}/{{ item.item.kernel }}"
    --initrd="{{ item.item.file }}/{{ item.item.initrd }}"
    {% if item.item.os_version is defined %}--os-version={{ item.item.os_version }}{% endif %}
    --arch={{ item.item.arch | quote }}
    --breed={{ item.item.breed }}
    --kopts="{{ item.item.kopts | default('') }}"
  when:
    item.rc != 0 and
    item.item.managed_by|default('') == ''
  with_items: distro_exists.results

- name: cobbler | populate | Add Profile
  become: yes
  shell: >
    cobbler profile report --name "{{ item[1].distro_id }}-{{ item[1].id }}" ||
    cobbler profile add
    --name="{{ item[1].distro_id }}-{{ item[1].id }}"
    --distro="{{ item[1].distro_id }}"
    --kickstart="/var/lib/cobbler/kickstarts/{{ item[0].item.kickstart }}-{{ item[1].id }}"
  when:
    "'{{ item[0].item.name }}-{{ item[0].item.arch }}' == '{{ item[1].distro_id }}'"
  with_nested:
      - distro_exists.results
      - bminfo.servers

- name: cobbler | populate | Check system exists in cobbler
  become: yes
  with_items: bminfo.servers
  command: cobbler system report --name={{ item.id | quote }}
  register: systems_exists
  changed_when: false
  failed_when: false

# I think we should probably assign the ip addresses here as static
# Need to get dhcp managed by cobbler
- name: cobbler | populate | Load servers into cobbler
  become: yes
  shell: >
    cobbler system add
    --name={{ item.item.id | quote }}
    --profile="{{ item.item.distro_id }}-{{ item.item.id }}"
    --ip-address={{ item.item.ip_addr | quote }}
    {% if item.item.distro_id | search('^hlinux') or
          item.item.distro_id | search('^rhel') %}
    --kopts="interface={{ item.item.mac_addr }} netcfg/dhcp_timeout={{ dhcp_timeout }} {{ item.item.kopt_extras | default('') }}"
    {% elif item.item.distro_id | search('^sles') %}
    --kopts="ifcfg={{ item.item.mac_addr }}=dhcp4,DHCLIENT_WAIT_AT_BOOT={{ dhcp_timeout }},WAIT_FOR_INTERFACES={{ dhcp_timeout }} {{ item.item.kopt_extras | default('') }}"
    {% endif %}
    --gateway={{ cobbler_gateway }}
    --mac={{ item.item.mac_addr | quote }}
    --interface={{ item.item.mac_addr | quote }}
    --hostname={{ item.item.id | quote }}
    --netboot-enabled=true
    --power-type=ipmitool
    --power-address={{ item.item.ilo_ip | quote }}
    --power-user="redacted"
    --power-pass="redacted"
  when: item.rc != 0 and bminfo.whoami != item.item.id
  with_items: systems_exists.results

- name: cobbler | populate | Cobbler sync
  become: yes
  command: cobbler sync

# WARNING: If you need to call cobbler sync again, files listed below need to be
# copied again to tftp dir, because cobbler sync will remove them.

# In Debian, pxelinux v6 needs additional loadable module which is not properly
# copied during cobbler sync. In SLES, pxelinux v4 does not require this module.
- name: cobbler | populate | Insert ldlinux.c32 file
  become: yes
  command: "cp -f /var/lib/cobbler/loaders/ldlinux.c32 {{ cobbler_tftp_dir }}/ldlinux.c32"
  when: ansible_os_family == 'Debian'

# grub/shim.efi.signed and grub/grub.cfg are needed for UEFI boot
- name: cobbler | populate | Insert shim.efi.signed file
  become: yes
  command: "cp -f /var/lib/cobbler/loaders/shim.efi.signed {{ cobbler_tftp_dir }}/grub"

# in SLES/OpenSUSE, cobbler puts invalid symlink for grub/grub.efi, where we need a hardcopy file
- name: cobbler | populate | Insert shim.efi.signed file
  become: yes
  command: "cp -f --remove-destination {{ cobbler_tftp_dir }}/grub/x86_64-efi/grub.efi {{ cobbler_tftp_dir }}/grub/grub.efi"
  when: cobbler_is_sles

- name: cobbler | populate | Insert grub.cfg file
  become: yes
  template:
    src: grub.cfg.j2
    dest: "{{ cobbler_tftp_dir }}/grub/grub.cfg"

# Seems we need the xinetd restart here
- name: cobbler | populate | Enable and restart xinetd
  become: yes
  service:
    name: xinetd
    state: restarted
    enabled: yes
07070100000045000081A400000000000000000000000162FCFEE100000478000000000000000000000000000000000000004E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/power-cycle.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | power-cycle | Check power status
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=status
  register: pstatus

- name: cobbler | power-cycle | Power cycle node if on
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=cycle sleep=1
  when: pstatus.power == "on"

- name: cobbler | power-cycle | Power up node if off
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=on sleep=1
  when: pstatus.power == "off"
07070100000046000081A400000000000000000000000162FCFEE1000003DB000000000000000000000000000000000000004D00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/power-down.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# We probably don't want to power down potentially hundreds of nodes in the
# data center in one go. For now we will simply pause between commands, but
# longer term we may need something more sophisticated.
- name: cobbler | power-down | Power the node down
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=off sleep=1
07070100000047000081A400000000000000000000000162FCFEE100000302000000000000000000000000000000000000004B00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/power-up.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | power-up | Power node up
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=on sleep=3
07070100000048000081A400000000000000000000000162FCFEE1000006B3000000000000000000000000000000000000005000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/reconfig-dhcp.yml#
# (c) Copyright 2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#

# --------------------------------------------------------------------------
# The name of the network interface that Cobbler is using will potentially
# change after the NIC Mappings are applied in osconfig-run. If that happens
# then the Cobbler DHCP configuration will be stale and we need to update it
# with the new name of that interface. The correct value has already been
# computed in set-vars and is available to us as "cobbler_server_interface".
---
- name: cobbler | reconfig-dhcp | am i running cobbler dhcp
  stat:
    path: /etc/init.d/isc-dhcp-server
  register: cobbler_dhcp_here_result

- name: cobbler | reconfig-dhcp | set interface name
  become: yes
  lineinfile:
    create: no
    dest: /etc/default/isc-dhcp-server
    regexp: ^INTERFACES=.*
    line: INTERFACES="{{ cobbler_server_interface }}"
  when: cobbler_dhcp_here_result.stat.exists
  register: cobbler_dhcp_changed_result

- name: cobbler | reconfig-dhcp | restart service
  become: yes
  service:
    name: isc-dhcp-server
    state: restarted
  when: cobbler_dhcp_changed_result | changed
07070100000049000081A400000000000000000000000162FCFEE10000080F000000000000000000000000000000000000004F00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/set-diskboot.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | set-diskboot | Set boot order to local disk
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} bootdev=disk options=persistent

# BUG 1484 Sending options=persistent to a node that is in UEFI mode
# will cause it to switch to Legacy BIOS on its next reset. We don't
# want that to happen, so send it options=efiboot to tell it that it's
# it's OK to stay in UEFI mode. Despite its name, this option means
# "stay in whatever boot mode you're in" so it is safe to send to
# Legacy nodes also i.e. it will not switch them to UEFI.
# Some older iLOs don't support this flag and will return an error.
- name: cobbler | set-diskboot | Get bios mode
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} passthru="mc info"
  register: my_result

- name: cobbler | set-diskboot | Get the oemhp_bootmode when HP ILO
  hpilo: name={{ inventory_hostname }} credsfile={{ baremetal_config }}
         command="show /system1/bootconfig1 oemhp_bootmode"
  register: oemhp_bootmode
  when: my_result.stdout | search("Hewlett-Packard")

- name: cobbler | set-diskboot | Make UEFI/Legacy mode sticky
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} bootdev=disk options=efiboot
  ignore_errors: True
  when: not my_result.stdout | search("Hewlett-Packard") or
        (my_result.stdout | search("Hewlett-Packard") and oemhp_bootmode.stdout | search("UEFI"))

0707010000004A000081A400000000000000000000000162FCFEE100000801000000000000000000000000000000000000004E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/set-pxeboot.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | set-pxeboot | Set boot order to PXE
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} bootdev=pxe options=persistent

# BUG 1484 Sending options=persistent to a node that is in UEFI mode
# will cause it to switch to Legacy BIOS on its next reset. We don't
# want that to happen, so send it options=efiboot to tell it that it's
# it's OK to stay in UEFI mode. Despite its name, this option means
# "stay in whatever boot mode you're in" so it is safe to send to
# Legacy nodes also i.e. it will not switch them to UEFI.
# Some older iLOs don't support this flag and will return an error.
- name: cobbler | set-pxeboot | Get bios mode
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} passthru="mc info"
  register: my_result

- name: cobbler | set-pxeboot | Get the oemhp_bootmode when HP ILO
  hpilo: name={{ inventory_hostname }} credsfile={{ baremetal_config }}
         command="show /system1/bootconfig1 oemhp_bootmode"
  register: oemhp_bootmode
  when: my_result.stdout | search("Hewlett-Packard")

- name: cobbler | set-pxeboot | Make UEFI/Legacy mode sticky
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} bootdev=pxe options=efiboot
  ignore_errors: True
  when: not my_result.stdout | search("Hewlett-Packard") or
        (my_result.stdout | search("Hewlett-Packard") and oemhp_bootmode.stdout | search("UEFI"))
0707010000004B000081A400000000000000000000000162FCFEE100000477000000000000000000000000000000000000005000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/set-rhel-vars.yml#
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- name: cobbler | set-rhel-vars | Set rhel vars for distro used via supported
        distro and bminfo servers data
  set_fact:
    rhel_profile_name: "{{ item[0].name }}"
    rhel_entry_name: "{{ item[0].entry_name }}"
    rhel_grub2_efi_rpm: "{{ item[0].grub2_efi_rpm }}"
    rhel_shim_rpm: "{{ item[0].rhel_shim_rpm }}"
  when:
    "'{{ item[0].name }}-{{ item[0].arch }}' == '{{ item[1].distro_id }}' and \
     {{ 'managed_by' in item[0] }} and \
     '{{ item[0].managed_by }}' == 'rhel'"
  with_nested:
      - remote_distros
      - bminfo.servers
0707010000004C000081A400000000000000000000000162FCFEE100000333000000000000000000000000000000000000005000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/set-sles-vars.yml#
# (c) Copyright 2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

# Set vars for SUSE repos
- include: check-sles-repos.yml
  vars:
    _input_repos_list: "{{ sles_expected_media_repos[sles_version_name] }}"
    _input_uri_pattern: "^dir\\:\\/\\/\\/srv\\/www\\/suse-{{ansible_distribution_version}}\\/"

0707010000004D000081A400000000000000000000000162FCFEE100000CEE000000000000000000000000000000000000004B00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/set-vars.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#

# This task uses the bminfo struct from get-baremetal-info.yml to derive a
# bunch of convenience variables that are used in various other plays. It then
# goes further and figures out the name of the network interface that Cobbler
# is using, by comparing the baremetal CIDR specified in the model with the
# actual values in "ip a" on localhost.

---
- include: get-baremetal-info.yml

- name: cobbler | set-vars | Set baremetal network subnet
  set_fact:
    cobbler_subnet: "{{ bminfo.network.subnet }}"
  when: cobbler_subnet is not defined

- name: cobbler | set-vars | Set baremetal network netmask
  set_fact:
    cobbler_netmask: "{{ bminfo.network.netmask }}"
  when: cobbler_netmask is not defined

- name: cobbler | set-vars | Set baremetal network cidr
  set_fact:
    cobbler_cidr: "{{ bminfo.network.cidr }}"
  when: cobbler_cidr is not defined

- name: cobbler | set-vars | List available nics
  local_action: shell ip a | awk '/^[0-9]/ { sub(":","",$2) ; iface=$2 } $1 == "inet"  || $1 == "inet6" {print iface, $2 }'
  register: _candidates
  when: cobbler_server_interface is not defined
  changed_when: false
  run_once: True

- name: cobbler | set-vars | Search for an ip interface on this cidr
  delegate_to: localhost
  netaddr-match-cidr:
    cidr: "{{ cobbler_cidr }}"
    ips: "{{ _candidates.stdout }}"
  register: _selected
  when: cobbler_server_interface is not defined
  run_once: True

# We want this in the log for debug purposes, in case it's wrong and needs manual override.
- debug: var=_selected
  when: _selected is defined

- name: cobbler | set-vars | Select this interface
  set_fact:
    cobbler_server_interface: "{{ _selected.stdout }}"
  when: cobbler_server_interface is not defined
  run_once: True

- name: cobbler | set-vars | Select ip address
  set_fact:
    cobbler_server_ip_addr: "{{ _selected.ip }}"
  when: cobbler_server_ip_addr is not defined
  run_once: True

# An override gateway  for CI
- name: cobbler | set-vars | Set baremetal network gateway
  set_fact:
    cobbler_gateway: "{{ cobbler_server_ip_addr }}"
  when: cobbler_gateway is not defined

# An override nameserver for CI
- name: cobbler | set-vars | Set baremetal network name server
  set_fact:
    cobbler_name_server: "{{ cobbler_server_ip_addr }}"
  when: cobbler_name_server is not defined

- name: cobbler | set-vars | Set local repo ip url
  set_fact:
    deployer_server: "http://{{ cobbler_server_ip_addr | ipwrap }}:{{ deployer_server_port }}"
  when: deployer_server is not defined

# Set vars for currently used rhel distro
- include: set-rhel-vars.yml

# Set vars for currently used SLES distro
- include: set-sles-vars.yml

0707010000004E000081A400000000000000000000000162FCFEE100000486000000000000000000000000000000000000004800000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/start.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- name: cobbler | start | Enable and restart dhcp service
  become: yes
  service: name={{ cobbler_dhcp_service_name }} state=restarted enabled=yes

- name:  cobbler | start | Enable and restart apache2
  become: yes
  service: name=apache2 state=restarted enabled=yes

- name: cobbler | start | Enable and restart cobblerd
  become: yes
  service: name=cobblerd state=restarted enabled=yes

- name: cobbler | start | Enable and restart xinetd
  become: yes
  service: name=xinetd state=restarted enabled=yes
0707010000004F000081A400000000000000000000000162FCFEE1000006F3000000000000000000000000000000000000005200000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/synchronize-iso.yml#
# (c) Copyright 2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---

- name: cobbler | synchronize-iso | Check if ISO exists
  stat:
    path: "{{ iso_src }}"
    get_checksum: no
    get_md5: no
  register: _iso_exists

- name: cobbler | synchronize-iso | Create temporary mount directory
  command: mktemp -d
  register: _mount_tmpdir
  when: _iso_exists.stat.exists

- name: cobbler | synchronize-iso | Mount ISO
  become: yes
  shell: |
    mount -o loop "{{ iso_src }}" "{{ _mount_tmpdir.stdout }}"
  when: _iso_exists.stat.exists

- name: cobbler | synchronize-iso | Create ISO destination
  become: yes
  file:
    path: "{{ iso_dest }}"
    state: directory
    mode: 0755
  when: _iso_exists.stat.exists

- name: cobbler | synchronize-iso | Synchronize ISO
  become: yes
  synchronize:
    src: "{{ _mount_tmpdir.stdout }}/"
    dest: "{{ iso_dest }}"
  when: _iso_exists.stat.exists

- name: cobbler | synchronize-iso | Umount ISO
  become: yes
  shell: |
    umount {{ _mount_tmpdir.stdout }}
  when: _iso_exists.stat.exists

- name: cobbler | synchronize-iso | Remove temporary mount directory
  file:
    path: "{{ _mount_tmpdir.stdout }}"
    state: absent
  when: _iso_exists.stat.exists

07070100000050000081A400000000000000000000000162FCFEE10000039F000000000000000000000000000000000000005300000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/target-all-nodes.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
# If the caller has already set target_nodes then we'll respect that.
- include: get-baremetal-info.yml

- name: cobbler | target-all-nodes | Compute generic target list
  set_fact: target_nodes="{{ bminfo.server_ids }}"
  when: target_nodes is undefined

- include: get-nodelist.yml
07070100000051000081A400000000000000000000000162FCFEE1000004BE000000000000000000000000000000000000005700000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/target-netboot-nodes.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
# If the caller has already set target_nodes then we'll respect that.

- name: cobbler | target-netboot-nodes | Compute the list of netboot nodes
  become: yes
  shell: cobbler system report | awk '/^Name *:/ {name=$NF} /^Netboot Enabled *. True/ {print name}' | sort -n
  register: netbootnodes
  when: target_nodes is undefined
  changed_when: false

- name: cobbler | target-netboot-nodes | Target the netboot nodes
  set_fact: target_nodes="{{ netbootnodes.stdout_lines }}"
  when: target_nodes is undefined and netbootnodes.stdout != ""

- include: get-nodelist.yml
07070100000052000081A400000000000000000000000162FCFEE100000643000000000000000000000000000000000000005400000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/update-signatures.yml#
# (c) Copyright 2020 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# Task list to update cobbler distro_signatures.json files if needed
---

- name: cobbler | update-signatures | Determine timestamp info for renames
  set_fact:
    rename_ts:
      date: "{{ ansible_date_time.date | replace('-', '') }}"
      time: "{{ ansible_date_time.time | replace(':', '') }}"
  run_once: true

- name: cobbler | update-signatures | Verify cobbler package
  command: >-
    rpm -V cobbler
  failed_when: false
  changed_when: false
  register: verify_distro_signatures_result

- name: cobbler | update-signatures | Move signature files aside if out-of-date
  become: yes
  shell: >-
    mv {{ item }} {{ item }}.{{ rename_ts.date }}{{ rename_ts.time }}
  register: rename_distro_signatures_result
  with_items: distro_signatures_files
  when:
    - item in verify_distro_signatures_result.stdout

- name: cobbler | update-signatures | Force a re-install of cobbler if needed
  become: yes
  command:
    zypper install --no-confirm --force cobbler
  when:
    - rename_distro_signatures_result | changed
07070100000053000081A400000000000000000000000162FCFEE100000441000000000000000000000000000000000000005400000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/verify-bm-install.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: vagrant-vm | verify-bm-install | Get md5sum
  local_action: shell md5sum {{ local_timestamp_file }} | awk '{print $1}'
  register: local_md5sum_data

- name: vagrant-vm | verify-bm-install | Stat baremetal install verification file
  become: yes
  shell: md5sum /etc/cobbler_ardana_installed | awk '{print $1}'
  register: remote_md5sum_data
  failed_when: remote_md5sum_data.stdout != local_md5sum_data.stdout
  changed_when: false
07070100000054000081A400000000000000000000000162FCFEE100000479000000000000000000000000000000000000005400000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/wait-for-shutdown.yml#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
- name: cobbler | wait-for-shutdown | Wait for nodes to power down after network install
  ipmi: name={{ inventory_hostname }} credsfile={{ baremetal_config }} power=status retries=8 delay=20
  register: pstate
  until: pstate | failed or pstate.power == "off"
  retries: "{{ off_poll_retries }}"
  delay: "{{ off_poll_seconds }}"
  failed_when: pstate | failed or pstate.power != "off"

- name: cobbler | wait-for-shutdown | Report any retries
  debug: msg="{{pstate.stdout}}"
  when: pstate.stdout != ""
07070100000055000081A400000000000000000000000162FCFEE100000757000000000000000000000000000000000000004F00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/tasks/wait-for-ssh.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
---
- name: cobbler | wait-for-ssh | Derive node ip
  local_action: bmconfig file={{ baremetal_config }} node={{ inventory_hostname }} field=ip_addr
  register: cobbler_ip

- name: cobbler | wait-for-ssh | Wait for ssh to come online
  local_action: wait_for port=22 host="{{ cobbler_ip.stdout }}" search_regex=OpenSSH timeout="{{ ssh_wait_seconds }}"

- name: cobbler | wait-for-ssh | Wait for pam_nologin module to cease
  local_action: |
    shell ssh -l {{ ardanauser }} -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null {{ cobbler_ip.stdout }} hostname
  register: remote_ssh_test_result
  until: remote_ssh_test_result.stderr.find("pam_nologin") == -1
  retries: 10
  delay: 5

- name: cobbler | wait-for-ssh | Get md5sum
  local_action: shell md5sum {{ local_timestamp_file }} | awk '{print $1}'
  register: local_md5sum_data

- name: cobbler | wait-for-ssh | check the timestamp on the dest with local
  local_action: |
    shell ssh -l {{ ardanauser }} -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null {{ cobbler_ip.stdout }} \
    md5sum /etc/cobbler_ardana_installed | awk '{print $1}'
  register: remote_md5sum_data
  failed_when: remote_md5sum_data.stdout != local_md5sum_data.stdout
07070100000056000041ED00000000000000000000000262FCFEE100000000000000000000000000000000000000000000004200000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates07070100000057000081A400000000000000000000000162FCFEE100000A2A000000000000000000000000000000000000005B00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/cobbler.dhcp.template.j2{#
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
#}
# ******************************************************************
# Cobbler managed dhcpd.conf file
#
# generated from cobbler dhcp.conf template ($date)
# Do NOT make changes to /etc/dhcpd.conf. Instead, make your changes
# in /etc/cobbler/dhcp.template, as /etc/dhcpd.conf will be
# overwritten.
#
# ******************************************************************

ddns-update-style interim;

allow booting;
allow bootp;

ignore client-updates;
set vendorclass = option vendor-class-identifier;

option pxe-system-type code 93 = unsigned integer 16;

subnet {{ cobbler_subnet }} netmask {{ cobbler_netmask }} {
     option routers             {{ cobbler_gateway }};
     option domain-name-servers {{ cobbler_name_server }};
     option subnet-mask         {{ cobbler_netmask }};
     deny unknown-clients;
     default-lease-time         21600;
     max-lease-time             43200;
     next-server                $next_server;
     class "pxeclients" {
          match if substring (option vendor-class-identifier, 0, 9) = "PXEClient";
          if option pxe-system-type = 00:02 {
                  filename "ia64/elilo.efi";
          } else if option pxe-system-type = 00:06 {
                  filename "grub/grub-x86.efi";
          } else if option pxe-system-type = 00:07 {
                  filename "grub/shim.efi.signed";
          } else {
                  filename "pxelinux.0";
          }
     }

}

#for dhcp_tag in $dhcp_tags.keys():
    ## group could be subnet if your dhcp tags line up with your subnets
    ## or really any valid dhcpd.conf construct ... if you only use the
    ## default dhcp tag in cobbler, the group block can be deleted for a
    ## flat configuration
# group for Cobbler DHCP tag: $dhcp_tag
group {
        #for mac in $dhcp_tags[$dhcp_tag].keys():
            #set iface = $dhcp_tags[$dhcp_tag][$mac]
    host $iface.name {
        hardware ethernet $mac;
        #if $iface.ip_address:
        fixed-address $iface.ip_address;
        #end if
        #if $iface.hostname:
        option host-name "$iface.hostname";
        #end if
        #if $iface.netmask:
        option subnet-mask $iface.netmask;
        #end if
        #if $iface.gateway:
        option routers $iface.gateway;
        #end if
        ## Cobbler defaults to $next_server, but some users
        ## may like to use $iface.system.server for proxied setups
        next-server $next_server;
        ## next-server $iface.next_server;
    }
        #end for
}
#end for

07070100000058000081A400000000000000000000000162FCFEE100000686000000000000000000000000000000000000005A00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/configure_network.sh.j2#!/bin/bash
{#
# (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#}
intf=$(ip addr | grep -v inet6 | awk '/scope global/ { print $NF }')
cidr=$(ip addr | grep -v inet6 | awk '/scope global/ {print $2}')
gateway=$(ip route | awk '/default/ {print $3}')

#Check for SLES
if [[ -e /etc/SuSE-release ]] || grep -qsi suse /etc/*-release
then
   intf=$(echo ${intf} | cut -d' ' -f1)
   cidr=$(echo ${cidr} | cut -d' ' -f1)

   cat > /etc/sysconfig/network/ifcfg-${intf} << EOF
BOOTPROTO='static'
BROADCAST=''
ETHTOOL_OPTIONS=''
IPADDR=${cidr}
MTU=''
REMOTE_IPADDR=''
STARTMODE='auto'
USERCONTROL='no'
EOF

else

   echo source "/etc/network/interfaces.d/*" > /etc/network/interfaces
   echo auto lo >> /etc/network/interfaces
   echo iface lo inet loopback >> /etc/network/interfaces
   echo auto ${intf}  > /etc/network/interfaces.d/${intf}
   echo iface ${intf} inet static >>  /etc/network/interfaces.d/${intf}
   echo address ${cidr} >>  /etc/network/interfaces.d/${intf}
   {% if enable_gateway %}
   echo gateway ${gateway} >> /etc/network/interfaces.d/${intf}
   {% endif %}

fi
07070100000059000081A400000000000000000000000162FCFEE1000002BB000000000000000000000000000000000000005C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/dhcpd-start-limit.conf.j2{#
#
# (c) Copyright 2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
#}
[Service]
StartLimitInterval={{ sles_dhcpd_start_limit_interval }}
StartLimitBurst={{ sles_dhcpd_start_limit_burst }}0707010000005A000081A400000000000000000000000162FCFEE1000003DC000000000000000000000000000000000000005000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/dhcpd.conf.j2{#
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
#}
option domain-name "deployer";

subnet {{ cobbler_subnet }} netmask {{ cobbler_netmask }}  {
    option subnet-mask {{ cobbler_netmask }};
    option routers {{ cobbler_gateway }};
    deny unknown-clients;
    option domain-name-servers {{ cobbler_gateway }};
    filename    "/pxelinux.0";
    next-server    {{ cobbler_server_ip_addr }};
}
0707010000005B000081A400000000000000000000000162FCFEE100000199000000000000000000000000000000000000004E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/grub.cfg.j2{#
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017,2018 SUSE LLC
#
#}
set default=0
loadfont /boot/grub/fonts/unicode.pf2
set gfxmode=auto
insmod efi_gop
insmod efi_uga
insmod gfxterm
insmod legacycfg
set locale_dir=/boot/grub/locale
set lang=en_US
set timeout=10
insmod gettext
terminal_output gfxterm

configfile=/grub/grub.cfg-01-$net_default_mac
source "$configfile"
0707010000005C000081A400000000000000000000000162FCFEE100000235000000000000000000000000000000000000004B00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/grub2.j2{#
#
# (c) Copyright 2016-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
#}
set timeout=5
menuentry '{{ rhel_entry_name }} Cobbler install' {
  linuxefi images/{{ rhel_profile_name }}-x86_64/vmlinuz interface={{ item.stdout }} inst.ks=http://{{ cobbler_server_ip_addr | ipwrap }}:79/cblr/svc/op/ks/system/{{ item.item }} inst.repo=http://{{ cobbler_server_ip_addr }}:79/cblr/ks_mirror/{{ rhel_profile_name }} inst.ks.sendmac inst.text ip=dhcp ksdevice=bootif lang=
  initrdefi images/{{ rhel_profile_name }}-x86_64/initrd.img
}
0707010000005D000081A400000000000000000000000162FCFEE100001C67000000000000000000000000000000000000005E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/hlinux-server-vm.preseed.j2{#
#
# (c) Copyright 2015-2016 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
#}
#Necessary to access the remote hlinux repo
# Will need to be change to point to local
d-i mirror/suite string {{ hlinux_distro }}
d-i mirror/udeb/suite string {{ hlinux_distro }}
{% if item[1].boot_from_san %}
disk-detect disk-detect/multipath/enable boolean true
{% endif %}

d-i mirror/protocol string http
d-i mirror/country string manual
d-i mirror/http/hostname string {{ deployer_server | replace('http://', '') }}
d-i mirror/http/hostname seen true
d-i mirror/http/directory string /{{ hlinux_path }}
d-i mirror/http/directory seen true
d-i mirror/codename string {{ hlinux_distro }}

#Ensure the Keyboard config is set ok
d-i debian-installer/locale string en_US.UTF-8
d-i keymap select us
d-i keyboard-configuration/xkb-keymap select us
d-i debian-installer/splash boolean false
d-i console-setup/ask_detect        boolean false
d-i console-setup/layoutcode        string us
d-i console-setup/variantcode       string
#May need to modify this for static assignment
d-i netcfg/get_nameservers  string
d-i netcfg/get_ipaddress    string
d-i netcfg/get_netmask      string {{ cobbler_netmask }}
d-i netcfg/get_gateway      string
d-i netcfg/dhcp_timeout     string 240
d-i netcfg/confirm_static   boolean true
d-i netcfg/hostname string ardana
#Do not attempt remote ntp config
d-i clock-setup/ntp boolean false
d-i time/zone string UTC
d-i clock-setup/utc boolean true
# The d-i netcfg/hostname string ardana does not appear to work
# The vgremove should be conditional - as should the rest of
# directives to blow away existing config
d-i partman/early_command string \
hostname ardana; \
echo ardana > /etc/hostname; \
vgremove -f ardana-vg; \
wget http://$http_server/preseed/configure_partitioning; \
sh ./configure_partitioning $http_server

d-i partman-auto/method string lvm
# Blow away without prejudice what was there previously
# May need to be a bit more conservative here for BM
# Also need to add more intelligence to the disk partitioning
{% if item[1].boot_from_san %}
d-i partman-auto/disk string {{ boot_from_san_root_device }}
{% else %}
d-i partman-auto/disk string {{ cobbler_root_device }}
{% endif %}

{% if item[1].persistent_interfaces | length > 0 %}
d-i netcfg/persistent_interfaces string {{ item[1].persistent_interfaces | join (", ") }}
{% endif %}

{% if (item[1].fcoe_interfaces) | length  > 0 %}
d-i partman-fcoe/interfaces string {{ item[1].fcoe_interfaces | join(',') }}
d-i disk-detect/fcoe/enable boolean true
{% endif %}

d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-lvm/device_remove_lvm_span boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-basicmethods/method_only boolean false
d-i partman-auto/choose_recipe select ardana-config
d-i partman-auto/expert_recipe_file string /partition_scheme
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman-md/confirm boolean true
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman-basicfilesystems/no_swap boolean false
d-i partman-basicfilesystems partman-basicfilesystems/no_mount_point boolean false
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/device_remove_lvm_span boolean true
d-i partman-lvm/confirm boolean true
d-i partman-lvm/confirm_nooverwrite boolean true
d-i partman-efi/non_efi_system  true

# Do not set up additional apt repos for now
d-i apt-setup/services-select multiselect
d-i apt-setup/security_host string
d-i base-installer/kernel/image     string linux-server
# Do not install any extra packages
tasksel    tasksel/first    multiselect    none
# Other than these specific ones
d-i pkgsel/include string dbus eject openssh-server rsync python python-apt hpssacli gdisk
d-i passwd/root-login       boolean false
d-i passwd/make-user        boolean true
d-i passwd/user-fullname    string {{ ardanauser }}
d-i passwd/username string {{ ardanauser }}
# Need to generate this on the fly
d-i passwd/user-password-crypted    password {{ ardanauser_password | password_hash('sha512') }}
d-i passwd/user-uid string
d-i user-setup/allow-password-weak  boolean false
d-i user-setup/encrypt-home boolean false
d-i debian-installer/allow_unauthenticated  string false
# The ssh key populate may need more review - ok for now
# The wget at the end is so that the net boot is turned off once installed
# as per cobbler pxe_just_once settings
d-i preseed/late_command string \
wget http://$http_server/preseed/timestamp;\
in-target touch /etc/cobbler_ardana_installed;\
cp ./timestamp /target/etc/cobbler_ardana_installed;\
in-target mkdir -p {{ ardanauser_home }}/.ssh;\
in-target chown {{ ardanauser }}:{{ ardanauser }} {{ ardanauser_home }}/.ssh;\
in-target chmod 700 {{ ardanauser_home }}/.ssh;\
echo "{{ deployer_ssh_pub_key }}" > /target/{{ ardanauser_home }}/.ssh/authorized_keys;\
in-target chown {{ ardanauser }}:{{ ardanauser }} {{ ardanauser_home }}/.ssh/authorized_keys;\
in-target sed -i "s,sudo[\t]ALL=(ALL:ALL) ALL,sudo ALL = (ALL) NOPASSWD: ALL,g" /etc/sudoers;\
{% if disable_pwd_auth == true %}
in-target sed -i "s,#PasswordAuthentication yes,PasswordAuthentication no,g" /etc/ssh/sshd_config;\
{% endif %}
umount /target/unused; \
lvremove -f /dev/ardana-vg/unused;\
in-target sed -i '/unused/d' /etc/fstab;\
wget http://$http_server/preseed/configure_network.sh; \
cp ./configure_network.sh /target/tmp;\
in-target bash /tmp/configure_network.sh ;\
in-target rm /tmp/configure_network.sh;\
wget http://$http_server/preseed/configure_kdump; \
cp ./configure_kdump /target/tmp;\
in-target bash /tmp/configure_kdump ;\
in-target rm /tmp/configure_kdump;\
sed -i "s,deb http,deb [arch=amd64] http,g" /target/etc/apt/sources.list;\
echo "deb [arch=i386] http://$http_server/ardana/cmc32 cattleprod main" >> /target/etc/apt/sources.list;\
in-target dpkg --add-architecture i386;\
in-target apt-get update;\
in-target rm /etc/resolv.conf;\
wget http://$http_server/preseed/bnx2x.conf;\
touch /target/etc/modprobe.d/bnx2x.conf;\
cp ./bnx2x.conf /target/etc/modprobe.d/bnx2x.conf;\
chmod 644 /target/etc/modprobe.d/bnx2x.conf;\
{% if (item[1].fcoe_interfaces) | length  > 0 %}
wget http://$http_server/preseed/update_fcoe_udev.py; \
/target/usr/bin/python ./update_fcoe_udev.py;\
in-target update-initramfs -k all -u ;\
{% endif %}
wget http://$http_server/cblr/svc/op/nopxe/system/$name
d-i pkgsel/update-policy    select none
{% if item[1].boot_from_san %}
d-i grub-installer/bootdev string {{ boot_from_san_root_device }}
{% else %}
d-i grub-installer/bootdev string {{ cobbler_root_device }}
{% endif %}
d-i grub-installer/skip     boolean false
d-i lilo-installer/skip     boolean false
d-i grub-installer/only_debian      boolean true
d-i grub-installer/with_other_os    boolean true
d-i finish-install/keep-consoles    boolean false
d-i finish-install/reboot_in_progress       note
d-i cdrom-detect/eject      boolean true
#d-i debian-installer/exit/halt  boolean true
# Power off machine at the end
d-i debian-installer/exit/poweroff  boolean true
0707010000005E000081A400000000000000000000000162FCFEE10000031E000000000000000000000000000000000000005500000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/isc-dhcp-server.j2{#
#
# (c) Copyright 2015 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017 SUSE LLC
#
#}
# Defaults for isc-dhcp-server initscript
# sourced by /etc/init.d/isc-dhcp-server
# installed at /etc/default/isc-dhcp-server by the maintainer scripts

#
# This is a POSIX shell fragment
#

# Path to dhcpd's config file (default: /etc/dhcp/dhcpd.conf).
#DHCPD_CONF=/etc/dhcp/dhcpd.conf

# Path to dhcpd's PID file (default: /var/run/dhcpd.pid).
#DHCPD_PID=/var/run/dhcpd.pid

# Additional options to start dhcpd with.
#       Don't use options -cf or -pf here; use DHCPD_CONF/ DHCPD_PID instead
#OPTIONS=""

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
INTERFACES="{{ cobbler_server_interface }}"
0707010000005F000081A400000000000000000000000162FCFEE100001BBB000000000000000000000000000000000000005C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/rhel75-anaconda-ks.cfg.j2#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
#version=DEVEL
# System authorization information
auth --enableshadow --passalgo=sha512
repo --name="Server-HighAvailability" --baseurl=file:///run/install/repo/addons/HighAvailability
repo --name="Server-ResilientStorage" --baseurl=file:///run/install/repo/addons/ResilientStorage

url --url=$tree

# Run the Setup Agent on first boot
firstboot --enable

# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'
# System language
lang en_US.utf8
# System timezone
timezone Etc/UTC --isUtc --nontp

# Misc
firewall --disabled

poweroff

# Network information
# Qlogic-FCOE: Uncomment the below lines if using qlogic fcoe boot from san
# Modify the interface names (ens1f2, ens1f3) if appropriate
# fcoe --nic=ens1f2 --autovlan
# fcoe --nic=ens1f3 --autovlan

# Root password
user --groups=wheel --name="{{ ardanauser }}" --password="{{ ardanauser_password | password_hash('sha512') }}" --homedir="{{ ardanauser_home }}" --iscrypted --gecos="{{ ardanauser }}"

# System bootloader configuration
bootloader --location=mbr --boot-drive={{ cobbler_root_device }}
zerombr

# TODO: Target only cobbler_root_device not all disks.
# ignoredisk --only-use={{ cobbler_root_device }}

# Blow away without prejudice what was there previously - same as we do on hLinux
clearpart --all --initlabel

# Disk partitioning information
#part biosboot --fstype="biosboot" --size=1
part /boot --fstype="ext3" --ondisk={{ cobbler_root_device }} --size=512
part /boot/efi --fstype="efi" --ondisk={{ cobbler_root_device }} --size=512
part pv.275 --fstype="lvmpv" --ondisk={{ cobbler_root_device }} --size=1 --grow
volgroup ardana-vg --pesize=4096 pv.275
logvol / --fstype="ext4" --name=root --vgname=ardana-vg --size=32000

%packages
@^minimal
@core
kexec-tools
dbus
eject
openssh-server
rsync
python
gdisk
wget

%end

%pre --log=/var/log/anaconda-pre.log --erroronfail
# Qlogic-FCOE: Uncomment the below lines if using qlogic fcoe boot from san
# Modify the interface names (ens1f2, ens1f3) if appropriate
# cat /proc/partitions
# ip link set ens1f2 up
# ip link set ens1f3 up
# modprobe 8021q
# modprobe fcoe
# fipvlan -c -s ens1f2
# fipvlan -c -s ens1f3
# cat /proc/partitions
# sleep 240
# cat /proc/partitions

set -eux
set -o pipefail

date
df -h
cat /proc/partitions
if which multipath ; then
    multipath -ll
fi

# record the "before" picture in the log file.
vgs
lvs
pvs
lsblk

if vgs | grep -w ardana-vg ; then
    # This is an old volume group that we inherited from a previous
    # install of the node. Wipe the filesystems on it and then remove.
    # It's important to remove the filesystems because otherwise they
    # will be rediscovered by lvcreate in osconfig and it'll ask if you
    # want to keep them - and hang because you can't answer. DEBUG 3431.
    vgreduce --debug --yes -ff --removemissing ardana-vg
    luns="`ls -l /dev/ardana-vg/ | awk 'NR > 1 {print $NF}' | tr '\n' ' '`"
    for lun in $luns
    do
        wipefs -af /dev/ardana-vg/$lun
        # belt and braces as wipefs is unreliable. use +e in case the
        # device is so small that we overrun the end.
        set +e
        dd if=/dev/zero of=/dev/ardana-vg/$lun bs=1048576 count=1000 oflag=direct
        dsize=`blockdev --getsz /dev/ardana-vg/$lun`
        (( seek_value = dsize*512/1048576 - 1000 ))
        dd if=/dev/zero of=/dev/ardana-vg/$lun bs=1048576 count=1000 seek=$seek_value oflag=direct
        set -e
    done
    devs="`pvs | awk '$2 == \"ardana-vg\" { print $1 }' | tr '\n' ' '`"
    lvremove --debug --yes -ff ardana-vg
    vgremove --debug --yes -ff ardana-vg
    for d in $devs
    do
        pvremove --debug --yes -ff $d
    done
    # record the "after" picture in the log file.
    vgs
    lvs
    pvs
    lsblk
fi
date
%end

# Instead of this we use the ip addr script below
# network --device=eth2 --bootproto=static --ip=192.168.10.8 --netmask=255.255.255.0

%post --log=/var/log/anaconda-post.log --erroronfail
set -eux
set -o pipefail

# Allow ssh from deployer
mkdir --mode=0700 {{ ardanauser_home }}/.ssh
chown {{ ardanauser }}:{{ ardanauser }} {{ ardanauser_home }}/.ssh
deployer_ssh_pub_key="{{ deployer_ssh_pub_key }}"
echo "$deployer_ssh_pub_key" > {{ ardanauser_home }}/.ssh/authorized_keys
chown {{ ardanauser }}:{{ ardanauser }} {{ ardanauser_home }}/.ssh/authorized_keys
chmod 0600 {{ ardanauser_home }}/.ssh/authorized_keys

systemctl disable NetworkManager

# Configure sudo to not require tty
sed -r -i "s,^(Defaults\s+requiretty),# \0," /etc/sudoers
sed -r -i "s,^(Defaults\s+\!visiblepw),# \0," /etc/sudoers

# In a nutshell we copy this from configure_network.sh.j2 but during RHEL kickstart
# all devices are marked as UP but have only the one configured by cobbler has an ip.
# So we have to do things slightly differently here.
ip addr
intf=`ip addr | grep -v inet6 | awk '/scope global/ { print $NF }'`
cidr=`ip addr | grep -v inet6 | awk '/scope global/ { print $2 }'`
intf=`echo ${intf} | cut -d' ' -f1`
cidr=`echo ${cidr} | cut -d' ' -f1`
ipaddr=`echo $cidr | awk -F/ '{ print $1 }'`
ipprefix=`echo $cidr | awk -F/ '{ print $2 }'`
gateway=`ip route | awk '/default/ { print $3 }'`
cat <<EOF | tee /etc/sysconfig/network-scripts/ifcfg-$intf
# Kickstart $intf initialization
TYPE=Ethernet
DEVICE=$intf
BOOTPROTO=none
IPADDR=$ipaddr
PREFIX=$ipprefix
ONBOOT=yes
EOF

# Enable passwordless sudo access for ardanauser
echo "{{ ardanauser }} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/{{ ardanauser }}
chmod 0440 /etc/sudoers.d/{{ ardanauser }}

{% if disable_pwd_auth == true %}
sed -i "s/^PasswordAuthentication yes/PasswordAuthentication no/g" /etc/ssh/sshd_config
{% endif %}

if [ -e /etc/yum/pluginconf.d/subscription-manager.conf ] ; then
    sed -i "s/enabled=1/enabled=0/g" /etc/yum/pluginconf.d/subscription-manager.conf
fi

# remove external yum repo definitions, if any
rm -f /etc/yum.repos.d/*.repo

$yum_config_stanza

# Anaconda will have configured the node to use the deployer as a gateway
# which is wrong. A correct version will be written later, in osconfig.
rm /etc/resolv.conf

# Configure bnx2x driver module options
curl http://$http_server/preseed/bnx2x.conf > /etc/modprobe.d/bnx2x.conf
chmod 0644 /etc/modprobe.d/bnx2x.conf

# Let Ardana know that we completed successfully.
curl http://$http_server/preseed/timestamp > /etc/cobbler_ardana_installed

# Let Cobbler know
curl http://$http_server/cblr/svc/op/nopxe/system/$name > /dev/null
%end

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end
07070100000060000081A400000000000000000000000162FCFEE100004D49000000000000000000000000000000000000004E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/settings.j2{#
#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
#}
#
---
# cobbler settings file
# restart cobblerd and run "cobbler sync" after making changes
# This config file is in YAML 1.0 format
# see http://yaml.org
# ==========================================================
# if 1, cobbler will allow insertions of system records that duplicate
# the --dns-name information of other system records.  In general,
# this is undesirable and should be left 0.
allow_duplicate_hostnames: 0

# if 1, cobbler will allow insertions of system records that duplicate
# the ip address information of other system records.  In general,
# this is undesirable and should be left 0.
allow_duplicate_ips: 0

# if 1, cobbler will allow insertions of system records that duplicate
# the mac address information of other system records.  In general,
# this is undesirable.
allow_duplicate_macs: 0

# if 1, cobbler will allow settings to be changed dynamically without
# a restart of the cobblerd daemon. You can only change this variable
# by manually editing the settings file, and you MUST restart cobblerd
# after changing it.
allow_dynamic_settings: 0

# by default, installs are *not* set to send installation logs to the cobbler
# # # server.  With 'anamon_enabled', kickstart templates may use the pre_anamon
# # # snippet to allow remote live monitoring of their installations from the
# # # cobbler server.  Installation logs will be stored under
# # # /var/log/cobbler/anamon/.  NOTE: This does allow an xmlrpc call to send logs
# # # to this directory, without authentication, so enable only if you are
# # # ok with this limitation.
anamon_enabled: 0

# If using authn_pam in the modules.conf, this can be configured
# to change the PAM service authentication will be tested against.
# The default value is "login".
authn_pam_service: "login"

# How long the authentication token is valid for, in seconds
auth_token_expiration: 3600

# Email out a report when cobbler finishes installing a system.
# enabled: set to 1 to turn this feature on
# sender: optional
# email: which addresses to email
# smtp_server: used to specify another server for an MTA
# subject: use the default subject unless overridden
build_reporting_enabled: 0
build_reporting_sender: ""
build_reporting_email: [ 'root@localhost' ]
build_reporting_smtp_server: "localhost"
build_reporting_subject: ""
build_reporting_ignorelist: [ "" ]

# Cheetah-language kickstart templates can import Python modules.
# while this is a useful feature, it is not safe to allow them to
# import anything they want. This whitelists which modules can be
# imported through Cheetah.  Users can expand this as needed but
# should never allow modules such as subprocess or those that
# allow access to the filesystem as Cheetah templates are evaluated
# by cobblerd as code.
cheetah_import_whitelist:
 - "random"
 - "re"
 - "time"

# Default createrepo_flags to use for new repositories. If you have
# createrepo >= 0.4.10, consider "-c cache --update -C", which can
# dramatically improve your "cobbler reposync" time.  "-s sha"
# enables working with Fedora repos from F11/F12 from EL-4 or
# EL-5 without python-hashlib installed (which is not available
# on EL-4)
createrepo_flags: "-c cache -s sha"

# if no kickstart is specified to profile add, use this template
default_kickstart: /var/lib/cobbler/kickstarts/default.ks

# configure all installed systems to use these nameservers by default
# unless defined differently in the profile.  For DHCP configurations
# you probably do /not/ want to supply this.
default_name_servers: []

# if using the authz_ownership module (see the Wiki), objects
# created without specifying an owner are assigned to this
# owner and/or group.  Can be a comma seperated list.
default_ownership:
 - "admin"

# cobbler has various sample kickstart templates stored
# in /var/lib/cobbler/kickstarts/.  This controls
# what install (root) password is set up for those
# systems that reference this variable.  The factory
# default is "cobbler" and cobbler check will warn if
# this is not changed.
# The simplest way to change the password is to run
# openssl passwd -1
# and put the output between the "" below.
default_password_crypted: "{{ cobbler_default_passwd }}"

# the default template type to use in the absence of any
# other detected template. If you do not specify the template
# with '#template=<template_type>' on the first line of your
# templates/snippets, cobbler will assume try to use the
# following template engine to parse the templates.
#
# Current valid values are: cheetah, jinja2
default_template_type: "cheetah"

# for libvirt based installs in koan, if no virt bridge
# is specified, which bridge do we try?  For EL 4/5 hosts
# this should be xenbr0, for all versions of Fedora, try
# "virbr0".  This can be overriden on a per-profile
# basis or at the koan command line though this saves
# typing to just set it here to the most common option.
default_virt_bridge: xenbr0

# use this as the default disk size for virt guests (GB)
default_virt_file_size: 5

# use this as the default memory size for virt guests (MB)
default_virt_ram: 512

# if koan is invoked without --virt-type and no virt-type
# is set on the profile/system, what virtualization type
# should be assumed?  Values: xenpv, xenfv, qemu, vmware
# (NOTE: this does not change what virt_type is chosen by import)
default_virt_type: xenpv

# enable gPXE booting? Enabling this option will cause cobbler
# to copy the undionly.kpxe file to the tftp root directory,
# and if a profile/system is configured to boot via gpxe it will
# chain load off pxelinux.0.
# Default: 0
enable_gpxe: 0

# controls whether cobbler will add each new profile entry to the default
# PXE boot menu.  This can be over-ridden on a per-profile
# basis when adding/editing profiles with --enable-menu=0/1.  Users
# should ordinarily leave this setting enabled unless they are concerned
# with accidental reinstalls from users who select an entry at the PXE
# boot menu.  Adding a password to the boot menus templates
# may also be a good solution to prevent unwanted reinstallations
enable_menu: 1

# enable Func-integration?  This makes sure each installed machine is set up
# to use func out of the box, which is a powerful way to script and control
# remote machines.
# Func lives at http://fedorahosted.org/func
# read more at https://github.com/cobbler/cobbler/wiki/Func-integration
# you will need to mirror Fedora/EPEL packages for this feature, so see
# https://github.com/cobbler/cobbler/wiki/Manage-yum-repos if you want cobbler
# to help you with this
func_auto_setup: 0
func_master: overlord.example.org

# change this port if Apache is not running plaintext on port
# 80.  Most people can leave this alone.
http_port: {{ deployer_server_port }}

# kernel options that should be present in every cobbler installation.
# kernel options can also be applied at the distro/profile/system
# level.
kernel_options:
 ksdevice: bootif
 lang: 'en_US'
 text: ~

# s390 systems require additional kernel options in addition to the
# above defaults
kernel_options_s390x:
 RUNKS: 1
 ramdisk_size: 40000
 root: /dev/ram0
 ro: ~
 ip: off
 vnc: ~

# configuration options if using the authn_ldap module. See the
# the Wiki for details.  This can be ignored if you are not using
# LDAP for WebUI/XMLRPC authentication.
ldap_server: "ldap.example.com"
ldap_base_dn: "DC=example,DC=com"
ldap_port: 389
ldap_tls: 1
ldap_anonymous_bind: 1
ldap_search_bind_dn: ''
ldap_search_passwd: ''
ldap_search_prefix: 'uid='
ldap_tls_cacertfile: ''
ldap_tls_keyfile: ''
ldap_tls_certfile: ''

# cobbler has a feature that allows for integration with config management
# systems such as Puppet.  The following parameters work in conjunction with
# --mgmt-classes  and are described in furhter detail at:
# https://github.com/cobbler/cobbler/wiki/Using-cobbler-with-a-configuration-management-system
mgmt_classes: []
mgmt_parameters:
 from_cobbler: 1

# if enabled, this setting ensures that puppet is installed during
# machine provision, a client certificate is generated and a
# certificate signing request is made with the puppet master server
puppet_auto_setup: 0

# when puppet starts on a system after installation it needs to have
# its certificate signed by the puppet master server. Enabling the
# following feature will ensure that the puppet server signs the
# certificate after installation if the puppet master server is
# running on the same machine as cobbler. This requires
# puppet_auto_setup above to be enabled
sign_puppet_certs_automatically: 0

# location of the puppet executable, used for revoking certificates
puppetca_path: "/usr/bin/puppet"

# when a puppet managed machine is reinstalled it is necessary to
# remove the puppet certificate from the puppet master server before a
# new certificate is signed (see above). Enabling the following
# feature will ensure that the certificate for the machine to be
# installed is removed from the puppet master server if the puppet
# master server is running on the same machine as cobbler. This
# requires puppet_auto_setup above to be enabled
remove_old_puppet_certs_automatically: 0

# choose a --server argument when running puppetd/puppet agent during kickstart
#puppet_server: 'puppet'

# let cobbler know that you're using a newer version of puppet
# choose version 3 to use: 'puppet agent'; version 2 uses status quo: 'puppetd'
#puppet_version: 2

# choose whether to enable puppet parameterized classes or not.
# puppet versions prior to 2.6.5 do not support parameters
#puppet_parameterized_classes: 1

# set to 1 to enable Cobbler's DHCP management features.
# the choice of DHCP management engine is in /etc/cobbler/modules.conf
manage_dhcp: 1

# set to 1 to enable Cobbler's DNS management features.
# the choice of DNS mangement engine is in /etc/cobbler/modules.conf
manage_dns: 0

# set to path of bind chroot to create bind-chroot compatible bind
# configuration files.  This should be automatically detected.
bind_chroot_path: ""

# set to the ip address of the master bind DNS server for creating secondary
# bind configuration files
bind_master: 127.0.0.1

# set to 1 to enable Cobbler's TFTP management features.
# the choice of TFTP mangement engine is in /etc/cobbler/modules.conf
manage_tftpd: 1

# set to 1 to enable Cobbler's RSYNC management features.
manage_rsync: 0

# if using BIND (named) for DNS management in /etc/cobbler/modules.conf
# and manage_dns is enabled (above), this lists which zones are managed
# See the Wiki (https://github.com/cobbler/cobbler/wiki/Dns-management) for more info
manage_forward_zones: []
manage_reverse_zones: []

# if using cobbler with manage_dhcp, put the IP address
# of the cobbler server here so that PXE booting guests can find it
# if you do not set this correctly, this will be manifested in TFTP open timeouts.
next_server: {{ cobbler_server_ip_addr }}

# settings for power management features.  optional.
# see https://github.com/cobbler/cobbler/wiki/Power-management to learn more
# choices (refer to codes.py):
#    apc_snmp bladecenter bullpap drac ether_wake ilo integrity
#    ipmilan ipmitool lpar rsa virsh wti
power_management_default_type: 'ipmitool'

# the commands used by the power management module are sourced
# from what directory?
power_template_dir: "/etc/cobbler/power"

# if this setting is set to 1, cobbler systems that pxe boot
# will request at the end of their installation to toggle the
# --netboot-enabled record in the cobbler system record.  This eliminates
# the potential for a PXE boot loop if the system is set to PXE
# first in it's BIOS order.  Enable this if PXE is first in your BIOS
# boot order, otherwise leave this disabled.   See the manpage
# for --netboot-enabled.
pxe_just_once: 1

# the templates used for PXE config generation are sourced
# from what directory?
pxe_template_dir: "/etc/cobbler/pxe"

# Path to where system consoles are
consoles: "/var/consoles"

# Are you using a Red Hat management platform in addition to Cobbler?
# Cobbler can help you register to it.  Choose one of the following:
#   "off"    : I'm not using Red Hat Network, Satellite, or Spacewalk
#   "hosted" : I'm using Red Hat Network
#   "site"   : I'm using Red Hat Satellite Server or Spacewalk
# You will also want to read: https://github.com/cobbler/cobbler/wiki/Tips-for-RHN
redhat_management_type: "off"

# if redhat_management_type is enabled, choose your server
#   "management.example.org" : For Satellite or Spacewalk
#   "xmlrpc.rhn.redhat.com"  : For Red Hat Network
# This setting is also used by the code that supports using Spacewalk/Satellite users/passwords
# within Cobbler Web and Cobbler XMLRPC.  Using RHN Hosted for this is not supported.
# This feature can be used even if redhat_management_type is off, you just have
# to have authn_spacewalk selected in modules.conf
redhat_management_server: "xmlrpc.rhn.redhat.com"

# specify the default Red Hat authorization key to use to register
# system.  If left blank, no registration will be attempted.  Similarly
# you can set the --redhat-management-key to blank on any system to
# keep it from trying to register.
redhat_management_key: ""

# if using authn_spacewalk in modules.conf to let cobbler authenticate
# against Satellite/Spacewalk's auth system, by default it will not allow per user
# access into Cobbler Web and Cobbler XMLRPC.
# in order to permit this, the following setting must be enabled HOWEVER
# doing so will permit all Spacewalk/Satellite users of certain types to edit all
# of cobbler's configuration.
# these roles are:  config_admin and org_admin
# users should turn this on only if they want this behavior and
# do not have a cross-multi-org seperation concern.  If you have
# a single org in your satellite, it's probably safe to turn this
# on and then you can use CobblerWeb alongside a Satellite install.
redhat_management_permissive: 0

# if set to 1, allows /usr/bin/cobbler-register (part of the koan package)
# to be used to remotely add new cobbler system records to cobbler.
# this effectively allows for registration of new hardware from system
# records.
register_new_installs: 0

# Flags to use for yum's reposync.  If your version of yum reposync
# does not support -l, you may need to remove that option.
reposync_flags: "-l -n -d"

# when DHCP and DNS management are enabled, cobbler sync can automatically
# restart those services to apply changes.  The exception for this is
# if using ISC for DHCP, then omapi eliminates the need for a restart.
# omapi, however, is experimental and not recommended for most configurations.
# If DHCP and DNS are going to be managed, but hosted on a box that
# is not on this server, disable restarts here and write some other
# script to ensure that the config files get copied/rsynced to the destination
# box.  This can be done by modifying the restart services trigger.
# Note that if manage_dhcp and manage_dns are disabled, the respective
# parameter will have no effect.  Most users should not need to change
# this.
restart_dns: 1
restart_dhcp: 1

# install triggers are scripts in /var/lib/cobbler/triggers/install
# that are triggered in kickstart pre and post sections.  Any
# executable script in those directories is run.  They can be used
# to send email or perform other actions.  They are currently
# run as root so if you do not need this functionality you can
# disable it, though this will also disable "cobbler status" which
# uses a logging trigger to audit install progress.
run_install_triggers: 1

# enables a trigger which version controls all changes to /var/lib/cobbler
# when add, edit, or sync events are performed.  This can be used
# to revert to previous database versions, generate RSS feeds, or for
# other auditing or backup purposes. "git" and "hg" are currently suported,
# but git is the recommend SCM for use with this feature.
scm_track_enabled: 0
scm_track_mode: "git"

# this is the address of the cobbler server -- as it is used
# by systems during the install process, it must be the address
# or hostname of the system as those systems can see the server.
# if you have a server that appears differently to different subnets
# (dual homed, etc), you need to read the --server-override section
# of the manpage for how that works.
server: {{ cobbler_server_ip_addr }}

# If set to 1, all commands will be forced to use the localhost address
# instead of using the above value which can force commands like
# cobbler sync to open a connection to a remote address if one is in the
# configuration and would traceback.
client_use_localhost: 0

# If set to 1, all commands to the API (not directly to the XMLRPC
# server) will go over HTTPS instead of plaintext. Be sure to change
# the http_port setting to the correct value for the web server
client_use_https: 0

# this is a directory of files that cobbler uses to make
# templating easier.  See the Wiki for more information.  Changing
# this directory should not be required.
snippetsdir: /var/lib/cobbler/snippets

# Normally if a kickstart is specified at a remote location, this
# URL will be passed directly to the kickstarting system, thus bypassing
# the usual snippet templating Cobbler does for local kickstart files. If
# this option is enabled, Cobbler will fetch the file contents internally
# and serve a templated version of the file to the client.
template_remote_kickstarts: 0

# should new profiles for virtual machines default to auto booting with the physical host when the physical host reboots?
# this can be overridden on each profile or system object.
virt_auto_boot: 1

# cobbler's web directory.  Don't change this setting -- see the
# Wiki on "relocating your cobbler install" if your /var partition
# is not large enough.
webdir: /srv/www/cobbler

# cobbler's public XMLRPC listens on this port.  Change this only
# if absolutely needed, as you'll have to start supplying a new
# port option to koan if it is not the default.
xmlrpc_port: 25151

# "cobbler repo add" commands set cobbler up with repository
# information that can be used during kickstart and is automatically
# set up in the cobbler kickstart templates.  By default, these
# are only available at install time.  To make these repositories
# usable on installed systems (since cobbler makes a very convient)
# mirror, set this to 1.  Most users can safely set this to 1.  Users
# who have a dual homed cobbler server, or are installing laptops that
# will not always have access to the cobbler server may wish to leave
# this as 0.  In that case, the cobbler mirrored yum repos are still
# accessable at http://cobbler.example.org/cblr/repo_mirror and yum
# configuration can still be done manually.  This is just a shortcut.
yum_post_install_mirror: 1

# the default yum priority for all the distros.  This is only used
# if yum-priorities plugin is used.  1=maximum.  Tweak with caution.
yum_distro_priority: 1

# Flags to use for yumdownloader.  Not all versions may support
# --resolve.
yumdownloader_flags: "--resolve"

# sort and indent JSON output to make it more human-readable
serializer_pretty_json: 0

# replication rsync options for distros, kickstarts, snippets set to override default value of "-avzH"
replicate_rsync_options: "-avzH"

# replication rsync options for repos set to override default value of "-avzH"
replicate_repo_rsync_options: "-avzH"

# always write DHCP entries, regardless if netboot is enabled
always_write_dhcp_entries: 0

# external proxy - used by: get-loaders, reposync, signature update
# eg: proxy_url_ext: "http://192.168.1.1:8080"

# internal proxy - used by systems to reach cobbler for kickstarts
# eg: proxy_url_int: "http://10.0.0.1:8080"
proxy_url_int:
07070100000061000081A400000000000000000000000162FCFEE1000001AA000000000000000000000000000000000000005000000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/sles.grub2.j2{#
#
# (c) Copyright 2017,2018 SUSE LLC
#
#}
set timeout=5
menuentry 'SLES 12 SP4 Cobbler install' {
  linuxefi images/{{ sles_version_name }}-x86_64/linux ifcfg={{ item.stdout }}=dhcp install=http://{{ cobbler_server_ip_addr | ipwrap }}:79/cblr/ks_mirror/{{ sles_version_name }} AutoYaST2=http://{{ cobbler_server_ip_addr }}:79/cblr/svc/op/ks/system/{{ item.item }}
  initrdefi images/{{ sles_version_name }}-x86_64/initrd
}
07070100000062000081A400000000000000000000000162FCFEE100001CDF000000000000000000000000000000000000005C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/sles12sp3-autoyast.xml.j2{#
# (c) Copyright 2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#}
<?xml version="1.0"?>
<!DOCTYPE profile>
<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns">
  <deploy_image>
    <image_installation config:type="boolean">false</image_installation>
  </deploy_image>
  <language>
    <language>en_US</language>
    <languages>en_GB,de_DE</languages>
  </language>
  <general>
    <mode>
      <confirm config:type="boolean">false</confirm>
      <final_halt config:type="boolean">false</final_halt>
      <final_reboot config:type="boolean">false</final_reboot>
      <halt config:type="boolean">true</halt>
      <second_stage config:type="boolean">false</second_stage>
    </mode>
    <signature-handling>
      <accept_file_without_checksum config:type="boolean">false</accept_file_without_checksum>
      <accept_non_trusted_gpg_key config:type="boolean">false</accept_non_trusted_gpg_key>
      <accept_unknown_gpg_key config:type="boolean">false</accept_unknown_gpg_key>
      <accept_unsigned_file config:type="boolean">false</accept_unsigned_file>
      <accept_verification_failed config:type="boolean">false</accept_verification_failed>
      <import_gpg_key config:type="boolean">false</import_gpg_key>
    </signature-handling>
    <storage/>
  </general>
{% if sles_configured_media_repos | length > 0 %}
  <add-on>
    <add_on_products config:type="list">
{% for m_repo in sles_configured_media_repos %}
      <listentry>
        <name>{{ m_repo.name }}</name>
        <product>{{ m_repo.name }}</product>
        <media_url>{{ deployer_server }}/SUSE-12-3/{{ ansible_architecture }}/repos/{{ m_repo.alias }}</media_url>
        <priority>{{ m_repo.priority | default('99', true) | int }}</priority>
        <ask_on_error config:type="boolean">{{ m_repo.ask_on_error | default('False', true) | bool }}</ask_on_error>
        <alias>{{ m_repo.alias }}</alias>
      </listentry>
{% endfor %}
    </add_on_products>
  </add-on>
{% endif %}
  <software>
    <install_recommended config:type="boolean">true</install_recommended>
    <packages config:type="list">
      <package>cron</package>
      <package>dracut</package>
      <package>gcc</package>
      <package>gptfdisk</package>
      <package>iputils</package>
      <package>kdump</package>
      <package>kernel-firmware</package>
      <package>kexec-tools</package>
      <package>man</package>
      <package>openssh</package>
      <package>python</package>
      <package>python-xml</package>
      <package>rsync</package>
      <package>rsyslog</package>
      <package>sudo</package>
      <package>util-linux</package>
    </packages>
  </software>
  <kdump>
    <add_crash_kernel config:type="boolean">true</add_crash_kernel>
    <crash_kernel config:type="list">
      <listentry>128M,low</listentry>
      <listentry>768M,high</listentry>
    </crash_kernel>
  </kdump>
  <networking>
    <interfaces config:type="list">
      <interface>
        <bootproto>dhcp</bootproto>
        <device>eth0</device>
        <dhclient_set_default_route>no</dhclient_set_default_route>
        <dhclient_set_hostname>no</dhclient_set_hostname>
        <startmode>auto</startmode>
      </interface>
    </interfaces>
    <ipv6 config:type="boolean">true</ipv6>
    <keep_install_network config:type="boolean">true</keep_install_network>
    <managed config:type="boolean">false</managed>
    <routing>
      <ipv4_forward config:type="boolean">false</ipv4_forward>
      <ipv6_forward config:type="boolean">false</ipv6_forward>
    </routing>
  </networking>
  <partitioning config:type="list">
    <drive>
      <device>{{ cobbler_root_device }}</device>
      <disklabel>gpt</disklabel>
      <initialize config:type="boolean">true</initialize>
      <partitions config:type="list">
        <partition>
          <create config:type="boolean">true</create>
          <format config:type="boolean">true</format>
          <filesystem config:type="symbol">ext4</filesystem>
          <mount>/boot</mount>
          <size>250M</size>
        </partition>
        <partition>
          <create config:type="boolean">true</create>
          <format config:type="boolean">true</format>
          <filesystem config:type="symbol">vfat</filesystem>
          <mount>/boot/efi</mount>
          <size>250M</size>
        </partition>
        <partition>
          <lvm_group>ardana-vg</lvm_group>
        </partition>
      </partitions>
      <type config:type="symbol">CT_DISK</type>
      <use>all</use>
    </drive>
    <drive>
      <device>/dev/ardana-vg</device>
      <partitions config:type="list">
        <partition>
          <create config:type="boolean">true</create>
          <format config:type="boolean">true</format>
          <filesystem config:type="symbol">ext4</filesystem>
          <lv_name>root</lv_name>
          <mount>/</mount>
          <size>30G</size>
        </partition>
      </partitions>
      <type config:type="symbol">CT_LVM</type>
      <use>all</use>
    </drive>
  </partitioning>
  <scripts>
    <init-scripts config:type="list">
      <script>
        <filename>autoyast-init-scripts-0.sh</filename>
        <source><![CDATA[
            systemctl enable sshd kdump rsyslog
            systemctl start sshd
        ]]></source>
      </script>
      <script>
        <filename>autoyast-init-scripts-1.sh</filename>
        <source><![CDATA[
# check network
IP=`echo "$http_server" | sed 's/:.*//'`
COUNTER=60
until ping -c1 "$IP" 2>&1 >/dev/null || [ $COUNTER -lt 1 ]; do sleep 1; let COUNTER-=1; done

# set flag
wget http://$http_server/preseed/timestamp -O /etc/cobbler_ardana_installed

# ardanauser access
mkdir -p {{ ardanauser_home }}/.ssh
echo "{{ deployer_ssh_pub_key }}" > {{ ardanauser_home }}/.ssh/authorized_keys
chown -R {{ ardanauser }}:{{ ardanauser }} {{ ardanauser_home }}/.ssh
chmod 0700 {{ ardanauser_home }}/.ssh
chmod 0600 {{ ardanauser_home }}/.ssh/authorized_keys

# sudo
dest=/etc/sudoers
sed -i "s,sudo[\t]ALL=(ALL:ALL) ALL,sudo ALL = (ALL) NOPASSWD: ALL,g" $dest
line="%sudo ALL = (ALL) NOPASSWD: ALL"
r=`grep "$line" $dest`
if [ -z "$r" ]; then
  echo >> $dest
  echo "# Allow members of group sudo to execute any command" >> $dest
  echo $line >> $dest
fi

{% if disable_pwd_auth == true %}
# SSH
sed -i "s,#PasswordAuthentication yes,PasswordAuthentication no,g" /etc/ssh/sshd_config
{% endif %}

rm /etc/resolv.conf

wget http://$http_server/preseed/bnx2x.conf -O /etc/modprobe.d/bnx2x.conf
chmod 644 /etc/modprobe.d/bnx2x.conf

wget http://$http_server/preseed/configure_network.sh -O  /tmp/configure_network.sh
bash /tmp/configure_network.sh
rm /tmp/configure_network.sh
        ]]></source>
      </script>
    </init-scripts>
  </scripts>
  <groups config:type="list">
    <group>
      <groupname>sudo</groupname>
      <gid>1000</gid>
      <userlist>{{ ardanauser }}</userlist>
    </group>
    <group>
      <groupname>{{ ardanauser }}</groupname>
      <gid>1001</gid>
      <userlist>{{ ardanauser }}</userlist>
    </group>
  </groups>
  <users config:type="list">
    <user>
      <username>{{ ardanauser }}</username>
      <gid>1001</gid>
      <user_password>{{ ardanauser_password | password_hash('sha512') }}</user_password><encrypted config:type="boolean">true</encrypted>
      <home>{{ ardanauser_home }}</home>
    </user>
  </users>
</profile>
07070100000063000081A400000000000000000000000162FCFEE100001CDF000000000000000000000000000000000000005C00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/sles12sp4-autoyast.xml.j2{#
# (c) Copyright 2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#}
<?xml version="1.0"?>
<!DOCTYPE profile>
<profile xmlns="http://www.suse.com/1.0/yast2ns" xmlns:config="http://www.suse.com/1.0/configns">
  <deploy_image>
    <image_installation config:type="boolean">false</image_installation>
  </deploy_image>
  <language>
    <language>en_US</language>
    <languages>en_GB,de_DE</languages>
  </language>
  <general>
    <mode>
      <confirm config:type="boolean">false</confirm>
      <final_halt config:type="boolean">false</final_halt>
      <final_reboot config:type="boolean">false</final_reboot>
      <halt config:type="boolean">true</halt>
      <second_stage config:type="boolean">false</second_stage>
    </mode>
    <signature-handling>
      <accept_file_without_checksum config:type="boolean">false</accept_file_without_checksum>
      <accept_non_trusted_gpg_key config:type="boolean">false</accept_non_trusted_gpg_key>
      <accept_unknown_gpg_key config:type="boolean">false</accept_unknown_gpg_key>
      <accept_unsigned_file config:type="boolean">false</accept_unsigned_file>
      <accept_verification_failed config:type="boolean">false</accept_verification_failed>
      <import_gpg_key config:type="boolean">false</import_gpg_key>
    </signature-handling>
    <storage/>
  </general>
{% if sles_configured_media_repos | length > 0 %}
  <add-on>
    <add_on_products config:type="list">
{% for m_repo in sles_configured_media_repos %}
      <listentry>
        <name>{{ m_repo.name }}</name>
        <product>{{ m_repo.name }}</product>
        <media_url>{{ deployer_server }}/SUSE-12-4/{{ ansible_architecture }}/repos/{{ m_repo.alias }}</media_url>
        <priority>{{ m_repo.priority | default('99', true) | int }}</priority>
        <ask_on_error config:type="boolean">{{ m_repo.ask_on_error | default('False', true) | bool }}</ask_on_error>
        <alias>{{ m_repo.alias }}</alias>
      </listentry>
{% endfor %}
    </add_on_products>
  </add-on>
{% endif %}
  <software>
    <install_recommended config:type="boolean">true</install_recommended>
    <packages config:type="list">
      <package>cron</package>
      <package>dracut</package>
      <package>gcc</package>
      <package>gptfdisk</package>
      <package>iputils</package>
      <package>kdump</package>
      <package>kernel-firmware</package>
      <package>kexec-tools</package>
      <package>man</package>
      <package>openssh</package>
      <package>python</package>
      <package>python-xml</package>
      <package>rsync</package>
      <package>rsyslog</package>
      <package>sudo</package>
      <package>util-linux</package>
    </packages>
  </software>
  <kdump>
    <add_crash_kernel config:type="boolean">true</add_crash_kernel>
    <crash_kernel config:type="list">
      <listentry>128M,low</listentry>
      <listentry>768M,high</listentry>
    </crash_kernel>
  </kdump>
  <networking>
    <interfaces config:type="list">
      <interface>
        <bootproto>dhcp</bootproto>
        <device>eth0</device>
        <dhclient_set_default_route>no</dhclient_set_default_route>
        <dhclient_set_hostname>no</dhclient_set_hostname>
        <startmode>auto</startmode>
      </interface>
    </interfaces>
    <ipv6 config:type="boolean">true</ipv6>
    <keep_install_network config:type="boolean">true</keep_install_network>
    <managed config:type="boolean">false</managed>
    <routing>
      <ipv4_forward config:type="boolean">false</ipv4_forward>
      <ipv6_forward config:type="boolean">false</ipv6_forward>
    </routing>
  </networking>
  <partitioning config:type="list">
    <drive>
      <device>{{ cobbler_root_device }}</device>
      <disklabel>gpt</disklabel>
      <initialize config:type="boolean">true</initialize>
      <partitions config:type="list">
        <partition>
          <create config:type="boolean">true</create>
          <format config:type="boolean">true</format>
          <filesystem config:type="symbol">ext4</filesystem>
          <mount>/boot</mount>
          <size>250M</size>
        </partition>
        <partition>
          <create config:type="boolean">true</create>
          <format config:type="boolean">true</format>
          <filesystem config:type="symbol">vfat</filesystem>
          <mount>/boot/efi</mount>
          <size>250M</size>
        </partition>
        <partition>
          <lvm_group>ardana-vg</lvm_group>
        </partition>
      </partitions>
      <type config:type="symbol">CT_DISK</type>
      <use>all</use>
    </drive>
    <drive>
      <device>/dev/ardana-vg</device>
      <partitions config:type="list">
        <partition>
          <create config:type="boolean">true</create>
          <format config:type="boolean">true</format>
          <filesystem config:type="symbol">ext4</filesystem>
          <lv_name>root</lv_name>
          <mount>/</mount>
          <size>30G</size>
        </partition>
      </partitions>
      <type config:type="symbol">CT_LVM</type>
      <use>all</use>
    </drive>
  </partitioning>
  <scripts>
    <init-scripts config:type="list">
      <script>
        <filename>autoyast-init-scripts-0.sh</filename>
        <source><![CDATA[
            systemctl enable sshd kdump rsyslog
            systemctl start sshd
        ]]></source>
      </script>
      <script>
        <filename>autoyast-init-scripts-1.sh</filename>
        <source><![CDATA[
# check network
IP=`echo "$http_server" | sed 's/:.*//'`
COUNTER=60
until ping -c1 "$IP" 2>&1 >/dev/null || [ $COUNTER -lt 1 ]; do sleep 1; let COUNTER-=1; done

# set flag
wget http://$http_server/preseed/timestamp -O /etc/cobbler_ardana_installed

# ardanauser access
mkdir -p {{ ardanauser_home }}/.ssh
echo "{{ deployer_ssh_pub_key }}" > {{ ardanauser_home }}/.ssh/authorized_keys
chown -R {{ ardanauser }}:{{ ardanauser }} {{ ardanauser_home }}/.ssh
chmod 0700 {{ ardanauser_home }}/.ssh
chmod 0600 {{ ardanauser_home }}/.ssh/authorized_keys

# sudo
dest=/etc/sudoers
sed -i "s,sudo[\t]ALL=(ALL:ALL) ALL,sudo ALL = (ALL) NOPASSWD: ALL,g" $dest
line="%sudo ALL = (ALL) NOPASSWD: ALL"
r=`grep "$line" $dest`
if [ -z "$r" ]; then
  echo >> $dest
  echo "# Allow members of group sudo to execute any command" >> $dest
  echo $line >> $dest
fi

{% if disable_pwd_auth == true %}
# SSH
sed -i "s,#PasswordAuthentication yes,PasswordAuthentication no,g" /etc/ssh/sshd_config
{% endif %}

rm /etc/resolv.conf

wget http://$http_server/preseed/bnx2x.conf -O /etc/modprobe.d/bnx2x.conf
chmod 644 /etc/modprobe.d/bnx2x.conf

wget http://$http_server/preseed/configure_network.sh -O  /tmp/configure_network.sh
bash /tmp/configure_network.sh
rm /tmp/configure_network.sh
        ]]></source>
      </script>
    </init-scripts>
  </scripts>
  <groups config:type="list">
    <group>
      <groupname>sudo</groupname>
      <gid>1000</gid>
      <userlist>{{ ardanauser }}</userlist>
    </group>
    <group>
      <groupname>{{ ardanauser }}</groupname>
      <gid>1001</gid>
      <userlist>{{ ardanauser }}</userlist>
    </group>
  </groups>
  <users config:type="list">
    <user>
      <username>{{ ardanauser }}</username>
      <gid>1001</gid>
      <user_password>{{ ardanauser_password | password_hash('sha512') }}</user_password><encrypted config:type="boolean">true</encrypted>
      <home>{{ ardanauser_home }}</home>
    </user>
  </users>
</profile>
07070100000064000081A400000000000000000000000162FCFEE100000332000000000000000000000000000000000000004E00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/templates/srv.conf.j2{#
#
# (c) Copyright 2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
#}
<Directory /srv/www/cobbler>
    Require all granted
</Directory>

Alias /preseed /srv/www/preseed

<Directory "/srv/www/preseed">
    Require all granted
</Directory>
07070100000065000041ED00000000000000000000000262FCFEE100000000000000000000000000000000000000000000003D00000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/vars07070100000066000081A400000000000000000000000162FCFEE10000075E000000000000000000000000000000000000004800000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/vars/debian.yml#
# (c) Copyright 2015-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#

# This task uses the bminfo struct from get-baremetal-info.yml to derive a
# bunch of convenience variables that are used in various other plays. It then
# goes further and figures out the name of the network interface that Cobbler
# is using, by comparing the baremetal CIDR specified in the model with the
# actual values in "ip a" on localhost.

cobbler_is_sles: False

cobbler_remove_packages:
  - atftpd

cobbler_install_packages:
  - python-jsonschema
  - python-yaml
  - cobbler
  - syslinux-common
  - debian-installer-8-netboot-amd64
  - tftpd-hpa
  - xinetd
  - fence-agents
  - ipmitool
  - shim-signed
  - grub-efi-amd64-signed

cobbler_tftp_service_name: tftpd-hpa
cobbler_dhcp_package_name: isc-dhcp-server
cobbler_dhcp_service_name: isc-dhcp-server
cobbler_dhcp_config_file: /etc/dhcp/dhcpd.conf
cobbler_bootloader_sources:
  - { src: "/usr/lib/syslinux/modules/bios/menu.c32", filename: "menu.c32" }
  - { src: "/usr/lib/debian-installer/images/8/amd64/gtk/pxelinux.0", filename: "pxelinux.0" }
  - { src: "/usr/lib/debian-installer/images/8/amd64/gtk/ldlinux.c32", filename: "ldlinux.c32" }
  - { src: "/usr/lib/shim/shim.efi.signed", filename: "shim.efi.signed" }
  - { src: "/usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed", filename: "grubx64.efi" }
cobbler_tftp_dir: /srv/tftp
07070100000067000081A400000000000000000000000162FCFEE10000073C000000000000000000000000000000000000004600000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/vars/main.yml#
# (c) Copyright 2015-2017 Hewlett Packard Enterprise Development LP
# (c) Copyright 2017-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#

# Specify variables for the cobbler environment

# User to create on managed node
ardanauser: "{{ ansible_env['USER'] }}"
# User home folder on managed node
ardanauser_home: "{{ ansible_env['HOME'] }}"
# Local folder on deployer, where RHEL and SLES artifacts are expected to be
ardanauser_deployer_home: "{{ ansible_env['HOME'] }}"

# The new default is to expect baremetal information inline in servers.yml
baremetal_config: "{{ playbook_dir }}/../../my_cloud/definition/data/servers.yml"
ansible_setup_bin_dir: "/usr/bin/"
bm_schema_base_dir: "{{ 'config-processor' | share_dir }}"
bm_schema_path: "/ardana-config-processor/Data/Site/Schema/2.0/server.yml"

iso_dir: /srv/www/cobbler/iso
cobbler_root_device: /dev/sda
boot_from_san_root_device: /dev/mapper/mpatha
disable_pwd_auth: true

off_poll_seconds: 15
off_poll_retries: 150

ssh_wait_seconds: 1500

hlinux_server_port: 79
deployer_server_port: "{{ hlinux_server_port }}"
hlinux_path: "ardana/hlinux"
suse_path: "ardana/suse"
hlinux_url: "{{ deployer_server }}/{{ hlinux_path }}"
suse_url: "{{ deployer_server }}/{{ suse_path }}"

dhcp_timeout: 240

local_timestamp_file: "/srv/www/preseed/timestamp"

set_bootdev: true

enable_gateway: false
07070100000068000081A400000000000000000000000162FCFEE100000615000000000000000000000000000000000000004600000000ardana-cobbler-9.0+git.1660747489.119efcd/roles/cobbler/vars/suse.yml#
# (c) Copyright 2015-2018 SUSE LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#

# This task uses the bminfo struct from get-baremetal-info.yml to derive a
# bunch of convenience variables that are used in various other plays. It then
# goes further and figures out the name of the network interface that Cobbler
# is using, by comparing the baremetal CIDR specified in the model with the
# actual values in "ip a" on localhost.

cobbler_is_sles: True

cobbler_remove_packages:
  - atftp

cobbler_install_packages:
  - tftp
  - cobbler
  - xinetd
  - dhcp-server
  - syslinux
  - shim
  - python-jsonschema
  - python-passlib
  - python-pexpect

cobbler_tftp_service_name: tftp
cobbler_dhcp_package_name: dhcp-server
cobbler_dhcp_service_name: dhcpd
cobbler_dhcp_config_file: /etc/dhcpd.conf
cobbler_bootloader_sources:
  - { src: "/usr/share/syslinux/menu.c32", filename: "menu.c32" }
  - { src: "/usr/share/syslinux/pxelinux.0", filename: "pxelinux.0" }
  - { src: "/usr/lib64/efi/shim.efi", filename: "shim.efi.signed" }
cobbler_tftp_dir: /srv/tftpboot
07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!566 blocks
openSUSE Build Service is sponsored by