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

Context compoent:

- progress on migration to CockroachDB (partial)
parent 177e96a8
No related branches found
No related tags found
2 merge requests!54Release 2.0.0,!34Context Scalability extensions using CockroachDB + Removal of Stateful database inside Device + other
Showing with 709 additions and 804 deletions
......@@ -36,14 +36,16 @@ cd $PROJECTDIR/src
#export REDIS_SERVICE_HOST=$(kubectl get node $TFS_K8S_HOSTNAME -o 'jsonpath={.status.addresses[?(@.type=="InternalIP")].address}')
#export REDIS_SERVICE_PORT=$(kubectl --namespace $TFS_K8S_NAMESPACE get service redis-tests -o 'jsonpath={.spec.ports[?(@.port==6379)].nodePort}')
export CRDB_URI="cockroachdb://tfs:tfs123@10.1.7.195:26257/tfs?sslmode=require"
#export CRDB_URI="cockroachdb://tfs:tfs123@127.0.0.1:26257/tfs_test?sslmode=require"
export CRDB_URI="cockroachdb://tfs:tfs123@10.1.7.195:26257/tfs_test?sslmode=require"
export PYTHONPATH=/home/tfs/tfs-ctrl/src
# Run unitary tests and analyze coverage of code at same time
#coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose --maxfail=1 \
# context/tests/test_unitary.py
pytest --log-level=INFO --verbose -o log_cli=true --maxfail=1 \
# --log-level=INFO -o log_cli=true
pytest --verbose --maxfail=1 --durations=0 \
context/tests/test_unitary.py
#kubectl --namespace $TFS_K8S_NAMESPACE delete service redis-tests
This diff is collapsed.
......@@ -20,21 +20,31 @@ LOGGER = logging.getLogger(__name__)
APP_NAME = 'tfs'
class Engine:
def get_engine(self) -> sqlalchemy.engine.Engine:
@staticmethod
def get_engine() -> sqlalchemy.engine.Engine:
crdb_uri = get_setting('CRDB_URI')
try:
engine = sqlalchemy.create_engine(
crdb_uri, connect_args={'application_name': APP_NAME}, echo=False, future=True)
crdb_uri, connect_args={'application_name': APP_NAME}, echo=True, future=True)
except: # pylint: disable=bare-except
LOGGER.exception('Failed to connect to database: {:s}'.format(crdb_uri))
return None
try:
if not sqlalchemy_utils.database_exists(engine.url):
sqlalchemy_utils.create_database(engine.url)
Engine.create_database(engine)
except: # pylint: disable=bare-except
LOGGER.exception('Failed to check/create to database: {:s}'.format(crdb_uri))
LOGGER.exception('Failed to check/create to database: {:s}'.format(engine.url))
return None
return engine
@staticmethod
def create_database(engine : sqlalchemy.engine.Engine) -> None:
if not sqlalchemy_utils.database_exists(engine.url):
sqlalchemy_utils.create_database(engine.url)
@staticmethod
def drop_database(engine : sqlalchemy.engine.Engine) -> None:
if sqlalchemy_utils.database_exists(engine.url):
sqlalchemy_utils.drop_database(engine.url)
......@@ -45,7 +45,7 @@ def main():
metrics_port = get_metrics_port()
start_http_server(metrics_port)
db_engine = Engine().get_engine()
db_engine = Engine.get_engine()
rebuild_database(db_engine, drop_if_exists=False)
# Get message broker instance
......
......@@ -12,15 +12,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import Dict
from typing import Dict, List
from sqlalchemy import Column, Float, String
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from ._Base import _Base
LOGGER = logging.getLogger(__name__)
class ContextModel(_Base):
__tablename__ = 'context'
context_uuid = Column(UUID(as_uuid=False), primary_key=True)
......@@ -28,33 +25,20 @@ class ContextModel(_Base):
created_at = Column(Float)
topology = relationship('TopologyModel', back_populates='context')
#service = relationship('ServiceModel', back_populates='context')
#slice = relationship('SliceModel', back_populates='context')
def dump_id(self) -> Dict:
return {'context_uuid': {'uuid': self.context_uuid}}
#@staticmethod
#def main_pk_name():
# return 'context_uuid'
"""
def dump_service_ids(self) -> List[Dict]:
from .ServiceModel import ServiceModel # pylint: disable=import-outside-toplevel
db_service_pks = self.references(ServiceModel)
return [ServiceModel(self.database, pk).dump_id() for pk,_ in db_service_pks]
def dump_topology_ids(self) -> List[Dict]:
from .TopologyModel import TopologyModel # pylint: disable=import-outside-toplevel
db_topology_pks = self.references(TopologyModel)
return [TopologyModel(self.database, pk).dump_id() for pk,_ in db_topology_pks]
"""
def dump(self,
include_services : bool = True, # pylint: disable=arguments-differ
include_slices : bool = True, # pylint: disable=arguments-differ
include_topologies : bool = True # pylint: disable=arguments-differ
) -> Dict:
result = {'context_id': self.dump_id(), 'name': self.context_name}
# if include_services: result['service_ids'] = self.dump_service_ids()
# if include_slices: result['slice_ids'] = self.dump_slice_ids()
# if include_topologies: result['topology_ids'] = self.dump_topology_ids()
return result
return
def dump(self) -> Dict:
return {
'context_id' : self.dump_id(),
'name' : self.context_name,
'topology_ids': [obj.dump_id() for obj in self.topology],
#'service_ids' : [obj.dump_id() for obj in self.service ],
#'slice_ids' : [obj.dump_id() for obj in self.slice ],
}
......@@ -11,17 +11,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import enum
import functools, logging
import uuid
from typing import Dict, List
from common.orm.Database import Database
from common.orm.backend.Tools import key_to_str
#import uuid
from typing import Dict #, List
#from common.orm.Database import Database
#from common.orm.backend.Tools import key_to_str
from common.proto.context_pb2 import DeviceDriverEnum, DeviceOperationalStatusEnum
from sqlalchemy import Column, ForeignKey, String, Enum
from sqlalchemy import Column, Float, ForeignKey, String, Enum
from sqlalchemy.dialects.postgresql import UUID, ARRAY
from context.service.database._Base import Base
from sqlalchemy.orm import relationship
from context.service.database._Base import _Base
from .Tools import grpc_to_enum
LOGGER = logging.getLogger(__name__)
......@@ -46,80 +47,152 @@ class ORM_DeviceOperationalStatusEnum(enum.Enum):
grpc_to_enum__device_operational_status = functools.partial(
grpc_to_enum, DeviceOperationalStatusEnum, ORM_DeviceOperationalStatusEnum)
class DeviceModel(Base):
__tablename__ = 'Device'
class DeviceModel(_Base):
__tablename__ = 'device'
device_uuid = Column(UUID(as_uuid=False), primary_key=True)
device_type = Column(String)
device_config_uuid = Column(UUID(as_uuid=False), ForeignKey("Config.config_uuid", ondelete='CASCADE'))
device_operational_status = Column(Enum(ORM_DeviceOperationalStatusEnum, create_constraint=False,
native_enum=False))
device_name = Column(String(), nullable=False)
device_type = Column(String(), nullable=False)
#device_config_uuid = Column(UUID(as_uuid=False), ForeignKey('config.config_uuid', ondelete='CASCADE'))
device_operational_status = Column(Enum(ORM_DeviceOperationalStatusEnum))
device_drivers = Column(ARRAY(Enum(ORM_DeviceDriverEnum), dimensions=1))
created_at = Column(Float)
# Relationships
device_config = relationship("ConfigModel", passive_deletes=True, lazy="joined")
driver = relationship("DriverModel", passive_deletes=True, back_populates="device")
endpoints = relationship("EndPointModel", passive_deletes=True, back_populates="device")
topology_device = relationship('TopologyDeviceModel', back_populates='devices')
#device_config = relationship("ConfigModel", passive_deletes=True, lazy="joined")
endpoints = relationship('EndPointModel', passive_deletes=True, back_populates='device')
def dump_id(self) -> Dict:
return {'device_uuid': {'uuid': self.device_uuid}}
def dump_config(self) -> Dict:
return self.device_config.dump()
def dump_drivers(self) -> List[int]:
response = []
for a in self.driver:
response.append(a.dump())
return response
def dump_endpoints(self) -> List[Dict]:
response = []
for a in self.endpoints:
response.append(a.dump())
return response
def dump( # pylint: disable=arguments-differ
self, include_config_rules=True, include_drivers=True, include_endpoints=True
) -> Dict:
result = {
'device_id': self.dump_id(),
'device_type': self.device_type,
def dump(self) -> Dict:
return {
'device_id' : self.dump_id(),
'name' : self.device_name,
'device_type' : self.device_type,
'device_operational_status': self.device_operational_status.value,
'device_drivers' : [d.value for d in self.device_drivers],
#'device_config' : {'config_rules': self.device_config.dump()},
#'device_endpoints' : [ep.dump() for ep in self.endpoints],
}
if include_config_rules: result.setdefault('device_config', {})['config_rules'] = self.dump_config()
if include_drivers: result['device_drivers'] = self.dump_drivers()
if include_endpoints: result['device_endpoints'] = self.dump_endpoints()
return result
@staticmethod
def main_pk_name():
return 'device_uuid'
class DriverModel(Base): # pylint: disable=abstract-method
__tablename__ = 'Driver'
# driver_uuid = Column(UUID(as_uuid=False), primary_key=True)
device_uuid = Column(UUID(as_uuid=False), ForeignKey("Device.device_uuid", ondelete='CASCADE'), primary_key=True)
driver = Column(Enum(ORM_DeviceDriverEnum, create_constraint=False, native_enum=False))
# Relationships
device = relationship("DeviceModel", back_populates="driver")
def dump(self) -> Dict:
return self.driver.value
@staticmethod
def main_pk_name():
return 'device_uuid'
#def set_drivers(database : Database, db_device : DeviceModel, grpc_device_drivers):
# db_device_pk = db_device.device_uuid
# for driver in grpc_device_drivers:
# orm_driver = grpc_to_enum__device_driver(driver)
# str_device_driver_key = key_to_str([db_device_pk, orm_driver.name])
# db_device_driver = DriverModel(database, str_device_driver_key)
# db_device_driver.device_fk = db_device
# db_device_driver.driver = orm_driver
# db_device_driver.save()
# def set_kpi_sample_types(self, db_endpoint: EndPointModel, grpc_endpoint_kpi_sample_types):
# db_endpoint_pk = db_endpoint.endpoint_uuid
# for kpi_sample_type in grpc_endpoint_kpi_sample_types:
# orm_kpi_sample_type = grpc_to_enum__kpi_sample_type(kpi_sample_type)
# # str_endpoint_kpi_sample_type_key = key_to_str([db_endpoint_pk, orm_kpi_sample_type.name])
# data = {'endpoint_uuid': db_endpoint_pk,
# 'kpi_sample_type': orm_kpi_sample_type.name,
# 'kpi_uuid': str(uuid.uuid4())}
# db_endpoint_kpi_sample_type = KpiSampleTypeModel(**data)
# self.database.create(db_endpoint_kpi_sample_type)
# def set_drivers(self, db_device: DeviceModel, grpc_device_drivers):
# db_device_pk = db_device.device_uuid
# for driver in grpc_device_drivers:
# orm_driver = grpc_to_enum__device_driver(driver)
# str_device_driver_key = key_to_str([db_device_pk, orm_driver.name])
# driver_config = {
# # "driver_uuid": str(uuid.uuid4()),
# "device_uuid": db_device_pk,
# "driver": orm_driver.name
# }
# db_device_driver = DriverModel(**driver_config)
# db_device_driver.device_fk = db_device
# db_device_driver.driver = orm_driver
#
# self.database.create_or_update(db_device_driver)
def set_drivers(database : Database, db_device : DeviceModel, grpc_device_drivers):
db_device_pk = db_device.device_uuid
for driver in grpc_device_drivers:
orm_driver = grpc_to_enum__device_driver(driver)
str_device_driver_key = key_to_str([db_device_pk, orm_driver.name])
db_device_driver = DriverModel(database, str_device_driver_key)
db_device_driver.device_fk = db_device
db_device_driver.driver = orm_driver
db_device_driver.save()
# def update_config(
# self, session, db_parent_pk: str, config_name: str,
# raw_config_rules: List[Tuple[ORM_ConfigActionEnum, str, str]]
# ) -> List[Tuple[Union[ConfigModel, ConfigRuleModel], bool]]:
#
# created = False
#
# db_config = session.query(ConfigModel).filter_by(**{ConfigModel.main_pk_name(): db_parent_pk}).one_or_none()
# if not db_config:
# db_config = ConfigModel()
# setattr(db_config, ConfigModel.main_pk_name(), db_parent_pk)
# session.add(db_config)
# session.commit()
# created = True
#
# LOGGER.info('UPDATED-CONFIG: {}'.format(db_config.dump()))
#
# db_objects: List[Tuple[Union[ConfigModel, ConfigRuleModel], bool]] = [(db_config, created)]
#
# for position, (action, resource_key, resource_value) in enumerate(raw_config_rules):
# if action == ORM_ConfigActionEnum.SET:
# result : Tuple[ConfigRuleModel, bool] = self.set_config_rule(
# db_config, position, resource_key, resource_value)
# db_config_rule, updated = result
# db_objects.append((db_config_rule, updated))
# elif action == ORM_ConfigActionEnum.DELETE:
# self.delete_config_rule(db_config, resource_key)
# else:
# msg = 'Unsupported action({:s}) for resource_key({:s})/resource_value({:s})'
# raise AttributeError(
# msg.format(str(ConfigActionEnum.Name(action)), str(resource_key), str(resource_value)))
#
# return db_objects
#
# def set_config_rule(self, db_config: ConfigModel, position: int, resource_key: str, resource_value: str,
# ): # -> Tuple[ConfigRuleModel, bool]:
#
# from src.context.service.database.Tools import fast_hasher
# str_rule_key_hash = fast_hasher(resource_key)
# str_config_rule_key = key_to_str([db_config.config_uuid, str_rule_key_hash], separator=':')
# pk = str(uuid.uuid5(uuid.UUID('9566448d-e950-425e-b2ae-7ead656c7e47'), str_config_rule_key))
# data = {'config_rule_uuid': pk, 'config_uuid': db_config.config_uuid, 'position': position,
# 'action': ORM_ConfigActionEnum.SET, 'key': resource_key, 'value': resource_value}
# to_add = ConfigRuleModel(**data)
#
# result, updated = self.database.create_or_update(to_add)
# return result, updated
#
# def delete_config_rule(
# self, db_config: ConfigModel, resource_key: str
# ) -> None:
#
# from src.context.service.database.Tools import fast_hasher
# str_rule_key_hash = fast_hasher(resource_key)
# str_config_rule_key = key_to_str([db_config.pk, str_rule_key_hash], separator=':')
#
# db_config_rule = self.database.get_object(ConfigRuleModel, str_config_rule_key, raise_if_not_found=False)
#
# if db_config_rule is None:
# return
# db_config_rule.delete()
#
# def delete_all_config_rules(self, db_config: ConfigModel) -> None:
#
# db_config_rule_pks = db_config.references(ConfigRuleModel)
# for pk, _ in db_config_rule_pks: ConfigRuleModel(self.database, pk).delete()
#
# """
# for position, (action, resource_key, resource_value) in enumerate(raw_config_rules):
# if action == ORM_ConfigActionEnum.SET:
# result: Tuple[ConfigRuleModel, bool] = set_config_rule(
# database, db_config, position, resource_key, resource_value)
# db_config_rule, updated = result
# db_objects.append((db_config_rule, updated))
# elif action == ORM_ConfigActionEnum.DELETE:
# delete_config_rule(database, db_config, resource_key)
# else:
# msg = 'Unsupported action({:s}) for resource_key({:s})/resource_value({:s})'
# raise AttributeError(
# msg.format(str(ConfigActionEnum.Name(action)), str(resource_key), str(resource_value)))
#
# return db_objects
# """
......@@ -12,93 +12,63 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import Dict, List, Optional, Tuple
from common.orm.Database import Database
from common.orm.HighLevel import get_object
from common.orm.backend.Tools import key_to_str
from common.proto.context_pb2 import EndPointId
from .KpiSampleType import ORM_KpiSampleTypeEnum, grpc_to_enum__kpi_sample_type
from sqlalchemy import Column, ForeignKey, String, Enum, ForeignKeyConstraint
from sqlalchemy.dialects.postgresql import UUID
from context.service.database._Base import Base
import enum, functools
from typing import Dict
from sqlalchemy import Column, String, Enum, ForeignKeyConstraint
from sqlalchemy.dialects.postgresql import ARRAY, UUID
from sqlalchemy.orm import relationship
LOGGER = logging.getLogger(__name__)
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from ._Base import _Base
from .Tools import grpc_to_enum
class EndPointModel(Base):
__tablename__ = 'EndPoint'
topology_uuid = Column(UUID(as_uuid=False), ForeignKey("Topology.topology_uuid"), primary_key=True)
device_uuid = Column(UUID(as_uuid=False), ForeignKey("Device.device_uuid", ondelete='CASCADE'), primary_key=True)
endpoint_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True)
endpoint_type = Column(String)
class ORM_KpiSampleTypeEnum(enum.Enum):
UNKNOWN = KpiSampleType.KPISAMPLETYPE_UNKNOWN
PACKETS_TRANSMITTED = KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED
PACKETS_RECEIVED = KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED
BYTES_TRANSMITTED = KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED
BYTES_RECEIVED = KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED
grpc_to_enum__kpi_sample_type = functools.partial(
grpc_to_enum, KpiSampleType, ORM_KpiSampleTypeEnum)
# Relationships
kpi_sample_types = relationship("KpiSampleTypeModel", passive_deletes=True, back_populates="EndPoint")
device = relationship("DeviceModel", back_populates="endpoints")
class EndPointModel(_Base):
__tablename__ = 'endpoint'
context_uuid = Column(UUID(as_uuid=False), primary_key=True)
topology_uuid = Column(UUID(as_uuid=False), primary_key=True)
device_uuid = Column(UUID(as_uuid=False), primary_key=True)
endpoint_uuid = Column(UUID(as_uuid=False), primary_key=True)
endpoint_type = Column(String)
kpi_sample_types = Column(ARRAY(Enum(ORM_KpiSampleTypeEnum), dimensions=1))
@staticmethod
def main_pk_name():
return 'endpoint_uuid'
__table_args__ = (
ForeignKeyConstraint(
['context_uuid', 'topology_uuid'],
['topology.context_uuid', 'topology.topology_uuid'],
ondelete='CASCADE'),
ForeignKeyConstraint(
['device_uuid'],
['device.device_uuid'],
ondelete='CASCADE'),
)
def delete(self) -> None:
for db_kpi_sample_type_pk,_ in self.references(KpiSampleTypeModel):
KpiSampleTypeModel(self.database, db_kpi_sample_type_pk).delete()
super().delete()
topology = relationship('TopologyModel', back_populates='endpoints')
device = relationship('DeviceModel', back_populates='endpoints')
def dump_id(self) -> Dict:
result = {
'topology_id': self.topology.dump_id(),
'device_id': self.device.dump_id(),
'endpoint_uuid': {'uuid': self.endpoint_uuid},
}
return result
def dump_kpi_sample_types(self) -> List[int]:
# db_kpi_sample_type_pks = self.references(KpiSampleTypeModel)
# return [KpiSampleTypeModel(self.database, pk).dump() for pk,_ in db_kpi_sample_type_pks]
response = []
for a in self.kpi_sample_types:
response.append(a.dump())
return response
def dump( # pylint: disable=arguments-differ
self, include_kpi_sample_types=True
) -> Dict:
result = {
'endpoint_id': self.dump_id(),
'endpoint_type': self.endpoint_type,
}
if include_kpi_sample_types: result['kpi_sample_types'] = self.dump_kpi_sample_types()
return result
class KpiSampleTypeModel(Base): # pylint: disable=abstract-method
__tablename__ = 'KpiSampleType'
kpi_uuid = Column(UUID(as_uuid=False), primary_key=True)
endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid", ondelete='CASCADE'))
kpi_sample_type = Column(Enum(ORM_KpiSampleTypeEnum, create_constraint=False,
native_enum=False))
# __table_args__ = (ForeignKeyConstraint([endpoint_uuid], [EndPointModel.endpoint_uuid]), {})
# Relationships
EndPoint = relationship("EndPointModel", passive_deletes=True, back_populates="kpi_sample_types")
def dump(self) -> Dict:
return self.kpi_sample_type.value
def main_pk_name(self):
return 'kpi_uuid'
return {
'endpoint_id' : self.dump_id(),
'endpoint_type' : self.endpoint_type,
'kpi_sample_types': [kst.value for kst in self.kpi_sample_types],
}
"""
def set_kpi_sample_types(database : Database, db_endpoint : EndPointModel, grpc_endpoint_kpi_sample_types):
db_endpoint_pk = db_endpoint.pk
for kpi_sample_type in grpc_endpoint_kpi_sample_types:
orm_kpi_sample_type = grpc_to_enum__kpi_sample_type(kpi_sample_type)
str_endpoint_kpi_sample_type_key = key_to_str([db_endpoint_pk, orm_kpi_sample_type.name])
db_endpoint_kpi_sample_type = KpiSampleTypeModel(database, str_endpoint_kpi_sample_type_key)
db_endpoint_kpi_sample_type.endpoint_fk = db_endpoint
db_endpoint_kpi_sample_type.kpi_sample_type = orm_kpi_sample_type
db_endpoint_kpi_sample_type.save()
"""
# def get_endpoint(
# database : Database, grpc_endpoint_id : EndPointId,
# validate_topology_exists : bool = True, validate_device_in_topology : bool = True
......
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import functools
import enum
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from .Tools import grpc_to_enum
class ORM_KpiSampleTypeEnum(enum.Enum):
UNKNOWN = KpiSampleType.KPISAMPLETYPE_UNKNOWN
PACKETS_TRANSMITTED = KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED
PACKETS_RECEIVED = KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED
BYTES_TRANSMITTED = KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED
BYTES_RECEIVED = KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED
grpc_to_enum__kpi_sample_type = functools.partial(
grpc_to_enum, KpiSampleType, ORM_KpiSampleTypeEnum)
......@@ -13,39 +13,39 @@
# limitations under the License.
import logging
from sqlalchemy import Column, ForeignKey
from sqlalchemy import Column, ForeignKey, ForeignKeyConstraint
from sqlalchemy.dialects.postgresql import UUID
from context.service.database._Base import Base
from sqlalchemy.orm import relationship
from context.service.database._Base import _Base
LOGGER = logging.getLogger(__name__)
#
# class ConnectionSubServiceModel(Model): # pylint: disable=abstract-method
# class ConnectionSubServiceModel(Model):
# pk = PrimaryKeyField()
# connection_fk = ForeignKeyField(ConnectionModel)
# sub_service_fk = ForeignKeyField(ServiceModel)
#
class LinkEndPointModel(Base): # pylint: disable=abstract-method
__tablename__ = 'LinkEndPoint'
# uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True)
link_uuid = Column(UUID(as_uuid=False), ForeignKey("Link.link_uuid"))
endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid"), primary_key=True)
@staticmethod
def main_pk_name():
return 'endpoint_uuid'
#class LinkEndPointModel(Base):
# __tablename__ = 'LinkEndPoint'
# # uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True)
# link_uuid = Column(UUID(as_uuid=False), ForeignKey("Link.link_uuid"))
# endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid"), primary_key=True)
#
# class ServiceEndPointModel(Model): # pylint: disable=abstract-method
# @staticmethod
# def main_pk_name():
# return 'endpoint_uuid'
#
# class ServiceEndPointModel(Model):
# pk = PrimaryKeyField()
# service_fk = ForeignKeyField(ServiceModel)
# endpoint_fk = ForeignKeyField(EndPointModel)
#
# class SliceEndPointModel(Model): # pylint: disable=abstract-method
# class SliceEndPointModel(Model):
# pk = PrimaryKeyField()
# slice_fk = ForeignKeyField(SliceModel)
# endpoint_fk = ForeignKeyField(EndPointModel)
#
# class SliceServiceModel(Model): # pylint: disable=abstract-method
# class SliceServiceModel(Model):
# pk = PrimaryKeyField()
# slice_fk = ForeignKeyField(SliceModel)
# service_fk = ForeignKeyField(ServiceMo# pylint: disable=abstract-method
......@@ -55,26 +55,32 @@ class LinkEndPointModel(Base): # pylint: disable=abstract-method
# endpoint_uuid = Column(UUID(as_uuid=False), ForeignKey("EndPoint.endpoint_uuid"))
#del)
#
# class SliceSubSliceModel(Model): # pylint: disable=abstract-method
# class SliceSubSliceModel(Model):
# pk = PrimaryKeyField()
# slice_fk = ForeignKeyField(SliceModel)
# sub_slice_fk = ForeignKeyField(SliceModel)
class TopologyDeviceModel(Base): # pylint: disable=abstract-method
__tablename__ = 'TopologyDevice'
# uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True)
topology_uuid = Column(UUID(as_uuid=False), ForeignKey("Topology.topology_uuid"))
device_uuid = Column(UUID(as_uuid=False), ForeignKey("Device.device_uuid"), primary_key=True)
class TopologyDeviceModel(_Base):
__tablename__ = 'topology_device'
context_uuid = Column(UUID(as_uuid=False), primary_key=True)
topology_uuid = Column(UUID(as_uuid=False), primary_key=True)
device_uuid = Column(UUID(as_uuid=False), primary_key=True)
@staticmethod
def main_pk_name():
return 'device_uuid'
#
class TopologyLinkModel(Base): # pylint: disable=abstract-method
__tablename__ = 'TopologyLink'
topology_uuid = Column(UUID(as_uuid=False), ForeignKey("Topology.topology_uuid"))
link_uuid = Column(UUID(as_uuid=False), ForeignKey("Link.link_uuid"), primary_key=True)
topologies = relationship('TopologyModel', back_populates='topology_device')
devices = relationship('DeviceModel', back_populates='topology_device')
__table_args__ = (
ForeignKeyConstraint(
['context_uuid', 'topology_uuid'],
['topology.context_uuid', 'topology.topology_uuid'],
ondelete='CASCADE'),
ForeignKeyConstraint(
['device_uuid'],
['device.device_uuid'],
ondelete='CASCADE'),
)
@staticmethod
def main_pk_name():
return 'link_uuid'
\ No newline at end of file
#class TopologyLinkModel(Base):
# __tablename__ = 'TopologyLink'
# topology_uuid = Column(UUID(as_uuid=False), ForeignKey("Topology.topology_uuid"))
# link_uuid = Column(UUID(as_uuid=False), ForeignKey("Link.link_uuid"), primary_key=True)
......@@ -12,40 +12,35 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging #, operator
from typing import Dict #, List
from sqlalchemy import Column, ForeignKey
from typing import Dict
from sqlalchemy import Column, Float, ForeignKey, String
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from ._Base import _Base
LOGGER = logging.getLogger(__name__)
class TopologyModel(_Base):
__tablename__ = 'Topology'
__tablename__ = 'topology'
context_uuid = Column(UUID(as_uuid=False), ForeignKey('context.context_uuid'), primary_key=True)
topology_uuid = Column(UUID(as_uuid=False), primary_key=True, unique=True)
topology_name = Column(String(), nullable=False)
created_at = Column(Float)
# Relationships
context = relationship('ContextModel', back_populates='topology')
context = relationship('ContextModel', back_populates='topology')
topology_device = relationship('TopologyDeviceModel', back_populates='topologies')
#topology_link = relationship('TopologyLinkModel', back_populates='topology')
endpoints = relationship('EndPointModel', back_populates='topology')
def dump_id(self) -> Dict:
context_id = self.context.dump_id()
return {
'context_id': context_id,
'context_id': self.context.dump_id(),
'topology_uuid': {'uuid': self.topology_uuid},
}
#@staticmethod
#def main_pk_name() -> str:
# return 'topology_uuid'
def dump(self) -> Dict:
# pylint: disable=arguments-differ
result = {'topology_id': self.dump_id()}
# params: , devices=None, links=None
#if devices:
# result['device_ids'] = [device.dump_id() for device in devices]
#if links:
# result['link_ids'] = [link.dump_id() for link in links]
return result
return {
'topology_id': self.dump_id(),
'name' : self.topology_name,
'device_ids' : [{'device_uuid': {'uuid': td.device_uuid}} for td in self.topology_device],
#'link_ids' : [{'link_uuid' : {'uuid': td.link_uuid }} for td in self.topology_link ],
}
......@@ -11,7 +11,3 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from ._Base import _Base, rebuild_database
from .ContextModel import ContextModel
from .TopologyModel import TopologyModel
This diff is collapsed.
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