Background: I've been commissioned by my supervisor to create a script that will identify what virtual machines are located on a given server. This problem arose because no naming convention was established between the virtual machine configuration name and the DNS name (ie. a VM called taco has a DNS name of hotdog). While I think it would just be better to go establish a naming convention and spend a few hours to rename all the configuration files to the DNS names, my superiors want a "clever solution".
Purpose: If a machine critical VM goes down, they need to know what machine it is on to resolve the problem(s).
What I Use: Doing some voodoo I manage to pull out possible DNS names from the database to what an actual VM might be associated with. The goal initially was to use tcpdump to listen for traffic on each DNS, timing out after say 15 seconds or a minute or even 5 minutes if there is not traffic. Since this runs as a cron job at night, there isn't a lot of traffic and the script thinks that the real DNS name is bogus since tcpdump ends up not returning anything useful.
Proposed Solution: I am new to thread programming, but I understand the concept to a minimal degree. The idea is to launch a series of say 10 pings at the DNS name and have tcpdump listen for those pings. I had two terminals open, I started the pinging and then started the tcpdump. With pefect commands and associated parameters I figured I could plug and chug and everything would work wonderfully.
Problem: I run tcpdump in an eval block with a SIG{ALRM} to kill it after so long if it doesn't get any packets. Unfortunately it doesn't seem to be working. I'm suspicious this is a newbish misuse of threads that's causing the problem, because a previous eval statement killed tcpdump just fine, but now it won't.
Code:
sub vm_tcp_dump { my $macaddress = $_[0]; my $dns_name = $_[1]; my $good_dns_name = undef;; eval{ local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n req +uired alarm 15; my $ping_thread = threads->new(\&vm_ping, $dns_name); print ("CMD: tcpdump -q -i eth0 'ether dst host $macad +dress and proto ICMP and src host $hostname' -c 1\n"); my $dumpdata = undef; my $dump_thread = threads->new(sub {my $ipaddress = un +def; $dumpdata = `tcpdump -q -i eth +0 'ether dst host $macaddress and proto ICMP and src host $hostname' +-c 1`; return $dumpdata; }); $dumpdata = $dump_thread->join(); print "\nTEST\n\n"; print "\n".$dumpdata."\n\n"; $good_dns_name = $ping_thread->join(); alarm 0; }; print "tcpdump done\n"; return $good_dns_name; } sub vm_ping { my $dns_name = $_[0]; my $good_dns_name; print("DNS: $dns_name\n"); eval{ local $SIG{ALRM} = sub {die "alarm\n" }; alarm 15; my $data = `ping $dns_name -c 10 -s 256`; if(!($data =~ m/Destination Host Unreachable/g)){ $data =~ m/PING (.*).et.byu.edu/g; $good_dns_name = $1; print($data."\n"); } alarm 0; }; print "\nDONE\n\n"; return $good_dns_name; }
I've tweaked and tweaked and now I'm looking for that good ol' perlmonk wisdom. Does my thread management look okay? The ping function does execute and finish after the tcpdump is started. Tcpdump just doesn't break out of the 15 second timeout I set up for it.
In reply to Threads, bash, and networking by morganda
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |