summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/unused-imports.yml39
-rw-r--r--Makefile4
-rw-r--r--interface-definitions/service_dhcp-server.xml.in21
-rw-r--r--python/vyos/template.py15
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py71
-rwxr-xr-xsmoketest/scripts/cli/test_service_dhcp-server.py65
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py13
-rwxr-xr-xsrc/conf_mode/service_dhcp-server.py8
-rwxr-xr-xsrc/op_mode/generate_tech-support_archive.py2
-rw-r--r--src/services/api/graphql/generate/composite_function.py4
-rw-r--r--src/services/api/graphql/graphql/auth_token_mutation.py8
-rw-r--r--src/services/api/graphql/graphql/directives.py4
-rw-r--r--src/services/api/graphql/graphql/mutations.py8
-rw-r--r--src/services/api/graphql/graphql/queries.py8
-rw-r--r--src/services/api/graphql/libs/op_mode.py6
-rwxr-xr-xsrc/services/api/graphql/session/composite/system_status.py11
-rw-r--r--src/services/api/graphql/session/session.py3
17 files changed, 227 insertions, 63 deletions
diff --git a/.github/workflows/unused-imports.yml b/.github/workflows/unused-imports.yml
index 83098ddf6..e716a9c01 100644
--- a/.github/workflows/unused-imports.yml
+++ b/.github/workflows/unused-imports.yml
@@ -1,29 +1,20 @@
name: Check for unused imports using Pylint
-on:
- pull_request_target:
- types: [opened, reopened, ready_for_review, locked]
+on: push
+ # pull_request_target:
+ # types: [opened, reopened, ready_for_review, locked]
jobs:
- build:
+ Check-Unused-Imports:
runs-on: ubuntu-latest
- strategy:
- matrix:
- python-version: ["3.11"]
steps:
- - uses: actions/checkout@v3
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v3
- with:
- python-version: ${{ matrix.python-version }}
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install pylint
- - name: Analysing the code with pylint
- run: |
- tmp=$(git ls-files *.py | xargs pylint | grep W0611 | wc -l)
- if [[ $tmp -gt 0 ]]; then
- echo "Found $tmp occurrence of unused Python import statements!"
- exit 1
- fi
- exit 0
+ - uses: actions/checkout@v3
+ - name: Set up Python
+ uses: actions/setup-python@v3
+ with:
+ python-version: 3.11
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install pylint
+ - name: Analysing the code with pylint
+ run: make unused-imports
diff --git a/Makefile b/Makefile
index 0868025ae..432de7547 100644
--- a/Makefile
+++ b/Makefile
@@ -6,8 +6,8 @@ SHIM_DIR := src/shim
LIBS := -lzmq
CFLAGS :=
BUILD_ARCH := $(shell dpkg-architecture -q DEB_BUILD_ARCH)
-
J2LINT := $(shell command -v j2lint 2> /dev/null)
+PYLINT_FILES := $(shell git ls-files *.py)
config_xml_src = $(wildcard interface-definitions/*.xml.in)
config_xml_obj = $(config_xml_src:.xml.in=.xml)
@@ -114,7 +114,7 @@ sonar:
.PHONY: unused-imports
unused-imports:
- git ls-files *.py | xargs pylint | grep W0611
+ @pylint --disable=all --enable=W0611 $(PYLINT_FILES)
deb:
dpkg-buildpackage -uc -us -tc -b
diff --git a/interface-definitions/service_dhcp-server.xml.in b/interface-definitions/service_dhcp-server.xml.in
index 2afa05a8a..cb5f9a804 100644
--- a/interface-definitions/service_dhcp-server.xml.in
+++ b/interface-definitions/service_dhcp-server.xml.in
@@ -22,6 +22,27 @@
</properties>
<children>
#include <include/source-address-ipv4.xml.i>
+ <leafNode name="mode">
+ <properties>
+ <help>Configure high availability mode</help>
+ <completionHelp>
+ <list>active-active active-passive</list>
+ </completionHelp>
+ <valueHelp>
+ <format>active-active</format>
+ <description>Both server attend DHCP requests</description>
+ </valueHelp>
+ <valueHelp>
+ <format>active-passive</format>
+ <description>Only primary server attends DHCP requests</description>
+ </valueHelp>
+ <constraint>
+ <regex>(active-active|active-passive)</regex>
+ </constraint>
+ <constraintErrorMessage>Invalid DHCP high availability mode</constraintErrorMessage>
+ </properties>
+ <defaultValue>active-active</defaultValue>
+ </leafNode>
<leafNode name="remote">
<properties>
<help>IPv4 remote address used for connection</help>
diff --git a/python/vyos/template.py b/python/vyos/template.py
index 3e468eb82..ac77e8a3d 100644
--- a/python/vyos/template.py
+++ b/python/vyos/template.py
@@ -823,10 +823,19 @@ def kea_high_availability_json(config):
source_addr = config['source_address']
remote_addr = config['remote']
+ ha_mode = 'hot-standby' if config['mode'] == 'active-passive' else 'load-balancing'
+ ha_role = config['status']
+
+ if ha_role == 'primary':
+ peer1_role = 'primary'
+ peer2_role = 'standby' if ha_mode == 'hot-standby' else 'secondary'
+ else:
+ peer1_role = 'standby' if ha_mode == 'hot-standby' else 'secondary'
+ peer2_role = 'primary'
data = {
'this-server-name': os.uname()[1],
- 'mode': 'hot-standby',
+ 'mode': ha_mode,
'heartbeat-delay': 10000,
'max-response-delay': 10000,
'max-ack-delay': 5000,
@@ -835,13 +844,13 @@ def kea_high_availability_json(config):
{
'name': os.uname()[1],
'url': f'http://{source_addr}:647/',
- 'role': 'standby' if config['status'] == 'secondary' else 'primary',
+ 'role': peer1_role,
'auto-failover': True
},
{
'name': config['name'],
'url': f'http://{remote_addr}:647/',
- 'role': 'primary' if config['status'] == 'secondary' else 'standby',
+ 'role': peer2_role,
'auto-failover': True
}]
}
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 60c49b8b4..03daa34aa 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -1259,6 +1259,77 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn('neighbor peer1 route-reflector-client', conf)
+ def test_bgp_28_peer_group_member_all_internal_or_external(self):
+ def _common_config_check(conf, include_ras=True):
+ if include_ras:
+ self.assertIn(f'neighbor {int_neighbors[0]} remote-as {ASN}', conf)
+ self.assertIn(f'neighbor {int_neighbors[1]} remote-as {ASN}', conf)
+ self.assertIn(f'neighbor {ext_neighbors[0]} remote-as {int(ASN) + 1}',conf)
+
+ self.assertIn(f'neighbor {int_neighbors[0]} peer-group {int_pg_name}', conf)
+ self.assertIn(f'neighbor {int_neighbors[1]} peer-group {int_pg_name}', conf)
+ self.assertIn(f'neighbor {ext_neighbors[0]} peer-group {ext_pg_name}', conf)
+
+ int_neighbors = ['192.0.2.2', '192.0.2.3']
+ ext_neighbors = ['192.122.2.2', '192.122.2.3']
+ int_pg_name, ext_pg_name = 'SMOKETESTINT', 'SMOKETESTEXT'
+
+ self.cli_set(base_path + ['neighbor', int_neighbors[0], 'peer-group', int_pg_name])
+ self.cli_set(base_path + ['neighbor', int_neighbors[0], 'remote-as', ASN])
+ self.cli_set(base_path + ['peer-group', int_pg_name, 'address-family', 'ipv4-unicast'])
+ self.cli_set(base_path + ['neighbor', ext_neighbors[0], 'peer-group', ext_pg_name])
+ self.cli_set(base_path + ['neighbor', ext_neighbors[0], 'remote-as', f'{int(ASN) + 1}'])
+ self.cli_set(base_path + ['peer-group', ext_pg_name, 'address-family', 'ipv4-unicast'])
+ self.cli_commit()
+
+ # test add external remote-as to internal group
+ self.cli_set(base_path + ['neighbor', int_neighbors[1], 'peer-group', int_pg_name])
+ self.cli_set(base_path + ['neighbor', int_neighbors[1], 'remote-as', f'{int(ASN) + 1}'])
+
+ with self.assertRaises(ConfigSessionError) as e:
+ self.cli_commit()
+ # self.assertIn('\nPeer-group members must be all internal or all external\n', str(e.exception))
+
+ # test add internal remote-as to internal group
+ self.cli_set(base_path + ['neighbor', int_neighbors[1], 'remote-as', ASN])
+ self.cli_commit()
+
+ conf = self.getFRRconfig(f'router bgp {ASN}')
+ _common_config_check(conf)
+
+ # test add internal remote-as to external group
+ self.cli_set(base_path + ['neighbor', ext_neighbors[1], 'peer-group', ext_pg_name])
+ self.cli_set(base_path + ['neighbor', ext_neighbors[1], 'remote-as', ASN])
+
+ with self.assertRaises(ConfigSessionError) as e:
+ self.cli_commit()
+ # self.assertIn('\nPeer-group members must be all internal or all external\n', str(e.exception))
+
+ # test add external remote-as to external group
+ self.cli_set(base_path + ['neighbor', ext_neighbors[1], 'remote-as', f'{int(ASN) + 2}'])
+ self.cli_commit()
+
+ conf = self.getFRRconfig(f'router bgp {ASN}')
+ _common_config_check(conf)
+ self.assertIn(f'neighbor {ext_neighbors[1]} remote-as {int(ASN) + 2}', conf)
+ self.assertIn(f'neighbor {ext_neighbors[1]} peer-group {ext_pg_name}', conf)
+
+ # test named remote-as
+ self.cli_set(base_path + ['neighbor', int_neighbors[0], 'remote-as', 'internal'])
+ self.cli_set(base_path + ['neighbor', int_neighbors[1], 'remote-as', 'internal'])
+ self.cli_set(base_path + ['neighbor', ext_neighbors[0], 'remote-as', 'external'])
+ self.cli_set(base_path + ['neighbor', ext_neighbors[1], 'remote-as', 'external'])
+ self.cli_commit()
+
+ conf = self.getFRRconfig(f'router bgp {ASN}')
+ _common_config_check(conf, include_ras=False)
+
+ self.assertIn(f'neighbor {int_neighbors[0]} remote-as internal', conf)
+ self.assertIn(f'neighbor {int_neighbors[1]} remote-as internal', conf)
+ self.assertIn(f'neighbor {ext_neighbors[0]} remote-as external', conf)
+ self.assertIn(f'neighbor {ext_neighbors[1]} remote-as external', conf)
+ self.assertIn(f'neighbor {ext_neighbors[1]} peer-group {ext_pg_name}', conf)
+
def test_bgp_99_bmp(self):
target_name = 'instance-bmp'
target_address = '127.0.0.1'
diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py
index abf40cd3b..46c4e25a1 100755
--- a/smoketest/scripts/cli/test_service_dhcp-server.py
+++ b/smoketest/scripts/cli/test_service_dhcp-server.py
@@ -699,6 +699,7 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ['high-availability', 'name', failover_name])
self.cli_set(base_path + ['high-availability', 'remote', failover_remote])
self.cli_set(base_path + ['high-availability', 'status', 'primary'])
+ ## No mode defined -> its active-active mode by default
# commit changes
self.cli_commit()
@@ -717,7 +718,69 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):
self.verify_config_object(
obj,
['Dhcp4', 'hooks-libraries', 0, 'parameters', 'high-availability', 0, 'peers'],
- {'name': failover_name, 'url': f'http://{failover_remote}:647/', 'role': 'standby', 'auto-failover': True})
+ {'name': failover_name, 'url': f'http://{failover_remote}:647/', 'role': 'secondary', 'auto-failover': True})
+
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name)
+ self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
+
+ # Verify options
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'option-data'],
+ {'name': 'routers', 'data': router})
+
+ # Verify pools
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'shared-networks', 0, 'subnet4', 0, 'pools'],
+ {'pool': f'{range_0_start} - {range_0_stop}'})
+
+ # Check for running process
+ self.assertTrue(process_named_running(PROCESS_NAME))
+ self.assertTrue(process_named_running(CTRL_PROCESS_NAME))
+
+ def test_dhcp_high_availability_standby(self):
+ shared_net_name = 'FAILOVER'
+ failover_name = 'VyOS-Failover'
+
+ range_0_start = inc_ip(subnet, 10)
+ range_0_stop = inc_ip(subnet, 20)
+
+ pool = base_path + ['shared-network-name', shared_net_name, 'subnet', subnet]
+ self.cli_set(pool + ['subnet-id', '1'])
+ # we use the first subnet IP address as default gateway
+ self.cli_set(pool + ['option', 'default-router', router])
+ self.cli_set(pool + ['range', '0', 'start', range_0_start])
+ self.cli_set(pool + ['range', '0', 'stop', range_0_stop])
+
+ # failover
+ failover_local = router
+ failover_remote = inc_ip(router, 1)
+
+ self.cli_set(base_path + ['high-availability', 'source-address', failover_local])
+ self.cli_set(base_path + ['high-availability', 'name', failover_name])
+ self.cli_set(base_path + ['high-availability', 'remote', failover_remote])
+ self.cli_set(base_path + ['high-availability', 'status', 'secondary'])
+ self.cli_set(base_path + ['high-availability', 'mode', 'active-passive'])
+
+ # commit changes
+ self.cli_commit()
+
+ config = read_file(KEA4_CONF)
+ obj = loads(config)
+
+ # Verify failover
+ self.verify_config_value(obj, ['Dhcp4', 'control-socket'], 'socket-name', KEA4_CTRL)
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'hooks-libraries', 0, 'parameters', 'high-availability', 0, 'peers'],
+ {'name': os.uname()[1], 'url': f'http://{failover_local}:647/', 'role': 'standby', 'auto-failover': True})
+
+ self.verify_config_object(
+ obj,
+ ['Dhcp4', 'hooks-libraries', 0, 'parameters', 'high-availability', 0, 'peers'],
+ {'name': failover_name, 'url': f'http://{failover_remote}:647/', 'role': 'primary', 'auto-failover': True})
self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name)
self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet)
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 512fa26e9..2b16de775 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -285,6 +285,7 @@ def verify(bgp):
elif tmp != 'default':
raise ConfigError(f'{error_msg} "{tmp}"!')
+ peer_groups_context = dict()
# Common verification for both peer-group and neighbor statements
for neighbor in ['neighbor', 'peer_group']:
# bail out early if there is no neighbor or peer-group statement
@@ -301,6 +302,18 @@ def verify(bgp):
raise ConfigError(f'Specified peer-group "{peer_group}" for '\
f'neighbor "{neighbor}" does not exist!')
+ if 'remote_as' in peer_config:
+ is_ibgp = True
+ if peer_config['remote_as'] != 'internal' and \
+ peer_config['remote_as'] != bgp['system_as']:
+ is_ibgp = False
+
+ if peer_group not in peer_groups_context:
+ peer_groups_context[peer_group] = is_ibgp
+ elif peer_groups_context[peer_group] != is_ibgp:
+ raise ConfigError(f'Peer-group members must be '
+ f'all internal or all external')
+
if 'local_role' in peer_config:
#Ensure Local Role has only one value.
if len(peer_config['local_role']) > 1:
diff --git a/src/conf_mode/service_dhcp-server.py b/src/conf_mode/service_dhcp-server.py
index bf4454fda..f4fb78f57 100755
--- a/src/conf_mode/service_dhcp-server.py
+++ b/src/conf_mode/service_dhcp-server.py
@@ -143,8 +143,12 @@ def get_config(config=None):
dhcp['shared_network_name'][network]['subnet'][subnet].update(
{'range' : new_range_dict})
- if dict_search('high_availability.certificate', dhcp):
- dhcp['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True)
+ if len(dhcp['high_availability']) == 1:
+ ## only default value for mode is set, need to remove ha node
+ del dhcp['high_availability']
+ else:
+ if dict_search('high_availability.certificate', dhcp):
+ dhcp['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True)
return dhcp
diff --git a/src/op_mode/generate_tech-support_archive.py b/src/op_mode/generate_tech-support_archive.py
index c490b0137..41b53cd15 100755
--- a/src/op_mode/generate_tech-support_archive.py
+++ b/src/op_mode/generate_tech-support_archive.py
@@ -120,7 +120,7 @@ if __name__ == '__main__':
# Temporary directory creation
tmp_dir_path = f'{tmp_path}/drops-debug_{time_now}'
tmp_dir: Path = Path(tmp_dir_path)
- tmp_dir.mkdir()
+ tmp_dir.mkdir(parents=True)
report_file: Path = Path(f'{tmp_dir_path}/show_tech-support_report.txt')
report_file.touch()
diff --git a/src/services/api/graphql/generate/composite_function.py b/src/services/api/graphql/generate/composite_function.py
index bc9d80fbb..d6626fd1f 100644
--- a/src/services/api/graphql/generate/composite_function.py
+++ b/src/services/api/graphql/generate/composite_function.py
@@ -1,11 +1,7 @@
# typing information for composite functions: those that invoke several
# elementary requests, and return the result as a single dict
-import typing
-
def system_status():
pass
queries = {'system_status': system_status}
-
mutations = {}
-
diff --git a/src/services/api/graphql/graphql/auth_token_mutation.py b/src/services/api/graphql/graphql/auth_token_mutation.py
index 603a13758..a53fa4d60 100644
--- a/src/services/api/graphql/graphql/auth_token_mutation.py
+++ b/src/services/api/graphql/graphql/auth_token_mutation.py
@@ -1,4 +1,4 @@
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2022-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
@@ -13,10 +13,10 @@
# 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/>.
-import jwt
import datetime
-from typing import Any, Dict
-from ariadne import ObjectType, UnionType
+from typing import Any
+from typing import Dict
+from ariadne import ObjectType
from graphql import GraphQLResolveInfo
from .. libs.token_auth import generate_token
diff --git a/src/services/api/graphql/graphql/directives.py b/src/services/api/graphql/graphql/directives.py
index a7919854a..3927aee58 100644
--- a/src/services/api/graphql/graphql/directives.py
+++ b/src/services/api/graphql/graphql/directives.py
@@ -1,4 +1,4 @@
-# Copyright 2021 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2021-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
@@ -13,7 +13,7 @@
# 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/>.
-from ariadne import SchemaDirectiveVisitor, ObjectType
+from ariadne import SchemaDirectiveVisitor
from . queries import *
from . mutations import *
diff --git a/src/services/api/graphql/graphql/mutations.py b/src/services/api/graphql/graphql/mutations.py
index 8254e22b1..d115a8e94 100644
--- a/src/services/api/graphql/graphql/mutations.py
+++ b/src/services/api/graphql/graphql/mutations.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2021-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
@@ -14,11 +14,13 @@
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from importlib import import_module
-from typing import Any, Dict, Optional
from ariadne import ObjectType, convert_camel_case_to_snake
-from graphql import GraphQLResolveInfo
from makefun import with_signature
+# used below by func_sig
+from typing import Any, Dict, Optional # pylint: disable=W0611
+from graphql import GraphQLResolveInfo # pylint: disable=W0611
+
from .. import state
from .. libs import key_auth
from api.graphql.session.session import Session
diff --git a/src/services/api/graphql/graphql/queries.py b/src/services/api/graphql/graphql/queries.py
index daccc19b2..717098259 100644
--- a/src/services/api/graphql/graphql/queries.py
+++ b/src/services/api/graphql/graphql/queries.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2021-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
@@ -14,11 +14,13 @@
# along with this library. If not, see <http://www.gnu.org/licenses/>.
from importlib import import_module
-from typing import Any, Dict, Optional
from ariadne import ObjectType, convert_camel_case_to_snake
-from graphql import GraphQLResolveInfo
from makefun import with_signature
+# used below by func_sig
+from typing import Any, Dict, Optional # pylint: disable=W0611
+from graphql import GraphQLResolveInfo # pylint: disable=W0611
+
from .. import state
from .. libs import key_auth
from api.graphql.session.session import Session
diff --git a/src/services/api/graphql/libs/op_mode.py b/src/services/api/graphql/libs/op_mode.py
index 5022f7d4e..86e38eae6 100644
--- a/src/services/api/graphql/libs/op_mode.py
+++ b/src/services/api/graphql/libs/op_mode.py
@@ -1,4 +1,4 @@
-# Copyright 2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2022-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
@@ -16,7 +16,9 @@
import os
import re
import typing
-from typing import Union, Tuple, Optional
+
+from typing import Union
+from typing import Optional
from humps import decamelize
from vyos.defaults import directories
diff --git a/src/services/api/graphql/session/composite/system_status.py b/src/services/api/graphql/session/composite/system_status.py
index d809f32e3..516a4eff6 100755
--- a/src/services/api/graphql/session/composite/system_status.py
+++ b/src/services/api/graphql/session/composite/system_status.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2022 VyOS maintainers and contributors
+# Copyright (C) 2022-2024 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
@@ -13,15 +13,6 @@
#
# 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
-import json
-import importlib.util
-
-from vyos.defaults import directories
from api.graphql.libs.op_mode import load_op_mode_as_module
diff --git a/src/services/api/graphql/session/session.py b/src/services/api/graphql/session/session.py
index 3c5a062b6..6ae44b9bf 100644
--- a/src/services/api/graphql/session/session.py
+++ b/src/services/api/graphql/session/session.py
@@ -1,4 +1,4 @@
-# Copyright 2021-2022 VyOS maintainers and contributors <maintainers@vyos.io>
+# Copyright 2021-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
@@ -21,7 +21,6 @@ from ariadne import convert_camel_case_to_snake
from vyos.config import Config
from vyos.configtree import ConfigTree
from vyos.defaults import directories
-from vyos.template import render
from vyos.opmode import Error as OpModeError
from api.graphql.libs.op_mode import load_op_mode_as_module, split_compound_op_mode_name