Merged
【57cdc9b33e1f526334d496df144e3fdc】feat:优化BIOS备件配置恢复 #262
liucongAdd on Aug 17
【57cdc9b33e1f526334d496df144e3fdc】feat:优化BIOS备件配置恢复 #262
Merged
liucongAdd on Aug 17
Total: 5 files changed+267-60
@@ -527,6 +527,30 @@ sequenceDiagram
527- 摘要计算在文件写入后异步 `skynet.fork` 执行,不阻塞 IPMI 响应;多系统各独立,无消息队列堆积风险。527- 摘要计算在文件写入后异步 `skynet.fork` 执行,不阻塞 IPMI 响应;多系统各独立,无消息队列堆积风险。
528 528 
529### 2.2.6 可靠性分析529### 2.2.6 可靠性分析
530+ 
531+#### SFMEA 分析表
532+ 
533+| 用例编号 | 关键步骤 | 故障模式 | 故障影响 | 严重程度 | 容错措施 | 可定位性信息 | 故障注入方法 | 是否已落入DT(未落入说明原因) | 备注 |
534+|---------|---------|---------|---------|-------|---------|------------|------------|----------------------------|------|
535+| TC-SFMEA-001 | 初始化兜底备份 | ST-002 文件写入失败(备份副本拷贝失败) | 兜底备份缺失,后续备件更换比对无基准,误判为不一致而置位 | 严重 | 备份失败打印 error 日志不阻断初始化;下次上报或重启重试 | ERROR [bios]system %s backup %s fail | 源文件目录置为只读/无写权限后触发 init_backup | 可以落入DT(test_init_backup_missing/error 已覆盖) | |
536+| TC-SFMEA-002 | 初始化兜底备份 | DT-002 数据掉电丢失(补备过程中断电/异常退出) | 备份文件半写入或未落盘,备份与源不一致,恢复时用损坏备份 | 严重 | backup_file 拷贝完成后再落盘;拷贝过程应用临时文件+重命名原子写 | ERROR cache not flushed / backup incomplete | 补备过程中强制断电 | 需要开发分析:断电时机难以在DT精确注入 | |
537+| TC-SFMEA-003 | 带内文件写入 | ST-005 磁盘空间不足(/data/opt 空间满) | 源文件写入失败或备份拷贝失败,备份缺失致无法恢复配置 | 严重 | 写入前检查剩余空间;失败打印 error 日志不阻断 IPMI 响应,下次上报重试 | ERROR No space left on device;df -h 检查 | 填充磁盘至满后触发 WriteFileToBmc | 需要开发分析:磁盘空间耗尽环境构造受限 | |
538+| TC-SFMEA-004 | 带内文件写入 | ST-003 文件内容损坏/格式错误(BIOS 上报半写入/空文件) | 空或损坏的源文件被当作正常配置备份,覆盖有效历史备份,后续比对失效 | 严重 | backup_file 前用 is_file_nonempty 校验源文件非空;备份内容回读校验 | ERROR source file empty / content corrupt | 上报空文件或截断文件 | 可以落入DT(test_backup_file_error 已覆盖) | |
539+| TC-SFMEA-005 | 备份副本刷新 | DT-001 数据校验不一致(拷贝后未校验,备份与源内容不一致) | 备份内容与源不一致,备件更换比对时误判一致/不一致,恢复出错误配置 | 严重 | 拷贝成功后回读计算哈希与源文件比对(compare_file_with_backup 自校验),不一致则重试 | WARN backup checksum mismatch | 拷贝后篡改备份文件再比对 | 可以落入DT(test_replace_flag_same_noset/diff_set 已覆盖) | |
540+| TC-SFMEA-006 | 备件更换检测 | IPC-003 D-Bus/MDB 调用失败 / SV-003 依赖服务返回错误(GetComponentComponentObject 失败) | 无法获取 ReplaceFlag,按容错视为未更换,备件更换后漏置位,用户配置丢失 | 严重 | 沿用既有 pcall 容错,失败时记录日志并视为未更换;下次上报重试刷新 | ERROR get_replace_flag failed;告警 ReplaceFlagQueryFailed | mock GetComponentComponentObject 返回异常/超时 | 需要开发分析:依赖组件服务环境与 mock 构造复杂 | |
541+| TC-SFMEA-007 | 备件更换检测 | HW-006 硬件状态异常(replace_flag 属性读取值不准确/抖动) | replace_flag 误置 true 触发误置位,或漏置导致不恢复 | 严重 | 状态变化前先连续确认;依赖既有组件状态上报机制;误置位可经恢复流程修正 | WARN replace_flag unexpected change | 模拟 replace_flag 多次翻转 | 可以落入DT(test_replace_trigger_set 已覆盖) | |
542+| TC-SFMEA-008 | 内容比对 | ST-001 文件读取失败(备份文件读取失败) | 备份读取失败视为不一致而误置位,触发不必要恢复;或读源失败无法比对 | 一般 | compare_file_with_backup 内备份不存在/读取失败返回 false 前打印日志,供人工确认 | ERROR read backup file fail / hash nil | 删除或改名备份文件后触发比对 | 可以落入DT(test_replace_flag_diff_set 已覆盖) | |
543+| TC-SFMEA-009 | 内容比对 | ST-003 文件内容损坏/格式错误(备份文件被破坏/哈希异常) | 备份损坏致比对误判,恢复时导入失败,配置无法恢复 | 严重 | 比对前校验备份文件完整性(存在且非空);损坏时告警并保留损坏备份供人工恢复 | ERROR backup file corrupt / hash mismatch;告警 BackupCorrupted | 篡改备份文件内容 | 可以落入DT(test_import_old_setup_partial_fail 已覆盖) | |
544+| TC-SFMEA-010 | 恢复标记置位与持久化 | DT-002 数据掉电丢失 / SQL-008 数据库持久化失败(置位后未及时落库) | NeedRecoverSetup 丢失,重启后不恢复配置,用户配置永久丢失 | 致命 | 置位后立即 info_db:save() 持久化;持久化失败重试并告警 | CRIT NeedRecoverSetup persist fail;log:notice 置位事件 | 置位后立即断电;mock save 失败 | 需要开发分析:断电时机难以在DT精确注入 | |
545+| TC-SFMEA-011 | 配置恢复 ImportOldSetup | SC-002 证书校验失败(安全启动证书导入失败) | secureboot 证书未恢复,恢复流程保留 NeedRecoverSetup 反复重试,其余配置已恢复 | 一般 | 失败项打印 error 日志并保留标记等待重试;恢复流程不部分提交,但证书为追加语义可重入 | ERROR recover secureboot fail / cert import failed | 构造非法证书串导入 | 可以落入DT(test_import_old_setup_secureboot/partial_fail 已覆盖) | |
546+| TC-SFMEA-012 | 配置恢复 ImportOldSetup | IPC-005 通信对端无响应(PolicyConfig IMU 下发无响应/超时) | ConfigValue 恢复挂起或超时,恢复任务超时异常,配置未恢复 | 严重 | import_json 既有超时机制;恢复任务设置超时并标记 Exception 保留 NeedRecoverSetup 重试 | ERROR IMU no response / policy config send timeout | 断连 IMU 通道后触发恢复 | 需要开发分析:IMU 对端不可达场景依赖跨组件环境 | |
547+| TC-SFMEA-013 | 配置恢复 ImportOldSetup | TS-001 操作时序错乱(BIOS 状态不允许导入 secureboot) | 安全启动证书导入被拒,恢复部分失败,配置不完整 | 严重 | 恢复前置校验 BIOS_STARTUP_STATE_OFF/POST_STAGE_FINISH,不满足则挂起等待上报完成后再触发 | ERROR BIOS state not allow import;log:notice 记录当前状态 | 在 BIOS POST 中触发恢复 | 可以落入DT(test_import_old_setup_all_ok 预置状态已覆盖) | |
548+| TC-SFMEA-014 | 配置恢复 ImportOldSetup | ST-003 文件内容损坏/格式错误(备份 JSON 格式错误/结构不符) | 备份解析失败导入失败,配置无法恢复,保留标记反复重试 | 严重 | 导入前 get_file_json 解析校验,格式错误明确报错并保留标记;提供人工介入恢复路径 | ERROR recover currentvalue/ConfigValue fail / parse error | 写入畸形 JSON 备份文件 | 可以落入DT(test_import_old_setup_partial_fail 已覆盖) | |
549+| TC-SFMEA-015 | 配置恢复 ImportOldSetup | DT-001 数据校验不一致(部分导入成功不回滚,多处数据不一致) | setting.json/new_secureboot.json/ConfigValue.json 部分更新,后续上报比对产生新差异 | 一般 | 设计约定为追加语义不回滚,仅保留标记重试;重试前按备份整体覆盖,最终收敛一致 | WARN partial import, keep NeedRecoverSetup | 置某份备份缺失后触发恢复 | 可以落入DT(test_import_old_setup_partial_fail 已覆盖) | |
550+| TC-SFMEA-016 | 多系统并发备份/恢复 | CC-001 竞态条件(多 system 并发上报备份/比对/置位,同对象多文件并发写) | 备份与比对交错,置位状态竞态,备份文件错乱 | 一般 | 各 system_id 路径隔离 + 既有 skynet_queue 串行化写文件;set_need_recover_setup 经对象串行执行 | log:notice 记录各 system 置位/备份事件 | 双系统同时上报不同文件 | 可以落入DT(test_multihost_isolation/recover_setup_parallel 已覆盖) | |
551+| TC-SFMEA-017 | 配置恢复任务执行 | CC-004 异步任务异常 / TS-002 超时未完成(恢复任务异常/挂起,recover_setup_task 未复位) | 任务异常退出后 recover_setup_task 未清,本对象后续恢复被防重入拒绝,无法重试 | 严重 | 任务 finally 复位 recover_setup_task=nil;任务设置超时监控,异常时更新任务为 Exception | ERROR recover setup task abnormal / task stuck | 恢复逻辑中抛异常强制退出任务 | 可以落入DT(test_recover_setup_task_reentry 已覆盖) | |
552+| TC-SFMEA-018 | 恢复后备份刷新与标记清除 | SQL-002 数据库写入失败(清除标记持久化失败) | NeedRecoverSetup 未清除,每次上报重复触发恢复,或清除成功但备份未刷新致反复比对 | 严重 | set_need_recover_setup(false) 持久化失败时告警并重试;先清标记再刷新备份,顺序保证 | ERROR clear NeedRecoverSetup persist fail | mock info_db save 失败 | 可以落入DT(test_need_recover_persist 已覆盖) | |
553+ 
530| 编号 | 场景 | 问题描述 | 可靠性影响 | 问题级别 | 建议解决方案/需求 | 讨论结果 | 跟踪人 | 备注 |554| 编号 | 场景 | 问题描述 | 可靠性影响 | 问题级别 | 建议解决方案/需求 | 讨论结果 | 跟踪人 | 备注 |
531| --- | --- | --- | --- | --- | --- | --- | --- | --- |555| --- | --- | --- | --- | --- | --- | --- | --- | --- |
532| 1 | 备份时源文件/目录异常 | 备份副本写入失败 | 无法恢复配置 | 中 | 备份失败打印 error 日志,不阻断主流程;下次上报重试 | | liucong | |556| 1 | 备份时源文件/目录异常 | 备份副本写入失败 | 无法恢复配置 | 中 | 备份失败打印 error 日志,不阻断主流程;下次上报重试 | | liucong | |
@@ -39,6 +39,13 @@ local table_cache = require('mc.table_cache')
39local tbl_cache = table_cache.new()39local tbl_cache = table_cache.new()
40local file_service = require('service.file_service')40local file_service = require('service.file_service')
41 41 
42+local pwd_backup_map = {
43+ { obj_def.PROPERTY_BIOS_SETUP_PWD_OLD, obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP },
44+ { obj_def.PROPERTY_BIOS_SETUP_PWD_NEW, obj_def.PROPERTY_BIOS_SETUP_PWD_NEW_BACKUP },
45+ { obj_def.PROPERTY_BIOS_USER_SETUP_PWD_OLD, obj_def.PROPERTY_BIOS_USER_SETUP_PWD_OLD_BACKUP },
46+ { obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW, obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW_BACKUP },
47+}
48+ 
42local function get_valid_version(version)49local function get_valid_version(version)
43 local valid_version = ''50 local valid_version = ''
44 for name in string.gmatch(version, '[%w.]') do51 for name in string.gmatch(version, '[%w.]') do
@@ -122,7 +129,7 @@ function bios_object:get_replace_flag()
122 log:error('[bios] system %s get cpu board replace flag failed', self.system_id)129 log:error('[bios] system %s get cpu board replace flag failed', self.system_id)
123 return130 return
124 end131 end
125- self.replace_flag = (obj['ReplaceFlag'] == 0)132+ self.replace_flag = (obj['ReplaceFlag'] == 1)
126end133end
127 134 
128function bios_object:async_fetch_info()135function bios_object:async_fetch_info()
@@ -439,6 +446,10 @@ function bios_object:select_info_db()
439 NewSetupPassword = '',446 NewSetupPassword = '',
440 UserOldSetupPassword = '',447 UserOldSetupPassword = '',
441 UserNewSetupPassword = '',448 UserNewSetupPassword = '',
449+ OldSetupPasswordBackup = '',
450+ NewSetupPasswordBackup = '',
451+ UserOldSetupPasswordBackup = '',
452+ UserNewSetupPasswordBackup = '',
442 SystemStartupState = 0,453 SystemStartupState = 0,
443 ResetBiosToDefaultsPending = false,454 ResetBiosToDefaultsPending = false,
444 BiosBootStage = 0,455 BiosBootStage = 0,
@@ -463,6 +474,10 @@ function bios_object:select_info_db()
463 NewSetupPassword = '',474 NewSetupPassword = '',
464 UserOldSetupPassword = '',475 UserOldSetupPassword = '',
465 UserNewSetupPassword = '',476 UserNewSetupPassword = '',
477+ OldSetupPasswordBackup = '',
478+ NewSetupPasswordBackup = '',
479+ UserOldSetupPasswordBackup = '',
480+ UserNewSetupPasswordBackup = '',
466 SystemStartupState = 0,481 SystemStartupState = 0,
467 ResetBiosToDefaultsPending = false,482 ResetBiosToDefaultsPending = false,
468 BiosBootStage = 0,483 BiosBootStage = 0,
@@ -1254,18 +1269,17 @@ function bios_object:init_backup()
1254 self:backup_config_file(f.name, f.src)1269 self:backup_config_file(f.name, f.src)
1255 end1270 end
1256 end1271 end
1257- local pwd_map = {1272+ local need_pwd_recover = false
1258- { obj_def.PROPERTY_BIOS_SETUP_PWD_OLD, obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP },1273+ for _, pair in ipairs(pwd_backup_map) do
1259- { obj_def.PROPERTY_BIOS_SETUP_PWD_NEW, obj_def.PROPERTY_BIOS_SETUP_PWD_NEW_BACKUP },
1260- { obj_def.PROPERTY_BIOS_USER_SETUP_PWD_OLD, obj_def.PROPERTY_BIOS_USER_SETUP_PWD_OLD_BACKUP },
1261- { obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW, obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW_BACKUP },
1262- }
1263- for _, pair in ipairs(pwd_map) do
1264 local src, bak = pair[1], pair[2]1274 local src, bak = pair[1], pair[2]
1265- if #self:get_prop(src) > 0 then1275+ local bak_val = self.info_db[bak]
1276+ if #bak_val == 0 and #self:get_prop(src) > 0 then
1266 self:set_db_prop(bak, self:get_prop(src))1277 self:set_db_prop(bak, self:get_prop(src))
1278+ elseif bak_val ~= self:get_prop(src) then
1279+ need_pwd_recover = true
1267 end1280 end
1268 end1281 end
1282+ self:set_need_recover_setup(need_pwd_recover)
1269end1283end
1270 1284 
1271-- 备份三份文件中指定的一份(复制为同目录_bak副本)1285-- 备份三份文件中指定的一份(复制为同目录_bak副本)
@@ -1382,7 +1396,20 @@ function bios_object:recover_bios_setup(ctx)
1382 log:error('[bios]system %s recover ConfigValue fail, err is %s', self.system_id, err3)1396 log:error('[bios]system %s recover ConfigValue fail, err is %s', self.system_id, err3)
1383 end1397 end
1384 1398 
1385- if ok1 and ok2 and ok3 then1399+ local ok4, err4 = pcall(function()
1400+ for _, pair in ipairs(pwd_backup_map) do
1401+ local src, bak = pair[1], pair[2]
1402+ local bak_val = self.info_db[bak]
1403+ if #bak_val > 0 then
1404+ self:set_prop(src, bak_val)
1405+ end
1406+ end
1407+ end)
1408+ if not ok4 then
1409+ log:error('[bios]system %s recover setup password fail, err is %s', self.system_id, err4)
1410+ end
1411+ 
1412+ if ok1 and ok2 and ok3 and ok4 then
1386 log:notice('[bios]system %s ImportOldSetup success, clear NeedRecoverSetup', self.system_id)1413 log:notice('[bios]system %s ImportOldSetup success, clear NeedRecoverSetup', self.system_id)
1387 self:set_need_recover_setup(false)1414 self:set_need_recover_setup(false)
1388 else1415 else
@@ -348,13 +348,13 @@ function bios_service:get_all_objs()
348 return self.bios_object_collection348 return self.bios_object_collection
349end349end
350 350 
351-function bios_service:recover_bios_setup(ctx, system_id, path)351+function bios_service:recover_bios_setup(ctx, system_id)
352 local bios_obj = self:get_obj(system_id)352 local bios_obj = self:get_obj(system_id)
353 if not bios_obj then353 if not bios_obj then
354 log:error('[bios]recover_bios_setup: system id(%s) invalid', system_id)354 log:error('[bios]recover_bios_setup: system id(%s) invalid', system_id)
355 error(base_messages.InternalError())355 error(base_messages.InternalError())
356 end356 end
357- return bios_obj:recover_bios_setup(ctx, path)357+ return bios_obj:recover_bios_setup(ctx)
358end358end
359 359 
360function bios_service:notify_dft_mode()360function bios_service:notify_dft_mode()
@@ -60,19 +60,32 @@ local function make_bios_obj()
60 return bios_obj60 return bios_obj
61end61end
62 62 
63+local function make_info_db()
64+ return {
65+ OldSetupPassword = '',
66+ NewSetupPassword = '',
67+ UserOldSetupPassword = '',
68+ UserNewSetupPassword = '',
69+ OldSetupPasswordBackup = '',
70+ NewSetupPasswordBackup = '',
71+ UserOldSetupPasswordBackup = '',
72+ UserNewSetupPasswordBackup = '',
73+ }
74+end
75+ 
63TestBackupConfig = {}76TestBackupConfig = {}
64 77 
65function TestBackupConfig:test_get_replace_flag_success()78function TestBackupConfig:test_get_replace_flag_success()
66 local bios_obj = make_bios_obj()79 local bios_obj = make_bios_obj()
67 local get_component_mock = client.GetComponentComponentObject80 local get_component_mock = client.GetComponentComponentObject
68 client.GetComponentComponentObject = function(_, req)81 client.GetComponentComponentObject = function(_, req)
69- return { ReplaceFlag = 0 }82+ return { ReplaceFlag = 1 }
70 end83 end
71 bios_obj:get_replace_flag()84 bios_obj:get_replace_flag()
72 lu.assertIsTrue(bios_obj.replace_flag)85 lu.assertIsTrue(bios_obj.replace_flag)
73 86 
74 client.GetComponentComponentObject = function(_, req)87 client.GetComponentComponentObject = function(_, req)
75- return { ReplaceFlag = 1 }88+ return { ReplaceFlag = 0 }
76 end89 end
77 bios_obj:get_replace_flag()90 bios_obj:get_replace_flag()
78 lu.assertIsFalse(bios_obj.replace_flag)91 lu.assertIsFalse(bios_obj.replace_flag)
@@ -111,7 +124,9 @@ end
111 124 
112function TestBackupConfig:test_init_backup_without_bak()125function TestBackupConfig:test_init_backup_without_bak()
113 local bios_obj = make_bios_obj()126 local bios_obj = make_bios_obj()
127+ bios_obj.info_db = make_info_db()
114 local backup_count = 0128 local backup_count = 0
129+ local need_recover = nil
115 bios_obj.backup_config_file = function(_, file_name, src_path)130 bios_obj.backup_config_file = function(_, file_name, src_path)
116 backup_count = backup_count + 1131 backup_count = backup_count + 1
117 return true132 return true
@@ -131,6 +146,9 @@ function TestBackupConfig:test_init_backup_without_bak()
131 bios_obj.set_db_prop = function(_, key, value)146 bios_obj.set_db_prop = function(_, key, value)
132 db_prop[key] = value147 db_prop[key] = value
133 end148 end
149+ bios_obj.set_need_recover_setup = function(_, value)
150+ need_recover = value
151+ end
134 prop_map[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD] = 'old_pwd_enc'152 prop_map[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD] = 'old_pwd_enc'
135 prop_map[obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW] = 'user_new_pwd_enc'153 prop_map[obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW] = 'user_new_pwd_enc'
136 154 
@@ -139,12 +157,15 @@ function TestBackupConfig:test_init_backup_without_bak()
139 lu.assertEquals(db_prop[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP], 'old_pwd_enc')157 lu.assertEquals(db_prop[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP], 'old_pwd_enc')
140 lu.assertEquals(db_prop[obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW_BACKUP], 'user_new_pwd_enc')158 lu.assertEquals(db_prop[obj_def.PROPERTY_BIOS_USER_SETUP_PWD_NEW_BACKUP], 'user_new_pwd_enc')
141 lu.assertIsNil(db_prop[obj_def.PROPERTY_BIOS_SETUP_PWD_NEW_BACKUP])159 lu.assertIsNil(db_prop[obj_def.PROPERTY_BIOS_SETUP_PWD_NEW_BACKUP])
160+ lu.assertIsFalse(need_recover)
142 bs_util.is_file_nonempty = is_nonempty_mock161 bs_util.is_file_nonempty = is_nonempty_mock
143end162end
144 163 
145function TestBackupConfig:test_init_backup_with_existing_bak()164function TestBackupConfig:test_init_backup_with_existing_bak()
146 local bios_obj = make_bios_obj()165 local bios_obj = make_bios_obj()
166+ bios_obj.info_db = make_info_db()
147 local backup_count = 0167 local backup_count = 0
168+ local need_recover = nil
148 bios_obj.backup_config_file = function(_, file_name, src_path)169 bios_obj.backup_config_file = function(_, file_name, src_path)
149 backup_count = backup_count + 1170 backup_count = backup_count + 1
150 return true171 return true
@@ -157,8 +178,64 @@ function TestBackupConfig:test_init_backup_with_existing_bak()
157 return ''178 return ''
158 end179 end
159 bios_obj.set_db_prop = function() end180 bios_obj.set_db_prop = function() end
181+ bios_obj.set_need_recover_setup = function(_, value)
182+ need_recover = value
183+ end
160 bios_obj:init_backup()184 bios_obj:init_backup()
161 lu.assertEquals(backup_count, 0)185 lu.assertEquals(backup_count, 0)
186+ lu.assertIsFalse(need_recover)
187+ bs_util.is_file_nonempty = is_nonempty_mock
188+end
189+ 
190+function TestBackupConfig:test_init_backup_pwd_mismatch_sets_recover()
191+ local bios_obj = make_bios_obj()
192+ local info_db = make_info_db()
193+ info_db[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP] = 'backup_old'
194+ bios_obj.info_db = info_db
195+ local need_recover = nil
196+ bios_obj.backup_config_file = function() end
197+ local is_nonempty_mock = bs_util.is_file_nonempty
198+ bs_util.is_file_nonempty = function(path)
199+ return true
200+ end
201+ bios_obj.get_prop = function(_, key)
202+ if key == obj_def.PROPERTY_BIOS_SETUP_PWD_OLD then
203+ return 'current_old'
204+ end
205+ return ''
206+ end
207+ bios_obj.set_db_prop = function() end
208+ bios_obj.set_need_recover_setup = function(_, value)
209+ need_recover = value
210+ end
211+ bios_obj:init_backup()
212+ lu.assertIsTrue(need_recover)
213+ bs_util.is_file_nonempty = is_nonempty_mock
214+end
215+ 
216+function TestBackupConfig:test_init_backup_pwd_match_no_recover()
217+ local bios_obj = make_bios_obj()
218+ local info_db = make_info_db()
219+ info_db[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP] = 'same_pwd'
220+ bios_obj.info_db = info_db
221+ local need_recover = nil
222+ bios_obj.backup_config_file = function() end
223+ local is_nonempty_mock = bs_util.is_file_nonempty
224+ bs_util.is_file_nonempty = function(path)
225+ return true
226+ end
227+ bios_obj.get_prop = function(_, key)
228+ if key == obj_def.PROPERTY_BIOS_SETUP_PWD_OLD then
229+ return 'same_pwd'
230+ end
231+ return ''
232+ end
233+ bios_obj.set_db_prop = function() end
234+ bios_obj.set_need_recover_setup = function(_, value)
235+ need_recover = value
236+ end
237+ bios_obj:init_backup()
238+ lu.assertIsFalse(need_recover)
162 bs_util.is_file_nonempty = is_nonempty_mock239 bs_util.is_file_nonempty = is_nonempty_mock
163end240end
164 241 
@@ -274,14 +351,11 @@ local function build_full_backup_json()
274 }351 }
275end352end
276 353 
277-function TestBackupConfig:test_recover_bios_setup_import_success()354+local function mock_recover_services()
278- local bios_obj = make_bios_obj()
279- bios_obj.obj.ComponentName = 'Bios'
280 local import_calls = {}355 local import_calls = {}
281 local sb_calls = {}356 local sb_calls = {}
282 local boot_cert_calls = {}357 local boot_cert_calls = {}
283 local boot_crl_calls = {}358 local boot_crl_calls = {}
284- local need_recover = nil
285 359 
286 local file_service_new_mock = file_service.new360 local file_service_new_mock = file_service.new
287 file_service.new = function()361 file_service.new = function()
@@ -309,6 +383,26 @@ function TestBackupConfig:test_recover_bios_setup_import_success()
309 end,383 end,
310 }384 }
311 end385 end
386+ 
387+ local function restore()
388+ file_service.new = file_service_new_mock
389+ bios_factory.get_service = get_service_mock
390+ end
391+ 
392+ return {
393+ import_calls = import_calls,
394+ sb_calls = sb_calls,
395+ boot_cert_calls = boot_cert_calls,
396+ boot_crl_calls = boot_crl_calls,
397+ restore = restore,
398+ }
399+end
400+ 
401+function TestBackupConfig:test_recover_bios_setup_import_success()
402+ local bios_obj = make_bios_obj()
403+ bios_obj.info_db = make_info_db()
404+ bios_obj.obj.ComponentName = 'Bios'
405+ local mocks = mock_recover_services()
312 local get_file_json_mock = bs_util.get_file_json406 local get_file_json_mock = bs_util.get_file_json
313 bs_util.get_file_json = function(path)407 bs_util.get_file_json = function(path)
314 if path and string.find(path, 'currentvalue_bak') then408 if path and string.find(path, 'currentvalue_bak') then
@@ -322,70 +416,54 @@ function TestBackupConfig:test_recover_bios_setup_import_success()
322 end416 end
323 return nil417 return nil
324 end418 end
419+ local need_recover = nil
325 bios_obj.set_need_recover_setup = function(_, value)420 bios_obj.set_need_recover_setup = function(_, value)
326 need_recover = value421 need_recover = value
327 end422 end
328 423 
329 bios_obj:recover_bios_setup({})424 bios_obj:recover_bios_setup({})
330- lu.assertEquals(#import_calls, 2)425+ lu.assertEquals(#mocks.import_calls, 2)
331- lu.assertEquals(import_calls[1], 'WebConfig')426+ lu.assertEquals(mocks.import_calls[1], 'WebConfig')
332- lu.assertEquals(import_calls[2], 'PolicyConfig')427+ lu.assertEquals(mocks.import_calls[2], 'PolicyConfig')
333- lu.assertEquals(#sb_calls, 2)428+ lu.assertEquals(#mocks.sb_calls, 2)
334- lu.assertEquals(sb_calls[1].db_type, prop_def.INTERACT_KEY_SECUREBOOT_DB)429+ lu.assertEquals(mocks.sb_calls[1].db_type, prop_def.INTERACT_KEY_SECUREBOOT_DB)
335- lu.assertEquals(sb_calls[1].cert_str, 'CERT_DB_1')430+ lu.assertEquals(mocks.sb_calls[1].cert_str, 'CERT_DB_1')
336- lu.assertEquals(sb_calls[2].db_type, prop_def.INTERACT_KEY_SECUREBOOT_DBX)431+ lu.assertEquals(mocks.sb_calls[2].db_type, prop_def.INTERACT_KEY_SECUREBOOT_DBX)
337- lu.assertEquals(#boot_cert_calls, 1)432+ lu.assertEquals(#mocks.boot_cert_calls, 1)
338- lu.assertEquals(boot_cert_calls[1], 'BOOT_CERT_1')433+ lu.assertEquals(mocks.boot_cert_calls[1], 'BOOT_CERT_1')
339- lu.assertEquals(#boot_crl_calls, 1)434+ lu.assertEquals(#mocks.boot_crl_calls, 1)
340- lu.assertEquals(boot_crl_calls[1], 'BOOT_CRL_1')435+ lu.assertEquals(mocks.boot_crl_calls[1], 'BOOT_CRL_1')
341 lu.assertIsFalse(need_recover)436 lu.assertIsFalse(need_recover)
342 437 
343- file_service.new = file_service_new_mock438+ mocks.restore()
344- bios_factory.get_service = get_service_mock
345 bs_util.get_file_json = get_file_json_mock439 bs_util.get_file_json = get_file_json_mock
346end440end
347 441 
348function TestBackupConfig:test_recover_bios_setup_no_backup()442function TestBackupConfig:test_recover_bios_setup_no_backup()
349 local bios_obj = make_bios_obj()443 local bios_obj = make_bios_obj()
444+ bios_obj.info_db = make_info_db()
350 bios_obj.obj.ComponentName = 'Bios'445 bios_obj.obj.ComponentName = 'Bios'
351- local import_calls = {}446+ local mocks = mock_recover_services()
352- local need_recover = nil
353- 
354- local file_service_new_mock = file_service.new
355- file_service.new = function()
356- return {
357- import_json = function(_, ctx, file_type, content, sys_id)
358- import_calls[#import_calls + 1] = file_type
359- end,
360- }
361- end
362- local get_service_mock = bios_factory.get_service
363- bios_factory.get_service = function(name)
364- return {
365- import_secure_boot_certificate = function() end,
366- import_boot_certificate = function() end,
367- import_boot_crl = function() end,
368- }
369- end
370 local get_file_json_mock = bs_util.get_file_json447 local get_file_json_mock = bs_util.get_file_json
371 bs_util.get_file_json = function(path)448 bs_util.get_file_json = function(path)
372 return nil449 return nil
373 end450 end
451+ local need_recover = nil
374 bios_obj.set_need_recover_setup = function(_, value)452 bios_obj.set_need_recover_setup = function(_, value)
375 need_recover = value453 need_recover = value
376 end454 end
377 455 
378 bios_obj:recover_bios_setup({})456 bios_obj:recover_bios_setup({})
379- lu.assertEquals(#import_calls, 0)457+ lu.assertEquals(#mocks.import_calls, 0)
380 lu.assertIsFalse(need_recover)458 lu.assertIsFalse(need_recover)
381 459 
382- file_service.new = file_service_new_mock460+ mocks.restore()
383- bios_factory.get_service = get_service_mock
384 bs_util.get_file_json = get_file_json_mock461 bs_util.get_file_json = get_file_json_mock
385end462end
386 463 
387function TestBackupConfig:test_recover_bios_setup_partial_fail()464function TestBackupConfig:test_recover_bios_setup_partial_fail()
388 local bios_obj = make_bios_obj()465 local bios_obj = make_bios_obj()
466+ bios_obj.info_db = make_info_db()
389 bios_obj.obj.ComponentName = 'Bios'467 bios_obj.obj.ComponentName = 'Bios'
390 local need_recover = nil468 local need_recover = nil
391 469 
@@ -423,26 +501,91 @@ function TestBackupConfig:test_recover_bios_setup_partial_fail()
423 bs_util.get_file_json = get_file_json_mock501 bs_util.get_file_json = get_file_json_mock
424end502end
425 503 
504+function TestBackupConfig:test_recover_bios_setup_password_recover_success()
505+ local bios_obj = make_bios_obj()
506+ local info_db = make_info_db()
507+ info_db[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP] = 'old_bak'
508+ info_db[obj_def.PROPERTY_BIOS_SETUP_PWD_NEW_BACKUP] = 'new_bak'
509+ bios_obj.info_db = info_db
510+ bios_obj.obj.ComponentName = 'Bios'
511+ local mocks = mock_recover_services()
512+ local set_prop_calls = {}
513+ bios_obj.set_prop = function(_, key, value)
514+ set_prop_calls[#set_prop_calls + 1] = { key = key, value = value }
515+ return true
516+ end
517+ local get_file_json_mock = bs_util.get_file_json
518+ bs_util.get_file_json = function(path)
519+ return nil
520+ end
521+ local need_recover = nil
522+ bios_obj.set_need_recover_setup = function(_, value)
523+ need_recover = value
524+ end
525+ 
526+ bios_obj:recover_bios_setup({})
527+ lu.assertEquals(#set_prop_calls, 2)
528+ lu.assertEquals(set_prop_calls[1].key, obj_def.PROPERTY_BIOS_SETUP_PWD_OLD)
529+ lu.assertEquals(set_prop_calls[1].value, 'old_bak')
530+ lu.assertEquals(set_prop_calls[2].key, obj_def.PROPERTY_BIOS_SETUP_PWD_NEW)
531+ lu.assertEquals(set_prop_calls[2].value, 'new_bak')
532+ lu.assertIsFalse(need_recover)
533+ 
534+ mocks.restore()
535+ bs_util.get_file_json = get_file_json_mock
536+end
537+ 
538+function TestBackupConfig:test_recover_bios_setup_password_recover_fail()
539+ local bios_obj = make_bios_obj()
540+ local info_db = make_info_db()
541+ info_db[obj_def.PROPERTY_BIOS_SETUP_PWD_OLD_BACKUP] = 'old_bak'
542+ bios_obj.info_db = info_db
543+ bios_obj.obj.ComponentName = 'Bios'
544+ local mocks = mock_recover_services()
545+ bios_obj.set_prop = function()
546+ error('set_prop fail')
547+ end
548+ local get_file_json_mock = bs_util.get_file_json
549+ bs_util.get_file_json = function(path)
550+ return nil
551+ end
552+ local need_recover = nil
553+ bios_obj.set_need_recover_setup = function(_, value)
554+ need_recover = value
555+ end
556+ 
557+ local ok, err = pcall(bios_obj.recover_bios_setup, bios_obj, {})
558+ lu.assertFalse(ok)
559+ lu.assertStrContains(err, 'Type=Bios')
560+ lu.assertIsNil(need_recover)
561+ 
562+ mocks.restore()
563+ bs_util.get_file_json = get_file_json_mock
564+end
565+ 
426function TestBackupConfig:test_bios_service_recover_bios_setup()566function TestBackupConfig:test_bios_service_recover_bios_setup()
427 local bios_obj = make_bios_obj()567 local bios_obj = make_bios_obj()
428 local recover_called = false568 local recover_called = false
429- bios_obj.recover_bios_setup = function(_, ctx, path)569+ local recover_ctx = nil
570+ bios_obj.recover_bios_setup = function(_, ctx)
430 recover_called = true571 recover_called = true
572+ recover_ctx = ctx
431 return true573 return true
432 end574 end
433 local get_obj_mock = bios_service.get_obj575 local get_obj_mock = bios_service.get_obj
434 bios_service.get_obj = function(_, sys_id)576 bios_service.get_obj = function(_, sys_id)
435 return bios_obj577 return bios_obj
436 end578 end
437- local ret = bios_service:recover_bios_setup({}, 1, '/test/path')579+ local ret = bios_service:recover_bios_setup({}, 1)
438 lu.assertIsTrue(ret)580 lu.assertIsTrue(ret)
439 lu.assertIsTrue(recover_called)581 lu.assertIsTrue(recover_called)
582+ lu.assertNotNil(recover_ctx)
440 583 
441 bios_service.get_obj = function()584 bios_service.get_obj = function()
442 return nil585 return nil
443 end586 end
444 local ok = pcall(function()587 local ok = pcall(function()
445- return bios_service:recover_bios_setup({}, 2, '/test/path')588+ return bios_service:recover_bios_setup({}, 2)
446 end)589 end)
447 lu.assertIsFalse(ok)590 lu.assertIsFalse(ok)
448 bios_service.get_obj = get_obj_mock591 bios_service.get_obj = get_obj_mock
@@ -544,6 +687,7 @@ end
544 687 
545function TestBackupConfig:test_recover_bios_setup_secureboot_fail()688function TestBackupConfig:test_recover_bios_setup_secureboot_fail()
546 local bios_obj = make_bios_obj()689 local bios_obj = make_bios_obj()
690+ bios_obj.info_db = make_info_db()
547 bios_obj.obj.ComponentName = 'Bios'691 bios_obj.obj.ComponentName = 'Bios'
548 692 
549 local file_service_new_mock = file_service.new693 local file_service_new_mock = file_service.new
@@ -11,6 +11,7 @@ local bios_service = require('service.bios_service')
11local lu = require('luaunit')11local lu = require('luaunit')
12local open_db = require('bios.db')12local open_db = require('bios.db')
13local vos = require('utils.vos')13local vos = require('utils.vos')
14+local file_sec = require('utils.file')
14 15 
15local test_common = require('test_common.utils')16local test_common = require('test_common.utils')
16local bus = test_common.dbus_launch('../.dbus', nil, true)17local bus = test_common.dbus_launch('../.dbus', nil, true)
@@ -29,19 +30,29 @@ end
29 30 
30function TestWriteToBmc:test_write_firmware_data_to_bmc()31function TestWriteToBmc:test_write_firmware_data_to_bmc()
31 local bios_ser = bios_service.new(bus, construct_db())32 local bios_ser = bios_service.new(bus, construct_db())
32- bios_ser.get_data_opt = function() end
33 bios_ser.dft_mode = true33 bios_ser.dft_mode = true
34 bios_ser.upg_fw_file = false34 bios_ser.upg_fw_file = false
35+ local offset = 0
35 bios_ser.get_data_opt = function()36 bios_ser.get_data_opt = function()
36 local obj = {}37 local obj = {}
37 obj.get_offset = function()38 obj.get_offset = function()
38- return 039+ return offset
39 end40 end
41+ obj.set_offset = function() end
40 return obj42 return obj
41 end43 end
44+ local open_s_mock = file_sec.open_s
45+ file_sec.open_s = function(path, mode)
46+ return {
47+ write = function()
48+ return true
49+ end,
50+ close = function() end,
51+ }
52+ end
42 53 
43 local ok = pcall(function()54 local ok = pcall(function()
44- bios_ser:write_firmware_data_to_bmc({}, {}, 1)55+ bios_ser:write_firmware_data_to_bmc({}, { FileData = 'data' }, 1)
45 end)56 end)
46 lu.assertEquals(ok, true)57 lu.assertEquals(ok, true)
47 58 
@@ -58,10 +69,11 @@ function TestWriteToBmc:test_write_firmware_data_to_bmc()
58 },69 },
59 }70 }
60 ok = pcall(function()71 ok = pcall(function()
61- bios_ser:write_firmware_data_to_bmc({}, {}, {}, ctx)72+ bios_ser:write_firmware_data_to_bmc({}, { FileData = 'data' }, 1, ctx)
62 end)73 end)
63 lu.assertEquals(ok, true)74 lu.assertEquals(ok, true)
64 vos.get_file_accessible = get_file_accessible75 vos.get_file_accessible = get_file_accessible
76+ file_sec.open_s = open_s_mock
65end77end
66 78 
67function TestWriteToBmc:test_write_prepare_firmware_data_to_bmc()79function TestWriteToBmc:test_write_prepare_firmware_data_to_bmc()