免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8337 | 回复: 10
打印 上一主题 下一主题

实现真实的机柜模拟图[原创] [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-07-09 23:38 |只看该作者 |倒序浏览
本帖最后由 phpcool 于 2010-07-09 23:40 编辑

一般能反映机房设备位置、结构我们都喜欢通过网络拓扑图来展现,但个人感觉还不够直观、明了的表现出自己想要的结果(自己太挑剔了,呵呵)。因此写一个生成真实机柜模拟图平台,实现与真实服务器外观、服务状态、空闲位置等信息。

系统截图
1、平台显示某一排截图


2、平台显示某台服务器详细信息截图


3、状态说明
2U服务器正常状态

2U服务器当机状态


系统原理
       通过获取运维平台的服务器信息(包括位置、操作系统、机型等),格式为XML,通过c++的tinyxml来解析并渲染成比较美观的HTML格式。当机的信息通过Nagios来获取。这样就可以生成非常人性化的展现平台了:)



系统代码Servermap.cpp

  1. /***************************************************************************
  2. *   Copyright (C) 2010 by Liu Tiansi   *
  3. *   liutiansi@gmail.com   *
  4. *                                                                         *
  5. *   This program is free software; you can redistribute it and/or modify  *
  6. *   it under the terms of the GNU General Public License as published by  *
  7. *   the Free Software Foundation; either version 2 of the License, or     *
  8. *   (at your option) any later version.                                   *
  9. *                                                                         *
  10. *   This program is distributed in the hope that it will be useful,       *
  11. *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  12. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  13. *   GNU General Public License for more details.                          *
  14. *                                                                         *
  15. *   You should have received a copy of the GNU General Public License     *
  16. *   along with this program; if not, write to the                         *
  17. *   Free Software Foundation, Inc.,                                       *
  18. *   59 Temple Place - Suite 330, Boston, MA  02111-1307, CN.             *
  19. ***************************************************************************/


  20. #include <iostream>
  21. #include <vector>
  22. #include <string>
  23. #include <fstream>
  24. #include "tinyxml.h"
  25. #include "tinyxml.cpp"
  26. #include "tinystr.h"
  27. #include "tinystr.cpp"
  28. #include "tinyxmlparser.cpp"
  29. #include "tinyxmlerror.cpp"

  30. using namespace std;

  31. class servermap {

  32.   public:
  33.     servermap( string *serverrow,string _idctype);
  34.     ~servermap();
  35.     string int2str( int num);
  36.     void Getdownserver ();
  37.     string writefile (string filename);
  38.     string GetServerCondition (string ip,string servertype);
  39.     string (*displayXmlDocument_info (string filename))[5];
  40.     void ProduRow();
  41.     void ProduCurrServer();

  42.   private:
  43.     string idctype;
  44.     string (*p_info)[5];  // 所有的服务器信息指针(从XML文件中遍历);
  45.     string (*pserver_info)[5];  // 当前机房的服务器信息指针(从XML文件中遍历);
  46.     string ServerInfo[800][5];  // 所有的服务器信息数组(从XML文件中遍历);
  47.     string ServerInfo_CurrServer[300][5];  //当前机房数组,从ServerInfo中过滤出来;
  48.     string ServerDownIP[50];    //当服务器清单;
  49.     int ServerInfoNumber;  //获取所有信息的有效行;
  50.     string *CurrServer_row;  //指向当前机房数组的指针;
  51.     int CurrServerInfoNumber;  //获取当前机房信息的有效行;
  52.     string HTMLstr;    //存储HTML串;
  53. };

  54. //构造func,传入排数及机房类型;
  55. servermap::servermap( string *Serverrow,string _idctype)
  56. {
  57.   idctype=_idctype;
  58.   //初始化HTML头;
  59.   HTMLstr="<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"  content=\"5\">\n<title>服务器模拟状态图</title>\n";
  60.   HTMLstr+="<script src='/js/server_top.js' language='javascript'></script>\n";
  61.   
  62.   //机房排数组;
  63.   CurrServer_row=Serverrow;
  64.   ServerInfoNumber=0;
  65.   CurrServerInfoNumber=0;

  66.   //获取当前服务器清单;
  67.   Getdownserver();

  68.   //遍历所有服务器信息;
  69.   displayXmlDocument_info("ServerInfoAll.xml");

  70.   //简化当前机房服务器清单;
  71.   ProduCurrServer();
  72. }

  73. //类虚构func,销毁创建的指针;
  74. servermap::~servermap()
  75. {
  76.   //clear mem;
  77. }

  78. //整形转字符串方法(来源于互联网);
  79. string servermap::int2str( int num)
  80. {
  81.     if (num == 0 )
  82.        return " 0 ";
  83.     string str = "" ;
  84.     int num_ = num > 0 ? num : - 1 * num;

  85.     while (num_)
  86.     {
  87.        str = ( char )(num_ % 10 + 48 ) + str;
  88.        num_ /= 10 ;
  89.     }

  90.     if (num < 0 )
  91.        str = " - " + str;
  92.     return str;
  93. }

  94. //返回服务器状态图片;
  95. string servermap::GetServerCondition (string ip,string servertype)
  96. {
  97.   bool Obtaining=false;
  98.   for (int i=0;i<50;i++)
  99.   {
  100.     if (ServerDownIP[i]==ip)
  101.     {
  102.       Obtaining=true;
  103.       break;
  104.     }
  105.   }

  106.   if (servertype=="1U")
  107.   if (Obtaining)
  108.     return "1u_down.gif";
  109.   else return "1u_normal.gif";

  110.   if (servertype=="2U")
  111.   if (Obtaining)
  112.     return "2u_down.gif";
  113.   else return "2u_normal.gif";

  114.   if (servertype=="6U")
  115.   if (Obtaining)
  116.     return "ta_down.gif";
  117.   else return "ta_normal.gif";
  118. }

  119. //获取当机服务器清单,从文件中获取;
  120. void servermap::Getdownserver()
  121. {
  122.   string mainpath="ServerDownlist";
  123.   string ip;
  124.   ifstream FileObject;
  125.   FileObject.open(mainpath.c_str(),ios::in);
  126.   int i=0;
  127.       while(getline(FileObject,ip))
  128.       {
  129.     ServerDownIP[i]=ip;
  130.     i+=1;
  131.   }
  132.      FileObject.close();
  133. }

  134. //写配置文件方法,形参为文件名;
  135. string servermap::writefile(string filename)
  136. {
  137.   string mainpath="/www/webroot/"+filename;
  138.   ofstream FileObject;
  139.   FileObject.open(mainpath.c_str(),ios::out);
  140.   FileObject<<HTMLstr<<endl;
  141.      FileObject.close();
  142.   return "1";
  143. }


  144. //获取XML文件服务器信息数据到指针;
  145. string (* servermap::displayXmlDocument_info(string filename))[5]
  146. {
  147.   TiXmlDocument doc(filename.c_str());
  148.   doc.LoadFile();
  149.   TiXmlElement *root_r = doc.RootElement();
  150.   //static vector<vector<string> > ClassInfo(m,vector<string>(n));
  151.   int i=0;
  152.   for(TiXmlNode *node = root_r->FirstChild(); node; node = node->NextSibling())
  153.   {
  154.     //输出元素节点名称;
  155.     //cout << node->Value() << endl;

  156.     //遍历输出节点属性名称及值;
  157.     if (node->Type() == TiXmlNode::ELEMENT)
  158.     {
  159.       for(TiXmlAttribute *attr = node->ToElement()->FirstAttribute(); attr; attr = attr->Next())
  160.       {
  161.         cout << "    " << attr->Name() << " =: " << attr->Value() << endl;
  162.       }
  163.     }
  164.     //遍历输出子节点名称及值;
  165.     TiXmlNode *child = node->FirstChild();
  166.     int j=0;
  167.     while(child)
  168.     {
  169.       int type = child->Type();
  170.       if (type == TiXmlNode::ELEMENT)
  171.       {
  172.         ServerInfo[i][j]=child->ToElement()->GetText();
  173.       }
  174.       child = node->IterateChildren(child);
  175.       j+=1;
  176.     }
  177.     i+=1;

  178.   }
  179.   ServerInfoNumber=i;
  180.   p_info=ServerInfo;
  181.   //free(ClassInfo);
  182. }

  183. //生成当前机房数组;
  184. void servermap::ProduCurrServer()
  185. {
  186.   const char * strtmp;
  187.   string strswap,stradd,Position0,Position1,Position2,Position3;

  188.   for (int i=0;i<10;i++)
  189.   {
  190.     if (CurrServer_row[i]=="")
  191.       break;
  192.     for (int j=0;j<ServerInfoNumber;j++)
  193.     {
  194.       strswap=*(*(p_info+j)+3);
  195.       strtmp=strswap.c_str();
  196.       Position0=strtmp[0];
  197.       Position1=strtmp[1];
  198.       Position2=strtmp[2];
  199.       Position3=strtmp[3];
  200.       if (idctype=="idc")
  201.         stradd=Position0+Position1;
  202.       else
  203.         stradd=Position0+Position1+Position2+Position3;
  204.       if (stradd==CurrServer_row[i])
  205.       {
  206.         CurrServerInfoNumber+=1;
  207.         ServerInfo_CurrServer[CurrServerInfoNumber][0]=*(*(p_info+j)+0);
  208.         ServerInfo_CurrServer[CurrServerInfoNumber][1]=*(*(p_info+j)+1);
  209.         ServerInfo_CurrServer[CurrServerInfoNumber][2]=*(*(p_info+j)+2);
  210.         ServerInfo_CurrServer[CurrServerInfoNumber][3]=*(*(p_info+j)+3);
  211.         ServerInfo_CurrServer[CurrServerInfoNumber][4]=*(*(p_info+j)+4);
  212.       }
  213.     }
  214.   }
  215.   pserver_info=ServerInfo_CurrServer;
  216. }

  217. //生成服务器拓扑状态图;
  218. void servermap::ProduRow()
  219. {
  220.   string point_moddle_key="-0";
  221.   string point_moddle="";
  222.   string point_last="";
  223.   string point_all="";
  224.   string substrServer="";
  225.   string DIVstr="";
  226.   int allservercount=0;
  227.   //所有机柜循环体;
  228.   for (int i=0;i<10;i++)
  229.   {
  230.     if (CurrServer_row[i]=="")
  231.       break;

  232.     //当前排循环体;
  233.     if (idctype=="idc")
  234.       HTMLstr+="<div align=center>"+CurrServer_row[i].substr(0,2)+"排</div>\n";
  235.     else
  236.       HTMLstr+="<div align=center>"+CurrServer_row[i].substr(2,2)+"排</div>\n";
  237.     HTMLstr+="<table width='1024' border='0' cellpadding='1' cellspacing='3' bgcolor='#ffffff' class='jjtable'>\n";
  238.           HTMLstr+="<tr align='center' valign='top'>\n";

  239.     for (int j=1;j<=7;j++)
  240.     {
  241.       point_moddle=point_moddle_key+int2str(j);
  242.               HTMLstr+="<td width='147' bgcolor='#eeeeee' background=\"/images/serverico/jg.gif\" >\n";
  243.       //HTMLstr+="<td width='147' style=\"BACKGROUND: url(/images/serverico/jg.gif) #edf6fb repeat-y 0px 0px;\">\n"  ;
  244.       HTMLstr+="<table width='99%' height='440'  border='0' cellpadding='1' cellspacing='0'>\n";
  245.             HTMLstr+="<tr>\n";
  246.               HTMLstr+="  <td height='30' align='center' valign='bottom'  class='jgtable'><font class=jgtitle>0"+int2str(j)+"</font></td></tr>\n";

  247.       //当前列循环体;
  248.       for (int k=1;k<=10;k++)
  249.       {
  250.         if (k==10)
  251.           point_last="-10";
  252.         else
  253.           point_last=point_moddle_key+int2str(k);
  254.         point_all=CurrServer_row[i]+point_moddle+point_last;

  255.         HTMLstr+="<tr>\n";
  256.         HTMLstr+="  <td height='30' align='center' valign='bottom' class='jgtable'>\n";

  257.         for (int m=0;m<=CurrServerInfoNumber;m++)
  258.         {
  259.           //过滤空元素;
  260.           //cout<<point_all<<"=="<<*(*(pserver_info+j)+3)<<endl;
  261.           substrServer=*(*(pserver_info+m)+3);
  262.           if (idctype=="idc")
  263.             substrServer=substrServer.substr(0,8);
  264.           else
  265.             substrServer=substrServer.substr(0,10);
  266.           if (point_all==substrServer)
  267.           {
  268.             DIVstr+="IP:"+*(*(pserver_info+m)+0)+"<br>";
  269.             DIVstr+="操作系统:"+*(*(pserver_info+m)+2)+"<br>";
  270.             DIVstr+="位置:"+*(*(pserver_info+m)+3)+"<br>";
  271.             DIVstr+="机型:"+*(*(pserver_info+m)+4)+"<br>";
  272.             if (*(*(pserver_info+m)+4)=="1U")
  273.               HTMLstr+="<img src='/images/serverico/"+GetServerCondition(*(*(pserver_info+m)+0),"1U")+"' width='127' height='12' style=\"vertical-align:bottom;\" onmouseover=\"displayDIV('operate"+int2str(allservercount)+"'); return false\" onmouseout=\"hiddenDIV('operate"+int2str(allservercount)+"'); return false\">";
  274.             else if (*(*(pserver_info+m)+4)=="2U")
  275.               HTMLstr+="<img src='/images/serverico/"+GetServerCondition(*(*(pserver_info+m)+0),"2U")+"' width='127' height='24' style=\"vertical-align:bottom;\" onmouseover=\"displayDIV('operate"+int2str(allservercount)+"'); return false\" onmouseout=\"hiddenDIV('operate"+int2str(allservercount)+"'); return false\">";
  276.             else  HTMLstr+="<img src='/images/serverico/"+GetServerCondition(*(*(pserver_info+m)+0),"6U")+"'  height='76' style=\"vertical-align:bottom;\" onmouseover=\"displayDIV('operate"+int2str(allservercount)+"'); return false\" onmouseout=\"hiddenDIV('operate"+int2str(allservercount)+"'); return false\">";

  277.             HTMLstr+="<div id=\"operate"+int2str(allservercount)+"\" style=\"filter:Alpha(opacity=90);display:none;position:absolute; width:200px;BORDER-RIGHT: 2px outset; BORDER-TOP: 1px outset; BACKGROUND: #ffffff; BORDER-LEFT: 1px outset; BORDER-BOTTOM: 2px outset; text-align:left;\"><table cellpadding=\"3\" cellspacing=\"1\"><tr><td>"+DIVstr+"</td></tr></table></div>\n";
  278.             allservercount+=1;
  279.             DIVstr="";
  280.             break;
  281.           }
  282.             
  283.         }
  284.         HTMLstr+=" </td>\n";
  285.         HTMLstr+="  </tr>\n";
  286.       }
  287.       HTMLstr+=" </table>\n";
  288.       HTMLstr+="</td>\n";

  289.     }
  290.     HTMLstr+="</tr>\n";
  291.       HTMLstr+="</table>\n";
  292.         HTMLstr+="<p> </p>\n";
  293.   }
  294.   HTMLstr+="<script src='/js/server_down.js' language='javascript'></script>\n";
  295. }

  296. //类入 口main(),接受用户参数;
  297. int main()
  298. {
  299.   string * row;
  300.   string idctype="";

  301.   //定义机柜排号;
  302.   string IDCA[10]={"01","02","03","04","05","06"};
  303.   string IDCC[10]={"18","19","20"};

  304.   
  305.   //IDC A
  306.   idctype="idc";
  307.   row=IDCA;
  308.   servermap appa(row,idctype);
  309.   appa.ProduRow();
  310.   appa.writefile("idca.html");
  311.   //IDC C
  312.   idctype="idc";
  313.   row=IDCC;
  314.   servermap appc(row,idctype);
  315.   appc.ProduRow();
  316.   appc.writefile("idcc.html");

  317.   //free(p);
  318.   return 0;
  319. }
复制代码
XML数据格式

  1. <?xml version="1.0" ?><wml>
  2. <serverinfo>
  3.   <ip>192.168.0.1</ip>
  4.   <classid>18</classid>
  5.   <os>windows-server</os>
  6.   <locate>CC06-05-08</locate>
  7.   <bodytype>6U</bodytype>
  8. </serverinfo>
  9. <serverinfo>
  10.   <ip>192.168.0.2</ip>
  11.   <classid>19</classid>
  12.   <os>linux-server</os>
  13.   <locate>CC06-05-07-R</locate>
  14.   <bodytype>6U</bodytype>
  15. </serverinfo>
  16. <serverinfo>
  17.   <ip>192.168.0.3</ip>
  18.   <classid>20</classid>
  19.   <os>windows-server</os>
  20.   <locate>CC06-04-07</locate>
  21.   <bodytype>6U</bodytype>
  22. </serverinfo>
  23. </wml>
复制代码

论坛徽章:
0
2 [报告]
发表于 2010-07-11 00:07 |只看该作者
不得不说,你这个还挺靠谱,能拿来主义吗?

论坛徽章:
0
3 [报告]
发表于 2010-07-11 00:34 |只看该作者
本帖最后由 初学vb 于 2010-07-11 00:37 编辑

我做图能力和编程能力是比较差的,但又很想做个测试,所以站短了,谢谢,目前我们自己的监控就是用nagios的页面,我有个想法,如果能测试成功的话,理论上可以把带宽监控加进来,nagios上可以做个PING监控,HTML显示上有问题就红线,没问题就绿线,可以实现实时监控。

论坛徽章:
0
4 [报告]
发表于 2010-07-11 00:39 |只看该作者


突然发现,很像自己编程的 what's up

论坛徽章:
0
5 [报告]
发表于 2010-07-11 00:51 |只看该作者
我发现

//返回服务器状态图片;

string servermap::GetServerCondition (string ip,string servertype)

{

  bool Obtaining=false;

  for (int i=0;i<50;i++)

  {

    if (ServerDownIP[i]==ip)

    {

      Obtaining=true;

      break;

    }

  }



  if (servertype=="1U")

  if (Obtaining)

    return "1u_down.gif";

  else return "1u_normal.gif";



  if (servertype=="2U")

  if (Obtaining)

    return "2u_down.gif";

  else return "2u_normal.gif";



  if (servertype=="6U")

  if (Obtaining)

    return "ta_down.gif";

  else return "ta_normal.gif";

}

是控制主机显示DOWN或NORMAL,如何和nagios结合起来用呢??

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2010-07-11 01:34 |只看该作者
当机清单存放在ServerDownlist文件中,由于Nagios不提供当机清单接口(如新版有请告知),目前通过一个比较笨的方法来实现,就是分析页面再将IP导入到ServerDownlist文件。
string mainpath="ServerDownlist";

论坛徽章:
0
7 [报告]
发表于 2010-07-11 23:33 |只看该作者
明白了,这块可能是个硬伤,我现在在琢磨用图形来实现链路联通的实时报警,有一种方法就是用cacti里的weathermap实现,还没有发现其他更好的方法,而我们机房的报警就直接用nagios的MAP,另外关于机房的位置图有一个国产软件叫visualnet

论坛徽章:
0
8 [报告]
发表于 2010-07-14 12:22 |只看该作者
学习

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2010-07-14 16:17 |只看该作者
项目已开源,托管地址:
http://code.google.com/p/servermap/
初接触c++,N人勿笑。

论坛徽章:
0
10 [报告]
发表于 2010-07-14 16:52 |只看该作者
回复 1# phpcool


很好的想法,支持!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP