08533b45c3
This change modifies the argument_spec making it so we load the options key from the documentation constant. This will reduce the code we have to maintain and ensure our documentation is always in sync with the module capabilities. Change-Id: Iaf94b6300a58de4367b4c9f2c83cc112e7c5361a Co-Authored-by: Kevin Carter <kecarter@redhat.com> Signed-off-by: Gael Chamoulaud <gchamoul@redhat.com>
128 lines
3.8 KiB
Python
128 lines
3.8 KiB
Python
#!/usr/bin/env python
|
|
# Copyright 2019 Red Hat, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# 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 collections
|
|
|
|
from ansible.module_utils.basic import AnsibleModule # noqa
|
|
from oslo_utils import uuidutils
|
|
from yaml import safe_load as yaml_safe_load
|
|
|
|
DOCUMENTATION = '''
|
|
---
|
|
module: check_ironic_boot_config
|
|
short_description:
|
|
- Check that overcloud nodes have the correct associated ramdisk and kernel
|
|
image
|
|
description:
|
|
- Each overcloud node needs to have the correct associated ramdisk and
|
|
kernel image according to its architecture and platform. This can be
|
|
validated by making sure that like nodes have associated deploy images
|
|
not exceeding a certain standard of diversity.
|
|
options:
|
|
nodes:
|
|
required: true
|
|
description:
|
|
- A list of nodes from Ironic
|
|
type: list
|
|
|
|
author: Jeremy Freudberg
|
|
'''
|
|
|
|
EXAMPLES = '''
|
|
- hosts: undercloud
|
|
tasks:
|
|
- name: Check Ironic boot config
|
|
check_ironic_boot_config:
|
|
nodes: "{{ lookup('ironic_nodes', wantlist=True) }}"
|
|
'''
|
|
|
|
|
|
GLANCE = 'Glance'
|
|
FILE = 'file-based'
|
|
|
|
|
|
def _too_diverse(mapping_type, node_info, images):
|
|
image_type = "deploy_%s" % node_info[0]
|
|
return (
|
|
"There is more than one {} {} associated to nodes with architecture "
|
|
"{} and platform {}. Probably only one of {} should be associated."
|
|
).format(mapping_type, image_type, node_info[1], node_info[2], images)
|
|
|
|
|
|
def _invalid_image_entry(image_type_base, image_entry, node_id):
|
|
image_type = "deploy_%s" % image_type_base
|
|
return (
|
|
"The {} associated to node {} is of an invalid form. Could not "
|
|
"determine whether {} refers to a file or Glance image."
|
|
).format(image_type, node_id, image_entry)
|
|
|
|
|
|
def validate_boot_config(nodes):
|
|
errors = []
|
|
|
|
associated_images = {
|
|
GLANCE: collections.defaultdict(set),
|
|
FILE: collections.defaultdict(set)
|
|
}
|
|
|
|
for node in nodes:
|
|
arch = node["properties"].get("cpu_arch", None)
|
|
platform = node["extra"].get("tripleo_platform", None)
|
|
|
|
for image_type in ['kernel', 'ramdisk']:
|
|
image_entry = (
|
|
node["driver_info"].get("deploy_%s" % image_type, None)
|
|
)
|
|
if uuidutils.is_uuid_like(image_entry):
|
|
mapping = GLANCE
|
|
elif str(image_entry).startswith("file://"):
|
|
mapping = FILE
|
|
# TODO(jfreud): uncomment when Ironic supports empty driver_info
|
|
# elif image_entry is None:
|
|
# continue
|
|
else:
|
|
errors.append(_invalid_image_entry(
|
|
image_type, image_entry, node["uuid"]))
|
|
continue
|
|
node_info = (image_type, arch, platform)
|
|
associated_images[mapping][node_info].add(image_entry)
|
|
|
|
for mapping_type, mapping in associated_images.items():
|
|
for node_info, images in mapping.items():
|
|
if len(images) > 1:
|
|
errors.append(_too_diverse(mapping_type, node_info, images))
|
|
|
|
return errors
|
|
|
|
|
|
def main():
|
|
module = AnsibleModule(
|
|
argument_spec=yaml_safe_load(DOCUMENTATION)['options']
|
|
)
|
|
|
|
nodes = module.params.get('nodes')
|
|
|
|
errors = validate_boot_config(nodes)
|
|
|
|
if errors:
|
|
module.fail_json("".join(errors))
|
|
else:
|
|
module.exit_json()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|