aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--actions.yml1
-rw-r--r--automato/command.py37
-rw-r--r--automato/transport.py23
-rw-r--r--endpoints.yml6
4 files changed, 66 insertions, 1 deletions
diff --git a/actions.yml b/actions.yml
index c91759c..caf6e70 100644
--- a/actions.yml
+++ b/actions.yml
@@ -11,3 +11,4 @@ send-hello:
msg: Hello
- host1.notify:
msg: World!
+ - host1.wol: {}
diff --git a/automato/command.py b/automato/command.py
index 49956a0..1926c2e 100644
--- a/automato/command.py
+++ b/automato/command.py
@@ -1,5 +1,11 @@
from . import transport
+import logging
+
+import binascii
+import socket
+
+logger = logging.getLogger(__name__)
'''
Implementations of Command:
@@ -25,3 +31,34 @@ class NotifyCommand(Command):
def execute(self, msg: str):
self._transport.execHandleStderror(f'notify-send "{msg}"')
+
+'''
+WakeOnLanCommand sends a WOL magic packet to wake a device.
+
+Transport: MetaDataTransport with attribute 'mac' set to the devices'
+MAC Address in the standard XX:XX:XX:XX:XX:XX format.
+'''
+class WakeOnLanCommand(Command):
+
+ def __init__(self, transport: transport.MetaDataTransport):
+ self._transport = transport
+
+ def execute(self):
+ mac_bytes = b''
+ try:
+ mac_bytes = binascii.unhexlify(self._transport.mac.replace(':',''))
+ except binascii.Error:
+ logger.error(f'MAC Address "{self._transport.mac}" failed to parse to binary')
+ return
+
+ if len(mac_bytes) != 6:
+ logger.error(f'MAC Address "{self._transport.mac}" is malformed')
+ return
+
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+
+ magic = b'\xff' * 6 + mac_bytes * 16
+ s.sendto(magic, ('<broadcast>', 7))
+
+ logger.debug(f'Sent magic packet to {self._transport.mac}')
diff --git a/automato/transport.py b/automato/transport.py
index 5067a92..327946e 100644
--- a/automato/transport.py
+++ b/automato/transport.py
@@ -1,6 +1,8 @@
import paramiko
import logging
+from typing import Union
+
logger = logging.getLogger(__name__)
HOLD = 1
@@ -57,10 +59,29 @@ class Transport:
def isConnected(self) -> bool:
return self._connected
+'''
+MetaDataTransport holds any data passed to it.
+It does not establish any connection and is only used
+to store metadata that may be used by commands that do not
+require a connection, such as Wake on Lan.
+'''
+class MetaDataTransport(Transport):
+ CONNECTION=THROWAWAY
+
+ def __init__(self, **kwargs):
+ self._metadata = kwargs
+
+ def __getattr__(self, attr):
+ return self._metadata[attr]
+
+ def check(self):
+ return True
+
+
class SshTransport(Transport):
CONNECTION=HOLD
- def __init__(self, hostname: str, port=22, username='root', password = None, id_file = None, allow_agent=False):
+ def __init__(self, hostname: str, port=22, username='root', password = None, id_file = None, allow_agent = False):
super().__init__()
self._hostname = hostname
self._port = port
diff --git a/endpoints.yml b/endpoints.yml
index 26d5340..8a59517 100644
--- a/endpoints.yml
+++ b/endpoints.yml
@@ -5,10 +5,16 @@ host1:
hostname: 'localhost'
username: 'jonas'
allow_agent: True
+ meta:
+ class: automato.transport.MetaDataTransport
+ mac: 00:00:00:00:00:00
commands:
notify:
class: automato.command.NotifyCommand
transport: ssh
+ wol:
+ class: automato.command.WakeOnLanCommand
+ transport: meta
states:
user:
class: automato.state.UserSessionState