HA-EasyComputerManager/utils.py
2023-04-04 13:44:07 +02:00

194 lines
6.8 KiB
Python

import logging
import fabric2
from fabric2 import Connection
_LOGGER = logging.getLogger(__name__)
# _LOGGER.setLevel(logging.DEBUG)
def create_ssh_connection(host: str, username: str, password: str, port=22):
"""Create an SSH connection to a host using a username and password specified in the config flow."""
conf = fabric2.Config()
conf.run.hide = True
conf.run.warn = True
conf.warn = True
conf.sudo.password = password
conf.password = password
connection = Connection(
host=host, user=username, port=port, connect_timeout=3, connect_kwargs={"password": password},
config=conf
)
_LOGGER.info("CONNECTED SSH")
return connection
def test_connection(connection: Connection):
"""Test the connection to the host by running a simple command."""
try:
connection.run('ls')
return True
except Exception:
return False
def is_unix_system(connection: Connection):
"""Return a boolean based on get_operating_system result."""
return get_operating_system(connection) == "Linux/Unix"
def get_operating_system_version(connection: Connection, is_unix=None):
"""Return the running operating system name and version."""
if is_unix is None:
is_unix = is_unix_system(connection)
if is_unix:
return connection.run(
"lsb_release -a | awk '/Description/ {print $2, $3, $4}'"
).stdout
else:
return connection.run(
'for /f "tokens=1 delims=|" %i in (\'wmic os get Name ^| findstr /B /C:"Microsoft"\') do @echo %i'
).stdout
def get_operating_system(connection: Connection):
"""Return the running operating system type."""
result = connection.run("uname")
if result.return_code == 0:
return "Linux/Unix"
else:
return "Windows/Other"
def shutdown_system(connection: Connection, is_unix=None):
"""Shutdown the system."""
if is_unix is None:
is_unix = is_unix_system(connection)
if is_unix:
# First method using shutdown command
result = connection.run("sudo shutdown -h now")
if result.return_code != 0:
# Try a second method using init command
result = connection.run("sudo init 0")
if result.return_code != 0:
# Try a third method using systemctl command
result = connection.run("sudo systemctl poweroff")
if result.return_code != 0:
_LOGGER.error("Cannot restart system, all methods failed.")
else:
# First method using shutdown command
result = connection.run("shutdown /s /t 0")
if result.return_code != 0:
# Try a second method using init command
result = connection.run("wmic os where Primary=TRUE call Shutdown")
if result.return_code != 0:
_LOGGER.error("Cannot restart system, all methods failed.")
connection.close()
def restart_system(connection: Connection, is_unix=None):
"""Restart the system."""
if is_unix is None:
is_unix = is_unix_system(connection)
if is_unix:
# First method using shutdown command
result = connection.run("sudo shutdown -r now")
if result.return_code != 0:
# Try a second method using init command
result = connection.run("sudo init 6")
if result.return_code != 0:
# Try a third method using systemctl command
result = connection.run("sudo systemctl reboot")
if result.return_code != 0:
_LOGGER.error("Cannot restart system, all methods failed.")
else:
# First method using shutdown command
result = connection.run("shutdown /r /t 0")
if result.return_code != 0:
# Try a second method using wmic command
result = connection.run("wmic os where Primary=TRUE call Reboot")
if result.return_code != 0:
_LOGGER.error("Cannot restart system, all methods failed.")
def sleep_system(connection: Connection, is_unix=None):
"""Put the system to sleep."""
if is_unix is None:
is_unix = is_unix_system(connection)
if is_unix:
# First method using systemctl command
result = connection.run("sudo systemctl suspend")
if result.return_code != 0:
# Try a second method using pm-suspend command
result = connection.run("sudo pm-suspend")
if result.return_code != 0:
_LOGGER.error("Cannot restart system, all methods failed.")
else:
# First method using shutdown command
result = connection.run("shutdown /h /t 0")
if result.return_code != 0:
# Try a second method using rundll32 command
result = connection.run("rundll32.exe powrprof.dll,SetSuspendState Sleep")
if result.return_code != 0:
_LOGGER.error("Cannot restart system, all methods failed.")
def get_windows_entry_in_grub(connection: Connection):
"""
Grabs the Windows entry name in GRUB.
Used later with grub-reboot to specify which entry to boot.
"""
result = connection.run("sudo awk -F \"'\" '/windows/ {print $2}' /boot/grub/grub.cfg")
if result.return_code == 0:
_LOGGER.debug("Found Windows entry in grub : " + result.stdout.strip())
else:
result = connection.run("sudo awk -F \"'\" '/windows/ {print $2}' /boot/grub2/grub.cfg")
if result.return_code == 0:
_LOGGER.debug("Found windows entry in grub2 : " + result.stdout.strip())
else:
_LOGGER.error("Cannot find windows entry in grub")
return None
# Check if the entry is valid
if result.stdout.strip() != "":
return result.stdout.strip()
else:
_LOGGER.error("Cannot find windows entry in grub")
return None
def restart_to_windows_from_linux(connection: Connection):
"""Restart a running Linux system to Windows."""
if is_unix_system(connection):
windows_entry = get_windows_entry_in_grub(connection)
if windows_entry is not None:
# First method using grub-reboot command
result = connection.run(f"sudo grub-reboot \"{windows_entry}\"")
if result.return_code != 0:
# Try a second method using grub2-reboot command
result = connection.run(f"sudo grub2-reboot \"{windows_entry}\"")
# Restart system if successful grub(2)-reboot command
if result.return_code == 0:
_LOGGER.info("Rebooting to Windows")
restart_system(connection)
else:
_LOGGER.error("Cannot restart system to windows from linux, all methods failed.")
else:
_LOGGER.error("Cannot restart to Windows from Linux, system is not Linux/Unix")