Skip to content

Commit b87013a

Browse files
authored
interior crocodile alligator (kurisufriend#1)
* check for blocking * fiddle with timeouts? * move stuff around * a * typo * timestamp serber logs * &tear * nab whipper conf * pass along ws * stupendous things * or gathering wood at your campsite reduces the spread of invasive species * select stdout to display webside * send discinfo no matter the drive state * rip with --cdr and -U (-unknown) * extend timeouts. just cause. * songtitle n reduce mainloop polling rate (gotta scrimp n save dem packets) * eep~ * namecollide on 'nodes'. my bad! * delineate blocks * multilines somehow generating? test. * advertising neals * bleh * fix title parsing * s/song title/album title/g * s not working... * whitespace is the mind killer. whitespace is the little death that leads to total annihalation. * reset rip status on tray open * s/saya/\$hostname/ for key specified in mount * final touches to the deploy stack + all working nodes * definitely send diskinfo before ripping
1 parent a9c9a19 commit b87013a

File tree

6 files changed

+104
-38
lines changed

6 files changed

+104
-38
lines changed

client/client.py

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,31 @@ def disk_id():
117117
def diskinfo():
118118
return {"type": "diskinfo", "data": {"open": get_drive_status(), "title": disk_id()}}
119119

120-
async def rip():
121-
cmd = ["whipper", "cd", "rip", "-O", "/mnt/chip/ripz/" + disk_id()]
120+
async def rip(ws):
121+
cmd = ["whipper", "cd", "rip", "--cdr", "-U", "-O", "/mnt/chip/ripz/" + disk_id()]
122122
process = await asyncio.create_subprocess_exec(*cmd, stdout=asyncio.subprocess.PIPE)
123123

124+
await ws.send(json.dumps({"type": "songtitle", "data": {"songtitle": "not sure yet..."}}))
125+
await ws.send(json.dumps(diskinfo()))
126+
124127
acc = ""
125128
while not process.stdout.at_eof():
126129
newc = await process.stdout.read(1)
127-
time.sleep(.01)
130+
await asyncio.sleep(.01)
128131
if not newc:
129132
break
130133
acc += newc.decode("latin-1")
131134
if "\r" in acc:
132135
print(acc)
133-
acc = ""
136+
acc = acc.strip()
137+
if acc == "": continue # don't blank out rip status! whipper sends newlines sometimes.
138+
# god only knows why.
139+
if "Title" in acc:
140+
tit = [i for i in acc.split("\n") if "Title" in i][0]
141+
142+
await ws.send(json.dumps({"type": "songtitle", "data": {"songtitle": tit}}))
134143
await ws.send(json.dumps({"type": "liverip", "data": {"stdout": acc, "stderr": ""}}))
144+
acc = ""
135145

136146

137147

@@ -142,28 +152,22 @@ async def rip():
142152
# assert whipper cfg exists
143153
if not os.path.exists("/root/.config/whipper/whipper.conf"):
144154
os.makedirs("/root/.config/whipper", exist_ok=True)
145-
urllib.request.urlretrieve("https://raw.githubusercontent.com/kurisufriend/chip/refs/heads/master/tools/whipper/whipper.conf")
146-
155+
urllib.request.urlretrieve("https://raw.githubusercontent.com/kurisufriend/chip/refs/heads/master/tools/whipper/whipper.conf", filename="/root/.config/whipper/whipper.conf")
147156

148-
# event loop
149-
async def fuck():
150-
# checkin
151-
ws = await websockets.connect("ws://"+cfg["master-fqdn"]+":"+str(cfg["master-ws-port"]))
152-
hostname = subprocess.check_output("hostname", shell=True).decode("latin-1").strip()
153-
await ws.send(json.dumps({"type": "checkin/client", "data": {
154-
"hostname": hostname,
155-
"meta": "",
156-
"diskinfo": diskinfo()
157-
}}))
158-
print("semt")
157+
# mind to the drive
158+
async def handle_drive(ws):
159159
while True:
160-
time.sleep(1)
160+
await ws.send(json.dumps(diskinfo()))
161+
await asyncio.sleep(5)
161162
# tray closed w nothing in
162163
if get_drive_status() == "empty":
163164
drive_open()
165+
await ws.send(json.dumps({"type": "songtitle", "data": {"songtitle": "no disk"}}))
166+
continue
167+
elif get_drive_status() == "open":
168+
await ws.send(json.dumps({"type": "songtitle", "data": {"songtitle": "no disk"}}))
169+
await ws.send(json.dumps({"type": "liverip", "data": {"stdout": "", "stderr": ""}}))
164170
continue
165-
elif get_drive_status() == "open": continue
166-
167171
# => we full
168172
did = disk_id()
169173

@@ -172,10 +176,22 @@ async def fuck():
172176
drive_open()
173177
continue
174178

175-
# => we got an unripped disk.
179+
# => we got an unripped disk.
180+
await rip(ws)
176181

177-
await ws.send(json.dumps(diskinfo()))
178-
#await rip()
182+
183+
# event loop
184+
async def fuck():
185+
# checkin
186+
ws = await websockets.connect("ws://"+cfg["master-fqdn"]+":"+str(cfg["master-ws-port"]), ping_timeout=40, close_timeout=60)
187+
hostname = subprocess.check_output("hostname", shell=True).decode("latin-1").strip()
188+
await ws.send(json.dumps({"type": "checkin/client", "data": {
189+
"hostname": hostname,
190+
"meta": "",
191+
"diskinfo": diskinfo()
192+
}}))
193+
print("semt")
194+
await handle_drive(ws)
179195
await ws.close()
180196

181197
asyncio.run(fuck())

fe/index.html

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,19 @@ <h1>cdr (legally distinct from jtr)</h1>
3232

3333
let ws = new WebSocket(backend)
3434

35+
const nodes_pos = {
36+
"sweeneytodd": "1",
37+
"williamafton": "2",
38+
"patrickbateman": "3",
39+
"lightyagami": "6",
40+
"victorzsasz": "10",
41+
"hanniballecter": "11",
42+
"jasonvoorhess": "13",
43+
"michaelmeyers": "17",
44+
"carcer": "4",
45+
"saya": "8"
46+
}
47+
3548
ws.addEventListener('open', (event) => {
3649
console.log('connected');
3750
ws.send(JSON.stringify(
@@ -48,10 +61,11 @@ <h1>cdr (legally distinct from jtr)</h1>
4861
if (j["type"] == "state")
4962
{
5063
const nodes = j.data.map((node) => ({
51-
id: 0,
64+
id: nodes_pos[node.hostname] || "?",
5265
hostname: node.hostname,
5366
tray_status: node.diskinfo.data.open,
5467
barcode: node.diskinfo.data.title,
68+
song_title: node.songtitle,
5569
rip_status: node.ripstatus,
5670
}));
5771

@@ -75,6 +89,7 @@ <h1>cdr (legally distinct from jtr)</h1>
7589
<th>hostname</th>\
7690
<th>tray status</th>\
7791
<th>barcode</th>\
92+
<th>album title</th>\
7893
<th>rip status</th>\
7994
</tr>';
8095

@@ -93,6 +108,9 @@ <h1>cdr (legally distinct from jtr)</h1>
93108
let barcode = row.insertCell();
94109
barcode.textContent = node['barcode'];
95110

111+
let song_title = row.insertCell();
112+
song_title.textContent = node['song_title'];
113+
96114
let rip_status = row.insertCell();
97115
rip_status.textContent = node['rip_status'];
98116
});

nodes.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,33 @@
22
{
33
"host": "saya",
44
"ipv4": "192.168.10.103"
5+
},
6+
{
7+
"host": "sweeneytodd",
8+
"ipv4": "192.168.10.112"
9+
},
10+
{
11+
"host": "williamafton",
12+
"ipv4": "192.168.10.114"
13+
},
14+
{
15+
"host": "patrickbateman",
16+
"ipv4": "192.168.10.143"
17+
},
18+
{
19+
"host": "lightyagami",
20+
"ipv4": "192.168.10.100"
21+
},
22+
{
23+
"host": "victorzsasz",
24+
"ipv4": "192.168.10.122"
25+
},
26+
{
27+
"host": "hanniballecter",
28+
"ipv4": "192.168.10.108"
29+
},
30+
{
31+
"host": "michaelmeyers",
32+
"ipv4": "192.168.10.87"
533
}
634
]

serb/serb.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,26 @@ async def ws_handler(self, ws):
6363
print("new FE")
6464
continue
6565

66-
print("FROM " + self.clients[ws.remote_address]["hostname"] + json.dumps(j, indent=2))
66+
print(time.ctime() + " // FROM " + self.clients[ws.remote_address]["hostname"] + json.dumps(j, indent=2))
6767

6868
async def wsh_checkin_client(self, ws, message):
6969
self.clients[ws.remote_address] = {"hostname": message["data"]["hostname"]}
7070
self.clients[ws.remote_address]["diskinfo"] = message["data"]["diskinfo"]
7171
self.clients[ws.remote_address]["ws"] = ws
7272
self.clients[ws.remote_address]["ripstatus"] = "..."
73+
self.clients[ws.remote_address]["songtitle"] = "..."
7374

7475
async def wsh_checkin_fe(self, ws, message):
7576
self.fes[ws.remote_address] = {"yay": "louder", "ws": ws}
7677

7778
async def wsh_diskinfo(self, ws, message):
7879
self.clients[ws.remote_address]["diskinfo"] = message
80+
81+
async def wsh_songtitle(self, ws, message):
82+
self.clients[ws.remote_address]["songtitle"] = message["data"]["songtitle"]
83+
84+
async def wsh_liverip(self, ws, message):
85+
self.clients[ws.remote_address]["ripstatus"] = message["data"]["stdout"]
7986

8087
async def update_fes(self):
8188
while True:
@@ -87,6 +94,7 @@ async def update_fes(self):
8794
"hostname": client["hostname"],
8895
"diskinfo": client["diskinfo"],
8996
"ripstatus": client["ripstatus"],
97+
"songtitle": client["songtitle"]
9098
}
9199
package["data"].append(res)
92100
for fek in self.fes.keys():

tools/bootstrap.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@
33
import os, sys, subprocess
44

55

6-
if not os.getenv("SSHPASS"):
7-
print("SSHPASS environment variable must be set the the password of the `chip` service user on alexandria")
8-
print("try something like\nexport SSHPASS=\"passwd goes here\" && python3 tools/bootstrap.py")
9-
sys.exit(1)
10-
116
# run as root
127
if subprocess.check_output(["whoami"]).decode("ascii").replace("\n", "") != "root":
138
print("run as root")
@@ -39,12 +34,10 @@ def notsed(file, old, new):
3934
os.system("systemctl restart sshd")
4035

4136

42-
# install sshpass
43-
os.system("apt install -y sshpass")
44-
4537
# generate new keys & copy to chip@alexandria
4638
os.system("ssh-keygen -f /root/.ssh/$(hostname)-whoreslayer-node -t ed25519")
47-
os.system("sshpass -e ssh-copy-id -i /root/.ssh/$(hostname)-whoreslayer-node [email protected]")
39+
os.system("ssh-copy-id -i /root/.ssh/$(hostname)-whoreslayer-node [email protected]")
40+
os.system("ssh-keyscan -t ed25519 alexandria.wuvt.vt.edu >> /root/.ssh/known_hosts")
4841

4942
# clear bash_history to minimize cred leakage
5043
os.system("rm /root/.bash_history")

tools/deploy.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import os, json
1+
import os, json, sys
22

33
manifest = []
44

@@ -14,15 +14,16 @@
1414
"curl",
1515
"beep"
1616
]
17+
manifest.append("apt update")
1718
manifest.append("apt install -y " + " ".join(pkgs))
1819

1920

2021
# add sshfs mount to <strike>/etc/fstab</strike> crontab
2122

2223
manifest.append("mkdir -p /mnt/chip")
2324
# idempotent as heck
24-
manifest.append("(echo \\\"@reboot sshfs /mnt/chip/ [email protected]:/tank/archive/rips/chip -o IdentityFile=/root/.ssh/saya-whoreslayer-node\\\") | crontab -")
25-
manifest.append("(crontab -l; echo \\\"*/1 * * * * [ -d /mnt/chip/tools ] || sshfs /mnt/chip/ [email protected]:/tank/archive/rips/chip -o IdentityFile=/root/.ssh/saya-whoreslayer-node\\\") | crontab -")
25+
manifest.append("(echo \\\"@reboot sshfs /mnt/chip/ [email protected]:/tank/archive/rips/chip -o IdentityFile=/root/.ssh/$$$HOSTNAME$$$-whoreslayer-node\\\") | crontab -")
26+
manifest.append("(crontab -l; echo \\\"*/1 * * * * [ -d /mnt/chip/tools ] || sshfs /mnt/chip/ [email protected]:/tank/archive/rips/chip -o IdentityFile=/root/.ssh/$$$HOSTNAME$$$-whoreslayer-node\\\") | crontab -")
2627

2728
# install systemd service (re-installs every time: idempotent by default)
2829
link = "https://raw.githubusercontent.com/kurisufriend/chip/refs/heads/master/tools/service/chip-client.service"
@@ -36,6 +37,8 @@
3637
with open("nodes.json", "r") as f:
3738
nodes = json.loads(f.read())
3839
for n in nodes:
40+
if "--specify" in sys.argv and not n["host"] in sys.argv:
41+
continue
3942
for cmd in manifest:
4043
print(">> " + cmd)
41-
os.system(f"ssh root@{n['ipv4']} \"{cmd}\"")
44+
os.system(f"ssh root@{n['ipv4']} \"{cmd}\"".replace("$$$HOSTNAME$$$", n["host"]))

0 commit comments

Comments
 (0)