Link to home
Start Free TrialLog in
Avatar of tbalz
tbalz

asked on

Need help with Python networking script

Hi Guys,

My goal is to ping a group of 8 HP switches to individually load network configs via TFTP and SSH. All of this is controlled by a Python script i'm trying to get to work correctly
. I just have two test switch IP addresses in there and want get these working before adding them all in. As of right now my script just freezes while running and I tried to debug it with pdb but it didn't make much sense. Below is my script
#!/usr/bin/env python
import subprocess
import getpass
#import ping
import time

#This script will attempt to ping all switches

switchiplist = ['10.1.1.15', '10.1.1.16']

for switchip in switchiplist:


try:
    pingtry = os.popen("ping -q -c2 "+self.ip,"r", timeout=1)
    #upload config
except socket.error, e:
    print "Ping Error:", e
    time.sleep(10) wait for 30s and then try again

Open in new window

Avatar of xterm
xterm

Since you're not using any native function of python specifically here, why not just do it in a standard shell script?  Something like this would work fine
#!/bin/sh

SWITCHES="10.1.1.15 10.1.1.16"

for SWITCH in `echo $SWITCHES`;
do
        RESULT=`ping -c2 -W1 $SWITCH | grep transmitted | awk '{print $6}'`
        if [ x"$RESULT" = x"0%" ]; then
                echo "Ping $SWITCH successful"
                # Upload config
        else
                echo "Ping $SWITCH failed"
        fi
done

Open in new window

Avatar of tbalz

ASKER

I was hoping to get this working in Python because I eventually want to move this script to using threading so eventually I can get all the switches to reboot at once. Would tit be possible with bash script to use some type of threading?
Not easily - I'd use PHP if I wanted to fork threads.

But even sequentially, you're talking maybe 10 seconds to boot them all?
Avatar of tbalz

ASKER

It takes awhile to boot them up because like the script you provided goes one by one. I sometimes have to wait a few seconds to ping because of network respans. thats why I needed to put the error checking in there.I really have on how to use PHP and am very new to Python as well. Any other ideas you may have?
Here's how I'd do it in PHP.  As you can see if you run this, it forks each test, so your console is returned to you immediately while the results trickle in a couple of seconds later.
#!/usr/bin/php -q
<?php

$switches=array("10.1.1.15", "10.1.1.16");

function myping($switch) {
        // RETURN 0 IF ALIVE, 1 IF DEAD
        $success=exec("ping -c2 -W1 $switch | grep transmitted | awk '{print $6}'");
        if($success=="0%") {
                return(0);
        } else {
                return(1);
        }
}

foreach ($switches as $switch) {
        $pid = pcntl_fork();
        if( $pid == -1 ) {
                exit(1);
        } else if ( $pid ) {
                $children[] = $pid;
                if(count($children) >= 30) {
                        $pid = array_shift($children);
                        pcntl_waitpid($pid, $status);
                }
        } else {
                if (!myping($switch)) {
                        echo "ping is good\n";
                        # reboot switch here
                } else {
                        echo "ping failed\n";
                }
        exit(0); // Kill the worker child when finished
        }
}

?>

Open in new window

Avatar of pepr
Try the following easy script first:

a.py
#!/usr/bin/env python

import subprocess

#This script will attempt to ping all switches
ipLst = ['10.1.1.15', '10.1.1.16']

# Start the ping processes and collect the information to the list.
procLst = []  

for ip in ipLst:
    cmd = 'ping ' + ip         # the constructed ping command
    print 'Starting', cmd             # just to see it started
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE) # redirect the output
    procLst.append( (ip, p) )         # remember the ping object


for id, p in procLst:
    print id, p
    print p.communicate()[0]    # waits for the process to terminate, and prints its stdout

Open in new window

The following modification is usefull only when you do not know how long the processes can run.  It is ad-hoc solution.  It uses busy-loop with sleeping for a short time.  It uses the .poll() method to check whether the process already finished or not.  For visualization, when the process is checked, the IP address is printed.  (Fix the params of the ping command.  I am on Windows now, and the ping is not the same here.):

b.py
#!/usr/bin/env python

import subprocess
import time

#This script will attempt to ping all switches
ipLst = ['10.1.1.15', '10.1.1.16']

# Start the ping processes and collect the information to the list.
procLst = []

for ip in ipLst:
    cmd = 'ping ' + ip         # the constructed ping command
    print 'Starting', cmd             # just to see it started
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE) # redirect the output
    procLst.append( (ip, p) )         # remember the ping object


print '-' * 70
while procLst:
    # Loop through the processes and process the result of the one
    # that already finished.
    for n, (id, p) in enumerate(procLst):
        print id, 
        retcode = p.poll()
        if retcode is not None:  
            print '\n---------------'
            print id, p
            print p.communicate()[0]
            procLst[n] = None    # already processed

    # Remove all the None's from the list and if there is no change,
    # sleep for a while.
    len1 = len(procLst)
    procLst = [e for e in procLst if e is not None]
    if len(procLst) == len1:
        time.sleep(0.1)          # sleep for 0.1 sec

    # You can decide here whether the timeout was met (not implemented here),
    # and then you can kill the process via p.kill().

Open in new window

If it is usefull at all, feel free to ask for what is not clear (even the tiny Python details :)
Avatar of tbalz

ASKER

Hi pepr,

I got this problem when i attempted to run the first script you sent on my box.  

File "./switch1.py", line 22
    Toggle HighlightingOpen in New WindowSelect All
                          ^
SyntaxError: invalid syntax
Avatar of tbalz

ASKER

Nevermind the last error, that was a mistake on my part:

This is the error i got after running the script:

Starting ping 10.1.1.15
Traceback (most recent call last):
  File "./switch1.py", line 15, in ?
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE) # redirect the output
  File "/usr/lib64/python2.4/subprocess.py", line 550, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.4/subprocess.py", line 993, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
Did you try the PHP one by chance?  Seems like it should do what you need and more since the forks are already implemented.
Avatar of tbalz

ASKER

xterm,

if the ping fails is there a way to have it wait and try to re-ping the switch util it comes back up?
Sure, I can fork loops that will ping repeatedly until the switch comes up, but then the other switches will be booted in the mean time - is that the behavior you want?
tbalz, you can also use the "Select All" link below the snippet window.  It is probably more reliable than doing it manually.
Avatar of tbalz

ASKER

xterm,

ideally i would like it to ping everyone and boot them at the same time. In the beginning I know for a fact all the switches will be up. Would it be possible to knock out all eight switches in one blow so they don't have to wait for each other to come back if a respan happens?

So logic is, ping all switches in sequence to make sure they're up.

If none fail, boot all at the same time using fork()

Right?
ASKER CERTIFIED SOLUTION
Avatar of xterm
xterm

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of tbalz

ASKER

not exactly boot but run another script which i have which is an expect script that basically ssh's into each switch individually and gets the switch ready to receive new configs and then sends them via my tftp server, after this happens the switch is immediately rebooted. After the switch is rebooted, i need them to be all pinged once again and send out some additionl post install commands via a different script. would this be possible and consistent?
Okay, so then the fork actually has to occur in your other script right?  Since it logs into each switch sequentially, but you want it to do it simultaneously?

I would make a copy of your other script and have it instead only log into one switch, supplied on the command line.  So your script would be called as "yourscript 1.1.1.1" and it would then send the tftp config to that script.

That way, my script could be modified on line 49 only to exec("/path/to/your/script $switch"); and you would accomplish the simultaneous reboot that you are wanting.

And yes, if you need to ping them again later, simply make a copy of my script to a new one which you call right at the end of this one (line 53)  with exec("/path/to/second/script.php");

Then the 2nd script would have for line 49 exec("/path/to/your/post/install/commands/script");

That logic pretty close?

BTW, keep in mind that we're going well above and beyond your original question at this point, but I'm trying to be accommodating nevertheless.
Avatar of tbalz

ASKER

xterm,

I appreciate your help.