Beispiel #1
0
 public static void ValidatePathsUsingDijkstra(Topology.IGP.Topology igp_topology, List <Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath> hlsps)
 {
     foreach (var hlsp in hlsps)
     {
         ValidatePathsUsingDijkstra(igp_topology, hlsp);
     }
 }
Beispiel #2
0
        public static CICDJob Test(string repo_url, string user, string password, Topology.IGP.Topology igp_topology, Topology.MPLS.Topology mpls_topology)
        {
            CICDJob newJob = new CICDJob(repo_url, user, password, JobType.Test, igp_topology, mpls_topology);

            cicd_jobs.TryAdd(newJob.Id, newJob);

            return(newJob);
        }
Beispiel #3
0
        public Scheduler(Topology.IGP.Topology igpTopology, Config config)
        {
            this.igp_topology = igpTopology;
            this.config       = config;

            IntentTimer.Elapsed += IntentTimer_Elapsed;
            IntentTimer.Enabled  = true;
        }
            public void LoadGraph(Topology.IGP.Topology Topology, string EdgeCostPropertyName)
            {
                List <Topology.Node.Node>     nodes_copy = Topology.Nodes.DeepClone();
                List <Topology.IGP.Link.Link> links_copy = Topology.Links.DeepClone();

                foreach (var n in nodes_copy)
                {
                    this.AddVertex(n);
                }
                foreach (var l in links_copy)
                {
                    this.AddEdge(l, EdgeCostPropertyName);
                }
            }
Beispiel #5
0
        public CICDJob(string repo_url, string user, string password, JobType jobType,
                       Topology.IGP.Topology igp_topology, Topology.MPLS.Topology mpls_topology)
        {
            this.Completed      = false;
            this.Id             = Guid.NewGuid();
            this.RepositoryURL  = repo_url;
            this.DeployUsername = user;
            this.DeployPassword = password;
            this.JobType        = jobType;

            this.igp_topology  = igp_topology;
            this.mpls_topology = mpls_topology;

            this.JobResults = new List <CICDJobResult>();

            this.Worker                     = new BackgroundWorker();
            this.Worker.DoWork             += Worker_DoWork;
            this.Worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
        }
Beispiel #6
0
        public static CICDJob Deploy(string repo_url, string user, string password, Topology.IGP.Topology igp_topology, Topology.MPLS.Topology mpls_topology)
        {
            CICDJob newJob = new CICDJob(repo_url, user, password, JobType.Deploy, igp_topology, mpls_topology);

            // Update intent jobs concurrent dict
            newJob.OnJobCompletedCallback += (CICDJob cicdJob) => {
                foreach (var result in cicdJob.JobResults)
                {
                    if (result.IntentJob != null)
                    {
                        intent_jobs.AddOrUpdate(result.IntentJob.FileName, result.IntentJob, (k, v) => result.IntentJob);

                        IntentJobs.Set(intent_jobs.Count);
                    }
                }
            };

            cicd_jobs.TryAdd(newJob.Id, newJob);

            return(newJob);
        }
        public void LoadIGPTopology(Topology.IGP.Topology topology)
        {
            topology.Clear();

            foreach (var record in GetIGPTopology())
            {
                var path = record.Values["p"].As <IPath>();

                Dictionary <long, string> nodeDatabaseIds = new Dictionary <long, string>();
                Dictionary <long, bool>   pseudonodes     = new Dictionary <long, bool>();

                foreach (var node in path.Nodes)
                {
                    string igpRouterIdentifier = TryGetNodePropertyAsString(node, "IGP_Router_Identifier");

                    if (!string.IsNullOrWhiteSpace(igpRouterIdentifier))
                    {
                        nodeDatabaseIds.Add(node.Id, igpRouterIdentifier);

                        Topology.Node.Node n = new Topology.Node.Node()
                        {
                            IgpRouterIdentifier = igpRouterIdentifier,
                            Psn = TryGetNodeProperty <int>(node, "psn"),
                            IPv4RouterIdentifier = TryGetNodePropertyAsString(node, "IPv4_Router_Identifier"),
                            NodeName             = TryGetNodePropertyAsString(node, "Node_Name"),
                            FirstSeen            = TryGetNodeProperty <long>(node, "First_Seen"),
                            LastEvent            = TryGetNodeProperty <long>(node, "Last_Event"),
                            OperationalStatus    = true
                        };

                        if (Regex.IsMatch(igpRouterIdentifier, @"^\d{12}$") && n.Psn == 0)
                        {
                            n.IsPseudonode = false;
                            n.NodeCost     = 1;

                            pseudonodes.Add(node.Id, n.IsPseudonode);
                        }
                        else
                        {
                            if (Regex.IsMatch(igpRouterIdentifier, @"^\d{12}\d+$") && n.Psn != 0)
                            {
                                n.IsPseudonode = true;
                                n.NodeCost     = 0;

                                pseudonodes.Add(node.Id, n.IsPseudonode);
                            }
                        }

                        topology.Update(n);
                    }
                }

                foreach (var link in path.Relationships)
                {
                    Topology.IGP.Link.Link l = new Topology.IGP.Link.Link()
                    {
                        SourceNode                     = nodeDatabaseIds[link.StartNodeId],
                        TargetNode                     = nodeDatabaseIds[link.EndNodeId],
                        Asn                            = TryGetRelProperty <long>(link, "asn"),
                        MaximumLinkBandwidth           = TryGetRelProperty <double>(link, "Maximum_Link_Bandwidth"),
                        MaximumReservableLinkBandwidth = TryGetRelProperty <double>(link, "Maximum_Reservable_Bandwidth"),
                        UnreservedBandwidth            = TryGetRelPropertyAsArray <double>(link, "Unreserved_Bandwidth"),
                        Rtt                            = TryGetRelProperty <long>(link, "rtt"),
                        IPv4InterfaceAddress           = TryGetRelPropertyAsString(link, "IPv4_Interface_Address"),
                        SharedRiskLinkGroups           = TryGetRelPropertyAsArray <long>(link, "Shared_Risk_Link_Groups"),
                        FirstSeen                      = TryGetRelProperty <long>(link, "First_Seen"),
                        LastEvent                      = TryGetRelProperty <long>(link, "Last_Event"),
                        OperationalStatus              = true
                    };

                    if (pseudonodes[link.StartNodeId] || pseudonodes[link.EndNodeId])
                    {
                        l.LinkCost = 0.5;
                    }
                    else
                    {
                        l.LinkCost = 1;
                    }

                    topology.Update(l);
                }
            }
        }
        public static void IntentProcessor(object result, Topology.MPLS.Topology mpls_topology, Topology.IGP.Topology igp_topology,
                                           string controller_uri, string controller_username, string controller_password,
                                           string ansible_tower_uri, string ansible_tower_username, string ansible_tower_password)
        {
            if (result != null)
            {
                if (result.GetType() == typeof(Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath))
                {
                    Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath hlsp =
                        (Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath)result;

                    HLSP_Processor(
                        hlsp,
                        igp_topology, mpls_topology,
                        controller_uri, controller_username, controller_password,
                        ansible_tower_uri, ansible_tower_username, ansible_tower_password
                        );
                }
                else
                {
                    if (result.GetType() == typeof(List <Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath>))
                    {
                        List <Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath> hlsps =
                            (List <Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath>)result;

                        HLSP_Processor(
                            hlsps,
                            igp_topology, mpls_topology,
                            controller_uri, controller_username, controller_password,
                            ansible_tower_uri, ansible_tower_username, ansible_tower_password
                            );
                    }
                }
            }
        }
        private static void HLSP_Processor(
            List <Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath> hlsps,
            Topology.IGP.Topology igp_topology, Topology.MPLS.Topology mpls_topology,
            string controller_uri, string controller_username, string controller_password,
            string ansible_tower_uri, string ansible_tower_username, string ansible_tower_password)
        {
            bool allSameAnsibleTowerHost = !hlsps
                                           .Select(h => new { h.AnsibleTowerHost, h.AnsibleTowerJobTemplateId, h.Configure, h.UpdateConfiguration, h.Delete })
                                           .Distinct().Skip(1)
                                           .Any();

            if (allSameAnsibleTowerHost && hlsps.First().Configure&& hlsps.First().UpdateConfiguration)
            {
                // Ansible Tower Client
                Ansible.TowerClient tc = new Ansible.TowerClient(ansible_tower_uri, ansible_tower_username, ansible_tower_password);

                dynamic payload = new ExpandoObject();
                payload.AnsibleTowerHost = hlsps.First().AnsibleTowerHost;
                payload.HierarchicalLabelSwitchedPaths = hlsps;

                var jobId = tc.LaunchJob(hlsps.First().AnsibleTowerJobTemplateId, payload, hlsps.First().AnsibleTowerHost);

                if (jobId != -1)
                {
                    // Check if job is completed, max 90 times * 10 seconds = 15 min
                    Console.WriteLine("Ansible Tower checking for job {0}.", jobId);
                    var jobCompleted = tc.CheckJobCompleted(jobId);

                    for (int i = 0; i < 90; i++)
                    {
                        Console.WriteLine("Ansible Tower checking for job {0}.", jobId);
                        jobCompleted = tc.CheckJobCompleted(jobId);

                        if (jobCompleted)
                        {
                            Console.WriteLine("Ansible Tower job {0} completed.", jobId);

                            if (tc.CheckJobSuccessful(jobId))
                            {
                                Console.WriteLine("Ansible Tower job {0} successful.", jobId);

                                if (!hlsps.First().Delete)
                                {
                                    // Update paths through SDN controller

                                    Controllers.OpenDayLight.Nitrogen.ODLClient nitrogen =
                                        new Controllers.OpenDayLight.Nitrogen.ODLClient(controller_uri, controller_username, controller_password);

                                    foreach (var hlsp in hlsps)
                                    {
                                        foreach (var lsp in hlsp.Children)
                                        {
                                            if (lsp.Optimise)
                                            {
                                                nitrogen.UpdateLabelSwitchedPath(lsp);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("Ansible Tower job " + jobId + " failed.");
                            }

                            break;
                        }

                        System.Threading.Thread.Sleep(1000 * 10);
                    }

                    if (!jobCompleted)
                    {
                        Console.WriteLine("Timed out checking for Ansible Tower job " + jobId + ". Please check Ansible Tower logs.");
                    }
                }
                else
                {
                    Console.WriteLine("Unable to start Ansible Tower job.");
                }
            }
            else
            {
                foreach (var hlsp in hlsps)
                {
                    HLSP_Processor(
                        hlsp,
                        igp_topology, mpls_topology,
                        controller_uri, controller_username, controller_password,
                        ansible_tower_uri, ansible_tower_username, ansible_tower_password
                        );
                }
            }
        }
        private static void HLSP_Processor(
            Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath hlsp,
            Topology.IGP.Topology igp_topology, Topology.MPLS.Topology mpls_topology,
            string controller_uri, string controller_username, string controller_password,
            string ansible_tower_uri, string ansible_tower_username, string ansible_tower_password)
        {
            if (string.IsNullOrWhiteSpace(hlsp.PCC))
            {
                hlsp.PCC = hlsp.IPv4TunnelSenderAddress;
            }
            if (string.IsNullOrWhiteSpace(hlsp.AnsibleTowerHost))
            {
                hlsp.AnsibleTowerHost = hlsp.PCC;
            }

            // Check if HLSP needs to be removed from configuration
            if (!hlsp.Delete)
            {
                // SDN Controller API Client
                Controllers.OpenDayLight.Nitrogen.ODLClient nitrogen = new Controllers.OpenDayLight.Nitrogen.ODLClient(controller_uri, controller_username, controller_password);


                // Check if HLSP does not exist or is marked as requiring a config update and launch Ansible Tower job to deploy (or update) base HLSP (including children)
                if ((mpls_topology.HierarchicalLabelSwitchedPaths.Where(h => h.SymbolicPathName == hlsp.SymbolicPathName).Count() == 0 || hlsp.UpdateConfiguration) && hlsp.Configure)
                {
                    // Ansible Tower Client
                    Ansible.TowerClient tc = new Ansible.TowerClient(ansible_tower_uri, ansible_tower_username, ansible_tower_password);

                    var hlsps = new List <Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath>();
                    hlsps.Add(hlsp);

                    dynamic payload = new ExpandoObject();
                    payload.AnsibleTowerHost = hlsp.AnsibleTowerHost;
                    payload.HierarchicalLabelSwitchedPaths = hlsps;

                    var jobId = tc.LaunchJob(hlsp.AnsibleTowerJobTemplateId, payload, hlsp.AnsibleTowerHost);

                    if (jobId != -1)
                    {
                        // Check if job is completed, max 60 times * 5 seconds = 5 min
                        Console.WriteLine("Ansible Tower checking for job {0}.", jobId);
                        var jobCompleted = tc.CheckJobCompleted(jobId);

                        for (int i = 0; i < 60; i++)
                        {
                            Console.WriteLine("Ansible Tower checking for job {0}.", jobId);
                            jobCompleted = tc.CheckJobCompleted(jobId);

                            if (jobCompleted)
                            {
                                Console.WriteLine("Ansible Tower job {0} completed.", jobId);

                                if (tc.CheckJobSuccessful(jobId))
                                {
                                    Console.WriteLine("Ansible Tower job {0} successful.", jobId);

                                    // Update paths through SDN controller
                                    foreach (var lsp in hlsp.Children)
                                    {
                                        if (lsp.Optimise)
                                        {
                                            nitrogen.UpdateLabelSwitchedPath(lsp);
                                        }
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Ansible Tower job " + jobId + " failed.");
                                }

                                break;
                            }

                            System.Threading.Thread.Sleep(1000 * 5);
                        }

                        if (!jobCompleted)
                        {
                            Console.WriteLine("Timed out checking for Ansible Tower job " + jobId + ". Please check Ansible Tower logs.");
                        }
                    }
                    else
                    {
                        Console.WriteLine("Unable to start Ansible Tower job.");
                    }
                }
                else
                {
                    // Update paths through SDN controller
                    foreach (var lsp in hlsp.Children)
                    {
                        if (lsp.Optimise)
                        {
                            nitrogen.UpdateLabelSwitchedPath(lsp);
                        }
                    }
                }
            }
            else
            {
                if (hlsp.Configure)
                {
                    // Ansible Tower Client
                    Ansible.TowerClient tc = new Ansible.TowerClient(ansible_tower_uri, ansible_tower_username, ansible_tower_password);

                    var hlsps = new List <Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath>();
                    hlsps.Add(hlsp);

                    dynamic payload = new ExpandoObject();
                    payload.AnsibleTowerHost = hlsp.AnsibleTowerHost;
                    payload.HierarchicalLabelSwitchedPaths = hlsps;

                    var jobId = tc.LaunchJob(hlsp.AnsibleTowerJobTemplateId, payload, hlsp.AnsibleTowerHost);

                    if (jobId != -1)
                    {
                        // Check if job is completed, max 60 times * 5 seconds = 5 min
                        Console.WriteLine("Ansible Tower checking for job {0}.", jobId);
                        var jobCompleted = tc.CheckJobCompleted(jobId);

                        for (int i = 0; i < 60; i++)
                        {
                            Console.WriteLine("Ansible Tower checking for job {0}.", jobId);
                            jobCompleted = tc.CheckJobCompleted(jobId);

                            if (jobCompleted)
                            {
                                Console.WriteLine("Ansible Tower job {0} completed.", jobId);

                                if (tc.CheckJobSuccessful(jobId))
                                {
                                    Console.WriteLine("Ansible Tower job {0} successful.", jobId);
                                }
                                else
                                {
                                    Console.WriteLine("Ansible Tower job " + jobId + " failed.");
                                }

                                break;
                            }

                            System.Threading.Thread.Sleep(1000 * 5);
                        }

                        if (!jobCompleted)
                        {
                            Console.WriteLine("Timed out checking for Ansible Tower job " + jobId + ". Please check Ansible Tower logs.");
                        }
                    }
                    else
                    {
                        Console.WriteLine("Unable to start Ansible Tower job.");
                    }
                }
            }
        }
Beispiel #11
0
        // Job Type: Test
        public CICDJobResult(CompilerResults compilerResults, JobType jobType,
                             Topology.IGP.Topology igp_topology, Topology.MPLS.Topology mpls_topology, string fileName)
        {
            switch (jobType)
            {
            case JobType.Build:
                throw new Exception("JobType.Build: Incorrect number of parameters.");

            case JobType.Test:
                this.JobType        = jobType;
                this.CompilerErrors = compilerResults.Errors;
                this.FileName       = fileName;


                if (compilerResults.Errors.Count > 0)
                {
                    this.Success = false;
                }
                else
                {
                    try
                    {
                        var      tempType   = compilerResults.CompiledAssembly.GetType("ShiftPolicy");
                        object[] parameters = { igp_topology, mpls_topology, new yggdrasil2.PathComputation.PathComputation.YggdrasilNM2() };

                        #region Mandatory Properties
                        bool     enabled     = (bool)tempType.GetProperty("Enabled").GetGetMethod().Invoke(null, null);
                        int      period      = (int)tempType.GetProperty("Period").GetGetMethod().Invoke(null, null);
                        DateTime validBefore = (DateTime)tempType.GetProperty("ValidBefore").GetGetMethod().Invoke(null, null);

                        List <Topology.Node.Node> iterateNodes = (List <Topology.Node.Node>)tempType.GetMethod("IterateNodes").Invoke(null, new object[] { igp_topology });
                        #endregion

                        if (enabled && validBefore > DateTime.Now)
                        {
                            var intentTestResult = tempType.GetMethod("Test").Invoke(null, parameters);

                            this.IntentTesterResults = ((Intent.IntentTester)intentTestResult).TestResults;

                            if (((Intent.IntentTester)intentTestResult).TestResults.Errors.Count > 0)
                            {
                                this.Success = false;
                            }
                            else
                            {
                                this.Success = true;
                            }
                        }
                        else
                        {
                            this.Success = true;     // true = skip
                        }
                    }
                    catch (Exception ex)
                    {
                        // Console.WriteLine(ex.Message + " at " + MethodBase.GetCurrentMethod().Name);
                        this.Success = false;
                        this.LastExceptionMessage = ex.Message;
                    }
                }
                break;

            case JobType.Deploy:
                throw new Exception("JobType.Deploy: Incorrect number of parameters.");

            default:
                break;
            }
        }
Beispiel #12
0
        // Job Type: Deploy
        public CICDJobResult(CompilerResults compilerResults, JobType jobType, Topology.IGP.Topology igp_topology, string fileName)
        {
            switch (jobType)
            {
            case JobType.Build:
                throw new Exception("JobType.Build: Incorrect number of parameters.");

            case JobType.Test:
                throw new Exception("JobType.Test: Incorrect number of parameters.");

            case JobType.Deploy:
                this.JobType        = jobType;
                this.CompilerErrors = compilerResults.Errors;
                this.FileName       = fileName;

                if (compilerResults.Errors.Count > 0)
                {
                    this.Success = false;
                    break;
                }
                else
                {
                    try
                    {
                        var tempType = compilerResults.CompiledAssembly.GetType("ShiftPolicy");

                        #region Mandatory Properties
                        bool     enabled     = (bool)tempType.GetProperty("Enabled").GetGetMethod().Invoke(null, null);
                        int      period      = (int)tempType.GetProperty("Period").GetGetMethod().Invoke(null, null);
                        DateTime validBefore = (DateTime)tempType.GetProperty("ValidBefore").GetGetMethod().Invoke(null, null);

                        List <Topology.Node.Node> iterateNodes = (List <Topology.Node.Node>)tempType.GetMethod("IterateNodes").Invoke(null, new object[] { igp_topology });
                        #endregion

                        bool requiresIteration = false;

                        if (iterateNodes.Count > 0)
                        {
                            requiresIteration = true;
                        }

                        if (enabled && validBefore > DateTime.Now)
                        {
                            this.IntentJob = new IntentJob(
                                fileName: fileName,
                                intentCode: File.ReadAllText(fileName),
                                period: period,
                                validBefore: validBefore,
                                requiresIteration: requiresIteration
                                );
                        }
                    }
                    catch (Exception ex)
                    {
                        // Console.WriteLine(ex.Message + " at " + MethodBase.GetCurrentMethod().Name);
                        this.Success = false;
                        this.LastExceptionMessage = ex.Message;
                    }

                    this.Success = true;
                }
                break;

            default:
                break;
            }
        }
Beispiel #13
0
        public static void ValidatePathsUsingDijkstra(Topology.IGP.Topology igp_topology, Topology.MPLS.HierarchicalLabelSwitchedPath.HierarchicalLabelSwitchedPath hlsp)
        {
            Console.WriteLine("\n====Validating Paths====\n");

            List <yggdrasil2.Topology.Node.Node>     nodes_copy = igp_topology.Nodes.DeepClone();
            List <yggdrasil2.Topology.IGP.Link.Link> links_copy = igp_topology.Links.DeepClone();

            BidirectionalGraph <string, TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link> > graph =
                new BidirectionalGraph <string, TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link> >();

            Dictionary <TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link>, double> cost =
                new Dictionary <TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link>, double>();


            var start = nodes_copy.Where(n => n.IPv4RouterIdentifier == hlsp.IPv4TunnelSenderAddress).SingleOrDefault();
            var end   = nodes_copy.Where(n => n.IPv4RouterIdentifier == hlsp.IPv4TunnelEndpointAddress).SingleOrDefault();

            if (start != null && end != null)
            {
                foreach (var lsp in hlsp.Children)
                {
                    graph.Clear();

                    foreach (var node in nodes_copy)
                    {
                        graph.AddVertex(node.Id);
                    }

                    if (!start.IsPseudonode)  // it will never be a pseudonode, get rid of this
                    {
                        var nodeLinks = links_copy.Where(l => l.SourceNode == start.Id).ToList();

                        foreach (var l in nodeLinks)
                        {
                            if (!graph.ContainsEdge(l.SourceNode, l.TargetNode))
                            {
                                if (l.OperationalStatus)
                                {
                                    var forwardEdge = new TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link>(l.SourceNode, l.TargetNode, l);
                                    graph.AddEdge(forwardEdge);
                                    cost.Add(forwardEdge, 1);
                                }
                            }
                        }
                    }

                    foreach (var hop in lsp.ComputedExplicitRouteObject)
                    {
                        var link = links_copy.Where(l => l.IPv4InterfaceAddress == hop).SingleOrDefault();

                        if (link != null)
                        {
                            if (!graph.ContainsEdge(link.SourceNode, link.TargetNode))
                            {
                                if (link.OperationalStatus)
                                {
                                    var backwardEdge = new TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link>(link.TargetNode, link.SourceNode, link);
                                    graph.AddEdge(backwardEdge);
                                    cost.Add(backwardEdge, 1);
                                }

                                //var srcNode = nodes_copy.Where(n => n.IgpRouterIdentifier == link.SourceNode).SingleOrDefault();
                                var dstNode = nodes_copy.Where(n => n.IgpRouterIdentifier == link.TargetNode).SingleOrDefault();

                                //if (srcNode != null)
                                //{

                                //    if (srcNode.IsPseudonode)
                                //    {
                                //        var nodeLinks = links_copy.Where(l => l.TargetNode == srcNode.Id).ToList();

                                //        foreach (var l in nodeLinks)
                                //        {

                                //            if (!graph.ContainsEdge(l.SourceNode, l.TargetNode))
                                //            {
                                //                if (l.OperationalStatus)
                                //                {
                                //                    var forwardEdge = new TaggedEdge<string, yggdrasil2.Topology.IGP.Link.Link>(l.SourceNode, l.TargetNode, l);
                                //                    graph.AddEdge(forwardEdge);
                                //                    cost.Add(forwardEdge, 1);
                                //                }
                                //            }
                                //        }
                                //    }

                                //}

                                if (dstNode != null)
                                {
                                    if (dstNode.IsPseudonode)
                                    {
                                        var nodeLinks = links_copy.Where(l => l.TargetNode == dstNode.Id).ToList();

                                        foreach (var l in nodeLinks)
                                        {
                                            if (!graph.ContainsEdge(l.SourceNode, l.TargetNode))
                                            {
                                                if (l.OperationalStatus)
                                                {
                                                    var forwardEdge = new TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link>(l.SourceNode, l.TargetNode, l);
                                                    graph.AddEdge(forwardEdge);
                                                    cost.Add(forwardEdge, 1);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    DijkstraShortestPathAlgorithm <string, TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link> > dijkstra =
                        new DijkstraShortestPathAlgorithm <string, TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link> >(graph,
                                                                                                                            AlgorithmExtensions.GetIndexer <TaggedEdge <string, yggdrasil2.Topology.IGP.Link.Link>, double>(cost));

                    dijkstra.Compute(start.Id);

                    if (dijkstra.Distances.ContainsKey(end.Id) && dijkstra.Distances[end.Id] != double.MaxValue)
                    {
                        lsp.Feasible = true;
                        Console.WriteLine("Path {0} is \u001b[32mFEASIBLE\u001b[0m.\n\t{1} is REACHABLE from {2} in {3} hops (includes pseudonodes).",
                                          lsp.SymbolicPathName, lsp.IPv4TunnelEndpointAddress, lsp.IPv4TunnelSenderAddress, dijkstra.Distances[end.Id]);
                    }
                    else
                    {
                        lsp.Feasible = false;
                        Console.WriteLine("Path {0} is \u001b[31mNOT FEASIBLE\u001b[0m.\n\t{1} is UREACHABLE from {2}.",
                                          lsp.SymbolicPathName, lsp.IPv4TunnelEndpointAddress, lsp.IPv4TunnelSenderAddress);
                    }
                }
            }
        }
        static void Main(string[] args)
        {
            #region SHIFT YGGRDASIL2

            igp_topology  = new Topology.IGP.Topology();
            mpls_topology = new Topology.MPLS.Topology();

            ConcurrentQueue <JObject> igp_topology_changes_queue = new ConcurrentQueue <JObject>(); // IGP Topology Buffer
            bool igp_topology_task_enabled = false;

            ConcurrentQueue <JObject> mpls_topology_changes_queue = new ConcurrentQueue <JObject>(); // MPLS Topology Buffer
            bool mpls_topology_task_enabled = false;

            // Messaging
            Messaging.ControlQueue cq = new Messaging.ControlQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.ControlQueueRoutingKey
                );

            Messaging.IGP.TopologyQueue tq_igp = new Messaging.IGP.TopologyQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.IGPTopologyQueueRoutingKey
                );
            Messaging.MPLS.TopologyQueue tq_mpls = new Messaging.MPLS.TopologyQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.MPLSTopologyQueueRoutingKey
                );

            Messaging.PerformanceQueue pq = new Messaging.PerformanceQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.PerformanceQueueRoutingKey
                );
            Messaging.NodePCCQueue nq = new Messaging.NodePCCQueue(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.NodePCCQueueRoutingKey
                );

            Messaging.IntentQueueConsumer intentQueueConsumer = new Messaging.IntentQueueConsumer(
                brokerHostname: config.MessageBrokerHostname,
                brokerPort: config.MessageBrokerPort,
                brokerUsername: config.MessageBrokerUsername,
                brokerPassword: config.MessageBrokerPassword,
                routingKey: config.IntentQueueRoutingKey
                );
            #endregion

            #region SHIFT BACKEND CONNECTION

            // IGP Topology Queue Task
            var igp_topology_queue_task = new Task(() =>
            {
                while (igp_topology_task_enabled)
                {
                    while (!igp_topology_changes_queue.IsEmpty)
                    {
                        if (igp_topology_changes_queue.TryDequeue(out JObject data))
                        {
                            // Console.WriteLine("Topology Change: " + data);
                            igp_topology.Update(data);
                        }
                    }

                    Thread.Sleep(10);
                }
            }, TaskCreationOptions.LongRunning);

            // MPLS Topology Queue Task
            var mpls_topology_queue_task = new Task(() =>
            {
                while (mpls_topology_task_enabled)
                {
                    while (!mpls_topology_changes_queue.IsEmpty)
                    {
                        if (mpls_topology_changes_queue.TryDequeue(out JObject data))
                        {
                            // Console.WriteLine("Topology Change: " + data);
                            mpls_topology.Update(data);
                        }
                    }

                    Thread.Sleep(10);
                }
            }, TaskCreationOptions.LongRunning);

            // Control Queue Event Setup
            cq.OnStartCallback += (routing_key) =>
            {
                // IGP Topology Queue
                tq_igp.RoutingKey = routing_key;
                tq_igp.Connect();

                // MPLS Topology Queue
                tq_mpls.Connect();

                // Performance Queue
                pq.Connect();

                // Node PCC Queue
                nq.Connect();

                // Setup Topology Events
                igp_topology.OnNodeUpdateCallback += Igp_topology_OnNodeUpdateCallback;
                igp_topology.OnLinkUpdateCallback += Igp_topology_OnLinkUpdateCallback;
                igp_topology.OnLinkUpCallback     += Igp_topology_OnLinkUpCallback;
                igp_topology.OnLinkDownCallback   += Igp_topology_OnLinkDownCallback;

                // Load Topology
                data.Neo4J Neo4J = new data.Neo4J
                {
                    Neo4J_URI      = config.Neo4J_URI,
                    Neo4J_User     = config.Neo4J_User,
                    Neo4J_Password = config.Neo4J_Password
                };

                Neo4J.LoadIGPTopology(igp_topology);
                mpls_topology = Neo4J.LoadMPLSTopology();

                // Start Processing IGP Topology Changes Queue
                igp_topology_task_enabled = true;
                igp_topology_queue_task.Start();

                // Start Processing MPLS Topology Changes Queue
                mpls_topology_task_enabled = true;
                mpls_topology_queue_task.Start();

                // Connect Intent Queue Consumer
                intentQueueConsumer.Connect();
            };

            cq.OnTopologyQueueChangeCallback += (routing_key) =>
            {
                // Disconnect Intent Queue Cosumer
                intentQueueConsumer.Disconnect();

                // Stop Processing Topology Changes Queue
                igp_topology_task_enabled = false;
                while (igp_topology_queue_task.Status == TaskStatus.Running)
                {
                    Thread.Sleep(100);
                }

                // IGP Topology Queue
                tq_igp.RoutingKey = routing_key;
                tq_igp.Connect();

                // Setup Topology Events
                igp_topology.OnNodeUpdateCallback += Igp_topology_OnNodeUpdateCallback;
                igp_topology.OnLinkUpdateCallback += Igp_topology_OnLinkUpdateCallback;
                igp_topology.OnLinkUpCallback     += Igp_topology_OnLinkUpCallback;
                igp_topology.OnLinkDownCallback   += Igp_topology_OnLinkDownCallback;

                // Load Topology
                data.Neo4J Neo4J = new data.Neo4J
                {
                    Neo4J_URI      = config.Neo4J_URI,
                    Neo4J_User     = config.Neo4J_User,
                    Neo4J_Password = config.Neo4J_Password
                };

                Neo4J.LoadIGPTopology(igp_topology);
                mpls_topology = Neo4J.LoadMPLSTopology();

                // Start Processing Topology Changes Queue
                igp_topology_task_enabled = true;
                igp_topology_queue_task.Start();

                // Connect Intent Queue Consumer
                intentQueueConsumer.Connect();
            };

            // IGP Topology Queue Event Setup
            tq_igp.OnTopologyChangeCallback += (data) =>
            {
                // Enqueue Topology Change
                igp_topology_changes_queue.Enqueue(data);
            };

            // MPLS Topology Queue Event Setup
            tq_mpls.OnTopologyChangeCallback += (data) =>
            {
                // Enqueue Topology Change
                mpls_topology_changes_queue.Enqueue(data);
            };

            // Performance Queue Event Setup
            pq.OnPerformanceUpdateCallback += (data) =>
            {
                //Console.WriteLine("Performance Update: " + data);

                igp_topology.Update(data);
            };

            // Node PCC Queue Event Setup
            nq.OnNodePCCUpdateCallback += (data) =>
            {
                // Console.WriteLine("Node PCC Update: " + data);

                igp_topology.Update(data);
            };

            // Intent Queue Event Setup
            intentQueueConsumer.OnIntentJobCallback += IntentQueueConsumer_OnIntentJobCallback;

            // Control Queue Connect
            cq.Connect();

            #endregion

            Console.WriteLine("Runner Started.");

            string cmd = Console.ReadLine();

            while (cmd != "exit")
            {
                Console.WriteLine("Command not found.");
                Console.Write("> ");
                cmd = Console.ReadLine();
            }

            #region SHIFT BACKEND DISCONNECT
            cq.Disconnect();

            tq_igp.Disconnect();
            tq_mpls.Disconnect();

            pq.Disconnect();
            nq.Disconnect();

            intentQueueConsumer.Disconnect();
            #endregion
        }