2018-02-02 23:49:12 +00:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright: (c) 2017, Bruno Calogero <brunocalogero@hotmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import , division , print_function
__metaclass__ = type
ANSIBLE_METADATA = { ' metadata_version ' : ' 1.1 ' ,
' status ' : [ ' preview ' ] ,
2018-10-11 20:34:35 +00:00
' supported_by ' : ' certified ' }
2018-02-02 23:49:12 +00:00
DOCUMENTATION = r '''
- - -
module : aci_fabric_node
2018-02-24 00:27:37 +00:00
short_description : Manage Fabric Node Members ( fabric : NodeIdentP )
2018-02-02 23:49:12 +00:00
description :
2018-02-24 00:27:37 +00:00
- Manage Fabric Node Members on Cisco ACI fabrics .
2018-02-02 23:49:12 +00:00
version_added : ' 2.5 '
options :
pod_id :
description :
- The pod id of the new Fabric Node Member .
2018-07-11 21:03:24 +00:00
type : int
2018-02-02 23:49:12 +00:00
serial :
description :
- Serial Number for the new Fabric Node Member .
2018-12-17 17:23:10 +00:00
type : str
2018-02-02 23:49:12 +00:00
aliases : [ serial_number ]
node_id :
description :
- Node ID Number for the new Fabric Node Member .
2018-07-11 21:03:24 +00:00
type : int
2018-02-02 23:49:12 +00:00
switch :
description :
- Switch Name for the new Fabric Node Member .
2018-12-17 17:23:10 +00:00
type : str
2018-02-21 18:35:59 +00:00
aliases : [ name , switch_name ]
2018-02-02 23:49:12 +00:00
description :
description :
- Description for the new Fabric Node Member .
2018-12-17 17:23:10 +00:00
type : str
2018-02-02 23:49:12 +00:00
aliases : [ descr ]
role :
description :
- Role for the new Fabric Node Member .
2018-12-17 17:23:10 +00:00
type : str
2018-02-02 23:49:12 +00:00
aliases : [ role_name ]
choices : [ leaf , spine , unspecified ]
state :
description :
- Use C ( present ) or C ( absent ) for adding or removing .
- Use C ( query ) for listing an object or multiple objects .
2018-12-17 17:23:10 +00:00
type : str
2018-02-02 23:49:12 +00:00
choices : [ absent , present , query ]
default : present
extends_documentation_fragment : aci
2019-02-26 13:55:40 +00:00
seealso :
- name : APIC Management Information Model reference
description : More information about the internal APIC class B ( fabric : NodeIdentP ) .
link : https : / / developer . cisco . com / docs / apic - mim - ref /
author :
- Bruno Calogero ( @brunocalogero )
2018-02-02 23:49:12 +00:00
'''
EXAMPLES = r '''
2018-02-23 01:39:58 +00:00
- name : Add fabric node
2018-02-02 23:49:12 +00:00
aci_fabric_node :
host : apic
2018-02-23 01:39:58 +00:00
username : admin
password : SomeSecretPassword
2018-02-23 02:04:40 +00:00
serial : FDO2031124L
node_id : 1011
switch : fab4 - sw1011
2018-02-02 23:49:12 +00:00
state : present
2018-08-08 21:24:50 +00:00
delegate_to : localhost
2018-02-23 01:39:58 +00:00
- name : Remove fabric node
aci_fabric_node :
host : apic
username : admin
password : SomeSecretPassword
2018-02-23 02:04:40 +00:00
serial : FDO2031124L
node_id : 1011
2018-02-23 01:39:58 +00:00
state : absent
2018-08-08 21:24:50 +00:00
delegate_to : localhost
2018-02-23 01:39:58 +00:00
- name : Query fabric nodes
aci_fabric_node :
host : apic
username : admin
password : SomeSecretPassword
state : query
2018-08-08 21:24:50 +00:00
delegate_to : localhost
register : query_result
2018-02-02 23:49:12 +00:00
'''
RETURN = r '''
2018-02-21 18:35:59 +00:00
current :
description : The existing configuration from the APIC after the module has finished
returned : success
type : list
sample :
[
{
" fvTenant " : {
" attributes " : {
" descr " : " Production environment " ,
" dn " : " uni/tn-production " ,
" name " : " production " ,
" nameAlias " : " " ,
" ownerKey " : " " ,
" ownerTag " : " "
}
}
}
]
error :
description : The error information as returned from the APIC
returned : failure
type : dict
sample :
{
" code " : " 122 " ,
" text " : " unknown managed object class foo "
}
raw :
description : The raw output returned by the APIC REST API ( xml or json )
returned : parse error
2018-12-18 21:25:30 +00:00
type : str
2018-02-21 18:35:59 +00:00
sample : ' <?xml version= " 1.0 " encoding= " UTF-8 " ?><imdata totalCount= " 1 " ><error code= " 122 " text= " unknown managed object class foo " /></imdata> '
sent :
description : The actual / minimal configuration pushed to the APIC
returned : info
type : list
sample :
{
" fvTenant " : {
" attributes " : {
" descr " : " Production environment "
}
}
}
previous :
description : The original configuration from the APIC before the module has started
returned : info
type : list
sample :
[
{
" fvTenant " : {
" attributes " : {
" descr " : " Production " ,
" dn " : " uni/tn-production " ,
" name " : " production " ,
" nameAlias " : " " ,
" ownerKey " : " " ,
" ownerTag " : " "
}
}
}
]
proposed :
description : The assembled configuration from the user - provided parameters
returned : info
type : dict
sample :
{
" fvTenant " : {
" attributes " : {
" descr " : " Production environment " ,
" name " : " production "
}
}
}
filter_string :
description : The filter string used for the request
returned : failure or debug
2018-12-18 21:25:30 +00:00
type : str
2018-02-21 18:35:59 +00:00
sample : ' ?rsp-prop-include=config-only '
method :
description : The HTTP method used for the request to the APIC
returned : failure or debug
2018-12-18 21:25:30 +00:00
type : str
2018-02-21 18:35:59 +00:00
sample : POST
response :
description : The HTTP response from the APIC
returned : failure or debug
2018-12-18 21:25:30 +00:00
type : str
2018-02-21 18:35:59 +00:00
sample : OK ( 30 bytes )
status :
description : The HTTP status from the APIC
returned : failure or debug
type : int
sample : 200
url :
description : The HTTP url used for the request to the APIC
returned : failure or debug
2018-12-18 21:25:30 +00:00
type : str
2018-02-21 18:35:59 +00:00
sample : https : / / 10.11 .12 .13 / api / mo / uni / tn - production . json
2018-02-02 23:49:12 +00:00
'''
from ansible . module_utils . basic import AnsibleModule
2019-02-26 13:55:40 +00:00
from ansible . module_utils . network . aci . aci import ACIModule , aci_argument_spec
2018-02-02 23:49:12 +00:00
# NOTE: (This problem is also present on the APIC GUI)
# NOTE: When specifying a C(role) the new Fabric Node Member will be created but Role on GUI will be "unknown", hence not what seems to be a module problem
def main ( ) :
argument_spec = aci_argument_spec ( )
argument_spec . update (
description = dict ( type = ' str ' , aliases = [ ' descr ' ] ) ,
2018-02-21 18:35:59 +00:00
node_id = dict ( type = ' int ' ) , # Not required for querying all objects
pod_id = dict ( type = ' int ' ) ,
2018-02-02 23:49:12 +00:00
role = dict ( type = ' str ' , choices = [ ' leaf ' , ' spine ' , ' unspecified ' ] , aliases = [ ' role_name ' ] ) ,
2018-02-21 18:35:59 +00:00
serial = dict ( type = ' str ' , aliases = [ ' serial_number ' ] ) , # Not required for querying all objects
switch = dict ( type = ' str ' , aliases = [ ' name ' , ' switch_name ' ] ) ,
2018-02-02 23:49:12 +00:00
state = dict ( type = ' str ' , default = ' present ' , choices = [ ' absent ' , ' present ' , ' query ' ] ) ,
)
module = AnsibleModule (
argument_spec = argument_spec ,
supports_check_mode = True ,
required_if = [
2018-02-21 18:35:59 +00:00
[ ' state ' , ' absent ' , [ ' node_id ' , ' serial ' ] ] ,
[ ' state ' , ' present ' , [ ' node_id ' , ' serial ' ] ] ,
2018-02-02 23:49:12 +00:00
] ,
)
pod_id = module . params [ ' pod_id ' ]
serial = module . params [ ' serial ' ]
node_id = module . params [ ' node_id ' ]
switch = module . params [ ' switch ' ]
description = module . params [ ' description ' ]
role = module . params [ ' role ' ]
state = module . params [ ' state ' ]
aci = ACIModule ( module )
aci . construct_url (
root_class = dict (
aci_class = ' fabricNodeIdentP ' ,
aci_rn = ' controller/nodeidentpol/nodep- {0} ' . format ( serial ) ,
module_object = serial ,
2018-08-07 21:54:54 +00:00
target_filter = { ' serial ' : serial } ,
2018-02-02 23:49:12 +00:00
)
)
aci . get_existing ( )
if state == ' present ' :
aci . payload (
aci_class = ' fabricNodeIdentP ' ,
class_config = dict (
2018-02-21 18:35:59 +00:00
descr = description ,
2018-02-02 23:49:12 +00:00
name = switch ,
2018-02-21 18:35:59 +00:00
nodeId = node_id ,
podId = pod_id ,
2018-08-09 00:27:22 +00:00
# NOTE: Originally we were sending 'rn', but now we need 'dn' for idempotency
# FIXME: Did this change with ACI version ?
dn = ' uni/controller/nodeidentpol/nodep- {0} ' . format ( serial ) ,
# rn='nodep-{0}'.format(serial),
2018-02-21 18:35:59 +00:00
role = role ,
serial = serial ,
2018-02-02 23:49:12 +00:00
)
)
aci . get_diff ( aci_class = ' fabricNodeIdentP ' )
aci . post_config ( )
elif state == ' absent ' :
aci . delete_config ( )
2018-02-21 18:35:59 +00:00
aci . exit_json ( * * aci . result )
2018-02-02 23:49:12 +00:00
if __name__ == " __main__ " :
main ( )