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

NAS-129460 / 24.10 / add more keys to webui.enclosure.dashboard (per UI team) #13859

Merged
merged 6 commits into from
Jun 7, 2024
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
4 changes: 4 additions & 0 deletions src/middlewared/middlewared/plugins/enclosure_/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
MINI_MODEL_BASE = 'MINI'
MINIR_MODEL_BASE = f'{MINI_MODEL_BASE}R'
HEAD_UNIT_DISK_SLOT_START_NUMBER = 1
DISK_FRONT_KEY = 'is_front'
DISK_REAR_KEY = 'is_rear'
DISK_TOP_KEY = 'is_top'
DISK_INTERNAL_KEY = 'is_internal'
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def temp(value_raw):
if (temp := (value_raw & 0xff00) >> 8):
# 8 bits represents -19C to +235C
# value of 0 would imply -20C
return f'{temp -20}C'
return f'{temp - 20}C'


def psu(value_raw):
Expand Down
140 changes: 116 additions & 24 deletions src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,21 @@

from middlewared.utils.scsi_generic import inquiry

from .constants import MINI_MODEL_BASE, MINIR_MODEL_BASE
from .constants import (
MINI_MODEL_BASE,
MINIR_MODEL_BASE,
SYSFS_SLOT_KEY,
MAPPED_SLOT_KEY,
SUPPORTS_IDENTIFY_KEY,
DISK_FRONT_KEY,
DISK_REAR_KEY,
DISK_TOP_KEY,
DISK_INTERNAL_KEY,
)
from .element_types import ELEMENT_TYPES, ELEMENT_DESC
from .enums import ControllerModels, ElementDescriptorsToIgnore, ElementStatusesToIgnore, JbodModels
from .sysfs_disks import map_disks_to_enclosure_slots
from .slot_mappings import get_slot_info, SYSFS_SLOT_KEY, MAPPED_SLOT_KEY, SUPPORTS_IDENTIFY_KEY
from .slot_mappings import get_slot_info

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -47,6 +57,8 @@ def asdict(self):
'pci': self.pci, # the pci info (0:0:0:0)
'rackmount': self.rackmount, # requested by UI team
'top_loaded': self.top_loaded, # requested by UI team
'top_slots': self.top_slots, # requested by UI team
'front_loaded': self.front_loaded, # requested by UI team
'front_slots': self.front_slots, # requested by UI team
'rear_slots': self.rear_slots, # requested by UI team
'internal_slots': self.internal_slots, # requested by UI team
Expand Down Expand Up @@ -241,6 +253,7 @@ def _get_array_device_mapping_info(self):

def _parse_elements(self, elements):
final = {}
disk_position_mapping = self.determine_disk_slot_positions()
for slot, element in elements.items():
try:
element_type = ELEMENT_TYPES[element['type']]
Expand Down Expand Up @@ -294,6 +307,9 @@ def _parse_elements(self, elements):
parsed[SUPPORTS_IDENTIFY_KEY] = self.disks_map[slot][SUPPORTS_IDENTIFY_KEY]

mapped_slot = self.disks_map[slot][MAPPED_SLOT_KEY]
# is this a front, rear or internal slot?
parsed.update(disk_position_mapping.get(mapped_slot, dict()))

parsed['original'] = {
'enclosure_id': self.encid,
'enclosure_sg': self.sg,
Expand Down Expand Up @@ -572,35 +588,63 @@ def top_loaded(self):
self.is_102_bay_jbod
))

@property
def top_slots(self):
"""Determine the total number of top drive bays.

Args:
Returns: int
"""
if self.top_loaded:
if self.is_r40 or self.is_r50_series:
return 48
elif self.is_60_bay_jbod:
return 60
elif self.is_102_bay_jbod:
return 102
else:
return 0
return 0

@property
def front_loaded(self):
"""Determine if the enclosure device has its disk slots loaded
from the front.

Args:
Returns: bool
"""
return any((
self.is_xseries,
self.is_r30,
self.is_12_bay_jbod,
self.is_r20_series,
self.is_hseries,
self.is_r10,
self.is_fseries,
self.is_mseries,
self.is_24_bay_jbod
))

@property
def front_slots(self):
"""Determine the total number of front drive bays.

NOTE: The `front_slots` phrase is used all the same to
represent the drive bay slots for our platforms that are
"top loaded".

Args:
Returns: int
"""
if not self.model:
return 0
elif any((self.is_xseries, self.is_r30, self.is_12_bay_jbod)):
return 12
elif self.is_r20_series:
return 14
elif any((self.is_hseries, self.is_r10)):
return 16
elif any((self.is_fseries, self.is_mseries, self.is_24_bay_jbod)):
return 24
elif any((self.is_r40, self.is_r50_series)):
return 48
elif self.is_60_bay_jbod:
return 60
elif self.is_102_bay_jbod:
return 102
else:
return 0
if self.front_loaded:
if any((self.is_xseries, self.is_r30, self.is_12_bay_jbod)):
return 12
elif self.is_r20_series:
return 14
elif any((self.is_hseries, self.is_r10)):
return 16
elif any((self.is_fseries, self.is_mseries, self.is_24_bay_jbod)):
return 24
else:
return 0
return 0

@property
def rear_slots(self):
Expand Down Expand Up @@ -632,3 +676,51 @@ def internal_slots(self):
Returns: int
"""
return 4 if self.is_r30 else 0

def determine_disk_slot_positions(self):
"""Determine the disk slot positions in the enclosure.
Is this a front slot, rear slot or internal slot?

NOTE: requested by UI team so that when a user clicks on
a slot in the UI for a given enclosure, it will update the
picture to the rear of the machine if the slot chosen is
a rear slot (ditto for internal or front slots)

Args:
Returns: dict
"""
fs, rs, ins, ts = self.front_slots, self.rear_slots, self.internal_slots, self.top_slots
has_rear = has_internal = False
has_front = has_top = False
if fs:
has_front = True
total = fs
elif ts:
has_top = True
total = ts
else:
# huh? shouldn't happen
return dict()

if rs:
has_rear = True
total += rs
elif ins:
# NOTE: only 1 platform has internal slots
# and it DOES NOT have rear slots. If we
# ever have a platform that has both rear
# AND internal slots, this logic wont work
# and we'll need to fix it
has_internal = True
total += ins

rv = dict()
for slot in range(1, total + 1):
rv[slot] = {
DISK_FRONT_KEY: True if has_front and slot <= fs else False,
DISK_TOP_KEY: True if has_top and slot <= ts else False,
DISK_REAR_KEY: True if has_rear and slot > (fs or ts) else False,
DISK_INTERNAL_KEY: True if has_internal and slot > (fs or ts) else False,
}

return rv
Loading