From c8440f4158805fed1c49d1f06cd71f324eac26a2 Mon Sep 17 00:00:00 2001 From: Koren Lev Date: Mon, 18 Dec 2017 19:16:16 +0200 Subject: release 1.2 + new tagging Change-Id: I1e876451ec4a330f458dd57adadb15e39969b225 Signed-off-by: Koren Lev (cherry picked from commit 98c3ac7c859e34fe60d061b9ca591aba429e4118) --- app/utils/api_access_base.py | 51 ++++++++++++++++++++++++++++++++++++++++++++ app/utils/inventory_mgr.py | 26 +++++++++++++--------- app/utils/mongo_access.py | 6 ++++-- app/utils/ssh_connection.py | 6 ++++-- app/utils/util.py | 9 ++++---- 5 files changed, 80 insertions(+), 18 deletions(-) create mode 100644 app/utils/api_access_base.py (limited to 'app/utils') diff --git a/app/utils/api_access_base.py b/app/utils/api_access_base.py new file mode 100644 index 0000000..31f50b4 --- /dev/null +++ b/app/utils/api_access_base.py @@ -0,0 +1,51 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# and others # +# # +# All rights reserved. This program and the accompanying materials # +# are made available under the terms of the Apache License, Version 2.0 # +# which accompanies this distribution, and is available at # +# http://www.apache.org/licenses/LICENSE-2.0 # +############################################################################### +import requests + +from discover.configuration import Configuration +from discover.fetcher import Fetcher + + +class ApiAccessBase(Fetcher): + + CONNECT_TIMEOUT = 5 + + def __init__(self, api_name=None, config=None): + super().__init__() + if api_name is None: + raise ValueError('ApiAccessBase: api_name must be defined') + self.config = {api_name: config} if config else Configuration() + self.api_config = self.config.get(api_name) + if self.api_config is None: + raise ValueError('ApiAccessBase: section "{}" missing in config' + .format(api_name)) + self.host = self.api_config.get('host', '') + self.port = self.api_config.get('port', '') + if not (self.host and self.port): + raise ValueError('Missing definition of host or port ' + + 'for {} API access' + .format(api_name)) + + def get_rel_url(self, relative_url, headers): + req_url = self.base_url + relative_url + return self.get_url(req_url, headers) + + def get_url(self, req_url, headers): + response = requests.get(req_url, headers=headers) + if response.status_code != requests.codes.ok: + # some error happened + if 'reason' in response: + msg = ', reason: {}'.format(response.reason) + else: + msg = ', response: {}'.format(response.text) + self.log.error('req_url: {} {}'.format(req_url, msg)) + return None + ret = response.json() + return ret diff --git a/app/utils/inventory_mgr.py b/app/utils/inventory_mgr.py index 722d0aa..bbc5542 100644 --- a/app/utils/inventory_mgr.py +++ b/app/utils/inventory_mgr.py @@ -265,6 +265,7 @@ class InventoryMgr(MongoAccess, metaclass=Singleton): # source_label, target_label: labels for the ends of the link (optional) def create_link(self, env, src, source_id, target, target_id, link_type, link_name, state, link_weight, + implicit=False, source_label="", target_label="", host=None, switch=None, extra_attributes=None): @@ -282,6 +283,7 @@ class InventoryMgr(MongoAccess, metaclass=Singleton): "link_weight": link_weight, "source_label": source_label, "target_label": target_label, + "implicit": implicit, "attributes": extra_attributes if extra_attributes else {} } if host: @@ -347,16 +349,18 @@ class InventoryMgr(MongoAccess, metaclass=Singleton): if not env_config: return False - # Workaround for mechanism_drivers field type - mechanism_driver = env_config['mechanism_drivers'][0] \ - if isinstance(env_config['mechanism_drivers'], list) \ - else env_config['mechanism_drivers'] + # Workarounds for mechanism_drivers and distribution_version field types + mechanism_driver = env_config.get('mechanism_drivers') + if isinstance(mechanism_driver, list): + mechanism_driver = mechanism_driver[0] + env_distribution_version = env_config.get('distribution_version') + if isinstance(env_distribution_version, list): + env_distribution_version = env_distribution_version[0] full_env = { - 'environment.distribution': env_config['distribution'], - 'environment.distribution_version': - {"$in": [env_config['distribution_version']]}, - 'environment.type_drivers': env_config['type_drivers'], + 'environment.distribution': env_config.get('distribution'), + 'environment.distribution_version': env_distribution_version, + 'environment.type_drivers': env_config.get('type_drivers'), 'environment.mechanism_drivers': mechanism_driver } return self.is_feature_supported_in_env(full_env, feature) @@ -394,8 +398,10 @@ class InventoryMgr(MongoAccess, metaclass=Singleton): self.log.error("failed to find master parent " + master_parent_id) return False - folder_id_path = "/".join((master_parent["id_path"], o["parent_id"])) - folder_name_path = "/".join((master_parent["name_path"], o["parent_text"])) + folder_id_path = "/".join((master_parent["id_path"], + o["parent_id"])) + folder_name_path = "/".join((master_parent["name_path"], + o["parent_text"])) folder = { "environment": parent["environment"], "parent_id": master_parent_id, diff --git a/app/utils/mongo_access.py b/app/utils/mongo_access.py index d4599f1..75c265c 100644 --- a/app/utils/mongo_access.py +++ b/app/utils/mongo_access.py @@ -36,8 +36,10 @@ class MongoAccess(DictNamingConverter): def __init__(self): super().__init__() - self.log_file = os.path.join(FileLogger.LOG_DIRECTORY, - MongoAccess.LOG_FILENAME) + log_dir = FileLogger.LOG_DIRECTORY \ + if os.path.isdir(FileLogger.LOG_DIRECTORY) \ + else os.path.abspath('.') + self.log_file = os.path.join(log_dir, MongoAccess.LOG_FILENAME) try: self.log = FileLogger(self.log_file) diff --git a/app/utils/ssh_connection.py b/app/utils/ssh_connection.py index e9dd39a..b9b1cde 100644 --- a/app/utils/ssh_connection.py +++ b/app/utils/ssh_connection.py @@ -22,6 +22,7 @@ class SshConnection(BinaryConverter): max_call_count_per_con = 100 timeout = 15 # timeout for exec in seconds + CONNECT_TIMEOUT = 5 DEFAULT_PORT = 22 @@ -118,7 +119,8 @@ class SshConnection(BinaryConverter): pkey=k, port=self.port if self.port is not None else self.DEFAULT_PORT, - password=self.pwd, timeout=30) + password=self.pwd, + timeout=self.CONNECT_TIMEOUT) else: port = None try: @@ -127,7 +129,7 @@ class SshConnection(BinaryConverter): username=self.user, password=self.pwd, port=port, - timeout=30) + timeout=self.CONNECT_TIMEOUT) except paramiko.ssh_exception.AuthenticationException: self.log.error('Failed SSH connect to host {}, port={}' .format(self.host, port)) diff --git a/app/utils/util.py b/app/utils/util.py index ae7b518..17a31c0 100644 --- a/app/utils/util.py +++ b/app/utils/util.py @@ -47,7 +47,6 @@ class ClassResolver: class_name = ''.join(name_parts) return class_name - @staticmethod def get_fully_qualified_class(class_name: str = None, package_name: str = "discover", @@ -58,8 +57,9 @@ class ClassResolver: module_name = ".".join(module_parts) try: class_module = importlib.import_module(module_name) - except ImportError: - raise ValueError('could not import module {}'.format(module_name)) + except ImportError as e: + raise ValueError('could not import module {}: {}' + .format(module_name, str(e))) clazz = getattr(class_module, class_name) return clazz @@ -74,7 +74,8 @@ class ClassResolver: class_name = ClassResolver.get_class_name_by_module(module_name) if class_name in ClassResolver.instances: return 'instance', ClassResolver.instances[class_name] - clazz = ClassResolver.get_fully_qualified_class(class_name, package_name, + clazz = ClassResolver.get_fully_qualified_class(class_name, + package_name, module_name) return 'class', clazz -- cgit 1.2.3-korg