Skip to content

Add os_ironic_state role #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions plugins/modules/baremetal_node_state.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#!/usr/bin/python
# coding: utf-8 -*-

# (c) 2015, Hewlett-Packard Development Company, L.P.
# Copyright 2017 StackHPC Ltd.
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

DOCUMENTATION = r'''
module: baremetal_node_state
short_description: Set provision state of Bare Metal Resources from OpenStack
author: "Mark Goddard <[email protected]>"
extends_documentation_fragment: openstack
description:
- Set the provision state of OpenStack ironic bare metal nodes.
options:
provision_state:
description:
- Indicates desired provision state of the resource
choices: ['manage', 'provide']
default: present
uuid:
description:
- globally unique identifier (UUID) to be given to the resource.
required: false
default: None
ironic_url:
description:
- If noauth mode is utilized, this is required to be set to the
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
settings set to None.
required: false
default: None
wait:
description:
- A boolean value instructing the module to wait for node
activation or deactivation to complete before returning.
required: false
default: False
version_added: "2.1"
timeout:
description:
- An integer value representing the number of seconds to
wait for the node activation or deactivation to complete.
version_added: "2.1"
availability_zone:
description:
- Ignored. Present for backwards compatibility
required: false
'''

EXAMPLES = r'''
baremeta_node_state:
cloud: "openstack"
uuid: "d44666e1-35b3-4f6b-acb0-88ab7052da69"
provision_state: provide
delegate_to: localhost
'''

from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
OpenStackModule
)


def _choose_id_value(module):
if module.params['uuid']:
return module.params['uuid']
if module.params['name']:
return module.params['name']
return None


def _change_required(current_provision_state, action):
"""Return whether a change to the provision state is required.

:param current_provision_state: The current provision state of the node.
:param action: The requested action.
"""
if action == 'manage':
if current_provision_state == 'manageable':
return False
if action == 'provide':
if current_provision_state == 'available':
return False
return True


class BaremetalDeployTemplateModule(OpenStackModule):
argument_spec = dict(
uuid=dict(required=False),
name=dict(required=False),
ironic_url=dict(required=False),
provision_state=dict(required=True,
choices=['manage', 'provide']),
wait=dict(type='bool', required=False, default=False),
timeout=dict(required=False, type='int', default=1800),
)
module_kwargs = dict(
required_one_of=[
('uuid', 'name'),
],
)

def run(self):
if (self.params['auth_type'] in [None, 'None'] and
self.params['ironic_url'] is None):
self.fail_json(msg="Authentication appears disabled, Please "
"define an ironic_url parameter")

if (self.params['ironic_url'] and
self.params['auth_type'] in [None, 'None']):
self.params['auth'] = dict(
endpoint=self.params['ironic_url']
)

node_id = _choose_id_value(self)

if not node_id:
self.fail_json(msg="A uuid or name value must be defined "
"to use this module.")

try:
sdk, cloud = openstack_cloud_from_module(self)
node = cloud.get_machine(node_id)

if node is None:
self.fail_json(msg="node not found")

uuid = node['uuid']
changed = False
wait = self.params['wait']
timeout = self.params['timeout']
provision_state = self.params['provision_state']

if node['provision_state'] in [
'cleaning',
'deleting',
'wait call-back']:
self.fail_json(msg="Node is in %s state, cannot act upon the "
"request as the node is in a transition "
"state" % node['provision_state'])

if _change_required(node['provision_state'], provision_state):
cloud.node_set_provision_state(uuid, provision_state, wait=wait,
timeout=timeout)
changed = True

self.exit_json(changed=changed)

except Exception as e:
self.fail_json(msg=str(e))


def main():
module = BaremetalNodeStateModule()
module()


if __name__ == "__main__":
main()
50 changes: 50 additions & 0 deletions roles/os_ironic_state/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
OpenStack Ironic Node State
===========================

This role can be used to set the provision state of ironic nodes.

Requirements
------------

The OpenStack keystone and ironic APIs should be accessible from the target
host.

Role Variables
--------------

`os_ironic_state_auth_type`: Authentication type as used by `os_*` modules'
`auth_type` argument.

`os_ironic_state_auth`: Authentication options as used by `os_*` modules'
`auth` argument.

`os_ironic_state_cacert`: CA certificate as used by `os_*` modules' `cacert`
argument.

`os_ironic_state_interface` is the endpoint URL type to fetch from the service
catalog. Maybe be one of `public`, `admin`, or `internal`.

`os_ironic_state_name`: Name of the ironic node.

`os_ironic_state_provision_state`: Desired provision state.

`os_ironic_state_delegate_to`: Host to delegate to.

`os_ironic_state_wait`: Whether to wait for the state transition to complete.
Default is `True`.

`os_ironic_state_timeout`: Time to wait for state transition to complete, if
`os_ironic_state_wait` is `True`. Default is 1200 seconds.

Dependencies
------------

The delegate host should have the `openstacksdk` Python package installed.

Example Playbook
----------------

Author Information
------------------

- Mark Goddard (<[email protected]>)
29 changes: 29 additions & 0 deletions roles/os_ironic_state/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
# Authentication type as used by os_* modules' 'auth_type' argument.
os_ironic_state_auth_type:

# Authentication options as used by os_* modules' 'auth' argument.
os_ironic_state_auth: {}

# CA certificate as used by os_* modules' 'cacert' argument.
os_ironic_state_cacert:

# Endpoint URL type to fetch from the service catalog. Maybe be one of:
# public, admin, or internal.
os_ironic_state_interface:

# Name of the ironic node.
os_ironic_state_name:

# Desired provision state.
os_ironic_state_provision_state:

# Host to delegate to.
os_ironic_state_delegate_to:

# Whether to wait for the state transition to complete.
os_ironic_state_wait: true

# Time to wait for state transition to complete, if os_ironic_state_wait is
# True.
os_ironic_state_timeout: 1200
16 changes: 16 additions & 0 deletions roles/os_ironic_state/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
- name: Ensure baremetal compute nodes provision states are set
stackhpc.openstack.baremetal_node_state:
auth_type: "{{ os_ironic_state_auth_type }}"
auth: "{{ os_ironic_state_auth }}"
cacert: "{{ os_ironic_state_cacert | default(omit, true) }}"
interface: "{{ os_ironic_state_interface | default(omit, true) }}"
name: "{{ os_ironic_state_name }}"
provision_state: "{{ os_ironic_state_provision_state }}"
timeout: "{{ os_ironic_state_timeout }}"
wait: "{{ os_ironic_state_wait }}"
delegate_to: "{{ os_ironic_state_delegate_to }}"
vars:
# NOTE: Without this, the delegate hosts's ansible_host variable will not
# be respected.
ansible_host: "{{ hostvars[os_ironic_state_delegate_to].ansible_host | default(os_ironic_state_delegate_to) }}"
1 change: 1 addition & 0 deletions roles/os_ironic_state/tests/inventory
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
localhost ansible_connection='local' ansible_python_interpreter='/usr/bin/env python'
6 changes: 6 additions & 0 deletions roles/os_ironic_state/tests/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
- name: Test os_ironic_state
hosts: all
connection: local
roles:
- stackhpc.openstack.os_ironic_state