实现真实的机柜模拟图
本帖最后由 so_brave 于 2012-01-12 14:05 编辑实现真实的机柜模拟图
一般能反映机房设备位置、结构我们都喜欢通过网络拓扑图来展现,但个人感觉还不够直观、明了的表现出自己想要的结果(自己太挑剔了,呵呵)。因此写一个生成真实机柜模拟图平台,实现与真实服务器外观、服务状态、空闲位置等信息。
系统截图
1、平台显示某一排截图
2、平台显示某台服务器详细信息截图
3、状态说明
2U服务器正常状态
2U服务器当机状态
系统原理
通过获取运维平台的服务器信息(包括位置、操作系统、机型等),格式为XML,通过c++的tinyxml来解析并渲染成比较美观的HTML格式。当机的信息通过Nagios来获取。这样就可以生成非常人性化的展现平台了:)
系统代码Servermap.cpp/***************************************************************************
* 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, MA02111-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));
void ProduRow();
void ProduCurrServer();
private:
string idctype;
string (*p_info);// 所有的服务器信息指针(从XML文件中遍历);
string (*pserver_info);// 当前机房的服务器信息指针(从XML文件中遍历);
string ServerInfo;// 所有的服务器信息数组(从XML文件中遍历);
string ServerInfo_CurrServer;//当前机房数组,从ServerInfo中过滤出来;
string ServerDownIP; //当服务器清单;
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==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=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))
{
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=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=="")
break;
for (int j=0;j<ServerInfoNumber;j++)
{
strswap=*(*(p_info+j)+3);
strtmp=strswap.c_str();
Position0=strtmp;
Position1=strtmp;
Position2=strtmp;
Position3=strtmp;
if (idctype=="idc")
stradd=Position0+Position1;
else
stradd=Position0+Position1+Position2+Position3;
if (stradd==CurrServer_row)
{
CurrServerInfoNumber+=1;
ServerInfo_CurrServer=*(*(p_info+j)+0);
ServerInfo_CurrServer=*(*(p_info+j)+1);
ServerInfo_CurrServer=*(*(p_info+j)+2);
ServerInfo_CurrServer=*(*(p_info+j)+3);
ServerInfo_CurrServer=*(*(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=="")
break;
//当前排循环体;
if (idctype=="idc")
HTMLstr+="<div align=center>"+CurrServer_row.substr(0,2)+"排</div>\n";
else
HTMLstr+="<div align=center>"+CurrServer_row.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+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\">";
elseHTMLstr+="<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={"01","02","03","04","05","06"};
string IDCC={"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数据格式<?xml version="1.0" ?><wml><serverinfo>
<ip>192.168.0.1</ip>
<classid>18</classid>
<os>windows-server</os>
<locate>CC06-05-08</locate>
<bodytype>6U</bodytype>
</serverinfo>
<serverinfo>
<ip>192.168.0.2</ip>
<classid>19</classid>
<os>linux-server</os>
<locate>CC06-05-07-R</locate>
<bodytype>6U</bodytype>
</serverinfo>
<serverinfo>
<ip>192.168.0.3</ip>
<classid>20</classid>
<os>windows-server</os>
<locate>CC06-04-07</locate>
<bodytype>6U</bodytype>
</serverinfo>
</wml>
复制代码 谢谢分享
页:
[1]