Add new options to salt cloud for Windows installer

This commit is contained in:
Shane Lee 2024-04-16 12:49:57 -06:00 committed by Daniel Wozniak
parent aad71fdbcf
commit 352b83aea7
4 changed files with 127 additions and 21 deletions

2
changelog/61318.added.md Normal file
View file

@ -0,0 +1,2 @@
Added two new options, ``win_delay_start`` and ``win_install_dir``, to pass to
the Windows installer in salt-cloud

View file

@ -31,7 +31,6 @@ which Salt Cloud is running. See
and using the Salt Minion Windows installer.
.. _new-pywinrm:
Self Signed Certificates with WinRM
@ -39,18 +38,18 @@ Self Signed Certificates with WinRM
Salt-Cloud can use versions of ``pywinrm<=0.1.1`` or ``pywinrm>=0.2.1``.
For versions greater than `0.2.1`, ``winrm_verify_ssl`` needs to be set to
`False` if the certificate is self signed and not verifiable.
For versions greater than ``0.2.1``, ``winrm_verify_ssl`` needs to be set to
``False`` if the certificate is self signed and not verifiable.
Firewall Settings
=================
Because Salt Cloud makes use of `smbclient` and `winexe`, port 445 must be open
on the target image. This port is not generally open by default on a standard
Windows distribution, and care must be taken to use an image in which this port
is open, or the Windows firewall is disabled.
Because Salt Cloud makes use of ``smbclient`` and ``winexe``, port 445 must be
open on the target image. This port is not generally open by default on a
standard Windows distribution, and care must be taken to use an image in which
this port is open, or the Windows firewall is disabled.
If supported by the cloud provider, a PowerShell script may be used to open up
this port automatically, using the cloud provider's `userdata`. The following
this port automatically, using the cloud provider's ``userdata``. The following
script would open up port 445, and apply the changes:
.. code-block:: text
@ -62,7 +61,7 @@ script would open up port 445, and apply the changes:
</powershell>
For EC2, this script may be saved as a file, and specified in the provider or
profile configuration as `userdata_file`. For instance:
profile configuration as ``userdata_file``. For instance:
.. code-block:: yaml
@ -142,9 +141,9 @@ the following userdata example:
Restart-Service winrm
</powershell>
No certificate store is available by default on EC2 images and creating
one does not seem possible without an MMC (cannot be automated). To use the
default EC2 Windows images the above copies the RDP store.
No certificate store is available by default on EC2 images and creating one does
not seem possible without an MMC (cannot be automated). To use the default EC2
Windows images the above copies the RDP store.
Configuration
=============
@ -168,23 +167,42 @@ Setting the installer in ``/etc/salt/cloud.providers``:
win_password: letmein
smb_port: 445
The default Windows user is `Administrator`, and the default Windows password
The default Windows user is ``Administrator``, and the default Windows password
is blank.
If WinRM is to be used ``use_winrm`` needs to be set to `True`. ``winrm_port``
If WinRM is to be used ``use_winrm`` needs to be set to ``True``. ``winrm_port``
can be used to specify a custom port (must be HTTPS listener). And
``winrm_verify_ssl`` can be set to `False` to use a self signed certificate.
``winrm_verify_ssl`` can be set to ``False`` to use a self signed certificate.
Two new options have been added to allow you to set some additional parameters
to pass to the installer. ``win_delay_start`` will set the minion service to
start delayed. ``win_install_dir`` will allow you to specify the Salt install
location.
.. code-block:: yaml
my-softlayer:
driver: softlayer
user: MYUSER1138
apikey: 'e3b68aa711e6deadc62d5b76355674beef7cc3116062ddbacafe5f7e465bfdc9'
minion:
master: saltmaster.example.com
win_installer: /root/Salt-Minion-2014.7.0-AMD64-Setup.exe
win_delay_start: True
win_install_dir: D:\Program Files\Salt Project\Salt
win_username: Administrator
win_password: letmein
smb_port: 445
Auto-Generated Passwords on EC2
===============================
On EC2, when the `win_password` is set to `auto`, Salt Cloud will query EC2 for
an auto-generated password. This password is expected to take at least 4 minutes
to generate, adding additional time to the deploy process.
On EC2, when the ``win_password`` is set to ``auto``, Salt Cloud will query EC2
for an auto-generated password. This password is expected to take at least 4
minutes to generate, adding additional time to the deploy process.
When the EC2 API is queried for the auto-generated password, it will be returned
in a message encrypted with the specified `keyname`. This requires that the
appropriate `private_key` file is also specified. Such a profile configuration
in a message encrypted with the specified ``keyname``. This requires that the
appropriate ``private_key`` file is also specified. Such a profile configuration
might look like:
.. code-block:: yaml

View file

@ -574,6 +574,13 @@ def bootstrap(vm_, opts=None):
"smb_port", vm_, opts, default=445
)
deploy_kwargs["win_installer"] = win_installer
deploy_kwargs["win_delay_start"] = salt.config.get_cloud_config_value(
"win_delay_start", vm_, opts, default=""
)
deploy_kwargs["win_install_dir"] = salt.config.get_cloud_config_value(
"win_install_dir", vm_, opts, default=""
)
minion = minion_config(opts, vm_)
deploy_kwargs["master"] = minion["master"]
deploy_kwargs["username"] = salt.config.get_cloud_config_value(
@ -1236,6 +1243,8 @@ def deploy_windows(
port_timeout=15,
preseed_minion_keys=None,
win_installer=None,
win_delay_start=False,
win_install_dir="",
master=None,
tmp_dir="C:\\salttmp",
opts=None,
@ -1357,6 +1366,11 @@ def deploy_windows(
f"/master={_format_master_param(master)}",
f"/minion-name={name}",
]
if win_delay_start:
args.append("/start-minion-delayed")
if win_install_dir:
args.append(f'/install-dir="{win_install_dir}"')
if use_winrm:
winrm_cmd(winrm_session, cmd, args)
@ -1423,7 +1437,7 @@ def deploy_windows(
if ret_code != 0:
return False
log.debug("Run psexec: sc start salt-minion")
log.debug("Run psexec: net start salt-minion")
stdout, stderr, ret_code = run_psexec_command(
"cmd.exe", "/c net start salt-minion", host, username, password
)

View file

@ -449,6 +449,78 @@ def test_deploy_windows_programdata_minion_conf():
mock_smb.put_str.assert_called_with(config, expected, conn=mock_conn)
@pytest.mark.skip_unless_on_windows(reason="Only applicable for Windows.")
def test_deploy_windows_install_delay_start():
mock_true = MagicMock(return_value=True)
mock_tuple = MagicMock(return_value=(0, 0, 0))
mock_conn = MagicMock()
with patch("salt.utils.smb", MagicMock()) as mock_smb:
mock_smb.get_conn.return_value = mock_conn
mock_smb.mkdirs.return_value = None
mock_smb.put_file.return_value = None
mock_smb.put_str.return_value = None
mock_smb.delete_file.return_value = None
mock_smb.delete_directory.return_value = None
with patch("time.sleep", MagicMock()), patch.object(
cloud, "wait_for_port", mock_true
), patch.object(cloud, "fire_event", MagicMock()), patch.object(
cloud, "wait_for_psexecsvc", mock_true
), patch.object(
cloud, "run_psexec_command", mock_tuple
) as mock_psexec:
minion_conf = {"master": "test-master"}
cloud.deploy_windows(
host="test",
minion_conf=minion_conf,
win_installer="install.exe",
win_delay_start=True,
)
mock_psexec.assert_any_call(
"c:\\salttemp\\install.exe",
"/S /master=None /minion-name=None /start-minion-delayed",
"test",
"Administrator",
None,
)
@pytest.mark.skip_unless_on_windows(reason="Only applicable for Windows.")
def test_deploy_windows_install_install_dir():
mock_true = MagicMock(return_value=True)
mock_tuple = MagicMock(return_value=(0, 0, 0))
mock_conn = MagicMock()
with patch("salt.utils.smb", MagicMock()) as mock_smb:
mock_smb.get_conn.return_value = mock_conn
mock_smb.mkdirs.return_value = None
mock_smb.put_file.return_value = None
mock_smb.put_str.return_value = None
mock_smb.delete_file.return_value = None
mock_smb.delete_directory.return_value = None
with patch("time.sleep", MagicMock()), patch.object(
cloud, "wait_for_port", mock_true
), patch.object(cloud, "fire_event", MagicMock()), patch.object(
cloud, "wait_for_psexecsvc", mock_true
), patch.object(
cloud, "run_psexec_command", mock_tuple
) as mock_psexec:
minion_conf = {"master": "test-master"}
cloud.deploy_windows(
host="test",
minion_conf=minion_conf,
win_installer="install.exe",
win_install_dir="C:\\salt",
)
mock_psexec.assert_any_call(
"c:\\salttemp\\install.exe",
'/S /master=None /minion-name=None /install-dir="C:\\salt"',
"test",
"Administrator",
None,
)
@pytest.mark.skip_unless_on_windows(reason="Only applicable for Windows.")
def test_winrm_pinnned_version():
"""