mirror of
https://github.com/saltstack/salt.git
synced 2025-04-16 17:50:20 +00:00
Added power cfg module and state for windows minions
- Allows you to set power settings on a windows minion for things like the monitor and disk
This commit is contained in:
parent
3b0b55b888
commit
899ba78e79
7 changed files with 514 additions and 0 deletions
6
doc/ref/modules/all/salt.modules.win_powercfg.rst
Normal file
6
doc/ref/modules/all/salt.modules.win_powercfg.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
=========================
|
||||
salt.modules.win_powercfg
|
||||
=========================
|
||||
|
||||
.. automodule:: salt.modules.win_powercfg
|
||||
:members:
|
6
doc/ref/states/all/salt.states.win_powercfg.rst
Normal file
6
doc/ref/states/all/salt.states.win_powercfg.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
========================
|
||||
salt.states.win_powercfg
|
||||
========================
|
||||
|
||||
.. automodule:: salt.states.win_powercfg
|
||||
:members:
|
189
salt/modules/win_powercfg.py
Normal file
189
salt/modules/win_powercfg.py
Normal file
|
@ -0,0 +1,189 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
This module allows you to control the power settings of a windows minion via
|
||||
powercfg
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.set_monitor_timeout 0 power=dc
|
||||
salt '*' powercfg.set_disk_timeout 120 power=ac
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
import re
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = "powercfg"
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only work on Windows
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return __virtualname__
|
||||
return False
|
||||
|
||||
|
||||
def _get_current_scheme():
|
||||
cmd = "powercfg /getactivescheme"
|
||||
out = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
matches = re.search(r"GUID: (.*) \(", out)
|
||||
return matches.groups()[0].strip()
|
||||
|
||||
|
||||
def _get_powercfg_minute_values(scheme, guid, subguid):
|
||||
'''
|
||||
Returns the AC/DC values in an array for a guid and subguid for a the given scheme
|
||||
'''
|
||||
cmd = "powercfg /q {0} {1} {2}".format(scheme, guid, subguid)
|
||||
out = __salt__['cmd.run'](cmd, python_shell=False)
|
||||
raw_settings = re.findall(r"Power Setting Index: ([0-9a-fx]+)", out)
|
||||
return {"ac": int(raw_settings[0], 0) / 60, "dc": int(raw_settings[1], 0) / 60}
|
||||
|
||||
|
||||
def _set_powercfg_value(setting, power, value):
|
||||
'''
|
||||
Sets the value of a setting with a given power (ac/dc) to
|
||||
the current scheme
|
||||
'''
|
||||
cmd = "powercfg /x {0}-{1} {2}".format(setting, power, value)
|
||||
return __salt__['cmd.run'](cmd, python_shell=False)
|
||||
|
||||
|
||||
def set_monitor_timeout(timeout, power="ac"):
|
||||
'''
|
||||
Set the monitor timeout in minutes for the current power scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.set_monitor_timeout 30 power=ac
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the monitor will timeout
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
'''
|
||||
return _set_powercfg_value("monitor-timeout", power, timeout)
|
||||
|
||||
|
||||
def get_monitor_timeout():
|
||||
'''
|
||||
Get the current monitor timeout of the current scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_monitor_timeout
|
||||
'''
|
||||
return _get_powercfg_minute_values(_get_current_scheme(), "SUB_VIDEO", "VIDEOIDLE")
|
||||
|
||||
|
||||
def set_disk_timeout(timeout, power="ac"):
|
||||
'''
|
||||
Set the disk timeout in minutes for the current power scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.set_disk_timeout 30 power=dc
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the disk will timeout
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
'''
|
||||
return _set_powercfg_value("disk-timeout", power, timeout)
|
||||
|
||||
|
||||
def get_disk_timeout():
|
||||
'''
|
||||
Get the current disk timeout of the current scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_disk_timeout
|
||||
'''
|
||||
return _get_powercfg_minute_values(_get_current_scheme(), "SUB_DISK", "DISKIDLE")
|
||||
|
||||
|
||||
def set_standby_timeout(timeout, power="ac"):
|
||||
'''
|
||||
Set the standby timeout in minutes for the current power scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.set_standby_timeout 30 power=dc
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the computer sleeps
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
'''
|
||||
return _set_powercfg_value("standby-timeout", power, timeout)
|
||||
|
||||
|
||||
def get_standby_timeout():
|
||||
'''
|
||||
Get the current standby timeout of the current scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_standby_timeout
|
||||
'''
|
||||
return _get_powercfg_minute_values(_get_current_scheme(), "SUB_SLEEP", "STANDBYIDLE")
|
||||
|
||||
|
||||
def set_hibernate_timeout(timeout, power="ac"):
|
||||
'''
|
||||
Set the hibernate timeout in minutes for the current power scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.set_hibernate_timeout 30 power=pc
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the computer hibernates
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
|
||||
'''
|
||||
return _set_powercfg_value("hibernate-timeout", power, timeout)
|
||||
|
||||
|
||||
def get_hibernate_timeout():
|
||||
'''
|
||||
Get the current hibernate timeout of the current scheme
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' powercfg.get_hibernate_timeout
|
||||
'''
|
||||
return _get_powercfg_minute_values(_get_current_scheme(), "SUB_SLEEP", "HIBERNATEIDLE")
|
||||
|
||||
|
95
salt/states/win_powercfg.py
Normal file
95
salt/states/win_powercfg.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
|
||||
This module allows you to control the power settings of a windows minion via
|
||||
powercfg
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
monitor:
|
||||
powercfg.set_timeout:
|
||||
- value: 30
|
||||
- power: dc
|
||||
'''
|
||||
|
||||
# Import python libs
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
__virtualname__ = "powercfg"
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only work on Windows
|
||||
'''
|
||||
if __grains__['os'] == 'Windows':
|
||||
return __virtualname__
|
||||
return False
|
||||
|
||||
|
||||
def _check_or_set(check_func, set_func, value, power):
|
||||
values = check_func()
|
||||
if values[power] == value:
|
||||
return True
|
||||
else:
|
||||
set_func(value, power)
|
||||
return False
|
||||
|
||||
|
||||
def set_timeout(name, value, power="ac"):
|
||||
'''
|
||||
Set the sleep timeouts of specific items such as disk, monitor.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
monitor:
|
||||
powercfg.set_timeout:
|
||||
- value: 30
|
||||
- power: dc
|
||||
|
||||
disk:
|
||||
powercfg.set_timeout:
|
||||
- value: 12
|
||||
- power: ac
|
||||
|
||||
name
|
||||
The setting to change, can be one of the following: monitor, disk, standby, hibernate
|
||||
|
||||
timeout
|
||||
The amount of time in minutes before the item will timeout i.e the monitor
|
||||
|
||||
power
|
||||
Should we set the value for AC or DC (battery)? Valid options ac,dc.
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'result': True,
|
||||
'comment': '',
|
||||
'changes': {}}
|
||||
|
||||
comment = []
|
||||
|
||||
if name not in ["monitor", "disk", "standby", "hibernate"]:
|
||||
ret["result"] = False
|
||||
comment.append("{0} is not a valid setting".format(name))
|
||||
elif power not in ["ac", "dc"]:
|
||||
ret["result"] = False
|
||||
comment.append("{0} is not a power type".format(power))
|
||||
else:
|
||||
check_func = __salt__["powercfg.get_{0}_timeout".format(name)]
|
||||
set_func = __salt__["powercfg.set_{0}_timeout".format(name)]
|
||||
|
||||
values = check_func()
|
||||
if values[power] == value:
|
||||
comment.append ("{0} {1} is already set with the value {2}.".format(name, power, value))
|
||||
else:
|
||||
ret['changes'] = {name: {power: value}}
|
||||
set_func(value, power)
|
||||
|
||||
ret['comment'] = ' '.join(comment)
|
||||
return ret
|
0
tests/runtests.py
Normal file → Executable file
0
tests/runtests.py
Normal file → Executable file
150
tests/unit/modules/win_powercfg_test.py
Normal file
150
tests/unit/modules/win_powercfg_test.py
Normal file
|
@ -0,0 +1,150 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.modules import win_powercfg as powercfg
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import skipIf, TestCase
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
from salttesting.mock import (
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON,
|
||||
MagicMock,
|
||||
patch,
|
||||
call
|
||||
)
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
powercfg.__salt__ = {}
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class PowerCfgTestCase(TestCase):
|
||||
query_ouput = '''Subgroup GUID: 238c9fa8-0aad-41ed-83f4-97be242c8f20 (Hibernate)
|
||||
GUID Alias: SUB_SLEEP
|
||||
Power Setting GUID: 29f6c1db-86da-48c5-9fdb-f2b67b1f44da (Hibernate after)
|
||||
GUID Alias: HIBERNATEIDLE
|
||||
Minimum Possible Setting: 0x00000000
|
||||
Maximum Possible Setting: 0xffffffff
|
||||
Possible Settings increment: 0x00000001
|
||||
Possible Settings units: Seconds
|
||||
Current AC Power Setting Index: 0x00000708
|
||||
Current DC Power Setting Index: 0x00000384'''
|
||||
|
||||
'''
|
||||
Validate the powercfg state
|
||||
'''
|
||||
def test_set_monitor_timeout(self):
|
||||
'''
|
||||
Test to make sure we can set the monitor timeout value
|
||||
'''
|
||||
mock = MagicMock(return_value="")
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
powercfg.set_monitor_timeout(0, "dc")
|
||||
mock.assert_called_once_with('powercfg /x monitor-timeout-dc 0', python_shell=False)
|
||||
|
||||
def test_set_disk_timeout(self):
|
||||
'''
|
||||
Test to make sure we can set the disk timeout value
|
||||
'''
|
||||
mock = MagicMock(return_value="")
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
powercfg.set_disk_timeout(0, "dc")
|
||||
mock.assert_called_once_with('powercfg /x disk-timeout-dc 0', python_shell=False)
|
||||
|
||||
def test_set_standby_timeout(self):
|
||||
'''
|
||||
Test to make sure we can set the standby timeout value
|
||||
'''
|
||||
mock = MagicMock(return_value="")
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
powercfg.set_standby_timeout(0, "dc")
|
||||
mock.assert_called_once_with('powercfg /x standby-timeout-dc 0', python_shell=False)
|
||||
|
||||
|
||||
def test_set_hibernate_timeout(self):
|
||||
'''
|
||||
Test to make sure we can set the hibernate timeout value
|
||||
'''
|
||||
mock = MagicMock(return_value="")
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
powercfg.set_hibernate_timeout(0, "dc")
|
||||
mock.assert_called_once_with('powercfg /x hibernate-timeout-dc 0', python_shell=False)
|
||||
|
||||
|
||||
def test_get_monitor_timeout(self):
|
||||
'''
|
||||
Test to make sure we can get the monitor timeout value
|
||||
'''
|
||||
mock = MagicMock()
|
||||
mock.side_effect = ["Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", self.query_ouput]
|
||||
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
ret = powercfg.get_monitor_timeout()
|
||||
calls = [
|
||||
call('powercfg /getactivescheme', python_shell=False),
|
||||
call('powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_VIDEO VIDEOIDLE', python_shell=False)
|
||||
]
|
||||
mock.assert_has_calls(calls)
|
||||
|
||||
self.assertEqual({'ac': 30, 'dc': 15}, ret)
|
||||
|
||||
|
||||
def test_get_disk_timeout(self):
|
||||
'''
|
||||
Test to make sure we can get the disk timeout value
|
||||
'''
|
||||
mock = MagicMock()
|
||||
mock.side_effect = ["Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", self.query_ouput]
|
||||
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
ret = powercfg.get_disk_timeout()
|
||||
calls = [
|
||||
call('powercfg /getactivescheme', python_shell=False),
|
||||
call('powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_DISK DISKIDLE', python_shell=False)
|
||||
]
|
||||
mock.assert_has_calls(calls)
|
||||
|
||||
self.assertEqual({'ac': 30, 'dc': 15}, ret)
|
||||
|
||||
def test_get_standby_timeout(self):
|
||||
'''
|
||||
Test to make sure we can get the standby timeout value
|
||||
'''
|
||||
mock = MagicMock()
|
||||
mock.side_effect = ["Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", self.query_ouput]
|
||||
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
ret = powercfg.get_standby_timeout()
|
||||
calls = [
|
||||
call('powercfg /getactivescheme', python_shell=False),
|
||||
call('powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP STANDBYIDLE', python_shell=False)
|
||||
]
|
||||
mock.assert_has_calls(calls)
|
||||
|
||||
self.assertEqual({'ac': 30, 'dc': 15}, ret)
|
||||
|
||||
def test_get_hibernate_timeout(self):
|
||||
'''
|
||||
Test to make sure we can get the hibernate timeout value
|
||||
'''
|
||||
mock = MagicMock()
|
||||
mock.side_effect = ["Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced)", self.query_ouput]
|
||||
|
||||
with patch.dict(powercfg.__salt__, {'cmd.run': mock}):
|
||||
ret = powercfg.get_hibernate_timeout()
|
||||
calls = [
|
||||
call('powercfg /getactivescheme', python_shell=False),
|
||||
call('powercfg /q 381b4222-f694-41f0-9685-ff5bb260df2e SUB_SLEEP HIBERNATEIDLE', python_shell=False)
|
||||
]
|
||||
mock.assert_has_calls(calls)
|
||||
|
||||
self.assertEqual({'ac': 30, 'dc': 15}, ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(PowerCfgTestCase, needs_daemon=False)
|
68
tests/unit/states/win_powercfg_test.py
Normal file
68
tests/unit/states/win_powercfg_test.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Import Python libs
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Salt Libs
|
||||
from salt.states import win_powercfg as powercfg
|
||||
|
||||
# Import Salt Testing Libs
|
||||
from salttesting import skipIf, TestCase
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
from salttesting.mock import (
|
||||
NO_MOCK,
|
||||
NO_MOCK_REASON,
|
||||
MagicMock,
|
||||
patch
|
||||
)
|
||||
|
||||
ensure_in_syspath('../../')
|
||||
|
||||
powercfg.__salt__ = {}
|
||||
|
||||
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||
class PowerCfgTestCase(TestCase):
|
||||
'''
|
||||
Validate the powercfg state
|
||||
'''
|
||||
def test_set_monitor(self):
|
||||
'''
|
||||
Test to make sure we can set the monitor timeout value
|
||||
'''
|
||||
ret = {'changes': {'monitor': {'ac': 0}}, 'comment': '', 'name': 'monitor', 'result': True}
|
||||
monitor_val = {"ac": 45, "dc": 22}
|
||||
with patch.dict(powercfg.__salt__, {"powercfg.get_monitor_timeout": MagicMock(return_value=monitor_val),
|
||||
"powercfg.set_monitor_timeout": MagicMock(return_value=True)}):
|
||||
|
||||
self.assertEqual(powercfg.set_timeout("monitor", 0), ret)
|
||||
|
||||
def test_set_monitor_already_set(self):
|
||||
'''
|
||||
Test to make sure we can set the monitor timeout value
|
||||
'''
|
||||
ret = {'changes': {}, 'comment': 'monitor ac is already set with the value 0.', 'name': 'monitor', 'result': True}
|
||||
monitor_val = {"ac": 0, "dc": 0}
|
||||
with patch.dict(powercfg.__salt__, {"powercfg.get_monitor_timeout": MagicMock(return_value=monitor_val),
|
||||
"powercfg.set_monitor_timeout": MagicMock(return_value=True)}):
|
||||
|
||||
self.assertEqual(powercfg.set_timeout("monitor", 0), ret)
|
||||
|
||||
def test_fail_invalid_setting(self):
|
||||
'''
|
||||
Test to make sure we can set the monitor timeout value
|
||||
'''
|
||||
ret = {'changes': {}, 'comment': 'fakesetting is not a valid setting', 'name': 'fakesetting', 'result': False}
|
||||
self.assertEqual(powercfg.set_timeout("fakesetting", 0), ret)
|
||||
|
||||
|
||||
def test_fail_invalid_power(self):
|
||||
'''
|
||||
Test to make sure we can set the monitor timeout value
|
||||
'''
|
||||
ret = {'changes': {}, 'comment': 'fakepower is not a power type', 'name': 'monitor', 'result': False}
|
||||
self.assertEqual(powercfg.set_timeout("monitor", 0, power="fakepower"), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
run_tests(PowerCfgTestCase, needs_daemon=False)
|
Loading…
Add table
Reference in a new issue