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