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

Device component - OpenConfig Driver

- added device identification per log line
parent 04ca36b1
No related branches found
No related tags found
2 merge requests!142Release TeraFlowSDN 2.1,!37Revision of OpenConfigDriver
...@@ -38,8 +38,6 @@ logging.getLogger('apscheduler.executors.default').setLevel(logging.INFO if DEBU ...@@ -38,8 +38,6 @@ logging.getLogger('apscheduler.executors.default').setLevel(logging.INFO if DEBU
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)
LOGGER = logging.getLogger(__name__)
RE_GET_ENDPOINT_FROM_INTERFACE_KEY = re.compile(r'.*interface\[([^\]]+)\].*') RE_GET_ENDPOINT_FROM_INTERFACE_KEY = re.compile(r'.*interface\[([^\]]+)\].*')
RE_GET_ENDPOINT_FROM_INTERFACE_XPATH = re.compile(r".*interface\[oci\:name\='([^\]]+)'\].*") RE_GET_ENDPOINT_FROM_INTERFACE_XPATH = re.compile(r".*interface\[oci\:name\='([^\]]+)'\].*")
...@@ -141,8 +139,9 @@ def compute_delta_sample(previous_sample, previous_timestamp, current_sample, cu ...@@ -141,8 +139,9 @@ def compute_delta_sample(previous_sample, previous_timestamp, current_sample, cu
return delta_sample return delta_sample
class SamplesCache: class SamplesCache:
def __init__(self, netconf_handler : NetconfSessionHandler) -> None: def __init__(self, netconf_handler : NetconfSessionHandler, logger : logging.Logger) -> None:
self.__netconf_handler = netconf_handler self.__netconf_handler = netconf_handler
self.__logger = logger
self.__lock = threading.Lock() self.__lock = threading.Lock()
self.__timestamp = None self.__timestamp = None
self.__absolute_samples = {} self.__absolute_samples = {}
...@@ -166,7 +165,7 @@ class SamplesCache: ...@@ -166,7 +165,7 @@ class SamplesCache:
self.__absolute_samples[interface] = samples self.__absolute_samples[interface] = samples
self.__timestamp = now self.__timestamp = now
except: # pylint: disable=bare-except except: # pylint: disable=bare-except
LOGGER.exception('Error collecting samples') self.__logger.exception('Error collecting samples')
def get(self, resource_key : str) -> Tuple[float, Dict]: def get(self, resource_key : str) -> Tuple[float, Dict]:
self._refresh_samples() self._refresh_samples()
...@@ -176,31 +175,33 @@ class SamplesCache: ...@@ -176,31 +175,33 @@ class SamplesCache:
interface = match.group(1) interface = match.group(1)
return self.__timestamp, copy.deepcopy(self.__delta_samples.get(interface, {})) return self.__timestamp, copy.deepcopy(self.__delta_samples.get(interface, {}))
def do_sampling(samples_cache : SamplesCache, resource_key : str, out_samples : queue.Queue) -> None: def do_sampling(
samples_cache : SamplesCache, logger : logging.Logger, resource_key : str, out_samples : queue.Queue
) -> None:
try: try:
timestamp, samples = samples_cache.get(resource_key) timestamp, samples = samples_cache.get(resource_key)
counter_name = resource_key.split('/')[-1].split(':')[-1] counter_name = resource_key.split('/')[-1].split(':')[-1]
value = samples.get(counter_name) value = samples.get(counter_name)
if value is None: if value is None:
LOGGER.warning('[do_sampling] value not found for {:s}'.format(resource_key)) logger.warning('[do_sampling] value not found for {:s}'.format(resource_key))
return return
sample = (timestamp, resource_key, value) sample = (timestamp, resource_key, value)
out_samples.put_nowait(sample) out_samples.put_nowait(sample)
except: # pylint: disable=bare-except except: # pylint: disable=bare-except
LOGGER.exception('Error retrieving samples') logger.exception('Error retrieving samples')
def edit_config( def edit_config(
netconf_handler : NetconfSessionHandler, resources : List[Tuple[str, Any]], delete=False, commit_per_rule= False, netconf_handler : NetconfSessionHandler, logger : logging.Logger, resources : List[Tuple[str, Any]], delete=False,
target='running', default_operation='merge', test_option=None, error_option=None, commit_per_rule= False, target='running', default_operation='merge', test_option=None, error_option=None,
format='xml' # pylint: disable=redefined-builtin format='xml' # pylint: disable=redefined-builtin
): ):
str_method = 'DeleteConfig' if delete else 'SetConfig' str_method = 'DeleteConfig' if delete else 'SetConfig'
LOGGER.info('[{:s}] resources = {:s}'.format(str_method, str(resources))) logger.info('[{:s}] resources = {:s}'.format(str_method, str(resources)))
results = [None for _ in resources] results = [None for _ in resources]
for i,resource in enumerate(resources): for i,resource in enumerate(resources):
str_resource_name = 'resources[#{:d}]'.format(i) str_resource_name = 'resources[#{:d}]'.format(i)
try: try:
LOGGER.info('[{:s}] resource = {:s}'.format(str_method, str(resource))) logger.info('[{:s}] resource = {:s}'.format(str_method, str(resource)))
chk_type(str_resource_name, resource, (list, tuple)) chk_type(str_resource_name, resource, (list, tuple))
chk_length(str_resource_name, resource, min_length=2, max_length=2) chk_length(str_resource_name, resource, min_length=2, max_length=2)
resource_key,resource_value = resource resource_key,resource_value = resource
...@@ -208,7 +209,7 @@ def edit_config( ...@@ -208,7 +209,7 @@ def edit_config(
str_config_message = compose_config( str_config_message = compose_config(
resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor) resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor)
if str_config_message is None: raise UnsupportedResourceKeyException(resource_key) if str_config_message is None: raise UnsupportedResourceKeyException(resource_key)
LOGGER.info('[{:s}] str_config_message[{:d}] = {:s}'.format( logger.info('[{:s}] str_config_message[{:d}] = {:s}'.format(
str_method, len(str_config_message), str(str_config_message))) str_method, len(str_config_message), str(str_config_message)))
netconf_handler.edit_config( netconf_handler.edit_config(
config=str_config_message, target=target, default_operation=default_operation, config=str_config_message, target=target, default_operation=default_operation,
...@@ -219,7 +220,7 @@ def edit_config( ...@@ -219,7 +220,7 @@ def edit_config(
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
str_operation = 'preparing' if target == 'candidate' else ('deleting' if delete else 'setting') str_operation = 'preparing' if target == 'candidate' else ('deleting' if delete else 'setting')
msg = '[{:s}] Exception {:s} {:s}: {:s}' msg = '[{:s}] Exception {:s} {:s}: {:s}'
LOGGER.exception(msg.format(str_method, str_operation, str_resource_name, str(resource))) logger.exception(msg.format(str_method, str_operation, str_resource_name, str(resource)))
results[i] = e # if validation fails, store the exception results[i] = e # if validation fails, store the exception
return results return results
...@@ -243,6 +244,7 @@ METRICS_POOL.get_or_create('UnsubscribeState', MetricTypeEnum.HISTOGRAM_DURATION ...@@ -243,6 +244,7 @@ METRICS_POOL.get_or_create('UnsubscribeState', MetricTypeEnum.HISTOGRAM_DURATION
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.__logger = logging.getLogger('{:s}:[{:s}:{:s}]'.format(str(__name__), str(address), str(port)))
self.__lock = threading.Lock() self.__lock = threading.Lock()
#self.__initial = TreeNode('.') #self.__initial = TreeNode('.')
#self.__running = TreeNode('.') #self.__running = TreeNode('.')
...@@ -257,7 +259,7 @@ class OpenConfigDriver(_Driver): ...@@ -257,7 +259,7 @@ class OpenConfigDriver(_Driver):
timezone=pytz.utc) timezone=pytz.utc)
self.__out_samples = queue.Queue() self.__out_samples = queue.Queue()
self.__netconf_handler : NetconfSessionHandler = NetconfSessionHandler(address, port, **settings) self.__netconf_handler : NetconfSessionHandler = NetconfSessionHandler(address, port, **settings)
self.__samples_cache = SamplesCache(self.__netconf_handler) self.__samples_cache = SamplesCache(self.__netconf_handler, self.__logger)
def Connect(self) -> bool: def Connect(self) -> bool:
with self.__lock: with self.__lock:
...@@ -295,13 +297,14 @@ class OpenConfigDriver(_Driver): ...@@ -295,13 +297,14 @@ class OpenConfigDriver(_Driver):
try: try:
chk_string(str_resource_name, resource_key, allow_empty=False) chk_string(str_resource_name, resource_key, allow_empty=False)
str_filter = get_filter(resource_key) str_filter = get_filter(resource_key)
LOGGER.info('[GetConfig] str_filter = {:s}'.format(str(str_filter))) self.__logger.info('[GetConfig] str_filter = {:s}'.format(str(str_filter)))
if str_filter is None: str_filter = resource_key if str_filter is None: str_filter = resource_key
xml_data = self.__netconf_handler.get(filter=str_filter).data_ele xml_data = self.__netconf_handler.get(filter=str_filter).data_ele
if isinstance(xml_data, Exception): raise xml_data if isinstance(xml_data, Exception): raise xml_data
results.extend(parse(resource_key, xml_data)) results.extend(parse(resource_key, xml_data))
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
LOGGER.exception('Exception retrieving {:s}: {:s}'.format(str_resource_name, str(resource_key))) MSG = 'Exception retrieving {:s}: {:s}'
self.__logger.exception(MSG.format(str_resource_name, str(resource_key)))
results.append((resource_key, e)) # if validation fails, store the exception results.append((resource_key, e)) # if validation fails, store the exception
return results return results
...@@ -312,17 +315,19 @@ class OpenConfigDriver(_Driver): ...@@ -312,17 +315,19 @@ class OpenConfigDriver(_Driver):
with self.__lock: with self.__lock:
if self.__netconf_handler.use_candidate: if self.__netconf_handler.use_candidate:
with self.__netconf_handler.locked(target='candidate'): with self.__netconf_handler.locked(target='candidate'):
if self.__netconf_handler.commit_per_rule: commit_per_rule = bool(self.__netconf_handler.commit_per_rule)
results = edit_config(self.__netconf_handler, resources, target='candidate', commit_per_rule= True) results = edit_config(
else: self.__netconf_handler, self.__logger, resources, target='candidate',
results = edit_config(self.__netconf_handler, resources, target='candidate') commit_per_rule=commit_per_rule)
if not commit_per_rule:
try: try:
self.__netconf_handler.commit() self.__netconf_handler.commit()
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
LOGGER.exception('[SetConfig] Exception commiting resources: {:s}'.format(str(resources))) MSG = '[SetConfig] Exception commiting resources: {:s}'
self.__logger.exception(MSG.format(str(resources)))
results = [e for _ in resources] # if commit fails, set exception in each resource results = [e for _ in resources] # if commit fails, set exception in each resource
else: else:
results = edit_config(self.__netconf_handler, resources) results = edit_config(self.__netconf_handler, self.__logger, resources)
return results return results
@metered_subclass_method(METRICS_POOL) @metered_subclass_method(METRICS_POOL)
...@@ -332,17 +337,19 @@ class OpenConfigDriver(_Driver): ...@@ -332,17 +337,19 @@ class OpenConfigDriver(_Driver):
with self.__lock: with self.__lock:
if self.__netconf_handler.use_candidate: if self.__netconf_handler.use_candidate:
with self.__netconf_handler.locked(target='candidate'): with self.__netconf_handler.locked(target='candidate'):
if self.__netconf_handler.commit_per_rule: commit_per_rule = bool(self.__netconf_handler.commit_per_rule)
results = edit_config(self.__netconf_handler, resources, target='candidate', delete=True, commit_per_rule= True) results = edit_config(
else: self.__netconf_handler, self.__logger, resources, target='candidate', delete=True,
results = edit_config(self.__netconf_handler, resources, target='candidate', delete=True) commit_per_rule=commit_per_rule)
if not commit_per_rule:
try: try:
self.__netconf_handler.commit() self.__netconf_handler.commit()
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
LOGGER.exception('[DeleteConfig] Exception commiting resources: {:s}'.format(str(resources))) MSG = '[DeleteConfig] Exception commiting resources: {:s}'
self.__logger.exception(MSG.format(str(resources)))
results = [e for _ in resources] # if commit fails, set exception in each resource results = [e for _ in resources] # if commit fails, set exception in each resource
else: else:
results = edit_config(self.__netconf_handler, resources, delete=True) results = edit_config(self.__netconf_handler, self.__logger, resources, delete=True)
return results return results
@metered_subclass_method(METRICS_POOL) @metered_subclass_method(METRICS_POOL)
...@@ -363,7 +370,8 @@ class OpenConfigDriver(_Driver): ...@@ -363,7 +370,8 @@ class OpenConfigDriver(_Driver):
chk_float(str_subscription_name + '.sampling_duration', sampling_duration, min_value=0) chk_float(str_subscription_name + '.sampling_duration', sampling_duration, min_value=0)
chk_float(str_subscription_name + '.sampling_interval', sampling_interval, min_value=0) chk_float(str_subscription_name + '.sampling_interval', sampling_interval, min_value=0)
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
LOGGER.exception('Exception validating {:s}: {:s}'.format(str_subscription_name, str(resource_key))) MSG = 'Exception validating {:s}: {:s}'
self.__logger.exception(MSG.format(str_subscription_name, str(resource_key)))
results.append(e) # if validation fails, store the exception results.append(e) # if validation fails, store the exception
continue continue
...@@ -374,7 +382,7 @@ class OpenConfigDriver(_Driver): ...@@ -374,7 +382,7 @@ class OpenConfigDriver(_Driver):
job_id = 'k={:s}/d={:f}/i={:f}'.format(resource_key, sampling_duration, sampling_interval) job_id = 'k={:s}/d={:f}/i={:f}'.format(resource_key, sampling_duration, sampling_interval)
job = self.__scheduler.add_job( job = self.__scheduler.add_job(
do_sampling, args=(self.__samples_cache, resource_key, self.__out_samples), do_sampling, args=(self.__samples_cache, self.__logger, resource_key, self.__out_samples),
kwargs={}, id=job_id, trigger='interval', seconds=sampling_interval, kwargs={}, id=job_id, trigger='interval', seconds=sampling_interval,
start_date=start_date, end_date=end_date, timezone=pytz.utc) start_date=start_date, end_date=end_date, timezone=pytz.utc)
...@@ -401,7 +409,8 @@ class OpenConfigDriver(_Driver): ...@@ -401,7 +409,8 @@ class OpenConfigDriver(_Driver):
chk_float(str_subscription_name + '.sampling_duration', sampling_duration, min_value=0) chk_float(str_subscription_name + '.sampling_duration', sampling_duration, min_value=0)
chk_float(str_subscription_name + '.sampling_interval', sampling_interval, min_value=0) chk_float(str_subscription_name + '.sampling_interval', sampling_interval, min_value=0)
except Exception as e: # pylint: disable=broad-except except Exception as e: # pylint: disable=broad-except
LOGGER.exception('Exception validating {:s}: {:s}'.format(str_subscription_name, str(resource_key))) MSG = 'Exception validating {:s}: {:s}'
self.__logger.exception(MSG.format(str_subscription_name, str(resource_key)))
results.append(e) # if validation fails, store the exception results.append(e) # if validation fails, store the exception
continue continue
......
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