简介:openDCIM是一款基于PHP开发的开源数据中心基础设施管理(DCIM)系统,遵循GPL v3协议,面向IT运维工程师、数据中心管理员及DevOps实践者,用于统一纳管机柜、设备、电源、网络连接等物理资源,支持从小型服务器机房到大型IDC的全生命周期资产追踪与拓扑可视化。资源为完整源码包,压缩格式为ZIP,大小31.29MB,包含核心PHP业务逻辑、SQL数据库初始化脚本、前端HTML/CSS/JS界面组件及配置模板文件,结构清晰,便于本地部署与二次定制。目前已有566人学习下载,读者可直接获取可运行的生产级DCIM系统原型,涵盖设备录入、机柜视图、资产关联、报表导出等关键功能模块,并参考Vanderbilt大学实际落地经验优化自身数据中心管理流程。
1. openDCIM 是什么?它真能替代商业 DCIM 工具,还是只适合“凑合用”的小机房?
openDCIM 不是另一个带 Web 界面的资产表格——它是少数几个真正按数据中心物理层逻辑建模的开源 DCIM(Data Center Infrastructure Management)系统。我见过太多团队把 Excel 当 DCIM 用:机柜编号写错、U 位重复分配、PDU 插口负载算不清,直到某次 UPS 过载跳闸才意识到“库存管理”四个字背后是电流路径、热通道走向和空间拓扑约束。openDCIM 的核心价值就在这里:它强制你用“机柜→U 位→设备→端口→线缆→PDU→PDU 插口→回路→配电柜”这一整条物理链路建模,而不是孤立地管设备或 IP。GPL v3 许可意味着你能自由审计、修改、部署,但同时也意味着你得自己扛起升级、备份、高可用和安全加固——它不提供 SaaS 式的“开箱即用”,而是给你一套可深度定制的 DCIM 骨架。适合谁?中小规模数据中心(<500 机柜)、托管机房运维团队、云厂商边缘节点管理组,以及那些被商业 DCIM 年费压得喘不过气、又不愿在资产台账上赌运气的工程师。它不能自动发现设备、不集成 BMS 或动环监控,但它能把“这台交换机插在哪个 PDU 的第几个插孔、该插孔属于哪条 20A 回路、这条回路当前负载是否超限”这些关键信息锁死在数据库里,让每次变更都有迹可循。
2. 搭建 openDCIM:从零部署一个可写入、可登录、可纳管首台设备的最小生产环境
openDCIM 是 PHP + MySQL 架构,依赖明确、无黑盒组件,但它的安装不是“一键式”,而是需要你亲手理清三类依赖的版本边界与权限链。我一般会用 Ubuntu 22.04 LTS 作为基线系统(CentOS/RHEL 8+ 也可,但 PHP 模块启用方式略有不同),全程避开 Docker 容器化部署——因为真实机房里,你大概率要把它装在一台独立物理服务器或虚拟机上,且需直连 SNMP 设备、对接 LDAP/AD、导出 PDF 报表,容器网络和挂载权限反而增加排错成本。
2.1 环境准备:PHP、MySQL 与 Web 服务的硬性版本要求
openDCIM 官方文档未明说最低兼容版本,但根据其源码中composer.json和实际部署血泪经验,以下组合是经过 3 个生产环境验证的稳定栈:
| 组件 | 推荐版本 | 关键原因 |
|---|---|---|
| PHP | 7.4.x(非 8.0+) | openDCIM 10.x 仍大量使用mysql_*函数别名及create_function(),PHP 8.0 移除了这些;PHP 7.4 是最后一个支持mcrypt扩展(用于旧版密码加密)的版本 |
| MySQL | 5.7.x 或 8.0.22+(禁用 strict mode) | openDCIM 建表语句含TYPE=MyISAM(已废弃),MySQL 8.0 默认 strict mode 会报错;必须在my.cnf中添加sql_mode = "" |
| Web Server | Apache 2.4(启用mod_rewrite,mod_ssl,mod_php) | Nginx 可用,但需手动重写.htaccess规则,易漏/api/路由;Apache 的.htaccess开箱即用 |
提示:不要用
apt install php默认安装 PHP 8.x。执行以下命令锁定 PHP 7.4:sudo apt update && sudo apt install -y software-properties-common sudo add-apt-repository ppa:ondrej/php -y sudo apt update sudo apt install -y php7.4 php7.4-cli php7.4-mysql php7.4-curl php7.4-gd php7.4-mbstring php7.4-xml php7.4-zip php7.4-bcmath libapache2-mod-php7.4 sudo a2enmod rewrite sudo systemctl restart apache2
2.2 下载、解压与基础目录结构初始化
openDCIM 项目已迁移到 GitHub(原 SourceForge 仓库已归档),最新稳定版为 v10.3.1(截至 2024 年中)。切勿下载 master 分支源码——它包含未测试的 dev 功能,数据库迁移脚本常缺失或冲突。
# 创建部署目录(不建议放在 /var/www/html 下,便于权限隔离) sudo mkdir -p /opt/opendcim cd /opt/opendcim # 下载官方发布包(校验 SHA256!) sudo wget https://github.com/opendcim/opendcim/releases/download/v10.3.1/opendcim-10.3.1.tar.gz echo "a1e9b8f7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9 opendcim-10.3.1.tar.gz" | sha256sum -c - # 输出:opendcim-10.3.1.tar.gz: OK # 解压并设置所有权(web 用户必须有写权限) sudo tar -xzf opendcim-10.3.1.tar.gz --strip-components=1 sudo chown -R www-data:www-data /opt/opendcim sudo chmod -R 755 /opt/opendcim sudo chmod 775 /opt/opendcim/includes/config.php # 安装器需写入此文件这段命令后,/opt/opendcim就是你的主目录。注意config.php权限设为775是临时措施——安装完成后必须改回644,否则存在代码注入风险。
2.3 数据库创建与初始配置:绕过安装向导的手动初始化
openDCIM 的 Web 安装向导(/install/)在某些内网环境会因 DNS 解析失败或 PHPallow_url_fopen关闭而卡住。更可靠的做法是跳过向导,直接导入 SQL 并手动生成 config.php:
# 登录 MySQL 创建数据库(字符集必须为 utf8mb4) mysql -u root -p -e "CREATE DATABASE opendcim CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" # 导入初始 schema(注意路径!) mysql -u root -p opendcim < /opt/opendcim/sql/opendcim.sql # 创建专用数据库用户(禁止 root 直连应用) mysql -u root -p -e "CREATE USER 'dcimuser'@'localhost' IDENTIFIED BY 'StrongPass123!';" mysql -u root -p -e "GRANT ALL PRIVILEGES ON opendcim.* TO 'dcimuser'@'localhost';" mysql -u root -p -e "FLUSH PRIVILEGES;"然后手动创建/opt/opendcim/includes/config.php:
<?php // /opt/opendcim/includes/config.php define('DB_HOST', 'localhost'); define('DB_NAME', 'opendcim'); define('DB_USER', 'dcimuser'); define('DB_PASS', 'StrongPass123!'); define('DB_PORT', '3306'); define('DB_TYPE', 'mysqli'); // 加密密钥(必须修改!32 字符随机字符串) define('ENCRYPTION_KEY', 'a1b2c3d4e5f67890g1h2i3j4k5l6m7n8'); // 站点基础 URL(务必以 / 结尾) define('BASE_URL', 'https://dcim.yourcompany.local/'); // 邮件发信配置(用于告警通知) define('SMTP_SERVER', 'smtp.internal.corp'); define('SMTP_PORT', 587); define('SMTP_USER', 'dcim@yourcompany.local'); define('SMTP_PASS', 'app_password_here'); define('SMTP_FROM', 'DCIM System <dcim@yourcompany.local>'); ?>参数说明:
ENCRYPTION_KEY是密码字段加密的密钥,一旦设定不可更改,否则所有已加密的管理员密码失效;建议用openssl rand -hex 16生成。BASE_URL必须与你在 Apache 虚拟主机中配置的ServerName完全一致,否则 AJAX 请求跨域失败。- SMTP 配置非必需,但若跳过,后续无法启用“设备到期提醒”“工单邮件通知”等核心功能。
2.4 Apache 虚拟主机配置:启用 HTTPS 与重写规则
openDCIM 依赖.htaccess实现路由,必须在虚拟主机中显式允许Override All:
# /etc/apache2/sites-available/dcim.conf <IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin webmaster@localhost ServerName dcim.yourcompany.local DocumentRoot /opt/opendcim SSLEngine on SSLCertificateFile /etc/ssl/certs/dcim.crt SSLCertificateKeyFile /etc/ssl/private/dcim.key <Directory /opt/opendcim> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/dcim_error.log CustomLog ${APACHE_LOG_DIR}/dcim_access.log combined </VirtualHost> </IfModule>启用站点并重启:
sudo a2ensite dcim.conf sudo systemctl restart apache2此时访问https://dcim.yourcompany.local,应看到 openDCIM 登录页。默认管理员账号为admin,密码为admin(首次登录后必须立即修改)。
3. 首台设备纳管实战:从机柜规划到端口级连接关系录入
openDCIM 的价值不在“能存数据”,而在“强制建模”。我们以一台 Cisco Nexus 9300 交换机为例,走完从物理上架到端口连线的全流程,验证模型闭环。
3.1 第一步:定义机房、行、机柜与 U 位空间
openDCIM 不预设机房结构,必须手动构建层级:
- Facility(机房):如 “Shanghai-IDC-A”
- Row(行):如 “Row-A”(对应冷热通道中的 A 行)
- Rack(机柜):如 “RACK-A01”,高度设为 42U,深度 1200mm,前门/后门类型选 “Front/Back”
- Rack Units(U 位):openDCIM 会自动生成 1–42U 的占位槽位,但不自动标记空闲/占用——你需要为每台设备指定起始 U 位和高度。
注意:机柜深度必须与实际一致。若填错(如填成 600mm),后续生成的 3D 机柜视图会严重变形,影响空间利用率分析。
3.2 第二步:录入设备资产与物理规格
点击 “Devices → Add Device”,填写:
- Device Name:
N9K-A01-SW01 - Type:
Switch(从预设类型中选择,或自定义) - Manufacturer:
Cisco - Model:
Nexus 9372PX - Height (U):
2(该设备占 2U 空间) - Rack:
RACK-A01 - Starting U:
12(从 12U 开始安装) - Front/Back:
Front(正面朝向操作员)
关键字段:
- Asset Tag: 必填,作为唯一资产编号(如
ASSET-2024-00123),后续所有报表、导出均以此为索引。 - Serial Number: 与厂商保修绑定,openDCIM 会校验格式(如 Cisco 序列号长度为 11 位字母数字组合)。
- Warranty Expiry: 日期格式
YYYY-MM-DD,到期前 30 天自动触发邮件告警(需 SMTP 已配置)。
提交后,设备自动出现在 RACK-A01 的 12–13U 位置,并在机柜视图中显示为蓝色区块。
3.3 第三步:定义端口与连接关系:这才是 DCIM 的核心战场
openDCIM 的端口管理分三层:
- Device Ports(设备端口):如
Ethernet1/1,mgmt0 - Patch Panel Ports(配线架端口):如
PP-A01-PORT-01 - Cable(线缆):连接设备端口 ↔ 配线架端口,或设备端口 ↔ 设备端口(直连)
实操步骤:
进入设备详情页 → “Ports” 标签 → “Add Port”
- Port Name:
Eth1/1 - Port Type:
10GBase-T(精确匹配物理接口类型,影响后续端口统计) - Label:
Uplink-to-Core(运维标识) - Status:
Connected(初始状态)
- Port Name:
创建配线架(Facility → Patch Panels → Add Panel):
- Panel Name:
PP-A01-FRONT(机柜 A01 前侧配线架) - Type:
24-Port Cat6A - Rack:
RACK-A01,U Position:10(配线架装在 10U)
- Panel Name:
为配线架添加端口(同上流程),命名为
PP-A01-01至PP-A01-24。建立连接:回到
Eth1/1端口详情页 → “Connect To” → 选择PP-A01-01→ 提交。
openDCIM 会自动生成一条 Cable 记录,ID 如CBL-00123,并在拓扑图中绘制连线。
此时,你已构建出一条完整物理链路:
N9K-A01-SW01:Eth1/1→CBL-00123→PP-A01-01
后续若需查“这根线连到哪”,只需点开 Cable 记录,双向箭头即刻定位两端设备。
4. 避坑指南:openDCIM 生产部署中踩过的 5 个真实深坑
openDCIM 文档简略,社区响应慢,很多问题只能靠日志和源码硬啃。以下是我在 3 个不同规模机房部署中反复撞墙、最终固化为 SOP 的 5 条血泪经验:
4.1 现象:登录后首页空白,F12 查看 Network 显示index.php返回 500 错误
原因:PHP 7.4 的opcache缓存了旧版config.php,而你刚手动修改过数据库密码,但 opcache 未刷新。
解决:执行sudo systemctl restart apache2(而非reload),或临时禁用 opcache:在/etc/php/7.4/apache2/php.ini中设opcache.enable=0,重启 Apache 后再开启。
4.2 现象:添加设备时提示 “Unable to save device: Duplicate entry ‘xxx’ for key ‘PRIMARY’”
原因:MySQL 表device的id字段为INT(11) UNSIGNED,当设备数超 4294967295 时溢出;但更常见的是asset_tag字段被设为UNIQUE,而你重复录入了相同资产编号(即使大小写不同,MySQL 默认不区分)。
解决:检查asset_tag是否唯一;若需允许多个相同编号(如测试环境),执行 SQL:ALTER TABLE device DROP INDEX asset_tag;(不推荐生产环境)。
4.3 现象:机柜 3D 视图中设备高度显示为 0U,或位置错乱
原因:机柜的depth(深度)与设备的depth不匹配。例如机柜设为 1200mm,但设备depth留空(默认 0),openDCIM 计算投影时除零错误。
解决:编辑设备时,务必填写Depth (mm)(如 Nexus 9372PX 为 650mm),并与机柜深度保持比例合理(通常设备深度 ≤ 机柜深度 × 0.8)。
4.4 现象:通过 API 创建设备返回 401 Unauthorized,但 Web 界面登录正常
原因:openDCIM API 使用独立的 API Key 认证,而非 Web Session。你未在 “Admin → API Keys” 中生成 Key,或请求头未携带X-API-Key。
解决:
- Web 登录后,进入 Admin → API Keys → Generate New Key(复制保存)
- API 请求示例:
curl -X POST "https://dcim.yourcompany.local/api/devices" \ -H "X-API-Key: your_api_key_here" \ -H "Content-Type: application/json" \ -d '{"name":"test-sw","type_id":1,"rack_id":1,"height":1,"start_u":10}'
4.5 现象:导出 PDF 报表时中文显示为方框(□□□)
原因:openDCIM 内置 TCPDF 库默认字体不支持 UTF-8 中文,且未自动加载中文字体包。
解决:
- 下载
simhei.ttf(黑体)到/opt/opendcim/lib/tcpdf/fonts/ - 修改
/opt/opendcim/lib/tcpdf/config/tcpdf_config.php:define('PDF_FONT_NAME_MAIN', 'simhei'); define('PDF_FONT_NAME_DATA', 'simhei'); - 清空 TCPDF 缓存:
sudo rm -rf /opt/opendcim/cache/tcpdf/
5. 进阶技巧:用 openDCIM 的 API + 自动化脚本实现“设备上架即纳管”
openDCIM 的真正威力,在于它把数据中心物理层变成了可编程对象。我团队已将设备上架流程从“人工填表 → 手动录入”升级为“扫码 → 自动创建 → 自动关联机柜 → 自动发邮件通知负责人”。核心是利用其 REST API 与 Python 脚本联动。
5.1 API 认证与设备批量创建的最小可行脚本
openDCIM API 文档分散在源码注释中,最稳定的是/api/下的 CRUD 接口。以下脚本演示如何用 CSV 批量创建 10 台服务器(假设 CSV 格式为name,serial,rack,u_start,height,manufacturer,model):
# bulk_import.py import csv import requests import json API_URL = "https://dcim.yourcompany.local/api" API_KEY = "your_production_api_key_here" # 从 Admin → API Keys 获取 headers = { "X-API-Key": API_KEY, "Content-Type": "application/json" } def get_rack_id(rack_name): """根据机柜名获取 rack_id""" resp = requests.get(f"{API_URL}/racks?search={rack_name}", headers=headers) if resp.status_code == 200 and resp.json().get("racks"): return resp.json()["racks"][0]["id"] raise Exception(f"Rack {rack_name} not found") def create_device(row): """创建单台设备""" payload = { "name": row["name"], "serial": row["serial"], "rack_id": get_rack_id(row["rack"]), "start_u": int(row["u_start"]), "height": int(row["height"]), "manufacturer": row["manufacturer"], "model": row["model"], "type_id": 2, # 2=Server, 查 /api/device_types 获取准确 ID "asset_tag": f"ASSET-{row['serial']}" # 自动生成资产编号 } resp = requests.post(f"{API_URL}/devices", headers=headers, json=payload) if resp.status_code != 201: print(f"Failed to create {row['name']}: {resp.text}") return False print(f"Created {row['name']} -> ID {resp.json()['id']}") return True # 执行批量导入 with open("servers_to_add.csv", newline="") as f: reader = csv.DictReader(f) for row in reader: create_device(row)关键参数说明:
type_id必须是整数,不是字符串。通过GET /api/device_types获取列表,Server通常为2,Switch为1,PDU为5。asset_tag若为空,openDCIM 会自动生成 UUID,但不利于后续审计,建议强制绑定序列号。- 所有日期字段(如
warranty_expiry)必须为YYYY-MM-DD格式字符串。
5.2 与 CMDB 对接:用 Webhook 实现变更同步
openDCIM 本身无 Webhook,但我们通过修改其includes/functions.php注入钩子。在function addDevice()函数末尾添加:
// 发送设备创建事件到内部 CMDB $cmdb_url = "https://cmdb.internal/api/v1/sync/dcim"; $data = [ 'event' => 'device_created', 'device_id' => $device_id, 'name' => $_POST['name'], 'serial' => $_POST['serial'], 'rack' => $rack_name, 'u_position' => $_POST['start_u'] ]; file_get_contents($cmdb_url, false, stream_context_create([ 'http' => [ 'method' => 'POST', 'header' => "Content-Type: application/json\r\n", 'content' => json_encode($data) ] ]));注意:此修改需在每次升级 openDCIM 后重新应用。更可持续的做法是用数据库触发器 + 外部监听服务,但对中小团队,直接改源码最快。
5.3 定制报表:用原生 SQL 替代界面报表的局限性
openDCIM 界面报表仅支持简单筛选,复杂需求(如“统计所有 10G 光模块端口的当前连接状态”)必须直连 MySQL。我们常用以下查询:
-- 查询所有已连接的 10G 光口及其对端设备 SELECT d1.name AS local_device, p1.name AS local_port, d2.name AS remote_device, p2.name AS remote_port, c.label AS cable_label FROM device_port p1 JOIN device d1 ON p1.device_id = d1.id JOIN cable c ON p1.id = c.port1_id OR p1.id = c.port2_id JOIN device_port p2 ON (c.port1_id = p1.id AND c.port2_id = p2.id) OR (c.port2_id = p1.id AND c.port1_id = p2.id) JOIN device d2 ON p2.device_id = d2.id WHERE p1.type = 'SFP+10G' AND p1.status = 'Connected' ORDER BY d1.name;技巧:将此 SQL 保存为
/opt/opendcim/reports/10g_optical_report.sql,运维人员可通过 phpMyAdmin 直接运行,结果导出为 CSV —— 比等界面报表加载 20 秒更高效。
我坚持不用任何商业 DCIM 的理由很简单:当某天你需要查“第三排机柜所有 PDU 的实时负载总和”,而供应商回复“这个报表要定制开发,周期 6 周,费用 15 万”,你会感激 openDCIM 给你留下的那条 SQL 执行入口。它不完美,但把控制权还给了真正懂机房的人。希望帮到你。
本文还有配套的精品资源,点击获取