@ -21,8 +21,8 @@ DOCUMENTATION = """
- - -
- - -
module : eos_eapi
module : eos_eapi
version_added : " 2.1 "
version_added : " 2.1 "
author : " Chris Houseknecht (@chouseknecht )"
author : " Peter Sprygada (@privateip )"
short_description : Manage and configure eAPI.
short_description : Manage and configure Arista EOS eAPI.
requirements :
requirements :
- " EOS v4.12 or greater "
- " EOS v4.12 or greater "
description :
description :
@ -35,78 +35,128 @@ description:
- Requires EOS v4 .12 or greater .
- Requires EOS v4 .12 or greater .
extends_documentation_fragment : eos
extends_documentation_fragment : eos
options :
options :
state :
http :
description :
description :
- A state of I ( started ) will
- The C ( http ) argument controls the operating state of the HTTP
enable eAPI access , and a state of I ( stopped ) will
transport protocol when eAPI is present in the running - config .
disable or shutdown all eAPI access .
When the value is set to True , the HTTP protocol is enabled and
choices:
when the value is set to False , the HTTP protocol is disabled .
- started
By default , when eAPI is first configured , the HTTP protocol is
- stopped
disabled .
required : false
required : false
default : started
default : yes
choices : [ ' yes ' , ' no ' ]
aliases : [ ' enable_http ' ]
http_port :
http_port :
description :
description :
- Port on which the HTTP server will listen .
- Configures the HTTP port that will listen for connections when
the HTTP transport protocol is enabled . This argument accepts
integer values in the valid range of 1 to 65535.
required : false
required : false
default : 80
default : 80
https :
description :
- The C ( https ) argument controls the operating state of the HTTPS
transport protocol when eAPI is present in the running - config .
When the value is set to True , the HTTPS protocol is enabled and
when the value is set to False , the HTTPS protocol is disabled .
By default , when eAPI is first configured , the HTTPS protocol is
enabled .
required : false
default : yes
choices : [ ' yes ' , ' no ' ]
aliases : [ ' enable_http ' ]
https_port :
https_port :
description :
description :
- Port on which the HTTPS server will listen .
- Configures the HTTP port that will listen for connections when
the HTTP transport protocol is enabled . This argument accepts
integer values in the valid range of 1 to 65535.
required : false
required : false
default : 443
default : 443
local_http :
description :
- The C ( local_http ) argument controls the operating state of the
local HTTP transport protocol when eAPI is present in the
running - config . When the value is set to True , the HTTP protocol
is enabled and restricted to connections from localhost only . When
the value is set to False , the HTTP local protocol is disabled .
- Note is value is independent of the C ( http ) argument
required : false
default : false
choices : [ ' yes ' , ' no ' ]
aliases : [ ' enable_local_http ' ]
local_http_port :
local_http_port :
description :
description :
- Port on which the local HTTP server will listen .
- Configures the HTTP port that will listen for connections when
the HTTP transport protocol is enabled . This argument accepts
integer values in the valid range of 1 to 65535.
required : false
required : false
default : 8080
default : 8080
http :
socket :
description :
description :
- Enable HTTP server access .
- The C ( socket ) argument controls the operating state of the UNIX
Domain Socket used to receive eAPI requests . When the value
of this argument is set to True , the UDS will listen for eAPI
requests . When the value is set to False , the UDS will not be
available to handle requests . By default when eAPI is first
configured , the UDS is disabled .
required : false
required : false
default : true
default : false
choices :
choices : [ ' yes ' , ' no ' ]
- yes
aliases : [ ' enable_socket ' ]
- no
vrf :
aliases :
- enable_http
https :
description :
description :
- Enable HTTPS server access .
- The C ( vrf ) argument will configure eAPI to listen for connections
in the specified VRF . By default , eAPI transports will listen
for connections in the global table . This value requires the
VRF to already be created otherwise the task will fail .
required : false
required : false
default : true
default : default
choices :
version_added : " 2.2 "
- yes
qos :
- no
aliases :
- enable_https
local_http :
description :
description :
- Enable local HTTP server access .
- The C ( qos ) argument configures the IP DSCP value to assign to
eAPI response packets . This argument accepts integer values
in the valid IP DSCP range of 0 to 63.
required : false
required : false
default : false
default : 0
choices :
version_added : " 2.2 "
- yes
config :
- no
aliases :
- enable_local_http
socket :
description :
description :
- Enable Unix socket server access .
- The module , by default , will connect to the remote device and
retrieve the current running - config to use as a base for comparing
against the contents of source . There are times when it is not
desirable to have the task get the current running - config for
every task in a playbook . The I ( config ) argument allows the
implementer to pass in the configuration to use as the base
config for comparison .
required : false
required : false
default : false
default : nul
choices :
version_added : " 2.2 "
- yes
state :
- no
description :
aliases :
- The C ( state ) argument controls the operational state of eAPI
- enable_socket
on the remote device . When this argument is set to C ( started ) ,
eAPI is enabled to receive requests and when this argument is
C ( stopped ) , eAPI is disabled and will not receive requests .
required : false
default : started
choices : [ ' started ' , ' stopped ' ]
"""
"""
EXAMPLES = """
EXAMPLES = """
# Note: examples below use the following provider dict to handle
# transport and authentication to the node.
vars :
cli :
host : " {{ inventory_hostname }} "
username : admin
password : admin
- name : Enable eAPI access with default configuration
- name : Enable eAPI access with default configuration
eos_eapi :
eos_eapi :
state : started
state : started
provider : { { provider } }
provider : { { cli } }
- name : Enable eAPI with no HTTP , HTTPS at port 9443 , local HTTP at port 80 , and socket enabled
- name : Enable eAPI with no HTTP , HTTPS at port 9443 , local HTTP at port 80 , and socket enabled
eos_eapi :
eos_eapi :
@ -116,178 +166,204 @@ EXAMPLES = """
local_http : yes
local_http : yes
local_http_port : 80
local_http_port : 80
socket : yes
socket : yes
provider : { { provider } }
provider : { { cli } }
- name : Shutdown eAPI access
- name : Shutdown eAPI access
eos_eapi :
eos_eapi :
state : stopped
state : stopped
provider : { { provider } }
provider : { { cli } }
"""
"""
RETURN = """
RETURN = """
changed :
updates :
description :
- Indicates if commands were sent to the device .
returned : always
type : boolean
sample : false
commands :
description :
description :
- Set of commands to be executed on remote device
- Set of commands to be executed on remote device
returned : always
returned : always
type : list
type : list
sample : [
sample : [ ' management api http-commands ' , ' shutdown ' ]
' management api http-commands ' ,
urls :
' shutdown '
description : Hash of URL endpoints eAPI is listening on per interface
]
returned : when eAPI is started
type : dict
_config :
sample : { ' Management1 ' : [ ' http://172.26.10.1:80 ' ] }
description :
- Configuration found on the device prior to executing any commands .
returned : always
type : object
sample : { . . . }
"""
"""
import re
import time
from ansible . module_utils . netcfg import NetworkConfig , dumps
from ansible . module_utils . eos import NetworkModule , NetworkError
from ansible . module_utils . basic import get_exception
def http_commands ( protocol , port , enable , config ) :
PRIVATE_KEYS_RE = re . compile ( ' __.+__ ' )
started_config = config [ ' {0} Server ' . format ( protocol ) ]
commands = [ ]
changed = False
if started_config . get ( ' running ' ) :
if not enable :
# turn off server
commands . append ( ' no protocol {0} ' . format ( protocol ) )
changed = True
elif started_config . get ( ' port ' ) != port :
# update the port
commands . append ( ' protocol {0} port {1} ' . format ( protocol , port ) )
changed = True
elif not started_config . get ( ' running ' ) and enable :
# turn on server
commands . append ( ' protocol {0} port {1} ' . format ( protocol , port ) )
changed = True
return commands , changed
def execute_commands ( module , commands ) :
if not module . params . get ( ' check_mode ' ) :
def invoke ( name , * args , * * kwargs ) :
module . configure ( commands )
func = globals ( ) . get ( name )
if func :
return func ( * args , * * kwargs )
def started ( module , commands ) :
def config_server ( module ) :
state = module . params . get ( ' state ' )
local_http_port = module . params . get ( ' local_http_port ' )
socket = module . params . get ( ' socket ' )
local_http = module . params . get ( ' local_http ' )
config = module . from_json ( module . execute ( [ ' show management api http-commands | json ' ] ) [ 0 ] )
result = dict ( changed = False , _config = config , commands = [ ] )
commands = [
' management api http-commands '
]
if not config . get ( ' enabled ' ) :
if state == ' started ' :
# turn on eAPI access
commands . append ( ' no shutdown ' )
commands . append ( ' no shutdown ' )
result [ ' changed ' ] = True
setters = set ( )
else :
for key , value in module . argument_spec . iteritems ( ) :
# state is stopped. nothing to do
if module . params [ key ] is not None :
return result
setter = value . get ( ' setter ' ) or ' set_ %s ' % key
if setter not in setters :
if config . get ( ' enabled ' ) and state == ' stopped ' :
setters . add ( setter )
# turn off eAPI access and exit
invoke ( setter , module , commands )
def stopped ( module , commands ) :
commands . append ( ' shutdown ' )
commands . append ( ' shutdown ' )
result [ ' changed ' ] = True
result [ ' commands ' ] = commands
execute_commands ( module , commands )
return result
# http and https
for protocol in [ ' http ' , ' https ' ] :
cmds , chg = http_commands ( protocol , module . params [ ' {0} _port ' . format ( protocol ) ] ,
module . params [ ' {0} ' . format ( protocol ) ] , config )
if chg :
commands + = cmds
result [ ' changed ' ] = True
# local HTTP
if config . get ( ' localHttpServer ' ) . get ( ' running ' ) :
if not local_http :
# turn off local http server
commands . append ( ' no protocol http localhost ' )
result [ ' changed ' ] = True
elif config . get ( ' localHttpServer ' ) . get ( ' port ' ) != local_http_port :
# update the local http port
commands . append ( ' protocol http localhost port {0} ' . format ( local_http_port ) )
result [ ' changed ' ] = True
if not config . get ( ' localHttpServer ' ) . get ( ' running ' ) and local_http :
# turn on local http server
commands . append ( ' protocol http localhost port {0} ' . format ( local_http_port ) )
result [ ' changed ' ] = True
# socket server
if config . get ( ' unixSocketServer ' ) . get ( ' running ' ) and not socket :
# turn off unix socket
commands . append ( ' no protocol unix-socket ' )
result [ ' changed ' ] = True
if not config . get ( ' unixSocketServer ' ) . get ( ' running ' ) and socket :
def set_protocol_http ( module , commands ) :
# turn on unix socket
port = module . params [ ' http_port ' ]
if not 1 < = port < = 65535 :
module . fail_json ( msg = ' http_port must be between 1 and 65535 ' )
elif module . params [ ' http ' ] is True :
commands . append ( ' protocol http port %s ' % port )
elif module . params [ ' http ' ] is False :
commands . append ( ' no protocol http ' )
def set_protocol_https ( module , commands ) :
port = module . params [ ' https_port ' ]
if not 1 < = port < = 65535 :
module . fail_json ( msg = ' https_port must be between 1 and 65535 ' )
elif module . params [ ' https ' ] is True :
commands . append ( ' protocol https port %s ' % port )
elif module . params [ ' https ' ] is False :
commands . append ( ' no protocol https ' )
def set_local_http ( module , commands ) :
port = module . params [ ' local_http_port ' ]
if not 1 < = port < = 65535 :
module . fail_json ( msg = ' local_http_port must be between 1 and 65535 ' )
elif module . params [ ' local_http ' ] is True :
commands . append ( ' protocol http localhost port %s ' % port )
elif module . params [ ' local_http ' ] is False :
commands . append ( ' no protocol http localhost port 8080 ' )
def set_socket ( module , commands ) :
if module . params [ ' socket ' ] is True :
commands . append ( ' protocol unix-socket ' )
commands . append ( ' protocol unix-socket ' )
result [ ' changed ' ] = True
elif module . params [ ' socket ' ] is False :
commands . append ( ' no protocol unix-socket ' )
if len ( commands ) > 1 :
# something requires change
execute_commands ( module , commands )
result [ ' commands ' ] = commands
return result
def set_vrf ( module , commands ) :
vrf = module . params [ ' vrf ' ]
if vrf != ' default ' :
resp = module . cli ( [ ' show vrf ' ] )
if vrf not in resp [ 0 ] :
module . fail_json ( msg = " vrf ' %s ' is not configured " % vrf )
commands . append ( ' vrf %s ' % vrf )
def set_qos ( module , commands ) :
if not 0 < = module . params [ ' qos ' ] < = 63 :
module . fail_json ( msg = ' qos must be between 0 and 63 ' )
commands . append ( ' qos dscp %s ' % module . params [ ' qos ' ] )
def get_config ( module ) :
contents = module . params [ ' config ' ]
if not contents :
cmd = ' show running-config all section management api http-commands '
contents = module . cli ( [ cmd ] )
config = NetworkConfig ( indent = 3 , contents = contents [ 0 ] )
return config
def load_config ( module , commands , result ) :
session = ' ansible_ %s ' % int ( time . time ( ) )
commit = not module . check_mode
diff = module . config . load_config ( commands , session = session , commit = commit )
# once the configuration is done, remove the config session and
# remove the session name from the result
module . cli ( [ ' no configure session %s ' % session ] )
result [ ' diff ' ] = dict ( prepared = diff )
result [ ' changed ' ] = diff is not None
def load ( module , commands , result ) :
candidate = NetworkConfig ( indent = 3 )
candidate . add ( commands , parents = [ ' management api http-commands ' ] )
config = get_config ( module )
configobjs = candidate . difference ( config )
if configobjs :
commands = dumps ( configobjs , ' commands ' ) . split ( ' \n ' )
result [ ' updates ' ] = commands
load_config ( module , commands , result )
def clean_result ( result ) :
# strip out any keys that have two leading and two trailing
# underscore characters
for key in result . keys ( ) :
if PRIVATE_KEYS_RE . match ( key ) :
del result [ key ]
def collect_facts ( module , result ) :
resp = module . cli ( [ ' show management api http-commands ' ] , output = ' json ' )
facts = dict ( eos_eapi_urls = dict ( ) )
for each in resp [ 0 ] [ ' urls ' ] :
intf , url = each . split ( ' : ' )
key = str ( intf ) . strip ( )
if key not in facts [ ' eos_eapi_urls ' ] :
facts [ ' eos_eapi_urls ' ] [ key ] = list ( )
facts [ ' eos_eapi_urls ' ] [ key ] . append ( str ( url ) . strip ( ) )
result [ ' ansible_facts ' ] = facts
def check_version ( module ) :
config = module . from_json ( module . execute ( [ ' show version | json ' ] ) [ 0 ] )
versions = config [ ' version ' ] . split ( ' . ' )
if int ( versions [ 0 ] ) < 4 or int ( versions [ 1 ] ) < 12 :
module . fail_json ( msg = " Device version {0} does not support eAPI. eAPI was introduced in EOS 4.12. " )
def main ( ) :
def main ( ) :
""" main entry point for module execution
""" main entry point for module execution
"""
"""
argument_spec = dict (
argument_spec = dict (
state = dict ( default = ' started ' , choices = [ ' stopped ' , ' started ' ] ) ,
http = dict ( aliases = [ ' enable_http ' ] , default = False , type = ' bool ' , setter = ' set_protocol_http ' ) ,
http_port = dict ( default = 80 , type = ' int ' ) ,
http_port = dict ( default = 80 , type = ' int ' , setter = ' set_protocol_http ' ) ,
https_port = dict ( default = 443 , type = ' int ' ) ,
local_http_port = dict ( default = 8080 , type = ' int ' ) ,
https = dict ( aliases = [ ' enable_https ' ] , default = True , type = ' bool ' , setter = ' set_protocol_https ' ) ,
http = dict ( aliases = [ ' enable_http ' ] , default = True , type = ' bool ' ) ,
https_port = dict ( default = 443 , type = ' int ' , setter = ' set_protocol_https ' ) ,
https = dict ( aliases = [ ' enable_https ' ] , default = True , type = ' bool ' ) ,
local_http = dict ( aliases = [ ' enable_local_http ' ] , default = False , type = ' bool ' , setter = ' set_local_http ' ) ,
local_http_port = dict ( default = 8080 , type = ' int ' , setter = ' set_local_http ' ) ,
socket = dict ( aliases = [ ' enable_socket ' ] , default = False , type = ' bool ' ) ,
socket = dict ( aliases = [ ' enable_socket ' ] , default = False , type = ' bool ' ) ,
local_http = dict ( aliases = [ ' enable_local_http ' ] , default = False , type = ' bool ' ) ,
vrf = dict ( default = ' default ' ) ,
qos = dict ( default = 0 , type = ' int ' ) ,
config = dict ( ) ,
# Only allow use of transport cli when configuring eAPI
# Only allow use of transport cli when configuring eAPI
transport = dict ( required = True , choices = [ ' cli ' ] )
transport = dict ( required = True , choices = [ ' cli ' ] ) ,
state = dict ( default = ' started ' , choices = [ ' stopped ' , ' started ' ] ) ,
)
)
module = get_module ( argument_spec = argument_spec ,
module = NetworkModule ( argument_spec = argument_spec ,
connect_on_load = False ,
supports_check_mode = True )
supports_check_mode = True )
check_version ( module )
state = module . params [ ' state ' ]
warnings = list ( )
result = dict ( changed = False , warnings = warnings )
commands = list ( )
invoke ( state , module , commands )
result = config_server ( module )
try :
load ( module , commands , result )
except NetworkError :
exc = get_exception ( )
module . fail_json ( msg = str ( exc ) , * * exc . kwargs )
return module . exit_json ( * * result )
collect_facts ( module , result )
clean_result ( result )
module . exit_json ( * * result )
from ansible . module_utils . basic import *
from ansible . module_utils . shell import *
from ansible . module_utils . eos import *
if __name__ == ' __main__ ' :
if __name__ == ' __main__ ' :
main ( )
main ( )