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

Fix - Drives request from volume endpoints is failing #561

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
26 changes: 26 additions & 0 deletions oneview_redfish_toolkit/api/drive.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,32 @@ def build_for_resource_block(drive, drive_enclosure):

return Drive(attrs)

@staticmethod
def build_for_computer_system_volume(drive_id, server_profile, drive):
enclosure_id = server_profile["enclosureUri"].split("/")[-1]
profile_uuid = server_profile["uri"].split("/")[-1]
odata_id = "{}/{}/Storage/1/Drives/{}"\
.format(ComputerSystem.BASE_URI, profile_uuid, drive_id)
media_type = drive["driveMedia"]
media_type = None if (media_type == "Unknown") else media_type
attrs = {
"Id": drive_id,
"Name": drive["name"],
"Status": status_mapping.STATUS_MAP.get(drive["status"]),
"CapacityBytes": Drive.get_capacity_in_bytes(
drive["capacity"]),
"Protocol": drive["deviceInterface"],
"MediaType": media_type,
"Links": {
"Chassis": {
"@odata.id": "/redfish/v1/Chassis/" + enclosure_id
}
},
"@odata.id": odata_id
}

return Drive(attrs)

@staticmethod
def get_capacity_in_bytes(capacity_in_gb):
size_in_bytes = float(capacity_in_gb) * 1024 * 1024 * 1024
Expand Down
38 changes: 23 additions & 15 deletions oneview_redfish_toolkit/api/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,24 +108,12 @@ def build_volume_details(uuid, volume_id):
abort(status.HTTP_404_NOT_FOUND, "Volume {} not found"
.format(volume_id))

sas_Logical_Interconnect_Uri = \
sas_logical_jbod["sasLogicalInterconnectUri"]

drivepaths = []
for logical_Drive_Bay_Uri in sas_logical_jbod["logicalDriveBayUris"]:
drivepath = get_drive_path_from_logical_Drive_Bay_Uri(
logical_Drive_Bay_Uri)
drivepaths.append(drivepath)

drive_enclosure_uri = \
get_drive_enclosure_uri_from_sas_Logical_Interconnect(
sas_Logical_Interconnect_Uri)

drive_enclosure_object = get_drive_enclosure_object(
drive_enclosure_uri)
drive_enclosure_object, drivepaths = \
get_drive_enclosure_and_drivepaths(sas_logical_jbod)

drivebayuris = get_drivebayuris_from_drive_enclosure_object(
drivepaths, drive_enclosure_object)

device_slot = get_device_slot_from_sas_logical_jbod_by_volumeid(
server_profile, volume_id)
raidlevel = get_raidLevel(server_profile, device_slot, volume_id)
Expand Down Expand Up @@ -196,6 +184,26 @@ def build_external_storage_volume_details(sp_uuid, volume, volume_id):
return Volume(attrs)


def get_drive_enclosure_and_drivepaths(sas_logical_jbod):
sas_Logical_Interconnect_Uri = \
sas_logical_jbod["sasLogicalInterconnectUri"]

drivepaths = []
for logical_Drive_Bay_Uri in sas_logical_jbod["logicalDriveBayUris"]:
drivepath = get_drive_path_from_logical_Drive_Bay_Uri(
logical_Drive_Bay_Uri)
drivepaths.append(drivepath)

drive_enclosure_uri = \
get_drive_enclosure_uri_from_sas_Logical_Interconnect(
sas_Logical_Interconnect_Uri)

drive_enclosure_object = get_drive_enclosure_object(
drive_enclosure_uri)

return drive_enclosure_object, drivepaths


def get_sas_logical_jbod_by_volumeid(server_profile, volume_id):

for logical_jbod in server_profile["localStorage"]["sasLogicalJBODs"]:
Expand Down
65 changes: 50 additions & 15 deletions oneview_redfish_toolkit/blueprints/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
from oneview_redfish_toolkit.api.computer_system import ComputerSystem
from oneview_redfish_toolkit.api.drive import Drive
from oneview_redfish_toolkit.api.storage import Storage
from oneview_redfish_toolkit.api.volume import \
get_drive_enclosure_and_drivepaths
from oneview_redfish_toolkit.api.volume import Volume
from oneview_redfish_toolkit.api.volume_collection import VolumeCollection
from oneview_redfish_toolkit.blueprints.util.response_builder import \
Expand Down Expand Up @@ -85,27 +87,34 @@ def get_drive(profile_id, drive_id):

"""

drive_id_int = None
logical_jbod = None
try:
drive_id_int = int(drive_id)
except ValueError:
abort(status.HTTP_400_BAD_REQUEST, "Drive id should be a integer")

server_profile = g.oneview_client.server_profiles.get(profile_id)
sas_logical_jbods = _find_sas_logical_jbods_by(server_profile)

logical_jbod = _get_logical_jbod(drive_id_int, logical_jbod,
sas_logical_jbods)
try:
logical_jbod = None
drive_id_int = int(drive_id)

if logical_jbod is None:
abort(status.HTTP_404_NOT_FOUND, "Drive {} not found"
.format(drive_id))
logical_jbod = _get_logical_jbod(drive_id_int, logical_jbod,
sas_logical_jbods)
if logical_jbod is None:
abort(status.HTTP_404_NOT_FOUND, "Drive {} not found"
.format(drive_id))

drive_details = Drive.build_for_computer_system(drive_id_int,
server_profile,
logical_jbod)
except ValueError:
# if drive id is not a number then check for computer system volume
# drive
drive = _get_drive(sas_logical_jbods, drive_id)

drive_details = Drive.build_for_computer_system(drive_id_int,
server_profile,
logical_jbod)
if drive is None:
abort(status.HTTP_404_NOT_FOUND, "Drive {} not found"
.format(drive_id))

drive_details = Drive.build_for_computer_system_volume(drive_id,
server_profile,
drive)
return ResponseBuilder.success(drive_details)


Expand Down Expand Up @@ -202,3 +211,29 @@ def _is_volume_id_number(volume_id):
return True
except ValueError:
return False


def _get_drive(sas_logical_jbods, drive_id):
drive = None
for sas_logical_jbod in sas_logical_jbods:
drive_enclosure_object, drivepaths = \
get_drive_enclosure_and_drivepaths(sas_logical_jbod)
drive_bays = _get_drive_bays(drivepaths, drive_enclosure_object)
for drive_bay in drive_bays:
if drive_bay["uri"].split("/")[-1] == drive_id:
drive = drive_bay["drive"]
break
if drive:
break

return drive


def _get_drive_bays(drivepaths, drive_enclosure_object):
drive_bays = []
for drivebay in drive_enclosure_object["driveBays"]:
for drivepath in drivebay["drive"]["drivePaths"]:
if drivepath in drivepaths:
drive_bays.append(drivebay)

return drive_bays
62 changes: 56 additions & 6 deletions oneview_redfish_toolkit/tests/blueprints/test_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,24 +310,74 @@ def test_get_drive_when_drive_not_found(self):
]
)

def test_get_drive_when_drive_id_is_invalid(self):
@mock.patch.object(volume, "get_drive_path_from_logical_Drive_Bay_Uri")
@mock.patch.object(volume, "get_drive_enclosure_uri_from_sas_Logical_"
"Interconnect")
def test_get_drive_when_drive_id_is_not_int(self, get_drive_enclosure_uri,
get_drive_mock):
"""Tests when drive id is not a number"""

expected_result = {
"@odata.context": "/redfish/v1/$metadata#Drive.Drive",
"@odata.id": "/redfish/v1/Systems/b425802b-a6a5-4941-8885-"
"aab68dfa2ee2/Storage/1/Drives/"
"5c3e5214-e9fb-469d-a8d5-2159fe2d97d8",
"@odata.type": "#Drive.v1_4_0.Drive",
"CapacityBytes": 107374182400,
"Id": "5c3e5214-e9fb-469d-a8d5-2159fe2d97d8",
"Links": {
"Chassis": {
"@odata.id": "/redfish/v1/Chassis/0000000000A66101"
}
},
"MediaType": "SSD",
"Name": "Drive 1",
"Protocol": "SATA",
"Status": {
"Health": "OK",
"State": "Enabled"
}
}
self.oneview_client.\
server_profiles.get.return_value = self.server_profile
self.oneview_client.\
sas_logical_jbods.get.side_effect = self.logical_jbods

get_drive_mock.return_value = "1:1:1"
get_drive_enclosure_uri.return_value = "/rest/drive-enclosures/"
"SN123100"

self.oneview_client.\
drive_enclosures.get.return_value = self.drive_enclosures

response = self.client.get(
"/redfish/v1/Systems/"
"b425802b-a6a5-4941-8885-aab68dfa2ee2/Storage/1/Drives/"
"5c3e5214-e9fb-469d-a8d5-2159fe2d97d8"
)

result = json.loads(response.data.decode("utf-8"))
self.assertEqual(result, expected_result)
self.assertEqual("application/json", response.mimetype)

def test_get_drive_when_drive_id_invalid(self):
self.oneview_client.\
server_profiles.get.return_value = self.server_profile
self.oneview_client.\
sas_logical_jbods.get.side_effect = None

response = self.client.get(
"/redfish/v1/Systems/"
"b425802b-a6a5-4941-8885-aab68dfa2ee2/Storage/1/Drives/abc"
"b425802b-a6a5-4941-8885-aab68dfa2ee2/Storage/1/Drives/"
"invalid_id"
)

self.assertEqual(status.HTTP_400_BAD_REQUEST, response.status_code)
result = json.loads(response.data.decode("utf-8"))
self.assertEqual(status.HTTP_404_NOT_FOUND, response.status_code)
self.assertEqual(result["error"]["message"],
"Drive invalid_id not found")

self.assertEqual("application/json", response.mimetype)
self.assertIn("Drive id should be a integer", str(response.data))
self.oneview_client.server_profiles.get.assert_not_called()
self.oneview_client.sas_logical_jbods.get.assert_not_called()

def test_composed_system_without_drives(self):
"""Tests Storage when it does not have drives"""
Expand Down