Skip to content

Instantly share code, notes, and snippets.

@jphenow
Created July 10, 2011 22:50
Show Gist options
  • Save jphenow/1075061 to your computer and use it in GitHub Desktop.
Save jphenow/1075061 to your computer and use it in GitHub Desktop.
Little script for running Wake On LAN on a sqlite db of nodes. Must suppy a sqlite file with 'hostname', 'mac_addr', 'ip_addr' columns within a table 'client_info'. Must enable WOL in BIOS and there may still be issues, WOL can be finicky (mostly because
#!/usr/bin/python -u
# mywol.py
# TODO need to check that too many options aren't being mixed at once, some should be exclusive
import subprocess
import sqlite3
from subprocess import Popen, PIPE
from optparse import OptionParser
import sys
# Command line option parse setup
usage = "usage: %prog [options]"
parser = OptionParser( usage )
parser.add_option( "--displayoffline", action="store_true",
dest="displayoffline", default="False", help="Instead of running wol, will display list of known disconnected nodes -- cannot use with wakeoffline or wakeall" )
parser.add_option( "--wakeoffline", action="store_true",
dest="wakeoffline", default="False", help="Runs wol on all offline computers unless given in an --exclude option -- cannot use with displayoffline or wakeall" )
parser.add_option( "--wakeall", action="store",
dest="wakeall", default="", help="List of computer classification groups to wake up -- cannot use with displayoffline or wakeoffline" )
parser.add_option( "--exclude", action="store",
dest="exclude", default="", help="Excludes given hosts from running wol. List hostnames, separate by commas with no spaces." )
parser.add_option( "--verbose", action="store_true",
dest="verbose", default="false", help="Lists where its at as its pinging each computer" )
(options, args) = parser.parse_args( )
# Basic tool variable setup
disconnectedNodes = []
connectedNodes = []
process_excludes = []
# SQLite connection prep
conn = sqlite3.connect( '/path/to/sqlite' ) # Directory to a sqlite file with 'hostname', 'mac_addr', 'ip_addr' columns within a table 'client_info'
conn.row_factory = sqlite3.Row
c = conn.cursor( )
# Setting up arrays based on option args
excludes = str( options.exclude ).split(',')
wakeall = str( options.wakeall ).split(',')
# Main dealings with SQL for displayoffline and wakeoffline
if options.displayoffline is True or options.wakeoffline is True:
# Select statement
c.execute( 'select hostname, mac_addr, ip_addr from client_info' )
# Loop through rows of the select and ping each set of values
for row in c:
iparg = str(row['ip_addr'])
macarg = str(row['mac_addr'])
hostname = str(row['hostname'])
if options.verbose is True:
print "pinging", hostname,
# Call ping on current IP in the for loop
is_online = subprocess.call([ "ping", "-c1", "-w4", iparg ], stdout=PIPE )
if options.verbose is True:
print "... status:", is_online
# Add set of main values into a set of tuples for nodes currently connected or to a list of disconnected nodes
if is_online == 0:
connectedNodes.append((hostname, iparg, macarg))
else:
disconnectedNodes.append((hostname, iparg, macarg))
# Using the args provided with the exclude option add each value to a list so we can exclude these from having wol applied
if len( excludes ) > 0 and options.wakeoffline is True:
for tup in excludes:
if tup == hostname:
excludes.remove( tup )
process_excludes.append((hostname, iparg, macarg))
print "Excluding: ", hostname
# If wakeall is used then use this specific SQL dealing -- should figure out a refactoring, there's lots of repitition here.
elif len(wakeall[0]) > 0:
# Dumb loop to construct a decent string for the SQL select
stringlist = ""
for i in wakeall:
if len( stringlist ) == 0:
stringlist = i+""
else:
stringlist = stringlist, i+""
t = ( stringlist, )
c.execute( "select hostname, mac_addr, ip_addr from client_info where classification in (?)", t )
# This is where refactor should happen... its the exact same as above. Yes I agree, gunshot to the head.
for row in c:
iparg = str(row['ip_addr'])
macarg = str(row['mac_addr'])
hostname = str(row['hostname'])
if options.verbose is True:
print "pinging", hostname,
is_online = subprocess.call([ "ping", "-c1", "-w4", iparg ], stdout=PIPE )
if options.verbose is True:
print "... status:", is_online
if is_online == 0:
connectedNodes.append((hostname, iparg, macarg))
else:
disconnectedNodes.append((hostname, iparg, macarg))
if len( excludes ) > 0 and options.wakeoffline is True or options.wakeall > 0:
for tup in excludes:
if tup == hostname:
excludes.remove( tup )
process_excludes.append((hostname, iparg, macarg))
print "Excluding from wake-up: ", hostname
# Whoops someone forgot to use ANY options, this yells at them and shows a --help before exitting
else:
print "You must supply an option such as --wakeoffline, --displayoffline, or --wakeall to run this script\n\n"
parser.print_help( )
sys.exit()
# Almost forgot this
conn.commit( )
c.close( )
# Could probably do this a little better too, but this rechecks options and displays offline nodes
if options.displayoffline is True:
print "\nCurrently offline nodes:\n"
for node in disconnectedNodes:
print node[0]
# Rechecks options and wakes all computers not in excludes list
elif options.wakeoffline is True:
print "\n\nWol with disconnected nodes"
for node in disconnectedNodes:
if node not in process_excludes:
print "Waking", node[0], "...",
subprocess.call([ "wol", "-i"+ node[1], node[2] ], stdout=PIPE )
print "DONE"
# Rechecks options (REFACTOR DAMNIT) and wakes all computers in wakeall classification and not in excludes (THIS IS THE SAME AS ABOVE)
elif options.wakeall > 0:
print "\n\nAttempting to wake up each computer in:", options.wakeall
for node in disconnectedNodes:
if node not in process_excludes:
print "\nWaking offline computers...\n"
print "Waking", node[0], "...",
subprocess.call([ "wol", "-i"+ node[1], node[2] ], stdout=PIPE )
print "DONE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment