Adding a state module to manage beacons. adding a new method to the beacon execution module to modify existing beacons.

This commit is contained in:
Gareth J. Greenaway 2015-05-20 21:04:41 -07:00
parent 92cdfec637
commit 4f0e50a758
4 changed files with 303 additions and 0 deletions

View file

@ -129,6 +129,25 @@ class Beacon(object):
return True
def modify_beacon(self, name, beacon_data):
'''
Modify a beacon item
'''
data = {}
data[name] = beacon_data
log.info('Updating settings for beacon '
'item: {0}'.format(name))
self.opts['beacons'].update(data)
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_modify_complete')
return True
def delete_beacon(self, name):
'''
Delete a beacon item

View file

@ -1361,6 +1361,8 @@ class Minion(MinionBase):
if func == 'add':
self.beacons.add_beacon(name, beacon_data)
elif func == 'modify':
self.beacons.modify_beacon(name, beacon_data)
elif func == 'delete':
self.beacons.delete_beacon(name)
elif func == 'enable':

View file

@ -8,6 +8,7 @@ Module for managing the Salt beacons on a minion
# Import Python libs
from __future__ import absolute_import
import difflib
import os
import yaml
@ -74,6 +75,10 @@ def add(name, beacon_data, **kwargs):
ret = {'comment': 'Failed to add beacon {0}.'.format(name),
'result': False}
if name in list_(return_yaml=False):
ret['comment'] = 'Beacon {0} is already configured.'.format(name)
return ret
if 'test' in kwargs and kwargs['test']:
ret['result'] = True
ret['comment'] = 'Beacon: {0} would be added.'.format(name)
@ -115,6 +120,82 @@ def add(name, beacon_data, **kwargs):
return ret
def modify(name, beacon_data, **kwargs):
'''
Modify an existing job in the schedule
CLI Example:
.. code-block:: bash
salt '*' schedule.modify job1 function='test.ping' seconds=3600
'''
ret = {'comment': '',
'result': True}
current_beacons = list_(return_yaml=False)
if name not in current_beacons:
ret['comment'] = 'Beacon {0} is not configured.'.format(name)
return ret
if 'test' in kwargs and kwargs['test']:
ret['result'] = True
ret['comment'] = 'Beacon: {0} would be added.'.format(name)
else:
# Attempt to load the beacon module so we have access to the validate function
try:
beacon_module = __import__('salt.beacons.' + name, fromlist=['validate'])
log.debug('Successfully imported beacon.')
except ImportError:
ret['comment'] = 'Beacon {0} does not exist'.format(name)
return ret
# Attempt to validate
if hasattr(beacon_module, 'validate'):
valid = beacon_module.validate(beacon_data)
else:
log.info('Beacon {0} does not have a validate'
' function, skipping validation.'.format(name))
valid = True
if not valid:
ret['comment'] = 'Beacon {0} configuration invalid, not modifying.'.format(name)
return ret
_current = current_beacons[name]
_new = beacon_data
if _new == _current:
ret['comment'] = 'Job {0} in correct state'.format(name)
return ret
_current_lines = ['{0}:{1}\n'.format(key, value)
for (key, value) in sorted(_current.items())]
_new_lines = ['{0}:{1}\n'.format(key, value)
for (key, value) in sorted(_new.items())]
_diff = difflib.unified_diff(_current_lines, _new_lines)
ret['changes'] = {}
ret['changes']['diff'] = ''.join(_diff)
try:
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'name': name, 'beacon_data': beacon_data, 'func': 'modify'}, 'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_modify_complete', wait=30)
if event_ret and event_ret['complete']:
beacons = event_ret['beacons']
if name in beacons and beacons[name] == beacon_data:
ret['result'] = True
ret['comment'] = 'Modified beacon: {0}.'.format(name)
return ret
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacon add failed.'
return ret
def delete(name, **kwargs):
'''
Delete a beacon item

201
salt/states/beacon.py Normal file
View file

@ -0,0 +1,201 @@
# -*- coding: utf-8 -*-
'''
Management of the Salt beacons
==============================================
.. code-block:: yaml
ps:
beacon.present:
- enable: False
- salt-master: running
- apache2: stopped
sh:
beacon.present:
load:
beacon.present:
- 1m:
- 0.0
- 2.0
- 5m:
- 0.0
- 1.5
- 15m:
- 0.1
- 1.0
'''
import logging
log = logging.getLogger(__name__)
def present(name,
**kwargs):
'''
Ensure beacon is configured with the included beacon data.
name
The name of the beacon ensure is configured.
'''
ret = {'name': name,
'result': True,
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](return_yaml=False)
beacon_data = kwargs
if name in current_beacons:
if beacon_data == current_beacons[name]:
ret['comment'].append('Job {0} in correct state'.format(name))
else:
if 'test' in __opts__ and __opts__['test']:
kwargs['test'] = True
result = __salt__['beacons.modify'](name, beacon_data, **kwargs)
ret['comment'].append(result['comment'])
ret['changes'] = result['changes']
else:
result = __salt__['beacons.modify'](name, beacon_data, **kwargs)
if not result['result']:
ret['result'] = result['result']
ret['comment'] = result['comment']
return ret
else:
ret['comment'].append('Modifying {0} in beacons'.format(name))
ret['changes'] = result['changes']
else:
if 'test' in __opts__ and __opts__['test']:
kwargs['test'] = True
result = __salt__['beacons.add'](name, beacon_data, **kwargs)
ret['comment'].append(result['comment'])
else:
result = __salt__['beacons.add'](name, beacon_data, **kwargs)
if not result['result']:
ret['result'] = result['result']
ret['comment'] = result['comment']
return ret
else:
ret['comment'].append('Adding {0} to beacons'.format(name))
ret['comment'] = '\n'.join(ret['comment'])
return ret
def absent(name, **kwargs):
'''
Ensure beacon is absent.
name
The name of the beacon ensured absent.
'''
### NOTE: The keyword arguments in **kwargs are ignored in this state, but
### cannot be removed from the function definition, otherwise the use
### of unsupported arguments will result in a traceback.
ret = {'name': name,
'result': True,
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](return_yaml=False)
if name in current_beacons:
if 'test' in __opts__ and __opts__['test']:
kwargs['test'] = True
result = __salt__['beacons.delete'](name, **kwargs)
ret['comment'].append(result['comment'])
else:
result = __salt__['beacons.delete'](name, **kwargs)
if not result['result']:
ret['result'] = result['result']
ret['comment'] = result['comment']
return ret
else:
ret['comment'].append('Removed {0} from beacons'.format(name))
else:
ret['comment'].append('{0} not configured in beacons'.format(name))
ret['comment'] = '\n'.join(ret['comment'])
return ret
def enabled(name, **kwargs):
'''
Enable a beacon.
name
The name of the beacon to enable.
'''
### NOTE: The keyword arguments in **kwargs are ignored in this state, but
### cannot be removed from the function definition, otherwise the use
### of unsupported arguments will result in a traceback.
ret = {'name': name,
'result': True,
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](show_all=True, return_yaml=False)
if name in current_beacons:
if 'test' in __opts__ and __opts__['test']:
kwargs['test'] = True
result = __salt__['beacons.enable_beacon'](name, **kwargs)
ret['comment'].append(result['comment'])
else:
result = __salt__['beacons.enable_job'](name, **kwargs)
if not result['result']:
ret['result'] = result['result']
ret['comment'] = result['comment']
return ret
else:
ret['comment'].append('Enabled {0} from beacons'.format(name))
else:
ret['comment'].append('{0} not a configured beacon'.format(name))
ret['comment'] = '\n'.join(ret['comment'])
return ret
def disabled(name, **kwargs):
'''
Disable a beacon.
name
The name of the beacon to enable.
'''
### NOTE: The keyword arguments in **kwargs are ignored in this state, but
### cannot be removed from the function definition, otherwise the use
### of unsupported arguments will result in a traceback.
ret = {'name': name,
'result': True,
'changes': {},
'comment': []}
current_beacons = __salt__['beacons.list'](show_all=True, return_yaml=False)
if name in current_beacons:
if 'test' in __opts__ and __opts__['test']:
kwargs['test'] = True
result = __salt__['beacons.disable_beacon'](name, **kwargs)
ret['comment'].append(result['comment'])
else:
result = __salt__['beacons.disable_beacon'](name, **kwargs)
if not result['result']:
ret['result'] = result['result']
ret['comment'] = result['comment']
return ret
else:
ret['comment'].append('Disabled beacon {0}.'.format(name))
else:
ret['comment'].append('Job {0} is not configured.'.format(name))
ret['comment'] = '\n'.join(ret['comment'])
return ret