Commit c8fa042e authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Preliminary unfinished version of device service and Context API based on...

Preliminary unfinished version of device service and Context API based on Redis. To be finished, it is just a backup.
parent 5f749f41
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deviceservice
spec:
  selector:
    matchLabels:
      app: deviceservice
  template:
    metadata:
      labels:
        app: deviceservice
    spec:
      terminationGracePeriodSeconds: 5
      containers:
      - name: server
        image: device:dockerfile
        imagePullPolicy: Never
        ports:
        - containerPort: 7070
        env:
        - name: DB_ENGINE
          value: "redis"
        - name: REDISDB_DATABASE_ID
          value: "0"
        - name: LOG_LEVEL
          value: "DEBUG"
        readinessProbe:
          exec:
            command: ["/bin/grpc_health_probe", "-addr=:7070"]
        livenessProbe:
          exec:
            command: ["/bin/grpc_health_probe", "-addr=:7070"]
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
          limits:
            cpu: 700m
            memory: 1024Mi
---
apiVersion: v1
kind: Service
metadata:
  name: deviceservice
spec:
  type: ClusterIP
  selector:
    app: deviceservice
  ports:
  - name: grpc
    port: 7070
    targetPort: 7070
+37 −0
Original line number Diff line number Diff line
from redis.client import Redis
from .tools._Entity import _Entity
from .tools.EntityAttributes import EntityAttributes
from .tools.EntityCollection import EntityCollection
from .tools.Mutex import Mutex
from .Keys import KEY_CONTEXT, KEY_TOPOLOGIES
from .Topology import Topology

VALIDATORS = {}

class Context(_Entity):
    def __init__(self, context_uuid : str, redis_client: Redis):
        self.__redis_client = redis_client
        self.__mutex = Mutex(self.__redis_client)
        self.__acquired = False
        self.__owner_key = None
        self.__entity_key = KEY_CONTEXT.format(context_uuid=context_uuid)
        super().__init__(context_uuid, self)
        self.context_uuid = self.get_uuid()
        self.attributes = EntityAttributes(self, KEY_CONTEXT, validators=VALIDATORS)
        self.topologies = EntityCollection(self, KEY_TOPOLOGIES)

    def get_parent(self): return(self)
    def get_context(self): return(self)
    def get_redis_client(self): return(self.__redis_client)

    def __enter__(self):
        self.__acquired,self.__owner_key = self.__mutex.acquire(self.__entity_key, owner_key=self.__owner_key)
        if not self.__acquired: raise Exception('Unable to acquire {}'.format(self.__entity_key))
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if not self.__acquired: return
        self.__mutex.release(self.__entity_key, self.__owner_key)

    def topology(self, topology_uuid : str) -> Topology:
        return Topology(topology_uuid, self)
+63 −0
Original line number Diff line number Diff line
from typing import Dict
from .tools._Entity import _Entity
from .tools.EntityAttributes import EntityAttributes
from .tools.EntityCollection import EntityCollection
from .Keys import KEY_DEVICE, KEY_DEVICE_ENDPOINTS
from .Endpoint import Endpoint
from .OperationalStatus import OperationalStatus, to_operationalstatus_enum

VALIDATORS = {
    'device_type': lambda v: v is None or isinstance(v, str),
    'device_config': lambda v: v is None or isinstance(v, str),
    'device_operational_status': lambda v: v is None or isinstance(v, OperationalStatus),
}

TRANSCODERS = {
    'device_operational_status': {
        OperationalStatus: lambda v: v.value,
        str              : lambda v: to_operationalstatus_enum(v),
    }
}

class Device(_Entity):
    def __init__(self, device_uuid : str, parent : 'Topology'): # type: ignore
        super().__init__(device_uuid, parent=parent)
        self.device_uuid = self.get_uuid()
        self.topology_uuid = self._parent.get_uuid()
        self.context_uuid = self._parent._parent.get_uuid()
        self.attributes = EntityAttributes(self, KEY_DEVICE, VALIDATORS, transcoders=TRANSCODERS)
        self.endpoints = EntityCollection(self, KEY_DEVICE_ENDPOINTS)

    def endpoint(self, endpoint_uuid : str) -> Endpoint:
        return Endpoint(endpoint_uuid, self)

    def create(self, type : str, config : str, operational_status : OperationalStatus) -> 'Device':
        self.update(update_attributes={
            'device_type': type,
            'device_config': config,
            'device_operational_status': operational_status,
        })
        self._parent.devices.add(self.get_uuid())
        return self

    def update(self, update_attributes={}, remove_attributes=[]) -> 'Device':
        self.attributes.update(update_attributes=update_attributes, remove_attributes=remove_attributes)
        return self

    def delete(self) -> None:
        remove_attributes = ['device_type', 'device_config', 'device_operational_status']
        self.update(remove_attributes=remove_attributes)
        self._parent.devices.delete(self.get_uuid())

    def dump(self) -> Dict:
        attributes = self.attributes.get()
        dev_op_status = attributes.get('device_operational_status', None)
        if isinstance(dev_op_status, OperationalStatus): dev_op_status = dev_op_status.value
        endpoints = [self.endpoint(endpoint_uuid).dump() for endpoint_uuid in self.endpoints.get()]
        return {
            'device_id': {'device_id': {'uuid': self.device_uuid}},
            'device_type': attributes.get('device_type', None),
            'device_config': {'device_config': attributes.get('device_config', None)},
            'devOperationalStatus': dev_op_status,
            'endpointList': endpoints
        }
+47 −0
Original line number Diff line number Diff line
from typing import Dict
from .tools._Entity import _Entity
from .tools.EntityAttributes import EntityAttributes
from .Keys import KEY_ENDPOINT

VALIDATORS = {
    'port_type': lambda v: v is None or isinstance(v, str),
}

class Endpoint(_Entity):
    def __init__(self, endpoint_uuid : str, parent : 'Device'): # type: ignore
        super().__init__(endpoint_uuid, parent=parent)
        self.endpoint_uuid = self.get_uuid()
        self.device_uuid = self._parent.get_uuid()
        self.topology_uuid = self._parent._parent.get_uuid()
        self.context_uuid = self._parent._parent._parent.get_uuid()
        self.attributes = EntityAttributes(self, KEY_ENDPOINT, VALIDATORS)

    def create(self, type : str) -> 'Endpoint':
        self.update(update_attributes={
            'port_type': type
        })
        self._parent.endpoints.add(self.get_uuid())
        return self

    def update(self, update_attributes={}, remove_attributes=[]) -> 'Endpoint':
        self.attributes.update(update_attributes=update_attributes, remove_attributes=remove_attributes)
        return self

    def delete(self) -> None:
        remove_attributes = ['port_type']
        self.update(remove_attributes=remove_attributes)
        self._parent.endpoints.delete(self.get_uuid())

    def dump_uuid(self) -> Dict:
        return {
            'topoId': {'uuid': self.topology_uuid},
            'dev_id': {'uuid': self.device_uuid},
            'port_id': {'uuid': self.endpoint_uuid},
        }

    def dump(self) -> Dict:
        attributes = self.attributes.get()
        return {
            'port_id': self.dump_uuid(),
            'port_type': attributes.get('port_type', None),
        }
+11 −0
Original line number Diff line number Diff line
KEY_CONTEXT          =                'context[{context_uuid}]'
KEY_TOPOLOGIES       = KEY_CONTEXT  + '/topologies{container_name}'
KEY_TOPOLOGY         = KEY_CONTEXT  + '/topology[{topology_uuid}]' 
KEY_DEVICES          = KEY_TOPOLOGY + '/devices{container_name}'
KEY_LINKS            = KEY_TOPOLOGY + '/links{container_name}'
KEY_DEVICE           = KEY_TOPOLOGY + '/device[{device_uuid}]' 
KEY_DEVICE_ENDPOINTS = KEY_DEVICE   + '/endpoints{container_name}'
KEY_ENDPOINT         = KEY_DEVICE   + '/endpoint[{endpoint_uuid}]' 
KEY_LINK             = KEY_TOPOLOGY + '/link[{link_uuid}]' 
KEY_LINK_ENDPOINTS   = KEY_LINK     + '/endpoints{container_name}'
KEY_LINK_ENDPOINT    = KEY_LINK     + '/endpoint[{link_endpoint_uuid}]'
Loading