1""" 2Common functions for working with powershell 3 4.. note:: The PSModulePath environment variable should be set to the default 5 location for PowerShell modules. This applies to all OS'es that support 6 powershell. If not set, then Salt will attempt to use some default paths. 7 If Salt can't find your modules, ensure that the PSModulePath is set and 8 pointing to all locations of your Powershell modules. 9""" 10 11import logging 12import os 13 14import salt.utils.path 15 16log = logging.getLogger(__name__) 17 18 19def module_exists(name): 20 """ 21 Check if a module exists on the system. 22 23 Use this utility instead of attempting to import the module with powershell. 24 Using powershell to try to import the module is expensive. 25 26 Args: 27 28 name (str): 29 The name of the module to check 30 31 Returns: 32 bool: True if present, otherwise returns False 33 34 Example: 35 36 .. code-block:: python 37 38 import salt.utils.powershell 39 exists = salt.utils.powershell.module_exists('ServerManager') 40 """ 41 return name in get_modules() 42 43 44def get_modules(): 45 """ 46 Get a list of the PowerShell modules which are potentially available to be 47 imported. The intent is to mimic the functionality of ``Get-Module 48 -ListAvailable | Select-Object -Expand Name``, without the delay of loading 49 PowerShell to do so. 50 51 Returns: 52 list: A list of modules available to Powershell 53 54 Example: 55 56 .. code-block:: python 57 58 import salt.utils.powershell 59 modules = salt.utils.powershell.get_modules() 60 """ 61 ret = list() 62 valid_extensions = (".psd1", ".psm1", ".cdxml", ".xaml", ".dll") 63 # need to create an info function to get PS information including version 64 # __salt__ is not available from salt.utils... need to create a salt.util 65 # for the registry to avoid loading powershell to get the version 66 # not sure how to get the powershell version in linux outside of powershell 67 # if running powershell to get version need to use subprocess.Popen 68 # That information will be loaded here 69 # ps_version = info()['version_raw'] 70 root_paths = [] 71 72 home_dir = os.environ.get("HOME", os.environ.get("HOMEPATH")) 73 system_dir = "{}\\System32".format(os.environ.get("WINDIR", "C:\\Windows")) 74 program_files = os.environ.get("ProgramFiles", "C:\\Program Files") 75 default_paths = [ 76 "{}/.local/share/powershell/Modules".format(home_dir), 77 # Once version is available, these can be enabled 78 # '/opt/microsoft/powershell/{0}/Modules'.format(ps_version), 79 # '/usr/local/microsoft/powershell/{0}/Modules'.format(ps_version), 80 "/usr/local/share/powershell/Modules", 81 "{}\\WindowsPowerShell\\v1.0\\Modules\\".format(system_dir), 82 "{}\\WindowsPowerShell\\Modules".format(program_files), 83 ] 84 default_paths = ";".join(default_paths) 85 86 ps_module_path = os.environ.get("PSModulePath", default_paths) 87 88 # Check if defaults exist, add them if they do 89 ps_module_path = ps_module_path.split(";") 90 for item in ps_module_path: 91 if os.path.exists(item): 92 root_paths.append(item) 93 94 # Did we find any, if not log the error and return 95 if not root_paths: 96 log.error("Default paths not found") 97 return ret 98 99 for root_path in root_paths: 100 101 # only recurse directories 102 if not os.path.isdir(root_path): 103 continue 104 105 # get a list of all files in the root_path 106 for root_dir, sub_dirs, file_names in salt.utils.path.os_walk(root_path): 107 for file_name in file_names: 108 base_name, file_extension = os.path.splitext(file_name) 109 110 # If a module file or module manifest is present, check if 111 # the base name matches the directory name. 112 113 if file_extension.lower() in valid_extensions: 114 dir_name = os.path.basename(os.path.normpath(root_dir)) 115 116 # Stop recursion once we find a match, and use 117 # the capitalization from the directory name. 118 if dir_name not in ret and base_name.lower() == dir_name.lower(): 119 del sub_dirs[:] 120 ret.append(dir_name) 121 122 return ret 123