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

WebUI component:

- added section to control load generator
- updated basic Debug API endpoints
parent 73efb256
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from flask_wtf import FlaskForm
from wtforms import BooleanField, FloatField, IntegerField, StringField, SubmitField
from wtforms.validators import DataRequired, NumberRange

class LoadGenStartForm(FlaskForm):
    num_requests = IntegerField('Num Requests', default=100, validators=[DataRequired(), NumberRange(min=0)])
    num_generated = IntegerField('Num Generated', render_kw={'readonly': True})

    request_type_service_l2nm = BooleanField('Service L2NM', default=False)
    request_type_service_l3nm = BooleanField('Service L3NM', default=False)
    request_type_service_mw = BooleanField('Service MW', default=False)
    request_type_service_tapi = BooleanField('Service TAPI', default=False)
    request_type_slice_l2nm = BooleanField('Slice L2NM', default=True)
    request_type_slice_l3nm = BooleanField('Slice L3NM', default=False)

    offered_load = FloatField('Offered Load [Erlang]', default=50, validators=[NumberRange(min=1.e-12)])
    holding_time = FloatField('Holding Time [seconds]', default=10, validators=[NumberRange(min=1.e-12)])
    inter_arrival_time = FloatField('Inter Arrival Time[seconds]', default=0, validators=[NumberRange(min=1.e-12)])

    do_teardown = BooleanField('Do Teardown', default=True)

    record_to_dlt = BooleanField('Record to DLT', default=False)
    dlt_domain_id = StringField('DLT Domain Id', default='')

    infinite_loop = BooleanField('Infinite Loop', render_kw={'readonly': True})
    running = BooleanField('Running', render_kw={'readonly': True})

    submit = SubmitField('Start')

class LoadGenStopForm(FlaskForm):
    submit = SubmitField('Stop')
+85 −24
Original line number Diff line number Diff line
@@ -14,26 +14,49 @@

from flask import render_template, Blueprint, flash
from common.proto.context_pb2 import Empty
from common.proto.load_generator_pb2 import Parameters, RequestTypeEnum
from load_generator.client.LoadGeneratorClient import LoadGeneratorClient
from .forms import LoadGenStartForm, LoadGenStopForm

load_gen = Blueprint('load_gen', __name__, url_prefix='/load_gen')

@load_gen.route('start', methods=['GET'])
def start():
@load_gen.route('home', methods=['GET', 'POST'])
def home():
    load_gen_client = LoadGeneratorClient()

    form_start = LoadGenStartForm()
    form_stop = LoadGenStopForm()

    if form_start.validate_on_submit():
        load_gen_params = Parameters()
        load_gen_params.num_requests       = form_start.num_requests.data
        load_gen_params.offered_load       = form_start.offered_load.data
        load_gen_params.holding_time       = form_start.holding_time.data
        load_gen_params.inter_arrival_time = form_start.inter_arrival_time.data
        load_gen_params.do_teardown        = form_start.do_teardown.data
        load_gen_params.dry_mode           = False
        load_gen_params.record_to_dlt      = form_start.record_to_dlt.data
        load_gen_params.dlt_domain_id      = form_start.dlt_domain_id.data

        del load_gen_params.request_types[:] # pylint: disable=no-member
        request_types = list()
        if form_start.request_type_service_l2nm.data: request_types.append(RequestTypeEnum.REQUESTTYPE_SERVICE_L2NM)
        if form_start.request_type_service_l3nm.data: request_types.append(RequestTypeEnum.REQUESTTYPE_SERVICE_L3NM)
        if form_start.request_type_service_mw  .data: request_types.append(RequestTypeEnum.REQUESTTYPE_SERVICE_MW  )
        if form_start.request_type_service_tapi.data: request_types.append(RequestTypeEnum.REQUESTTYPE_SERVICE_TAPI)
        if form_start.request_type_slice_l2nm  .data: request_types.append(RequestTypeEnum.REQUESTTYPE_SLICE_L2NM  )
        if form_start.request_type_slice_l3nm  .data: request_types.append(RequestTypeEnum.REQUESTTYPE_SLICE_L3NM  )
        load_gen_params.request_types.extend(request_types) # pylint: disable=no-member

        try:
            load_gen_client.connect()
        load_gen_client.Start(Empty())
            load_gen_client.Start(load_gen_params)
            load_gen_client.close()
            flash('Load Generator Started.', 'success')
        except Exception as e: # pylint: disable=broad-except
            flash('Problem starting Load Generator. {:s}'.format(str(e)), 'danger')

    return render_template('main/debug.html')

@load_gen.route('stop', methods=['GET'])
def stop():
    load_gen_client = LoadGeneratorClient()
    if form_stop.validate_on_submit():
        try:
            load_gen_client.connect()
            load_gen_client.Stop(Empty())
@@ -42,4 +65,42 @@ def stop():
        except Exception as e: # pylint: disable=broad-except
            flash('Problem stopping Load Generator. {:s}'.format(str(e)), 'danger')

    return render_template('main/debug.html')
    load_gen_client.connect()
    status = load_gen_client.GetStatus(Empty())
    load_gen_client.close()

    form_start.num_requests      .default = status.parameters.num_requests
    form_start.offered_load      .default = status.parameters.offered_load
    form_start.holding_time      .default = status.parameters.holding_time
    form_start.inter_arrival_time.default = status.parameters.inter_arrival_time
    form_start.do_teardown       .default = status.parameters.do_teardown
    form_start.record_to_dlt     .default = status.parameters.record_to_dlt
    form_start.dlt_domain_id     .default = status.parameters.dlt_domain_id
    form_start.num_generated     .default = status.num_generated
    form_start.infinite_loop     .default = status.infinite_loop
    form_start.running           .default = status.running

    request_types = status.parameters.request_types
    form_start.request_type_service_l2nm.default = RequestTypeEnum.REQUESTTYPE_SERVICE_L2NM in request_types
    form_start.request_type_service_l3nm.default = RequestTypeEnum.REQUESTTYPE_SERVICE_L3NM in request_types
    form_start.request_type_service_mw  .default = RequestTypeEnum.REQUESTTYPE_SERVICE_MW   in request_types
    form_start.request_type_service_tapi.default = RequestTypeEnum.REQUESTTYPE_SERVICE_TAPI in request_types
    form_start.request_type_slice_l2nm  .default = RequestTypeEnum.REQUESTTYPE_SLICE_L2NM   in request_types
    form_start.request_type_slice_l3nm  .default = RequestTypeEnum.REQUESTTYPE_SLICE_L3NM   in request_types

    form_start.num_requests      .render_kw['readonly'] = status.running
    form_start.offered_load      .render_kw['readonly'] = status.running
    form_start.holding_time      .render_kw['readonly'] = status.running
    form_start.inter_arrival_time.render_kw['readonly'] = status.running
    form_start.do_teardown       .render_kw['readonly'] = status.running
    form_start.record_to_dlt     .render_kw['readonly'] = status.running
    form_start.dlt_domain_id     .render_kw['readonly'] = status.running

    form_start.request_type_service_l2nm.render_kw['readonly'] = status.running
    form_start.request_type_service_l3nm.render_kw['readonly'] = status.running
    form_start.request_type_service_mw  .render_kw['readonly'] = status.running
    form_start.request_type_service_tapi.render_kw['readonly'] = status.running
    form_start.request_type_slice_l2nm  .render_kw['readonly'] = status.running
    form_start.request_type_slice_l3nm  .render_kw['readonly'] = status.running

    return render_template('load_gen/home.html', form_start=form_start, form_stop=form_stop)
+7 −1
Original line number Diff line number Diff line
@@ -86,10 +86,16 @@
                <li class="nav-item">
                  <a class="nav-link" href="/grafana" id="grafana_link" target="grafana">Grafana</a>
                </li>
  
                <li class="nav-item">
                  <a class="nav-link" href="{{ url_for('main.debug') }}">Debug</a>
                </li>
                <li class="nav-item">
                  {% if '/load-gen/' in request.path %}
                  <a class="nav-link active" aria-current="page" href="{{ url_for('load_gen.home') }}">Load Generator</a>
                  {% else %}
                  <a class="nav-link" href="{{ url_for('load_gen.home') }}">Load Generator</a>
                  {% endif %}
                </li>
  
                <!-- <li class="nav-item">
                  <a class="nav-link" href="#">Context</a>
+164 −0
Original line number Diff line number Diff line
<!--
 Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-->

{% extends 'base.html' %}

{% block content %}
    <h1>Load Generator</h1>
    <br />

    <form id="load_gen_start" method="POST">
        {{ form_start.hidden_tag() }}
        <fieldset>
            <div class="row mb-3">
                {{ form_start.num_requests.label(class="col-sm-2 col-form-label") }}
                <div class="col-sm-10">
                    {% if form_start.num_requests.errors %}
                        {{ form_start.num_requests(class="form-control is-invalid") }}
                        <div class="invalid-feedback">
                            {% for error in form_start.num_requests.errors %}<span>{{ error }}</span>{% endfor %}
                        </div>
                    {% else %}
                        {{ form_start.num_requests(class="form-control") }}
                    {% endif %}
                </div>
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.num_generated.label(class="col-sm-2 col-form-label") }}
                <div class="col-sm-10">
                    {% if form_start.num_generated.errors %}
                        {{ form_start.num_generated(class="form-control is-invalid") }}
                        <div class="invalid-feedback">
                            {% for error in form_start.num_generated.errors %}<span>{{ error }}</span>{% endfor %}
                        </div>
                    {% else %}
                        {{ form_start.num_generated(class="form-control") }}
                    {% endif %}
                </div>
            </div>
            <br />

            <div class="row mb-3">
                <div class="col-sm-2 col-form-label">Service Types:</div>
                <div class="col-sm-10">
                    {{ form_start.request_type_service_l2nm }} {{ form_start.request_type_service_l2nm.label(class="col-sm-3 col-form-label") }}
                    {{ form_start.request_type_service_l3nm }} {{ form_start.request_type_service_l3nm.label(class="col-sm-3 col-form-label") }}
                    {{ form_start.request_type_service_mw   }} {{ form_start.request_type_service_mw  .label(class="col-sm-3 col-form-label") }}
                    {{ form_start.request_type_service_tapi }} {{ form_start.request_type_service_tapi.label(class="col-sm-3 col-form-label") }}
                    {{ form_start.request_type_slice_l2nm   }} {{ form_start.request_type_slice_l2nm  .label(class="col-sm-3 col-form-label") }}
                    {{ form_start.request_type_slice_l3nm   }} {{ form_start.request_type_slice_l3nm  .label(class="col-sm-3 col-form-label") }}
                </div>
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.offered_load.label(class="col-sm-2 col-form-label") }}
                <div class="col-sm-10">
                    {% if form_start.offered_load.errors %}
                        {{ form_start.offered_load(class="form-control is-invalid") }}
                        <div class="invalid-feedback">
                            {% for error in form_start.offered_load.errors %}<span>{{ error }}</span>{% endfor %}
                        </div>
                    {% else %}
                        {{ form_start.offered_load(class="form-control") }}
                    {% endif %}
                </div>
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.holding_time.label(class="col-sm-2 col-form-label") }}
                <div class="col-sm-10">
                    {% if form_start.holding_time.errors %}
                        {{ form_start.holding_time(class="form-control is-invalid") }}
                        <div class="invalid-feedback">
                            {% for error in form_start.holding_time.errors %}<span>{{ error }}</span>{% endfor %}
                        </div>
                    {% else %}
                        {{ form_start.holding_time(class="form-control") }}
                    {% endif %}
                </div>
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.inter_arrival_time.label(class="col-sm-2 col-form-label") }}
                <div class="col-sm-10">
                    {% if form_start.inter_arrival_time.errors %}
                        {{ form_start.inter_arrival_time(class="form-control is-invalid") }}
                        <div class="invalid-feedback">
                            {% for error in form_start.inter_arrival_time.errors %}<span>{{ error }}</span>{% endfor %}
                        </div>
                    {% else %}
                        {{ form_start.inter_arrival_time(class="form-control") }}
                    {% endif %}
                </div>
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.do_teardown(class="form-control") }} {{ form_start.do_teardown.label(class="col-sm-2 col-form-label") }}
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.record_to_dlt(class="form-control") }} {{ form_start.record_to_dlt.label(class="col-sm-2 col-form-label") }}
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.dlt_domain_id.label(class="col-sm-2 col-form-label") }}
                <div class="col-sm-10">
                    {% if form_start.dlt_domain_id.errors %}
                        {{ form_start.dlt_domain_id(class="form-control is-invalid") }}
                        <div class="invalid-feedback">
                            {% for error in form_start.dlt_domain_id.errors %}<span>{{ error }}</span>{% endfor %}
                        </div>
                    {% else %}
                        {{ form_start.dlt_domain_id(class="form-control") }}
                    {% endif %}
                </div>
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.infinite_loop(class="form-control") }} {{ form_start.infinite_loop.label(class="col-sm-2 col-form-label") }}
            </div>
            <br />

            <div class="row mb-3">
                {{ form_start.running(class="form-control") }} {{ form_start.running.label(class="col-sm-2 col-form-label") }}
            </div>
            <br />

            <div class="d-grid gap-2 d-md-flex justify-content-md-start">
                {{ form_start.submit(class="btn btn-primary") }}
            </div>
        </fieldset>
    </form>

    <form id="load_gen_stop" method="POST">
        {{ form_stop.hidden_tag() }}
        <fieldset>
            <div class="d-grid gap-2 d-md-flex justify-content-md-start">
                {{ form_stop.submit(class="btn btn-primary") }}
            </div>
        </fieldset>
    </form>

{% endblock %}
+6 −20
Original line number Diff line number Diff line
@@ -17,26 +17,12 @@
{% extends 'base.html' %}

{% block content %}
    <h1>Debug</h1>
    <h1>Debug API</h1>

    <!--
        <h3>Dump ContextDB:</h3>
    <ul>
            <li>
                <a class="nav-link" href="/context/api/dump/html" id="context_html_link" target="context_html">
                    as HTML
                </a>
            </li>
            <li>
                <a class="nav-link" href="/context/api/dump/text" id="context_text_link" target="context_text">
                    as Text
                </a>
            </li>
        <li><a class="nav-link" href="/restconf/debug-api/contexts" id="contexts_link" target="contexts">Contexts</a></li>
        <li><a class="nav-link" href="/restconf/debug-api/devices" id="devices_link" target="devices">Devices</a></li>
        <li><a class="nav-link" href="/restconf/debug-api/links" id="links_link" target="links">Links</a></li>
    </ul>
    -->

    <h3>Load Generator:</h3>
    <a href="{{ url_for('load_gen.start') }}" class="btn btn-primary" style="margin-bottom: 10px;">Start</a>
    <a href="{{ url_for('load_gen.stop') }}" class="btn btn-primary" style="margin-bottom: 10px;">Stop</a>

{% endblock %}