ansible-collections-openstack/plugins/modules/baremetal_node_action.py
Jakob Meng f73a0e385e Use true and false instead of yes and no for boolean values
Story: 2010586
Task: 47380
Change-Id: I1b88aa925d823d74b2d012153dfe26d35c93dfd5
2023-02-21 13:07:29 +01:00

269 lines
9.8 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2015, Hewlett-Packard Development Company, L.P.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = r'''
---
module: baremetal_node_action
short_description: Activate/Deactivate Bare Metal nodes from OpenStack
author: OpenStack Ansible SIG
description:
- Deploy to Bare Metal nodes controlled by Ironic.
options:
deploy:
description:
- Indicates if the resource should be deployed. Allows for deployment
logic to be disengaged and control of the node power or maintenance
state to be changed.
type: bool
default: true
config_drive:
description:
- A configdrive file or HTTP(S) URL that will be passed along to the
node.
type: raw
instance_info:
description:
- Definition of the instance information which is used to deploy
the node. This information is only required when I(state) is
set to C(present) or C(on).
type: dict
suboptions:
image_source:
description:
- An HTTP(S) URL where the image can be retrieved from.
image_checksum:
description:
- The checksum of image_source.
image_disk_format:
description:
- The type of image that has been requested to be deployed.
maintenance:
description:
- Set node into maintenance mode.
- The power state as controlled with I(power) will not be changed
when maintenance mode of a node is changed.
type: bool
maintenance_reason:
description:
- A string expression regarding the reason a node is in a
maintenance mode.
type: str
name:
description:
- Name or ID of the Bare Metal node.
type: str
required: true
aliases: ['id', 'uuid']
power:
description:
- A setting to allow power state to be asserted allowing nodes
that are not yet deployed to be powered on, and nodes that
are deployed to be powered off.
- I(power) can be C(present), C(absent), C(maintenance), C(on) or
C(off).
choices: ['present', 'absent', 'maintenance', 'on', 'off']
default: present
type: str
state:
description:
- Indicates desired state of the resource.
- I(state) can be C(present), C(absent), C(maintenance), C(on) or
C(off).
choices: ['present', 'absent', 'maintenance', 'on', 'off']
default: present
type: str
timeout:
description:
- Number of seconds to wait for the node activation or deactivation
to complete.
type: int
default: 1800
extends_documentation_fragment:
- openstack.cloud.openstack
'''
EXAMPLES = r'''
# Activate a node by booting an image with a configdrive attached
- openstack.cloud.baremetal_node_action:
instance_info:
image_source: "http://192.168.1.1/deploy_image.img"
image_checksum: "356a6b55ecc511a20c33c946c4e678af"
image_disk_format: "qcow"
delegate_to: localhost
deploy: true
cloud: "openstack"
config_drive: "http://192.168.1.1/host-configdrive.iso"
maintenance: false
power: present
uuid: "d44666e1-35b3-4f6b-acb0-88ab7052da69"
state: present
# Activate a node by booting an image with a configdrive json object
- openstack.cloud.baremetal_node_action:
auth_type: None
auth:
endpoint: "http://192.168.1.1:6385/"
id: "d44666e1-35b3-4f6b-acb0-88ab7052da69"
config_drive:
meta_data:
hostname: node1
public_keys:
default: ssh-rsa AAA...BBB==
delegate_to: localhost
instance_info:
image_source: "http://192.168.1.1/deploy_image.img"
image_checksum: "356a6b55ecc511a20c33c946c4e678af"
image_disk_format: "qcow"
'''
RETURN = r'''
'''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
OpenStackModule
)
class BaremetalNodeActionModule(OpenStackModule):
argument_spec = dict(
config_drive=dict(type='raw'),
deploy=dict(type='bool', default=True),
instance_info=dict(type='dict'),
maintenance=dict(type='bool'),
maintenance_reason=dict(),
name=dict(required=True, aliases=['id', 'uuid']),
power=dict(default='present',
choices=['present', 'absent', 'maintenance', 'on', 'off']),
state=dict(default='present',
choices=['present', 'absent', 'maintenance', 'on', 'off']),
timeout=dict(type='int', default=1800), # increased default value
)
module_kwargs = dict(
required_if=[
('state', 'present', ('instance_info',)),
],
)
def run(self):
# Fail early on invalid arguments
config_drive = self.params['config_drive']
if config_drive and not isinstance(config_drive, (str, dict)):
self.fail_json(msg='config_drive must be of type str or dict,'
' not {0}'.format(type(config_drive)))
# User has requested desired state to be in maintenance state.
if self.params['state'] == 'maintenance':
if self.params['maintenance'] is False:
self.fail_json(
msg='state=maintenance contradicts with maintenance=false')
self.params['maintenance'] = True
name_or_id = self.params['name']
node = self.conn.baremetal.find_node(name_or_id, ignore_missing=False)
if node['provision_state'] in ['cleaning',
'deleting',
'wait call-back']:
self.fail_json(msg='Node is in {0} state, cannot act upon the'
' request as the node is in a transition'
' state'.format(node['provision_state']))
changed = False
# Update maintenance state
if self.params['maintenance']:
maintenance_reason = self.params['maintenance_reason']
if not node['maintenance'] \
or node['maintenance_reason'] != maintenance_reason:
self.conn.baremetal.set_node_maintenance(
node['id'], reason=maintenance_reason)
self.exit_json(changed=True)
else: # self.params['maintenance'] is False
if node['maintenance']:
self.conn.baremetal.unset_node_maintenance(node['id'])
if node['provision_state'] in 'active':
# Maintenance state changed
self.exit_json(changed=True)
changed = True
node = self.conn.baremetal.get_node(node['id'])
# Update power state
if node['power_state'] == 'power on':
if self.params['power'] in ['absent', 'off']:
# User has requested the node be powered off.
self.conn.baremetal.set_node_power_state(node['id'],
'power off')
self.exit_json(changed=True)
elif node['power_state'] == 'power off':
if self.params['power'] not in ['absent', 'off'] \
or self.params['state'] not in ['absent', 'off']:
# In the event the power has been toggled on and
# deployment has been requested, we need to skip this
# step.
if self.params['power'] == 'present' \
and not self.params['deploy']:
# Node is powered down when it is not awaiting to be
# provisioned
self.conn.baremetal.set_node_power_state(node['id'],
'power on')
changed = True
node = self.conn.baremetal.get_node(node['id'])
else:
self.fail_json(msg='Node has unknown power state {0}'
.format(node['power_state']))
if self.params['state'] in ['present', 'on']:
if not self.params['deploy']:
# User request has explicitly disabled deployment logic
self.exit_json(changed=changed)
if 'active' in node['provision_state']:
# Node already in an active state
self.exit_json(changed=changed)
# TODO(TheJulia): Update instance info, however info is
# deployment specific. Perhaps consider adding rebuild
# support, although there is a known desire to remove
# rebuild support from Ironic at some point in the future.
self.conn.baremetal.update_node(
node['id'],
instance_info=self.params['instance_info'])
self.conn.baremetal.validate_node(node['id'])
self.conn.baremetal.set_node_provision_state(
node['id'],
target='active',
config_drive=self.params['config_drive'],
wait=self.params['wait'],
timeout=self.params['timeout'])
# TODO(TheJulia): Add more error checking..
self.exit_json(changed=True)
elif node['provision_state'] not in 'deleted':
self.conn.baremetal.update_node(node['id'], instance_info={})
self.conn.baremetal.set_node_provision_state(
node['id'],
target='deleted',
wait=self.params['wait'],
timeout=self.params['timeout'])
self.exit_json(changed=True)
else:
# self.params['state'] in ['absent', 'off']
# and node['provision_state'] in 'deleted'
self.exit_json(changed=changed)
def main():
module = BaremetalNodeActionModule()
module()
if __name__ == "__main__":
main()