7
7
8
8
# Import necessary packages
9
9
import traceback
10
+ from itertools import chain
10
11
from ansible .module_utils .compat import ipaddress
11
12
from ansible .module_utils ._text import to_text
12
13
180
181
"vrfs" : "vrf" ,
181
182
}
182
183
183
- FACE_ID = dict (front = 0 , rear = 1 )
184
-
185
- DEVICE_STATUS = dict (offline = 0 , active = 1 , planned = 2 , staged = 3 , failed = 4 , inventory = 5 )
186
-
187
- IP_ADDRESS_STATUS = dict (active = 1 , reserved = 2 , deprecated = 3 , dhcp = 5 )
188
-
189
- IP_ADDRESS_ROLE = dict (
190
- loopback = 10 , secondary = 20 , anycast = 30 , vip = 40 , vrrp = 41 , hsrp = 42 , glbp = 43 , carp = 44
191
- )
192
-
193
- PREFIX_STATUS = dict (container = 0 , active = 1 , reserved = 2 , deprecated = 3 )
194
-
195
- SITE_STATUS = dict (active = 1 , planned = 2 , retired = 4 )
196
-
197
- RACK_STATUS = dict (active = 3 , planned = 2 , reserved = 0 , available = 1 , deprecated = 4 )
198
-
199
- RACK_UNIT = dict (millimeters = 1000 , inches = 2000 )
200
-
201
- SUBDEVICE_ROLES = dict (parent = True , child = False )
202
-
203
- VLAN_STATUS = dict (active = 1 , reserved = 2 , deprecated = 3 )
204
-
205
- SERVICE_PROTOCOL = dict (tcp = 6 , udp = 17 )
206
-
207
- RACK_TYPE = {
208
- "2-post frame" : 100 ,
209
- "4-post frame" : 200 ,
210
- "4-post cabinet" : 300 ,
211
- "wall-mounted frame" : 1000 ,
212
- "wall-mounted cabinet" : 1100 ,
213
- }
214
-
215
- INTF_FORM_FACTOR = {
216
- "virtual" : 0 ,
217
- "link aggregation group (lag)" : 200 ,
218
- "100base-tx (10/100me)" : 800 ,
219
- "1000base-t (1ge)" : 1000 ,
220
- "10gbase-t (10ge)" : 1150 ,
221
- "10gbase-cx4 (10ge)" : 1170 ,
222
- "gbic (1ge)" : 1050 ,
223
- "sfp (1ge)" : 1100 ,
224
- "2.5gbase-t (2.5ge)" : 1120 ,
225
- "5gbase-t (5ge)" : 1130 ,
226
- "sfp+ (10ge)" : 1200 ,
227
- "xfp (10ge)" : 1300 ,
228
- "xenpak (10ge)" : 1310 ,
229
- "x2 (10ge)" : 1320 ,
230
- "sfp28 (25ge)" : 1350 ,
231
- "qsfp+ (40ge)" : 1400 ,
232
- "qsfp28 (50ge)" : 1420 ,
233
- "cfp (100ge)" : 1500 ,
234
- "cfp2 (100ge)" : 1510 ,
235
- "cfp2 (200ge)" : 1650 ,
236
- "cfp4 (100ge)" : 1520 ,
237
- "cisco cpak (100ge)" : 1550 ,
238
- "qsfp28 (100ge)" : 1600 ,
239
- "qsfp56 (200ge)" : 1700 ,
240
- "qsfp-dd (400ge)" : 1750 ,
241
- "ieee 802.11a" : 2600 ,
242
- "ieee 802.11b/g" : 2610 ,
243
- "ieee 802.11n" : 2620 ,
244
- "ieee 802.11ac" : 2630 ,
245
- "ieee 802.11ad" : 2640 ,
246
- "gsm" : 2810 ,
247
- "cdma" : 2820 ,
248
- "lte" : 2830 ,
249
- "oc-3/stm-1" : 6100 ,
250
- "oc-12/stm-4" : 6200 ,
251
- "oc-48/stm-16" : 6300 ,
252
- "oc-192/stm-64" : 6400 ,
253
- "oc-768/stm-256" : 6500 ,
254
- "oc-1920/stm-640" : 6600 ,
255
- "oc-3840/stm-1234" : 6700 ,
256
- "sfp (1gfc)" : 3010 ,
257
- "sfp (2gfc)" : 3020 ,
258
- "sfp (4gfc)" : 3040 ,
259
- "sfp+ (8gfc)" : 3080 ,
260
- "sfp+ (16gfc)" : 3160 ,
261
- "sfp28 (32gfc)" : 3320 ,
262
- "qsfp28 (128gfc)" : 3400 ,
263
- "t1 (1.544 mbps)" : 4000 ,
264
- "e1 (2.048 mbps)" : 4010 ,
265
- "t3 (45 mbps)" : 4040 ,
266
- "e3 (34 mbps)" : 4050 ,
267
- "cisco stackwise" : 5000 ,
268
- "cisco stackwise plus" : 5050 ,
269
- "cisco flexstack" : 5100 ,
270
- "cisco flexstack plus" : 5150 ,
271
- "juniper vcp" : 5200 ,
272
- "extreme summitstack" : 5300 ,
273
- "extreme summitstack-128" : 5310 ,
274
- "extreme summitstack-256" : 5320 ,
275
- "extreme summitstack-512" : 5330 ,
276
- "other" : 32767 ,
277
- }
278
-
279
- INTF_MODE = {"access" : 100 , "tagged" : 200 , "tagged all" : 300 }
280
-
281
- VIRTUAL_MACHINE_STATUS = dict (offline = 0 , active = 1 , staged = 3 )
282
-
283
- CIRCUIT_STATUS = dict (
284
- deprovisioning = 0 , active = 1 , planned = 2 , provisioning = 3 , offline = 4 , decommissioned = 5 ,
285
- )
286
-
287
- # This is used when attempting to search for existing endpoints
288
184
ALLOWED_QUERY_PARAMS = {
289
185
"aggregate" : set (["prefix" , "rir" ]),
290
186
"circuit" : set (["cid" ]),
344
240
]
345
241
)
346
242
347
- # This is used when converting static choices to an ID value acceptable to Netbox API
348
243
REQUIRED_ID_FIND = {
349
- "circuits" : [{ "status" : CIRCUIT_STATUS }] ,
350
- "devices" : [{ "status" : DEVICE_STATUS , "face" : FACE_ID }] ,
351
- "device_types" : [{ "subdevice_role" : SUBDEVICE_ROLES }] ,
352
- "interfaces" : [{ "form_factor" : INTF_FORM_FACTOR , "mode" : INTF_MODE }] ,
353
- "ip_addresses" : [{ "status" : IP_ADDRESS_STATUS , "role" : IP_ADDRESS_ROLE }] ,
354
- "prefixes" : [{ "status" : PREFIX_STATUS }] ,
355
- "racks" : [{ "status" : RACK_STATUS , "outer_unit" : RACK_UNIT , "type" : RACK_TYPE }] ,
356
- "services" : [{ "protocol" : SERVICE_PROTOCOL }] ,
357
- "sites" : [{ "status" : SITE_STATUS }] ,
358
- "virtual_machines" : [{ "status" : VIRTUAL_MACHINE_STATUS , "face" : FACE_ID }] ,
359
- "vlans" : [{ "status" : VLAN_STATUS }] ,
244
+ "circuits" : set ([ "status" ]) ,
245
+ "devices" : set ([ "status" , "face" ]) ,
246
+ "device_types" : set ([ "subdevice_role" ]) ,
247
+ "interfaces" : set ([ "form_factor" , "mode" ]) ,
248
+ "ip_addresses" : set ([ "status" , "role" ]) ,
249
+ "prefixes" : set ([ "status" ]) ,
250
+ "racks" : set ([ "status" , "outer_unit" , "type" ]) ,
251
+ "services" : set ([ "protocol" ]) ,
252
+ "sites" : set ([ "status" ]) ,
253
+ "virtual_machines" : set ([ "status" , "face" ]) ,
254
+ "vlans" : set ([ "status" ]) ,
360
255
}
361
256
362
257
# This is used to map non-clashing keys to Netbox API compliant keys to prevent bad logic in code for similar keys but different modules
@@ -416,6 +311,7 @@ def __init__(self, module, endpoint, nb_client=None):
416
311
self .state = self .module .params ["state" ]
417
312
self .check_mode = self .module .check_mode
418
313
self .endpoint = endpoint
314
+ self .version = None
419
315
420
316
if not HAS_PYNETBOX :
421
317
self .module .fail_json (
@@ -443,7 +339,7 @@ def _connect_netbox_api(self, url, token, ssl_verify):
443
339
try :
444
340
nb = pynetbox .api (url , token = token , ssl_verify = ssl_verify )
445
341
try :
446
- self .version = nb .version
342
+ self .version = float ( nb .version )
447
343
except AttributeError :
448
344
self .module .fail_json (msg = "Must have pynetbox >=4.1.0" )
449
345
except Exception :
@@ -486,6 +382,9 @@ def _convert_identical_keys(self, data):
486
382
Returns data
487
383
:params data (dict): Data dictionary after _find_ids method ran
488
384
"""
385
+ if self .version and self .version >= 2.7 :
386
+ if data .get ("form_factor" ):
387
+ data ["type" ] = data .pop ("form_factor" )
489
388
for key in data :
490
389
if key in CONVERT_KEYS :
491
390
new_key = CONVERT_KEYS [key ]
@@ -580,6 +479,23 @@ def _build_query_params(self, parent, module_data, child=None):
580
479
query_dict = self ._convert_identical_keys (query_dict )
581
480
return query_dict
582
481
482
+ def _fetch_choice_value (self , search , endpoint ):
483
+ app = self ._find_app (endpoint )
484
+ nb_app = getattr (self .nb , app )
485
+ nb_endpoint = getattr (nb_app , endpoint )
486
+ endpoint_choices = nb_endpoint .choices ()
487
+
488
+ choices = [x for x in chain .from_iterable (endpoint_choices .values ())]
489
+
490
+ for item in choices :
491
+ if item ["display_name" ].lower () == search .lower ():
492
+ return item ["value" ]
493
+ elif item ["value" ] == search .lower ():
494
+ return item ["value" ]
495
+ self ._handle_errors (
496
+ msg = "%s was not found as a valid choice for %s" % (search , endpoint )
497
+ )
498
+
583
499
def _change_choices_id (self , endpoint , data ):
584
500
"""Used to change data that is static and under _choices for the application.
585
501
ex. DEVICE_STATUS
@@ -590,17 +506,11 @@ def _change_choices_id(self, endpoint, data):
590
506
if REQUIRED_ID_FIND .get (endpoint ):
591
507
required_choices = REQUIRED_ID_FIND [endpoint ]
592
508
for choice in required_choices :
593
- for key , value in choice .items ():
594
- if data .get (key ):
595
- if isinstance (data [key ], int ):
596
- break
597
- try :
598
- data [key ] = value [data [key ].lower ()]
599
- except KeyError :
600
- self ._handle_errors (
601
- msg = "%s may not be a valid choice. If it is valid, please submit bug report."
602
- % (key )
603
- )
509
+ if data .get (choice ):
510
+ if isinstance (data [choice ], int ):
511
+ continue
512
+ choice_value = self ._fetch_choice_value (data [choice ], endpoint )
513
+ data [choice ] = choice_value
604
514
605
515
return data
606
516
0 commit comments