diff --git a/src/webui/service/service/forms.py b/src/webui/service/service/forms.py index 5105df79e65490f92acdedd1983375d6265fd43d..80476870a100efa6acdd8cc8ba00c37ae1f1b9bb 100644 --- a/src/webui/service/service/forms.py +++ b/src/webui/service/service/forms.py @@ -13,7 +13,6 @@ # limitations under the License. import ipaddress, re -from flask import flash, Flask from flask_wtf import FlaskForm from wtforms import StringField, SelectField, IntegerField, DecimalField from wtforms.validators import InputRequired, Optional, NumberRange, ValidationError, StopValidation @@ -25,75 +24,71 @@ def validate_ipv4_address(form, field): except ipaddress.AddressValueError: raise ValidationError('Invalid IPv4 address format') -def validate_ipv6_address(form, field): #Custom validator for ensuring a valid IPv6 address is submitted - # Check for a valid IPv6 address +# Custom IPv6 address validator +def validate_ipv6_address(form, field): try: ipaddress.IPv6Address(field.data) except ipaddress.AddressValueError: raise ValidationError('Invalid IPv6 address format') - -def validate_mac_address(form, field): #Custom validator for ensuring a valid MAC address is submitted - # Check for a valid MAC [L2] address + +# Custom Mac address validator +def validate_mac_address(form, field): if not re.match(r'^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$', field.data): raise ValidationError('Invalid MAC address format') -def validate_route_distinguisher(form,field): #Custom validator for the input of Route Distinguisher value +# Custom route distinguisher validator +def validate_route_distinguisher(form,field): pattern = r'^([0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]):([0-9]|[1-9][0-9]{1,8}|[1-3][0-9]{9}|4[01][0-9]{8}|42[0-8][0-9]{7}|429[0-3][0-9]{6}|4294[0-8][0-9]{5}|42949[0-5][0-9]{4}|429496[0-6][0-9]{3}|4294967[01][0-9]{2}|42949672[0-8][0-9]|429496729[0-5])$' if not re.match(pattern, field.data): raise ValidationError('Invalid Route Distinguisher') -def validate_uint32(form, field): #Custom validator for ensuring uint32 integers +# Custom integer validator +def validate_uint32(form, field): if not 0 <= field.data <= 2**32-1: raise ValidationError('Value must be a positive integer within the range of uint32') -def validate_NI_as(form, field): #Custom validator that checks if NI_protocol_name is BGP and NI_as is not provided +# Custom BGP AS validator +def validate_NI_as(form, field): if form.NI_protocol.data == 'BGP' and field.data == None: raise StopValidation('AS field is required if the BGP protocol is selected.') - -#def validator_ADVA(form, field): -# if field.name == 'Device_1_NI_VC_ID' and form.Device_1_IF_vendor.data == 'ADVA' and form.Device_1_NI_VC_ID.data != form.Device_1_IF_vlan_id.data: -# raise StopValidation('For the ADVA vendor, it is mandatory that the VC_ID is the same as the Vlan_ID.') -# -# if field.name == 'Device_2_NI_VC_ID' and form.Device_2_IF_vendor.data == 'ADVA' and form.Device_2_NI_VC_ID.data != form.Device_2_IF_vlan_id.data: -# raise StopValidation('For the ADVA vendor, it is mandatory that the VC_ID is the same as the Vlan_ID.') - - -class CustomInputRequired(): #Custom validator that ensures that the required data is provided - def __init__(self, message=None): #Define a constructor that takes an optional message parameter - self.message = message or "This field is required." #If message is provided, use it. Otherwise, set a default message. - - def __call__(self, form, field): #Define a __call__ method that takes in the form and field to be validated - if field.data is None or field.data == '': #Check if the field data is empty or None - raise StopValidation(self.message) #If the data is empty or None, raise a StopValidation exception with the provided message +class CustomInputRequired(): + def __init__(self, message=None): + self.message = message or "This field is required." + def __call__(self, form, field): + if field.data is None or field.data == '': + raise StopValidation(self.message) -class AddServiceForm_1(FlaskForm): #Form-1 - Formulary Fields -> Select the type of new service to add +class AddServiceForm_1(FlaskForm): service_type = SelectField('Type of service', choices=[('', 'Select a type of service to add'), ('ACL_L2', 'ACL_L2'), ('ACL_IPV4', 'ACL_IPV4'), ('ACL_IPV6', 'ACL_IPV6'), ('L2VPN', 'L2VPN'), ('L3VPN', 'L3VPN')], validators=[InputRequired()]) -class AddServiceForm_ACL_L2(FlaskForm): #ACL_L2 - Formulary Fields +class AddServiceForm_ACL_L2(FlaskForm): #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY) - service_name = StringField('Service Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - service_type = SelectField('Service Type', choices=[(2, '2 (L2NM)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> L3NM - service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 + service_name = StringField('Service Name', validators=[CustomInputRequired()]) + service_type = SelectField('Service Type', choices=[(2, '2 (L2NM)')], validators=[CustomInputRequired()]) + service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) + service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL) - service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) + service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) + service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) + service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) + service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), + ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), + ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), + ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) #MANDATORY_PARAMETERS - name = StringField('ACL Name', validators=[CustomInputRequired("The name of the ACL is a mandatory parameter")]) #MANDATORY PARAMETER - type = SelectField('ACL Type', choices=[('ACL_L2', 'ACL_L2')], validators=[CustomInputRequired("The type of the ACL is a mandatory parameter")]) #MANDATORY PARAMETER - sequence_id = IntegerField('ACL Sequence ID', validators=[CustomInputRequired("The name of the Sequence ID of the ACL is a mandatory parameter"), validate_uint32]) #MANDATORY PARAMETER + name = StringField('ACL Name', validators=[CustomInputRequired("The name of the ACL is a mandatory parameter")]) + type = SelectField('ACL Type', choices=[('ACL_L2', 'ACL_L2')], validators=[CustomInputRequired("The type of the ACL is a mandatory parameter")]) + sequence_id = IntegerField('ACL Sequence ID', validators=[CustomInputRequired("The name of the Sequence ID of the ACL is a mandatory parameter"), validate_uint32]) forwarding_action = SelectField('ACL Fowarding Action', choices=[('', 'Select an action (Mandatory)'), ('ACCEPT', 'Accept'), ('DROP','Drop'),('REJECT','Reject')], validators=[CustomInputRequired("The Forwarding Action of the ACL is a mandatory parameter")]) log_action = SelectField('ACL Log Action', choices=[(None, 'Select a log action (Optional)'), ('LOG_SYSLOG', 'Syslog'), ('LOG_NONE','None')], validators=[Optional()]) #PARAMETERS FOR Associating ACL to IF - interface = StringField('Interface Name', validators=[CustomInputRequired("The name of the Interface is a mandatory parameter")]) #MANDATORY PARAMETER + interface = StringField('Interface Name', validators=[CustomInputRequired("The name of the Interface is a mandatory parameter")]) subinterface = StringField('Subinterface Index', validators=[Optional()]) traffic_flow = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[CustomInputRequired("The direction of the traffic flow is a mandatory parameter")]) #MANDATORY PARAMETER @@ -101,192 +96,167 @@ class AddServiceForm_ACL_L2(FlaskForm): #ACL_L2 - Formulary Field source_mac = StringField('Source MAC Address', validators=[Optional(), validate_mac_address]) destination_mac = StringField('Destination MAC Address', validators=[Optional(), validate_mac_address]) -class AddServiceForm_ACL_IPV4(FlaskForm): #ACL_IPV4 - Formulary Fields +class AddServiceForm_ACL_IPV4(FlaskForm): #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY) - service_name = StringField('Service Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - service_type = SelectField('Service Type', choices=[(1, '1 (L3NM)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> L3NM - service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 + service_name = StringField('Service Name', validators=[CustomInputRequired()]) + service_type = SelectField('Service Type', choices=[(1, '1 (L3NM)')], validators=[CustomInputRequired()]) + service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) + service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL) - service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) + service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) + service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) + service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) + service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), + ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), + ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), + ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) #MANDATORY_PARAMETERS - name = StringField('ACL Name', validators=[CustomInputRequired("The name of the ACL is a mandatory parameter")]) #MANDATORY PARAMETER - type = SelectField('ACL Type', choices=[('ACL_IPV4', 'ACL_IPV4')], validators=[CustomInputRequired("The type of the ACL is a mandatory parameter")]) #MANDATORY PARAMETER - sequence_id = IntegerField('ACL Sequence ID', validators=[InputRequired(), NumberRange(min=1, message="Sequence ID must be greater than 0")]) #MANDATORY PARAMETER #MANDATORY PARAMETER + name = StringField('ACL Name', validators=[CustomInputRequired("The name of the ACL is a mandatory parameter")]) + type = SelectField('ACL Type', choices=[('ACL_IPV4', 'ACL_IPV4')], validators=[CustomInputRequired("The type of the ACL is a mandatory parameter")]) + sequence_id = IntegerField('ACL Sequence ID', validators=[InputRequired(), NumberRange(min=1, message="Sequence ID must be greater than 0")]) forwarding_action = SelectField('ACL Fowarding Action', choices=[(None, 'Select an action (Mandatory)'), ('ACCEPT', 'Accept'), ('DROP','Drop'),('REJECT','Reject')], validators=[InputRequired()]) log_action = SelectField('ACL Log Action', choices=[(None, 'Select a log action (Optional)'), ('LOG_SYSLOG', 'Syslog'), ('LOG_NONE','None')], validators=[Optional()]) #PARAMETERS FOR Associating ACL to IF - interface = StringField('Interface Name', validators=[InputRequired()]) #MANDATORY PARAMETER + interface = StringField('Interface Name', validators=[InputRequired()]) subinterface = StringField('Subinterface Index', validators=[Optional()]) - traffic_flow = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[InputRequired()]) #MANDATORY PARAMETER + traffic_flow = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[InputRequired()]) #OPTIONAL_PARAMETERS - Creating ACL Entry [ACL_IPV4] source_address = StringField('Source Address', validators=[Optional(), validate_ipv4_address]) destination_address = StringField('Destination Address', validators=[Optional(), validate_ipv4_address]) - protocol = IntegerField('Protocol', validators=[Optional(),NumberRange(min=1, max=255, message="Protocol number is between 1 and 255 as defined by IANA")]) #Protocols are defined from 1 - 255 as defined in IANA (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml) - hop_limit = IntegerField('Hop Limit', validators=[Optional(),NumberRange(min=1, max=255, message="The Hop limit value has to be between 0 and 255")]) #Max. value of Hop Limit = 255 - dscp = IntegerField('DSCP', validators=[Optional(),NumberRange(min=1, max=255, message="The DSCP value has to be between 0 and 63")]) #Max. value of DSCP = 63 - source_port = IntegerField('Source Port', validators=[Optional(),NumberRange(min=0, max=65535, message="The Port value has to be between 0 and 655535")]) #Range of existing ports in a PC - destination_port = IntegerField('Destination Port', validators=[Optional(),NumberRange(min=0, max=65535, message="The Port value has to be between 0 and 655535")]) #Range of existing ports in a PC - tcp_flags = SelectField('TCP Flags', choices=[(None, 'Select a TCP Flag (Optional)'),('TCP_SYN', 'TCP_SYN'),('TCP_ACK', 'TCP_ACK'),('TCP_RST', 'TCP_RST'),('TCP_FIN', 'TCP_FIN'),('TCP_PSH', 'TCP_PSH'),('TCP_URG', 'TCP_URG') ,('TCP_ECE', 'TCP_ECE'),('TCP_CWR', 'TCP_CWR')], validators=[Optional()]) + protocol = IntegerField('Protocol', validators=[Optional(),NumberRange(min=1, max=255, message="Protocol number is between 1 and 255 as defined by IANA")]) + hop_limit = IntegerField('Hop Limit', validators=[Optional(),NumberRange(min=1, max=255, message="The Hop limit value has to be between 0 and 255")]) + dscp = IntegerField('DSCP', validators=[Optional(),NumberRange(min=1, max=255, message="The DSCP value has to be between 0 and 63")]) + source_port = IntegerField('Source Port', validators=[Optional(),NumberRange(min=0, max=65535, message="The Port value has to be between 0 and 655535")]) + destination_port = IntegerField('Destination Port', validators=[Optional(),NumberRange(min=0, max=65535, message="The Port value has to be between 0 and 655535")]) + tcp_flags = SelectField('TCP Flags', choices=[(None, 'Select a TCP Flag (Optional)'),('TCP_SYN', 'TCP_SYN'),('TCP_ACK', 'TCP_ACK'),('TCP_RST', 'TCP_RST'),('TCP_FIN', 'TCP_FIN'), + ('TCP_PSH', 'TCP_PSH'),('TCP_URG', 'TCP_URG') ,('TCP_ECE', 'TCP_ECE'),('TCP_CWR', 'TCP_CWR')], validators=[Optional()]) -class AddServiceForm_ACL_IPV6(FlaskForm): #ACL_IPV6 - Formulary Fields +class AddServiceForm_ACL_IPV6(FlaskForm): #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY) - service_name = StringField('Service Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - service_type = SelectField('Service Type', choices=[(1, '1 (L3NM)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> L2NM - service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 + service_name = StringField('Service Name', validators=[CustomInputRequired()]) + service_type = SelectField('Service Type', choices=[(1, '1 (L3NM)')], validators=[CustomInputRequired()]) + service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) + service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL) - service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) + service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) + service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) + service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) + service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), + ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), + ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), + ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) #MANDATORY_PARAMETERS - name = StringField('ACL Name', validators=[InputRequired()]) #MANDATORY PARAMETER - type = SelectField('ACL Type', choices=[('ACL_IPV6', 'ACL_IPV6')], validators=[InputRequired()]) #MANDATORY PARAMETER - sequence_id = IntegerField('ACL Sequence ID', validators=[InputRequired(), NumberRange(min=1, message="Sequence ID must be greater than 0")]) #MANDATORY PARAMETER]) #MANDATORY PARAMETER + name = StringField('ACL Name', validators=[InputRequired()]) + type = SelectField('ACL Type', choices=[('ACL_IPV6', 'ACL_IPV6')], validators=[InputRequired()]) + sequence_id = IntegerField('ACL Sequence ID', validators=[InputRequired(), NumberRange(min=1, message="Sequence ID must be greater than 0")]) forwarding_action = SelectField('ACL Fowarding Action', choices=[(None, 'Select an action (Mandatory)'), ('ACCEPT', 'Accept'), ('DROP','Drop'),('REJECT','Reject')], validators=[InputRequired()]) log_action = SelectField('ACL Log Action', choices=[(None, 'Select a log action (Optional)'), ('LOG_SYSLOG', 'Syslog'), ('LOG_NONE','None')], validators=[Optional()]) #PARAMETERS FOR Associating ACL to IF - interface = StringField('Interface Name', validators=[InputRequired()]) #MANDATORY PARAMETER + interface = StringField('Interface Name', validators=[InputRequired()]) subinterface = StringField('Subinterface Index', validators=[Optional()]) - traffic_flow = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[InputRequired()]) #MANDATORY PARAMETER + traffic_flow = SelectField('ACL Traffic Flow Direction', choices=[('', 'Select a direction (Mandatory)'), ('Ingress', 'Ingress'), ('Egress','Egress')], validators=[InputRequired()]) #SPECIFIC PARAMETERS - Creating ACL Entry [ACL_IPV6] source_address = StringField('Source Address', validators=[Optional(), validate_ipv6_address]) destination_address = StringField('Destination Address', validators=[Optional(), validate_ipv6_address]) - protocol = IntegerField('Protocol', validators=[Optional(),NumberRange(min=1, max=255, message="Protocol number is between 1 and 255 as defined by IANA")]) #Protocols are defined from 1 - 255 as defined in IANA (https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml) - hop_limit = IntegerField('Hop Limit', validators=[Optional(),NumberRange(min=1, max=255, message="The Hop limit value has to be between 0 and 255")]) #Max. value of Hop Limit = 255 - dscp = IntegerField('DSCP', validators=[Optional(),NumberRange(min=1, max=255, message="The DSCP value has to be between 0 and 63")]) #Max. value of DSCP = 63 + protocol = IntegerField('Protocol', validators=[Optional(),NumberRange(min=1, max=255, message="Protocol number is between 1 and 255 as defined by IANA")]) + hop_limit = IntegerField('Hop Limit', validators=[Optional(),NumberRange(min=1, max=255, message="The Hop limit value has to be between 0 and 255")]) + dscp = IntegerField('DSCP', validators=[Optional(),NumberRange(min=1, max=255, message="The DSCP value has to be between 0 and 63")]) -class AddServiceForm_L2VPN(FlaskForm): #L2VPN - Formulary Fields +class AddServiceForm_L2VPN(FlaskForm): #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY) - service_name = StringField('Service Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - service_type = SelectField('Service Type', choices=[(2, '2 (L2NM)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> L2NM - service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - #Device_1_IF_vendor = SelectField ('Device_1 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - #Device_2_IF_vendor = SelectField ('Device_2 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - #Device_1_Template = SelectField ('Device_1 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - #Device_2_Template = SelectField ('Device_2 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - - + service_name = StringField('Service Name', validators=[CustomInputRequired()]) + service_type = SelectField('Service Type', choices=[(2, '2 (L2NM)')], validators=[CustomInputRequired()]) + service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) + service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) + #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL) - service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) + service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) + service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) + service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) + service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), + ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), + ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), + ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) - #NI parameters - #Common for the service - NI_name = StringField('NI Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - #NI_type = SelectField('NI Type', choices=[('L2VSI', 'L2VSI')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> L2VSI - NI_mtu = IntegerField('NI MTU', default=1500, validators=[CustomInputRequired(), NumberRange(min=0, message="MTU value can't be negative")]) #MANDATORY PARAMETER - FIXED VALUE -> 1500 - NI_description = StringField('NI Description', validators=[Optional()]) #OPTIONAL PARAMETER + + NI_name = StringField('NI Name', validators=[CustomInputRequired()]) + NI_mtu = IntegerField('NI MTU', default=1500, validators=[CustomInputRequired(), NumberRange(min=0, message="MTU value can't be negative")]) + NI_description = StringField('NI Description', validators=[Optional()]) #Device_1 specific - #Device_1_NI_VC_ID = IntegerField('Device_1 NI VC_ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative"), validator_ADVA]) #MANDATORY PARAMETER - Device_1_NI_remote_system = StringField('Device_1 NI Remote System', validators=[CustomInputRequired(),validate_ipv4_address]) #MANDATORY PARAMETER - Device_1_NI_VC_ID = IntegerField('Device_1 NI VC ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative")]) #MANDATORY PARAMETER - Device_1_NI_connection_point = StringField('Device_1 NI Conection Point', validators=[CustomInputRequired()]) #MANDATORY PARAMETER + Device_1_NI_remote_system = StringField('Device_1 NI Remote System', validators=[CustomInputRequired(),validate_ipv4_address]) + Device_1_NI_VC_ID = IntegerField('Device_1 NI VC ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative")]) + Device_1_NI_connection_point = StringField('Device_1 NI Conection Point', validators=[CustomInputRequired()]) #Device_2 specific - #Device_2_NI_VC_ID = IntegerField('Device_2 NI VC_ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative"), validator_ADVA]) #MANDATORY PARAMETER - Device_2_NI_remote_system = StringField ('Device_2 NI Remote System', validators=[CustomInputRequired(),validate_ipv4_address]) #MANDATORY PARAMETER - Device_2_NI_VC_ID = IntegerField('Device_2 NI VC ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative")]) #MANDATORY PARAMETER - Device_2_NI_connection_point = StringField ('Device_2 NI Conection Point', validators=[CustomInputRequired()]) #MANDATORY PARAMETER + Device_2_NI_remote_system = StringField ('Device_2 NI Remote System', validators=[CustomInputRequired(),validate_ipv4_address]) + Device_2_NI_VC_ID = IntegerField('Device_2 NI VC ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VC can't be negative")]) + Device_2_NI_connection_point = StringField ('Device_2 NI Conection Point', validators=[CustomInputRequired()]) #Interface parameters (DEVICE SPECIFIC) - #Device-1 - #Device_1_IF_name = StringField ('Device_1 Interface Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - #Device_1_IF_type = StringField ('Device_1 Interface Type', default="l2vlan", validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> l2vlan? - Device_1_IF_index = IntegerField('Device_1 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) #MANDATORY PARAMETER - Device_1_IF_vlan_id = IntegerField('Device_1 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) #MANDATORY PARAMETER - Device_1_IF_mtu = IntegerField('Device_1 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) #OPTIONAL PARAMETER - FIXED VALUE -> 3000? - Device_1_IF_description = StringField ('Device_1 SubIF Description', validators=[Optional()]) #OPTIONAL PARAMETER - #Device-2 - #Device_2_IF_name = StringField ('Device_2 Interface Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - #Device_2_IF_type = StringField ('Device_2 Interface Type', default="l2vlan", validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> l2vlan? - Device_2_IF_index = IntegerField('Device_2 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) #MANDATORY PARAMETER - Device_2_IF_vlan_id = IntegerField('Device_2 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) #MANDATORY PARAMETER - Device_2_IF_mtu = IntegerField('Device_2 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) #OPTIONAL PARAMETER - FIXED VALUE -> 3000? - Device_2_IF_description = StringField ('Device_2 SubIF Description', validators=[Optional()]) #OPTIONAL PARAMETER + Device_1_IF_index = IntegerField('Device_1 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) + Device_1_IF_vlan_id = IntegerField('Device_1 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) + Device_1_IF_mtu = IntegerField('Device_1 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) + Device_1_IF_description = StringField ('Device_1 SubIF Description', validators=[Optional()]) + + Device_2_IF_index = IntegerField('Device_2 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) + Device_2_IF_vlan_id = IntegerField('Device_2 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) + Device_2_IF_mtu = IntegerField('Device_2 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) + Device_2_IF_description = StringField ('Device_2 SubIF Description', validators=[Optional()]) -class AddServiceForm_L3VPN(FlaskForm): #L3VPN - Formulary Fields +class AddServiceForm_L3VPN(FlaskForm): #GENERIC SERVICE PARAMETERS (COMMON & MANDATORY) - service_name = StringField('Service Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - service_type = SelectField('Service Type', choices=[(1, '1 (L3NM)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> L3NM - service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - #Device_1_IF_vendor = SelectField ('Device_1 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - #Device_2_IF_vendor = SelectField ('Device_2 Vendor', choices=[('', 'Select a vendor (Mandatory)'),('ADVA', 'ADVA'), ('CISCO','CISCO'), ('Huawei', 'Huawei'),('Juniper', 'Juniper'),('Nokia', 'Nokia')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - #Device_1_Template = SelectField ('Device_1 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-1 - #Device_2_Template = SelectField ('Device_2 Template', choices=[('', 'Select a type of template (Mandatory)'),('Jinja', 'Jinja'), ('Pyangbind','Pyangbind')], validators=[CustomInputRequired()]) #MANDATORY PARAMETER - DEVICE-2 - + service_name = StringField('Service Name', validators=[CustomInputRequired()]) + service_type = SelectField('Service Type', choices=[(1, '1 (L3NM)')], validators=[CustomInputRequired()]) + service_device_1 = SelectField('Device_1', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_device_2 = SelectField('Device_2', choices=[('', 'Select a device (Mandatory)')], validators=[CustomInputRequired()]) + service_endpoint_1 = StringField('Device_1 Endpoint', validators=[CustomInputRequired()]) + service_endpoint_2 = StringField('Device_2 Endpoint', validators=[CustomInputRequired()]) + #GENERIC SERVICE CONSTRAINT PARAMETERS (ALL OPTIONAL) - service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) #OPTIONAL PARAMETER - service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) + service_capacity = DecimalField('Service Capacity', places=2, default=10.00, validators=[Optional(), NumberRange(min=0)]) + service_latency = DecimalField('Service Latency', places=2, default=15.20, validators=[Optional(), NumberRange(min=0)]) + service_availability= DecimalField('Service Availability', places=2, validators=[Optional(), NumberRange(min=0)]) + service_isolation = SelectField('Service Isolation', choices=[('', 'Select (Optional)'), ('NO_ISOLATION', 'NO_ISOLATION'), ('PHYSICAL_ISOLATION', 'PHYSICAL_ISOLATION'), + ('LOGICAL_ISOLATION', 'LOGICAL_ISOLATION'), ('PROCESS_ISOLATION', 'PROCESS_ISOLATION'), ('PHYSICAL_MEMORY_ISOLATION', 'PHYSICAL_MEMORY_ISOLATION'), + ('PHYSICAL_NETWORK_ISOLATION', 'PHYSICAL_NETWORK_ISOLATION'), ('VIRTUAL_RESOURCE_ISOLATION', 'VIRTUAL_RESOURCE_ISOLATION'), + ('NETWORK_FUNCTIONS_ISOLATION', 'NETWORK_FUNCTIONS_ISOLATION'), ('SERVICE_ISOLATION', 'SERVICE_ISOLATION')], validators=[Optional()]) - ## Network Instance (NI) PARAMS - #Create a NI - NI_name = StringField('Name', validators=[InputRequired()]) #MANDATORY PARAMETER - #NI_type = SelectField('Type', choices=[('L3VRF', 'L3VRF')], validators=[InputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> L3VRF - NI_route_distinguisher = StringField('Route Distinguisher', validators=[InputRequired(),validate_route_distinguisher]) #MANDATORY PARAMETER - NI_router_id = StringField('Router ID', validators=[Optional(), validate_ipv4_address]) #OPTIONAL PARAMETER - NI_description = StringField('Description', validators=[Optional()]) #OPTIONAL PARAMETER - #Add a protocol to NI + NI_name = StringField('Name', validators=[InputRequired()]) + NI_route_distinguisher = StringField('Route Distinguisher', validators=[InputRequired(),validate_route_distinguisher]) + NI_router_id = StringField('Router ID', validators=[Optional(), validate_ipv4_address]) + NI_description = StringField('Description', validators=[Optional()]) NI_protocol = SelectField('Protocol', choices=[('', 'Select a type (Mandatory)'),('STATIC', 'STATIC'),('DIRECTLY_CONNECTED', 'DIRECTLY_CONNECTED'),('BGP', 'BGP')], validators=[InputRequired()]) NI_as = IntegerField('AS', default=None, validators=[validate_NI_as, Optional(), validate_uint32]) - #Create Connections Table - #NI_src_protocol = SelectField('Source Protocol', choices=[('', 'Select a type'),('STATIC', 'STATIC'),('DIRECTLY_CONNECTED', 'DIRECTLY_CONNECTED'),('BGP', 'BGP')], validators=[InputRequired()]) - #NI_dst_protocol = SelectField('Destination Protocol', choices=[('', 'Select a type'),('STATIC', 'STATIC'),('DIRECTLY_CONNECTED', 'DIRECTLY_CONNECTED'),('BGP', 'BGP')], validators=[InputRequired()]) NI_address_family = SelectField('Protocol Address Family', choices=[('', 'Select a type (Mandatory)'),('IPV4', 'IPV4'),('IPV6', 'IPV6')], validators=[InputRequired()]) NI_default_import_policy = SelectField('Default Network Instance Import Policy', choices=[('', 'Select a policy (Mandatory)'),('ACCEPT_ROUTE', 'ACCEPT_ROUTE'),('REJECT_ROUTE', 'REJECT_ROUTE')], validators=[Optional()]) - #Associate RP to NI - NI_import_policy = StringField('Name of the Network Instance Import Policy', validators=[Optional()]) #OPTIONAL PARAMETER - NI_export_policy = StringField('Name of the Network Instance Export Policy', validators=[Optional()]) #OPTIONAL PARAMETER + NI_import_policy = StringField('Name of the Network Instance Import Policy', validators=[Optional()]) + NI_export_policy = StringField('Name of the Network Instance Export Policy', validators=[Optional()]) ## Interface (IF) PARAMS - #Device-1 - #Device_1_IF_name = StringField ('Device_1 Interface Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - #Device_1_IF_type = StringField ('Device_1 Interface Type', default="l3ipvlan", validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> l3ipvlan? - Device_1_IF_index = IntegerField('Device_1 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) #MANDATORY PARAMETER - Device_1_IF_vlan_id = IntegerField('Device_1 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) #MANDATORY PARAMETER - Device_1_IF_mtu = IntegerField('Device_1 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) #OPTIONAL PARAMETER - FIXED VALUE -> 3000? - Device_1_IF_address_ip = StringField('Device_1 IP Address', validators=[CustomInputRequired(), validate_ipv4_address]) #MANDATORY PARAMETER - Device_1_IF_address_prefix = IntegerField('Device_1 IP Prefix length', validators=[CustomInputRequired(), validate_uint32]) #MANDATORY PARAMETER - Device_1_IF_description = StringField ('Device_1 SubIF Description', validators=[Optional()]) #OPTIONAL PARAMETER - #Device-2 - #Device_2_IF_name = StringField ('Device_2 Interface Name', validators=[CustomInputRequired()]) #MANDATORY PARAMETER - #Device_2_IF_type = StringField ('Device_1 Interface Type', default="l3ipvlan", validators=[CustomInputRequired()]) #MANDATORY PARAMETER - FIXED VALUE -> l3ipvlan? - Device_2_IF_index = IntegerField('Device_2 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) #MANDATORY PARAMETER - Device_2_IF_vlan_id = IntegerField('Device_2 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) #MANDATORY PARAMETER - Device_2_IF_mtu = IntegerField('Device_2 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) #MANDATORY PARAMETER - FIXED VALUE -> 3000? - Device_2_IF_address_ip = StringField('Device_2 IP Address', validators=[CustomInputRequired(), validate_ipv4_address]) #MANDATORY PARAMETER - Device_2_IF_address_prefix = IntegerField('Device_2 IP Prefix length', validators=[CustomInputRequired(), validate_uint32]) #MANDATORY PARAMETER - Device_2_IF_description = StringField ('Device_2 SubIF Description', validators=[Optional()]) #OPTIONAL PARAMETER + Device_1_IF_index = IntegerField('Device_1 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) + Device_1_IF_vlan_id = IntegerField('Device_1 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) + Device_1_IF_mtu = IntegerField('Device_1 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) + Device_1_IF_address_ip = StringField('Device_1 IP Address', validators=[CustomInputRequired(), validate_ipv4_address]) + Device_1_IF_address_prefix = IntegerField('Device_1 IP Prefix length', validators=[CustomInputRequired(), validate_uint32]) + Device_1_IF_description = StringField ('Device_1 SubIF Description', validators=[Optional()]) - ## Routing Policy (RP) parameters - #RP_policy_name = StringField('Policy Name', validators=[InputRequired()]) #MANDATORY PARAMETER - #RP_statement_name = StringField('Statement Name', validators=[InputRequired()]) #MANDATORY PARAMETER - #RP_policy_result = SelectField('Policy Result', choices=[(None, 'Not Defined'), ('ACCEPT_ROUTE', 'ACCEPT_ROUTE'),('REJECT_ROUTE', 'REJECT_ROUTE')], validators=[Optional()]) - #RP_ext_community_set_name = StringField('Ext Community Set Name', validators=[InputRequired()]) #MANDATORY PARAMETER - #RP_ext_community_member = StringField('Ext Community Member', validators=[InputRequired()]) #MANDATORY PARAMETER - + Device_2_IF_index = IntegerField('Device_2 SubIF Index', validators=[CustomInputRequired(), NumberRange(min=0, message="SubIf index can't be negative")]) + Device_2_IF_vlan_id = IntegerField('Device_2 VLAN ID', validators=[CustomInputRequired(), NumberRange(min=0, message="VlanID can't be negative")]) + Device_2_IF_mtu = IntegerField('Device_2 Interface MTU', validators=[Optional(), NumberRange(min=0, message="MTU value can't be negative")]) + Device_2_IF_address_ip = StringField('Device_2 IP Address', validators=[CustomInputRequired(), validate_ipv4_address]) + Device_2_IF_address_prefix = IntegerField('Device_2 IP Prefix length', validators=[CustomInputRequired(), validate_uint32]) + Device_2_IF_description = StringField ('Device_2 SubIF Description', validators=[Optional()]) + \ No newline at end of file diff --git a/src/webui/service/service/routes.py b/src/webui/service/service/routes.py index 9aff0ad79ab2f92d244502ad2b32ad927860766f..1d3e254905ef3fec9f78b06eb843a112c1c8edff 100644 --- a/src/webui/service/service/routes.py +++ b/src/webui/service/service/routes.py @@ -13,8 +13,7 @@ # limitations under the License. -import base64, json, logging #, re -from contextlib import contextmanager +import json, logging #, re import json import grpc from collections import defaultdict @@ -38,7 +37,6 @@ from common.tools.descriptor.Loader import DescriptorLoader, compose_notificatio from common.tools.object_factory.ConfigRule import json_config_rule_set from common.tools.object_factory.Device import json_device_id from common.tools.object_factory.EndPoint import json_endpoint_id -#from src.common.tools.grpc.Tools import grpc_message_to_json_string 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 @@ -46,10 +44,10 @@ from common.tools.object_factory.Topology import json_topology_id from typing import Optional, Set LOGGER = logging.getLogger(__name__) -service = Blueprint('service', __name__, url_prefix='/service') #Define a flask Blueprint called "service" behind the url "/service" +service = Blueprint('service', __name__, url_prefix='/service') -context_client = ContextClient() #Create an instance of ContextClient class as defined in /src/service/client/ContextClient.py -service_client = ServiceClient() #Create an instance of ServiceClient class as defined in /src/service/client/ServiceClient.py +context_client = ContextClient() +service_client = ServiceClient() device_client = DeviceClient() type = ["ACL_UNDEFINED", "ACL_IPV4","ACL_IPV6","ACL_L2","ACL_MPLS","ACL_MIXED"] @@ -66,7 +64,7 @@ def connected_client(c): finally: c.close() ''' -# Context client must be in connected state when calling this function + 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) @@ -80,15 +78,15 @@ def get_device_drivers_in_use(topology_uuid: str, context_uuid: str) -> Set[str] @service.get('/') def home(): - if 'context_uuid' not in session or 'topology_uuid' not in session: #Check if context_uuid and topology_uuid are defined in the current seession - flash("Please select a context!", "warning") #If they are not defined in the current session [Return to main page - STOP] + if 'context_uuid' not in session or 'topology_uuid' not in session: + flash("Please select a context!", "warning") return redirect(url_for("main.home")) context_uuid = session['context_uuid'] topology_uuid = session['topology_uuid'] - context_client.connect() #Creates a connection, as specified in the connect method of the ContextClient() class + context_client.connect() - context_obj = get_context(context_client, context_uuid, rw_copy=False) #Using the get_context function, defined in /src/common/ + context_obj = get_context(context_client, context_uuid, rw_copy=False) if context_obj is None: flash('Context({:s}) not found'.format(str(context_uuid)), 'danger') services, device_names, endpoints_data = list(), list(), list() @@ -113,13 +111,10 @@ def home(): 'service/home.html', services=services, device_names=device_names, endpoints_data=endpoints_data, ste=ServiceTypeEnum, sse=ServiceStatusEnum, active_drivers=active_drivers) - @service.route('add', methods=['GET', 'POST']) def add(): flash('Add service route called', 'danger') raise NotImplementedError() - #return render_template('service/home.html') - def get_hub_module_name(dev: Device) -> Optional[str]: for cr in dev.device_config.config_rules: @@ -176,8 +171,6 @@ def add_xr(): hub_interfaces_by_device[d.name].sort() leaf_interfaces_by_device[d.name].sort() - # Find out what endpoints are already used so that they can be disabled - # in the create screen context_obj = get_context(context_client, context_uuid, rw_copy=False) if context_obj is None: flash('Context({:s}) not found'.format(str(context_uuid)), 'danger') @@ -300,7 +293,7 @@ def detail(service_uuid: str): current_app.logger.exception(e) return redirect(url_for('service.home')) -@service.get('<path:service_uuid>/delete') #Route for deleting a specific service +@service.get('<path:service_uuid>/delete') def delete(service_uuid: str): if 'context_uuid' not in session or 'topology_uuid' not in session: flash("Please select a context!", "warning") @@ -321,14 +314,10 @@ def delete(service_uuid: str): current_app.logger.exception(e) return redirect(url_for('service.home')) -#Added routes for creating a new Service -@service.route('add/configure', methods=['GET', 'POST']) #Route for adding a new service [Selecting the type of operation to be performed - First Form] +@service.route('add/configure', methods=['GET', 'POST']) def add_configure(): form_1 = AddServiceForm_1() if form_1.validate_on_submit(): - #store the selected service type in session - #session['service_type'] = form_1.service_type.data - #redirect to the same page to display the second form 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': @@ -339,21 +328,19 @@ def add_configure(): return redirect(url_for('service.add_configure_L2VPN')) elif form_1.service_type.data == 'L3VPN': return redirect(url_for('service.add_configure_L3VPN')) - # display the first form return render_template('service/add.html', form_1=form_1, submit_text='Continue to configuraton') -@service.route('add/configure/ACL_L2', methods=['GET', 'POST']) #Route for adding a new ACL_L2 service [Setting the parameters for defining the service] +@service.route('add/configure/ACL_L2', methods=['GET', 'POST']) def add_configure_ACL_L2(): form_acl = AddServiceForm_ACL_L2() service_obj = Service() - context_uuid, topology_uuid = get_context_and_topology_uuids() #Get the topology and context UUIDS - if context_uuid and topology_uuid: #If the UUIDs exist - context_client.connect() #Connects to the context service using the context_client object - grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) #Call the get_topology() function to retrieve the topology information for the given context and topology UUIDs - if grpc_topology: #If the topology is defined + context_uuid, topology_uuid = get_context_and_topology_uuids() + if context_uuid and topology_uuid: + context_client.connect() + grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) + if grpc_topology: topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids} - #devices = get_filtered_devices(context_client, topo_device_uuids) #Calls the fucntion that returns a list of devices that have UUIDs in the set of topology device UUIDs. context_obj = get_context(context_client, context_uuid, rw_copy=False) if context_obj is None: flash('Context({:s}) not found'.format(str(context_uuid)), 'danger') @@ -375,20 +362,20 @@ def add_configure_ACL_L2(): if device.device_id.device_uuid.uuid in devices_services: devices.append(device) - choices = get_device_choices(devices) #Returns a list of tuples, where each tuple contains the index of the device in the list and the name of the device - add_device_choices_to_form(choices, form_acl.service_device_1) #Adds the device choices to the select options for the form (Device1) - add_device_choices_to_form(choices, form_acl.service_device_2) #Adds the device choices to the select options for the form (Device2) + choices = get_device_choices(devices) + add_device_choices_to_form(choices, form_acl.service_device_1) + add_device_choices_to_form(choices, form_acl.service_device_2) else: - flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') #If the topology is not found, display an error message and set the devices list to an empty list + flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') else: - flash('Missing context or topology UUID', 'danger') #If the topology or context UUID is not found, display an error message + flash('Missing context or topology UUID', 'danger') if form_acl.validate_on_submit(): flash(f'New configuration was created', 'success') return redirect(url_for('service.home')) return render_template('service/configure_ACL_L2.html', form_acl=form_acl, submit_text='Add New Service') -@service.route('add/configure/ACL_IPV4', methods=['GET', 'POST']) #Route for adding a new ACL_IPV4 service [Setting the parameters for defining the service] +@service.route('add/configure/ACL_IPV4', methods=['GET', 'POST']) def add_configure_ACL_IPV4(): form_acl = AddServiceForm_ACL_IPV4() if form_acl.validate_on_submit(): @@ -397,7 +384,7 @@ def add_configure_ACL_IPV4(): print(form_acl.errors) return render_template('service/configure_ACL_IPV4.html', form_acl=form_acl, submit_text='Add New Service') -@service.route('add/configure/ACL_IPV6', methods=['GET', 'POST']) #Route for adding a new ACL_IPV6 service [Setting the parameters for defining the service] +@service.route('add/configure/ACL_IPV6', methods=['GET', 'POST']) def add_configure_ACL_IPV6(): form_acl = AddServiceForm_ACL_IPV6() if form_acl.validate_on_submit(): @@ -406,35 +393,34 @@ def add_configure_ACL_IPV6(): print(form_acl.errors) return render_template('service/configure_ACL_IPV6.html', form_acl=form_acl, submit_text='Add New Service') -@service.route('add/configure/L2VPN', methods=['GET', 'POST']) #Route for adding a new L2VPN service [Setting the parameters for defining the service] +@service.route('add/configure/L2VPN', methods=['GET', 'POST']) def add_configure_L2VPN(): - form_l2vpn = AddServiceForm_L2VPN() #Load the AddServiceForm_L3VPN form defined in forms.py - service_obj = Service() #Create a new instance of the Service class - - context_uuid, topology_uuid = get_context_and_topology_uuids() #Get the topology and context UUIDS - if context_uuid and topology_uuid: #If the UUIDs exist - context_client.connect() #Connects to the context service using the context_client object - grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) #Call the get_topology() function to retrieve the topology information for the given context and topology UUIDs - if grpc_topology: #If the topology is defined + form_l2vpn = AddServiceForm_L2VPN() + service_obj = Service() + + context_uuid, topology_uuid = get_context_and_topology_uuids() + if context_uuid and topology_uuid: + context_client.connect() + grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) + if grpc_topology: topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids} - devices = get_filtered_devices(context_client, topo_device_uuids) #Calls the fucntion that returns a list of devices that have UUIDs in the set of topology device UUIDs. - choices = get_device_choices(devices) #Returns a list of tuples, where each tuple contains the index of the device in the list and the name of the device - add_device_choices_to_form(choices, form_l2vpn.service_device_1) #Adds the device choices to the select options for the form (Device1) - add_device_choices_to_form(choices, form_l2vpn.service_device_2) #Adds the device choices to the select options for the form (Device2) + devices = get_filtered_devices(context_client, topo_device_uuids) + choices = get_device_choices(devices) + add_device_choices_to_form(choices, form_l2vpn.service_device_1) + add_device_choices_to_form(choices, form_l2vpn.service_device_2) else: - flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') #If the topology is not found, display an error message and set the devices list to an empty list + flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') else: - flash('Missing context or topology UUID', 'danger') #If the topology or context UUID is not found, display an error message + flash('Missing context or topology UUID', 'danger') - if form_l2vpn.validate_on_submit(): #Check if the form has been submitted and is valid - try: #Calls a function that validates the selected devices and endpoints exists and are correct + if form_l2vpn.validate_on_submit(): + try: [selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2] = validate_selected_devices_and_endpoints(form_l2vpn, devices) - except Exception as e: #Catch any exception raised during the validation process + except Exception as e: flash('{:s}'.format(str(e.args[0])), 'danger') current_app.logger.exception(e) - return render_template('service/configure_L2VPN.html', form_l2vpn=form_l2vpn, submit_text='Add New Service') #Render the L2VPN configuration form with the previously entered data and an error message + return render_template('service/configure_L2VPN.html', form_l2vpn=form_l2vpn, submit_text='Add New Service') - #Check the specific values of the parameters dependent by the vendor of the device [vendor_1, vendor_2] = get_device_vendor(form_l2vpn, devices) try: validate_params_vendor(form_l2vpn, vendor_1, 1) @@ -442,17 +428,16 @@ def add_configure_L2VPN(): except Exception as e: flash('{:s}'.format(str(e.args[0])), 'danger') current_app.logger.exception(e) - return render_template('service/configure_L2VPN.html', form_l2vpn=form_l2vpn, submit_text='Add New Service') #Render the L2VPN configuration form with the previously entered data and an error message + return render_template('service/configure_L2VPN.html', form_l2vpn=form_l2vpn, submit_text='Add New Service') - #Create definition of the Service: - service_uuid, service_type, endpoint_ids = set_service_parameters(service_obj, form_l2vpn, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2) #Calls the function to set the Service - Endpoint UUIDS - constraints = add_constraints(form_l2vpn) #Calls the function to add the constraint parameters for defining a service - params_device_1_with_data = get_device_params(form_l2vpn, 1, service_type) #Calls the function that getst the parameters that will configure the service in the device-1 - params_device_2_with_data = get_device_params(form_l2vpn, 2, service_type) #Calls the function that getst the parameters that will configure the service in the device-2 + service_uuid, service_type, endpoint_ids = set_service_parameters(service_obj, form_l2vpn, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2) + constraints = add_constraints(form_l2vpn) + params_device_1_with_data = get_device_params(form_l2vpn, 1, service_type) + params_device_2_with_data = get_device_params(form_l2vpn, 2, service_type) print(params_device_1_with_data) print(params_device_2_with_data) - params_settings = {} #Param settings (Defined despite it has no value) -> Avoid error - config_rules = [ #Create the configuration rules from the params_with_data + params_settings = {} + config_rules = [ json_config_rule_set( '/settings', params_settings ), @@ -467,54 +452,54 @@ def add_configure_L2VPN(): context_client.connect() device_client.connect() descriptor_json = json_service_l2nm_planned(service_uuid = service_uuid, endpoint_ids = endpoint_ids, constraints = constraints, config_rules = config_rules, context_uuid= context_uuid) - descriptor_json = {"services": [descriptor_json]} #Wrap the descriptor between the tag: "services": []" + descriptor_json = {"services": [descriptor_json]} try: process_descriptors(descriptor_json) - flash('Service "{:s}" added successfully!'.format(service_obj.service_id.service_uuid.uuid), 'success') #If the service was added succesfully -> Flash success message with newly added service UUID. - return redirect(url_for('service.home', service_uuid=service_obj.service_id.service_uuid.uuid)) #If the service was added succesfully -> Redirect to the service.home URL #Call the process_descriptors function to add the new service defined in the descriptor_json variable + flash('Service "{:s}" added successfully!'.format(service_obj.service_id.service_uuid.uuid), 'success') + return redirect(url_for('service.home', service_uuid=service_obj.service_id.service_uuid.uuid)) except Exception as e: - flash('Problem adding service: {:s}'.format((str(e.args[0]))), 'danger') #If the service was NOT added succesfully -> Include the exception message in a flashed message - current_app.logger.exception(e) #If the service was NOT added succesfully -> Log the exception using Flask's logger + flash('Problem adding service: {:s}'.format((str(e.args[0]))), 'danger') + current_app.logger.exception(e) finally: context_client.close() device_client.close() service_client.close() return render_template('service/configure_L2VPN.html', form_l2vpn=form_l2vpn, submit_text='Add New Service') -@service.route('add/configure/L3VPN', methods=['GET', 'POST']) #Route for adding a new L3VPN service [Setting the parameters for defining the service] +@service.route('add/configure/L3VPN', methods=['GET', 'POST']) def add_configure_L3VPN(): - form_l3vpn = AddServiceForm_L3VPN() #Load the AddServiceForm_L3VPN form defined in forms.py - service_obj = Service() #Create a new instance of the Service class - - context_uuid, topology_uuid = get_context_and_topology_uuids() #Get the topology and context UUIDS - if context_uuid and topology_uuid: #If the UUIDs exist - context_client.connect() #Connects to the context service using the context_client object - grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) #Call the get_topology() function to retrieve the topology information for the given context and topology UUIDs - if grpc_topology: #If the topology is defined + form_l3vpn = AddServiceForm_L3VPN() + service_obj = Service() + + context_uuid, topology_uuid = get_context_and_topology_uuids() + if context_uuid and topology_uuid: + context_client.connect() + grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False) + if grpc_topology: topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids} - devices = get_filtered_devices(context_client, topo_device_uuids) #Calls the fucntion that returns a list of devices that have UUIDs in the set of topology device UUIDs. - choices = get_device_choices(devices) #Returns a list of tuples, where each tuple contains the index of the device in the list and the name of the device - add_device_choices_to_form(choices, form_l3vpn.service_device_1) #Adds the device choices to the select options for the form (Device1) - add_device_choices_to_form(choices, form_l3vpn.service_device_2) #Adds the device choices to the select options for the form (Device2) + devices = get_filtered_devices(context_client, topo_device_uuids) + choices = get_device_choices(devices) + add_device_choices_to_form(choices, form_l3vpn.service_device_1) + add_device_choices_to_form(choices, form_l3vpn.service_device_2) else: - flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') #If the topology is not found, display an error message and set the devices list to an empty list + flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger') else: - flash('Missing context or topology UUID', 'danger') #If the topology or context UUID is not found, display an error message + flash('Missing context or topology UUID', 'danger') if form_l3vpn.validate_on_submit(): try: - [selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2] = validate_selected_devices_and_endpoints(form_l3vpn, devices) #Calls a function that validates the selected devices and endpoints exists and are correct - except Exception as e: # Catch any exception raised during the validation process + [selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2] = validate_selected_devices_and_endpoints(form_l3vpn, devices) + except Exception as e: flash('{:s}'.format(str(e.args[0])), 'danger') current_app.logger.exception(e) - return render_template('service/configure_L3VPN.html', form_l3vpn=form_l3vpn, submit_text='Add New Service') #Render the L3VPN configuration form with the previously entered data and an error message - #Create definition of the Service: - service_uuid, service_type, endpoint_ids = set_service_parameters(service_obj, form_l3vpn, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2) #Calls the function to set the Service - Endpoint UUIDS - constraints = add_constraints(form_l3vpn) #Calls the function to add the constraint parameters for defining a service + return render_template('service/configure_L3VPN.html', form_l3vpn=form_l3vpn, submit_text='Add New Service') + + service_uuid, service_type, endpoint_ids = set_service_parameters(service_obj, form_l3vpn, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2) + constraints = add_constraints(form_l3vpn) params_device_1_with_data = get_device_params(form_l3vpn, 1, service_type) params_device_2_with_data = get_device_params(form_l3vpn, 2, service_type) params_settings = {} - config_rules = [ #Create the configuration rules from the params_with_data + config_rules = [ json_config_rule_set( '/settings', params_settings ), @@ -529,14 +514,14 @@ def add_configure_L3VPN(): context_client.connect() device_client.connect() descriptor_json = json_service_l3nm_planned(service_uuid = service_uuid, endpoint_ids = endpoint_ids, constraints = constraints, config_rules = config_rules, context_uuid= context_uuid) - descriptor_json = {"services": [descriptor_json]} #Wrap the descriptor between the tag: "services": []" + descriptor_json = {"services": [descriptor_json]} try: process_descriptors(descriptor_json) - flash('Service "{:s}" added successfully!'.format(service_obj.service_id.service_uuid.uuid), 'success') #If the service was added succesfully -> Flash success message with newly added service UUID. - return redirect(url_for('service.home', service_uuid=service_obj.service_id.service_uuid.uuid)) #If the service was added succesfully -> Redirect to the service.home URL #Call the process_descriptors function to add the new service defined in the descriptor_json variable + flash('Service "{:s}" added successfully!'.format(service_obj.service_id.service_uuid.uuid), 'success') + return redirect(url_for('service.home', service_uuid=service_obj.service_id.service_uuid.uuid)) except Exception as e: - flash('Problem adding service: {:s}'.format((str(e.args[0]))), 'danger') #If the service was NOT added succesfully -> Include the exception message in a flashed message - current_app.logger.exception(e) #If the service was NOT added succesfully -> Log the exception using Flask's logger + flash('Problem adding service: {:s}'.format((str(e.args[0]))), 'danger') + current_app.logger.exception(e) finally: context_client.close() device_client.close() @@ -544,51 +529,49 @@ def add_configure_L3VPN(): return render_template('service/configure_L3VPN.html', form_l3vpn=form_l3vpn, submit_text='Add New Service') -##Function for creating the service DESCRIPTOR_LOADER_NUM_WORKERS = 10 -def process_descriptors(descriptors): #The function receives a "descriptors" parameter which has to be a JSON descriptor object - descriptor_loader = DescriptorLoader(descriptors, num_workers=DESCRIPTOR_LOADER_NUM_WORKERS) #Creates a descriptor_loader object - results = descriptor_loader.process() #Calls the descriptor_loader.process method and saves the result in the results variable - for message,level in compose_notifications(results): #Retrieve the notifications that are obtained in the proccess +def process_descriptors(descriptors): + descriptor_loader = DescriptorLoader(descriptors, num_workers=DESCRIPTOR_LOADER_NUM_WORKERS) + results = descriptor_loader.process() + for message,level in compose_notifications(results): if level == 'error': - LOGGER.warning('ERROR message={:s}'.format(str(message))) #Display any error message in the LOG - flash(message, level) #Show any notification message to the user in the webUI by using flash() + LOGGER.warning('ERROR message={:s}'.format(str(message))) + flash(message, level) -##Functions for having a higher leaver of abstraction and understanding in the code: -def get_context_and_topology_uuids(): #Retrieve the context and topology UUIDs from the session, if they exist +def get_context_and_topology_uuids(): context_uuid = session.get('context_uuid') topology_uuid = session.get('topology_uuid') - return context_uuid, topology_uuid #Return the UUIDs as a tuple, or None if either is missing + return context_uuid, topology_uuid -def get_filtered_devices(context_client, topo_device_uuids): #Call the ListDevices() method on the context client to retrieve a list of all devices +def get_filtered_devices(context_client, topo_device_uuids): grpc_devices = context_client.ListDevices(Empty()) - return [device for device in grpc_devices.devices if device.device_id.device_uuid.uuid in topo_device_uuids] #Filter the list of devices to only include those with UUIDs that appear in the topology + return [device for device in grpc_devices.devices if device.device_id.device_uuid.uuid in topo_device_uuids] -def get_device_choices(devices): #Create the tuple (Number, Device) that will be added to the form +def get_device_choices(devices): return [(i, str(device.name)) for i, device in enumerate(devices)] -def add_device_choices_to_form(choices, form): #Add the device choices (tuple) to the select options of the correspondent form +def add_device_choices_to_form(choices, form): form.choices += choices -def validate_selected_devices_and_endpoints(form, devices): #Validates that the 2 selected devices and 2 endpoints exist and are valid. Then it returns them - selected_device_1 = devices[int(form.service_device_1.data)] #Selected_Device1 will be the one selected by the user in the previously defined form field - selected_device_2 = devices[int(form.service_device_2.data)] #Selected_Device2 will be the one selected by the user in the previously defined form field +def validate_selected_devices_and_endpoints(form, devices): + selected_device_1 = devices[int(form.service_device_1.data)] + selected_device_2 = devices[int(form.service_device_2.data)] if selected_device_1 == selected_device_2: - raise ValidationError('The devices must be different!. Please select two valid and different devices') # If it is not a valid endpoint -> Raise a Validation Error - elif form.service_endpoint_1.data not in [endpoint.name for endpoint in selected_device_1.device_endpoints]: # Check if the endpoint submitted by the user is a valid endpoint of the selected device + raise ValidationError('The devices must be different!. Please select two valid and different devices') + elif form.service_endpoint_1.data not in [endpoint.name for endpoint in selected_device_1.device_endpoints]: raise ValidationError('The selected endpoint: ' + form.service_endpoint_1.data + ' is not a valid endpoint for: '+ selected_device_1.name + '. Please select an endpoint that is available for this device') - elif form.service_endpoint_2.data not in [endpoint.name for endpoint in selected_device_2.device_endpoints]: # Check if the endpoint submitted by the user is a valid endpoint of the selected device + elif form.service_endpoint_2.data not in [endpoint.name for endpoint in selected_device_2.device_endpoints]: raise ValidationError('The selected endpoint: ' + form.service_endpoint_2.data + ' is not a valid endpoint for: '+ selected_device_2.name + '. Please select an endpoint that is available for this device') else: - selected_endpoint_1 = form.service_endpoint_1.data #If the selected endpoint is valid, save it in a variable - selected_endpoint_2 = form.service_endpoint_2.data #If the selected endpoint is valid, save it in a variable - return selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2 #Return the devices and endpoints + selected_endpoint_1 = form.service_endpoint_1.data + selected_endpoint_2 = form.service_endpoint_2.data + return selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2 def get_device_vendor(form, devices): - selected_device_1 = devices[int(form.service_device_1.data)] #Selected_Device1 will be the one selected by the user in the previously defined form field - selected_device_2 = devices[int(form.service_device_2.data)] #Selected_Device2 will be the one selected by the user in the previously defined form field + selected_device_1 = devices[int(form.service_device_1.data)] + selected_device_2 = devices[int(form.service_device_2.data)] vendor_value_1 = None vendor_value_2 = None @@ -611,7 +594,7 @@ def get_device_vendor(form, devices): return vendor_value_1, vendor_value_2 -def validate_params_vendor(form, vendor, device_num): #num is an auxiliar variable that can be 1 or 2 for knowing if it corresponds to the first or second device +def validate_params_vendor(form, vendor, device_num): if vendor == "ADVA": 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"') @@ -622,35 +605,33 @@ def validate_params_vendor(form, vendor, device_num): #num is an auxiliar varia None return None -def set_service_parameters(service_obj, form, selected_device_1, selected_device_2, selected_endpoint_1, selected_endpoint_2): #Function to retrieve and set the service parameters for defining the service - #Service UUID: - service_obj.service_id.service_uuid.uuid = str(form.service_name.data) #Create the Service UUID (Unique Identifier of the service) from the service name +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) service_uuid = service_obj.service_id.service_uuid.uuid - #Service type [OPTIONS Defined in Context.proto]: 0(Unknown), 1(L3NM), 2(L2NM), 3(TAPI_CONNECTIVITY_SERVICE), 4(ACL) - service_obj.service_type = int(form.service_type.data) #Set the Service type as selected by the user in the form + service_obj.service_type = int(form.service_type.data) service_type = service_obj.service_type - # Set the endpoint IDs - endpoint_ids = [ #Create a list containing a element that represents the Selected Device ID and the Selected Endpoint + + endpoint_ids = [ json_endpoint_id(json_device_id(selected_device_1.name), str(selected_endpoint_1)), json_endpoint_id(json_device_id(selected_device_2.name), str(selected_endpoint_2)) ] return service_uuid, service_type, endpoint_ids -def add_constraints(form): #Function to add the constraints for a definition of a service - constraints = [] #Constraints -> Creates a list in which the constraints for the service will be added +def add_constraints(form): + constraints = [] if form.service_capacity.data: - constraints.append(json_constraint_sla_capacity(float(form.service_capacity.data))) #Capacity [Gbps] + constraints.append(json_constraint_sla_capacity(float(form.service_capacity.data))) if form.service_latency.data: - constraints.append(json_constraint_sla_latency(float(form.service_latency.data))) #Latency [ms] + constraints.append(json_constraint_sla_latency(float(form.service_latency.data))) if form.service_availability.data: - constraints.append(json_constraint_sla_availability(1, True, float(form.service_availability.data))) #Availability [%] + constraints.append(json_constraint_sla_availability(1, True, float(form.service_availability.data))) if form.service_isolation.data is not None and form.service_isolation.data != '': - constraints.append(json_constraint_sla_isolation([getattr(IsolationLevelEnum, str(form.service_isolation.data))])) #Isolation (Predefined values) + constraints.append(json_constraint_sla_isolation([getattr(IsolationLevelEnum, str(form.service_isolation.data))])) - return constraints #Returns a list with the constraints and values + return constraints -def get_device_params(form, device_num, form_type): #Function to retrieve and set the device parameters for defining the service - if form_type == 2: #Type2 = L2NM +def get_device_params(form, device_num, form_type): + if form_type == 2: device_params = { 'ni_name': str(getattr(form, 'NI_name').data), 'sub_interface_index': str(getattr(form, f'Device_{device_num}_IF_index').data), @@ -662,7 +643,7 @@ def get_device_params(form, device_num, form_type): 'ni_description': str(getattr(form, 'NI_description').data), 'subif_description': str(getattr(form, f'Device_{device_num}_IF_description').data), } - elif form_type == 1: #Type1 = L3NM + elif form_type == 1: if device_num == 1: policy_az_field = 'NI_import_policy' policy_za_field = 'NI_export_policy' @@ -687,5 +668,5 @@ def get_device_params(form, device_num, form_type): else: raise ValueError(f'Unsupported form type: {form_type}') - params_with_data = {k: v for k, v in device_params.items() if v is not None and str(v) != 'None' and v != ''} #Retrieve the params that do not have value (None or ' ') + params_with_data = {k: v for k, v in device_params.items() if v is not None and str(v) != 'None' and v != ''} return params_with_data diff --git a/src/webui/service/templates/service/detail.html b/src/webui/service/templates/service/detail.html index 64f56f254e0516ab2c182f135bf163e269508e28..ff2de8a3c60d8732d9bfdfe0cb361fdddee172f6 100644 --- a/src/webui/service/templates/service/detail.html +++ b/src/webui/service/templates/service/detail.html @@ -26,15 +26,8 @@ Back to service list </button> </div> - <!-- + <div class="col-sm-3"> - <a id="update" class="btn btn-secondary" href="#"> - <i class="bi bi-pencil-square"></i> - Update - </a> - </div>--> - <div class="col-sm-3"> - <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete service</button> --> <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal"> <i class="bi bi-x-square"></i> Delete service diff --git a/src/webui/service/templates/service/home.html b/src/webui/service/templates/service/home.html index a079dbd28b91a89210072f0c0df56b20d948ddb2..14226b7dcde572e196465b1e59e3ddf44c4193d9 100644 --- a/src/webui/service/templates/service/home.html +++ b/src/webui/service/templates/service/home.html @@ -19,7 +19,7 @@ {% block content %} <h1>Services</h1> - <div class="row"> <!-- Button for adding a New Service --> + <div class="row"> <div class="col"> <a href="{{ url_for('service.add_configure') }}" class="btn btn-primary" style="margin-bottom: 10px;"> <i class="bi bi-plus"></i> @@ -27,8 +27,6 @@ </a> </div> - <!-- Only display XR service addition button if there are XR constellations. Otherwise it might confuse - user, as other service types do not have GUI to add service yet. --> {% if "DEVICEDRIVER_XR" in active_drivers %} <div class="col"> <a href="{{ url_for('service.add_xr') }}" class="btn btn-primary" style="margin-bottom: 10px;"> @@ -41,14 +39,6 @@ <div class="col"> {{ services | length }} services found in context <i>{{ session['context_uuid'] }}</i> </div> - <!-- <div class="col"> Search engine for a service in the table of services - <form> - <div class="input-group"> - <input type="text" aria-label="Search" placeholder="Search..." class="form-control"/> - <button type="submit" class="btn btn-primary">Search</button> - </div> - </form> - </div> --> </div> <table class="table table-striped table-hover"> @@ -67,9 +57,7 @@ {% for service in services %} <tr> <td> - <!-- <a href="{{ url_for('service.detail', service_uuid=service.service_id.service_uuid.uuid) }}"> --> {{ service.service_id.service_uuid.uuid }} - <!-- </a> --> </td> <td> {{ service.name }}