@ -18,54 +18,19 @@
#
#
import re
import re
import collections
from ansible . module_utils . basic import json , json_dict_bytes_to_unicode
from ansible . module_utils . basic import json , get_exception
from ansible . module_utils . network import Net Cli , NetworkError , ModuleStub
from ansible . module_utils . network import Net workModule , NetworkError , ModuleStub
from ansible . module_utils . network import add_argument , register_transport , to_list
from ansible . module_utils . network import add_argument , register_transport , to_list
from ansible . module_utils . shell import CliBase
from ansible . module_utils . netcfg import NetworkConfig
from ansible . module_utils . netcfg import NetworkConfig
from ansible . module_utils . netcli import Command
from ansible . module_utils . urls import fetch_url , url_argument_spec
from ansible . module_utils . urls import fetch_url , url_argument_spec
# temporary fix until modules are update. to be removed before 2.2 final
from ansible . module_utils . network import get_module
add_argument ( ' use_ssl ' , dict ( default = False , type = ' bool ' ) )
add_argument ( ' use_ssl ' , dict ( default = False , type = ' bool ' ) )
add_argument ( ' validate_certs ' , dict ( default = True , type = ' bool ' ) )
add_argument ( ' validate_certs ' , dict ( default = True , type = ' bool ' ) )
def argument_spec ( ) :
return dict (
# config options
running_config = dict ( aliases = [ ' config ' ] ) ,
save_config = dict ( type = ' bool ' , default = False , aliases = [ ' save ' ] ) ,
)
nxos_argument_spec = argument_spec ( )
def get_config ( module ) :
config = module . params [ ' running_config ' ]
if not config :
config = module . config . get_config ( include_defaults = True )
return NetworkConfig ( indent = 2 , contents = config )
def load_config ( module , candidate ) :
config = get_config ( module )
commands = candidate . difference ( config )
commands = [ str ( c ) . strip ( ) for c in commands ]
save_config = module . params [ ' save_config ' ]
result = dict ( changed = False )
if commands :
if not module . check_mode :
module . config ( commands )
if save_config :
module . config . save_config ( )
result [ ' changed ' ] = True
result [ ' updates ' ] = commands
return result
class Nxapi ( object ) :
class Nxapi ( object ) :
@ -85,7 +50,9 @@ class Nxapi(object):
def _error ( self , msg , * * kwargs ) :
def _error ( self , msg , * * kwargs ) :
self . _nxapi_auth = None
self . _nxapi_auth = None
raise NetworkError ( msg , url = self . url )
if ' url ' not in kwargs :
kwargs [ ' url ' ] = self . url
raise NetworkError ( msg , * * kwargs )
def _get_body ( self , commands , output , version = ' 1.0 ' , chunk = ' 0 ' , sid = None ) :
def _get_body ( self , commands , output , version = ' 1.0 ' , chunk = ' 0 ' , sid = None ) :
""" Encodes a NXAPI JSON request message
""" Encodes a NXAPI JSON request message
@ -106,7 +73,7 @@ class Nxapi(object):
' chunk ' : chunk ,
' chunk ' : chunk ,
' sid ' : sid ,
' sid ' : sid ,
' input ' : commands ,
' input ' : commands ,
' output_format ' : output
' output_format ' : ' json '
}
}
return dict ( ins_api = msg )
return dict ( ins_api = msg )
@ -136,15 +103,31 @@ class Nxapi(object):
self . _connected = False
self . _connected = False
def execute ( self , commands , output = None , * * kwargs ) :
def execute ( self , commands , output = None , * * kwargs ) :
""" Send commands to the device.
commands = collections . deque ( commands )
"""
commands = to_list ( commands )
output = output or self . default_output
output = output or self . default_output
data = self . _get_body ( commands , output )
# only 10 commands can be encoded in each request
# messages sent to the remote device
stack = list ( )
requests = list ( )
while commands :
stack . append ( commands . popleft ( ) )
if len ( stack ) == 10 :
data = self . _get_body ( stack , output )
data = self . _jsonify ( data )
requests . append ( data )
stack = list ( )
if stack :
data = self . _get_body ( stack , output )
data = self . _jsonify ( data )
data = self . _jsonify ( data )
requests . append ( data )
headers = { ' Content-Type ' : ' application/json ' }
headers = { ' Content-Type ' : ' application/json ' }
result = list ( )
for req in requests :
if self . _nxapi_auth :
if self . _nxapi_auth :
headers [ ' Cookie ' ] = self . _nxapi_auth
headers [ ' Cookie ' ] = self . _nxapi_auth
@ -159,20 +142,40 @@ class Nxapi(object):
try :
try :
response = json . loads ( response . read ( ) )
response = json . loads ( response . read ( ) )
except ValueError :
except ValueError :
raise NetworkError ( msg = ' unable to load repsonse from device ' )
raise NetworkError ( msg = ' unable to load response from device ' )
result = list ( )
output = response [ ' ins_api ' ] [ ' outputs ' ] [ ' output ' ]
output = response [ ' ins_api ' ] [ ' outputs ' ] [ ' output ' ]
for item in to_list ( output ) :
for item in to_list ( output ) :
if item [ ' code ' ] != ' 200 ' :
if item [ ' code ' ] != ' 200 ' :
self . _error ( * * item )
self . _error ( output = output , * * item )
else :
else :
result . append ( item [ ' body ' ] )
result . append ( item [ ' body ' ] )
return result
return result
### implemented by network.Config ###
### implemention of netcli.Cli ###
def run_commands ( self , commands ) :
output = None
cmds = list ( )
responses = list ( )
for cmd in commands :
if output and output != cmd . output :
responses . extend ( self . execute ( cmds , output = output ) )
cmds = list ( )
output = cmd . output
cmds . append ( str ( cmd ) )
if cmds :
responses . extend ( self . execute ( cmds , output = output ) )
return responses
### end of netcli.Cli ###
### implemention of netcfg.Config ###
def configure ( self , commands ) :
def configure ( self , commands ) :
commands = to_list ( commands )
commands = to_list ( commands )
@ -184,17 +187,13 @@ class Nxapi(object):
cmd + = ' all '
cmd + = ' all '
return self . execute ( [ cmd ] , output = ' text ' ) [ 0 ]
return self . execute ( [ cmd ] , output = ' text ' ) [ 0 ]
def load_config ( self , * * kwargs ) :
def load_config ( self , config , * * kwargs ) :
raise NotImplementedError
return self . configure ( config )
def replace_config ( self , * * kwargs ) :
raise NotImplementedError
def commit _config( self , * * kwargs ) :
def save_config ( self , * * kwargs ) :
raise NotImplementedError
self . execute ( [ ' copy running-config startup-config ' ] )
def abort_config ( self , * * kwargs ) :
### end netcfg.Config ###
raise NotImplementedError
def _jsonify ( self , data ) :
def _jsonify ( self , data ) :
for encoding in ( " utf-8 " , " latin-1 " ) :
for encoding in ( " utf-8 " , " latin-1 " ) :
@ -210,10 +209,12 @@ class Nxapi(object):
except UnicodeDecodeError :
except UnicodeDecodeError :
continue
continue
self . _error ( msg = ' Invalid unicode encoding encountered ' )
self . _error ( msg = ' Invalid unicode encoding encountered ' )
Nxapi = register_transport ( ' nxapi ' ) ( Nxapi )
Nxapi = register_transport ( ' nxapi ' ) ( Nxapi )
class Cli ( NetCli ) :
class Cli ( CliBase ) :
NET_PASSWD_RE = re . compile ( r " [ \ r \ n]?password: $ " , re . I )
NET_PASSWD_RE = re . compile ( r " [ \ r \ n]?password: $ " , re . I )
CLI_PROMPTS_RE = [
CLI_PROMPTS_RE = [
@ -238,7 +239,7 @@ class Cli(NetCli):
super ( Cli , self ) . connect ( params , kickstart = False , * * kwargs )
super ( Cli , self ) . connect ( params , kickstart = False , * * kwargs )
self . shell . send ( ' terminal length 0 ' )
self . shell . send ( ' terminal length 0 ' )
### implementation of net work .Cli ###
### implementation of net cli .Cli ###
def run_commands ( self , commands ) :
def run_commands ( self , commands ) :
cmds = list ( prepare_commands ( commands ) )
cmds = list ( prepare_commands ( commands ) )
@ -254,13 +255,7 @@ class Cli(NetCli):
)
)
return responses
return responses
### implemented by network.Config ###
### implemented by netcfg.Config ###
def get_config ( self , * * kwargs ) :
cmd = ' show running-config '
if kwargs . get ( ' include_defaults ' ) :
cmd + = ' all '
return self . execute ( [ cmd ] ) [ 0 ]
def configure ( self , commands , * * kwargs ) :
def configure ( self , commands , * * kwargs ) :
commands = prepare_config ( commands )
commands = prepare_config ( commands )
@ -268,20 +263,18 @@ class Cli(NetCli):
responses . pop ( 0 )
responses . pop ( 0 )
return responses
return responses
def load_config ( self ) :
def get_config ( self , include_defaults = False , * * kwargs ) :
raise NotImplementedError
cmd = ' show running-config '
if kwargs . get ( ' include_defaults ' ) :
def replace_config ( self , * * kwargs ) :
cmd + = ' all '
raise NotImplementedError
return self . execute ( [ cmd ] ) [ 0 ]
def commit_config ( self ) :
raise NotImplementedError
def abort_config( self ) :
def load_config ( self , commands , * * kwargs ) :
r aise NotImplementedError
return self . configure ( commands )
def save_config ( self ) :
def save_config ( self ) :
self . execute ( [ ' copy running-config startup-config ' ] )
self . execute ( [ ' copy running-config startup-config ' ] )
Cli = register_transport ( ' cli ' , default = True ) ( Cli )
Cli = register_transport ( ' cli ' , default = True ) ( Cli )
def prepare_config ( commands ) :
def prepare_config ( commands ) :
@ -290,12 +283,9 @@ def prepare_config(commands):
commands . append ( ' end ' )
commands . append ( ' end ' )
return commands
return commands
def prepare_commands ( commands ) :
def prepare_commands ( commands ) :
jsonify = lambda x : ' %s | json ' % x
jsonify = lambda x : ' %s | json ' % x
for cmd in to_list ( commands ) :
for cmd in to_list ( commands ) :
if cmd . output == ' json ' :
if cmd . output == ' json ' :
cmd = jsonify ( cmd )
cmd . command = jsonify ( cmd )
else :
cmd = str ( cmd )
yield cmd
yield cmd