Shutdown the Lab, with Alexa
Contents
Summary⌗
As this is a home lab, there is a tenancy to start it up, play around for a bit and then forget about it and go do something else. This is a bit of a problem at the end of the day when you realise everything else has been shutdown but this power hungry monster is still running. Being rather lazy, the thought of finding a laptop or some other method to shut it all down cleanly is not very appealing but neither is the bill for it running all the time. So this is my solution:
Alexa & IFTTT⌗
IFTTT (If This, Then That) is a nice option that makes adding custom hooks to Amazon’s Alexa nice and easy. The applet in this case will post a message into a particular slack channel saying “Switch off the lab”. The main reason for going this way about it, is I don’t really want anything connecting into the lab or other parts of the home. Rather, a message queue (of sorts) that can be picked up by the lab itself.
IFTTT Applet
Slack & Hubot⌗
So once the message has been posted into the slack channel;
10.44.90.187 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP3QvRkD3b9hIc0FzVABR397yZ5rHob08dLx4ffYdtJP
it gets picked up by Hubot, running with the slack adaptor on the lab box.
Hubot was installed using the npm installer and then set up as a systemd unit to start when the lab does. In order for the bot to read and write into the slack channel, the Hubot app needed to be added to the workspace, this then gives you a legacy bot token for Hubot.
Once Hubot is connected you can then add the scripts required.
This will be moved into Ansible or ideally Ansible Tower so that jobs can be triggered with webhooks, rather than just running arbitrary scripts from Hubot!
This is the Hubot lab.coffee
script that’s running:
module.exports = (robot) ->
# Checks into the room so that you know it's online
robot.messageRoom("automation", "I'm online")
robot.hear /whats running/i, (res) ->
# Resonds with a list of running VMs
@exec = require('child_process').exec
cmd = 'virsh list'
res.send "Checking what VMs are running..."
@exec cmd, (error, stdout, stderr) ->
if error
res.send "```#{error}```"
res.send "```#{stderr}```"
else
res.send "```#{stdout}```"
robot.hear /switch off the lab/i, (res) ->
# Runs a bash script to shut down all the VMs cleanly, then powers off the host
@exec = require('child_process').exec
cmd = './bash_scripts/shutdown.sh'
res.send "Shutting down the lab..
@exec cmd, (error, stdout, stderr) ->
if error
res.send "```#{error}```"
res.send "```#{stderr}```"
else
res.send "```#{stdout}```"
And the Hubot service:
[Unit]
Description=Hubot service
Requires=network.target
After=network.target
[Service]
Type=simple
Environment=HUBOT_SLACK_TOKEN=xoxb-<Slack bot token>
WorkingDirectory=<Hubot install directory>
ExecStart=/bin/bash -a -c 'cd <Hubot install directory> && ./bin/hubot --adapter slack'
[Install]
WantedBy=multi-user.target
As Hubot is just looking for particular strings in messages posted to the channel, it’s possible to skip the Alexa / IFTTT setup and just post messages into the channel directly to trigger Hubot jobs.
Ansible⌗
The plan is to move from bash scripts doing the work to an Ansible Tower / AWX setup. This will then allow Hubot to make web calls to start Ansible jobs. This will probably be documented in a future post.