Wednesday, December 20, 2017

Mixing Powershell with Jenkins and Python, Lazy DevOps Way


This post is for the DevOps guys or the system guys or whoever to get the work done done with just fix it approach who just found out powershell is quicker while dealing with VMware automation.
The case could be; you already have your automation code written in python for your in house data center and later on your infrastructure migrated to VMware and now you have to modify or rewrite everything or you have jenkins master and now you have to run powershell script somehow or likewise.
VMware API documentation is not friendly enough in my experience, and if you are Python person then something like PyVMomi might work as well.

Found out Powershell is better with working with VMware. So, here is the way to use Powershell in Jenkins and inside your python code.



1. Jenkins run Powershell
Use Powershell plugin in Jenkins.
If you have Jenkins in Linux machine then PowerCLI for Linux can be installed. Its in development and you can get started with Alpha release. Till then you need to have Windows machine to run Powershell and install VMware libraries. In this case, you can just  connect Windows machine as slave and executed the Powershell script from master Jenkins. Now in this, if you are very new to Powershell world then questions like "how to assign variables in script? " and "how to use  Jenkins job parameters inside Powershell script? " are the interesting one. And below code just answers these questions.

Listing Snapshots of VMware Machine

Jenkins Build Step: Execute Powershell

Import-Module VMware.VimAutomation.Core

"Hello From Powershell @ Remote Windows Machine"
"Listing all the snapshots of vm: $env:vm_name"

Set-Variable -Name "username" -Value “myusername@username.com”
Set-Variable -Name "password" -Value “mypasswd@passwd.com”

#connect to vsphere at
myserverdomain.com
Connect-VIServer -Server myserverdomain.com -Protocol https -User $username -Password $password

#getting list of all the snapshot of vm
Get-VM -Name $env:vm_name | get-snapshot | format-list VM,Name,PowerState,Description, Children,VMId,ParentSnapshot,IsCurrent


In above code, $env:vm_name is the way to get Jenkins Job Parameter in Powershell script where vm_name is the parameter name.



2. Use Python Fabric to execute powershell in remote windows.
Python fabric api is use to execute commands in the remote machines. Its one of the custom code way to do automation or effective configuration management. Setting up the host and credential we can ask Fabric to execute commands in the remote machines. Fabric uses SSH beneath so, we have to install SSH service in Windows. Now this method consist of 3 components; your powershell script located in remote windows machine, your python script and fabfile.py thats Fabric stuff you need to code as well :) Get into Fabric to know about fabfile.

Revert Snapshot with PowerCLI

my_revertsnapshot.ps1

Param(
  [string]$vm_name,
  [string]$snapshot_name
)

Import-Module VMware.VimAutomation.Core

"Hello From Powershell"
"Reverting snapshot of vm: $vm_name"
"Reverting the snapshot state named: $snapshot_name"

Set-Variable -Name "username" -Value “myusername@username.com”
Set-Variable -Name "password" -Value “mypasswd”

#connect to vsphere myvmwaredomain.com

Connect-VIServer -Server myvmwaredomain.com -Protocol https -User $username -Password $password

#revert snapshot of vm
set-vm -vm $vm_name -snapshot $snapshot_name -Confirm:$false

"Snapshot might have been reverted. Please verify"



-Confirm:$false is to just bypass the yes/no confirmation in powershell that worked for me.

The fabfile.py would look like this, you can write this out in more manageable way than this dirty way :)

fabfile.py

from fabric.api import env, run, task

@task
def revert_snapshot_vm():
   
    env.user = “user”
    env.password = “userpassword”
    env.hosts = [‘w.x.y.z’] # ip address of host

    print('executing powershell in remote windows')
    try:

        run("powershell -file c:\jenkins\my_revertsnapshot.ps1 vmmachine123 myfirstsnapshot”, shell=False, pty=False)

        print('snapshot might have been reverted')
    except Exception as e:
        print("error calling revert snapshot in ESXI machine: ", e)


Calling Fabric from Python Code


run_powershell.py

import fabfile
from fabric.api import env
from fabric.main import execute

## run the powershell command in remote windows

def call_powershell_snapshot():
    env.hosts = [‘w.x.y.z’]
    try:
        execute(getattr(fabfile, 'revert_snapshot_vm'))

    except Exception as ex:
        print("error running method ", ex)
        pass

call_powershell_snapshot()


Usage is: python run_powershell.py in linux terminal  :)

Enjoy scripting ;)