Commit 93af7f2a authored by Carlos Natalino's avatar Carlos Natalino
Browse files

Implementing the add device form. Now need to integrate with the device component.

parent 3a438c6f
Loading
Loading
Loading
Loading
+7 −27
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
  syntax='proto3',
  serialized_options=None,
  create_key=_descriptor._internal_create_key,
  serialized_pb=b'\n\rservice.proto\x12\x07service\x1a\rcontext.proto2\xed\x02\n\x0eServiceService\x12\x38\n\x0eGetServiceList\x12\x0e.context.Empty\x1a\x14.context.ServiceList\"\x00\x12\x37\n\rCreateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x37\n\rUpdateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x35\n\rDeleteService\x12\x12.context.ServiceId\x1a\x0e.context.Empty\"\x00\x12\x38\n\x0eGetServiceById\x12\x12.context.ServiceId\x1a\x10.context.Service\"\x00\x12>\n\x11GetConnectionList\x12\x0e.context.Empty\x1a\x17.context.ConnectionList\"\x00\x62\x06proto3'
  serialized_pb=b'\n\rservice.proto\x12\x07service\x1a\rcontext.proto2\xfd\x01\n\x0eServiceService\x12\x37\n\rCreateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x37\n\rUpdateService\x12\x10.context.Service\x1a\x12.context.ServiceId\"\x00\x12\x35\n\rDeleteService\x12\x12.context.ServiceId\x1a\x0e.context.Empty\"\x00\x12\x42\n\x11GetConnectionList\x12\x12.context.ServiceId\x1a\x17.context.ConnectionList\"\x00\x62\x06proto3'
  ,
  dependencies=[context__pb2.DESCRIPTOR,])

@@ -38,22 +38,12 @@ _SERVICESERVICE = _descriptor.ServiceDescriptor(
  serialized_options=None,
  create_key=_descriptor._internal_create_key,
  serialized_start=42,
  serialized_end=407,
  serialized_end=295,
  methods=[
  _descriptor.MethodDescriptor(
    name='GetServiceList',
    full_name='service.ServiceService.GetServiceList',
    index=0,
    containing_service=None,
    input_type=context__pb2._EMPTY,
    output_type=context__pb2._SERVICELIST,
    serialized_options=None,
    create_key=_descriptor._internal_create_key,
  ),
  _descriptor.MethodDescriptor(
    name='CreateService',
    full_name='service.ServiceService.CreateService',
    index=1,
    index=0,
    containing_service=None,
    input_type=context__pb2._SERVICE,
    output_type=context__pb2._SERVICEID,
@@ -63,7 +53,7 @@ _SERVICESERVICE = _descriptor.ServiceDescriptor(
  _descriptor.MethodDescriptor(
    name='UpdateService',
    full_name='service.ServiceService.UpdateService',
    index=2,
    index=1,
    containing_service=None,
    input_type=context__pb2._SERVICE,
    output_type=context__pb2._SERVICEID,
@@ -73,29 +63,19 @@ _SERVICESERVICE = _descriptor.ServiceDescriptor(
  _descriptor.MethodDescriptor(
    name='DeleteService',
    full_name='service.ServiceService.DeleteService',
    index=3,
    index=2,
    containing_service=None,
    input_type=context__pb2._SERVICEID,
    output_type=context__pb2._EMPTY,
    serialized_options=None,
    create_key=_descriptor._internal_create_key,
  ),
  _descriptor.MethodDescriptor(
    name='GetServiceById',
    full_name='service.ServiceService.GetServiceById',
    index=4,
    containing_service=None,
    input_type=context__pb2._SERVICEID,
    output_type=context__pb2._SERVICE,
    serialized_options=None,
    create_key=_descriptor._internal_create_key,
  ),
  _descriptor.MethodDescriptor(
    name='GetConnectionList',
    full_name='service.ServiceService.GetConnectionList',
    index=5,
    index=3,
    containing_service=None,
    input_type=context__pb2._EMPTY,
    input_type=context__pb2._SERVICEID,
    output_type=context__pb2._CONNECTIONLIST,
    serialized_options=None,
    create_key=_descriptor._internal_create_key,
+31 −6
Original line number Diff line number Diff line
# external imports
from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, SubmitField
from wtforms.validators import DataRequired, Length, NumberRange
from wtforms import StringField, SelectField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Length, NumberRange, Regexp, ValidationError

from webui.utils.form_validators import key_value_validator
from webui.proto.context_pb2 import (DeviceDriverEnum, DeviceOperationalStatusEnum)

class AddDeviceForm(FlaskForm):
    device_id = StringField('Device ID', 
    device_id = StringField('ID', 
                           validators=[DataRequired(), Length(min=5)])
    device_type = StringField('Device Type', 
    device_type = StringField('Type', 
                           validators=[DataRequired(), Length(min=5)])
    device_config = TextAreaField('Configurations', validators=[key_value_validator()])
    operational_status = SelectField('Operational Status',
                           choices=[(-1, 'Select...'), (0, 'Undefined'), (1, 'Disabled'), (2, 'Enabled')],
                        #    choices=[(-1, 'Select...'), (0, 'Undefined'), (1, 'Disabled'), (2, 'Enabled')],
                           coerce=int,
                           validators=[DataRequired(), NumberRange(min=0)])
                           validators=[NumberRange(min=0)])
    device_drivers = TextAreaField('Drivers', validators=[DataRequired(), Regexp('^\d+(,\d+)*$')])
    submit = SubmitField('Add')

    def validate_operational_status(form, field):
        if field.data not in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_number:
            raise ValidationError('The operational status value selected is incorrect!')
    
    def validate_device_drivers(form, field):
        if ',' not in field.data:
            data = str(field.data) + ','
        else:
            data = field.data
        for value in data.split(','):
            value = value.strip()
            if len(value) == 0:
                continue
            try:
                value_int = int(value)
            except:
                raise ValidationError(f'The value "{value}" is not a valid driver identified.')
            if value_int not in DeviceDriverEnum.DESCRIPTOR.values_by_number:
                values = ', '.join([str(x) for x in DeviceDriverEnum.DESCRIPTOR.values_by_number])
                raise ValidationError(f'The device driver {value_int} is not correct. Allowed values are: {values}.')
+56 −3
Original line number Diff line number Diff line
from flask import render_template, Blueprint, flash, session
from context.proto.context_pb2 import ConfigActionEnum, ConfigRule, TopologyIdList, TopologyList
from webui.Config import CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT
from context.client.ContextClient import ContextClient
from webui.proto.context_pb2 import (ContextId, DeviceList, DeviceId,
@@ -21,10 +22,63 @@ def home():
@device.route('add', methods=['GET', 'POST'])
def add():
    form = AddDeviceForm()

    request: ContextId = ContextId()
    request.context_uuid.uuid = session['context_uuid']
    client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
    response: TopologyIdList = client.ListTopologyIds(request)
    client.close()

    # listing enum values
    form.operational_status.choices = [(-1, 'Select...')]
    for key, value in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_name.items():
        form.operational_status.choices.append((DeviceOperationalStatusEnum.Value(key), key.replace('DEVICEOPERATIONALSTATUS_', '')))
    
    # device driver ids
    device_driver_ids = []
    for key in DeviceDriverEnum.DESCRIPTOR.values_by_name:
        device_driver_ids.append(f"{DeviceDriverEnum.Value(key)}={key.replace('DEVICEDRIVER_', '')}")
    device_driver_ids = ', '.join(device_driver_ids)

    if form.validate_on_submit():
        pass
        device: Device = Device()
        device.device_id.device_uuid.uuid = form.device_id.data
        device.device_type = form.device_type.data
        if '\n' not in form.device_config.data:
            data = form.device_config.data.strip() + '\n'
        else:
            data = form.device_config.data.strip()
        
        for config in data.split('\n'):
            if len(config.strip()) > 0:
                parts = config.strip().split('=')
                config_rule: ConfigRule = ConfigRule()
                config_rule.action = ConfigActionEnum.CONFIGACTION_SET
                config_rule.resource_key = parts[0].strip()
                config_rule.resource_value = parts[1].strip()
                device.device_config.config_rules.extend([config_rule])

        device.device_operational_status = form.operational_status.data

        if ',' not in form.device_drivers.data:
            data = form.device_drivers.data.strip() + ','
        else:
            data = form.device_drivers.data.strip()
        
        for driver in data.split(','):
            driver = driver.strip()
            if len(driver) == 0:
                continue
            device.device_drivers.extend([int(driver)])
        client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
        response: DeviceId = client.SetDevice(request)
        client.close()

        flash(f'New device was created with ID "{response.device_uuid.uuid}".', 'success')
        
    return render_template('device/add.html', form=form,
                    submit_text='Add New Device')
                    submit_text='Add New Device',
                    device_driver_ids=device_driver_ids)

@device.route('detail/<device_uuid>', methods=['GET', 'POST'])
def detail(device_uuid: str):
@@ -32,6 +86,5 @@ def detail(device_uuid: str):
    request.device_uuid.uuid = device_uuid
    client: ContextClient = ContextClient(CONTEXT_SERVICE_ADDRESS, CONTEXT_SERVICE_PORT)
    response: Device = client.GetDevice(request)
    print(response)
    client.close()
    return render_template('device/detail.html', device=response)
+4 −0
Original line number Diff line number Diff line
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
  return new bootstrap.Tooltip(tooltipTriggerEl)
})
+1 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@

    <!-- Option 1: Bootstrap Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-kQtW33rZJAHjgefvhyyzcGF3C5TFyBQBA13V1RKPf4uH+bwyzQxZ6CmMZHmNBEfJ" crossorigin="anonymous"></script>
    <!-- <script src="{{ url_for('static', filename='site.js') }}"/> -->

    <!-- Option 2: Separate Popper and Bootstrap JS -->
    <!--
Loading