so_brave 发表于 2012-01-12 14:01

实现真实的机柜模拟图

本帖最后由 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>&#92;n<head>&#92;n<meta http-equiv=&#92;"Content-Type&#92;" content=&#92;"text/html; charset=utf-8&#92;"content=&#92;"5&#92;">&#92;n<title>服务器模拟状态图</title>&#92;n";

HTMLstr+="<script src='/js/server_top.js' language='javascript'></script>&#92;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>&#92;n";

    else

      HTMLstr+="<div align=center>"+CurrServer_row.substr(2,2)+"排</div>&#92;n";

    HTMLstr+="<table width='1024' border='0' cellpadding='1' cellspacing='3' bgcolor='#ffffff' class='jjtable'>&#92;n";

          HTMLstr+="<tr align='center' valign='top'>&#92;n";



    for (int j=1;j<=7;j++)

    {

      point_moddle=point_moddle_key+int2str(j);

            HTMLstr+="<td width='147' bgcolor='#eeeeee' background=&#92;"/images/serverico/jg.gif&#92;" >&#92;n";

      //HTMLstr+="<td width='147' style=&#92;"BACKGROUND: url(/images/serverico/jg.gif) #edf6fb repeat-y 0px 0px;&#92;">&#92;n";

      HTMLstr+="<table width='99%' height='440'border='0' cellpadding='1' cellspacing='0'>&#92;n";

            HTMLstr+="<tr>&#92;n";

            HTMLstr+="<td height='30' align='center' valign='bottom'class='jgtable'><font class=jgtitle>0"+int2str(j)+"</font></td></tr>&#92;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>&#92;n";

      HTMLstr+="<td height='30' align='center' valign='bottom' class='jgtable'>&#92;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=&#92;"vertical-align:bottom;&#92;" onmouseover=&#92;"displayDIV('operate"+int2str(allservercount)+"'); return false&#92;" onmouseout=&#92;"hiddenDIV('operate"+int2str(allservercount)+"'); return false&#92;">";

            else if (*(*(pserver_info+m)+4)=="2U")

            HTMLstr+="<img src='/images/serverico/"+GetServerCondition(*(*(pserver_info+m)+0),"2U")+"' width='127' height='24' style=&#92;"vertical-align:bottom;&#92;" onmouseover=&#92;"displayDIV('operate"+int2str(allservercount)+"'); return false&#92;" onmouseout=&#92;"hiddenDIV('operate"+int2str(allservercount)+"'); return false&#92;">";

            elseHTMLstr+="<img src='/images/serverico/"+GetServerCondition(*(*(pserver_info+m)+0),"6U")+"'height='76' style=&#92;"vertical-align:bottom;&#92;" onmouseover=&#92;"displayDIV('operate"+int2str(allservercount)+"'); return false&#92;" onmouseout=&#92;"hiddenDIV('operate"+int2str(allservercount)+"'); return false&#92;">";



            HTMLstr+="<div id=&#92;"operate"+int2str(allservercount)+"&#92;" style=&#92;"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;&#92;"><table cellpadding=&#92;"3&#92;" cellspacing=&#92;"1&#92;"><tr><td>"+DIVstr+"</td></tr></table></div>&#92;n";

            allservercount+=1;

            DIVstr="";

            break;

          }

            

      }

      HTMLstr+="&nbsp</td>&#92;n";

      HTMLstr+="</tr>&#92;n";

      }

      HTMLstr+=" </table>&#92;n";

      HTMLstr+="</td>&#92;n";



    }

    HTMLstr+="</tr>&#92;n";

      HTMLstr+="</table>&#92;n";

      HTMLstr+="<p> </p>&#92;n";

}

HTMLstr+="<script src='/js/server_down.js' language='javascript'></script>&#92;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>
复制代码

在我心中舞动 发表于 2012-01-12 15:03

谢谢分享
页: [1]
查看完整版本: 实现真实的机柜模拟图