From f3e996fc0613bfb1fda94e5a2b4355496ce6fb76 Mon Sep 17 00:00:00 2001 From: Kevin <kevlu@nvidia.com> Date: Thu, 9 Jan 2025 20:45:28 -0500 Subject: [PATCH 1/5] add error log sending to master template and create provisioning function to configure it --- nvflare/lighter/constants.py | 1 + nvflare/lighter/ctx.py | 15 +++++++++++++- nvflare/lighter/impl/static_file.py | 20 ++++++++++++++++++- nvflare/lighter/templates/master_template.yml | 14 +++++++++++-- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/nvflare/lighter/constants.py b/nvflare/lighter/constants.py index a6341d3abb..5a62052901 100644 --- a/nvflare/lighter/constants.py +++ b/nvflare/lighter/constants.py @@ -43,6 +43,7 @@ class PropKey: OVERSEER_END_POINT = "overseer_end_point" ADMIN_PORT = "admin_port" FED_LEARN_PORT = "fed_learn_port" + ALLOW_ERROR_SENDING = "allow_error_sending" class CtxKey(WorkDir, PropKey): diff --git a/nvflare/lighter/ctx.py b/nvflare/lighter/ctx.py index f55cdfd303..8838873787 100644 --- a/nvflare/lighter/ctx.py +++ b/nvflare/lighter/ctx.py @@ -13,6 +13,7 @@ # limitations under the License. import json import os +from calendar import c import yaml @@ -103,8 +104,20 @@ def yaml_load_template_section(self, section_key: str): def json_load_template_section(self, section_key: str): return json.loads(self.get_template_section(section_key)) - def build_from_template(self, dest_dir: str, temp_section: str, file_name, replacement=None, mode="t", exe=False): + def build_from_template( + self, + dest_dir: str, + temp_section: str, + file_name, + replacement=None, + mode="t", + exe=False, + content_modify_cb=None, + **cb_kwargs, + ): section = self.get_template_section(temp_section) if replacement: section = utils.sh_replace(section, replacement) + if content_modify_cb: + section = content_modify_cb(section, **cb_kwargs) utils.write(os.path.join(dest_dir, file_name), section, mode, exe=exe) diff --git a/nvflare/lighter/impl/static_file.py b/nvflare/lighter/impl/static_file.py index 742f2eaac2..a6d85abd31 100644 --- a/nvflare/lighter/impl/static_file.py +++ b/nvflare/lighter/impl/static_file.py @@ -17,6 +17,8 @@ import os import yaml +from sphinx import ret +from sympy import comp, content from nvflare.lighter import utils from nvflare.lighter.constants import CtxKey, OverseerRole, PropKey, ProvFileName, ProvisionMode, TemplateSectionKey @@ -218,7 +220,11 @@ def _build_client(self, client, ctx): ctx.build_from_template(dest_dir, TemplateSectionKey.LOG_CONFIG, ProvFileName.LOG_CONFIG_DEFAULT) ctx.build_from_template( - dest_dir, TemplateSectionKey.LOCAL_CLIENT_RESOURCES, ProvFileName.RESOURCES_JSON_DEFAULT + dest_dir, + TemplateSectionKey.LOCAL_CLIENT_RESOURCES, + ProvFileName.RESOURCES_JSON_DEFAULT, + content_modify_cb=self._modify_error_sender, + client=client, ) ctx.build_from_template( @@ -233,6 +239,18 @@ def _build_client(self, client, ctx): dest_dir = ctx.get_ws_dir(client) ctx.build_from_template(dest_dir, TemplateSectionKey.CLIENT_README, ProvFileName.README_TXT) + def _modify_error_sender(self, section: dict, client: Participant): + allow = client.get_prop_fb(PropKey.ALLOW_ERROR_SENDING, False) + if not allow: + components = section.get("components") + assert isinstance(components, list) + for c in components: + if c["id"] == "error_log_sender": + components.remove(c) + break + + return section + @staticmethod def _check_host_name(host_name: str, server: Participant) -> str: if host_name == server.get_default_host(): diff --git a/nvflare/lighter/templates/master_template.yml b/nvflare/lighter/templates/master_template.yml index 68961077d2..d5ca34a1fc 100644 --- a/nvflare/lighter/templates/master_template.yml +++ b/nvflare/lighter/templates/master_template.yml @@ -97,7 +97,12 @@ local_client_resources: | "id": "process_launcher", "path": "nvflare.app_common.job_launcher.client_process_launcher.ClientProcessJobLauncher", "args": {} - } + }, + { + "id": "error_log_sender", + "path": "nvflare.app_common.logging.log_sender.ErrorLogSender", + "args": {} + }, ] } @@ -226,7 +231,12 @@ local_server_resources: | "id": "process_launcher", "path": "nvflare.app_common.job_launcher.server_process_launcher.ServerProcessJobLauncher", "args": {} - } + }, + { + "id": "log_receiver", + "path": "nvflare.app_common.logging.log_receiver.LogReceiver", + "args": {} + }, ] } From 3bdb1e02105fd42bc8e4e94bfec0adcbef5d35a9 Mon Sep 17 00:00:00 2001 From: Kevin <kevlu@nvidia.com> Date: Fri, 10 Jan 2025 17:09:21 -0500 Subject: [PATCH 2/5] fix ci --- nvflare/lighter/ctx.py | 1 - nvflare/lighter/impl/static_file.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/nvflare/lighter/ctx.py b/nvflare/lighter/ctx.py index 8838873787..ad44fce735 100644 --- a/nvflare/lighter/ctx.py +++ b/nvflare/lighter/ctx.py @@ -13,7 +13,6 @@ # limitations under the License. import json import os -from calendar import c import yaml diff --git a/nvflare/lighter/impl/static_file.py b/nvflare/lighter/impl/static_file.py index a6d85abd31..299712e24e 100644 --- a/nvflare/lighter/impl/static_file.py +++ b/nvflare/lighter/impl/static_file.py @@ -17,8 +17,6 @@ import os import yaml -from sphinx import ret -from sympy import comp, content from nvflare.lighter import utils from nvflare.lighter.constants import CtxKey, OverseerRole, PropKey, ProvFileName, ProvisionMode, TemplateSectionKey From c9d6873abf081df7ab034693b2221f55791a94e3 Mon Sep 17 00:00:00 2001 From: Kevin <kevlu@nvidia.com> Date: Mon, 13 Jan 2025 15:00:34 -0500 Subject: [PATCH 3/5] add docstring --- nvflare/lighter/ctx.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/nvflare/lighter/ctx.py b/nvflare/lighter/ctx.py index ad44fce735..2d0a2ce603 100644 --- a/nvflare/lighter/ctx.py +++ b/nvflare/lighter/ctx.py @@ -114,6 +114,19 @@ def build_from_template( content_modify_cb=None, **cb_kwargs, ): + """Build a file from a template section and writes it to the specified location. + + Args: + dest_dir: destination directory + temp_section: template section key + file_name: file name + replacement: replacement dict + mode: file mode + exe: executable + content_modify_cb: content modification callback, can be included to take the section content as the first argument and return the modified content + cb_kwargs: additional keyword arguments for the callback + + """ section = self.get_template_section(temp_section) if replacement: section = utils.sh_replace(section, replacement) From 5d882b768d88e6eb3b9c1a3f1fee1e6e08a74959 Mon Sep 17 00:00:00 2001 From: Kevin <kevlu@nvidia.com> Date: Wed, 15 Jan 2025 13:28:39 -0500 Subject: [PATCH 4/5] fix problem with CI --- nvflare/lighter/impl/static_file.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nvflare/lighter/impl/static_file.py b/nvflare/lighter/impl/static_file.py index 0c88325df1..e8ffcaaf90 100644 --- a/nvflare/lighter/impl/static_file.py +++ b/nvflare/lighter/impl/static_file.py @@ -274,6 +274,8 @@ def _build_client(self, client, ctx): ctx.build_from_template(dest_dir, TemplateSectionKey.CLIENT_README, ProvFileName.README_TXT) def _modify_error_sender(self, section: dict, client: Participant): + if not isinstance(section, dict): + return section allow = client.get_prop_fb(PropKey.ALLOW_ERROR_SENDING, False) if not allow: components = section.get("components") From 7d7a60ebfdcaacb379e11dfe2797c9a2c1bafc63 Mon Sep 17 00:00:00 2001 From: Kevin <kevlu@nvidia.com> Date: Wed, 15 Jan 2025 14:20:19 -0500 Subject: [PATCH 5/5] try to fix ci --- nvflare/lighter/templates/master_template.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nvflare/lighter/templates/master_template.yml b/nvflare/lighter/templates/master_template.yml index d5ca34a1fc..d9dbd58521 100644 --- a/nvflare/lighter/templates/master_template.yml +++ b/nvflare/lighter/templates/master_template.yml @@ -102,7 +102,7 @@ local_client_resources: | "id": "error_log_sender", "path": "nvflare.app_common.logging.log_sender.ErrorLogSender", "args": {} - }, + } ] } @@ -236,7 +236,7 @@ local_server_resources: | "id": "log_receiver", "path": "nvflare.app_common.logging.log_receiver.LogReceiver", "args": {} - }, + } ] }