@@ -429,6 +429,17 @@ def __init__(self, hostname, username, password, timeout=60, optional_args=None)
429
429
hostname , username , password , timeout = timeout , optional_args = optional_args
430
430
)
431
431
self .platform = "nxos_ssh"
432
+ self .connector_type_map = {
433
+ "1000base-LH" : "LC_CONNECTOR" ,
434
+ "1000base-SX" : "LC_CONNECTOR" ,
435
+ "1000base-T" : "Unknown" ,
436
+ "10Gbase-LR" : "LC_CONNECTOR" ,
437
+ "10Gbase-SR" : "LC_CONNECTOR" ,
438
+ "SFP-H10GB-CU1M" : "DAC_CONNECTOR" ,
439
+ "SFP-H10GB-CU1.45M" : "DAC_CONNECTOR" ,
440
+ "SFP-H10GB-CU3M" : "DAC_CONNECTOR" ,
441
+ "SFP-H10GB-CU3.45M" : "DAC_CONNECTOR" ,
442
+ }
432
443
433
444
def open (self ):
434
445
self .device = self ._netmiko_open (
@@ -1528,3 +1539,105 @@ def get_vlans(self):
1528
1539
"interfaces" : self ._parse_vlan_ports (vlan ["vlanshowplist-ifidx" ]),
1529
1540
}
1530
1541
return vlans
1542
+
1543
+ def get_optics (self ):
1544
+ command = "show interface transceiver details"
1545
+ output = self ._send_command (command )
1546
+
1547
+ # Formatting data into return data structure
1548
+ optics_detail = {}
1549
+
1550
+ # Extraction Regexps
1551
+ port_ts_re = re .compile (r"^Ether.*?(?=\nEther|\Z)" , re .M | re .DOTALL )
1552
+ port_re = re .compile (r"^(Ether.*)[ ]*?$" , re .M )
1553
+ vendor_re = re .compile ("name is (.*)$" , re .M )
1554
+ vendor_part_re = re .compile ("part number is (.*)$" , re .M )
1555
+ vendor_rev_re = re .compile ("revision is (.*)$" , re .M )
1556
+ serial_no_re = re .compile ("serial number is (.*)$" , re .M )
1557
+ type_no_re = re .compile ("type is (.*)$" , re .M )
1558
+ rx_instant_re = re .compile (r"Rx Power[ ]+(?:(\S+?)[ ]+dBm|(N.A))" , re .M )
1559
+ tx_instant_re = re .compile (r"Tx Power[ ]+(?:(\S+?)[ ]+dBm|(N.A))" , re .M )
1560
+ current_instant_re = re .compile (r"Current[ ]+(?:(\S+?)[ ]+mA|(N.A))" , re .M )
1561
+
1562
+ port_ts_l = port_ts_re .findall (output )
1563
+
1564
+ for port_ts in port_ts_l :
1565
+ port = port_re .search (port_ts ).group (1 )
1566
+ # No transceiver is present in those case
1567
+ if "transceiver is not present" in port_ts :
1568
+ continue
1569
+ if "transceiver is not applicable" in port_ts :
1570
+ continue
1571
+ port_detail = {"physical_channels" : {"channel" : []}}
1572
+ # No metric present
1573
+ vendor = vendor_re .search (port_ts ).group (1 )
1574
+ vendor_part = vendor_part_re .search (port_ts ).group (1 )
1575
+ vendor_rev = vendor_rev_re .search (port_ts ).group (1 )
1576
+ serial_no = serial_no_re .search (port_ts ).group (1 )
1577
+ type_s = type_no_re .search (port_ts ).group (1 )
1578
+ state = {
1579
+ "vendor" : vendor .strip (),
1580
+ "vendor_part" : vendor_part .strip (),
1581
+ "vendor_rev" : vendor_rev .strip (),
1582
+ "serial_no" : serial_no .strip (),
1583
+ "connector_type" : self .connector_type_map .get (type_s , "Unknown" ),
1584
+ }
1585
+ if "DOM is not supported" not in port_ts :
1586
+ res = rx_instant_re .search (port_ts )
1587
+ input_power = res .group (1 ) or res .group (2 )
1588
+ res = tx_instant_re .search (port_ts )
1589
+ output_power = res .group (1 ) or res .group (2 )
1590
+ res = current_instant_re .search (port_ts )
1591
+ current = res .group (1 ) or res .group (2 )
1592
+
1593
+ # If interface is shutdown it returns "N/A" as output power
1594
+ # or "N/A" as input power
1595
+ # Converting that to -100.0 float
1596
+ try :
1597
+ float (output_power )
1598
+ except ValueError :
1599
+ output_power = - 100.0
1600
+ try :
1601
+ float (input_power )
1602
+ except ValueError :
1603
+ input_power = - 100.0
1604
+ try :
1605
+ float (current )
1606
+ except ValueError :
1607
+ current = - 100.0
1608
+
1609
+ # Defaulting avg, min, max values to -100.0 since device does not
1610
+ # return these values
1611
+ optic_states = {
1612
+ "index" : 0 ,
1613
+ "state" : {
1614
+ "input_power" : {
1615
+ "instant" : (
1616
+ float (input_power ) if "input_power" else - 100.0
1617
+ ),
1618
+ "avg" : - 100.0 ,
1619
+ "min" : - 100.0 ,
1620
+ "max" : - 100.0 ,
1621
+ },
1622
+ "output_power" : {
1623
+ "instant" : (
1624
+ float (output_power ) if "output_power" else - 100.0
1625
+ ),
1626
+ "avg" : - 100.0 ,
1627
+ "min" : - 100.0 ,
1628
+ "max" : - 100.0 ,
1629
+ },
1630
+ "laser_bias_current" : {
1631
+ "instant" : (float (current ) if "current" else - 100.0 ),
1632
+ "avg" : 0.0 ,
1633
+ "min" : 0.0 ,
1634
+ "max" : 0.0 ,
1635
+ },
1636
+ },
1637
+ }
1638
+ port_detail ["physical_channels" ]["channel" ].append (optic_states )
1639
+
1640
+ port_detail ["state" ] = state
1641
+ optics_detail [port ] = port_detail
1642
+
1643
+ return optics_detail
0 commit comments