summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2025-11-05 12:21:14 -0600
committerGitHub <noreply@github.com>2025-11-05 12:21:14 -0600
commitfd56247b9a0f278a2cc7553bef46005dfd78e759 (patch)
treed2ea48159b34c35d049633f9df49f8cea79840be /python
parentcc60275ab0db2c45f2ad7387d6a91a96fa9d6337 (diff)
parenta02b7d54c561368d8a9a22a0643a1b4fb1e90345 (diff)
downloadvyos-1x-fd56247b9a0f278a2cc7553bef46005dfd78e759.tar.gz
vyos-1x-fd56247b9a0f278a2cc7553bef46005dfd78e759.zip
Merge pull request #4807 from jestabro/vyconf-session-management
T7910: Standardize vyconf session resource management
Diffstat (limited to 'python')
-rw-r--r--python/vyos/configsession.py22
-rw-r--r--python/vyos/configsource.py7
-rw-r--r--python/vyos/proto/vyconf_pb2.py150
-rw-r--r--python/vyos/proto/vyconf_proto.py12
-rw-r--r--python/vyos/vyconf_session.py115
5 files changed, 184 insertions, 122 deletions
diff --git a/python/vyos/configsession.py b/python/vyos/configsession.py
index f0a22d930..62ce34b22 100644
--- a/python/vyos/configsession.py
+++ b/python/vyos/configsession.py
@@ -16,6 +16,7 @@
import os
import re
import sys
+import weakref
import subprocess
from tempfile import NamedTemporaryFile
from typing import TypeAlias
@@ -199,10 +200,15 @@ class ConfigSession(object):
self.shared = shared
+ if not self.shared and self._vyconf_session:
+ self._finalizer = weakref.finalize(
+ self, self.finalize_vyconf, self._vyconf_session
+ )
+
def __del__(self):
if self.shared:
return
- if self._vyconf_session is None:
+ if not vyconf_backend():
try:
output = (
subprocess.check_output(
@@ -223,12 +229,14 @@ class ConfigSession(object):
'Could not tear down session {0}: {1}'.format(self.__session_id, e),
file=sys.stderr,
)
- else:
- if self._vyconf_session.session_changed():
- Warn('Exiting with uncommitted changes')
- self._vyconf_session.discard()
- self._vyconf_session.exit_config_mode()
- self._vyconf_session.teardown()
+
+ @classmethod
+ def finalize_vyconf(cls, session: VyconfSession):
+ if session.session_changed():
+ Warn('Exiting with uncommitted changes')
+ session.discard()
+ session.exit_config_mode()
+ session.teardown()
def __run_command(self, cmd_list):
p = subprocess.Popen(
diff --git a/python/vyos/configsource.py b/python/vyos/configsource.py
index 6bf794d9e..33852a182 100644
--- a/python/vyos/configsource.py
+++ b/python/vyos/configsource.py
@@ -355,13 +355,6 @@ class ConfigSourceVyconfSession(ConfigSource):
# cf. T7374
self._level = []
- def __del__(self):
- try:
- if not self._vyconf_session.in_session():
- self._vyconf_session.teardown()
- except AttributeError:
- pass
-
def get_level(self):
return self._level
diff --git a/python/vyos/proto/vyconf_pb2.py b/python/vyos/proto/vyconf_pb2.py
index 164dbc1d7..61047a068 100644
--- a/python/vyos/proto/vyconf_pb2.py
+++ b/python/vyos/proto/vyconf_pb2.py
@@ -13,85 +13,87 @@ _sym_db = _symbol_database.Default()
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cvyconf.proto\"\xc5\x17\n\x07Request\x12!\n\x06prompt\x18\x01 \x01(\x0b\x32\x0f.Request.PromptH\x00\x12.\n\rsetup_session\x18\x02 \x01(\x0b\x32\x15.Request.SetupSessionH\x00\x12\x1b\n\x03set\x18\x03 \x01(\x0b\x32\x0c.Request.SetH\x00\x12!\n\x06\x64\x65lete\x18\x04 \x01(\x0b\x32\x0f.Request.DeleteH\x00\x12!\n\x06rename\x18\x05 \x01(\x0b\x32\x0f.Request.RenameH\x00\x12\x1d\n\x04\x63opy\x18\x06 \x01(\x0b\x32\r.Request.CopyH\x00\x12#\n\x07\x63omment\x18\x07 \x01(\x0b\x32\x10.Request.CommentH\x00\x12!\n\x06\x63ommit\x18\x08 \x01(\x0b\x32\x0f.Request.CommitH\x00\x12%\n\x08rollback\x18\t \x01(\x0b\x32\x11.Request.RollbackH\x00\x12\x1f\n\x05merge\x18\n \x01(\x0b\x32\x0e.Request.MergeH\x00\x12\x1d\n\x04save\x18\x0b \x01(\x0b\x32\r.Request.SaveH\x00\x12*\n\x0bshow_config\x18\x0c \x01(\x0b\x32\x13.Request.ShowConfigH\x00\x12!\n\x06\x65xists\x18\r \x01(\x0b\x32\x0f.Request.ExistsH\x00\x12&\n\tget_value\x18\x0e \x01(\x0b\x32\x11.Request.GetValueH\x00\x12(\n\nget_values\x18\x0f \x01(\x0b\x32\x12.Request.GetValuesH\x00\x12.\n\rlist_children\x18\x10 \x01(\x0b\x32\x15.Request.ListChildrenH\x00\x12)\n\x0brun_op_mode\x18\x11 \x01(\x0b\x32\x12.Request.RunOpModeH\x00\x12#\n\x07\x63onfirm\x18\x12 \x01(\x0b\x32\x10.Request.ConfirmH\x00\x12\x43\n\x18\x65nter_configuration_mode\x18\x13 \x01(\x0b\x32\x1f.Request.EnterConfigurationModeH\x00\x12\x41\n\x17\x65xit_configuration_mode\x18\x14 \x01(\x0b\x32\x1e.Request.ExitConfigurationModeH\x00\x12%\n\x08validate\x18\x15 \x01(\x0b\x32\x11.Request.ValidateH\x00\x12%\n\x08teardown\x18\x16 \x01(\x0b\x32\x11.Request.TeardownH\x00\x12\x30\n\x0ereload_reftree\x18\x17 \x01(\x0b\x32\x16.Request.ReloadReftreeH\x00\x12\x1d\n\x04load\x18\x18 \x01(\x0b\x32\r.Request.LoadH\x00\x12#\n\x07\x64iscard\x18\x19 \x01(\x0b\x32\x10.Request.DiscardH\x00\x12\x32\n\x0fsession_changed\x18\x1a \x01(\x0b\x32\x17.Request.SessionChangedH\x00\x12/\n\x0esession_of_pid\x18\x1b \x01(\x0b\x32\x15.Request.SessionOfPidH\x00\x12\x30\n\x0esession_exists\x18\x1c \x01(\x0b\x32\x16.Request.SessionExistsH\x00\x12(\n\nget_config\x18\x1d \x01(\x0b\x32\x12.Request.GetConfigH\x00\x12\"\n\x07\x61ux_set\x18\x1e \x01(\x0b\x32\x0f.Request.AuxSetH\x00\x12(\n\naux_delete\x18\x1f \x01(\x0b\x32\x12.Request.AuxDeleteH\x00\x1a\x08\n\x06Prompt\x1a\x83\x01\n\x0cSetupSession\x12\x12\n\nclient_pid\x18\x01 \x02(\x05\x12\x1a\n\x12\x63lient_application\x18\x02 \x01(\t\x12\x14\n\x0con_behalf_of\x18\x03 \x01(\x05\x12\x13\n\x0b\x63lient_user\x18\x04 \x01(\t\x12\x18\n\x10\x63lient_sudo_user\x18\x05 \x01(\t\x1a\"\n\x0cSessionOfPid\x12\x12\n\nclient_pid\x18\x01 \x02(\x05\x1a\x1e\n\rSessionExists\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a\x1a\n\tGetConfig\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a \n\x08Teardown\x12\x14\n\x0con_behalf_of\x18\x01 \x01(\x05\x1a\x46\n\x08Validate\x12\x0c\n\x04Path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1a\x13\n\x03Set\x12\x0c\n\x04path\x18\x01 \x03(\t\x1a\x16\n\x06\x44\x65lete\x12\x0c\n\x04path\x18\x01 \x03(\t\x1a>\n\x06\x41uxSet\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x13\n\x0bscript_name\x18\x02 \x02(\t\x12\x11\n\ttag_value\x18\x03 \x01(\t\x1a\x41\n\tAuxDelete\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x13\n\x0bscript_name\x18\x02 \x02(\t\x12\x11\n\ttag_value\x18\x03 \x01(\t\x1a\x18\n\x07\x44iscard\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a\x1f\n\x0eSessionChanged\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a\x41\n\x06Rename\x12\x12\n\nedit_level\x18\x01 \x03(\t\x12\x0e\n\x06source\x18\x02 \x02(\t\x12\x13\n\x0b\x64\x65stination\x18\x03 \x02(\t\x1a?\n\x04\x43opy\x12\x12\n\nedit_level\x18\x01 \x03(\t\x12\x0e\n\x06source\x18\x02 \x02(\t\x12\x13\n\x0b\x64\x65stination\x18\x03 \x02(\t\x1a(\n\x07\x43omment\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x0f\n\x07\x63omment\x18\x02 \x02(\t\x1aT\n\x06\x43ommit\x12\x0f\n\x07\x63onfirm\x18\x01 \x01(\x08\x12\x17\n\x0f\x63onfirm_timeout\x18\x02 \x01(\x05\x12\x0f\n\x07\x63omment\x18\x03 \x01(\t\x12\x0f\n\x07\x64ry_run\x18\x04 \x01(\x08\x1a\x1c\n\x08Rollback\x12\x10\n\x08revision\x18\x01 \x02(\x05\x1aO\n\x04Load\x12\x10\n\x08location\x18\x01 \x02(\t\x12\x0e\n\x06\x63\x61\x63hed\x18\x02 \x02(\x08\x12%\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x15.Request.ConfigFormat\x1aU\n\x05Merge\x12\x10\n\x08location\x18\x01 \x02(\t\x12\x13\n\x0b\x64\x65structive\x18\x02 \x02(\x08\x12%\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x15.Request.ConfigFormat\x1a?\n\x04Save\x12\x10\n\x08location\x18\x01 \x02(\t\x12%\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x15.Request.ConfigFormat\x1a\x41\n\nShowConfig\x12\x0c\n\x04path\x18\x01 \x03(\t\x12%\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x15.Request.ConfigFormat\x1a\x16\n\x06\x45xists\x12\x0c\n\x04path\x18\x01 \x03(\t\x1a\x46\n\x08GetValue\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1aG\n\tGetValues\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1aJ\n\x0cListChildren\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1aG\n\tRunOpMode\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1a\t\n\x07\x43onfirm\x1aG\n\x16\x45nterConfigurationMode\x12\x11\n\texclusive\x18\x01 \x02(\x08\x12\x1a\n\x12override_exclusive\x18\x02 \x02(\x08\x1a\x17\n\x15\x45xitConfigurationMode\x1a%\n\rReloadReftree\x12\x14\n\x0con_behalf_of\x18\x01 \x01(\x05\"#\n\x0c\x43onfigFormat\x12\t\n\x05\x43URLY\x10\x00\x12\x08\n\x04JSON\x10\x01\")\n\x0cOutputFormat\x12\x0c\n\x08OutPlain\x10\x00\x12\x0b\n\x07OutJSON\x10\x01\x42\x05\n\x03msg\";\n\x0fRequestEnvelope\x12\r\n\x05token\x18\x01 \x01(\t\x12\x19\n\x07request\x18\x02 \x02(\x0b\x32\x08.Request\"S\n\x08Response\x12\x17\n\x06status\x18\x01 \x02(\x0e\x32\x07.Errnum\x12\x0e\n\x06output\x18\x02 \x01(\t\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12\x0f\n\x07warning\x18\x04 \x01(\t*\xd2\x01\n\x06\x45rrnum\x12\x0b\n\x07SUCCESS\x10\x00\x12\x08\n\x04\x46\x41IL\x10\x01\x12\x10\n\x0cINVALID_PATH\x10\x02\x12\x11\n\rINVALID_VALUE\x10\x03\x12\x16\n\x12\x43OMMIT_IN_PROGRESS\x10\x04\x12\x18\n\x14\x43ONFIGURATION_LOCKED\x10\x05\x12\x12\n\x0eINTERNAL_ERROR\x10\x06\x12\x15\n\x11PERMISSION_DENIED\x10\x07\x12\x17\n\x13PATH_ALREADY_EXISTS\x10\x08\x12\x16\n\x12UNCOMMITED_CHANGES\x10\t')
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cvyconf.proto\"\xb2\x18\n\x07Request\x12!\n\x06prompt\x18\x01 \x01(\x0b\x32\x0f.Request.PromptH\x00\x12.\n\rsetup_session\x18\x02 \x01(\x0b\x32\x15.Request.SetupSessionH\x00\x12\x1b\n\x03set\x18\x03 \x01(\x0b\x32\x0c.Request.SetH\x00\x12!\n\x06\x64\x65lete\x18\x04 \x01(\x0b\x32\x0f.Request.DeleteH\x00\x12!\n\x06rename\x18\x05 \x01(\x0b\x32\x0f.Request.RenameH\x00\x12\x1d\n\x04\x63opy\x18\x06 \x01(\x0b\x32\r.Request.CopyH\x00\x12#\n\x07\x63omment\x18\x07 \x01(\x0b\x32\x10.Request.CommentH\x00\x12!\n\x06\x63ommit\x18\x08 \x01(\x0b\x32\x0f.Request.CommitH\x00\x12%\n\x08rollback\x18\t \x01(\x0b\x32\x11.Request.RollbackH\x00\x12\x1f\n\x05merge\x18\n \x01(\x0b\x32\x0e.Request.MergeH\x00\x12\x1d\n\x04save\x18\x0b \x01(\x0b\x32\r.Request.SaveH\x00\x12*\n\x0bshow_config\x18\x0c \x01(\x0b\x32\x13.Request.ShowConfigH\x00\x12!\n\x06\x65xists\x18\r \x01(\x0b\x32\x0f.Request.ExistsH\x00\x12&\n\tget_value\x18\x0e \x01(\x0b\x32\x11.Request.GetValueH\x00\x12(\n\nget_values\x18\x0f \x01(\x0b\x32\x12.Request.GetValuesH\x00\x12.\n\rlist_children\x18\x10 \x01(\x0b\x32\x15.Request.ListChildrenH\x00\x12)\n\x0brun_op_mode\x18\x11 \x01(\x0b\x32\x12.Request.RunOpModeH\x00\x12#\n\x07\x63onfirm\x18\x12 \x01(\x0b\x32\x10.Request.ConfirmH\x00\x12\x43\n\x18\x65nter_configuration_mode\x18\x13 \x01(\x0b\x32\x1f.Request.EnterConfigurationModeH\x00\x12\x41\n\x17\x65xit_configuration_mode\x18\x14 \x01(\x0b\x32\x1e.Request.ExitConfigurationModeH\x00\x12%\n\x08validate\x18\x15 \x01(\x0b\x32\x11.Request.ValidateH\x00\x12%\n\x08teardown\x18\x16 \x01(\x0b\x32\x11.Request.TeardownH\x00\x12\x30\n\x0ereload_reftree\x18\x17 \x01(\x0b\x32\x16.Request.ReloadReftreeH\x00\x12\x1d\n\x04load\x18\x18 \x01(\x0b\x32\r.Request.LoadH\x00\x12#\n\x07\x64iscard\x18\x19 \x01(\x0b\x32\x10.Request.DiscardH\x00\x12\x32\n\x0fsession_changed\x18\x1a \x01(\x0b\x32\x17.Request.SessionChangedH\x00\x12/\n\x0esession_of_pid\x18\x1b \x01(\x0b\x32\x15.Request.SessionOfPidH\x00\x12\x30\n\x0esession_exists\x18\x1c \x01(\x0b\x32\x16.Request.SessionExistsH\x00\x12(\n\nget_config\x18\x1d \x01(\x0b\x32\x12.Request.GetConfigH\x00\x12\"\n\x07\x61ux_set\x18\x1e \x01(\x0b\x32\x0f.Request.AuxSetH\x00\x12(\n\naux_delete\x18\x1f \x01(\x0b\x32\x12.Request.AuxDeleteH\x00\x12.\n\rshow_sessions\x18 \x01(\x0b\x32\x15.Request.ShowSessionsH\x00\x1a\x08\n\x06Prompt\x1a\x83\x01\n\x0cSetupSession\x12\x12\n\nclient_pid\x18\x01 \x02(\x05\x12\x1a\n\x12\x63lient_application\x18\x02 \x01(\t\x12\x14\n\x0con_behalf_of\x18\x03 \x01(\x05\x12\x13\n\x0b\x63lient_user\x18\x04 \x01(\t\x12\x18\n\x10\x63lient_sudo_user\x18\x05 \x01(\t\x1a\"\n\x0cSessionOfPid\x12\x12\n\nclient_pid\x18\x01 \x02(\x05\x1a\x1e\n\rSessionExists\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a\x1a\n\tGetConfig\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a \n\x08Teardown\x12\x14\n\x0con_behalf_of\x18\x01 \x01(\x05\x1a\x46\n\x08Validate\x12\x0c\n\x04Path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1a\x13\n\x03Set\x12\x0c\n\x04path\x18\x01 \x03(\t\x1a\x16\n\x06\x44\x65lete\x12\x0c\n\x04path\x18\x01 \x03(\t\x1a>\n\x06\x41uxSet\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x13\n\x0bscript_name\x18\x02 \x02(\t\x12\x11\n\ttag_value\x18\x03 \x01(\t\x1a\x41\n\tAuxDelete\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x13\n\x0bscript_name\x18\x02 \x02(\t\x12\x11\n\ttag_value\x18\x03 \x01(\t\x1a\x18\n\x07\x44iscard\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a\x1f\n\x0eSessionChanged\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\x1a\x41\n\x06Rename\x12\x12\n\nedit_level\x18\x01 \x03(\t\x12\x0e\n\x06source\x18\x02 \x02(\t\x12\x13\n\x0b\x64\x65stination\x18\x03 \x02(\t\x1a?\n\x04\x43opy\x12\x12\n\nedit_level\x18\x01 \x03(\t\x12\x0e\n\x06source\x18\x02 \x02(\t\x12\x13\n\x0b\x64\x65stination\x18\x03 \x02(\t\x1a(\n\x07\x43omment\x12\x0c\n\x04path\x18\x01 \x03(\t\x12\x0f\n\x07\x63omment\x18\x02 \x02(\t\x1aT\n\x06\x43ommit\x12\x0f\n\x07\x63onfirm\x18\x01 \x01(\x08\x12\x17\n\x0f\x63onfirm_timeout\x18\x02 \x01(\x05\x12\x0f\n\x07\x63omment\x18\x03 \x01(\t\x12\x0f\n\x07\x64ry_run\x18\x04 \x01(\x08\x1a\x1c\n\x08Rollback\x12\x10\n\x08revision\x18\x01 \x02(\x05\x1aO\n\x04Load\x12\x10\n\x08location\x18\x01 \x02(\t\x12\x0e\n\x06\x63\x61\x63hed\x18\x02 \x02(\x08\x12%\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x15.Request.ConfigFormat\x1aU\n\x05Merge\x12\x10\n\x08location\x18\x01 \x02(\t\x12\x13\n\x0b\x64\x65structive\x18\x02 \x02(\x08\x12%\n\x06\x66ormat\x18\x03 \x01(\x0e\x32\x15.Request.ConfigFormat\x1a?\n\x04Save\x12\x10\n\x08location\x18\x01 \x02(\t\x12%\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x15.Request.ConfigFormat\x1a\x41\n\nShowConfig\x12\x0c\n\x04path\x18\x01 \x03(\t\x12%\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x15.Request.ConfigFormat\x1a\x16\n\x06\x45xists\x12\x0c\n\x04path\x18\x01 \x03(\t\x1a\x46\n\x08GetValue\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1aG\n\tGetValues\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1aJ\n\x0cListChildren\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1aG\n\tRunOpMode\x12\x0c\n\x04path\x18\x01 \x03(\t\x12,\n\routput_format\x18\x02 \x01(\x0e\x32\x15.Request.OutputFormat\x1a\t\n\x07\x43onfirm\x1aG\n\x16\x45nterConfigurationMode\x12\x11\n\texclusive\x18\x01 \x02(\x08\x12\x1a\n\x12override_exclusive\x18\x02 \x02(\x08\x1a\x17\n\x15\x45xitConfigurationMode\x1a%\n\rReloadReftree\x12\x14\n\x0con_behalf_of\x18\x01 \x01(\x05\x1a;\n\x0cShowSessions\x12\x14\n\x0c\x65xclude_self\x18\x01 \x02(\x08\x12\x15\n\rexclude_other\x18\x02 \x02(\x08\"#\n\x0c\x43onfigFormat\x12\t\n\x05\x43URLY\x10\x00\x12\x08\n\x04JSON\x10\x01\")\n\x0cOutputFormat\x12\x0c\n\x08OutPlain\x10\x00\x12\x0b\n\x07OutJSON\x10\x01\x42\x05\n\x03msg\";\n\x0fRequestEnvelope\x12\r\n\x05token\x18\x01 \x01(\t\x12\x19\n\x07request\x18\x02 \x02(\x0b\x32\x08.Request\"S\n\x08Response\x12\x17\n\x06status\x18\x01 \x02(\x0e\x32\x07.Errnum\x12\x0e\n\x06output\x18\x02 \x01(\t\x12\r\n\x05\x65rror\x18\x03 \x01(\t\x12\x0f\n\x07warning\x18\x04 \x01(\t*\xd2\x01\n\x06\x45rrnum\x12\x0b\n\x07SUCCESS\x10\x00\x12\x08\n\x04\x46\x41IL\x10\x01\x12\x10\n\x0cINVALID_PATH\x10\x02\x12\x11\n\rINVALID_VALUE\x10\x03\x12\x16\n\x12\x43OMMIT_IN_PROGRESS\x10\x04\x12\x18\n\x14\x43ONFIGURATION_LOCKED\x10\x05\x12\x12\n\x0eINTERNAL_ERROR\x10\x06\x12\x15\n\x11PERMISSION_DENIED\x10\x07\x12\x17\n\x13PATH_ALREADY_EXISTS\x10\x08\x12\x16\n\x12UNCOMMITED_CHANGES\x10\t')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'vyconf_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
- _ERRNUM._serialized_start=3179
- _ERRNUM._serialized_end=3389
+ _ERRNUM._serialized_start=3288
+ _ERRNUM._serialized_end=3498
_REQUEST._serialized_start=17
- _REQUEST._serialized_end=3030
- _REQUEST_PROMPT._serialized_start=1308
- _REQUEST_PROMPT._serialized_end=1316
- _REQUEST_SETUPSESSION._serialized_start=1319
- _REQUEST_SETUPSESSION._serialized_end=1450
- _REQUEST_SESSIONOFPID._serialized_start=1452
- _REQUEST_SESSIONOFPID._serialized_end=1486
- _REQUEST_SESSIONEXISTS._serialized_start=1488
- _REQUEST_SESSIONEXISTS._serialized_end=1518
- _REQUEST_GETCONFIG._serialized_start=1520
- _REQUEST_GETCONFIG._serialized_end=1546
- _REQUEST_TEARDOWN._serialized_start=1548
- _REQUEST_TEARDOWN._serialized_end=1580
- _REQUEST_VALIDATE._serialized_start=1582
- _REQUEST_VALIDATE._serialized_end=1652
- _REQUEST_SET._serialized_start=1654
- _REQUEST_SET._serialized_end=1673
- _REQUEST_DELETE._serialized_start=1675
- _REQUEST_DELETE._serialized_end=1697
- _REQUEST_AUXSET._serialized_start=1699
- _REQUEST_AUXSET._serialized_end=1761
- _REQUEST_AUXDELETE._serialized_start=1763
- _REQUEST_AUXDELETE._serialized_end=1828
- _REQUEST_DISCARD._serialized_start=1830
- _REQUEST_DISCARD._serialized_end=1854
- _REQUEST_SESSIONCHANGED._serialized_start=1856
- _REQUEST_SESSIONCHANGED._serialized_end=1887
- _REQUEST_RENAME._serialized_start=1889
- _REQUEST_RENAME._serialized_end=1954
- _REQUEST_COPY._serialized_start=1956
- _REQUEST_COPY._serialized_end=2019
- _REQUEST_COMMENT._serialized_start=2021
- _REQUEST_COMMENT._serialized_end=2061
- _REQUEST_COMMIT._serialized_start=2063
- _REQUEST_COMMIT._serialized_end=2147
- _REQUEST_ROLLBACK._serialized_start=2149
- _REQUEST_ROLLBACK._serialized_end=2177
- _REQUEST_LOAD._serialized_start=2179
- _REQUEST_LOAD._serialized_end=2258
- _REQUEST_MERGE._serialized_start=2260
- _REQUEST_MERGE._serialized_end=2345
- _REQUEST_SAVE._serialized_start=2347
- _REQUEST_SAVE._serialized_end=2410
- _REQUEST_SHOWCONFIG._serialized_start=2412
- _REQUEST_SHOWCONFIG._serialized_end=2477
- _REQUEST_EXISTS._serialized_start=2479
- _REQUEST_EXISTS._serialized_end=2501
- _REQUEST_GETVALUE._serialized_start=2503
- _REQUEST_GETVALUE._serialized_end=2573
- _REQUEST_GETVALUES._serialized_start=2575
- _REQUEST_GETVALUES._serialized_end=2646
- _REQUEST_LISTCHILDREN._serialized_start=2648
- _REQUEST_LISTCHILDREN._serialized_end=2722
- _REQUEST_RUNOPMODE._serialized_start=2724
- _REQUEST_RUNOPMODE._serialized_end=2795
- _REQUEST_CONFIRM._serialized_start=2797
- _REQUEST_CONFIRM._serialized_end=2806
- _REQUEST_ENTERCONFIGURATIONMODE._serialized_start=2808
- _REQUEST_ENTERCONFIGURATIONMODE._serialized_end=2879
- _REQUEST_EXITCONFIGURATIONMODE._serialized_start=2881
- _REQUEST_EXITCONFIGURATIONMODE._serialized_end=2904
- _REQUEST_RELOADREFTREE._serialized_start=2906
- _REQUEST_RELOADREFTREE._serialized_end=2943
- _REQUEST_CONFIGFORMAT._serialized_start=2945
- _REQUEST_CONFIGFORMAT._serialized_end=2980
- _REQUEST_OUTPUTFORMAT._serialized_start=2982
- _REQUEST_OUTPUTFORMAT._serialized_end=3023
- _REQUESTENVELOPE._serialized_start=3032
- _REQUESTENVELOPE._serialized_end=3091
- _RESPONSE._serialized_start=3093
- _RESPONSE._serialized_end=3176
+ _REQUEST._serialized_end=3139
+ _REQUEST_PROMPT._serialized_start=1356
+ _REQUEST_PROMPT._serialized_end=1364
+ _REQUEST_SETUPSESSION._serialized_start=1367
+ _REQUEST_SETUPSESSION._serialized_end=1498
+ _REQUEST_SESSIONOFPID._serialized_start=1500
+ _REQUEST_SESSIONOFPID._serialized_end=1534
+ _REQUEST_SESSIONEXISTS._serialized_start=1536
+ _REQUEST_SESSIONEXISTS._serialized_end=1566
+ _REQUEST_GETCONFIG._serialized_start=1568
+ _REQUEST_GETCONFIG._serialized_end=1594
+ _REQUEST_TEARDOWN._serialized_start=1596
+ _REQUEST_TEARDOWN._serialized_end=1628
+ _REQUEST_VALIDATE._serialized_start=1630
+ _REQUEST_VALIDATE._serialized_end=1700
+ _REQUEST_SET._serialized_start=1702
+ _REQUEST_SET._serialized_end=1721
+ _REQUEST_DELETE._serialized_start=1723
+ _REQUEST_DELETE._serialized_end=1745
+ _REQUEST_AUXSET._serialized_start=1747
+ _REQUEST_AUXSET._serialized_end=1809
+ _REQUEST_AUXDELETE._serialized_start=1811
+ _REQUEST_AUXDELETE._serialized_end=1876
+ _REQUEST_DISCARD._serialized_start=1878
+ _REQUEST_DISCARD._serialized_end=1902
+ _REQUEST_SESSIONCHANGED._serialized_start=1904
+ _REQUEST_SESSIONCHANGED._serialized_end=1935
+ _REQUEST_RENAME._serialized_start=1937
+ _REQUEST_RENAME._serialized_end=2002
+ _REQUEST_COPY._serialized_start=2004
+ _REQUEST_COPY._serialized_end=2067
+ _REQUEST_COMMENT._serialized_start=2069
+ _REQUEST_COMMENT._serialized_end=2109
+ _REQUEST_COMMIT._serialized_start=2111
+ _REQUEST_COMMIT._serialized_end=2195
+ _REQUEST_ROLLBACK._serialized_start=2197
+ _REQUEST_ROLLBACK._serialized_end=2225
+ _REQUEST_LOAD._serialized_start=2227
+ _REQUEST_LOAD._serialized_end=2306
+ _REQUEST_MERGE._serialized_start=2308
+ _REQUEST_MERGE._serialized_end=2393
+ _REQUEST_SAVE._serialized_start=2395
+ _REQUEST_SAVE._serialized_end=2458
+ _REQUEST_SHOWCONFIG._serialized_start=2460
+ _REQUEST_SHOWCONFIG._serialized_end=2525
+ _REQUEST_EXISTS._serialized_start=2527
+ _REQUEST_EXISTS._serialized_end=2549
+ _REQUEST_GETVALUE._serialized_start=2551
+ _REQUEST_GETVALUE._serialized_end=2621
+ _REQUEST_GETVALUES._serialized_start=2623
+ _REQUEST_GETVALUES._serialized_end=2694
+ _REQUEST_LISTCHILDREN._serialized_start=2696
+ _REQUEST_LISTCHILDREN._serialized_end=2770
+ _REQUEST_RUNOPMODE._serialized_start=2772
+ _REQUEST_RUNOPMODE._serialized_end=2843
+ _REQUEST_CONFIRM._serialized_start=2845
+ _REQUEST_CONFIRM._serialized_end=2854
+ _REQUEST_ENTERCONFIGURATIONMODE._serialized_start=2856
+ _REQUEST_ENTERCONFIGURATIONMODE._serialized_end=2927
+ _REQUEST_EXITCONFIGURATIONMODE._serialized_start=2929
+ _REQUEST_EXITCONFIGURATIONMODE._serialized_end=2952
+ _REQUEST_RELOADREFTREE._serialized_start=2954
+ _REQUEST_RELOADREFTREE._serialized_end=2991
+ _REQUEST_SHOWSESSIONS._serialized_start=2993
+ _REQUEST_SHOWSESSIONS._serialized_end=3052
+ _REQUEST_CONFIGFORMAT._serialized_start=3054
+ _REQUEST_CONFIGFORMAT._serialized_end=3089
+ _REQUEST_OUTPUTFORMAT._serialized_start=3091
+ _REQUEST_OUTPUTFORMAT._serialized_end=3132
+ _REQUESTENVELOPE._serialized_start=3141
+ _REQUESTENVELOPE._serialized_end=3200
+ _RESPONSE._serialized_start=3202
+ _RESPONSE._serialized_end=3285
# @@protoc_insertion_point(module_scope)
diff --git a/python/vyos/proto/vyconf_proto.py b/python/vyos/proto/vyconf_proto.py
index a7fb24337..080d103f9 100644
--- a/python/vyos/proto/vyconf_proto.py
+++ b/python/vyos/proto/vyconf_proto.py
@@ -175,6 +175,11 @@ class ReloadReftree:
on_behalf_of: int = None
@dataclass
+class ShowSessions:
+ exclude_self: bool = False
+ exclude_other: bool = False
+
+@dataclass
class Request:
prompt: Prompt = None
setup_session: SetupSession = None
@@ -207,6 +212,7 @@ class Request:
get_config: GetConfig = None
aux_set: AuxSet = None
aux_delete: AuxDelete = None
+ show_sessions: ShowSessions = None
@dataclass
class RequestEnvelope:
@@ -405,3 +411,9 @@ def set_request_reload_reftree(token: str = None, on_behalf_of: int = None):
req = Request(reload_reftree=reqi)
req_env = RequestEnvelope(token, req)
return req_env
+
+def set_request_show_sessions(token: str = None, exclude_self: bool = False, exclude_other: bool = False):
+ reqi = ShowSessions (exclude_self, exclude_other)
+ req = Request(show_sessions=reqi)
+ req_env = RequestEnvelope(token, req)
+ return req_env
diff --git a/python/vyos/vyconf_session.py b/python/vyos/vyconf_session.py
index 379de4e24..5748ab2dd 100644
--- a/python/vyos/vyconf_session.py
+++ b/python/vyos/vyconf_session.py
@@ -16,7 +16,9 @@
#
import os
+import weakref
import tempfile
+import json
from functools import wraps
from typing import Type
@@ -36,45 +38,76 @@ class VyconfSessionError(Exception):
pass
+def new_session(pid: int, sudo_user: str, user: str):
+ out = vyconf_client.send_request(
+ 'setup_session',
+ client_pid=pid,
+ client_sudo_user=sudo_user,
+ client_user=user,
+ )
+ return out.output
+
+
class VyconfSession:
def __init__(
- self, token: str = None, pid: int = None, on_error: Type[Exception] = None
+ self,
+ pid: int = None,
+ token: str = None,
+ extant=False,
+ on_error: Type[Exception] = None,
):
- self.pid = os.getpid() if pid is None else pid
+ self.pid = pid if pid else os.getpid()
self.sudo_user = os.environ.get('SUDO_USER', None)
self.user = os.environ.get('USER', None)
- if token is None:
- # CLI applications with arg pid=getppid() allow coordination
- # with the ambient session; other uses (such as ConfigSession)
- # may default to self pid
- out = vyconf_client.send_request('session_of_pid', client_pid=self.pid)
- if out.output is None:
- out = vyconf_client.send_request(
- 'setup_session',
- client_pid=self.pid,
- client_sudo_user=self.sudo_user,
- client_user=self.user,
- )
- self.__token = out.output
- else:
- out = vyconf_client.send_request('session_exists', token=token)
- if out.status:
- raise ValueError(f'No existing session for token: {token}')
- self.__token = token
-
self.in_config_session = in_config_session()
- if self.in_config_session:
- out = vyconf_client.send_request(
- 'enter_configuration_mode', token=self.__token
- )
- if out.status:
- raise VyconfSessionError(self.output(out))
+
+ match token:
+ case None:
+ # config-mode sessions are persistent, and managed by caller (CLI or ConfigSession)
+ #
+ # op-mode sessions are ephemeral, unless forced with extant=True:
+ # --- open a new session on init; teardown in finalizer
+ if self.in_config_session:
+ out = vyconf_client.send_request(
+ 'session_of_pid', client_pid=self.pid
+ )
+ if out.output is None:
+ self.__token = new_session(self.pid, self.sudo_user, self.user)
+ out = vyconf_client.send_request(
+ 'enter_configuration_mode', token=self.__token
+ )
+ if out.status:
+ raise VyconfSessionError(self.output(out))
+ else:
+ self.__token = out.output
+ else:
+ if not extant:
+ self.__token = new_session(self.pid, self.sudo_user, self.user)
+ else:
+ out = vyconf_client.send_request(
+ 'session_of_pid', client_pid=self.pid
+ )
+ if out.output is None:
+ raise ValueError(f'No existing session for pid {self.pid}')
+ self.__token = out.output
+ case _:
+ out = vyconf_client.send_request('session_exists', token=token)
+ if out.status:
+ raise ValueError(f'No existing session for token: {token}')
+ self.__token = token
+
+ if not self.in_config_session and not extant:
+ self._finalizer = weakref.finalize(self, self._teardown, self.__token)
self.on_error = on_error
+ @classmethod
+ def _teardown(cls, token):
+ vyconf_client.send_request('teardown', token)
+
def teardown(self):
- vyconf_client.send_request('teardown', token=self.__token)
+ self._teardown(self.__token)
def exit_config_mode(self):
if self.session_changed():
@@ -95,6 +128,21 @@ class VyconfSession:
raise VyconfSessionError(self.output(out))
return out.output
+ def show_sessions(
+ self, exclude_self: bool = False, exclude_other: bool = False
+ ) -> list | dict:
+ out = vyconf_client.send_request(
+ 'show_sessions',
+ token=self.__token,
+ exclude_self=exclude_self,
+ exclude_other=exclude_other,
+ )
+
+ lst = json.loads(out.output)
+ if len(lst) == 1:
+ return lst[0]
+ return lst
+
@staticmethod
def config_mode(f):
@wraps(f)
@@ -129,6 +177,11 @@ class VyconfSession:
out = out + res
return out
+ @config_mode
+ def discard(self) -> tuple[str, int]:
+ out = vyconf_client.send_request('discard', token=self.__token)
+ return self.output(out), out.status
+
@raise_exception
@config_mode
def set(self, path: list[str]) -> tuple[str, int]:
@@ -189,12 +242,6 @@ class VyconfSession:
@raise_exception
@config_mode
- def discard(self) -> tuple[str, int]:
- out = vyconf_client.send_request('discard', token=self.__token)
- return self.output(out), out.status
-
- @raise_exception
- @config_mode
def load_config(
self, file_name: str, migrate: bool = False, cached: bool = False
) -> tuple[str, int]: