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

WebUI component:

- solved bug with JSON descripotor file load.
parent 77cd2507
Loading
Loading
Loading
Loading
+75 −0
Original line number Diff line number Diff line
# 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 copy
from typing import Dict, List, Optional, Tuple

def get_descriptors_add_contexts(contexts : List[Dict]) -> List[Dict]:
    contexts_add = copy.deepcopy(contexts)
    for context in contexts_add:
        context['topology_ids'] = []
        context['service_ids'] = []
    return contexts_add

def get_descriptors_add_topologies(topologies : List[Dict]) -> List[Dict]:
    topologies_add = copy.deepcopy(topologies)
    for topology in topologies_add:
        topology['device_ids'] = []
        topology['link_ids'] = []
    return topologies_add

def get_descriptors_add_services(services : List[Dict]) -> List[Dict]:
    services_add = []
    for service in services:
        service_copy = copy.deepcopy(service)
        service_copy['service_endpoint_ids'] = []
        service_copy['service_constraints'] = []
        service_copy['service_config'] = {'config_rules': []}
        services_add.append(service_copy)
    return services_add

def get_descriptors_add_slices(slices : List[Dict]) -> List[Dict]:
    slices_add = []
    for slice in slices:
        slice_copy = copy.deepcopy(slice)
        slice_copy['slice_endpoint_ids'] = []
        slice_copy['slice_constraints'] = []
        slice_copy['slice_config'] = {'config_rules': []}
        slices_add.append(slice_copy)
    return slices_add

def split_devices_by_rules(devices : List[Dict]) -> Tuple[List[Dict], List[Dict]]:
    devices_add = []
    devices_config = []
    for device in devices:
        connect_rules = []
        config_rules = []
        for config_rule in device.get('device_config', {}).get('config_rules', []):
            custom_resource_key : Optional[str] = config_rule.get('custom', {}).get('resource_key')
            if custom_resource_key is not None and custom_resource_key.startswith('_connect/'):
                connect_rules.append(config_rule)
            else:
                config_rules.append(config_rule)

        if len(connect_rules) > 0:
            device_add = copy.deepcopy(device)
            device_add['device_endpoints'] = []
            device_add['device_config'] = {'config_rules': connect_rules}
            devices_add.append(device_add)

        if len(config_rules) > 0:
            device['device_config'] = {'config_rules': config_rules}
            devices_config.append(device)

    return devices_add, devices_config
+39 −77
Original line number Diff line number Diff line
@@ -12,8 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import copy, json, logging
from typing import Optional
import json, logging
from flask import jsonify, redirect, render_template, Blueprint, flash, session, url_for, request
from common.proto.context_pb2 import Connection, Context, Device, Empty, Link, Service, Slice, Topology, ContextIdList
from common.tools.grpc.Tools import grpc_message_to_json_string
@@ -21,6 +20,9 @@ from context.client.ContextClient import ContextClient
from device.client.DeviceClient import DeviceClient
from service.client.ServiceClient import ServiceClient
from slice.client.SliceClient import SliceClient
from webui.service.main.DescriptorTools import (
    get_descriptors_add_contexts, get_descriptors_add_services, get_descriptors_add_slices,
    get_descriptors_add_topologies, split_devices_by_rules)
from webui.service.main.forms import ContextForm, DescriptorForm

main = Blueprint('main', __name__)
@@ -82,82 +84,40 @@ def process_descriptors(descriptors):
    slices      = descriptors.get('slices'     , [])
    connections = descriptors.get('connections', [])

    # Context and Topology require to create the entity first, and add devices, links, services, slices, etc. in a
    # second stage.
    contexts_add = get_descriptors_add_contexts(contexts)
    topologies_add = get_descriptors_add_topologies(topologies)

    if dummy_mode:
        # Dummy Mode: used to pre-load databases (WebUI debugging purposes) with no smart or automated tasks.
        context_client.connect()

        contexts_add = copy.deepcopy(contexts)
        for context in contexts_add:
            context['topology_ids'] = []
            context['service_ids'] = []

        topologies_add = copy.deepcopy(topologies)
        for topology in topologies_add:
            topology['device_ids'] = []
            topology['link_ids'] = []

        process_descriptor('context',    'add',    context_client.SetContext,    Context,    contexts_add  )
        process_descriptor('topology',   'add',    context_client.SetTopology,   Topology,   topologies_add)
        process_descriptor('device',     'add',    context_client.SetDevice,     Device,     devices       )
        process_descriptor('link',       'add',    context_client.SetLink,       Link,       links         )
        process_descriptor('service',    'add',    context_client.SetService,    Service,    services      )
        process_descriptor('context',    'update', context_client.SetContext,    Context,    contexts      )
        process_descriptor('topology',   'update', context_client.SetTopology,   Topology,   topologies    )
        process_descriptor('slice',      'add',    context_client.SetSlice,      Slice,      slices        )
        process_descriptor('connection', 'add',    context_client.SetConnection, Connection, connections   )
        process_descriptor('context',    'update', context_client.SetContext,    Context,    contexts      )
        process_descriptor('topology',   'update', context_client.SetTopology,   Topology,   topologies    )
        context_client.close()
        return

    else:
        # Normal mode: follows the automated workflows in the different components
        assert len(connections) == 0, 'in normal mode, connections should not be set'

    # in normal mode, connections should not be set
    assert len(connections) == 0

    devices_add = []
    devices_config = []
    for device in devices:
        connect_rules = []
        config_rules = []
        for config_rule in device.get('device_config', {}).get('config_rules', []):
            custom_resource_key : Optional[str] = config_rule.get('custom', {}).get('resource_key')
            if custom_resource_key is not None and custom_resource_key.startswith('_connect/'):
                connect_rules.append(config_rule)
            else:
                config_rules.append(config_rule)

        if len(connect_rules) > 0:
            device_add = copy.deepcopy(device)
            device_add['device_endpoints'] = []
            device_add['device_config'] = {'config_rules': connect_rules}
            devices_add.append(device_add)

        if len(config_rules) > 0:
            device['device_config'] = {'config_rules': config_rules}
            devices_config.append(device)

    services_add = []
    for service in services:
        service_copy = copy.deepcopy(service)
        service_copy['service_endpoint_ids'] = []
        service_copy['service_constraints'] = []
        service_copy['service_config'] = {'config_rules': []}
        services_add.append(service_copy)

    slices_add = []
    for slice in slices:
        slice_copy = copy.deepcopy(slice)
        slice_copy['slice_endpoint_ids'] = []
        slice_copy['slice_constraints'] = []
        slice_copy['slice_config'] = {'config_rules': []}
        slices_add.append(slice_copy)
        # Device, Service and Slice require to first create the entity and the configure it
        devices_add, devices_config = split_devices_by_rules(devices)
        services_add = get_descriptors_add_services(services)
        slices_add = get_descriptors_add_slices(slices)

        context_client.connect()
        device_client.connect()
        service_client.connect()
        slice_client.connect()

    process_descriptor('context',  'add',    context_client.SetContext,      Context,  contexts      )
    process_descriptor('topology', 'add',    context_client.SetTopology,     Topology, topologies    )
        process_descriptor('context',    'add',    context_client.SetContext,      Context,    contexts_add  )
        process_descriptor('topology',   'add',    context_client.SetTopology,     Topology,   topologies_add)
        process_descriptor('device',     'add',    device_client .AddDevice,       Device,     devices_add   )
        process_descriptor('device',     'config', device_client .ConfigureDevice, Device,     devices_config)
        process_descriptor('link',       'add',    context_client.SetLink,         Link,       links         )
@@ -165,6 +125,8 @@ def process_descriptors(descriptors):
        process_descriptor('service',    'update', service_client.UpdateService,   Service,    services      )
        process_descriptor('slice',      'add',    slice_client  .CreateSlice,     Slice,      slices_add    )
        process_descriptor('slice',      'update', slice_client  .UpdateSlice,     Slice,      slices        )
        process_descriptor('context',    'update', context_client.SetContext,      Context,    contexts      )
        process_descriptor('topology',   'update', context_client.SetTopology,     Topology,   topologies    )

        slice_client.close()
        service_client.close()