contrib/automation/hgautomation/winrm.py
changeset 42024 b05a3e28cf24
child 42279 f30184484dd1
equal deleted inserted replaced
42023:bf87d34a675c 42024:b05a3e28cf24
       
     1 # winrm.py - Interact with Windows Remote Management (WinRM)
       
     2 #
       
     3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com>
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 
       
     8 # no-check-code because Python 3 native.
       
     9 
       
    10 import logging
       
    11 import pprint
       
    12 import time
       
    13 
       
    14 from pypsrp.client import (
       
    15     Client,
       
    16 )
       
    17 from pypsrp.powershell import (
       
    18     PowerShell,
       
    19     PSInvocationState,
       
    20     RunspacePool,
       
    21 )
       
    22 import requests.exceptions
       
    23 
       
    24 
       
    25 logger = logging.getLogger(__name__)
       
    26 
       
    27 
       
    28 def wait_for_winrm(host, username, password, timeout=120, ssl=False):
       
    29     """Wait for the Windows Remoting (WinRM) service to become available.
       
    30 
       
    31     Returns a ``psrpclient.Client`` instance.
       
    32     """
       
    33 
       
    34     end_time = time.time() + timeout
       
    35 
       
    36     while True:
       
    37         try:
       
    38             client = Client(host, username=username, password=password,
       
    39                             ssl=ssl, connection_timeout=5)
       
    40             client.execute_cmd('echo "hello world"')
       
    41             return client
       
    42         except requests.exceptions.ConnectionError:
       
    43             if time.time() >= end_time:
       
    44                 raise
       
    45 
       
    46             time.sleep(1)
       
    47 
       
    48 
       
    49 def format_object(o):
       
    50     if isinstance(o, str):
       
    51         return o
       
    52 
       
    53     try:
       
    54         o = str(o)
       
    55     except TypeError:
       
    56         o = pprint.pformat(o.extended_properties)
       
    57 
       
    58     return o
       
    59 
       
    60 
       
    61 def run_powershell(client, script):
       
    62     with RunspacePool(client.wsman) as pool:
       
    63         ps = PowerShell(pool)
       
    64         ps.add_script(script)
       
    65 
       
    66         ps.begin_invoke()
       
    67 
       
    68         while ps.state == PSInvocationState.RUNNING:
       
    69             ps.poll_invoke()
       
    70             for o in ps.output:
       
    71                 print(format_object(o))
       
    72 
       
    73             ps.output[:] = []
       
    74 
       
    75         ps.end_invoke()
       
    76 
       
    77         for o in ps.output:
       
    78             print(format_object(o))
       
    79 
       
    80         if ps.state == PSInvocationState.FAILED:
       
    81             raise Exception('PowerShell execution failed: %s' %
       
    82                             ' '.join(map(format_object, ps.streams.error)))