diff --git a/ci-scripts/python_v2/README.md b/ci-scripts/python_v2/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c27442d328e258d62a598d0b604ef23679b2156d
--- /dev/null
+++ b/ci-scripts/python_v2/README.md
@@ -0,0 +1,90 @@
+# How to contribute in the OAI new python framework. #
+
+The [PEP 8 style guide](https://www.python.org/dev/peps/pep-0008/) is authoritative.
+
+## Documentation ##
+
+*  Document all public functions and *keep those docs up to date* when you make changes.
+*  We use Google style docstrings in our codebase
+
+Example:
+
+```python
+def foo(arg1: str) -> int:
+    """Returns the length of arg1.
+
+    Args:
+        arg1 (str): string to calculate the length of
+
+    Returns: the length of the provided parameter
+    """
+    return len(arg1)
+```
+
+## Formatters ##
+
+* We recommend to use `autopep8`, `isort` and `add-trailing-comma` as they conform to pep8.
+* We do not recommend other formatters such as `black`, as it diverges from pep8 on basic things like line length, etc.
+
+### Installation of `isort` ###
+
+See for details at [isort](https://pypi.org/project/isort/)
+
+```bash
+pip install isort
+```
+
+Usage:
+
+```bash
+isort oai-ci-test-main.py
+```
+
+### Installation of `autopep8` ###
+
+See for details at [autopep8](https://pypi.org/project/autopep8/)
+
+```bash
+pip install --upgrade autopep8
+```
+
+Usage:
+
+```bash
+autopep8 --select W191,W291,W292,W293,W391,E2,E3 -r --in-place oai-ci-test-main.py
+```
+
+### Installation of `add-trailing-comma` ###
+
+See for details at [add-trailing-comma](https://pypi.org/project/add-trailing-comma/)
+
+```bash
+pip install add-trailing-comma
+```
+
+Usage:
+
+```bash
+add-trailing-comma --py35-plus --exit-zero-even-if-changed oai-ci-test-main.py
+```
+
+### Linter ###
+
+Formatting does not mean your code is pep8-compliant.
+
+See for details at [flake8](https://pypi.org/project/flake8/)
+
+```bash
+pip install flake8
+```
+
+Usage:
+
+You shall be in this folder so it can use `setup.cfg` file as configuration file.
+
+```bash
+cd ci-scripts/python_v2
+flake8 oai-ci-test-main.py
+```
+
+You shall have no error message.
diff --git a/ci-scripts/python_v2/cls_cn.py b/ci-scripts/python_v2/cls_cn.py
index cf7a7842362a3bd0ca702c1479882ab8ba4e7d89..fb5596a2bddba88afd8c11bd4bc066b81b05fa65 100644
--- a/ci-scripts/python_v2/cls_cn.py
+++ b/ci-scripts/python_v2/cls_cn.py
@@ -1,6 +1,34 @@
+"""
+Licensed to the OpenAirInterface (OAI) Software Alliance.
+
+This code is licensed to OSA under one or more contributor license agreements.
+See the NOTICE file distributed with this work for additional information
+regarding copyright ownership.
+The OpenAirInterface Software Alliance licenses this file to You under
+the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+
+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.
+------------------------------------------------------------------------------
+For more information about the OpenAirInterface (OAI) Software Alliance:
+
+    contact@openairinterface.org
+
+"""
+
+
 class CN:
-    def __init__(self,infra,config,deployment):
-        self.Deployment=deployment
-        self.Infra=infra
-        for k,v in config.items():
-            setattr(self,k,v)  
\ No newline at end of file
+    """Object class to support any Core Network operations."""
+
+    def __init__(self, infra, config, deployment):
+        self.Deployment = deployment
+        self.Infra = infra
+        for key, val in config.items():
+            setattr(self, key, val)
diff --git a/ci-scripts/python_v2/cls_ran.py b/ci-scripts/python_v2/cls_ran.py
index 121d011b5306503bdfc77d7ec20d55ec6ec9c548..6733ead9034556cd1011f5d0aab9558ef18aa01b 100644
--- a/ci-scripts/python_v2/cls_ran.py
+++ b/ci-scripts/python_v2/cls_ran.py
@@ -1,6 +1,34 @@
+"""
+Licensed to the OpenAirInterface (OAI) Software Alliance.
+
+This code is licensed to OSA under one or more contributor license agreements.
+See the NOTICE file distributed with this work for additional information
+regarding copyright ownership.
+The OpenAirInterface Software Alliance licenses this file to You under
+the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+
+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.
+------------------------------------------------------------------------------
+For more information about the OpenAirInterface (OAI) Software Alliance:
+
+    contact@openairinterface.org
+
+"""
+
+
 class NodeB:
-    def __init__(self,infra,config,deployment):
-        self.Deployment=deployment
-        self.Infra=infra
-        for k,v in config.items():
-            setattr(self,k,v)
\ No newline at end of file
+    """Object class to support any RAN (eNB/gNB) operations."""
+
+    def __init__(self, infra, config, deployment):
+        self.Deployment = deployment
+        self.Infra = infra
+        for key, val in config.items():
+            setattr(self, key, val)
diff --git a/ci-scripts/python_v2/cls_ue.py b/ci-scripts/python_v2/cls_ue.py
index f0cf440f2c7bd2e8831b9401422235fa5ec0ab56..9e8ad755a9f07f7eb4e171ad0ec1be85a51ca98a 100644
--- a/ci-scripts/python_v2/cls_ue.py
+++ b/ci-scripts/python_v2/cls_ue.py
@@ -1,6 +1,34 @@
+"""
+Licensed to the OpenAirInterface (OAI) Software Alliance.
+
+This code is licensed to OSA under one or more contributor license agreements.
+See the NOTICE file distributed with this work for additional information
+regarding copyright ownership.
+The OpenAirInterface Software Alliance licenses this file to You under
+the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+
+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.
+------------------------------------------------------------------------------
+For more information about the OpenAirInterface (OAI) Software Alliance:
+
+    contact@openairinterface.org
+
+"""
+
+
 class UE:
-    def __init__(self,infra,config,deployment):
-        self.Deployment=deployment
-        self.Infra=infra
-        for k,v in config.items():
-            setattr(self,k,v)  
\ No newline at end of file
+    """Object class to support any UE operations."""
+
+    def __init__(self, infra, config, deployment):
+        self.Deployment = deployment
+        self.Infra = infra
+        for key, val in config.items():
+            setattr(self, key, val)
diff --git a/ci-scripts/python_v2/main.py b/ci-scripts/python_v2/main.py
deleted file mode 100644
index 1fab121ed33a3cc8b35101c01e5c3d436ec50fa3..0000000000000000000000000000000000000000
--- a/ci-scripts/python_v2/main.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#loading xml action list from yaml
-import yaml
-
-import cls_ue
-import cls_ran
-import cls_cn
-
-
-#from yaml description of test infrastructure, return infrastructure data model
-def GetTestInfrastructure(filename):
-
-    with open(filename,'r') as f:
-        infra = yaml.load(f)
-    return infra
-    
-    
-#from yaml description of testcase, return configuration data model
-def GetTestConfig(filename):
-
-    with open(filename,'r') as f:
-        test_config = yaml.load(f)   
-    return test_config 
-
-
-
-def GetTestObjects(key,infrastructure,test_cfg):
-   
-    part=test_cfg['config'][key]['key'] #identify the relevant infra part from test config naming ex : RAN_0
-    elements=test_cfg['config'][key][key].keys() #retrieve the effective elements under test
-
-    #create dict of Objects under test
-    OBJ={}
-    for n in elements:
-        deployment = test_cfg['config'][key][key][n]['Deploy']          
-        obj_part=infrastructure[part][n] #retrieve the infra part of the element under test only
-        if key=='RAN':
-            OBJ[n]=cls_ran.NodeB(infrastructure,obj_part,deployment)  
-        elif key=='CN':
-            OBJ[n]=cls_cn.CN(infrastructure,obj_part,deployment)
-        elif key=='UE':    
-            OBJ[n]=cls_ue.UE(infrastructure,obj_part,deployment)
-        else:
-            pass
-    return OBJ #dictionary of objects under test
-    
-
-
-if __name__ == "__main__":
-    testbench='testinfra-as-code.yaml'
-    test='test-example.yaml'
-    infrastructure=GetTestInfrastructure(testbench)
-    test_cfg=GetTestConfig(test)
-    RAN=GetTestObjects('RAN',infrastructure,test_cfg)
-    CN=GetTestObjects('CN',infrastructure,test_cfg)
-    UEs=GetTestObjects('UE',infrastructure,test_cfg)
-
diff --git a/ci-scripts/python_v2/oai-ci-test-main.py b/ci-scripts/python_v2/oai-ci-test-main.py
new file mode 100644
index 0000000000000000000000000000000000000000..8dd125a914df3e1f428fb48f63c5c0b87ea0cfdd
--- /dev/null
+++ b/ci-scripts/python_v2/oai-ci-test-main.py
@@ -0,0 +1,104 @@
+"""
+Licensed to the OpenAirInterface (OAI) Software Alliance.
+
+This code is licensed to OSA under one or more contributor license agreements.
+See the NOTICE file distributed with this work for additional information
+regarding copyright ownership.
+The OpenAirInterface Software Alliance licenses this file to You under
+the OAI Public License, Version 1.1  (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.openairinterface.org/?page_id=698
+
+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.
+------------------------------------------------------------------------------
+For more information about the OpenAirInterface (OAI) Software Alliance:
+
+    contact@openairinterface.org
+
+"""
+
+import yaml
+
+import cls_cn
+import cls_ran
+import cls_ue
+
+
+def get_test_infrastructure(filename):
+    """
+    Load the test infrastructure.
+
+    Args:
+        filename: yaml description file of test infrastructure
+
+    Returns:
+        infra: infrastructure data model
+    """
+    with open(filename, 'r') as infra_yml:
+        infra = yaml.safe_load(infra_yml)
+    return infra
+
+
+def get_test_config(filename):
+    """
+    Load the test configuration data model.
+
+    Args:
+        filename: yaml description file of testcase
+
+    Returns:
+        test_config: test configuration data model
+    """
+    with open(filename, 'r') as test_yml:
+        test_config = yaml.safe_load(test_yml)
+    return test_config
+
+
+def get_test_objects(key, infrastructure, test_cfg):
+    """
+    Load the test objects.
+
+    Args:
+        key: relevant keys to select
+        infrastructure: infrastructure data model
+        test_cfg: test configuration data model
+
+    Returns:
+        dict_obj: dictionary of objects under test
+    """
+    # identify the relevant infra part from test config naming ex : RAN_0
+    part = test_cfg['config'][key]['key']
+    # retrieve the effective elements under test
+    elements = test_cfg['config'][key][key].keys()
+
+    # create dict of Objects under test
+    dict_obj = {}
+    for elt in elements:
+        deployment = test_cfg['config'][key][key][elt]['Deploy']
+        # retrieve the infra part of the element under test only
+        obj_part = infrastructure[part][elt]
+        if key == 'RAN':
+            dict_obj[elt] = cls_ran.NodeB(infrastructure, obj_part, deployment)
+        elif key == 'CN':
+            dict_obj[elt] = cls_cn.CN(infrastructure, obj_part, deployment)
+        elif key == 'UE':
+            dict_obj[elt] = cls_ue.UE(infrastructure, obj_part, deployment)
+        else:
+            pass
+    return dict_obj
+
+
+if __name__ == '__main__':
+    testbench = 'testinfra-as-code.yaml'
+    test = 'test-example.yaml'
+    infrastructure = get_test_infrastructure(testbench)
+    test_cfg = get_test_config(test)
+    RAN = get_test_objects('RAN', infrastructure, test_cfg)
+    CN = get_test_objects('CN', infrastructure, test_cfg)
+    UEs = get_test_objects('UE', infrastructure, test_cfg)
diff --git a/ci-scripts/python_v2/setup.cfg b/ci-scripts/python_v2/setup.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..64051865972a5e69899f45915d65a20fd7b687f3
--- /dev/null
+++ b/ci-scripts/python_v2/setup.cfg
@@ -0,0 +1,19 @@
+[flake8]
+max-complexity = 20
+strictness = short
+
+ignore =
+    WPS102, # Found incorrect module name pattern
+    WPS110, # Found wrong variable name
+    WPS210, # Found too many local variables
+    WPS219, # Found too deep access level
+    WPS306, # Found class without a base class
+    WPS420, # Found wrong keyword
+    # pydocstyle warnings
+    D107,   # Missing docstring in __init_
+    D2,     # White space formatting for doc strings
+    D400,   # First line should end with a period
+
+[isort]
+# Is the same as 80 in flake8:
+line_length = 80
diff --git a/ci-scripts/python_v2/test_read_yaml_struct.py b/ci-scripts/python_v2/test_read_yaml_struct.py
deleted file mode 100644
index 32fa057ef29042a234377f144a8216318bfeb6c2..0000000000000000000000000000000000000000
--- a/ci-scripts/python_v2/test_read_yaml_struct.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-"""
-Created on Tue Jun 29 09:38:02 2021
-
-@author: hardy
-"""
-
-
-class NodeB:
-    def __init__(self,infra,config,deployment):
-        self.deployment=deployment
-        self.infra=infra
-        for k,v in config.items():
-            setattr(self,k,v)
-    
-class UE:
-    def __init__(self,infra,config):
-        self.infra=infra
-        for k,v in config.items():
-            setattr(self,k,v)              
-
-#loading xml action list from yaml
-import yaml
-yaml_file='testinfra-as-code.yaml'
-with open(yaml_file,'r') as f:
-    infra = yaml.load(f)
-    
-    
-yaml_file='test-example.yaml'
-with open(yaml_file,'r') as f:
-    test = yaml.load(f)    
-    
-
-#RAN spec from test    
-ran_key=test['config']['RAN']['key']
-nodes_key=test['config']['RAN']['Nodes'].keys()
-
- #create dict of RAN objects RAN under Test
-RAN={}
-for n in nodes_key:
-    deployment = test['config']['RAN']['Nodes'][n]['Deploy']
-    config=infra[ran_key][n]
-    RAN[n]=NodeB(infra,config,deployment)  
-    
-    
-
-#UE spec from test
-ue_key=test['config']['UE']['key']
-allues_key=test['config']['UE']['UEs'].keys()
-
-#create dict of UE objects UE under Test
-UEs={}
-for u in allues_key:
-    config=infra[ue_key][u]
-    UEs[u]=UE(infra,config)  
-    
-
-
-
-
diff --git a/ci-scripts/python_v2/testinfra-as-code.yaml b/ci-scripts/python_v2/testinfra-as-code.yaml
old mode 100755
new mode 100644