Source code for networkapi.plugins.BGP.NXAPI.Generic

# -*- coding: utf-8 -*-
import json
import logging

import requests
from requests.auth import HTTPBasicAuth
from requests.exceptions import HTTPError

from networkapi.equipamento.models import EquipamentoAcesso
from networkapi.plugins import exceptions
from networkapi.plugins.BGP.base import BaseBgpPlugin

log = logging.getLogger(__name__)


[docs]class NxApiPlugin(BaseBgpPlugin): """Plugin base para interação com NX API.""" protocol = 'http' def __init__(self, **kwargs): super(NxApiPlugin, self).__init__(**kwargs) self.equipment_access = self._get_equipment_access()
[docs] def create_neighbor(self, kwargs): commands = [] if kwargs['local_as']: cmd = 'router bgp {local_as}'.format(remote_as=kwargs['local_as']) commands.append(cmd) else: raise Exception('Local AS is needed.') if kwargs['vrf']: cmd = 'vrf {vrf}'.format(vrf=kwargs['vrf']) commands.append(cmd) else: raise Exception('VRF is needed.') if kwargs['remote_ip']: if kwargs['remote_as']: cmd = 'neighbor {remote_ip} remote-as {remote_as}'.format( remote_ip=kwargs['remote_ip'], remote_as=kwargs['remote_as']) commands.append(cmd) else: raise Exception('Remote AS is needed.') else: raise Exception('Remote Ip is needed.') if kwargs['description']: cmd = 'description {description}'.format( description=kwargs['description']) commands.append(cmd) else: raise Exception('Description is needed.') cmd = 'dynamic-capability' if kwargs['virtual_interface']: cmd = 'update-source {virtual_interface}'.format( virtual_interface=kwargs['virtual_interface']) commands.append(cmd) else: raise Exception('Interface is needed.') if kwargs['timers']: cmd = 'timers {timer_keepalive}'.format( timer_keepalive=kwargs['timer_keepalive']) if kwargs['timers']: cmd += ' {timer_timeout}'.format( timer_timeout=kwargs['timer_timeout']) commands.append(cmd) else: raise Exception('Timer timeout is needed.') else: raise Exception('Keep alive is needed.') if kwargs['password']: cmd = 'password {password}'.format(password=kwargs['password']) commands.append(cmd) if kwargs['maximum_hops']: cmd = 'maximum-hops {maximum_hops}'.format( maximum_hops=kwargs['maximum_hops']) commands.append(cmd) cmd = 'address-family {address_family} unicast'.format( address_family=kwargs['address_family']) if kwargs['route_map_in']: 'route-map {route_map_in} in'.format( route_map_in=kwargs['route_map_in']) if kwargs['route_map_out']: 'route-map {route_map_out} out'.format( route_map_out=kwargs['route_map_out']) if kwargs['community']: cmd = 'send-community both' commands.append(cmd) if kwargs['remove_private_as']: cmd = 'remove-private-as' commands.append(cmd) if kwargs['next_hop_self']: cmd = 'next-hop-self' commands.append(cmd) cmd = 'next-hop-third-party' if kwargs['soft_reconfiguration']: cmd = 'soft-reconfiguration inbound' commands.append(cmd) payload = json.dumps(self._contruct(commands)) self._request(data=payload, contentType='json-rpc', path='ins')
[docs] def delete_neighbor(self, kwargs): commands = [] if kwargs['local_as']: cmd = 'router bgp {local_as}'.format(remote_as=kwargs['local_as']) commands.append(cmd) else: raise Exception('Local AS is needed.') if kwargs['vrf']: cmd = 'vrf {vrf}'.format(vrf=kwargs['vrf']) commands.append(cmd) else: raise Exception('VRF is needed.') if kwargs['remote_ip']: if kwargs['remote_as']: cmd = 'no neighbor {remote_ip} remote-as {remote_as}'.format( remote_ip=kwargs['remote_ip'], remote_as=kwargs['remote_as']) commands.append(cmd) else: raise Exception('Remote AS is needed.') else: raise Exception('Remote Ip is needed.') payload = json.dumps(self._contruct(commands)) self._request(data=payload, contentType='json-rpc', path='ins')
def _contruct(self, commands): payload = list() for index, command in enumerate(commands): payload.append({ 'jsonrpc': '2.0', 'method': 'cli_ascii', 'params': { 'cmd': command, 'version': 1.2 }, 'id': index }) return payload def _request(self, **kwargs): # Params and default values params = { 'path': '', 'data': None, 'contentType': 'json-rpc', 'verify': False } # Setting params via kwargs or use the defaults for param in params: if param in kwargs: params[param] = kwargs.get(param) headers = self._get_headers(content_type=params['contentType']) uri = self._get_uri(path=params['path']) log.info( 'Starting {method} request to NX-API {equipment} at {uri}. \ Data to be sent: {data}'.format( method=params['method'], equipment=self.equipment.nome, uri=uri, data=params['data'])) try: # Raises AttributeError if method is not valid request = requests.post( uri, auth=self._get_auth(), headers=headers, verify=params['verify'], data=params['data'] ) request.raise_for_status() try: return json.loads(request.text) except: return except HTTPError: try: response = json.loads(request.text) for error in response['errors']['error']: log.error(error['error-message']) except: log.error('Unknown error during request to NX-API') raise HTTPError(request.status_code) def _get_auth(self): return self._basic_auth() def _basic_auth(self): return HTTPBasicAuth( self.equipment_access.user, self.equipment_access.password ) def _get_host(self): if not hasattr(self, 'host') or self.host is None: if not isinstance(self.equipment_access, EquipamentoAcesso): log.error( 'No fqdn could be found for equipment {equipment}.'.format( equipment=self.equipment.nome)) raise exceptions.InvalidEquipmentAccessException() self.host = self.equipment_access.fqdn.strip() if self.host.find('://') < 0: self.host = self.protocol + '://' + self.host return self.host def _get_uri(self, host=None, path='ins'): if host is None: host = self._get_host() host = host.strip() path = path.strip() if host[len(host) - 1] == '/': host = host[0:len(host) - 1] if path[0] == '/': path = path[1:len(path)] self.uri = host + '/' + path return self.uri def _get_headers(self, content_type): types = { 'json-rpc': 'application/json-rpc' } return {'content-type': types[content_type]} def _get_equipment_access(self): try: return EquipamentoAcesso.search( None, self.equipment, 'http').uniqueResult() except Exception: log.error('Access type %s not found for equipment %s.' % ('http', self.equipment.nome)) raise exceptions.InvalidEquipmentAccessException()