%PDF- %PDF-
Direktori : /lib/python2.7/site-packages/salt/modules/ |
Current File : //lib/python2.7/site-packages/salt/modules/win_status.py |
# -*- coding: utf-8 -*- ''' Module for returning various status data about a minion. These data can be useful for compiling into stats later, or for problem solving if your minion is having problems. .. versionadded:: 0.12.0 :depends: - wmi ''' # Import Python Libs from __future__ import absolute_import, unicode_literals, print_function import ctypes import datetime import logging import subprocess log = logging.getLogger(__name__) # Import Salt Libs import salt.utils.event import salt.utils.platform import salt.utils.stringutils import salt.utils.win_pdh from salt.utils.network import host_to_ips as _host_to_ips from salt.utils.functools import namespaced_function as _namespaced_function # Import 3rd party Libs from salt.ext import six # These imports needed for namespaced functions # pylint: disable=W0611 from salt.modules.status import ping_master, time_ import copy # pylint: enable=W0611 # Import 3rd Party Libs try: if salt.utils.platform.is_windows(): import wmi import salt.utils.winapi HAS_WMI = True else: HAS_WMI = False except ImportError: HAS_WMI = False HAS_PSUTIL = False if salt.utils.platform.is_windows(): import psutil HAS_PSUTIL = True __opts__ = {} __virtualname__ = 'status' # Taken from https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/performance.htm class SYSTEM_PERFORMANCE_INFORMATION(ctypes.Structure): _fields_ = [('IdleProcessTime', ctypes.c_int64), ('IoReadTransferCount', ctypes.c_int64), ('IoWriteTransferCount', ctypes.c_int64), ('IoOtherTransferCount', ctypes.c_int64), ('IoReadOperationCount', ctypes.c_ulong), ('IoWriteOperationCount', ctypes.c_ulong), ('IoOtherOperationCount', ctypes.c_ulong), ('AvailablePages', ctypes.c_ulong), ('CommittedPages', ctypes.c_ulong), ('CommitLimit', ctypes.c_ulong), ('PeakCommitment', ctypes.c_ulong), ('PageFaultCount', ctypes.c_ulong), ('CopyOnWriteCount', ctypes.c_ulong), ('TransitionCount', ctypes.c_ulong), ('CacheTransitionCount', ctypes.c_ulong), ('DemandZeroCount', ctypes.c_ulong), ('PageReadCount', ctypes.c_ulong), ('PageReadIoCount', ctypes.c_ulong), ('CacheReadCount', ctypes.c_ulong), # Was c_ulong ** 2 ('CacheIoCount', ctypes.c_ulong), ('DirtyPagesWriteCount', ctypes.c_ulong), ('DirtyWriteIoCount', ctypes.c_ulong), ('MappedPagesWriteCount', ctypes.c_ulong), ('MappedWriteIoCount', ctypes.c_ulong), ('PagedPoolPages', ctypes.c_ulong), ('NonPagedPoolPages', ctypes.c_ulong), ('PagedPoolAllocs', ctypes.c_ulong), ('PagedPoolFrees', ctypes.c_ulong), ('NonPagedPoolAllocs', ctypes.c_ulong), ('NonPagedPoolFrees', ctypes.c_ulong), ('FreeSystemPtes', ctypes.c_ulong), ('ResidentSystemCodePage', ctypes.c_ulong), ('TotalSystemDriverPages', ctypes.c_ulong), ('TotalSystemCodePages', ctypes.c_ulong), ('NonPagedPoolLookasideHits', ctypes.c_ulong), ('PagedPoolLookasideHits', ctypes.c_ulong), ('AvailablePagedPoolPages', ctypes.c_ulong), ('ResidentSystemCachePage', ctypes.c_ulong), ('ResidentPagedPoolPage', ctypes.c_ulong), ('ResidentSystemDriverPage', ctypes.c_ulong), ('CcFastReadNoWait', ctypes.c_ulong), ('CcFastReadWait', ctypes.c_ulong), ('CcFastReadResourceMiss', ctypes.c_ulong), ('CcFastReadNotPossible', ctypes.c_ulong), ('CcFastMdlReadNoWait', ctypes.c_ulong), ('CcFastMdlReadWait', ctypes.c_ulong), ('CcFastMdlReadResourceMiss', ctypes.c_ulong), ('CcFastMdlReadNotPossible', ctypes.c_ulong), ('CcMapDataNoWait', ctypes.c_ulong), ('CcMapDataWait', ctypes.c_ulong), ('CcMapDataNoWaitMiss', ctypes.c_ulong), ('CcMapDataWaitMiss', ctypes.c_ulong), ('CcPinMappedDataCount', ctypes.c_ulong), ('CcPinReadNoWait', ctypes.c_ulong), ('CcPinReadWait', ctypes.c_ulong), ('CcPinReadNoWaitMiss', ctypes.c_ulong), ('CcPinReadWaitMiss', ctypes.c_ulong), ('CcCopyReadNoWait', ctypes.c_ulong), ('CcCopyReadWait', ctypes.c_ulong), ('CcCopyReadNoWaitMiss', ctypes.c_ulong), ('CcCopyReadWaitMiss', ctypes.c_ulong), ('CcMdlReadNoWait', ctypes.c_ulong), ('CcMdlReadWait', ctypes.c_ulong), ('CcMdlReadNoWaitMiss', ctypes.c_ulong), ('CcMdlReadWaitMiss', ctypes.c_ulong), ('CcReadAheadIos', ctypes.c_ulong), ('CcLazyWriteIos', ctypes.c_ulong), ('CcLazyWritePages', ctypes.c_ulong), ('CcDataFlushes', ctypes.c_ulong), ('CcDataPages', ctypes.c_ulong), ('ContextSwitches', ctypes.c_ulong), ('FirstLevelTbFills', ctypes.c_ulong), ('SecondLevelTbFills', ctypes.c_ulong), ('SystemCalls', ctypes.c_ulong), # Windows 8 and above ('CcTotalDirtyPages', ctypes.c_ulonglong), ('CcDirtyPagesThreshold', ctypes.c_ulonglong), ('ResidentAvailablePages', ctypes.c_longlong), # Windows 10 and above ('SharedCommittedPages', ctypes.c_ulonglong)] def __virtual__(): ''' Only works on Windows systems with WMI and WinAPI ''' if not salt.utils.platform.is_windows(): return False, 'win_status.py: Requires Windows' if not HAS_WMI: return False, 'win_status.py: Requires WMI and WinAPI' if not HAS_PSUTIL: return False, 'win_status.py: Requires psutil' # Namespace modules from `status.py` global ping_master, time_ ping_master = _namespaced_function(ping_master, globals()) time_ = _namespaced_function(time_, globals()) return __virtualname__ __func_alias__ = { 'time_': 'time' } def cpustats(): ''' Return information about the CPU. Returns dict: A dictionary containing information about the CPU stats CLI Example: .. code-block:: bash salt * status.cpustats ''' # Tries to gather information similar to that returned by a Linux machine # Avoid using WMI as there's a lot of overhead # Time related info user, system, idle, interrupt, dpc = psutil.cpu_times() cpu = {'user': user, 'system': system, 'idle': idle, 'irq': interrupt, 'dpc': dpc} # Count related info ctx_switches, interrupts, soft_interrupts, sys_calls = psutil.cpu_stats() intr = {'irqs': {'irqs': [], 'total': interrupts}} soft_irq = {'softirqs': [], 'total': soft_interrupts} return {'btime': psutil.boot_time(), 'cpu': cpu, 'ctxt': ctx_switches, 'intr': intr, 'processes': len(psutil.pids()), 'softirq': soft_irq, 'syscalls': sys_calls} def meminfo(): ''' Return information about physical and virtual memory on the system Returns: dict: A dictionary of information about memory on the system CLI Example: .. code-block:: bash salt * status.meminfo ''' # Get physical memory vm_total, vm_available, vm_percent, vm_used, vm_free = psutil.virtual_memory() # Get swap memory swp_total, swp_used, swp_free, swp_percent, _, _ = psutil.swap_memory() def get_unit_value(memory): symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') prefix = {} for i, s in enumerate(symbols): prefix[s] = 1 << (i + 1) * 10 for s in reversed(symbols): if memory >= prefix[s]: value = float(memory) / prefix[s] return {'unit': s, 'value': value} return {'unit': 'B', 'value': memory} return {'VmallocTotal': get_unit_value(vm_total), 'VmallocUsed': get_unit_value(vm_used), 'VmallocFree': get_unit_value(vm_free), 'VmallocAvail': get_unit_value(vm_available), 'SwapTotal': get_unit_value(swp_total), 'SwapUsed': get_unit_value(swp_used), 'SwapFree': get_unit_value(swp_free)} def vmstats(): ''' Return information about the virtual memory on the machine Returns: dict: A dictionary of virtual memory stats CLI Example: .. code-block:: bash salt * status.vmstats ''' # Setup the SPI Structure spi = SYSTEM_PERFORMANCE_INFORMATION() retlen = ctypes.c_ulong() # 2 means to query System Performance Information and return it in a # SYSTEM_PERFORMANCE_INFORMATION Structure ctypes.windll.ntdll.NtQuerySystemInformation( 2, ctypes.byref(spi), ctypes.sizeof(spi), ctypes.byref(retlen)) # Return each defined field in a dict ret = {} for field in spi._fields_: ret.update({field[0]: getattr(spi, field[0])}) return ret def loadavg(): ''' Returns counter information related to the load of the machine Returns: dict: A dictionary of counters CLI Example: .. code-block:: bash salt * status.loadavg ''' # Counter List (obj, instance, counter) counter_list = [ ('Memory', None, 'Available Bytes'), ('Memory', None, 'Pages/sec'), ('Paging File', '*', '% Usage'), ('Processor', '*', '% Processor Time'), ('Processor', '*', 'DPCs Queued/sec'), ('Processor', '*', '% Privileged Time'), ('Processor', '*', '% User Time'), ('Processor', '*', '% DPC Time'), ('Processor', '*', '% Interrupt Time'), ('Server', None, 'Work Item Shortages'), ('Server Work Queues', '*', 'Queue Length'), ('System', None, 'Processor Queue Length'), ('System', None, 'Context Switches/sec'), ] return salt.utils.win_pdh.get_counters(counter_list=counter_list) def cpuload(): ''' .. versionadded:: 2015.8.0 Return the processor load as a percentage CLI Example: .. code-block:: bash salt '*' status.cpuload ''' return psutil.cpu_percent() def diskusage(human_readable=False, path=None): ''' .. versionadded:: 2015.8.0 Return the disk usage for this minion human_readable : False If ``True``, usage will be in KB/MB/GB etc. CLI Example: .. code-block:: bash salt '*' status.diskusage path=c:/salt ''' if not path: path = 'c:/' disk_stats = psutil.disk_usage(path) total_val = disk_stats.total used_val = disk_stats.used free_val = disk_stats.free percent = disk_stats.percent if human_readable: total_val = _byte_calc(total_val) used_val = _byte_calc(used_val) free_val = _byte_calc(free_val) return {'total': total_val, 'used': used_val, 'free': free_val, 'percent': percent} def procs(count=False): ''' Return the process data count : False If ``True``, this function will simply return the number of processes. .. versionadded:: 2015.8.0 CLI Example: .. code-block:: bash salt '*' status.procs salt '*' status.procs count ''' with salt.utils.winapi.Com(): wmi_obj = wmi.WMI() processes = wmi_obj.win32_process() #this short circuit's the function to get a short simple proc count. if count: return len(processes) #a propper run of the function, creating a nonsensically long out put. process_info = {} for proc in processes: process_info[proc.ProcessId] = _get_process_info(proc) return process_info def saltmem(human_readable=False): ''' .. versionadded:: 2015.8.0 Returns the amount of memory that salt is using human_readable : False return the value in a nicely formatted number CLI Example: .. code-block:: bash salt '*' status.saltmem salt '*' status.saltmem human_readable=True ''' # psutil.Process defaults to current process (`os.getpid()`) p = psutil.Process() # Use oneshot to get a snapshot with p.oneshot(): mem = p.memory_info().rss if human_readable: return _byte_calc(mem) return mem def uptime(human_readable=False): ''' .. versionadded:: 2015.8.0 Return the system uptime for the machine Args: human_readable (bool): Return uptime in human readable format if ``True``, otherwise return seconds. Default is ``False`` .. note:: Human readable format is ``days, hours:min:sec``. Days will only be displayed if more than 0 Returns: str: The uptime in seconds or human readable format depending on the value of ``human_readable`` CLI Example: .. code-block:: bash salt '*' status.uptime salt '*' status.uptime human_readable=True ''' # Get startup time startup_time = datetime.datetime.fromtimestamp(psutil.boot_time()) # Subtract startup time from current time to get the uptime of the system uptime = datetime.datetime.now() - startup_time return six.text_type(uptime) if human_readable else uptime.total_seconds() def _get_process_info(proc): ''' Return process information ''' cmd = salt.utils.stringutils.to_unicode(proc.CommandLine or '') name = salt.utils.stringutils.to_unicode(proc.Name) info = dict( cmd=cmd, name=name, **_get_process_owner(proc) ) return info def _get_process_owner(process): owner = {} domain, error_code, user = None, None, None try: domain, error_code, user = process.GetOwner() owner['user'] = salt.utils.stringutils.to_unicode(user) owner['user_domain'] = salt.utils.stringutils.to_unicode(domain) except Exception as exc: pass if not error_code and all((user, domain)): owner['user'] = salt.utils.stringutils.to_unicode(user) owner['user_domain'] = salt.utils.stringutils.to_unicode(domain) elif process.ProcessId in [0, 4] and error_code == 2: # Access Denied for System Idle Process and System owner['user'] = 'SYSTEM' owner['user_domain'] = 'NT AUTHORITY' else: log.warning('Error getting owner of process; PID=\'%s\'; Error: %s', process.ProcessId, error_code) return owner def _byte_calc(val): if val < 1024: tstr = six.text_type(val)+'B' elif val < 1038336: tstr = six.text_type(val/1024)+'KB' elif val < 1073741824: tstr = six.text_type(val/1038336)+'MB' elif val < 1099511627776: tstr = six.text_type(val/1073741824)+'GB' else: tstr = six.text_type(val/1099511627776)+'TB' return tstr def master(master=None, connected=True): ''' .. versionadded:: 2015.5.0 Fire an event if the minion gets disconnected from its master. This function is meant to be run via a scheduled job from the minion. If master_ip is an FQDN/Hostname, is must be resolvable to a valid IPv4 address. CLI Example: .. code-block:: bash salt '*' status.master ''' def _win_remotes_on(port): ''' Windows specific helper function. Returns set of ipv4 host addresses of remote established connections on local or remote tcp port. Parses output of shell 'netstat' to get connections PS C:> netstat -n -p TCP Active Connections Proto Local Address Foreign Address State TCP 10.1.1.26:3389 10.1.1.1:4505 ESTABLISHED TCP 10.1.1.26:56862 10.1.1.10:49155 TIME_WAIT TCP 10.1.1.26:56868 169.254.169.254:80 CLOSE_WAIT TCP 127.0.0.1:49197 127.0.0.1:49198 ESTABLISHED TCP 127.0.0.1:49198 127.0.0.1:49197 ESTABLISHED ''' remotes = set() try: data = subprocess.check_output(['netstat', '-n', '-p', 'TCP']) # pylint: disable=minimum-python-version except subprocess.CalledProcessError: log.error('Failed netstat') raise lines = salt.utils.stringutils.to_unicode(data).split('\n') for line in lines: if 'ESTABLISHED' not in line: continue chunks = line.split() remote_host, remote_port = chunks[2].rsplit(':', 1) if int(remote_port) != port: continue remotes.add(remote_host) return remotes # the default publishing port port = 4505 master_ips = None if master: master_ips = _host_to_ips(master) if not master_ips: return if __salt__['config.get']('publish_port') != '': port = int(__salt__['config.get']('publish_port')) master_connection_status = False connected_ips = _win_remotes_on(port) # Get connection status for master for master_ip in master_ips: if master_ip in connected_ips: master_connection_status = True break # Connection to master is not as expected if master_connection_status is not connected: event = salt.utils.event.get_event('minion', opts=__opts__, listen=False) if master_connection_status: event.fire_event({'master': master}, salt.minion.master_event(type='connected')) else: event.fire_event({'master': master}, salt.minion.master_event(type='disconnected')) return master_connection_status