An open API service indexing awesome lists of open source software.

https://github.com/dnaeon/cl-wol

Wake on LAN (WoL) system for Common Lisp
https://github.com/dnaeon/cl-wol

common-lisp lisp wake-on-lan wakeonlan wol

Last synced: 3 months ago
JSON representation

Wake on LAN (WoL) system for Common Lisp

Awesome Lists containing this project

README

        

* cl-wol

=cl-wol= is a Common Lisp system and CLI application, which can power
on remote systems using [[https://en.wikipedia.org/wiki/Wake-on-LAN][Wake on LAN (WoL)]].

* Requirements

- [[https://www.quicklisp.org/beta/][Quicklisp]]

* Installation

=cl-wol= is not yet in Quicklisp, so in order to install it you will need to
clone the repo and add it to your [[https://www.quicklisp.org/beta/faq.html][Quicklisp local-projects]].

#+begin_src shell
cd ~/quicklisp/local-projects
git clone https://github.com/dnaeon/cl-wol.git
#+end_src

If you are installing the CLI application, you will also need a recent
version of [[https://github.com/dnaeon/clingon][clingon]], as the one found in Quicklisp is not yet updated
to the latest release.

* Systems

=cl-wol= provides the following systems.

The =cl-wol.core= system provides the core functionallity for powering
on remote systems using [[https://en.wikipedia.org/wiki/Wake-on-LAN][Wake on LAN (WoL)]] by broadcasting a magic
packet to a destination port and address.

The =cl-wol.test= system provides the test suite of =cl-wol.core=.

The =cl-wol.cli= system provides a command-line interface application,
built on top of =cl-wol.core=, which comes with support for looking up
hosts and their MAC addresses from a local SQLite database.

* Usage

The following formats of MAC addresses are supported by =cl-wol=.

- As a string in =AA:BB:CC:DD:EE:FF= format
- As a string in =AA-BB-CC-DD-EE-FF= format
- As a =(simple-array (unsigned-byte 8) (6))= vector

** API

The following section describes how to use the =cl-wol.core= system.

First, start your Lisp REPL and load the system.

#+begin_src lisp
CL-USER> (ql:quickload :cl-wol.core)
To load "cl-wol.core":
Load 1 ASDF system:
cl-wol.core
; Loading "cl-wol.core"

(:CL-WOL.CORE)
#+end_src

In order to wake a remote system identified by a given MAC address we
first need to create a new instance of =CL-WOL.CORE:MAGIC-PACKET=.

#+begin_src lisp
CL-USER> (defparameter *magic-packet*
(cl-wol.core:make-magic-packet "aa:bb:cc:dd:ee:ff"))
*MAGIC-PACKET*
#+end_src

The =CL-WOL.CORE:MAKE-MAGIC-PACKET= function accepts an optional
second argument, which represents a =SecureOn= password. The format of
the =SecureOn= password is the same as the one for MAC addresses. For
example, if you need to create a magic packet with =SecureOn= password
appended to the payload you can evaluate the following expression.

#+begin_src lisp
CL-USER> (defparameter *magic-packet*
(cl-wol.core:make-magic-packet "aa:bb:cc:dd:ee:ff" "00-00-00-00-00-00"))
*MAGIC-PACKET*
#+end_src

Another way to create a magic packet is by providing a =(simple-array
(unsigned-byte 8) (6)= vector to =CL-WOL.CORE:MAKE-MAGIC-PACKET=. You
can also use the =CL-WOL.CORE:MAKE-OCTET-VECTOR= function to create a
new octet vector. For example.

#+begin_src lisp
CL-USER> (defparameter *magic-packet*
(cl-wol.core:make-magic-packet (cl-wol.core:make-octet-vector #(1 2 3 4 5 6))))
*MAGIC-PACKET*
#+end_src

Now that we have a magic packet we can broadcast it to a given port
and address. In order to do that we will use the =CL-WOL.CORE:WAKE=
generic function. The following example broadcasts the magic packet
to =255.255.255.255= on port =7=.

#+begin_src lisp
CL-USER> (cl-wol.core:wake *magic-packet* "255.255.255.255" 7)
T
#+end_src

** CLI

[[./images/wol-demo.gif]]

You can build the CLI application of =cl-wol= by executing the
following command.

#+begin_src shell
make cli
#+end_src

The default Lisp implementation is SBCL, so if you are using a
different implementation simply pass the =LISP= environment variable
before invoking the =cli= target. This command builds the CLI
application using Clozure Common Lisp for example.

#+begin_src shell
LISP=ccl make cli
#+end_src

Once the app is built you can find the executable in the =bin=
directory of the =cl-wol.cli= system, which you can later install
somewhere in your =PATH=, e.g.

#+begin_src shell
sudo install ./bin/wol /usr/local/bin
#+end_src

You can also generate Zsh completions for the CLI application by
executing the =wol zsh-completions= sub-command, e.g.

#+begin_src shell
wol zsh-completions > ~/.zsh-completions/_wol
#+end_src

You can wake up remote systems by using the =wol wake=
sub-command. Multiple MAC addresses can be specified on the
command-line as separate arguments, e.g.

#+begin_src shell
$ wol wake 00:01:02:03:04:05 aa:bb:cc:dd:ee:ff
Waking up 00:01:02:03:04:05 ...
Waking up aa:bb:cc:dd:ee:ff ...
#+end_src

Instead of remembering MAC addresses by heart the =cl-wol= CLI
application supports storing MAC addresses in a local SQLite database,
which can be looked up by the various sub-commands.

First, we need to initialize a new database file using the =wol
init-db= sub-command.

#+begin_src shell
$ wol init-db --database wol.db
[14:25:36] cl-migratum.core core.lisp (apply-pending) -
Found 1 pending migration(s) to be applied
[14:25:36] cl-migratum.core core.lisp (apply-and-register) -
Applying migration 20211222183337 - add_hosts_table
#+end_src

Once the database is initialized you can add hosts to it. For example:

#+begin_src shell
wol add-host --database wol.db --address aa:bb:cc:dd:ee:ff --name box-01
wol add-host --database wol.db --address 01:02:03:04:05:06 --name box-02
#+end_src

Listing the hosts from the database is done via the =wol list-hosts=
sub-command.

#+begin_src shell
$ wol list-hosts --database wol.db
+----+--------+-------------------+---------------------+
| ID | NAME | ADDR | CREATED AT |
+----+--------+-------------------+---------------------+
| 1 | box-01 | aa:bb:cc:dd:ee:ff | 2021-12-26 14:27:19 |
| 2 | box-02 | 01:02:03:04:05:06 | 2021-12-26 14:27:30 |
+----+--------+-------------------+---------------------+
#+end_src

You can now wake up hosts by referring to their names. In order to do
that use the =--database= and =--name= options of the =wol wake=
sub-command. The =--name= option can be repeated multiple times in
order to refer to different hosts, e.g.

#+begin_src shell
$ wol wake --database wol.db --name box-01 --name box-02
Waking up 01:02:03:04:05:06 ...
Waking up aa:bb:cc:dd:ee:ff ...
#+end_src

Deleting hosts from the database is done via the =wol delete-host=
sub-command, e.g.

#+begin_src shell
wol delete-host --database wol.db box-01 box-02
#+end_src

* Tests

Tests are provided as part of the =:cl-wol.test= system.

In order to run the tests you can evaluate the following expressions
from your Lisp REPL.

#+begin_src lisp
CL-USER> (ql:quickload :cl-wol.test)
CL-USER> (asdf:test-system :cl-wol.test)
#+end_src

Or you can run the tests using the =test= target instead, e.g.

#+begin_src shell
make test
#+end_src

Here's how to run the tests against SBCL, CCL and ECL for example.

#+begin_src shell
for lisp in sbcl ccl ecl; do
echo "Running tests using ${lisp} ..."
LISP=${lisp} make test > ${lisp}-tests.out
done
#+end_src

* Docker Images

You can build and run a Docker image of the CLI application by
executing the following commands.

#+begin_src shell
docker build -t cl-wol.cli:latest -f Dockerfile .
#+end_src

A separate image can be built for running the test suite of =cl-wol=.

#+begin_src shell
docker build -t cl-wol.test:latest -f Dockerfile.tests .
docker run --rm cl-wol.test:latest
#+end_src

* Contributing

=cl-wol= is hosted on [[https://github.com/dnaeon/cl-wol][Github]]. Please contribute by reporting issues,
suggesting features or by sending patches using pull requests.

* License

This project is Open Source and licensed under the [[http://opensource.org/licenses/BSD-2-Clause][BSD License]].

* Authors

- Marin Atanasov Nikolov