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