Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DellEMC: get_change_event Platform API implementation for S6000, S6100 and Z9100 #4593

Merged
merged 2 commits into from
May 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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