Loading src/common/tools/rest_conf/server/restconf_server/Config.py 0 → 100644 +22 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os, secrets RESTCONF_PREFIX = os.environ.get('RESTCONF_PREFIX', '/restconf' ) YANG_SEARCH_PATH = os.environ.get('YANG_SEARCH_PATH', './yang' ) STARTUP_FILE = os.environ.get('STARTUP_FILE', './startup.json') SECRET_KEY = os.environ.get('SECRET_KEY', secrets.token_hex(64)) src/common/tools/rest_conf/server/restconf_server/RestConfServerApplication.py 0 → 100644 +95 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json, logging, time from flask import Flask, request from flask_restful import Api from .Config import RESTCONF_PREFIX, SECRET_KEY, STARTUP_FILE, YANG_SEARCH_PATH from .Dispatch import RestConfDispatch from .HostMeta import HostMeta from .YangHandler import YangHandler from .YangModelDiscoverer import YangModuleDiscoverer logging.basicConfig( level=logging.INFO, format='[Worker-%(process)d][%(asctime)s] %(levelname)s:%(name)s:%(message)s', ) LOGGER = logging.getLogger(__name__) def log_request(response): timestamp = time.strftime('[%Y-%b-%d %H:%M]') LOGGER.info( '%s %s %s %s %s', timestamp, request.remote_addr, request.method, request.full_path, response.status ) return response class RestConfServerApplication: def __init__(self) -> None: self._ymd = YangModuleDiscoverer(YANG_SEARCH_PATH) self._yang_module_names = self._ymd.run(do_log_order=True) with open(STARTUP_FILE, mode='r', encoding='UTF-8') as fp: self._yang_startup_data = json.loads(fp.read()) self._yang_handler = YangHandler( YANG_SEARCH_PATH, self._yang_module_names, self._yang_startup_data ) self._app = Flask(__name__) self._app.config['SECRET_KEY'] = SECRET_KEY self._app.after_request(log_request) self._api = Api(self._app, prefix=RESTCONF_PREFIX) def get_startup_data(self) -> None: return self._yang_startup_data def register_host_meta(self) -> None: self._api.add_resource( HostMeta, '/.well-known/host-meta', resource_class_args=(RESTCONF_PREFIX,) ) def register_restconf(self) -> None: self._api.add_resource( RestConfDispatch, '/data', '/data/', '/data/<path:subpath>', '/data/<path:subpath>/', resource_class_args=(self._yang_handler,) ) def register_endpoints(self) -> None: self.register_host_meta() self.register_restconf() def get_flask_app(self) -> Flask: return self._app def get_flask_api(self) -> Api: return self._api def dump_configuration(self) -> None: LOGGER.info('Available RESTCONF paths:') restconf_paths = self._yang_handler.get_schema_paths() for restconf_path in sorted(restconf_paths): LOGGER.info('- {:s}'.format(str(restconf_path))) src/common/tools/rest_conf/server/restconf_server/app.py +8 −64 Original line number Diff line number Diff line Loading @@ -13,19 +13,8 @@ # limitations under the License. import json, logging, os, secrets, time from flask import Flask, request from flask_restful import Api from .Dispatch import RestConfDispatch from .HostMeta import HostMeta from .YangHandler import YangHandler from .YangModelDiscoverer import YangModuleDiscoverer RESTCONF_PREFIX = os.environ.get('RESTCONF_PREFIX', '/restconf' ) YANG_SEARCH_PATH = os.environ.get('YANG_SEARCH_PATH', './yang' ) STARTUP_FILE = os.environ.get('STARTUP_FILE', './startup.json') SECRET_KEY = os.environ.get('SECRET_KEY', secrets.token_hex(64)) import logging from .RestConfServerApplication import RestConfServerApplication logging.basicConfig( Loading @@ -34,56 +23,11 @@ logging.basicConfig( ) LOGGER = logging.getLogger(__name__) LOGGER.info('Starting...') rcs_app = RestConfServerApplication() LOGGER.info('All connectors registered') def log_request(response): timestamp = time.strftime('[%Y-%b-%d %H:%M]') LOGGER.info( '%s %s %s %s %s', timestamp, request.remote_addr, request.method, request.full_path, response.status ) return response ymd = YangModuleDiscoverer(YANG_SEARCH_PATH) YANG_MODULE_NAMES = ymd.run(do_log_order=True) with open(STARTUP_FILE, mode='r', encoding='UTF-8') as fp: YANG_STARTUP_DATA = json.loads(fp.read()) ymd = YangModuleDiscoverer(YANG_SEARCH_PATH) YANG_MODULE_NAMES = ymd.run(do_log_order=True) with open(STARTUP_FILE, mode='r', encoding='UTF-8') as fp: YANG_STARTUP_DATA = json.loads(fp.read()) yang_handler = YangHandler( YANG_SEARCH_PATH, YANG_MODULE_NAMES, YANG_STARTUP_DATA ) restconf_paths = yang_handler.get_schema_paths() app = Flask(__name__) app.config['SECRET_KEY'] = SECRET_KEY app.after_request(log_request) api = Api(app) api.add_resource( HostMeta, '/.well-known/host-meta', resource_class_args=(RESTCONF_PREFIX,) ) api.add_resource( RestConfDispatch, RESTCONF_PREFIX + '/data', RESTCONF_PREFIX + '/data/', RESTCONF_PREFIX + '/data/<path:subpath>', RESTCONF_PREFIX + '/data/<path:subpath>/', resource_class_args=(yang_handler,) ) rcs_app.dump_configuration() app = rcs_app.get_flask_app() LOGGER.info('Available RESTCONF paths:') for restconf_path in sorted(restconf_paths): LOGGER.info('- {:s}'.format(str(restconf_path))) LOGGER.info('Initialization completed!') Loading
src/common/tools/rest_conf/server/restconf_server/Config.py 0 → 100644 +22 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os, secrets RESTCONF_PREFIX = os.environ.get('RESTCONF_PREFIX', '/restconf' ) YANG_SEARCH_PATH = os.environ.get('YANG_SEARCH_PATH', './yang' ) STARTUP_FILE = os.environ.get('STARTUP_FILE', './startup.json') SECRET_KEY = os.environ.get('SECRET_KEY', secrets.token_hex(64))
src/common/tools/rest_conf/server/restconf_server/RestConfServerApplication.py 0 → 100644 +95 −0 Original line number Diff line number Diff line # Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json, logging, time from flask import Flask, request from flask_restful import Api from .Config import RESTCONF_PREFIX, SECRET_KEY, STARTUP_FILE, YANG_SEARCH_PATH from .Dispatch import RestConfDispatch from .HostMeta import HostMeta from .YangHandler import YangHandler from .YangModelDiscoverer import YangModuleDiscoverer logging.basicConfig( level=logging.INFO, format='[Worker-%(process)d][%(asctime)s] %(levelname)s:%(name)s:%(message)s', ) LOGGER = logging.getLogger(__name__) def log_request(response): timestamp = time.strftime('[%Y-%b-%d %H:%M]') LOGGER.info( '%s %s %s %s %s', timestamp, request.remote_addr, request.method, request.full_path, response.status ) return response class RestConfServerApplication: def __init__(self) -> None: self._ymd = YangModuleDiscoverer(YANG_SEARCH_PATH) self._yang_module_names = self._ymd.run(do_log_order=True) with open(STARTUP_FILE, mode='r', encoding='UTF-8') as fp: self._yang_startup_data = json.loads(fp.read()) self._yang_handler = YangHandler( YANG_SEARCH_PATH, self._yang_module_names, self._yang_startup_data ) self._app = Flask(__name__) self._app.config['SECRET_KEY'] = SECRET_KEY self._app.after_request(log_request) self._api = Api(self._app, prefix=RESTCONF_PREFIX) def get_startup_data(self) -> None: return self._yang_startup_data def register_host_meta(self) -> None: self._api.add_resource( HostMeta, '/.well-known/host-meta', resource_class_args=(RESTCONF_PREFIX,) ) def register_restconf(self) -> None: self._api.add_resource( RestConfDispatch, '/data', '/data/', '/data/<path:subpath>', '/data/<path:subpath>/', resource_class_args=(self._yang_handler,) ) def register_endpoints(self) -> None: self.register_host_meta() self.register_restconf() def get_flask_app(self) -> Flask: return self._app def get_flask_api(self) -> Api: return self._api def dump_configuration(self) -> None: LOGGER.info('Available RESTCONF paths:') restconf_paths = self._yang_handler.get_schema_paths() for restconf_path in sorted(restconf_paths): LOGGER.info('- {:s}'.format(str(restconf_path)))
src/common/tools/rest_conf/server/restconf_server/app.py +8 −64 Original line number Diff line number Diff line Loading @@ -13,19 +13,8 @@ # limitations under the License. import json, logging, os, secrets, time from flask import Flask, request from flask_restful import Api from .Dispatch import RestConfDispatch from .HostMeta import HostMeta from .YangHandler import YangHandler from .YangModelDiscoverer import YangModuleDiscoverer RESTCONF_PREFIX = os.environ.get('RESTCONF_PREFIX', '/restconf' ) YANG_SEARCH_PATH = os.environ.get('YANG_SEARCH_PATH', './yang' ) STARTUP_FILE = os.environ.get('STARTUP_FILE', './startup.json') SECRET_KEY = os.environ.get('SECRET_KEY', secrets.token_hex(64)) import logging from .RestConfServerApplication import RestConfServerApplication logging.basicConfig( Loading @@ -34,56 +23,11 @@ logging.basicConfig( ) LOGGER = logging.getLogger(__name__) LOGGER.info('Starting...') rcs_app = RestConfServerApplication() LOGGER.info('All connectors registered') def log_request(response): timestamp = time.strftime('[%Y-%b-%d %H:%M]') LOGGER.info( '%s %s %s %s %s', timestamp, request.remote_addr, request.method, request.full_path, response.status ) return response ymd = YangModuleDiscoverer(YANG_SEARCH_PATH) YANG_MODULE_NAMES = ymd.run(do_log_order=True) with open(STARTUP_FILE, mode='r', encoding='UTF-8') as fp: YANG_STARTUP_DATA = json.loads(fp.read()) ymd = YangModuleDiscoverer(YANG_SEARCH_PATH) YANG_MODULE_NAMES = ymd.run(do_log_order=True) with open(STARTUP_FILE, mode='r', encoding='UTF-8') as fp: YANG_STARTUP_DATA = json.loads(fp.read()) yang_handler = YangHandler( YANG_SEARCH_PATH, YANG_MODULE_NAMES, YANG_STARTUP_DATA ) restconf_paths = yang_handler.get_schema_paths() app = Flask(__name__) app.config['SECRET_KEY'] = SECRET_KEY app.after_request(log_request) api = Api(app) api.add_resource( HostMeta, '/.well-known/host-meta', resource_class_args=(RESTCONF_PREFIX,) ) api.add_resource( RestConfDispatch, RESTCONF_PREFIX + '/data', RESTCONF_PREFIX + '/data/', RESTCONF_PREFIX + '/data/<path:subpath>', RESTCONF_PREFIX + '/data/<path:subpath>/', resource_class_args=(yang_handler,) ) rcs_app.dump_configuration() app = rcs_app.get_flask_app() LOGGER.info('Available RESTCONF paths:') for restconf_path in sorted(restconf_paths): LOGGER.info('- {:s}'.format(str(restconf_path))) LOGGER.info('Initialization completed!')