From 09dfbc5b30b1e4f46361587a023bb9cf43f64f5e Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 7 Jun 2024 09:55:53 -0400 Subject: [PATCH 1/6] add more constants --- src/middlewared/middlewared/plugins/enclosure_/constants.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/middlewared/middlewared/plugins/enclosure_/constants.py b/src/middlewared/middlewared/plugins/enclosure_/constants.py index 47d74b3205da3..e679db476b8ac 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/constants.py +++ b/src/middlewared/middlewared/plugins/enclosure_/constants.py @@ -4,3 +4,6 @@ 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_INTERNAL_KEY = 'is_internal' From aa6a13c8770555a511d035fb914cf6f697710b25 Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 7 Jun 2024 09:56:11 -0400 Subject: [PATCH 2/6] add new method and fix imports --- .../plugins/enclosure_/enclosure_class.py | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py index ec890dc521413..4443681158a56 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py @@ -7,11 +7,20 @@ 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_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__) @@ -241,6 +250,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']] @@ -294,6 +304,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, @@ -632,3 +645,40 @@ 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 = self.front_slots, self.rear_slots, self.internal_slots + has_rear = has_internal = False + total = fs + 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 slot <= fs else False, + DISK_REAR_KEY: True if has_rear and slot > fs else False, + DISK_INTERNAL_KEY: True if has_internal and slot > fs else False, + } + + return rv From dec450f2f408e5fa38db8e837683a6227404767b Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 7 Jun 2024 11:38:37 -0400 Subject: [PATCH 3/6] add top_slots and front_loaded properties --- .../plugins/enclosure_/enclosure_class.py | 59 +++++++++++++------ 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py index 4443681158a56..e929d3fbecaa4 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py @@ -56,6 +56,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 @@ -585,6 +587,33 @@ def top_loaded(self): self.is_102_bay_jbod )) + @property + def top_slots(self): + 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): + 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. @@ -596,24 +625,18 @@ def front_slots(self): 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): From 4de2f2be44b777c217b0d56a08f8136ba82b9f4f Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 7 Jun 2024 11:47:56 -0400 Subject: [PATCH 4/6] add is_top key for each disk --- .../plugins/enclosure_/constants.py | 1 + .../plugins/enclosure_/enclosure_class.py | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/middlewared/middlewared/plugins/enclosure_/constants.py b/src/middlewared/middlewared/plugins/enclosure_/constants.py index e679db476b8ac..85cede1e5bb41 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/constants.py +++ b/src/middlewared/middlewared/plugins/enclosure_/constants.py @@ -6,4 +6,5 @@ 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' diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py index e929d3fbecaa4..a3cf3b1ccbca1 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py @@ -15,6 +15,7 @@ SUPPORTS_IDENTIFY_KEY, DISK_FRONT_KEY, DISK_REAR_KEY, + DISK_TOP_KEY, DISK_INTERNAL_KEY, ) from .element_types import ELEMENT_TYPES, ELEMENT_DESC @@ -681,9 +682,19 @@ def determine_disk_slot_positions(self): Args: Returns: dict """ - fs, rs, ins = self.front_slots, self.rear_slots, self.internal_slots + fs, rs, ins, ts = self.front_slots, self.rear_slots, self.internal_slots, self.top_slots has_rear = has_internal = False - total = fs + 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 @@ -699,9 +710,10 @@ def determine_disk_slot_positions(self): rv = dict() for slot in range(1, total + 1): rv[slot] = { - DISK_FRONT_KEY: True if slot <= fs else False, - DISK_REAR_KEY: True if has_rear and slot > fs else False, - DISK_INTERNAL_KEY: True if has_internal and slot > fs else False, + 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 From f7651187e8e1d684fa2a56b2008eebb4136ae47e Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 7 Jun 2024 11:49:25 -0400 Subject: [PATCH 5/6] flake8 while im here --- src/middlewared/middlewared/plugins/enclosure_/element_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/middlewared/middlewared/plugins/enclosure_/element_types.py b/src/middlewared/middlewared/plugins/enclosure_/element_types.py index 51eb26bad4a24..27ce2d3d2bc3e 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/element_types.py +++ b/src/middlewared/middlewared/plugins/enclosure_/element_types.py @@ -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): From fb1996147b8aaf35acb14dba42159db89287c40d Mon Sep 17 00:00:00 2001 From: caleb Date: Fri, 7 Jun 2024 11:59:54 -0400 Subject: [PATCH 6/6] add and fix docstrings --- .../plugins/enclosure_/enclosure_class.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py index a3cf3b1ccbca1..95a2439166922 100644 --- a/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py +++ b/src/middlewared/middlewared/plugins/enclosure_/enclosure_class.py @@ -590,6 +590,11 @@ def top_loaded(self): @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 @@ -603,6 +608,12 @@ def top_slots(self): @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, @@ -619,10 +630,6 @@ def front_loaded(self): 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 """