HewlettPackard / oneview-ansible-collection

Ansible Collection and Sample Playbooks for HPE OneView

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Suspected bug with oneview_server_profile when using state: compliant

liamwh opened this issue · comments

Am trying to idempotently ensure OneView Server Profile is compliant with the server profile template.

Have tried various different key/values in the data dict using the module like so:

Issue occurs specifically when using the compliant state.

- name: "{{ esx_hostname }}: Ensure server profile is compliant"
  hpe.oneview.oneview_server_profile:
    hostname: "{{ oneview_address }}"
    username: "{{ oneview_username }}"
    password: "{{ oneview_password }}"
    auth_login_domain: "{{ oneview_auth_login_domain }}"
    state: compliant
    data:
      name: "{{ management_card_hostname_no_fqdn }}"
      # server_template_name: "{{ server_profile_template }}"
      # serverHardwareUri: "{{ server_hardware_uri }}"
  delegate_to: localhost

OneView version

Firmware 6.20.00-0443754

Ansible version

[root@0ca7edca0a5b ansible]# ansible --version
ansible [core 2.11.5]
  config file = /mnt/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.8/site-packages/ansible
  ansible collection location = /mnt/ansible/collections/ansible_collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.8.6 (default, Jan 22 2021, 11:41:28) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1)]
  jinja version = 3.0.1
  libyaml = True

Collection version

[root@0ca7edca0a5b ansible]# ansible-galaxy collection list
# /mnt/ansible/collections/ansible_collections
Collection              Version
----------------------- -------
community.general       3.1.0
hpe.oneview             6.3.0
...

Traceback:

The full traceback is:
Traceback (most recent call last):
  File "/root/.ansible/tmp/ansible-tmp-1632415592.882123-29070-46239097238132/AnsiballZ_oneview_server_profile.py", line 100, in <module>
    _ansiballz_main()
  File "/root/.ansible/tmp/ansible-tmp-1632415592.882123-29070-46239097238132/AnsiballZ_oneview_server_profile.py", line 92, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/root/.ansible/tmp/ansible-tmp-1632415592.882123-29070-46239097238132/AnsiballZ_oneview_server_profile.py", line 40, in invoke_module
    runpy.run_module(mod_name='ansible_collections.hpe.oneview.plugins.modules.oneview_server_profile', init_globals=dict(_module_fqn='ansible_collections.hpe.oneview.plugins.modules.oneview_server_profile', _modlib_path=modlib_path),
  File "/usr/lib64/python3.8/runpy.py", line 207, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib64/python3.8/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib64/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py", line 693, in <module>
  File "/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py", line 689, in main
  File "/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/module_utils/oneview.py", line 633, in run
  File "/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py", line 296, in execute_module
  File "/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py", line 605, in __make_compliant
AttributeError: 'NoneType' object has no attribute 'data'
fatal: [hostname_here -> localhost]: FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/root/.ansible/tmp/ansible-tmp-1632415592.882123-29070-46239097238132/AnsiballZ_oneview_server_profile.py\", line 100, in <module>\n    _ansiballz_main()\n  File \"/root/.ansible/tmp/ansible-tmp-1632415592.882123-29070-46239097238132/AnsiballZ_oneview_server_profile.py\", line 92, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/root/.ansible/tmp/ansible-tmp-1632415592.882123-29070-46239097238132/AnsiballZ_oneview_server_profile.py\", line 40, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.hpe.oneview.plugins.modules.oneview_server_profile', init_globals=dict(_module_fqn='ansible_collections.hpe.oneview.plugins.modules.oneview_server_profile', _modlib_path=modlib_path),\n  File \"/usr/lib64/python3.8/runpy.py\", line 207, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib64/python3.8/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib64/python3.8/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py\", line 693, in <module>\n  File \"/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py\", line 689, in main\n  File \"/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/module_utils/oneview.py\", line 633, in run\n  File \"/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py\", line 296, in execute_module\n  File \"/tmp/ansible_hpe.oneview.oneview_server_profile_payload_kc_ozrot/ansible_hpe.oneview.oneview_server_profile_payload.zip/ansible_collections/hpe/oneview/plugins/modules/oneview_server_profile.py\", line 605, in __make_compliant\nAttributeError: 'NoneType' object has no attribute 'data'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

@liamwh Thanks for reaching out.
I suspect that you are using state 'compliant' with non-existent server profile. Please check that aspect from your end. If yes, try to run 'compliant' state with already created server profile. if you still face any issues, please let us know.
We have added a check for this and will push to master branch shortly.

The server profile already exists, however it doesn't have the correct name yet. Only the server hardware and server profile template have the correct name at this point.

  1. Can we rename the server profile using ansible first, then attempt to enforce compliance?
  2. Another issue worth mentioning is that the server hardware uri is not gathered in the server_hardware_facts module, but in the server_hardware module.
  3. See comment in below code about idempotency for the oneview server profile module (task: Create a Server Profile from a Server Profile Template).

Right now the playbook looks as follows:

- name: "{{ esx_hostname }}: Gather facts about an existing Server Hardware"
  hpe.oneview.oneview_server_hardware_facts:
    hostname: "{{ oneview_address }}"
    username: "{{ oneview_username }}"
    password: "{{ oneview_password }}"
    auth_login_domain: "{{ oneview_auth_login_domain }}"
    name: "{{ management_card_hostname }}"
  delegate_to: localhost
  register: hardware_facts

- name: "{{ esx_hostname }}: Set fact server profile uri from server hardware"
  when: hardware_facts.ansible_facts.server_hardwares.serverProfileUri is defined
  ansible.builtin.set_fact:
    server_profile_uri: "{{ hardware_facts.ansible_facts.server_hardwares.serverProfileUri }}"

- name: "{{ esx_hostname }}: Ensure Server Hardware is correct in OneView"
  hpe.oneview.oneview_server_hardware:
    hostname: "{{ oneview_address }}"
    username: "{{ oneview_username }}"
    password: "{{ oneview_password }}"
    # api_version: "{{ oneview_api_version }}"
    auth_login_domain: "{{ oneview_auth_login_domain }}"
    state: present
    data:
      hostname: "{{ management_card_hostname }}"
      username: "{{ management_card_username }}"
      password: "{{ management_card_password }}"
      licensingIntent: "OneView"
      force: false
      configurationState: "Managed"
  delegate_to: localhost
  register: server_hardware_configuration

- name: "{{ esx_hostname }}: Set fact for server hardware uri"
  ansible.builtin.set_fact:
    server_hardware_uri: "{{ server_hardware_configuration.ansible_facts.server_hardware.uri }}"

# This module should be idempotent, but isn't. 
# If a server profile already exists, it will shut down the server, realise there is already a profile, and fail.  
- name: "{{ esx_hostname }}: Create a Server Profile from a Server Profile Template"
  when: server_profile_uri is not defined
  block:
    - name: "{{ esx_hostname }}: Create a Server Profile from a Server Profile Template"
      hpe.oneview.oneview_server_profile:
        hostname: "{{ oneview_address }}"
        username: "{{ oneview_username }}"
        password: "{{ oneview_password }}"
        auth_login_domain: "{{ oneview_auth_login_domain }}"
        state: present
        data:
          serverProfileTemplateName: "{{ server_profile_template }}"
          name: "{{ esx_hostname }}"
          description: "Configured by Ansible."
          serverHardwareUri: "{{ hardware_facts.ansible_facts.server_hardwares.uri }}"
      delegate_to: localhost

    - name: "{{ esx_hostname }}: Refresh facts from server hardware"
      hpe.oneview.oneview_server_hardware_facts:
        hostname: "{{ oneview_address }}"
        username: "{{ oneview_username }}"
        password: "{{ oneview_password }}"
        auth_login_domain: "{{ oneview_auth_login_domain }}"
        name: "{{ management_card_hostname }}"
      delegate_to: localhost
      register: hardware_facts

    - name: "{{ esx_hostname }}: Set fact server profile uri from server hardware"
      ansible.builtin.set_fact:
        server_profile_uri: "{{ hardware_facts.ansible_facts.server_hardwares.server_profile_uri }}"

- name: "{{ esx_hostname }}: Gather facts about Server Profile by uri"
  hpe.oneview.oneview_server_profile_facts:
    hostname: "{{ oneview_address }}"
    username: "{{ oneview_username }}"
    password: "{{ oneview_password }}"
    auth_login_domain: "{{ oneview_auth_login_domain }}"
    uri: "{{ server_profile_uri }}"
  delegate_to: localhost
  register: server_profile_facts

- name: "{{ esx_hostname }}: Set fact for server profile template uri"
  ansible.builtin.set_fact:
    server_profile_template_uri: "{{ server_profile_facts.ansible_facts.server_profiles[0].serverProfileTemplateUri }}"

# This is the module that errors.
- name: "{{ esx_hostname }}: Ensure server profile is compliant"
  hpe.oneview.oneview_server_profile:
    hostname: "{{ oneview_address }}"
    username: "{{ oneview_username }}"
    password: "{{ oneview_password }}"
    auth_login_domain: "{{ oneview_auth_login_domain }}"
    state: compliant
    data:
      name: "{{ management_card_hostname_no_fqdn }}"
  delegate_to: localhost

Hi @liamwh,

  1. Can we rename the server profile using ansible first, then attempt to enforce compliance? - yes, we can rename through ansible playbook. Supported changes for that scenario will be into master branch shortly. Please let me know if you can run a compliance operation with existing functional server profile because we are not facing issue with 'compliance' operation.
  2. Another issue worth mentioning is that the server hardware uri is not gathered in the server_hardware_facts module, but in the server_hardware module. - we are able to get server_hardware_uri from server_hardware_facts module. Please try the below snippet:

  • name: Gather facts about all Server Hardwares
    hpe.oneview.oneview_server_hardware_facts:
    config: "{{ config }}"
    delegate_to: localhost

  • ansible.builtin.set_fact: server_hardware_uri = "{{ server_hardwares[0]['uri'] }}"

  • name: Gather facts about a Server Hardware by name
    hpe.oneview.oneview_server_hardware_facts:
    config: "{{ config }}"
    name: "{{ server_hardwares[0]['name'] }}"
    delegate_to: localhost

  • name: Gather facts about a Server Hardware by uri
    hpe.oneview.oneview_server_hardware_facts:
    config: "{{ config }}"
    uri: "{{ server_hardwares['uri'] }}"
    delegate_to: localhost

  • debug: var=server_hardware_uri

  1. This module should be idempotent, but isn't. If a server profile already exists, it will shut down the server, realise there is already a profile, and fail. - We are not facing an issue with this. Please attach error message for the respective operation.

Hi @liamwh ,
As we didn't heard back from you for last 7 days, assuming the issue on 'complaint' operation is working as expected.
Please feel free to reopen the issue if anything doesn't works for you.