Skip to content

Commit bd0f32d

Browse files
authored
Merge pull request #71 from rjsears/v0.991b
V0.991b
2 parents a8b3492 + a4018c6 commit bd0f32d

File tree

7 files changed

+393
-106
lines changed

7 files changed

+393
-106
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h2 align="center">
22
<a name="chia_drive_logo" href="https://github.com/rjsears/chia_plot_manager"><img src="https://github.com/rjsears/chia_plot_manager/blob/main/images/chia_plot_manager_new.png" alt="Chia Plot Manager"></a><br>
33

4-
Chia Plot, Drive Manager, Coin Monitor & Auto Drive (V0.991a - August 28th, 2023)
4+
Chia Plot, Drive Manager, Coin Monitor & Auto Drive (V0.991b - Sept. 4th, 2023)
55
</h2>
66
<p align="center">
77
Multi-Server Chia Plot, Drive Management Solution & Coin Monitor
@@ -582,7 +582,7 @@ Dual Power supplies
582582
<h2>Chia Famer Node</h2>
583583

584584
```
585-
Ubuntu 20.04.3 LTS VM running on Proxmox
585+
Ubuntu 22.04.3 LTS VM running on Proxmox
586586
```
587587

588588
My extra drive chassis are empty right now, but as you can see from my drive layout and mounting
@@ -591,6 +591,9 @@ the strategy above, it is super easy to add more drives.
591591
<br><hr>
592592

593593
### <a name="changelog"></a>Changelog
594+
<b>V0.991b 2023-09-04</b>
595+
- Relocated & reconfigured Farmer & Harvester Health checks so they could be installed/used standalone.
596+
594597
<b>V0.991a 2023-08-28</b>
595598
- Updated farmer_health_check.py to include notifications, better checks, and better logging.
596599
- Updated install script for additional packages

extras/harvester_health_check.py

Lines changed: 0 additions & 104 deletions
This file was deleted.
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#!/usr/bin/python3
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
Simple script that checks to make sure our chia_harvester is running and if not
6+
attempts to (re)start it. Sends notifications when necessary via email to text.
7+
8+
This ONLY checks to see if 'chia_harvester' is a zombie process, or if it is not
9+
running at all. All other psutil p.info(status) just pass through.
10+
11+
Set the email address and hostname below and load in your chia user crontab.
12+
"""
13+
VERSION = "V0.991b (2023-09-04)"
14+
15+
import subprocess
16+
import apt
17+
import os
18+
import configparser
19+
import logging
20+
from system_logging import setup_logging
21+
from system_logging import read_logging_config
22+
from datetime import datetime
23+
import time
24+
from system_info import notify_email_address, notify_sms_address, from_address, host
25+
import psutil
26+
27+
# Set config
28+
config = configparser.ConfigParser()
29+
30+
# Do some housework
31+
today = datetime.today().strftime('%A').lower()
32+
current_military_time = datetime.now().strftime('%H:%M:%S')
33+
current_timestamp = int(time.time())
34+
35+
36+
# Setup Module logging. Main logging is configured in system_logging.py
37+
setup_logging()
38+
level = read_logging_config('harvester_health_config', 'system_logging', 'log_level')
39+
level = logging._checkLevel(level)
40+
log = logging.getLogger(__name__)
41+
log.setLevel(level)
42+
43+
# Setup to read and write to our config file.
44+
# If we are expecting a boolean back pass True/1 for bool,
45+
# otherwise False/0
46+
def read_config_data(file, section, item, bool):
47+
log.debug('read_config_data() Started')
48+
pathname = '/home/chia/harvester_health/' + file
49+
config.read(pathname)
50+
if bool:
51+
return config.getboolean(section, item)
52+
else:
53+
return config.get(section, item)
54+
55+
def update_config_data(file, section, item, value):
56+
log.debug('update_config_data() Started')
57+
pathname = '/home/chia/harvester_health/' + file
58+
config.read(pathname)
59+
cfgfile = open(pathname, 'w')
60+
config.set(section, item, value)
61+
config.write(cfgfile)
62+
cfgfile.close()
63+
64+
65+
# First, let's try and detect how we were installed
66+
# Depending on how we were installed (APT vs. Git) will
67+
# depend on how we call chia. If you installed via Git,
68+
# it is assumed that you installed at '/home/chia/', if
69+
# this is incorrect, you need to update the paths below.
70+
71+
def how_installed():
72+
log.debug('how_installed() called')
73+
cache = apt.Cache()
74+
cache.open()
75+
response = "apt"
76+
try:
77+
cache['chia-blockchain'].is_installed or cache['chia-blockchain-cli'].is_installed
78+
log.debug('It appears Chia was installed via apt....')
79+
except KeyError:
80+
log.debug('A Binary APT installation of Chia was not found, falling back to VENV!')
81+
if os.path.isfile('/home/chia/chia-blockchain/venv/bin/chia'):
82+
log.debug('It appears Chia was installed via VNEV....')
83+
response = "venv"
84+
else:
85+
log.debug('A Chia Installation was not found. Exiting!')
86+
exit()
87+
return (response)
88+
89+
90+
def get_process(process_name):
91+
log.debug('get_process() called')
92+
procs = {p.pid: p.info for p in psutil.process_iter(['status']) if p.name() == process_name}
93+
for i in procs:
94+
for j, k in procs[i].items():
95+
return (k)
96+
97+
def return_process_status(process_name):
98+
log.debug('return_process_status() called')
99+
status = (get_process(process_name))
100+
if status is None:
101+
return False
102+
else:
103+
return(status)
104+
105+
def check_status(process):
106+
log.debug('check_status() called')
107+
status = return_process_status(process)
108+
if not status:
109+
return ('not_running')
110+
elif status == 'zombie':
111+
return ('zombie')
112+
else:
113+
return (status)
114+
115+
116+
def start_chia_harvester():
117+
log.debug('start_chia_harvester() called')
118+
installed = how_installed()
119+
if installed == 'apt':
120+
subprocess.call(['/usr/bin/chia', 'stop', '-d', 'all'])
121+
time.sleep(10)
122+
subprocess.call(['/usr/bin/chia', 'start', 'harvester'])
123+
else:
124+
subprocess.call(['/home/chia/chia-blockchain/venv/bin/chia', 'stop', '-d', 'all'])
125+
time.sleep(10)
126+
subprocess.call(['/home/chia/chia-blockchain/venv/bin/chia', 'start', 'harvester', '-r'])
127+
128+
def check_chia_harvester():
129+
log.debug('check_chia_haravester() called')
130+
status = check_status('chia_harvester')
131+
if status == 'zombie':
132+
start_chia_harvester()
133+
time.sleep(10)
134+
status = check_status('chia_harvester')
135+
if status == 'zombie':
136+
notify('Zombie Infection', f'Harvester {host} has a Zombie Infection - Attempted Restart Failed - HELP ME!')
137+
log.debug('Zombie detected and we could not restart, we are exiting....')
138+
exit()
139+
else:
140+
send_email(notify_email_address, host, 'Zombie Killed, Harvester Restarted')
141+
notify('Zombie Infection Killed', f'Harvester {host} had a Zombie Infection - Attempted Restart Succeeded')
142+
log.debug('Zombie detected and Harvester Restart successful....')
143+
elif status == 'not_running':
144+
start_chia_harvester()
145+
time.sleep(5)
146+
status = check_status('chia_harvester')
147+
if status == 'not_running':
148+
notify('Harvester Not Running!', f'Harvester {host} NOT Running - Attempted Start Failed - HELP ME!')
149+
log.debug('Harvester not running and an attempted restart failed...we are exiting')
150+
exit()
151+
else:
152+
notify('Harvester Restart Successful', f'Harvester {host} has been restarted.')
153+
log.debug('Harvester not running and an attempted restart was successful.....')
154+
else:
155+
print(status)
156+
157+
def send_email(recipient, subject, body):
158+
"""
159+
Part of our notification system.
160+
Setup to send email via the builtin linux mail command.
161+
Your local system **must** be configured already to send mail or this will fail.
162+
https://stackoverflow.com/questions/27874102/executing-shell-mail-command-using-python
163+
https://nedbatchelder.com/text/unipain.html
164+
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-20-04
165+
"""
166+
try:
167+
subprocess.run(['mail', '-s', subject, '-r', from_address, recipient], input=body, encoding='utf-8')
168+
log.debug(f"Email Notification Sent: Subject: {subject}, Recipient: {recipient}, Message: {body}")
169+
except subprocess.CalledProcessError as e:
170+
log.debug(f'send_email error: {e}')
171+
except Exception as e:
172+
log.debug(f'send_email: Unknown Error! Email not sent.')
173+
174+
175+
def notify(title, message):
176+
""" Notify system for email, and sms (via Email to SMS)"""
177+
log.debug(f'notify() called with Title: {title} and Message: {message}')
178+
if (read_config_data('farmer_health_config', 'notifications', 'alerting', True)):
179+
if (read_config_data('harvester_health_config', 'notifications', 'email', True)):
180+
for email_address in notify_email_address:
181+
send_email(email_address, title, message)
182+
if (read_config_data('harvester_health_config', 'notifications', 'sms', True)):
183+
for email_address in notify_sms_address:
184+
send_email(email_address, title, message)
185+
else:
186+
pass
187+
188+
189+
190+
191+
def main():
192+
log.debug('harvester_health_check.py started')
193+
check_chia_harvester()
194+
195+
if __name__ == '__main__':
196+
main()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[system_logging]
2+
logging = True
3+
log_level = DEBUG
4+
5+
[notifications]
6+
alerting = True
7+
email = True
8+
sms = True

0 commit comments

Comments
 (0)