實現真實的機柜模擬圖[原創]


一般能反映機房設備位置、結構我們都喜歡通過網絡拓撲圖來展現,但個人感覺還不夠直觀、明了的表現出自己想要的結果(自己太挑剔了,呵呵)。因此寫一個生成真實機柜模擬圖平臺,實現與真實服務器外觀、服務狀態、空閑位置等信息。
在線效果圖
http://blog.liuts.com/idc/
系統截圖
1、平臺顯示某一排截圖
1.png
2、平臺顯示某臺服務器詳細信息截圖
2.png
3、狀態說明
3.gif
2U服務器正常狀態
4.gif
2U服務器當機狀態

系統原理
       通過獲取運維平臺的服務器信息(包括位置、操作系統、機型等),格式為XML,通過c++的tinyxml來解析并渲染成比較美觀的HTML格式。當機的信息通過Nagios來獲取。這樣就可以生成非常人性化的展現平臺了:)

系統代碼Servermap.cpp

view plainprint?
/*************************************************************************** 
 *   Copyright (C) 2010 by Liu Tiansi   * 
 *   liutiansi@gmail.com   * 
 *                                                                         * 
 *   This program is free software; you can redistribute it and/or modify  * 
 *   it under the terms of the GNU General Public License as published by  * 
 *   the Free Software Foundation; either version 2 of the License, or     * 
 *   (at your option) any later version.                                   * 
 *                                                                         * 
 *   This program is distributed in the hope that it will be useful,       * 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * 
 *   GNU General Public License for more details.                          * 
 *                                                                         * 
 *   You should have received a copy of the GNU General Public License     * 
 *   along with this program; if not, write to the                         * 
 *   Free Software Foundation, Inc.,                                       * 
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, CN.             * 
 ***************************************************************************/  
  
  
#include <iostream>  
#include <vector>  
#include <string>  
#include <fstream>  
#include "tinyxml.h"  
#include "tinyxml.cpp"  
#include "tinystr.h"  
#include "tinystr.cpp"  
#include "tinyxmlparser.cpp"  
#include "tinyxmlerror.cpp"  
  
using namespace std;  
  
class servermap {  
  
  public:  
    servermap( string *serverrow,string _idctype);  
    ~servermap();  
    string int2str( int num);  
    void Getdownserver ();  
    string writefile (string filename);  
    string GetServerCondition (string ip,string servertype);  
    string (*displayXmlDocument_info (string filename))[5];  
    void ProduRow();  
    void ProduCurrServer();  
  
  private:  
    string idctype;  
    string (*p_info)[5];  // 所有的服務器信息指針(從XML文件中遍歷);  
    string (*pserver_info)[5];  // 當前機房的服務器信息指針(從XML文件中遍歷);  
    string ServerInfo[800][5];  // 所有的服務器信息數組(從XML文件中遍歷);  
    string ServerInfo_CurrServer[300][5];  //當前機房數組,從ServerInfo中過濾出來;  
    string ServerDownIP[50];    //當服務器清單;  
    int ServerInfoNumber;  //獲取所有信息的有效行;  
    string *CurrServer_row;  //指向當前機房數組的指針;  
    int CurrServerInfoNumber;  //獲取當前機房信息的有效行;  
    string HTMLstr;    //存儲HTML串;  
};  
  
//構造func,傳入排數及機房類型;  
servermap::servermap( string *Serverrow,string _idctype)  
{  
  idctype=_idctype;  
  //初始化HTML頭;  
  HTMLstr="<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"  content=\"5\">\n<title>服務器模擬狀態圖</title>\n";  
  HTMLstr+="<script src='/js/server_top.js' language='javascript'></script>\n";  
    
  //機房排數組;  
  CurrServer_row=Serverrow;  
  ServerInfoNumber=0;  
  CurrServerInfoNumber=0;  
  
  //獲取當前服務器清單;  
  Getdownserver();  
  
  //遍歷所有服務器信息;  
  displayXmlDocument_info("ServerInfoAll.xml");  
  
  //簡化當前機房服務器清單;  
  ProduCurrServer();  
}  
  
//類虛構func,銷毀創建的指針;  
servermap::~servermap()  
{  
  //clear mem;  
}  
  
//整形轉字符串方法;  
 string servermap::int2str( int num)  
{  
    if (num == 0 )  
       return " 0 ";  
    string str = "" ;  
    int num_ = num > 0 ? num : - 1 * num;  
  
    while (num_)  
    {  
       str = ( char )(num_ % 10 + 48 ) + str;  
       num_ /= 10 ;  
    }  
  
    if (num < 0 )  
       str = " - " + str;  
    return str;  
}  
  
//返回服務器狀態圖片;  
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";  
}  
  
//獲取當機服務器清單,從文件中獲??;  
void servermap::Getdownserver()  
{  
  string mainpath="/ServerDownlist";  
  string ip;  
  ifstream FileObject;  
  FileObject.open(mainpath.c_str(),ios::in);  
  int i=0;  
      while(getline(FileObject,ip))  
      {  
    ServerDownIP[i]=ip;  
    i+=1;  
  }  
     FileObject.close();  
}  
  
//寫配置文件方法,形參為文件名;  
string servermap::writefile(string filename)  
{  
  string mainpath="/www/webroot/"+filename;  
  ofstream FileObject;  
  FileObject.open(mainpath.c_str(),ios::out);  
  FileObject<<HTMLstr<<endl;  
     FileObject.close();  
  return "1";  
}  
  
  
//獲取XML文件服務器信息數據到指針;  
string (* servermap::displayXmlDocument_info(string filename))[5]  
{  
  TiXmlDocument doc(filename.c_str());  
  doc.LoadFile();  
  TiXmlElement *root_r = doc.RootElement();  
  //static vector<vector<string> > ClassInfo(m,vector<string>(n));  
  int i=0;  
  for(TiXmlNode *node = root_r->FirstChild(); node; node = node->NextSibling())  
  {  
    //輸出元素節點名稱;  
    //cout << node->Value() << endl;  
  
    //遍歷輸出節點屬性名稱及值;  
    if (node->Type() == TiXmlNode::ELEMENT)  
    {  
      for(TiXmlAttribute *attr = node->ToElement()->FirstAttribute(); attr; attr = attr->Next())  
      {  
        cout << "    " << attr->Name() << " =: " << attr->Value() << endl;  
      }  
    }  
    //遍歷輸出子節點名稱及值;  
    TiXmlNode *child = node->FirstChild();  
    int j=0;  
    while(child)  
    {  
      int type = child->Type();  
      if (type == TiXmlNode::ELEMENT)  
      {  
        ServerInfo[i][j]=child->ToElement()->GetText();  
      }  
      child = node->IterateChildren(child);  
      j+=1;  
    }  
    i+=1;  
  
  }  
  ServerInfoNumber=i;  
  p_info=ServerInfo;  
  //free(ClassInfo);  
}  
  
//生成當前機房數組;  
void servermap::ProduCurrServer()  
{  
  const char * strtmp;  
  string strswap,stradd,Position0,Position1,Position2,Position3;  
  
  for (int i=0;i<10;i++)  
  {  
    if (CurrServer_row[i]=="")  
      break;  
    for (int j=0;j<ServerInfoNumber;j++)  
    {  
      strswap=*(*(p_info+j)+3);  
      strtmp=strswap.c_str();  
      Position0=strtmp[0];  
      Position1=strtmp[1];  
      Position2=strtmp[2];  
      Position3=strtmp[3];  
      if (idctype=="idc")  
        stradd=Position0+Position1;  
      else  
        stradd=Position0+Position1+Position2+Position3;  
      if (stradd==CurrServer_row[i])  
      {  
        CurrServerInfoNumber+=1;  
        ServerInfo_CurrServer[CurrServerInfoNumber][0]=*(*(p_info+j)+0);  
        ServerInfo_CurrServer[CurrServerInfoNumber][1]=*(*(p_info+j)+1);  
        ServerInfo_CurrServer[CurrServerInfoNumber][2]=*(*(p_info+j)+2);  
        ServerInfo_CurrServer[CurrServerInfoNumber][3]=*(*(p_info+j)+3);  
        ServerInfo_CurrServer[CurrServerInfoNumber][4]=*(*(p_info+j)+4);  
      }  
    }  
  }  
  pserver_info=ServerInfo_CurrServer;  
}  
  
//生成服務器拓撲狀態圖;  
void servermap::ProduRow()  
{  
  string point_moddle_key="-0";  
  string point_moddle="";  
  string point_last="";  
  string point_all="";  
  string substrServer="";  
  string DIVstr="";  
  int allservercount=0;  
  //所有機柜循環體;  
  for (int i=0;i<10;i++)  
  {  
    if (CurrServer_row[i]=="")  
      break;  
  
    //當前排循環體;  
    if (idctype=="idc")  
      HTMLstr+="<div align=center>"+CurrServer_row[i].substr(0,2)+"排</div>\n";  
    else  
      HTMLstr+="<div align=center>"+CurrServer_row[i].substr(2,2)+"排</div>\n";  
    HTMLstr+="<table width='1024' border='0' cellpadding='1' cellspacing='3' bgcolor='#ffffff' class='jjtable'>\n";  
          HTMLstr+="<tr align='center' valign='top'>\n";  
  
    for (int j=1;j<=7;j++)  
    {  
      point_moddle=point_moddle_key+int2str(j);  
              HTMLstr+="<td width='147' bgcolor='#eeeeee' background=\"/images/serverico/jg.gif\" >\n";  
      //HTMLstr+="<td width='147' style=\"BACKGROUND: url(/images/serverico/jg.gif) #edf6fb repeat-y 0px 0px;\">\n"  ;  
      HTMLstr+="<table width='99%' height='440'  border='0' cellpadding='1' cellspacing='0'>\n";  
            HTMLstr+="<tr>\n";  
              HTMLstr+="  <td height='30' align='center' valign='bottom'  class='jgtable'><font class=jgtitle>0"+int2str(j)+"</font></td></tr>\n";  
  
      //當前列循環體;  
      for (int k=1;k<=10;k++)  
      {  
        if (k==10)  
          point_last="-10";  
        else  
          point_last=point_moddle_key+int2str(k);  
        point_all=CurrServer_row[i]+point_moddle+point_last;  
  
        HTMLstr+="<tr>\n";  
        HTMLstr+="  <td height='30' align='center' valign='bottom' class='jgtable'>\n";  
  
        for (int m=0;m<=CurrServerInfoNumber;m++)  
        {  
          //過濾空元素;  
          //cout<<point_all<<"=="<<*(*(pserver_info+j)+3)<<endl;  
          substrServer=*(*(pserver_info+m)+3);  
          if (idctype=="idc")  
            substrServer=substrServer.substr(0,8);  
          else  
            substrServer=substrServer.substr(0,10);  
          if (point_all==substrServer)  
          {  
            DIVstr+="IP:"+*(*(pserver_info+m)+0)+"<br/>";  
            DIVstr+="操作系統:"+*(*(pserver_info+m)+2)+"<br/>";  
            DIVstr+="位置:"+*(*(pserver_info+m)+3)+"<br/>";  
            DIVstr+="機型:"+*(*(pserver_info+m)+4)+"<br/>";  
            if (*(*(pserver_info+m)+4)=="1U")  
              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\">";  
            else if (*(*(pserver_info+m)+4)=="2U")  
              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\">";  
            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\">";  
  
            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";  
            allservercount+=1;  
            DIVstr="";  
            break;  
          }  
              
        }  
        HTMLstr+=" </td>\n";  
        HTMLstr+="  </tr>\n";  
      }  
      HTMLstr+=" </table>\n";  
      HTMLstr+="</td>\n";  
  
    }  
    HTMLstr+="</tr>\n";  
      HTMLstr+="</table>\n";  
        HTMLstr+="<p> </p>\n";  
  }  
  HTMLstr+="<script src='/js/server_down.js' language='javascript'></script>\n";  
}  
  
//類入 口main(),接受用戶參數;  
int main()  
{  
  string * row;  
  string idctype="";  
  
  //定義機柜排號;  
  string IDCA[10]={"01","02","03","04","05","06"};  
  string IDCC[10]={"18","19","20"};  
  
    
  //IDC A  
  idctype="idc";  
  row=IDCA;  
  servermap appa(row,idctype);  
  appa.ProduRow();  
  appa.writefile("idca.html");  
  //IDC C  
  idctype="idc";  
  row=IDCC;  
  servermap appc(row,idctype);  
  appc.ProduRow();  
  appc.writefile("idcc.html");  
  
  //free(p);  
  return 0;  
}

XML數據格式

view plainprint?
<?xml version="1.0" ?><wml>  
<serverinfo>  
  <ip>192.168.0.1</ip>  
  <classid>18</classid>  
  <os>windows-server</os>  
  <locate>CC06-05-08</locate>  
  <body         type>6U</bodytype>  
</serverinfo>  
<serverinfo>  
  <ip>192.168.0.2</ip>  
  <classid>19</classid>  
  <os>linux-server</os>  
  <locate>CC06-05-07-R</locate>  
  <body         type>6U</bodytype>  
</serverinfo>  
<serverinfo>  
  <ip>192.168.0.3</ip>  
  <classid>20</classid>  
  <os>windows-server</os>  
  <locate>CC06-04-07</locate>  
  <body         type>6U</bodytype>  
</serverinfo>  
</wml>

如大家有什么疑問或感興趣的話題可以通過weibo與我交流http://t.qq.com/yorkoliu

轉自:http://blog.liuts.com/post/206/#entrymore

原創文章,作者:s19930811,如若轉載,請注明出處:http://www.www58058.com/1755

(0)
s19930811s19930811
上一篇 2015-03-27
下一篇 2015-03-27

相關推薦

  • nginx負載均衡搭建

    組 網絡拓撲圖 nginx負載均衡服務器搭建 首先準備三臺機器 主機A(nginx負載均衡器) 主機B 主機C 主機A需兩塊網卡(一塊外網,一塊內網) 主機B和主機C各一塊 (各一塊內網的IP,如果主機B C和主機A內網網卡在一個網段就不需要配置網關地址了。 規劃好網絡后,nginx負載主機分別ping下各rs主機是否可通 主機A打開核心轉發功能 #echo…

    Linux干貨 2017-05-17
  • 最簡單也最難:運維監控的最后1公里

    談運維我們不得不提監控,監控是運維的起點,也是難點。隨著IT架構逐漸復雜化,從前端到IT底層,中間涉及瀏覽器、網絡、服務器、操作系統、中間件、應用、數據庫等,每個環節廠商不盡相同。當出現異常需要定位哪個環節出了問題的時候,排查就耗時耗力,若使用優云監控產品,以上難題不再是問題。優云全棧運維監控覆蓋了所有環節的監控,真正做到監控無盲區,運維無隱患。 運維最后一…

    系統運維 2017-01-09
  • vim編輯器

    回顧:     正則表達式(BRE, ERE)     BRE:字符匹配:., [], [^]     次數匹配:*,\?,\+,\{m\},\{m,n}     位置錨定:^,$,\<,\>     分組及引用:(),\1,\2,…&…

    Linux干貨 2016-12-23
  • linux 進程解析

    博文介紹了進程信息以及部分進程管理命令

    2017-09-09
  • 根據作業淺析正則表達式

        什么是正則?正則就是,那種體現出某種規律的不變性或者對稱性的物理量或關系。     正則表達式(Regular Expression):由一類特殊字符及文本字符所編寫的模式,其中有些字符(元字符)不表示字符字面意義,而表示控制或通配的功能(linux中,可以使用:man …

    Linux干貨 2017-07-30
  • bash小腳本

    1、編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,包括主機名,IPv4地址,操作系統版本,內核版本,CPU型號,內存大小,硬盤大小。 [root@centos6 scripts]# cat systeminfo.sh #!/bin/bash HostName=`uname -n` Ipv…

    Linux干貨 2016-08-15
欧美性久久久久