mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Implemented restart service
Implemented an OS and environment safe restart service. This works by running Home Assistant in a child process. If the child process terminates with an exit code > 0, HASS is restarted. SIGTERM and KeyboardInterrupts to the parent process are forwarded to the child process. KeyboardInterrupts will only be forwarded once. The second KeyboardInterrupt will be handled by the parent.
This commit is contained in:
parent
14cd27aaa7
commit
b596fa33d6
@ -1,7 +1,10 @@
|
|||||||
""" Starts home assistant. """
|
""" Starts home assistant. """
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
from multiprocessing import Process
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
import threading
|
||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
@ -204,6 +207,61 @@ def uninstall_osx():
|
|||||||
print("Home Assistant has been uninstalled.")
|
print("Home Assistant has been uninstalled.")
|
||||||
|
|
||||||
|
|
||||||
|
def setup_and_run_hass(config_dir, args):
|
||||||
|
""" Setup HASS and run. Block until stopped. """
|
||||||
|
if args.demo_mode:
|
||||||
|
config = {
|
||||||
|
'frontend': {},
|
||||||
|
'demo': {}
|
||||||
|
}
|
||||||
|
hass = bootstrap.from_config_dict(
|
||||||
|
config, config_dir=config_dir, daemon=args.daemon,
|
||||||
|
verbose=args.verbose, skip_pip=args.skip_pip,
|
||||||
|
log_rotate_days=args.log_rotate_days)
|
||||||
|
else:
|
||||||
|
config_file = ensure_config_file(config_dir)
|
||||||
|
print('Config directory:', config_dir)
|
||||||
|
hass = bootstrap.from_config_file(
|
||||||
|
config_file, daemon=args.daemon, verbose=args.verbose,
|
||||||
|
skip_pip=args.skip_pip, log_rotate_days=args.log_rotate_days)
|
||||||
|
|
||||||
|
if args.open_ui:
|
||||||
|
def open_browser(event):
|
||||||
|
""" Open the webinterface in a browser. """
|
||||||
|
if hass.config.api is not None:
|
||||||
|
import webbrowser
|
||||||
|
webbrowser.open(hass.config.api.base_url)
|
||||||
|
|
||||||
|
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, open_browser)
|
||||||
|
|
||||||
|
hass.start()
|
||||||
|
sys.exit(int(hass.block_till_stopped()))
|
||||||
|
|
||||||
|
|
||||||
|
def run_hass_process(hass_proc):
|
||||||
|
""" Runs a child hass process. Returns True if it should be restarted. """
|
||||||
|
requested_stop = threading.Event()
|
||||||
|
hass_proc.daemon = True
|
||||||
|
|
||||||
|
def request_stop():
|
||||||
|
""" request hass stop """
|
||||||
|
requested_stop.set()
|
||||||
|
hass_proc.terminate()
|
||||||
|
|
||||||
|
try:
|
||||||
|
signal.signal(signal.SIGTERM, request_stop)
|
||||||
|
except ValueError:
|
||||||
|
print('Could not bind to SIGQUIT. Are you running in a thread?')
|
||||||
|
|
||||||
|
hass_proc.start()
|
||||||
|
try:
|
||||||
|
hass_proc.join()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
request_stop()
|
||||||
|
hass_proc.join()
|
||||||
|
return not requested_stop.isSet() and hass_proc.exitcode > 0
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
""" Starts Home Assistant. """
|
""" Starts Home Assistant. """
|
||||||
validate_python()
|
validate_python()
|
||||||
@ -233,33 +291,12 @@ def main():
|
|||||||
if args.pid_file:
|
if args.pid_file:
|
||||||
write_pid(args.pid_file)
|
write_pid(args.pid_file)
|
||||||
|
|
||||||
if args.demo_mode:
|
# Run hass is child process. Restart if necessary.
|
||||||
config = {
|
keep_running = True
|
||||||
'frontend': {},
|
while keep_running:
|
||||||
'demo': {}
|
hass_proc = Process(target=setup_and_run_hass, args=(config_dir, args))
|
||||||
}
|
keep_running = run_hass_process(hass_proc)
|
||||||
hass = bootstrap.from_config_dict(
|
|
||||||
config, config_dir=config_dir, daemon=args.daemon,
|
|
||||||
verbose=args.verbose, skip_pip=args.skip_pip,
|
|
||||||
log_rotate_days=args.log_rotate_days)
|
|
||||||
else:
|
|
||||||
config_file = ensure_config_file(config_dir)
|
|
||||||
print('Config directory:', config_dir)
|
|
||||||
hass = bootstrap.from_config_file(
|
|
||||||
config_file, daemon=args.daemon, verbose=args.verbose,
|
|
||||||
skip_pip=args.skip_pip, log_rotate_days=args.log_rotate_days)
|
|
||||||
|
|
||||||
if args.open_ui:
|
|
||||||
def open_browser(event):
|
|
||||||
""" Open the webinterface in a browser. """
|
|
||||||
if hass.config.api is not None:
|
|
||||||
import webbrowser
|
|
||||||
webbrowser.open(hass.config.api.base_url)
|
|
||||||
|
|
||||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, open_browser)
|
|
||||||
|
|
||||||
hass.start()
|
|
||||||
hass.block_till_stopped()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -10,7 +10,6 @@ MATCH_ALL = '*'
|
|||||||
DEVICE_DEFAULT_NAME = "Unnamed Device"
|
DEVICE_DEFAULT_NAME = "Unnamed Device"
|
||||||
|
|
||||||
# #### CONFIG ####
|
# #### CONFIG ####
|
||||||
CONF_ICON = "icon"
|
|
||||||
CONF_LATITUDE = "latitude"
|
CONF_LATITUDE = "latitude"
|
||||||
CONF_LONGITUDE = "longitude"
|
CONF_LONGITUDE = "longitude"
|
||||||
CONF_TEMPERATURE_UNIT = "temperature_unit"
|
CONF_TEMPERATURE_UNIT = "temperature_unit"
|
||||||
@ -124,6 +123,7 @@ ATTR_GPS_ACCURACY = 'gps_accuracy'
|
|||||||
|
|
||||||
# #### SERVICES ####
|
# #### SERVICES ####
|
||||||
SERVICE_HOMEASSISTANT_STOP = "stop"
|
SERVICE_HOMEASSISTANT_STOP = "stop"
|
||||||
|
SERVICE_HOMEASSISTANT_RESTART = "restart"
|
||||||
|
|
||||||
SERVICE_TURN_ON = 'turn_on'
|
SERVICE_TURN_ON = 'turn_on'
|
||||||
SERVICE_TURN_OFF = 'turn_off'
|
SERVICE_TURN_OFF = 'turn_off'
|
||||||
|
@ -16,7 +16,8 @@ from collections import namedtuple
|
|||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
__version__, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
__version__, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
||||||
SERVICE_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED, EVENT_STATE_CHANGED,
|
SERVICE_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_RESTART,
|
||||||
|
EVENT_TIME_CHANGED, EVENT_STATE_CHANGED,
|
||||||
EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL,
|
EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL,
|
||||||
EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED,
|
EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED,
|
||||||
TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_FRIENDLY_NAME)
|
TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_FRIENDLY_NAME)
|
||||||
@ -70,13 +71,21 @@ class HomeAssistant(object):
|
|||||||
def block_till_stopped(self):
|
def block_till_stopped(self):
|
||||||
"""Register service homeassistant/stop and will block until called."""
|
"""Register service homeassistant/stop and will block until called."""
|
||||||
request_shutdown = threading.Event()
|
request_shutdown = threading.Event()
|
||||||
|
request_restart = threading.Event()
|
||||||
|
|
||||||
def stop_homeassistant(*args):
|
def stop_homeassistant(*args):
|
||||||
"""Stop Home Assistant."""
|
"""Stop Home Assistant."""
|
||||||
request_shutdown.set()
|
request_shutdown.set()
|
||||||
|
|
||||||
|
def restart_homeassistant(*args):
|
||||||
|
"""Reset Home Assistant."""
|
||||||
|
request_restart.set()
|
||||||
|
request_shutdown.set()
|
||||||
|
|
||||||
self.services.register(
|
self.services.register(
|
||||||
DOMAIN, SERVICE_HOMEASSISTANT_STOP, stop_homeassistant)
|
DOMAIN, SERVICE_HOMEASSISTANT_STOP, stop_homeassistant)
|
||||||
|
self.services.register(
|
||||||
|
DOMAIN, SERVICE_HOMEASSISTANT_RESTART, restart_homeassistant)
|
||||||
|
|
||||||
if os.name != "nt":
|
if os.name != "nt":
|
||||||
try:
|
try:
|
||||||
@ -92,6 +101,7 @@ class HomeAssistant(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
self.stop()
|
self.stop()
|
||||||
|
return request_restart.isSet()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Stop Home Assistant and shuts down all threads."""
|
"""Stop Home Assistant and shuts down all threads."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user