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

Context component:

- Added support to explicitly add devices and links to topologies
- Added configuration settings to deactivate this behavior
parent 1128a2f9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -41,6 +41,10 @@ spec:
          value: "nats"
        - name: LOG_LEVEL
          value: "DEBUG"
        - name: ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY
          value: "TRUE"
        - name: ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY
          value: "TRUE"
        envFrom:
        - secretRef:
            name: crdb-data
+11 −0
Original line number Diff line number Diff line
@@ -12,3 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from common.Settings import get_setting

TRUE_VALUES = {'Y', 'YES', 'T', 'TRUE', 'E', 'ENABLE', 'ENABLED'}
def is_enabled(setting_name : str, default_value : bool) -> bool:
    _is_enabled = get_setting(setting_name, default=None)
    if _is_enabled is None: return default_value
    str_is_enabled = str(_is_enabled).upper()
    return str_is_enabled in TRUE_VALUES

ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY = is_enabled('ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY', True)
ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY   = is_enabled('ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY',   True)
+51 −6
Original line number Diff line number Diff line
@@ -17,17 +17,20 @@ from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.engine import Engine
from sqlalchemy.orm import Session, selectinload, sessionmaker
from sqlalchemy_cockroachdb import run_transaction
from typing import Dict, List, Optional
from typing import Dict, List, Optional, Set
from common.proto.context_pb2 import (
    ContextId, Empty, EventTypeEnum, Topology, TopologyDetails, TopologyId, TopologyIdList, TopologyList)
from common.message_broker.MessageBroker import MessageBroker
from common.method_wrappers.ServiceExceptions import NotFoundException
from common.tools.object_factory.Context import json_context_id
from common.tools.object_factory.Topology import json_topology_id
from context.Config import ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY, ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY
from .models.DeviceModel import DeviceModel
from .models.LinkModel import LinkModel
from .models.TopologyModel import TopologyDeviceModel, TopologyLinkModel, TopologyModel
from .uuids.Context import context_get_uuid
from .uuids.Device import device_get_uuid
from .uuids.Link import link_get_uuid
from .uuids.Topology import topology_get_uuid
from .Events import notify_event_context, notify_event_topology

@@ -98,11 +101,33 @@ def topology_set(db_engine : Engine, messagebroker : MessageBroker, request : To
    # topology. Explicit addition into the topology is done automatically when creating the devices and links, based
    # on the topologies specified in the endpoints associated with the devices and links.

    related_devices : List[Dict] = list()
    if ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY:
        device_uuids : Set[str] = set()
        for device_id in request.device_ids:
            device_uuid = device_get_uuid(device_id)
            if device_uuid not in device_uuids: continue
            related_devices.append({'topology_uuid': topology_uuid, 'device_uuid': device_uuid})
            device_uuids.add(device_uuid)
    else:
        if len(request.device_ids) > 0: # pragma: no cover
        LOGGER.warning('Items in field "device_ids" ignored. This field is used for retrieval purposes only.')
            MSG = 'ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY={:s}; '.format(str(ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY))
            MSG += 'Items in field "device_ids" ignored. This field is used for retrieval purposes only.'
            LOGGER.warning(MSG)

    related_links : List[Dict] = list()
    if ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY:
        link_uuids : Set[str] = set()
        for link_id in request.link_ids:
            link_uuid = link_get_uuid(link_id)
            if link_uuid not in link_uuids: continue
            related_links.append({'topology_uuid': topology_uuid, 'link_uuid': link_uuid})
            link_uuids.add(link_uuid)
    else:
        if len(request.link_ids) > 0:   # pragma: no cover
        LOGGER.warning('Items in field "link_ids" ignored. This field is used for retrieval purposes only.')
            MSG = 'ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY={:s}; '.format(str(ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY))
            MSG += 'Items in field "link_ids" ignored. This field is used for retrieval purposes only.'
            LOGGER.warning(MSG)

    now = datetime.datetime.utcnow()
    topology_data = [{
@@ -124,7 +149,27 @@ def topology_set(db_engine : Engine, messagebroker : MessageBroker, request : To
        )
        stmt = stmt.returning(TopologyModel.created_at, TopologyModel.updated_at)
        created_at,updated_at = session.execute(stmt).fetchone()
        return updated_at > created_at
        updated = updated_at > created_at

        updated_topology_device = False
        if len(related_devices) > 0:
            stmt = insert(TopologyDeviceModel).values(related_devices)
            stmt = stmt.on_conflict_do_nothing(
                index_elements=[TopologyDeviceModel.topology_uuid, TopologyDeviceModel.device_uuid]
            )
            topology_device_inserts = session.execute(stmt)
            updated_topology_device = int(topology_device_inserts.rowcount) > 0

        updated_topology_link = False
        if len(related_links) > 0:
            stmt = insert(TopologyLinkModel).values(related_links)
            stmt = stmt.on_conflict_do_nothing(
                index_elements=[TopologyLinkModel.topology_uuid, TopologyLinkModel.link_uuid]
            )
            topology_link_inserts = session.execute(stmt)
            updated_topology_link = int(topology_link_inserts.rowcount) > 0

        return updated or updated_topology_device or updated_topology_link

    updated = run_transaction(sessionmaker(bind=db_engine), callback)
    context_id = json_context_id(context_uuid)