Skip to content
Snippets Groups Projects
Commit 5ebb9dcb authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Merge branch 'feat/device-oc-acl-candidate' into 'develop'

Device component: Added support for ACLs and Candidate datastore in OpenConfigDriver

See merge request teraflow-h2020/controller!102
parents f83b23a5 bc601571
No related branches found
No related tags found
1 merge request!54Release 2.0.0
Showing
with 333 additions and 61 deletions
...@@ -4,7 +4,7 @@ fastcache==1.1.0 ...@@ -4,7 +4,7 @@ fastcache==1.1.0
grpcio==1.43.0 grpcio==1.43.0
grpcio-health-checking==1.43.0 grpcio-health-checking==1.43.0
Jinja2==3.0.3 Jinja2==3.0.3
netconf-client==2.0.0 #1.7.3 ncclient==0.6.13
p4runtime==1.3.0 p4runtime==1.3.0
paramiko==2.9.2 paramiko==2.9.2
prometheus-client==0.13.0 prometheus-client==0.13.0
......
...@@ -21,6 +21,7 @@ RESOURCE_ENDPOINTS = '__endpoints__' ...@@ -21,6 +21,7 @@ RESOURCE_ENDPOINTS = '__endpoints__'
RESOURCE_INTERFACES = '__interfaces__' RESOURCE_INTERFACES = '__interfaces__'
RESOURCE_NETWORK_INSTANCES = '__network_instances__' RESOURCE_NETWORK_INSTANCES = '__network_instances__'
RESOURCE_ROUTING_POLICIES = '__routing_policies__' RESOURCE_ROUTING_POLICIES = '__routing_policies__'
RESOURCE_ACL = '__acl__'
class _Driver: class _Driver:
def __init__(self, address : str, port : int, **settings) -> None: def __init__(self, address : str, port : int, **settings) -> None:
......
...@@ -20,8 +20,7 @@ from apscheduler.executors.pool import ThreadPoolExecutor ...@@ -20,8 +20,7 @@ from apscheduler.executors.pool import ThreadPoolExecutor
from apscheduler.job import Job from apscheduler.job import Job
from apscheduler.jobstores.memory import MemoryJobStore from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.background import BackgroundScheduler
from netconf_client.connect import connect_ssh, Session from ncclient.manager import Manager, connect_ssh
from netconf_client.ncclient import Manager
from common.tools.client.RetryDecorator import delay_exponential from common.tools.client.RetryDecorator import delay_exponential
from common.type_checkers.Checkers import chk_length, chk_string, chk_type, chk_float from common.type_checkers.Checkers import chk_length, chk_string, chk_type, chk_float
from device.service.driver_api.Exceptions import UnsupportedResourceKeyException from device.service.driver_api.Exceptions import UnsupportedResourceKeyException
...@@ -31,8 +30,10 @@ from device.service.driver_api.AnyTreeTools import TreeNode, get_subnode, set_su ...@@ -31,8 +30,10 @@ from device.service.driver_api.AnyTreeTools import TreeNode, get_subnode, set_su
from .templates import ALL_RESOURCE_KEYS, EMPTY_CONFIG, compose_config, get_filter, parse from .templates import ALL_RESOURCE_KEYS, EMPTY_CONFIG, compose_config, get_filter, parse
from .RetryDecorator import retry from .RetryDecorator import retry
DEBUG_MODE = False DEBUG_MODE = False
#logging.getLogger('ncclient.transport.ssh').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING) logging.getLogger('ncclient.manager').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING)
logging.getLogger('ncclient.transport.ssh').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING)
logging.getLogger('apscheduler.executors.default').setLevel(logging.INFO if DEBUG_MODE else logging.ERROR) logging.getLogger('apscheduler.executors.default').setLevel(logging.INFO if DEBUG_MODE else logging.ERROR)
logging.getLogger('apscheduler.scheduler').setLevel(logging.INFO if DEBUG_MODE else logging.ERROR) logging.getLogger('apscheduler.scheduler').setLevel(logging.INFO if DEBUG_MODE else logging.ERROR)
logging.getLogger('monitoring-client').setLevel(logging.INFO if DEBUG_MODE else logging.ERROR) logging.getLogger('monitoring-client').setLevel(logging.INFO if DEBUG_MODE else logging.ERROR)
...@@ -59,29 +60,41 @@ class NetconfSessionHandler: ...@@ -59,29 +60,41 @@ class NetconfSessionHandler:
self.__connected = threading.Event() self.__connected = threading.Event()
self.__address = address self.__address = address
self.__port = int(port) self.__port = int(port)
self.__username = settings.get('username') self.__username = settings.get('username')
self.__password = settings.get('password') self.__password = settings.get('password')
self.__timeout = int(settings.get('timeout', 120)) self.__key_filename = settings.get('key_filename')
self.__netconf_session : Session = None self.__hostkey_verify = settings.get('hostkey_verify', True)
self.__netconf_manager : Manager = None self.__look_for_keys = settings.get('look_for_keys', True)
self.__allow_agent = settings.get('allow_agent', True)
self.__force_running = settings.get('force_running', False)
self.__device_params = settings.get('device_params', {})
self.__manager_params = settings.get('manager_params', {})
self.__nc_params = settings.get('nc_params', {})
self.__manager : Manager = None
self.__candidate_supported = False
def connect(self): def connect(self):
with self.__lock: with self.__lock:
self.__netconf_session = connect_ssh( self.__manager = connect_ssh(
host=self.__address, port=self.__port, username=self.__username, password=self.__password) host=self.__address, port=self.__port, username=self.__username, password=self.__password,
self.__netconf_manager = Manager(self.__netconf_session, timeout=self.__timeout) device_params=self.__device_params, manager_params=self.__manager_params, nc_params=self.__nc_params,
self.__netconf_manager.set_logger_level(logging.DEBUG if DEBUG_MODE else logging.WARNING) key_filename=self.__key_filename, hostkey_verify=self.__hostkey_verify, allow_agent=self.__allow_agent,
look_for_keys=self.__look_for_keys)
self.__candidate_supported = ':candidate' in self.__manager.server_capabilities
self.__connected.set() self.__connected.set()
def disconnect(self): def disconnect(self):
if not self.__connected.is_set(): return if not self.__connected.is_set(): return
with self.__lock: with self.__lock:
self.__netconf_manager.close_session() self.__manager.close_session()
@property
def use_candidate(self): return self.__candidate_supported and not self.__force_running
@RETRY_DECORATOR @RETRY_DECORATOR
def get(self, filter=None, with_defaults=None): # pylint: disable=redefined-builtin def get(self, filter=None, with_defaults=None): # pylint: disable=redefined-builtin
with self.__lock: with self.__lock:
return self.__netconf_manager.get(filter=filter, with_defaults=with_defaults) return self.__manager.get(filter=filter, with_defaults=with_defaults)
@RETRY_DECORATOR @RETRY_DECORATOR
def edit_config( def edit_config(
...@@ -90,10 +103,16 @@ class NetconfSessionHandler: ...@@ -90,10 +103,16 @@ class NetconfSessionHandler:
): ):
if config == EMPTY_CONFIG: return if config == EMPTY_CONFIG: return
with self.__lock: with self.__lock:
self.__netconf_manager.edit_config( self.__manager.edit_config(
config, target=target, default_operation=default_operation, test_option=test_option, config, target=target, default_operation=default_operation, test_option=test_option,
error_option=error_option, format=format) error_option=error_option, format=format)
def locked(self, target):
return self.__manager.locked(target=target)
def commit(self, confirmed=False, timeout=None, persist=None, persist_id=None):
return self.__manager.commit(confirmed=confirmed, timeout=timeout, persist=persist, persist_id=persist_id)
def compute_delta_sample(previous_sample, previous_timestamp, current_sample, current_timestamp): def compute_delta_sample(previous_sample, previous_timestamp, current_sample, current_timestamp):
if previous_sample is None: return None if previous_sample is None: return None
if previous_timestamp is None: return None if previous_timestamp is None: return None
...@@ -162,6 +181,36 @@ def do_sampling(samples_cache : SamplesCache, resource_key : str, out_samples : ...@@ -162,6 +181,36 @@ def do_sampling(samples_cache : SamplesCache, resource_key : str, out_samples :
except: # pylint: disable=bare-except except: # pylint: disable=bare-except
LOGGER.exception('Error retrieving samples') LOGGER.exception('Error retrieving samples')
def edit_config(
netconf_handler : NetconfSessionHandler, resources : List[Tuple[str, Any]], delete=False, target='running',
default_operation='merge', test_option=None, error_option=None, format='xml' # pylint: disable=redefined-builtin
):
str_method = 'DeleteConfig' if delete else 'SetConfig'
LOGGER.info('[{:s}] resources = {:s}'.format(str_method, str(resources)))
results = [None for _ in resources]
for i,resource in enumerate(resources):
str_resource_name = 'resources[#{:d}]'.format(i)
try:
LOGGER.info('[{:s}] resource = {:s}'.format(str_method, str(resource)))
chk_type(str_resource_name, resource, (list, tuple))
chk_length(str_resource_name, resource, min_length=2, max_length=2)
resource_key,resource_value = resource
chk_string(str_resource_name + '.key', resource_key, allow_empty=False)
str_config_message = compose_config(resource_key, resource_value, delete=delete)
if str_config_message is None: raise UnsupportedResourceKeyException(resource_key)
LOGGER.info('[{:s}] str_config_message[{:d}] = {:s}'.format(
str_method, len(str_config_message), str(str_config_message)))
netconf_handler.edit_config(
config=str_config_message, target=target, default_operation=default_operation,
test_option=test_option, error_option=error_option, format=format)
results[i] = True
except Exception as e: # pylint: disable=broad-except
str_operation = 'preparing' if target == 'candidate' else ('deleting' if delete else 'setting')
msg = '[{:s}] Exception {:s} {:s}: {:s}'
LOGGER.exception(msg.format(str_method, str_operation, str_resource_name, str(resource)))
results[i] = e # if validation fails, store the exception
return results
class OpenConfigDriver(_Driver): class OpenConfigDriver(_Driver):
def __init__(self, address : str, port : int, **settings) -> None: # pylint: disable=super-init-not-called def __init__(self, address : str, port : int, **settings) -> None: # pylint: disable=super-init-not-called
self.__lock = threading.Lock() self.__lock = threading.Lock()
...@@ -227,51 +276,33 @@ class OpenConfigDriver(_Driver): ...@@ -227,51 +276,33 @@ class OpenConfigDriver(_Driver):
def SetConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: def SetConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
chk_type('resources', resources, list) chk_type('resources', resources, list)
if len(resources) == 0: return [] if len(resources) == 0: return []
results = []
LOGGER.info('[SetConfig] resources = {:s}'.format(str(resources)))
with self.__lock: with self.__lock:
for i,resource in enumerate(resources): if self.__netconf_handler.use_candidate:
str_resource_name = 'resources[#{:d}]'.format(i) with self.__netconf_handler.locked(target='candidate'):
try: results = edit_config(self.__netconf_handler, resources, target='candidate')
LOGGER.info('[SetConfig] resource = {:s}'.format(str(resource))) try:
chk_type(str_resource_name, resource, (list, tuple)) self.__netconf_handler.commit()
chk_length(str_resource_name, resource, min_length=2, max_length=2) except Exception as e: # pylint: disable=broad-except
resource_key,resource_value = resource LOGGER.exception('[SetConfig] Exception commiting resources: {:s}'.format(str(resources)))
chk_string(str_resource_name + '.key', resource_key, allow_empty=False) results = [e for _ in resources] # if commit fails, set exception in each resource
str_config_message = compose_config(resource_key, resource_value) else:
if str_config_message is None: raise UnsupportedResourceKeyException(resource_key) results = edit_config(self.__netconf_handler, resources)
LOGGER.info('[SetConfig] str_config_message[{:d}] = {:s}'.format(
len(str_config_message), str(str_config_message)))
self.__netconf_handler.edit_config(str_config_message, target='running')
results.append(True)
except Exception as e: # pylint: disable=broad-except
LOGGER.exception('Exception setting {:s}: {:s}'.format(str_resource_name, str(resource)))
results.append(e) # if validation fails, store the exception
return results return results
def DeleteConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: def DeleteConfig(self, resources : List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
chk_type('resources', resources, list) chk_type('resources', resources, list)
if len(resources) == 0: return [] if len(resources) == 0: return []
results = []
LOGGER.info('[DeleteConfig] resources = {:s}'.format(str(resources)))
with self.__lock: with self.__lock:
for i,resource in enumerate(resources): if self.__netconf_handler.use_candidate:
str_resource_name = 'resources[#{:d}]'.format(i) with self.__netconf_handler.locked(target='candidate'):
try: results = edit_config(self.__netconf_handler, resources, target='candidate', delete=True)
LOGGER.info('[DeleteConfig] resource = {:s}'.format(str(resource))) try:
chk_type(str_resource_name, resource, (list, tuple)) self.__netconf_handler.commit()
chk_length(str_resource_name, resource, min_length=2, max_length=2) except Exception as e: # pylint: disable=broad-except
resource_key,resource_value = resource LOGGER.exception('[DeleteConfig] Exception commiting resources: {:s}'.format(str(resources)))
chk_string(str_resource_name + '.key', resource_key, allow_empty=False) results = [e for _ in resources] # if commit fails, set exception in each resource
str_config_message = compose_config(resource_key, resource_value, delete=True) else:
if str_config_message is None: raise UnsupportedResourceKeyException(resource_key) results = edit_config(self.__netconf_handler, resources, delete=True)
LOGGER.info('[DeleteConfig] str_config_message[{:d}] = {:s}'.format(
len(str_config_message), str(str_config_message)))
self.__netconf_handler.edit_config(str_config_message, target='running')
results.append(True)
except Exception as e: # pylint: disable=broad-except
LOGGER.exception('Exception deleting {:s}: {:s}'.format(str_resource_name, str(resource_key)))
results.append(e) # if validation fails, store the exception
return results return results
def SubscribeState(self, subscriptions : List[Tuple[str, float, float]]) -> List[Union[bool, Exception]]: def SubscribeState(self, subscriptions : List[Tuple[str, float, float]]) -> List[Union[bool, Exception]]:
......
# Copyright 2021-2023 H2020 TeraFlow (https://www.teraflow-h2020.eu/)
#
# 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 logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES
from .Tools import add_value_from_tag
LOGGER = logging.getLogger(__name__)
XPATH_ACL_SET = "//ocacl:acl/ocacl:acl-sets/ocacl:acl-set"
XPATH_A_ACL_ENTRY = ".//ocacl:acl-entries/ocacl:ecl-entry"
XPATH_A_IPv4 = ".//ocacl:ipv4/ocacl:config"
XPATH_A_TRANSPORT = ".//ocacl:transport/ocacl:config"
XPATH_A_ACTIONS = ".//ocacl:actions/ocacl:config"
XPATH_INTERFACE = "//ocacl:acl/ocacl:interfaces/ocacl:interface"
XPATH_I_INGRESS = ".//ocacl:ingress-acl-sets/ocacl:ingress-acl-set"
XPATH_I_EGRESS = ".//ocacl:egress-acl-sets/ocacl:egress-acl-set"
def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
#LOGGER.info('[ACL] xml_data = {:s}'.format(str(ET.tostring(xml_data))))
response = []
acl = {}
for xml_acl in xml_data.xpath(XPATH_ACL_SET, namespaces=NAMESPACES):
#LOGGER.info('xml_acl = {:s}'.format(str(ET.tostring(xml_acl))))
acl_name = xml_acl.find('ocacl:name', namespaces=NAMESPACES)
if acl_name is None or acl_name.text is None: continue
add_value_from_tag(acl, 'name', acl_name)
acl_type = xml_acl.find('ocacl:type', namespaces=NAMESPACES)
add_value_from_tag(acl, 'type', acl_type)
for xml_acl_entries in xml_acl.xpath(XPATH_A_ACL_ENTRY, namespaces=NAMESPACES):
acl_id = xml_acl_entries.find('ocacl:sequence_id', namespaces=NAMESPACES)
add_value_from_tag(acl, 'sequence_id', acl_id)
for xml_ipv4 in xml_acl_entries.xpath(XPATH_A_IPv4, namespaces=NAMESPACES):
ipv4_source = xml_ipv4.find('ocacl:source_address', namespaces=NAMESPACES)
add_value_from_tag(acl, 'source_address' , ipv4_source)
ipv4_destination = xml_ipv4.find('ocacl:destination_address', namespaces=NAMESPACES)
add_value_from_tag(acl, 'destination_address' , ipv4_destination)
ipv4_protocol = xml_ipv4.find('ocacl:protocol', namespaces=NAMESPACES)
add_value_from_tag(acl, 'protocol' , ipv4_protocol)
ipv4_dscp = xml_ipv4.find('ocacl:dscp', namespaces=NAMESPACES)
add_value_from_tag(acl, 'dscp' , ipv4_dscp)
ipv4_hop_limit = xml_ipv4.find('ocacl:hop_limit', namespaces=NAMESPACES)
add_value_from_tag(acl, 'hop_limit' , ipv4_hop_limit)
for xml_transport in xml_acl_entries.xpath(XPATH_A_TRANSPORT, namespaces=NAMESPACES):
transport_source = xml_transport.find('ocacl:source_port', namespaces=NAMESPACES)
add_value_from_tag(acl, 'source_port' ,transport_source)
transport_destination = xml_transport.find('ocacl:destination_port', namespaces=NAMESPACES)
add_value_from_tag(acl, 'destination_port' ,transport_destination)
transport_tcp_flags = xml_transport.find('ocacl:tcp_flags', namespaces=NAMESPACES)
add_value_from_tag(acl, 'tcp_flags' ,transport_tcp_flags)
for xml_action in xml_acl_entries.xpath(XPATH_A_ACTIONS, namespaces=NAMESPACES):
action = xml_action.find('ocacl:forwarding_action', namespaces=NAMESPACES)
add_value_from_tag(acl, 'forwarding_action' ,action)
log_action = xml_action.find('ocacl:log_action', namespaces=NAMESPACES)
add_value_from_tag(acl, 'log_action' ,log_action)
resource_key = '/acl/acl-set[{:s}][{:s}]/acl-entry[{:s}]'.format(
acl['name'], acl['type'], acl['sequence-id'])
response.append((resource_key,acl))
for xml_interface in xml_data.xpath(XPATH_INTERFACE, namespaces=NAMESPACES):
interface = {}
interface_id = xml_interface.find('ocacl:id', namespaces=NAMESPACES)
add_value_from_tag(interface, 'id' , interface_id)
for xml_ingress in xml_interface.xpath(XPATH_I_INGRESS, namespaces=NAMESPACES):
i_name = xml_ingress.find('ocacl:set_name_ingress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'ingress_set_name' , i_name)
i_type = xml_ingress.find('ocacl:type_ingress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'ingress_type' , i_type)
resource_key = '/acl/interfaces/ingress[{:s}][{:s}]'.format(
acl['name'], acl['type'])
response.append((resource_key,interface))
for xml_egress in xml_interface.xpath(XPATH_I_EGRESS, namespaces=NAMESPACES):
e_name = xml_egress.find('ocacl:set_name_egress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'egress_set_name' , e_name)
e_type = xml_egress.find('ocacl:type_egress', namespaces=NAMESPACES)
add_value_from_tag(interface, 'egress_type' , e_type)
resource_key = '/acl/interfaces/egress[{:s}][{:s}]'.format(
acl['name'], acl['type'])
response.append((resource_key,interface))
return response
...@@ -13,8 +13,9 @@ ...@@ -13,8 +13,9 @@
# limitations under the License. # limitations under the License.
NAMESPACE_NETCONF = 'urn:ietf:params:xml:ns:netconf:base:1.0' NAMESPACE_NETCONF = 'urn:ietf:params:xml:ns:netconf:base:1.0'
NAMESPACE_ACL = 'http://openconfig.net/yang/acl'
NAMESPACE_BGP_POLICY = 'http://openconfig.net/yang/bgp-policy' NAMESPACE_BGP_POLICY = 'http://openconfig.net/yang/bgp-policy'
NAMESPACE_INTERFACES = 'http://openconfig.net/yang/interfaces' NAMESPACE_INTERFACES = 'http://openconfig.net/yang/interfaces'
NAMESPACE_INTERFACES_IP = 'http://openconfig.net/yang/interfaces/ip' NAMESPACE_INTERFACES_IP = 'http://openconfig.net/yang/interfaces/ip'
...@@ -30,6 +31,7 @@ NAMESPACE_VLAN = 'http://openconfig.net/yang/vlan' ...@@ -30,6 +31,7 @@ NAMESPACE_VLAN = 'http://openconfig.net/yang/vlan'
NAMESPACES = { NAMESPACES = {
'nc' : NAMESPACE_NETCONF, 'nc' : NAMESPACE_NETCONF,
'ocacl': NAMESPACE_ACL,
'ocbp' : NAMESPACE_BGP_POLICY, 'ocbp' : NAMESPACE_BGP_POLICY,
'oci' : NAMESPACE_INTERFACES, 'oci' : NAMESPACE_INTERFACES,
'ociip': NAMESPACE_INTERFACES_IP, 'ociip': NAMESPACE_INTERFACES_IP,
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
import copy, logging, lxml.etree as ET import copy, logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES from .Namespace import NAMESPACES
from .Tools import add_value_from_collection, add_value_from_tag from .Tools import add_value_from_tag
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
......
...@@ -16,17 +16,19 @@ import json, logging, lxml.etree as ET, re ...@@ -16,17 +16,19 @@ import json, logging, lxml.etree as ET, re
from typing import Any, Dict from typing import Any, Dict
from jinja2 import Environment, PackageLoader, select_autoescape from jinja2 import Environment, PackageLoader, select_autoescape
from device.service.driver_api._Driver import ( from device.service.driver_api._Driver import (
RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES, RESOURCE_ROUTING_POLICIES) RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES, RESOURCE_ROUTING_POLICIES, RESOURCE_ACL)
from .EndPoints import parse as parse_endpoints from .EndPoints import parse as parse_endpoints
from .Interfaces import parse as parse_interfaces, parse_counters from .Interfaces import parse as parse_interfaces, parse_counters
from .NetworkInstances import parse as parse_network_instances from .NetworkInstances import parse as parse_network_instances
from .RoutingPolicy import parse as parse_routing_policy from .RoutingPolicy import parse as parse_routing_policy
from .Acl import parse as parse_acl
ALL_RESOURCE_KEYS = [ ALL_RESOURCE_KEYS = [
RESOURCE_ENDPOINTS, RESOURCE_ENDPOINTS,
RESOURCE_INTERFACES, RESOURCE_INTERFACES,
RESOURCE_ROUTING_POLICIES, # routing policies should come before network instances RESOURCE_ROUTING_POLICIES, # routing policies should come before network instances
RESOURCE_NETWORK_INSTANCES, RESOURCE_NETWORK_INSTANCES,
RESOURCE_ACL,
] ]
RESOURCE_KEY_MAPPINGS = { RESOURCE_KEY_MAPPINGS = {
...@@ -34,6 +36,7 @@ RESOURCE_KEY_MAPPINGS = { ...@@ -34,6 +36,7 @@ RESOURCE_KEY_MAPPINGS = {
RESOURCE_INTERFACES : 'interface', RESOURCE_INTERFACES : 'interface',
RESOURCE_NETWORK_INSTANCES: 'network_instance', RESOURCE_NETWORK_INSTANCES: 'network_instance',
RESOURCE_ROUTING_POLICIES : 'routing_policy', RESOURCE_ROUTING_POLICIES : 'routing_policy',
RESOURCE_ACL : 'acl',
} }
RESOURCE_PARSERS = { RESOURCE_PARSERS = {
...@@ -42,6 +45,7 @@ RESOURCE_PARSERS = { ...@@ -42,6 +45,7 @@ RESOURCE_PARSERS = {
'network_instance': parse_network_instances, 'network_instance': parse_network_instances,
'routing_policy' : parse_routing_policy, 'routing_policy' : parse_routing_policy,
'interfaces/interface/state/counters': parse_counters, 'interfaces/interface/state/counters': parse_counters,
'acl' : parse_acl,
} }
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
......
<acl xmlns="http://openconfig.net/yang/acl">
<acl-sets>
<acl-set{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
<name>{{name}}</name>
<type>{{type}}</type>
<config>
<name>{{name}}</name>
<type>{{type}}</type>
</config>
<acl-entries>
<acl-entry>
<sequence-id>{{sequence_id}}</sequence-id>
<config>
<sequence-id>{{sequence_id}}</sequence-id>
</config>
<ipv4>
<config>
{% if source_address is defined %}<source-address>{{source_address}}</source-address>{% endif%}
{% if destination_address is defined %}<destination-address>{{destination_address}}</destination-address>{% endif%}
{% if protocol is defined %}<protocol>{{protocol}}</protocol>{% endif%}
{% if dscp is defined %}<dscp>{{dscp}}</dscp>{% endif%}
{% if hop_limit is defined %}<hop-limit>{{hop_limit}}</hop-limit>{% endif%}
</config>
</ipv4>
<transport>
<config>
{% if source_port is defined %}<source-port>{{source_port}}</source-port>{% endif%}
{% if destination_port is defined %}<destination-port>{{destination_port}}</destination-port>{% endif%}
{% if tcp_flags is defined %}<tcp-flags>{{tcp_flags}}</tcp-flags>{% endif%}
</config>
</transport>
<actions>
<config>
{% if forwarding_action is defined %}<forwarding-action>{{forwarding_action}}</forwarding-action>{% endif%}
{% if log_action is defined %}<log-action>{{log_action}}</log-action>{% endif%}
</config>
</actions>
</acl-entry>
</acl-entries>
</acl-set>
</acl-sets>
</acl>
<acl xmlns="http://openconfig.net/yang/acl">
<acl-sets>
</acl-sets>
<interfaces>
</interfaces>
</acl>
\ No newline at end of file
<acl xmlns="http://openconfig.net/yang/acl">
<interfaces>
<interface{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
<id>{{id}}</id>
<config>
<id>{{id}}</id>
</config>
<interface-ref>
<config>
<interface>{{interface}}</interface>
{% if subinterface is defined %}<subinterface>{{subinterface}}</subinterface>{% endif%}
</config>
</interface-ref>
<egress-acl-sets>
<egress-acl-set>
<set-name>{{set_name_egress}}</set-name>
<type>{{type_egress}}</type>
<config>
<set-name>{{set_name_egress}}</set-name>
<type>{{type_egress}}</type>
</config>
</egress-acl-set>
</egress-acl-sets>
</interface>
</interfaces>
</acl>
<acl xmlns="http://openconfig.net/yang/acl">
<interfaces>
<interface{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
<id>{{id}}</id>
<config>
<id>{{id}}</id>
</config>
<interface-ref>
<config>
<interface>{{interface}}</interface>
{% if subinterface is defined %}<subinterface>{{subinterface}}</subinterface>{% endif%}
</config>
</interface-ref>
<ingress-acl-sets>
<ingress-acl-set>
<set-name>{{set_name_ingress}}</set-name>
<type>{{type_ingress}}</type>
<config>
<set-name>{{set_name_ingress}}</set-name>
<type>{{type_ingress}}</type>
</config>
</ingress-acl-set>
</ingress-acl-sets>
</interface>
</interfaces>
</acl>
# Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc. # Add here your files containing confidential testbed details such as IP addresses, ports, usernames, passwords, etc.
Device_OpenConfig_Adva*
Device_OpenConfig_Cisco*
Device_OpenConfig_Infinera* Device_OpenConfig_Infinera*
Device_Transport_Api* Device_Transport_Api*
...@@ -20,15 +20,20 @@ DEVICE_OC_ADDRESS = '127.0.0.1' # populate the Netconf Server IP address of th ...@@ -20,15 +20,20 @@ DEVICE_OC_ADDRESS = '127.0.0.1' # populate the Netconf Server IP address of th
DEVICE_OC_PORT = 830 # populate the Netconf Server port of the device to test DEVICE_OC_PORT = 830 # populate the Netconf Server port of the device to test
DEVICE_OC_USERNAME = 'username' # populate the Netconf Server username of the device to test DEVICE_OC_USERNAME = 'username' # populate the Netconf Server username of the device to test
DEVICE_OC_PASSWORD = 'password' # populate the Netconf Server password of the device to test DEVICE_OC_PASSWORD = 'password' # populate the Netconf Server password of the device to test
DEVICE_OC_TIMEOUT = 120 DEVICE_OC_TIMEOUT = 15
DEVICE_OC_ID = json_device_id(DEVICE_OC_UUID) DEVICE_OC_ID = json_device_id(DEVICE_OC_UUID)
DEVICE_OC = json_device_packetrouter_disabled(DEVICE_OC_UUID) DEVICE_OC = json_device_packetrouter_disabled(DEVICE_OC_UUID)
DEVICE_OC_CONNECT_RULES = json_device_connect_rules(DEVICE_OC_ADDRESS, DEVICE_OC_PORT, { DEVICE_OC_CONNECT_RULES = json_device_connect_rules(DEVICE_OC_ADDRESS, DEVICE_OC_PORT, {
'username': DEVICE_OC_USERNAME, 'username' : DEVICE_OC_USERNAME,
'password': DEVICE_OC_PASSWORD, 'password' : DEVICE_OC_PASSWORD,
'timeout' : DEVICE_OC_TIMEOUT, 'force_running' : False,
'hostkey_verify' : True,
'look_for_keys' : True,
'allow_agent' : True,
'device_params' : {'name': 'default'},
'manager_params' : {'timeout' : DEVICE_OC_TIMEOUT},
}) })
DEVICE_OC_CONFIG_RULES = [] # populate your configuration rules to test DEVICE_OC_CONFIG_RULES = [] # populate your configuration rules to test
......
...@@ -55,6 +55,9 @@ ENABLE_EMULATED = True ...@@ -55,6 +55,9 @@ ENABLE_EMULATED = True
try: try:
from .Device_OpenConfig_Infinera1 import( from .Device_OpenConfig_Infinera1 import(
#from .Device_OpenConfig_Infinera2 import( #from .Device_OpenConfig_Infinera2 import(
#from .Device_OpenConfig_Cisco import(
#from .Device_OpenConfig_Adva import(
DEVICE_OC, DEVICE_OC_CONFIG_RULES, DEVICE_OC_DECONFIG_RULES, DEVICE_OC_CONNECT_RULES, DEVICE_OC_ID, DEVICE_OC, DEVICE_OC_CONFIG_RULES, DEVICE_OC_DECONFIG_RULES, DEVICE_OC_CONNECT_RULES, DEVICE_OC_ID,
DEVICE_OC_UUID) DEVICE_OC_UUID)
ENABLE_OPENCONFIG = True ENABLE_OPENCONFIG = True
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment