ironic/ironic/drivers/modules/ansible/playbooks/library/root_hints.py

104 lines
3.4 KiB
Python

# -*- coding: utf-8 -*-
#
# 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.
GIB = 1 << 30
EXTRA_PARAMS = set(['wwn', 'serial', 'wwn_with_extension',
'wwn_vendor_extension'])
IGNORE_DEVICES = ['sr', 'loop', 'mem', 'fd']
# NOTE: ansible calculates device size as float with 2-digits precision,
# Ironic requires size in GiB, if we will use ansible size parameter
# a bug is possible for devices > 1 TB
def size_gib(device_info):
sectors = device_info.get('sectors')
sectorsize = device_info.get('sectorsize')
if sectors is None or sectorsize is None:
return '0'
return str((int(sectors) * int(sectorsize)) // GIB)
def merge_devices_info(devices, devices_wwn):
merged_info = devices.copy()
for device in merged_info:
if device in devices_wwn:
merged_info[device].update(devices_wwn[device])
# replace size
merged_info[device]['size'] = size_gib(merged_info[device])
return merged_info
def root_hint(hints, devices):
hint = None
name = hints.pop('name', None)
for device in devices:
if any(x in device for x in IGNORE_DEVICES):
# NOTE(TheJulia): Devices like CD roms, Loop devices, and ramdisks
# should not be considered as target devices.
continue
for key in hints:
if hints[key] != devices[device].get(key):
break
else:
# If multiple hints are specified, a device must satisfy all
# the hints
dev_name = '/dev/' + device
if name is None or name == dev_name:
hint = dev_name
break
return hint
def main():
module = AnsibleModule( # noqa This is normal for Ansible modules.
argument_spec=dict(
root_device_hints=dict(required=True, type='dict'),
ansible_devices=dict(required=True, type='dict'),
ansible_devices_wwn=dict(required=True, type='dict')
),
supports_check_mode=True)
hints = module.params['root_device_hints']
devices = module.params['ansible_devices']
devices_wwn = module.params['ansible_devices_wwn']
if not devices_wwn:
extra = set(hints) & EXTRA_PARAMS
if extra:
module.fail_json(msg='Extra hints (supported by additional ansible'
' module) are set but this information can not be'
' collected. Extra hints: %s' % ', '.join(extra))
devices_info = merge_devices_info(devices, devices_wwn or {})
hint = root_hint(hints, devices_info)
if hint is None:
module.fail_json(msg='Root device hints are set, but none of the '
'devices satisfy them. Collected devices info: %s'
% devices_info)
ret_data = {'ansible_facts': {'ironic_root_device': hint}}
module.exit_json(**ret_data)
from ansible.module_utils.basic import * # noqa
if __name__ == '__main__':
main()