Monday, October 21, 2013

Python in Action: Paramiko handling ssh connection

I came across the ssh interactive session from bash long time ago using the expect. But, this morning I am exploring paramiko, and start to draft a stupid easy codes to test out the library. It is clean and blazing fast. Hope this small chunks of codes can get you started with all the complicated paramiko codes.

#!/usr/bin/python                                                          
import os                                                                  
import paramiko                                                            
import getpass                                                             
                                                                            
user=os.getlogin()                                                         
print "Connecting via %s: what is your password?" % user                   
pw = getpass.getpass()                                                     
ssh = paramiko.SSHClient()                                                 
#ssh.load_host_keys()                                                      
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())                  
ssh.connect('centos64-1', username=user, password=pw)                      
stdin, stdout, stderr = ssh.exec_command('uname -a')                       
print "output", stdout.read()                                              
ssh.close() 


 
After a day so, I feel like I want to do a little of enhancement out of it. So, I recode it something like below. Still feeling it is not as neath as I love to. But, overall it can carry out the work.

#!/usr/bin/python
import os
import paramiko
import getpass
import socket

def get_credential():
    user=os.getlogin()
    print "Connecting via [%s]: what is your password?" % user
    pw = getpass.getpass()
    return (user, pw)

def ssh_connect():
    (user, pw) = get_credential()
    try:
        ssh = paramiko.SSHClient()
        #ssh.load_host_keys()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect('centos64-1', username=user, password=pw)
        stdin, stdout, stderr = ssh.exec_command('uname -a')
        print "output: ", stdout.read()
        ssh.close()
    except paramiko.SSHException, e:
        print "Password is invalid:" , e
    except paramiko.AuthenticationException:
        print "Authentication failed for some reason"
    except socket.error, e:
        print "Socket connection failed:", e

def main():
    ssh_connect() 


if __name__ == '__main__':                                                    
    main()                 



After a day so, I have done some polishing on the same codes. Now, it can accept a list of target hosts with a comma delimiter. Then, the script will be connecting to target hosts one by one. Feel free to copy/use it. Thanks!

#!/usr/bin/python
import os
import paramiko
import getpass
import socket

def get_host():
    target_host = []
    input = raw_input("What is your target host? ")
    for item in input.split(","):
        target_host.append(item.strip())
    return target_host

def get_credential():
    pw = ""
    user=os.getlogin()
    print "Connecting via [%s]: what is your password?" % user
    while not pw:
        pw = getpass.getpass()
    return (user, pw)


def ssh_connect():
    target_host = get_host()
    (user, pw) = get_credential()

    ssh = paramiko.SSHClient()
    #ssh.load_host_keys()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    for h in target_host:
        try:
            print "Connecting to %s ..." % h
            ssh.connect(h, username=user, password=pw)
            stdin, stdout, stderr = ssh.exec_command('uname -a')
            print "%s>" % h,stdout.read()
        except paramiko.SSHException, e:
            print "Password is invalid:" , e
        except paramiko.AuthenticationException:
            print "Authentication failed for some reason"
        except socket.error, e:
            print "Socket connection failed on %s:" % h, e
    ssh.close()
def main():
    ssh_connect()

if __name__ == '__main__':                                                    
    main()



Here is the output that I got.

hiuy@nasilemak ~ $ ./pyssh.py
What is your target host? centos64-1, centos64-2
Connecting via [hiuy]: what is your password?
Password:
Connecting to centos64-1 ...
centos64-1> Linux centos64-1.hiu.com 2.6.32-358.18.1.el6.x86_64 #1 SMP Wed Aug 28 17:19:38 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

Connecting to centos64-2 ...
centos64-2> Linux localhost.localdomain 2.6.32-358.el6.x86_64 #1 SMP Fri Feb 22 00:31:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

Thursday, October 10, 2013

Script to report the HBA cards status

I have a small function to detect the emulex, and qlogic HBA cards for a quick one. If you find it useful in your automation you can embed this function to your script and start calling it. Hope that it helps you in your works. Thanks!

function check_hba ()
{

        # Checking Emulex HBA cards status

        if grep -q -i "online" /sys/class/fc_host/host*/port_state 2>/dev/null
        then
                num_online_hba=`grep -i "online" /sys/class/fc_host/host*/port_state | wc -l`
                total_hbas=`ls -1 /sys/class/fc_host/host*/node_name | wc -l`

                echo "Linux discovered $num_online_hba HBAs is online out of $total_hbas cards."

                for h in `ls -1 /sys/class/fc_host/host*/node_name | awk -F/ '{print $5}'`
                do
                        wwn=`cat /sys/class/fc_host/$h/port_name`
                        state=`cat /sys/class/fc_host/$h/port_state`
                        #modelname=`cat /sys/class/scsi_host/$h/modelname`
                        #echo "HBA $modelname : $wwn is $state"
                        echo "HBA : $wwn is $state"
                done
        fi

        # Checking Qlogic HBA cards status
        if grep -q -i "ready" /proc/scsi/qla2xxx/* 2>/dev/null
        then
                total_hbas=`ls -1 /proc/scsi/qla2xxx/* | wc -l`
                num_online_hba=`grep -i "ready" /proc/scsi/qla2xxx/*| wc -l`

                echo "Linux discovered $num_online_hba is online out of $total_hbas cards."

                for h in `ls -1 /proc/scsi/qla2xxx/*`
                do
                        wwn=`cat $h|grep "scsi-qla.-adapter-port*" | awk -F= '{print $2}' | sed -e 's|;||g'`
                        grep -i -q "Host adapter.*ready" $h && echo "HBA : $wwn is Online" || echo "HBA : $wwn is Offline"
                done
        fi

}

Thursday, October 3, 2013

LVM and hosttag

hi all,

LVM is working well with host tag especially when working for a active/passive cluster nodes. There are just some simple lines needed at /etc/lvm/lvm.conf

1. volume_list = [ "vg00", "vg01", "vg02", "vg03", "vg04", "vg05" ]
2. tags  { hosttags = 1 }


At the same time, you have to create another conf file with this command

echo "activation { volume_list=["@`hostname -f`"] }" >  /etc/lvm/lvm_`hostname -f`.conf

So, the result with the something like this.

[root@node01c lvm]# cat /etc/lvm/lvm_node01c.hiu.com.conf
activation { volume_list=["@node01c.hiu.com"] }

Once you are done, pretty much you are done.

When you are importing the vg01, you will need to add a tag onto it: vgchange --addtag vg01 upon the activation. Otherwise, you have to deport it so another node within the cluster can import it. To deport it, you have to do vgchange --deltag vg01. 

if you are working well, you will notice that the tagging is working against the lvdisplay too. For example:

[root@node01c lvm]# lvdisplay @node01c.hiu.com
  --- Logical volume ---
  LV Path                /dev/vg02/lvol01
  LV Name                lvol01
  VG Name                vg02
  LV UUID                CXLHnj-FWUY-Puej-r2SN-S7d5-Bkse-Ufx9yH
  LV Write Access        read/write
  LV Creation host, time node01c.hiu.com, 2013-10-03 15:34:30 +0800
  LV Status              available
  # open                 1
  LV Size                71.98 GiB
  Current LE             18428
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:19

Whereas, in the passive node, you wont find any output is printed.

[root@node02c lvm]# lvdisplay @node02c.hiu.com
[root@node02c lvm]#


Another method to determine your tagging is working fine by using the command lvs.


[root@node01c lvm]# lvs
  LV     VG   Attr     LSize  Pool Origin Data%  Move Log Copy%  Convert
  crash  vg00 -wi-ao--  7.81g
  home   vg00 -wi-ao--  4.00g
  opt    vg00 -wi-ao--  4.00g
  tmp    vg00 -wi-ao--  4.00g
  usr    vg00 -wi-ao--  4.00g
  var    vg00 -wi-ao--  4.00g
  lvol01 vg01 -wi-ao--  3.98g
  lvol01 vg02 -wi-ao-- 71.98g
  lvol01 vg03 -wi-ao--  1.98g
  lvol01 vg04 -wi-ao-- 61.98g
  lvol01 vg05 -wi-ao--  4.98g

[root@node02c lvm]# lvs
  LV     VG   Attr     LSize  Pool Origin Data%  Move Log Copy%  Convert
  crash  vg00 -wi-ao--  7.81g
  home   vg00 -wi-ao--  4.00g
  opt    vg00 -wi-ao--  4.00g
  tmp    vg00 -wi-ao--  4.00g
  usr    vg00 -wi-ao--  4.00g
  var    vg00 -wi-ao--  4.00g
  lvol01 vg01 -wi-----  3.98g
  lvol01 vg02 -wi----- 71.98g
  lvol01 vg03 -wi-----  1.98g
  lvol01 vg04 -wi----- 61.98g
  lvol01 vg05 -wi-----  4.98g

with this output, you can clearly see that there is a string like "wi-ao" appended onto the activated volume at the active node.