summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/config_mgmt.py96
-rwxr-xr-xsrc/conf_mode/container.py16
-rwxr-xr-xsrc/conf_mode/interfaces-pppoe.py3
-rwxr-xr-xsrc/op_mode/config_mgmt.py85
-rwxr-xr-xsrc/op_mode/lldp.py13
5 files changed, 208 insertions, 5 deletions
diff --git a/src/conf_mode/config_mgmt.py b/src/conf_mode/config_mgmt.py
new file mode 100755
index 000000000..c681a8405
--- /dev/null
+++ b/src/conf_mode/config_mgmt.py
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import sys
+
+from vyos import ConfigError
+from vyos.config import Config
+from vyos.config_mgmt import ConfigMgmt
+from vyos.config_mgmt import commit_post_hook_dir, commit_hooks
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+
+ base = ['system', 'config-management']
+ if not conf.exists(base):
+ return None
+
+ mgmt = ConfigMgmt(config=conf)
+
+ return mgmt
+
+def verify(_mgmt):
+ return
+
+def generate(mgmt):
+ if mgmt is None:
+ return
+
+ mgmt.initialize_revision()
+
+def apply(mgmt):
+ if mgmt is None:
+ return
+
+ locations = mgmt.locations
+ archive_target = os.path.join(commit_post_hook_dir,
+ commit_hooks['commit_archive'])
+ if locations:
+ try:
+ os.symlink('/usr/bin/config-mgmt', archive_target)
+ except FileExistsError:
+ pass
+ except OSError as exc:
+ raise ConfigError from exc
+ else:
+ try:
+ os.unlink(archive_target)
+ except FileNotFoundError:
+ pass
+ except OSError as exc:
+ raise ConfigError from exc
+
+ revisions = mgmt.max_revisions
+ revision_target = os.path.join(commit_post_hook_dir,
+ commit_hooks['commit_revision'])
+ if revisions > 0:
+ try:
+ os.symlink('/usr/bin/config-mgmt', revision_target)
+ except FileExistsError:
+ pass
+ except OSError as exc:
+ raise ConfigError from exc
+ else:
+ try:
+ os.unlink(revision_target)
+ except FileNotFoundError:
+ pass
+ except OSError as exc:
+ raise ConfigError from exc
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ sys.exit(1)
diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py
index 7567444db..08861053d 100755
--- a/src/conf_mode/container.py
+++ b/src/conf_mode/container.py
@@ -75,6 +75,8 @@ def get_config(config=None):
default_values = defaults(base + ['name'])
if 'port' in default_values:
del default_values['port']
+ if 'volume' in default_values:
+ del default_values['volume']
for name in container['name']:
container['name'][name] = dict_merge(default_values, container['name'][name])
@@ -85,6 +87,13 @@ def get_config(config=None):
default_values = defaults(base + ['name', 'port'])
container['name'][name]['port'][port] = dict_merge(
default_values, container['name'][name]['port'][port])
+ # XXX: T2665: we can not safely rely on the defaults() when there are
+ # tagNodes in place, it is better to blend in the defaults manually.
+ if 'volume' in container['name'][name]:
+ for volume in container['name'][name]['volume']:
+ default_values = defaults(base + ['name', 'volume'])
+ container['name'][name]['volume'][volume] = dict_merge(
+ default_values, container['name'][name]['volume'][volume])
# Delete container network, delete containers
tmp = node_changed(conf, base + ['network'])
@@ -245,7 +254,7 @@ def generate_run_arguments(name, container_config):
env_opt = ''
if 'environment' in container_config:
for k, v in container_config['environment'].items():
- env_opt += f" -e \"{k}={v['value']}\""
+ env_opt += f" --env \"{k}={v['value']}\""
# Publish ports
port = ''
@@ -255,7 +264,7 @@ def generate_run_arguments(name, container_config):
protocol = container_config['port'][portmap]['protocol']
sport = container_config['port'][portmap]['source']
dport = container_config['port'][portmap]['destination']
- port += f' -p {sport}:{dport}/{protocol}'
+ port += f' --publish {sport}:{dport}/{protocol}'
# Bind volume
volume = ''
@@ -263,7 +272,8 @@ def generate_run_arguments(name, container_config):
for vol, vol_config in container_config['volume'].items():
svol = vol_config['source']
dvol = vol_config['destination']
- volume += f' -v {svol}:{dvol}'
+ mode = vol_config['mode']
+ volume += f' --volume {svol}:{dvol}:{mode}'
container_base_cmd = f'--detach --interactive --tty --replace {cap_add} ' \
f'--memory {memory}m --shm-size {shared_memory}m --memory-swap 0 --restart {restart} ' \
diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py
index ee4defa0d..5f0b76f90 100755
--- a/src/conf_mode/interfaces-pppoe.py
+++ b/src/conf_mode/interfaces-pppoe.py
@@ -54,7 +54,8 @@ def get_config(config=None):
# All parameters that can be changed on-the-fly (like interface description)
# should not lead to a reconnect!
for options in ['access-concentrator', 'connect-on-demand', 'service-name',
- 'source-interface', 'vrf', 'no-default-route', 'authentication']:
+ 'source-interface', 'vrf', 'no-default-route',
+ 'authentication', 'host_uniq']:
if is_node_changed(conf, base + [ifname, options]):
pppoe.update({'shutdown_required': {}})
# bail out early - no need to further process other nodes
diff --git a/src/op_mode/config_mgmt.py b/src/op_mode/config_mgmt.py
new file mode 100755
index 000000000..0ffb1468b
--- /dev/null
+++ b/src/op_mode/config_mgmt.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import sys
+import typing
+
+import vyos.opmode
+from vyos.config_mgmt import ConfigMgmt
+
+def show_commit_diff(raw: bool, rev: int, revb: typing.Optional[int],
+ commands: bool):
+ config_mgmt = ConfigMgmt()
+ config_diff = config_mgmt.show_commit_diff(rev, revb, commands)
+
+ if raw:
+ revb = (rev+1) if revb is None else revb
+ if commands:
+ d = {f'config_command_diff_{revb}_{rev}': config_diff}
+ else:
+ d = {f'config_file_diff_{revb}_{rev}': config_diff}
+ return d
+
+ return config_diff
+
+def show_commit_file(raw: bool, rev: int):
+ config_mgmt = ConfigMgmt()
+ config_file = config_mgmt.show_commit_file(rev)
+
+ if raw:
+ d = {f'config_revision_{rev}': config_file}
+ return d
+
+ return config_file
+
+def show_commit_log(raw: bool):
+ config_mgmt = ConfigMgmt()
+
+ msg = ''
+ if config_mgmt.max_revisions == 0:
+ msg = ('commit-revisions is not configured;\n'
+ 'commit log is empty or stale:\n\n')
+
+ data = config_mgmt.get_raw_log_data()
+ if raw:
+ return data
+
+ out = config_mgmt.format_log_data(data)
+ out = msg + out
+
+ return out
+
+def show_commit_log_brief(raw: bool):
+ # used internally for completion help for 'rollback'
+ # option 'raw' will return same as 'show_commit_log'
+ config_mgmt = ConfigMgmt()
+
+ data = config_mgmt.get_raw_log_data()
+ if raw:
+ return data
+
+ out = config_mgmt.format_log_data_brief(data)
+
+ return out
+
+if __name__ == '__main__':
+ try:
+ res = vyos.opmode.run(sys.modules[__name__])
+ if res:
+ print(res)
+ except (ValueError, vyos.opmode.Error) as e:
+ print(e)
+ sys.exit(1)
diff --git a/src/op_mode/lldp.py b/src/op_mode/lldp.py
index dc2b1e0b5..1a1b94783 100755
--- a/src/op_mode/lldp.py
+++ b/src/op_mode/lldp.py
@@ -61,7 +61,14 @@ def _get_raw_data(interface=None, detail=False):
def _get_formatted_output(raw_data):
data_entries = []
- for neighbor in dict_search('lldp.interface', raw_data):
+ tmp = dict_search('lldp.interface', raw_data)
+ if not tmp:
+ return None
+ # One can not always ensure that "interface" is of type list, add safeguard.
+ # E.G. Juniper Networks, Inc. ex2300-c-12t only has a dict, not a list of dicts
+ if isinstance(tmp, dict):
+ tmp = [tmp]
+ for neighbor in tmp:
for local_if, values in neighbor.items():
tmp = []
@@ -80,6 +87,10 @@ def _get_formatted_output(raw_data):
# Capabilities
cap = ''
capabilities = jmespath.search('chassis.[*][0][0].capability', values)
+ # One can not always ensure that "capability" is of type list, add
+ # safeguard. E.G. Unify US-24-250W only has a dict, not a list of dicts
+ if isinstance(capabilities, dict):
+ capabilities = [capabilities]
if capabilities:
for capability in capabilities:
if capability['enabled']: