Commit 4d0efcc9 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch 'develop' into 'main'

Release TeraFlowSDN NSC 7.0

See merge request !27
parents b13d64aa d0a1d22e
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (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.

__pycache__/
*.pyc
*.db
+15 −0
Original line number Diff line number Diff line
# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (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.

__pycache__/
swagger/__pycache__/
src/__pycache__/
venv/
.env
slice.db
.python-version
+1 −1
Original line number Diff line number Diff line
# Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (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.
+67 −10
Original line number Diff line number Diff line
# Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (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.
@@ -16,23 +16,80 @@

FROM python:3.12-slim

# Stablish woking directory
# Set working directory
WORKDIR /app

# Install system dependencies
# Install system and build dependencies
RUN apt-get update -qq && \
    apt-get install -y -qq git python3-dev && \
    apt-get install -y -qq \
        git \
        python3-dev \
        build-essential \
        cmake \
        pkg-config \
        libssl-dev \
        libpcre2-dev \
        libssh-dev \
        libcurl4-openssl-dev \
        zlib1g-dev \
        ca-certificates && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# Copy project content
COPY . /app
################################
# Build & install libyang
################################
RUN git clone https://github.com/CESNET/libyang.git /tmp/libyang && \
    cd /tmp/libyang && \
    git checkout v3.13.6 && \
    mkdir build && cd build && \
    cmake -D CMAKE_BUILD_TYPE=Release .. && \
    make -j$(nproc) && \
    make install && \
    ldconfig && \
    rm -rf /tmp/libyang

################################
# Build & install sysrepo
################################
RUN git clone https://github.com/sysrepo/sysrepo.git /tmp/sysrepo && \
    cd /tmp/sysrepo && \
    git checkout v3.7.11 && \
    mkdir build && cd build && \
    cmake .. && \
    make -j$(nproc) && \
    make install && \
    ldconfig && \
    rm -rf /tmp/sysrepo

################################
# Python dependencies
################################
COPY requirements.txt /app/requirements.txt

# Intall python dependencies
RUN pip install --upgrade pip && \
    pip install -r requirements.txt
    pip install --no-cache-dir -r requirements.txt

################################
# Application
################################
COPY . /app

# Expose port
EXPOSE 8081
EXPOSE 8085

RUN sysrepoctl -i /app/yang-modules/ietf-routing-types@2017-12-04.yang \
    -i /app/yang-modules/ietf-geo-location@2022-02-11.yang \
    -i /app/yang-modules/ietf-ethertypes@2019-03-04.yang \
    -i /app/yang-modules/ietf-packet-fields@2019-03-04.yang \
    -i /app/yang-modules/ietf-vpn-common@2022-02-11.yang \
    -i /app/yang-modules/ietf-network@2018-02-26.yang \
    -i /app/yang-modules/ietf-network-topology@2018-02-26.yang \
    -i /app/yang-modules/ietf-key-chain@2017-06-15.yang \
    -i /app/yang-modules/ietf-ac-common@2025-09-29.yang \
    -i /app/yang-modules/ietf-ac-svc@2025-09-29.yang \
    -i /app/yang-modules/ietf-te-types@2025-10-17.yang \
    -i /app/yang-modules/ietf-te-packet-types@2025-01-24.yang \
    -i /app/yang-modules/ietf-network-slice-service@2025-05-09.yang

# Init command
ENTRYPOINT ["python3", "app.py"]
 No newline at end of file
+45 −4
Original line number Diff line number Diff line
# Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
# Copyright 2022-2026 ETSI SDG TeraFlowSDN (TFS) (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.
@@ -15,17 +15,44 @@
# This file is an original contribution from Telefonica Innovación Digital S.L.

import logging
from flask import Flask
from flask import Flask, request, Response
from flask_restx import Api
from flask_cors import CORS
from swagger.tfs_namespace import tfs_ns
from swagger.ixia_namespace import ixia_ns
from swagger.E2E_namespace import e2e_ns
from swagger.restconf_namespace import restconf_ns
from src.config.constants import NSC_PORT
from src.webui.gui import gui_bp
from src.config.config import create_config
from src.database.db import init_db

# Paths that do not require authentication (Swagger UI and its static assets)
# /nsc       → Swagger UI
# /swaggerui → Swagger UI static assets (flask-restx)
# /swagger   → swagger.json spec file (flask-restx)
UNAUTHENTICATED_PREFIXES = ("/nsc", "/swaggerui", "/swagger")


def _unauthorized_response():
    """Return a 401 response without WWW-Authenticate header to avoid browser popup."""
    return Response(
        response="Unauthorized: valid credentials required.",
        status=401,
        headers={}
    )


def _check_basic_auth(app):
    """Validate Basic Auth credentials against the configured username and password."""
    credentials = request.authorization
    if not credentials:
        return False
    expected_username = app.config["API_USERNAME"]
    expected_password = app.config["API_PASSWORD"]
    return credentials.username == expected_username and credentials.password == expected_password


def create_app():
    """Create Flask application with configured API and namespaces."""
    init_db()
@@ -45,20 +72,34 @@ def create_app():
        version="1.0",
        title="Network Slice Controller (NSC) API",
        description="API for orchestrating and realizing transport network slice requests",
        doc="/nsc"  # Swagger UI URL
        doc="/nsc",  # Swagger UI URL
        authorizations={"basicAuth": {"type": "basic"}},
        security="basicAuth"
    )

    # Register namespaces
    api.add_namespace(tfs_ns, path="/tfs")
    api.add_namespace(ixia_ns, path="/ixia")
    api.add_namespace(e2e_ns, path="/e2e")
    api.add_namespace(restconf_ns, path="/restconf")

    if app.config["WEBUI_DEPLOY"]:
        app.secret_key = "clave-secreta-dev"
        app.register_blueprint(gui_bp)

    # Registered after Api and namespaces to ensure flask-restx does not override this hook
    @app.before_request
    def enforce_basic_auth():
        """Reject any request that does not include valid Basic Auth credentials."""
        # Allow unauthenticated access to Swagger UI and its static assets
        if request.path.startswith(UNAUTHENTICATED_PREFIXES):
            return None
        if not _check_basic_auth(app):
            return _unauthorized_response()

    return app


if __name__ == "__main__":
    app = create_app()
    app.run(host="0.0.0.0", port=NSC_PORT, debug=True)
 No newline at end of file
Loading