Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport #51379 #56792

Merged
merged 3 commits into from
Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Versions are `MAJOR.PATCH`.

### Added
- [#56627](https://github.com/saltstack/salt/pull/56627) - Add new salt-ssh set_path option
- [#51379](https://github.com/saltstack/salt/pull/56792) - Backport 51379 : Adds .set_domain_workgroup to win_system

## 3000.1

Expand Down
235 changes: 127 additions & 108 deletions salt/modules/win_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,14 @@
import salt.utils.platform
import salt.utils.winapi
from salt.exceptions import CommandExecutionError

# Import 3rd-party Libs
from salt.ext import six

try:
import wmi
import win32net
import pywintypes
import win32api
import win32con
import pywintypes
import win32net
import wmi
from ctypes import windll

HAS_WIN32NET_MODS = True
Expand Down Expand Up @@ -555,29 +553,6 @@ def byte_calc(val):

# Lookup dicts for Win32_OperatingSystem
os_type = {1: "Work Station", 2: "Domain Controller", 3: "Server"}
# Connect to WMI
with salt.utils.winapi.Com():
conn = wmi.WMI()
system = conn.Win32_OperatingSystem()[0]
ret = {
"name": get_computer_name(),
"description": system.Description,
"install_date": system.InstallDate,
"last_boot": system.LastBootUpTime,
"os_manufacturer": system.Manufacturer,
"os_name": system.Caption,
"users": system.NumberOfUsers,
"organization": system.Organization,
"os_architecture": system.OSArchitecture,
"primary": system.Primary,
"os_type": os_type[system.ProductType],
"registered_user": system.RegisteredUser,
"system_directory": system.SystemDirectory,
"system_drive": system.SystemDrive,
"os_version": system.Version,
"windows_directory": system.WindowsDirectory,
}

# lookup dicts for Win32_ComputerSystem
domain_role = {
0: "Standalone Workstation",
Expand Down Expand Up @@ -606,75 +581,92 @@ def byte_calc(val):
7: "Performance Server",
8: "Maximum",
}
# Must get chassis_sku_number this way for backwards compatibility
# system.ChassisSKUNumber is only available on Windows 10/2016 and newer
product = conn.Win32_ComputerSystemProduct()[0]
ret.update({"chassis_sku_number": product.SKUNumber})
system = conn.Win32_ComputerSystem()[0]
# Get pc_system_type depending on Windows version
if platform.release() in ["Vista", "7", "8"]:
# Types for Vista, 7, and 8
pc_system_type = pc_system_types[system.PCSystemType]
else:
# New types were added with 8.1 and newer
pc_system_types.update({8: "Slate", 9: "Maximum"})
pc_system_type = pc_system_types[system.PCSystemType]
ret.update(
{
"bootup_state": system.BootupState,
"caption": system.Caption,
"chassis_bootup_state": warning_states[system.ChassisBootupState],
"dns_hostname": system.DNSHostname,
"domain": system.Domain,
"domain_role": domain_role[system.DomainRole],
"hardware_manufacturer": system.Manufacturer,
"hardware_model": system.Model,
"network_server_mode_enabled": system.NetworkServerModeEnabled,
"part_of_domain": system.PartOfDomain,
"pc_system_type": pc_system_type,
"power_state": system.PowerState,
"status": system.Status,
"system_type": system.SystemType,
"total_physical_memory": byte_calc(system.TotalPhysicalMemory),
"total_physical_memory_raw": system.TotalPhysicalMemory,
"thermal_state": warning_states[system.ThermalState],
"workgroup": system.Workgroup,
}
)
# Get processor information
processors = conn.Win32_Processor()
ret["processors"] = 0
ret["processors_logical"] = 0
ret["processor_cores"] = 0
ret["processor_cores_enabled"] = 0
ret["processor_manufacturer"] = processors[0].Manufacturer
ret["processor_max_clock_speed"] = (
six.text_type(processors[0].MaxClockSpeed) + "MHz"
)
for system in processors:
ret["processors"] += 1
ret["processors_logical"] += system.NumberOfLogicalProcessors
ret["processor_cores"] += system.NumberOfCores
try:
ret["processor_cores_enabled"] += system.NumberOfEnabledCore
except (AttributeError, TypeError):
pass
if ret["processor_cores_enabled"] == 0:
ret.pop("processor_cores_enabled", False)

system = conn.Win32_BIOS()[0]
ret.update(
{
"hardware_serial": system.SerialNumber,
"bios_manufacturer": system.Manufacturer,
"bios_version": system.Version,
"bios_details": system.BIOSVersion,
"bios_caption": system.Caption,
"bios_description": system.Description,

# Connect to WMI
with salt.utils.winapi.Com():
conn = wmi.WMI()

system = conn.Win32_OperatingSystem()[0]
ret = {
"name": get_computer_name(),
"description": system.Description,
"install_date": system.InstallDate,
"last_boot": system.LastBootUpTime,
"os_manufacturer": system.Manufacturer,
"os_name": system.Caption,
"users": system.NumberOfUsers,
"organization": system.Organization,
"os_architecture": system.OSArchitecture,
"primary": system.Primary,
"os_type": os_type[system.ProductType],
"registered_user": system.RegisteredUser,
"system_directory": system.SystemDirectory,
"system_drive": system.SystemDrive,
"os_version": system.Version,
"windows_directory": system.WindowsDirectory,
}
)
ret["install_date"] = _convert_date_time_string(ret["install_date"])
ret["last_boot"] = _convert_date_time_string(ret["last_boot"])

system = conn.Win32_ComputerSystem()[0]
# Get pc_system_type depending on Windows version
if platform.release() in ["Vista", "7", "8"]:
# Types for Vista, 7, and 8
pc_system_type = pc_system_types[system.PCSystemType]
else:
# New types were added with 8.1 and newer
pc_system_types.update({8: "Slate", 9: "Maximum"})
pc_system_type = pc_system_types[system.PCSystemType]
ret.update(
{
"bootup_state": system.BootupState,
"caption": system.Caption,
"chassis_bootup_state": warning_states[system.ChassisBootupState],
"chassis_sku_number": system.ChassisSKUNumber,
"dns_hostname": system.DNSHostname,
"domain": system.Domain,
"domain_role": domain_role[system.DomainRole],
"hardware_manufacturer": system.Manufacturer,
"hardware_model": system.Model,
"network_server_mode_enabled": system.NetworkServerModeEnabled,
"part_of_domain": system.PartOfDomain,
"pc_system_type": pc_system_type,
"power_state": system.PowerState,
"status": system.Status,
"system_type": system.SystemType,
"total_physical_memory": byte_calc(system.TotalPhysicalMemory),
"total_physical_memory_raw": system.TotalPhysicalMemory,
"thermal_state": warning_states[system.ThermalState],
"workgroup": system.Workgroup,
}
)
# Get processor information
processors = conn.Win32_Processor()
ret["processors"] = 0
ret["processors_logical"] = 0
ret["processor_cores"] = 0
ret["processor_cores_enabled"] = 0
ret["processor_manufacturer"] = processors[0].Manufacturer
ret["processor_max_clock_speed"] = (
six.text_type(processors[0].MaxClockSpeed) + "MHz"
)
for processor in processors:
ret["processors"] += 1
ret["processors_logical"] += processor.NumberOfLogicalProcessors
ret["processor_cores"] += processor.NumberOfCores
ret["processor_cores_enabled"] += processor.NumberOfEnabledCore

bios = conn.Win32_BIOS()[0]
ret.update(
{
"hardware_serial": bios.SerialNumber,
"bios_manufacturer": bios.Manufacturer,
"bios_version": bios.Version,
"bios_details": bios.BIOSVersion,
"bios_caption": bios.Caption,
"bios_description": bios.Description,
}
)
ret["install_date"] = _convert_date_time_string(ret["install_date"])
ret["last_boot"] = _convert_date_time_string(ret["last_boot"])
return ret


Expand Down Expand Up @@ -742,13 +734,10 @@ def set_hostname(hostname):

salt 'minion-id' system.set_hostname newhostname
"""
curr_hostname = get_hostname()
cmd = "wmic computersystem where name='{0}' call rename name='{1}'".format(
curr_hostname, hostname
)
ret = __salt__["cmd.run"](cmd=cmd)

return "successful" in ret
with salt.utils.winapi.Com():
conn = wmi.WMI()
comp = conn.Win32_ComputerSystem()[0]
return comp.Rename(Name=hostname)


def join_domain(
Expand Down Expand Up @@ -1034,11 +1023,41 @@ def get_domain_workgroup():
"""
with salt.utils.winapi.Com():
conn = wmi.WMI()
for computer in conn.Win32_ComputerSystem():
if computer.PartOfDomain:
return {"Domain": computer.Domain}
else:
return {"Workgroup": computer.Domain}
for computer in conn.Win32_ComputerSystem():
if computer.PartOfDomain:
return {"Domain": computer.Domain}
else:
return {"Workgroup": computer.Domain}


def set_domain_workgroup(workgroup):
"""
Set the domain or workgroup the computer belongs to.

.. versionadded:: Sodium

Returns:
bool: ``True`` if successful, otherwise ``False``

CLI Example:

.. code-block:: bash

salt 'minion-id' system.set_domain_workgroup LOCAL
"""
if six.PY2:
workgroup = _to_unicode(workgroup)

# Initialize COM
with salt.utils.winapi.Com():
# Grab the first Win32_ComputerSystem object from wmi
conn = wmi.WMI()
comp = conn.Win32_ComputerSystem()[0]

# Now we can join the new workgroup
res = comp.JoinDomainOrWorkgroup(Name=workgroup.upper())

return True if not res[0] else False


def _try_parse_datetime(time_str, fmts):
Expand Down
91 changes: 85 additions & 6 deletions salt/states/win_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
# Import Salt libs
import salt.utils.functools
import salt.utils.platform

# Import 3rd party libs
from salt.ext import six

log = logging.getLogger(__name__)
Expand All @@ -36,11 +34,13 @@

def __virtual__():
"""
This only supports Windows
Make sure this Windows and that the win_system module is available
"""
if salt.utils.platform.is_windows() and "system.get_computer_desc" in __salt__:
return __virtualname__
return (False, "system module could not be loaded")
if not salt.utils.platform.is_windows():
return False, "win_system: Only available on Windows"
if "system.get_computer_desc" not in __salt__:
return False, "win_system: win_system execution module not available"
return __virtualname__


def computer_desc(name):
Expand Down Expand Up @@ -172,6 +172,85 @@ def hostname(name):
return ret


def workgroup(name):
"""
.. versionadded:: Sodium

Manage the workgroup of the computer

Args:
name (str): The workgroup to set

Example:

.. code-block:: yaml

set workgroup:
system.workgroup:
- name: local
"""
ret = {"name": name.upper(), "result": False, "changes": {}, "comment": ""}

# Grab the current domain/workgroup
out = __salt__["system.get_domain_workgroup"]()
current_workgroup = (
out["Domain"]
if "Domain" in out
else out["Workgroup"]
if "Workgroup" in out
else ""
)

# Notify the user if the requested workgroup is the same
if current_workgroup.upper() == name.upper():
ret["result"] = True
ret["comment"] = "Workgroup is already set to '{0}'".format(name.upper())
return ret

# If being run in test-mode, inform the user what is supposed to happen
if __opts__["test"]:
ret["result"] = None
ret["changes"] = {}
ret["comment"] = "Computer will be joined to workgroup '{0}'".format(name)
return ret

# Set our new workgroup, and then immediately ask the machine what it
# is again to validate the change
res = __salt__["system.set_domain_workgroup"](name.upper())
out = __salt__["system.get_domain_workgroup"]()
new_workgroup = (
out["Domain"]
if "Domain" in out
else out["Workgroup"]
if "Workgroup" in out
else ""
)

# Return our results based on the changes
ret = {}
if res and current_workgroup.upper() == new_workgroup.upper():
ret["result"] = True
ret["comment"] = "The new workgroup '{0}' is the same as '{1}'".format(
current_workgroup.upper(), new_workgroup.upper()
)
elif res:
ret["result"] = True
ret["comment"] = "The workgroup has been changed from '{0}' to '{1}'".format(
current_workgroup.upper(), new_workgroup.upper()
)
ret["changes"] = {
"old": current_workgroup.upper(),
"new": new_workgroup.upper(),
}
else:
ret["result"] = False
ret["comment"] = "Unable to join the requested workgroup '{0}'".format(
new_workgroup.upper()
)

return ret


def join_domain(
name,
username=None,
Expand Down
Loading