通过SetDateTime修改时间是否会被rtc覆盖(无NTP场景)

// 此模板仅供参考,如果不适用可以修改

问题描述

当前存在这样一个需求:NPU节点由于没有NTP配置,所以需要从CPU节点获取时间进行同步,保证时间信息一致

【NPU节点时间RTC时间同步时,当识别到时间与主机时间出现偏差,需要从CPU节点进行一次BMC时间校准同步】

此时存在以下问题:

  1. 在调用SetDateTime修改bmc时间后,是否会被rtc重新同步导致修改后的时间信息覆盖,进而导致时间同步失败;
  2. 如果会被rtc覆盖,那么是否应该调整时间信息获取的优先级,或者调用类似于SetRtcTime的方法同时修改rtc的时间、防止rtc时间同步的影响
  3. 是否需要做一种同步策略,当开始从CPU节点进行时间同步时,参考NTP的策略做成互斥或者不允许其他时间修改的策略

期望结果

期望效果为:NPU节点在轮询CPU节点的时间并且发现时间差值较大时,修改自身时间保持与CPU节点的时间一致,不会被rtc覆盖;

在通过其他方式(例如ipmi命令等)无法修改bmc时间

尝试过的解决方案

当前实现的方案是使用SetDateTime接口设置BMC时间【相关代码如下】:

相关接口:
bmc.kepler.Managers.Time.SetDateTime

-- 使用SetDateTime接口设置BMC时间
function time_sync_service:set_system_time_via_interface(timestamp)
    -- 获取Time对象
    local time_objects = client:GetTimeObjects()
    if not time_objects or next(time_objects) == nil then
        log:error('get time objects failed')
        return false
    end

    local time_obj = next(time_objects)
    
    -- 格式化时间为ISO 8601格式
    local datetime_str = os.date('%Y-%m-%dT%H:%M:%S+00:00', timestamp)
    
    -- 构造SetDateTime请求参数
    local time_params = {
        DateTime = datetime_str
    }
    
    log:info('setting bmc time via SetDateTime: %s', datetime_str)
    
    -- 调用SetDateTime方法
    local ok, result = pcall(time_obj.SetDateTime, context.new(), time_params)
    if not ok then
        log:error('SetDateTime failed: %s', result)
        return false
    end
    
    log:info('set bmc time successfully via SetDateTime: %s', datetime_str)
    return true
end

答案内容由AI生成,仅供参考:
根据您提供的回答内容,已找到明确标有“总结”章节的内容。现原样提取如下:

总结

  1. 结论:在无NTP场景下,SetDateTime 设置的时间确实会被RTC时间覆盖。BMC软件每6秒就会从RTC硬件芯片同步一次时间。
  2. 根源:BMC (bmc_time 组件) 依赖于硬件RTC芯片作为其核心时间源。
  3. 解决方案建议
    • 首选方案:寻找并调用一个直接修改RTC芯片硬件时间的API(如果存在),从根本上更新系统时间。
    • 备选方案:在您的 time_sync_service 中实现一个与RTC同步互斥的机制(例如,设置一个“手动同步中”的标志位,临时挂起RTC轮询同步),待设置完成后再恢复。
点击此处查看详细分析解答

根据您提供的Context中的信息,针对您的问题,回答如下:

1. 通过 SetDateTime 修改 BMC 时间是否会被 RTC 覆盖?

是的,会被覆盖。

Context中,有明确的讨论和直接证据指出了这一点:

  • 社区用户 zhangbaocun 的明确答复:在讨论通过IPMI设置时间的问题时,zhangbaocun 明确指出:“这是ipmi设置的时候bmc的软件时间,每隔6秒bmc又会从rtc同步时间,所以设置了又会被修改”。[reference_id: #3]
  • 社区用户 spjisgood_2lbdb 的补充说明:该用户也确认了相同的现象,指出通过IPMI设置的时间会被RTC的轮询同步覆盖。[reference_id: #3]
  • bmc_time 组件的同步机制bmc_time 组件的 Scanner_Rtc 配置中有一个 Period 属性,其值为 6000(即6000毫秒),这直接证明了系统会每隔6秒从RTC芯片读取并同步一次时间。[reference_id: #2]

因此,在无NTP场景下,单独调用 SetDateTime 修改BMC时间后,该时间会在最多6秒后被RTC时间覆盖,导致同步失败。

2. 如何避免被覆盖及同步策略建议

根据Context中的信息,可以总结出以下策略和结论:

(1)调整时间获取优先级或同时修改RTC时间

  • 同时修改RTC时间是最佳路径:根据 sunpeijun 的回复,bmc_time 组件的 Time_Bmc 对象通过 CpuBrdRtc 属性关联到RTC芯片(Eeprom_Rtc),并通过 Scanner_Rtc 读取芯片的原始二进制数据(包含年月日时分秒)。[reference_id: #2]
    • 这意味着,BMC的时间源是RTC芯片。为了避免被覆盖,最根本的解决方案是直接修改RTC芯片的时间。如果直接调用类似 SetRtcTime 的方法(需要您的系统支持)来修改RTC芯片的寄存器的值,那么BMC时间也会随之更新,且不会被覆盖。
    • 注意Context中并未提供名为 SetRtcTime 的具体API或方法。您需要确认您的BMC固件是否提供了直接操作RTC硬件寄存器的接口。

(2)关于互斥策略(类似于NTP)

  • NTP与RTC的同步是互斥的sunpeijun 在回答RTC同步问题时特别指出:“除此问题外,也要关注是否开启了NTP,因为开启NTP时是不会同步RTC时间的”。[reference_id: #2]
  • 建议实现类似的互斥逻辑:您的设想是合理的。可以参考NTP的策略实现在您的 time_sync_service 中:
    1. 创建一个标志位:当 time_sync_service 从CPU节点获取时间并准备调用 SetDateTime 时,设置一个同步标志(例如 manual_sync_in_progress)。
    2. 暂停RTC同步:在 bmc_time 或相关的RTC同步服务中检查此标志。如果标志为真,则暂停从RTC芯片轮询同步时间的操作。
    3. 恢复RTC同步:在CPU节点时间成功写入BMC后,清除该标志,并恢复正常的RTC同步。

总结

  1. 结论:在无NTP场景下,SetDateTime 设置的时间确实会被RTC时间覆盖。BMC软件每6秒就会从RTC硬件芯片同步一次时间。
  2. 根源:BMC (bmc_time 组件) 依赖于硬件RTC芯片作为其核心时间源。
  3. 解决方案建议
    • 首选方案:寻找并调用一个直接修改RTC芯片硬件时间的API(如果存在),从根本上更新系统时间。
    • 备选方案:在您的 time_sync_service 中实现一个与RTC同步互斥的机制(例如,设置一个“手动同步中”的标志位,临时挂起RTC轮询同步),待设置完成后再恢复。

您当前使用 SetDateTime 的代码实现是正确的,但无法独立解决RTC覆盖的问题。您需要按照以上建议,结合系统提供的其他接口或逻辑来实现时间同步不被覆盖的目标。

接口的初始使用场景就是无rtc场景

所以并没有考虑与rtc做互斥

并且无法简单的设计成接口设置后就弃用RTC

比如RTC短时间内无效,后续恢复了还是否同步

或者RTC时间被设置后BMC预期是要同步的

因此如果有优先级诉求建议在bmc_core sig 申报议题

决策是否增加配置项/固定优先级等方式

这样的话我还有两个问题呢:

  1. 如果我调SetRtcTime这个方法是否可以写入rtc,这样的话也能避免rtc时间覆写;
  2. 如果是默认策略的话,只有内部轮询会修改rtc时间,其他外部接口修改时间(如ipmi命令等)还是正常会被rtc时间覆盖,符合rtc时间同步策略

可以 直接修改RTC时间来修正