From a35496083c199e467301f04a42a2803c963e93af Mon Sep 17 00:00:00 2001 From: "leon.chiang" Date: Wed, 9 Feb 2022 09:21:22 +0800 Subject: [PATCH 1/2] [poed]Change timestamp calculate method and blocking action in cfg save/load 1. Change timestamp calculate method in unix timestamp format 2. When using the poecli cfg save/load function, user must wait poe agent until the chip state or runtime cfg updated. 3. Check ipc file (/run/poe_ipc_event) before open it, make sure it's named pipe. Signed-off-by: leon.chiang --- dentos-poe-agent/opt/poeagent/bin/poecli.py | 18 ++++++- dentos-poe-agent/opt/poeagent/bin/poed.py | 49 ++++++++++++++----- .../opt/poeagent/inc/poe_common.py | 9 ++-- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/dentos-poe-agent/opt/poeagent/bin/poecli.py b/dentos-poe-agent/opt/poeagent/bin/poecli.py index e626297..a261891 100755 --- a/dentos-poe-agent/opt/poeagent/bin/poecli.py +++ b/dentos-poe-agent/opt/poeagent/bin/poecli.py @@ -24,6 +24,7 @@ import imp import sys import subprocess +import stat import os import argparse import time @@ -422,8 +423,13 @@ def is_poed_alive(self): def send_ipc_event(self, action=POECLI_SET): try: - with open(POE_IPC_EVT, "w") as f: - f.write(action) + if check_file(POE_IPC_EVT) == True: + if stat.S_ISFIFO(os.stat(POE_IPC_EVT).st_mode) == False: + print_stderr( + "Invalid IPC channel: {0}".format(POE_IPC_EVT)) + return + with open(POE_IPC_EVT, "w") as f: + f.write(action) except Exception as e: pass @@ -500,7 +506,15 @@ def main(argv): if set_flag == True and poed_alive == True: poecli.send_ipc_event() elif len(cfg_action)>0 and poed_alive == True: + touch_file(POED_BUSY_FLAG) poecli.send_ipc_event(cfg_action) + if wait_poed_busy(title="Wait cfg action", timeout=SAVE_FILE_TIMEOUT) == True: + print_stderr("done") + if check_file(POED_BUSY_FLAG): + remove_file(POED_BUSY_FLAG) + + + if __name__ == '__main__': main(sys.argv) diff --git a/dentos-poe-agent/opt/poeagent/bin/poed.py b/dentos-poe-agent/opt/poeagent/bin/poed.py index 97f76aa..22f0f72 100755 --- a/dentos-poe-agent/opt/poeagent/bin/poed.py +++ b/dentos-poe-agent/opt/poeagent/bin/poed.py @@ -21,6 +21,7 @@ from pathlib import Path import os +import stat import sys import errno import threading @@ -82,13 +83,15 @@ def is_valid_gen_info(self, gen_info): self.is_valid_poe_cfg_ver(gen_info[POE_CFG_VER]) def is_increasing_time_sequence(self, t1, t2): - tDelta = datetime.strptime(t2, TIME_FMT) - \ - datetime.strptime(t1, TIME_FMT) - result1 =(tDelta.days > 0 or tDelta.seconds > 0) - result2 =(tDelta.days * tDelta.seconds) >= 0 - # print_stderr("is_increasing_time_sequence(self, t1, t2): result1={0},result2={1} ".format(str(result1), - # str(result2))) - return result1 and result2 + unixtime1 = time.mktime(datetime.strptime(t1, TIME_FMT).timetuple()) + unixtime2 = time.mktime(datetime.strptime(t2, TIME_FMT).timetuple()) + unixtime_diff = unixtime2-unixtime1 + # print_stderr( + # "unixtime diff: {0}-{1}={2}".format(unixtime2, unixtime1, (unixtime2-unixtime1))) + if unixtime_diff >=0: + return True + else: + return False def is_valid_timestamp(self, timestamp): last_save_time = timestamp[LAST_SAVE_TIME] last_set_time = timestamp[LAST_SET_TIME] @@ -312,6 +315,7 @@ def save_curerent_runtime(self): copyfile(self.runtime_cfg.path(), self.permanent_cfg.path()) + def autosave_main(self): global thread_flag self.log.info("Start autosave thread") @@ -320,6 +324,7 @@ def autosave_main(self): while thread_flag is True: try: if self.rt_counter >= self.cfg_update_intvl_rt: + # print_stderr("Load chip state") cfg_data = self.collect_running_state() if self.failsafe_flag == False: if self.save_poe_cfg(self.runtime_cfg, cfg_data) == True: @@ -413,11 +418,17 @@ def get_poe_agent_stae(self): return self.poe_agent_state def create_poe_set_ipc(self): + try: + if Path(POE_IPC_EVT).exists() and stat.S_ISFIFO(os.stat(POE_IPC_EVT).st_mode) == False: + #Remove non-namedpipe file + remove_file(POE_IPC_EVT) + except: + pass try: os.mkfifo(POE_IPC_EVT) except OSError as oe: if oe.errno != errno.EEXIST: - self.log.err("Failed to open named pipe: %s" % str(e)) + self.log.err("Failed to open named pipe: %s" % str(oe)) def get_prev_pid(): return int(open(POED_PID_PATH, 'r').read()) @@ -504,10 +515,10 @@ def main(argv): if data == POECLI_SET: pa.update_set_time() pa.log.info("Receive a set event from poecli!") - if pa.rt_counter 0: + print_stderr(".", end='') timeout -= 1 else: - print_stderr("\r\rpoe agent busy...timeout") + print_stderr("timeout") return False time.sleep(1) return True From 2054d6f00e71054f974b5690346ce5681aabed17 Mon Sep 17 00:00:00 2001 From: "leon.chiang" Date: Thu, 9 Jun 2022 17:32:31 +0800 Subject: [PATCH 2/2] [poed]Add global flag to blocking autosave thread Add global flag to blocking autosave thread when the ipc_event get save/load actions. Signed-off-by: leon.chiang --- dentos-poe-agent/opt/poeagent/bin/poed.py | 48 ++++++++++++++--------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/dentos-poe-agent/opt/poeagent/bin/poed.py b/dentos-poe-agent/opt/poeagent/bin/poed.py index 22f0f72..b66845f 100755 --- a/dentos-poe-agent/opt/poeagent/bin/poed.py +++ b/dentos-poe-agent/opt/poeagent/bin/poed.py @@ -40,6 +40,7 @@ TIME_FMT = "%Y/%m/%d %H:%M:%S" thread_flag = True +ipc_busy = False class PoeAgentState(object): CLEAN_START = 0 @@ -318,32 +319,36 @@ def save_curerent_runtime(self): def autosave_main(self): global thread_flag + global ipc_busy self.log.info("Start autosave thread") self.rt_counter = 0 self.fail_counter = 0 while thread_flag is True: - try: - if self.rt_counter >= self.cfg_update_intvl_rt: - # print_stderr("Load chip state") - cfg_data = self.collect_running_state() - if self.failsafe_flag == False: - if self.save_poe_cfg(self.runtime_cfg, cfg_data) == True: - self.rt_counter = 0 + if ipc_busy == True: + time.sleep(self.autosave_intvl) + else: + try: + if self.rt_counter >= self.cfg_update_intvl_rt: + # print_stderr("Load chip state") + cfg_data = self.collect_running_state() + if self.failsafe_flag == False: + if self.save_poe_cfg(self.runtime_cfg, cfg_data) == True: + self.rt_counter = 0 + else: + self.log.warn( + "Failed to save cfg data in autosave routine!") else: self.log.warn( - "Failed to save cfg data in autosave routine!") - else: - self.log.warn( - "POE Agent in failsafe mode, stop saving runtime cfg") - self.rt_counter = 0 + "POE Agent in failsafe mode, stop saving runtime cfg") + self.rt_counter = 0 - self.rt_counter += self.autosave_intvl - time.sleep(self.autosave_intvl) - except Exception as e: - self.fail_counter += 1 - self.log.err("An exception in autosave routine: %s, cnt: %d" % - (str(e), self.fail_counter)) - time.sleep(1) + self.rt_counter += self.autosave_intvl + time.sleep(self.autosave_intvl) + except Exception as e: + self.fail_counter += 1 + self.log.err("An exception in autosave routine: %s, cnt: %d" % + (str(e), self.fail_counter)) + time.sleep(1) @PoeAccessExclusiveLock def flush_settings_to_chip(self, poe_cfg): @@ -446,6 +451,7 @@ def save_cur_pid(): def main(argv): global thread_flag + global ipc_busy if os.geteuid() != 0: raise RuntimeError("Warning, poed service must be run as root!") @@ -535,6 +541,7 @@ def main(argv): apply = data_list[3] pa.log.info("CFG Apply: {0}".format(apply)) if action==POED_SAVE_ACTION: + ipc_busy=True touch_file(POED_BUSY_FLAG) pa.rt_counter = 0 cfg_data = pa.collect_running_state() @@ -554,7 +561,9 @@ def main(argv): pa.log.info( "CFG Save: Save runtime setting to {0}".format(file)) remove_file(POED_BUSY_FLAG) + ipc_busy = False elif action == POED_LOAD_ACTION: + ipc_busy = True if file == None: pa.log.info( "CFG Load: Load persistent file") @@ -568,6 +577,7 @@ def main(argv): remove_file(POED_BUSY_FLAG) if result == True: pa.update_set_time() + ipc_busy = False break else: pa.log.notice("Receive data: %s, skipped!" % data)