RASCSI/src/raspberrypi/rasctl_display.cpp
Uwe Seimet 94786aec54
Added support for operation meta data, code cleanup (#534)
* Added messages

* Comment update

* Interface update

* Support for localized descriptions

* Sort operations

* Completed meta data

* rasctl -s returns operation meta data

* Manpage update

* Type update

* Comment update

* Description updates

* Comment update

* Added convenience method

* Added convenience method

* Code cleanup

* Comment update

* Display permitted values

* For completeness sake added permitted boolean values

* Added support for default value

* Removed redundant message field

* Description update

* Description upddate

* Squashed commit of the following:

commit 8171c6ea27982c736c30c0db69a7fdde07ee10ce
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 12:43:14 2021 +0100

    The data type is implicit

commit fb01dc9d82e8ff7456b05a0cb9d08069adacc64c
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 12:37:49 2021 +0100

    Renaming

commit 057dbf1aca7be3f7e76a5ff89a582a276b6d3089
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 12:29:54 2021 +0100

    Comment update

commit 5f699aad2f835f72accdb445d1e59f094aeb108f
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 12:24:25 2021 +0100

    Signature update

commit cbcf8b09f9d1ba7b82f816269bcfe91d9f00eb6e
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 12:22:45 2021 +0100

    Signature update

commit a8148ef802ca809e5a305d2caa69856c9033d932
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 12:16:46 2021 +0100

    Comment update

commit ce685a92d4827e131d80d10ecd56e2b3baf173f8
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 12:15:46 2021 +0100

    Use map instead of list

commit 454c0438f3589904f5dbe5253963dd200ea416dd
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 10:47:36 2021 +0100

    Updated size check

commit b386dbba4b0262f4f6f02aecb2a1daeffd41f4a2
Author: Uwe Seimet <Uwe.Seimet@seimet.de>
Date:   Sat Dec 18 01:23:43 2021 +0100

    Initial improvements

* Default value update

* Comment update

* Comment update

* Map operations by ordinal

* Added safeguard against unknown operations

* Added cast

* Data type update

* Sort map by operation name

* Renaming

* Code cleanup

* Comment update

* Renaming

* Comment update

* Description updates

* Fixed typo

* Added operation

* Logging update

* Interface comment update

* Fixed typo

* Aded operation parameters

* Updated handling of mandatory parameters

* Updated assertion handling

* Added missing condition

* Removed duplicate cod3

* Code cleanup

* Logging update

* Removed duplicate code

* Code cleanup

* Squashed commit of the following:

commit 4ae273ccbd
Author: akuker <34318535+akuker@users.noreply.github.com>
Date:   Sun Dec 19 22:30:22 2021 -0600

    Loopback tester pcb (#545)

commit 46c5c1966f
Author: akuker <34318535+akuker@users.noreply.github.com>
Date:   Sun Dec 19 22:29:59 2021 -0600

    RaSCSI Zero version 1.0 (#546)

commit d09df31d67
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 20:25:23 2021 -0800

    Remove redundant code from OLED script (#547)

commit d8828da690
Author: akuker <34318535+akuker@users.noreply.github.com>
Date:   Sun Dec 19 21:02:50 2021 -0600

    Added list of sponsors

commit bcd7e8396d
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:51:45 2021 -0800

    Second attempt at properly creating the manpage dir (#542)

commit c887edfc8c
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:50:03 2021 -0800

    Remove special elevated privileges for the Web Interface (#536)

    * Use the pi_shutdown method to restart the rascsi service

    * Use the pi_shutdown method to restart the rascsi service

    * Remove modifications to sudoers no longer needed

    * Introduce sleeps attempting to connect to socket; reduce overall number of retries

    * Remove systemd helped methods and the functionality that depends on it

    * Attempts to speed up splash code

    * Remove unneccessary verbosity

    * Attempt to optimize service definition

commit 801aebfb96
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:47:22 2021 -0800

    More readable message when downloading a file (#531)

commit 29cf58288f
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:47:03 2021 -0800

    Add a warning notice when ejecting removable media (#526)

commit 7efa895239
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:46:22 2021 -0800

    Unzip zipfiles before storing to iso (#525)

    * Unzip zipfiles before storing to iso

    * Add helptext

    * Skip unzip for MacZip format

    * Should not be an fstring

commit 39bc485671
Author: Daniel Markstedt <markstedt@gmail.com>
Date:   Sun Dec 19 15:28:22 2021 -0800

    Add pip3 to global dependencies; remove duplicates from monitor_rascs… (#523)

    * Add pip3 to global dependencies; remove duplicates from monitor_rascsi dependencies

    * Cleanup

* Shutdown functionality is only available if started with root permissions

* Only restrict shutdown parameters, not everything if not root

* Updated operation count check
2021-12-21 08:43:21 +01:00

335 lines
9.5 KiB
C++

//---------------------------------------------------------------------------
//
// SCSI Target Emulator RaSCSI (*^..^*)
// for Raspberry Pi
//
// Copyright (C) 2021 Uwe Seimet
//
//---------------------------------------------------------------------------
#include "rascsi_interface.pb.h"
#include "rasutil.h"
#include "rasctl_display.h"
#include <iostream>
#include <list>
using namespace std;
using namespace rascsi_interface;
using namespace ras_util;
void RasctlDisplay::DisplayDevices(const PbDevicesInfo& devices_info)
{
const list<PbDevice>& devices = { devices_info.devices().begin(), devices_info.devices().end() };
cout << ListDevices(devices) << endl;
}
void RasctlDisplay::DisplayDeviceInfo(const PbDevice& pb_device)
{
cout << " " << pb_device.id() << ":" << pb_device.unit() << " " << PbDeviceType_Name(pb_device.type())
<< " " << pb_device.vendor() << ":" << pb_device.product() << ":" << pb_device.revision();
if (pb_device.block_size()) {
cout << " " << pb_device.block_size() << " bytes per sector";
if (pb_device.block_count()) {
cout << " " << pb_device.block_size() * pb_device.block_count() << " bytes capacity";
}
}
if (pb_device.properties().supports_file() && !pb_device.file().name().empty()) {
cout << " " << pb_device.file().name();
}
cout << " ";
bool hasProperty = false;
if (pb_device.properties().read_only()) {
cout << "read-only";
hasProperty = true;
}
if (pb_device.properties().protectable() && pb_device.status().protected_()) {
if (hasProperty) {
cout << ", ";
}
cout << "protected";
hasProperty = true;
}
if (pb_device.properties().stoppable() && pb_device.status().stopped()) {
if (hasProperty) {
cout << ", ";
}
cout << "stopped";
hasProperty = true;
}
if (pb_device.properties().removable() && pb_device.status().removed()) {
if (hasProperty) {
cout << ", ";
}
cout << "removed";
hasProperty = true;
}
if (pb_device.properties().lockable() && pb_device.status().locked()) {
if (hasProperty) {
cout << ", ";
}
cout << "locked";
}
if (hasProperty) {
cout << " ";
}
bool isFirst = true;
for (const auto& param : pb_device.params()) {
if (!isFirst) {
cout << " ";
}
isFirst = false;
cout << param.first << "=" << param.second;
}
cout << endl;
}
void RasctlDisplay::DisplayVersionInfo(const PbVersionInfo& version_info)
{
cout << "rascsi server version: " << version_info.major_version() << "." << version_info.minor_version();
if (version_info.patch_version() > 0) {
cout << "." << version_info.patch_version();
}
else if (version_info.patch_version() < 0) {
cout << " (development version)";
}
cout << endl;
}
void RasctlDisplay::DisplayLogLevelInfo(const PbLogLevelInfo& log_level_info)
{
if (!log_level_info.log_levels_size()) {
cout << " No log level settings available" << endl;
}
else {
cout << "rascsi log levels, sorted by severity:" << endl;
for (const auto& log_level : log_level_info.log_levels()) {
cout << " " << log_level << endl;
}
}
cout << "Current rascsi log level: " << log_level_info.current_log_level() << endl;
}
void RasctlDisplay::DisplayDeviceTypesInfo(const PbDeviceTypesInfo& device_types_info)
{
cout << "Supported device types and their properties:" << endl;
for (const auto& device_type_info : device_types_info.properties()) {
cout << " " << PbDeviceType_Name(device_type_info.type());
const PbDeviceProperties& properties = device_type_info.properties();
cout << " Supported LUN numbers: 0";
if (properties.luns() > 1) {
cout << "-" << (properties.luns() - 1);
}
cout << endl;
if (properties.read_only() || properties.protectable() || properties.stoppable() || properties.read_only()
|| properties.lockable()) {
cout << " Properties: ";
bool has_property = false;
if (properties.read_only()) {
cout << "read-only";
has_property = true;
}
if (properties.protectable()) {
cout << (has_property ? ", " : "") << "protectable";
has_property = true;
}
if (properties.stoppable()) {
cout << (has_property ? ", " : "") << "stoppable";
has_property = true;
}
if (properties.removable()) {
cout << (has_property ? ", " : "") << "removable";
has_property = true;
}
if (properties.lockable()) {
cout << (has_property ? ", " : "") << "lockable";
}
cout << endl;
}
if (properties.supports_file()) {
cout << " Image file support" << endl;
}
else if (properties.supports_params()) {
cout << " Parameter support" << endl;
}
if (properties.supports_params() && properties.default_params_size()) {
// Creates a sorted map
map<string, string> params = { properties.default_params().begin(), properties.default_params().end() };
cout << " Default parameters: ";
bool isFirst = true;
for (const auto& param : params) {
if (!isFirst) {
cout << ", ";
}
cout << param.first << "=" << param.second;
isFirst = false;
}
cout << endl;
}
if (properties.block_sizes_size()) {
// Creates a sorted set
set<uint32_t> block_sizes = { properties.block_sizes().begin(), properties.block_sizes().end() };
cout << " Configurable block sizes in bytes: ";
bool isFirst = true;
for (const auto& block_size : block_sizes) {
if (!isFirst) {
cout << ", ";
}
cout << block_size;
isFirst = false;
}
cout << endl;
}
}
}
void RasctlDisplay::DisplayReservedIdsInfo(const PbReservedIdsInfo& reserved_ids_info)
{
if (reserved_ids_info.ids_size()) {
cout << "Reserved device IDs: ";
for (int i = 0; i < reserved_ids_info.ids_size(); i++) {
if(i) {
cout << ", ";
}
cout << reserved_ids_info.ids(i);
}
cout <<endl;
}
}
void RasctlDisplay::DisplayImageFile(const PbImageFile& image_file_info)
{
cout << image_file_info.name() << " " << image_file_info.size() << " bytes";
if (image_file_info.read_only()) {
cout << " read-only";
}
if (image_file_info.type() != UNDEFINED) {
cout << " " << PbDeviceType_Name(image_file_info.type());
}
cout << endl;
}
void RasctlDisplay::DisplayImageFiles(const PbImageFilesInfo& image_files_info)
{
cout << "Default image file folder: " << image_files_info.default_image_folder() << endl;
if (image_files_info.image_files().empty()) {
cout << " No image files available" << endl;
}
else {
list<PbImageFile> image_files = { image_files_info.image_files().begin(), image_files_info.image_files().end() };
image_files.sort([](const auto& a, const auto& b) { return a.name() < b.name(); });
cout << "Available image files:" << endl;
for (const auto& image_file : image_files) {
cout << " ";
DisplayImageFile(image_file);
}
}
}
void RasctlDisplay::DisplayNetworkInterfaces(const PbNetworkInterfacesInfo& network_interfaces_info)
{
// Creates a sorted list
const list<string> interfaces = { network_interfaces_info.name().begin(), network_interfaces_info.name().end() };
cout << "Available (up) network interfaces:" << endl;
bool isFirst = true;
for (const auto& interface : interfaces) {
if (!isFirst) {
cout << ", ";
}
isFirst = false;
cout << interface;
}
cout << endl;
}
void RasctlDisplay::DisplayMappingInfo(const PbMappingInfo& mapping_info)
{
// Creates a sorted map
const map<string, PbDeviceType> mappings = { mapping_info.mapping().begin(), mapping_info.mapping().end() };
cout << "Supported image file extension to device type mappings:" << endl;
for (const auto& mapping : mappings) {
cout << " " << mapping.first << "->" << PbDeviceType_Name(mapping.second) << endl;
}
}
void RasctlDisplay::DisplayOperationInfo(const PbOperationInfo& operation_info)
{
const map<int, PbOperationMetaData> operations = { operation_info.operations().begin(), operation_info.operations().end() };
// Copies result into a map sorted by operation name
const PbOperationMetaData *unknown_operation = new PbOperationMetaData();
map<string, PbOperationMetaData> sorted_operations;
for (const auto& operation : operations) {
if (PbOperation_IsValid(static_cast<PbOperation>(operation.first))) {
sorted_operations[PbOperation_Name(static_cast<PbOperation>(operation.first))] = operation.second;
}
else {
// If the server-side operation is unknown for the client use the server-provided operation name
// No further operation information is available in this case
sorted_operations[operation.second.server_side_name()] = *unknown_operation;
}
}
cout << "Remote operations supported by rascsi and their parameters:" << endl;
for (const auto& operation : sorted_operations) {
if (!operation.second.server_side_name().empty()) {
cout << " " << operation.first;
if (!operation.second.description().empty()) {
cout << " (" << operation.second.description().at("en") << ")";
}
cout << endl;
for (const auto& parameter : operation.second.parameters()) {
cout << " " << parameter.name() << ": "
<< (parameter.is_mandatory() ? "mandatory" : "optional");
if (!parameter.description().empty()) {
cout << " (" << parameter.description().at("en") << ")";
}
cout << endl;
if (parameter.permitted_values_size()) {
cout << " Permitted values: ";
bool isFirst = true;
for (const auto& permitted_value : parameter.permitted_values()) {
if (!isFirst) {
cout << ", ";
}
isFirst = false;
cout << permitted_value;
}
cout << endl;
}
if (!parameter.default_value().empty()) {
cout << " Default value: " << parameter.default_value() << endl;
}
}
}
else {
cout << " " << operation.first << " (Unknown server-side operation)" << endl;
}
}
}