104 lines
3.4 KiB
Python
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()
|