NAS Drive · Python · Raspberry PI

Python Script: Wake on Lan

Here is a python script that demonstrates how the Wake-on-Lan (WOL) “magic packet” can be generated and sent over the network. I use this mainly for may NAS drive. Further reading: Mounting a NAS drive on Raspberry Pi

#! /usr/bin/python

# wakeonlan.py
#
# Wake on LAN
#
# Use:
# wol computer1
# wol computer1 computer2
# wol 00:11:22:33:44:55
#
# Author: Andreas Hess
#         ahess1@yahoo.de
#
# Original script : San Bergmans
#                   www.sbprojects.net
#

import sys, struct, socket
import time
import subprocess
import os

# Configuration variables
broadcast = ['192.168.1.255', '192.168.0.255']
WOL_PORT = 9
DELAY_TIME = 5  # time to wait between ping commands when waiting for the device to power up
WOL_ERROR = -1

known_computers = {
    'computer1'    : '00:11:22:33:44:55',
    'computer2'    : '00:66:77:88:99:AA',
    'computer3'    : '00:BB:CC:DD:EE:FF',
    }

def WakeOnLan(ethernet_address, port=WOL_PORT):

    # Construct 6 byte hardware address
    add_oct = ethernet_address.split(':')
    if len(add_oct) != 6:
        print "\n*** Illegal MAC address\n"
        print "MAC should be written as 00:11:22:33:44:55\n"
        return WOL_ERROR
    hwa = struct.pack('BBBBBB', int(add_oct[0],16),
        int(add_oct[1],16),
        int(add_oct[2],16),
        int(add_oct[3],16),
        int(add_oct[4],16),
        int(add_oct[5],16))

    # Build magic packet

    msg = '\xff' * 6 + hwa * 16

    # Send packet to broadcast address using UDP port 9

    soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    soc.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST,1)
    for mask in broadcast:
        soc.sendto(msg,(mask,port))
    soc.close()
    return 0

# main starts here
num_args = len (sys.argv)
if num_args == 1:
    print "\n*** No computer given to power up\n"
    print "Use: 'wol computername' or 'wol 00:11:22:33:44:55'"
    quit()

for i in range(1, num_args):
    arg = sys.argv[i]

    # Wake up known computers
    if arg in known_computers:
        if WakeOnLan(known_computers[arg]) == WOL_ERROR:
            print "An error occured when building the magic packet for %s!" % arg
            quit()

    # Wake up using MAC address
    elif len(arg.split(':')) == 6:
        if WakeOnLan(arg) == WOL_ERROR:
            print "An error occured when building the magic packet!"
            quit()
    else:
        print "\n*** Unknown computer " + arg + "\n"
        quit()

if num_args == 2:
    print "\nDone! Host %s should be up and running in a short while." % arg
else:
    print "\nDone! The computers should be up and running in a short while."

# ping known computers until ping responds. Time out is approx. 50* DELAY_TIME (for DELAY_TIME = 5, these are 4 Minutes)
# IP's for known computers is are in  /etc/hosts unless a local DNS server exists
# we cannot ping based on mAC address here (requires additional packages, i.e. bind9)

for i in range(1, num_args):
    arg = sys.argv[i]
    if arg in known_computers:
        k=0
        tstart = time.time()
        while k < 50:
            k += 1
            time.sleep(DELAY_TIME)
            p = subprocess.Popen(["ping", "-c1", "-i.2", arg], stdout = subprocess.PIPE, stderr=subprocess.PIPE)
            p.communicate() # we are not interested in the actual output
            if p.returncode  is 0:
                print "host %s reached." % arg
                break;
            else:
                subprocess.call(["clear"])
                print "wait while NAS is booting up%s" % ("." * k)

        print "time elapsed: %.0f seconds." % (time.time() - tstart)
        if k is 50:
            print "host unavailable."
        else:
            # host reached, now loop until it is mounted
            print "wait until %s is mounted" % arg
            tstart = time.time()
            for m in range(10):
                # print "wait DELAY_TIME seconds, then mount device."
                time.sleep(DELAY_TIME)
                result = subprocess.call(["sudo", "mount", "-a"], stdout = open("/var/tmp/trash.txt", "w"))
                print result
                if result is 0:
                    break

            subprocess.call(["df"])
            print "time elapsed: %.0f seconds." % (time.time() - tstart)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s