Loading src/webui/service/service/routes.py +167 −166 Original line number Diff line number Diff line Loading @@ -12,36 +12,38 @@ # See the License for the specific language governing permissions and # limitations under the License. import json, logging #, re import json import grpc import grpc, json, logging #, re from collections import defaultdict from flask import current_app, redirect, render_template, Blueprint, flash, session, url_for, request from typing import Optional, Set from wtforms.validators import ValidationError from common.proto.context_pb2 import ( ContextId, IsolationLevelEnum, Service, ServiceId, ServiceTypeEnum, ServiceStatusEnum, Connection, Empty, DeviceDriverEnum, ConfigActionEnum, Device, DeviceList) ContextId, IsolationLevelEnum, Service, ServiceId, ServiceTypeEnum, ServiceStatusEnum, Connection, Empty, DeviceDriverEnum, ConfigActionEnum, Device, DeviceList ) from common.tools.context_queries.Context import get_context from common.tools.context_queries.Topology import get_topology from common.tools.context_queries.EndPoint import get_endpoint_names from wtforms.validators import ValidationError from context.client.ContextClient import ContextClient from service.client.ServiceClient import ServiceClient from device.client.DeviceClient import DeviceClient from common.tools.object_factory.Service import ( json_service_l2nm_planned, json_service_l3nm_planned) from common.tools.object_factory.Constraint import ( json_constraint_sla_availability, json_constraint_sla_capacity, json_constraint_sla_isolation, json_constraint_sla_latency) from common.tools.context_queries.Service import get_service_by_uuid from common.tools.context_queries.Topology import get_topology from common.tools.descriptor.Loader import DescriptorLoader, compose_notifications from common.tools.object_factory.ConfigRule import json_config_rule_set from common.tools.object_factory.Constraint import ( json_constraint_sla_availability, json_constraint_sla_capacity, json_constraint_sla_isolation, json_constraint_sla_latency ) from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.EndPoint import json_endpoint_id from webui.service.service.forms import AddServiceForm_1, AddServiceForm_ACL_L2, AddServiceForm_ACL_IPV4, AddServiceForm_ACL_IPV6, AddServiceForm_L2VPN, AddServiceForm_L3VPN from common.tools.context_queries.Service import get_service_by_uuid from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Service import json_service_l2nm_planned, json_service_l3nm_planned from common.tools.object_factory.Topology import json_topology_id from typing import Optional, Set from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from service.client.ServiceClient import ServiceClient from webui.service.service.forms import ( AddServiceForm_1, AddServiceForm_ACL_L2, AddServiceForm_ACL_IPV4, AddServiceForm_ACL_IPV6, AddServiceForm_L2VPN, AddServiceForm_L3VPN ) LOGGER = logging.getLogger(__name__) service = Blueprint('service', __name__, url_prefix='/service') Loading @@ -50,21 +52,10 @@ context_client = ContextClient() service_client = ServiceClient() device_client = DeviceClient() type = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"] ACL_TYPE = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"] f_action = ["UNDEFINED", "DROP","ACCEPT","REJECT"] l_action = ["UNDEFINED", "LOG_NONE","LOG_SYSLOG"] ''' @service.get('/') #Route for the homepage of the created "service" blueprint @contextmanager def connected_client(c): try: c.connect() yield c finally: c.close() ''' def get_device_drivers_in_use(topology_uuid: str, context_uuid: str) -> Set[str]: active_drivers = set() grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) Loading Loading @@ -118,7 +109,9 @@ def add(): def get_hub_module_name(dev: Device) -> Optional[str]: for cr in dev.device_config.config_rules: if cr.action == ConfigActionEnum.CONFIGACTION_SET and cr.custom and cr.custom.resource_key == "_connect/settings": if cr.action != ConfigActionEnum.CONFIGACTION_SET: continue if not cr.custom: continue if cr.custom.resource_key != "_connect/settings": continue try: cr_dict = json.loads(cr.custom.resource_value) if "hub_module_name" in cr_dict: Loading @@ -142,7 +135,7 @@ def add_xr(): if grpc_topology is None: flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') return redirect(url_for("main.home")) else: topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids} grpc_devices= context_client.ListDevices(Empty()) devices = [ Loading Loading @@ -189,8 +182,11 @@ def add_xr(): context_client.close() if request.method != 'POST': return render_template('service/add-xr.html', devices=devices, hub_if=hub_interfaces_by_device, leaf_if=leaf_interfaces_by_device, ep_used_by=ep_used_by) else: return render_template( 'service/add-xr.html', devices=devices, hub_if=hub_interfaces_by_device, leaf_if=leaf_interfaces_by_device, ep_used_by=ep_used_by ) service_name = request.form["service_name"] if service_name == "": flash(f"Service name must be specified", 'danger') Loading Loading @@ -223,8 +219,16 @@ def add_xr(): }, 'service_type' : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, "service_endpoint_ids": [ {'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': hub_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid)}, {'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': leaf_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid)} { 'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': hub_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid) }, { 'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': leaf_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid) } ], 'service_status' : {'service_status': ServiceStatusEnum.SERVICESTATUS_PLANNED}, 'service_constraints' : [], Loading @@ -239,10 +243,12 @@ def add_xr(): } config_rule = json_config_rule_set('/settings', json_tapi_settings) with connected_client(service_client) as sc: try: service_client.connect() endpoints, sr['service_endpoint_ids'] = sr['service_endpoint_ids'], [] try: create_response = sc.CreateService(Service(**sr)) create_response = service_client.CreateService(Service(**sr)) except Exception as e: flash(f'Failure to update service name {service_name} with endpoints and configuration, exception {str(e)}', 'danger') return redirect(request.url) Loading @@ -251,13 +257,15 @@ def add_xr(): sr['service_config'] = {'config_rules': [config_rule]} try: update_response = sc.UpdateService(Service(**sr)) update_response = service_client.UpdateService(Service(**sr)) flash(f'Created service {update_response.service_uuid.uuid}', 'success') except Exception as e: flash(f'Failure to update service {create_response.service_uuid.uuid} with endpoints and configuration, exception {str(e)}', 'danger') return redirect(request.url) return redirect(url_for('service.home')) finally: service_client.close() @service.get('<path:service_uuid>/detail') def detail(service_uuid: str): Loading Loading @@ -287,7 +295,9 @@ def detail(service_uuid: str): context_client.close() return render_template( 'service/detail.html', service=service_obj, connections=connections, device_names=device_names, endpoints_data=endpoints_data, ste=ServiceTypeEnum, sse=ServiceStatusEnum, ile=IsolationLevelEnum, type = type, f_action = f_action, l_action = l_action) endpoints_data=endpoints_data, ste=ServiceTypeEnum, sse=ServiceStatusEnum, ile=IsolationLevelEnum, type=ACL_TYPE, f_action=f_action, l_action=l_action ) except Exception as e: flash('The system encountered an error and cannot show the details of this service.', 'warning') current_app.logger.exception(e) Loading Loading @@ -318,16 +328,9 @@ def delete(service_uuid: str): def add_configure(): form_1 = AddServiceForm_1() if form_1.validate_on_submit(): if form_1.service_type.data == 'ACL_L2': return redirect(url_for('service.add_configure_ACL_L2')) elif form_1.service_type.data == 'ACL_IPV4': return redirect(url_for('service.add_configure_ACL_IPV4')) elif form_1.service_type.data == 'ACL_IPV6': return redirect(url_for('service.add_configure_ACL_IPV6')) elif form_1.service_type.data == 'L2VPN': return redirect(url_for('service.add_configure_L2VPN')) elif form_1.service_type.data == 'L3VPN': return redirect(url_for('service.add_configure_L3VPN')) service_type = str(form_1.service_type.data) if service_type in {'ACL_L2', 'ACL_IPV4', 'ACL_IPV6', 'L2VPN', 'L3VPN'}: return redirect(url_for('service.add_configure_{:s}'.format(service_type))) return render_template('service/add.html', form_1=form_1, submit_text='Continue to configuraton') @service.route('add/configure/ACL_L2', methods=['GET', 'POST']) Loading Loading @@ -595,15 +598,13 @@ def get_device_vendor(form, devices): return vendor_value_1, vendor_value_2 def validate_params_vendor(form, vendor, device_num): if vendor == "ADVA": if vendor != "ADVA": return if form.NI_name.data != f"ELAN-AC:{getattr(form, f'Device_{device_num}_IF_vlan_id').data}": raise ValidationError('For an ADVA device, the name of the Network Instance should have this name: "ELAN-AC:vlanID"') elif getattr(form, f'Device_{device_num}_NI_VC_ID').data != getattr(form, f'Device_{device_num}_IF_vlan_id').data: raise ValidationError('For an ADVA device, the value of the VlanID and the value of the VC_ID must be the same') else: None return None def set_service_parameters(service_obj, form, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2): service_obj.service_id.service_uuid.uuid = str(form.service_name.data) Loading Loading
src/webui/service/service/routes.py +167 −166 Original line number Diff line number Diff line Loading @@ -12,36 +12,38 @@ # See the License for the specific language governing permissions and # limitations under the License. import json, logging #, re import json import grpc import grpc, json, logging #, re from collections import defaultdict from flask import current_app, redirect, render_template, Blueprint, flash, session, url_for, request from typing import Optional, Set from wtforms.validators import ValidationError from common.proto.context_pb2 import ( ContextId, IsolationLevelEnum, Service, ServiceId, ServiceTypeEnum, ServiceStatusEnum, Connection, Empty, DeviceDriverEnum, ConfigActionEnum, Device, DeviceList) ContextId, IsolationLevelEnum, Service, ServiceId, ServiceTypeEnum, ServiceStatusEnum, Connection, Empty, DeviceDriverEnum, ConfigActionEnum, Device, DeviceList ) from common.tools.context_queries.Context import get_context from common.tools.context_queries.Topology import get_topology from common.tools.context_queries.EndPoint import get_endpoint_names from wtforms.validators import ValidationError from context.client.ContextClient import ContextClient from service.client.ServiceClient import ServiceClient from device.client.DeviceClient import DeviceClient from common.tools.object_factory.Service import ( json_service_l2nm_planned, json_service_l3nm_planned) from common.tools.object_factory.Constraint import ( json_constraint_sla_availability, json_constraint_sla_capacity, json_constraint_sla_isolation, json_constraint_sla_latency) from common.tools.context_queries.Service import get_service_by_uuid from common.tools.context_queries.Topology import get_topology from common.tools.descriptor.Loader import DescriptorLoader, compose_notifications from common.tools.object_factory.ConfigRule import json_config_rule_set from common.tools.object_factory.Constraint import ( json_constraint_sla_availability, json_constraint_sla_capacity, json_constraint_sla_isolation, json_constraint_sla_latency ) from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.EndPoint import json_endpoint_id from webui.service.service.forms import AddServiceForm_1, AddServiceForm_ACL_L2, AddServiceForm_ACL_IPV4, AddServiceForm_ACL_IPV6, AddServiceForm_L2VPN, AddServiceForm_L3VPN from common.tools.context_queries.Service import get_service_by_uuid from common.tools.object_factory.Context import json_context_id from common.tools.object_factory.Service import json_service_l2nm_planned, json_service_l3nm_planned from common.tools.object_factory.Topology import json_topology_id from typing import Optional, Set from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from service.client.ServiceClient import ServiceClient from webui.service.service.forms import ( AddServiceForm_1, AddServiceForm_ACL_L2, AddServiceForm_ACL_IPV4, AddServiceForm_ACL_IPV6, AddServiceForm_L2VPN, AddServiceForm_L3VPN ) LOGGER = logging.getLogger(__name__) service = Blueprint('service', __name__, url_prefix='/service') Loading @@ -50,21 +52,10 @@ context_client = ContextClient() service_client = ServiceClient() device_client = DeviceClient() type = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"] ACL_TYPE = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"] f_action = ["UNDEFINED", "DROP","ACCEPT","REJECT"] l_action = ["UNDEFINED", "LOG_NONE","LOG_SYSLOG"] ''' @service.get('/') #Route for the homepage of the created "service" blueprint @contextmanager def connected_client(c): try: c.connect() yield c finally: c.close() ''' def get_device_drivers_in_use(topology_uuid: str, context_uuid: str) -> Set[str]: active_drivers = set() grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) Loading Loading @@ -118,7 +109,9 @@ def add(): def get_hub_module_name(dev: Device) -> Optional[str]: for cr in dev.device_config.config_rules: if cr.action == ConfigActionEnum.CONFIGACTION_SET and cr.custom and cr.custom.resource_key == "_connect/settings": if cr.action != ConfigActionEnum.CONFIGACTION_SET: continue if not cr.custom: continue if cr.custom.resource_key != "_connect/settings": continue try: cr_dict = json.loads(cr.custom.resource_value) if "hub_module_name" in cr_dict: Loading @@ -142,7 +135,7 @@ def add_xr(): if grpc_topology is None: flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') return redirect(url_for("main.home")) else: topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids} grpc_devices= context_client.ListDevices(Empty()) devices = [ Loading Loading @@ -189,8 +182,11 @@ def add_xr(): context_client.close() if request.method != 'POST': return render_template('service/add-xr.html', devices=devices, hub_if=hub_interfaces_by_device, leaf_if=leaf_interfaces_by_device, ep_used_by=ep_used_by) else: return render_template( 'service/add-xr.html', devices=devices, hub_if=hub_interfaces_by_device, leaf_if=leaf_interfaces_by_device, ep_used_by=ep_used_by ) service_name = request.form["service_name"] if service_name == "": flash(f"Service name must be specified", 'danger') Loading Loading @@ -223,8 +219,16 @@ def add_xr(): }, 'service_type' : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE, "service_endpoint_ids": [ {'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': hub_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid)}, {'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': leaf_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid)} { 'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': hub_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid) }, { 'device_id': {'device_uuid': {'uuid': constellation_uuid}}, 'endpoint_uuid': {'uuid': leaf_if_uuid}, 'topology_id': json_topology_id("admin", context_id=json_context_uuid) } ], 'service_status' : {'service_status': ServiceStatusEnum.SERVICESTATUS_PLANNED}, 'service_constraints' : [], Loading @@ -239,10 +243,12 @@ def add_xr(): } config_rule = json_config_rule_set('/settings', json_tapi_settings) with connected_client(service_client) as sc: try: service_client.connect() endpoints, sr['service_endpoint_ids'] = sr['service_endpoint_ids'], [] try: create_response = sc.CreateService(Service(**sr)) create_response = service_client.CreateService(Service(**sr)) except Exception as e: flash(f'Failure to update service name {service_name} with endpoints and configuration, exception {str(e)}', 'danger') return redirect(request.url) Loading @@ -251,13 +257,15 @@ def add_xr(): sr['service_config'] = {'config_rules': [config_rule]} try: update_response = sc.UpdateService(Service(**sr)) update_response = service_client.UpdateService(Service(**sr)) flash(f'Created service {update_response.service_uuid.uuid}', 'success') except Exception as e: flash(f'Failure to update service {create_response.service_uuid.uuid} with endpoints and configuration, exception {str(e)}', 'danger') return redirect(request.url) return redirect(url_for('service.home')) finally: service_client.close() @service.get('<path:service_uuid>/detail') def detail(service_uuid: str): Loading Loading @@ -287,7 +295,9 @@ def detail(service_uuid: str): context_client.close() return render_template( 'service/detail.html', service=service_obj, connections=connections, device_names=device_names, endpoints_data=endpoints_data, ste=ServiceTypeEnum, sse=ServiceStatusEnum, ile=IsolationLevelEnum, type = type, f_action = f_action, l_action = l_action) endpoints_data=endpoints_data, ste=ServiceTypeEnum, sse=ServiceStatusEnum, ile=IsolationLevelEnum, type=ACL_TYPE, f_action=f_action, l_action=l_action ) except Exception as e: flash('The system encountered an error and cannot show the details of this service.', 'warning') current_app.logger.exception(e) Loading Loading @@ -318,16 +328,9 @@ def delete(service_uuid: str): def add_configure(): form_1 = AddServiceForm_1() if form_1.validate_on_submit(): if form_1.service_type.data == 'ACL_L2': return redirect(url_for('service.add_configure_ACL_L2')) elif form_1.service_type.data == 'ACL_IPV4': return redirect(url_for('service.add_configure_ACL_IPV4')) elif form_1.service_type.data == 'ACL_IPV6': return redirect(url_for('service.add_configure_ACL_IPV6')) elif form_1.service_type.data == 'L2VPN': return redirect(url_for('service.add_configure_L2VPN')) elif form_1.service_type.data == 'L3VPN': return redirect(url_for('service.add_configure_L3VPN')) service_type = str(form_1.service_type.data) if service_type in {'ACL_L2', 'ACL_IPV4', 'ACL_IPV6', 'L2VPN', 'L3VPN'}: return redirect(url_for('service.add_configure_{:s}'.format(service_type))) return render_template('service/add.html', form_1=form_1, submit_text='Continue to configuraton') @service.route('add/configure/ACL_L2', methods=['GET', 'POST']) Loading Loading @@ -595,15 +598,13 @@ def get_device_vendor(form, devices): return vendor_value_1, vendor_value_2 def validate_params_vendor(form, vendor, device_num): if vendor == "ADVA": if vendor != "ADVA": return if form.NI_name.data != f"ELAN-AC:{getattr(form, f'Device_{device_num}_IF_vlan_id').data}": raise ValidationError('For an ADVA device, the name of the Network Instance should have this name: "ELAN-AC:vlanID"') elif getattr(form, f'Device_{device_num}_NI_VC_ID').data != getattr(form, f'Device_{device_num}_IF_vlan_id').data: raise ValidationError('For an ADVA device, the value of the VlanID and the value of the VC_ID must be the same') else: None return None def set_service_parameters(service_obj, form, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2): service_obj.service_id.service_uuid.uuid = str(form.service_name.data) Loading