def close(self): """ Disconnect to equipment via ssh using PyEz. :returns: True on success or raise an exception on any fail (will NOT return a false result, due project decision). """ log.info("Trying to close connection on host {} ... ".format(self.equipment_access.fqdn)) try: if self.remote_conn is not None: self.remote_conn.close() log.info("The connection was closed successfully on host {}!".format(self.equipment_access.fqdn)) return True else: log.warning("To connection couldn't be closed because object is None") except ConnectClosedError as e: message = "Cannot close connection on juniper host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) except Exception as e: message = "Unknown error while closing connection on host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message)
def act(self, action="", data=None, contentType='json'): actions = { 'get_nodes': { 'path': '/restconf/config/opendaylight-inventory:nodes', 'method': 'get', }, 'add_flow': { 'path': '/restconf/config/opendaylight-inventory:nodes', 'method': 'get', } } host = self._get_host() path = actions[action]["path"] uri = self._get_uri(host=host, path=path) method = actions[action]["method"] if data != None: data = json.dump(data) data = data.strip() print data raise exceptions.APIException() return self._request(method=method, uri=uri, data=data, contentType=contentType)
def __try_lock(self): """ Try to lock equipment. :returns: Returns True if success, otherwise, raise an exception. That means will NOT return a false result. """ log.info("Trying to lock host {} ...".format(self.equipment_access.fqdn)) for x in range(self.quantity_of_times_to_try_lock): try: self.configuration.lock() log.info("Host {} was locked successfully!".format(self.equipment_access.fqdn)) return True except LockError as e: count = x + 1 log.warning( "Host {} could not be locked. Automatic try in {} seconds ({}/{}): {}".format( self.equipment_access.fqdn, self.seconds_to_wait_to_try_lock, count, self.quantity_of_times_to_try_lock, e)) time.sleep(self.seconds_to_wait_to_try_lock) except Exception as e: log.error("Unknown error while trying to lock c the equipment on host {}: {}".format( self.equipment_access.fqdn, e)) message = "Errors occurred in all attempts to lock {}. Anybody has locked?".format(self.equipment_access.fqdn) log.error(message) raise exceptions.APIException(message)
def copyScriptFileToConfig(self, filename, use_vrf='', destination=''): """ Receives the file path (usually in /mnt/scripts/tftpboot/networkapi/generated_config/interface/) where contains the command to be executed in the equipment :param str filename: must contain the full path and file name :param str use_vrf: not used :param str destination: not used :returns: Returns a success message, otherwise, raise an exception. That means will NOT return a false result. """ log.info("Trying to load file configuration for host {} ...".format(self.equipment_access.fqdn)) # 'filename' was defined in super class, but in plugin junos the 'file_path' will be used instead file_path = filename file_path = self.check_configuration_file_exists(file_path) try: command_file = open(file_path, "r") command = command_file.read() log.info("Load configuration from file {} successfully!".format(file_path)) return self.exec_command(command) except IOError as e: self.close() message = "Configuration file not found." # Message to client log.error("{} {}: {}".format(message, file_path, e)) # Message to log raise exceptions.APIException(message)
def connect(self): """ Connects to equipment via ssh using PyEz and create connection with invoked shell object. :returns: True on success or raise an exception on any fail (will NOT return a false result, due project decision). """ if self.equipment_access is None: try: # Collect the credentials (user and password) for equipment self.equipment_access = EquipamentoAcesso.search(None, self.equipment, 'ssh').uniqueResult() except Exception as e: message = "Unknown error while accessing equipment {} in database.".format( self.equipment.nome) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) log.info("Trying to connect on host {} ... ".format(self.equipment_access.fqdn)) try: self.remote_conn = Device( host=self.equipment_access.fqdn, user=self.equipment_access.user, passwd=self.equipment_access.password, port=self.connect_port) self.remote_conn.open() self.configuration = Config(self.remote_conn) if self.remote_conn.connected: log.info("The connection on host {} was opened successfully!".format(self.equipment_access.fqdn)) return True except ConnectError as e: message = "Authentication failed trying to connect host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.ConnectionException(message) except Exception as e: message = "Unknown error while connecting to host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message)
def ensure_privilege_level(self, privilege_level=None): """ Ensure privilege level verifying if the current user is super-user. :returns: Returns True if success, otherwise, raise an exception (it will NOT return a false result) """ log.info("Trying to ensure privilege level for user {} on host {} ... ".format( self.equipment_access.user, self.equipment_access.fqdn)) try: # timeout: duration of time in seconds must wait for the expected result ss = StartShell(self.remote_conn, timeout=2) ss.open() output = ss.run('cli -c "show cli authorization"') # output is a tuple [bool, string], example: # (False, u'cli -c "show cli authorization"\r\r\nCurrent user: \'root \' class \'super-user\ ....) # This string will be parsed to get the user class: # get the target part and split it by \n result = output[1].split('\n') # get the target part; split by '; and get the target part current_user_class = result[1].split("'")[3] if current_user_class != 'super-user': message = "Couldn't validate user privileges on host {}.".format(self.equipment_access.fqdn) log.error("{}. User {} class is '{}' and need to be 'super-user'" "(close connection will be executed for safety)" .format(message, self.equipment_access.user, current_user_class)) self.close() raise exceptions.APIException(message) else: log.info("The privilege for user {} ('super-user') was satisfied on host {}!".format( self.equipment_access.user, self.equipment_access.fqdn)) return True except Exception as e: message = "Unknown error while verifying user privilege on host {} ".format(self.equipment_access.fqdn) log.error("(close connection will be executed for safety): {}".format(message, e)) self.close() raise exceptions.APIException(message)
def check_configuration_file_exists(self, file_path): """ This function try to find and build (if necessary) the configuration file path. The priorities are: (1) build the full path from system variable base and relative file path ('file_path'); or (2) build the full path from static variable base and relative file path ('file_path'); or (3) return the relative path it self ('file_path') :param str file_path: Relative path, examples: 'networkapi/plugins/Juniper/JUNOS/samples/sample_command.txt' or 'networkapi/generated_config/interface/int-d_24823_config_ROR9BX3ATQG93TALJAMO2G' :return: Return a valid configuration file path string. Ex.: 'networkapi/plugins/Juniper/JUNOS/samples/sample_command.txt' or '/mnt/scripts/tftpboot/networkapi/generated_config/interface/int-d_24823_config_ROR9BX3ATQG93TALJAMO2G' """ log.info("Checking configuration file exist: {}".format(file_path)) # Check in system variables for variable in self.alternative_variable_base_path_list: try: base_path = get_value(variable) if base_path != "": result_path = base_path + file_path if os.path.isfile(result_path): log.info("Configuration file {} was found by system variable {}!".format(result_path, variable)) return result_path except (DatabaseError, VariableDoesNotExistException): # DatabaseError means that variable table do not exist pass except Exception as e: log.warning("Unknown error while calling networkapi.system.facade.get_value({}): {} {} ".format( variable, e.__class__, e)) # Check possible static variables for static_path in self.alternative_static_base_path_list: result_path = static_path + file_path if os.path.isfile(result_path): log.info("Configuration file {} was found by static variable {}!".format(result_path, static_path)) return result_path # Check if relative path is valid (for dev tests) if os.path.isfile(file_path): log.info("Configuration file {} was found by relative path".format(file_path)) return file_path message = "An error occurred while finding configuration file." log.error("{} Could not find in: relative path ('{}'), system variables ({}) or static paths ({})".format( message, file_path, self.alternative_variable_base_path_list, self.alternative_static_base_path_list)) raise exceptions.APIException(message)
def add_flow(self, data): #TODO: como definir o flow id? onde guardar essa info? ou pegar essa info do controller? #TODO: como definir o controller id? path = "/restconf/config/opendaylight-inventory:nodes/node/openflow:200920773006274/flow-node-inventory:table/0/flow/3" uri = self._get_uri(path=path) data = json.dumps(data).strip().replace(' ', '') #remove qualquer espaço print data raise exceptions.APIException( ) #evitando enviar os flows para o controlador por enquanto return self._request(method=method, uri=uri, data=data, contentType='json')
def exec_command(self, command, success_regex='', invalid_regex=None, error_regex=None): """ Execute a junos command 'set' in the equipment. :param str command: junos command 'set' :param str success_regex: not used :param str invalid_regex: not used :param str error_regex: not used :returns: Returns a success message, otherwise, raise an exception. That means will NOT return a false result. """ log.info("Trying to execute a configuration on host {} ... ".format(self.equipment_access.fqdn)) try: self.__try_lock() self.configuration.rollback() self.configuration.load(command, format='set', ignore_warning=self.ignore_warning_list) self.configuration.commit_check() self.configuration.commit() self.configuration.unlock() result_message = "Configuration junos was executed successfully on {}".format(self.equipment_access.fqdn) log.info(result_message) return result_message except LockError as e: self.close() message = "Couldn't lock host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) except UnlockError as e: message = "Couldn't unlock host {}.".format(self.equipment_access.fqdn) log.error("{} (rollback and close will be tried for safety): {}".format(message, e)) self.configuration.rollback() self.close() raise exceptions.APIException(message) except ConfigLoadError as e: message = "Couldn't load configuration on host {}. Please check template syntax.".format( self.equipment_access.fqdn) log.error("{} (rollback, unlock and close will be tried for safety): {}".format(message, e)) self.configuration.rollback() self.configuration.unlock() self.close() raise exceptions.APIException(message) except CommitError as e: message = "Couldn't commit configuration on host {}.".format(self.equipment_access.fqdn) log.error("{} (rollback, unlock and close will be tried for safety): {}".format(message, e)) self.configuration.rollback() self.configuration.unlock() self.close() raise exceptions.APIException(message) except RpcError as e: message = "A remote procedure call exception occurred on host {} ".format(self.equipment_access.fqdn) log.error("{} (close will be tried for safety): {}".format(message, e)) self.close() raise exceptions.APIException(message)