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


一般能反映机房设备位置、结构我们都喜欢通过网络拓扑图来展现,但个人感觉还不够直观、明了的表现出自己想要的结果(自己太挑剔了,呵呵)。因此写一个生成真实机柜模拟图平台,实现与真实服务器外观、服务状态、空闲位置等信息。
在线效果图
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.178linux.com/1755

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

相关推荐

  • yum源设置

      yum是我们经常用到的一个程序,我们主要用它来安装或删除安装包,下面我来介绍一下怎样配置yum安装源?    配置yum安装源主要有两种方法:一种是用本地镜像做安装源,二是用提供镜像下载的网站做安装源。    一 配置本地安装源    本地安装源需要有系统镜像,操作步骤如下:…

    Linux干货 2016-01-16
  • 端口转发实例

    什么是端口转发?      端口转发(Port forwarding),有时被叫做隧道,是安全壳(SSH) 为网络安全通信使用的一种方法。端口转发是转发一个网络端口从一个网络节点到另一个网络节点的行为,其使一个外部用户从外部经过一个被激活的NAT路由器到达一个在私有内部IP地址(局域网内部)上的一个端口。 为什么需要端口转发? …

    2017-04-13
  • 系统管理之Selinux详解

    SELinux: SELinux概念SELinux配置启用SELinux管理文件安全标签管理端口标签管理SELinux布尔值开关管理日志查看SELinux帮助 SELinux概述 SELinux: Secure Enhanced Linux, 是美国国家安全局「NSA=The National Se…

    Linux干货 2016-09-21
  • LVS专题: NAT和DR模型实现Web负载均衡

    LVS专题: NAT和DR模型实现Web负载均衡 前言: NAT实现 Real Server配置 Director配置 测试 实验拓扑 实验环境 实验步骤 DR实现 Director配置 Real Server配置 测试 实验拓扑 实验环境 实验步骤 总结: 前言: 在上篇文章中我们讲了一些LVS的基本概念和相应模型的实验原理和流程,本篇文章我们主要使用lv…

    2016-04-05
  • N25第五周作业

    1、显示/boot/grub/grub.conf中以至少一个空白字符开头的行; ]# grep -E '^[[:space:]]+.*' /boot/grub/grub.conf 2、显示/etc/rc.d/rc.sysinit文件中以#开头,后面跟至少一个空白字符,而后又有至少一个非空白字符的行;…

    Linux干货 2017-01-08
  • PHP数组实际占用内存大小的分析

    我们在前面的php高效写法提到,尽量不要复制变量,特别是数组。一般来说,PHP数组的内存利用率只有 1/10, 也就是说,一个在C语言里面100M 内存的数组,在PHP里面就要1G。下面我们可以粗略的估算PHP数组占用内存的大小,首先我们测试1000个元素的整数占用的内存: <?php      &nb…

    系统运维 2015-05-28