Merge pull request #33654 from twangboy/fix_win_servermanager

Fix win servermanager
This commit is contained in:
Mike Place 2016-06-02 10:55:45 -07:00
commit 8a566ff4b9
3 changed files with 115 additions and 56 deletions

View File

@ -83,8 +83,9 @@ def list_available():
salt '*' win_servermanager.list_available
'''
cmd = 'Import-Module ServerManager; ' \
'Get-WindowsFeature -erroraction silentlycontinue ' \
'-warningaction silentlycontinue'
'Get-WindowsFeature ' \
'-ErrorAction SilentlyContinue ' \
'-WarningAction SilentlyContinue'
return __salt__['cmd.shell'](cmd, shell='powershell')
@ -102,9 +103,10 @@ def list_installed():
salt '*' win_servermanager.list_installed
'''
cmd = 'Get-WindowsFeature -erroraction silentlycontinue ' \
'-warningaction silentlycontinue | ' \
'Select DisplayName,Name,Installed'
cmd = 'Get-WindowsFeature ' \
'-ErrorAction SilentlyContinue ' \
'-WarningAction SilentlyContinue ' \
'| Select DisplayName,Name,Installed'
features = _pshell_json(cmd)
ret = {}
@ -115,7 +117,7 @@ def list_installed():
return ret
def install(feature, recurse=False):
def install(feature, recurse=False, source=None, restart=False):
'''
Install a feature
@ -129,7 +131,14 @@ def install(feature, recurse=False):
:param str feature: The name of the feature to install
:param bool recurse: Install all sub-features
:param bool recurse: Install all sub-features. Default is False
:param str source: Path to the source files if missing from the target
system. None means that the system will use windows update services to
find the required files. Default is None
:param bool restart: Restarts the computer when installation is complete, if
required by the role/feature installed. Default is False
:return: A dictionary containing the results of the install
:rtype: dict
@ -140,14 +149,28 @@ def install(feature, recurse=False):
salt '*' win_servermanager.install Telnet-Client
salt '*' win_servermanager.install SNMP-Service True
salt '*' win_servermanager.install TFTP-Client source=d:\\side-by-side
'''
mgmt_tools = ''
if salt.utils.version_cmp(__grains__['osversion'], '6.2') >= 0:
mgmt_tools = '-IncludeManagementTools'
sub = ''
if recurse:
sub = '-IncludeAllSubFeature'
cmd = 'Add-WindowsFeature -Name {0} {1} ' \
rst = ''
if restart:
rst = '-Restart'
src = ''
if source is not None:
src = '-Source {0}'.format(source)
cmd = 'Add-WindowsFeature -Name {0} {1} {2} {3} {4} ' \
'-ErrorAction SilentlyContinue ' \
'-WarningAction SilentlyContinue'.format(_cmd_quote(feature), sub)
'-WarningAction SilentlyContinue'\
.format(_cmd_quote(feature), mgmt_tools, sub, src, rst)
out = _pshell_json(cmd)
if out['FeatureResult']:
@ -162,8 +185,8 @@ def install(feature, recurse=False):
'Success': out['Success']}
def remove(feature):
'''
def remove(feature, remove_payload=False, restart=False):
r'''
Remove an installed feature
.. note::
@ -175,6 +198,13 @@ def remove(feature):
:param str feature: The name of the feature to remove
:param bool remove_payload: True will cause the feature to be removed from
the side-by-side store (``%SystemDrive%:\Windows\WinSxS``). Default is
False
:param bool restart: Restarts the computer when uninstall is complete, if
required by the role/feature removed. Default is False
:return: A dictionary containing the results of the uninstall
:rtype: dict
@ -184,9 +214,22 @@ def remove(feature):
salt -t 600 '*' win_servermanager.remove Telnet-Client
'''
cmd = 'Remove-WindowsFeature -Name {0} ' \
mgmt_tools = ''
if salt.utils.version_cmp(__grains__['osversion'], '6.2') >= 0:
mgmt_tools = '-IncludeManagementTools'
rmv = ''
if remove_payload:
rmv = '-Remove'
rst = ''
if restart:
rst = '-Restart'
cmd = 'Remove-WindowsFeature -Name {0} {1} {2} {3} ' \
'-ErrorAction SilentlyContinue ' \
'-WarningAction SilentlyContinue'.format(_cmd_quote(feature))
'-WarningAction SilentlyContinue'\
.format(_cmd_quote(feature), mgmt_tools, rmv, rst)
out = _pshell_json(cmd)
if out['FeatureResult']:

View File

@ -14,29 +14,33 @@ def __virtual__():
return 'win_servermanager' if 'win_servermanager.install' in __salt__ else False
def installed(name, recurse=False, force=False):
def installed(name, recurse=False, force=False, source=None, restart=False):
'''
Install the windows feature
name:
short name of the feature (the right column in win_servermanager.list_available)
recurse:
install all sub-features as well
force:
if the feature is installed but on of its sub-features are not installed set this to True to force
the installation of the sub-features
Args:
name (str): Short name of the feature (the right column in
win_servermanager.list_available)
recurse (Optional[bool]): install all sub-features as well
force (Optional[bool]): if the feature is installed but one of its
sub-features are not installed set this to True to force the
installation of the sub-features
source (Optional[str]): Path to the source files if missing from the
target system. None means that the system will use windows update
services to find the required files. Default is None
restart (Optional[bool]): Restarts the computer when installation is
complete, if required by the role/feature installed. Default is
False
Note:
Some features require reboot after un/installation. If so, until the server is restarted
other features can not be installed!
Some features require reboot after un/installation. If so, until the
server is restarted other features can not be installed!
Example:
Run ``salt MinionName win_servermanager.list_available`` to get a list of available roles and features. Use
the name in the right column. Do not use the role or feature names mentioned in the PKGMGR documentation. In
this example for IIS-WebServerRole the name to be used is Web-Server.
Run ``salt MinionName win_servermanager.list_available`` to get a list
of available roles and features. Use the name in the right column. Do
not use the role or feature names mentioned in the PKGMGR documentation.
In this example for IIS-WebServerRole the name to be used is Web-Server.
.. code-block:: yaml
@ -73,7 +77,8 @@ def installed(name, recurse=False, force=False):
ret['changes'] = {}
# Install the features
status = __salt__['win_servermanager.install'](name, recurse)
status = __salt__['win_servermanager.install'](
name, recurse, source, restart)
ret['result'] = status['Success']
if not ret['result']:
@ -91,23 +96,27 @@ def installed(name, recurse=False, force=False):
return ret
def removed(name):
def removed(name, remove_payload=False, restart=False):
'''
Remove the windows feature
name:
short name of the feature (the right column in win_servermanager.list_available)
Args:
name (str): Short name of the feature (the right column in
win_servermanager.list_available)
remove_payload (Optional[bool]): True will case the feature to be
removed from the side-by-side store
restart (Optional[bool]): Restarts the computer when uninstall is
complete, if required by the role/feature removed. Default is False
.. note::
Some features require a reboot after uninstallation. If so the feature will not be completely uninstalled until
the server is restarted.
Note:
Some features require a reboot after uninstallation. If so the feature
will not be completely uninstalled until the server is restarted.
Example:
Run ``salt MinionName win_servermanager.list_installed`` to get a list of all features installed. Use the top
name listed for each feature, not the indented one. Do not use the role or feature names mentioned in the
PKGMGR documentation.
Run ``salt MinionName win_servermanager.list_installed`` to get a list
of all features installed. Use the top name listed for each feature, not
the indented one. Do not use the role or feature names mentioned in the
PKGMGR documentation.
.. code-block:: yaml
@ -134,7 +143,7 @@ def removed(name):
ret['changes'] = {}
# Remove the features
status = __salt__['win_servermanager.remove'](name)
status = __salt__['win_servermanager.remove'](name, remove_payload, restart)
ret['result'] = status['Success']
if not ret['result']:

View File

@ -18,6 +18,7 @@ from salt.modules import win_servermanager
# Globals
win_servermanager.__salt__ = {}
win_servermanager.__grains__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
@ -56,13 +57,16 @@ class WinServermanagerTestCase(TestCase):
'FeatureResult':
[{'DisplayName': 'Spongebob',
'RestartNeeded': False}]})
with patch.object(win_servermanager, '_pshell_json', mock):
expected = {'ExitCode': 0,
'DisplayName': 'Spongebob',
'RestartNeeded': False,
'Success': True}
self.assertDictEqual(
win_servermanager.install('Telnet-Client'), expected)
grain_mock = MagicMock(return_value='10.0.15130')
with patch.dict(
win_servermanager.__grains__, {'osversion': grain_mock}):
with patch.object(win_servermanager, '_pshell_json', mock):
expected = {'ExitCode': 0,
'DisplayName': 'Spongebob',
'RestartNeeded': False,
'Success': True}
self.assertDictEqual(
win_servermanager.install('Telnet-Client'), expected)
def test_remove(self):
'''
@ -73,13 +77,16 @@ class WinServermanagerTestCase(TestCase):
'FeatureResult':
[{'DisplayName': 'Spongebob',
'RestartNeeded': False}]})
with patch.object(win_servermanager, '_pshell_json', mock):
expected = {'ExitCode': 0,
'DisplayName': 'Spongebob',
'RestartNeeded': False,
'Success': True}
self.assertDictEqual(
win_servermanager.remove('Telnet-Client'), expected)
grain_mock = MagicMock(return_value='10.0.15130')
with patch.dict(
win_servermanager.__grains__, {'osversion': grain_mock}):
with patch.object(win_servermanager, '_pshell_json', mock):
expected = {'ExitCode': 0,
'DisplayName': 'Spongebob',
'RestartNeeded': False,
'Success': True}
self.assertDictEqual(
win_servermanager.remove('Telnet-Client'), expected)
if __name__ == '__main__':