Exemplo n.º 1
0
    async def fetch_data(self):
        """Fetch current versions from Github.

        Is a coroutine.
        """
        url = URL_OPPIO_VERSION.format(channel=self.channel)
        machine = self.sys_machine or "default"

        try:
            _LOGGER.info("Fetching update data from %s", url)
            async with self.sys_websession.get(url, timeout=10) as request:
                data = await request.json(content_type=None)

        except (aiohttp.ClientError, asyncio.TimeoutError) as err:
            _LOGGER.warning("Can't fetch versions from %s: %s", url, err)
            raise UpdaterError() from err

        except json.JSONDecodeError as err:
            _LOGGER.warning("Can't parse versions from %s: %s", url, err)
            raise UpdaterError() from err

        # data valid?
        if not data or data.get(ATTR_CHANNEL) != self.channel:
            _LOGGER.warning("Invalid data from %s", url)
            raise UpdaterError()

        try:
            # Update supervisor version
            self._data[ATTR_SUPERVISOR] = AwesomeVersion(data["supervisor"])

            # Update Open Peer Power core version
            self._data[ATTR_OPENPEERPOWER] = AwesomeVersion(
                data["openpeerpower"][machine])

            # Update OppOS version
            if self.sys_oppos.board:
                self._data[ATTR_OPPOS] = AwesomeVersion(
                    data["oppos"][self.sys_oppos.board])
                self._data[ATTR_OTA] = data["ota"]

            # Update Open Peer Power plugins
            self._data[ATTR_CLI] = AwesomeVersion(data["cli"])
            self._data[ATTR_DNS] = AwesomeVersion(data["dns"])
            self._data[ATTR_AUDIO] = AwesomeVersion(data["audio"])
            self._data[ATTR_OBSERVER] = AwesomeVersion(data["observer"])
            self._data[ATTR_MULTICAST] = AwesomeVersion(data["multicast"])

            # Update images for that versions
            self._data[ATTR_IMAGE][ATTR_OPENPEERPOWER] = data["image"]["core"]
            self._data[ATTR_IMAGE][ATTR_SUPERVISOR] = data["image"][
                "supervisor"]
            self._data[ATTR_IMAGE][ATTR_AUDIO] = data["image"]["audio"]
            self._data[ATTR_IMAGE][ATTR_CLI] = data["image"]["cli"]
            self._data[ATTR_IMAGE][ATTR_DNS] = data["image"]["dns"]
            self._data[ATTR_IMAGE][ATTR_OBSERVER] = data["image"]["observer"]
            self._data[ATTR_IMAGE][ATTR_MULTICAST] = data["image"]["multicast"]

        except KeyError as err:
            _LOGGER.warning("Can't process version data: %s", err)
            raise UpdaterError() from err

        else:
            self.save_data()
Exemplo n.º 2
0
 def version(self) -> Optional[AwesomeVersion]:
     """Return version of Docker image."""
     if LABEL_VERSION not in self.meta_labels:
         return None
     return AwesomeVersion(self.meta_labels[LABEL_VERSION])
Exemplo n.º 3
0
 def release_url(self) -> str | None:
     """URL to the full release notes of the latest version available."""
     version = AwesomeVersion(self.latest_version)
     if version.dev or version.strategy == AwesomeVersionStrategy.UNKNOWN:
         return "https://github.com/home-assistant/supervisor/commits/main"
     return f"https://github.com/home-assistant/supervisor/releases/tag/{version}"
Exemplo n.º 4
0
 def release_url(self) -> str | None:
     """URL to the full release notes of the latest version available."""
     version = AwesomeVersion(self.latest_version)
     if version.dev:
         return "https://github.com/home-assistant/core/commits/dev"
     return f"https://{'rc' if version.beta else 'www'}.home-assistant.io/latest-release-notes/"
Exemplo n.º 5
0
 def new(data: Dict[str, Any]):
     """Create a object from docker info."""
     return DockerInfo(AwesomeVersion(data["ServerVersion"]),
                       data["Driver"], data["LoggingDriver"])
Exemplo n.º 6
0
def version_left_higher_then_right(left: str, right: str) -> bool:
    """Return a bool if source is newer than target, will also be true if identical."""
    return AwesomeVersion(left) >= AwesomeVersion(right)
Exemplo n.º 7
0
def test_simple():
    handlers = CompareHandlers(AwesomeVersion("2"), AwesomeVersion("1"))
    assert handlers.check()

    handlers = CompareHandlers(AwesomeVersion("1"), AwesomeVersion("2"))
    assert not handlers.check()
Exemplo n.º 8
0
)

if TYPE_CHECKING:
    from . import Recorder

_RecorderT = TypeVar("_RecorderT", bound="Recorder")
_P = ParamSpec("_P")

_LOGGER = logging.getLogger(__name__)

RETRIES = 3
QUERY_RETRY_WAIT = 0.1
SQLITE3_POSTFIXES = ["", "-wal", "-shm"]
DEFAULT_YIELD_STATES_ROWS = 32768

MIN_VERSION_MARIA_DB = AwesomeVersion("10.3.0",
                                      AwesomeVersionStrategy.SIMPLEVER)
MIN_VERSION_MYSQL = AwesomeVersion("8.0.0", AwesomeVersionStrategy.SIMPLEVER)
MIN_VERSION_PGSQL = AwesomeVersion("12.0", AwesomeVersionStrategy.SIMPLEVER)
MIN_VERSION_SQLITE = AwesomeVersion("3.31.0", AwesomeVersionStrategy.SIMPLEVER)

# This is the maximum time after the recorder ends the session
# before we no longer consider startup to be a "restart" and we
# should do a check on the sqlite3 database.
MAX_RESTART_TIME = timedelta(minutes=10)

# Retry when one of the following MySQL errors occurred:
RETRYABLE_MYSQL_ERRORS = (1205, 1206, 1213)
# 1205: Lock wait timeout exceeded; try restarting transaction
# 1206: The total number of locks exceeds the lock table size
# 1213: Deadlock found when trying to get lock; try restarting transaction
Exemplo n.º 9
0
 def version(self) -> AwesomeVersion | None:
     """Return the version of the integration."""
     if "version" not in self.manifest:
         return None
     return AwesomeVersion(self.manifest["version"])
Exemplo n.º 10
0
def test_sectons():
    handlers = CompareHandlers(AwesomeVersion("1.2.3.4.5b0"),
                               AwesomeVersion("1.2b0"))
    assert handlers.check()
Exemplo n.º 11
0
    CONF_PORT,
    CONF_SERVER,
    DATA_LIFX_MANAGER,
    DOMAIN as LIFX_DOMAIN,
)

_LOGGER = logging.getLogger(__name__)

SCAN_INTERVAL = timedelta(seconds=10)

DISCOVERY_INTERVAL = 60
MESSAGE_TIMEOUT = 1.0
MESSAGE_RETRIES = 8
UNAVAILABLE_GRACE = 90

FIX_MAC_FW = AwesomeVersion("3.70")
SWITCH_PRODUCT_IDS = [70, 71, 89]

SERVICE_LIFX_SET_STATE = "set_state"

ATTR_INFRARED = "infrared"
ATTR_ZONES = "zones"
ATTR_POWER = "power"

LIFX_SET_STATE_SCHEMA = cv.make_entity_service_schema({
    **LIGHT_TURN_ON_SCHEMA,
    ATTR_INFRARED:
    vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)),
    ATTR_ZONES:
    vol.All(cv.ensure_list, [cv.positive_int]),
    ATTR_POWER:
Exemplo n.º 12
0
    async def _block_till_run(self, version: AwesomeVersion) -> None:
        """Block until Home-Assistant is booting up or startup timeout."""
        # Skip landingpage
        if version == LANDINGPAGE:
            return
        _LOGGER.info("Wait until Home Assistant is ready")

        # Manage timeouts
        timeout: bool = True
        start_time = time.monotonic()
        with suppress(AwesomeVersionException):
            # Version provide early stage UI
            if version >= AwesomeVersion("0.112.0"):
                _LOGGER.debug("Disable startup timeouts - early UI")
                timeout = False

        # Database migration
        migration_progress = False
        migration_file = Path(self.sys_config.path_homeassistant,
                              ".migration_progress")

        # PIP installation
        pip_progress = False
        pip_file = Path(self.sys_config.path_homeassistant, ".pip_progress")

        while True:
            await asyncio.sleep(5)

            # 1: Check if Container is is_running
            if not await self.instance.is_running():
                _LOGGER.error("Home Assistant has crashed!")
                break

            # 2: Check if API response
            if await self.sys_homeassistant.api.check_api_state():
                _LOGGER.info("Detect a running Home Assistant instance")
                self._error_state = False
                return

            # 3: Running DB Migration
            if migration_file.exists():
                if not migration_progress:
                    migration_progress = True
                    _LOGGER.info("Home Assistant record migration in progress")
                continue
            if migration_progress:
                migration_progress = False  # Reset start time
                start_time = time.monotonic()
                _LOGGER.info("Home Assistant record migration done")

            # 4: Running PIP installation
            if pip_file.exists():
                if not pip_progress:
                    pip_progress = True
                    _LOGGER.info("Home Assistant pip installation in progress")
                continue
            if pip_progress:
                pip_progress = False  # Reset start time
                start_time = time.monotonic()
                _LOGGER.info("Home Assistant pip installation done")

            # 5: Timeout
            if (timeout and time.monotonic() - start_time >
                    self.sys_homeassistant.wait_boot):
                _LOGGER.warning(
                    "Don't wait anymore on Home Assistant startup!")
                break

        self._error_state = True
        raise HomeAssistantCrashError()
Exemplo n.º 13
0
    @property
    @final
    def state(self) -> str | None:
        """Return the entity state."""
        if (installed_version := self.installed_version) is None or (
                latest_version := self.latest_version) is None:
            return None

        if latest_version == self.__skipped_version:
            return STATE_OFF
        if latest_version == installed_version:
            return STATE_OFF

        try:
            newer = AwesomeVersion(latest_version) > installed_version
            return STATE_ON if newer else STATE_OFF
        except AwesomeVersionCompareException:
            # Can't compare versions, already tried exact match
            return STATE_ON

    @final
    @property
    def state_attributes(self) -> dict[str, Any] | None:
        """Return state attributes."""
        if (release_summary := self.release_summary) is not None:
            release_summary = release_summary[:255]

        # If entity supports progress, return the in_progress value.
        # Otherwise, we use the internal progress value.
        if self.supported_features & UpdateEntityFeature.PROGRESS:
Exemplo n.º 14
0
def test_strategy_match(version, strategy):
    """Test that the version matches the expected strategy."""
    assert AwesomeVersion(version).strategy == strategy
Exemplo n.º 15
0
    DBUS_ATTR_VERSION,
    DBUS_IFACE_NM,
    DBUS_NAME_NM,
    DBUS_OBJECT_BASE,
    DBUS_OBJECT_NM,
    DeviceType,
)
from ..interface import DBusInterface
from ..utils import dbus_connected
from .dns import NetworkManagerDNS
from .interface import NetworkInterface
from .settings import NetworkManagerSettings

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

MINIMAL_VERSION = AwesomeVersion("1.14.6")


class NetworkManager(DBusInterface):
    """Handle D-Bus interface for Network Manager.

    https://developer.gnome.org/NetworkManager/stable/gdbus-org.freedesktop.NetworkManager.html
    """

    name = DBUS_NAME_NM

    def __init__(self) -> None:
        """Initialize Properties."""
        self._dns: NetworkManagerDNS = NetworkManagerDNS()
        self._settings: NetworkManagerSettings = NetworkManagerSettings()
        self._interfaces: dict[str, NetworkInterface] = {}
Exemplo n.º 16
0
            },
            extra=vol.REMOVE_EXTRA,
        ),
        vol.Optional(ATTR_OTA): vol.Url(),
    },
    extra=vol.REMOVE_EXTRA,
)


# pylint: disable=no-value-for-parameter
SCHEMA_SUPERVISOR_CONFIG = vol.Schema(
    {
        vol.Optional(ATTR_TIMEZONE): validate_timezone,
        vol.Optional(ATTR_LAST_BOOT): str,
        vol.Optional(
            ATTR_VERSION, default=AwesomeVersion(SUPERVISOR_VERSION)
        ): version_tag,
        vol.Optional(ATTR_IMAGE): docker_image,
        vol.Optional(
            ATTR_ADDONS_CUSTOM_LIST,
            default=["https://github.com/hassio-addons/repository"],
        ): repositories,
        vol.Optional(ATTR_WAIT_BOOT, default=5): wait_boot,
        vol.Optional(ATTR_LOGGING, default=LogLevel.INFO): vol.Coerce(LogLevel),
        vol.Optional(ATTR_DEBUG, default=False): vol.Boolean(),
        vol.Optional(ATTR_DEBUG_BLOCK, default=False): vol.Boolean(),
        vol.Optional(ATTR_DIAGNOSTICS, default=None): vol.Maybe(vol.Boolean()),
    },
    extra=vol.REMOVE_EXTRA,
)
Exemplo n.º 17
0
 def version(self) -> AwesomeVersion:
     """Return if connectivity check is enabled."""
     return AwesomeVersion(self.properties[DBUS_ATTR_VERSION])
Exemplo n.º 18
0
def async_discover_single_value(
    value: ZwaveValue, device: DeviceEntry,
    discovered_value_ids: dict[str, set[str]]
) -> Generator[ZwaveDiscoveryInfo, None, None]:
    """Run discovery on a single ZWave value and return matching schema info."""
    discovered_value_ids[device.id].add(value.value_id)
    for schema in DISCOVERY_SCHEMAS:
        # check manufacturer_id
        if (schema.manufacturer_id is not None
                and value.node.manufacturer_id not in schema.manufacturer_id):
            continue

        # check product_id
        if (schema.product_id is not None
                and value.node.product_id not in schema.product_id):
            continue

        # check product_type
        if (schema.product_type is not None
                and value.node.product_type not in schema.product_type):
            continue

        # check firmware_version_range
        if schema.firmware_version_range is not None and (
            (schema.firmware_version_range.min is not None
             and schema.firmware_version_range.min_ver > AwesomeVersion(
                 value.node.firmware_version)) or
            (schema.firmware_version_range.max is not None
             and schema.firmware_version_range.max_ver < AwesomeVersion(
                 value.node.firmware_version))):
            continue

        # check firmware_version
        if (schema.firmware_version is not None and value.node.firmware_version
                not in schema.firmware_version):
            continue

        # check device_class_basic
        if not check_device_class(value.node.device_class.basic,
                                  schema.device_class_basic):
            continue

        # check device_class_generic
        if not check_device_class(value.node.device_class.generic,
                                  schema.device_class_generic):
            continue

        # check device_class_specific
        if not check_device_class(value.node.device_class.specific,
                                  schema.device_class_specific):
            continue

        # check primary value
        if not check_value(value, schema.primary_value):
            continue

        # check additional required values
        if schema.required_values is not None and not all(
                any(
                    check_value(val, val_scheme)
                    for val in value.node.values.values())
                for val_scheme in schema.required_values):
            continue

        # check for values that may not be present
        if schema.absent_values is not None and any(
                any(
                    check_value(val, val_scheme)
                    for val in value.node.values.values())
                for val_scheme in schema.absent_values):
            continue

        # resolve helper data from template
        resolved_data = None
        additional_value_ids_to_watch = set()
        if schema.data_template:
            try:
                resolved_data = schema.data_template.resolve_data(value)
            except UnknownValueData as err:
                LOGGER.error(
                    "Discovery for value %s on device '%s' (%s) will be skipped: %s",
                    value,
                    device.name_by_user or device.name,
                    value.node,
                    err,
                )
                continue
            additional_value_ids_to_watch = schema.data_template.value_ids_to_watch(
                resolved_data)

        # all checks passed, this value belongs to an entity
        yield ZwaveDiscoveryInfo(
            node=value.node,
            primary_value=value,
            assumed_state=schema.assumed_state,
            platform=schema.platform,
            platform_hint=schema.hint,
            platform_data_template=schema.data_template,
            platform_data=resolved_data,
            additional_value_ids_to_watch=additional_value_ids_to_watch,
            entity_registry_enabled_default=schema.
            entity_registry_enabled_default,
        )

        if not schema.allow_multi:
            # return early since this value may not be discovered by other schemas/platforms
            return
Exemplo n.º 19
0
 def version(self) -> AwesomeVersion:
     """Return version of running Home Assistant."""
     return AwesomeVersion(SUPERVISOR_VERSION)