如何绘制网页版拓扑图

最近为了实现一个网页版的拓扑图, 采用了qunee.js这个js库. 觉得挺不错 . 记一下自己的使用心得. 

qunee是一个js库,封装了html5的canvas的许多方法,在上面也做了自己的很多开发, 可以实现许多效果。 

下面列举和运维相关的一些应用: 

子网模式   http://demo.qunee.com/#SubNetwork  Demo 

内网拓扑   http://demo.qunee.com/#Sinopec  Network Demo 

公网拓扑  http://demo.qunee.com/#Public  Server Network

网络组织图表  http://demo.qunee.com/#Network  Organization Chart 

总线模式   http://demo.qunee.com/#Bus  Demo

设备面板  http://demo.qunee.com/#Equipment  Demo

设备告警图一   http://demo.qunee.com/#Monitoring  Demo

设备告警图二  http://demo.qunee.com/#Alarm  Demo

VOIP  http://demo.qunee.com/#VOIP  Demo 

网络数据流  http://demo.qunee.com/#Flowing  Demo

VPC管理  http://demo.qunee.com/#VPC  Manager Demo 

机房分布图  http://demo.qunee.com/#2.5D  Room Demo 

除此之外, qunee还能用来绘制流程图, 思维导图, 地铁图, 中国地图等等,  其它应用的demo请移步qunne的官网 http://demo.qunee.com/。 

我这边的项目要实现的是一个网络逻辑拓扑, 要绘制出各个IDC核心设备上的VRF和防火墙的逻辑连接关系。 之所以要实现逻辑路由是为了能够在交换机的vrf创建网关后, 可以实现自动在与其直连的防火墙上添加路由。 所以第一步就需要展示交换机的vrf和防火墙的关系。 

qunee官网上建议的开发流程是: 1. 采集数据  2. 转换数据  3. 数据呈现  4. 交互和操作

我也基本上是参照这个开发流程来做的。 

【数据采集】

1。 从核心交换机上抓取所有vrf的接口信息  show ip interface vrf <vrf_name>
2.   抓取防火墙上的接口信息(可以通过设备厂商提供的api或者通过设备配置得到)
3.   遍历从交换机和防火墙上获取的接口信息,如果两个接口在同一vlan下,且ip属于同一网段, 则认为两个接口在逻辑上是连接的


【数据转换】

这个取决于你要绘制出什么样的图形。 不过你可以先生成一个图, 后面在进行修正。不需要一步到位,可以根据最后图形展现的效果做多次迭代修改。 

数据格式可以转换成下面的形式:

{ "nodes" :[{ "name" :  "A" ,  "x" : -100,  "y" : -50,  "id" : 1}, { "name" :  "B" ,  "id" : 2}],  "edges" : [{ "name" :  "Edge" ,  "from" :1,  "to" :2}]}

这个格式是一个json的格式, 有两个大的键值, 一个是nodes,存储要创建的节点信息,一个是edges, 存储节点之间的连线信息,即节点之间是怎么连接的。 

需要说明的是, nodes中的“x” 和 “y”是指节点的x轴和y轴坐标, 这个信息不一定要有, 你可以指定,也可以不指定。个人推荐不指定x和y坐标值, 后面采用qunee提供的自动布局的方式,更加简单高效,而且可以应对拓扑会不断变化的需求。 

另外 nodes中 “id” 不一定是整数,也可以是字符串, 而edges中的from 和 to分别是两个节点的id。 

根据这个数据格式,需要编写对应的解析函数,转成对应的qunee元素,代码如下:

function  translateToQuneeElements(json, graph){
     var  map = {};
     if (json.nodes){
         Q.forEach(json.nodes,  function (data){
             var  node = graph.createNode(data.name, data.x || 0, data.y || 0);
             node.set( "data" , data);
             map[data.id] = node;
            // 节点加入图元容器,这个会在数据呈现部分说明
            model.add(node);
         });
     }
     if (json.edges){
         Q.forEach(json.edges,  function (data){
             var  from = map[data.from];
             var  to = map[data.to];
             if (!from || !to){
                 return ;
             }
             var  edge = graph.createEdge(data.name, from, to);
             edge.set( "data" , data);
         }, graph);
     }
}

    
【数据呈现】

布局上,我采用了弹簧自动布局方式
        // 弹簧布局
        var layouter = new Q.SpringLayouter(graph);
        layouter.elastic = 1;  //  设置弹性系数
        layouter.attractive = 0.1;  // 设置中心吸引力系数
        layouter.repulsion = 60;  // 设置斥力系数
        layouter.start();
通过调整上面的三个系数,可以得到松散适度的布局图。  更多关于弹簧布局的说明,请移步官网文档:  http://doc.qunee.com/pages/viewpage.action?pageId=1147023。 


另外我把所有的元素加入了图元容器model中, 加入图元容器可以方便的实现容器内节点的搜索,事件绑定等操作。 

关于图元容器的说明, 请移步官网的说明 http://doc.qunee.com/pages/viewpage.action?pageId=1146976 

同时我加了个搜索框,可以支持对图元进行搜索,

    $("#btn_search").on("click", function(){
       var _c = $("input#search").val();
       var c = _c.toUpperCase();
       var selectionModel = model.selectionModel;
        selectionModel.clear();
        model.forEachByDepthFirst(function(node){  // 图元的按图的深度优先遍历, 具体说明参考  http://doc.qunee.com/pages/viewpage.action?pageId=1146987 
            if (node.name.indexOf(c) > -1){
                Q.log(node.name);
                selectionModel.select(node);  // 如果匹配到对应的图元, 则置为选中模式

            }
        });
    });

为了让匹配到图元的时候,能够更加突出,我修改了图元选中模式的样式。 

    var styles = {};
    styles[Q.Styles.SELECTION_COLOR] = 'red';
    styles[Q.Styles.SELECTION_BORDER] = 2;
    styles[Q.Styles.SELECTION_SHADOW_BLUR] = 12;
    graph.styles = styles;


更多的样式说明, 请移步  http://doc.qunee.com/pages/viewpage.action?pageId=1147158

【交互和操作】

这块暂时还没有完善。 

后面会支持点击交换机或者防火墙可以跳转到对应的详情页面

还有提供源ip和目的ip,可以在拓扑上显示逻辑路由,实现可视化的traceroute。 

------------------<<<<<  未完待续  >>>>>>-----------------------

你可能感兴趣的:(拓扑图,qunee)