Skip to content

Commit

Permalink
Fix watchdog & scheduler (#1757)
Browse files Browse the repository at this point in the history
* Fix watchdog & scheduler

* Update supervisor/misc/scheduler.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Fix callback

* hmm

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
  • Loading branch information
pvizeli and MartinHjelmare committed May 28, 2020
1 parent 44fa342 commit 7bd6ff3
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 33 deletions.
8 changes: 5 additions & 3 deletions supervisor/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@
from .hassos import HassOS
from .homeassistant import HomeAssistant
from .host import HostManager
from .hwmon import HwMonitor
from .ingress import Ingress
from .misc.hwmon import HwMonitor
from .misc.scheduler import Scheduler
from .misc.secrets import SecretsManager
from .misc.tasks import Tasks
from .plugins import PluginManager
from .secrets import SecretsManager
from .services import ServiceManager
from .snapshots import SnapshotManager
from .store import StoreManager
from .supervisor import Supervisor
from .tasks import Tasks
from .updater import Updater
from .utils.dt import fetch_timezone

Expand Down Expand Up @@ -70,6 +71,7 @@ async def initialize_coresys() -> None:
coresys.dbus = DBusManager(coresys)
coresys.hassos = HassOS(coresys)
coresys.secrets = SecretsManager(coresys)
coresys.scheduler = Scheduler(coresys)

# bootstrap config
initialize_system_data(coresys)
Expand Down
1 change: 1 addition & 0 deletions supervisor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ class CoreStates(str, Enum):
STARTUP = "startup"
RUNNING = "running"
FREEZE = "freeze"
STOPPING = "stopping"


class LogLevel(str, Enum):
Expand Down
7 changes: 6 additions & 1 deletion supervisor/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ async def start(self):
async def stop(self):
"""Stop a running orchestration."""
# don't process scheduler anymore
self.sys_scheduler.suspend = True
self.state = CoreStates.STOPPING

# store new last boot / prevent time adjustments
if self.state == CoreStates.RUNNING:
Expand All @@ -213,12 +213,17 @@ async def stop(self):

async def shutdown(self):
"""Shutdown all running containers in correct order."""
# don't process scheduler anymore
self.state = CoreStates.STOPPING

# Shutdown Application Add-ons, using Home Assistant API
await self.sys_addons.shutdown(STARTUP_APPLICATION)

# Close Home Assistant
with suppress(HassioError):
await self.sys_homeassistant.stop()

# Shutdown System Add-ons
await self.sys_addons.shutdown(STARTUP_SERVICES)
await self.sys_addons.shutdown(STARTUP_SYSTEM)
await self.sys_addons.shutdown(STARTUP_INITIALIZE)
Expand Down
19 changes: 14 additions & 5 deletions supervisor/coresys.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from .const import UpdateChannels
from .docker import DockerAPI
from .misc.hardware import Hardware
from .misc.scheduler import Scheduler

if TYPE_CHECKING:
from .addons import AddonManager
Expand All @@ -21,16 +20,17 @@
from .dbus import DBusManager
from .discovery import Discovery
from .hassos import HassOS
from .hwmon import HwMonitor
from .misc.scheduler import Scheduler
from .misc.hwmon import HwMonitor
from .misc.secrets import SecretsManager
from .misc.tasks import Tasks
from .homeassistant import HomeAssistant
from .host import HostManager
from .ingress import Ingress
from .secrets import SecretsManager
from .services import ServiceManager
from .snapshots import SnapshotManager
from .supervisor import Supervisor
from .store import StoreManager
from .tasks import Tasks
from .updater import Updater
from .plugins import PluginManager

Expand Down Expand Up @@ -58,7 +58,6 @@ def __init__(self):
self._config: CoreConfig = CoreConfig()
self._hardware: Hardware = Hardware()
self._docker: DockerAPI = DockerAPI()
self._scheduler: Scheduler = Scheduler()

# Internal objects pointers
self._core: Optional[Core] = None
Expand All @@ -77,6 +76,7 @@ def __init__(self):
self._hassos: Optional[HassOS] = None
self._services: Optional[ServiceManager] = None
self._secrets: Optional[SecretsManager] = None
self._scheduler: Optional[Scheduler] = None
self._store: Optional[StoreManager] = None
self._discovery: Optional[Discovery] = None
self._hwmonitor: Optional[HwMonitor] = None
Expand Down Expand Up @@ -127,8 +127,17 @@ def docker(self) -> DockerAPI:
@property
def scheduler(self) -> Scheduler:
"""Return Scheduler object."""
if self._scheduler is None:
raise RuntimeError("Scheduler not set!")
return self._scheduler

@scheduler.setter
def scheduler(self, value: Scheduler) -> None:
"""Set a Scheduler object."""
if self._scheduler:
raise RuntimeError("Scheduler already set!")
self._scheduler = value

@property
def core(self) -> Core:
"""Return core object."""
Expand Down
4 changes: 2 additions & 2 deletions supervisor/hwmon.py → supervisor/misc/hwmon.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

import pyudev

from .coresys import CoreSys, CoreSysAttributes
from .utils import AsyncCallFilter
from ..coresys import CoreSys, CoreSysAttributes
from ..utils import AsyncCallFilter

_LOGGER: logging.Logger = logging.getLogger(__name__)

Expand Down
19 changes: 10 additions & 9 deletions supervisor/misc/scheduler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Schedule for Supervisor."""
import asyncio
from datetime import date, datetime, time, timedelta
import logging

from ..const import CoreStates
from ..coresys import CoreSys, CoreSysAttributes

_LOGGER: logging.Logger = logging.getLogger(__name__)

INTERVAL = "interval"
Expand All @@ -11,14 +13,13 @@
TASK = "task"


class Scheduler:
class Scheduler(CoreSysAttributes):
"""Schedule task inside Supervisor."""

def __init__(self):
def __init__(self, coresys: CoreSys):
"""Initialize task schedule."""
self.loop = asyncio.get_running_loop()
self.coresys: CoreSys = coresys
self._data = {}
self.suspend = False

def register_task(self, coro_callback, interval, repeat=True):
"""Schedule a coroutine.
Expand All @@ -40,8 +41,8 @@ def _run_task(self, task_id):
"""Run a scheduled task."""
data = self._data[task_id]

if not self.suspend:
self.loop.create_task(data[CALL]())
if self.sys_core.state == CoreStates.RUNNING:
self.sys_create_task(data[CALL]())

if data[REPEAT]:
self._schedule_task(data[INTERVAL], task_id)
Expand All @@ -51,7 +52,7 @@ def _run_task(self, task_id):
def _schedule_task(self, interval, task_id):
"""Schedule a task on loop."""
if isinstance(interval, (int, float)):
job = self.loop.call_later(interval, self._run_task, task_id)
job = self.sys_loop.call_later(interval, self._run_task, task_id)
elif isinstance(interval, time):
today = datetime.combine(date.today(), interval)
tomorrow = datetime.combine(date.today() + timedelta(days=1), interval)
Expand All @@ -62,7 +63,7 @@ def _schedule_task(self, interval, task_id):
else:
calc = tomorrow

job = self.loop.call_at(calc.timestamp(), self._run_task, task_id)
job = self.sys_loop.call_at(calc.timestamp(), self._run_task, task_id)
else:
_LOGGER.critical(
"Unknown interval %s (type: %s) for scheduler %s",
Expand Down
4 changes: 2 additions & 2 deletions supervisor/secrets.py → supervisor/misc/secrets.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

from ruamel.yaml import YAML, YAMLError

from .coresys import CoreSys, CoreSysAttributes
from .utils import AsyncThrottle
from ..coresys import CoreSys, CoreSysAttributes
from ..utils import AsyncThrottle

_LOGGER: logging.Logger = logging.getLogger(__name__)

Expand Down
4 changes: 2 additions & 2 deletions supervisor/tasks.py → supervisor/misc/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import asyncio
import logging

from .coresys import CoreSysAttributes
from .exceptions import (
from ..coresys import CoreSysAttributes
from ..exceptions import (
AudioError,
CliError,
CoreDNSError,
Expand Down
18 changes: 9 additions & 9 deletions supervisor/snapshots/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
from pathlib import Path

from ..const import FOLDER_HOMEASSISTANT, SNAPSHOT_FULL, SNAPSHOT_PARTIAL
from ..const import FOLDER_HOMEASSISTANT, SNAPSHOT_FULL, SNAPSHOT_PARTIAL, CoreStates
from ..coresys import CoreSysAttributes
from ..utils.dt import utcnow
from .snapshot import Snapshot
Expand Down Expand Up @@ -125,7 +125,7 @@ async def do_snapshot_full(self, name="", password=None):
snapshot = self._create_snapshot(name, SNAPSHOT_FULL, password)
_LOGGER.info("Full-Snapshot %s start", snapshot.slug)
try:
self.sys_scheduler.suspend = True
self.sys_core.state = CoreStates.FREEZE
await self.lock.acquire()

async with snapshot:
Expand All @@ -147,7 +147,7 @@ async def do_snapshot_full(self, name="", password=None):
return snapshot

finally:
self.sys_scheduler.suspend = False
self.sys_core.state = CoreStates.RUNNING
self.lock.release()

async def do_snapshot_partial(
Expand All @@ -164,7 +164,7 @@ async def do_snapshot_partial(

_LOGGER.info("Partial-Snapshot %s start", snapshot.slug)
try:
self.sys_scheduler.suspend = True
self.sys_core.state = CoreStates.FREEZE
await self.lock.acquire()

async with snapshot:
Expand Down Expand Up @@ -196,7 +196,7 @@ async def do_snapshot_partial(
return snapshot

finally:
self.sys_scheduler.suspend = False
self.sys_core.state = CoreStates.RUNNING
self.lock.release()

async def do_restore_full(self, snapshot, password=None):
Expand All @@ -215,7 +215,7 @@ async def do_restore_full(self, snapshot, password=None):

_LOGGER.info("Full-Restore %s start", snapshot.slug)
try:
self.sys_scheduler.suspend = True
self.sys_core.state = CoreStates.FREEZE
await self.lock.acquire()

async with snapshot:
Expand Down Expand Up @@ -267,7 +267,7 @@ async def do_restore_full(self, snapshot, password=None):
return True

finally:
self.sys_scheduler.suspend = False
self.sys_core.state = CoreStates.RUNNING
self.lock.release()

async def do_restore_partial(
Expand All @@ -287,7 +287,7 @@ async def do_restore_partial(

_LOGGER.info("Partial-Restore %s start", snapshot.slug)
try:
self.sys_scheduler.suspend = True
self.sys_core.state = CoreStates.FREEZE
await self.lock.acquire()

async with snapshot:
Expand Down Expand Up @@ -339,5 +339,5 @@ async def do_restore_partial(
return True

finally:
self.sys_scheduler.suspend = False
self.sys_core.state = CoreStates.RUNNING
self.lock.release()

0 comments on commit 7bd6ff3

Please sign in to comment.