Skip to content
Snippets Groups Projects
Commit 72a67e71 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Multiple changes:

Common:
- reorganized Database API to enable extension of Context API with entities (e.g. Service)
- solved minor bugs in Database API

Context and Device services:
- rearranged services and unit tests according to mentioned Context API changes

Service service:
- initial release (under development, this is just a backup of code)
parent 9cc44b30
No related branches found
No related tags found
1 merge request!54Release 2.0.0
Showing
with 527 additions and 69 deletions
apiVersion: apps/v1
kind: Deployment
metadata:
name: serviceservice
spec:
selector:
matchLabels:
app: serviceservice
template:
metadata:
labels:
app: serviceservice
spec:
terminationGracePeriodSeconds: 5
containers:
- name: server
image: registry.gitlab.com/teraflow-h2020/controller/device:latest
imagePullPolicy: Always
ports:
- containerPort: 3030
env:
- name: DB_ENGINE
value: "redis"
- name: REDIS_DATABASE_ID
value: "0"
- name: LOG_LEVEL
value: "DEBUG"
readinessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:3030"]
livenessProbe:
exec:
command: ["/bin/grpc_health_probe", "-addr=:3030"]
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
cpu: 700m
memory: 1024Mi
---
apiVersion: v1
kind: Service
metadata:
name: serviceservice
spec:
type: ClusterIP
selector:
app: serviceservice
ports:
- name: grpc
port: 3030
targetPort: 3030
import logging import logging
from typing import List from typing import List
from ..engines._DatabaseEngine import _DatabaseEngine from common.database.api.Exceptions import WrongDatabaseEngine, MutexException
from .context.Context import Context from common.database.api.context.Context import Context
from .Exceptions import WrongDatabaseEngine, MutexException from common.database.api.context.Keys import KEY_CONTEXTS
from common.database.api.entity.EntityCollection import EntityCollection
from common.database.engines._DatabaseEngine import _DatabaseEngine
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
...@@ -13,6 +15,10 @@ class Database: ...@@ -13,6 +15,10 @@ class Database:
self._database_engine = database_engine self._database_engine = database_engine
self._acquired = False self._acquired = False
self._owner_key = None self._owner_key = None
self._contexts = EntityCollection(self, KEY_CONTEXTS)
@property
def database_engine(self) -> _DatabaseEngine: return self._database_engine
def __enter__(self) -> '_DatabaseEngine': def __enter__(self) -> '_DatabaseEngine':
self._acquired, self._owner_key = self._database_engine.lock() self._acquired, self._owner_key = self._database_engine.lock()
...@@ -36,4 +42,7 @@ class Database: ...@@ -36,4 +42,7 @@ class Database:
entries.sort() entries.sort()
return ['[{:>4s}] {:100s} :: {}'.format(k_type, k_name, k_value) for k_name,k_type,k_value in entries] return ['[{:>4s}] {:100s} :: {}'.format(k_type, k_name, k_value) for k_name,k_type,k_value in entries]
@property
def contexts(self) -> EntityCollection: return self._contexts
def context(self, context_uuid : str) -> Context: return Context(context_uuid, self._database_engine) def context(self, context_uuid : str) -> Context: return Context(context_uuid, self._database_engine)
from typing import Dict from typing import Dict, List
from ...engines._DatabaseEngine import _DatabaseEngine from common.database.api.context.service.Service import Service
from ..entity._RootEntity import _RootEntity from common.database.api.context.topology.Topology import Topology
from ..entity.EntityCollection import EntityCollection from common.database.api.context.Keys import KEY_CONTEXT, KEY_SERVICES, KEY_TOPOLOGIES
from .Keys import KEY_CONTEXT, KEY_TOPOLOGIES from common.database.api.entity._RootEntity import _RootEntity
from .Topology import Topology from common.database.api.entity.EntityCollection import EntityCollection
from common.database.engines._DatabaseEngine import _DatabaseEngine
VALIDATORS = {} # no attributes accepted VALIDATORS = {} # no attributes accepted
TRANSCODERS = {} # no transcoding applied to attributes TRANSCODERS = {} # no transcoding applied to attributes
...@@ -12,6 +13,7 @@ class Context(_RootEntity): ...@@ -12,6 +13,7 @@ class Context(_RootEntity):
def __init__(self, context_uuid : str, database_engine : _DatabaseEngine): def __init__(self, context_uuid : str, database_engine : _DatabaseEngine):
super().__init__(database_engine, context_uuid, KEY_CONTEXT, VALIDATORS, TRANSCODERS) super().__init__(database_engine, context_uuid, KEY_CONTEXT, VALIDATORS, TRANSCODERS)
self._topologies = EntityCollection(self, KEY_TOPOLOGIES) self._topologies = EntityCollection(self, KEY_TOPOLOGIES)
self._services = EntityCollection(self, KEY_SERVICES)
@property @property
def parent(self) -> 'Context': return self def parent(self) -> 'Context': return self
...@@ -25,11 +27,17 @@ class Context(_RootEntity): ...@@ -25,11 +27,17 @@ class Context(_RootEntity):
@property @property
def topologies(self) -> EntityCollection: return self._topologies def topologies(self) -> EntityCollection: return self._topologies
@property
def services(self) -> EntityCollection: return self._services
def topology(self, topology_uuid : str) -> Topology: return Topology(topology_uuid, self) def topology(self, topology_uuid : str) -> Topology: return Topology(topology_uuid, self)
def service(self, service_uuid : str) -> Service: return Service(service_uuid, self)
def create(self) -> 'Context': return self def create(self) -> 'Context': return self
def delete(self): def delete(self):
for service_uuid in self.services.get(): self.service(service_uuid).delete()
for topology_uuid in self.topologies.get(): self.topology(topology_uuid).delete() for topology_uuid in self.topologies.get(): self.topology(topology_uuid).delete()
self.attributes.delete() self.attributes.delete()
...@@ -38,5 +46,19 @@ class Context(_RootEntity): ...@@ -38,5 +46,19 @@ class Context(_RootEntity):
'contextUuid': {'uuid': self.context_uuid}, 'contextUuid': {'uuid': self.context_uuid},
} }
def dump_topologies(self) -> List:
return [
self.topology(topology_uuid).dump() for topology_uuid in self.topologies.get()
]
def dump_services(self) -> List:
return [
self.service(service_uuid).dump() for service_uuid in self.services.get()
]
def dump(self) -> Dict: def dump(self) -> Dict:
return {topology_uuid : self.topology(topology_uuid).dump() for topology_uuid in self.topologies.get()} return {
'contextId': self.dump_id(),
'topologies': self.dump_topologies(),
'services': self.dump_services(),
}
KEY_CONTEXT = 'context[{context_uuid}]' # Database keys
KEY_TOPOLOGIES = KEY_CONTEXT + '/topologies{container_name}' KEY_CONTEXTS = 'contexts{container_name}'
KEY_TOPOLOGY = KEY_CONTEXT + '/topology[{topology_uuid}]'
KEY_DEVICES = KEY_TOPOLOGY + '/devices{container_name}' # Context keys
KEY_LINKS = KEY_TOPOLOGY + '/links{container_name}' KEY_CONTEXT = 'context[{context_uuid}]'
KEY_DEVICE = KEY_TOPOLOGY + '/device[{device_uuid}]' KEY_TOPOLOGIES = KEY_CONTEXT + '/topologies{container_name}'
KEY_DEVICE_ENDPOINTS = KEY_DEVICE + '/endpoints{container_name}' KEY_SERVICES = KEY_CONTEXT + '/services{container_name}'
KEY_ENDPOINT = KEY_DEVICE + '/endpoint[{endpoint_uuid}]'
KEY_LINK = KEY_TOPOLOGY + '/link[{link_uuid}]' # Context.Topology keys
KEY_LINK_ENDPOINTS = KEY_LINK + '/endpoints{container_name}' KEY_TOPOLOGY = KEY_CONTEXT + '/topology[{topology_uuid}]'
KEY_LINK_ENDPOINT = KEY_LINK + '/endpoint[{link_endpoint_uuid}]' KEY_DEVICES = KEY_TOPOLOGY + '/devices{container_name}'
KEY_LINKS = KEY_TOPOLOGY + '/links{container_name}'
# Context.Topology.Device keys
KEY_DEVICE = KEY_TOPOLOGY + '/device[{device_uuid}]'
KEY_DEVICE_ENDPOINTS = KEY_DEVICE + '/endpoints{container_name}'
# Context.Topology.Device.Endpoint keys
KEY_DEVICE_ENDPOINT = KEY_DEVICE + '/endpoint[{endpoint_uuid}]'
# Context.Topology.Link keys
KEY_LINK = KEY_TOPOLOGY + '/link[{link_uuid}]'
KEY_LINK_ENDPOINTS = KEY_LINK + '/endpoints{container_name}'
# Context.Topology.Link.Endpoint Keys
KEY_LINK_ENDPOINT = KEY_LINK + '/endpoint[{endpoint_uuid}]'
# Service keys
KEY_SERVICE = KEY_CONTEXT + '/service[{service_uuid}]'
KEY_SERVICE_ENDPOINTS = KEY_SERVICE + '/endpoints{container_name}'
KEY_SERVICE_CONSTRAINTS = KEY_SERVICE + '/constraints{container_name}'
# Context.Service.Endpoint Keys
KEY_SERVICE_ENDPOINT = KEY_SERVICE + '/endpoint[{endpoint_uuid}]'
# Context.Service.Constraint Keys
KEY_SERVICE_CONSTRAINT = KEY_SERVICE + '/constraint[{constraint_uuid}]'
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Internal structure # # Internal structure #
###################### ######################
Note (1): for containers like topologies, devices, links, etc. two containers are defined: Note (1): for containers like topologies, devices, links, services, etc. two containers are defined:
list List is a sorted list containing the uuid's of th elements belonging to the parent element. It is used to list List is a sorted list containing the uuid's of th elements belonging to the parent element. It is used to
define the order of the elements and enable to iterate them deterministically. define the order of the elements and enable to iterate them deterministically.
...@@ -26,6 +26,14 @@ context[<context_uuid>]/topologies_<container> ...@@ -26,6 +26,14 @@ context[<context_uuid>]/topologies_<container>
context[ctx-test]/topologies_set context[ctx-test]/topologies_set
{'base-topo', 'other-topo'} {'base-topo', 'other-topo'}
context[<context_uuid>]/services_<container>
Containers (see Note 1) with the service_uuid's belonging to the context.
Examples:
context[ctx-test]/service_list
['service-1', 'service-2']
context[ctx-test]/service_set
{'service-1', 'service-2'}
Topology structure: Topology structure:
------------------- -------------------
...@@ -58,11 +66,11 @@ context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>] ...@@ -58,11 +66,11 @@ context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>]
Defined attributes are: Defined attributes are:
device_type : string device_type : string
device_config : string device_config : string
device_operational_status: string "0"/"1" device_operational_status: string "0" (KEEP_STATUS) / "-1" (DISABLED) / "1" (ENABLED)
Example: {'device_type': 'ROADM', 'device_config': '<config/>', 'device_operational_status': '1'} Example: {'device_type': 'ROADM', 'device_config': '<config/>', 'device_operational_status': '1'}
context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>]/endpoints_<container> context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>]/endpoints_<container>
Containers (see Note 1) with the endpoints_uuid's belonging to the device. Containers (see Note 1) with the device_endpoints_uuid's belonging to the device.
Examples: Examples:
context[ctx-test]/topology[base-topo]/device[dev1]/endpoints_list context[ctx-test]/topology[base-topo]/device[dev1]/endpoints_list
['to-dev2', 'to-dev3', 'to-dev4'] ['to-dev2', 'to-dev3', 'to-dev4']
...@@ -72,8 +80,8 @@ context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>]/endpoint ...@@ -72,8 +80,8 @@ context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>]/endpoint
Device Endpoint structure: Device Endpoint structure:
-------------------------- --------------------------
context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>]/endpoint[<endpoint_uuid>] context[<context_uuid>]/topology[<topology_uuid>]/device[<device_uuid>]/endpoint[<device_endpoint_uuid>]
Hash set containing the attributes for the endpoint. Hash set containing the attributes for the device_endpoint.
Defined attributes are: Defined attributes are:
port_type: string port_type: string
Example: {'port_type': 'WDM'} Example: {'port_type': 'WDM'}
...@@ -103,5 +111,55 @@ context[<context_uuid>]/topology[<topology_uuid>]/link[<link_uuid>]/endpoint[<li ...@@ -103,5 +111,55 @@ context[<context_uuid>]/topology[<topology_uuid>]/link[<link_uuid>]/endpoint[<li
device_uuid: string device_uuid: string
endpoint_uuid: string endpoint_uuid: string
Example: Example:
context[ctx-test]/topology[base-topo]/link[dev1/to-dev2 ==> dev2/to-dev1]/endpointdev1/to-dev2 context[ctx-test]/topology[base-topo]/link[dev1/to-dev2 ==> dev2/to-dev1]/endpoint[dev1/to-dev2]
{'device_uuid': 'dev1', 'endpoint_uuid': 'to-dev2'} {'device_uuid': 'dev1', 'endpoint_uuid': 'to-dev2'}
Service structure:
------------------
context[<context_uuid>]/service[<service_uuid>]
Hash set containing the attributes for the service.
Defined attributes are:
service_type : string "0" (UNKNOWN) / "1" (L3NM) / "2" (L2NM) / "3" (TAPI_CONNECTIVITY_SERVICE)
service_config: string
service_state : string "0" (PLANNED) / "1" (ACTIVE) / "2" (PENDING_REMOVAL)
Example: ...
context[<context_uuid>]/service[<service_uuid>]/endpoints_<container>
Containers (see Note 1) with the service_endpoint_uuid's belonging to the service.
Examples:
context[ctx-test]/service[service-1]/endpoints_list
['base-topo:dev2/to-dev1', 'base-topo:dev3/to-dev1']
context[ctx-test]/service[service-1]/endpoints_set
{'base-topo:dev2/to-dev1', 'base-topo:dev3/to-dev1'}
context[<context_uuid>]/service[<service_uuid>]/constraints_<container>
Containers (see Note 1) with the constraint_type's belonging to the service.
Examples:
context[ctx-test]/service[service-1]/constraints_list
['latency_ms', 'hops']
context[ctx-test]/service[service-1]/constraints_set
{'latency_ms', 'hops'}
Service Endpoint structure:
---------------------------
context[<context_uuid>]/service[<service_uuid>]/endpoint[<service_endpoint_uuid>]
Hash set containing the attributes for the service_endpoint.
Defined attributes are:
topology_uuid: string
device_uuid: string
endpoint_uuid: string
Example:
context[ctx-test]/service[service-1]/endpoint[dev2/to-dev1]
{'topology_uuid': 'base-topo', 'device_uuid': 'dev2', 'endpoint_uuid': 'to-dev1'}
Service Constraint structure:
-----------------------------
context[<context_uuid>]/service[<service_uuid>]/constraint[<constraint_type>]
Hash set containing the attributes for the constraint.
Defined attributes are:
constraint_value: string
Example:
context[ctx-test]/service[service-1]/constraint['latency_ms']
{'constraint_value': '100'}
from __future__ import annotations
from typing import TYPE_CHECKING, Dict
from common.database.api.context.Keys import KEY_SERVICE_CONSTRAINT
from common.database.api.entity._Entity import _Entity
if TYPE_CHECKING:
from common.database.api.context.Context import Context
from common.database.api.context.service.Service import Service
VALIDATORS = {
'constraint_value': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
}
TRANSCODERS = {} # no transcoding applied to attributes
class Constraint(_Entity):
def __init__(self, constraint_type : str, parent : 'Service'):
super().__init__(parent, constraint_type, KEY_SERVICE_CONSTRAINT, VALIDATORS, TRANSCODERS)
@property
def parent(self) -> 'Service': return self._parent
@property
def context(self) -> 'Context': return self.parent.context
@property
def context_uuid(self) -> str: return self.parent.context_uuid
@property
def service(self) -> 'Service': return self.parent
@property
def service_uuid(self) -> str: return self.parent.service_uuid
@property
def constraint_type(self) -> str: return self._entity_uuid
def create(self, constraint_value : str) -> 'Constraint':
self.update(update_attributes={
'constraint_value': constraint_value,
})
self.parent.endpoints.add(self.constraint_type)
return self
def update(self, update_attributes={}, remove_attributes=[]) -> 'Constraint':
self.attributes.update(update_attributes=update_attributes, remove_attributes=remove_attributes)
return self
def delete(self) -> None:
self.attributes.delete()
self.parent.endpoints.delete(self.constraint_type)
def dump_id(self) -> Dict:
return {
'constraint_type': self.constraint_type,
}
def dump(self) -> Dict:
attributes = self.attributes.get()
return {
'constraint_type': self.constraint_type,
'constraint_value': attributes.get('constraint_value', None),
}
from __future__ import annotations
from typing import TYPE_CHECKING, Dict
from common.database.api.context.topology.device.Endpoint import Endpoint as DeviceEndpoint
from common.database.api.context.Keys import KEY_SERVICE_ENDPOINT
from common.database.api.entity._Entity import _Entity
if TYPE_CHECKING:
from common.database.api.context.Context import Context
from common.database.api.context.service.Service import Service
VALIDATORS = {
'topology_uuid': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
'device_uuid': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
'endpoint_uuid': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
}
TRANSCODERS = {} # no transcoding applied to attributes
class Endpoint(_Entity):
def __init__(self, endpoint_uuid : str, parent : 'Service'):
super().__init__(parent, endpoint_uuid, KEY_SERVICE_ENDPOINT, VALIDATORS, TRANSCODERS)
@property
def parent(self) -> 'Service': return self._parent
@property
def context(self) -> 'Context': return self.parent.context
@property
def context_uuid(self) -> str: return self.parent.context_uuid
@property
def service(self) -> 'Service': return self.parent
@property
def service_uuid(self) -> str: return self.parent.service_uuid
@property
def endpoint_uuid(self) -> str: return self._entity_uuid
def create(self, endpoint : DeviceEndpoint) -> 'Endpoint':
self.update(update_attributes={
'topology_uuid': endpoint.topology_uuid,
'device_uuid': endpoint.device_uuid,
'endpoint_uuid': endpoint.endpoint_uuid,
})
self.parent.endpoints.add(self.endpoint_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:
self.attributes.delete()
self.parent.endpoints.delete(self.endpoint_uuid)
def dump_id(self) -> Dict:
attributes = self.attributes.get()
topology_uuid = attributes.get('topology_uuid', None)
device_uuid = attributes.get('device_uuid', None)
endpoint_uuid = attributes.get('endpoint_uuid', None)
endpoint = self.context.topology(topology_uuid).device(device_uuid).endpoint(endpoint_uuid)
return endpoint.dump_id()
def dump(self) -> Dict:
return self.dump_id()
from __future__ import annotations
from typing import TYPE_CHECKING, Dict
from common.database.api.context.Keys import KEY_SERVICE, KEY_SERVICE_CONSTRAINTS, KEY_SERVICE_ENDPOINTS
from common.database.api.context.service.Constraint import Constraint
from common.database.api.context.service.Endpoint import Endpoint
from common.database.api.context.service.ServiceState import ServiceState, to_servicestate_enum
from common.database.api.context.service.ServiceType import ServiceType, to_servicetype_enum
from common.database.api.entity._Entity import _Entity
from common.database.api.entity.EntityCollection import EntityCollection
if TYPE_CHECKING:
from common.database.api.context.Context import Context
VALIDATORS = {
'service_type': lambda v: v is not None and isinstance(v, ServiceType),
'service_config': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
'service_state': lambda v: v is not None and isinstance(v, ServiceState),
}
TRANSCODERS = {
'service_type': {
ServiceType: lambda v: v.value,
int : lambda v: to_servicetype_enum(v),
str : lambda v: to_servicetype_enum(v),
},
'service_state': {
ServiceState: lambda v: v.value,
int : lambda v: to_servicestate_enum(v),
str : lambda v: to_servicestate_enum(v),
},
}
class Service(_Entity):
def __init__(self, service_uuid : str, parent : 'Context'):
super().__init__(parent, service_uuid, KEY_SERVICE, VALIDATORS, TRANSCODERS)
self._endpoints = EntityCollection(self, KEY_SERVICE_ENDPOINTS)
self._constraints = EntityCollection(self, KEY_SERVICE_CONSTRAINTS)
@property
def parent(self) -> 'Context': return self._parent
@property
def context(self) -> 'Context': return self._parent
@property
def context_uuid(self) -> str: return self.context.context_uuid
@property
def service_uuid(self) -> str: return self._entity_uuid
@property
def endpoints(self) -> EntityCollection: return self._endpoints
@property
def constraints(self) -> EntityCollection: return self._constraints
def endpoint(self, endpoint_uuid : str) -> Endpoint: return Endpoint(endpoint_uuid, self)
def constraint(self, constraint_type : str) -> Constraint: return Constraint(constraint_type, self)
def create(self, service_type : ServiceType, service_config : str, service_state : ServiceState) -> 'Service':
self.update(update_attributes={
'service_type': service_type,
'service_config': service_config,
'service_state': service_state,
})
self.parent.services.add(self.service_uuid)
return self
def update(self, update_attributes={}, remove_attributes=[]) -> 'Service':
self.attributes.update(update_attributes=update_attributes, remove_attributes=remove_attributes)
return self
def delete(self) -> None:
for endpoint_uuid in self.endpoints.get(): self.endpoint(endpoint_uuid).delete()
for constraint_uuid in self.constraints.get(): self.constraint(constraint_uuid).delete()
self.attributes.delete()
self.parent.services.delete(self.service_uuid)
def dump_id(self) -> Dict:
return {
'contextId': self.context.dump_id(),
'cs_id': {'uuid': self.service_uuid},
}
def dump(self) -> Dict:
attributes = self.attributes.get()
service_type = attributes.get('service_type', None)
if isinstance(service_type, ServiceType): service_type = service_type.value
service_state = attributes.get('service_state', None)
if isinstance(service_state, ServiceState): service_state = service_state.value
service_config = attributes.get('device_config', None)
endpoints = [self.endpoint(endpoint_uuid).dump() for endpoint_uuid in self.endpoints.get()]
constraints = [self.constraint(constraint_type).dump() for constraint_type in self.constraints.get()]
return {
'cs_id': self.dump_id(),
'serviceType': service_type,
'endpointList': endpoints,
'constraint': constraints,
'serviceState': {'serviceState': service_state},
'serviceConfig': {'serviceConfig': service_config}
}
from enum import Enum
class ServiceState(Enum):
PLANNED = 0
ACTIVE = 1
PENDING_REMOVAL = 2
ANY_TO_ENUM = {
0: ServiceState.PLANNED,
1: ServiceState.ACTIVE,
2: ServiceState.PENDING_REMOVAL,
'0': ServiceState.PLANNED,
'1': ServiceState.ACTIVE,
'2': ServiceState.PENDING_REMOVAL,
'PLANNED': ServiceState.PLANNED,
'ACTIVE': ServiceState.ACTIVE,
'PENDING_REMOVAL': ServiceState.PENDING_REMOVAL,
}
def servicestate_enum_values():
return {m.value for m in ServiceState.__members__.values()}
def to_servicestate_enum(int_or_str):
if isinstance(int_or_str, str): int_or_str = int_or_str.lower()
return ANY_TO_ENUM.get(int_or_str)
from enum import Enum
class ServiceType(Enum):
UNKNOWN = 0
L3NM = 1
L2NM = 2
TAPI_CONNECTIVITY_SERVICE = 3
ANY_TO_ENUM = {
0: ServiceType.UNKNOWN,
1: ServiceType.L3NM,
2: ServiceType.L2NM,
3: ServiceType.TAPI_CONNECTIVITY_SERVICE,
'0': ServiceType.UNKNOWN,
'1': ServiceType.L3NM,
'2': ServiceType.L2NM,
'3': ServiceType.TAPI_CONNECTIVITY_SERVICE,
'UNKNOWN': ServiceType.UNKNOWN,
'L3NM': ServiceType.L3NM,
'L2NM': ServiceType.L2NM,
'TAPI_CONNECTIVITY_SERVICE': ServiceType.TAPI_CONNECTIVITY_SERVICE,
}
def servicetype_enum_values():
return {m.value for m in ServiceType.__members__.values()}
def to_servicetype_enum(int_or_str):
if isinstance(int_or_str, str): int_or_str = int_or_str.lower()
return ANY_TO_ENUM.get(int_or_str)
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Dict from typing import TYPE_CHECKING, Dict
from ..entity._Entity import _Entity from common.database.api.context.Keys import KEY_TOPOLOGY, KEY_DEVICES, KEY_LINKS
from ..entity.EntityCollection import EntityCollection from common.database.api.context.topology.device.Device import Device
from .Keys import KEY_TOPOLOGY, KEY_DEVICES, KEY_LINKS from common.database.api.context.topology.link.Link import Link
from .Device import Device from common.database.api.entity._Entity import _Entity
from .Link import Link from common.database.api.entity.EntityCollection import EntityCollection
if TYPE_CHECKING: if TYPE_CHECKING:
from .Context import Context from common.database.api.context.Context import Context
VALIDATORS = {} # no attributes accepted VALIDATORS = {} # no attributes accepted
TRANSCODERS = {} # no transcoding applied to attributes TRANSCODERS = {} # no transcoding applied to attributes
...@@ -44,7 +44,7 @@ class Topology(_Entity): ...@@ -44,7 +44,7 @@ class Topology(_Entity):
self.parent.topologies.add(self.topology_uuid) self.parent.topologies.add(self.topology_uuid)
return self return self
def delete(self): def delete(self) -> None:
for device_uuid in self.devices.get(): self.device(device_uuid).delete() for device_uuid in self.devices.get(): self.device(device_uuid).delete()
for link_uuid in self.links.get(): self.link(link_uuid).delete() for link_uuid in self.links.get(): self.link(link_uuid).delete()
self.attributes.delete() self.attributes.delete()
...@@ -58,7 +58,7 @@ class Topology(_Entity): ...@@ -58,7 +58,7 @@ class Topology(_Entity):
def dump(self) -> Dict: def dump(self) -> Dict:
devices = [self.device(device_uuid).dump() for device_uuid in self.devices.get()] devices = [self.device(device_uuid).dump() for device_uuid in self.devices.get()]
links = [self.link (link_uuid ).dump() for link_uuid in self.links.get()] links = [self.link(link_uuid).dump() for link_uuid in self.links.get()]
return { return {
'topoId': self.dump_id(), 'topoId': self.dump_id(),
'device': devices, 'device': devices,
......
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Dict from typing import TYPE_CHECKING, Dict
from ..entity._Entity import _Entity from common.database.api.context.Keys import KEY_DEVICE, KEY_DEVICE_ENDPOINTS
from ..entity.EntityCollection import EntityCollection from common.database.api.context.topology.device.Endpoint import Endpoint
from .Endpoint import Endpoint from common.database.api.context.topology.device.OperationalStatus import OperationalStatus, to_operationalstatus_enum
from .Keys import KEY_DEVICE, KEY_DEVICE_ENDPOINTS from common.database.api.entity._Entity import _Entity
from .OperationalStatus import OperationalStatus, to_operationalstatus_enum from common.database.api.entity.EntityCollection import EntityCollection
if TYPE_CHECKING: if TYPE_CHECKING:
from .Context import Context from common.database.api.context.Context import Context
from .Topology import Topology from common.database.api.context.topology.Topology import Topology
VALIDATORS = { VALIDATORS = {
'device_type': lambda v: v is not None and isinstance(v, str) and (len(v) > 0), 'device_type': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
......
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Dict from typing import TYPE_CHECKING, Dict
from ..entity._Entity import _Entity from common.database.api.entity._Entity import _Entity
from .Keys import KEY_ENDPOINT from common.database.api.context.Keys import KEY_DEVICE_ENDPOINT
if TYPE_CHECKING: if TYPE_CHECKING:
from .Context import Context from common.database.api.context.Context import Context
from .Topology import Topology from common.database.api.context.topology.Topology import Topology
from .Device import Device from common.database.api.context.topology.device.Device import Device
VALIDATORS = { VALIDATORS = {
'port_type': lambda v: v is not None and isinstance(v, str) and (len(v) > 0), 'port_type': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
...@@ -16,7 +16,7 @@ TRANSCODERS = {} # no transcoding applied to attributes ...@@ -16,7 +16,7 @@ TRANSCODERS = {} # no transcoding applied to attributes
class Endpoint(_Entity): class Endpoint(_Entity):
def __init__(self, endpoint_uuid : str, parent : 'Device'): def __init__(self, endpoint_uuid : str, parent : 'Device'):
super().__init__(parent, endpoint_uuid, KEY_ENDPOINT, VALIDATORS, TRANSCODERS) super().__init__(parent, endpoint_uuid, KEY_DEVICE_ENDPOINT, VALIDATORS, TRANSCODERS)
@property @property
def parent(self) -> 'Device': return self._parent def parent(self) -> 'Device': return self._parent
......
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Dict from typing import TYPE_CHECKING, Dict
from ..entity._Entity import _Entity from common.database.api.context.topology.device.Endpoint import Endpoint as DeviceEndpoint
from .Endpoint import Endpoint from common.database.api.context.Keys import KEY_LINK_ENDPOINT
from .Keys import KEY_LINK_ENDPOINT from common.database.api.entity._Entity import _Entity
if TYPE_CHECKING: if TYPE_CHECKING:
from .Context import Context from common.database.api.context.Context import Context
from .Topology import Topology from common.database.api.context.topology.Topology import Topology
from .Link import Link from common.database.api.context.topology.link.Link import Link
VALIDATORS = { VALIDATORS = {
'device_uuid': lambda v: v is not None and isinstance(v, str) and (len(v) > 0), 'device_uuid': lambda v: v is not None and isinstance(v, str) and (len(v) > 0),
...@@ -16,9 +16,9 @@ VALIDATORS = { ...@@ -16,9 +16,9 @@ VALIDATORS = {
TRANSCODERS = {} # no transcoding applied to attributes TRANSCODERS = {} # no transcoding applied to attributes
class LinkEndpoint(_Entity): class Endpoint(_Entity):
def __init__(self, link_endpoint_uuid : str, parent : 'Link'): def __init__(self, endpoint_uuid : str, parent : 'Link'):
super().__init__(parent, link_endpoint_uuid, KEY_LINK_ENDPOINT, VALIDATORS, TRANSCODERS) super().__init__(parent, endpoint_uuid, KEY_LINK_ENDPOINT, VALIDATORS, TRANSCODERS)
@property @property
def parent(self) -> 'Link': return self._parent def parent(self) -> 'Link': return self._parent
...@@ -42,23 +42,23 @@ class LinkEndpoint(_Entity): ...@@ -42,23 +42,23 @@ class LinkEndpoint(_Entity):
def link_uuid(self) -> str: return self.parent.link_uuid def link_uuid(self) -> str: return self.parent.link_uuid
@property @property
def link_endpoint_uuid(self) -> str: return self._entity_uuid def endpoint_uuid(self) -> str: return self._entity_uuid
def create(self, endpoint : Endpoint) -> 'LinkEndpoint': def create(self, endpoint : DeviceEndpoint) -> 'Endpoint':
self.update(update_attributes={ self.update(update_attributes={
'device_uuid': endpoint.device_uuid, 'device_uuid': endpoint.device_uuid,
'endpoint_uuid': endpoint.endpoint_uuid, 'endpoint_uuid': endpoint.endpoint_uuid,
}) })
self.parent.endpoints.add(self.link_endpoint_uuid) self.parent.endpoints.add(self.endpoint_uuid)
return self return self
def update(self, update_attributes={}, remove_attributes=[]) -> 'LinkEndpoint': def update(self, update_attributes={}, remove_attributes=[]) -> 'Endpoint':
self.attributes.update(update_attributes=update_attributes, remove_attributes=remove_attributes) self.attributes.update(update_attributes=update_attributes, remove_attributes=remove_attributes)
return self return self
def delete(self) -> None: def delete(self) -> None:
self.attributes.delete() self.attributes.delete()
self.parent.endpoints.delete(self.link_endpoint_uuid) self.parent.endpoints.delete(self.endpoint_uuid)
def dump_id(self) -> Dict: def dump_id(self) -> Dict:
attributes = self.attributes.get() attributes = self.attributes.get()
......
from __future__ import annotations from __future__ import annotations
from typing import TYPE_CHECKING, Dict from typing import TYPE_CHECKING, Dict
from ..entity._Entity import _Entity from common.database.api.entity._Entity import _Entity
from ..entity.EntityCollection import EntityCollection from common.database.api.entity.EntityCollection import EntityCollection
from .LinkEndpoint import LinkEndpoint from common.database.api.context.topology.link.Endpoint import Endpoint
from .Keys import KEY_LINK, KEY_LINK_ENDPOINTS from common.database.api.context.Keys import KEY_LINK, KEY_LINK_ENDPOINTS
if TYPE_CHECKING: if TYPE_CHECKING:
from .Context import Context from common.database.api.context.Context import Context
from .Topology import Topology from common.database.api.context.topology.Topology import Topology
VALIDATORS = {} # no attributes accepted VALIDATORS = {} # no attributes accepted
TRANSCODERS = {} # no transcoding applied to attributes TRANSCODERS = {} # no transcoding applied to attributes
...@@ -38,7 +38,7 @@ class Link(_Entity): ...@@ -38,7 +38,7 @@ class Link(_Entity):
@property @property
def endpoints(self) -> EntityCollection: return self._endpoints def endpoints(self) -> EntityCollection: return self._endpoints
def endpoint(self, link_endpoint_uuid : str) -> LinkEndpoint: return LinkEndpoint(link_endpoint_uuid, self) def endpoint(self, link_endpoint_uuid : str) -> Endpoint: return Endpoint(link_endpoint_uuid, self)
def create(self) -> 'Link': def create(self) -> 'Link':
self.parent.links.add(self.link_uuid) self.parent.links.add(self.link_uuid)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment