File: //usr/lib/python2.7/site-packages/salt/states/mdadm_raid.py
# -*- coding: utf-8 -*-
'''
Managing software RAID with mdadm
==================================
:depends: mdadm
A state module for creating or destroying software RAID devices.
.. code-block:: yaml
/dev/md0:
raid.present:
- level: 5
- devices:
- /dev/xvdd
- /dev/xvde
- /dev/xvdf
- chunk: 256
- run: True
'''
# Import python libs
from __future__ import absolute_import, print_function, unicode_literals
import logging
# Import salt libs
import salt.utils.path
# Set up logger
log = logging.getLogger(__name__)
# Define the module's virtual name
__virtualname__ = 'raid'
def __virtual__():
'''
mdadm provides raid functions for Linux
'''
if __grains__['kernel'] != 'Linux':
return False
if not salt.utils.path.which('mdadm'):
return False
return __virtualname__
def present(name,
level,
devices,
**kwargs):
'''
Verify that the raid is present
.. versionchanged:: 2014.7.0
name
The name of raid device to be created
level
The RAID level to use when creating the raid.
devices
A list of devices used to build the array.
kwargs
Optional arguments to be passed to mdadm.
Example:
.. code-block:: yaml
/dev/md0:
raid.present:
- level: 5
- devices:
- /dev/xvdd
- /dev/xvde
- /dev/xvdf
- chunk: 256
- run: True
'''
ret = {'changes': {},
'comment': '',
'name': name,
'result': True}
# Device exists
raids = __salt__['raid.list']()
present = raids.get(name)
# Decide whether to create or assemble
missing = []
uuid_dict = {}
new_devices = []
for dev in devices:
if dev == 'missing' or not __salt__['file.access'](dev, 'f'):
missing.append(dev)
continue
superblock = __salt__['raid.examine'](dev, quiet=True)
if 'MD_UUID' in superblock:
uuid = superblock['MD_UUID']
if uuid not in uuid_dict:
uuid_dict[uuid] = []
uuid_dict[uuid].append(dev)
else:
new_devices.append(dev)
if len(uuid_dict) > 1:
ret['comment'] = 'Devices are a mix of RAID constituents with multiple MD_UUIDs: {0}.'.format(
sorted(uuid_dict.keys()))
ret['result'] = False
return ret
elif len(uuid_dict) == 1:
uuid = list(uuid_dict.keys())[0]
if present and present['uuid'] != uuid:
ret['comment'] = 'Devices MD_UUIDs: {0} differs from present RAID uuid {1}.'.format(uuid, present['uuid'])
ret['result'] = False
return ret
devices_with_superblock = uuid_dict[uuid]
else:
devices_with_superblock = []
if present:
do_assemble = False
do_create = False
elif len(devices_with_superblock) > 0:
do_assemble = True
do_create = False
verb = 'assembled'
else:
if len(new_devices) == 0:
ret['comment'] = 'All devices are missing: {0}.'.format(missing)
ret['result'] = False
return ret
do_assemble = False
do_create = True
verb = 'created'
# If running with test use the test_mode with create or assemble
if __opts__['test']:
if do_assemble:
res = __salt__['raid.assemble'](name,
devices_with_superblock,
test_mode=True,
**kwargs)
elif do_create:
res = __salt__['raid.create'](name,
level,
new_devices + ['missing'] * len(missing),
test_mode=True,
**kwargs)
if present:
ret['comment'] = 'Raid {0} already present.'.format(name)
if do_assemble or do_create:
ret['comment'] = 'Raid will be {0} with: {1}'.format(verb, res)
ret['result'] = None
if (do_assemble or present) and len(new_devices) > 0:
ret['comment'] += ' New devices will be added: {0}'.format(new_devices)
ret['result'] = None
if len(missing) > 0:
ret['comment'] += ' Missing devices: {0}'.format(missing)
return ret
# Attempt to create or assemble the array
if do_assemble:
__salt__['raid.assemble'](name,
devices_with_superblock,
**kwargs)
elif do_create:
__salt__['raid.create'](name,
level,
new_devices + ['missing'] * len(missing),
**kwargs)
if not present:
raids = __salt__['raid.list']()
changes = raids.get(name)
if changes:
ret['comment'] = 'Raid {0} {1}.'.format(name, verb)
ret['changes'] = changes
# Saving config
__salt__['raid.save_config']()
else:
ret['comment'] = 'Raid {0} failed to be {1}.'.format(name, verb)
ret['result'] = False
else:
ret['comment'] = 'Raid {0} already present.'.format(name)
if (do_assemble or present) and len(new_devices) > 0 and ret['result']:
for d in new_devices:
res = __salt__['raid.add'](name, d)
if not res:
ret['comment'] += ' Unable to add {0} to {1}.\n'.format(d, name)
ret['result'] = False
else:
ret['comment'] += ' Added new device {0} to {1}.\n'.format(d, name)
if ret['result']:
ret['changes']['added'] = new_devices
if len(missing) > 0:
ret['comment'] += ' Missing devices: {0}'.format(missing)
return ret
def absent(name):
'''
Verify that the raid is absent
name
The name of raid device to be destroyed
.. code-block:: yaml
/dev/md0:
raid:
- absent
'''
ret = {'changes': {},
'comment': '',
'name': name,
'result': True}
# Raid does not exist
if name not in __salt__['raid.list']():
ret['comment'] = 'Raid {0} already absent'.format(name)
return ret
elif __opts__['test']:
ret['comment'] = 'Raid {0} is set to be destroyed'.format(name)
ret['result'] = None
return ret
else:
# Attempt to destroy raid
ret['result'] = __salt__['raid.destroy'](name)
if ret['result']:
ret['comment'] = 'Raid {0} has been destroyed'.format(name)
else:
ret['comment'] = 'Raid {0} failed to be destroyed'.format(name)
return ret