Commit 0a1e4b3a authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch 'feat/404-cttc-multiple-enhancements-in-optical-controller' into 'develop'

Resolve "(CTTC) Multiple enhancements in optical controller"

See merge request !467
parents 23ae15fc f7b5f31f
Loading
Loading
Loading
Loading
+0 −0

File mode changed from 100644 to 100755.

scripts/dockerhub_login.sh

100644 → 100755
+0 −0

File mode changed from 100644 to 100755.

+0 −0

File mode changed from 100644 to 100755.

+32 −17
Original line number Diff line number Diff line
@@ -30,6 +30,15 @@ global links_dict
rsa = None


logging.basicConfig(level=logging.DEBUG)

LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG)

def print(*args) -> None:
    LOGGER.info(' '.join([str(a) for a in args]))


app = Flask(__name__)
api = Api(app, version='1.0', title='Optical controller API',
          description='Rest API to configure OC Optical devices in TFS')
@@ -338,7 +347,8 @@ class GetFlows(Resource):
                print(rsa.db_flows)
            return rsa.db_flows, 200
        except:
            return "Error", 404
            LOGGER.exception('Error while getting lightpaths')
            return 'Error', 404

@optical.route('/GetOpticalBands')
@optical.response(200, 'Success')
@@ -351,7 +361,8 @@ class GetBands(Resource):
                print(rsa.optical_bands)
            return rsa.optical_bands, 200
        except:
            return "Error", 404
            LOGGER.exception('Error while getting optical bands')
            return 'Error', 404


@optical.route('/GetOpticalBand/<int:ob_id>')
@@ -406,7 +417,8 @@ class GetFlows(Resource):
                print(links)
            return links, 200
        except:
            return "Error", 404
            LOGGER.exception('Error while getting links')
            return 'Error', 404
        
                
@optical.route('/GetTopology/<path:context_id>/<path:topology_id>',methods=['GET'])
@@ -431,13 +443,17 @@ class GetTopology(Resource):
            topo , nodes = readTopologyDataFromContext(topog_id)

            OPTICAL_ROADM_TYPES = {
                DeviceTypeEnum.OPTICAL_ROADM.value, DeviceTypeEnum.EMULATED_OPTICAL_ROADM.value
                DeviceTypeEnum.OPTICAL_ROADM.value,
                DeviceTypeEnum.EMULATED_OPTICAL_ROADM.value,
            }
            OPTICAL_OPENROADM_TYPES = {
                DeviceTypeEnum.OPEN_ROADM.value, DeviceTypeEnum.EMULATED_OPEN_ROADM.value
                DeviceTypeEnum.OPEN_ROADM.value,
                DeviceTypeEnum.EMULATED_OPEN_ROADM.value,
            }
            OPTICAL_TRANSPONDER_TYPES = {
                DeviceTypeEnum.OPTICAL_TRANSPONDER.value, DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value
                DeviceTypeEnum.OPTICAL_TRANSPONDER.value,
                DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value,
                DeviceTypeEnum.NETWORK.value,
            }
            added_device_uuids = set()
            for device in nodes:
@@ -490,12 +506,11 @@ class GetTopology(Resource):
            if debug:
                print(f'rsa.init_link_slots2() {rsa}')
                print(rsa.init_link_slots2())
        
        
            return  "ok" ,200
        except Exception as e:
            print(f"err {e}")
            return "Error", 400
            return 'OK', 200
        except Exception:
            LOGGER.exception('Error while processing topology data')
            #print(f'err {e}')
            return 'Error', 400

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=10060, debug=True)
+105 −69
Original line number Diff line number Diff line
@@ -13,12 +13,12 @@
# limitations under the License.

import logging
from typing import Dict, Tuple
from opticalcontroller.dijkstra import *
from opticalcontroller.tools import *
from opticalcontroller.variables import *


logging.basicConfig(level=logging.DEBUG)
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG)

@@ -31,17 +31,18 @@ class RSA():
        self.nodes_dict = nodes
        self.links_dict = links
        self.g = None
        self.node_key__to__node_name : Dict[str, Dict] = dict()
        self.link_key__to__src_dst_node_names : Dict[str, Tuple[str, str]] = dict()

        self.flow_id = 0
        self.opt_band_id = 0
        self.db_flows = {}
        self.initGraph2()
        self.init_graph()
        self.c_slot_number = 0
        self.l_slot_number = 0
        self.s_slot_number = 0
        self.optical_bands = {}

        
    def init_link_slots(self, testing):
        if full_links:
            for l in self.links_dict["optical_links"]:
@@ -97,45 +98,53 @@ class RSA():
                break
        return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number)

    def initGraph(self):
    def init_graph(self):
        self.node_key__to__node_name.clear()
        self.link_key__to__src_dst_node_names.clear()
        self.g = Graph()
        for n in self.nodes_dict:
            self.g.add_vertex(n)
        for l in self.links_dict["optical_links"]:
            #if debug:
            #    print(l)
            [s, d] = l["optical_link"]["name"].split('-')
            ps = l["optical_link"]["details"]["source"]
            pd = l["optical_link"]["details"]["target"]
            self.g.add_edge(s, d, ps, pd, 1)

        print("INFO: Graph initiated.")
        if debug:
            self.g.printGraph()
        for node_name, node_data in self.nodes_dict.items():
            MSG = '[RSA:init_graph] processing node: name={:s}, data={:s}'
            LOGGER.debug(MSG.format(str(node_name), str(node_data)))

    def initGraph2(self):
            node_id = node_data['id']
            self.node_key__to__node_name[node_id] = node_name
            self.node_key__to__node_name[node_name] = node_name
            self.g.add_vertex(node_name)

        self.g = Graph()
        for link in self.links_dict['optical_links']:
            MSG = '[RSA:init_graph] processing link: {:s}'
            LOGGER.debug(MSG.format(str(link)))

        for n in self.nodes_dict:
            self.g.add_vertex(n)
        for l in self.links_dict["optical_links"]:
            #if debug:
            #    print(l)
            [s, d] = l["name"].split('-')
            ps = l["optical_details"]["src_port"]
            pd = l["optical_details"]["dst_port"]
            self.g.add_edge(s, d, ps, pd, 1)
            src_ep_id = link['link_endpoint_ids'][ 0]
            src_node_uuid = src_ep_id['device_id']['device_uuid']['uuid']
            src_node_name = self.node_key__to__node_name[src_node_uuid]

        print("INFO: Graph initiated.2")
        if debug:
            dst_ep_id = link['link_endpoint_ids'][-1]
            dst_node_uuid = dst_ep_id['device_id']['device_uuid']['uuid']
            dst_node_name = self.node_key__to__node_name[dst_node_uuid]

            src_port = link['optical_details']['src_port']
            dst_port = link['optical_details']['dst_port']

            link_name = '{:s}-{:s}'.format(src_node_name, dst_node_name)
            self.link_key__to__src_dst_node_names[link_name] = (src_node_name, dst_node_name)
            link['name'] = link_name

            self.g.add_edge(src_node_name, dst_node_name, src_port, dst_port, 1)

        LOGGER.info('[RSA:init_graph] Graph initiated')
        self.g.printGraph()

    def compute_path(self, src, dst):
        path = shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst))
        print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance()))
        if debug:
            print(f"compute_path shortest_path {path}")

        MSG = '[RSA:compute_path] Path from {:s} to {:s} with distance {:f}'
        LOGGER.info(MSG.format(src, dst, float(self.g.get_vertex(dst).get_distance())))

        MSG = '[RSA:compute_path]   Path: {:s}'
        LOGGER.debug(MSG.format(str(path)))

        links = []
        for i in range(0, len(path) - 1):
            s = path[i]
@@ -155,10 +164,18 @@ class RSA():
    def compute_disjoint_path(self, src, dst, path1=None):
        if path1 is None:
            path1 = shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst))

        MSG = '[RSA:compute_disjoint_path] Path1: {:s}'
        LOGGER.info(MSG.format(str(path1)))

        path = disjoint_path(self.g, src, dst, path1, False)
        print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance()))
        if debug:
            print(path)

        MSG = '[RSA:compute_disjoint_path] Path from {:s} to {:s} with distance {:f}'
        LOGGER.info(MSG.format(src, dst, float(self.g.get_vertex(dst).get_distance())))

        MSG = '[RSA:compute_disjoint_path]   Path: {:s}'
        LOGGER.debug(MSG.format(str(path)))

        links = []
        for i in range(0, len(path) - 1):
            s = path[i]
@@ -195,13 +212,13 @@ class RSA():
        s_slots = {}
        add = ""
        drop = ""
        src_1, dst_1 = links[0].split('-')
        src_2, dst_2 = links[-1].split('-')
        src_1, dst_1 = self.link_key__to__src_dst_node_names[links[ 0]]
        src_2, dst_2 = self.link_key__to__src_dst_node_names[links[-1]]
        if self.nodes_dict[src_1]["type"] == "OC-TP":
            add = links[0]
        if self.nodes_dict[dst_2]["type"] == "OC-TP":
            drop = links[-1]
        found = 0

        for l in links:
            c_slots[l] = []
            l_slots[l] = []
@@ -411,9 +428,10 @@ class RSA():
            #self.restore_optical_band_2(o_b_id, slots, band,links)
        if bidir:
            for l in links:
                r_l = reverse_link(l)
                if debug:
                    print(f"reverse_link {r_l}")
                r_l = reverse_link(l, self.link_key__to__src_dst_node_names)
                MSG = '[RSA:del_flow] reverse link: {:s}'
                LOGGER.debug(MSG.format(str(r_l)))

                rlink = self.get_link_by_name(r_l)
                fib = rlink["optical_details"]
                #fib = self.get_link_by_name(r_l)["optical_details"]
@@ -496,7 +514,7 @@ class RSA():
            #self.restore_optical_band_2(o_b_id, slots, band,links)
            if bidir:
                for l in links:
                    r_l = reverse_link(l)
                    r_l = reverse_link(l, self.link_key__to__src_dst_node_names)
                    if debug:
                        print(r_l)
                    rlink = self.get_link_by_name(r_l)
@@ -524,6 +542,10 @@ class RSA():
            
             
    def get_fibers_forward(self, links, slots, band):
        LOGGER.info('[RSA:get_fibers_forward] Starting path forward computation')
        MSG = '[RSA:get_fibers_forward] Input parameters: links={:s}, slots={:s}, band={:s}'
        LOGGER.info(MSG.format(str(links), str(slots), str(band)))

        fiber_list = {}
        add = links[0]
        drop = links[-1]
@@ -560,17 +582,24 @@ class RSA():
                        #self.update_link(fib, slots, band)
                        self.update_link_2(fib,slots,band,link)
                        break
        print("INFO: Path forward computation completed")

        MSG = '[RSA:get_fibers_forward] Path forward computation completed: fiber_list={:s}'
        LOGGER.info(MSG.format(str(fiber_list)))
        return fiber_list

    def get_link_by_name (self, key):
    def get_link_by_name(self, key : str) -> Dict:
        for link in self.links_dict["optical_links"]:
            if link["name"] == key:
                #if debug:
                #    print(link)
                break
                return link

        MSG = '[RSA:get_link_by_name] Link with name {:s} not found. links_dict: {:s}'
        LOGGER.error(MSG.format(str(key), str(self.links_dict["optical_links"])))

        MSG = '[RSA:get_link_by_name] Link with name {:s} not found'
        raise ValueError(MSG.format(str(key)))

    def get_fiber_details(self, link_key, fiber_id):
        for link in self.links_dict["optical_links"]:
            if link["name"] == link_key:
@@ -582,9 +611,13 @@ class RSA():
        return None

    def get_fibers_backward(self, links, slots, band):
        LOGGER.info('[RSA:get_fibers_backward] Starting path backward computation')
        MSG = '[RSA:get_fibers_backward] Input parameters: links={:s}, slots={:s}, band={:s}'
        LOGGER.info(MSG.format(str(links), str(slots), str(band)))

        fiber_list = {}
        #r_drop = reverse_link(links[0])
        #r_add = reverse_link(links[-1])
        #r_drop = reverse_link(links[0], self.link_key__to__src_dst_node_names)
        #r_add = reverse_link(links[-1], self.link_key__to__src_dst_node_names)
        for l in links:
            fib = self.get_link_by_name(l)["optical_details"]
            '''
@@ -596,13 +629,14 @@ class RSA():
            s_port = fib["src_port"]
            d_port = fib["dst_port"]

            if debug:
                print(l, s_port, d_port)
            MSG = '[RSA:get_fibers_backward] processing link: {:s}, src_port: {:s}, dst_port: {:s}'
            LOGGER.debug(MSG.format(str(l), str(s_port), str(d_port)))

            r_l = reverse_link(l)
            r_l = reverse_link(l, self.link_key__to__src_dst_node_names)
            r_link = self.get_link_by_name(r_l)
            #if debug:
            #    print(r_l)

            MSG = '[RSA:get_fibers_backward] reverse link: {:s}'
            LOGGER.debug(MSG.format(str(r_l)))

            #for f in r_link["fibers"].keys():
            r_fib = r_link["optical_details"]
@@ -610,7 +644,9 @@ class RSA():
                if list_in_list(slots, str_list_to_int(r_fib[band].keys())):
                    #fiber_list[r_l] = r_fib["ID"]
                    self.update_link(r_fib, slots, band)
        print("INFO: Path backward computation completed")

        MSG = '[RSA:get_fibers_backward] Path backward computation completed: fiber_list={:s}'
        LOGGER.info(MSG.format(str(fiber_list)))
        return fiber_list

    #function invoked for lightpaths and OB
@@ -652,7 +688,7 @@ class RSA():
            
            fibx = self.get_fiber_details(lx, f)
            '''
            src, dst = llx.split("-")
            src, dst = self.link_key__to__src_dst_node_names[llx]
            #outport = self.links_dict[lx]['fibers'][f]["src_port"]
            lx = self.get_link_by_name(llx)["optical_details"]
            outport = lx["src_port"]
@@ -724,7 +760,7 @@ class RSA():
        t_flows = {}

        #flows_add_side
        src, dst = add.split("-")
        src, dst = self.link_key__to__src_dst_node_names[add]
        lx = self.get_link_by_name(add)["optical_details"]
        #outport = self.links_dict[add]['fibers'][f]["src_port"]
        outport = lx["src_port"]
@@ -761,7 +797,7 @@ class RSA():
        #flows_drop_side
        # R2 rules
        ly = self.get_link_by_name(drop)["optical_details"]
        src, dst = drop.split("-")
        src, dst = self.link_key__to__src_dst_node_names[drop]
        #outport = self.links_dict[drop]['fibers'][f]["src_port"]
        outport = ly["src_port"]

@@ -813,7 +849,7 @@ class RSA():

        '''
        #flows_add_side
        src, dst = add.split("-")
        src, dst = self.link_key__to__src_dst_node_names[add]
        lx = self.get_link_by_name(add)["optical_details"]
        #outport = self.links_dict[add]['fibers'][f]["src_port"]
        outport = lx["src_port"]
@@ -1268,8 +1304,8 @@ class RSA():
                temp_links2.append(list(dst_links.keys())[0])

            if len(temp_links2) == 2:
                [t_src, roadm_src] = temp_links2[0].split('-')
                [roadm_dst, t_dst] = temp_links2[1].split('-')
                t_src, roadm_src = self.link_key__to__src_dst_node_names[temp_links2[0]]
                roadm_dst, t_dst = self.link_key__to__src_dst_node_names[temp_links2[1]]
                temp_path.append(t_src)
                temp_path.append(roadm_src)
                temp_path.append(roadm_dst)
@@ -1585,7 +1621,7 @@ class RSA():
            #self.restore_optical_band_2(o_b_id, slots, band,links)
        if bidir:
            for l in links:
                r_l = reverse_link(l)
                r_l = reverse_link(l, self.link_key__to__src_dst_node_names)
                if debug:
                    print(r_l)
                rlink = self.get_link_by_name(r_l)
@@ -1627,8 +1663,8 @@ class RSA():
        r1 = ""
        r2 = ""
        if len(links) == 2:
            [t1, r1] = links[0].split("-")                    
            [r2, t2] = links[1].split("-")
            t1, r1 = self.link_key__to__src_dst_node_names[links[0]]
            r2, t2 = self.link_key__to__src_dst_node_names[links[1]]
        else:
            return 0, 0
        existing_ob = self.get_optical_bands(r1, r2)
Loading