public
Last active

Python with PowerShell Remoting (Windows equivalent for Unix ssh sessions)

  • Download Gist
gistfile1.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
# Note that target_env.login and target_env.password is global variables
 
# Maybe I should add this into Fabric project (http://docs.fabfile.org/en/1.4.2/index.html).
# This is complicated task for sure but it would be nice if Fabric could use ssh under Linux and PowerShell Remoting under Windows.
 
def remote_sh(target_host, command_text, ignore_error=False):
print('run PowerShell script block at {0}: {1}'.format(target_host, command_text))
 
command_text = command_text.replace('"', '\'')
 
# -NoProfile -NonInteractive PowerShell parameters decrease execution time
power_shell_text = """\
powershell -NoProfile -NonInteractive
\"$secure_password = ConvertTo-SecureString '{1}' -asPlainText -Force;
$credentials = New-Object Management.Automation.PSCredential('{0}', $secure_password);
$remote_session = New-PSSession -ComputerName {2} -Credential $credentials;
Invoke-Command -Session $remote_session -ScriptBlock {{ {3} }};
$remote_last_exit_code = Invoke-Command -Session $remote_session -ScriptBlock {{ $LastExitCode }};
Remove-PSSession -Session $remote_session;
exit $remote_last_exit_code\"""".format(
target_env.login,
target_env.password,
target_host,
command_text)
 
power_shell_text = dedent(power_shell_text).replace('\n', ' ')
 
# This print call could be uncommented for debugging purposes
# print('run shell command: {0}'.format(power_shell_text))
 
error_code = os.system(power_shell_text)
 
if error_code and not ignore_error:
raise Exception('Failed to execute PowerShell script block on host {0}. Actual return code was {1} '
'but only zero value is expected. '
'Script block is "{2}".'.format(target_host, error_code, command_text))
 
return error_code

To oddur. Sorry for delay with answer.

This gist (https://gist.github.com/2850866) is better than you have mention (https://gist.github.com/3228308) because it uses WinRS command line tool instead of PowerShell Remoting.

Basically we have WinRM protocol and two reference implementation:
1. WinRS command line tool which can be executed from cmd.exe shell or just as separate process.
2. PowerShell Remoting is more complicated/powerful but fit better if you are using PowerShell (not Python).

So, in context of Python scripting it would be much easier mix Python with cmd.exe with WinRS.

In case with PowerShell Remoting you have to know both Python and PowerShell.

Also I would like to stress that both cases works only on Windows Vista+ or Windows Server 2008+ :(

I'm planning develop cross-platform library which will execute remote commands via WinRM protocol in pure Python and move away from WinRS tool.

Hi !
I've tested this on my Windows 2008 servers and it works.
Why don't you propose this code into Fabric main project ?

To samyscoub.

Actually I was thinking about this right after I've implement this functionality and developed monkey patch for Fabric (check https://gist.github.com/3228308) which works with WinRM.

At the very beginning I wanted create cross-platform implementation of WinRM protocol (check https://github.com/diyan/pywinrm) and after that start working on Fabric.

But the more I think about this idea the less I liked it.

Fabric completely tied to ssh protocol implementation. I had to do major changes in it's architecture and change not only transport level implementation but also a lot of places which tied to Bash/Linux environment.

So, I changed my mind on this topic and don't have any plans integrate WinRM transport into Fabric project.

Sorry about that.

FYI, I'm looking now at Ansible project (https://github.com/ansible/ansible) now. It's much more complicated that Fabric for deployment tasks but it have interfaces for integrate WinRM transport.

So, it's really possible integrate pywinrm transport implementation into Ansible without too much effort.

Actually I have some working results on my own workstation but I'm not ready push them into Ansible yet.

I really liked Ansible source codes, their approach on writing modules and functionality (configuration management, ad-hoc task execution and deployment in single(!) product).

At the same time I don't really like Ansible's GPL license but I understand their choice and this is not showstopper for me.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.