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

tbalzAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

xtermCommented:
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

0
tbalzAuthor Commented:
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?
0
xtermCommented:
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?
0
OWASP Proactive Controls

Learn the most important control and control categories that every architect and developer should include in their projects.

tbalzAuthor Commented:
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?
0
xtermCommented:
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

0
peprCommented:
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

0
peprCommented:
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

0
peprCommented:
If it is usefull at all, feel free to ask for what is not clear (even the tiny Python details :)
0
tbalzAuthor Commented:
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
0
tbalzAuthor Commented:
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
0
xtermCommented:
Did you try the PHP one by chance?  Seems like it should do what you need and more since the forks are already implemented.
0
tbalzAuthor Commented:
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?
0
xtermCommented:
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?
0
peprCommented:
tbalz, you can also use the "Select All" link below the snippet window.  It is probably more reliable than doing it manually.
0
tbalzAuthor Commented:
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?

0
xtermCommented:
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?
0
xtermCommented:
Here is the way I describe above.  If all switches ping successfully, they will all get rebooted.  But if any fail, the script exits.  You can also now turn and off verbose operation using $debug variable.
#!/usr/bin/php -q
<?php

$switches=array("10.1.1.15", "10.1.1.16");
$debug=1;       // Set to 0 to run quietly
$failure=0;

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);
        }
}

function reboot($switch) {
        // Put your reboot code here
}

foreach ($switches as $switch) {
                if (!myping($switch)) {
                        if($debug==1) { echo "ping is good\n"; }
                } else {
                        if($debug==1) { echo "ping failed\n"; }
                        $failure=1;
                }
}

if($failure==1) {
        if($debug==1) { echo "One or more switches failed ping, exiting\n"; }
        exit;
}

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 {
                // Reboot the switch
                if($debug==1) { echo "Rebooting switch $switch\n"; }
                # reboot($switch)
                exit(0); // Kill the worker child when finished
        }
}

?>

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
tbalzAuthor Commented:
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?
0
xtermCommented:
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.
0
tbalzAuthor Commented:
xterm,

I appreciate your help.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Python

From novice to tech pro — start learning today.