已开启
fix: 支持SSU定位灯控制(Redfish/Web) #1505
huangminghao创建于 8 天前
fix: 支持SSU定位灯控制(Redfish/Web) #1505
已开启
huangminghao创建于 8 天前
5 个文件变更+419-1
@@ -1389,6 +1389,179 @@
1389 }1389 }
1390 ]1390 ]
1391 },1391 },
1392+ {
W
Wwangjian7 天前

PATCH 的 SetState 调用中,Params 为 ["${Statements/SetLocationIndicatorActiveState()}", 255],即 Interval 固定为 255。但 PR 描述中明确说明'PATCH true→SetState(5, 255)(闪烁255秒自动灭)',且 chassis 仓的 identify 倒计时为 interval10 秒。25510=2550 秒(42.5分钟),与 PR 描述中'闪烁255秒自动灭'不符。PR 描述声称 255 秒,但实际实现为 2550 秒,存在明显的时间语义偏差。

likedislike
1393+ "Uri": "/redfish/v1/Chassis/SSU:id",
1394+ "Interfaces": [
1395+ {
1396+ "Type": "GET",
1397+ "ResourceExist": {
1398+ "${Statements/IsValidSSUId()}": true
1399+ },
1400+ "RspBody": {
1401+ "@odata.context": "/redfish/v1/$metadata#Chassis.Chassis",
1402+ "@odata.id": "/redfish/v1/Chassis/SSU${Uri/id}",
1403+ "@odata.type": "#Chassis.v1_26_0.Chassis",
1404+ "Id": "${ProcessingFlow[1]/Destination/Id}",
1405+ "Name": "${ProcessingFlow[2]/Destination/Name}",
1406+ "ChassisType": "Module",
1407+ "LocationIndicatorActive": "${Statements/GetLocationIndicatorActive()}"
1408+ },
1409+ "Statements": {
1410+ "GetSSUPath": {
1411+ "Steps": [
1412+ {
1413+ "Type": "Plugin",
1414+ "Formula": "orchestrator.chassis.get_ssu_path(Uri.id)"
1415+ }
1416+ ]
1417+ },
1418+ "GetSSULedPath": {
1419+ "Steps": [
1420+ {
1421+ "Type": "Plugin",
1422+ "Formula": "orchestrator.chassis.get_ssu_led_path(Uri.id)"
1423+ }
1424+ ]
1425+ },
1426+ "IsValidSSUId": {
1427+ "Input": "${Statements/GetSSUPath()}",
1428+ "Steps": [
1429+ {
1430+ "Type": "Switch",
1431+ "Formula": [
1432+ {
1433+ "Case": "",
1434+ "To": false
1435+ },
1436+ {
1437+ "To": true
1438+ }
1439+ ]
1440+ }
1441+ ]
1442+ },
1443+ "GetLocationIndicatorActive": {
1444+ "Input": "${ProcessingFlow[3]/Destination/State}",
1445+ "Steps": [
1446+ {
1447+ "Type": "Switch",
1448+ "Formula": [
1449+ { "Case": 0, "To": false },
1450+ { "Case": 5, "To": true },
1451+ { "Case": 255, "To": true },
1452+ { "To": null }
1453+ ]
1454+ }
1455+ ]
1456+ }
1457+ },
1458+ "ProcessingFlow": [
1459+ {
1460+ "Type": "Property",
1461+ "Path": "${Statements/GetSSUPath()}",
1462+ "Interface": "bmc.dev.Chassis",
W
Wwangjian7 天前

资源协作接口 bmc.dev.Chassis 在 mdb_interface 中未定义(属性/方法须先在社区接口库定义)。

likedislike
1463+ "Destination": {
1464+ "Id": "Id"
1465+ }
1466+ },
1467+ {
1468+ "Type": "Property",
1469+ "Path": "${Statements/GetSSUPath()}",
1470+ "Interface": "bmc.dev.Board",
1471+ "Destination": {
1472+ "Name": "Name"
1473+ }
1474+ },
1475+ {
1476+ "Type": "Property",
1477+ "Path": "${Statements/GetSSULedPath()}",
1478+ "Interface": "bmc.kepler.Systems.Led",
1479+ "Destination": {
1480+ "State": "State"
1481+ }
1482+ }
1483+ ]
1484+ },
1485+ {
1486+ "Type": "PATCH",
1487+ "ResourceExist": {
1488+ "${Statements/IsValidSSUId()}": true
1489+ },
1490+ "LockdownAllow": true,
1491+ "ReqBody": {
1492+ "Type": "object",
1493+ "Required": true,
1494+ "Properties": {
1495+ "LocationIndicatorActive": {
1496+ "Type": "boolean"
1497+ }
1498+ }
1499+ },
1500+ "Statements": {
1501+ "GetSSUPath": {
1502+ "Steps": [
1503+ {
1504+ "Type": "Plugin",
1505+ "Formula": "orchestrator.chassis.get_ssu_path(Uri.id)"
1506+ }
1507+ ]
1508+ },
1509+ "GetSSULedPath": {
1510+ "Steps": [
1511+ {
1512+ "Type": "Plugin",
1513+ "Formula": "orchestrator.chassis.get_ssu_led_path(Uri.id)"
1514+ }
1515+ ]
1516+ },
1517+ "IsValidSSUId": {
1518+ "Input": "${Statements/GetSSUPath()}",
1519+ "Steps": [
1520+ {
1521+ "Type": "Switch",
1522+ "Formula": [
1523+ {
1524+ "Case": "",
1525+ "To": false
1526+ },
1527+ {
1528+ "To": true
1529+ }
1530+ ]
1531+ }
1532+ ]
1533+ },
1534+ "SetLocationIndicatorActiveState": {
1535+ "Input": "${ReqBody/LocationIndicatorActive}",
1536+ "Steps": [
1537+ {
1538+ "Type": "Switch",
1539+ "Formula": [
1540+ { "Case": true, "To": 5 },
1541+ { "Case": false, "To": 0 }
1542+ ]
1543+ }
1544+ ]
1545+ }
1546+ },
1547+ "ProcessingFlow": [
1548+ {
1549+ "Type": "Method",
1550+ "Path": "${Statements/GetSSULedPath()}",
1551+ "Interface": "bmc.kepler.Systems.Led",
1552+ "Name": "SetState",
1553+ "Params": [
1554+ "${Statements/SetLocationIndicatorActiveState()}",
1555+ 255
1556+ ],
1557+ "CallIf": {
1558+ "${ReqBody/LocationIndicatorActive}": "#WITH"
1559+ }
1560+ }
1561+ ]
1562+ }
1563+ ]
1564+ },
1392 {1565 {
1393 "Uri": "/Expand/Chassis/bmc/kepler/Systems/:systemid/Processors/CPU/:id",1566 "Uri": "/Expand/Chassis/bmc/kepler/Systems/:systemid/Processors/CPU/:id",
1394 "Interfaces": [1567 "Interfaces": [
@@ -250,6 +250,40 @@ function m.get_expansion_path(expansionid)
250 return path250 return path
251end251end
252 252 
253+-- 获取SSU模组Chassis对象路径
254+function m.get_ssu_path(ssuid)
255+ local id = 'SSU' .. ssuid
256+ local path = bus:call(
257+ 'bmc.kepler.maca',
258+ '/bmc/kepler/MdbService',
259+ 'bmc.kepler.Mdb',
260+ 'GetPath',
261+ 'a{ss}ssb',
262+ context.new(),
263+ 'bmc.dev.Chassis',
264+ cjson.encode({ Id = id }),
265+ false
266+ )
267+ return path
268+end
269+ 
270+-- 获取SSU模组定位灯对象路径
271+function m.get_ssu_led_path(ssuid)
272+ local name = 'SSU' .. ssuid .. '_UID'
273+ local path = bus:call(
274+ 'bmc.kepler.maca',
275+ '/bmc/kepler/MdbService',
276+ 'bmc.kepler.Mdb',
277+ 'GetPath',
278+ 'a{ss}ssb',
279+ context.new(),
280+ 'bmc.kepler.Systems.Led',
281+ cjson.encode({ Name = name }),
282+ false
283+ )
284+ return path
285+end
286+ 
253function m.get_manager_path(managers)287function m.get_manager_path(managers)
254 local num = string.match(managers[1] or '', 'Manager(%d+)')288 local num = string.match(managers[1] or '', 'Manager(%d+)')
255 local id = num and ('Expansion' .. num) or nil289 local id = num and ('Expansion' .. num) or nil
@@ -50,7 +50,8 @@
50 "deletable": false,50 "deletable": false,
51 "uris": [51 "uris": [
52 "/redfish/v1/Chassis/:chassisid",52 "/redfish/v1/Chassis/:chassisid",
53- "/redfish/v1/Chassis/Expansion:id"53+ "/redfish/v1/Chassis/Expansion:id",
54+ "/redfish/v1/Chassis/SSU:id"
54 ]55 ]
55 }56 }
56 },57 },
@@ -0,0 +1,168 @@
1+{
2+ "Resources": [
3+ {
4+ "Uri": "/UI/Rest/System/SSUs",
5+ "Interfaces": [
6+ {
7+ "Type": "GET",
8+ "RspBody": {
9+ "List": "${Statements/GetSSUList()}"
10+ },
11+ "Statements": {
12+ "GetSSUList": {
13+ "Steps": [
14+ {
15+ "Type": "Plugin",
16+ "Formula": "orchestrator.chassis.get_ssu_list()"
17+ }
18+ ]
19+ }
20+ }
21+ }
22+ ]
23+ },
24+ {
25+ "Uri": "/UI/Rest/System/SSUs/:id",
26+ "Interfaces": [
27+ {
28+ "Type": "GET",
29+ "ResourceExist": {
30+ "${Statements/IsValidSSUId()}": true
31+ },
32+ "RspBody": {
33+ "Id": "${Uri/id}",
34+ "LocationIndicatorActive": "${Statements/GetLocationIndicatorActive()}",
35+ "SystemId": 1
36+ },
37+ "Statements": {
38+ "GetSSUPath": {
39+ "Steps": [
40+ {
41+ "Type": "Plugin",
42+ "Formula": "orchestrator.chassis.get_ssu_path(Uri.id)"
43+ }
44+ ]
45+ },
46+ "GetSSULedPath": {
47+ "Steps": [
48+ {
49+ "Type": "Plugin",
50+ "Formula": "orchestrator.chassis.get_ssu_led_path(Uri.id)"
51+ }
52+ ]
53+ },
54+ "IsValidSSUId": {
55+ "Input": "${Statements/GetSSUPath()}",
56+ "Steps": [
57+ {
58+ "Type": "Switch",
59+ "Formula": [
60+ { "Case": "", "To": false },
61+ { "To": true }
62+ ]
63+ }
64+ ]
65+ },
66+ "GetLocationIndicatorActive": {
67+ "Input": "${ProcessingFlow[1]/Destination/State}",
68+ "Steps": [
69+ {
70+ "Type": "Switch",
71+ "Formula": [
72+ { "Case": 0, "To": false },
73+ { "Case": 5, "To": true },
74+ { "Case": 255, "To": true },
75+ { "To": null }
76+ ]
77+ }
78+ ]
79+ }
80+ },
81+ "ProcessingFlow": [
82+ {
83+ "Type": "Property",
84+ "Path": "${Statements/GetSSULedPath()}",
85+ "Interface": "bmc.kepler.Systems.Led",
86+ "Destination": {
87+ "State": "State"
88+ }
89+ }
90+ ]
91+ },
92+ {
93+ "Type": "PATCH",
94+ "ResourceExist": {
95+ "${Statements/IsValidSSUId()}": true
96+ },
97+ "LockdownAllow": true,
98+ "ReqBody": {
99+ "Type": "object",
100+ "Required": true,
101+ "Properties": {
102+ "LocationIndicatorActive": {
103+ "Type": "boolean"
104+ }
105+ }
106+ },
107+ "Statements": {
108+ "GetSSUPath": {
109+ "Steps": [
110+ {
111+ "Type": "Plugin",
112+ "Formula": "orchestrator.chassis.get_ssu_path(Uri.id)"
113+ }
114+ ]
115+ },
116+ "GetSSULedPath": {
117+ "Steps": [
118+ {
119+ "Type": "Plugin",
120+ "Formula": "orchestrator.chassis.get_ssu_led_path(Uri.id)"
121+ }
122+ ]
123+ },
124+ "IsValidSSUId": {
125+ "Input": "${Statements/GetSSUPath()}",
126+ "Steps": [
127+ {
128+ "Type": "Switch",
129+ "Formula": [
130+ { "Case": "", "To": false },
131+ { "To": true }
132+ ]
133+ }
134+ ]
135+ },
136+ "SetLocationIndicatorActiveState": {
137+ "Input": "${ReqBody/LocationIndicatorActive}",
138+ "Steps": [
139+ {
140+ "Type": "Switch",
141+ "Formula": [
142+ { "Case": true, "To": 5 },
143+ { "Case": false, "To": 0 }
144+ ]
145+ }
146+ ]
147+ }
148+ },
149+ "ProcessingFlow": [
150+ {
151+ "Type": "Method",
152+ "Path": "${Statements/GetSSULedPath()}",
153+ "Interface": "bmc.kepler.Systems.Led",
154+ "Name": "SetState",
155+ "Params": [
156+ "${Statements/SetLocationIndicatorActiveState()}",
157+ 255
158+ ],
159+ "CallIf": {
160+ "${ReqBody/LocationIndicatorActive}": "#WITH"
161+ }
162+ }
163+ ]
164+ }
165+ ]
166+ }
167+ ]
168+}
@@ -10,6 +10,7 @@
10 10 
11local cjson = require('cjson')11local cjson = require('cjson')
12local log = require('mc.logging')12local log = require('mc.logging')
13+local mdb_service = require('mc.mdb.mdb_service')
13local detection_path = '/bmc/kepler/Chassis/1/ThermalSubsystem/LeakDetection'14local detection_path = '/bmc/kepler/Chassis/1/ThermalSubsystem/LeakDetection'
14local detection_interface = 'bmc.kepler.Chassis.LeakDetection'15local detection_interface = 'bmc.kepler.Chassis.LeakDetection'
15 16 
@@ -94,4 +95,45 @@ function m.getpowerstate()
94 end95 end
95end96end
96 97 
98+-- 获取SSU模组Chassis对象路径
99+function m.get_ssu_path(ssu_id)
100+ local filter = cjson.encode({ Id = ssu_id })
101+ local ok, rsp = pcall(mdb_service.get_path, bus, 'bmc.dev.Chassis', filter, false)
102+ if not ok or not rsp or rsp.Path == '' then
103+ return ''
104+ end
105+ return rsp.Path
106+end
107+ 
108+-- 获取SSU模组定位灯对象路径
109+function m.get_ssu_led_path(ssu_id)
110+ local filter = cjson.encode({ Name = ssu_id .. '_UID' })
111+ local ok, rsp = pcall(mdb_service.get_path, bus, 'bmc.kepler.Systems.Led', filter, false)
112+ if not ok or not rsp or rsp.Path == '' then
113+ return ''
114+ end
115+ return rsp.Path
116+end
117+ 
118+-- 获取所有SSU模组的Id列表
119+function m.get_ssu_list()
120+ local ok, res = pcall(mdb_service.get_sub_objects, bus, '/bmc/dev', 4, { 'bmc.dev.Chassis' })
121+ if not ok or not res or not res.SubObjects then
122+ return {}
123+ end
124+ local list = {}
125+ for path, _ in pairs(res.SubObjects) do
126+ local obj_ok, obj = pcall(mdb.get_object, bus, path, 'bmc.dev.Chassis')
127+ if obj_ok and obj and obj.Id and string.match(obj.Id, '^SSU') then
128+ table.insert(list, '/UI/Rest/System/SSUs/' .. obj.Id)
129+ end
130+ end
131+ table.sort(list, function(a, b)
132+ local na = tonumber(string.match(a, 'SSU(%d+)'))
133+ local nb = tonumber(string.match(b, 'SSU(%d+)'))
134+ return na < nb
135+ end)
136+ return list
137+end
138+ 
97return m139return m