mirror of
https://github.com/akuker/RASCSI.git
synced 2025-08-10 05:24:58 +00:00
Add docstrings and clean up layout
This commit is contained in:
@@ -5,6 +5,15 @@ import rascsi_interface_pb2 as proto
|
|||||||
|
|
||||||
|
|
||||||
def get_server_info():
|
def get_server_info():
|
||||||
|
"""
|
||||||
|
Sends a SERVER_INFO command to the server.
|
||||||
|
Returns a dict with:
|
||||||
|
- boolean status
|
||||||
|
- str version (RaSCSI version number)
|
||||||
|
- list of str log_levels (the log levels RaSCSI supports)
|
||||||
|
- str current_log_level
|
||||||
|
- list of int reserved_ids
|
||||||
|
"""
|
||||||
command = proto.PbCommand()
|
command = proto.PbCommand()
|
||||||
command.operation = proto.PbOperation.SERVER_INFO
|
command.operation = proto.PbOperation.SERVER_INFO
|
||||||
|
|
||||||
@@ -17,10 +26,22 @@ def get_server_info():
|
|||||||
log_levels = result.server_info.log_levels
|
log_levels = result.server_info.log_levels
|
||||||
current_log_level = result.server_info.current_log_level
|
current_log_level = result.server_info.current_log_level
|
||||||
reserved_ids = list(result.server_info.reserved_ids)
|
reserved_ids = list(result.server_info.reserved_ids)
|
||||||
return {"status": result.status, "version": version, "log_levels": log_levels, "current_log_level": current_log_level, "reserved_ids": reserved_ids}
|
return {
|
||||||
|
"status": result.status,
|
||||||
|
"version": version,
|
||||||
|
"log_levels": log_levels,
|
||||||
|
"current_log_level": current_log_level,
|
||||||
|
"reserved_ids": reserved_ids
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_network_info():
|
def get_network_info():
|
||||||
|
"""
|
||||||
|
Sends a NETWORK_INTERFACES_INFO command to the server.
|
||||||
|
Returns a dict with:
|
||||||
|
- boolean status
|
||||||
|
- list of str ifs (network interfaces detected by RaSCSI)
|
||||||
|
"""
|
||||||
command = proto.PbCommand()
|
command = proto.PbCommand()
|
||||||
command.operation = proto.PbOperation.NETWORK_INTERFACES_INFO
|
command.operation = proto.PbOperation.NETWORK_INTERFACES_INFO
|
||||||
|
|
||||||
@@ -32,6 +53,12 @@ def get_network_info():
|
|||||||
|
|
||||||
|
|
||||||
def get_device_types():
|
def get_device_types():
|
||||||
|
"""
|
||||||
|
Sends a DEVICE_TYPES_INFO command to the server.
|
||||||
|
Returns a dict with:
|
||||||
|
- boolean status
|
||||||
|
- list of str device_types (device types that RaSCSI supports, ex. SCHD, SCCD, etc)
|
||||||
|
"""
|
||||||
command = proto.PbCommand()
|
command = proto.PbCommand()
|
||||||
command.operation = proto.PbOperation.DEVICE_TYPES_INFO
|
command.operation = proto.PbOperation.DEVICE_TYPES_INFO
|
||||||
|
|
||||||
@@ -45,6 +72,12 @@ def get_device_types():
|
|||||||
|
|
||||||
|
|
||||||
def validate_scsi_id(scsi_id):
|
def validate_scsi_id(scsi_id):
|
||||||
|
"""
|
||||||
|
Checks that scsi_id is a valid SCSI ID, i.e. a number between 0 and 7.
|
||||||
|
Returns a dict with:
|
||||||
|
- boolean status
|
||||||
|
- str msg (result message)
|
||||||
|
"""
|
||||||
from re import match
|
from re import match
|
||||||
if match("[0-7]", str(scsi_id)) != None:
|
if match("[0-7]", str(scsi_id)) != None:
|
||||||
return {"status": True, "msg": "Valid SCSI ID."}
|
return {"status": True, "msg": "Valid SCSI ID."}
|
||||||
@@ -53,6 +86,10 @@ def validate_scsi_id(scsi_id):
|
|||||||
|
|
||||||
|
|
||||||
def get_valid_scsi_ids(devices, reserved_ids):
|
def get_valid_scsi_ids(devices, reserved_ids):
|
||||||
|
"""
|
||||||
|
Takes a list of dicts devices, and list of ints reserved_ids.
|
||||||
|
Returns a list of ints valid_ids, which are the SCSI ids where it is possible to attach a device.
|
||||||
|
"""
|
||||||
occupied_ids = []
|
occupied_ids = []
|
||||||
for d in devices:
|
for d in devices:
|
||||||
# Make it possible to insert images on top of a
|
# Make it possible to insert images on top of a
|
||||||
@@ -69,12 +106,23 @@ def get_valid_scsi_ids(devices, reserved_ids):
|
|||||||
except:
|
except:
|
||||||
# May reach this state if the RaSCSI Web UI thinks an ID
|
# May reach this state if the RaSCSI Web UI thinks an ID
|
||||||
# is reserved but RaSCSI has not actually reserved it.
|
# is reserved but RaSCSI has not actually reserved it.
|
||||||
logging.warning(f"SCSI ID {id} flagged as both valid and invalid. Try restarting the RaSCSI Web UI.")
|
logging.warning(f"SCSI ID {id} flagged as both valid and invalid. \
|
||||||
|
Try restarting the RaSCSI Web UI.")
|
||||||
valid_ids.reverse()
|
valid_ids.reverse()
|
||||||
return valid_ids
|
return valid_ids
|
||||||
|
|
||||||
|
|
||||||
def attach_image(scsi_id, **kwargs):
|
def attach_image(scsi_id, **kwargs):
|
||||||
|
"""
|
||||||
|
Takes int scsi_id and kwargs containing 0 or more device properties
|
||||||
|
|
||||||
|
If the current attached device is a removable device wihout media inserted,
|
||||||
|
this sends a INJECT command to the server.
|
||||||
|
If there is no currently attached device, this sends the ATTACH command to the server.
|
||||||
|
|
||||||
|
Returns boolean status and return message str msg
|
||||||
|
|
||||||
|
"""
|
||||||
command = proto.PbCommand()
|
command = proto.PbCommand()
|
||||||
devices = proto.PbDeviceDefinition()
|
devices = proto.PbDeviceDefinition()
|
||||||
devices.id = int(scsi_id)
|
devices.id = int(scsi_id)
|
||||||
@@ -130,6 +178,10 @@ def attach_image(scsi_id, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def detach_by_id(scsi_id):
|
def detach_by_id(scsi_id):
|
||||||
|
"""
|
||||||
|
Takes int scsi_id and sends a DETACH command to the server.
|
||||||
|
Returns boolean status and return message str msg.
|
||||||
|
"""
|
||||||
devices = proto.PbDeviceDefinition()
|
devices = proto.PbDeviceDefinition()
|
||||||
devices.id = int(scsi_id)
|
devices.id = int(scsi_id)
|
||||||
|
|
||||||
@@ -144,6 +196,10 @@ def detach_by_id(scsi_id):
|
|||||||
|
|
||||||
|
|
||||||
def detach_all():
|
def detach_all():
|
||||||
|
"""
|
||||||
|
Sends a DETACH_ALL command to the server.
|
||||||
|
Returns boolean status and return message str msg.
|
||||||
|
"""
|
||||||
command = proto.PbCommand()
|
command = proto.PbCommand()
|
||||||
command.operation = proto.PbOperation.DETACH_ALL
|
command.operation = proto.PbOperation.DETACH_ALL
|
||||||
|
|
||||||
@@ -154,6 +210,10 @@ def detach_all():
|
|||||||
|
|
||||||
|
|
||||||
def eject_by_id(scsi_id):
|
def eject_by_id(scsi_id):
|
||||||
|
"""
|
||||||
|
Takes int scsi_id and sends an EJECT command to the server.
|
||||||
|
Returns boolean status and return message str msg.
|
||||||
|
"""
|
||||||
devices = proto.PbDeviceDefinition()
|
devices = proto.PbDeviceDefinition()
|
||||||
devices.id = int(scsi_id)
|
devices.id = int(scsi_id)
|
||||||
|
|
||||||
@@ -168,6 +228,13 @@ def eject_by_id(scsi_id):
|
|||||||
|
|
||||||
|
|
||||||
def list_devices(scsi_id=None):
|
def list_devices(scsi_id=None):
|
||||||
|
"""
|
||||||
|
Takes optional int scsi_id and sends a DEVICES_INFO command to the server.
|
||||||
|
If no scsi_id is provided, returns a list of dicts of all attached devices.
|
||||||
|
If scsi_id is is provided, returns a list of one dict for the given device.
|
||||||
|
If no attached device is found, returns an empty list.
|
||||||
|
Returns bolean status, list of dicts device_list
|
||||||
|
"""
|
||||||
from os import path
|
from os import path
|
||||||
command = proto.PbCommand()
|
command = proto.PbCommand()
|
||||||
command.operation = proto.PbOperation.DEVICES_INFO
|
command.operation = proto.PbOperation.DEVICES_INFO
|
||||||
@@ -226,6 +293,11 @@ def list_devices(scsi_id=None):
|
|||||||
|
|
||||||
|
|
||||||
def sort_and_format_devices(devices):
|
def sort_and_format_devices(devices):
|
||||||
|
"""
|
||||||
|
Takes a list of dicts devices and returns a list of dicts.
|
||||||
|
Sorts by SCSI ID acending (0 to 7).
|
||||||
|
For SCSI IDs where no device is attached, inject a dict with placeholder text.
|
||||||
|
"""
|
||||||
occupied_ids = []
|
occupied_ids = []
|
||||||
for d in devices:
|
for d in devices:
|
||||||
occupied_ids.append(d["id"])
|
occupied_ids.append(d["id"])
|
||||||
@@ -244,7 +316,11 @@ def sort_and_format_devices(devices):
|
|||||||
|
|
||||||
|
|
||||||
def set_log_level(log_level):
|
def set_log_level(log_level):
|
||||||
'''Sends a command to the server to change the log level. Takes target log level as an argument.'''
|
"""
|
||||||
|
Sends a LOG_LEVEL command to the server.
|
||||||
|
Takes str log_level as an argument.
|
||||||
|
Returns bolean status and str msg.
|
||||||
|
"""
|
||||||
command = proto.PbCommand()
|
command = proto.PbCommand()
|
||||||
command.operation = proto.PbOperation.LOG_LEVEL
|
command.operation = proto.PbOperation.LOG_LEVEL
|
||||||
command.params["level"] = str(log_level)
|
command.params["level"] = str(log_level)
|
||||||
@@ -256,6 +332,10 @@ def set_log_level(log_level):
|
|||||||
|
|
||||||
|
|
||||||
def send_pb_command(payload):
|
def send_pb_command(payload):
|
||||||
|
"""
|
||||||
|
Takes a str containing a serialized protobuf as argument.
|
||||||
|
Establishes a socket connection with RaSCSI.
|
||||||
|
"""
|
||||||
# Host and port number where rascsi is listening for socket connections
|
# Host and port number where rascsi is listening for socket connections
|
||||||
HOST = 'localhost'
|
HOST = 'localhost'
|
||||||
PORT = 6868
|
PORT = 6868
|
||||||
@@ -285,6 +365,13 @@ def send_pb_command(payload):
|
|||||||
|
|
||||||
|
|
||||||
def send_over_socket(s, payload):
|
def send_over_socket(s, payload):
|
||||||
|
"""
|
||||||
|
Takes a socket object and str payload with serialized protobuf.
|
||||||
|
Sends payload to RaSCSI over socket and captures the response.
|
||||||
|
Tries to extract and interpret the protobuf header to get response size.
|
||||||
|
Reads data from socket in 2048 bytes chunks until all data is received.
|
||||||
|
|
||||||
|
"""
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
|
|
||||||
# Prepending a little endian 32bit header with the message size
|
# Prepending a little endian 32bit header with the message size
|
||||||
@@ -303,13 +390,20 @@ def send_over_socket(s, payload):
|
|||||||
chunk = s.recv(min(response_length - bytes_recvd, 2048))
|
chunk = s.recv(min(response_length - bytes_recvd, 2048))
|
||||||
if chunk == b'':
|
if chunk == b'':
|
||||||
from flask import abort
|
from flask import abort
|
||||||
logging.error("Read an empty chunk from the socket. Socket connection may have dropped unexpectedly. Check if RaSCSI has crashed.")
|
logging.error("Read an empty chunk from the socket. \
|
||||||
abort(503, "Lost connection to RaSCSI. Please go back and try again. If the issue persists, please report a bug.")
|
Socket connection has dropped unexpectedly. \
|
||||||
|
RaSCSI may have has crashed.")
|
||||||
|
abort(503, "Lost connection to RaSCSI. \
|
||||||
|
Please go back and try again. \
|
||||||
|
If the issue persists, please report a bug.")
|
||||||
chunks.append(chunk)
|
chunks.append(chunk)
|
||||||
bytes_recvd = bytes_recvd + len(chunk)
|
bytes_recvd = bytes_recvd + len(chunk)
|
||||||
response_message = b''.join(chunks)
|
response_message = b''.join(chunks)
|
||||||
return response_message
|
return response_message
|
||||||
else:
|
else:
|
||||||
from flask import abort
|
from flask import abort
|
||||||
logging.error("The response from RaSCSI did not contain a protobuf header.")
|
logging.error("The response from RaSCSI did not contain a protobuf header. \
|
||||||
abort(500, "Did not get a valid response from RaSCSI. Please go back and try again. If the issue persists, please report a bug.")
|
RaSCSI may have crashed.")
|
||||||
|
abort(500, "Did not get a valid response from RaSCSI. \
|
||||||
|
Please go back and try again. \
|
||||||
|
If the issue persists, please report a bug.")
|
||||||
|
Reference in New Issue
Block a user