build.main.Main.setup()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nop 1
dl 0
loc 10
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
"""Main module of amlight/sdntrace Kytos Network Application.
2
3
An OpenFlow Data Path Trace.
4
5
The AmLight SDNTrace is a Kytos Network Application allows users to trace a
6
path directly from the data plane. Originally written for Ryu
7
(github.com/amlight/sdntrace).
8
9
Steps:
10
    1 - User requests a trace using a specific flow characteristic,
11
        for example VLAN = 1000 and Dest IP address = 2.2.2.2
12
    2 - REST module inserts trace request in a queue provided by the
13
        TraceManager
14
    3 - The TraceManager runs the Tracer, basically sending PacketOuts
15
        and waiting for PacketIn until reaching a timeout
16
    4 - After Timeout, result is provided back to REST that provides it
17
        back to user
18
Dependencies:
19
    * - amlight/coloring Napp will color all switches
20
21
At this moment, OpenFlow 1.3 is supported.
22
"""
23
24 1
import pathlib
25
26 1
from napps.amlight.sdntrace import settings
27 1
from napps.amlight.sdntrace.backends.of_parser import process_packet_in
28 1
from napps.amlight.sdntrace.shared.switches import Switches
29 1
from napps.amlight.sdntrace.tracing.trace_manager import TraceManager
30
31 1
from kytos.core import KytosNApp, rest
32 1
from kytos.core.helpers import listen_to, load_spec, validate_openapi
33 1
from kytos.core.rest_api import JSONResponse, Request, get_json_or_400
34
35
36 1
class Main(KytosNApp):
37
    """Main class of amlight/sdntrace NApp.
38
39
    REST methods:
40
        /sdntrace/trace ['PUT'] - request a trace
41
        /sdntrace/trace ['GET'] - list of previous trace requests and results
42
        /sdntrace/trace/<trace_id> - get the results of trace requested
43
        /sdntrace/stats - Show the number of requests received and active
44
        /sdntrace/settings - list the settings
45
    """
46
47 1
    spec = load_spec(pathlib.Path(__file__).parent / "openapi.yml")
48
49 1
    def setup(self):
50
        """Default Kytos/Napps setup call."""
51
52
        # Create list of switches
53 1
        self.switches = Switches(
54
            self.controller.switches
55
        )  # noqa: E501  pylint: disable=attribute-defined-outside-init
56
57
        # Instantiate TraceManager
58 1
        self.tracing = TraceManager(self.controller)  # pylint: disable=W0201
59
60 1
    def execute(self):
61
        """Kytos Napp execute method"""
62
63 1
    def shutdown(self):
64
        """Execute when your napp is unloaded.
65
66
        If you have some cleanup procedure, insert it here.
67
        """
68
        self.tracing.stop_traces()
69
70 1
    @listen_to("kytos/of_core.v0x04.messages.in.ofpt_packet_in")
71 1
    def handle_packet_in(self, event):
72
        """Receives OpenFlow PacketIn msgs and search from trace packets.
73
        If process_packet_in returns 0,0,0, it means it is not a probe
74
        packet. Otherwise, store the msg for later use by Tracers.
75
76
        Args:
77
            event (KycoPacketIn): Received Event
78
        """
79
        ethernet, in_port, switch = process_packet_in(event)
80
        if not isinstance(ethernet, int):
81
            self.tracing.queue_probe_packet(event, ethernet, in_port, switch)
82
83 1
    @rest("/v1/trace", methods=["PUT"])
84 1
    @validate_openapi(spec)
85 1
    def run_trace(self, request: Request) -> JSONResponse:
86
        """Submit a trace request."""
87 1
        body = get_json_or_400(request, self.controller.loop)
88 1
        return JSONResponse(self.tracing.rest_new_trace(body))
89
90 1
    @rest("/v1/trace", methods=["GET"])
91 1
    def get_results(self, _request: Request) -> JSONResponse:
92
        """List all traces performed so far."""
93 1
        return JSONResponse(self.tracing.rest_list_results())
94
95 1
    @rest("/v1/trace/{trace_id}", methods=["GET"])
96 1
    def get_result(self, request: Request) -> JSONResponse:
97
        """List All Traces performed since the Napp loaded."""
98 1
        trace_id = request.path_params["trace_id"]
99 1
        return JSONResponse(self.tracing.rest_get_result(trace_id))
100
101 1
    @rest("/v1/stats", methods=["GET"])
102 1
    def get_stats(self, _request: Request) -> JSONResponse:
103
        """Get statistics."""
104 1
        return JSONResponse(self.tracing.rest_list_stats())
105
106 1
    @staticmethod
107 1
    @rest("/v1/settings", methods=["GET"])
108 1
    def list_settings(_request: Request) -> JSONResponse:
109
        """List the SDNTrace settings
110
111
        Return:
112
            SETTINGS in JSON format
113
        """
114 1
        settings_dict = {}
115 1
        settings_dict["color_field"] = settings.COLOR_FIELD
116 1
        settings_dict["color_value"] = settings.COLOR_VALUE
117 1
        settings_dict["trace_interval"] = settings.TRACE_INTERVAL
118 1
        settings_dict["parallel_traces"] = settings.PARALLEL_TRACES
119
        return JSONResponse(settings_dict)
120