Skip to content

Commit

Permalink
DellEMC: get_change_event Platform API implementation for S6000, S610…
Browse files Browse the repository at this point in the history
…0 and Z9100
  • Loading branch information
ArunSaravananBalachandran committed May 14, 2020
1 parent cbe948e commit 5e9c885
Show file tree
Hide file tree
Showing 3 changed files with 305 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -237,13 +237,32 @@ def _get_transceiver_status(self):

return int(content, 16)

def get_transceiver_change_event(self, timeout=0):
def get_change_event(self, timeout=0):
"""
Returns a dictionary containing sfp changes which have
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
Args:
timeout: Timeout in milliseconds (optional). If timeout == 0,
this method will block until a change is detected.
Returns:
(bool, dict):
- True if call successful, False if not;
- A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the
format of {'device_id':'device_event'},
where device_id is the device ID for this device and
device_event,
status='1' represents device inserted,
status='0' represents device removed.
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
indicates that fan 0 has been removed, fan 2
has been inserted and sfp 11 has been removed.
"""
start_time = time.time()
port_dict = {}
ret_dict = {"sfp": port_dict}
port = self.PORT_START
forever = False

Expand All @@ -256,7 +275,7 @@ def get_transceiver_change_event(self, timeout=0):
end_time = start_time + timeout

if (start_time > end_time):
return False, {} # Time wrap or possibly incorrect timeout
return False, ret_dict # Time wrap or possibly incorrect timeout

while (timeout >= 0):
# Check for OIR events and return updated port_dict
Expand All @@ -276,7 +295,7 @@ def get_transceiver_change_event(self, timeout=0):

# Update reg value
self.modprs_register = reg_value
return True, port_dict
return True, ret_dict

if forever:
time.sleep(1)
Expand All @@ -287,7 +306,7 @@ def get_transceiver_change_event(self, timeout=0):
else:
if timeout > 0:
time.sleep(timeout)
return True, {}
return False, {}
return True, ret_dict
return False, ret_dict


Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Chassis(ChassisBase):
HWMON_DIR = "/sys/devices/platform/SMF.512/hwmon/"
HWMON_NODE = os.listdir(HWMON_DIR)[0]
MAILBOX_DIR = HWMON_DIR + HWMON_NODE
POLL_INTERVAL = 1 # Poll interval in seconds

reset_reason_dict = {}
reset_reason_dict[11] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
Expand Down Expand Up @@ -81,6 +82,7 @@ def __init__(self):
self._component_list.append(component)

self._watchdog = Watchdog()
self._transceiver_presence = self._get_transceiver_presence()

def _get_reboot_reason_smf_register(self):
# In S6100, mb_poweron_reason register will
Expand Down Expand Up @@ -111,6 +113,24 @@ def _get_pmc_register(self, reg_name):
rv = rv.lstrip(" ")
return rv

def _get_register(self, reg_file):
# On successful read, returns the value read from given
# reg_name and on failure returns 'ERR'
rv = 'ERR'

if (not os.path.isfile(reg_file)):
return rv

try:
with open(reg_file, 'r') as fd:
rv = fd.read()
except Exception as error:
rv = 'ERR'

rv = rv.rstrip('\r\n')
rv = rv.lstrip(" ")
return rv

def get_name(self):
"""
Retrieves the name of the chassis
Expand Down Expand Up @@ -215,3 +235,103 @@ def get_reboot_cause(self):
return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)

return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")

def _get_transceiver_presence(self):

cpld2_modprs = self._get_register(
"/sys/class/i2c-adapter/i2c-14/14-003e/qsfp_modprs")
cpld3_modprs = self._get_register(
"/sys/class/i2c-adapter/i2c-15/15-003e/qsfp_modprs")
cpld4_modprs = self._get_register(
"/sys/class/i2c-adapter/i2c-16/16-003e/qsfp_modprs")
cpld5_modprs = self._get_register(
"/sys/class/i2c-adapter/i2c-17/17-003e/qsfp_modprs")

# If IOM is not present, register read will fail.
# Handle the scenario gracefully
if (cpld2_modprs == 'read error') or (cpld2_modprs == 'ERR'):
cpld2_modprs = '0x0'
if (cpld3_modprs == 'read error') or (cpld3_modprs == 'ERR'):
cpld3_modprs = '0x0'
if (cpld4_modprs == 'read error') or (cpld4_modprs == 'ERR'):
cpld4_modprs = '0x0'
if (cpld5_modprs == 'read error') or (cpld5_modprs == 'ERR'):
cpld5_modprs = '0x0'

# Make it contiguous
transceiver_presence = (int(cpld2_modprs, 16) & 0xffff) |\
((int(cpld4_modprs, 16) & 0xffff) << 16) |\
((int(cpld3_modprs, 16) & 0xffff) << 32) |\
((int(cpld5_modprs, 16) & 0xffff) << 48)

return transceiver_presence

def get_change_event(self, timeout=0):
"""
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
Args:
timeout: Timeout in milliseconds (optional). If timeout == 0,
this method will block until a change is detected.
Returns:
(bool, dict):
- True if call successful, False if not;
- A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the
format of {'device_id':'device_event'},
where device_id is the device ID for this device and
device_event,
status='1' represents device inserted,
status='0' represents device removed.
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
indicates that fan 0 has been removed, fan 2
has been inserted and sfp 11 has been removed.
"""
port_dict = {}
ret_dict = {'sfp': port_dict}
forever = False

if timeout == 0:
forever = True
elif timeout > 0:
timeout = timeout / float(1000) # Convert to secs
else:
return False, ret_dict # Incorrect timeout

while True:
if forever:
timer = self.POLL_INTERVAL
else:
timer = min(timeout, self.POLL_INTERVAL)
start_time = time.time()

time.sleep(timer)
cur_presence = self._get_transceiver_presence()

# Update dict only if a change has been detected
if cur_presence != self._transceiver_presence:
changed_ports = self._transceiver_presence ^ cur_presence
for port in range(self.get_num_sfps()):
# Mask off the bit corresponding to particular port
mask = 1 << port
if changed_ports & mask:
# qsfp_modprs 1 => optics is removed
if cur_presence & mask:
port_dict[port] = '0'
# qsfp_modprs 0 => optics is inserted
else:
port_dict[port] = '1'

# Update current presence
self._transceiver_presence = cur_presence
break

if not forever:
elapsed_time = time.time() - start_time
timeout = round(timeout - elapsed_time, 3)
if timeout <= 0:
break

return True, ret_dict
Loading

0 comments on commit 5e9c885

Please sign in to comment.