kayobe/ansible/roles/ironic-inspector-rules/library/os_ironic_inspector_rule.py

172 lines
5.7 KiB
Python

#!/usr/bin/python3
# Copyright (c) 2017 StackHPC Ltd.
#
# 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 copy
from ansible.module_utils.basic import *
from ansible.module_utils.openstack import *
# Store a list of import errors to report to the user.
IMPORT_ERRORS = []
try:
import openstack
except Exception as e:
IMPORT_ERRORS.append(e)
DOCUMENTATION = """
module: os_ironic_inspector_rule
short_description: Create or destroy an Ironic Inspector rule.
author: "Mark Goddard <mark@stackhpc.com>"
extends_documentation_fragment: openstack
description:
- Create or destroy an Ironic inspector rule.
options:
state:
description:
- State of the rule
choices: ["present", "absent"]
uuid:
description:
- Globally unique identifier for the rule.
required: false
description:
description:
- Description for the rule.
required: false
conditions:
description:
- List of conditions that must be met in order to apply the rule.
required: true
actions:
description:
- List of actions to be taken when the conditions are met.
required: true
"""
EXAMPLES = """
# Ensure that an inspector rule exists.
os_ironic_inspector_rule:
cloud: "openstack"
state: present
uuid: "d44666e1-35b3-4f6b-acb0-88ab7052da69"
description: Set IPMI username in driver_info if not set
conditions:
- field: "node://driver_info.ipmi_username"
op: "is-empty"
actions:
- action: "set-attribute"
path: "driver_info/ipmi_username"
value: "root"
"""
def _get_client(module, cloud):
"""Return an Ironic inspector client."""
return cloud.baremetal_introspection
def _ensure_rule_present(module, client):
"""Ensure that an inspector rule is present."""
if module.params['uuid']:
response = client.get('/rules/{}'.format(module.params['uuid']))
if not response.ok:
if response.status_code != 404:
module.fail_json(msg="Failed retrieving Inspector rule %s: %s"
% (module.params['uuid'], repr(e)))
else:
rule = response.json()
# Check whether the rule differs from the request.
keys = ('conditions', 'actions', 'description')
for key in keys:
expected = module.params[key]
if key == 'conditions':
# Rules returned from the API include default values in the
# conditions that may not be in the requested rule. Apply
# defaults to allow the comparison to succeed.
expected = copy.deepcopy(expected)
for condition in expected:
condition.setdefault('invert', False)
condition.setdefault('multiple', 'any')
if rule[key] != expected:
break
else:
# Nothing to do - rule exists and is as requested.
return False
# Rule differs - delete it before recreating.
_ensure_rule_absent(module, client)
rule = {
"conditions": module.params['conditions'],
"actions": module.params['actions'],
"description": module.params['description'],
"uuid": module.params['uuid'],
}
response = client.post("/rules", json=rule)
if not response.ok:
module.fail_json(msg="Failed creating Inspector rule %s: %s"
% (module.params['uuid'], response.text))
return True
def _ensure_rule_absent(module, client):
"""Ensure that an inspector rule is absent."""
if not module.params['uuid']:
module.fail_json(msg="UUID is required to ensure rules are absent")
response = client.delete("/rules/{}".format(module.params['uuid']))
if not response.ok:
# If the rule does not exist, no problem and no change.
if response.status_code == 404:
return False
module.fail_json(msg="Failed retrieving Inspector rule %s: %s"
% (module.params['uuid'], response.text))
return True
def main():
argument_spec = openstack_full_argument_spec(
conditions=dict(type='list', required=True),
actions=dict(type='list', required=True),
description=dict(required=False),
uuid=dict(required=False),
state=dict(required=False, default='present',
choices=['present', 'absent']),
)
module_kwargs = openstack_module_kwargs()
module = AnsibleModule(argument_spec, **module_kwargs)
# Fail if there were any exceptions when importing modules.
if IMPORT_ERRORS:
module.fail_json(msg="Import errors: %s" %
", ".join([repr(e) for e in IMPORT_ERRORS]))
sdk, cloud = openstack_cloud_from_module(module)
try:
client = _get_client(module, cloud)
if module.params["state"] == "present":
changed = _ensure_rule_present(module, client)
else:
changed = _ensure_rule_absent(module, client)
except Exception as e:
module.fail_json(msg="Failed to configure Ironic Inspector rule: %s" %
repr(e))
else:
module.exit_json(changed=changed)
if __name__ == '__main__':
main()