Added frontend components for cloud instances.

This commit is contained in:
Fabio Manganiello 2023-03-26 12:27:17 +02:00
parent bc2730c841
commit 295758bb20
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774
4 changed files with 60 additions and 12 deletions

View file

@ -29,6 +29,9 @@
"light.hue": { "light.hue": {
"class": "fas fa-lightbulb" "class": "fas fa-lightbulb"
}, },
"linode": {
"class": "fas fa-cloud"
},
"media.jellyfin": { "media.jellyfin": {
"imgUrl": "/icons/jellyfin.svg" "imgUrl": "/icons/jellyfin.svg"
}, },

View file

@ -0,0 +1 @@
Device.vue

View file

@ -39,6 +39,14 @@
} }
}, },
"cloud_instance": {
"name": "Cloud Entity",
"name_plural": "Cloud Entities",
"icon": {
"class": "fas fa-cloud"
}
},
"bluetooth_service": { "bluetooth_service": {
"name": "Service", "name": "Service",
"name_plural": "Services", "name_plural": "Services",

View file

@ -1,4 +1,4 @@
from typing import Collection, Dict, List, Optional from typing import Collection, List, Optional
from typing_extensions import override from typing_extensions import override
@ -6,17 +6,19 @@ from linode_api4 import LinodeClient, Instance, objects
from platypush.context import get_bus from platypush.context import get_bus
from platypush.entities.cloud import CloudInstance from platypush.entities.cloud import CloudInstance
from platypush.entities.managers.cloud import CloudInstanceEntityManager, InstanceId
from platypush.entities.managers.switches import EnumSwitchEntityManager
from platypush.entities.switches import EnumSwitch
from platypush.message.event.linode import LinodeInstanceStatusChanged from platypush.message.event.linode import LinodeInstanceStatusChanged
from platypush.schemas.linode import ( from platypush.schemas.linode import (
LinodeInstance, LinodeInstance,
LinodeInstanceSchema, LinodeInstanceSchema,
LinodeInstanceStatus, LinodeInstanceStatus,
) )
from platypush.entities.managers.cloud import CloudInstanceEntityManager, InstanceId
from platypush.plugins import RunnablePlugin, action from platypush.plugins import RunnablePlugin, action
class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager): class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager, EnumSwitchEntityManager):
""" """
This plugin can interact with a Linode account and manage node and volumes. This plugin can interact with a Linode account and manage node and volumes.
@ -36,7 +38,7 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager):
""" """
def __init__(self, token: str, poll_interval: float = 10.0, **kwargs): def __init__(self, token: str, poll_interval: float = 60.0, **kwargs):
""" """
:param token: Linode API token. :param token: Linode API token.
:param poll_interval: How often to poll the Linode API :param poll_interval: How often to poll the Linode API
@ -44,8 +46,6 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager):
""" """
super().__init__(poll_interval=poll_interval, **kwargs) super().__init__(poll_interval=poll_interval, **kwargs)
self._token = token self._token = token
self._instances: Dict[int, CloudInstance] = {}
""" ``{instance_id: CloudInstance}`` mapping. """
def _get_client(self, token: Optional[str] = None) -> LinodeClient: def _get_client(self, token: Optional[str] = None) -> LinodeClient:
""" """
@ -66,9 +66,9 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager):
""" """
client = self._get_client(token) client = self._get_client(token)
if isinstance(instance, str): if isinstance(instance, str):
filters = Instance.label == instance filters = [Instance.label == instance]
elif isinstance(instance, int): elif isinstance(instance, int):
filters = Instance.id == instance filters = [Instance.id == instance]
else: else:
raise AssertionError(f'Invalid instance type: {type(instance)}') raise AssertionError(f'Invalid instance type: {type(instance)}')
@ -90,13 +90,20 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager):
@override @override
def main(self): def main(self):
instances = []
while not self.should_stop(): while not self.should_stop():
status = self._instances.copy() status = {instance.id: instance for instance in instances}
new_status = self.status(publish_entities=False).output
new_status = {
instance.id: instance
for instance in self.status(publish_entities=False).output
}
changed_instances = ( changed_instances = (
[ [
instance instance
for instance in new_status for instance in new_status.values()
if not ( if not (
status.get(instance.id) status.get(instance.id)
and status[instance.id].status == instance.status and status[instance.id].status == instance.status
@ -123,7 +130,7 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager):
self.publish_entities(changed_instances) self.publish_entities(changed_instances)
self._instances = new_status instances = new_status.values()
self.wait_stop(self.poll_interval) self.wait_stop(self.poll_interval)
@override @override
@ -135,6 +142,14 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager):
[ [
CloudInstance( CloudInstance(
reachable=instance.status == LinodeInstanceStatus.RUNNING, reachable=instance.status == LinodeInstanceStatus.RUNNING,
children=[
EnumSwitch(
id=f'{instance.id}:__action__',
name='Actions',
values=['boot', 'reboot', 'shutdown'],
is_write_only=True,
)
],
**schema.dump(instance), **schema.dump(instance),
) )
for instance in entities for instance in entities
@ -217,5 +232,26 @@ class LinodePlugin(RunnablePlugin, CloudInstanceEntityManager):
node = self._get_instance(instance=instance, token=token) node = self._get_instance(instance=instance, token=token)
assert node.shutdown(), 'Shutdown failed' assert node.shutdown(), 'Shutdown failed'
@override
@action
def set(self, entity: str, value: str, **kwargs):
"""
Entity framework compatible method to run an action on the instance
through an ``EnumSwitch``.
:param entity: Entity ID, as ``<instance_id>`` or
``<instance_id>:__action__``.
:param value: Action to run, one among ``boot``, ``reboot`` and
``shutdown``.
"""
try:
instance_id = int(entity.removesuffix(':__action__'))
except (TypeError, ValueError) as e:
raise AssertionError(f'Invalid entity: {entity}') from e
assert value in {'boot', 'reboot', 'shutdown'}, f'Invalid action: {value}'
method = getattr(self, value)
return method(instance_id, **kwargs)
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et: