diff options
-rw-r--r-- | data/templates/container/containers.conf.j2 | 8 | ||||
-rw-r--r-- | interface-definitions/container.xml.in | 43 | ||||
-rw-r--r-- | interface-definitions/include/version/container-version.xml.i | 2 | ||||
-rw-r--r-- | op-mode-definitions/container.xml.in | 7 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_container.py | 10 | ||||
-rwxr-xr-x | src/conf_mode/container.py | 3 | ||||
-rw-r--r-- | src/migration-scripts/container/2-to-3 | 31 | ||||
-rwxr-xr-x | src/op_mode/container.py | 42 |
8 files changed, 106 insertions, 40 deletions
diff --git a/data/templates/container/containers.conf.j2 b/data/templates/container/containers.conf.j2 index 65436801e..414c3e849 100644 --- a/data/templates/container/containers.conf.j2 +++ b/data/templates/container/containers.conf.j2 @@ -170,14 +170,6 @@ default_sysctls = [ # #label = true -# Logging driver for the container. Available options: k8s-file and journald. -# -{% if log_driver is vyos_defined %} -log_driver = "{{ log_driver }}" -{% else %} -#log_driver = "k8s-file" -{% endif %} - # Maximum size allowed for the container log file. Negative numbers indicate # that no size limit is imposed. If positive, it must be >= 8192 to match or # exceed conmon's read buffer. The file is truncated and re-opened so the diff --git a/interface-definitions/container.xml.in b/interface-definitions/container.xml.in index 434bf7528..f20fd7690 100644 --- a/interface-definitions/container.xml.in +++ b/interface-definitions/container.xml.in @@ -532,6 +532,30 @@ </leafNode> </children> </tagNode> + <leafNode name="log-driver"> + <properties> + <help>Configure container log driver</help> + <completionHelp> + <list>k8s-file journald none</list> + </completionHelp> + <valueHelp> + <format>k8s-file</format> + <description>Logs to plain-text file</description> + </valueHelp> + <valueHelp> + <format>journald</format> + <description>Logs to systemd's journal</description> + </valueHelp> + <valueHelp> + <format>none</format> + <description>Disable logging for the container</description> + </valueHelp> + <constraint> + <regex>(k8s-file|journald|none)</regex> + </constraint> + </properties> + <defaultValue>journald</defaultValue> + </leafNode> </children> </tagNode> <tagNode name="network"> @@ -627,25 +651,6 @@ </node> </children> </tagNode> - <leafNode name="log-driver"> - <properties> - <help>Configure container log driver</help> - <completionHelp> - <list>k8s-file journald</list> - </completionHelp> - <valueHelp> - <format>k8s-file</format> - <description>Logs to plain-text json file</description> - </valueHelp> - <valueHelp> - <format>journald</format> - <description>Logs to systemd's journal</description> - </valueHelp> - <constraint> - <regex>(k8s-file|journald)</regex> - </constraint> - </properties> - </leafNode> </children> </node> </interfaceDefinition> diff --git a/interface-definitions/include/version/container-version.xml.i b/interface-definitions/include/version/container-version.xml.i index ed6e942cd..046bacfdc 100644 --- a/interface-definitions/include/version/container-version.xml.i +++ b/interface-definitions/include/version/container-version.xml.i @@ -1,3 +1,3 @@ <!-- include start from include/version/container-version.xml.i --> -<syntaxVersion component='container' version='2'></syntaxVersion> +<syntaxVersion component='container' version='3'></syntaxVersion> <!-- include end --> diff --git a/op-mode-definitions/container.xml.in b/op-mode-definitions/container.xml.in index df28a792c..70ab4b6e5 100644 --- a/op-mode-definitions/container.xml.in +++ b/op-mode-definitions/container.xml.in @@ -89,7 +89,7 @@ <path>container name</path> </completionHelp> </properties> - <command>podman logs --follow --names "$4"</command> + <command>${vyos_op_scripts_dir}/container.py show_log --follow --name "$4"</command> </tagNode> </children> </node> @@ -132,8 +132,7 @@ <path>container name</path> </completionHelp> </properties> - <!-- no admin check --> - <command>podman logs --names "$4"</command> + <command>${vyos_op_scripts_dir}/container.py show_log --name "$4"</command> </tagNode> <node name="network"> <properties> @@ -162,7 +161,7 @@ <path>container name</path> </completionHelp> </properties> - <command>podman logs --names "$4"</command> + <command>${vyos_op_scripts_dir}/container.py show_log --name "$4"</command> </tagNode> </children> </node> diff --git a/smoketest/scripts/cli/test_container.py b/smoketest/scripts/cli/test_container.py index daad3a909..892d7ae0b 100755 --- a/smoketest/scripts/cli/test_container.py +++ b/smoketest/scripts/cli/test_container.py @@ -95,7 +95,7 @@ class TestContainer(VyOSUnitTestSHIM.TestCase): '4096', ] ) - + self.cli_set(base_path + ['name', cont_name, 'log-driver', 'journald']) # commit changes self.cli_commit() @@ -110,13 +110,9 @@ class TestContainer(VyOSUnitTestSHIM.TestCase): tmp = cmd(f'sudo podman exec -it {cont_name} sysctl kernel.msgmax') self.assertEqual(tmp, 'kernel.msgmax = 4096') - def test_log_driver(self): - self.cli_set(base_path + ['log-driver', 'journald']) - - self.cli_commit() + l = cmd_to_json(f'sudo podman container inspect {cont_name}') + self.assertEqual(l['HostConfig']['LogConfig']['Type'], 'journald') - tmp = cmd('podman info --format "{{ .Host.LogDriver }}"') - self.assertEqual(tmp, 'journald') def test_name_server(self): cont_name = 'dns-test' diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index 83e6dee11..a381ace5c 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -310,6 +310,7 @@ def generate_run_arguments(name, container_config): memory = container_config['memory'] shared_memory = container_config['shared_memory'] restart = container_config['restart'] + log_driver = container_config['log_driver'] # Add sysctl options sysctl_opt = '' @@ -408,7 +409,7 @@ def generate_run_arguments(name, container_config): name_server += f'--dns {ns}' container_base_cmd = f'--detach --interactive --tty --replace {capabilities} {privileged} --cpus {cpu_quota} {sysctl_opt} ' \ - f'--memory {memory}m --shm-size {shared_memory}m --memory-swap 0 --restart {restart} ' \ + f'--memory {memory}m --shm-size {shared_memory}m --memory-swap 0 --restart {restart} --log-driver={log_driver} ' \ f'--name {name} {hostname} {device} {port} {name_server} {volume} {tmpfs} {env_opt} {label} {uid} {host_pid}' entrypoint = '' diff --git a/src/migration-scripts/container/2-to-3 b/src/migration-scripts/container/2-to-3 new file mode 100644 index 000000000..54c6ec4c8 --- /dev/null +++ b/src/migration-scripts/container/2-to-3 @@ -0,0 +1,31 @@ +# Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library. If not, see <http://www.gnu.org/licenses/>. + +# T7473: container: allow log-driver to be set per container + +from vyos.configtree import ConfigTree + +def migrate(config: ConfigTree) -> None: + log_base = ['container', 'log-driver'] + container_base = ['container', 'name'] + + if not config.exists(log_base): + return + else: + log_driver = config.return_value(log_base) + for container in config.list_nodes(container_base): + # Set the log-driver for each container + config.set(container_base + [container, 'log-driver'], value=log_driver) + config.delete(log_base) diff --git a/src/op_mode/container.py b/src/op_mode/container.py index 05f65df1f..f93df0fc4 100755 --- a/src/op_mode/container.py +++ b/src/op_mode/container.py @@ -16,6 +16,7 @@ import json import sys +import subprocess from vyos.utils.process import cmd from vyos.utils.process import rc_cmd @@ -109,6 +110,47 @@ def restart(name: str): print(f'Container "{name}" restarted!') return output +def show_log(name: str, follow: bool = False, raw: bool = False): + """ + Show or monitor logs for a specific container. + Use --follow to continuously stream logs. + """ + from vyos.configquery import ConfigTreeQuery + conf = ConfigTreeQuery() + container = conf.get_config_dict(['container', 'name', name], get_first_key=True, with_recursive_defaults=True) + log_type = container.get('log-driver') + if log_type == 'k8s-file': + if follow: + log_command_list = ['sudo', 'podman', 'logs', '--follow', '--names', name] + else: + log_command_list = ['sudo', 'podman', 'logs', '--names', name] + elif log_type == 'journald': + if follow: + log_command_list = ['journalctl', '--follow', '--unit', f'vyos-container-{name}.service'] + else: + log_command_list = ['journalctl', '-e', '--no-pager', '--unit', f'vyos-container-{name}.service'] + elif log_type == 'none': + print(f'Container "{name}" has disabled logs.') + return None + else: + raise vyos.opmode.InternalError(f'Unknown log type "{log_type}" for container "{name}".') + + process = None + try: + process = subprocess.Popen(log_command_list, + stdout=sys.stdout, + stderr=sys.stderr) + process.wait() + except KeyboardInterrupt: + if process: + process.terminate() + process.wait() + return None + except Exception as e: + raise vyos.opmode.InternalError(f"Error starting logging command: {e} ") + return None + + if __name__ == '__main__': try: res = vyos.opmode.run(sys.modules[__name__]) |