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
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
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?
But even sequentially, you're talking maybe 10 seconds to boot them all?
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
}
}
?>
Try the following easy script first:
a.py
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
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
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().
If it is usefull at all, feel free to ask for what is not clear (even the tiny Python details :)
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
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
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/subp rocess.py" , line 550, in __init__
errread, errwrite)
File "/usr/lib64/python2.4/subp rocess.py" , line 993, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
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/subp
errread, errwrite)
File "/usr/lib64/python2.4/subp
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.
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?
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.
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?
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?
If none fail, boot all at the same time using fork()
Right?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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/scri pt.php");
Then the 2nd script would have for line 49 exec("/path/to/your/post/i nstall/com mands/scri pt");
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.
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
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/scri
Then the 2nd script would have for line 49 exec("/path/to/your/post/i
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.
ASKER
xterm,
I appreciate your help.
I appreciate your help.
Open in new window