diff --git a/webroot/monitor/infra/underlay/ui/js/flow_queries.js b/webroot/monitor/infra/underlay/ui/js/flow_queries.js index 1da5d700b..b101d8553 100644 --- a/webroot/monitor/infra/underlay/ui/js/flow_queries.js +++ b/webroot/monitor/infra/underlay/ui/js/flow_queries.js @@ -91,7 +91,7 @@ frQuery['columnDisplay'] = [ {select:"destip", display:{id:"destip", field:"destip", width:90, name:"Destination IP", groupable:true, formatter: function(r, c, v, cd, dc){ return (validateIPAddress(handleNull4Grid(dc['destip'])) == true ? handleNull4Grid(dc['destip']) : noDataStr)}}}, {select:"dport", display:{id:"dport", field:"dport", width:70, name:"Destination Port", groupable:true, formatter: function(r, c, v, cd, dc){ return handleNull4Grid(dc.dport);}}}, {select:"agg-bytes", display:{id:'agg-bytes', field:'agg-bytes', width:120, name:"Bytes/Packets", groupable:false,formatter: function(r, c, v, cd, dc) {return contrail.format("{0}/{1}",formatBytes(dc['agg-bytes'],'-'),dc['agg-packets']);}}}, -]; + ]; frQuery['defaultColumns'] = ['sourcevn', 'sourceip', 'sport', 'destvn', 'destip', 'dport', 'protocol', 'direction_ing']; fsQuery['defaultColumns'] = ['flow_class_id', 'direction_ing']; @@ -803,7 +803,7 @@ function viewFRQueryResults(dataItem, params) { loadFlowResultsForUnderlay(options, reqQueryObj, queryColumnDisplay); }; -function loadFlowResultsForUnderlay(options, reqQueryObj, columnDisplay, fcGridDisplay,reverseTraceFlow) { +function loadFlowResultsForUnderlay(options, reqQueryObj, columnDisplay, fcGridDisplay,traceFlow) { var grid = $('#' + options.elementId).data('contrailGrid'), url = "/api/admin/reports/query", btnId = options.btnId, @@ -879,6 +879,10 @@ function loadFlowResultsForUnderlay(options, reqQueryObj, columnDisplay, fcGridD type: 'status', iconClasses: '', text: 'Your query has been queued.' + },error: { + type: 'error', + iconClasses: 'icon-warning', + text: 'Error in fetching details' } } }, @@ -886,7 +890,7 @@ function loadFlowResultsForUnderlay(options, reqQueryObj, columnDisplay, fcGridD pager : { options : { pageSize : options.pageSize, - pageSizeSelect : [10, 50, 100, 200, 500 ] + pageSizeSelect : [10, 50, 100, 200 ] } } } @@ -900,42 +904,57 @@ function loadFlowResultsForUnderlay(options, reqQueryObj, columnDisplay, fcGridD ']; } else if(options.queryPrefix == 'fr'){ - var customControls = [ - '' - ]; - if(reverseTraceFlow == true){ - customControls = [ - '', - '', - ]; - } - gridConfig.header.customControls = customControls, gridConfig.body.options = { - checkboxSelectable: { - enableRowCheckbox: true, - onNothingChecked: function(e){ - $("#mapflow").attr('disabled','disabled'); - $("#traceFlowBtn").attr('disabled','disabled'); - $("#revTraceFlowBtn").attr('disabled','disabled'); - }, - onSomethingChecked: function(e){ - $("#mapflow").removeAttr('disabled'); - $("#traceFlowBtn").removeAttr('disabled'); - $("#revTraceFlowBtn").removeAttr('disabled'); - } - }, actionCell: [], lazyLoading:true, + actionCellPosition : 'start' + }; + if(getValueByJsonPath(globalObj['webServerInfo'],'disabledFeatures;disabled',[]).indexOf('mon_infra_underlay') == -1) { + if(traceFlow == true) { + gridConfig.body.options.actionCell.push({ + title:'TraceFlow', + iconClass: 'icon-contrail-trace-flow', + onClick: function(rowId,targetElement){ + if(typeof underlayRenderer === 'object') { + $("#"+options.elementId+" div.selected-slick-row").each(function(idx,obj){ + $(obj).removeClass('selected-slick-row'); + }); + $(targetElement).parent().parent().addClass('selected-slick-row'); + underlayRenderer.getView().doTraceFlow(rowId); + } + } + },{ + title:'Reverse TraceFlow', + iconClass: 'icon-contrail-reverse-flow', + onClick: function(rowId,targetElement){ + if(typeof underlayRenderer === 'object') { + $("#"+options.elementId+" div.selected-slick-row").each(function(idx,obj){ + $(obj).removeClass('selected-slick-row'); + }); + $(targetElement).parent().parent().addClass('selected-slick-row'); + underlayRenderer.getView().doReverseTraceFlow(rowId); + } + } + }); + } else { + gridConfig.body.options.actionCell.push({ + title: 'Show Underlay Paths', + iconClass: 'icon-contrail-trace-flow', + onClick: function(rowIndex,targetElement){ + var dataItem = $('#' + options.elementId).data('contrailGrid')._grid.getDataItem(rowIndex); + var startTime = $("#"+options.queryPrefix+"-results").data('startTimeUTC'); + var endTime = $("#"+options.queryPrefix+"-results").data('endTimeUTC'); + dataItem['startTime'] = startTime; + dataItem['endTime'] = endTime; + $("#fr-results div.selected-slick-row").each(function(idx,obj){ + $(obj).removeClass('selected-slick-row'); + }); + $(targetElement).parent().parent().addClass('selected-slick-row'); + showUnderlayPaths(dataItem); + } + }); + } }; - $("#mapflow").die('click').live('click',function(e){ - var startTime = $("#"+options.queryPrefix+"-results").data('startTimeUTC'); - var endTime = $("#"+options.queryPrefix+"-results").data('endTimeUTC'); - var checkedRows = $("#"+options.queryPrefix+"-results").data('contrailGrid').getCheckedRows(); - var dataItem = ifNull(checkedRows[0],{}); - dataItem['startTime'] = startTime; - dataItem['endTime'] = endTime; - showUnderlayPaths(dataItem); - }); } $("#" + options.elementId).contrailGrid(gridConfig); gridObject = $("#"+options.elementId).data('contrailGrid'); diff --git a/webroot/monitor/infra/underlay/ui/js/monitor_infra_underlay.js b/webroot/monitor/infra/underlay/ui/js/monitor_infra_underlay.js index c245be5db..0a452859f 100644 --- a/webroot/monitor/infra/underlay/ui/js/monitor_infra_underlay.js +++ b/webroot/monitor/infra/underlay/ui/js/monitor_infra_underlay.js @@ -453,7 +453,7 @@ underlayModel.prototype.destroy = function() { this.reset(); } -underlayModel.prototype.checkIPInVrouterList = function(data) { +underlayModel.prototype.checkIPInVrouterList = function (data) { var vRouterList = getValueByJsonPath(globalObj,'topologyResponse;vRouterList',[]); for(var i = 0; i < ifNull(vRouterList,[]).length; i++) { var vRouterData = vRouterList[i]; @@ -776,7 +776,7 @@ underlayView.prototype.createElementsFromAdjacencyList = function() { return; } } - } + } var parentNode = jsonPath(nodes, "$[?(@.name=='" + parentElementLabel + "')]"); if(false !== parentNode && parentNode.length === 1) { parentNode = parentNode[0]; @@ -790,7 +790,7 @@ underlayView.prototype.createElementsFromAdjacencyList = function() { } }); - _.each(adjacencyList, function(edges, parentElementLabel) { + _.each(adjacencyList, function(edges, parentElementLabel) { var parentNode = jsonPath(nodes, "$[?(@.name=='" + parentElementLabel + "')]"); if(false !== parentNode && parentNode.length === 1) { parentNode = parentNode[0]; @@ -1432,7 +1432,7 @@ underlayView.prototype.initGraphEvents = function() { paper.on('blank:pointerdblclick', function (evt, x, y) { evt.stopImmediatePropagation(); - _this.resetTopology(); + _this.resetTopology(false); }); paper.on("cell:pointerdblclick", function (cellView, evt, x, y) { @@ -1579,7 +1579,7 @@ underlayView.prototype.initGraphEvents = function() { } var vnNameArr = ifNull(vnList[0].split(':'),[]); var networkName = ifNull(vnNameArr[2],'-'); - var projectName = '('+ifNull(vnNameArr[2],'-')+')'; + var projectName = '('+ifNull(vnNameArr[1],'-')+')'; srcVN += networkName +" "+ projectName; break; } @@ -2084,7 +2084,10 @@ underlayView.prototype.renderTracePath = function(options) { var name = $.grep(computeNodes,function(value,idx){ return (getValueByJsonPath(value,'more_attributes;VrouterAgent;self_ip_list;0','-') == dc['peer_vrouter']); }); - return contrail.format('{0} ({1})',getValueByJsonPath(name,'0;name','-'),dc['peer_vrouter']); + if(validateIPAddress(dc['peer_vrouter'])) + return contrail.format('{0} ({1})',getValueByJsonPath(name,'0;name','-'),dc['peer_vrouter']); + else + return '-'; } }, { @@ -2182,10 +2185,8 @@ underlayView.prototype.renderTracePath = function(options) { text : 'Flows' }, customControls: [ - '', - '', - '', - '', + '', + '', ], }, columnHeader : { @@ -2195,19 +2196,33 @@ underlayView.prototype.renderTracePath = function(options) { options : { forceFitColumns: true, sortable : false, - checkboxSelectable: { - enableRowCheckbox: true, - onNothingChecked: function(e){ - $("#mapflow").attr('disabled','disabled'); - $("#traceFlowBtn").attr('disabled','disabled'); - $("#revTraceFlowBtn").attr('disabled','disabled'); - }, - onSomethingChecked: function(e){ - $("#mapflow").removeAttr('disabled'); - $("#traceFlowBtn").removeAttr('disabled'); - $("#revTraceFlowBtn").removeAttr('disabled'); + actionCellPosition: 'start', + actionCell:[{ + title:'TraceFlow', + iconClass: 'icon-contrail-trace-flow', + onClick: function(rowId,targetElement){ + if(typeof underlayRenderer == 'object') { + $("#vrouterflows div.selected-slick-row").each(function(idx,obj){ + $(obj).removeClass('selected-slick-row'); + }); + $(targetElement).parent().parent().addClass('selected-slick-row'); + underlayRenderer.getView().doTraceFlow(rowId); + } } - }, + },{ + title:'Reverse TraceFlow', + iconClass: 'icon-contrail-reverse-flow', + onClick: function(rowId,targetElement){ + if(typeof underlayRenderer == 'object') { + $("#vrouterflows div.selected-slick-row").each(function(idx,obj){ + $(obj).removeClass('selected-slick-row'); + }); + $(targetElement).parent().parent().addClass('selected-slick-row'); + underlayRenderer.getView().doReverseTraceFlow(rowId); + } + } + } + ], }, dataSource : { remote: { @@ -2229,6 +2244,7 @@ underlayView.prototype.renderTracePath = function(options) { onDataBoundCB : function () { var gridObj = $("#vrouterflows").data('contrailGrid'); $("#vrouterflows").find('input.headerRowCheckbox').parent('span').remove(); + vrouterflowsGrid.removeGridMessage('loading'); if(gridObj != null) { var dataItems = gridObj._dataView.getItems(); var dataItemsLen = dataItems.length; @@ -2254,12 +2270,12 @@ underlayView.prototype.renderTracePath = function(options) { text: 'Error in getting Data.' } } - }, - footer : false + },footer:false }); var newAjaxConfig = {}; $("#btnNextFlows").click(function(){ if(flowKeyStack.length > 0 && flowKeyStack[flowKeyStack.length - 1] != null){ + vrouterflowsGrid.showGridMessage('loading'); nextClicked = true; newAjaxConfig = { url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(computeNodeInfo) @@ -2272,9 +2288,8 @@ underlayView.prototype.renderTracePath = function(options) { } }); $("#btnPrevFlows").click(function(){ - if(nextClicked) - flowKeyStack.pop(); - nextClicked = false; + flowKeyStack.pop(); + vrouterflowsGrid.showGridMessage('loading'); if(flowKeyStack.length > 0) { newAjaxConfig = { url: monitorInfraUrls['VROUTER_FLOWS'] + '?ip=' + getIPOrHostName(computeNodeInfo) @@ -2288,8 +2303,6 @@ underlayView.prototype.renderTracePath = function(options) { + '&introspectPort=' + computeNodeInfo['introspectPort'], type:'Get' }; - //Need to disable the prev button because flowKeystack < 1 which means first set of records call - $("#btnPrevFlows").attr('disabled','disabled'); } vrouterflowsGrid.setRemoteAjaxConfig(newAjaxConfig); reloadGrid(vrouterflowsGrid); @@ -2419,209 +2432,6 @@ underlayView.prototype.renderTracePath = function(options) { } } }); - - $("#traceFlowBtn").die('click').live('click',function(e){ - var flowGrid = $("#vrouterflows").data('contrailGrid'); - var checkedRows = flowGrid.getCheckedRows(); - var dataItem = ifNull(checkedRows[0],{}); - var item = tracePathDropdown.getSelectedData(); - var contextVrouterIp = ''; - try { - contextVrouterIp = item[0]['text'].split("(")[1].slice(0,-1); - }catch(err) { - } - /* - * For egress flows the source vm ip may not spawned in the same vrouter, - * so need to pick the peer_vrouter - */ - var postData = {},nwFqName = ''; - var postData = { - srcIP: dataItem['sourceip'] != null ? dataItem['sourceip'] : dataItem['sip'], - destIP: dataItem['destip'] != null ? dataItem['destip'] : dataItem['dip'], - srcPort: dataItem['sport'] != null ? dataItem['sport'] : dataItem['src_port'], - destPort: dataItem['dport'] != null ? dataItem['dport'] : dataItem['dst_port'], - srcVN: dataItem['src_vn'] != null ? dataItem['src_vn'] : dataItem['sourcevn'], - destVN: dataItem['dst_vn'] != null ? dataItem['dst_vn'] : dataItem['destvn'], - protocol: dataItem['protocol'], - maxAttempts: 3, - interval: 5, - }; - //We are sending the VrfId of the flow for trace router request, in some cases like egress flows, the Vrf Id is in context with the - //current Vrouter introspect but we are issuing the trace route request to other vrouter,which throws error to fix these cases - //resolveVrfId IP used. - if(dataItem['direction_ing'] == 1 || dataItem['direction'] == 'ingress') { - if($("#vrouterRadiobtn").is(':checked')) { - postData['nodeIP'] = contextVrouterIp; - postData['resolveVrfId'] = contextVrouterIp; - } else if($("#instRadiobtn").is(':checked')) { - if (dataItem['vrouter_ip'] != null) { - postData['nodeIP'] = dataItem['vrouter_ip']; - } else if (dataItem['vrouter'] != null){ - var vrouterDetails = underlayView.prototype.getvRouterVMDetails(dataItem['vrouter'],'name',VROUTER); - postData['nodeIP'] = getValueByJsonPath(vrouterDetails,'more_attributes;VrouterAgent;self_ip_list;0','-'); - } - } - if(dataItem['raw_json'] != null && dataItem['raw_json']['vrf'] != null) { - postData['vrfId'] = parseInt(dataItem['raw_json']['vrf']); - } - nwFqName = dataItem['sourcevn'] != null ? dataItem['sourcevn'] : dataItem['src_vn']; - } else if(dataItem['direction_ing'] == 0 || dataItem['direction'] == 'egress') { - if(dataItem['raw_json'] != null && dataItem['raw_json']['vrf'] != null) { - postData['vrfId'] = parseInt(dataItem['raw_json']['vrf']); - postData['resolveVrfId'] = contextVrouterIp; - } - postData['nodeIP'] = dataItem['other_vrouter_ip'] != null ? dataItem['other_vrouter_ip'] : dataItem['peer_vrouter']; - nwFqName = dataItem['sourcevn'] != null ? dataItem['sourcevn'] : dataItem['src_vn']; - } - if(typeof underlayRenderer === 'object' && !underlayRenderer.getModel().checkIPInVrouterList(postData)) { - showInfoWindow("Cannot Trace the path for the selected flow", "Info"); - return; - } - var progressBar = $("#network_topology").find('.topology-visualization-loading'); - $(progressBar).show(); - $(progressBar).css('margin-bottom',$(progressBar).parent().height()); - if (postData['vrfId'] != null) { - doTraceFlow(postData); - } else { - $.ajax({ - url:'api/tenant/networking/virtual-network/summary?fqNameRegExp='+nwFqName, - }).always(function(networkDetails){ - if(networkDetails['value']!= null && networkDetails['value'][0] != null && networkDetails['value'][0]['value'] != null) { - var vrfList = getValueByJsonPath(networkDetails,'value;0;value;UveVirtualNetworkConfig;routing_instance_list',[]); - if(vrfList[0] != null) - nwFqName += ":"+vrfList[0]; - } else - // if there is no vrf name in the response then just constructing it in general format - nwFqName += ":"+nwFqName.split(':')[2]; - postData['vrfName'] = nwFqName; - doTraceFlow(postData); - }); - } - - function doTraceFlow (postData) { - $.ajax({ - url:'/api/tenant/networking/trace-flow', - type:'POST', - timeout:5000, - data:{ - data: postData - } - }).done(function(response) { - if(typeof underlayRenderer === 'object') { - underlayRenderer.getModel().setFlowPath(response); - } - _this.highlightPath(response, {data: postData}); - }).fail(function(error,status) { - _this.resetTopology(false); - if(status == 'timeout') { - showInfoWindow('Timeout in fetching details','Error'); - } else if (status != 'success') { - showInfoWindow('Error in fetching details','Error'); - } - }).always(function(ajaxObj,status) { - $(progressBar).hide(); - }); - } - }); - $("#revTraceFlowBtn").die('click').live('click',function(e){ - var flowGrid = $("#vrouterflows").data('contrailGrid'); - var checkedRows = flowGrid.getCheckedRows(); - var dataItem = ifNull(checkedRows[0],{}),nwFqName = ''; - var item = tracePathDropdown.getSelectedData(); - var contextVrouterIp = ''; - try { - contextVrouterIp = item[0]['text'].split("(")[1].slice(0,-1); - }catch(err) { - } - /* - * For egress flows the source vm ip may not spawned in the same vrouter, - * so need to pick the peer_vrouter - */ - var postData = { - srcIP: dataItem['destip'] != null ? dataItem['destip'] : dataItem['dip'], - destIP: dataItem['sourceip'] != null ? dataItem['sourceip'] : dataItem['sip'], - srcPort: dataItem['dport'] != null ? dataItem['dport'] : dataItem['dst_port'], - destPort: dataItem['sport'] != null ? dataItem['sport'] : dataItem['src_port'], - srcVN: dataItem['src_vn'] != null ? dataItem['src_vn'] : dataItem['sourcevn'], - destVN: dataItem['dst_vn'] != null ? dataItem['dst_vn'] : dataItem['destvn'], - protocol: dataItem['protocol'], - maxAttempts: 3, - interval: 5, - }; - if(dataItem['direction_ing'] == 0 || dataItem['direction'] == 'egress') { - if($("#vrouterRadiobtn").is(':checked')) { - postData['nodeIP'] = contextVrouterIp; - postData['resolveVrfId'] = contextVrouterIp; - } else if($("#instRadiobtn").is(':checked')) { - if (dataItem['vrouter_ip'] != null) { - postData['nodeIP'] = dataItem['vrouter_ip']; - } else if (dataItem['vrouter'] != null){ - var vrouterDetails = underlayView.prototype.getvRouterVMDetails(dataItem['vrouter'],'name',VROUTER); - postData['nodeIP'] = getValueByJsonPath(vrouterDetails,'more_attributes;VrouterAgent;self_ip_list;0','-'); - } - } - nwFqName = dataItem['destvn'] != null ? dataItem['destvn'] : dataItem['dst_vn']; - if(dataItem['raw_json'] != null && dataItem['raw_json']['dest_vrf'] != null) { - postData['vrfId'] = parseInt(dataItem['raw_json']['dest_vrf']); - } - } else if(dataItem['direction_ing'] == 1 || dataItem['direction'] == 'ingress') { - postData['nodeIP'] = dataItem['other_vrouter_ip'] != null ? dataItem['other_vrouter_ip'] : dataItem['peer_vrouter']; - nwFqName = dataItem['destvn'] != null ? dataItem['destvn'] : dataItem['dst_vn']; - if(dataItem['raw_json'] != null && dataItem['raw_json']['dest_vrf'] != null) { - postData['vrfId'] = parseInt(dataItem['raw_json']['dest_vrf']); - postData['resolveVrfId'] = contextVrouterIp; - } - } - if(typeof underlayRenderer === 'object' && !underlayRenderer.getModel().checkIPInVrouterList(postData)) { - showInfoWindow("Cannot Trace the path for the selected flow", "Info"); - return; - } - var progressBar = $("#network_topology").find('.topology-visualization-loading'); - $(progressBar).show(); - $(progressBar).css('margin-bottom',$(progressBar).parent().height()); - if(postData['vrfId'] != null) { - doReverseFlow(postData); - } else { - $.ajax({ - url:'api/tenant/networking/virtual-network/summary?fqNameRegExp='+nwFqName, - }).always(function(networkDetails){ - if(networkDetails['value']!= null && networkDetails['value'][0] != null && networkDetails['value'][0]['value'] != null) { - var vrfList = getValueByJsonPath(networkDetails,'value;0;value;UveVirtualNetworkConfig;routing_instance_list',[]); - if(vrfList[0] != null) - nwFqName += ":"+vrfList[0]; - } else - // if there is no vrf name in the response then just constructing it in general format - nwFqName += ":"+nwFqName.split(':')[2]; - postData['vrfName'] = nwFqName; - doReverseFlow(postData); - }); - } - function doReverseFlow (postData) { - $.ajax({ - url:'/api/tenant/networking/trace-flow', - type:'POST', - timeout:5000, - data:{ - data: postData - } - }).done(function(response) { - if(typeof underlayRenderer === 'object') { - underlayRenderer.getModel().setFlowPath(response); - } - _this.highlightPath(response, {data: postData}); - }).fail(function(error,status) { - _this.resetTopology(false); - if(status == 'timeout') { - showInfoWindow('Timeout in fetching details','Error'); - } else if (status != 'success') { - showInfoWindow('Error in fetching details','Error'); - } - }).always(function(ajaxObj,status) { - $(progressBar).hide(); - }); - } - }); - function getInstFlowsUrl(name){ var req = {}; var ajaxData = { @@ -2656,6 +2466,167 @@ underlayView.prototype.renderTracePath = function(options) { return req; } } + +underlayView.prototype.doTraceFlow = function (rowId) { + var flowGrid = $("#vrouterflows").data('contrailGrid'); + var checkedRows = flowGrid.getCheckedRows(),tracePathDropdown = $("#tracePathDropdown").data('contrailDropdown');; + var dataItem = null; + if (rowId != null) { + dataItem = ifNull(flowGrid._grid.getDataItem(rowId),{}); + } else { + dataItem = ifNull(checkedRows[0],{}); + } + var item = tracePathDropdown.getSelectedData(); + var contextVrouterIp = ''; + try { + contextVrouterIp = item[0]['text'].split("(")[1].slice(0,-1); + }catch(err) { + } + /* + * For egress flows the source vm ip may not spawned in the same vrouter, + * so need to pick the peer_vrouter + */ + var postData = {},nwFqName = ''; + var postData = { + srcIP: dataItem['sourceip'] != null ? dataItem['sourceip'] : dataItem['sip'], + destIP: dataItem['destip'] != null ? dataItem['destip'] : dataItem['dip'], + srcPort: dataItem['sport'] != null ? dataItem['sport'] : dataItem['src_port'], + destPort: dataItem['dport'] != null ? dataItem['dport'] : dataItem['dst_port'], + srcVN: dataItem['src_vn'] != null ? dataItem['src_vn'] : dataItem['sourcevn'], + destVN: dataItem['dst_vn'] != null ? dataItem['dst_vn'] : dataItem['destvn'], + protocol: dataItem['protocol'], + maxAttempts: 3, + interval: 5, + }; + //We are sending the VrfId of the flow for trace router request, in some cases like egress flows, the Vrf Id is in context with the + //current Vrouter introspect but we are issuing the trace route request to other vrouter,which throws error to fix these cases + //resolveVrfId IP used. + if(dataItem['direction_ing'] == 1 || dataItem['direction'] == 'ingress') { + if($("#vrouterRadiobtn").is(':checked')) { + postData['nodeIP'] = contextVrouterIp; + postData['resolveVrfId'] = contextVrouterIp; + } else if($("#instRadiobtn").is(':checked')) { + if (dataItem['vrouter_ip'] != null) { + postData['nodeIP'] = dataItem['vrouter_ip']; + } else if (dataItem['vrouter'] != null){ + var vrouterDetails = underlayView.prototype.getvRouterVMDetails(dataItem['vrouter'],'name',VROUTER); + postData['nodeIP'] = getValueByJsonPath(vrouterDetails,'more_attributes;VrouterAgent;self_ip_list;0','-'); + } + } + if(dataItem['raw_json'] != null && dataItem['raw_json']['vrf'] != null) { + postData['vrfId'] = parseInt(dataItem['raw_json']['vrf']); + } + nwFqName = dataItem['sourcevn'] != null ? dataItem['sourcevn'] : dataItem['src_vn']; + } else if(dataItem['direction_ing'] == 0 || dataItem['direction'] == 'egress') { + if(dataItem['raw_json'] != null && dataItem['raw_json']['vrf'] != null) { + postData['vrfId'] = parseInt(dataItem['raw_json']['vrf']); + postData['resolveVrfId'] = contextVrouterIp; + } + postData['nodeIP'] = dataItem['other_vrouter_ip'] != null ? dataItem['other_vrouter_ip'] : dataItem['peer_vrouter']; + nwFqName = dataItem['sourcevn'] != null ? dataItem['sourcevn'] : dataItem['src_vn']; + } + if(typeof underlayRenderer === 'object' && !underlayRenderer.getModel().checkIPInVrouterList(postData)) { + showInfoWindow("Cannot Trace route for the selected flow", "Info"); + return; + } + if (postData['vrfId'] != null) { + doTraceFlowRequest(postData); + } else { + $.ajax({ + url:'api/tenant/networking/virtual-network/summary?fqNameRegExp='+nwFqName, + }).always(function(networkDetails){ + if(networkDetails['value']!= null && networkDetails['value'][0] != null && networkDetails['value'][0]['value'] != null) { + var vrfList = getValueByJsonPath(networkDetails,'value;0;value;UveVirtualNetworkConfig;routing_instance_list',[]); + if(vrfList[0] != null) + nwFqName += ":"+vrfList[0]; + } else + // if there is no vrf name in the response then just constructing it in general format + nwFqName += ":"+nwFqName.split(':')[2]; + postData['vrfName'] = nwFqName; + doTraceFlowRequest(postData); + }); + } +} + +underlayView.prototype.doReverseTraceFlow = function (rowId) { + + var flowGrid = $("#vrouterflows").data('contrailGrid'); + var checkedRows = flowGrid.getCheckedRows(),tracePathDropdown = $("#tracePathDropdown").data('contrailDropdown'); + var dataItem = null; + if (rowId != null) { + dataItem = ifNull(flowGrid._grid.getDataItem(rowId),{}); + } else { + dataItem = ifNull(checkedRows[0],{}); + } + var item = tracePathDropdown.getSelectedData(); + var contextVrouterIp = ''; + try { + contextVrouterIp = item[0]['text'].split("(")[1].slice(0,-1); + }catch(err) { + } + /* + * For egress flows the source vm ip may not spawned in the same vrouter, + * so need to pick the peer_vrouter + */ + var postData = { + srcIP: dataItem['destip'] != null ? dataItem['destip'] : dataItem['dip'], + destIP: dataItem['sourceip'] != null ? dataItem['sourceip'] : dataItem['sip'], + srcPort: dataItem['dport'] != null ? dataItem['dport'] : dataItem['dst_port'], + destPort: dataItem['sport'] != null ? dataItem['sport'] : dataItem['src_port'], + srcVN: dataItem['src_vn'] != null ? dataItem['src_vn'] : dataItem['sourcevn'], + destVN: dataItem['dst_vn'] != null ? dataItem['dst_vn'] : dataItem['destvn'], + protocol: dataItem['protocol'], + maxAttempts: 3, + interval: 5, + }; + if(dataItem['direction_ing'] == 0 || dataItem['direction'] == 'egress') { + if($("#vrouterRadiobtn").is(':checked')) { + postData['nodeIP'] = contextVrouterIp; + postData['resolveVrfId'] = contextVrouterIp; + } else if($("#instRadiobtn").is(':checked')) { + if (dataItem['vrouter_ip'] != null) { + postData['nodeIP'] = dataItem['vrouter_ip']; + } else if (dataItem['vrouter'] != null){ + var vrouterDetails = underlayView.prototype.getvRouterVMDetails(dataItem['vrouter'],'name',VROUTER); + postData['nodeIP'] = getValueByJsonPath(vrouterDetails,'more_attributes;VrouterAgent;self_ip_list;0','-'); + } + } + nwFqName = dataItem['destvn'] != null ? dataItem['destvn'] : dataItem['dst_vn']; + if(dataItem['raw_json'] != null && dataItem['raw_json']['dest_vrf'] != null) { + postData['vrfId'] = parseInt(dataItem['raw_json']['dest_vrf']); + } + } else if(dataItem['direction_ing'] == 1 || dataItem['direction'] == 'ingress') { + postData['nodeIP'] = dataItem['other_vrouter_ip'] != null ? dataItem['other_vrouter_ip'] : dataItem['peer_vrouter']; + nwFqName = dataItem['destvn'] != null ? dataItem['destvn'] : dataItem['dst_vn']; + if(dataItem['raw_json'] != null && dataItem['raw_json']['dest_vrf'] != null) { + postData['vrfId'] = parseInt(dataItem['raw_json']['dest_vrf']); + postData['resolveVrfId'] = contextVrouterIp; + } + } + if(typeof underlayRenderer === 'object' && !underlayRenderer.getModel().checkIPInVrouterList(postData)) { + showInfoWindow("Cannot Trace route for the selected flow", "Info"); + return; + } + if(postData['vrfId'] != null) { + doTraceFlowRequest(postData); + } else { + $.ajax({ + url:'api/tenant/networking/virtual-network/summary?fqNameRegExp='+nwFqName, + }).always(function(networkDetails){ + if(networkDetails['value']!= null && networkDetails['value'][0] != null && networkDetails['value'][0]['value'] != null) { + var vrfList = getValueByJsonPath(networkDetails,'value;0;value;UveVirtualNetworkConfig;routing_instance_list',[]); + if(vrfList[0] != null) + nwFqName += ":"+vrfList[0]; + } else + // if there is no vrf name in the response then just constructing it in general format + nwFqName += ":"+nwFqName.split(':')[2]; + postData['vrfName'] = nwFqName; + doTraceFlowRequest(postData); + }); + } + +} + /* * This is utility function which accepts value to compare and key to lookup * and type to check in globalObj and get the response where we lookup for the @@ -3390,4 +3361,44 @@ underlayController.prototype.getModelData = function(cfg) { underlayController.prototype.destroy = function() { //tbd } - +function doTraceFlowRequest (postData) { + var progressBar = $("#network_topology").find('.topology-visualization-loading'); + $(progressBar).show(); + $(progressBar).css('margin-bottom',$(progressBar).parent().height()); + + $.ajax({ + url:'/api/tenant/networking/trace-flow', + type:'POST', + timeout:5000, + data:{ + data: postData + } + }).done(function(response) { + if(typeof underlayRenderer === 'object') { + underlayRenderer.getModel().setFlowPath(response); + } + if(response.nodes <=0 || response.links <= 0){ + showInfoWindow("Cannot Trace the path for the selected flow.", "Info"); + if(null !== underlayRenderer && typeof underlayRenderer === "object"){ + underlayRenderer.getView().resetTopology(false); + } + return; + } + if(typeof underlayRenderer == 'object') { + underlayRenderer.getView().highlightPath(response, {data: postData}); + } + if(typeof response != 'string') + $('html,body').animate({scrollTop:0}, 500); + }).fail(function(error,status) { + if(typeof underlayRenderer == 'object') { + underlayRenderer.getView().resetTopology(false); + } + if(status == 'timeout') { + showInfoWindow('Timeout in fetching details','Error'); + } else if (status != 'success') { + showInfoWindow('Error in fetching details','Error'); + } + }).always(function(ajaxObj,status) { + $(progressBar).hide(); + }); +} diff --git a/webroot/monitor/infra/vrouter/ui/js/monitor_infra_vrouter_flows.js b/webroot/monitor/infra/vrouter/ui/js/monitor_infra_vrouter_flows.js index 209ae7a7c..ea8392db8 100644 --- a/webroot/monitor/infra/vrouter/ui/js/monitor_infra_vrouter_flows.js +++ b/webroot/monitor/infra/vrouter/ui/js/monitor_infra_vrouter_flows.js @@ -425,7 +425,7 @@ monitorInfraComputeFlowsClass = (function() { if(isAllPrevFirstTimeClicked) { //we need to do this because when we click the prev for the first time the stack would contain the next uuid as well. //We need to pop out the uuids 3 times to get the prev uuid. - flowKeyStack.pop(); + //flowKeyStack.pop(); isAllPrevFirstTimeClicked = false; } flowKeyStack.pop();//need to pop twice to get the prev last flowkey