Fix TTY implementation
[libremanage.git] / libremanage.py
CommitLineData
3f7ab73a
AR
1"""
2libremanage - Lightweight, free software for remote side-chanel server management
3
4Copyright (C) 2018 Alyssa Rosenzweig
5
6This program is free software: you can redistribute it and/or modify
7it under the terms of the GNU Affero General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU Affero General Public License for more details.
15
16You should have received a copy of the GNU Affero General Public License
17along with this program. If not, see <https://www.gnu.org/licenses/>.
18"""
93f19e92 19
b266c229 20USAGE = """
93f19e92
AR
21Usage:
22
23 $ libremanage [server name] [command]
24
25Example:
26
27 $ libremanage web2 reboot
28
29Server names are defined in the accompanying config.py.
30
31Valid commands are as follows:
32
33 - shutdown, reboot, poweron: Power management
9ed4bf16 34 - tty: Open TTY in GNU Screen
93f19e92
AR
35"""
36
22f864bb
AR
37import sys
38import json
39import functools
40import subprocess
e14c36b3 41
28c204f9
AR
42def open_ssh(server, command):
43 config = server["ssh"]
e51c7dbc 44 subprocess.run(["ssh", "-t", config["username"] + "@" + config["host"], "-p", str(config["port"]), command])
e14c36b3 45
40a688c0
AR
46def die_with_usage(message):
47 print(message)
b266c229
AR
48 print(USAGE)
49 sys.exit(1)
50
d8ddde1a 51def get_server_handle(name):
38e0ee81
AR
52 try:
53 server = CONFIG["servers"][name]
54 except KeyError:
55 die_with_usage("Unknown server, please configure")
56
57 # Associate manager configuration
82ee0c31 58 server["ssh"] = CONFIG["managers"][server["manager"]]
38e0ee81 59
82ee0c31 60 return server
d8ddde1a
AR
61
62def set_server_power(state, server):
20249149 63 print("Setting to power state " + str(state))
e799dcd1
AR
64 conf = server["power"]
65
66 # Set invert to write LOW for power on and HIGH for off
67 if conf["invert"]:
68 state = 1 - state
69
70 print(conf["pin"])
282c96f8 71
c10fa78c 72 # Export pin, configure, write value, unexport
282c96f8 73 open_ssh(server, "echo " + str(conf["pin"]) + " > /sys/class/gpio/export")
c2e97249 74 open_ssh(server, "echo out > /sys/class/gpio/gpio" + str(conf["pin"]) + "/direction")
c10fa78c 75 open_ssh(server, "echo " + str(state) + " > /sys/class/gpio/gpio" + str(conf["pin"]) + "/value")
282c96f8 76 open_ssh(server, "echo " + str(conf["pin"]) + " > /sys/class/gpio/unexport")
d8ddde1a
AR
77
78COMMANDS = {
e14d7650
AR
79 # Power managemment
80
da2eb513
AR
81 "shutdown": functools.partial(set_server_power, 0),
82 "poweron": functools.partial(set_server_power, 1),
83 "reboot": lambda s: (set_server_power(0, s), set_server_power(1, s)),
e14d7650
AR
84
85 # TTY access (or keyboard if wired as such)
86
e51c7dbc 87 "tty": lambda s: open_ssh(s, "screen " + s["tty"]["file"] + " " + str(s["tty"]["baud"])),
e14c36b3 88
da2eb513 89 # SSH sanity tests
82ee0c31 90
28c204f9
AR
91 "sanity": lambda s: open_ssh(s, "whoami"),
92 "console": lambda s: open_ssh(s, ""),
d8ddde1a
AR
93}
94
d24528e4 95def issue_command(server_name, command):
d8ddde1a 96 server = get_server_handle(server_name)
d24528e4 97 print(server_name, command)
40a688c0
AR
98
99 try:
da2eb513 100 callback = COMMANDS[command]
40a688c0
AR
101 except KeyError:
102 die_with_usage("Invalid command supplied")
d24528e4 103
82ee0c31 104 callback(server)
e14d7650 105
22f864bb
AR
106# Load configuration, get command, and go!
107
108with open("config.json") as f:
109 CONFIG = json.load(f)
110
111if len(sys.argv) != 3:
112 die_with_usage("Incorrect number of arguments")
113
d24528e4 114issue_command(sys.argv[1], sys.argv[2])