实现真实的机柜模拟图[原创]

发布于 2022-09-04 22:37:30 字数 23880 浏览 12 评论 9

本帖最后由 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>

复制代码

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

十二 2022-09-10 06:18:15

回复 1# phpcool

很好的想法,支持!

暮色兮凉城 2022-09-10 06:17:53

项目已开源,托管地址:
http://code.google.com/p/servermap/
初接触c++,N人勿笑。

帅气尐潴 2022-09-10 06:15:29

明白了,这块可能是个硬伤,我现在在琢磨用图形来实现链路联通的实时报警,有一种方法就是用cacti里的weathermap实现,还没有发现其他更好的方法,而我们机房的报警就直接用nagios的MAP,另外关于机房的位置图有一个国产软件叫visualnet

左秋 2022-09-10 06:07:17

当机清单存放在ServerDownlist文件中,由于Nagios不提供当机清单接口(如新版有请告知),目前通过一个比较笨的方法来实现,就是分析页面再将IP导入到ServerDownlist文件。
string mainpath="ServerDownlist";

幻想少年梦 2022-09-10 04:50:53

我发现

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

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结合起来用呢??

贩梦商人 2022-09-10 03:58:36

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

债姬 2022-09-07 23:50:20

本帖最后由 初学vb 于 2010-07-11 00:37 编辑

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

有木有妳兜一样 2022-09-05 10:43:06

不得不说,你这个还挺靠谱,能拿来主义吗?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文