add server wake up

This commit is contained in:
crate 2024-10-11 21:38:20 -05:00
parent 3e39ba13f3
commit 672690974d

106
power.py
View File

@ -4,11 +4,14 @@ import logging
import smtplib import smtplib
import asyncio import asyncio
import discord import discord
from ping3 import ping
from nut2 import PyNUTClient from nut2 import PyNUTClient
from proxmoxer import ProxmoxAPI from proxmoxer import ProxmoxAPI
from email.mime.text import MIMEText from email.mime.text import MIMEText
from wakeonlan import send_magic_packet
from logging.handlers import TimedRotatingFileHandler from logging.handlers import TimedRotatingFileHandler
# Config
ups_id = config.UPS_ID ups_id = config.UPS_ID
gmail_user = config.GMAIL_USER gmail_user = config.GMAIL_USER
gmail_password = config.GMAIL_PASS gmail_password = config.GMAIL_PASS
@ -22,6 +25,13 @@ pve_user = config.PVE_USER
pve_pass = config.PVE_PASS pve_pass = config.PVE_PASS
pve_nodes = ['pve', 'c530'] pve_nodes = ['pve', 'c530']
wol_targets = {
'host1': {'mac': config.HOST1_MAC, 'ip': config.HOST1_IP},
'host2': {'mac': config.HOST2_MAC, 'ip': config.HOST2_IP},
'host3': {'mac': config.HOST3_MAC, 'ip': config.HOST3_IP}
}
# Log Setup
def setup_logging(): def setup_logging():
logger = logging.getLogger('powerlog') logger = logging.getLogger('powerlog')
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
@ -42,6 +52,44 @@ def setup_logging():
logger = setup_logging() logger = setup_logging()
# Email
def send_email(subject, body):
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = gmail_user
msg['To'] = recipient_email
try:
with smtplib.SMTP('smtp.gmail.com', 587) as server:
server.starttls()
server.login(gmail_user, gmail_password)
server.send_message(msg)
logger.info(f"Email message sent: {subject}")
except Exception as e:
logger.info(f"Failed to send email: {e}")
intents = discord.Intents.default()
client = discord.Client(intents=intents)
# Discord
def send_discord(message):
async def message_send():
intents = discord.Intents.default()
client = discord.Client(intents=intents)
@client.event
async def on_ready():
logger.info(f"Client connected as {client.user}")
try:
user = await client.fetch_user(user_id)
await user.send(message)
logger.info(f"Discord message sent: {message}")
except Exception as e:
logger.error(e)
finally:
await client.close()
await client.start(bot_token)
asyncio.run(message_send())
# Server Power Management
proxmox = ProxmoxAPI(pve_host, user=pve_user, password=pve_pass, verify_ssl=False) proxmox = ProxmoxAPI(pve_host, user=pve_user, password=pve_pass, verify_ssl=False)
def shutdown_pve(node): def shutdown_pve(node):
@ -63,46 +111,31 @@ def monitor_ups():
logger.error(f"Error communicating with NUT: {e}") logger.error(f"Error communicating with NUT: {e}")
return None return None
def send_email(subject, body): def wake_up(battery):
msg = MIMEText(body) if battery > 90:
msg['Subject'] = subject for target, addr in wol_targets.items():
msg['From'] = gmail_user mac = addr['mac']
msg['To'] = recipient_email ip = addr['ip']
try: while True:
with smtplib.SMTP('smtp.gmail.com', 587) as server: response = ping(ip)
server.starttls() if response:
server.login(gmail_user, gmail_password) logger.info(response)
server.send_message(msg) logger.info(f"Host {mac} at {ip} is up. Ping {response}.")
logger.info(f"Email message sent: {subject}") time.sleep(5)
except Exception as e: break
logger.info(f"Failed to send email: {e}") else:
send_magic_packet(mac)
intents = discord.Intents.default() logger.warning(f"Host {mac} at {ip} is offline. Sending magic packet.")
client = discord.Client(intents=intents) time.sleep(10)
def send_discord(message):
async def message_send():
intents = discord.Intents.default()
client = discord.Client(intents=intents)
@client.event
async def on_ready():
logger.info(f"Client connected as {client.user}")
try:
user = await client.fetch_user(user_id)
await user.send(message)
logger.info(f"Discord message sent: {message}")
except Exception as e:
logger.error(e)
finally:
await client.close()
await client.start(bot_token)
asyncio.run(message_send())
# Status Communications
def pwr_online(battery): def pwr_online(battery):
message = f"{ups_id} UPS power has been restored. {battery}% charge remaining." message = f"{ups_id} UPS power has been restored. {battery}% charge remaining."
logger.info(message) logger.info(message)
send_email(f"{ups_id}: Power On Line", message) send_email(f"{ups_id}: Power On Line", message)
send_discord(message) send_discord(message)
if ups_id == "Server":
wake_up(battery)
def pwr_offline(battery): def pwr_offline(battery):
message = f"{ups_id} UPS is running on battery power! {battery}% charge remaining." message = f"{ups_id} UPS is running on battery power! {battery}% charge remaining."
@ -122,9 +155,10 @@ def batt_crit(battery):
send_email(f"{ups_id} battery critical!!", message) send_email(f"{ups_id} battery critical!!", message)
send_discord(message) send_discord(message)
# Main Loop
def main(): def main():
logger.info("Starting UPS monitoring service.") logger.info("Starting UPS monitoring service.")
prev_status = None prev_status = "OL"
while True: while True:
ups_data = monitor_ups() ups_data = monitor_ups()
if ups_data: if ups_data:
@ -134,7 +168,7 @@ def main():
if status == "OB DISCHRG": if status == "OB DISCHRG":
pwr_offline(battery) pwr_offline(battery)
elif status == "OL" or status == "OL CHRG": elif status == "OL" or status == "OL CHRG":
pwr_online(battery) pwr_online(battery)
else: else:
logger.info(f"UPS status changed to: {status}") logger.info(f"UPS status changed to: {status}")
prev_status = status prev_status = status