def __init__(self, username, password, host, port): try: self.client = ydk_client.NetconfClient(username, password, host, port, 0) except Exception as e: if isinstance(e, ImportError): raise YPYServiceProviderError( error_msg= 'Native YDK client is not installed. Try installing all dependencies in README and re-installing ydk: ' + str(e)) else: raise YPYServiceProviderError( error_msg=str(type(e)) + '. Could not connect to client: ' + str(e))
def _connect_to_netconf(self, session_config): login_user = self._set_login_user(session_config.username) # Connect with netconf agent via ssh proxy client BUFSIZE = 8192 STDIN = '0' # Assuming stdin will be always 0 on any env STDOUT = '1' # Assuming stdout will be always 1 on any env self.netconf_sp_logger.info( "Connecting to netconf agent on the box...") try: self.p = subprocess.Popen([ 'netconf_sshd_proxy', '-i', STDIN, '-o', STDOUT, '-u', login_user ], bufsize=BUFSIZE, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False) except Exception as err: self.netconf_sp_logger.error("failed (%s)\n" % str(err)) error_msg = ("\nFailed to start netconf session!" "Please make sure you have 'netconf-yang agent ssh'" "configured on your router.") self.netconf_sp_logger.error(error_msg) raise YPYServiceProviderError( error_msg="failed to start netconf session")
def _handle_commit(self, payload, reply_str): if self.onbox: commit = ( '<rpc message-id="101" ' 'xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\n <commit/>\n</rpc>\n' ) else: commit = '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\n <commit/>\n</rpc>\n' self.netconf_sp_logger.debug('\n%s', _get_pretty(commit)) if self.use_native_client: assert self.ydk_client is not None rep = self.ydk_client.execute_payload(commit) elif self.onbox: rep = self.onbox_client.execute_payload(commit) else: assert self._nc_manager is not None rep = self._nc_manager.commit() rep = rep.xml if 'ok' not in rep: self.netconf_sp_logger.error('\n%s\n%s\ncommit-reply\n%s', payload, reply_str, rep) raise YPYServiceProviderError( error_code=YPYErrorCode.SERVER_COMMIT_ERR, error_msg=rep) else: self.netconf_sp_logger.debug('\n%s', _get_pretty(reply_str))
def __init__(self, **kwargs): if (len(kwargs) == 0): raise YPYServiceProviderError('Codec type is required') codec_type = '' for key, val in kwargs.items(): if key == 'type': codec_type = val if codec_type == 'xml': self.encoder = XmlEncoder() self.decoder = XmlDecoder() else: raise YPYServiceProviderError( 'Codec type "{0}" not yet supported'.format(codec_type)) self.logger = logging.getLogger(__name__)
def _create_top_level_entity_from_read_filter(self, read_filter): non_list_filter = read_filter while isinstance(non_list_filter, YList): non_list_filter = non_list_filter.parent if non_list_filter is None: self.netconf_sp_logger.error( 'Cannot determine hierarchy for entity. Please set the parent reference' ) raise YPYServiceProviderError( error_msg= 'Cannot determine hierarchy for entity. Please set the parent reference' ) top_entity_meta_info = non_list_filter._meta_info() while hasattr(top_entity_meta_info, 'parent') and top_entity_meta_info.parent is not None: # need to find the member that has top_entity_meta_info = top_entity_meta_info.parent module = importlib.import_module(top_entity_meta_info.pmodule_name) entity = getattr(module, top_entity_meta_info.name)() return entity
def decode(self, payload, read_filter): if read_filter is None: return XmlDecoder().decode(payload) if self._is_rpc_reply(read_filter): if 'ok' in payload or not self._is_rpc_reply_with_output_data( read_filter): return None XmlDecoder()._bind_to_object(payload, read_filter.output, {}) return read_filter.output # In order to figure out which fields are the # ones we are interested find the field list entity = self._create_top_level_entity_from_read_filter(read_filter) XmlDecoder._bind_to_object(payload, entity, self._get_capabilities()) # drill down to figure out the field access expression # that matches the entity or entities to be returned # not the argument passed in as a filter might have # incomplete key paths, in which case what is returned # will be the entity whose common path can be determined current = entity current_entity = read_filter current_meta = current_entity.i_meta yang_nodes = [] while hasattr(current_meta, 'parent'): yang_nodes.append(current_meta.yang_name) current_meta = current_meta.parent if current_meta: yang_nodes.append(current_meta.yang_name) yang_nodes = list(reversed(yang_nodes)) yang_nodes = yang_nodes[1:] for yang_node_name in yang_nodes: found = False for member in current._meta_info().meta_info_class_members: if member.name == yang_node_name: found = True current = getattr(current, member.presentation_name) if current is None: return None if isinstance(current, YList): if len(current) == 0: return None if len(current) > 2: return current if len(current) == 1: current = current[0] break if not found: self.netconf_sp_logger.error( 'Error determing what needs to be returned') raise YPYServiceProviderError( error_msg='Error determining what needs to be returned') return current
def execute_payload(self, payload): reply = '' try: reply = self.client.execute_payload(payload) return reply except Exception as e: raise YPYServiceProviderError(error_msg='Could not execute RPC: ' + str(e))
def execute_payload(self, payload): # Send the request try: reply = self.send_and_receive(payload) return reply except: reply_str = "Failed to send data!" raise YPYServiceProviderError(error_code=YPYErrorCode.SERVER_REJ, error_msg=reply_str)
def _read(self, num_of_chars): data = self.p.stdout.read(num_of_chars) if not data: error_msg = ("\nFailed to get response from netconf!" "Please make sure you have 'netconf-yang agent ssh' " "configured on your router.") self.netconf_sp_logger.error(error_msg) raise YPYServiceProviderError( error_msg="failed to get response from netconf") return data
def get_root(payload_root, top_entity, NSMAP): prefix = top_entity._meta_info().module_name tag = top_entity._meta_info().yang_name namespace = NSMAP[prefix] if payload_root.tag == 'rpc-reply': root = payload_root.find('{}:{}'.format(prefix, tag), namespaces=NSMAP) elif payload_root.tag == '{{{}}}{}'.format(namespace, tag): root = payload_root else: raise YPYServiceProviderError( error_code=YPYErrorCode.INVALID_DECODE_VALUE) return root
def get_root_schema(self, bundle_name): """Return root_schema for bundle_name. Args: bundle_name (str): bundle name. """ if self._user_provided_repo: return self._root_schema_table[_USER_PROVIDED_REPO] if bundle_name not in self._root_schema_table: self.logger.error("Root schema not created") raise YPYServiceProviderError(error_msg="Root schema not created") return self._root_schema_table[bundle_name]
def _raise_non_rpc_error(self): self.netconf_sp_logger.error(YPYErrorCode.INVALID_RPC) raise YPYServiceProviderError(error_code=YPYErrorCode.INVALID_RPC)
def _raise_read_only_edit_error(self): self.netconf_sp_logger.error(YPYErrorCode.INVALID_MODIFY) raise YPYServiceProviderError(error_code=YPYErrorCode.INVALID_MODIFY)
def _raise_key_missing_error(self): self.netconf_sp_logger.error(YPYErrorCode.INVALID_HIERARCHY_KEY) raise YPYServiceProviderError( error_code=YPYErrorCode.INVALID_HIERARCHY_KEY)
def _raise_parent_hierarchy_error(self): self.netconf_sp_logger.error(YPYErrorCode.INVALID_HIERARCHY_PARENT) raise YPYServiceProviderError( error_code=YPYErrorCode.INVALID_HIERARCHY_PARENT)
def decode(self, payload, read_filter): if read_filter is None: return XmlDecoder().decode(payload) if hasattr(read_filter, 'is_rpc') and read_filter.is_rpc: if 'ok' in payload: return None r = etree.fromstring(payload) ch = r.getchildren()[0] # TODO HACK if ch.tag == '{urn:ietf:params:xml:ns:netconf:base:1.0}data': if len(ch.getchildren()) > 0: ch = ch.getchildren()[0] else: return None return XmlDecoder().decode(etree.tostring(ch)) # In order to figure out which fields are the # ones we are interested find the field list entity = self._create_top_level_entity_from_read_filter(read_filter) XmlDecoder._bind_to_object(payload, entity, self._get_capabilities()) # drill down to figure out the field access expression # that matches the entity or entities to be returned # not the argument passed in as a filter might have # incomplete key paths, in which case what is returned # will be the entity whose common path can be determined current = entity current_entity = read_filter current_meta = current_entity.i_meta yang_nodes = [] while hasattr(current_meta, 'parent'): yang_nodes.append(current_meta.yang_name) current_meta = current_meta.parent if current_meta: yang_nodes.append(current_meta.yang_name) yang_nodes = list(reversed(yang_nodes)) yang_nodes = yang_nodes[1:] for yang_node_name in yang_nodes: found = False for member in current._meta_info().meta_info_class_members: if member.name == yang_node_name: found = True current = getattr(current, member.presentation_name) if current is None: return None if isinstance(current, YList): if len(current) == 0: return None if len(current) > 0: return current break if not found: self.crud_logger.error( 'Error determing what needs to be returned') raise YPYServiceProviderError( error_msg='Error determining what needs to be returned') return current
def _handle_rpc_error(self, payload, reply_str, pathlist): self.netconf_sp_logger.error('\n%s\n%s', payload, reply_str) raise YPYServiceProviderError(error_code=YPYErrorCode.SERVER_REJ, error_msg=reply_str)