Mercurial > public > mercurial-scm > hg
annotate contrib/automation/hgautomation/winrm.py @ 42661:e91930d712e8 stable 5.1
automation: execute powershell when connecting
For some reason, the ability to execute PS scripts appears to
come online after the ability to execute regular command scripts.
This is creating race conditions when connecting to instances
resulting in our wait_for_winrm() returning before PS is available
leading to an exception being thrown in other code.
Let's change the client connection code to execute a minimal
PS script so we can try to trap the exception in wait_for_winrm().
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sun, 28 Jul 2019 18:32:31 -0700 |
parents | f30184484dd1 |
children | 2372284d9457 |
rev | line source |
---|---|
42024
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
1 # winrm.py - Interact with Windows Remote Management (WinRM) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
2 # |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
3 # Copyright 2019 Gregory Szorc <gregory.szorc@gmail.com> |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
4 # |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
6 # GNU General Public License version 2 or any later version. |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
7 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
8 # no-check-code because Python 3 native. |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
9 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
10 import logging |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
11 import pprint |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
12 import time |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
13 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
14 from pypsrp.client import ( |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
15 Client, |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
16 ) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
17 from pypsrp.powershell import ( |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
18 PowerShell, |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
19 PSInvocationState, |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
20 RunspacePool, |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
21 ) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
22 import requests.exceptions |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
23 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
24 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
25 logger = logging.getLogger(__name__) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
26 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
27 |
42279
f30184484dd1
automation: wait longer for WinRM connection
Gregory Szorc <gregory.szorc@gmail.com>
parents:
42024
diff
changeset
|
28 def wait_for_winrm(host, username, password, timeout=180, ssl=False): |
42024
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
29 """Wait for the Windows Remoting (WinRM) service to become available. |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
30 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
31 Returns a ``psrpclient.Client`` instance. |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
32 """ |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
33 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
34 end_time = time.time() + timeout |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
35 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
36 while True: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
37 try: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
38 client = Client(host, username=username, password=password, |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
39 ssl=ssl, connection_timeout=5) |
42661
e91930d712e8
automation: execute powershell when connecting
Gregory Szorc <gregory.szorc@gmail.com>
parents:
42279
diff
changeset
|
40 client.execute_ps("Write-Host 'Hello, World!'") |
42024
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
41 return client |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
42 except requests.exceptions.ConnectionError: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
43 if time.time() >= end_time: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
44 raise |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
45 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
46 time.sleep(1) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
47 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
48 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
49 def format_object(o): |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
50 if isinstance(o, str): |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
51 return o |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
52 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
53 try: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
54 o = str(o) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
55 except TypeError: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
56 o = pprint.pformat(o.extended_properties) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
57 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
58 return o |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
59 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
60 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
61 def run_powershell(client, script): |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
62 with RunspacePool(client.wsman) as pool: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
63 ps = PowerShell(pool) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
64 ps.add_script(script) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
65 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
66 ps.begin_invoke() |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
67 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
68 while ps.state == PSInvocationState.RUNNING: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
69 ps.poll_invoke() |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
70 for o in ps.output: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
71 print(format_object(o)) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
72 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
73 ps.output[:] = [] |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
74 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
75 ps.end_invoke() |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
76 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
77 for o in ps.output: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
78 print(format_object(o)) |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
79 |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
80 if ps.state == PSInvocationState.FAILED: |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
81 raise Exception('PowerShell execution failed: %s' % |
b05a3e28cf24
automation: perform tasks on remote machines
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff
changeset
|
82 ' '.join(map(format_object, ps.streams.error))) |